diff --git a/node_modules/react-native/Libraries/Renderer/implementations/ReactFabric-dev.js b/node_modules/react-native/Libraries/Renderer/implementations/ReactFabric-dev.js index 1c5266e..ad00ec2 100644 --- a/node_modules/react-native/Libraries/Renderer/implementations/ReactFabric-dev.js +++ b/node_modules/react-native/Libraries/Renderer/implementations/ReactFabric-dev.js @@ -13,24112 +13,24154 @@ 'use strict'; +import defrost from '@d11/de-frost' + 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"; + /* 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 React = require("react"); -require("react-native/Libraries/ReactPrivate/ReactNativePrivateInitializeCore"); -var ReactNativePrivateInterface = require("react-native/Libraries/ReactPrivate/ReactNativePrivateInterface"); -var Scheduler = require("scheduler"); + var React = require("react"); + require("react-native/Libraries/ReactPrivate/ReactNativePrivateInitializeCore"); + var updatedComponents = []; + var updatedComponentForProfiler = null; + function insertUpdateComponents(componentName, flags, key) { + updatedComponents.push({ componentName, flags, key }); + } + var ReactNativePrivateInterface = require("react-native/Libraries/ReactPrivate/ReactNativePrivateInterface"); + var Scheduler = require("scheduler"); -var ReactSharedInternals = - React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; + var ReactSharedInternals = + React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; -// by calls to these methods by a Babel plugin. -// -// In PROD (or in packages without access to React internals), -// they are left as they are instead. + // by calls to these methods by a Babel plugin. + // + // In PROD (or in packages without access to React internals), + // they are left as they are instead. -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]; - } + 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("warn", format, args); + } } - - printWarning("error", format, args); } - } -} - -function printWarning(level, format, args) { - // When changing this logic, you might want to also - // update consoleWithStackDev.www.js as well. - { - var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; - var stack = ReactDebugCurrentFrame.getStackAddendum(); - - if (stack !== "") { - format += "%s"; - args = args.concat([stack]); - } // eslint-disable-next-line react-internal/safe-string-coercion + 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 argsWithFormat = args.map(function(item) { - return String(item); - }); // Careful: RN currently depends on this prefix + printWarning("error", format, args); + } + } + } - argsWithFormat.unshift("Warning: " + format); // We intentionally don't use spread (or .apply) directly because it - // breaks IE9: https://github.com/facebook/react/issues/13610 - // eslint-disable-next-line react-internal/no-production-logging + function printWarning(level, format, args) { + // When changing this logic, you might want to also + // update consoleWithStackDev.www.js as well. + { + var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; + var stack = ReactDebugCurrentFrame.getStackAddendum(); - Function.prototype.apply.call(console[level], console, argsWithFormat); - } -} + if (stack !== "") { + format += "%s"; + args = args.concat([stack]); + } // eslint-disable-next-line react-internal/safe-string-coercion -function invokeGuardedCallbackProd(name, func, context, a, b, c, d, e, f) { - var funcArgs = Array.prototype.slice.call(arguments, 3); + var argsWithFormat = args.map(function (item) { + return String(item); + }); // Careful: RN currently depends on this prefix - try { - func.apply(context, funcArgs); - } catch (error) { - this.onError(error); - } -} + argsWithFormat.unshift("Warning: " + format); // We intentionally don't use spread (or .apply) directly because it + // breaks IE9: https://github.com/facebook/react/issues/13610 + // eslint-disable-next-line react-internal/no-production-logging -var invokeGuardedCallbackImpl = invokeGuardedCallbackProd; - -{ - // In DEV mode, we swap out invokeGuardedCallback for a special version - // that plays more nicely with the browser's DevTools. The idea is to preserve - // "Pause on exceptions" behavior. Because React wraps all user-provided - // functions in invokeGuardedCallback, and the production version of - // invokeGuardedCallback uses a try-catch, all user exceptions are treated - // like caught exceptions, and the DevTools won't pause unless the developer - // takes the extra step of enabling pause on caught exceptions. This is - // unintuitive, though, because even though React has caught the error, from - // the developer's perspective, the error is uncaught. - // - // To preserve the expected "Pause on exceptions" behavior, we don't use a - // try-catch in DEV. Instead, we synchronously dispatch a fake event to a fake - // DOM node, and call the user-provided callback from inside an event handler - // for that fake event. If the callback throws, the error is "captured" using - // a global event handler. But because the error happens in a different - // event loop context, it does not interrupt the normal program flow. - // Effectively, this gives us try-catch behavior without actually using - // try-catch. Neat! - // Check that the browser supports the APIs we need to implement our special - // DEV version of invokeGuardedCallback - if ( - typeof window !== "undefined" && - typeof window.dispatchEvent === "function" && - typeof document !== "undefined" && - typeof document.createEvent === "function" - ) { - var fakeNode = document.createElement("react"); - - invokeGuardedCallbackImpl = function invokeGuardedCallbackDev( - name, - func, - context, - a, - b, - c, - d, - e, - f - ) { - // If document doesn't exist we know for sure we will crash in this method - // when we call document.createEvent(). However this can cause confusing - // errors: https://github.com/facebook/create-react-app/issues/3482 - // So we preemptively throw with a better message instead. - if (typeof document === "undefined" || document === null) { - throw new Error( - "The `document` global was defined when React was initialized, but is not " + - "defined anymore. This can happen in a test environment if a component " + - "schedules an update from an asynchronous callback, but the test has already " + - "finished running. To solve this, you can either unmount the component at " + - "the end of your test (and ensure that any asynchronous operations get " + - "canceled in `componentWillUnmount`), or you can change the test itself " + - "to be asynchronous." - ); + Function.prototype.apply.call(console[level], console, argsWithFormat); } + } - var evt = document.createEvent("Event"); - var didCall = false; // Keeps track of whether the user-provided callback threw an error. We - // set this to true at the beginning, then set it to false right after - // calling the function. If the function errors, `didError` will never be - // set to false. This strategy works even if the browser is flaky and - // fails to call our global error handler, because it doesn't rely on - // the error event at all. - - var didError = true; // Keeps track of the value of window.event so that we can reset it - // during the callback to let user code access window.event in the - // browsers that support it. - - var windowEvent = window.event; // Keeps track of the descriptor of window.event to restore it after event - // dispatching: https://github.com/facebook/react/issues/13688 + function invokeGuardedCallbackProd(name, func, context, a, b, c, d, e, f) { + var funcArgs = Array.prototype.slice.call(arguments, 3); - var windowEventDescriptor = Object.getOwnPropertyDescriptor( - window, - "event" - ); + try { + func.apply(context, funcArgs); + } catch (error) { + this.onError(error); + } + } - function restoreAfterDispatch() { - // We immediately remove the callback from event listeners so that - // nested `invokeGuardedCallback` calls do not clash. Otherwise, a - // nested call would trigger the fake event handlers of any call higher - // in the stack. - fakeNode.removeEventListener(evtType, callCallback, false); // We check for window.hasOwnProperty('event') to prevent the - // window.event assignment in both IE <= 10 as they throw an error - // "Member not found" in strict mode, and in Firefox which does not - // support window.event. + var invokeGuardedCallbackImpl = invokeGuardedCallbackProd; - if ( - typeof window.event !== "undefined" && - window.hasOwnProperty("event") + { + // In DEV mode, we swap out invokeGuardedCallback for a special version + // that plays more nicely with the browser's DevTools. The idea is to preserve + // "Pause on exceptions" behavior. Because React wraps all user-provided + // functions in invokeGuardedCallback, and the production version of + // invokeGuardedCallback uses a try-catch, all user exceptions are treated + // like caught exceptions, and the DevTools won't pause unless the developer + // takes the extra step of enabling pause on caught exceptions. This is + // unintuitive, though, because even though React has caught the error, from + // the developer's perspective, the error is uncaught. + // + // To preserve the expected "Pause on exceptions" behavior, we don't use a + // try-catch in DEV. Instead, we synchronously dispatch a fake event to a fake + // DOM node, and call the user-provided callback from inside an event handler + // for that fake event. If the callback throws, the error is "captured" using + // a global event handler. But because the error happens in a different + // event loop context, it does not interrupt the normal program flow. + // Effectively, this gives us try-catch behavior without actually using + // try-catch. Neat! + // Check that the browser supports the APIs we need to implement our special + // DEV version of invokeGuardedCallback + if ( + typeof window !== "undefined" && + typeof window.dispatchEvent === "function" && + typeof document !== "undefined" && + typeof document.createEvent === "function" + ) { + var fakeNode = document.createElement("react"); + + invokeGuardedCallbackImpl = function invokeGuardedCallbackDev( + name, + func, + context, + a, + b, + c, + d, + e, + f ) { - window.event = windowEvent; - } - } // Create an event handler for our fake event. We will synchronously - // dispatch our fake event using `dispatchEvent`. Inside the handler, we - // call the user-provided callback. - - var funcArgs = Array.prototype.slice.call(arguments, 3); - - function callCallback() { - didCall = true; - restoreAfterDispatch(); - func.apply(context, funcArgs); - didError = false; - } // Create a global error event handler. We use this to capture the value - // that was thrown. It's possible that this error handler will fire more - // than once; for example, if non-React code also calls `dispatchEvent` - // and a handler for that event throws. We should be resilient to most of - // those cases. Even if our error event handler fires more than once, the - // last error event is always used. If the callback actually does error, - // we know that the last error event is the correct one, because it's not - // possible for anything else to have happened in between our callback - // erroring and the code that follows the `dispatchEvent` call below. If - // the callback doesn't error, but the error event was fired, we know to - // ignore it because `didError` will be false, as described above. - - var error; // Use this to track whether the error event is ever called. - - var didSetError = false; - var isCrossOriginError = false; - - function handleWindowError(event) { - error = event.error; - didSetError = true; - - if (error === null && event.colno === 0 && event.lineno === 0) { - isCrossOriginError = true; - } - - if (event.defaultPrevented) { - // Some other error handler has prevented default. - // Browsers silence the error report if this happens. - // We'll remember this to later decide whether to log it or not. - if (error != null && typeof error === "object") { - try { - error._suppressLogging = true; - } catch (inner) { - // Ignore. - } + // If document doesn't exist we know for sure we will crash in this method + // when we call document.createEvent(). However this can cause confusing + // errors: https://github.com/facebook/create-react-app/issues/3482 + // So we preemptively throw with a better message instead. + if (typeof document === "undefined" || document === null) { + throw new Error( + "The `document` global was defined when React was initialized, but is not " + + "defined anymore. This can happen in a test environment if a component " + + "schedules an update from an asynchronous callback, but the test has already " + + "finished running. To solve this, you can either unmount the component at " + + "the end of your test (and ensure that any asynchronous operations get " + + "canceled in `componentWillUnmount`), or you can change the test itself " + + "to be asynchronous." + ); } - } - } // Create a fake event type. - var evtType = "react-" + (name ? name : "invokeguardedcallback"); // Attach our event handlers + var evt = document.createEvent("Event"); + var didCall = false; // Keeps track of whether the user-provided callback threw an error. We + // set this to true at the beginning, then set it to false right after + // calling the function. If the function errors, `didError` will never be + // set to false. This strategy works even if the browser is flaky and + // fails to call our global error handler, because it doesn't rely on + // the error event at all. - window.addEventListener("error", handleWindowError); - fakeNode.addEventListener(evtType, callCallback, false); // Synchronously dispatch our fake event. If the user-provided function - // errors, it will trigger our global error handler. + var didError = true; // Keeps track of the value of window.event so that we can reset it + // during the callback to let user code access window.event in the + // browsers that support it. - evt.initEvent(evtType, false, false); - fakeNode.dispatchEvent(evt); - - if (windowEventDescriptor) { - Object.defineProperty(window, "event", windowEventDescriptor); - } + var windowEvent = window.event; // Keeps track of the descriptor of window.event to restore it after event + // dispatching: https://github.com/facebook/react/issues/13688 - if (didCall && didError) { - if (!didSetError) { - // The callback errored, but the error event never fired. - // eslint-disable-next-line react-internal/prod-error-codes - error = new Error( - "An error was thrown inside one of your components, but React " + - "doesn't know what it was. This is likely due to browser " + - 'flakiness. React does its best to preserve the "Pause on ' + - 'exceptions" behavior of the DevTools, which requires some ' + - "DEV-mode only tricks. It's possible that these don't work in " + - "your browser. Try triggering the error in production mode, " + - "or switching to a modern browser. If you suspect that this is " + - "actually an issue with React, please file an issue." - ); - } else if (isCrossOriginError) { - // eslint-disable-next-line react-internal/prod-error-codes - error = new Error( - "A cross-origin error was thrown. React doesn't have access to " + - "the actual error object in development. " + - "See https://react.dev/link/crossorigin-error for more information." + var windowEventDescriptor = Object.getOwnPropertyDescriptor( + window, + "event" ); - } - this.onError(error); - } // Remove our event listeners - - window.removeEventListener("error", handleWindowError); + function restoreAfterDispatch() { + // We immediately remove the callback from event listeners so that + // nested `invokeGuardedCallback` calls do not clash. Otherwise, a + // nested call would trigger the fake event handlers of any call higher + // in the stack. + fakeNode.removeEventListener(evtType, callCallback, false); // We check for window.hasOwnProperty('event') to prevent the + // window.event assignment in both IE <= 10 as they throw an error + // "Member not found" in strict mode, and in Firefox which does not + // support window.event. - if (!didCall) { - // Something went really wrong, and our event was not dispatched. - // https://github.com/facebook/react/issues/16734 - // https://github.com/facebook/react/issues/16585 - // Fall back to the production implementation. - restoreAfterDispatch(); - return invokeGuardedCallbackProd.apply(this, arguments); - } - }; - } -} + if ( + typeof window.event !== "undefined" && + window.hasOwnProperty("event") + ) { + window.event = windowEvent; + } + } // Create an event handler for our fake event. We will synchronously + // dispatch our fake event using `dispatchEvent`. Inside the handler, we + // call the user-provided callback. + + var funcArgs = Array.prototype.slice.call(arguments, 3); + + function callCallback() { + didCall = true; + restoreAfterDispatch(); + func.apply(context, funcArgs); + didError = false; + } // Create a global error event handler. We use this to capture the value + // that was thrown. It's possible that this error handler will fire more + // than once; for example, if non-React code also calls `dispatchEvent` + // and a handler for that event throws. We should be resilient to most of + // those cases. Even if our error event handler fires more than once, the + // last error event is always used. If the callback actually does error, + // we know that the last error event is the correct one, because it's not + // possible for anything else to have happened in between our callback + // erroring and the code that follows the `dispatchEvent` call below. If + // the callback doesn't error, but the error event was fired, we know to + // ignore it because `didError` will be false, as described above. + + var error; // Use this to track whether the error event is ever called. + + var didSetError = false; + var isCrossOriginError = false; + + function handleWindowError(event) { + error = event.error; + didSetError = true; + + if (error === null && event.colno === 0 && event.lineno === 0) { + isCrossOriginError = true; + } -var invokeGuardedCallbackImpl$1 = invokeGuardedCallbackImpl; + if (event.defaultPrevented) { + // Some other error handler has prevented default. + // Browsers silence the error report if this happens. + // We'll remember this to later decide whether to log it or not. + if (error != null && typeof error === "object") { + try { + error._suppressLogging = true; + } catch (inner) { + // Ignore. + } + } + } + } // Create a fake event type. -var hasError = false; -var caughtError = null; // Used by event system to capture/rethrow the first error. + var evtType = "react-" + (name ? name : "invokeguardedcallback"); // Attach our event handlers -var hasRethrowError = false; -var rethrowError = null; -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 - */ + window.addEventListener("error", handleWindowError); + fakeNode.addEventListener(evtType, callCallback, false); // Synchronously dispatch our fake event. If the user-provided function + // errors, it will trigger our global error handler. -function invokeGuardedCallback(name, func, context, a, b, c, d, e, f) { - hasError = false; - caughtError = null; - invokeGuardedCallbackImpl$1.apply(reporter, arguments); -} -/** - * Same as invokeGuardedCallback, but instead of returning an error, it stores - * it in a global so it can be rethrown by `rethrowCaughtError` later. - * TODO: See if caughtError and rethrowError can be unified. - * - * @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 - */ + evt.initEvent(evtType, false, false); + fakeNode.dispatchEvent(evt); -function invokeGuardedCallbackAndCatchFirstError( - name, - func, - context, - a, - b, - c, - d, - e, - f -) { - invokeGuardedCallback.apply(this, arguments); - - if (hasError) { - var error = clearCaughtError(); - - if (!hasRethrowError) { - hasRethrowError = true; - rethrowError = error; - } - } -} -/** - * During execution of guarded functions we will capture the first error which - * we will rethrow to be handled by the top level error handler. - */ + if (windowEventDescriptor) { + Object.defineProperty(window, "event", windowEventDescriptor); + } -function rethrowCaughtError() { - if (hasRethrowError) { - var error = rethrowError; - hasRethrowError = false; - rethrowError = null; - throw error; - } -} -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." - ); - } -} + if (didCall && didError) { + if (!didSetError) { + // The callback errored, but the error event never fired. + // eslint-disable-next-line react-internal/prod-error-codes + error = new Error( + "An error was thrown inside one of your components, but React " + + "doesn't know what it was. This is likely due to browser " + + 'flakiness. React does its best to preserve the "Pause on ' + + 'exceptions" behavior of the DevTools, which requires some ' + + "DEV-mode only tricks. It's possible that these don't work in " + + "your browser. Try triggering the error in production mode, " + + "or switching to a modern browser. If you suspect that this is " + + "actually an issue with React, please file an issue." + ); + } else if (isCrossOriginError) { + // eslint-disable-next-line react-internal/prod-error-codes + error = new Error( + "A cross-origin error was thrown. React doesn't have access to " + + "the actual error object in development. " + + "See https://react.dev/link/crossorigin-error for more information." + ); + } -var isArrayImpl = Array.isArray; // eslint-disable-next-line no-redeclare + this.onError(error); + } // Remove our event listeners -function isArray(a) { - return isArrayImpl(a); -} + window.removeEventListener("error", handleWindowError); -var getFiberCurrentPropsFromNode = null; -var getInstanceFromNode = null; -var getNodeFromInstance = null; -function setComponentTree( - getFiberCurrentPropsFromNodeImpl, - getInstanceFromNodeImpl, - getNodeFromInstanceImpl -) { - getFiberCurrentPropsFromNode = getFiberCurrentPropsFromNodeImpl; - getInstanceFromNode = getInstanceFromNodeImpl; - getNodeFromInstance = getNodeFromInstanceImpl; - - { - if (!getNodeFromInstance || !getInstanceFromNode) { - error( - "EventPluginUtils.setComponentTree(...): Injected " + - "module is missing getNodeFromInstance or getInstanceFromNode." - ); + if (!didCall) { + // Something went really wrong, and our event was not dispatched. + // https://github.com/facebook/react/issues/16734 + // https://github.com/facebook/react/issues/16585 + // Fall back to the production implementation. + restoreAfterDispatch(); + return invokeGuardedCallbackProd.apply(this, arguments); + } + }; + } } - } -} -var validateEventDispatches; - -{ - validateEventDispatches = function(event) { - var dispatchListeners = event._dispatchListeners; - var dispatchInstances = event._dispatchInstances; - var listenersIsArr = isArray(dispatchListeners); - var listenersLen = listenersIsArr - ? dispatchListeners.length - : dispatchListeners - ? 1 - : 0; - var instancesIsArr = isArray(dispatchInstances); - var instancesLen = instancesIsArr - ? dispatchInstances.length - : dispatchInstances - ? 1 - : 0; - - if (instancesIsArr !== listenersIsArr || instancesLen !== listenersLen) { - error("EventPluginUtils: Invalid `event`."); - } - }; -} -/** - * Dispatch the event to the listener. - * @param {SyntheticEvent} event SyntheticEvent to handle - * @param {function} listener Application-level callback - * @param {*} inst Internal component instance - */ - -function executeDispatch(event, listener, inst) { - var type = event.type || "unknown-event"; - event.currentTarget = getNodeFromInstance(inst); - invokeGuardedCallbackAndCatchFirstError(type, listener, undefined, event); - event.currentTarget = null; -} -/** - * Standard/simple iteration through an event's collected dispatches. - */ -function executeDispatchesInOrder(event) { - var dispatchListeners = event._dispatchListeners; - var dispatchInstances = event._dispatchInstances; + var invokeGuardedCallbackImpl$1 = invokeGuardedCallbackImpl; - { - validateEventDispatches(event); - } + var hasError = false; + var caughtError = null; // Used by event system to capture/rethrow the first error. - if (isArray(dispatchListeners)) { - for (var i = 0; i < dispatchListeners.length; i++) { - if (event.isPropagationStopped()) { - break; - } // Listeners and Instances are two parallel arrays that are always in sync. + var hasRethrowError = false; + var rethrowError = null; + 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 + */ - executeDispatch(event, dispatchListeners[i], dispatchInstances[i]); + function invokeGuardedCallback(name, func, context, a, b, c, d, e, f) { + hasError = false; + caughtError = null; + invokeGuardedCallbackImpl$1.apply(reporter, arguments); } - } else if (dispatchListeners) { - executeDispatch(event, dispatchListeners, dispatchInstances); - } - - event._dispatchListeners = null; - event._dispatchInstances = null; -} -/** - * Standard/simple iteration through an event's collected dispatches, but stops - * at the first dispatch execution returning true, and returns that id. - * - * @return {?string} id of the first dispatch execution who's listener returns - * true, or null if no listener returned true. - */ + /** + * Same as invokeGuardedCallback, but instead of returning an error, it stores + * it in a global so it can be rethrown by `rethrowCaughtError` later. + * TODO: See if caughtError and rethrowError can be unified. + * + * @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 executeDispatchesInOrderStopAtTrueImpl(event) { - var dispatchListeners = event._dispatchListeners; - var dispatchInstances = event._dispatchInstances; + function invokeGuardedCallbackAndCatchFirstError( + name, + func, + context, + a, + b, + c, + d, + e, + f + ) { + invokeGuardedCallback.apply(this, arguments); - { - validateEventDispatches(event); - } + if (hasError) { + var error = clearCaughtError(); - if (isArray(dispatchListeners)) { - for (var i = 0; i < dispatchListeners.length; i++) { - if (event.isPropagationStopped()) { - break; - } // Listeners and Instances are two parallel arrays that are always in sync. + if (!hasRethrowError) { + hasRethrowError = true; + rethrowError = error; + } + } + } + /** + * During execution of guarded functions we will capture the first error which + * we will rethrow to be handled by the top level error handler. + */ - if (dispatchListeners[i](event, dispatchInstances[i])) { - return dispatchInstances[i]; + function rethrowCaughtError() { + if (hasRethrowError) { + var error = rethrowError; + hasRethrowError = false; + rethrowError = null; + throw error; } } - } else if (dispatchListeners) { - if (dispatchListeners(event, dispatchInstances)) { - return dispatchInstances; + 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." + ); + } } - } - return null; -} -/** - * @see executeDispatchesInOrderStopAtTrueImpl - */ + var isArrayImpl = Array.isArray; // eslint-disable-next-line no-redeclare -function executeDispatchesInOrderStopAtTrue(event) { - var ret = executeDispatchesInOrderStopAtTrueImpl(event); - event._dispatchInstances = null; - event._dispatchListeners = null; - return ret; -} -/** - * Execution of a "direct" dispatch - there must be at most one dispatch - * accumulated on the event or it is considered an error. It doesn't really make - * sense for an event with multiple dispatches (bubbled) to keep track of the - * return values at each dispatch execution, but it does tend to make sense when - * dealing with "direct" dispatches. - * - * @return {*} The return value of executing the single dispatch. - */ + function isArray(a) { + return isArrayImpl(a); + } -function executeDirectDispatch(event) { - { - validateEventDispatches(event); - } - - var dispatchListener = event._dispatchListeners; - var dispatchInstance = event._dispatchInstances; - - if (isArray(dispatchListener)) { - throw new Error("executeDirectDispatch(...): Invalid `event`."); - } - - event.currentTarget = dispatchListener - ? getNodeFromInstance(dispatchInstance) - : null; - var res = dispatchListener ? dispatchListener(event) : null; - event.currentTarget = null; - event._dispatchListeners = null; - event._dispatchInstances = null; - return res; -} -/** - * @param {SyntheticEvent} event - * @return {boolean} True iff number of dispatches accumulated is greater than 0. - */ + var getFiberCurrentPropsFromNode = null; + var getInstanceFromNode = null; + var getNodeFromInstance = null; + function setComponentTree( + getFiberCurrentPropsFromNodeImpl, + getInstanceFromNodeImpl, + getNodeFromInstanceImpl + ) { + getFiberCurrentPropsFromNode = getFiberCurrentPropsFromNodeImpl; + getInstanceFromNode = getInstanceFromNodeImpl; + getNodeFromInstance = getNodeFromInstanceImpl; -function hasDispatches(event) { - return !!event._dispatchListeners; -} + { + if (!getNodeFromInstance || !getInstanceFromNode) { + error( + "EventPluginUtils.setComponentTree(...): Injected " + + "module is missing getNodeFromInstance or getInstanceFromNode." + ); + } + } + } + var validateEventDispatches; -var assign = Object.assign; + { + validateEventDispatches = function (event) { + var dispatchListeners = event._dispatchListeners; + var dispatchInstances = event._dispatchInstances; + var listenersIsArr = isArray(dispatchListeners); + var listenersLen = listenersIsArr + ? dispatchListeners.length + : dispatchListeners + ? 1 + : 0; + var instancesIsArr = isArray(dispatchInstances); + var instancesLen = instancesIsArr + ? dispatchInstances.length + : dispatchInstances + ? 1 + : 0; + + if (instancesIsArr !== listenersIsArr || instancesLen !== listenersLen) { + error("EventPluginUtils: Invalid `event`."); + } + }; + } + /** + * Dispatch the event to the listener. + * @param {SyntheticEvent} event SyntheticEvent to handle + * @param {function} listener Application-level callback + * @param {*} inst Internal component instance + */ -var EVENT_POOL_SIZE = 10; -/** - * @interface Event - * @see http://www.w3.org/TR/DOM-Level-3-Events/ - */ + function executeDispatch(event, listener, inst) { + var type = event.type || "unknown-event"; + event.currentTarget = getNodeFromInstance(inst); + invokeGuardedCallbackAndCatchFirstError(type, listener, undefined, event); + event.currentTarget = null; + } + /** + * Standard/simple iteration through an event's collected dispatches. + */ -var EventInterface = { - type: null, - target: null, - // currentTarget is set when dispatching; no use in copying it here - currentTarget: function() { - return null; - }, - eventPhase: null, - bubbles: null, - cancelable: null, - timeStamp: function(event) { - return event.timeStamp || Date.now(); - }, - defaultPrevented: null, - isTrusted: null -}; - -function functionThatReturnsTrue() { - return true; -} + function executeDispatchesInOrder(event) { + var dispatchListeners = event._dispatchListeners; + var dispatchInstances = event._dispatchInstances; -function functionThatReturnsFalse() { - return false; -} -/** - * Synthetic events are dispatched by event plugins, typically in response to a - * top-level event delegation handler. - * - * These systems should generally use pooling to reduce the frequency of garbage - * collection. The system should check `isPersistent` to determine whether the - * event should be released into the pool after being dispatched. Users that - * need a persisted event should invoke `persist`. - * - * Synthetic events (and subclasses) implement the DOM Level 3 Events API by - * normalizing browser quirks. Subclasses do not necessarily have to implement a - * DOM interface; custom application-specific events can also subclass this. - * - * @param {object} dispatchConfig Configuration used to dispatch this event. - * @param {*} targetInst Marker identifying the event target. - * @param {object} nativeEvent Native browser event. - * @param {DOMEventTarget} nativeEventTarget Target node. - */ + { + validateEventDispatches(event); + } -function SyntheticEvent( - dispatchConfig, - targetInst, - nativeEvent, - nativeEventTarget -) { - { - // these have a getter/setter for warnings - delete this.nativeEvent; - delete this.preventDefault; - delete this.stopPropagation; - delete this.isDefaultPrevented; - delete this.isPropagationStopped; - } - - this.dispatchConfig = dispatchConfig; - this._targetInst = targetInst; - this.nativeEvent = nativeEvent; - this._dispatchListeners = null; - this._dispatchInstances = null; - var Interface = this.constructor.Interface; - - for (var propName in Interface) { - if (!Interface.hasOwnProperty(propName)) { - continue; - } + if (isArray(dispatchListeners)) { + for (var i = 0; i < dispatchListeners.length; i++) { + if (event.isPropagationStopped()) { + break; + } // Listeners and Instances are two parallel arrays that are always in sync. - { - delete this[propName]; // this has a getter/setter for warnings + executeDispatch(event, dispatchListeners[i], dispatchInstances[i]); + } + } else if (dispatchListeners) { + executeDispatch(event, dispatchListeners, dispatchInstances); + } + + event._dispatchListeners = null; + event._dispatchInstances = null; } + /** + * Standard/simple iteration through an event's collected dispatches, but stops + * at the first dispatch execution returning true, and returns that id. + * + * @return {?string} id of the first dispatch execution who's listener returns + * true, or null if no listener returned true. + */ - var normalize = Interface[propName]; + function executeDispatchesInOrderStopAtTrueImpl(event) { + var dispatchListeners = event._dispatchListeners; + var dispatchInstances = event._dispatchInstances; - if (normalize) { - this[propName] = normalize(nativeEvent); - } else { - if (propName === "target") { - this.target = nativeEventTarget; - } else { - this[propName] = nativeEvent[propName]; + { + validateEventDispatches(event); + } + + if (isArray(dispatchListeners)) { + for (var i = 0; i < dispatchListeners.length; i++) { + if (event.isPropagationStopped()) { + break; + } // Listeners and Instances are two parallel arrays that are always in sync. + + if (dispatchListeners[i](event, dispatchInstances[i])) { + return dispatchInstances[i]; + } + } + } else if (dispatchListeners) { + if (dispatchListeners(event, dispatchInstances)) { + return dispatchInstances; + } } + + return null; } - } + /** + * @see executeDispatchesInOrderStopAtTrueImpl + */ - var defaultPrevented = - nativeEvent.defaultPrevented != null - ? nativeEvent.defaultPrevented - : nativeEvent.returnValue === false; + function executeDispatchesInOrderStopAtTrue(event) { + var ret = executeDispatchesInOrderStopAtTrueImpl(event); + event._dispatchInstances = null; + event._dispatchListeners = null; + return ret; + } + /** + * Execution of a "direct" dispatch - there must be at most one dispatch + * accumulated on the event or it is considered an error. It doesn't really make + * sense for an event with multiple dispatches (bubbled) to keep track of the + * return values at each dispatch execution, but it does tend to make sense when + * dealing with "direct" dispatches. + * + * @return {*} The return value of executing the single dispatch. + */ - if (defaultPrevented) { - this.isDefaultPrevented = functionThatReturnsTrue; - } else { - this.isDefaultPrevented = functionThatReturnsFalse; - } + function executeDirectDispatch(event) { + { + validateEventDispatches(event); + } - this.isPropagationStopped = functionThatReturnsFalse; - return this; -} + var dispatchListener = event._dispatchListeners; + var dispatchInstance = event._dispatchInstances; -assign(SyntheticEvent.prototype, { - preventDefault: function() { - this.defaultPrevented = true; - var event = this.nativeEvent; + if (isArray(dispatchListener)) { + throw new Error("executeDirectDispatch(...): Invalid `event`."); + } - if (!event) { - return; + event.currentTarget = dispatchListener + ? getNodeFromInstance(dispatchInstance) + : null; + var res = dispatchListener ? dispatchListener(event) : null; + event.currentTarget = null; + event._dispatchListeners = null; + event._dispatchInstances = null; + return res; } + /** + * @param {SyntheticEvent} event + * @return {boolean} True iff number of dispatches accumulated is greater than 0. + */ - if (event.preventDefault) { - event.preventDefault(); - } else if (typeof event.returnValue !== "unknown") { - event.returnValue = false; + function hasDispatches(event) { + return !!event._dispatchListeners; } - this.isDefaultPrevented = functionThatReturnsTrue; - }, - stopPropagation: function() { - var event = this.nativeEvent; + var assign = Object.assign; + + var EVENT_POOL_SIZE = 10; + /** + * @interface Event + * @see http://www.w3.org/TR/DOM-Level-3-Events/ + */ + + var EventInterface = { + type: null, + target: null, + // currentTarget is set when dispatching; no use in copying it here + currentTarget: function () { + return null; + }, + eventPhase: null, + bubbles: null, + cancelable: null, + timeStamp: function (event) { + return event.timeStamp || Date.now(); + }, + defaultPrevented: null, + isTrusted: null + }; - if (!event) { - return; + function functionThatReturnsTrue() { + return true; } - if (event.stopPropagation) { - event.stopPropagation(); - } else if (typeof event.cancelBubble !== "unknown") { - // The ChangeEventPlugin registers a "propertychange" event for - // IE. This event does not support bubbling or cancelling, and - // any references to cancelBubble throw "Member not found". A - // typeof check of "unknown" circumvents this issue (and is also - // IE specific). - event.cancelBubble = true; + function functionThatReturnsFalse() { + return false; } + /** + * Synthetic events are dispatched by event plugins, typically in response to a + * top-level event delegation handler. + * + * These systems should generally use pooling to reduce the frequency of garbage + * collection. The system should check `isPersistent` to determine whether the + * event should be released into the pool after being dispatched. Users that + * need a persisted event should invoke `persist`. + * + * Synthetic events (and subclasses) implement the DOM Level 3 Events API by + * normalizing browser quirks. Subclasses do not necessarily have to implement a + * DOM interface; custom application-specific events can also subclass this. + * + * @param {object} dispatchConfig Configuration used to dispatch this event. + * @param {*} targetInst Marker identifying the event target. + * @param {object} nativeEvent Native browser event. + * @param {DOMEventTarget} nativeEventTarget Target node. + */ + + function SyntheticEvent( + dispatchConfig, + targetInst, + nativeEvent, + nativeEventTarget + ) { + { + // these have a getter/setter for warnings + delete this.nativeEvent; + delete this.preventDefault; + delete this.stopPropagation; + delete this.isDefaultPrevented; + delete this.isPropagationStopped; + } + + this.dispatchConfig = dispatchConfig; + this._targetInst = targetInst; + this.nativeEvent = nativeEvent; + this._dispatchListeners = null; + this._dispatchInstances = null; + var Interface = this.constructor.Interface; + + for (var propName in Interface) { + if (!Interface.hasOwnProperty(propName)) { + continue; + } - this.isPropagationStopped = functionThatReturnsTrue; - }, + { + delete this[propName]; // this has a getter/setter for warnings + } - /** - * We release all dispatched `SyntheticEvent`s after each event loop, adding - * them back into the pool. This allows a way to hold onto a reference that - * won't be added back into the pool. - */ - persist: function() { - this.isPersistent = functionThatReturnsTrue; - }, + var normalize = Interface[propName]; - /** - * Checks if this event should be released back into the pool. - * - * @return {boolean} True if this should not be released, false otherwise. - */ - isPersistent: functionThatReturnsFalse, + if (normalize) { + this[propName] = normalize(nativeEvent); + } else { + if (propName === "target") { + this.target = nativeEventTarget; + } else { + this[propName] = nativeEvent[propName]; + } + } + } - /** - * `PooledClass` looks for `destructor` on each instance it releases. - */ - destructor: function() { - var Interface = this.constructor.Interface; + var defaultPrevented = + nativeEvent.defaultPrevented != null + ? nativeEvent.defaultPrevented + : nativeEvent.returnValue === false; - for (var propName in Interface) { - { - Object.defineProperty( - this, - propName, - getPooledWarningPropertyDefinition(propName, Interface[propName]) - ); + if (defaultPrevented) { + this.isDefaultPrevented = functionThatReturnsTrue; + } else { + this.isDefaultPrevented = functionThatReturnsFalse; } + + this.isPropagationStopped = functionThatReturnsFalse; + return this; } - this.dispatchConfig = null; - this._targetInst = null; - this.nativeEvent = null; - this.isDefaultPrevented = functionThatReturnsFalse; - this.isPropagationStopped = functionThatReturnsFalse; - this._dispatchListeners = null; - this._dispatchInstances = null; + assign(SyntheticEvent.prototype, { + preventDefault: function () { + this.defaultPrevented = true; + var event = this.nativeEvent; - { - Object.defineProperty( - this, - "nativeEvent", - getPooledWarningPropertyDefinition("nativeEvent", null) - ); - Object.defineProperty( - this, - "isDefaultPrevented", - getPooledWarningPropertyDefinition( - "isDefaultPrevented", - functionThatReturnsFalse - ) - ); - Object.defineProperty( - this, - "isPropagationStopped", - getPooledWarningPropertyDefinition( - "isPropagationStopped", - functionThatReturnsFalse - ) - ); - Object.defineProperty( - this, - "preventDefault", - getPooledWarningPropertyDefinition("preventDefault", function() {}) - ); - Object.defineProperty( - this, - "stopPropagation", - getPooledWarningPropertyDefinition("stopPropagation", function() {}) - ); - } - } -}); -SyntheticEvent.Interface = EventInterface; -/** - * Helper to reduce boilerplate when creating subclasses. - */ + if (!event) { + return; + } -SyntheticEvent.extend = function(Interface) { - var Super = this; + if (event.preventDefault) { + event.preventDefault(); + } else if (typeof event.returnValue !== "unknown") { + event.returnValue = false; + } - var E = function() {}; + this.isDefaultPrevented = functionThatReturnsTrue; + }, + stopPropagation: function () { + var event = this.nativeEvent; - E.prototype = Super.prototype; - var prototype = new E(); + if (!event) { + return; + } - function Class() { - return Super.apply(this, arguments); - } + if (event.stopPropagation) { + event.stopPropagation(); + } else if (typeof event.cancelBubble !== "unknown") { + // The ChangeEventPlugin registers a "propertychange" event for + // IE. This event does not support bubbling or cancelling, and + // any references to cancelBubble throw "Member not found". A + // typeof check of "unknown" circumvents this issue (and is also + // IE specific). + event.cancelBubble = true; + } - assign(prototype, Class.prototype); - Class.prototype = prototype; - Class.prototype.constructor = Class; - Class.Interface = assign({}, Super.Interface, Interface); - Class.extend = Super.extend; - addEventPoolingTo(Class); - return Class; -}; + this.isPropagationStopped = functionThatReturnsTrue; + }, + + /** + * We release all dispatched `SyntheticEvent`s after each event loop, adding + * them back into the pool. This allows a way to hold onto a reference that + * won't be added back into the pool. + */ + persist: function () { + this.isPersistent = functionThatReturnsTrue; + }, + + /** + * Checks if this event should be released back into the pool. + * + * @return {boolean} True if this should not be released, false otherwise. + */ + isPersistent: functionThatReturnsFalse, + + /** + * `PooledClass` looks for `destructor` on each instance it releases. + */ + destructor: function () { + var Interface = this.constructor.Interface; + + for (var propName in Interface) { + { + Object.defineProperty( + this, + propName, + getPooledWarningPropertyDefinition(propName, Interface[propName]) + ); + } + } -addEventPoolingTo(SyntheticEvent); -/** - * Helper to nullify syntheticEvent instance properties when destructing - * - * @param {String} propName - * @param {?object} getVal - * @return {object} defineProperty object - */ + this.dispatchConfig = null; + this._targetInst = null; + this.nativeEvent = null; + this.isDefaultPrevented = functionThatReturnsFalse; + this.isPropagationStopped = functionThatReturnsFalse; + this._dispatchListeners = null; + this._dispatchInstances = null; -function getPooledWarningPropertyDefinition(propName, getVal) { - function set(val) { - var action = isFunction ? "setting the method" : "setting the property"; - warn(action, "This is effectively a no-op"); - return val; - } - - function get() { - var action = isFunction ? "accessing the method" : "accessing the property"; - var result = isFunction - ? "This is a no-op function" - : "This is set to null"; - warn(action, result); - return getVal; - } - - function warn(action, result) { - { - error( - "This synthetic event is reused for performance reasons. If you're seeing this, " + - "you're %s `%s` on a released/nullified synthetic event. %s. " + - "If you must keep the original synthetic event around, use event.persist(). " + - "See https://react.dev/link/event-pooling for more information.", - action, - propName, - result - ); - } - } + { + Object.defineProperty( + this, + "nativeEvent", + getPooledWarningPropertyDefinition("nativeEvent", null) + ); + Object.defineProperty( + this, + "isDefaultPrevented", + getPooledWarningPropertyDefinition( + "isDefaultPrevented", + functionThatReturnsFalse + ) + ); + Object.defineProperty( + this, + "isPropagationStopped", + getPooledWarningPropertyDefinition( + "isPropagationStopped", + functionThatReturnsFalse + ) + ); + Object.defineProperty( + this, + "preventDefault", + getPooledWarningPropertyDefinition("preventDefault", function () { }) + ); + Object.defineProperty( + this, + "stopPropagation", + getPooledWarningPropertyDefinition("stopPropagation", function () { }) + ); + } + } + }); + SyntheticEvent.Interface = EventInterface; + /** + * Helper to reduce boilerplate when creating subclasses. + */ - var isFunction = typeof getVal === "function"; - return { - configurable: true, - set: set, - get: get - }; -} + SyntheticEvent.extend = function (Interface) { + var Super = this; -function createOrGetPooledEvent( - dispatchConfig, - targetInst, - nativeEvent, - nativeInst -) { - var EventConstructor = this; - - if (EventConstructor.eventPool.length) { - var instance = EventConstructor.eventPool.pop(); - EventConstructor.call( - instance, + var E = function () { }; + + E.prototype = Super.prototype; + var prototype = new E(); + + function Class() { + return Super.apply(this, arguments); + } + + assign(prototype, Class.prototype); + Class.prototype = prototype; + Class.prototype.constructor = Class; + Class.Interface = assign({}, Super.Interface, Interface); + Class.extend = Super.extend; + addEventPoolingTo(Class); + return Class; + }; + + addEventPoolingTo(SyntheticEvent); + /** + * Helper to nullify syntheticEvent instance properties when destructing + * + * @param {String} propName + * @param {?object} getVal + * @return {object} defineProperty object + */ + + function getPooledWarningPropertyDefinition(propName, getVal) { + function set(val) { + var action = isFunction ? "setting the method" : "setting the property"; + warn(action, "This is effectively a no-op"); + return val; + } + + function get() { + var action = isFunction ? "accessing the method" : "accessing the property"; + var result = isFunction + ? "This is a no-op function" + : "This is set to null"; + warn(action, result); + return getVal; + } + + function warn(action, result) { + { + error( + "This synthetic event is reused for performance reasons. If you're seeing this, " + + "you're %s `%s` on a released/nullified synthetic event. %s. " + + "If you must keep the original synthetic event around, use event.persist(). " + + "See https://react.dev/link/event-pooling for more information.", + action, + propName, + result + ); + } + } + + var isFunction = typeof getVal === "function"; + return { + configurable: true, + set: set, + get: get + }; + } + + function createOrGetPooledEvent( dispatchConfig, targetInst, nativeEvent, nativeInst - ); - return instance; - } - - return new EventConstructor( - dispatchConfig, - targetInst, - nativeEvent, - nativeInst - ); -} - -function releasePooledEvent(event) { - var EventConstructor = this; + ) { + var EventConstructor = this; - if (!(event instanceof EventConstructor)) { - throw new Error( - "Trying to release an event instance into a pool of a different type." - ); - } + if (EventConstructor.eventPool.length) { + var instance = EventConstructor.eventPool.pop(); + EventConstructor.call( + instance, + dispatchConfig, + targetInst, + nativeEvent, + nativeInst + ); + return instance; + } - event.destructor(); + return new EventConstructor( + dispatchConfig, + targetInst, + nativeEvent, + nativeInst + ); + } - if (EventConstructor.eventPool.length < EVENT_POOL_SIZE) { - EventConstructor.eventPool.push(event); - } -} + function releasePooledEvent(event) { + var EventConstructor = this; -function addEventPoolingTo(EventConstructor) { - EventConstructor.getPooled = createOrGetPooledEvent; - EventConstructor.eventPool = []; - EventConstructor.release = releasePooledEvent; -} + if (!(event instanceof EventConstructor)) { + throw new Error( + "Trying to release an event instance into a pool of a different type." + ); + } -/** - * `touchHistory` isn't actually on the native event, but putting it in the - * interface will ensure that it is cleaned up when pooled/destroyed. The - * `ResponderEventPlugin` will populate it appropriately. - */ + event.destructor(); -var ResponderSyntheticEvent = SyntheticEvent.extend({ - touchHistory: function(nativeEvent) { - return null; // Actually doesn't even look at the native event. - } -}); - -var TOP_TOUCH_START = "topTouchStart"; -var TOP_TOUCH_MOVE = "topTouchMove"; -var TOP_TOUCH_END = "topTouchEnd"; -var TOP_TOUCH_CANCEL = "topTouchCancel"; -var TOP_SCROLL = "topScroll"; -var TOP_SELECTION_CHANGE = "topSelectionChange"; -function isStartish(topLevelType) { - return topLevelType === TOP_TOUCH_START; -} -function isMoveish(topLevelType) { - return topLevelType === TOP_TOUCH_MOVE; -} -function isEndish(topLevelType) { - return topLevelType === TOP_TOUCH_END || topLevelType === TOP_TOUCH_CANCEL; -} -var startDependencies = [TOP_TOUCH_START]; -var moveDependencies = [TOP_TOUCH_MOVE]; -var endDependencies = [TOP_TOUCH_CANCEL, TOP_TOUCH_END]; + if (EventConstructor.eventPool.length < EVENT_POOL_SIZE) { + EventConstructor.eventPool.push(event); + } + } -/** - * Tracks the position and time of each active touch by `touch.identifier`. We - * should typically only see IDs in the range of 1-20 because IDs get recycled - * when touches end and start again. - */ + function addEventPoolingTo(EventConstructor) { + EventConstructor.getPooled = createOrGetPooledEvent; + EventConstructor.eventPool = []; + EventConstructor.release = releasePooledEvent; + } -var MAX_TOUCH_BANK = 20; -var touchBank = []; -var touchHistory = { - touchBank: touchBank, - numberActiveTouches: 0, - // If there is only one active touch, we remember its location. This prevents - // us having to loop through all of the touches all the time in the most - // common case. - indexOfSingleActiveTouch: -1, - mostRecentTimeStamp: 0 -}; - -function timestampForTouch(touch) { - // The legacy internal implementation provides "timeStamp", which has been - // renamed to "timestamp". Let both work for now while we iron it out - // TODO (evv): rename timeStamp to timestamp in internal code - return touch.timeStamp || touch.timestamp; -} -/** - * TODO: Instead of making gestures recompute filtered velocity, we could - * include a built in velocity computation that can be reused globally. - */ + /** + * `touchHistory` isn't actually on the native event, but putting it in the + * interface will ensure that it is cleaned up when pooled/destroyed. The + * `ResponderEventPlugin` will populate it appropriately. + */ -function createTouchRecord(touch) { - return { - touchActive: true, - startPageX: touch.pageX, - startPageY: touch.pageY, - startTimeStamp: timestampForTouch(touch), - currentPageX: touch.pageX, - currentPageY: touch.pageY, - currentTimeStamp: timestampForTouch(touch), - previousPageX: touch.pageX, - previousPageY: touch.pageY, - previousTimeStamp: timestampForTouch(touch) - }; -} + var ResponderSyntheticEvent = SyntheticEvent.extend({ + touchHistory: function (nativeEvent) { + return null; // Actually doesn't even look at the native event. + } + }); -function resetTouchRecord(touchRecord, touch) { - touchRecord.touchActive = true; - touchRecord.startPageX = touch.pageX; - touchRecord.startPageY = touch.pageY; - touchRecord.startTimeStamp = timestampForTouch(touch); - touchRecord.currentPageX = touch.pageX; - touchRecord.currentPageY = touch.pageY; - touchRecord.currentTimeStamp = timestampForTouch(touch); - touchRecord.previousPageX = touch.pageX; - touchRecord.previousPageY = touch.pageY; - touchRecord.previousTimeStamp = timestampForTouch(touch); -} + var TOP_TOUCH_START = "topTouchStart"; + var TOP_TOUCH_MOVE = "topTouchMove"; + var TOP_TOUCH_END = "topTouchEnd"; + var TOP_TOUCH_CANCEL = "topTouchCancel"; + var TOP_SCROLL = "topScroll"; + var TOP_SELECTION_CHANGE = "topSelectionChange"; + function isStartish(topLevelType) { + return topLevelType === TOP_TOUCH_START; + } + function isMoveish(topLevelType) { + return topLevelType === TOP_TOUCH_MOVE; + } + function isEndish(topLevelType) { + return topLevelType === TOP_TOUCH_END || topLevelType === TOP_TOUCH_CANCEL; + } + var startDependencies = [TOP_TOUCH_START]; + var moveDependencies = [TOP_TOUCH_MOVE]; + var endDependencies = [TOP_TOUCH_CANCEL, TOP_TOUCH_END]; -function getTouchIdentifier(_ref) { - var identifier = _ref.identifier; + /** + * Tracks the position and time of each active touch by `touch.identifier`. We + * should typically only see IDs in the range of 1-20 because IDs get recycled + * when touches end and start again. + */ - if (identifier == null) { - throw new Error("Touch object is missing identifier."); - } + var MAX_TOUCH_BANK = 20; + var touchBank = []; + var touchHistory = { + touchBank: touchBank, + numberActiveTouches: 0, + // If there is only one active touch, we remember its location. This prevents + // us having to loop through all of the touches all the time in the most + // common case. + indexOfSingleActiveTouch: -1, + mostRecentTimeStamp: 0 + }; - { - if (identifier > MAX_TOUCH_BANK) { - error( - "Touch identifier %s is greater than maximum supported %s which causes " + - "performance issues backfilling array locations for all of the indices.", - identifier, - MAX_TOUCH_BANK - ); + function timestampForTouch(touch) { + // The legacy internal implementation provides "timeStamp", which has been + // renamed to "timestamp". Let both work for now while we iron it out + // TODO (evv): rename timeStamp to timestamp in internal code + return touch.timeStamp || touch.timestamp; } - } + /** + * TODO: Instead of making gestures recompute filtered velocity, we could + * include a built in velocity computation that can be reused globally. + */ - return identifier; -} + function createTouchRecord(touch) { + return { + touchActive: true, + startPageX: touch.pageX, + startPageY: touch.pageY, + startTimeStamp: timestampForTouch(touch), + currentPageX: touch.pageX, + currentPageY: touch.pageY, + currentTimeStamp: timestampForTouch(touch), + previousPageX: touch.pageX, + previousPageY: touch.pageY, + previousTimeStamp: timestampForTouch(touch) + }; + } -function recordTouchStart(touch) { - var identifier = getTouchIdentifier(touch); - var touchRecord = touchBank[identifier]; + function resetTouchRecord(touchRecord, touch) { + touchRecord.touchActive = true; + touchRecord.startPageX = touch.pageX; + touchRecord.startPageY = touch.pageY; + touchRecord.startTimeStamp = timestampForTouch(touch); + touchRecord.currentPageX = touch.pageX; + touchRecord.currentPageY = touch.pageY; + touchRecord.currentTimeStamp = timestampForTouch(touch); + touchRecord.previousPageX = touch.pageX; + touchRecord.previousPageY = touch.pageY; + touchRecord.previousTimeStamp = timestampForTouch(touch); + } - if (touchRecord) { - resetTouchRecord(touchRecord, touch); - } else { - touchBank[identifier] = createTouchRecord(touch); - } + function getTouchIdentifier(_ref) { + var identifier = _ref.identifier; - touchHistory.mostRecentTimeStamp = timestampForTouch(touch); -} + if (identifier == null) { + throw new Error("Touch object is missing identifier."); + } -function recordTouchMove(touch) { - var touchRecord = touchBank[getTouchIdentifier(touch)]; - - if (touchRecord) { - touchRecord.touchActive = true; - touchRecord.previousPageX = touchRecord.currentPageX; - touchRecord.previousPageY = touchRecord.currentPageY; - touchRecord.previousTimeStamp = touchRecord.currentTimeStamp; - touchRecord.currentPageX = touch.pageX; - touchRecord.currentPageY = touch.pageY; - touchRecord.currentTimeStamp = timestampForTouch(touch); - touchHistory.mostRecentTimeStamp = timestampForTouch(touch); - } else { - { - warn( - "Cannot record touch move without a touch start.\n" + - "Touch Move: %s\n" + - "Touch Bank: %s", - printTouch(touch), - printTouchBank() - ); - } - } -} + { + if (identifier > MAX_TOUCH_BANK) { + error( + "Touch identifier %s is greater than maximum supported %s which causes " + + "performance issues backfilling array locations for all of the indices.", + identifier, + MAX_TOUCH_BANK + ); + } + } -function recordTouchEnd(touch) { - var touchRecord = touchBank[getTouchIdentifier(touch)]; - - if (touchRecord) { - touchRecord.touchActive = false; - touchRecord.previousPageX = touchRecord.currentPageX; - touchRecord.previousPageY = touchRecord.currentPageY; - touchRecord.previousTimeStamp = touchRecord.currentTimeStamp; - touchRecord.currentPageX = touch.pageX; - touchRecord.currentPageY = touch.pageY; - touchRecord.currentTimeStamp = timestampForTouch(touch); - touchHistory.mostRecentTimeStamp = timestampForTouch(touch); - } else { - { - warn( - "Cannot record touch end without a touch start.\n" + - "Touch End: %s\n" + - "Touch Bank: %s", - printTouch(touch), - printTouchBank() - ); + return identifier; } - } -} -function printTouch(touch) { - return JSON.stringify({ - identifier: touch.identifier, - pageX: touch.pageX, - pageY: touch.pageY, - timestamp: timestampForTouch(touch) - }); -} + function recordTouchStart(touch) { + var identifier = getTouchIdentifier(touch); + var touchRecord = touchBank[identifier]; -function printTouchBank() { - var printed = JSON.stringify(touchBank.slice(0, MAX_TOUCH_BANK)); + if (touchRecord) { + resetTouchRecord(touchRecord, touch); + } else { + touchBank[identifier] = createTouchRecord(touch); + } - if (touchBank.length > MAX_TOUCH_BANK) { - printed += " (original size: " + touchBank.length + ")"; - } + touchHistory.mostRecentTimeStamp = timestampForTouch(touch); + } - return printed; -} + function recordTouchMove(touch) { + var touchRecord = touchBank[getTouchIdentifier(touch)]; -var instrumentationCallback; -var ResponderTouchHistoryStore = { - /** - * Registers a listener which can be used to instrument every touch event. - */ - instrument: function(callback) { - instrumentationCallback = callback; - }, - recordTouchTrack: function(topLevelType, nativeEvent) { - if (instrumentationCallback != null) { - instrumentationCallback(topLevelType, nativeEvent); - } - - if (isMoveish(topLevelType)) { - nativeEvent.changedTouches.forEach(recordTouchMove); - } else if (isStartish(topLevelType)) { - nativeEvent.changedTouches.forEach(recordTouchStart); - touchHistory.numberActiveTouches = nativeEvent.touches.length; - - if (touchHistory.numberActiveTouches === 1) { - touchHistory.indexOfSingleActiveTouch = - nativeEvent.touches[0].identifier; - } - } else if (isEndish(topLevelType)) { - nativeEvent.changedTouches.forEach(recordTouchEnd); - touchHistory.numberActiveTouches = nativeEvent.touches.length; - - if (touchHistory.numberActiveTouches === 1) { - for (var i = 0; i < touchBank.length; i++) { - var touchTrackToCheck = touchBank[i]; - - if (touchTrackToCheck != null && touchTrackToCheck.touchActive) { - touchHistory.indexOfSingleActiveTouch = i; - break; - } + if (touchRecord) { + touchRecord.touchActive = true; + touchRecord.previousPageX = touchRecord.currentPageX; + touchRecord.previousPageY = touchRecord.currentPageY; + touchRecord.previousTimeStamp = touchRecord.currentTimeStamp; + touchRecord.currentPageX = touch.pageX; + touchRecord.currentPageY = touch.pageY; + touchRecord.currentTimeStamp = timestampForTouch(touch); + touchHistory.mostRecentTimeStamp = timestampForTouch(touch); + } else { + { + warn( + "Cannot record touch move without a touch start.\n" + + "Touch Move: %s\n" + + "Touch Bank: %s", + printTouch(touch), + printTouchBank() + ); } + } + } - { - var activeRecord = touchBank[touchHistory.indexOfSingleActiveTouch]; + function recordTouchEnd(touch) { + var touchRecord = touchBank[getTouchIdentifier(touch)]; - if (activeRecord == null || !activeRecord.touchActive) { - error("Cannot find single active touch."); - } + if (touchRecord) { + touchRecord.touchActive = false; + touchRecord.previousPageX = touchRecord.currentPageX; + touchRecord.previousPageY = touchRecord.currentPageY; + touchRecord.previousTimeStamp = touchRecord.currentTimeStamp; + touchRecord.currentPageX = touch.pageX; + touchRecord.currentPageY = touch.pageY; + touchRecord.currentTimeStamp = timestampForTouch(touch); + touchHistory.mostRecentTimeStamp = timestampForTouch(touch); + } else { + { + warn( + "Cannot record touch end without a touch start.\n" + + "Touch End: %s\n" + + "Touch Bank: %s", + printTouch(touch), + printTouchBank() + ); } } } - }, - touchHistory: touchHistory -}; - -/** - * Accumulates items that must not be null or undefined. - * - * This is used to conserve memory by avoiding array allocations. - * - * @return {*|array<*>} An accumulation of items. - */ -function accumulate(current, next) { - if (next == null) { - throw new Error( - "accumulate(...): Accumulated items must not be null or undefined." - ); - } + function printTouch(touch) { + return JSON.stringify({ + identifier: touch.identifier, + pageX: touch.pageX, + pageY: touch.pageY, + timestamp: timestampForTouch(touch) + }); + } - if (current == null) { - return next; - } // Both are not empty. Warning: Never call x.concat(y) when you are not - // certain that x is an Array (x could be a string with concat method). + function printTouchBank() { + var printed = JSON.stringify(touchBank.slice(0, MAX_TOUCH_BANK)); - if (isArray(current)) { - return current.concat(next); - } + if (touchBank.length > MAX_TOUCH_BANK) { + printed += " (original size: " + touchBank.length + ")"; + } - if (isArray(next)) { - return [current].concat(next); - } + return printed; + } - return [current, next]; -} + var instrumentationCallback; + var ResponderTouchHistoryStore = { + /** + * Registers a listener which can be used to instrument every touch event. + */ + instrument: function (callback) { + instrumentationCallback = callback; + }, + recordTouchTrack: function (topLevelType, nativeEvent) { + if (instrumentationCallback != null) { + instrumentationCallback(topLevelType, nativeEvent); + } -/** - * Accumulates items that must not be null or undefined into the first one. This - * is used to conserve memory by avoiding array allocations, and thus sacrifices - * API cleanness. Since `current` can be null before being passed in and not - * null after this function, make sure to assign it back to `current`: - * - * `a = accumulateInto(a, b);` - * - * This API should be sparingly used. Try `accumulate` for something cleaner. - * - * @return {*|array<*>} An accumulation of items. - */ + if (isMoveish(topLevelType)) { + nativeEvent.changedTouches.forEach(recordTouchMove); + } else if (isStartish(topLevelType)) { + nativeEvent.changedTouches.forEach(recordTouchStart); + touchHistory.numberActiveTouches = nativeEvent.touches.length; -function accumulateInto(current, next) { - if (next == null) { - throw new Error( - "accumulateInto(...): Accumulated items must not be null or undefined." - ); - } + if (touchHistory.numberActiveTouches === 1) { + touchHistory.indexOfSingleActiveTouch = + nativeEvent.touches[0].identifier; + } + } else if (isEndish(topLevelType)) { + nativeEvent.changedTouches.forEach(recordTouchEnd); + touchHistory.numberActiveTouches = nativeEvent.touches.length; - if (current == null) { - return next; - } // Both are not empty. Warning: Never call x.concat(y) when you are not - // certain that x is an Array (x could be a string with concat method). + if (touchHistory.numberActiveTouches === 1) { + for (var i = 0; i < touchBank.length; i++) { + var touchTrackToCheck = touchBank[i]; - if (isArray(current)) { - if (isArray(next)) { - current.push.apply(current, next); - return current; - } + if (touchTrackToCheck != null && touchTrackToCheck.touchActive) { + touchHistory.indexOfSingleActiveTouch = i; + break; + } + } - current.push(next); - return current; - } + { + var activeRecord = touchBank[touchHistory.indexOfSingleActiveTouch]; - if (isArray(next)) { - // A bit too dangerous to mutate `next`. - return [current].concat(next); - } + if (activeRecord == null || !activeRecord.touchActive) { + error("Cannot find single active touch."); + } + } + } + } + }, + touchHistory: touchHistory + }; - return [current, next]; -} + /** + * Accumulates items that must not be null or undefined. + * + * This is used to conserve memory by avoiding array allocations. + * + * @return {*|array<*>} An accumulation of items. + */ -/** - * @param {array} arr an "accumulation" of items which is either an Array or - * a single item. Useful when paired with the `accumulate` module. This is a - * simple utility that allows us to reason about a collection of items, but - * handling the case when there is exactly one item (and we do not need to - * allocate an array). - * @param {function} cb Callback invoked with each element or a collection. - * @param {?} [scope] Scope used as `this` in a callback. - */ -function forEachAccumulated(arr, cb, scope) { - if (Array.isArray(arr)) { - arr.forEach(cb, scope); - } else if (arr) { - cb.call(scope, arr); - } -} + function accumulate(current, next) { + if (next == null) { + throw new Error( + "accumulate(...): Accumulated items must not be null or undefined." + ); + } -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; + if (current == null) { + return next; + } // Both are not empty. Warning: Never call x.concat(y) when you are not + // certain that x is an Array (x could be a string with concat method). -/** - * Instance of element that should respond to touch/move types of interactions, - * as indicated explicitly by relevant callbacks. - */ + if (isArray(current)) { + return current.concat(next); + } -var responderInst = null; -/** - * Count of current touches. A textInput should become responder iff the - * selection changes while there is a touch on the screen. - */ + if (isArray(next)) { + return [current].concat(next); + } -var trackedTouchCount = 0; + return [current, next]; + } -var changeResponder = function(nextResponderInst, blockHostResponder) { - var oldResponderInst = responderInst; - responderInst = nextResponderInst; + /** + * Accumulates items that must not be null or undefined into the first one. This + * is used to conserve memory by avoiding array allocations, and thus sacrifices + * API cleanness. Since `current` can be null before being passed in and not + * null after this function, make sure to assign it back to `current`: + * + * `a = accumulateInto(a, b);` + * + * This API should be sparingly used. Try `accumulate` for something cleaner. + * + * @return {*|array<*>} An accumulation of items. + */ - if (ResponderEventPlugin.GlobalResponderHandler !== null) { - ResponderEventPlugin.GlobalResponderHandler.onChange( - oldResponderInst, - nextResponderInst, - blockHostResponder - ); - } -}; - -var eventTypes = { - /** - * On a `touchStart`/`mouseDown`, is it desired that this element become the - * responder? - */ - startShouldSetResponder: { - phasedRegistrationNames: { - bubbled: "onStartShouldSetResponder", - captured: "onStartShouldSetResponderCapture" - }, - dependencies: startDependencies - }, - - /** - * On a `scroll`, is it desired that this element become the responder? This - * is usually not needed, but should be used to retroactively infer that a - * `touchStart` had occurred during momentum scroll. During a momentum scroll, - * a touch start will be immediately followed by a scroll event if the view is - * currently scrolling. - * - * TODO: This shouldn't bubble. - */ - scrollShouldSetResponder: { - phasedRegistrationNames: { - bubbled: "onScrollShouldSetResponder", - captured: "onScrollShouldSetResponderCapture" - }, - dependencies: [TOP_SCROLL] - }, - - /** - * On text selection change, should this element become the responder? This - * is needed for text inputs or other views with native selection, so the - * JS view can claim the responder. - * - * TODO: This shouldn't bubble. - */ - selectionChangeShouldSetResponder: { - phasedRegistrationNames: { - bubbled: "onSelectionChangeShouldSetResponder", - captured: "onSelectionChangeShouldSetResponderCapture" - }, - dependencies: [TOP_SELECTION_CHANGE] - }, - - /** - * On a `touchMove`/`mouseMove`, is it desired that this element become the - * responder? - */ - moveShouldSetResponder: { - phasedRegistrationNames: { - bubbled: "onMoveShouldSetResponder", - captured: "onMoveShouldSetResponderCapture" - }, - dependencies: moveDependencies - }, - - /** - * Direct responder events dispatched directly to responder. Do not bubble. - */ - responderStart: { - registrationName: "onResponderStart", - dependencies: startDependencies - }, - responderMove: { - registrationName: "onResponderMove", - dependencies: moveDependencies - }, - responderEnd: { - registrationName: "onResponderEnd", - dependencies: endDependencies - }, - responderRelease: { - registrationName: "onResponderRelease", - dependencies: endDependencies - }, - responderTerminationRequest: { - registrationName: "onResponderTerminationRequest", - dependencies: [] - }, - responderGrant: { - registrationName: "onResponderGrant", - dependencies: [] - }, - responderReject: { - registrationName: "onResponderReject", - dependencies: [] - }, - responderTerminate: { - registrationName: "onResponderTerminate", - dependencies: [] - } -}; // Start of inline: the below functions were inlined from -// EventPropagator.js, as they deviated from ReactDOM's newer -// implementations. - -function getParent(inst) { - do { - inst = inst.return; // TODO: If this is a HostRoot we might want to bail out. - // That is depending on if we want nested subtrees (layers) to bubble - // events to their parent. We could also go through parentNode on the - // host node but that wouldn't work for React Native and doesn't let us - // do the portal feature. - } while (inst && inst.tag !== HostComponent); - - if (inst) { - return inst; - } - - return null; -} -/** - * Return the lowest common ancestor of A and B, or null if they are in - * different trees. - */ + function accumulateInto(current, next) { + if (next == null) { + throw new Error( + "accumulateInto(...): Accumulated items must not be null or undefined." + ); + } -function getLowestCommonAncestor(instA, instB) { - var depthA = 0; + if (current == null) { + return next; + } // Both are not empty. Warning: Never call x.concat(y) when you are not + // certain that x is an Array (x could be a string with concat method). - for (var tempA = instA; tempA; tempA = getParent(tempA)) { - depthA++; - } + if (isArray(current)) { + if (isArray(next)) { + current.push.apply(current, next); + return current; + } - var depthB = 0; + current.push(next); + return current; + } - for (var tempB = instB; tempB; tempB = getParent(tempB)) { - depthB++; - } // If A is deeper, crawl up. + if (isArray(next)) { + // A bit too dangerous to mutate `next`. + return [current].concat(next); + } - while (depthA - depthB > 0) { - instA = getParent(instA); - depthA--; - } // If B is deeper, crawl up. + return [current, next]; + } - while (depthB - depthA > 0) { - instB = getParent(instB); - depthB--; - } // Walk in lockstep until we find a match. + /** + * @param {array} arr an "accumulation" of items which is either an Array or + * a single item. Useful when paired with the `accumulate` module. This is a + * simple utility that allows us to reason about a collection of items, but + * handling the case when there is exactly one item (and we do not need to + * allocate an array). + * @param {function} cb Callback invoked with each element or a collection. + * @param {?} [scope] Scope used as `this` in a callback. + */ + function forEachAccumulated(arr, cb, scope) { + if (Array.isArray(arr)) { + arr.forEach(cb, scope); + } else if (arr) { + cb.call(scope, arr); + } + } + + 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 depth = depthA; + /** + * Instance of element that should respond to touch/move types of interactions, + * as indicated explicitly by relevant callbacks. + */ - while (depth--) { - if (instA === instB || instA === instB.alternate) { - return instA; - } + var responderInst = null; + /** + * Count of current touches. A textInput should become responder iff the + * selection changes while there is a touch on the screen. + */ - instA = getParent(instA); - instB = getParent(instB); - } + var trackedTouchCount = 0; - return null; -} -/** - * Return if A is an ancestor of B. - */ + var changeResponder = function (nextResponderInst, blockHostResponder) { + var oldResponderInst = responderInst; + responderInst = nextResponderInst; -function isAncestor(instA, instB) { - while (instB) { - if (instA === instB || instA === instB.alternate) { - return true; - } + if (ResponderEventPlugin.GlobalResponderHandler !== null) { + ResponderEventPlugin.GlobalResponderHandler.onChange( + oldResponderInst, + nextResponderInst, + blockHostResponder + ); + } + }; - instB = getParent(instB); - } + var eventTypes = { + /** + * On a `touchStart`/`mouseDown`, is it desired that this element become the + * responder? + */ + startShouldSetResponder: { + phasedRegistrationNames: { + bubbled: "onStartShouldSetResponder", + captured: "onStartShouldSetResponderCapture" + }, + dependencies: startDependencies + }, + + /** + * On a `scroll`, is it desired that this element become the responder? This + * is usually not needed, but should be used to retroactively infer that a + * `touchStart` had occurred during momentum scroll. During a momentum scroll, + * a touch start will be immediately followed by a scroll event if the view is + * currently scrolling. + * + * TODO: This shouldn't bubble. + */ + scrollShouldSetResponder: { + phasedRegistrationNames: { + bubbled: "onScrollShouldSetResponder", + captured: "onScrollShouldSetResponderCapture" + }, + dependencies: [TOP_SCROLL] + }, + + /** + * On text selection change, should this element become the responder? This + * is needed for text inputs or other views with native selection, so the + * JS view can claim the responder. + * + * TODO: This shouldn't bubble. + */ + selectionChangeShouldSetResponder: { + phasedRegistrationNames: { + bubbled: "onSelectionChangeShouldSetResponder", + captured: "onSelectionChangeShouldSetResponderCapture" + }, + dependencies: [TOP_SELECTION_CHANGE] + }, + + /** + * On a `touchMove`/`mouseMove`, is it desired that this element become the + * responder? + */ + moveShouldSetResponder: { + phasedRegistrationNames: { + bubbled: "onMoveShouldSetResponder", + captured: "onMoveShouldSetResponderCapture" + }, + dependencies: moveDependencies + }, + + /** + * Direct responder events dispatched directly to responder. Do not bubble. + */ + responderStart: { + registrationName: "onResponderStart", + dependencies: startDependencies + }, + responderMove: { + registrationName: "onResponderMove", + dependencies: moveDependencies + }, + responderEnd: { + registrationName: "onResponderEnd", + dependencies: endDependencies + }, + responderRelease: { + registrationName: "onResponderRelease", + dependencies: endDependencies + }, + responderTerminationRequest: { + registrationName: "onResponderTerminationRequest", + dependencies: [] + }, + responderGrant: { + registrationName: "onResponderGrant", + dependencies: [] + }, + responderReject: { + registrationName: "onResponderReject", + dependencies: [] + }, + responderTerminate: { + registrationName: "onResponderTerminate", + dependencies: [] + } + }; // Start of inline: the below functions were inlined from + // EventPropagator.js, as they deviated from ReactDOM's newer + // implementations. + + function getParent(inst) { + do { + inst = inst.return; // TODO: If this is a HostRoot we might want to bail out. + // That is depending on if we want nested subtrees (layers) to bubble + // events to their parent. We could also go through parentNode on the + // host node but that wouldn't work for React Native and doesn't let us + // do the portal feature. + } while (inst && inst.tag !== HostComponent); - return false; -} -/** - * Simulates the traversal of a two-phase, capture/bubble event dispatch. - */ + if (inst) { + return inst; + } -function traverseTwoPhase(inst, fn, arg) { - var path = []; + return null; + } + /** + * Return the lowest common ancestor of A and B, or null if they are in + * different trees. + */ - while (inst) { - path.push(inst); - inst = getParent(inst); - } + function getLowestCommonAncestor(instA, instB) { + var depthA = 0; - var i; + for (var tempA = instA; tempA; tempA = getParent(tempA)) { + depthA++; + } - for (i = path.length; i-- > 0; ) { - fn(path[i], "captured", arg); - } + var depthB = 0; - for (i = 0; i < path.length; i++) { - fn(path[i], "bubbled", arg); - } -} + for (var tempB = instB; tempB; tempB = getParent(tempB)) { + depthB++; + } // If A is deeper, crawl up. -function getListener(inst, registrationName) { - var stateNode = inst.stateNode; + while (depthA - depthB > 0) { + instA = getParent(instA); + depthA--; + } // If B is deeper, crawl up. - if (stateNode === null) { - // Work in progress (ex: onload events in incremental mode). - return null; - } + while (depthB - depthA > 0) { + instB = getParent(instB); + depthB--; + } // Walk in lockstep until we find a match. - var props = getFiberCurrentPropsFromNode(stateNode); + var depth = depthA; - if (props === null) { - // Work in progress. - return null; - } + while (depth--) { + if (instA === instB || instA === instB.alternate) { + return instA; + } - var listener = props[registrationName]; + instA = getParent(instA); + instB = getParent(instB); + } - if (listener && typeof listener !== "function") { - throw new Error( - "Expected `" + - registrationName + - "` listener to be a function, instead got a value of `" + - typeof listener + - "` type." - ); - } + return null; + } + /** + * Return if A is an ancestor of B. + */ - return listener; -} + function isAncestor(instA, instB) { + while (instB) { + if (instA === instB || instA === instB.alternate) { + return true; + } -function listenerAtPhase(inst, event, propagationPhase) { - var registrationName = - event.dispatchConfig.phasedRegistrationNames[propagationPhase]; - return getListener(inst, registrationName); -} + instB = getParent(instB); + } -function accumulateDirectionalDispatches(inst, phase, event) { - { - if (!inst) { - error("Dispatching inst must not be null"); + return false; } - } + /** + * Simulates the traversal of a two-phase, capture/bubble event dispatch. + */ - var listener = listenerAtPhase(inst, event, phase); + function traverseTwoPhase(inst, fn, arg) { + var path = []; - if (listener) { - event._dispatchListeners = accumulateInto( - event._dispatchListeners, - listener - ); - event._dispatchInstances = accumulateInto(event._dispatchInstances, inst); - } -} -/** - * Accumulates without regard to direction, does not look for phased - * registration names. Same as `accumulateDirectDispatchesSingle` but without - * requiring that the `dispatchMarker` be the same as the dispatched ID. - */ + while (inst) { + path.push(inst); + inst = getParent(inst); + } -function accumulateDispatches(inst, ignoredDirection, event) { - if (inst && event && event.dispatchConfig.registrationName) { - var registrationName = event.dispatchConfig.registrationName; - var listener = getListener(inst, registrationName); + var i; - if (listener) { - event._dispatchListeners = accumulateInto( - event._dispatchListeners, - listener - ); - event._dispatchInstances = accumulateInto(event._dispatchInstances, inst); + for (i = path.length; i-- > 0;) { + fn(path[i], "captured", arg); + } + + for (i = 0; i < path.length; i++) { + fn(path[i], "bubbled", arg); + } } - } -} -/** - * Accumulates dispatches on an `SyntheticEvent`, but only for the - * `dispatchMarker`. - * @param {SyntheticEvent} event - */ -function accumulateDirectDispatchesSingle(event) { - if (event && event.dispatchConfig.registrationName) { - accumulateDispatches(event._targetInst, null, event); - } -} + function getListener(inst, registrationName) { + var stateNode = inst.stateNode; -function accumulateDirectDispatches(events) { - forEachAccumulated(events, accumulateDirectDispatchesSingle); -} + if (stateNode === null) { + // Work in progress (ex: onload events in incremental mode). + return null; + } -function accumulateTwoPhaseDispatchesSingleSkipTarget(event) { - if (event && event.dispatchConfig.phasedRegistrationNames) { - var targetInst = event._targetInst; - var parentInst = targetInst ? getParent(targetInst) : null; - traverseTwoPhase(parentInst, accumulateDirectionalDispatches, event); - } -} + var props = getFiberCurrentPropsFromNode(stateNode); -function accumulateTwoPhaseDispatchesSkipTarget(events) { - forEachAccumulated(events, accumulateTwoPhaseDispatchesSingleSkipTarget); -} + if (props === null) { + // Work in progress. + return null; + } -function accumulateTwoPhaseDispatchesSingle(event) { - if (event && event.dispatchConfig.phasedRegistrationNames) { - traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event); - } -} + var listener = props[registrationName]; -function accumulateTwoPhaseDispatches(events) { - forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle); -} // End of inline + if (listener && typeof listener !== "function") { + throw new Error( + "Expected `" + + registrationName + + "` listener to be a function, instead got a value of `" + + typeof listener + + "` type." + ); + } -/** - * - * Responder System: - * ---------------- - * - * - A global, solitary "interaction lock" on a view. - * - If a node becomes the responder, it should convey visual feedback - * immediately to indicate so, either by highlighting or moving accordingly. - * - To be the responder means, that touches are exclusively important to that - * responder view, and no other view. - * - While touches are still occurring, the responder lock can be transferred to - * a new view, but only to increasingly "higher" views (meaning ancestors of - * the current responder). - * - * Responder being granted: - * ------------------------ - * - * - Touch starts, moves, and scrolls can cause an ID to become the responder. - * - We capture/bubble `startShouldSetResponder`/`moveShouldSetResponder` to - * the "appropriate place". - * - If nothing is currently the responder, the "appropriate place" is the - * initiating event's `targetID`. - * - If something *is* already the responder, the "appropriate place" is the - * first common ancestor of the event target and the current `responderInst`. - * - Some negotiation happens: See the timing diagram below. - * - Scrolled views automatically become responder. The reasoning is that a - * platform scroll view that isn't built on top of the responder system has - * began scrolling, and the active responder must now be notified that the - * interaction is no longer locked to it - the system has taken over. - * - * - Responder being released: - * As soon as no more touches that *started* inside of descendants of the - * *current* responderInst, an `onResponderRelease` event is dispatched to the - * current responder, and the responder lock is released. - * - * TODO: - * - on "end", a callback hook for `onResponderEndShouldRemainResponder` that - * determines if the responder lock should remain. - * - If a view shouldn't "remain" the responder, any active touches should by - * default be considered "dead" and do not influence future negotiations or - * bubble paths. It should be as if those touches do not exist. - * -- For multitouch: Usually a translate-z will choose to "remain" responder - * after one out of many touches ended. For translate-y, usually the view - * doesn't wish to "remain" responder after one of many touches end. - * - Consider building this on top of a `stopPropagation` model similar to - * `W3C` events. - * - Ensure that `onResponderTerminate` is called on touch cancels, whether or - * not `onResponderTerminationRequest` returns `true` or `false`. - * - */ + return listener; + } -/* Negotiation Performed - +-----------------------+ - / \ -Process low level events to + Current Responder + wantsResponderID -determine who to perform negot-| (if any exists at all) | -iation/transition | Otherwise just pass through| --------------------------------+----------------------------+------------------+ -Bubble to find first ID | | -to return true:wantsResponderID| | - | | - +-------------+ | | - | onTouchStart| | | - +------+------+ none | | - | return| | -+-----------v-------------+true| +------------------------+ | -|onStartShouldSetResponder|----->|onResponderStart (cur) |<-----------+ -+-----------+-------------+ | +------------------------+ | | - | | | +--------+-------+ - | returned true for| false:REJECT +-------->|onResponderReject - | wantsResponderID | | | +----------------+ - | (now attempt | +------------------+-----+ | - | handoff) | | onResponder | | - +------------------->| TerminationRequest| | - | +------------------+-----+ | - | | | +----------------+ - | true:GRANT +-------->|onResponderGrant| - | | +--------+-------+ - | +------------------------+ | | - | | onResponderTerminate |<-----------+ - | +------------------+-----+ | - | | | +----------------+ - | +-------->|onResponderStart| - | | +----------------+ -Bubble to find first ID | | -to return true:wantsResponderID| | - | | - +-------------+ | | - | onTouchMove | | | - +------+------+ none | | - | return| | -+-----------v-------------+true| +------------------------+ | -|onMoveShouldSetResponder |----->|onResponderMove (cur) |<-----------+ -+-----------+-------------+ | +------------------------+ | | - | | | +--------+-------+ - | returned true for| false:REJECT +-------->|onResponderRejec| - | wantsResponderID | | | +----------------+ - | (now attempt | +------------------+-----+ | - | handoff) | | onResponder | | - +------------------->| TerminationRequest| | - | +------------------+-----+ | - | | | +----------------+ - | true:GRANT +-------->|onResponderGrant| - | | +--------+-------+ - | +------------------------+ | | - | | onResponderTerminate |<-----------+ - | +------------------+-----+ | - | | | +----------------+ - | +-------->|onResponderMove | - | | +----------------+ - | | - | | - Some active touch started| | - inside current responder | +------------------------+ | - +------------------------->| onResponderEnd | | - | | +------------------------+ | - +---+---------+ | | - | onTouchEnd | | | - +---+---------+ | | - | | +------------------------+ | - +------------------------->| onResponderEnd | | - No active touches started| +-----------+------------+ | - inside current responder | | | - | v | - | +------------------------+ | - | | onResponderRelease | | - | +------------------------+ | - | | - + + */ + function listenerAtPhase(inst, event, propagationPhase) { + var registrationName = + event.dispatchConfig.phasedRegistrationNames[propagationPhase]; + return getListener(inst, registrationName); + } -/** - * A note about event ordering in the `EventPluginRegistry`. - * - * Suppose plugins are injected in the following order: - * - * `[R, S, C]` - * - * To help illustrate the example, assume `S` is `SimpleEventPlugin` (for - * `onClick` etc) and `R` is `ResponderEventPlugin`. - * - * "Deferred-Dispatched Events": - * - * - The current event plugin system will traverse the list of injected plugins, - * in order, and extract events by collecting the plugin's return value of - * `extractEvents()`. - * - These events that are returned from `extractEvents` are "deferred - * dispatched events". - * - When returned from `extractEvents`, deferred-dispatched events contain an - * "accumulation" of deferred dispatches. - * - These deferred dispatches are accumulated/collected before they are - * returned, but processed at a later time by the `EventPluginRegistry` (hence the - * name deferred). - * - * In the process of returning their deferred-dispatched events, event plugins - * themselves can dispatch events on-demand without returning them from - * `extractEvents`. Plugins might want to do this, so that they can use event - * dispatching as a tool that helps them decide which events should be extracted - * in the first place. - * - * "On-Demand-Dispatched Events": - * - * - On-demand-dispatched events are not returned from `extractEvents`. - * - On-demand-dispatched events are dispatched during the process of returning - * the deferred-dispatched events. - * - They should not have side effects. - * - They should be avoided, and/or eventually be replaced with another - * abstraction that allows event plugins to perform multiple "rounds" of event - * extraction. - * - * Therefore, the sequence of event dispatches becomes: - * - * - `R`s on-demand events (if any) (dispatched by `R` on-demand) - * - `S`s on-demand events (if any) (dispatched by `S` on-demand) - * - `C`s on-demand events (if any) (dispatched by `C` on-demand) - * - `R`s extracted events (if any) (dispatched by `EventPluginRegistry`) - * - `S`s extracted events (if any) (dispatched by `EventPluginRegistry`) - * - `C`s extracted events (if any) (dispatched by `EventPluginRegistry`) - * - * In the case of `ResponderEventPlugin`: If the `startShouldSetResponder` - * on-demand dispatch returns `true` (and some other details are satisfied) the - * `onResponderGrant` deferred dispatched event is returned from - * `extractEvents`. The sequence of dispatch executions in this case - * will appear as follows: - * - * - `startShouldSetResponder` (`ResponderEventPlugin` dispatches on-demand) - * - `touchStartCapture` (`EventPluginRegistry` dispatches as usual) - * - `touchStart` (`EventPluginRegistry` dispatches as usual) - * - `responderGrant/Reject` (`EventPluginRegistry` dispatches as usual) - */ + function accumulateDirectionalDispatches(inst, phase, event) { + { + if (!inst) { + error("Dispatching inst must not be null"); + } + } -function setResponderAndExtractTransfer( - topLevelType, - targetInst, - nativeEvent, - nativeEventTarget -) { - var shouldSetEventType = isStartish(topLevelType) - ? eventTypes.startShouldSetResponder - : isMoveish(topLevelType) - ? eventTypes.moveShouldSetResponder - : topLevelType === TOP_SELECTION_CHANGE - ? eventTypes.selectionChangeShouldSetResponder - : eventTypes.scrollShouldSetResponder; // TODO: stop one short of the current responder. - - var bubbleShouldSetFrom = !responderInst - ? targetInst - : getLowestCommonAncestor(responderInst, targetInst); // When capturing/bubbling the "shouldSet" event, we want to skip the target - // (deepest ID) if it happens to be the current responder. The reasoning: - // It's strange to get an `onMoveShouldSetResponder` when you're *already* - // the responder. - - var skipOverBubbleShouldSetFrom = bubbleShouldSetFrom === responderInst; - var shouldSetEvent = ResponderSyntheticEvent.getPooled( - shouldSetEventType, - bubbleShouldSetFrom, - nativeEvent, - nativeEventTarget - ); - shouldSetEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; - - if (skipOverBubbleShouldSetFrom) { - accumulateTwoPhaseDispatchesSkipTarget(shouldSetEvent); - } else { - accumulateTwoPhaseDispatches(shouldSetEvent); - } - - var wantsResponderInst = executeDispatchesInOrderStopAtTrue(shouldSetEvent); - - if (!shouldSetEvent.isPersistent()) { - shouldSetEvent.constructor.release(shouldSetEvent); - } - - if (!wantsResponderInst || wantsResponderInst === responderInst) { - return null; - } - - var extracted; - var grantEvent = ResponderSyntheticEvent.getPooled( - eventTypes.responderGrant, - wantsResponderInst, - nativeEvent, - nativeEventTarget - ); - grantEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; - accumulateDirectDispatches(grantEvent); - var blockHostResponder = executeDirectDispatch(grantEvent) === true; - - if (responderInst) { - var terminationRequestEvent = ResponderSyntheticEvent.getPooled( - eventTypes.responderTerminationRequest, - responderInst, - nativeEvent, - nativeEventTarget - ); - terminationRequestEvent.touchHistory = - ResponderTouchHistoryStore.touchHistory; - accumulateDirectDispatches(terminationRequestEvent); - var shouldSwitch = - !hasDispatches(terminationRequestEvent) || - executeDirectDispatch(terminationRequestEvent); + var listener = listenerAtPhase(inst, event, phase); + + if (listener) { + event._dispatchListeners = accumulateInto( + event._dispatchListeners, + listener + ); + event._dispatchInstances = accumulateInto(event._dispatchInstances, inst); + } + } + /** + * Accumulates without regard to direction, does not look for phased + * registration names. Same as `accumulateDirectDispatchesSingle` but without + * requiring that the `dispatchMarker` be the same as the dispatched ID. + */ + + function accumulateDispatches(inst, ignoredDirection, event) { + if (inst && event && event.dispatchConfig.registrationName) { + var registrationName = event.dispatchConfig.registrationName; + var listener = getListener(inst, registrationName); + + if (listener) { + event._dispatchListeners = accumulateInto( + event._dispatchListeners, + listener + ); + event._dispatchInstances = accumulateInto(event._dispatchInstances, inst); + } + } + } + /** + * Accumulates dispatches on an `SyntheticEvent`, but only for the + * `dispatchMarker`. + * @param {SyntheticEvent} event + */ - if (!terminationRequestEvent.isPersistent()) { - terminationRequestEvent.constructor.release(terminationRequestEvent); + function accumulateDirectDispatchesSingle(event) { + if (event && event.dispatchConfig.registrationName) { + accumulateDispatches(event._targetInst, null, event); + } + } + + function accumulateDirectDispatches(events) { + forEachAccumulated(events, accumulateDirectDispatchesSingle); + } + + function accumulateTwoPhaseDispatchesSingleSkipTarget(event) { + if (event && event.dispatchConfig.phasedRegistrationNames) { + var targetInst = event._targetInst; + var parentInst = targetInst ? getParent(targetInst) : null; + traverseTwoPhase(parentInst, accumulateDirectionalDispatches, event); + } + } + + function accumulateTwoPhaseDispatchesSkipTarget(events) { + forEachAccumulated(events, accumulateTwoPhaseDispatchesSingleSkipTarget); } - if (shouldSwitch) { - var terminateEvent = ResponderSyntheticEvent.getPooled( - eventTypes.responderTerminate, - responderInst, + function accumulateTwoPhaseDispatchesSingle(event) { + if (event && event.dispatchConfig.phasedRegistrationNames) { + traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event); + } + } + + function accumulateTwoPhaseDispatches(events) { + forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle); + } // End of inline + + /** + * + * Responder System: + * ---------------- + * + * - A global, solitary "interaction lock" on a view. + * - If a node becomes the responder, it should convey visual feedback + * immediately to indicate so, either by highlighting or moving accordingly. + * - To be the responder means, that touches are exclusively important to that + * responder view, and no other view. + * - While touches are still occurring, the responder lock can be transferred to + * a new view, but only to increasingly "higher" views (meaning ancestors of + * the current responder). + * + * Responder being granted: + * ------------------------ + * + * - Touch starts, moves, and scrolls can cause an ID to become the responder. + * - We capture/bubble `startShouldSetResponder`/`moveShouldSetResponder` to + * the "appropriate place". + * - If nothing is currently the responder, the "appropriate place" is the + * initiating event's `targetID`. + * - If something *is* already the responder, the "appropriate place" is the + * first common ancestor of the event target and the current `responderInst`. + * - Some negotiation happens: See the timing diagram below. + * - Scrolled views automatically become responder. The reasoning is that a + * platform scroll view that isn't built on top of the responder system has + * began scrolling, and the active responder must now be notified that the + * interaction is no longer locked to it - the system has taken over. + * + * - Responder being released: + * As soon as no more touches that *started* inside of descendants of the + * *current* responderInst, an `onResponderRelease` event is dispatched to the + * current responder, and the responder lock is released. + * + * TODO: + * - on "end", a callback hook for `onResponderEndShouldRemainResponder` that + * determines if the responder lock should remain. + * - If a view shouldn't "remain" the responder, any active touches should by + * default be considered "dead" and do not influence future negotiations or + * bubble paths. It should be as if those touches do not exist. + * -- For multitouch: Usually a translate-z will choose to "remain" responder + * after one out of many touches ended. For translate-y, usually the view + * doesn't wish to "remain" responder after one of many touches end. + * - Consider building this on top of a `stopPropagation` model similar to + * `W3C` events. + * - Ensure that `onResponderTerminate` is called on touch cancels, whether or + * not `onResponderTerminationRequest` returns `true` or `false`. + * + */ + + /* Negotiation Performed + +-----------------------+ + / \ + Process low level events to + Current Responder + wantsResponderID + determine who to perform negot-| (if any exists at all) | + iation/transition | Otherwise just pass through| + -------------------------------+----------------------------+------------------+ + Bubble to find first ID | | + to return true:wantsResponderID| | + | | + +-------------+ | | + | onTouchStart| | | + +------+------+ none | | + | return| | + +-----------v-------------+true| +------------------------+ | + |onStartShouldSetResponder|----->|onResponderStart (cur) |<-----------+ + +-----------+-------------+ | +------------------------+ | | + | | | +--------+-------+ + | returned true for| false:REJECT +-------->|onResponderReject + | wantsResponderID | | | +----------------+ + | (now attempt | +------------------+-----+ | + | handoff) | | onResponder | | + +------------------->| TerminationRequest| | + | +------------------+-----+ | + | | | +----------------+ + | true:GRANT +-------->|onResponderGrant| + | | +--------+-------+ + | +------------------------+ | | + | | onResponderTerminate |<-----------+ + | +------------------+-----+ | + | | | +----------------+ + | +-------->|onResponderStart| + | | +----------------+ + Bubble to find first ID | | + to return true:wantsResponderID| | + | | + +-------------+ | | + | onTouchMove | | | + +------+------+ none | | + | return| | + +-----------v-------------+true| +------------------------+ | + |onMoveShouldSetResponder |----->|onResponderMove (cur) |<-----------+ + +-----------+-------------+ | +------------------------+ | | + | | | +--------+-------+ + | returned true for| false:REJECT +-------->|onResponderRejec| + | wantsResponderID | | | +----------------+ + | (now attempt | +------------------+-----+ | + | handoff) | | onResponder | | + +------------------->| TerminationRequest| | + | +------------------+-----+ | + | | | +----------------+ + | true:GRANT +-------->|onResponderGrant| + | | +--------+-------+ + | +------------------------+ | | + | | onResponderTerminate |<-----------+ + | +------------------+-----+ | + | | | +----------------+ + | +-------->|onResponderMove | + | | +----------------+ + | | + | | + Some active touch started| | + inside current responder | +------------------------+ | + +------------------------->| onResponderEnd | | + | | +------------------------+ | + +---+---------+ | | + | onTouchEnd | | | + +---+---------+ | | + | | +------------------------+ | + +------------------------->| onResponderEnd | | + No active touches started| +-----------+------------+ | + inside current responder | | | + | v | + | +------------------------+ | + | | onResponderRelease | | + | +------------------------+ | + | | + + + */ + + /** + * A note about event ordering in the `EventPluginRegistry`. + * + * Suppose plugins are injected in the following order: + * + * `[R, S, C]` + * + * To help illustrate the example, assume `S` is `SimpleEventPlugin` (for + * `onClick` etc) and `R` is `ResponderEventPlugin`. + * + * "Deferred-Dispatched Events": + * + * - The current event plugin system will traverse the list of injected plugins, + * in order, and extract events by collecting the plugin's return value of + * `extractEvents()`. + * - These events that are returned from `extractEvents` are "deferred + * dispatched events". + * - When returned from `extractEvents`, deferred-dispatched events contain an + * "accumulation" of deferred dispatches. + * - These deferred dispatches are accumulated/collected before they are + * returned, but processed at a later time by the `EventPluginRegistry` (hence the + * name deferred). + * + * In the process of returning their deferred-dispatched events, event plugins + * themselves can dispatch events on-demand without returning them from + * `extractEvents`. Plugins might want to do this, so that they can use event + * dispatching as a tool that helps them decide which events should be extracted + * in the first place. + * + * "On-Demand-Dispatched Events": + * + * - On-demand-dispatched events are not returned from `extractEvents`. + * - On-demand-dispatched events are dispatched during the process of returning + * the deferred-dispatched events. + * - They should not have side effects. + * - They should be avoided, and/or eventually be replaced with another + * abstraction that allows event plugins to perform multiple "rounds" of event + * extraction. + * + * Therefore, the sequence of event dispatches becomes: + * + * - `R`s on-demand events (if any) (dispatched by `R` on-demand) + * - `S`s on-demand events (if any) (dispatched by `S` on-demand) + * - `C`s on-demand events (if any) (dispatched by `C` on-demand) + * - `R`s extracted events (if any) (dispatched by `EventPluginRegistry`) + * - `S`s extracted events (if any) (dispatched by `EventPluginRegistry`) + * - `C`s extracted events (if any) (dispatched by `EventPluginRegistry`) + * + * In the case of `ResponderEventPlugin`: If the `startShouldSetResponder` + * on-demand dispatch returns `true` (and some other details are satisfied) the + * `onResponderGrant` deferred dispatched event is returned from + * `extractEvents`. The sequence of dispatch executions in this case + * will appear as follows: + * + * - `startShouldSetResponder` (`ResponderEventPlugin` dispatches on-demand) + * - `touchStartCapture` (`EventPluginRegistry` dispatches as usual) + * - `touchStart` (`EventPluginRegistry` dispatches as usual) + * - `responderGrant/Reject` (`EventPluginRegistry` dispatches as usual) + */ + + function setResponderAndExtractTransfer( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget + ) { + var shouldSetEventType = isStartish(topLevelType) + ? eventTypes.startShouldSetResponder + : isMoveish(topLevelType) + ? eventTypes.moveShouldSetResponder + : topLevelType === TOP_SELECTION_CHANGE + ? eventTypes.selectionChangeShouldSetResponder + : eventTypes.scrollShouldSetResponder; // TODO: stop one short of the current responder. + + var bubbleShouldSetFrom = !responderInst + ? targetInst + : getLowestCommonAncestor(responderInst, targetInst); // When capturing/bubbling the "shouldSet" event, we want to skip the target + // (deepest ID) if it happens to be the current responder. The reasoning: + // It's strange to get an `onMoveShouldSetResponder` when you're *already* + // the responder. + + var skipOverBubbleShouldSetFrom = bubbleShouldSetFrom === responderInst; + var shouldSetEvent = ResponderSyntheticEvent.getPooled( + shouldSetEventType, + bubbleShouldSetFrom, nativeEvent, nativeEventTarget ); - terminateEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; - accumulateDirectDispatches(terminateEvent); - extracted = accumulate(extracted, [grantEvent, terminateEvent]); - changeResponder(wantsResponderInst, blockHostResponder); - } else { - var rejectEvent = ResponderSyntheticEvent.getPooled( - eventTypes.responderReject, + shouldSetEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; + + if (skipOverBubbleShouldSetFrom) { + accumulateTwoPhaseDispatchesSkipTarget(shouldSetEvent); + } else { + accumulateTwoPhaseDispatches(shouldSetEvent); + } + + var wantsResponderInst = executeDispatchesInOrderStopAtTrue(shouldSetEvent); + + if (!shouldSetEvent.isPersistent()) { + shouldSetEvent.constructor.release(shouldSetEvent); + } + + if (!wantsResponderInst || wantsResponderInst === responderInst) { + return null; + } + + var extracted; + var grantEvent = ResponderSyntheticEvent.getPooled( + eventTypes.responderGrant, wantsResponderInst, nativeEvent, nativeEventTarget ); - rejectEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; - accumulateDirectDispatches(rejectEvent); - extracted = accumulate(extracted, rejectEvent); - } - } else { - extracted = accumulate(extracted, grantEvent); - changeResponder(wantsResponderInst, blockHostResponder); - } + grantEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; + accumulateDirectDispatches(grantEvent); + var blockHostResponder = executeDirectDispatch(grantEvent) === true; + + if (responderInst) { + var terminationRequestEvent = ResponderSyntheticEvent.getPooled( + eventTypes.responderTerminationRequest, + responderInst, + nativeEvent, + nativeEventTarget + ); + terminationRequestEvent.touchHistory = + ResponderTouchHistoryStore.touchHistory; + accumulateDirectDispatches(terminationRequestEvent); + var shouldSwitch = + !hasDispatches(terminationRequestEvent) || + executeDirectDispatch(terminationRequestEvent); + + if (!terminationRequestEvent.isPersistent()) { + terminationRequestEvent.constructor.release(terminationRequestEvent); + } - return extracted; -} -/** - * A transfer is a negotiation between a currently set responder and the next - * element to claim responder status. Any start event could trigger a transfer - * of responderInst. Any move event could trigger a transfer. - * - * @param {string} topLevelType Record from `BrowserEventConstants`. - * @return {boolean} True if a transfer of responder could possibly occur. - */ + if (shouldSwitch) { + var terminateEvent = ResponderSyntheticEvent.getPooled( + eventTypes.responderTerminate, + responderInst, + nativeEvent, + nativeEventTarget + ); + terminateEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; + accumulateDirectDispatches(terminateEvent); + extracted = accumulate(extracted, [grantEvent, terminateEvent]); + changeResponder(wantsResponderInst, blockHostResponder); + } else { + var rejectEvent = ResponderSyntheticEvent.getPooled( + eventTypes.responderReject, + wantsResponderInst, + nativeEvent, + nativeEventTarget + ); + rejectEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; + accumulateDirectDispatches(rejectEvent); + extracted = accumulate(extracted, rejectEvent); + } + } else { + extracted = accumulate(extracted, grantEvent); + changeResponder(wantsResponderInst, blockHostResponder); + } -function canTriggerTransfer(topLevelType, topLevelInst, nativeEvent) { - return ( - topLevelInst && // responderIgnoreScroll: We are trying to migrate away from specifically - // tracking native scroll events here and responderIgnoreScroll indicates we - // will send topTouchCancel to handle canceling touch events instead - ((topLevelType === TOP_SCROLL && !nativeEvent.responderIgnoreScroll) || - (trackedTouchCount > 0 && topLevelType === TOP_SELECTION_CHANGE) || - isStartish(topLevelType) || - isMoveish(topLevelType)) - ); -} -/** - * Returns whether or not this touch end event makes it such that there are no - * longer any touches that started inside of the current `responderInst`. - * - * @param {NativeEvent} nativeEvent Native touch end event. - * @return {boolean} Whether or not this touch end event ends the responder. - */ + return extracted; + } + /** + * A transfer is a negotiation between a currently set responder and the next + * element to claim responder status. Any start event could trigger a transfer + * of responderInst. Any move event could trigger a transfer. + * + * @param {string} topLevelType Record from `BrowserEventConstants`. + * @return {boolean} True if a transfer of responder could possibly occur. + */ -function noResponderTouches(nativeEvent) { - var touches = nativeEvent.touches; + function canTriggerTransfer(topLevelType, topLevelInst, nativeEvent) { + return ( + topLevelInst && // responderIgnoreScroll: We are trying to migrate away from specifically + // tracking native scroll events here and responderIgnoreScroll indicates we + // will send topTouchCancel to handle canceling touch events instead + ((topLevelType === TOP_SCROLL && !nativeEvent.responderIgnoreScroll) || + (trackedTouchCount > 0 && topLevelType === TOP_SELECTION_CHANGE) || + isStartish(topLevelType) || + isMoveish(topLevelType)) + ); + } + /** + * Returns whether or not this touch end event makes it such that there are no + * longer any touches that started inside of the current `responderInst`. + * + * @param {NativeEvent} nativeEvent Native touch end event. + * @return {boolean} Whether or not this touch end event ends the responder. + */ - if (!touches || touches.length === 0) { - return true; - } + function noResponderTouches(nativeEvent) { + var touches = nativeEvent.touches; - for (var i = 0; i < touches.length; i++) { - var activeTouch = touches[i]; - var target = activeTouch.target; + if (!touches || touches.length === 0) { + return true; + } - if (target !== null && target !== undefined && target !== 0) { - // Is the original touch location inside of the current responder? - var targetInst = getInstanceFromNode(target); + for (var i = 0; i < touches.length; i++) { + var activeTouch = touches[i]; + var target = activeTouch.target; - if (isAncestor(responderInst, targetInst)) { - return false; + if (target !== null && target !== undefined && target !== 0) { + // Is the original touch location inside of the current responder? + var targetInst = getInstanceFromNode(target); + + if (isAncestor(responderInst, targetInst)) { + return false; + } + } } + + return true; } - } - return true; -} + var ResponderEventPlugin = { + /* For unit testing only */ + _getResponder: function () { + return responderInst; + }, + eventTypes: eventTypes, -var ResponderEventPlugin = { - /* For unit testing only */ - _getResponder: function() { - return responderInst; - }, - eventTypes: eventTypes, - - /** - * We must be resilient to `targetInst` being `null` on `touchMove` or - * `touchEnd`. On certain platforms, this means that a native scroll has - * assumed control and the original touch targets are destroyed. - */ - extractEvents: function( - topLevelType, - targetInst, - nativeEvent, - nativeEventTarget, - eventSystemFlags - ) { - if (isStartish(topLevelType)) { - trackedTouchCount += 1; - } else if (isEndish(topLevelType)) { - if (trackedTouchCount >= 0) { - trackedTouchCount -= 1; - } else { - { - warn( - "Ended a touch event which was not counted in `trackedTouchCount`." + /** + * We must be resilient to `targetInst` being `null` on `touchMove` or + * `touchEnd`. On certain platforms, this means that a native scroll has + * assumed control and the original touch targets are destroyed. + */ + extractEvents: function ( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget, + eventSystemFlags + ) { + if (isStartish(topLevelType)) { + trackedTouchCount += 1; + } else if (isEndish(topLevelType)) { + if (trackedTouchCount >= 0) { + trackedTouchCount -= 1; + } else { + { + warn( + "Ended a touch event which was not counted in `trackedTouchCount`." + ); + } + + return null; + } + } + + ResponderTouchHistoryStore.recordTouchTrack(topLevelType, nativeEvent); + var extracted = canTriggerTransfer(topLevelType, targetInst, nativeEvent) + ? setResponderAndExtractTransfer( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget + ) + : null; // Responder may or may not have transferred on a new touch start/move. + // Regardless, whoever is the responder after any potential transfer, we + // direct all touch start/move/ends to them in the form of + // `onResponderMove/Start/End`. These will be called for *every* additional + // finger that move/start/end, dispatched directly to whoever is the + // current responder at that moment, until the responder is "released". + // + // These multiple individual change touch events are are always bookended + // by `onResponderGrant`, and one of + // (`onResponderRelease/onResponderTerminate`). + + var isResponderTouchStart = responderInst && isStartish(topLevelType); + var isResponderTouchMove = responderInst && isMoveish(topLevelType); + var isResponderTouchEnd = responderInst && isEndish(topLevelType); + var incrementalTouch = isResponderTouchStart + ? eventTypes.responderStart + : isResponderTouchMove + ? eventTypes.responderMove + : isResponderTouchEnd + ? eventTypes.responderEnd + : null; + + if (incrementalTouch) { + var gesture = ResponderSyntheticEvent.getPooled( + incrementalTouch, + responderInst, + nativeEvent, + nativeEventTarget + ); + gesture.touchHistory = ResponderTouchHistoryStore.touchHistory; + accumulateDirectDispatches(gesture); + extracted = accumulate(extracted, gesture); + } + + var isResponderTerminate = + responderInst && topLevelType === TOP_TOUCH_CANCEL; + var isResponderRelease = + responderInst && + !isResponderTerminate && + isEndish(topLevelType) && + noResponderTouches(nativeEvent); + var finalTouch = isResponderTerminate + ? eventTypes.responderTerminate + : isResponderRelease + ? eventTypes.responderRelease + : null; + + if (finalTouch) { + var finalEvent = ResponderSyntheticEvent.getPooled( + finalTouch, + responderInst, + nativeEvent, + nativeEventTarget + ); + finalEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; + accumulateDirectDispatches(finalEvent); + extracted = accumulate(extracted, finalEvent); + changeResponder(null); + } + + return extracted; + }, + GlobalResponderHandler: null, + injection: { + /** + * @param {{onChange: (ReactID, ReactID) => void} GlobalResponderHandler + * Object that handles any change in responder. Use this to inject + * integration with an existing touch handling system etc. + */ + injectGlobalResponderHandler: function (GlobalResponderHandler) { + ResponderEventPlugin.GlobalResponderHandler = GlobalResponderHandler; + } + } + }; + + /** + * Injectable ordering of event plugins. + */ + var eventPluginOrder = null; + /** + * Injectable mapping from names to event plugin modules. + */ + + var namesToPlugins = {}; + /** + * Recomputes the plugin list using the injected plugins and plugin ordering. + * + * @private + */ + + function recomputePluginOrdering() { + if (!eventPluginOrder) { + // Wait until an `eventPluginOrder` is injected. + return; + } + + for (var pluginName in namesToPlugins) { + var pluginModule = namesToPlugins[pluginName]; + var pluginIndex = eventPluginOrder.indexOf(pluginName); + + if (pluginIndex <= -1) { + throw new Error( + "EventPluginRegistry: Cannot inject event plugins that do not exist in " + + ("the plugin ordering, `" + pluginName + "`.") + ); + } + + if (plugins[pluginIndex]) { + continue; + } + + if (!pluginModule.extractEvents) { + throw new Error( + "EventPluginRegistry: Event plugins must implement an `extractEvents` " + + ("method, but `" + pluginName + "` does not.") ); } - return null; + plugins[pluginIndex] = pluginModule; + var publishedEvents = pluginModule.eventTypes; + + for (var eventName in publishedEvents) { + if ( + !publishEventForPlugin( + publishedEvents[eventName], + pluginModule, + eventName + ) + ) { + throw new Error( + "EventPluginRegistry: Failed to publish event `" + + eventName + + "` for plugin `" + + pluginName + + "`." + ); + } + } + } + } + /** + * Publishes an event so that it can be dispatched by the supplied plugin. + * + * @param {object} dispatchConfig Dispatch configuration for the event. + * @param {object} PluginModule Plugin publishing the event. + * @return {boolean} True if the event was successfully published. + * @private + */ + + function publishEventForPlugin(dispatchConfig, pluginModule, eventName) { + if (eventNameDispatchConfigs.hasOwnProperty(eventName)) { + throw new Error( + "EventPluginRegistry: More than one plugin attempted to publish the same " + + ("event name, `" + eventName + "`.") + ); + } + + eventNameDispatchConfigs[eventName] = dispatchConfig; + var phasedRegistrationNames = dispatchConfig.phasedRegistrationNames; + + if (phasedRegistrationNames) { + for (var phaseName in phasedRegistrationNames) { + if (phasedRegistrationNames.hasOwnProperty(phaseName)) { + var phasedRegistrationName = phasedRegistrationNames[phaseName]; + publishRegistrationName( + phasedRegistrationName, + pluginModule, + eventName + ); + } + } + + return true; + } else if (dispatchConfig.registrationName) { + publishRegistrationName( + dispatchConfig.registrationName, + pluginModule, + eventName + ); + return true; + } + + return false; + } + /** + * Publishes a registration name that is used to identify dispatched events. + * + * @param {string} registrationName Registration name to add. + * @param {object} PluginModule Plugin publishing the event. + * @private + */ + + function publishRegistrationName(registrationName, pluginModule, eventName) { + if (registrationNameModules[registrationName]) { + throw new Error( + "EventPluginRegistry: More than one plugin attempted to publish the same " + + ("registration name, `" + registrationName + "`.") + ); + } + + registrationNameModules[registrationName] = pluginModule; + registrationNameDependencies[registrationName] = + pluginModule.eventTypes[eventName].dependencies; + + { + var lowerCasedName = registrationName.toLowerCase(); + } + } + /** + * Registers plugins so that they can extract and dispatch events. + */ + + /** + * Ordered list of injected plugins. + */ + + var plugins = []; + /** + * Mapping from event name to dispatch config + */ + + var eventNameDispatchConfigs = {}; + /** + * Mapping from registration name to plugin module + */ + + var registrationNameModules = {}; + /** + * Mapping from registration name to event name + */ + + var registrationNameDependencies = {}; + + /** + * Injects an ordering of plugins (by plugin name). This allows the ordering + * to be decoupled from injection of the actual plugins so that ordering is + * always deterministic regardless of packaging, on-the-fly injection, etc. + * + * @param {array} InjectedEventPluginOrder + * @internal + */ + + function injectEventPluginOrder(injectedEventPluginOrder) { + if (eventPluginOrder) { + throw new Error( + "EventPluginRegistry: Cannot inject event plugin ordering more than " + + "once. You are likely trying to load more than one copy of React." + ); + } // Clone the ordering so it cannot be dynamically mutated. + + eventPluginOrder = Array.prototype.slice.call(injectedEventPluginOrder); + recomputePluginOrdering(); + } + /** + * Injects plugins to be used by plugin event system. The plugin names must be + * in the ordering injected by `injectEventPluginOrder`. + * + * Plugins can be injected as part of page initialization or on-the-fly. + * + * @param {object} injectedNamesToPlugins Map from names to plugin modules. + * @internal + */ + + function injectEventPluginsByName(injectedNamesToPlugins) { + var isOrderingDirty = false; + + for (var pluginName in injectedNamesToPlugins) { + if (!injectedNamesToPlugins.hasOwnProperty(pluginName)) { + continue; + } + + var pluginModule = injectedNamesToPlugins[pluginName]; + + if ( + !namesToPlugins.hasOwnProperty(pluginName) || + namesToPlugins[pluginName] !== pluginModule + ) { + if (namesToPlugins[pluginName]) { + throw new Error( + "EventPluginRegistry: Cannot inject two different event plugins " + + ("using the same name, `" + pluginName + "`.") + ); + } + + namesToPlugins[pluginName] = pluginModule; + isOrderingDirty = true; + } + } + + if (isOrderingDirty) { + recomputePluginOrdering(); + } + } + + /** + * Get a list of listeners for a specific event, in-order. + * For React Native we treat the props-based function handlers + * as the first-class citizens, and they are always executed first + * for both capture and bubbling phase. + * + * We need "phase" propagated to this point to support the HostComponent + * EventEmitter API, which does not mutate the name of the handler based + * on phase (whereas prop handlers are registered as `onMyEvent` and `onMyEvent_Capture`). + * + * Native system events emitted into React Native + * will be emitted both to the prop handler function and to imperative event + * listeners. + * + * This will either return null, a single Function without an array, or + * an array of 2+ items. + */ + + function getListeners( + inst, + registrationName, + phase, + dispatchToImperativeListeners + ) { + var stateNode = inst.stateNode; + + if (stateNode === null) { + return null; + } // If null: Work in progress (ex: onload events in incremental mode). + + var props = getFiberCurrentPropsFromNode(stateNode); + + if (props === null) { + // Work in progress. + return null; + } + + var listener = props[registrationName]; + + if (listener && typeof listener !== "function") { + throw new Error( + "Expected `" + + registrationName + + "` listener to be a function, instead got a value of `" + + typeof listener + + "` type." + ); + } // If there are no imperative listeners, early exit. + + if ( + !( + dispatchToImperativeListeners && + stateNode.canonical && + stateNode.canonical._eventListeners + ) + ) { + return listener; + } // Below this is the de-optimized path. + // If you are using _eventListeners, we do not (yet) + // expect this to be as performant as the props-only path. + // If/when this becomes a bottleneck, it can be refactored + // to avoid unnecessary closures and array allocations. + // + // Previously, there was only one possible listener for an event: + // the onEventName property in props. + // Now, it is also possible to have N listeners + // for a specific event on a node. Thus, we accumulate all of the listeners, + // including the props listener, and return a function that calls them all in + // order, starting with the handler prop and then the listeners in order. + // We return either a non-empty array or null. + + var listeners = []; + + if (listener) { + listeners.push(listener); + } // TODO: for now, all of these events get an `rn:` prefix to enforce + // that the user knows they're only getting non-W3C-compliant events + // through this imperative event API. + // Events might not necessarily be noncompliant, but we currently have + // no verification that /any/ events are compliant. + // Thus, we prefix to ensure no collision with W3C event names. + + var requestedPhaseIsCapture = phase === "captured"; + var mangledImperativeRegistrationName = requestedPhaseIsCapture + ? "rn:" + registrationName.replace(/Capture$/, "") + : "rn:" + registrationName; // Get imperative event listeners for this event + + if ( + stateNode.canonical._eventListeners[mangledImperativeRegistrationName] && + stateNode.canonical._eventListeners[mangledImperativeRegistrationName] + .length > 0 + ) { + var eventListeners = + stateNode.canonical._eventListeners[mangledImperativeRegistrationName]; + eventListeners.forEach(function (listenerObj) { + // Make sure phase of listener matches requested phase + var isCaptureEvent = + listenerObj.options.capture != null && listenerObj.options.capture; + + if (isCaptureEvent !== requestedPhaseIsCapture) { + return; + } // For now (this is an area of future optimization) we must wrap + // all imperative event listeners in a function to unwrap the SyntheticEvent + // and pass them an Event. + // When this API is more stable and used more frequently, we can revisit. + + var listenerFnWrapper = function (syntheticEvent) { + var eventInst = new ReactNativePrivateInterface.CustomEvent( + mangledImperativeRegistrationName, + { + detail: syntheticEvent.nativeEvent + } + ); + eventInst.isTrusted = true; // setSyntheticEvent is present on the React Native Event shim. + // It is used to forward method calls on Event to the underlying SyntheticEvent. + // $FlowFixMe + + eventInst.setSyntheticEvent(syntheticEvent); + + for ( + var _len = arguments.length, + args = new Array(_len > 1 ? _len - 1 : 0), + _key = 1; + _key < _len; + _key++ + ) { + args[_key - 1] = arguments[_key]; + } + + listenerObj.listener.apply(listenerObj, [eventInst].concat(args)); + }; // Only call once? + // If so, we ensure that it's only called once by setting a flag + // and by removing it from eventListeners once it is called (but only + // when it's actually been executed). + + if (listenerObj.options.once) { + listeners.push(function () { + // Remove from the event listener once it's been called + stateNode.canonical.removeEventListener_unstable( + mangledImperativeRegistrationName, + listenerObj.listener, + listenerObj.capture + ); // Guard against function being called more than once in + // case there are somehow multiple in-flight references to + // it being processed + + if (!listenerObj.invalidated) { + listenerObj.invalidated = true; + listenerObj.listener.apply(listenerObj, arguments); + } + }); + } else { + listeners.push(listenerFnWrapper); + } + }); + } + + if (listeners.length === 0) { + return null; + } + + if (listeners.length === 1) { + return listeners[0]; + } + + return listeners; + } + + var customBubblingEventTypes = + ReactNativePrivateInterface.ReactNativeViewConfigRegistry + .customBubblingEventTypes, + customDirectEventTypes = + ReactNativePrivateInterface.ReactNativeViewConfigRegistry + .customDirectEventTypes; // Start of inline: the below functions were inlined from + // EventPropagator.js, as they deviated from ReactDOM's newer + // implementations. + + function listenersAtPhase(inst, event, propagationPhase) { + var registrationName = + event.dispatchConfig.phasedRegistrationNames[propagationPhase]; + return getListeners(inst, registrationName, propagationPhase, true); + } + + function accumulateListenersAndInstances(inst, event, listeners) { + var listenersLength = listeners + ? isArray(listeners) + ? listeners.length + : 1 + : 0; + + if (listenersLength > 0) { + event._dispatchListeners = accumulateInto( + event._dispatchListeners, + listeners + ); // Avoid allocating additional arrays here + + if (event._dispatchInstances == null && listenersLength === 1) { + event._dispatchInstances = inst; + } else { + event._dispatchInstances = event._dispatchInstances || []; + + if (!isArray(event._dispatchInstances)) { + event._dispatchInstances = [event._dispatchInstances]; + } + + for (var i = 0; i < listenersLength; i++) { + event._dispatchInstances.push(inst); + } + } + } + } + + function accumulateDirectionalDispatches$1(inst, phase, event) { + { + if (!inst) { + error("Dispatching inst must not be null"); + } + } + + var listeners = listenersAtPhase(inst, event, phase); + accumulateListenersAndInstances(inst, event, listeners); + } + + function getParent$1(inst) { + do { + inst = inst.return; // TODO: If this is a HostRoot we might want to bail out. + // That is depending on if we want nested subtrees (layers) to bubble + // events to their parent. We could also go through parentNode on the + // host node but that wouldn't work for React Native and doesn't let us + // do the portal feature. + } while (inst && inst.tag !== HostComponent); + + if (inst) { + return inst; + } + + return null; + } + /** + * Simulates the traversal of a two-phase, capture/bubble event dispatch. + */ + + function traverseTwoPhase$1(inst, fn, arg, skipBubbling) { + var path = []; + + while (inst) { + path.push(inst); + inst = getParent$1(inst); + } + + var i; + + for (i = path.length; i-- > 0;) { + fn(path[i], "captured", arg); + } + + if (skipBubbling) { + // Dispatch on target only + fn(path[0], "bubbled", arg); + } else { + for (i = 0; i < path.length; i++) { + fn(path[i], "bubbled", arg); + } + } + } + + function accumulateTwoPhaseDispatchesSingle$1(event) { + if (event && event.dispatchConfig.phasedRegistrationNames) { + traverseTwoPhase$1( + event._targetInst, + accumulateDirectionalDispatches$1, + event, + false + ); + } + } + + function accumulateTwoPhaseDispatches$1(events) { + forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle$1); + } + + function accumulateCapturePhaseDispatches(event) { + if (event && event.dispatchConfig.phasedRegistrationNames) { + traverseTwoPhase$1( + event._targetInst, + accumulateDirectionalDispatches$1, + event, + true + ); + } + } + /** + * Accumulates without regard to direction, does not look for phased + * registration names. Same as `accumulateDirectDispatchesSingle` but without + * requiring that the `dispatchMarker` be the same as the dispatched ID. + */ + + function accumulateDispatches$1(inst, ignoredDirection, event) { + if (inst && event && event.dispatchConfig.registrationName) { + var registrationName = event.dispatchConfig.registrationName; + var listeners = getListeners(inst, registrationName, "bubbled", false); + accumulateListenersAndInstances(inst, event, listeners); + } + } + /** + * Accumulates dispatches on an `SyntheticEvent`, but only for the + * `dispatchMarker`. + * @param {SyntheticEvent} event + */ + + function accumulateDirectDispatchesSingle$1(event) { + if (event && event.dispatchConfig.registrationName) { + accumulateDispatches$1(event._targetInst, null, event); + } + } + + function accumulateDirectDispatches$1(events) { + forEachAccumulated(events, accumulateDirectDispatchesSingle$1); + } // End of inline + + var ReactNativeBridgeEventPlugin = { + eventTypes: {}, + extractEvents: function ( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget + ) { + if (targetInst == null) { + // Probably a node belonging to another renderer's tree. + return null; + } + + var bubbleDispatchConfig = customBubblingEventTypes[topLevelType]; + var directDispatchConfig = customDirectEventTypes[topLevelType]; + + if (!bubbleDispatchConfig && !directDispatchConfig) { + throw new Error( // $FlowFixMe - Flow doesn't like this string coercion because DOMTopLevelEventType is opaque + 'Unsupported top level event type "' + topLevelType + '" dispatched' + ); + } + + var event = SyntheticEvent.getPooled( + bubbleDispatchConfig || directDispatchConfig, + targetInst, + nativeEvent, + nativeEventTarget + ); + + if (bubbleDispatchConfig) { + var skipBubbling = + event != null && + event.dispatchConfig.phasedRegistrationNames != null && + event.dispatchConfig.phasedRegistrationNames.skipBubbling; + + if (skipBubbling) { + accumulateCapturePhaseDispatches(event); + } else { + accumulateTwoPhaseDispatches$1(event); + } + } else if (directDispatchConfig) { + accumulateDirectDispatches$1(event); + } else { + return null; + } + + return event; + } + }; + + var ReactNativeEventPluginOrder = [ + "ResponderEventPlugin", + "ReactNativeBridgeEventPlugin" + ]; + + /** + * Make sure essential globals are available and are patched correctly. Please don't remove this + * line. Bundles created by react-packager `require` it before executing any application code. This + * ensures it exists in the dependency graph and can be `require`d. + * TODO: require this in packager, not in React #10932517 + */ + /** + * Inject module for resolving DOM hierarchy and plugin ordering. + */ + + injectEventPluginOrder(ReactNativeEventPluginOrder); + /** + * Some important event plugins included by default (without having to require + * them). + */ + + injectEventPluginsByName({ + ResponderEventPlugin: ResponderEventPlugin, + ReactNativeBridgeEventPlugin: ReactNativeBridgeEventPlugin + }); + + function getInstanceFromInstance(instanceHandle) { + return instanceHandle; + } + + function getTagFromInstance(inst) { + var nativeInstance = inst.stateNode.canonical; + + if (!nativeInstance._nativeTag) { + throw new Error("All native instances should have a tag."); + } + + return nativeInstance; + } + function getFiberCurrentPropsFromNode$1(inst) { + return inst.canonical.currentProps; + } + + // Module provided by RN: + var ReactFabricGlobalResponderHandler = { + onChange: function (from, to, blockNativeResponder) { + var fromOrTo = from || to; + var fromOrToStateNode = fromOrTo && fromOrTo.stateNode; + var isFabric = !!( + fromOrToStateNode && fromOrToStateNode.canonical._internalInstanceHandle + ); + + if (isFabric) { + if (from) { + // equivalent to clearJSResponder + nativeFabricUIManager.setIsJSResponder( + from.stateNode.node, + false, + blockNativeResponder || false + ); + } + + if (to) { + // equivalent to setJSResponder + nativeFabricUIManager.setIsJSResponder( + to.stateNode.node, + true, + blockNativeResponder || false + ); + } + } else { + if (to !== null) { + var tag = to.stateNode.canonical._nativeTag; + ReactNativePrivateInterface.UIManager.setJSResponder( + tag, + blockNativeResponder + ); + } else { + ReactNativePrivateInterface.UIManager.clearJSResponder(); + } + } + } + }; + + setComponentTree( + getFiberCurrentPropsFromNode$1, + getInstanceFromInstance, + getTagFromInstance + ); + ResponderEventPlugin.injection.injectGlobalResponderHandler( + ReactFabricGlobalResponderHandler + ); + + /** + * `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 enableSchedulingProfiler = false; + var enableProfilerTimer = true; + var enableProfilerCommitHooks = true; + var warnAboutStringRefs = false; + var enableSuspenseAvoidThisFallback = false; + var enableNewReconciler = false; + var enableLazyContextPropagation = false; + var enableLegacyHidden = false; + + // 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; + } + + 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." + ); + } + } + + if (typeof type === "function") { + return type.displayName || type.name || null; + } + + if (typeof type === "string") { + return type; + } + + switch (type) { + case REACT_FRAGMENT_TYPE: + return "Fragment"; + + case REACT_PORTAL_TYPE: + return "Portal"; + + case REACT_PROFILER_TYPE: + return "Profiler"; + + case REACT_STRICT_MODE_TYPE: + return "StrictMode"; + + case REACT_SUSPENSE_TYPE: + return "Suspense"; + + case REACT_SUSPENSE_LIST_TYPE: + return "SuspenseList"; + } + + 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"; + + case REACT_FORWARD_REF_TYPE: + return getWrappedName(type, type.render, "ForwardRef"); + + case REACT_MEMO_TYPE: + var outerName = type.displayName || null; + + if (outerName !== null) { + return outerName; + } + + return getComponentNameFromType(type.type) || "Memo"; + + case REACT_LAZY_TYPE: { + var lazyComponent = type; + var payload = lazyComponent._payload; + var init = lazyComponent._init; + + try { + return getComponentNameFromType(init(payload)); + } catch (x) { + return null; + } + } + + // eslint-disable-next-line no-fallthrough + } + } + + return null; + } + + function getWrappedName$1(outerType, innerType, wrapperName) { + var functionName = innerType.displayName || innerType.name || ""; + return ( + outerType.displayName || + (functionName !== "" ? wrapperName + "(" + functionName + ")" : wrapperName) + ); + } // Keep in sync with shared/getComponentNameFromType + + function getContextName$1(type) { + return type.displayName || "Context"; + } + + function getComponentNameFromFiber(fiber) { + var tag = fiber.tag, + type = fiber.type; + + switch (tag) { + case CacheComponent: + return "Cache"; + + case ContextConsumer: + var context = type; + return getContextName$1(context) + ".Consumer"; + + case ContextProvider: + var provider = type; + return getContextName$1(provider._context) + ".Provider"; + + case DehydratedFragment: + return "DehydratedFragment"; + + case ForwardRef: + return getWrappedName$1(type, type.render, "ForwardRef"); + + case Fragment: + return "Fragment"; + + case HostComponent: + // Host component type is the display name (e.g. "div", "View") + return type; + + case HostPortal: + return "Portal"; + + case HostRoot: + return "Root"; + + case HostText: + return "Text"; + + 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"; + } + + return "Mode"; + + case OffscreenComponent: + return "Offscreen"; + + case Profiler: + return "Profiler"; + + case ScopeComponent: + return "Scope"; + + case SuspenseComponent: + return "Suspense"; + + case SuspenseListComponent: + return "SuspenseList"; + + 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; + } + + if (typeof type === "string") { + return type; + } + + break; + } + + return null; + } + + // Don't change these two values. They're used by React Dev Tools. + var NoFlags = + /* */ + 0; + var PerformedWork = + /* */ + 1; // You can change the rest (and add more). + + var Placement = + /* */ + 2; + var Update = + /* */ + 4; + var ChildDeletion = + /* */ + 16; + var ContentReset = + /* */ + 32; + var Callback = + /* */ + 64; + var DidCapture = + /* */ + 128; + var ForceClientRender = + /* */ + 256; + var Ref = + /* */ + 512; + var Snapshot = + /* */ + 1024; + var Passive = + /* */ + 2048; + var Hydrating = + /* */ + 4096; + var Visibility = + /* */ + 8192; + var StoreConsistency = + /* */ + 16384; + var LifecycleEffectMask = + Passive | 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 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; // These flags allow us to traverse to fibers that have effects on mount + // 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 | 0; + var MutationMask = + Placement | + Update | + ChildDeletion | + ContentReset | + Ref | + Hydrating | + Visibility; + var LayoutMask = Update | Callback | Ref | Visibility; // TODO: Split into PassiveMountMask and PassiveUnmountMask + + var PassiveMask = Passive | 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; + + var ReactCurrentOwner = 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) { + // 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; + } + + 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.current; + + if (owner !== null && owner.tag === ClassComponent) { + var ownerFiber = owner; + var instance = ownerFiber.stateNode; + + 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" + ); + } + + instance._warnedAboutRefsInRender = true; + } + } + + var fiber = get(component); + + 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."); + } + } + + function findCurrentFiberUsingSlowPath(fiber) { + var alternate = fiber.alternate; + + if (!alternate) { + // If there is no alternate, then we only need to check if it is mounted. + var nearestMounted = getNearestMountedFiber(fiber); + + if (nearestMounted === null) { + throw new Error("Unable to find node on an unmounted component."); + } + + if (nearestMounted !== fiber) { + return null; + } + + 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. + + var a = fiber; + var b = alternate; + + while (true) { + var parentA = a.return; + + if (parentA === null) { + // We're at the root. + break; + } + + var parentB = parentA.alternate; + + 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 (nextParent !== null) { + a = b = nextParent; + continue; + } // If there's no parent, we're at the root. + + 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) { + // We've determined that B is the current branch. + assertIsMounted(parentA); + return alternate; + } + + 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. + + 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 (_child === b) { + didFindChild = true; + b = parentA; + a = parentB; + break; + } + + _child = _child.sibling; + } + + if (!didFindChild) { + // Search parent B's child set + _child = parentB.child; + + while (_child) { + if (_child === a) { + didFindChild = true; + a = parentB; + b = parentA; + break; + } + + if (_child === b) { + didFindChild = true; + b = parentB; + a = parentA; + break; + } + + _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 (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.stateNode.current === a) { + // We've determined that A is the current branch. + return fiber; + } // Otherwise B has to be current branch. + + return alternate; + } + function findCurrentHostFiber(parent) { + var currentParent = findCurrentFiberUsingSlowPath(parent); + return currentParent !== null + ? findCurrentHostFiberImpl(currentParent) + : null; + } + + function findCurrentHostFiberImpl(node) { + // Next we'll drill down this component to find the first HostComponent/Text. + if (node.tag === HostComponent || node.tag === HostText) { + return node; + } + + var child = node.child; + + while (child !== null) { + var match = findCurrentHostFiberImpl(child); + + if (match !== null) { + return match; + } + + child = child.sibling; + } + + return null; + } + + /** + * In the future, we should cleanup callbacks by cancelling them instead of + * using this. + */ + function mountSafeCallback_NOT_REALLY_SAFE(context, callback) { + return function () { + if (!callback) { + return undefined; + } // This protects against createClass() components. + // We don't know if there is code depending on it. + // We intentionally don't use isMounted() because even accessing + // isMounted property on a React ES6 class will trigger a warning. + + if (typeof context.__isMounted === "boolean") { + if (!context.__isMounted) { + return undefined; + } + } // FIXME: there used to be other branches that protected + // against unmounted host components. But RN host components don't + // define isMounted() anymore, so those checks didn't do anything. + // They caused false positive warning noise so we removed them: + // https://github.com/facebook/react-native/issues/18868#issuecomment-413579095 + // However, this means that the callback is NOT guaranteed to be safe + // for host components. The solution we should implement is to make + // UIManager.measure() and similar calls truly cancelable. Then we + // can change our own code calling them to cancel when something unmounts. + + return callback.apply(context, arguments); + }; + } + function warnForStyleProps(props, validAttributes) { + { + for (var key in validAttributes.style) { + if (!(validAttributes[key] || props[key] === undefined)) { + error( + "You are setting the style `{ %s" + + ": ... }` as a prop. You " + + "should nest it in a style object. " + + "E.g. `{ style: { %s" + + ": ... } }`", + key, + key + ); + } + } + } + } + + // Modules provided by RN: + var emptyObject = {}; + /** + * Create a payload that contains all the updates between two sets of props. + * + * These helpers are all encapsulated into a single module, because they use + * mutation as a performance optimization which leads to subtle shared + * dependencies between the code paths. To avoid this mutable state leaking + * across modules, I've kept them isolated to this module. + */ + + // Tracks removed keys + var removedKeys = null; + var removedKeyCount = 0; + var deepDifferOptions = { + unsafelyIgnoreFunctions: true + }; + + function defaultDiffer(prevProp, nextProp) { + if (typeof nextProp !== "object" || nextProp === null) { + // Scalars have already been checked for equality + return true; + } else { + // For objects and arrays, the default diffing algorithm is a deep compare + return ReactNativePrivateInterface.deepDiffer( + prevProp, + nextProp, + deepDifferOptions + ); + } + } + + function restoreDeletedValuesInNestedArray( + updatePayload, + node, + validAttributes + ) { + if (isArray(node)) { + var i = node.length; + + while (i-- && removedKeyCount > 0) { + restoreDeletedValuesInNestedArray( + updatePayload, + node[i], + validAttributes + ); + } + } else if (node && removedKeyCount > 0) { + var obj = node; + + for (var propKey in removedKeys) { + if (!removedKeys[propKey]) { + continue; + } + + var nextProp = obj[propKey]; + + if (nextProp === undefined) { + continue; + } + + var attributeConfig = validAttributes[propKey]; + + if (!attributeConfig) { + continue; // not a valid native prop + } + + if (typeof nextProp === "function") { + nextProp = true; + } + + if (typeof nextProp === "undefined") { + nextProp = null; + } + + if (typeof attributeConfig !== "object") { + // case: !Object is the default case + updatePayload[propKey] = nextProp; + } else if ( + typeof attributeConfig.diff === "function" || + typeof attributeConfig.process === "function" + ) { + // case: CustomAttributeConfiguration + var nextValue = + typeof attributeConfig.process === "function" + ? attributeConfig.process(nextProp) + : nextProp; + updatePayload[propKey] = nextValue; + } + + removedKeys[propKey] = false; + removedKeyCount--; + } + } + } + + function diffNestedArrayProperty( + updatePayload, + prevArray, + nextArray, + validAttributes + ) { + var minLength = + prevArray.length < nextArray.length ? prevArray.length : nextArray.length; + var i; + + for (i = 0; i < minLength; i++) { + // Diff any items in the array in the forward direction. Repeated keys + // will be overwritten by later values. + updatePayload = diffNestedProperty( + updatePayload, + prevArray[i], + nextArray[i], + validAttributes + ); + } + + for (; i < prevArray.length; i++) { + // Clear out all remaining properties. + updatePayload = clearNestedProperty( + updatePayload, + prevArray[i], + validAttributes + ); + } + + for (; i < nextArray.length; i++) { + // Add all remaining properties. + updatePayload = addNestedProperty( + updatePayload, + nextArray[i], + validAttributes + ); + } + + return updatePayload; + } + + function diffNestedProperty( + updatePayload, + prevProp, + nextProp, + validAttributes + ) { + if (!updatePayload && prevProp === nextProp) { + // If no properties have been added, then we can bail out quickly on object + // equality. + return updatePayload; + } + + if (!prevProp || !nextProp) { + if (nextProp) { + return addNestedProperty(updatePayload, nextProp, validAttributes); + } + + if (prevProp) { + return clearNestedProperty(updatePayload, prevProp, validAttributes); + } + + return updatePayload; + } + + if (!isArray(prevProp) && !isArray(nextProp)) { + // Both are leaves, we can diff the leaves. + return diffProperties(updatePayload, prevProp, nextProp, validAttributes); + } + + if (isArray(prevProp) && isArray(nextProp)) { + // Both are arrays, we can diff the arrays. + return diffNestedArrayProperty( + updatePayload, + prevProp, + nextProp, + validAttributes + ); + } + + if (isArray(prevProp)) { + return diffProperties( + updatePayload, // $FlowFixMe - We know that this is always an object when the input is. + ReactNativePrivateInterface.flattenStyle(prevProp), // $FlowFixMe - We know that this isn't an array because of above flow. + nextProp, + validAttributes + ); + } + + return diffProperties( + updatePayload, + prevProp, // $FlowFixMe - We know that this is always an object when the input is. + ReactNativePrivateInterface.flattenStyle(nextProp), + validAttributes + ); + } + /** + * addNestedProperty takes a single set of props and valid attribute + * attribute configurations. It processes each prop and adds it to the + * updatePayload. + */ + + function addNestedProperty(updatePayload, nextProp, validAttributes) { + if (!nextProp) { + return updatePayload; + } + + if (!isArray(nextProp)) { + // Add each property of the leaf. + return addProperties(updatePayload, nextProp, validAttributes); + } + + for (var i = 0; i < nextProp.length; i++) { + // Add all the properties of the array. + updatePayload = addNestedProperty( + updatePayload, + nextProp[i], + validAttributes + ); + } + + return updatePayload; + } + /** + * clearNestedProperty takes a single set of props and valid attributes. It + * adds a null sentinel to the updatePayload, for each prop key. + */ + + function clearNestedProperty(updatePayload, prevProp, validAttributes) { + if (!prevProp) { + return updatePayload; + } + + if (!isArray(prevProp)) { + // Add each property of the leaf. + return clearProperties(updatePayload, prevProp, validAttributes); + } + + for (var i = 0; i < prevProp.length; i++) { + // Add all the properties of the array. + updatePayload = clearNestedProperty( + updatePayload, + prevProp[i], + validAttributes + ); + } + + return updatePayload; + } + /** + * diffProperties takes two sets of props and a set of valid attributes + * and write to updatePayload the values that changed or were deleted. + * If no updatePayload is provided, a new one is created and returned if + * anything changed. + */ + + function diffProperties(updatePayload, prevProps, nextProps, validAttributes) { + var attributeConfig; + var nextProp; + var prevProp; + + for (var propKey in nextProps) { + attributeConfig = validAttributes[propKey]; + + if (!attributeConfig) { + continue; // not a valid native prop + } + + prevProp = prevProps[propKey]; + nextProp = nextProps[propKey]; // functions are converted to booleans as markers that the associated + // events should be sent from native. + + if (typeof nextProp === "function") { + nextProp = true; // If nextProp is not a function, then don't bother changing prevProp + // since nextProp will win and go into the updatePayload regardless. + + if (typeof prevProp === "function") { + prevProp = true; + } + } // An explicit value of undefined is treated as a null because it overrides + // any other preceding value. + + if (typeof nextProp === "undefined") { + nextProp = null; + + if (typeof prevProp === "undefined") { + prevProp = null; + } + } + + if (removedKeys) { + removedKeys[propKey] = false; + } + + if (updatePayload && updatePayload[propKey] !== undefined) { + // Something else already triggered an update to this key because another + // value diffed. Since we're now later in the nested arrays our value is + // more important so we need to calculate it and override the existing + // value. It doesn't matter if nothing changed, we'll set it anyway. + // Pattern match on: attributeConfig + if (typeof attributeConfig !== "object") { + // case: !Object is the default case + updatePayload[propKey] = nextProp; + } else if ( + typeof attributeConfig.diff === "function" || + typeof attributeConfig.process === "function" + ) { + // case: CustomAttributeConfiguration + var nextValue = + typeof attributeConfig.process === "function" + ? attributeConfig.process(nextProp) + : nextProp; + updatePayload[propKey] = nextValue; + } + + continue; + } + + if (prevProp === nextProp) { + continue; // nothing changed + } // Pattern match on: attributeConfig + + if (typeof attributeConfig !== "object") { + // case: !Object is the default case + if (defaultDiffer(prevProp, nextProp)) { + // a normal leaf has changed + (updatePayload || (updatePayload = {}))[propKey] = nextProp; + } + } else if ( + typeof attributeConfig.diff === "function" || + typeof attributeConfig.process === "function" + ) { + // case: CustomAttributeConfiguration + var shouldUpdate = + prevProp === undefined || + (typeof attributeConfig.diff === "function" + ? attributeConfig.diff(prevProp, nextProp) + : defaultDiffer(prevProp, nextProp)); + + if (shouldUpdate) { + var _nextValue = + typeof attributeConfig.process === "function" + ? attributeConfig.process(nextProp) + : nextProp; + + (updatePayload || (updatePayload = {}))[propKey] = _nextValue; + } + } else { + // default: fallthrough case when nested properties are defined + removedKeys = null; + removedKeyCount = 0; // We think that attributeConfig is not CustomAttributeConfiguration at + // this point so we assume it must be AttributeConfiguration. + + updatePayload = diffNestedProperty( + updatePayload, + prevProp, + nextProp, + attributeConfig + ); + + if (removedKeyCount > 0 && updatePayload) { + restoreDeletedValuesInNestedArray( + updatePayload, + nextProp, + attributeConfig + ); + removedKeys = null; + } + } + } // Also iterate through all the previous props to catch any that have been + // removed and make sure native gets the signal so it can reset them to the + // default. + + for (var _propKey in prevProps) { + if (nextProps[_propKey] !== undefined) { + continue; // we've already covered this key in the previous pass + } + + attributeConfig = validAttributes[_propKey]; + + if (!attributeConfig) { + continue; // not a valid native prop + } + + if (updatePayload && updatePayload[_propKey] !== undefined) { + // This was already updated to a diff result earlier. + continue; + } + + prevProp = prevProps[_propKey]; + + if (prevProp === undefined) { + continue; // was already empty anyway + } // Pattern match on: attributeConfig + + if ( + typeof attributeConfig !== "object" || + typeof attributeConfig.diff === "function" || + typeof attributeConfig.process === "function" + ) { + // case: CustomAttributeConfiguration | !Object + // Flag the leaf property for removal by sending a sentinel. + (updatePayload || (updatePayload = {}))[_propKey] = null; + + if (!removedKeys) { + removedKeys = {}; + } + + if (!removedKeys[_propKey]) { + removedKeys[_propKey] = true; + removedKeyCount++; + } + } else { + // default: + // This is a nested attribute configuration where all the properties + // were removed so we need to go through and clear out all of them. + updatePayload = clearNestedProperty( + updatePayload, + prevProp, + attributeConfig + ); + } + } + + return updatePayload; + } + /** + * addProperties adds all the valid props to the payload after being processed. + */ + + function addProperties(updatePayload, props, validAttributes) { + // TODO: Fast path + return diffProperties(updatePayload, emptyObject, props, validAttributes); + } + /** + * clearProperties clears all the previous props by adding a null sentinel + * to the payload for each valid key. + */ + + function clearProperties(updatePayload, prevProps, validAttributes) { + // TODO: Fast path + return diffProperties(updatePayload, prevProps, emptyObject, validAttributes); + } + + function create(props, validAttributes) { + return addProperties( + null, // updatePayload + props, + validAttributes + ); + } + function diff(prevProps, nextProps, validAttributes) { + return diffProperties( + null, // updatePayload + prevProps, + nextProps, + validAttributes + ); + } + + // Used as a way to call batchedUpdates when we don't have a reference to + // the renderer. Such as when we're dispatching events or if third party + // libraries need to call batchedUpdates. Eventually, this API will go away when + // everything is batched by default. We'll then have a similar API to opt-out of + // scheduled work and instead do synchronous work. + // Defaults + var batchedUpdatesImpl = function (fn, bookkeeping) { + return fn(bookkeeping); + }; + + var isInsideEventHandler = false; + function batchedUpdates(fn, bookkeeping) { + if (isInsideEventHandler) { + // If we are currently inside another batch, we need to wait until it + // fully completes before restoring state. + return fn(bookkeeping); + } + + isInsideEventHandler = true; + + try { + return batchedUpdatesImpl(fn, bookkeeping); + } finally { + isInsideEventHandler = false; + } + } + function setBatchingImplementation(_batchedUpdatesImpl, _discreteUpdatesImpl) { + batchedUpdatesImpl = _batchedUpdatesImpl; + } + + /** + * Internal queue of events that have accumulated their dispatches and are + * waiting to have their dispatches executed. + */ + + var eventQueue = null; + /** + * Dispatches an event and releases it back into the pool, unless persistent. + * + * @param {?object} event Synthetic event to be dispatched. + * @private + */ + + var executeDispatchesAndRelease = function (event) { + if (event) { + executeDispatchesInOrder(event); + + if (!event.isPersistent()) { + event.constructor.release(event); + } + } + }; + + var executeDispatchesAndReleaseTopLevel = function (e) { + return executeDispatchesAndRelease(e); + }; + + function runEventsInBatch(events) { + if (events !== null) { + eventQueue = accumulateInto(eventQueue, events); + } // Set `eventQueue` to null before processing it so that we can tell if more + // events get enqueued while processing. + + var processingEventQueue = eventQueue; + eventQueue = null; + + if (!processingEventQueue) { + return; + } + + forEachAccumulated(processingEventQueue, executeDispatchesAndReleaseTopLevel); + + if (eventQueue) { + throw new Error( + "processEventQueue(): Additional events were enqueued while processing " + + "an event queue. Support for this has not yet been implemented." + ); + } // This would be a good time to rethrow if any of the event handlers threw. + + rethrowCaughtError(); + } + + /** + * Allows registered plugins an opportunity to extract events from top-level + * native browser events. + * + * @return {*} An accumulation of synthetic events. + * @internal + */ + + function extractPluginEvents( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget + ) { + var events = null; + var legacyPlugins = plugins; + + for (var i = 0; i < legacyPlugins.length; i++) { + // Not every plugin in the ordering may be loaded at runtime. + var possiblePlugin = legacyPlugins[i]; + + if (possiblePlugin) { + var extractedEvents = possiblePlugin.extractEvents( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget + ); + + if (extractedEvents) { + events = accumulateInto(events, extractedEvents); + } + } + } + + return events; + } + + function runExtractedPluginEventsInBatch( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget + ) { + var events = extractPluginEvents( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget + ); + runEventsInBatch(events); + } + + function dispatchEvent(target, topLevelType, nativeEvent) { + var targetFiber = target; + var eventTarget = null; + + if (targetFiber != null) { + var stateNode = targetFiber.stateNode; // Guard against Fiber being unmounted + + if (stateNode != null) { + eventTarget = stateNode.canonical; + } + } + + batchedUpdates(function () { + // Emit event to the RawEventEmitter. This is an unused-by-default EventEmitter + // that can be used to instrument event performance monitoring (primarily - could be useful + // for other things too). + // + // NOTE: this merely emits events into the EventEmitter below. + // If *you* do not add listeners to the `RawEventEmitter`, + // then all of these emitted events will just blackhole and are no-ops. + // It is available (although not officially supported... yet) if you want to collect + // perf data on event latency in your application, and could also be useful for debugging + // low-level events issues. + // + // If you do not have any event perf monitoring and are extremely concerned about event perf, + // it is safe to disable these "emit" statements; it will prevent checking the size of + // an empty array twice and prevent two no-ops. Practically the overhead is so low that + // we don't think it's worth thinking about in prod; your perf issues probably lie elsewhere. + // + // We emit two events here: one for listeners to this specific event, + // and one for the catchall listener '*', for any listeners that want + // to be notified for all events. + // Note that extracted events are *not* emitted, + // only events that have a 1:1 mapping with a native event, at least for now. + var event = { + eventName: topLevelType, + nativeEvent: nativeEvent + }; + ReactNativePrivateInterface.RawEventEmitter.emit(topLevelType, event); + ReactNativePrivateInterface.RawEventEmitter.emit("*", event); // Heritage plugin event system + + runExtractedPluginEventsInBatch( + topLevelType, + targetFiber, + nativeEvent, + eventTarget + ); + }); // React Native doesn't use ReactControlledComponent but if it did, here's + // where it would do it. + } + + // This module only exists as an ESM wrapper around the external CommonJS + var scheduleCallback = Scheduler.unstable_scheduleCallback; + var cancelCallback = Scheduler.unstable_cancelCallback; + var shouldYield = Scheduler.unstable_shouldYield; + var requestPaint = Scheduler.unstable_requestPaint; + var now = Scheduler.unstable_now; + var ImmediatePriority = Scheduler.unstable_ImmediatePriority; + var UserBlockingPriority = Scheduler.unstable_UserBlockingPriority; + var NormalPriority = Scheduler.unstable_NormalPriority; + var IdlePriority = Scheduler.unstable_IdlePriority; + + var rendererID = null; + var injectedHook = 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://react.dev/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 + }); + } + + 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; + } + } + 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); + } + } + } + } + } + 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; + break; + + case IdleEventPriority: + schedulerPriority = IdlePriority; + break; + + default: + schedulerPriority = NormalPriority; + break; + } + + injectedHook.onCommitFiberRoot( + rendererID, + root, + schedulerPriority, + didError + ); + } else { + injectedHook.onCommitFiberRoot(rendererID, root, undefined, didError); + } + } catch (err) { + { + if (!hasLoggedError) { + hasLoggedError = true; + + 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; + + 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; + + error("React instrumentation encountered an error: %s", err); + } + } + } + } + } + + function injectProfilingHooks(profilingHooks) { } + + function getLaneLabelMap() { + { + return null; + } + } + function markComponentRenderStopped() { } + function markComponentErrored(fiber, thrownValue, lanes) { } + function markComponentSuspended(fiber, wakeable, lanes) { } + + var NoMode = + /* */ + 0; // TODO: Remove ConcurrentMode by reading from the root tag instead + + var ConcurrentMode = + /* */ + 1; + var ProfileMode = + /* */ + 2; + var StrictLegacyMode = + /* */ + 8; + + // 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 = Math.log; + var LN2 = Math.LN2; + + function clz32Fallback(x) { + var asUint = x >>> 0; + + if (asUint === 0) { + return 32; + } + + return (31 - ((log(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 SyncLane = + /* */ + 1; + var InputContinuousHydrationLane = + /* */ + 2; + var InputContinuousLane = + /* */ + 4; + var DefaultHydrationLane = + /* */ + 8; + var DefaultLane = + /* */ + 16; + var TransitionHydrationLane = + /* */ + 32; + var TransitionLanes = + /* */ + 4194240; + var TransitionLane1 = + /* */ + 64; + var TransitionLane2 = + /* */ + 128; + var TransitionLane3 = + /* */ + 256; + var TransitionLane4 = + /* */ + 512; + var TransitionLane5 = + /* */ + 1024; + var TransitionLane6 = + /* */ + 2048; + var TransitionLane7 = + /* */ + 4096; + var TransitionLane8 = + /* */ + 8192; + var TransitionLane9 = + /* */ + 16384; + var TransitionLane10 = + /* */ + 32768; + var TransitionLane11 = + /* */ + 65536; + var TransitionLane12 = + /* */ + 131072; + var TransitionLane13 = + /* */ + 262144; + var TransitionLane14 = + /* */ + 524288; + var TransitionLane15 = + /* */ + 1048576; + var TransitionLane16 = + /* */ + 2097152; + var RetryLanes = + /* */ + 130023424; + var RetryLane1 = + /* */ + 4194304; + var RetryLane2 = + /* */ + 8388608; + var RetryLane3 = + /* */ + 16777216; + var RetryLane4 = + /* */ + 33554432; + var RetryLane5 = + /* */ + 67108864; + var SomeRetryLane = RetryLane1; + var SelectiveHydrationLane = + /* */ + 134217728; + var NonIdleLanes = + /* */ + 268435455; + var IdleHydrationLane = + /* */ + 268435456; + var IdleLane = + /* */ + 536870912; + var OffscreenLane = + /* */ + 1073741824; // This function is used for the experimental timeline (react-devtools-timeline) + var NoTimestamp = -1; + var nextTransitionLane = TransitionLane1; + var nextRetryLane = RetryLane1; + + function getHighestPriorityLanes(lanes) { + switch (getHighestPriorityLane(lanes)) { + 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: + case TransitionLane16: + return lanes & TransitionLanes; + + case RetryLane1: + case RetryLane2: + case RetryLane3: + case RetryLane4: + case RetryLane5: + return lanes & RetryLanes; + + case SelectiveHydrationLane: + return SelectiveHydrationLane; + + case IdleHydrationLane: + return IdleHydrationLane; + + case IdleLane: + return IdleLane; + + case OffscreenLane: + return OffscreenLane; + + 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; + } + } + + function getNextLanes(root, wipLanes) { + // Early bailout if there's no pending work left. + var pendingLanes = root.pendingLanes; + + if (pendingLanes === NoLanes) { + return NoLanes; + } + + 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. + + var nonIdlePendingLanes = pendingLanes & NonIdleLanes; + + if (nonIdlePendingLanes !== NoLanes) { + var nonIdleUnblockedLanes = nonIdlePendingLanes & ~suspendedLanes; + + if (nonIdleUnblockedLanes !== NoLanes) { + nextLanes = getHighestPriorityLanes(nonIdleUnblockedLanes); + } else { + var nonIdlePingedLanes = nonIdlePendingLanes & pingedLanes; + + if (nonIdlePingedLanes !== NoLanes) { + nextLanes = getHighestPriorityLanes(nonIdlePingedLanes); + } + } + } else { + // The only remaining work is Idle. + var unblockedLanes = pendingLanes & ~suspendedLanes; + + if (unblockedLanes !== NoLanes) { + nextLanes = getHighestPriorityLanes(unblockedLanes); + } else { + if (pingedLanes !== NoLanes) { + nextLanes = getHighestPriorityLanes(pingedLanes); + } + } + } + + 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; + } + } + + if ((nextLanes & 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. + nextLanes |= pendingLanes & 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, like + // useMutableSource, we should ensure that there is no partial work at the + // time we apply the entanglement. + + var entangledLanes = root.entangledLanes; + + if (entangledLanes !== NoLanes) { + var entanglements = root.entanglements; + var lanes = nextLanes & entangledLanes; + + while (lanes > 0) { + var index = pickArbitraryLaneIndex(lanes); + var lane = 1 << index; + nextLanes |= entanglements[index]; + lanes &= ~lane; + } + } + + return nextLanes; + } + function getMostRecentEventTime(root, lanes) { + var eventTimes = root.eventTimes; + var mostRecentEventTime = NoTimestamp; + + while (lanes > 0) { + var index = pickArbitraryLaneIndex(lanes); + var lane = 1 << index; + var eventTime = eventTimes[index]; + + if (eventTime > mostRecentEventTime) { + mostRecentEventTime = eventTime; + } + + lanes &= ~lane; + } + + return mostRecentEventTime; + } + + function computeExpirationTime(lane, currentTime) { + switch (lane) { + 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: + case TransitionLane16: + return currentTime + 5000; + + case RetryLane1: + case RetryLane2: + case RetryLane3: + case RetryLane4: + case RetryLane5: + // 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: + // 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. + + var lanes = pendingLanes; + + 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); + } + } 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) { + var everythingButOffscreen = root.pendingLanes & ~OffscreenLane; + + if (everythingButOffscreen !== NoLanes) { + return everythingButOffscreen; + } + + if (everythingButOffscreen & OffscreenLane) { + return OffscreenLane; + } + + return NoLanes; + } + function includesSyncLane(lanes) { + return (lanes & SyncLane) !== NoLanes; + } + function includesNonIdleWork(lanes) { + return (lanes & NonIdleLanes) !== NoLanes; + } + function includesOnlyRetries(lanes) { + return (lanes & RetryLanes) === lanes; + } + function includesOnlyNonUrgentLanes(lanes) { + var UrgentLanes = SyncLane | InputContinuousLane | DefaultLane; + return (lanes & UrgentLanes) === NoLanes; + } + function includesOnlyTransitions(lanes) { + return (lanes & TransitionLanes) === lanes; + } + function includesBlockingLane(root, lanes) { + 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 ((nextRetryLane & RetryLanes) === NoLanes) { + nextRetryLane = RetryLane1; + } + + 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); + } + + function pickArbitraryLaneIndex(lanes) { + return 31 - clz32(lanes); + } + + function laneToIndex(lane) { + return pickArbitraryLaneIndex(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). + + function laneToLanes(lane) { + return lane; + } + function createLaneMap(initial) { + // Intentionally pushing one by one. + // https://v8.dev/blog/elements-kinds#avoid-creating-holes + var laneMap = []; + + for (var i = 0; i < TotalLanes; i++) { + laneMap.push(initial); + } + + return laneMap; + } + function markRootUpdated(root, updateLane, eventTime) { + 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; + } + + var eventTimes = root.eventTimes; + var index = laneToIndex(updateLane); // We can always overwrite an existing timestamp because we prefer the most + // recent event, and we assume time is monotonically increasing. + + eventTimes[index] = eventTime; + } + function markRootSuspended(root, suspendedLanes) { + 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; + } + } + function markRootPinged(root, pingedLanes, eventTime) { + root.pingedLanes |= root.suspendedLanes & pingedLanes; + } + function markRootFinished(root, remainingLanes) { + var noLongerPendingLanes = root.pendingLanes & ~remainingLanes; + root.pendingLanes = remainingLanes; // Let's try everything again + + root.suspendedLanes = NoLanes; + root.pingedLanes = NoLanes; + root.expiredLanes &= remainingLanes; + root.mutableReadLanes &= remainingLanes; + root.entangledLanes &= remainingLanes; + var entanglements = root.entanglements; + var eventTimes = root.eventTimes; + var expirationTimes = root.expirationTimes; // Clear the lanes that no longer have pending work + + var lanes = noLongerPendingLanes; + + while (lanes > 0) { + var index = pickArbitraryLaneIndex(lanes); + var lane = 1 << index; + entanglements[index] = NoLanes; + eventTimes[index] = NoTimestamp; + expirationTimes[index] = NoTimestamp; + lanes &= ~lane; + } + } + 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 ( + // 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 getBumpedLaneForHydration(root, renderLanes) { + var renderLane = getHighestPriorityLane(renderLanes); + var lane; + + switch (renderLane) { + 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 TransitionLane16: + case RetryLane1: + case RetryLane2: + case RetryLane3: + case RetryLane4: + case RetryLane5: + 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 pendingUpdatersLaneMap = root.pendingUpdatersLaneMap; + var memoizedUpdaters = root.memoizedUpdaters; + + while (lanes > 0) { + var index = laneToIndex(lanes); + var lane = 1 << index; + var updaters = pendingUpdatersLaneMap[index]; + + if (updaters.size > 0) { + updaters.forEach(function (fiber) { + var alternate = fiber.alternate; + + if (alternate === null || !memoizedUpdaters.has(alternate)) { + memoizedUpdaters.add(fiber); + } + }); + updaters.clear(); + } + + lanes &= ~lane; + } + } + function getTransitionsForLanes(root, lanes) { + { + return null; + } + } + + 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; + } + + if (!isHigherEventPriority(ContinuousEventPriority, lane)) { + return ContinuousEventPriority; + } + + if (includesNonIdleWork(lane)) { + return DefaultEventPriority; + } + + return IdleEventPriority; + } + + // Renderers that don't support mutation + // can re-export everything from this module. + function shim() { + throw new Error( + "The current renderer does not support mutation. " + + "This error is likely caused by a bug in React. " + + "Please file an issue." + ); + } // Mutation (when unsupported) + var commitMount = shim; + + // Renderers that don't support hydration + // can re-export everything from this module. + function shim$1() { + 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$1; + var isSuspenseInstanceFallback = shim$1; + var getSuspenseInstanceFallbackErrorDetails = shim$1; + var registerSuspenseInstanceRetry = shim$1; + var hydrateTextInstance = shim$1; + var errorHydratingContainer = shim$1; + + var _nativeFabricUIManage = nativeFabricUIManager, + createNode = _nativeFabricUIManage.createNode, + cloneNode = _nativeFabricUIManage.cloneNode, + cloneNodeWithNewChildren = _nativeFabricUIManage.cloneNodeWithNewChildren, + cloneNodeWithNewChildrenAndProps = + _nativeFabricUIManage.cloneNodeWithNewChildrenAndProps, + cloneNodeWithNewProps = _nativeFabricUIManage.cloneNodeWithNewProps, + createChildNodeSet = _nativeFabricUIManage.createChildSet, + appendChildNode = _nativeFabricUIManage.appendChild, + appendChildNodeToSet = _nativeFabricUIManage.appendChildToSet, + completeRoot = _nativeFabricUIManage.completeRoot, + registerEventHandler = _nativeFabricUIManage.registerEventHandler, + fabricMeasure = _nativeFabricUIManage.measure, + fabricMeasureInWindow = _nativeFabricUIManage.measureInWindow, + fabricMeasureLayout = _nativeFabricUIManage.measureLayout, + FabricDefaultPriority = _nativeFabricUIManage.unstable_DefaultEventPriority, + FabricDiscretePriority = _nativeFabricUIManage.unstable_DiscreteEventPriority, + fabricGetCurrentEventPriority = + _nativeFabricUIManage.unstable_getCurrentEventPriority, + _setNativeProps = _nativeFabricUIManage.setNativeProps; + var getViewConfigForType = + ReactNativePrivateInterface.ReactNativeViewConfigRegistry.get; // Counter for uniquely identifying views. + // % 10 === 1 means it is a rootTag. + // % 2 === 0 means it is a Fabric tag. + // This means that they never overlap. + + var nextReactTag = 2; + + // TODO: Remove this conditional once all changes have propagated. + if (registerEventHandler) { + /** + * Register the event emitter with the native bridge + */ + registerEventHandler(dispatchEvent); + } + /** + * This is used for refs on host components. + */ + + var ReactFabricHostComponent = /*#__PURE__*/ (function () { + function ReactFabricHostComponent( + tag, + viewConfig, + props, + internalInstanceHandle + ) { + this._nativeTag = tag; + this.viewConfig = viewConfig; + this.currentProps = props; + this._internalInstanceHandle = internalInstanceHandle; + } + + var _proto = ReactFabricHostComponent.prototype; + + _proto.blur = function blur() { + ReactNativePrivateInterface.TextInputState.blurTextInput(this); + }; + + _proto.focus = function focus() { + ReactNativePrivateInterface.TextInputState.focusTextInput(this); + }; + + _proto.measure = function measure(callback) { + var stateNode = this._internalInstanceHandle.stateNode; + + if (stateNode != null) { + fabricMeasure( + stateNode.node, + mountSafeCallback_NOT_REALLY_SAFE(this, callback) + ); + } + }; + + _proto.measureInWindow = function measureInWindow(callback) { + var stateNode = this._internalInstanceHandle.stateNode; + + if (stateNode != null) { + fabricMeasureInWindow( + stateNode.node, + mountSafeCallback_NOT_REALLY_SAFE(this, callback) + ); + } + }; + + _proto.measureLayout = function measureLayout( + relativeToNativeNode, + onSuccess, + onFail + ) /* currently unused */ { + if ( + typeof relativeToNativeNode === "number" || + !(relativeToNativeNode instanceof ReactFabricHostComponent) + ) { + { + error( + "Warning: ref.measureLayout must be called with a ref to a native component." + ); + } + + return; + } + + var toStateNode = this._internalInstanceHandle.stateNode; + var fromStateNode = relativeToNativeNode._internalInstanceHandle.stateNode; + + if (toStateNode != null && fromStateNode != null) { + fabricMeasureLayout( + toStateNode.node, + fromStateNode.node, + mountSafeCallback_NOT_REALLY_SAFE(this, onFail), + mountSafeCallback_NOT_REALLY_SAFE(this, onSuccess) + ); + } + }; + + _proto.setNativeProps = function setNativeProps(nativeProps) { + { + warnForStyleProps(nativeProps, this.viewConfig.validAttributes); + } + + var updatePayload = create(nativeProps, this.viewConfig.validAttributes); + var stateNode = this._internalInstanceHandle.stateNode; + + if (stateNode != null && updatePayload != null) { + _setNativeProps(stateNode.node, updatePayload); + } + }; // This API (addEventListener, removeEventListener) attempts to adhere to the + // w3 Level2 Events spec as much as possible, treating HostComponent as a DOM node. + // + // Unless otherwise noted, these methods should "just work" and adhere to the W3 specs. + // If they deviate in a way that is not explicitly noted here, you've found a bug! + // + // See: + // * https://www.w3.org/TR/DOM-Level-2-Events/events.html + // * https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener + // * https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener + // + // And notably, not implemented (yet?): + // * https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/dispatchEvent + // + // + // Deviations from spec/TODOs: + // (1) listener must currently be a function, we do not support EventListener objects yet. + // (2) we do not support the `signal` option / AbortSignal yet + + _proto.addEventListener_unstable = function addEventListener_unstable( + eventType, + listener, + options + ) { + if (typeof eventType !== "string") { + throw new Error("addEventListener_unstable eventType must be a string"); + } + + if (typeof listener !== "function") { + throw new Error("addEventListener_unstable listener must be a function"); + } // The third argument is either boolean indicating "captures" or an object. + + var optionsObj = + typeof options === "object" && options !== null ? options : {}; + var capture = + (typeof options === "boolean" ? options : optionsObj.capture) || false; + var once = optionsObj.once || false; + var passive = optionsObj.passive || false; + var signal = null; // TODO: implement signal/AbortSignal + + var eventListeners = this._eventListeners || {}; + + if (this._eventListeners == null) { + this._eventListeners = eventListeners; + } + + var namedEventListeners = eventListeners[eventType] || []; + + if (eventListeners[eventType] == null) { + eventListeners[eventType] = namedEventListeners; + } + + namedEventListeners.push({ + listener: listener, + invalidated: false, + options: { + capture: capture, + once: once, + passive: passive, + signal: signal + } + }); + }; // See https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener + + _proto.removeEventListener_unstable = function removeEventListener_unstable( + eventType, + listener, + options + ) { + // eventType and listener must be referentially equal to be removed from the listeners + // data structure, but in "options" we only check the `capture` flag, according to spec. + // That means if you add the same function as a listener with capture set to true and false, + // you must also call removeEventListener twice with capture set to true/false. + var optionsObj = + typeof options === "object" && options !== null ? options : {}; + var capture = + (typeof options === "boolean" ? options : optionsObj.capture) || false; // If there are no event listeners or named event listeners, we can bail early - our + // job is already done. + + var eventListeners = this._eventListeners; + + if (!eventListeners) { + return; + } + + var namedEventListeners = eventListeners[eventType]; + + if (!namedEventListeners) { + return; + } // TODO: optimize this path to make remove cheaper + + eventListeners[eventType] = namedEventListeners.filter(function ( + listenerObj + ) { + return !( + listenerObj.listener === listener && + listenerObj.options.capture === capture + ); + }); + }; + + return ReactFabricHostComponent; + })(); // eslint-disable-next-line no-unused-expressions + function appendInitialChild(parentInstance, child) { + appendChildNode(parentInstance.node, child.node); + } + function createInstance( + type, + props, + rootContainerInstance, + hostContext, + internalInstanceHandle + ) { + var tag = nextReactTag; + nextReactTag += 2; + var viewConfig = getViewConfigForType(type); + + { + for (var key in viewConfig.validAttributes) { + if (props.hasOwnProperty(key)) { + ReactNativePrivateInterface.deepFreezeAndThrowOnMutationInDev( + props[key] + ); + } + } + } + + var updatePayload = create(props, viewConfig.validAttributes); + var node = createNode( + tag, // reactTag + viewConfig.uiViewClassName, // viewName + rootContainerInstance, // rootTag + updatePayload, // props + internalInstanceHandle // internalInstanceHandle + ); + var component = new ReactFabricHostComponent( + tag, + viewConfig, + props, + internalInstanceHandle + ); + return { + node: node, + canonical: component + }; + } + function createTextInstance( + text, + rootContainerInstance, + hostContext, + internalInstanceHandle + ) { + { + if (!hostContext.isInAParentText) { + error("Text strings must be rendered within a component."); + } + } + + var tag = nextReactTag; + nextReactTag += 2; + var node = createNode( + tag, // reactTag + "RCTRawText", // viewName + rootContainerInstance, // rootTag + { + text: text + }, // props + internalInstanceHandle // instance handle + ); + return { + node: node + }; + } + function getRootHostContext(rootContainerInstance) { + return { + isInAParentText: false + }; + } + function getChildHostContext(parentHostContext, type, rootContainerInstance) { + var prevIsInAParentText = parentHostContext.isInAParentText; + var isInAParentText = + type === "AndroidTextInput" || // Android + type === "RCTMultilineTextInputView" || // iOS + type === "RCTSinglelineTextInputView" || // iOS + type === "RCTText" || + type === "RCTVirtualText"; // TODO: If this is an offscreen host container, we should reuse the + // parent context. + + if (prevIsInAParentText !== isInAParentText) { + return { + isInAParentText: isInAParentText + }; + } else { + return parentHostContext; + } + } + function getPublicInstance(instance) { + return instance.canonical; + } + function prepareForCommit(containerInfo) { + // Noop + return null; + } + function prepareUpdate( + instance, + type, + oldProps, + newProps, + rootContainerInstance, + hostContext + ) { + var viewConfig = instance.canonical.viewConfig; + var updatePayload = diff(oldProps, newProps, viewConfig.validAttributes); // TODO: If the event handlers have changed, we need to update the current props + // in the commit phase but there is no host config hook to do it yet. + // So instead we hack it by updating it in the render phase. + + instance.canonical.currentProps = newProps; + return updatePayload; + } + function resetAfterCommit(containerInfo) { + // Noop + } + function shouldSetTextContent(type, props) { + // TODO (bvaughn) Revisit this decision. + // Always returning false simplifies the createInstance() implementation, + // But creates an additional child Fiber for raw text children. + // No additional native views are created though. + // It's not clear to me which is better so I'm deferring for now. + // More context @ github.com/facebook/react/pull/8560#discussion_r92111303 + return false; + } + function getCurrentEventPriority() { + var currentEventPriority = fabricGetCurrentEventPriority + ? fabricGetCurrentEventPriority() + : null; + + if (currentEventPriority != null) { + switch (currentEventPriority) { + case FabricDiscretePriority: + return DiscreteEventPriority; + + case FabricDefaultPriority: + default: + return DefaultEventPriority; + } + } + + return DefaultEventPriority; + } // The Fabric renderer is secondary to the existing React Native renderer. + + var warnsIfNotActing = false; + var scheduleTimeout = setTimeout; + var cancelTimeout = clearTimeout; + var noTimeout = -1; // ------------------- + function cloneInstance( + instance, + updatePayload, + type, + oldProps, + newProps, + internalInstanceHandle, + keepChildren, + recyclableInstance + ) { + var node = instance.node; + var clone; + + if (keepChildren) { + if (updatePayload !== null) { + clone = cloneNodeWithNewProps(node, updatePayload); + } else { + clone = cloneNode(node); + } + } else { + if (updatePayload !== null) { + clone = cloneNodeWithNewChildrenAndProps(node, updatePayload); + } else { + clone = cloneNodeWithNewChildren(node); + } + } + + return { + node: clone, + canonical: instance.canonical + }; + } + function cloneHiddenInstance(instance, type, props, internalInstanceHandle) { + var viewConfig = instance.canonical.viewConfig; + var node = instance.node; + var updatePayload = create( + { + style: { + display: "none" + } + }, + viewConfig.validAttributes + ); + return { + node: cloneNodeWithNewProps(node, updatePayload), + canonical: instance.canonical + }; + } + function cloneHiddenTextInstance(instance, text, internalInstanceHandle) { + throw new Error("Not yet implemented."); + } + function createContainerChildSet(container) { + return createChildNodeSet(container); + } + function appendChildToContainerChildSet(childSet, child) { + appendChildNodeToSet(childSet, child.node); + } + function finalizeContainerChildren(container, newChildren) { + completeRoot(container, newChildren); + } + function replaceContainerChildren(container, newChildren) { } + function preparePortalMount(portalInstance) { + // noop + } + + var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher; + function describeBuiltInComponentFrame(name, source, ownerFn) { + { + var ownerName = null; + + if (ownerFn) { + ownerName = ownerFn.displayName || ownerFn.name || null; + } + + return describeComponentFrame(name, source, ownerName); } } + var componentFrameCache; - ResponderTouchHistoryStore.recordTouchTrack(topLevelType, nativeEvent); - var extracted = canTriggerTransfer(topLevelType, targetInst, nativeEvent) - ? setResponderAndExtractTransfer( - topLevelType, - targetInst, - nativeEvent, - nativeEventTarget - ) - : null; // Responder may or may not have transferred on a new touch start/move. - // Regardless, whoever is the responder after any potential transfer, we - // direct all touch start/move/ends to them in the form of - // `onResponderMove/Start/End`. These will be called for *every* additional - // finger that move/start/end, dispatched directly to whoever is the - // current responder at that moment, until the responder is "released". - // - // These multiple individual change touch events are are always bookended - // by `onResponderGrant`, and one of - // (`onResponderRelease/onResponderTerminate`). - - var isResponderTouchStart = responderInst && isStartish(topLevelType); - var isResponderTouchMove = responderInst && isMoveish(topLevelType); - var isResponderTouchEnd = responderInst && isEndish(topLevelType); - var incrementalTouch = isResponderTouchStart - ? eventTypes.responderStart - : isResponderTouchMove - ? eventTypes.responderMove - : isResponderTouchEnd - ? eventTypes.responderEnd - : null; - - if (incrementalTouch) { - var gesture = ResponderSyntheticEvent.getPooled( - incrementalTouch, - responderInst, - nativeEvent, - nativeEventTarget - ); - gesture.touchHistory = ResponderTouchHistoryStore.touchHistory; - accumulateDirectDispatches(gesture); - extracted = accumulate(extracted, gesture); - } - - var isResponderTerminate = - responderInst && topLevelType === TOP_TOUCH_CANCEL; - var isResponderRelease = - responderInst && - !isResponderTerminate && - isEndish(topLevelType) && - noResponderTouches(nativeEvent); - var finalTouch = isResponderTerminate - ? eventTypes.responderTerminate - : isResponderRelease - ? eventTypes.responderRelease - : null; - - if (finalTouch) { - var finalEvent = ResponderSyntheticEvent.getPooled( - finalTouch, - responderInst, - nativeEvent, - nativeEventTarget - ); - finalEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; - accumulateDirectDispatches(finalEvent); - extracted = accumulate(extracted, finalEvent); - changeResponder(null); - } - - return extracted; - }, - GlobalResponderHandler: null, - injection: { - /** - * @param {{onChange: (ReactID, ReactID) => void} GlobalResponderHandler - * Object that handles any change in responder. Use this to inject - * integration with an existing touch handling system etc. - */ - injectGlobalResponderHandler: function(GlobalResponderHandler) { - ResponderEventPlugin.GlobalResponderHandler = GlobalResponderHandler; + { + var PossiblyWeakMap = typeof WeakMap === "function" ? WeakMap : Map; + componentFrameCache = new PossiblyWeakMap(); } - } -}; + var BEFORE_SLASH_RE = /^(.*)[\\\/]/; -/** - * Injectable ordering of event plugins. - */ -var eventPluginOrder = null; -/** - * Injectable mapping from names to event plugin modules. - */ + function describeComponentFrame(name, source, ownerName) { + var sourceInfo = ""; -var namesToPlugins = {}; -/** - * Recomputes the plugin list using the injected plugins and plugin ordering. - * - * @private - */ + if (source) { + var path = source.fileName; + var fileName = path.replace(BEFORE_SLASH_RE, ""); // In DEV, include code for a common special case: + // prefer "folder/index.js" instead of just "index.js". -function recomputePluginOrdering() { - if (!eventPluginOrder) { - // Wait until an `eventPluginOrder` is injected. - return; - } + if (/^index\./.test(fileName)) { + var match = path.match(BEFORE_SLASH_RE); - for (var pluginName in namesToPlugins) { - var pluginModule = namesToPlugins[pluginName]; - var pluginIndex = eventPluginOrder.indexOf(pluginName); + if (match) { + var pathBeforeSlash = match[1]; - if (pluginIndex <= -1) { - throw new Error( - "EventPluginRegistry: Cannot inject event plugins that do not exist in " + - ("the plugin ordering, `" + pluginName + "`.") - ); - } + if (pathBeforeSlash) { + var folderName = pathBeforeSlash.replace(BEFORE_SLASH_RE, ""); + fileName = folderName + "/" + fileName; + } + } + } - if (plugins[pluginIndex]) { - continue; - } + sourceInfo = " (at " + fileName + ":" + source.lineNumber + ")"; + } else if (ownerName) { + sourceInfo = " (created by " + ownerName + ")"; + } - if (!pluginModule.extractEvents) { - throw new Error( - "EventPluginRegistry: Event plugins must implement an `extractEvents` " + - ("method, but `" + pluginName + "` does not.") - ); + return "\n in " + (name || "Unknown") + sourceInfo; } - plugins[pluginIndex] = pluginModule; - var publishedEvents = pluginModule.eventTypes; - - for (var eventName in publishedEvents) { - if ( - !publishEventForPlugin( - publishedEvents[eventName], - pluginModule, - eventName - ) - ) { - throw new Error( - "EventPluginRegistry: Failed to publish event `" + - eventName + - "` for plugin `" + - pluginName + - "`." - ); + function describeClassComponentFrame(ctor, source, ownerFn) { + { + return describeFunctionComponentFrame(ctor, source, ownerFn); } } - } -} -/** - * Publishes an event so that it can be dispatched by the supplied plugin. - * - * @param {object} dispatchConfig Dispatch configuration for the event. - * @param {object} PluginModule Plugin publishing the event. - * @return {boolean} True if the event was successfully published. - * @private - */ + function describeFunctionComponentFrame(fn, source, ownerFn) { + { + if (!fn) { + return ""; + } -function publishEventForPlugin(dispatchConfig, pluginModule, eventName) { - if (eventNameDispatchConfigs.hasOwnProperty(eventName)) { - throw new Error( - "EventPluginRegistry: More than one plugin attempted to publish the same " + - ("event name, `" + eventName + "`.") - ); - } + var name = fn.displayName || fn.name || null; + var ownerName = null; - eventNameDispatchConfigs[eventName] = dispatchConfig; - var phasedRegistrationNames = dispatchConfig.phasedRegistrationNames; + if (ownerFn) { + ownerName = ownerFn.displayName || ownerFn.name || null; + } - if (phasedRegistrationNames) { - for (var phaseName in phasedRegistrationNames) { - if (phasedRegistrationNames.hasOwnProperty(phaseName)) { - var phasedRegistrationName = phasedRegistrationNames[phaseName]; - publishRegistrationName( - phasedRegistrationName, - pluginModule, - eventName - ); + return describeComponentFrame(name, source, ownerName); } } - return true; - } else if (dispatchConfig.registrationName) { - publishRegistrationName( - dispatchConfig.registrationName, - pluginModule, - eventName - ); - return true; - } + function describeUnknownElementTypeFrameInDEV(type, source, ownerFn) { + if (type == null) { + return ""; + } - return false; -} -/** - * Publishes a registration name that is used to identify dispatched events. - * - * @param {string} registrationName Registration name to add. - * @param {object} PluginModule Plugin publishing the event. - * @private - */ + if (typeof type === "function") { + { + return describeFunctionComponentFrame(type, source, ownerFn); + } + } -function publishRegistrationName(registrationName, pluginModule, eventName) { - if (registrationNameModules[registrationName]) { - throw new Error( - "EventPluginRegistry: More than one plugin attempted to publish the same " + - ("registration name, `" + registrationName + "`.") - ); - } + if (typeof type === "string") { + return describeBuiltInComponentFrame(type, source, ownerFn); + } - registrationNameModules[registrationName] = pluginModule; - registrationNameDependencies[registrationName] = - pluginModule.eventTypes[eventName].dependencies; + switch (type) { + case REACT_SUSPENSE_TYPE: + return describeBuiltInComponentFrame("Suspense", source, ownerFn); - { - var lowerCasedName = registrationName.toLowerCase(); - } -} -/** - * Registers plugins so that they can extract and dispatch events. - */ + case REACT_SUSPENSE_LIST_TYPE: + return describeBuiltInComponentFrame("SuspenseList", source, ownerFn); + } -/** - * Ordered list of injected plugins. - */ + if (typeof type === "object") { + switch (type.$$typeof) { + case REACT_FORWARD_REF_TYPE: + return describeFunctionComponentFrame(type.render, source, ownerFn); -var plugins = []; -/** - * Mapping from event name to dispatch config - */ + case REACT_MEMO_TYPE: + // Memo may contain any component type so we recursively resolve it. + return describeUnknownElementTypeFrameInDEV(type.type, source, ownerFn); -var eventNameDispatchConfigs = {}; -/** - * Mapping from registration name to plugin module - */ + case REACT_LAZY_TYPE: { + var lazyComponent = type; + var payload = lazyComponent._payload; + var init = lazyComponent._init; -var registrationNameModules = {}; -/** - * Mapping from registration name to event name - */ + try { + // Lazy may contain any component type so we recursively resolve it. + return describeUnknownElementTypeFrameInDEV( + init(payload), + source, + ownerFn + ); + } catch (x) { } + } + } + } -var registrationNameDependencies = {}; + return ""; + } -/** - * Injects an ordering of plugins (by plugin name). This allows the ordering - * to be decoupled from injection of the actual plugins so that ordering is - * always deterministic regardless of packaging, on-the-fly injection, etc. - * - * @param {array} InjectedEventPluginOrder - * @internal - */ + var hasOwnProperty = Object.prototype.hasOwnProperty; -function injectEventPluginOrder(injectedEventPluginOrder) { - if (eventPluginOrder) { - throw new Error( - "EventPluginRegistry: Cannot inject event plugin ordering more than " + - "once. You are likely trying to load more than one copy of React." - ); - } // Clone the ordering so it cannot be dynamically mutated. + var loggedTypeFailures = {}; + var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; - eventPluginOrder = Array.prototype.slice.call(injectedEventPluginOrder); - recomputePluginOrdering(); -} -/** - * Injects plugins to be used by plugin event system. The plugin names must be - * in the ordering injected by `injectEventPluginOrder`. - * - * Plugins can be injected as part of page initialization or on-the-fly. - * - * @param {object} injectedNamesToPlugins Map from names to plugin modules. - * @internal - */ + 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); + } + } + } -function injectEventPluginsByName(injectedNamesToPlugins) { - var isOrderingDirty = false; + function checkPropTypes(typeSpecs, values, location, componentName, element) { + { + // $FlowFixMe This is okay but Flow doesn't know it. + var has = Function.call.bind(hasOwnProperty); - for (var pluginName in injectedNamesToPlugins) { - if (!injectedNamesToPlugins.hasOwnProperty(pluginName)) { - continue; - } + 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 pluginModule = injectedNamesToPlugins[pluginName]; + 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 ( - !namesToPlugins.hasOwnProperty(pluginName) || - namesToPlugins[pluginName] !== pluginModule - ) { - if (namesToPlugins[pluginName]) { - throw new Error( - "EventPluginRegistry: Cannot inject two different event plugins " + - ("using the same name, `" + pluginName + "`.") - ); - } + error$1 = typeSpecs[typeSpecName]( + values, + typeSpecName, + componentName, + location, + null, + "SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED" + ); + } catch (ex) { + error$1 = ex; + } - namesToPlugins[pluginName] = pluginModule; - isOrderingDirty = true; - } - } + if (error$1 && !(error$1 instanceof Error)) { + setCurrentlyValidatingElement(element); - if (isOrderingDirty) { - recomputePluginOrdering(); - } -} + 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 + ); -/** - * Get a list of listeners for a specific event, in-order. - * For React Native we treat the props-based function handlers - * as the first-class citizens, and they are always executed first - * for both capture and bubbling phase. - * - * We need "phase" propagated to this point to support the HostComponent - * EventEmitter API, which does not mutate the name of the handler based - * on phase (whereas prop handlers are registered as `onMyEvent` and `onMyEvent_Capture`). - * - * Native system events emitted into React Native - * will be emitted both to the prop handler function and to imperative event - * listeners. - * - * This will either return null, a single Function without an array, or - * an array of 2+ items. - */ + setCurrentlyValidatingElement(null); + } -function getListeners( - inst, - registrationName, - phase, - dispatchToImperativeListeners -) { - var stateNode = inst.stateNode; - - if (stateNode === null) { - return null; - } // If null: Work in progress (ex: onload events in incremental mode). - - var props = getFiberCurrentPropsFromNode(stateNode); - - if (props === null) { - // Work in progress. - return null; - } - - var listener = props[registrationName]; - - if (listener && typeof listener !== "function") { - throw new Error( - "Expected `" + - registrationName + - "` listener to be a function, instead got a value of `" + - typeof listener + - "` type." - ); - } // If there are no imperative listeners, early exit. - - if ( - !( - dispatchToImperativeListeners && - stateNode.canonical && - stateNode.canonical._eventListeners - ) - ) { - return listener; - } // Below this is the de-optimized path. - // If you are using _eventListeners, we do not (yet) - // expect this to be as performant as the props-only path. - // If/when this becomes a bottleneck, it can be refactored - // to avoid unnecessary closures and array allocations. - // - // Previously, there was only one possible listener for an event: - // the onEventName property in props. - // Now, it is also possible to have N listeners - // for a specific event on a node. Thus, we accumulate all of the listeners, - // including the props listener, and return a function that calls them all in - // order, starting with the handler prop and then the listeners in order. - // We return either a non-empty array or null. - - var listeners = []; - - if (listener) { - listeners.push(listener); - } // TODO: for now, all of these events get an `rn:` prefix to enforce - // that the user knows they're only getting non-W3C-compliant events - // through this imperative event API. - // Events might not necessarily be noncompliant, but we currently have - // no verification that /any/ events are compliant. - // Thus, we prefix to ensure no collision with W3C event names. - - var requestedPhaseIsCapture = phase === "captured"; - var mangledImperativeRegistrationName = requestedPhaseIsCapture - ? "rn:" + registrationName.replace(/Capture$/, "") - : "rn:" + registrationName; // Get imperative event listeners for this event - - if ( - stateNode.canonical._eventListeners[mangledImperativeRegistrationName] && - stateNode.canonical._eventListeners[mangledImperativeRegistrationName] - .length > 0 - ) { - var eventListeners = - stateNode.canonical._eventListeners[mangledImperativeRegistrationName]; - eventListeners.forEach(function(listenerObj) { - // Make sure phase of listener matches requested phase - var isCaptureEvent = - listenerObj.options.capture != null && listenerObj.options.capture; - - if (isCaptureEvent !== requestedPhaseIsCapture) { - return; - } // For now (this is an area of future optimization) we must wrap - // all imperative event listeners in a function to unwrap the SyntheticEvent - // and pass them an Event. - // When this API is more stable and used more frequently, we can revisit. - - var listenerFnWrapper = function(syntheticEvent) { - var eventInst = new ReactNativePrivateInterface.CustomEvent( - mangledImperativeRegistrationName, - { - detail: syntheticEvent.nativeEvent - } - ); - eventInst.isTrusted = true; // setSyntheticEvent is present on the React Native Event shim. - // It is used to forward method calls on Event to the underlying SyntheticEvent. - // $FlowFixMe + 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); - eventInst.setSyntheticEvent(syntheticEvent); + error("Failed %s type: %s", location, error$1.message); - for ( - var _len = arguments.length, - args = new Array(_len > 1 ? _len - 1 : 0), - _key = 1; - _key < _len; - _key++ - ) { - args[_key - 1] = arguments[_key]; - } - - listenerObj.listener.apply(listenerObj, [eventInst].concat(args)); - }; // Only call once? - // If so, we ensure that it's only called once by setting a flag - // and by removing it from eventListeners once it is called (but only - // when it's actually been executed). - - if (listenerObj.options.once) { - listeners.push(function() { - // Remove from the event listener once it's been called - stateNode.canonical.removeEventListener_unstable( - mangledImperativeRegistrationName, - listenerObj.listener, - listenerObj.capture - ); // Guard against function being called more than once in - // case there are somehow multiple in-flight references to - // it being processed - - if (!listenerObj.invalidated) { - listenerObj.invalidated = true; - listenerObj.listener.apply(listenerObj, arguments); + setCurrentlyValidatingElement(null); + } } - }); - } else { - listeners.push(listenerFnWrapper); + } } - }); - } - - if (listeners.length === 0) { - return null; - } - - if (listeners.length === 1) { - return listeners[0]; - } + } - return listeners; -} + var valueStack = []; + var fiberStack; -var customBubblingEventTypes = - ReactNativePrivateInterface.ReactNativeViewConfigRegistry - .customBubblingEventTypes, - customDirectEventTypes = - ReactNativePrivateInterface.ReactNativeViewConfigRegistry - .customDirectEventTypes; // Start of inline: the below functions were inlined from -// EventPropagator.js, as they deviated from ReactDOM's newer -// implementations. - -function listenersAtPhase(inst, event, propagationPhase) { - var registrationName = - event.dispatchConfig.phasedRegistrationNames[propagationPhase]; - return getListeners(inst, registrationName, propagationPhase, true); -} + { + fiberStack = []; + } -function accumulateListenersAndInstances(inst, event, listeners) { - var listenersLength = listeners - ? isArray(listeners) - ? listeners.length - : 1 - : 0; + var index = -1; - if (listenersLength > 0) { - event._dispatchListeners = accumulateInto( - event._dispatchListeners, - listeners - ); // Avoid allocating additional arrays here + function createCursor(defaultValue) { + return { + current: defaultValue + }; + } - if (event._dispatchInstances == null && listenersLength === 1) { - event._dispatchInstances = inst; - } else { - event._dispatchInstances = event._dispatchInstances || []; + function pop(cursor, fiber) { + if (index < 0) { + { + error("Unexpected pop."); + } - if (!isArray(event._dispatchInstances)) { - event._dispatchInstances = [event._dispatchInstances]; + return; } - for (var i = 0; i < listenersLength; i++) { - event._dispatchInstances.push(inst); + { + if (fiber !== fiberStack[index]) { + error("Unexpected Fiber popped."); + } } - } - } -} - -function accumulateDirectionalDispatches$1(inst, phase, event) { - { - if (!inst) { - error("Dispatching inst must not be null"); - } - } - - var listeners = listenersAtPhase(inst, event, phase); - accumulateListenersAndInstances(inst, event, listeners); -} -function getParent$1(inst) { - do { - inst = inst.return; // TODO: If this is a HostRoot we might want to bail out. - // That is depending on if we want nested subtrees (layers) to bubble - // events to their parent. We could also go through parentNode on the - // host node but that wouldn't work for React Native and doesn't let us - // do the portal feature. - } while (inst && inst.tag !== HostComponent); + cursor.current = valueStack[index]; + valueStack[index] = null; - if (inst) { - return inst; - } + { + fiberStack[index] = null; + } - return null; -} -/** - * Simulates the traversal of a two-phase, capture/bubble event dispatch. - */ + index--; + } -function traverseTwoPhase$1(inst, fn, arg, skipBubbling) { - var path = []; + function push(cursor, value, fiber) { + index++; + valueStack[index] = cursor.current; - while (inst) { - path.push(inst); - inst = getParent$1(inst); - } + { + fiberStack[index] = fiber; + } - var i; + cursor.current = value; + } - for (i = path.length; i-- > 0; ) { - fn(path[i], "captured", arg); - } + var warnedAboutMissingGetChildContext; - if (skipBubbling) { - // Dispatch on target only - fn(path[0], "bubbled", arg); - } else { - for (i = 0; i < path.length; i++) { - fn(path[i], "bubbled", arg); + { + warnedAboutMissingGetChildContext = {}; } - } -} - -function accumulateTwoPhaseDispatchesSingle$1(event) { - if (event && event.dispatchConfig.phasedRegistrationNames) { - traverseTwoPhase$1( - event._targetInst, - accumulateDirectionalDispatches$1, - event, - false - ); - } -} -function accumulateTwoPhaseDispatches$1(events) { - forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle$1); -} + var emptyContextObject = {}; -function accumulateCapturePhaseDispatches(event) { - if (event && event.dispatchConfig.phasedRegistrationNames) { - traverseTwoPhase$1( - event._targetInst, - accumulateDirectionalDispatches$1, - event, - true - ); - } -} -/** - * Accumulates without regard to direction, does not look for phased - * registration names. Same as `accumulateDirectDispatchesSingle` but without - * requiring that the `dispatchMarker` be the same as the dispatched ID. - */ + { + Object.freeze(emptyContextObject); + } // A cursor to the current merged context object on the stack. -function accumulateDispatches$1(inst, ignoredDirection, event) { - if (inst && event && event.dispatchConfig.registrationName) { - var registrationName = event.dispatchConfig.registrationName; - var listeners = getListeners(inst, registrationName, "bubbled", false); - accumulateListenersAndInstances(inst, event, listeners); - } -} -/** - * Accumulates dispatches on an `SyntheticEvent`, but only for the - * `dispatchMarker`. - * @param {SyntheticEvent} event - */ + var contextStackCursor = createCursor(emptyContextObject); // A cursor to a boolean indicating whether the context has changed. -function accumulateDirectDispatchesSingle$1(event) { - if (event && event.dispatchConfig.registrationName) { - accumulateDispatches$1(event._targetInst, null, event); - } -} + 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. -function accumulateDirectDispatches$1(events) { - forEachAccumulated(events, accumulateDirectDispatchesSingle$1); -} // End of inline - -var ReactNativeBridgeEventPlugin = { - eventTypes: {}, - extractEvents: function( - topLevelType, - targetInst, - nativeEvent, - nativeEventTarget - ) { - if (targetInst == null) { - // Probably a node belonging to another renderer's tree. - return null; - } + var previousContext = emptyContextObject; - var bubbleDispatchConfig = customBubblingEventTypes[topLevelType]; - var directDispatchConfig = customDirectEventTypes[topLevelType]; + 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; + } - if (!bubbleDispatchConfig && !directDispatchConfig) { - throw new Error( // $FlowFixMe - Flow doesn't like this string coercion because DOMTopLevelEventType is opaque - 'Unsupported top level event type "' + topLevelType + '" dispatched' - ); + return contextStackCursor.current; + } } - var event = SyntheticEvent.getPooled( - bubbleDispatchConfig || directDispatchConfig, - targetInst, - nativeEvent, - nativeEventTarget - ); - - if (bubbleDispatchConfig) { - var skipBubbling = - event != null && - event.dispatchConfig.phasedRegistrationNames != null && - event.dispatchConfig.phasedRegistrationNames.skipBubbling; - - if (skipBubbling) { - accumulateCapturePhaseDispatches(event); - } else { - accumulateTwoPhaseDispatches$1(event); + function cacheContext(workInProgress, unmaskedContext, maskedContext) { + { + var instance = workInProgress.stateNode; + instance.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext; + instance.__reactInternalMemoizedMaskedChildContext = maskedContext; } - } else if (directDispatchConfig) { - accumulateDirectDispatches$1(event); - } else { - return null; } - return event; - } -}; - -var ReactNativeEventPluginOrder = [ - "ResponderEventPlugin", - "ReactNativeBridgeEventPlugin" -]; - -/** - * Make sure essential globals are available and are patched correctly. Please don't remove this - * line. Bundles created by react-packager `require` it before executing any application code. This - * ensures it exists in the dependency graph and can be `require`d. - * TODO: require this in packager, not in React #10932517 - */ -/** - * Inject module for resolving DOM hierarchy and plugin ordering. - */ + function getMaskedContext(workInProgress, unmaskedContext) { + { + var type = workInProgress.type; + var contextTypes = type.contextTypes; -injectEventPluginOrder(ReactNativeEventPluginOrder); -/** - * Some important event plugins included by default (without having to require - * them). - */ + 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. -injectEventPluginsByName({ - ResponderEventPlugin: ResponderEventPlugin, - ReactNativeBridgeEventPlugin: ReactNativeBridgeEventPlugin -}); + var instance = workInProgress.stateNode; -function getInstanceFromInstance(instanceHandle) { - return instanceHandle; -} + if ( + instance && + instance.__reactInternalMemoizedUnmaskedChildContext === unmaskedContext + ) { + return instance.__reactInternalMemoizedMaskedChildContext; + } -function getTagFromInstance(inst) { - var nativeInstance = inst.stateNode.canonical; + var context = {}; - if (!nativeInstance._nativeTag) { - throw new Error("All native instances should have a tag."); - } + for (var key in contextTypes) { + context[key] = unmaskedContext[key]; + } - return nativeInstance; -} -function getFiberCurrentPropsFromNode$1(inst) { - return inst.canonical.currentProps; -} + { + 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. -// Module provided by RN: -var ReactFabricGlobalResponderHandler = { - onChange: function(from, to, blockNativeResponder) { - var fromOrTo = from || to; - var fromOrToStateNode = fromOrTo && fromOrTo.stateNode; - var isFabric = !!( - fromOrToStateNode && fromOrToStateNode.canonical._internalInstanceHandle - ); + if (instance) { + cacheContext(workInProgress, unmaskedContext, context); + } - if (isFabric) { - if (from) { - // equivalent to clearJSResponder - nativeFabricUIManager.setIsJSResponder( - from.stateNode.node, - false, - blockNativeResponder || false - ); + return context; } + } - if (to) { - // equivalent to setJSResponder - nativeFabricUIManager.setIsJSResponder( - to.stateNode.node, - true, - blockNativeResponder || false - ); + function hasContextChanged() { + { + return didPerformWorkStackCursor.current; } - } else { - if (to !== null) { - var tag = to.stateNode.canonical._nativeTag; - ReactNativePrivateInterface.UIManager.setJSResponder( - tag, - blockNativeResponder - ); - } else { - ReactNativePrivateInterface.UIManager.clearJSResponder(); + } + + function isContextProvider(type) { + { + var childContextTypes = type.childContextTypes; + return childContextTypes !== null && childContextTypes !== undefined; } } - } -}; -setComponentTree( - getFiberCurrentPropsFromNode$1, - getInstanceFromInstance, - getTagFromInstance -); -ResponderEventPlugin.injection.injectGlobalResponderHandler( - ReactFabricGlobalResponderHandler -); + function popContext(fiber) { + { + pop(didPerformWorkStackCursor, fiber); + pop(contextStackCursor, fiber); + } + } -/** - * `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; -} + function popTopLevelContextObject(fiber) { + { + pop(didPerformWorkStackCursor, fiber); + pop(contextStackCursor, fiber); + } + } -var enableSchedulingProfiler = false; -var enableProfilerTimer = true; -var enableProfilerCommitHooks = true; -var warnAboutStringRefs = false; -var enableSuspenseAvoidThisFallback = false; -var enableNewReconciler = false; -var enableLazyContextPropagation = false; -var enableLegacyHidden = false; - -// 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; -} + function pushTopLevelContextObject(fiber, context, didChange) { + { + if (contextStackCursor.current !== emptyContextObject) { + throw new Error( + "Unexpected context found on stack. " + + "This error is likely caused by a bug in React. Please file an issue." + ); + } -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." - ); + push(contextStackCursor, context, fiber); + push(didPerformWorkStackCursor, didChange, fiber); + } } - } - if (typeof type === "function") { - return type.displayName || type.name || null; - } - - if (typeof type === "string") { - return type; - } + 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. - switch (type) { - case REACT_FRAGMENT_TYPE: - return "Fragment"; + if (typeof instance.getChildContext !== "function") { + { + var componentName = getComponentNameFromFiber(fiber) || "Unknown"; - case REACT_PORTAL_TYPE: - return "Portal"; + if (!warnedAboutMissingGetChildContext[componentName]) { + warnedAboutMissingGetChildContext[componentName] = true; - case REACT_PROFILER_TYPE: - return "Profiler"; + 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 + ); + } + } - case REACT_STRICT_MODE_TYPE: - return "StrictMode"; + return parentContext; + } - case REACT_SUSPENSE_TYPE: - return "Suspense"; + var childContext = instance.getChildContext(); - case REACT_SUSPENSE_LIST_TYPE: - return "SuspenseList"; - } + for (var contextKey in childContext) { + if (!(contextKey in childContextTypes)) { + throw new Error( + (getComponentNameFromFiber(fiber) || "Unknown") + + '.getChildContext(): key "' + + contextKey + + '" is not defined in childContextTypes.' + ); + } + } - if (typeof type === "object") { - switch (type.$$typeof) { - case REACT_CONTEXT_TYPE: - var context = type; - return getContextName(context) + ".Consumer"; + { + var name = getComponentNameFromFiber(fiber) || "Unknown"; + checkPropTypes(childContextTypes, childContext, "child context", name); + } - case REACT_PROVIDER_TYPE: - var provider = type; - return getContextName(provider._context) + ".Provider"; + return assign({}, parentContext, childContext); + } + } - case REACT_FORWARD_REF_TYPE: - return getWrappedName(type, type.render, "ForwardRef"); + 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.current; + push(contextStackCursor, memoizedMergedChildContext, workInProgress); + push( + didPerformWorkStackCursor, + didPerformWorkStackCursor.current, + workInProgress + ); + return true; + } + } - case REACT_MEMO_TYPE: - var outerName = type.displayName || null; + function invalidateContextProvider(workInProgress, type, didChange) { + { + var instance = workInProgress.stateNode; - if (outerName !== null) { - return outerName; + 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." + ); } - return getComponentNameFromType(type.type) || "Memo"; + 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. - case REACT_LAZY_TYPE: { - var lazyComponent = type; - var payload = lazyComponent._payload; - var init = lazyComponent._init; + pop(didPerformWorkStackCursor, workInProgress); + pop(contextStackCursor, workInProgress); // Now push the new context and mark that it has changed. - try { - return getComponentNameFromType(init(payload)); - } catch (x) { - return null; + push(contextStackCursor, mergedContext, workInProgress); + push(didPerformWorkStackCursor, didChange, workInProgress); + } else { + pop(didPerformWorkStackCursor, workInProgress); + push(didPerformWorkStackCursor, didChange, workInProgress); } } - - // eslint-disable-next-line no-fallthrough } - } - return null; -} - -function getWrappedName$1(outerType, innerType, wrapperName) { - var functionName = innerType.displayName || innerType.name || ""; - return ( - outerType.displayName || - (functionName !== "" ? wrapperName + "(" + functionName + ")" : wrapperName) - ); -} // Keep in sync with shared/getComponentNameFromType - -function getContextName$1(type) { - return type.displayName || "Context"; -} + 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 getComponentNameFromFiber(fiber) { - var tag = fiber.tag, - type = fiber.type; + var node = fiber; - switch (tag) { - case CacheComponent: - return "Cache"; + do { + switch (node.tag) { + case HostRoot: + return node.stateNode.context; - case ContextConsumer: - var context = type; - return getContextName$1(context) + ".Consumer"; + case ClassComponent: { + var Component = node.type; - case ContextProvider: - var provider = type; - return getContextName$1(provider._context) + ".Provider"; + if (isContextProvider(Component)) { + return node.stateNode.__reactInternalMemoizedMergedChildContext; + } - case DehydratedFragment: - return "DehydratedFragment"; + break; + } + } - case ForwardRef: - return getWrappedName$1(type, type.render, "ForwardRef"); + node = node.return; + } while (node !== null); - case Fragment: - return "Fragment"; + throw new Error( + "Found unexpected detached subtree parent. " + + "This error is likely caused by a bug in React. Please file an issue." + ); + } + } - case HostComponent: - // Host component type is the display name (e.g. "div", "View") - return type; + var LegacyRoot = 0; + var ConcurrentRoot = 1; - case HostPortal: - return "Portal"; + /** + * 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 + ); + } - case HostRoot: - return "Root"; + var objectIs = typeof Object.is === "function" ? Object.is : is; - case HostText: - return "Text"; + var syncQueue = null; + var includesLegacySyncCallbacks = false; + var isFlushingSyncQueue = false; + function scheduleSyncCallback(callback) { + // Push this callback into an internal queue. We'll flush these either in + // the next tick, or earlier if something calls `flushSyncCallbackQueue`. + if (syncQueue === null) { + syncQueue = [callback]; + } else { + // Push onto existing queue. Don't need to schedule a callback because + // we already scheduled one when we created the queue. + syncQueue.push(callback); + } + } + function scheduleLegacySyncCallback(callback) { + includesLegacySyncCallbacks = true; + scheduleSyncCallback(callback); + } + function flushSyncCallbacksOnlyInLegacyMode() { + // Only flushes the queue if there's a legacy sync callback scheduled. + // TODO: There's only a single type of callback: performSyncOnWorkOnRoot. So + // it might make more sense for the queue to be a list of roots instead of a + // list of generic callbacks. Then we can have two: one for legacy roots, one + // for concurrent roots. And this method would only flush the legacy ones. + if (includesLegacySyncCallbacks) { + flushSyncCallbacks(); + } + } + function flushSyncCallbacks() { + if (!isFlushingSyncQueue && syncQueue !== null) { + // Prevent re-entrance. + isFlushingSyncQueue = true; + var i = 0; + var previousUpdatePriority = getCurrentUpdatePriority(); - case LazyComponent: - // Name comes from the type in this case; we don't have a tag. - return getComponentNameFromType(type); + try { + var isSync = true; + var queue = syncQueue; // TODO: Is this necessary anymore? The only user code that runs in this + // queue is in the render or commit phases. - case Mode: - if (type === REACT_STRICT_MODE_TYPE) { - // Don't be less specific than shared/getComponentNameFromType - return "StrictMode"; - } + setCurrentUpdatePriority(DiscreteEventPriority); - return "Mode"; + for (; i < queue.length; i++) { + var callback = queue[i]; - case OffscreenComponent: - return "Offscreen"; + do { + callback = callback(isSync); + } while (callback !== null); + } - case Profiler: - return "Profiler"; + syncQueue = null; + includesLegacySyncCallbacks = false; + } catch (error) { + // If something throws, leave the remaining callbacks on the queue. + if (syncQueue !== null) { + syncQueue = syncQueue.slice(i + 1); + } // Resume flushing in the next tick - case ScopeComponent: - return "Scope"; + scheduleCallback(ImmediatePriority, flushSyncCallbacks); + throw error; + } finally { + setCurrentUpdatePriority(previousUpdatePriority); + isFlushingSyncQueue = false; + } + } - case SuspenseComponent: - return "Suspense"; + return null; + } - case SuspenseListComponent: - return "SuspenseList"; + // 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; + } + + // TODO: Use the unified fiber stack module instead of this local one? + // Intentionally not using it yet to derisk the initial implementation, because + // the way we push/pop these values is a bit unusual. If there's a mistake, I'd + // rather the ids be wrong than crash the whole reconciler. + var forkStack = []; + var forkStackIndex = 0; + var treeForkProvider = null; + var treeForkCount = 0; + var idStack = []; + var idStackIndex = 0; + var treeContextProvider = null; + var treeContextId = 1; + var treeContextOverflow = ""; + + function popTreeContext(workInProgress) { + // Restore the previous values. + // This is a bit more complicated than other context-like modules in Fiber + // because the same Fiber may appear on the stack multiple times and for + // different reasons. We have to keep popping until the work-in-progress is + // no longer at the top of the stack. + while (workInProgress === treeForkProvider) { + treeForkProvider = forkStack[--forkStackIndex]; + forkStack[forkStackIndex] = null; + treeForkCount = forkStack[--forkStackIndex]; + forkStack[forkStackIndex] = null; + } + + while (workInProgress === treeContextProvider) { + treeContextProvider = idStack[--idStackIndex]; + idStack[idStackIndex] = null; + treeContextOverflow = idStack[--idStackIndex]; + idStack[idStackIndex] = null; + treeContextId = idStack[--idStackIndex]; + idStack[idStackIndex] = null; + } + } + + 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 didSuspendOrErrorDEV = false; // Hydration errors that were thrown inside this boundary + + var hydrationErrors = null; + function didSuspendOrErrorWhileHydratingDEV() { + { + return didSuspendOrErrorDEV; + } + } - case TracingMarkerComponent: - return "TracingMarker"; - // The display name for this tags come from the user-provided type: + function reenterHydrationStateFromDehydratedSuspenseInstance( + fiber, + suspenseInstance, + treeContext + ) { + { + return false; + } + } - case ClassComponent: - case FunctionComponent: - case IncompleteClassComponent: - case IndeterminateComponent: - case MemoComponent: - case SimpleMemoComponent: - if (typeof type === "function") { - return type.displayName || type.name || null; + function prepareToHydrateHostInstance( + fiber, + rootContainerInstance, + 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 type === "string") { - return type; + 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 shouldUpdate = hydrateTextInstance(); + } - break; - } + 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." + ); + } + } - return null; -} + function popHydrationState(fiber) { + { + return false; + } + } -// Don't change these two values. They're used by React Dev Tools. -var NoFlags = - /* */ - 0; -var PerformedWork = - /* */ - 1; // You can change the rest (and add more). - -var Placement = - /* */ - 2; -var Update = - /* */ - 4; -var ChildDeletion = - /* */ - 16; -var ContentReset = - /* */ - 32; -var Callback = - /* */ - 64; -var DidCapture = - /* */ - 128; -var ForceClientRender = - /* */ - 256; -var Ref = - /* */ - 512; -var Snapshot = - /* */ - 1024; -var Passive = - /* */ - 2048; -var Hydrating = - /* */ - 4096; -var Visibility = - /* */ - 8192; -var StoreConsistency = - /* */ - 16384; -var LifecycleEffectMask = - Passive | 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 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; // These flags allow us to traverse to fibers that have effects on mount -// 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 | 0; -var MutationMask = - Placement | - Update | - ChildDeletion | - ContentReset | - Ref | - Hydrating | - Visibility; -var LayoutMask = Update | Callback | Ref | Visibility; // TODO: Split into PassiveMountMask and PassiveUnmountMask - -var PassiveMask = Passive | 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; - -var ReactCurrentOwner = 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) { - // 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; - } - - 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.current; + 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; + } + } - if (owner !== null && owner.tag === ClassComponent) { - var ownerFiber = owner; - var instance = ownerFiber.stateNode; + function getIsHydrating() { + return isHydrating; + } - 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 queueHydrationError(error) { + if (hydrationErrors === null) { + hydrationErrors = [error]; + } else { + hydrationErrors.push(error); } + } - instance._warnedAboutRefsInRender = true; + var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig; + var NoTransition = null; + function requestCurrentTransition() { + return ReactCurrentBatchConfig.transition; } - } - var fiber = get(component); + /** + * 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 (!fiber) { - return false; - } + function shallowEqual(objA, objB) { + if (objectIs(objA, objB)) { + return true; + } - return getNearestMountedFiber(fiber) === fiber; -} + if ( + typeof objA !== "object" || + objA === null || + typeof objB !== "object" || + objB === null + ) { + return false; + } -function assertIsMounted(fiber) { - if (getNearestMountedFiber(fiber) !== fiber) { - throw new Error("Unable to find node on an unmounted component."); - } -} + var keysA = Object.keys(objA); + var keysB = Object.keys(objB); -function findCurrentFiberUsingSlowPath(fiber) { - var alternate = fiber.alternate; + if (keysA.length !== keysB.length) { + return false; + } // Test for A's keys different from B. - if (!alternate) { - // If there is no alternate, then we only need to check if it is mounted. - var nearestMounted = getNearestMountedFiber(fiber); + for (var i = 0; i < keysA.length; i++) { + var currentKey = keysA[i]; - if (nearestMounted === null) { - throw new Error("Unable to find node on an unmounted component."); - } + if ( + !hasOwnProperty.call(objB, currentKey) || + !objectIs(objA[currentKey], objB[currentKey]) + ) { + return false; + } + } - if (nearestMounted !== fiber) { - return null; + return true; } - 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 describeFiber(fiber) { + var owner = fiber._debugOwner ? fiber._debugOwner.type : null; + var source = fiber._debugSource; - var a = fiber; - var b = alternate; + switch (fiber.tag) { + case HostComponent: + return describeBuiltInComponentFrame(fiber.type, source, owner); - while (true) { - var parentA = a.return; + case LazyComponent: + return describeBuiltInComponentFrame("Lazy", source, owner); - if (parentA === null) { - // We're at the root. - break; - } + case SuspenseComponent: + return describeBuiltInComponentFrame("Suspense", source, owner); - var parentB = parentA.alternate; + case SuspenseListComponent: + return describeBuiltInComponentFrame("SuspenseList", source, owner); - 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; + case FunctionComponent: + case IndeterminateComponent: + case SimpleMemoComponent: + return describeFunctionComponentFrame(fiber.type, source, owner); - if (nextParent !== null) { - a = b = nextParent; - continue; - } // If there's no parent, we're at the root. + case ForwardRef: + return describeFunctionComponentFrame(fiber.type.render, source, owner); - 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. + case ClassComponent: + return describeClassComponentFrame(fiber.type, source, owner); - if (parentA.child === parentB.child) { - var child = parentA.child; + default: + return ""; + } + } - while (child) { - if (child === a) { - // We've determined that A is the current branch. - assertIsMounted(parentA); - return fiber; - } + function getStackByFiberInDevAndProd(workInProgress) { + try { + var info = ""; + var node = workInProgress; - if (child === b) { - // We've determined that B is the current branch. - assertIsMounted(parentA); - return alternate; - } + do { + info += describeFiber(node); + node = node.return; + } while (node); - 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. - - 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; + return info; + } catch (x) { + return "\nError generating stack: " + x.message + "\n" + x.stack; + } + } - while (_child) { - if (_child === a) { - didFindChild = true; - a = parentA; - b = parentB; - break; + var ReactDebugCurrentFrame$1 = ReactSharedInternals.ReactDebugCurrentFrame; + var current = null; + var isRendering = false; + function getCurrentFiberOwnerNameInDevOrNull() { + { + if (current === null) { + return null; } - if (_child === b) { - didFindChild = true; - b = parentA; - a = parentB; - break; + var owner = current._debugOwner; + + if (owner !== null && typeof owner !== "undefined") { + return getComponentNameFromFiber(owner); } + } + + return null; + } - _child = _child.sibling; + 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); } + } - if (!didFindChild) { - // Search parent B's child set - _child = parentB.child; + 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; + } + } - while (_child) { - if (_child === a) { - didFindChild = true; - a = parentB; - b = parentA; - break; - } + var ReactStrictModeWarnings = { + recordUnsafeLifecycleWarnings: function (fiber, instance) { }, + flushPendingUnsafeLifecycleWarnings: function () { }, + recordLegacyContextWarning: function (fiber, instance) { }, + flushLegacyContextWarning: function () { }, + discardPendingWarnings: function () { } + }; - if (_child === b) { - didFindChild = true; - b = parentB; - a = parentA; - break; + { + var findStrictRoot = function (fiber) { + var maybeStrictRoot = null; + var node = fiber; + + while (node !== null) { + if (node.mode & StrictLegacyMode) { + maybeStrictRoot = node; } - _child = _child.sibling; + node = node.return; } - 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." - ); - } - } - } + return maybeStrictRoot; + }; - 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. + var setToSortedString = function (set) { + var array = []; + set.forEach(function (value) { + array.push(value); + }); + return array.sort().join(", "); + }; - if (a.tag !== HostRoot) { - throw new Error("Unable to find node on an unmounted component."); - } + var pendingComponentWillMountWarnings = []; + var pendingUNSAFE_ComponentWillMountWarnings = []; + var pendingComponentWillReceivePropsWarnings = []; + var pendingUNSAFE_ComponentWillReceivePropsWarnings = []; + var pendingComponentWillUpdateWarnings = []; + var pendingUNSAFE_ComponentWillUpdateWarnings = []; // Tracks components we have already warned about. - if (a.stateNode.current === a) { - // We've determined that A is the current branch. - return fiber; - } // Otherwise B has to be current branch. + var didWarnAboutUnsafeLifecycles = new Set(); - return alternate; -} -function findCurrentHostFiber(parent) { - var currentParent = findCurrentFiberUsingSlowPath(parent); - return currentParent !== null - ? findCurrentHostFiberImpl(currentParent) - : null; -} + ReactStrictModeWarnings.recordUnsafeLifecycleWarnings = function ( + fiber, + instance + ) { + // Dedupe strategy: Warn once per component. + if (didWarnAboutUnsafeLifecycles.has(fiber.type)) { + return; + } -function findCurrentHostFiberImpl(node) { - // Next we'll drill down this component to find the first HostComponent/Text. - if (node.tag === HostComponent || node.tag === HostText) { - return node; - } + if ( + typeof instance.componentWillMount === "function" && // Don't warn about react-lifecycles-compat polyfilled components. + instance.componentWillMount.__suppressDeprecationWarning !== true + ) { + pendingComponentWillMountWarnings.push(fiber); + } - var child = node.child; + if ( + fiber.mode & StrictLegacyMode && + typeof instance.UNSAFE_componentWillMount === "function" + ) { + pendingUNSAFE_ComponentWillMountWarnings.push(fiber); + } - while (child !== null) { - var match = findCurrentHostFiberImpl(child); + if ( + typeof instance.componentWillReceiveProps === "function" && + instance.componentWillReceiveProps.__suppressDeprecationWarning !== true + ) { + pendingComponentWillReceivePropsWarnings.push(fiber); + } - if (match !== null) { - return match; - } + if ( + fiber.mode & StrictLegacyMode && + typeof instance.UNSAFE_componentWillReceiveProps === "function" + ) { + pendingUNSAFE_ComponentWillReceivePropsWarnings.push(fiber); + } - child = child.sibling; - } + if ( + typeof instance.componentWillUpdate === "function" && + instance.componentWillUpdate.__suppressDeprecationWarning !== true + ) { + pendingComponentWillUpdateWarnings.push(fiber); + } - return null; -} + if ( + fiber.mode & StrictLegacyMode && + typeof instance.UNSAFE_componentWillUpdate === "function" + ) { + pendingUNSAFE_ComponentWillUpdateWarnings.push(fiber); + } + }; -/** - * In the future, we should cleanup callbacks by cancelling them instead of - * using this. - */ -function mountSafeCallback_NOT_REALLY_SAFE(context, callback) { - return function() { - if (!callback) { - return undefined; - } // This protects against createClass() components. - // We don't know if there is code depending on it. - // We intentionally don't use isMounted() because even accessing - // isMounted property on a React ES6 class will trigger a warning. - - if (typeof context.__isMounted === "boolean") { - if (!context.__isMounted) { - return undefined; - } - } // FIXME: there used to be other branches that protected - // against unmounted host components. But RN host components don't - // define isMounted() anymore, so those checks didn't do anything. - // They caused false positive warning noise so we removed them: - // https://github.com/facebook/react-native/issues/18868#issuecomment-413579095 - // However, this means that the callback is NOT guaranteed to be safe - // for host components. The solution we should implement is to make - // UIManager.measure() and similar calls truly cancelable. Then we - // can change our own code calling them to cancel when something unmounts. - - return callback.apply(context, arguments); - }; -} -function warnForStyleProps(props, validAttributes) { - { - for (var key in validAttributes.style) { - if (!(validAttributes[key] || props[key] === undefined)) { - error( - "You are setting the style `{ %s" + - ": ... }` as a prop. You " + - "should nest it in a style object. " + - "E.g. `{ style: { %s" + - ": ... } }`", - key, - key - ); - } - } - } -} + ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings = function () { + // We do an initial pass to gather component names + var componentWillMountUniqueNames = new Set(); -// Modules provided by RN: -var emptyObject = {}; -/** - * Create a payload that contains all the updates between two sets of props. - * - * These helpers are all encapsulated into a single module, because they use - * mutation as a performance optimization which leads to subtle shared - * dependencies between the code paths. To avoid this mutable state leaking - * across modules, I've kept them isolated to this module. - */ + if (pendingComponentWillMountWarnings.length > 0) { + pendingComponentWillMountWarnings.forEach(function (fiber) { + componentWillMountUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingComponentWillMountWarnings = []; + } -// Tracks removed keys -var removedKeys = null; -var removedKeyCount = 0; -var deepDifferOptions = { - unsafelyIgnoreFunctions: true -}; - -function defaultDiffer(prevProp, nextProp) { - if (typeof nextProp !== "object" || nextProp === null) { - // Scalars have already been checked for equality - return true; - } else { - // For objects and arrays, the default diffing algorithm is a deep compare - return ReactNativePrivateInterface.deepDiffer( - prevProp, - nextProp, - deepDifferOptions - ); - } -} + var UNSAFE_componentWillMountUniqueNames = new Set(); -function restoreDeletedValuesInNestedArray( - updatePayload, - node, - validAttributes -) { - if (isArray(node)) { - var i = node.length; + if (pendingUNSAFE_ComponentWillMountWarnings.length > 0) { + pendingUNSAFE_ComponentWillMountWarnings.forEach(function (fiber) { + UNSAFE_componentWillMountUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingUNSAFE_ComponentWillMountWarnings = []; + } - while (i-- && removedKeyCount > 0) { - restoreDeletedValuesInNestedArray( - updatePayload, - node[i], - validAttributes - ); - } - } else if (node && removedKeyCount > 0) { - var obj = node; + var componentWillReceivePropsUniqueNames = new Set(); - for (var propKey in removedKeys) { - if (!removedKeys[propKey]) { - continue; - } + if (pendingComponentWillReceivePropsWarnings.length > 0) { + pendingComponentWillReceivePropsWarnings.forEach(function (fiber) { + componentWillReceivePropsUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingComponentWillReceivePropsWarnings = []; + } - var nextProp = obj[propKey]; + var UNSAFE_componentWillReceivePropsUniqueNames = new Set(); - if (nextProp === undefined) { - continue; - } + if (pendingUNSAFE_ComponentWillReceivePropsWarnings.length > 0) { + pendingUNSAFE_ComponentWillReceivePropsWarnings.forEach(function (fiber) { + UNSAFE_componentWillReceivePropsUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingUNSAFE_ComponentWillReceivePropsWarnings = []; + } - var attributeConfig = validAttributes[propKey]; + var componentWillUpdateUniqueNames = new Set(); - if (!attributeConfig) { - continue; // not a valid native prop - } + if (pendingComponentWillUpdateWarnings.length > 0) { + pendingComponentWillUpdateWarnings.forEach(function (fiber) { + componentWillUpdateUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingComponentWillUpdateWarnings = []; + } - if (typeof nextProp === "function") { - nextProp = true; - } + var UNSAFE_componentWillUpdateUniqueNames = new Set(); - if (typeof nextProp === "undefined") { - nextProp = null; - } + 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 attributeConfig !== "object") { - // case: !Object is the default case - updatePayload[propKey] = nextProp; - } else if ( - typeof attributeConfig.diff === "function" || - typeof attributeConfig.process === "function" - ) { - // case: CustomAttributeConfiguration - var nextValue = - typeof attributeConfig.process === "function" - ? attributeConfig.process(nextProp) - : nextProp; - updatePayload[propKey] = nextValue; - } + if (UNSAFE_componentWillMountUniqueNames.size > 0) { + var sortedNames = setToSortedString(UNSAFE_componentWillMountUniqueNames); - removedKeys[propKey] = false; - removedKeyCount--; - } - } -} + error( + "Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code. " + + "See https://react.dev/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 + ); + } -function diffNestedArrayProperty( - updatePayload, - prevArray, - nextArray, - validAttributes -) { - var minLength = - prevArray.length < nextArray.length ? prevArray.length : nextArray.length; - var i; - - for (i = 0; i < minLength; i++) { - // Diff any items in the array in the forward direction. Repeated keys - // will be overwritten by later values. - updatePayload = diffNestedProperty( - updatePayload, - prevArray[i], - nextArray[i], - validAttributes - ); - } + if (UNSAFE_componentWillReceivePropsUniqueNames.size > 0) { + var _sortedNames = setToSortedString( + UNSAFE_componentWillReceivePropsUniqueNames + ); - for (; i < prevArray.length; i++) { - // Clear out all remaining properties. - updatePayload = clearNestedProperty( - updatePayload, - prevArray[i], - validAttributes - ); - } + error( + "Using UNSAFE_componentWillReceiveProps in strict mode is not recommended " + + "and may indicate bugs in your code. " + + "See https://react.dev/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://react.dev/link/derived-state\n" + + "\nPlease update the following components: %s", + _sortedNames + ); + } - for (; i < nextArray.length; i++) { - // Add all remaining properties. - updatePayload = addNestedProperty( - updatePayload, - nextArray[i], - validAttributes - ); - } + if (UNSAFE_componentWillUpdateUniqueNames.size > 0) { + var _sortedNames2 = setToSortedString( + UNSAFE_componentWillUpdateUniqueNames + ); - return updatePayload; -} + error( + "Using UNSAFE_componentWillUpdate in strict mode is not recommended " + + "and may indicate bugs in your code. " + + "See https://react.dev/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 diffNestedProperty( - updatePayload, - prevProp, - nextProp, - validAttributes -) { - if (!updatePayload && prevProp === nextProp) { - // If no properties have been added, then we can bail out quickly on object - // equality. - return updatePayload; - } + if (componentWillMountUniqueNames.size > 0) { + var _sortedNames3 = setToSortedString(componentWillMountUniqueNames); - if (!prevProp || !nextProp) { - if (nextProp) { - return addNestedProperty(updatePayload, nextProp, validAttributes); - } + warn( + "componentWillMount has been renamed, and is not recommended for use. " + + "See https://react.dev/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 + ); + } - if (prevProp) { - return clearNestedProperty(updatePayload, prevProp, validAttributes); - } + if (componentWillReceivePropsUniqueNames.size > 0) { + var _sortedNames4 = setToSortedString( + componentWillReceivePropsUniqueNames + ); - return updatePayload; - } + warn( + "componentWillReceiveProps has been renamed, and is not recommended for use. " + + "See https://react.dev/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://react.dev/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 + ); + } - if (!isArray(prevProp) && !isArray(nextProp)) { - // Both are leaves, we can diff the leaves. - return diffProperties(updatePayload, prevProp, nextProp, validAttributes); - } + if (componentWillUpdateUniqueNames.size > 0) { + var _sortedNames5 = setToSortedString(componentWillUpdateUniqueNames); - if (isArray(prevProp) && isArray(nextProp)) { - // Both are arrays, we can diff the arrays. - return diffNestedArrayProperty( - updatePayload, - prevProp, - nextProp, - validAttributes - ); - } + warn( + "componentWillUpdate has been renamed, and is not recommended for use. " + + "See https://react.dev/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 + ); + } + }; - if (isArray(prevProp)) { - return diffProperties( - updatePayload, // $FlowFixMe - We know that this is always an object when the input is. - ReactNativePrivateInterface.flattenStyle(prevProp), // $FlowFixMe - We know that this isn't an array because of above flow. - nextProp, - validAttributes - ); - } - - return diffProperties( - updatePayload, - prevProp, // $FlowFixMe - We know that this is always an object when the input is. - ReactNativePrivateInterface.flattenStyle(nextProp), - validAttributes - ); -} -/** - * addNestedProperty takes a single set of props and valid attribute - * attribute configurations. It processes each prop and adds it to the - * updatePayload. - */ + var pendingLegacyContextWarning = new Map(); // Tracks components we have already warned about. -function addNestedProperty(updatePayload, nextProp, validAttributes) { - if (!nextProp) { - return updatePayload; - } + var didWarnAboutLegacyContext = new Set(); - if (!isArray(nextProp)) { - // Add each property of the leaf. - return addProperties(updatePayload, nextProp, validAttributes); - } + ReactStrictModeWarnings.recordLegacyContextWarning = function ( + fiber, + instance + ) { + var strictRoot = findStrictRoot(fiber); - for (var i = 0; i < nextProp.length; i++) { - // Add all the properties of the array. - updatePayload = addNestedProperty( - updatePayload, - nextProp[i], - validAttributes - ); - } + 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 updatePayload; -} -/** - * clearNestedProperty takes a single set of props and valid attributes. It - * adds a null sentinel to the updatePayload, for each prop key. - */ + return; + } // Dedup strategy: Warn once per component. -function clearNestedProperty(updatePayload, prevProp, validAttributes) { - if (!prevProp) { - return updatePayload; - } + if (didWarnAboutLegacyContext.has(fiber.type)) { + return; + } - if (!isArray(prevProp)) { - // Add each property of the leaf. - return clearProperties(updatePayload, prevProp, validAttributes); - } + var warningsForRoot = pendingLegacyContextWarning.get(strictRoot); - for (var i = 0; i < prevProp.length; i++) { - // Add all the properties of the array. - updatePayload = clearNestedProperty( - updatePayload, - prevProp[i], - validAttributes - ); - } + if ( + fiber.type.contextTypes != null || + fiber.type.childContextTypes != null || + (instance !== null && typeof instance.getChildContext === "function") + ) { + if (warningsForRoot === undefined) { + warningsForRoot = []; + pendingLegacyContextWarning.set(strictRoot, warningsForRoot); + } - return updatePayload; -} -/** - * diffProperties takes two sets of props and a set of valid attributes - * and write to updatePayload the values that changed or were deleted. - * If no updatePayload is provided, a new one is created and returned if - * anything changed. - */ + warningsForRoot.push(fiber); + } + }; -function diffProperties(updatePayload, prevProps, nextProps, validAttributes) { - var attributeConfig; - var nextProp; - var prevProp; + ReactStrictModeWarnings.flushLegacyContextWarning = function () { + pendingLegacyContextWarning.forEach(function (fiberArray, strictRoot) { + if (fiberArray.length === 0) { + return; + } - for (var propKey in nextProps) { - attributeConfig = validAttributes[propKey]; + 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); - if (!attributeConfig) { - continue; // not a valid native prop - } + try { + setCurrentFiber(firstFiber); - prevProp = prevProps[propKey]; - nextProp = nextProps[propKey]; // functions are converted to booleans as markers that the associated - // events should be sent from native. + 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://react.dev/link/legacy-context", + sortedNames + ); + } finally { + resetCurrentFiber(); + } + }); + }; - if (typeof nextProp === "function") { - nextProp = true; // If nextProp is not a function, then don't bother changing prevProp - // since nextProp will win and go into the updatePayload regardless. + ReactStrictModeWarnings.discardPendingWarnings = function () { + pendingComponentWillMountWarnings = []; + pendingUNSAFE_ComponentWillMountWarnings = []; + pendingComponentWillReceivePropsWarnings = []; + pendingUNSAFE_ComponentWillReceivePropsWarnings = []; + pendingComponentWillUpdateWarnings = []; + pendingUNSAFE_ComponentWillUpdateWarnings = []; + pendingLegacyContextWarning = new Map(); + }; + } - if (typeof prevProp === "function") { - prevProp = true; + /* + * The `'' + value` pattern (used in 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 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"; + return type; } - } // An explicit value of undefined is treated as a null because it overrides - // any other preceding value. + } // $FlowFixMe only called in DEV, so void return is not possible. - if (typeof nextProp === "undefined") { - nextProp = null; - - if (typeof prevProp === "undefined") { - prevProp = null; + function willCoercionThrow(value) { + { + try { + testStringCoercion(value); + return false; + } catch (e) { + return true; + } } } - if (removedKeys) { - removedKeys[propKey] = false; + 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 before using it here.", + typeName(value) + ); - if (updatePayload && updatePayload[propKey] !== undefined) { - // Something else already triggered an update to this key because another - // value diffed. Since we're now later in the nested arrays our value is - // more important so we need to calculate it and override the existing - // value. It doesn't matter if nothing changed, we'll set it anyway. - // Pattern match on: attributeConfig - if (typeof attributeConfig !== "object") { - // case: !Object is the default case - updatePayload[propKey] = nextProp; - } else if ( - typeof attributeConfig.diff === "function" || - typeof attributeConfig.process === "function" - ) { - // case: CustomAttributeConfiguration - var nextValue = - typeof attributeConfig.process === "function" - ? attributeConfig.process(nextProp) - : nextProp; - updatePayload[propKey] = nextValue; + 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 before using it here.", + propName, + typeName(value) + ); - continue; + return testStringCoercion(value); // throw (to help callers find troubleshooting comments) + } + } } - if (prevProp === nextProp) { - continue; // nothing changed - } // Pattern match on: attributeConfig + function resolveDefaultProps(Component, baseProps) { + if (Component && Component.defaultProps) { + // Resolve default props. Taken from ReactElement + var props = assign({}, baseProps); + var defaultProps = Component.defaultProps; + + for (var propName in defaultProps) { + if (props[propName] === undefined) { + props[propName] = defaultProps[propName]; + } + } - if (typeof attributeConfig !== "object") { - // case: !Object is the default case - if (defaultDiffer(prevProp, nextProp)) { - // a normal leaf has changed - (updatePayload || (updatePayload = {}))[propKey] = nextProp; + return props; } - } else if ( - typeof attributeConfig.diff === "function" || - typeof attributeConfig.process === "function" - ) { - // case: CustomAttributeConfiguration - var shouldUpdate = - prevProp === undefined || - (typeof attributeConfig.diff === "function" - ? attributeConfig.diff(prevProp, nextProp) - : defaultDiffer(prevProp, nextProp)); - if (shouldUpdate) { - var _nextValue = - typeof attributeConfig.process === "function" - ? attributeConfig.process(nextProp) - : nextProp; + return baseProps; + } - (updatePayload || (updatePayload = {}))[propKey] = _nextValue; - } - } else { - // default: fallthrough case when nested properties are defined - removedKeys = null; - removedKeyCount = 0; // We think that attributeConfig is not CustomAttributeConfiguration at - // this point so we assume it must be AttributeConfiguration. + var valueCursor = createCursor(null); + var rendererSigil; - updatePayload = diffNestedProperty( - updatePayload, - prevProp, - nextProp, - attributeConfig - ); + { + // Use this to detect multiple renderers using the same context + rendererSigil = {}; + } - if (removedKeyCount > 0 && updatePayload) { - restoreDeletedValuesInNestedArray( - updatePayload, - nextProp, - attributeConfig - ); - removedKeys = 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; } } - } // Also iterate through all the previous props to catch any that have been - // removed and make sure native gets the signal so it can reset them to the - // default. - - for (var _propKey in prevProps) { - if (nextProps[_propKey] !== undefined) { - continue; // we've already covered this key in the previous pass + function enterDisallowedContextReadInDEV() { + { + isDisallowedContextReadInDEV = true; + } + } + function exitDisallowedContextReadInDEV() { + { + isDisallowedContextReadInDEV = false; + } } + function pushProvider(providerFiber, context, nextValue) { + { + push(valueCursor, context._currentValue2, providerFiber); + context._currentValue2 = nextValue; - attributeConfig = validAttributes[_propKey]; + { + 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 (!attributeConfig) { - continue; // not a valid native prop + context._currentRenderer2 = rendererSigil; + } + } } + function popProvider(context, providerFiber) { + var currentValue = valueCursor.current; + pop(valueCursor, providerFiber); - if (updatePayload && updatePayload[_propKey] !== undefined) { - // This was already updated to a diff result earlier. - continue; + { + { + context._currentValue2 = currentValue; + } + } } + function scheduleContextWorkOnParentPath(parent, renderLanes, propagationRoot) { + // Update the child lanes of all the ancestors, including the alternates. + var node = parent; - prevProp = prevProps[_propKey]; + while (node !== null) { + var alternate = node.alternate; - if (prevProp === undefined) { - continue; // was already empty anyway - } // Pattern match on: attributeConfig + if (!isSubsetOfLanes(node.childLanes, renderLanes)) { + node.childLanes = mergeLanes(node.childLanes, renderLanes); - if ( - typeof attributeConfig !== "object" || - typeof attributeConfig.diff === "function" || - typeof attributeConfig.process === "function" - ) { - // case: CustomAttributeConfiguration | !Object - // Flag the leaf property for removal by sending a sentinel. - (updatePayload || (updatePayload = {}))[_propKey] = null; + if (alternate !== null) { + alternate.childLanes = mergeLanes(alternate.childLanes, renderLanes); + } + } else if ( + alternate !== null && + !isSubsetOfLanes(alternate.childLanes, renderLanes) + ) { + alternate.childLanes = mergeLanes(alternate.childLanes, renderLanes); + } - if (!removedKeys) { - removedKeys = {}; + if (node === propagationRoot) { + break; + } + + node = node.return; } - if (!removedKeys[_propKey]) { - removedKeys[_propKey] = true; - removedKeyCount++; + { + 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) { + { + propagateContextChange_eager(workInProgress, context, renderLanes); } - } else { - // default: - // This is a nested attribute configuration where all the properties - // were removed so we need to go through and clear out all of them. - updatePayload = clearNestedProperty( - updatePayload, - prevProp, - attributeConfig - ); } - } - return updatePayload; -} -/** - * addProperties adds all the valid props to the payload after being processed. - */ + function propagateContextChange_eager(workInProgress, context, renderLanes) { + var fiber = workInProgress.child; -function addProperties(updatePayload, props, validAttributes) { - // TODO: Fast path - return diffProperties(updatePayload, emptyObject, props, validAttributes); -} -/** - * clearProperties clears all the previous props by adding a null sentinel - * to the payload for each valid key. - */ + if (fiber !== null) { + // Set the return pointer of the child to the work-in-progress fiber. + fiber.return = workInProgress; + } -function clearProperties(updatePayload, prevProps, validAttributes) { - // TODO: Fast path - return diffProperties(updatePayload, prevProps, emptyObject, validAttributes); -} + while (fiber !== null) { + var nextFiber = void 0; // Visit this fiber. -function create(props, validAttributes) { - return addProperties( - null, // updatePayload - props, - validAttributes - ); -} -function diff(prevProps, nextProps, validAttributes) { - return diffProperties( - null, // updatePayload - prevProps, - nextProps, - validAttributes - ); -} + var list = fiber.dependencies; -// Used as a way to call batchedUpdates when we don't have a reference to -// the renderer. Such as when we're dispatching events or if third party -// libraries need to call batchedUpdates. Eventually, this API will go away when -// everything is batched by default. We'll then have a similar API to opt-out of -// scheduled work and instead do synchronous work. -// Defaults -var batchedUpdatesImpl = function(fn, bookkeeping) { - return fn(bookkeeping); -}; - -var isInsideEventHandler = false; -function batchedUpdates(fn, bookkeeping) { - if (isInsideEventHandler) { - // If we are currently inside another batch, we need to wait until it - // fully completes before restoring state. - return fn(bookkeeping); - } - - isInsideEventHandler = true; - - try { - return batchedUpdatesImpl(fn, bookkeeping); - } finally { - isInsideEventHandler = false; - } -} -function setBatchingImplementation(_batchedUpdatesImpl, _discreteUpdatesImpl) { - batchedUpdatesImpl = _batchedUpdatesImpl; -} + if (list !== null) { + nextFiber = fiber.child; + var dependency = list.firstContext; -/** - * Internal queue of events that have accumulated their dispatches and are - * waiting to have their dispatches executed. - */ + 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(NoTimestamp, 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 -var eventQueue = null; -/** - * Dispatches an event and releases it back into the pool, unless persistent. - * - * @param {?object} event Synthetic event to be dispatched. - * @private - */ + var updateQueue = fiber.updateQueue; -var executeDispatchesAndRelease = function(event) { - if (event) { - executeDispatchesInOrder(event); + if (updateQueue === null); + else { + var sharedQueue = updateQueue.shared; + var pending = sharedQueue.pending; - if (!event.isPersistent()) { - event.constructor.release(event); - } - } -}; + if (pending === null) { + // This is the first update. Create a circular list. + update.next = update; + } else { + update.next = pending.next; + pending.next = update; + } + + sharedQueue.pending = update; + } + } -var executeDispatchesAndReleaseTopLevel = function(e) { - return executeDispatchesAndRelease(e); -}; + fiber.lanes = mergeLanes(fiber.lanes, renderLanes); + var alternate = fiber.alternate; -function runEventsInBatch(events) { - if (events !== null) { - eventQueue = accumulateInto(eventQueue, events); - } // Set `eventQueue` to null before processing it so that we can tell if more - // events get enqueued while processing. + if (alternate !== null) { + alternate.lanes = mergeLanes(alternate.lanes, renderLanes); + } - var processingEventQueue = eventQueue; - eventQueue = null; + scheduleContextWorkOnParentPath( + fiber.return, + renderLanes, + workInProgress + ); // Mark the updated lanes on the list, too. - if (!processingEventQueue) { - return; - } + list.lanes = mergeLanes(list.lanes, renderLanes); // Since we already found a match, we can stop traversing the + // dependency list. - forEachAccumulated(processingEventQueue, executeDispatchesAndReleaseTopLevel); + break; + } - if (eventQueue) { - throw new Error( - "processEventQueue(): Additional events were enqueued while processing " + - "an event queue. Support for this has not yet been implemented." - ); - } // This would be a good time to rethrow if any of the event handlers threw. + 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." + ); + } - rethrowCaughtError(); -} + parentSuspense.lanes = mergeLanes(parentSuspense.lanes, renderLanes); + var _alternate = parentSuspense.alternate; -/** - * Allows registered plugins an opportunity to extract events from top-level - * native browser events. - * - * @return {*} An accumulation of synthetic events. - * @internal - */ + 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. -function extractPluginEvents( - topLevelType, - targetInst, - nativeEvent, - nativeEventTarget -) { - var events = null; - var legacyPlugins = plugins; - - for (var i = 0; i < legacyPlugins.length; i++) { - // Not every plugin in the ordering may be loaded at runtime. - var possiblePlugin = legacyPlugins[i]; - - if (possiblePlugin) { - var extractedEvents = possiblePlugin.extractEvents( - topLevelType, - targetInst, - nativeEvent, - nativeEventTarget - ); + scheduleContextWorkOnParentPath( + parentSuspense, + renderLanes, + workInProgress + ); + nextFiber = fiber.sibling; + } 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; + } + } - if (extractedEvents) { - events = accumulateInto(events, extractedEvents); + fiber = nextFiber; } } - } + function prepareToReadContext(workInProgress, renderLanes) { + currentlyRenderingFiber = workInProgress; + lastContextDependency = null; + lastFullyObservedContext = null; + var dependencies = workInProgress.dependencies; - return events; -} + if (dependencies !== null) { + { + var firstContext = dependencies.firstContext; -function runExtractedPluginEventsInBatch( - topLevelType, - targetInst, - nativeEvent, - nativeEventTarget -) { - var events = extractPluginEvents( - topLevelType, - targetInst, - nativeEvent, - nativeEventTarget - ); - runEventsInBatch(events); -} + 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 + + 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 value = context._currentValue2; + + if (lastFullyObservedContext === context); + else { + var contextItem = { + context: context, + memoizedValue: value, + next: null + }; + + if (lastContextDependency === null) { + if (currentlyRenderingFiber === 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. + + lastContextDependency = contextItem; + currentlyRenderingFiber.dependencies = { + lanes: NoLanes, + firstContext: contextItem + }; + } else { + // Append a new context item. + lastContextDependency = lastContextDependency.next = contextItem; + } + } + + return value; + } + + // render. When this render exits, either because it finishes or because it is + // interrupted, the interleaved updates will be transferred onto the main part + // of the queue. -function dispatchEvent(target, topLevelType, nativeEvent) { - var targetFiber = target; - var eventTarget = null; + var concurrentQueues = null; + function pushConcurrentUpdateQueue(queue) { + if (concurrentQueues === null) { + concurrentQueues = [queue]; + } else { + concurrentQueues.push(queue); + } + } + function finishQueueingConcurrentUpdates() { + // Transfer the interleaved updates onto the main queue. Each queue has a + // `pending` field and an `interleaved` field. When they are not null, they + // point to the last node in a circular linked list. We need to append the + // interleaved list to the end of the pending list by joining them into a + // single, circular list. + if (concurrentQueues !== null) { + for (var i = 0; i < concurrentQueues.length; i++) { + var queue = concurrentQueues[i]; + var lastInterleavedUpdate = queue.interleaved; + + if (lastInterleavedUpdate !== null) { + queue.interleaved = null; + var firstInterleavedUpdate = lastInterleavedUpdate.next; + var lastPendingUpdate = queue.pending; + + if (lastPendingUpdate !== null) { + var firstPendingUpdate = lastPendingUpdate.next; + lastPendingUpdate.next = firstInterleavedUpdate; + lastInterleavedUpdate.next = firstPendingUpdate; + } - if (targetFiber != null) { - var stateNode = targetFiber.stateNode; // Guard against Fiber being unmounted + queue.pending = lastInterleavedUpdate; + } + } - if (stateNode != null) { - eventTarget = stateNode.canonical; + concurrentQueues = null; + } } - } + function enqueueConcurrentHookUpdate(fiber, queue, update, lane) { + var interleaved = queue.interleaved; - batchedUpdates(function() { - // Emit event to the RawEventEmitter. This is an unused-by-default EventEmitter - // that can be used to instrument event performance monitoring (primarily - could be useful - // for other things too). - // - // NOTE: this merely emits events into the EventEmitter below. - // If *you* do not add listeners to the `RawEventEmitter`, - // then all of these emitted events will just blackhole and are no-ops. - // It is available (although not officially supported... yet) if you want to collect - // perf data on event latency in your application, and could also be useful for debugging - // low-level events issues. - // - // If you do not have any event perf monitoring and are extremely concerned about event perf, - // it is safe to disable these "emit" statements; it will prevent checking the size of - // an empty array twice and prevent two no-ops. Practically the overhead is so low that - // we don't think it's worth thinking about in prod; your perf issues probably lie elsewhere. - // - // We emit two events here: one for listeners to this specific event, - // and one for the catchall listener '*', for any listeners that want - // to be notified for all events. - // Note that extracted events are *not* emitted, - // only events that have a 1:1 mapping with a native event, at least for now. - var event = { - eventName: topLevelType, - nativeEvent: nativeEvent - }; - ReactNativePrivateInterface.RawEventEmitter.emit(topLevelType, event); - ReactNativePrivateInterface.RawEventEmitter.emit("*", event); // Heritage plugin event system + if (interleaved === null) { + // This is the first update. Create a circular list. + update.next = update; // At the end of the current render, this queue's interleaved updates will + // be transferred to the pending queue. - runExtractedPluginEventsInBatch( - topLevelType, - targetFiber, - nativeEvent, - eventTarget - ); - }); // React Native doesn't use ReactControlledComponent but if it did, here's - // where it would do it. -} + pushConcurrentUpdateQueue(queue); + } else { + update.next = interleaved.next; + interleaved.next = update; + } -// This module only exists as an ESM wrapper around the external CommonJS -var scheduleCallback = Scheduler.unstable_scheduleCallback; -var cancelCallback = Scheduler.unstable_cancelCallback; -var shouldYield = Scheduler.unstable_shouldYield; -var requestPaint = Scheduler.unstable_requestPaint; -var now = Scheduler.unstable_now; -var ImmediatePriority = Scheduler.unstable_ImmediatePriority; -var UserBlockingPriority = Scheduler.unstable_UserBlockingPriority; -var NormalPriority = Scheduler.unstable_NormalPriority; -var IdlePriority = Scheduler.unstable_IdlePriority; - -var rendererID = null; -var injectedHook = 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://react.dev/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 - }); + queue.interleaved = update; + return markUpdateLaneFromFiberToRoot(fiber, lane); } + function enqueueConcurrentHookUpdateAndEagerlyBailout( + fiber, + queue, + update, + lane + ) { + var interleaved = queue.interleaved; - rendererID = hook.inject(internals); // We have successfully injected, so now it is safe to set up hooks. + if (interleaved === null) { + // This is the first update. Create a circular list. + update.next = update; // At the end of the current render, this queue's interleaved updates will + // be transferred to the pending queue. - injectedHook = hook; - } catch (err) { - // Catch all errors because it is unsafe to throw during initialization. - { - error("React instrumentation encountered an error: %s.", err); + pushConcurrentUpdateQueue(queue); + } else { + update.next = interleaved.next; + interleaved.next = update; + } + + queue.interleaved = update; } - } + function enqueueConcurrentClassUpdate(fiber, queue, update, lane) { + var interleaved = queue.interleaved; - 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; + if (interleaved === null) { + // This is the first update. Create a circular list. + update.next = update; // At the end of the current render, this queue's interleaved updates will + // be transferred to the pending queue. - error("React instrumentation encountered an error: %s", err); - } + pushConcurrentUpdateQueue(queue); + } else { + update.next = interleaved.next; + interleaved.next = update; } + + queue.interleaved = update; + return markUpdateLaneFromFiberToRoot(fiber, lane); } - } -} -function onCommitRoot(root, eventPriority) { - if (injectedHook && typeof injectedHook.onCommitFiberRoot === "function") { - try { - var didError = (root.current.flags & DidCapture) === DidCapture; + function enqueueConcurrentRenderForLane(fiber, lane) { + return markUpdateLaneFromFiberToRoot(fiber, lane); + } // Calling this function outside this module should only be done for backwards + // compatibility and should always be accompanied by a warning. - if (enableProfilerTimer) { - var schedulerPriority; + var unsafe_markUpdateLaneFromFiberToRoot = markUpdateLaneFromFiberToRoot; - switch (eventPriority) { - case DiscreteEventPriority: - schedulerPriority = ImmediatePriority; - break; + function markUpdateLaneFromFiberToRoot(sourceFiber, lane) { + // Update the source fiber's lanes + sourceFiber.lanes = mergeLanes(sourceFiber.lanes, lane); + var alternate = sourceFiber.alternate; - case ContinuousEventPriority: - schedulerPriority = UserBlockingPriority; - break; + if (alternate !== null) { + alternate.lanes = mergeLanes(alternate.lanes, lane); + } - case DefaultEventPriority: - schedulerPriority = NormalPriority; - break; + { + if ( + alternate === null && + (sourceFiber.flags & (Placement | Hydrating)) !== NoFlags + ) { + warnAboutUpdateOnNotYetMountedFiberInDEV(sourceFiber); + } + } // Walk the parent path to the root and update the child lanes. - case IdleEventPriority: - schedulerPriority = IdlePriority; - break; + var node = sourceFiber; + var parent = sourceFiber.return; - default: - schedulerPriority = NormalPriority; - break; + while (parent !== null) { + parent.childLanes = mergeLanes(parent.childLanes, lane); + alternate = parent.alternate; + + if (alternate !== null) { + alternate.childLanes = mergeLanes(alternate.childLanes, lane); + } else { + { + if ((parent.flags & (Placement | Hydrating)) !== NoFlags) { + warnAboutUpdateOnNotYetMountedFiberInDEV(sourceFiber); + } + } } - injectedHook.onCommitFiberRoot( - rendererID, - root, - schedulerPriority, - didError - ); - } else { - injectedHook.onCommitFiberRoot(rendererID, root, undefined, didError); + node = parent; + parent = parent.return; } - } catch (err) { - { - if (!hasLoggedError) { - hasLoggedError = true; - error("React instrumentation encountered an error: %s", err); - } + if (node.tag === HostRoot) { + var root = node.stateNode; + return root; + } else { + return null; } } - } -} -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 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 hasForceUpdate = false; + var didWarnUpdateInsideUpdate; + var currentlyProcessingQueue; + + { + didWarnUpdateInsideUpdate = false; + currentlyProcessingQueue = null; + } + + function initializeUpdateQueue(fiber) { + var queue = { + baseState: fiber.memoizedState, + firstBaseUpdate: null, + lastBaseUpdate: null, + shared: { + pending: null, + interleaved: null, + lanes: NoLanes + }, + effects: null + }; + fiber.updateQueue = queue; } - } -} -function onCommitUnmount(fiber) { - if (injectedHook && typeof injectedHook.onCommitFiberUnmount === "function") { - try { - injectedHook.onCommitFiberUnmount(rendererID, fiber); - } catch (err) { - { - if (!hasLoggedError) { - hasLoggedError = true; + function cloneUpdateQueue(current, workInProgress) { + // Clone the update queue from current. Unless it's already a clone. + var queue = workInProgress.updateQueue; + var currentQueue = current.updateQueue; - error("React instrumentation encountered an error: %s", err); - } + if (queue === currentQueue) { + var clone = { + baseState: currentQueue.baseState, + firstBaseUpdate: currentQueue.firstBaseUpdate, + lastBaseUpdate: currentQueue.lastBaseUpdate, + shared: currentQueue.shared, + effects: currentQueue.effects + }; + workInProgress.updateQueue = clone; } } - } -} + function createUpdate(eventTime, lane) { + var update = { + eventTime: eventTime, + lane: lane, + tag: UpdateState, + payload: null, + callback: null, + next: null + }; + return update; + } + function enqueueUpdate(fiber, update, lane) { + var updateQueue = fiber.updateQueue; -function injectProfilingHooks(profilingHooks) {} + if (updateQueue === null) { + // Only occurs if the fiber has been unmounted. + return null; + } -function getLaneLabelMap() { - { - return null; - } -} -function markComponentRenderStopped() {} -function markComponentErrored(fiber, thrownValue, lanes) {} -function markComponentSuspended(fiber, wakeable, lanes) {} - -var NoMode = - /* */ - 0; // TODO: Remove ConcurrentMode by reading from the root tag instead - -var ConcurrentMode = - /* */ - 1; -var ProfileMode = - /* */ - 2; -var StrictLegacyMode = - /* */ - 8; - -// 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 = Math.log; -var LN2 = Math.LN2; - -function clz32Fallback(x) { - var asUint = x >>> 0; - - if (asUint === 0) { - return 32; - } - - return (31 - ((log(asUint) / LN2) | 0)) | 0; -} + var sharedQueue = updateQueue.shared; -// If those values are changed that package should be rebuilt and redeployed. - -var TotalLanes = 31; -var NoLanes = - /* */ - 0; -var NoLane = - /* */ - 0; -var SyncLane = - /* */ - 1; -var InputContinuousHydrationLane = - /* */ - 2; -var InputContinuousLane = - /* */ - 4; -var DefaultHydrationLane = - /* */ - 8; -var DefaultLane = - /* */ - 16; -var TransitionHydrationLane = - /* */ - 32; -var TransitionLanes = - /* */ - 4194240; -var TransitionLane1 = - /* */ - 64; -var TransitionLane2 = - /* */ - 128; -var TransitionLane3 = - /* */ - 256; -var TransitionLane4 = - /* */ - 512; -var TransitionLane5 = - /* */ - 1024; -var TransitionLane6 = - /* */ - 2048; -var TransitionLane7 = - /* */ - 4096; -var TransitionLane8 = - /* */ - 8192; -var TransitionLane9 = - /* */ - 16384; -var TransitionLane10 = - /* */ - 32768; -var TransitionLane11 = - /* */ - 65536; -var TransitionLane12 = - /* */ - 131072; -var TransitionLane13 = - /* */ - 262144; -var TransitionLane14 = - /* */ - 524288; -var TransitionLane15 = - /* */ - 1048576; -var TransitionLane16 = - /* */ - 2097152; -var RetryLanes = - /* */ - 130023424; -var RetryLane1 = - /* */ - 4194304; -var RetryLane2 = - /* */ - 8388608; -var RetryLane3 = - /* */ - 16777216; -var RetryLane4 = - /* */ - 33554432; -var RetryLane5 = - /* */ - 67108864; -var SomeRetryLane = RetryLane1; -var SelectiveHydrationLane = - /* */ - 134217728; -var NonIdleLanes = - /* */ - 268435455; -var IdleHydrationLane = - /* */ - 268435456; -var IdleLane = - /* */ - 536870912; -var OffscreenLane = - /* */ - 1073741824; // This function is used for the experimental timeline (react-devtools-timeline) -var NoTimestamp = -1; -var nextTransitionLane = TransitionLane1; -var nextRetryLane = RetryLane1; - -function getHighestPriorityLanes(lanes) { - switch (getHighestPriorityLane(lanes)) { - 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: - case TransitionLane16: - return lanes & TransitionLanes; - - case RetryLane1: - case RetryLane2: - case RetryLane3: - case RetryLane4: - case RetryLane5: - return lanes & RetryLanes; - - case SelectiveHydrationLane: - return SelectiveHydrationLane; - - case IdleHydrationLane: - return IdleHydrationLane; - - case IdleLane: - return IdleLane; - - case OffscreenLane: - return OffscreenLane; - - 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; - } -} - -function getNextLanes(root, wipLanes) { - // Early bailout if there's no pending work left. - var pendingLanes = root.pendingLanes; - - if (pendingLanes === NoLanes) { - return NoLanes; - } + if ( + currentlyProcessingQueue === sharedQueue && + !didWarnUpdateInsideUpdate + ) { + 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." + ); - 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. + didWarnUpdateInsideUpdate = true; + } + } - var nonIdlePendingLanes = pendingLanes & NonIdleLanes; + 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 (nonIdlePendingLanes !== NoLanes) { - var nonIdleUnblockedLanes = nonIdlePendingLanes & ~suspendedLanes; + if (pending === null) { + // This is the first update. Create a circular list. + update.next = update; + } else { + update.next = pending.next; + pending.next = update; + } - if (nonIdleUnblockedLanes !== NoLanes) { - nextLanes = getHighestPriorityLanes(nonIdleUnblockedLanes); - } else { - var nonIdlePingedLanes = nonIdlePendingLanes & pingedLanes; + 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 (nonIdlePingedLanes !== NoLanes) { - nextLanes = getHighestPriorityLanes(nonIdlePingedLanes); + return unsafe_markUpdateLaneFromFiberToRoot(fiber, lane); + } else { + return enqueueConcurrentClassUpdate(fiber, sharedQueue, update, lane); } } - } else { - // The only remaining work is Idle. - var unblockedLanes = pendingLanes & ~suspendedLanes; + function entangleTransitions(root, fiber, lane) { + var updateQueue = fiber.updateQueue; - if (unblockedLanes !== NoLanes) { - nextLanes = getHighestPriorityLanes(unblockedLanes); - } else { - if (pingedLanes !== NoLanes) { - nextLanes = getHighestPriorityLanes(pingedLanes); + if (updateQueue === null) { + // Only occurs if the fiber has been unmounted. + return; } - } - } - 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. + var sharedQueue = updateQueue.shared; - 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 (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. - 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 ((nextLanes & 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. - nextLanes |= pendingLanes & 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, like - // useMutableSource, we should ensure that there is no partial work at the - // time we apply the entanglement. - - var entangledLanes = root.entangledLanes; - - if (entangledLanes !== NoLanes) { - var entanglements = root.entanglements; - var lanes = nextLanes & entangledLanes; - - while (lanes > 0) { - var index = pickArbitraryLaneIndex(lanes); - var lane = 1 << index; - nextLanes |= entanglements[index]; - lanes &= ~lane; - } - } - - return nextLanes; -} -function getMostRecentEventTime(root, lanes) { - var eventTimes = root.eventTimes; - var mostRecentEventTime = NoTimestamp; + queueLanes = intersectLanes(queueLanes, root.pendingLanes); // Entangle the new transition lane with the other transition lanes. - while (lanes > 0) { - var index = pickArbitraryLaneIndex(lanes); - var lane = 1 << index; - var eventTime = eventTimes[index]; + 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. - if (eventTime > mostRecentEventTime) { - mostRecentEventTime = eventTime; + 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. - lanes &= ~lane; - } + var current = workInProgress.alternate; - return mostRecentEventTime; -} + 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 computeExpirationTime(lane, currentTime) { - switch (lane) { - 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: - case TransitionLane16: - return currentTime + 5000; - - case RetryLane1: - case RetryLane2: - case RetryLane3: - case RetryLane4: - case RetryLane5: - // 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: - // Anything idle priority or lower should never expire. - return NoTimestamp; - - default: - { - error("Should have found matching lanes. This is a bug in React."); - } + do { + var clone = { + eventTime: update.eventTime, + lane: update.lane, + tag: update.tag, + payload: update.payload, + callback: update.callback, + next: null + }; + + if (newLast === null) { + newFirst = newLast = clone; + } else { + newLast.next = clone; + newLast = clone; + } - return NoTimestamp; - } -} + update = update.next; + } while (update !== null); // Append the captured update the end of the cloned list. -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. - - var lanes = pendingLanes; - - 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); - } - } else if (expirationTime <= currentTime) { - // This lane expired - root.expiredLanes |= lane; - } + if (newLast === null) { + newFirst = newLast = capturedUpdate; + } else { + newLast.next = capturedUpdate; + newLast = capturedUpdate; + } + } else { + // There are no base updates. + newFirst = newLast = capturedUpdate; + } - lanes &= ~lane; - } -} // This returns the highest priority pending lanes regardless of whether they -function getLanesToRetrySynchronouslyOnError(root) { - var everythingButOffscreen = root.pendingLanes & ~OffscreenLane; + queue = { + baseState: currentQueue.baseState, + firstBaseUpdate: newFirst, + lastBaseUpdate: newLast, + shared: currentQueue.shared, + effects: currentQueue.effects + }; + workInProgress.updateQueue = queue; + return; + } + } // Append the update to the end of the list. - if (everythingButOffscreen !== NoLanes) { - return everythingButOffscreen; - } + var lastBaseUpdate = queue.lastBaseUpdate; - if (everythingButOffscreen & OffscreenLane) { - return OffscreenLane; - } + if (lastBaseUpdate === null) { + queue.firstBaseUpdate = capturedUpdate; + } else { + lastBaseUpdate.next = capturedUpdate; + } - return NoLanes; -} -function includesSyncLane(lanes) { - return (lanes & SyncLane) !== NoLanes; -} -function includesNonIdleWork(lanes) { - return (lanes & NonIdleLanes) !== NoLanes; -} -function includesOnlyRetries(lanes) { - return (lanes & RetryLanes) === lanes; -} -function includesOnlyNonUrgentLanes(lanes) { - var UrgentLanes = SyncLane | InputContinuousLane | DefaultLane; - return (lanes & UrgentLanes) === NoLanes; -} -function includesOnlyTransitions(lanes) { - return (lanes & TransitionLanes) === lanes; -} -function includesBlockingLane(root, lanes) { - 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; + queue.lastBaseUpdate = capturedUpdate; + } - if ((nextRetryLane & RetryLanes) === NoLanes) { - nextRetryLane = RetryLane1; - } + function getStateFromUpdate( + workInProgress, + queue, + update, + prevState, + nextProps, + instance + ) { + switch (update.tag) { + case ReplaceState: { + var payload = update.payload; - 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 (typeof payload === "function") { + // Updater function + { + enterDisallowedContextReadInDEV(); + } -function pickArbitraryLaneIndex(lanes) { - return 31 - clz32(lanes); -} + var nextState = payload.call(instance, prevState, nextProps); -function laneToIndex(lane) { - return pickArbitraryLaneIndex(lane); -} + { + exitDisallowedContextReadInDEV(); + } -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). + return nextState; + } // State object -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 payload; + } - for (var i = 0; i < TotalLanes; i++) { - laneMap.push(initial); - } + case CaptureUpdate: { + workInProgress.flags = + (workInProgress.flags & ~ShouldCapture) | DidCapture; + } + // Intentional fallthrough - return laneMap; -} -function markRootUpdated(root, updateLane, eventTime) { - 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; - } - - var eventTimes = root.eventTimes; - var index = laneToIndex(updateLane); // We can always overwrite an existing timestamp because we prefer the most - // recent event, and we assume time is monotonically increasing. - - eventTimes[index] = eventTime; -} -function markRootSuspended(root, suspendedLanes) { - 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; - } -} -function markRootPinged(root, pingedLanes, eventTime) { - root.pingedLanes |= root.suspendedLanes & pingedLanes; -} -function markRootFinished(root, remainingLanes) { - var noLongerPendingLanes = root.pendingLanes & ~remainingLanes; - root.pendingLanes = remainingLanes; // Let's try everything again - - root.suspendedLanes = NoLanes; - root.pingedLanes = NoLanes; - root.expiredLanes &= remainingLanes; - root.mutableReadLanes &= remainingLanes; - root.entangledLanes &= remainingLanes; - var entanglements = root.entanglements; - var eventTimes = root.eventTimes; - var expirationTimes = root.expirationTimes; // Clear the lanes that no longer have pending work - - var lanes = noLongerPendingLanes; - - while (lanes > 0) { - var index = pickArbitraryLaneIndex(lanes); - var lane = 1 << index; - entanglements[index] = NoLanes; - eventTimes[index] = NoTimestamp; - expirationTimes[index] = NoTimestamp; - lanes &= ~lane; - } -} -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 UpdateState: { + var _payload = update.payload; + var partialState; - 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; - } + if (typeof _payload === "function") { + // Updater function + { + enterDisallowedContextReadInDEV(); + } - lanes &= ~lane; - } -} -function getBumpedLaneForHydration(root, renderLanes) { - var renderLane = getHighestPriorityLane(renderLanes); - var lane; - - switch (renderLane) { - 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 TransitionLane16: - case RetryLane1: - case RetryLane2: - case RetryLane3: - case RetryLane4: - case RetryLane5: - 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; - } + partialState = _payload.call(instance, prevState, nextProps); - var pendingUpdatersLaneMap = root.pendingUpdatersLaneMap; - var memoizedUpdaters = root.memoizedUpdaters; + { + exitDisallowedContextReadInDEV(); + } + } else { + // Partial state object + partialState = _payload; + } - while (lanes > 0) { - var index = laneToIndex(lanes); - var lane = 1 << index; - var updaters = pendingUpdatersLaneMap[index]; + if (partialState === null || partialState === undefined) { + // Null and undefined are treated as no-ops. + return prevState; + } // Merge the partial state and the previous state. - if (updaters.size > 0) { - updaters.forEach(function(fiber) { - var alternate = fiber.alternate; + return assign({}, prevState, partialState); + } - if (alternate === null || !memoizedUpdaters.has(alternate)) { - memoizedUpdaters.add(fiber); + case ForceUpdate: { + hasForceUpdate = true; + return prevState; } - }); - updaters.clear(); + } + + return prevState; } - lanes &= ~lane; - } -} -function getTransitionsForLanes(root, lanes) { - { - return null; - } -} + function processUpdateQueue(workInProgress, props, instance, renderLanes) { + // This is always non-null on a ClassComponent or HostRoot + var queue = workInProgress.updateQueue; + hasForceUpdate = false; -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); + { + currentlyProcessingQueue = queue.shared; + } - if (!isHigherEventPriority(DiscreteEventPriority, lane)) { - return DiscreteEventPriority; - } + var firstBaseUpdate = queue.firstBaseUpdate; + var lastBaseUpdate = queue.lastBaseUpdate; // Check if there are pending updates. If so, transfer them to the base queue. - if (!isHigherEventPriority(ContinuousEventPriority, lane)) { - return ContinuousEventPriority; - } + var pendingQueue = queue.shared.pending; - if (includesNonIdleWork(lane)) { - return DefaultEventPriority; - } + 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. - return IdleEventPriority; -} + var lastPendingUpdate = pendingQueue; + var firstPendingUpdate = lastPendingUpdate.next; + lastPendingUpdate.next = null; // Append pending updates to base queue -// Renderers that don't support mutation -// can re-export everything from this module. -function shim() { - throw new Error( - "The current renderer does not support mutation. " + - "This error is likely caused by a bug in React. " + - "Please file an issue." - ); -} // Mutation (when unsupported) -var commitMount = shim; - -// Renderers that don't support hydration -// can re-export everything from this module. -function shim$1() { - 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$1; -var isSuspenseInstanceFallback = shim$1; -var getSuspenseInstanceFallbackErrorDetails = shim$1; -var registerSuspenseInstanceRetry = shim$1; -var hydrateTextInstance = shim$1; -var errorHydratingContainer = shim$1; - -var _nativeFabricUIManage = nativeFabricUIManager, - createNode = _nativeFabricUIManage.createNode, - cloneNode = _nativeFabricUIManage.cloneNode, - cloneNodeWithNewChildren = _nativeFabricUIManage.cloneNodeWithNewChildren, - cloneNodeWithNewChildrenAndProps = - _nativeFabricUIManage.cloneNodeWithNewChildrenAndProps, - cloneNodeWithNewProps = _nativeFabricUIManage.cloneNodeWithNewProps, - createChildNodeSet = _nativeFabricUIManage.createChildSet, - appendChildNode = _nativeFabricUIManage.appendChild, - appendChildNodeToSet = _nativeFabricUIManage.appendChildToSet, - completeRoot = _nativeFabricUIManage.completeRoot, - registerEventHandler = _nativeFabricUIManage.registerEventHandler, - fabricMeasure = _nativeFabricUIManage.measure, - fabricMeasureInWindow = _nativeFabricUIManage.measureInWindow, - fabricMeasureLayout = _nativeFabricUIManage.measureLayout, - FabricDefaultPriority = _nativeFabricUIManage.unstable_DefaultEventPriority, - FabricDiscretePriority = _nativeFabricUIManage.unstable_DiscreteEventPriority, - fabricGetCurrentEventPriority = - _nativeFabricUIManage.unstable_getCurrentEventPriority, - _setNativeProps = _nativeFabricUIManage.setNativeProps; -var getViewConfigForType = - ReactNativePrivateInterface.ReactNativeViewConfigRegistry.get; // Counter for uniquely identifying views. -// % 10 === 1 means it is a rootTag. -// % 2 === 0 means it is a Fabric tag. -// This means that they never overlap. - -var nextReactTag = 2; - -// TODO: Remove this conditional once all changes have propagated. -if (registerEventHandler) { - /** - * Register the event emitter with the native bridge - */ - registerEventHandler(dispatchEvent); -} -/** - * This is used for refs on host components. - */ + if (lastBaseUpdate === null) { + firstBaseUpdate = firstPendingUpdate; + } else { + lastBaseUpdate.next = firstPendingUpdate; + } -var ReactFabricHostComponent = /*#__PURE__*/ (function() { - function ReactFabricHostComponent( - tag, - viewConfig, - props, - internalInstanceHandle - ) { - this._nativeTag = tag; - this.viewConfig = viewConfig; - this.currentProps = props; - this._internalInstanceHandle = internalInstanceHandle; - } - - var _proto = ReactFabricHostComponent.prototype; - - _proto.blur = function blur() { - ReactNativePrivateInterface.TextInputState.blurTextInput(this); - }; - - _proto.focus = function focus() { - ReactNativePrivateInterface.TextInputState.focusTextInput(this); - }; - - _proto.measure = function measure(callback) { - var stateNode = this._internalInstanceHandle.stateNode; - - if (stateNode != null) { - fabricMeasure( - stateNode.node, - mountSafeCallback_NOT_REALLY_SAFE(this, callback) - ); - } - }; + 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 - _proto.measureInWindow = function measureInWindow(callback) { - var stateNode = this._internalInstanceHandle.stateNode; + var current = workInProgress.alternate; - if (stateNode != null) { - fabricMeasureInWindow( - stateNode.node, - mountSafeCallback_NOT_REALLY_SAFE(this, callback) - ); - } - }; + if (current !== null) { + // This is always non-null on a ClassComponent or HostRoot + var currentQueue = current.updateQueue; + var currentLastBaseUpdate = currentQueue.lastBaseUpdate; - _proto.measureLayout = function measureLayout( - relativeToNativeNode, - onSuccess, - onFail - ) /* currently unused */ - { - if ( - typeof relativeToNativeNode === "number" || - !(relativeToNativeNode instanceof ReactFabricHostComponent) - ) { - { - error( - "Warning: ref.measureLayout must be called with a ref to a native component." - ); - } + if (currentLastBaseUpdate !== lastBaseUpdate) { + if (currentLastBaseUpdate === null) { + currentQueue.firstBaseUpdate = firstPendingUpdate; + } else { + currentLastBaseUpdate.next = firstPendingUpdate; + } - return; - } + currentQueue.lastBaseUpdate = lastPendingUpdate; + } + } + } // These values may change as we process the queue. - var toStateNode = this._internalInstanceHandle.stateNode; - var fromStateNode = relativeToNativeNode._internalInstanceHandle.stateNode; + 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; - if (toStateNode != null && fromStateNode != null) { - fabricMeasureLayout( - toStateNode.node, - fromStateNode.node, - mountSafeCallback_NOT_REALLY_SAFE(this, onFail), - mountSafeCallback_NOT_REALLY_SAFE(this, onSuccess) - ); - } - }; + do { + var updateLane = update.lane; + var updateEventTime = update.eventTime; + + if (!isSubsetOfLanes(renderLanes, updateLane)) { + // 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 = { + eventTime: updateEventTime, + 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. - _proto.setNativeProps = function setNativeProps(nativeProps) { - { - warnForStyleProps(nativeProps, this.viewConfig.validAttributes); - } - - var updatePayload = create(nativeProps, this.viewConfig.validAttributes); - var stateNode = this._internalInstanceHandle.stateNode; - - if (stateNode != null && updatePayload != null) { - _setNativeProps(stateNode.node, updatePayload); - } - }; // This API (addEventListener, removeEventListener) attempts to adhere to the - // w3 Level2 Events spec as much as possible, treating HostComponent as a DOM node. - // - // Unless otherwise noted, these methods should "just work" and adhere to the W3 specs. - // If they deviate in a way that is not explicitly noted here, you've found a bug! - // - // See: - // * https://www.w3.org/TR/DOM-Level-2-Events/events.html - // * https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener - // * https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener - // - // And notably, not implemented (yet?): - // * https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/dispatchEvent - // - // - // Deviations from spec/TODOs: - // (1) listener must currently be a function, we do not support EventListener objects yet. - // (2) we do not support the `signal` option / AbortSignal yet - - _proto.addEventListener_unstable = function addEventListener_unstable( - eventType, - listener, - options - ) { - if (typeof eventType !== "string") { - throw new Error("addEventListener_unstable eventType must be a string"); - } - - if (typeof listener !== "function") { - throw new Error("addEventListener_unstable listener must be a function"); - } // The third argument is either boolean indicating "captures" or an object. - - var optionsObj = - typeof options === "object" && options !== null ? options : {}; - var capture = - (typeof options === "boolean" ? options : optionsObj.capture) || false; - var once = optionsObj.once || false; - var passive = optionsObj.passive || false; - var signal = null; // TODO: implement signal/AbortSignal - - var eventListeners = this._eventListeners || {}; - - if (this._eventListeners == null) { - this._eventListeners = eventListeners; - } - - var namedEventListeners = eventListeners[eventType] || []; - - if (eventListeners[eventType] == null) { - eventListeners[eventType] = namedEventListeners; - } - - namedEventListeners.push({ - listener: listener, - invalidated: false, - options: { - capture: capture, - once: once, - passive: passive, - signal: signal - } - }); - }; // See https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener + newLanes = mergeLanes(newLanes, updateLane); + } else { + // This update does have sufficient priority. + if (newLastBaseUpdate !== null) { + var _clone = { + eventTime: updateEventTime, + // 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, + callback: update.callback, + next: null + }; + newLastBaseUpdate = newLastBaseUpdate.next = _clone; + } // Process this update. + + newState = getStateFromUpdate( + workInProgress, + queue, + update, + newState, + props, + instance + ); + var callback = update.callback; + + if ( + callback !== null && // If the update was already committed, we should not queue its + // callback again. + update.lane !== NoLane + ) { + workInProgress.flags |= Callback; + var effects = queue.effects; - _proto.removeEventListener_unstable = function removeEventListener_unstable( - eventType, - listener, - options - ) { - // eventType and listener must be referentially equal to be removed from the listeners - // data structure, but in "options" we only check the `capture` flag, according to spec. - // That means if you add the same function as a listener with capture set to true and false, - // you must also call removeEventListener twice with capture set to true/false. - var optionsObj = - typeof options === "object" && options !== null ? options : {}; - var capture = - (typeof options === "boolean" ? options : optionsObj.capture) || false; // If there are no event listeners or named event listeners, we can bail early - our - // job is already done. + if (effects === null) { + queue.effects = [update]; + } else { + effects.push(update); + } + } + } - var eventListeners = this._eventListeners; + update = update.next; - if (!eventListeners) { - return; - } + if (update === null) { + pendingQueue = queue.shared.pending; - var namedEventListeners = eventListeners[eventType]; + 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 (!namedEventListeners) { - return; - } // TODO: optimize this path to make remove cheaper + if (newLastBaseUpdate === null) { + newBaseState = newState; + } - eventListeners[eventType] = namedEventListeners.filter(function( - listenerObj - ) { - return !( - listenerObj.listener === listener && - listenerObj.options.capture === capture - ); - }); - }; + queue.baseState = newBaseState; + queue.firstBaseUpdate = newFirstBaseUpdate; + queue.lastBaseUpdate = newLastBaseUpdate; // Interleaved updates are stored on a separate queue. We aren't going to + // process them during this render, but we do need to track which lanes + // are remaining. + + var lastInterleaved = queue.shared.interleaved; + + if (lastInterleaved !== null) { + var interleaved = lastInterleaved; + + do { + newLanes = mergeLanes(newLanes, interleaved.lane); + interleaved = interleaved.next; + } while (interleaved !== lastInterleaved); + } else 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; + } - return ReactFabricHostComponent; -})(); // eslint-disable-next-line no-unused-expressions -function appendInitialChild(parentInstance, child) { - appendChildNode(parentInstance.node, child.node); -} -function createInstance( - type, - props, - rootContainerInstance, - hostContext, - internalInstanceHandle -) { - var tag = nextReactTag; - nextReactTag += 2; - var viewConfig = getViewConfigForType(type); - - { - for (var key in viewConfig.validAttributes) { - if (props.hasOwnProperty(key)) { - ReactNativePrivateInterface.deepFreezeAndThrowOnMutationInDev( - props[key] - ); + { + currentlyProcessingQueue = null; } - } - } - - var updatePayload = create(props, viewConfig.validAttributes); - var node = createNode( - tag, // reactTag - viewConfig.uiViewClassName, // viewName - rootContainerInstance, // rootTag - updatePayload, // props - internalInstanceHandle // internalInstanceHandle - ); - var component = new ReactFabricHostComponent( - tag, - viewConfig, - props, - internalInstanceHandle - ); - return { - node: node, - canonical: component - }; -} -function createTextInstance( - text, - rootContainerInstance, - hostContext, - internalInstanceHandle -) { - { - if (!hostContext.isInAParentText) { - error("Text strings must be rendered within a component."); - } - } - - var tag = nextReactTag; - nextReactTag += 2; - var node = createNode( - tag, // reactTag - "RCTRawText", // viewName - rootContainerInstance, // rootTag - { - text: text - }, // props - internalInstanceHandle // instance handle - ); - return { - node: node - }; -} -function getRootHostContext(rootContainerInstance) { - return { - isInAParentText: false - }; -} -function getChildHostContext(parentHostContext, type, rootContainerInstance) { - var prevIsInAParentText = parentHostContext.isInAParentText; - var isInAParentText = - type === "AndroidTextInput" || // Android - type === "RCTMultilineTextInputView" || // iOS - type === "RCTSinglelineTextInputView" || // iOS - type === "RCTText" || - type === "RCTVirtualText"; // TODO: If this is an offscreen host container, we should reuse the - // parent context. - - if (prevIsInAParentText !== isInAParentText) { - return { - isInAParentText: isInAParentText - }; - } else { - return parentHostContext; - } -} -function getPublicInstance(instance) { - return instance.canonical; -} -function prepareForCommit(containerInfo) { - // Noop - return null; -} -function prepareUpdate( - instance, - type, - oldProps, - newProps, - rootContainerInstance, - hostContext -) { - var viewConfig = instance.canonical.viewConfig; - var updatePayload = diff(oldProps, newProps, viewConfig.validAttributes); // TODO: If the event handlers have changed, we need to update the current props - // in the commit phase but there is no host config hook to do it yet. - // So instead we hack it by updating it in the render phase. - - instance.canonical.currentProps = newProps; - return updatePayload; -} -function resetAfterCommit(containerInfo) { - // Noop -} -function shouldSetTextContent(type, props) { - // TODO (bvaughn) Revisit this decision. - // Always returning false simplifies the createInstance() implementation, - // But creates an additional child Fiber for raw text children. - // No additional native views are created though. - // It's not clear to me which is better so I'm deferring for now. - // More context @ github.com/facebook/react/pull/8560#discussion_r92111303 - return false; -} -function getCurrentEventPriority() { - var currentEventPriority = fabricGetCurrentEventPriority - ? fabricGetCurrentEventPriority() - : null; - - if (currentEventPriority != null) { - switch (currentEventPriority) { - case FabricDiscretePriority: - return DiscreteEventPriority; + } - case FabricDefaultPriority: - default: - return DefaultEventPriority; + 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); } - } - - return DefaultEventPriority; -} // The Fabric renderer is secondary to the existing React Native renderer. - -var warnsIfNotActing = false; -var scheduleTimeout = setTimeout; -var cancelTimeout = clearTimeout; -var noTimeout = -1; // ------------------- -function cloneInstance( - instance, - updatePayload, - type, - oldProps, - newProps, - internalInstanceHandle, - keepChildren, - recyclableInstance -) { - var node = instance.node; - var clone; - - if (keepChildren) { - if (updatePayload !== null) { - clone = cloneNodeWithNewProps(node, updatePayload); - } else { - clone = cloneNode(node); - } - } else { - if (updatePayload !== null) { - clone = cloneNodeWithNewChildrenAndProps(node, updatePayload); - } else { - clone = cloneNodeWithNewChildren(node); - } - } - - return { - node: clone, - canonical: instance.canonical - }; -} -function cloneHiddenInstance(instance, type, props, internalInstanceHandle) { - var viewConfig = instance.canonical.viewConfig; - var node = instance.node; - var updatePayload = create( - { - style: { - display: "none" - } - }, - viewConfig.validAttributes - ); - return { - node: cloneNodeWithNewProps(node, updatePayload), - canonical: instance.canonical - }; -} -function cloneHiddenTextInstance(instance, text, internalInstanceHandle) { - throw new Error("Not yet implemented."); -} -function createContainerChildSet(container) { - return createChildNodeSet(container); -} -function appendChildToContainerChildSet(childSet, child) { - appendChildNodeToSet(childSet, child.node); -} -function finalizeContainerChildren(container, newChildren) { - completeRoot(container, newChildren); -} -function replaceContainerChildren(container, newChildren) {} -function preparePortalMount(portalInstance) { - // noop -} -var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher; -function describeBuiltInComponentFrame(name, source, ownerFn) { - { - var ownerName = null; + function resetHasForceUpdateBeforeProcessing() { + hasForceUpdate = false; + } + function checkHasForceUpdateAfterProcessing() { + return hasForceUpdate; + } + function commitUpdateQueue(finishedWork, finishedQueue, instance) { + // Commit the effects + var effects = finishedQueue.effects; + finishedQueue.effects = null; + + if (effects !== null) { + for (var i = 0; i < effects.length; i++) { + var effect = effects[i]; + var callback = effect.callback; - if (ownerFn) { - ownerName = ownerFn.displayName || ownerFn.name || null; + if (callback !== null) { + effect.callback = null; + callCallback(callback, instance); + } + } + } } - return describeComponentFrame(name, source, ownerName); - } -} -var componentFrameCache; + var fakeInternalInstance = {}; // React.Component uses a shared frozen object by default. + // We'll use it to determine whether we need to initialize legacy refs. -{ - var PossiblyWeakMap = typeof WeakMap === "function" ? WeakMap : Map; - componentFrameCache = new PossiblyWeakMap(); -} -var BEFORE_SLASH_RE = /^(.*)[\\\/]/; + var emptyRefsObject = new React.Component().refs; + var didWarnAboutStateAssignmentForComponent; + var didWarnAboutUninitializedState; + var didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate; + var didWarnAboutLegacyLifecyclesAndDerivedState; + var didWarnAboutUndefinedDerivedState; + var warnOnUndefinedDerivedState; + var warnOnInvalidCallback; + var didWarnAboutDirectlyAssigningPropsToState; + var didWarnAboutContextTypeAndContextTypes; + var didWarnAboutInvalidateContextType; + + { + didWarnAboutStateAssignmentForComponent = new Set(); + didWarnAboutUninitializedState = new Set(); + didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate = new Set(); + didWarnAboutLegacyLifecyclesAndDerivedState = new Set(); + didWarnAboutDirectlyAssigningPropsToState = new Set(); + didWarnAboutUndefinedDerivedState = new Set(); + didWarnAboutContextTypeAndContextTypes = new Set(); + didWarnAboutInvalidateContextType = new Set(); + var didWarnOnInvalidCallback = new Set(); + + warnOnInvalidCallback = function (callback, callerName) { + if (callback === null || typeof callback === "function") { + return; + } + + var key = callerName + "_" + callback; -function describeComponentFrame(name, source, ownerName) { - var sourceInfo = ""; + if (!didWarnOnInvalidCallback.has(key)) { + didWarnOnInvalidCallback.add(key); - if (source) { - var path = source.fileName; - var fileName = path.replace(BEFORE_SLASH_RE, ""); // In DEV, include code for a common special case: - // prefer "folder/index.js" instead of just "index.js". + error( + "%s(...): Expected the last optional `callback` argument to be a " + + "function. Instead received: %s.", + callerName, + callback + ); + } + }; - if (/^index\./.test(fileName)) { - var match = path.match(BEFORE_SLASH_RE); + warnOnUndefinedDerivedState = function (type, partialState) { + if (partialState === undefined) { + var componentName = getComponentNameFromType(type) || "Component"; - if (match) { - var pathBeforeSlash = match[1]; + if (!didWarnAboutUndefinedDerivedState.has(componentName)) { + didWarnAboutUndefinedDerivedState.add(componentName); - if (pathBeforeSlash) { - var folderName = pathBeforeSlash.replace(BEFORE_SLASH_RE, ""); - fileName = folderName + "/" + fileName; + error( + "%s.getDerivedStateFromProps(): A valid state object (or null) must be returned. " + + "You have returned undefined.", + componentName + ); + } } - } + }; // 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); } - sourceInfo = " (at " + fileName + ":" + source.lineNumber + ")"; - } else if (ownerName) { - sourceInfo = " (created by " + ownerName + ")"; - } + function applyDerivedStateFromProps( + workInProgress, + ctor, + getDerivedStateFromProps, + nextProps + ) { + var prevState = workInProgress.memoizedState; + var partialState = getDerivedStateFromProps(nextProps, prevState); - return "\n in " + (name || "Unknown") + sourceInfo; -} + { + warnOnUndefinedDerivedState(ctor, partialState); + } // Merge the partial state and the previous state. -function describeClassComponentFrame(ctor, source, ownerFn) { - { - return describeFunctionComponentFrame(ctor, source, ownerFn); - } -} -function describeFunctionComponentFrame(fn, source, ownerFn) { - { - if (!fn) { - return ""; + 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; + } } - var name = fn.displayName || fn.name || null; - var ownerName = null; + var classComponentUpdater = { + isMounted: isMounted, + enqueueSetState: function (inst, payload, callback) { + var fiber = get(inst); + var eventTime = requestEventTime(); + var lane = requestUpdateLane(fiber); + var update = createUpdate(eventTime, lane); + update.payload = payload; - if (ownerFn) { - ownerName = ownerFn.displayName || ownerFn.name || null; - } + if (callback !== undefined && callback !== null) { + { + warnOnInvalidCallback(callback, "setState"); + } - return describeComponentFrame(name, source, ownerName); - } -} + update.callback = callback; + } -function describeUnknownElementTypeFrameInDEV(type, source, ownerFn) { - if (type == null) { - return ""; - } + var root = enqueueUpdate(fiber, update, lane); - if (typeof type === "function") { - { - return describeFunctionComponentFrame(type, source, ownerFn); - } - } + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, lane, eventTime); + entangleTransitions(root, fiber, lane); + } + }, + enqueueReplaceState: function (inst, payload, callback) { + var fiber = get(inst); + var eventTime = requestEventTime(); + var lane = requestUpdateLane(fiber); + var update = createUpdate(eventTime, lane); + update.tag = ReplaceState; + update.payload = payload; - if (typeof type === "string") { - return describeBuiltInComponentFrame(type, source, ownerFn); - } + if (callback !== undefined && callback !== null) { + { + warnOnInvalidCallback(callback, "replaceState"); + } + + update.callback = callback; + } - switch (type) { - case REACT_SUSPENSE_TYPE: - return describeBuiltInComponentFrame("Suspense", source, ownerFn); + var root = enqueueUpdate(fiber, update, lane); - case REACT_SUSPENSE_LIST_TYPE: - return describeBuiltInComponentFrame("SuspenseList", source, ownerFn); - } + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, lane, eventTime); + entangleTransitions(root, fiber, lane); + } + }, + enqueueForceUpdate: function (inst, callback) { + var fiber = get(inst); + var eventTime = requestEventTime(); + var lane = requestUpdateLane(fiber); + var update = createUpdate(eventTime, lane); + update.tag = ForceUpdate; - if (typeof type === "object") { - switch (type.$$typeof) { - case REACT_FORWARD_REF_TYPE: - return describeFunctionComponentFrame(type.render, source, ownerFn); + if (callback !== undefined && callback !== null) { + { + warnOnInvalidCallback(callback, "forceUpdate"); + } - case REACT_MEMO_TYPE: - // Memo may contain any component type so we recursively resolve it. - return describeUnknownElementTypeFrameInDEV(type.type, source, ownerFn); + update.callback = callback; + } - case REACT_LAZY_TYPE: { - var lazyComponent = type; - var payload = lazyComponent._payload; - var init = lazyComponent._init; + var root = enqueueUpdate(fiber, update, lane); - try { - // Lazy may contain any component type so we recursively resolve it. - return describeUnknownElementTypeFrameInDEV( - init(payload), - source, - ownerFn - ); - } catch (x) {} + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, lane, eventTime); + entangleTransitions(root, fiber, lane); + } } - } - } + }; - return ""; -} + function checkShouldComponentUpdate( + workInProgress, + ctor, + oldProps, + newProps, + oldState, + newState, + nextContext + ) { + var instance = workInProgress.stateNode; + + if (typeof instance.shouldComponentUpdate === "function") { + var shouldUpdate = instance.shouldComponentUpdate( + newProps, + newState, + nextContext + ); + + { + if (shouldUpdate === undefined) { + error( + "%s.shouldComponentUpdate(): Returned undefined instead of a " + + "boolean value. Make sure to return true or false.", + getComponentNameFromType(ctor) || "Component" + ); + } + } -var hasOwnProperty = Object.prototype.hasOwnProperty; + return shouldUpdate; + } -var loggedTypeFailures = {}; -var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; + if (ctor.prototype && ctor.prototype.isPureReactComponent) { + return ( + !shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState) + ); + } -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 true; } - } -} -function checkPropTypes(typeSpecs, values, location, componentName, element) { - { - // $FlowFixMe This is okay but Flow doesn't know it. - var has = Function.call.bind(hasOwnProperty); + function checkClassInstance(workInProgress, ctor, newProps) { + var instance = workInProgress.stateNode; - 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 name = getComponentNameFromType(ctor) || "Component"; + var renderPresent = instance.render; - 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`." + 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 ); - err.name = "Invariant Violation"; - throw err; } + } - error$1 = typeSpecs[typeSpecName]( - values, - typeSpecName, - componentName, - location, - null, - "SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED" + 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 ); - } catch (ex) { - error$1 = ex; } - if (error$1 && !(error$1 instanceof Error)) { - setCurrentlyValidatingElement(element); + 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 (instance.propTypes) { 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 + "propTypes was defined as an instance property on %s. Use a static " + + "property to define propTypes instead.", + name ); + } - setCurrentlyValidatingElement(null); + if (instance.contextType) { + error( + "contextType was defined as an instance property on %s. Use a static " + + "property to define contextType instead.", + name + ); } - 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 (instance.contextTypes) { + error( + "contextTypes was defined as an instance property on %s. Use a static " + + "property to define contextTypes instead.", + name + ); + } - error("Failed %s type: %s", location, error$1.message); + if ( + ctor.contextType && + ctor.contextTypes && + !didWarnAboutContextTypeAndContextTypes.has(ctor) + ) { + didWarnAboutContextTypeAndContextTypes.add(ctor); - setCurrentlyValidatingElement(null); + error( + "%s declares both contextTypes and contextType static properties. " + + "The legacy contextTypes property will be ignored.", + name + ); + } } - } - } - } -} - -var valueStack = []; -var fiberStack; -{ - fiberStack = []; -} + 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 index = -1; + 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 createCursor(defaultValue) { - return { - current: defaultValue - }; -} + if (typeof instance.componentDidUnmount === "function") { + error( + "%s has a method called " + + "componentDidUnmount(). But there is no such lifecycle method. " + + "Did you mean componentWillUnmount()?", + name + ); + } -function pop(cursor, fiber) { - if (index < 0) { - { - error("Unexpected pop."); - } + 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 + ); + } - return; - } + if (typeof instance.componentWillRecieveProps === "function") { + error( + "%s has a method called " + + "componentWillRecieveProps(). Did you mean componentWillReceiveProps()?", + name + ); + } - { - if (fiber !== fiberStack[index]) { - error("Unexpected Fiber popped."); - } - } + if (typeof instance.UNSAFE_componentWillRecieveProps === "function") { + error( + "%s has a method called " + + "UNSAFE_componentWillRecieveProps(). Did you mean UNSAFE_componentWillReceiveProps()?", + name + ); + } - cursor.current = valueStack[index]; - valueStack[index] = null; + var hasMutatedProps = instance.props !== newProps; - { - fiberStack[index] = null; - } + 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 + ); + } - index--; -} + 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 + ); + } -function push(cursor, value, fiber) { - index++; - valueStack[index] = cursor.current; + if ( + typeof instance.getSnapshotBeforeUpdate === "function" && + typeof instance.componentDidUpdate !== "function" && + !didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate.has(ctor) + ) { + didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate.add(ctor); - { - fiberStack[index] = fiber; - } + error( + "%s: getSnapshotBeforeUpdate() should be used with componentDidUpdate(). " + + "This component defines getSnapshotBeforeUpdate() only.", + getComponentNameFromType(ctor) + ); + } - cursor.current = value; -} + 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 + ); + } -var warnedAboutMissingGetChildContext; + 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 + ); + } -{ - warnedAboutMissingGetChildContext = {}; -} + 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 emptyContextObject = {}; + var _state = instance.state; -{ - Object.freeze(emptyContextObject); -} // A cursor to the current merged context object on the stack. + if (_state && (typeof _state !== "object" || isArray(_state))) { + error("%s.state: must be set to an object or null", name); + } -var contextStackCursor = createCursor(emptyContextObject); // A cursor to a boolean indicating whether the context has changed. + if ( + typeof instance.getChildContext === "function" && + typeof ctor.childContextTypes !== "object" + ) { + error( + "%s.getChildContext(): childContextTypes must be defined in order to " + + "use getChildContext().", + name + ); + } + } + } -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. + function adoptClassInstance(workInProgress, instance) { + instance.updater = classComponentUpdater; + workInProgress.stateNode = instance; // The instance needs access to the fiber so that it can schedule updates -var previousContext = emptyContextObject; + set(instance, workInProgress); -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; + { + instance._reactInternalInstance = fakeInternalInstance; + } } - return contextStackCursor.current; - } -} + function constructClassInstance(workInProgress, ctor, props) { + var isLegacyContextConsumer = false; + var unmaskedContext = emptyContextObject; + var context = emptyContextObject; + var contextType = ctor.contextType; -function cacheContext(workInProgress, unmaskedContext, maskedContext) { - { - var instance = workInProgress.stateNode; - instance.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext; - instance.__reactInternalMemoizedMaskedChildContext = maskedContext; - } -} + { + 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(", ") + + "}."; + } -function getMaskedContext(workInProgress, unmaskedContext) { - { - var type = workInProgress.type; - var contextTypes = type.contextTypes; + error( + "%s defines an invalid contextType. " + + "contextType should point to the Context object returned by React.createContext().%s", + getComponentNameFromType(ctor) || "Component", + addendum + ); + } + } + } - 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. + 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; + } - var instance = workInProgress.stateNode; + var instance = new ctor(props, context); // Instantiate twice to help detect side-effects. - if ( - instance && - instance.__reactInternalMemoizedUnmaskedChildContext === unmaskedContext - ) { - return instance.__reactInternalMemoizedMaskedChildContext; - } + var state = (workInProgress.memoizedState = + instance.state !== null && instance.state !== undefined + ? instance.state + : null); + adoptClassInstance(workInProgress, instance); - var context = {}; + { + if (typeof ctor.getDerivedStateFromProps === "function" && state === null) { + var componentName = getComponentNameFromType(ctor) || "Component"; - for (var key in contextTypes) { - context[key] = unmaskedContext[key]; - } + if (!didWarnAboutUninitializedState.has(componentName)) { + didWarnAboutUninitializedState.add(componentName); - { - 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. + 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. - if (instance) { - cacheContext(workInProgress, unmaskedContext, context); - } + if ( + typeof ctor.getDerivedStateFromProps === "function" || + typeof instance.getSnapshotBeforeUpdate === "function" + ) { + var foundWillMountName = null; + var foundWillReceivePropsName = null; + var foundWillUpdateName = null; - return context; - } -} + if ( + typeof instance.componentWillMount === "function" && + instance.componentWillMount.__suppressDeprecationWarning !== true + ) { + foundWillMountName = "componentWillMount"; + } else if (typeof instance.UNSAFE_componentWillMount === "function") { + foundWillMountName = "UNSAFE_componentWillMount"; + } -function hasContextChanged() { - { - return didPerformWorkStackCursor.current; - } -} + if ( + typeof instance.componentWillReceiveProps === "function" && + instance.componentWillReceiveProps.__suppressDeprecationWarning !== true + ) { + foundWillReceivePropsName = "componentWillReceiveProps"; + } else if ( + typeof instance.UNSAFE_componentWillReceiveProps === "function" + ) { + foundWillReceivePropsName = "UNSAFE_componentWillReceiveProps"; + } -function isContextProvider(type) { - { - var childContextTypes = type.childContextTypes; - return childContextTypes !== null && childContextTypes !== undefined; - } -} + if ( + typeof instance.componentWillUpdate === "function" && + instance.componentWillUpdate.__suppressDeprecationWarning !== true + ) { + foundWillUpdateName = "componentWillUpdate"; + } else if (typeof instance.UNSAFE_componentWillUpdate === "function") { + foundWillUpdateName = "UNSAFE_componentWillUpdate"; + } -function popContext(fiber) { - { - pop(didPerformWorkStackCursor, fiber); - pop(contextStackCursor, fiber); - } -} + if ( + foundWillMountName !== null || + foundWillReceivePropsName !== null || + foundWillUpdateName !== null + ) { + var _componentName = getComponentNameFromType(ctor) || "Component"; -function popTopLevelContextObject(fiber) { - { - pop(didPerformWorkStackCursor, fiber); - pop(contextStackCursor, fiber); - } -} + var newApiName = + typeof ctor.getDerivedStateFromProps === "function" + ? "getDerivedStateFromProps()" + : "getSnapshotBeforeUpdate()"; -function pushTopLevelContextObject(fiber, context, didChange) { - { - if (contextStackCursor.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 (!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://react.dev/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); + } - push(contextStackCursor, context, fiber); - push(didPerformWorkStackCursor, didChange, fiber); - } -} + return instance; + } -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. + function callComponentWillMount(workInProgress, instance) { + var oldState = instance.state; - if (typeof instance.getChildContext !== "function") { - { - var componentName = getComponentNameFromFiber(fiber) || "Unknown"; + if (typeof instance.componentWillMount === "function") { + instance.componentWillMount(); + } - if (!warnedAboutMissingGetChildContext[componentName]) { - warnedAboutMissingGetChildContext[componentName] = true; + if (typeof instance.UNSAFE_componentWillMount === "function") { + instance.UNSAFE_componentWillMount(); + } + if (oldState !== instance.state) { + { 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 + "%s.componentWillMount(): Assigning directly to this.state is " + + "deprecated (except inside a component's " + + "constructor). Use setState instead.", + getComponentNameFromFiber(workInProgress) || "Component" ); } - } - - return parentContext; - } - - var childContext = instance.getChildContext(); - for (var contextKey in childContext) { - if (!(contextKey in childContextTypes)) { - throw new Error( - (getComponentNameFromFiber(fiber) || "Unknown") + - '.getChildContext(): key "' + - contextKey + - '" is not defined in childContextTypes.' - ); + classComponentUpdater.enqueueReplaceState(instance, instance.state, null); } } - { - var name = getComponentNameFromFiber(fiber) || "Unknown"; - checkPropTypes(childContextTypes, childContext, "child context", name); - } + function callComponentWillReceiveProps( + workInProgress, + instance, + newProps, + nextContext + ) { + var oldState = instance.state; - return assign({}, parentContext, childContext); - } -} + if (typeof instance.componentWillReceiveProps === "function") { + instance.componentWillReceiveProps(newProps, nextContext); + } -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.current; - push(contextStackCursor, memoizedMergedChildContext, workInProgress); - push( - didPerformWorkStackCursor, - didPerformWorkStackCursor.current, - workInProgress - ); - return true; - } -} + if (typeof instance.UNSAFE_componentWillReceiveProps === "function") { + instance.UNSAFE_componentWillReceiveProps(newProps, nextContext); + } -function invalidateContextProvider(workInProgress, type, didChange) { - { - var instance = workInProgress.stateNode; + if (instance.state !== oldState) { + { + var componentName = + getComponentNameFromFiber(workInProgress) || "Component"; - 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 (!didWarnAboutStateAssignmentForComponent.has(componentName)) { + didWarnAboutStateAssignmentForComponent.add(componentName); - 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. + error( + "%s.componentWillReceiveProps(): Assigning directly to " + + "this.state is deprecated (except inside a component's " + + "constructor). Use setState instead.", + componentName + ); + } + } - pop(didPerformWorkStackCursor, workInProgress); - pop(contextStackCursor, workInProgress); // Now push the new context and mark that it has changed. + classComponentUpdater.enqueueReplaceState(instance, instance.state, null); + } + } // Invokes the mount life-cycles on a previously never rendered instance. - push(contextStackCursor, mergedContext, workInProgress); - push(didPerformWorkStackCursor, didChange, workInProgress); - } else { - pop(didPerformWorkStackCursor, workInProgress); - push(didPerformWorkStackCursor, didChange, workInProgress); - } - } -} + function mountClassInstance(workInProgress, ctor, newProps, renderLanes) { + { + checkClassInstance(workInProgress, ctor, newProps); + } -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." - ); - } + var instance = workInProgress.stateNode; + instance.props = newProps; + instance.state = workInProgress.memoizedState; + instance.refs = emptyRefsObject; + initializeUpdateQueue(workInProgress); + var contextType = ctor.contextType; - var node = fiber; + if (typeof contextType === "object" && contextType !== null) { + instance.context = readContext(contextType); + } else { + var unmaskedContext = getUnmaskedContext(workInProgress, ctor, true); + instance.context = getMaskedContext(workInProgress, unmaskedContext); + } - do { - switch (node.tag) { - case HostRoot: - return node.stateNode.context; + { + if (instance.state === newProps) { + var componentName = getComponentNameFromType(ctor) || "Component"; - case ClassComponent: { - var Component = node.type; + if (!didWarnAboutDirectlyAssigningPropsToState.has(componentName)) { + didWarnAboutDirectlyAssigningPropsToState.add(componentName); - if (isContextProvider(Component)) { - return node.stateNode.__reactInternalMemoizedMergedChildContext; + 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 + ); } - - break; } - } - 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." - ); - } -} - -var LegacyRoot = 0; -var ConcurrentRoot = 1; - -/** - * 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 - ); -} + if (workInProgress.mode & StrictLegacyMode) { + ReactStrictModeWarnings.recordLegacyContextWarning( + workInProgress, + instance + ); + } -var objectIs = typeof Object.is === "function" ? Object.is : is; - -var syncQueue = null; -var includesLegacySyncCallbacks = false; -var isFlushingSyncQueue = false; -function scheduleSyncCallback(callback) { - // Push this callback into an internal queue. We'll flush these either in - // the next tick, or earlier if something calls `flushSyncCallbackQueue`. - if (syncQueue === null) { - syncQueue = [callback]; - } else { - // Push onto existing queue. Don't need to schedule a callback because - // we already scheduled one when we created the queue. - syncQueue.push(callback); - } -} -function scheduleLegacySyncCallback(callback) { - includesLegacySyncCallbacks = true; - scheduleSyncCallback(callback); -} -function flushSyncCallbacksOnlyInLegacyMode() { - // Only flushes the queue if there's a legacy sync callback scheduled. - // TODO: There's only a single type of callback: performSyncOnWorkOnRoot. So - // it might make more sense for the queue to be a list of roots instead of a - // list of generic callbacks. Then we can have two: one for legacy roots, one - // for concurrent roots. And this method would only flush the legacy ones. - if (includesLegacySyncCallbacks) { - flushSyncCallbacks(); - } -} -function flushSyncCallbacks() { - if (!isFlushingSyncQueue && syncQueue !== null) { - // Prevent re-entrance. - isFlushingSyncQueue = true; - var i = 0; - var previousUpdatePriority = getCurrentUpdatePriority(); + { + ReactStrictModeWarnings.recordUnsafeLifecycleWarnings( + workInProgress, + instance + ); + } + } - try { - var isSync = true; - var queue = syncQueue; // TODO: Is this necessary anymore? The only user code that runs in this - // queue is in the render or commit phases. + instance.state = workInProgress.memoizedState; + var getDerivedStateFromProps = ctor.getDerivedStateFromProps; - setCurrentUpdatePriority(DiscreteEventPriority); + 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. - for (; i < queue.length; i++) { - var callback = queue[i]; + 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. - do { - callback = callback(isSync); - } while (callback !== null); + processUpdateQueue(workInProgress, newProps, instance, renderLanes); + instance.state = workInProgress.memoizedState; } - syncQueue = null; - includesLegacySyncCallbacks = false; - } catch (error) { - // If something throws, leave the remaining callbacks on the queue. - if (syncQueue !== null) { - syncQueue = syncQueue.slice(i + 1); - } // Resume flushing in the next tick + if (typeof instance.componentDidMount === "function") { + var fiberFlags = Update; - scheduleCallback(ImmediatePriority, flushSyncCallbacks); - throw error; - } finally { - setCurrentUpdatePriority(previousUpdatePriority); - isFlushingSyncQueue = false; + workInProgress.flags |= fiberFlags; + } } - } - return null; -} + 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; -// 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 (typeof contextType === "object" && contextType !== null) { + nextContext = readContext(contextType); + } else { + var nextLegacyUnmaskedContext = getUnmaskedContext( + workInProgress, + ctor, + true + ); + nextContext = getMaskedContext(workInProgress, nextLegacyUnmaskedContext); + } -// TODO: Use the unified fiber stack module instead of this local one? -// Intentionally not using it yet to derisk the initial implementation, because -// the way we push/pop these values is a bit unusual. If there's a mistake, I'd -// rather the ids be wrong than crash the whole reconciler. -var forkStack = []; -var forkStackIndex = 0; -var treeForkProvider = null; -var treeForkCount = 0; -var idStack = []; -var idStackIndex = 0; -var treeContextProvider = null; -var treeContextId = 1; -var treeContextOverflow = ""; - -function popTreeContext(workInProgress) { - // Restore the previous values. - // This is a bit more complicated than other context-like modules in Fiber - // because the same Fiber may appear on the stack multiple times and for - // different reasons. We have to keep popping until the work-in-progress is - // no longer at the top of the stack. - while (workInProgress === treeForkProvider) { - treeForkProvider = forkStack[--forkStackIndex]; - forkStack[forkStackIndex] = null; - treeForkCount = forkStack[--forkStackIndex]; - forkStack[forkStackIndex] = null; - } - - while (workInProgress === treeContextProvider) { - treeContextProvider = idStack[--idStackIndex]; - idStack[idStackIndex] = null; - treeContextOverflow = idStack[--idStackIndex]; - idStack[idStackIndex] = null; - treeContextId = idStack[--idStackIndex]; - idStack[idStackIndex] = null; - } -} + 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. -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 ( + !hasNewLifecycles && + (typeof instance.UNSAFE_componentWillReceiveProps === "function" || + typeof instance.componentWillReceiveProps === "function") + ) { + if (oldProps !== newProps || oldContext !== nextContext) { + callComponentWillReceiveProps( + workInProgress, + instance, + newProps, + nextContext + ); + } + } -var didSuspendOrErrorDEV = false; // Hydration errors that were thrown inside this boundary + resetHasForceUpdateBeforeProcessing(); + var oldState = workInProgress.memoizedState; + var newState = (instance.state = oldState); + processUpdateQueue(workInProgress, newProps, instance, renderLanes); + newState = workInProgress.memoizedState; -var hydrationErrors = null; -function didSuspendOrErrorWhileHydratingDEV() { - { - return didSuspendOrErrorDEV; - } -} + 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") { + var fiberFlags = Update; -function reenterHydrationStateFromDehydratedSuspenseInstance( - fiber, - suspenseInstance, - treeContext -) { - { - return false; - } -} + workInProgress.flags |= fiberFlags; + } -function prepareToHydrateHostInstance( - fiber, - rootContainerInstance, - hostContext -) { - { - throw new Error( - "Expected prepareToHydrateHostInstance() to never be called. " + - "This error is likely caused by a bug in React. Please file an issue." - ); - } -} + return false; + } -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 shouldUpdate = hydrateTextInstance(); -} + if (typeof getDerivedStateFromProps === "function") { + applyDerivedStateFromProps( + workInProgress, + ctor, + getDerivedStateFromProps, + newProps + ); + newState = workInProgress.memoizedState; + } -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 shouldUpdate = + checkHasForceUpdateAfterProcessing() || + checkShouldComponentUpdate( + workInProgress, + ctor, + oldProps, + newProps, + oldState, + newState, + nextContext + ); -function popHydrationState(fiber) { - { - return false; - } -} + 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 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; - } -} + if (typeof instance.UNSAFE_componentWillMount === "function") { + instance.UNSAFE_componentWillMount(); + } + } -function getIsHydrating() { - return isHydrating; -} + if (typeof instance.componentDidMount === "function") { + var _fiberFlags = Update; -function queueHydrationError(error) { - if (hydrationErrors === null) { - hydrationErrors = [error]; - } else { - hydrationErrors.push(error); - } -} + workInProgress.flags |= _fiberFlags; + } + } 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") { + var _fiberFlags2 = Update; + + workInProgress.flags |= _fiberFlags2; + } // 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 ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig; -var NoTransition = null; -function requestCurrentTransition() { - return ReactCurrentBatchConfig.transition; -} + 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. -/** - * 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 ( + !hasNewLifecycles && + (typeof instance.UNSAFE_componentWillReceiveProps === "function" || + typeof instance.componentWillReceiveProps === "function") + ) { + if ( + unresolvedOldProps !== unresolvedNewProps || + oldContext !== nextContext + ) { + callComponentWillReceiveProps( + workInProgress, + instance, + newProps, + nextContext + ); + } + } -function shallowEqual(objA, objB) { - if (objectIs(objA, objB)) { - return true; - } + resetHasForceUpdateBeforeProcessing(); + var oldState = workInProgress.memoizedState; + var newState = (instance.state = oldState); + processUpdateQueue(workInProgress, newProps, instance, renderLanes); + newState = workInProgress.memoizedState; - if ( - typeof objA !== "object" || - objA === null || - typeof objB !== "object" || - objB === null - ) { - return false; - } + if ( + unresolvedOldProps === unresolvedNewProps && + oldState === newState && + !hasContextChanged() && + !checkHasForceUpdateAfterProcessing() && + !enableLazyContextPropagation + ) { + // 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; + } + } - var keysA = Object.keys(objA); - var keysB = Object.keys(objB); + if (typeof instance.getSnapshotBeforeUpdate === "function") { + if ( + unresolvedOldProps !== current.memoizedProps || + oldState !== current.memoizedState + ) { + workInProgress.flags |= Snapshot; + } + } - if (keysA.length !== keysB.length) { - return false; - } // Test for A's keys different from B. + return false; + } - for (var i = 0; i < keysA.length; i++) { - var currentKey = keysA[i]; + if (typeof getDerivedStateFromProps === "function") { + applyDerivedStateFromProps( + workInProgress, + ctor, + getDerivedStateFromProps, + newProps + ); + newState = workInProgress.memoizedState; + } - if ( - !hasOwnProperty.call(objB, currentKey) || - !objectIs(objA[currentKey], objB[currentKey]) - ) { - return false; - } - } + 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; - return true; -} + 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 describeFiber(fiber) { - var owner = fiber._debugOwner ? fiber._debugOwner.type : null; - var source = fiber._debugSource; + if (typeof instance.UNSAFE_componentWillUpdate === "function") { + instance.UNSAFE_componentWillUpdate(newProps, newState, nextContext); + } + } - switch (fiber.tag) { - case HostComponent: - return describeBuiltInComponentFrame(fiber.type, source, owner); + if (typeof instance.componentDidUpdate === "function") { + workInProgress.flags |= Update; + } - case LazyComponent: - return describeBuiltInComponentFrame("Lazy", source, owner); + 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; + } + } - case SuspenseComponent: - return describeBuiltInComponentFrame("Suspense", source, owner); + 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. - case SuspenseListComponent: - return describeBuiltInComponentFrame("SuspenseList", source, owner); + workInProgress.memoizedProps = newProps; + workInProgress.memoizedState = newState; + } // Update the existing instance's state, props, and context pointers even + // if shouldComponentUpdate returns false. - case FunctionComponent: - case IndeterminateComponent: - case SimpleMemoComponent: - return describeFunctionComponentFrame(fiber.type, source, owner); + instance.props = newProps; + instance.state = newState; + instance.context = nextContext; + return shouldUpdate; + } - case ForwardRef: - return describeFunctionComponentFrame(fiber.type.render, source, owner); + var didWarnAboutMaps; + var didWarnAboutGenerators; + var didWarnAboutStringRefs; + var ownerHasKeyUseWarning; + var ownerHasFunctionTypeWarning; - case ClassComponent: - return describeClassComponentFrame(fiber.type, source, owner); + var warnForMissingKey = function (child, returnFiber) { }; - default: - return ""; - } -} + { + 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 getStackByFiberInDevAndProd(workInProgress) { - try { - var info = ""; - var node = workInProgress; + if (!child._store || child._store.validated || child.key != null) { + return; + } - do { - info += describeFiber(node); - node = node.return; - } while (node); + 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." + ); + } - return info; - } catch (x) { - return "\nError generating stack: " + x.message + "\n" + x.stack; - } -} + child._store.validated = true; + var componentName = getComponentNameFromFiber(returnFiber) || "Component"; -var ReactDebugCurrentFrame$1 = ReactSharedInternals.ReactDebugCurrentFrame; -var current = null; -var isRendering = false; -function getCurrentFiberOwnerNameInDevOrNull() { - { - if (current === null) { - return null; - } + if (ownerHasKeyUseWarning[componentName]) { + return; + } - var owner = current._debugOwner; + ownerHasKeyUseWarning[componentName] = true; - if (owner !== null && typeof owner !== "undefined") { - return getComponentNameFromFiber(owner); + error( + "Each child in a list should have a unique " + + '"key" prop. See https://react.dev/link/warning-keys for ' + + "more information." + ); + }; } - } - return null; -} + function coerceRef(returnFiber, current, element) { + var mixedRef = element.ref; -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 ( + mixedRef !== null && + typeof mixedRef !== "function" && + typeof mixedRef !== "object" + ) { + { + // TODO: Clean this up once we turn on the string ref warning for + // everyone, because the strict mode case will no longer be relevant + if ( + (returnFiber.mode & StrictLegacyMode || warnAboutStringRefs) && // 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 + ) + ) { + var componentName = + getComponentNameFromFiber(returnFiber) || "Component"; - return getStackByFiberInDevAndProd(current); - } -} + if (!didWarnAboutStringRefs[componentName]) { + { + error( + 'A string ref, "%s", has been found within a strict mode tree. ' + + "String refs are a source of potential bugs and should be avoided. " + + "We recommend using useRef() or createRef() instead. " + + "Learn more about using refs safely here: " + + "https://react.dev/link/strict-mode-string-ref", + mixedRef + ); + } -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; - } -} + didWarnAboutStringRefs[componentName] = true; + } + } + } -var ReactStrictModeWarnings = { - recordUnsafeLifecycleWarnings: function(fiber, instance) {}, - flushPendingUnsafeLifecycleWarnings: function() {}, - recordLegacyContextWarning: function(fiber, instance) {}, - flushLegacyContextWarning: function() {}, - discardPendingWarnings: function() {} -}; + if (element._owner) { + var owner = element._owner; + var inst; -{ - var findStrictRoot = function(fiber) { - var maybeStrictRoot = null; - var node = fiber; + if (owner) { + var ownerFiber = owner; - while (node !== null) { - if (node.mode & StrictLegacyMode) { - maybeStrictRoot = node; - } + 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://react.dev/link/strict-mode-string-ref" + ); + } - node = node.return; - } + inst = ownerFiber.stateNode; + } - return maybeStrictRoot; - }; + 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 setToSortedString = function(set) { - var array = []; - set.forEach(function(value) { - array.push(value); - }); - return array.sort().join(", "); - }; + var resolvedInst = inst; - var pendingComponentWillMountWarnings = []; - var pendingUNSAFE_ComponentWillMountWarnings = []; - var pendingComponentWillReceivePropsWarnings = []; - var pendingUNSAFE_ComponentWillReceivePropsWarnings = []; - var pendingComponentWillUpdateWarnings = []; - var pendingUNSAFE_ComponentWillUpdateWarnings = []; // Tracks components we have already warned about. + { + checkPropStringCoercion(mixedRef, "ref"); + } - var didWarnAboutUnsafeLifecycles = new Set(); + var stringRef = "" + mixedRef; // Check if previous string ref matches new string ref - ReactStrictModeWarnings.recordUnsafeLifecycleWarnings = function( - fiber, - instance - ) { - // Dedupe strategy: Warn once per component. - if (didWarnAboutUnsafeLifecycles.has(fiber.type)) { - return; - } + if ( + current !== null && + current.ref !== null && + typeof current.ref === "function" && + current.ref._stringRef === stringRef + ) { + return current.ref; + } - if ( - typeof instance.componentWillMount === "function" && // Don't warn about react-lifecycles-compat polyfilled components. - instance.componentWillMount.__suppressDeprecationWarning !== true - ) { - pendingComponentWillMountWarnings.push(fiber); - } + var ref = function (value) { + var refs = resolvedInst.refs; - if ( - fiber.mode & StrictLegacyMode && - typeof instance.UNSAFE_componentWillMount === "function" - ) { - pendingUNSAFE_ComponentWillMountWarnings.push(fiber); - } + if (refs === emptyRefsObject) { + // This is a lazy pooled frozen object, so we need to initialize. + refs = resolvedInst.refs = {}; + } - if ( - typeof instance.componentWillReceiveProps === "function" && - instance.componentWillReceiveProps.__suppressDeprecationWarning !== true - ) { - pendingComponentWillReceivePropsWarnings.push(fiber); - } + if (value === null) { + delete refs[stringRef]; + } else { + refs[stringRef] = value; + } + }; - if ( - fiber.mode & StrictLegacyMode && - typeof instance.UNSAFE_componentWillReceiveProps === "function" - ) { - pendingUNSAFE_ComponentWillReceivePropsWarnings.push(fiber); - } + 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 ( - typeof instance.componentWillUpdate === "function" && - instance.componentWillUpdate.__suppressDeprecationWarning !== true - ) { - pendingComponentWillUpdateWarnings.push(fiber); + 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://react.dev/link/refs-must-have-owner for more information." + ); + } + } + } + + return mixedRef; } - if ( - fiber.mode & StrictLegacyMode && - typeof instance.UNSAFE_componentWillUpdate === "function" - ) { - pendingUNSAFE_ComponentWillUpdateWarnings.push(fiber); + function throwOnInvalidObjectType(returnFiber, newChild) { + 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." + ); } - }; - ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings = function() { - // We do an initial pass to gather component names - var componentWillMountUniqueNames = new Set(); + function warnOnFunctionType(returnFiber) { + { + var componentName = getComponentNameFromFiber(returnFiber) || "Component"; - if (pendingComponentWillMountWarnings.length > 0) { - pendingComponentWillMountWarnings.forEach(function(fiber) { - componentWillMountUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingComponentWillMountWarnings = []; - } + if (ownerHasFunctionTypeWarning[componentName]) { + return; + } - var UNSAFE_componentWillMountUniqueNames = new Set(); + ownerHasFunctionTypeWarning[componentName] = true; - if (pendingUNSAFE_ComponentWillMountWarnings.length > 0) { - pendingUNSAFE_ComponentWillMountWarnings.forEach(function(fiber) { - UNSAFE_componentWillMountUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" + 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." ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingUNSAFE_ComponentWillMountWarnings = []; + } } - var componentWillReceivePropsUniqueNames = new Set(); + 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 (pendingComponentWillReceivePropsWarnings.length > 0) { - pendingComponentWillReceivePropsWarnings.forEach(function(fiber) { - componentWillReceivePropsUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingComponentWillReceivePropsWarnings = []; - } + function ChildReconciler(shouldTrackSideEffects) { + function deleteChild(returnFiber, childToDelete) { + if (!shouldTrackSideEffects) { + // Noop. + return; + } - var UNSAFE_componentWillReceivePropsUniqueNames = new Set(); + var deletions = returnFiber.deletions; - if (pendingUNSAFE_ComponentWillReceivePropsWarnings.length > 0) { - pendingUNSAFE_ComponentWillReceivePropsWarnings.forEach(function(fiber) { - UNSAFE_componentWillReceivePropsUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingUNSAFE_ComponentWillReceivePropsWarnings = []; - } + if (deletions === null) { + returnFiber.deletions = [childToDelete]; + returnFiber.flags |= ChildDeletion; + } else { + deletions.push(childToDelete); + } + } - var componentWillUpdateUniqueNames = new Set(); + 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. - if (pendingComponentWillUpdateWarnings.length > 0) { - pendingComponentWillUpdateWarnings.forEach(function(fiber) { - componentWillUpdateUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingComponentWillUpdateWarnings = []; - } + var childToDelete = currentFirstChild; - var UNSAFE_componentWillUpdateUniqueNames = new Set(); + while (childToDelete !== null) { + deleteChild(returnFiber, childToDelete); + childToDelete = childToDelete.sibling; + } - 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://react.dev/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 - ); - } + return null; + } - if (UNSAFE_componentWillReceivePropsUniqueNames.size > 0) { - var _sortedNames = setToSortedString( - UNSAFE_componentWillReceivePropsUniqueNames - ); + 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; - error( - "Using UNSAFE_componentWillReceiveProps in strict mode is not recommended " + - "and may indicate bugs in your code. " + - "See https://react.dev/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://react.dev/link/derived-state\n" + - "\nPlease update the following components: %s", - _sortedNames - ); - } + while (existingChild !== null) { + if (existingChild.key !== null) { + existingChildren.set(existingChild.key, existingChild); + } else { + existingChildren.set(existingChild.index, existingChild); + } - if (UNSAFE_componentWillUpdateUniqueNames.size > 0) { - var _sortedNames2 = setToSortedString( - UNSAFE_componentWillUpdateUniqueNames - ); + existingChild = existingChild.sibling; + } - error( - "Using UNSAFE_componentWillUpdate in strict mode is not recommended " + - "and may indicate bugs in your code. " + - "See https://react.dev/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 existingChildren; + } - if (componentWillMountUniqueNames.size > 0) { - var _sortedNames3 = setToSortedString(componentWillMountUniqueNames); + 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; + } - warn( - "componentWillMount has been renamed, and is not recommended for use. " + - "See https://react.dev/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 - ); - } + function placeChild(newFiber, lastPlacedIndex, newIndex) { + newFiber.index = newIndex; - if (componentWillReceivePropsUniqueNames.size > 0) { - var _sortedNames4 = setToSortedString( - componentWillReceivePropsUniqueNames - ); + 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; + } - warn( - "componentWillReceiveProps has been renamed, and is not recommended for use. " + - "See https://react.dev/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://react.dev/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 - ); - } + var current = newFiber.alternate; - if (componentWillUpdateUniqueNames.size > 0) { - var _sortedNames5 = setToSortedString(componentWillUpdateUniqueNames); + if (current !== null) { + var oldIndex = current.index; - warn( - "componentWillUpdate has been renamed, and is not recommended for use. " + - "See https://react.dev/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 - ); - } - }; + if (oldIndex < lastPlacedIndex) { + // This is a move. + newFiber.flags |= Placement; + return lastPlacedIndex; + } else { + // This item can stay in place. + return oldIndex; + } + } else { + // This is an insertion. + newFiber.flags |= Placement; + 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; + } - var pendingLegacyContextWarning = new Map(); // Tracks components we have already warned about. + return newFiber; + } - var didWarnAboutLegacyContext = new Set(); + 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; + } + } - ReactStrictModeWarnings.recordLegacyContextWarning = function( - fiber, - instance - ) { - var strictRoot = findStrictRoot(fiber); + function updateElement(returnFiber, current, element, lanes) { + var elementType = element.type; - 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 (elementType === REACT_FRAGMENT_TYPE) { + return updateFragment( + returnFiber, + current, + element.props.children, + lanes, + element.key + ); + } - return; - } // Dedup strategy: Warn once per component. + 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; - if (didWarnAboutLegacyContext.has(fiber.type)) { - return; - } + { + existing._debugSource = element._source; + existing._debugOwner = element._owner; + } - var warningsForRoot = pendingLegacyContextWarning.get(strictRoot); + return existing; + } + } // Insert - if ( - fiber.type.contextTypes != null || - fiber.type.childContextTypes != null || - (instance !== null && typeof instance.getChildContext === "function") - ) { - if (warningsForRoot === undefined) { - warningsForRoot = []; - pendingLegacyContextWarning.set(strictRoot, warningsForRoot); + var created = createFiberFromElement(element, returnFiber.mode, lanes); + created.ref = coerceRef(returnFiber, current, element); + created.return = returnFiber; + return created; } - warningsForRoot.push(fiber); - } - }; + 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; + } + } - ReactStrictModeWarnings.flushLegacyContextWarning = function() { - pendingLegacyContextWarning.forEach(function(fiberArray, strictRoot) { - if (fiberArray.length === 0) { - return; + 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 firstFiber = fiberArray[0]; - var uniqueNames = new Set(); - fiberArray.forEach(function(fiber) { - uniqueNames.add(getComponentNameFromFiber(fiber) || "Component"); - didWarnAboutLegacyContext.add(fiber.type); - }); - var sortedNames = setToSortedString(uniqueNames); + 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; + } - try { - setCurrentFiber(firstFiber); + if (typeof newChild === "object" && newChild !== null) { + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE: { + var _created = createFiberFromElement( + newChild, + returnFiber.mode, + 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://react.dev/link/legacy-context", - sortedNames - ); - } finally { - resetCurrentFiber(); - } - }); - }; - - ReactStrictModeWarnings.discardPendingWarnings = function() { - pendingComponentWillMountWarnings = []; - pendingUNSAFE_ComponentWillMountWarnings = []; - pendingComponentWillReceivePropsWarnings = []; - pendingUNSAFE_ComponentWillReceivePropsWarnings = []; - pendingComponentWillUpdateWarnings = []; - pendingUNSAFE_ComponentWillUpdateWarnings = []; - pendingLegacyContextWarning = new Map(); - }; -} + _created.ref = coerceRef(returnFiber, null, newChild); + _created.return = returnFiber; + return _created; + } -/* - * The `'' + value` pattern (used in 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 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"; - return type; - } -} // $FlowFixMe only called in DEV, so void return is not possible. - -function willCoercionThrow(value) { - { - try { - testStringCoercion(value); - return false; - } catch (e) { - return true; - } - } -} + case REACT_PORTAL_TYPE: { + var _created2 = createFiberFromPortal( + newChild, + returnFiber.mode, + lanes + ); -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 before using it here.", - typeName(value) - ); + _created2.return = returnFiber; + return _created2; + } - 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 before using it here.", - propName, - typeName(value) - ); + case REACT_LAZY_TYPE: { + var payload = newChild._payload; + var init = newChild._init; + return createChild(returnFiber, init(payload), lanes); + } + } - return testStringCoercion(value); // throw (to help callers find troubleshooting comments) - } - } -} + if (isArray(newChild) || getIteratorFn(newChild)) { + var _created3 = createFiberFromFragment( + newChild, + returnFiber.mode, + lanes, + null + ); + + _created3.return = returnFiber; + return _created3; + } + + throwOnInvalidObjectType(returnFiber, newChild); + } -function resolveDefaultProps(Component, baseProps) { - if (Component && Component.defaultProps) { - // Resolve default props. Taken from ReactElement - var props = assign({}, baseProps); - var defaultProps = Component.defaultProps; + { + if (typeof newChild === "function") { + warnOnFunctionType(returnFiber); + } + } - for (var propName in defaultProps) { - if (props[propName] === undefined) { - props[propName] = defaultProps[propName]; + return null; } - } - return props; - } + function updateSlot(returnFiber, oldFiber, newChild, lanes) { + // Update the fiber if the keys match, otherwise return null. + var key = oldFiber !== null ? oldFiber.key : null; - return baseProps; -} + 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; + } -var valueCursor = createCursor(null); -var rendererSigil; + return updateTextNode(returnFiber, oldFiber, "" + newChild, lanes); + } -{ - // Use this to detect multiple renderers using the same context - rendererSigil = {}; -} + 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; + } + } -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; + case REACT_PORTAL_TYPE: { + if (newChild.key === key) { + return updatePortal(returnFiber, oldFiber, newChild, lanes); + } else { + return null; + } + } - { - if ( - context._currentRenderer2 !== undefined && - context._currentRenderer2 !== null && - context._currentRenderer2 !== rendererSigil - ) { - error( - "Detected multiple renderers concurrently rendering the " + - "same context provider. This is currently unsupported." - ); - } + case REACT_LAZY_TYPE: { + var payload = newChild._payload; + var init = newChild._init; + return updateSlot(returnFiber, oldFiber, init(payload), lanes); + } + } - context._currentRenderer2 = rendererSigil; - } - } -} -function popProvider(context, providerFiber) { - var currentValue = valueCursor.current; - pop(valueCursor, providerFiber); + if (isArray(newChild) || getIteratorFn(newChild)) { + if (key !== null) { + return null; + } - { - { - context._currentValue2 = currentValue; - } - } -} -function scheduleContextWorkOnParentPath(parent, renderLanes, propagationRoot) { - // Update the child lanes of all the ancestors, including the alternates. - var node = parent; + return updateFragment(returnFiber, oldFiber, newChild, lanes, null); + } - while (node !== null) { - var alternate = node.alternate; + throwOnInvalidObjectType(returnFiber, newChild); + } - if (!isSubsetOfLanes(node.childLanes, renderLanes)) { - node.childLanes = mergeLanes(node.childLanes, renderLanes); + { + if (typeof newChild === "function") { + warnOnFunctionType(returnFiber); + } + } - if (alternate !== null) { - alternate.childLanes = mergeLanes(alternate.childLanes, renderLanes); + return null; } - } else if ( - alternate !== null && - !isSubsetOfLanes(alternate.childLanes, renderLanes) - ) { - alternate.childLanes = mergeLanes(alternate.childLanes, renderLanes); - } - if (node === propagationRoot) { - break; - } + 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); + } - node = node.return; - } + 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 !== 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) { - { - propagateContextChange_eager(workInProgress, context, renderLanes); - } -} + return updateElement(returnFiber, _matchedFiber, newChild, lanes); + } -function propagateContextChange_eager(workInProgress, context, renderLanes) { - var fiber = workInProgress.child; + case REACT_PORTAL_TYPE: { + var _matchedFiber2 = + existingChildren.get( + newChild.key === null ? newIdx : newChild.key + ) || null; - if (fiber !== null) { - // Set the return pointer of the child to the work-in-progress fiber. - fiber.return = workInProgress; - } + return updatePortal(returnFiber, _matchedFiber2, newChild, lanes); + } - while (fiber !== null) { - var nextFiber = void 0; // Visit this fiber. + case REACT_LAZY_TYPE: + var payload = newChild._payload; + var init = newChild._init; + return updateFromMap( + existingChildren, + returnFiber, + newIdx, + init(payload), + lanes + ); + } - var list = fiber.dependencies; + if (isArray(newChild) || getIteratorFn(newChild)) { + var _matchedFiber3 = existingChildren.get(newIdx) || null; - if (list !== null) { - nextFiber = fiber.child; - var dependency = list.firstContext; + return updateFragment( + returnFiber, + _matchedFiber3, + newChild, + lanes, + null + ); + } - 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(NoTimestamp, 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 - - var updateQueue = fiber.updateQueue; - - if (updateQueue === null); - else { - var sharedQueue = updateQueue.shared; - var pending = sharedQueue.pending; - - if (pending === null) { - // This is the first update. Create a circular list. - update.next = update; - } else { - update.next = pending.next; - pending.next = update; - } + throwOnInvalidObjectType(returnFiber, newChild); + } - sharedQueue.pending = update; - } + { + if (typeof newChild === "function") { + warnOnFunctionType(returnFiber); } + } - fiber.lanes = mergeLanes(fiber.lanes, renderLanes); - var alternate = fiber.alternate; + return null; + } + /** + * Warns if there is a duplicate or missing key + */ - if (alternate !== null) { - alternate.lanes = mergeLanes(alternate.lanes, renderLanes); + function warnOnInvalidKey(child, knownKeys, returnFiber) { + { + if (typeof child !== "object" || child === null) { + return knownKeys; } - scheduleContextWorkOnParentPath( - fiber.return, - renderLanes, - workInProgress - ); // Mark the updated lanes on the list, too. - - list.lanes = mergeLanes(list.lanes, renderLanes); // Since we already found a match, we can stop traversing the - // dependency list. + switch (child.$$typeof) { + case REACT_ELEMENT_TYPE: + case REACT_PORTAL_TYPE: + warnForMissingKey(child, returnFiber); + var key = child.key; - break; - } + if (typeof key !== "string") { + 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 (knownKeys === null) { + knownKeys = new Set(); + knownKeys.add(key); + break; + } - 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 (!knownKeys.has(key)) { + knownKeys.add(key); + break; + } - parentSuspense.lanes = mergeLanes(parentSuspense.lanes, renderLanes); - var _alternate = parentSuspense.alternate; + 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 + ); - 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. + break; - scheduleContextWorkOnParentPath( - parentSuspense, - renderLanes, - workInProgress - ); - nextFiber = fiber.sibling; - } 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; + case REACT_LAZY_TYPE: + var payload = child._payload; + var init = child._init; + warnOnInvalidKey(init(payload), knownKeys, returnFiber); + 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; + return knownKeys; } - } - fiber = nextFiber; - } -} -function prepareToReadContext(workInProgress, renderLanes) { - currentlyRenderingFiber = workInProgress; - lastContextDependency = null; - lastFullyObservedContext = null; - var dependencies = workInProgress.dependencies; + 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; - if (dependencies !== null) { - { - var firstContext = dependencies.firstContext; + for (var i = 0; i < newChildren.length; i++) { + var child = newChildren[i]; + knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); + } + } - 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 + 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; + } - 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 newFiber = updateSlot( + returnFiber, + oldFiber, + newChildren[newIdx], + lanes + ); - var value = context._currentValue2; + 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 (lastFullyObservedContext === context); - else { - var contextItem = { - context: context, - memoizedValue: value, - next: null - }; + break; + } - if (lastContextDependency === null) { - if (currentlyRenderingFiber === 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 (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); + } + } - lastContextDependency = contextItem; - currentlyRenderingFiber.dependencies = { - lanes: NoLanes, - firstContext: contextItem - }; - } else { - // Append a new context item. - lastContextDependency = lastContextDependency.next = contextItem; - } - } + lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx); - return value; -} + 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; + } -// render. When this render exits, either because it finishes or because it is -// interrupted, the interleaved updates will be transferred onto the main part -// of the queue. - -var concurrentQueues = null; -function pushConcurrentUpdateQueue(queue) { - if (concurrentQueues === null) { - concurrentQueues = [queue]; - } else { - concurrentQueues.push(queue); - } -} -function finishQueueingConcurrentUpdates() { - // Transfer the interleaved updates onto the main queue. Each queue has a - // `pending` field and an `interleaved` field. When they are not null, they - // point to the last node in a circular linked list. We need to append the - // interleaved list to the end of the pending list by joining them into a - // single, circular list. - if (concurrentQueues !== null) { - for (var i = 0; i < concurrentQueues.length; i++) { - var queue = concurrentQueues[i]; - var lastInterleavedUpdate = queue.interleaved; + previousNewFiber = newFiber; + oldFiber = nextOldFiber; + } - if (lastInterleavedUpdate !== null) { - queue.interleaved = null; - var firstInterleavedUpdate = lastInterleavedUpdate.next; - var lastPendingUpdate = queue.pending; + if (newIdx === newChildren.length) { + // We've reached the end of the new children. We can delete the rest. + deleteRemainingChildren(returnFiber, oldFiber); - if (lastPendingUpdate !== null) { - var firstPendingUpdate = lastPendingUpdate.next; - lastPendingUpdate.next = firstInterleavedUpdate; - lastInterleavedUpdate.next = firstPendingUpdate; + return resultingFirstChild; } - queue.pending = lastInterleavedUpdate; - } - } + 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); - concurrentQueues = null; - } -} -function enqueueConcurrentHookUpdate(fiber, queue, update, lane) { - var interleaved = queue.interleaved; - - if (interleaved === null) { - // This is the first update. Create a circular list. - update.next = update; // At the end of the current render, this queue's interleaved updates will - // be transferred to the pending queue. - - pushConcurrentUpdateQueue(queue); - } else { - update.next = interleaved.next; - interleaved.next = update; - } - - queue.interleaved = update; - return markUpdateLaneFromFiberToRoot(fiber, lane); -} -function enqueueConcurrentHookUpdateAndEagerlyBailout( - fiber, - queue, - update, - lane -) { - var interleaved = queue.interleaved; - - if (interleaved === null) { - // This is the first update. Create a circular list. - update.next = update; // At the end of the current render, this queue's interleaved updates will - // be transferred to the pending queue. - - pushConcurrentUpdateQueue(queue); - } else { - update.next = interleaved.next; - interleaved.next = update; - } - - queue.interleaved = update; -} -function enqueueConcurrentClassUpdate(fiber, queue, update, lane) { - var interleaved = queue.interleaved; - - if (interleaved === null) { - // This is the first update. Create a circular list. - update.next = update; // At the end of the current render, this queue's interleaved updates will - // be transferred to the pending queue. - - pushConcurrentUpdateQueue(queue); - } else { - update.next = interleaved.next; - interleaved.next = update; - } - - queue.interleaved = update; - return markUpdateLaneFromFiberToRoot(fiber, lane); -} -function enqueueConcurrentRenderForLane(fiber, lane) { - return markUpdateLaneFromFiberToRoot(fiber, lane); -} // Calling this function outside this module should only be done for backwards -// compatibility and should always be accompanied by a warning. + if (_newFiber === null) { + continue; + } -var unsafe_markUpdateLaneFromFiberToRoot = markUpdateLaneFromFiberToRoot; + lastPlacedIndex = placeChild(_newFiber, lastPlacedIndex, newIdx); -function markUpdateLaneFromFiberToRoot(sourceFiber, lane) { - // Update the source fiber's lanes - sourceFiber.lanes = mergeLanes(sourceFiber.lanes, lane); - var alternate = sourceFiber.alternate; + if (previousNewFiber === null) { + // TODO: Move out of the loop. This only happens for the first run. + resultingFirstChild = _newFiber; + } else { + previousNewFiber.sibling = _newFiber; + } - if (alternate !== null) { - alternate.lanes = mergeLanes(alternate.lanes, lane); - } + previousNewFiber = _newFiber; + } - { - if ( - alternate === null && - (sourceFiber.flags & (Placement | Hydrating)) !== NoFlags - ) { - warnAboutUpdateOnNotYetMountedFiberInDEV(sourceFiber); - } - } // Walk the parent path to the root and update the child lanes. + return resultingFirstChild; + } // Add all children to a key map for quick lookups. - var node = sourceFiber; - var parent = sourceFiber.return; + var existingChildren = mapRemainingChildren(returnFiber, oldFiber); // Keep scanning and use the map to restore deleted items as moves. - while (parent !== null) { - parent.childLanes = mergeLanes(parent.childLanes, lane); - alternate = parent.alternate; + for (; newIdx < newChildren.length; newIdx++) { + var _newFiber2 = updateFromMap( + existingChildren, + returnFiber, + newIdx, + newChildren[newIdx], + lanes + ); - if (alternate !== null) { - alternate.childLanes = mergeLanes(alternate.childLanes, lane); - } else { - { - if ((parent.flags & (Placement | Hydrating)) !== NoFlags) { - warnAboutUpdateOnNotYetMountedFiberInDEV(sourceFiber); - } - } - } + 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 + ); + } + } - node = parent; - parent = parent.return; - } + lastPlacedIndex = placeChild(_newFiber2, lastPlacedIndex, newIdx); - if (node.tag === HostRoot) { - var root = node.stateNode; - return root; - } else { - return null; - } -} + if (previousNewFiber === null) { + resultingFirstChild = _newFiber2; + } else { + previousNewFiber.sibling = _newFiber2; + } -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`. + previousNewFiber = _newFiber2; + } + } -var hasForceUpdate = false; -var didWarnUpdateInsideUpdate; -var currentlyProcessingQueue; + 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); + }); + } -{ - didWarnUpdateInsideUpdate = false; - currentlyProcessingQueue = null; -} + return resultingFirstChild; + } -function initializeUpdateQueue(fiber) { - var queue = { - baseState: fiber.memoizedState, - firstBaseUpdate: null, - lastBaseUpdate: null, - shared: { - pending: null, - interleaved: null, - lanes: NoLanes - }, - effects: 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, - effects: currentQueue.effects - }; - workInProgress.updateQueue = clone; - } -} -function createUpdate(eventTime, lane) { - var update = { - eventTime: eventTime, - lane: lane, - tag: UpdateState, - payload: null, - callback: null, - next: null - }; - return update; -} -function enqueueUpdate(fiber, update, lane) { - var updateQueue = fiber.updateQueue; + function reconcileChildrenIterator( + returnFiber, + currentFirstChild, + newChildrenIterable, + lanes + ) { + // This is the same implementation as reconcileChildrenArray(), + // but using the iterator instead. + var iteratorFn = getIteratorFn(newChildrenIterable); - if (updateQueue === null) { - // Only occurs if the fiber has been unmounted. - return null; - } + 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 sharedQueue = updateQueue.shared; + { + // We don't support rendering Generators because it's a mutation. + // See https://github.com/facebook/react/issues/12995 + if ( + typeof Symbol === "function" && // $FlowFixMe 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." + ); + } - { - if ( - currentlyProcessingQueue === sharedQueue && - !didWarnUpdateInsideUpdate - ) { - 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." - ); + didWarnAboutGenerators = true; + } // Warn about using Maps as children - didWarnUpdateInsideUpdate = true; - } - } + if (newChildrenIterable.entries === iteratorFn) { + if (!didWarnAboutMaps) { + error( + "Using Maps as children is not supported. " + + "Use an array of keyed ReactElements instead." + ); + } - 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; + didWarnAboutMaps = true; + } // First, validate keys. + // We'll get a different iterator later for the main pass. - if (pending === null) { - // This is the first update. Create a circular list. - update.next = update; - } else { - update.next = pending.next; - pending.next = update; - } + var _newChildren = iteratorFn.call(newChildrenIterable); - 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 (_newChildren) { + var knownKeys = null; - return unsafe_markUpdateLaneFromFiberToRoot(fiber, lane); - } else { - return enqueueConcurrentClassUpdate(fiber, sharedQueue, update, lane); - } -} -function entangleTransitions(root, fiber, lane) { - var updateQueue = fiber.updateQueue; + var _step = _newChildren.next(); - if (updateQueue === null) { - // Only occurs if the fiber has been unmounted. - return; - } + for (; !_step.done; _step = _newChildren.next()) { + var child = _step.value; + knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); + } + } + } - var sharedQueue = updateQueue.shared; + var newChildren = iteratorFn.call(newChildrenIterable); - 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. + if (newChildren == null) { + throw new Error("An iterable object provided no iterator."); + } - queueLanes = intersectLanes(queueLanes, root.pendingLanes); // Entangle the new transition lane with the other transition lanes. + var resultingFirstChild = null; + var previousNewFiber = null; + var oldFiber = currentFirstChild; + var lastPlacedIndex = 0; + var newIdx = 0; + var nextOldFiber = null; + var step = newChildren.next(); - 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. + for ( + ; + oldFiber !== null && !step.done; + newIdx++, step = newChildren.next() + ) { + if (oldFiber.index > newIdx) { + nextOldFiber = oldFiber; + oldFiber = null; + } else { + nextOldFiber = oldFiber.sibling; + } - 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 newFiber = updateSlot(returnFiber, oldFiber, step.value, lanes); - if (firstBaseUpdate !== null) { - // Loop through the updates and clone them. - var update = firstBaseUpdate; + 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; + } - do { - var clone = { - eventTime: update.eventTime, - lane: update.lane, - tag: update.tag, - payload: update.payload, - callback: update.callback, - next: null - }; + break; + } - if (newLast === null) { - newFirst = newLast = clone; - } else { - newLast.next = clone; - newLast = clone; + 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); + } } - update = update.next; - } while (update !== null); // Append the captured update the end of the cloned list. + lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx); - if (newLast === null) { - newFirst = newLast = capturedUpdate; - } else { - newLast.next = capturedUpdate; - newLast = capturedUpdate; + 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; } - } else { - // There are no base updates. - newFirst = newLast = capturedUpdate; - } - queue = { - baseState: currentQueue.baseState, - firstBaseUpdate: newFirst, - lastBaseUpdate: newLast, - shared: currentQueue.shared, - effects: currentQueue.effects - }; - workInProgress.updateQueue = queue; - return; - } - } // Append the update to the end of the list. + if (step.done) { + // We've reached the end of the new children. We can delete the rest. + deleteRemainingChildren(returnFiber, oldFiber); - var lastBaseUpdate = queue.lastBaseUpdate; + return resultingFirstChild; + } - if (lastBaseUpdate === null) { - queue.firstBaseUpdate = capturedUpdate; - } else { - lastBaseUpdate.next = capturedUpdate; - } + 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); - queue.lastBaseUpdate = capturedUpdate; -} + if (_newFiber3 === null) { + continue; + } -function getStateFromUpdate( - workInProgress, - queue, - update, - prevState, - nextProps, - instance -) { - switch (update.tag) { - case ReplaceState: { - var payload = update.payload; - - if (typeof payload === "function") { - // Updater function - { - enterDisallowedContextReadInDEV(); - } + lastPlacedIndex = placeChild(_newFiber3, lastPlacedIndex, newIdx); - var nextState = payload.call(instance, prevState, nextProps); + if (previousNewFiber === null) { + // TODO: Move out of the loop. This only happens for the first run. + resultingFirstChild = _newFiber3; + } else { + previousNewFiber.sibling = _newFiber3; + } - { - exitDisallowedContextReadInDEV(); - } + previousNewFiber = _newFiber3; + } - return nextState; - } // State object + return resultingFirstChild; + } // Add all children to a key map for quick lookups. - return payload; - } + var existingChildren = mapRemainingChildren(returnFiber, oldFiber); // Keep scanning and use the map to restore deleted items as moves. - case CaptureUpdate: { - workInProgress.flags = - (workInProgress.flags & ~ShouldCapture) | DidCapture; - } - // Intentional fallthrough + for (; !step.done; newIdx++, step = newChildren.next()) { + var _newFiber4 = updateFromMap( + existingChildren, + returnFiber, + newIdx, + step.value, + lanes + ); - case UpdateState: { - var _payload = update.payload; - var partialState; + 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 + ); + } + } - if (typeof _payload === "function") { - // Updater function - { - enterDisallowedContextReadInDEV(); - } + lastPlacedIndex = placeChild(_newFiber4, lastPlacedIndex, newIdx); - partialState = _payload.call(instance, prevState, nextProps); + if (previousNewFiber === null) { + resultingFirstChild = _newFiber4; + } else { + previousNewFiber.sibling = _newFiber4; + } - { - exitDisallowedContextReadInDEV(); + previousNewFiber = _newFiber4; + } } - } 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); - } + 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); + }); + } - case ForceUpdate: { - hasForceUpdate = true; - return prevState; - } - } + return resultingFirstChild; + } - return prevState; -} + 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. -function processUpdateQueue(workInProgress, props, instance, renderLanes) { - // This is always non-null on a ClassComponent or HostRoot - var queue = workInProgress.updateQueue; - hasForceUpdate = false; + deleteRemainingChildren(returnFiber, currentFirstChild); + var created = createFiberFromText(textContent, returnFiber.mode, lanes); + created.return = returnFiber; + return created; + } - { - currentlyProcessingQueue = queue.shared; - } + function reconcileSingleElement( + returnFiber, + currentFirstChild, + element, + lanes + ) { + var key = element.key; + var child = currentFirstChild; - var firstBaseUpdate = queue.firstBaseUpdate; - var lastBaseUpdate = queue.lastBaseUpdate; // Check if there are pending updates. If so, transfer them to the base queue. + 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; - var pendingQueue = queue.shared.pending; + if (elementType === REACT_FRAGMENT_TYPE) { + if (child.tag === Fragment) { + deleteRemainingChildren(returnFiber, child.sibling); + var existing = useFiber(child, element.props.children); + existing.return = returnFiber; - 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. + { + existing._debugSource = element._source; + existing._debugOwner = element._owner; + } - var lastPendingUpdate = pendingQueue; - var firstPendingUpdate = lastPendingUpdate.next; - lastPendingUpdate.next = null; // Append pending updates to base queue + 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; - if (lastBaseUpdate === null) { - firstBaseUpdate = firstPendingUpdate; - } else { - lastBaseUpdate.next = firstPendingUpdate; - } + { + _existing._debugSource = element._source; + _existing._debugOwner = element._owner; + } - 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 + return _existing; + } + } // Didn't match. - var current = workInProgress.alternate; + deleteRemainingChildren(returnFiber, child); + break; + } else { + deleteChild(returnFiber, child); + } - if (current !== null) { - // This is always non-null on a ClassComponent or HostRoot - var currentQueue = current.updateQueue; - var currentLastBaseUpdate = currentQueue.lastBaseUpdate; + child = child.sibling; + } - if (currentLastBaseUpdate !== lastBaseUpdate) { - if (currentLastBaseUpdate === null) { - currentQueue.firstBaseUpdate = firstPendingUpdate; + if (element.type === REACT_FRAGMENT_TYPE) { + var created = createFiberFromFragment( + element.props.children, + returnFiber.mode, + lanes, + element.key + ); + created.return = returnFiber; + return created; } else { - currentLastBaseUpdate.next = firstPendingUpdate; - } + var _created4 = createFiberFromElement(element, returnFiber.mode, lanes); - currentQueue.lastBaseUpdate = lastPendingUpdate; + _created4.ref = coerceRef(returnFiber, currentFirstChild, element); + _created4.return = returnFiber; + return _created4; + } } - } - } // 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 { - var updateLane = update.lane; - var updateEventTime = update.eventTime; + function reconcileSinglePortal( + returnFiber, + currentFirstChild, + portal, + lanes + ) { + var key = portal.key; + var child = currentFirstChild; - if (!isSubsetOfLanes(renderLanes, updateLane)) { - // 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 = { - eventTime: updateEventTime, - lane: updateLane, - tag: update.tag, - payload: update.payload, - callback: update.callback, - next: null - }; + 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); + } - if (newLastBaseUpdate === null) { - newFirstBaseUpdate = newLastBaseUpdate = clone; - newBaseState = newState; - } else { - newLastBaseUpdate = newLastBaseUpdate.next = clone; - } // Update the remaining priority in the queue. + child = child.sibling; + } - newLanes = mergeLanes(newLanes, updateLane); - } else { - // This update does have sufficient priority. - if (newLastBaseUpdate !== null) { - var _clone = { - eventTime: updateEventTime, - // 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, - callback: update.callback, - next: null - }; - newLastBaseUpdate = newLastBaseUpdate.next = _clone; - } // Process this update. + 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. - newState = getStateFromUpdate( - workInProgress, - queue, - update, - newState, - props, - instance - ); - var callback = update.callback; + function reconcileChildFibers( + 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. + 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 + ) + ); - if ( - callback !== null && // If the update was already committed, we should not queue its - // callback again. - update.lane !== NoLane - ) { - workInProgress.flags |= Callback; - var effects = queue.effects; + case REACT_PORTAL_TYPE: + return placeSingleChild( + reconcileSinglePortal( + returnFiber, + currentFirstChild, + newChild, + lanes + ) + ); - if (effects === null) { - queue.effects = [update]; - } else { - effects.push(update); + 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 + ); } - } - } - update = update.next; + if (isArray(newChild)) { + return reconcileChildrenArray( + returnFiber, + currentFirstChild, + newChild, + lanes + ); + } - if (update === null) { - pendingQueue = queue.shared.pending; + if (getIteratorFn(newChild)) { + return reconcileChildrenIterator( + returnFiber, + currentFirstChild, + newChild, + lanes + ); + } - 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. + throwOnInvalidObjectType(returnFiber, newChild); + } - var _firstPendingUpdate = _lastPendingUpdate.next; - _lastPendingUpdate.next = null; - update = _firstPendingUpdate; - queue.lastBaseUpdate = _lastPendingUpdate; - queue.shared.pending = null; + if ( + (typeof newChild === "string" && newChild !== "") || + typeof newChild === "number" + ) { + return placeSingleChild( + reconcileSingleTextNode( + returnFiber, + currentFirstChild, + "" + newChild, + lanes + ) + ); } - } - } while (true); - if (newLastBaseUpdate === null) { - newBaseState = newState; - } + { + if (typeof newChild === "function") { + warnOnFunctionType(returnFiber); + } + } // Remaining cases are all treated as empty. - queue.baseState = newBaseState; - queue.firstBaseUpdate = newFirstBaseUpdate; - queue.lastBaseUpdate = newLastBaseUpdate; // Interleaved updates are stored on a separate queue. We aren't going to - // process them during this render, but we do need to track which lanes - // are remaining. + return deleteRemainingChildren(returnFiber, currentFirstChild); + } - var lastInterleaved = queue.shared.interleaved; + return reconcileChildFibers; + } - if (lastInterleaved !== null) { - var interleaved = lastInterleaved; + var reconcileChildFibers = ChildReconciler(true); + var mountChildFibers = ChildReconciler(false); + function cloneChildFibers(current, workInProgress) { + if (current !== null && workInProgress.child !== current.child) { + throw new Error("Resuming work not yet implemented."); + } - do { - newLanes = mergeLanes(newLanes, interleaved.lane); - interleaved = interleaved.next; - } while (interleaved !== lastInterleaved); - } else 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; - } -} + if (workInProgress.child === null) { + return; + } -function callCallback(callback, context) { - if (typeof callback !== "function") { - throw new Error( - "Invalid argument passed as callback. Expected a function. Instead " + - ("received: " + callback) - ); - } + var currentChild = workInProgress.child; + var newChild = createWorkInProgress(currentChild, currentChild.pendingProps); + workInProgress.child = newChild; + newChild.return = workInProgress; - callback.call(context); -} + while (currentChild.sibling !== null) { + currentChild = currentChild.sibling; + newChild = newChild.sibling = createWorkInProgress( + currentChild, + currentChild.pendingProps + ); + newChild.return = workInProgress; + } -function resetHasForceUpdateBeforeProcessing() { - hasForceUpdate = false; -} -function checkHasForceUpdateAfterProcessing() { - return hasForceUpdate; -} -function commitUpdateQueue(finishedWork, finishedQueue, instance) { - // Commit the effects - var effects = finishedQueue.effects; - finishedQueue.effects = null; + newChild.sibling = null; + } // Reset a workInProgress child set to prepare it for a second pass. - if (effects !== null) { - for (var i = 0; i < effects.length; i++) { - var effect = effects[i]; - var callback = effect.callback; + function resetChildFibers(workInProgress, lanes) { + var child = workInProgress.child; - if (callback !== null) { - effect.callback = null; - callCallback(callback, instance); + while (child !== null) { + resetWorkInProgress(child, lanes); + child = child.sibling; } } - } -} - -var fakeInternalInstance = {}; // React.Component uses a shared frozen object by default. -// We'll use it to determine whether we need to initialize legacy refs. - -var emptyRefsObject = new React.Component().refs; -var didWarnAboutStateAssignmentForComponent; -var didWarnAboutUninitializedState; -var didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate; -var didWarnAboutLegacyLifecyclesAndDerivedState; -var didWarnAboutUndefinedDerivedState; -var warnOnUndefinedDerivedState; -var warnOnInvalidCallback; -var didWarnAboutDirectlyAssigningPropsToState; -var didWarnAboutContextTypeAndContextTypes; -var didWarnAboutInvalidateContextType; - -{ - didWarnAboutStateAssignmentForComponent = new Set(); - didWarnAboutUninitializedState = new Set(); - didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate = new Set(); - didWarnAboutLegacyLifecyclesAndDerivedState = new Set(); - didWarnAboutDirectlyAssigningPropsToState = new Set(); - didWarnAboutUndefinedDerivedState = new Set(); - didWarnAboutContextTypeAndContextTypes = new Set(); - didWarnAboutInvalidateContextType = new Set(); - var didWarnOnInvalidCallback = new Set(); - - warnOnInvalidCallback = function(callback, callerName) { - if (callback === null || typeof callback === "function") { - return; - } - - var key = callerName + "_" + callback; - - if (!didWarnOnInvalidCallback.has(key)) { - didWarnOnInvalidCallback.add(key); - - error( - "%s(...): Expected the last optional `callback` argument to be a " + - "function. Instead received: %s.", - callerName, - callback - ); - } - }; - warnOnUndefinedDerivedState = function(type, partialState) { - if (partialState === undefined) { - var componentName = getComponentNameFromType(type) || "Component"; + var NO_CONTEXT = {}; + var contextStackCursor$1 = createCursor(NO_CONTEXT); + var contextFiberStackCursor = createCursor(NO_CONTEXT); + var rootInstanceStackCursor = createCursor(NO_CONTEXT); - 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 requiredContext(c) { + if (c === NO_CONTEXT) { + throw new Error( + "Expected host context to exist. This error is likely caused by a bug " + + "in React. Please file an issue." ); } + + return c; } - }; // 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)." - ); + function getRootHostContainer() { + var rootInstance = requiredContext(rootInstanceStackCursor.current); + return rootInstance; } - }); - Object.freeze(fakeInternalInstance); -} -function applyDerivedStateFromProps( - workInProgress, - ctor, - getDerivedStateFromProps, - nextProps -) { - var prevState = workInProgress.memoizedState; - var partialState = getDerivedStateFromProps(nextProps, prevState); - - { - 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; - } -} + 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. -var classComponentUpdater = { - isMounted: isMounted, - enqueueSetState: function(inst, payload, callback) { - var fiber = get(inst); - var eventTime = requestEventTime(); - var lane = requestUpdateLane(fiber); - var update = createUpdate(eventTime, lane); - update.payload = payload; + 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 (callback !== undefined && callback !== null) { - { - warnOnInvalidCallback(callback, "setState"); - } + push(contextStackCursor$1, NO_CONTEXT, fiber); + var nextRootContext = getRootHostContext(); // Now that we know this function doesn't throw, replace it. - update.callback = callback; + pop(contextStackCursor$1, fiber); + push(contextStackCursor$1, nextRootContext, fiber); } - var root = enqueueUpdate(fiber, update, lane); - - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, lane, eventTime); - entangleTransitions(root, fiber, lane); + function popHostContainer(fiber) { + pop(contextStackCursor$1, fiber); + pop(contextFiberStackCursor, fiber); + pop(rootInstanceStackCursor, fiber); } - }, - enqueueReplaceState: function(inst, payload, callback) { - var fiber = get(inst); - var eventTime = requestEventTime(); - var lane = requestUpdateLane(fiber); - var update = createUpdate(eventTime, lane); - update.tag = ReplaceState; - update.payload = payload; - - if (callback !== undefined && callback !== null) { - { - warnOnInvalidCallback(callback, "replaceState"); - } - update.callback = callback; + function getHostContext() { + var context = requiredContext(contextStackCursor$1.current); + return context; } - var root = enqueueUpdate(fiber, update, lane); + function pushHostContext(fiber) { + var rootInstance = requiredContext(rootInstanceStackCursor.current); + var context = requiredContext(contextStackCursor$1.current); + var nextContext = getChildHostContext(context, fiber.type); // Don't push this Fiber's context unless it's unique. + + if (context === nextContext) { + return; + } // Track the context and the Fiber that provided it. + // This enables us to pop only Fibers that provide unique contexts. - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, lane, eventTime); - entangleTransitions(root, fiber, lane); + push(contextFiberStackCursor, fiber, fiber); + push(contextStackCursor$1, nextContext, fiber); } - }, - enqueueForceUpdate: function(inst, callback) { - var fiber = get(inst); - var eventTime = requestEventTime(); - var lane = requestUpdateLane(fiber); - var update = createUpdate(eventTime, lane); - update.tag = ForceUpdate; - if (callback !== undefined && callback !== null) { - { - warnOnInvalidCallback(callback, "forceUpdate"); + function popHostContext(fiber) { + // Do not pop unless this Fiber provided the current context. + // pushHostContext() only pushes Fibers that provide unique contexts. + if (contextFiberStackCursor.current !== fiber) { + return; } - update.callback = callback; + pop(contextStackCursor$1, fiber); + pop(contextFiberStackCursor, fiber); } - var root = enqueueUpdate(fiber, update, lane); + var DefaultSuspenseContext = 0; // The Suspense Context is split into two parts. The lower bits is + // inherited deeply down the subtree. The upper bits only affect + // this immediate suspense boundary and gets reset each new + // boundary or suspense list. + + var SubtreeSuspenseContextMask = 1; // Subtree Flags: + // InvisibleParentSuspenseContext indicates that one of our parent Suspense + // boundaries is not currently showing visible main content. + // Either because it is already showing a fallback or is not mounted at all. + // We can use this to determine if it is desirable to trigger a fallback at + // the parent. If not, then we might need to trigger undesirable boundaries + // and/or suspend the commit to avoid hiding the parent content. + + var InvisibleParentSuspenseContext = 1; // Shallow Flags: + // ForceSuspenseFallback can be used by SuspenseList to force newly added + // items into their fallback state during one of the render passes. - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, lane, eventTime); - entangleTransitions(root, fiber, lane); + var ForceSuspenseFallback = 2; + var suspenseStackCursor = createCursor(DefaultSuspenseContext); + function hasSuspenseContext(parentContext, flag) { + return (parentContext & flag) !== 0; + } + function setDefaultShallowSuspenseContext(parentContext) { + return parentContext & SubtreeSuspenseContextMask; + } + function setShallowSuspenseContext(parentContext, shallowContext) { + return (parentContext & SubtreeSuspenseContextMask) | shallowContext; + } + function addSubtreeSuspenseContext(parentContext, subtreeContext) { + return parentContext | subtreeContext; + } + function pushSuspenseContext(fiber, newContext) { + push(suspenseStackCursor, newContext, fiber); + } + function popSuspenseContext(fiber) { + pop(suspenseStackCursor, fiber); } - } -}; -function checkShouldComponentUpdate( - workInProgress, - ctor, - oldProps, - newProps, - oldState, - newState, - nextContext -) { - var instance = workInProgress.stateNode; + function shouldCaptureSuspense(workInProgress, hasInvisibleParent) { + // If it was the primary children that just suspended, capture and render the + // fallback. Otherwise, don't capture and bubble to the next boundary. + var nextState = workInProgress.memoizedState; - if (typeof instance.shouldComponentUpdate === "function") { - var shouldUpdate = instance.shouldComponentUpdate( - newProps, - newState, - nextContext - ); + if (nextState !== null) { + if (nextState.dehydrated !== null) { + // A dehydrated boundary always captures. + return true; + } - { - if (shouldUpdate === undefined) { - error( - "%s.shouldComponentUpdate(): Returned undefined instead of a " + - "boolean value. Make sure to return true or false.", - getComponentNameFromType(ctor) || "Component" - ); + return false; } + + var props = workInProgress.memoizedProps; // Regular boundaries always capture. + + { + return true; + } // If it's a boundary we should avoid, then we prefer to bubble up to the } + function findFirstSuspended(row) { + var node = row; - return shouldUpdate; - } + while (node !== null) { + if (node.tag === SuspenseComponent) { + var state = node.memoizedState; - if (ctor.prototype && ctor.prototype.isPureReactComponent) { - return ( - !shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState) - ); - } + if (state !== null) { + var dehydrated = state.dehydrated; - return true; -} + 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; -function checkClassInstance(workInProgress, ctor, newProps) { - var instance = workInProgress.stateNode; + if (didSuspend) { + return node; + } + } else if (node.child !== null) { + node.child.return = node; + node = node.child; + continue; + } - { - var name = getComponentNameFromType(ctor) || "Component"; - var renderPresent = instance.render; + if (node === row) { + return null; + } - 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 - ); + while (node.sibling === null) { + if (node.return === null || node.return === row) { + return null; + } + + node = node.return; + } + + node.sibling.return = node.return; + node = node.sibling; } - } - 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 - ); + return null; } - 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 - ); - } + var NoFlags$1 = + /* */ + 0; // Represents whether effect should fire. - if (instance.propTypes) { - error( - "propTypes was defined as an instance property on %s. Use a static " + - "property to define propTypes instead.", - name - ); - } + var HasEffect = + /* */ + 1; // Represents the phase in which the effect (not the clean-up) fires. - if (instance.contextType) { - error( - "contextType was defined as an instance property on %s. Use a static " + - "property to define contextType instead.", - name - ); - } + var Insertion = + /* */ + 2; + var Layout = + /* */ + 4; + var Passive$1 = + /* */ + 8; - { - if (instance.contextTypes) { - error( - "contextTypes was defined as an instance property on %s. Use a static " + - "property to define contextTypes instead.", - name - ); - } + // and should be reset before starting a new render. + // This tracks which mutable sources need to be reset after a render. - if ( - ctor.contextType && - ctor.contextTypes && - !didWarnAboutContextTypeAndContextTypes.has(ctor) - ) { - didWarnAboutContextTypeAndContextTypes.add(ctor); + var workInProgressSources = []; + function resetWorkInProgressVersions() { + for (var i = 0; i < workInProgressSources.length; i++) { + var mutableSource = workInProgressSources[i]; - error( - "%s declares both contextTypes and contextType static properties. " + - "The legacy contextTypes property will be ignored.", - name - ); + { + mutableSource._workInProgressVersionSecondary = null; + } } - } - 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 - ); + workInProgressSources.length = 0; } - 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" - ); - } + var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, + ReactCurrentBatchConfig$1 = ReactSharedInternals.ReactCurrentBatchConfig; + var didWarnAboutMismatchedHooksForComponent; + var didWarnUncachedGetSnapshot; - if (typeof instance.componentDidUnmount === "function") { - error( - "%s has a method called " + - "componentDidUnmount(). But there is no such lifecycle method. " + - "Did you mean componentWillUnmount()?", - name - ); + { + didWarnAboutMismatchedHooksForComponent = new Set(); } - 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 - ); - } + // 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. - if (typeof instance.componentWillRecieveProps === "function") { - error( - "%s has a method called " + - "componentWillRecieveProps(). Did you mean componentWillReceiveProps()?", - name - ); - } + 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. - if (typeof instance.UNSAFE_componentWillRecieveProps === "function") { - error( - "%s has a method called " + - "UNSAFE_componentWillRecieveProps(). Did you mean UNSAFE_componentWillReceiveProps()?", - name - ); - } + 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 hasMutatedProps = instance.props !== newProps; + 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`. - 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 - ); - } + var didScheduleRenderPhaseUpdateDuringThisPass = false; // Counts the number of useId hooks in this component. + // hydration). This counter is global, so client ids are not stable across + // render attempts. - 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 globalClientIdCounter = 0; + var RE_RENDER_LIMIT = 25; // In DEV, this is the name of the currently executing primitive hook - if ( - typeof instance.getSnapshotBeforeUpdate === "function" && - typeof instance.componentDidUpdate !== "function" && - !didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate.has(ctor) - ) { - didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate.add(ctor); + 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. - error( - "%s: getSnapshotBeforeUpdate() should be used with componentDidUpdate(). " + - "This component defines getSnapshotBeforeUpdate() only.", - getComponentNameFromType(ctor) - ); - } + 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. - 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 - ); - } + var ignorePreviousDependencies = false; - 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 mountHookTypesDev() { + { + var hookName = currentHookNameInDev; - 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 - ); + if (hookTypesDev === null) { + hookTypesDev = [hookName]; + } else { + hookTypesDev.push(hookName); + } + } } - var _state = instance.state; + function updateHookTypesDev() { + { + var hookName = currentHookNameInDev; - if (_state && (typeof _state !== "object" || isArray(_state))) { - error("%s.state: must be set to an object or null", name); - } + if (hookTypesDev !== null) { + hookTypesUpdateIndexDev++; - if ( - typeof instance.getChildContext === "function" && - typeof ctor.childContextTypes !== "object" - ) { - error( - "%s.getChildContext(): childContextTypes must be defined in order to " + - "use getChildContext().", - name - ); + if (hookTypesDev[hookTypesUpdateIndexDev] !== hookName) { + warnOnHookMismatchInDev(hookName); + } + } + } } - } -} - -function adoptClassInstance(workInProgress, instance) { - instance.updater = classComponentUpdater; - workInProgress.stateNode = instance; // The instance needs access to the fiber so that it can schedule updates - set(instance, workInProgress); - - { - instance._reactInternalInstance = fakeInternalInstance; - } -} - -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(", ") + - "}."; + 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 + ); } - - error( - "%s defines an invalid contextType. " + - "contextType should point to the Context object returned by React.createContext().%s", - getComponentNameFromType(ctor) || "Component", - addendum - ); } } - } - 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; - } - - var instance = new ctor(props, context); // Instantiate twice to help detect side-effects. + function warnOnHookMismatchInDev(currentHookName) { + { + var componentName = getComponentNameFromFiber(currentlyRenderingFiber$1); - var state = (workInProgress.memoizedState = - instance.state !== null && instance.state !== undefined - ? instance.state - : null); - adoptClassInstance(workInProgress, instance); + if (!didWarnAboutMismatchedHooksForComponent.has(componentName)) { + didWarnAboutMismatchedHooksForComponent.add(componentName); - { - if (typeof ctor.getDerivedStateFromProps === "function" && state === null) { - var componentName = getComponentNameFromType(ctor) || "Component"; + if (hookTypesDev !== null) { + var table = ""; + var secondColumnStart = 30; - if (!didWarnAboutUninitializedState.has(componentName)) { - didWarnAboutUninitializedState.add(componentName); + 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 - 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. + while (row.length < secondColumnStart) { + row += " "; + } - if ( - typeof ctor.getDerivedStateFromProps === "function" || - typeof instance.getSnapshotBeforeUpdate === "function" - ) { - var foundWillMountName = null; - var foundWillReceivePropsName = null; - var foundWillUpdateName = null; + row += newHookName + "\n"; + table += row; + } - if ( - typeof instance.componentWillMount === "function" && - instance.componentWillMount.__suppressDeprecationWarning !== true - ) { - foundWillMountName = "componentWillMount"; - } else if (typeof instance.UNSAFE_componentWillMount === "function") { - foundWillMountName = "UNSAFE_componentWillMount"; + 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://react.dev/link/rules-of-hooks\n\n" + + " Previous render Next render\n" + + " ------------------------------------------------------\n" + + "%s" + + " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + componentName, + table + ); + } + } } + } - if ( - typeof instance.componentWillReceiveProps === "function" && - instance.componentWillReceiveProps.__suppressDeprecationWarning !== true - ) { - foundWillReceivePropsName = "componentWillReceiveProps"; - } else if ( - typeof instance.UNSAFE_componentWillReceiveProps === "function" - ) { - foundWillReceivePropsName = "UNSAFE_componentWillReceiveProps"; - } + 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://react.dev/link/invalid-hook-call for tips about how to debug and fix this problem." + ); + } - if ( - typeof instance.componentWillUpdate === "function" && - instance.componentWillUpdate.__suppressDeprecationWarning !== true - ) { - foundWillUpdateName = "componentWillUpdate"; - } else if (typeof instance.UNSAFE_componentWillUpdate === "function") { - foundWillUpdateName = "UNSAFE_componentWillUpdate"; + function areHookInputsEqual(nextDeps, prevDeps) { + { + if (ignorePreviousDependencies) { + // Only true when this component is being hot reloaded. + return false; + } } - if ( - foundWillMountName !== null || - foundWillReceivePropsName !== null || - foundWillUpdateName !== null - ) { - var _componentName = getComponentNameFromType(ctor) || "Component"; - - var newApiName = - typeof ctor.getDerivedStateFromProps === "function" - ? "getDerivedStateFromProps()" - : "getSnapshotBeforeUpdate()"; + 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 + ); + } - if (!didWarnAboutLegacyLifecyclesAndDerivedState.has(_componentName)) { - didWarnAboutLegacyLifecyclesAndDerivedState.add(_componentName); + return false; + } + { + // Don't bother comparing lengths in prod because these arrays should be + // passed inline. + if (nextDeps.length !== prevDeps.length) { 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://react.dev/link/unsafe-component-lifecycles", - _componentName, - newApiName, - foundWillMountName !== null ? "\n " + foundWillMountName : "", - foundWillReceivePropsName !== null - ? "\n " + foundWillReceivePropsName - : "", - foundWillUpdateName !== null ? "\n " + foundWillUpdateName : "" + "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(", ") + "]" ); } } + + for (var i = 0; i < prevDeps.length && i < nextDeps.length; i++) { + if (objectIs(nextDeps[i], prevDeps[i])) { + continue; + } + + return false; + } + + return true; } - } // 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); - } + 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: - return instance; -} + ignorePreviousDependencies = + current !== null && current.type !== workInProgress.type; + } -function callComponentWillMount(workInProgress, instance) { - var oldState = instance.state; + workInProgress.memoizedState = null; + workInProgress.updateQueue = null; + workInProgress.lanes = NoLanes; // The following should have already been reset + // currentHook = null; + // workInProgressHook = null; + // didScheduleRenderPhaseUpdate = false; + // localIdCounter = 0; + // 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 (typeof instance.componentWillMount === "function") { - instance.componentWillMount(); - } + { + 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; + } + } - if (typeof instance.UNSAFE_componentWillMount === "function") { - instance.UNSAFE_componentWillMount(); - } + var children = Component(props, secondArg); // Check if there was a render phase update - 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" - ); - } + if (didScheduleRenderPhaseUpdateDuringThisPass) { + // Keep rendering in a loop for as long as render phase updates continue to + // be scheduled. Use a counter to prevent infinite loops. + var numberOfReRenders = 0; - classComponentUpdater.enqueueReplaceState(instance, instance.state, null); - } -} + do { + didScheduleRenderPhaseUpdateDuringThisPass = false; -function callComponentWillReceiveProps( - workInProgress, - instance, - newProps, - nextContext -) { - var oldState = instance.state; + if (numberOfReRenders >= RE_RENDER_LIMIT) { + throw new Error( + "Too many re-renders. React limits the number of renders to prevent " + + "an infinite loop." + ); + } - if (typeof instance.componentWillReceiveProps === "function") { - instance.componentWillReceiveProps(newProps, nextContext); - } + numberOfReRenders += 1; - if (typeof instance.UNSAFE_componentWillReceiveProps === "function") { - instance.UNSAFE_componentWillReceiveProps(newProps, nextContext); - } + { + // 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 - if (instance.state !== oldState) { - { - var componentName = - getComponentNameFromFiber(workInProgress) || "Component"; + currentHook = null; + workInProgressHook = null; + workInProgress.updateQueue = null; - if (!didWarnAboutStateAssignmentForComponent.has(componentName)) { - didWarnAboutStateAssignmentForComponent.add(componentName); + { + // Also validate hook order for cascading updates. + hookTypesUpdateIndexDev = -1; + } - error( - "%s.componentWillReceiveProps(): Assigning directly to " + - "this.state is deprecated (except inside a component's " + - "constructor). Use setState instead.", - componentName - ); - } - } + ReactCurrentDispatcher$1.current = HooksDispatcherOnRerenderInDEV; + children = Component(props, secondArg); + } while (didScheduleRenderPhaseUpdateDuringThisPass); + } // 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. - classComponentUpdater.enqueueReplaceState(instance, instance.state, null); - } -} // Invokes the mount life-cycles on a previously never rendered instance. + ReactCurrentDispatcher$1.current = ContextOnlyDispatcher; -function mountClassInstance(workInProgress, ctor, newProps, renderLanes) { - { - checkClassInstance(workInProgress, ctor, newProps); - } + { + workInProgress._debugHookTypes = hookTypesDev; + } // 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 instance = workInProgress.stateNode; - instance.props = newProps; - instance.state = workInProgress.memoizedState; - instance.refs = emptyRefsObject; - initializeUpdateQueue(workInProgress); - var contextType = ctor.contextType; + var didRenderTooFewHooks = currentHook !== null && currentHook.next !== null; + renderLanes = NoLanes; + currentlyRenderingFiber$1 = null; + currentHook = null; + workInProgressHook = null; - if (typeof contextType === "object" && contextType !== null) { - instance.context = readContext(contextType); - } else { - var unmaskedContext = getUnmaskedContext(workInProgress, ctor, true); - instance.context = getMaskedContext(workInProgress, unmaskedContext); - } + { + 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 (instance.state === newProps) { - var componentName = getComponentNameFromType(ctor) || "Component"; + 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." + ); + } + } - if (!didWarnAboutDirectlyAssigningPropsToState.has(componentName)) { - didWarnAboutDirectlyAssigningPropsToState.add(componentName); + didScheduleRenderPhaseUpdate = false; // This is reset by checkDidRenderIdHook + // localIdCounter = 0; - 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 (didRenderTooFewHooks) { + throw new Error( + "Rendered fewer hooks than expected. This may be caused by an accidental " + + "early return statement." ); } - } - - if (workInProgress.mode & StrictLegacyMode) { - ReactStrictModeWarnings.recordLegacyContextWarning( - workInProgress, - instance - ); - } - { - ReactStrictModeWarnings.recordUnsafeLifecycleWarnings( - workInProgress, - instance - ); + 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). - 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. - - 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") { - var fiberFlags = Update; - - workInProgress.flags |= fiberFlags; - } -} + { + workInProgress.flags &= ~(Passive | Update); + } -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 - ); + current.lanes = removeLanes(current.lanes, lanes); } - } - - 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") { - var fiberFlags = Update; + function resetHooksAfterThrow() { + // 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; - workInProgress.flags |= fiberFlags; - } + 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 = currentlyRenderingFiber$1.memoizedState; - return false; - } + while (hook !== null) { + var queue = hook.queue; - if (typeof getDerivedStateFromProps === "function") { - applyDerivedStateFromProps( - workInProgress, - ctor, - getDerivedStateFromProps, - newProps - ); - newState = workInProgress.memoizedState; - } + if (queue !== null) { + queue.pending = null; + } - var shouldUpdate = - checkHasForceUpdateAfterProcessing() || - checkShouldComponentUpdate( - workInProgress, - ctor, - oldProps, - newProps, - oldState, - newState, - nextContext - ); + hook = hook.next; + } - 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(); + didScheduleRenderPhaseUpdate = false; } - if (typeof instance.UNSAFE_componentWillMount === "function") { - instance.UNSAFE_componentWillMount(); - } - } + renderLanes = NoLanes; + currentlyRenderingFiber$1 = null; + currentHook = null; + workInProgressHook = null; - if (typeof instance.componentDidMount === "function") { - var _fiberFlags = Update; - - workInProgress.flags |= _fiberFlags; - } - } 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") { - var _fiberFlags2 = Update; - - workInProgress.flags |= _fiberFlags2; - } // 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( - 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 - ) { - // 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; + { + hookTypesDev = null; + hookTypesUpdateIndexDev = -1; + currentHookNameInDev = null; + isUpdatingOpaqueValueInRenderPhase = false; } - } - if (typeof instance.getSnapshotBeforeUpdate === "function") { - if ( - unresolvedOldProps !== current.memoizedProps || - oldState !== current.memoizedState - ) { - workInProgress.flags |= Snapshot; - } + didScheduleRenderPhaseUpdateDuringThisPass = false; } - return false; - } - - if (typeof getDerivedStateFromProps === "function") { - applyDerivedStateFromProps( - workInProgress, - ctor, - getDerivedStateFromProps, - newProps - ); - newState = workInProgress.memoizedState; - } + function mountWorkInProgressHook() { + var hook = { + memoizedState: null, + baseState: null, + baseQueue: null, + queue: null, + next: null + }; - 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; - - 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 (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; } - if (typeof instance.UNSAFE_componentWillUpdate === "function") { - instance.UNSAFE_componentWillUpdate(newProps, newState, nextContext); - } + return workInProgressHook; } - if (typeof instance.componentDidUpdate === "function") { - workInProgress.flags |= Update; - } + 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. When we reach the end of the base list, we must switch to + // the dispatcher used for mounts. + var nextCurrentHook; - 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 (currentHook === null) { + var current = currentlyRenderingFiber$1.alternate; - if (typeof instance.getSnapshotBeforeUpdate === "function") { - if ( - unresolvedOldProps !== current.memoizedProps || - oldState !== current.memoizedState - ) { - workInProgress.flags |= Snapshot; + if (current !== null) { + nextCurrentHook = current.memoizedState; + } else { + nextCurrentHook = null; + } + } else { + nextCurrentHook = currentHook.next; } - } // 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; -} -var didWarnAboutMaps; -var didWarnAboutGenerators; -var didWarnAboutStringRefs; -var ownerHasKeyUseWarning; -var ownerHasFunctionTypeWarning; + var nextWorkInProgressHook; -var warnForMissingKey = function(child, returnFiber) {}; + if (workInProgressHook === null) { + nextWorkInProgressHook = currentlyRenderingFiber$1.memoizedState; + } else { + nextWorkInProgressHook = workInProgressHook.next; + } -{ - 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. - */ + 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) { + throw new Error("Rendered more hooks than during the previous render."); + } - ownerHasKeyUseWarning = {}; - ownerHasFunctionTypeWarning = {}; + currentHook = nextCurrentHook; + var newHook = { + memoizedState: currentHook.memoizedState, + baseState: currentHook.baseState, + baseQueue: currentHook.baseQueue, + queue: currentHook.queue, + next: null + }; - warnForMissingKey = function(child, returnFiber) { - if (child === null || typeof child !== "object") { - return; - } + 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; + } + } - if (!child._store || child._store.validated || child.key != null) { - return; + return workInProgressHook; } - 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." - ); + function createFunctionComponentUpdateQueue() { + return { + lastEffect: null, + stores: null + }; } - child._store.validated = true; - var componentName = getComponentNameFromFiber(returnFiber) || "Component"; - - if (ownerHasKeyUseWarning[componentName]) { - return; + function basicStateReducer(state, action) { + // $FlowFixMe: Flow doesn't like mixed types + return typeof action === "function" ? action(state) : action; } - ownerHasKeyUseWarning[componentName] = true; - - error( - "Each child in a list should have a unique " + - '"key" prop. See https://react.dev/link/warning-keys for ' + - "more information." - ); - }; -} - -function coerceRef(returnFiber, current, element) { - var mixedRef = element.ref; - - if ( - mixedRef !== null && - typeof mixedRef !== "function" && - typeof mixedRef !== "object" - ) { - { - // TODO: Clean this up once we turn on the string ref warning for - // everyone, because the strict mode case will no longer be relevant - if ( - (returnFiber.mode & StrictLegacyMode || warnAboutStringRefs) && // 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 - ) - ) { - var componentName = - getComponentNameFromFiber(returnFiber) || "Component"; - - if (!didWarnAboutStringRefs[componentName]) { - { - error( - 'A string ref, "%s", has been found within a strict mode tree. ' + - "String refs are a source of potential bugs and should be avoided. " + - "We recommend using useRef() or createRef() instead. " + - "Learn more about using refs safely here: " + - "https://react.dev/link/strict-mode-string-ref", - mixedRef - ); - } + function mountReducer(reducer, initialArg, init) { + var hook = mountWorkInProgressHook(); + var initialState; - didWarnAboutStringRefs[componentName] = true; - } + if (init !== undefined) { + initialState = init(initialArg); + } else { + initialState = initialArg; } - } - 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://react.dev/link/strict-mode-string-ref" - ); - } + hook.memoizedState = hook.baseState = initialState; + var queue = { + pending: null, + interleaved: 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]; + } - inst = ownerFiber.stateNode; - } + function updateReducer(reducer, initialArg, init) { + var hook = updateWorkInProgressHook(); + var queue = hook.queue; - if (!inst) { + if (queue === null) { throw new Error( - "Missing owner for string ref " + - mixedRef + - ". This error is likely caused by a " + - "bug in React. Please file an issue." + "Should have a queue. This is likely 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 + queue.lastRenderedReducer = reducer; + var current = currentHook; // The last rebase update that is NOT part of the base state. - if ( - current !== null && - current.ref !== null && - typeof current.ref === "function" && - current.ref._stringRef === stringRef - ) { - return current.ref; - } + var baseQueue = current.baseQueue; // The last pending update that hasn't been processed yet. - var ref = function(value) { - var refs = resolvedInst.refs; + var pendingQueue = queue.pending; - if (refs === emptyRefsObject) { - // This is a lazy pooled frozen object, so we need to initialize. - refs = resolvedInst.refs = {}; + 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 (value === null) { - delete refs[stringRef]; - } else { - refs[stringRef] = value; + { + 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." + ); + } } - }; - - 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://react.dev/link/refs-must-have-owner for more information." - ); + current.baseQueue = baseQueue = pendingQueue; + queue.pending = null; } - } - } - return mixedRef; -} + if (baseQueue !== null) { + // We have a queue to process. + var first = baseQueue.next; + var newState = current.baseState; + var newBaseState = null; + var newBaseQueueFirst = null; + var newBaseQueueLast = null; + var update = first; -function throwOnInvalidObjectType(returnFiber, newChild) { - 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." - ); -} + do { + var updateLane = update.lane; + + if (!isSubsetOfLanes(renderLanes, updateLane)) { + // 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, + 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. + 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, + action: update.action, + hasEagerState: update.hasEagerState, + eagerState: update.eagerState, + next: null + }; + newBaseQueueLast = newBaseQueueLast.next = _clone; + } // Process this update. + + 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 { + var action = update.action; + newState = reducer(newState, action); + } + } -function warnOnFunctionType(returnFiber) { - { - var componentName = getComponentNameFromFiber(returnFiber) || "Component"; + update = update.next; + } while (update !== null && update !== first); - if (ownerHasFunctionTypeWarning[componentName]) { - return; - } + 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. - ownerHasFunctionTypeWarning[componentName] = true; + if (!objectIs(newState, hook.memoizedState)) { + markWorkInProgressReceivedUpdate(); + } - 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." - ); - } -} + hook.memoizedState = newState; + hook.baseState = newBaseState; + hook.baseQueue = newBaseQueueLast; + queue.lastRenderedState = newState; + } // Interleaved updates are stored on a separate queue. We aren't going to + // process them during this render, but we do need to track which lanes + // are remaining. -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 lastInterleaved = queue.interleaved; -function ChildReconciler(shouldTrackSideEffects) { - function deleteChild(returnFiber, childToDelete) { - if (!shouldTrackSideEffects) { - // Noop. - return; - } + if (lastInterleaved !== null) { + var interleaved = lastInterleaved; - var deletions = returnFiber.deletions; + do { + var interleavedLane = interleaved.lane; + currentlyRenderingFiber$1.lanes = mergeLanes( + currentlyRenderingFiber$1.lanes, + interleavedLane + ); + markSkippedUpdateLanes(interleavedLane); + interleaved = interleaved.next; + } while (interleaved !== lastInterleaved); + } else 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 (deletions === null) { - returnFiber.deletions = [childToDelete]; - returnFiber.flags |= ChildDeletion; - } else { - deletions.push(childToDelete); + var dispatch = queue.dispatch; + return [hook.memoizedState, dispatch]; } - } - 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. + function rerenderReducer(reducer, initialArg, init) { + var hook = updateWorkInProgressHook(); + var queue = hook.queue; - var childToDelete = currentFirstChild; + if (queue === null) { + throw new Error( + "Should have a queue. This is likely a bug in React. Please file an issue." + ); + } - while (childToDelete !== null) { - deleteChild(returnFiber, childToDelete); - childToDelete = childToDelete.sibling; - } + queue.lastRenderedReducer = reducer; // This is a re-render. Apply the new render phase updates to the previous + // work-in-progress hook. - return null; - } + var dispatch = queue.dispatch; + var lastRenderPhaseUpdate = queue.pending; + var newState = hook.memoizedState; - 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 (lastRenderPhaseUpdate !== null) { + // The queue doesn't persist past this render pass. + queue.pending = null; + var firstRenderPhaseUpdate = lastRenderPhaseUpdate.next; + var update = firstRenderPhaseUpdate; - while (existingChild !== null) { - if (existingChild.key !== null) { - existingChildren.set(existingChild.key, existingChild); - } else { - existingChildren.set(existingChild.index, existingChild); - } + 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. - existingChild = existingChild.sibling; - } + if (!objectIs(newState, hook.memoizedState)) { + markWorkInProgressReceivedUpdate(); + } - return existingChildren; - } + 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. - 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; - } + if (hook.baseQueue === null) { + hook.baseState = newState; + } - function placeChild(newFiber, lastPlacedIndex, newIndex) { - newFiber.index = newIndex; + queue.lastRenderedState = newState; + } - 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 [newState, dispatch]; } - var current = newFiber.alternate; - - if (current !== null) { - var oldIndex = current.index; - - if (oldIndex < lastPlacedIndex) { - // This is a move. - newFiber.flags |= Placement; - return lastPlacedIndex; - } else { - // This item can stay in place. - return oldIndex; + function mountMutableSource(source, getSnapshot, subscribe) { + { + return undefined; } - } else { - // This is an insertion. - newFiber.flags |= Placement; - 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; + function updateMutableSource(source, getSnapshot, subscribe) { + { + return undefined; + } } - 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 mountSyncExternalStore(subscribe, getSnapshot, getServerSnapshot) { + var fiber = currentlyRenderingFiber$1; + var hook = mountWorkInProgressHook(); + var nextSnapshot; - function updateElement(returnFiber, current, element, lanes) { - var elementType = element.type; + { + nextSnapshot = getSnapshot(); - if (elementType === REACT_FRAGMENT_TYPE) { - return updateFragment( - returnFiber, - current, - element.props.children, - lanes, - element.key - ); - } + { + if (!didWarnUncachedGetSnapshot) { + var cachedSnapshot = getSnapshot(); - 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; + if (!objectIs(nextSnapshot, cachedSnapshot)) { + error( + "The result of getSnapshot should be cached to avoid an infinite loop" + ); - { - existing._debugSource = element._source; - existing._debugOwner = element._owner; - } + 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. - return existing; - } - } // Insert + var root = getWorkInProgressRoot(); - var created = createFiberFromElement(element, returnFiber.mode, lanes); - created.ref = coerceRef(returnFiber, current, element); - created.return = returnFiber; - return created; - } + if (root === null) { + throw new Error( + "Expected a work-in-progress root. This is a bug in React. Please file an issue." + ); + } - 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 + if (!includesBlockingLane(root, renderLanes)) { + 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. + // TODO: We can move this to the passive phase once we add a pre-commit + // consistency check. See the next comment. + + fiber.flags |= Passive; + pushEffect( + HasEffect | Passive$1, + updateStoreInstance.bind(null, fiber, inst, nextSnapshot, getSnapshot), + undefined, + null ); - created.return = returnFiber; - return created; - } else { - // Update - var existing = useFiber(current, fragment); - existing.return = returnFiber; - return existing; + return nextSnapshot; } - } - 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 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. - _created.ref = coerceRef(returnFiber, null, newChild); - _created.return = returnFiber; - return _created; - } + var nextSnapshot = getSnapshot(); - case REACT_PORTAL_TYPE: { - var _created2 = createFiberFromPortal( - newChild, - returnFiber.mode, - lanes - ); + { + if (!didWarnUncachedGetSnapshot) { + var cachedSnapshot = getSnapshot(); - _created2.return = returnFiber; - return _created2; - } + if (!objectIs(nextSnapshot, cachedSnapshot)) { + error( + "The result of getSnapshot should be cached to avoid an infinite loop" + ); - case REACT_LAZY_TYPE: { - var payload = newChild._payload; - var init = newChild._init; - return createChild(returnFiber, init(payload), lanes); + didWarnUncachedGetSnapshot = true; + } } } - if (isArray(newChild) || getIteratorFn(newChild)) { - var _created3 = createFiberFromFragment( - newChild, - returnFiber.mode, - lanes, - null - ); - - _created3.return = returnFiber; - return _created3; - } - - throwOnInvalidObjectType(returnFiber, newChild); - } + var prevSnapshot = hook.memoizedState; + var snapshotChanged = !objectIs(prevSnapshot, nextSnapshot); - { - if (typeof newChild === "function") { - warnOnFunctionType(returnFiber); + if (snapshotChanged) { + hook.memoizedState = nextSnapshot; + markWorkInProgressReceivedUpdate(); } - } - - 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; + 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 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 ( + inst.getSnapshot !== getSnapshot || + snapshotChanged || // Check if the susbcribe 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; + pushEffect( + HasEffect | Passive$1, + updateStoreInstance.bind(null, fiber, inst, nextSnapshot, getSnapshot), + undefined, + 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 newChild === "object" && newChild !== null) { - switch (newChild.$$typeof) { - case REACT_ELEMENT_TYPE: { - if (newChild.key === key) { - return updateElement(returnFiber, oldFiber, newChild, lanes); - } else { - return null; - } - } + var root = getWorkInProgressRoot(); - case REACT_PORTAL_TYPE: { - if (newChild.key === key) { - return updatePortal(returnFiber, oldFiber, newChild, lanes); - } else { - return null; - } + if (root === null) { + throw new Error( + "Expected a work-in-progress root. This is a bug in React. Please file an issue." + ); } - case REACT_LAZY_TYPE: { - var payload = newChild._payload; - var init = newChild._init; - return updateSlot(returnFiber, oldFiber, init(payload), lanes); + if (!includesBlockingLane(root, renderLanes)) { + pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot); } } - if (isArray(newChild) || getIteratorFn(newChild)) { - if (key !== null) { - return null; - } + return nextSnapshot; + } - return updateFragment(returnFiber, oldFiber, newChild, lanes, null); - } + function pushStoreConsistencyCheck(fiber, getSnapshot, renderedSnapshot) { + fiber.flags |= StoreConsistency; + var check = { + getSnapshot: getSnapshot, + value: renderedSnapshot + }; + var componentUpdateQueue = currentlyRenderingFiber$1.updateQueue; - throwOnInvalidObjectType(returnFiber, newChild); - } + if (componentUpdateQueue === null) { + componentUpdateQueue = createFunctionComponentUpdateQueue(); + currentlyRenderingFiber$1.updateQueue = componentUpdateQueue; + componentUpdateQueue.stores = [check]; + } else { + var stores = componentUpdateQueue.stores; - { - if (typeof newChild === "function") { - warnOnFunctionType(returnFiber); + if (stores === null) { + componentUpdateQueue.stores = [check]; + } else { + stores.push(check); + } } } - return null; - } + 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. - 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 (checkIfSnapshotChanged(inst)) { + // Force a re-render. + forceStoreRerender(fiber); + } } - 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); + 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. - 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 - ); - } + return subscribe(handleStoreChange); + } - if (isArray(newChild) || getIteratorFn(newChild)) { - var _matchedFiber3 = existingChildren.get(newIdx) || null; + function checkIfSnapshotChanged(inst) { + var latestGetSnapshot = inst.getSnapshot; + var prevValue = inst.value; - return updateFragment( - returnFiber, - _matchedFiber3, - newChild, - lanes, - null - ); + try { + var nextValue = latestGetSnapshot(); + return !objectIs(prevValue, nextValue); + } catch (error) { + return true; } - - throwOnInvalidObjectType(returnFiber, newChild); } - { - if (typeof newChild === "function") { - warnOnFunctionType(returnFiber); + function forceStoreRerender(fiber) { + var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); } } - return null; - } - /** - * Warns if there is a duplicate or missing key - */ + function mountState(initialState) { + var hook = mountWorkInProgressHook(); - function warnOnInvalidKey(child, knownKeys, returnFiber) { - { - if (typeof child !== "object" || child === null) { - return knownKeys; + if (typeof initialState === "function") { + // $FlowFixMe: Flow doesn't like mixed types + initialState = initialState(); } - switch (child.$$typeof) { - case REACT_ELEMENT_TYPE: - case REACT_PORTAL_TYPE: - warnForMissingKey(child, returnFiber); - var key = child.key; - - if (typeof key !== "string") { - break; - } + hook.memoizedState = hook.baseState = initialState; + var queue = { + pending: null, + interleaved: null, + lanes: NoLanes, + dispatch: null, + lastRenderedReducer: basicStateReducer, + lastRenderedState: initialState + }; + hook.queue = queue; + var dispatch = (queue.dispatch = dispatchSetState.bind( + null, + currentlyRenderingFiber$1, + queue + )); + return [hook.memoizedState, dispatch]; + } - if (knownKeys === null) { - knownKeys = new Set(); - knownKeys.add(key); - break; - } + function updateState(initialState) { + return updateReducer(basicStateReducer); + } - if (!knownKeys.has(key)) { - knownKeys.add(key); - break; - } + function rerenderState(initialState) { + return rerenderReducer(basicStateReducer); + } - 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 - ); + function pushEffect(tag, create, destroy, deps) { + var effect = { + tag: tag, + create: create, + destroy: destroy, + deps: deps, + // Circular + next: null + }; + var componentUpdateQueue = currentlyRenderingFiber$1.updateQueue; - break; + if (componentUpdateQueue === null) { + componentUpdateQueue = createFunctionComponentUpdateQueue(); + currentlyRenderingFiber$1.updateQueue = componentUpdateQueue; + componentUpdateQueue.lastEffect = effect.next = effect; + } else { + var lastEffect = componentUpdateQueue.lastEffect; - case REACT_LAZY_TYPE: - var payload = child._payload; - var init = child._init; - warnOnInvalidKey(init(payload), knownKeys, returnFiber); - break; + if (lastEffect === null) { + componentUpdateQueue.lastEffect = effect.next = effect; + } else { + var firstEffect = lastEffect.next; + lastEffect.next = effect; + effect.next = firstEffect; + componentUpdateQueue.lastEffect = effect; + } } + + return effect; } - 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; + function mountRef(initialValue) { + var hook = mountWorkInProgressHook(); - for (var i = 0; i < newChildren.length; i++) { - var child = newChildren[i]; - knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); + { + var _ref2 = { + current: initialValue + }; + hook.memoizedState = _ref2; + return _ref2; } } - 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 updateRef(initialValue) { + var hook = updateWorkInProgressHook(); + return hook.memoizedState; + } - var newFiber = updateSlot( - returnFiber, - oldFiber, - newChildren[newIdx], - lanes + 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, + undefined, + nextDeps ); + } - 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 updateEffectImpl(fiberFlags, hookFlags, create, deps) { + var hook = updateWorkInProgressHook(); + var nextDeps = deps === undefined ? null : deps; + var destroy = undefined; - break; - } + if (currentHook !== null) { + var prevEffect = currentHook.memoizedState; + destroy = prevEffect.destroy; + + if (nextDeps !== null) { + var prevDeps = prevEffect.deps; - 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 (areHookInputsEqual(nextDeps, prevDeps)) { + hook.memoizedState = pushEffect(hookFlags, create, destroy, nextDeps); + return; + } } } - lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx); + currentlyRenderingFiber$1.flags |= fiberFlags; + hook.memoizedState = pushEffect( + HasEffect | hookFlags, + create, + destroy, + nextDeps + ); + } - 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; + function mountEffect(create, deps) { + { + return mountEffectImpl(Passive | PassiveStatic, Passive$1, create, deps); } - - 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; + function updateEffect(create, deps) { + return updateEffectImpl(Passive, Passive$1, create, deps); } - 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); + function mountInsertionEffect(create, deps) { + return mountEffectImpl(Update, Insertion, create, deps); + } - if (_newFiber === null) { - continue; - } + function updateInsertionEffect(create, deps) { + return updateEffectImpl(Update, Insertion, create, deps); + } - lastPlacedIndex = placeChild(_newFiber, lastPlacedIndex, newIdx); + function mountLayoutEffect(create, deps) { + var fiberFlags = Update; - if (previousNewFiber === null) { - // TODO: Move out of the loop. This only happens for the first run. - resultingFirstChild = _newFiber; - } else { - previousNewFiber.sibling = _newFiber; - } + return mountEffectImpl(fiberFlags, Layout, create, deps); + } - previousNewFiber = _newFiber; - } + function updateLayoutEffect(create, deps) { + return updateEffectImpl(Update, Layout, create, deps); + } - return resultingFirstChild; - } // Add all children to a key map for quick lookups. + function imperativeHandleEffect(create, ref) { + if (typeof ref === "function") { + var refCallback = ref; - var existingChildren = mapRemainingChildren(returnFiber, oldFiber); // Keep scanning and use the map to restore deleted items as moves. + var _inst = create(); - for (; newIdx < newChildren.length; newIdx++) { - var _newFiber2 = updateFromMap( - existingChildren, - returnFiber, - newIdx, - newChildren[newIdx], - lanes - ); + refCallback(_inst); + return function () { + refCallback(null); + }; + } else if (ref !== null && ref !== undefined) { + var refObject = ref; - 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 + { + 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(", ") + "}" ); } } - lastPlacedIndex = placeChild(_newFiber2, lastPlacedIndex, newIdx); - - if (previousNewFiber === null) { - resultingFirstChild = _newFiber2; - } else { - previousNewFiber.sibling = _newFiber2; - } + var _inst2 = create(); - previousNewFiber = _newFiber2; + refObject.current = _inst2; + return function () { + refObject.current = null; + }; } } - 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 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? - function reconcileChildrenIterator( - returnFiber, - currentFirstChild, - newChildrenIterable, - lanes - ) { - // This is the same implementation as reconcileChildrenArray(), - // but using the iterator instead. - var iteratorFn = getIteratorFn(newChildrenIterable); + var effectDeps = + deps !== null && deps !== undefined ? deps.concat([ref]) : null; + var fiberFlags = Update; - 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." + return mountEffectImpl( + fiberFlags, + Layout, + imperativeHandleEffect.bind(null, create, ref), + effectDeps ); } - { - // We don't support rendering Generators because it's a mutation. - // See https://github.com/facebook/react/issues/12995 - if ( - typeof Symbol === "function" && // $FlowFixMe Flow doesn't know about toStringTag - newChildrenIterable[Symbol.toStringTag] === "Generator" - ) { - if (!didWarnAboutGenerators) { + function updateImperativeHandle(ref, create, deps) { + { + if (typeof create !== "function") { 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." + "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; + return updateEffectImpl( + Update, + Layout, + imperativeHandleEffect.bind(null, create, ref), + effectDeps + ); + } - didWarnAboutGenerators = true; - } // Warn about using Maps as children + 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 (newChildrenIterable.entries === iteratorFn) { - if (!didWarnAboutMaps) { - error( - "Using Maps as children is not supported. " + - "Use an array of keyed ReactElements instead." - ); + 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 (prevState !== null) { + if (nextDeps !== null) { + var prevDeps = prevState[1]; + + if (areHookInputsEqual(nextDeps, prevDeps)) { + return prevState[0]; + } } + } - didWarnAboutMaps = true; - } // First, validate keys. - // We'll get a different iterator later for the main pass. + hook.memoizedState = [callback, nextDeps]; + return callback; + } - var _newChildren = iteratorFn.call(newChildrenIterable); + function mountMemo(nextCreate, deps) { + var hook = mountWorkInProgressHook(); + var nextDeps = deps === undefined ? null : deps; + var nextValue = nextCreate(); + hook.memoizedState = [nextValue, nextDeps]; + return nextValue; + } - if (_newChildren) { - var knownKeys = null; + function updateMemo(nextCreate, deps) { + var hook = updateWorkInProgressHook(); + var nextDeps = deps === undefined ? null : deps; + var prevState = hook.memoizedState; - var _step = _newChildren.next(); + if (prevState !== null) { + // Assume these are defined. If they're not, areHookInputsEqual will warn. + if (nextDeps !== null) { + var prevDeps = prevState[1]; - for (; !_step.done; _step = _newChildren.next()) { - var child = _step.value; - knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); + if (areHookInputsEqual(nextDeps, prevDeps)) { + return prevState[0]; + } } } + + var nextValue = nextCreate(); + hook.memoizedState = [nextValue, nextDeps]; + return nextValue; } - var newChildren = iteratorFn.call(newChildrenIterable); + function mountDeferredValue(value) { + var hook = mountWorkInProgressHook(); + hook.memoizedState = value; + return value; + } - if (newChildren == null) { - throw new Error("An iterable object provided no iterator."); + function updateDeferredValue(value) { + var hook = updateWorkInProgressHook(); + var resolvedCurrentHook = currentHook; + var prevValue = resolvedCurrentHook.memoizedState; + return updateDeferredValueImpl(hook, prevValue, value); } - var resultingFirstChild = null; - var previousNewFiber = null; - var oldFiber = currentFirstChild; - var lastPlacedIndex = 0; - var newIdx = 0; - var nextOldFiber = null; - var step = newChildren.next(); + function rerenderDeferredValue(value) { + var hook = updateWorkInProgressHook(); - for ( - ; - oldFiber !== null && !step.done; - newIdx++, step = newChildren.next() - ) { - if (oldFiber.index > newIdx) { - nextOldFiber = oldFiber; - oldFiber = null; + if (currentHook === null) { + // This is a rerender during a mount. + hook.memoizedState = value; + return value; } else { - nextOldFiber = oldFiber.sibling; + // This is a rerender during an update. + var prevValue = currentHook.memoizedState; + return updateDeferredValueImpl(hook, prevValue, value); } + } - var newFiber = updateSlot(returnFiber, oldFiber, step.value, lanes); + function updateDeferredValueImpl(hook, prevValue, value) { + var shouldDeferValue = !includesOnlyNonUrgentLanes(renderLanes); - 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 (shouldDeferValue) { + // This is an urgent update. If the value has changed, keep using the + // previous value and spawn a deferred render to update it later. + if (!objectIs(value, prevValue)) { + // Schedule a deferred render + var deferredLane = claimNextTransitionLane(); + currentlyRenderingFiber$1.lanes = mergeLanes( + currentlyRenderingFiber$1.lanes, + deferredLane + ); + markSkippedUpdateLanes(deferredLane); // Set this to true to indicate that the rendered value is inconsistent + // from the latest value. The name "baseState" doesn't really match how we + // use it because we're reusing a state hook field instead of creating a + // new one. - break; - } + hook.baseState = true; + } // Reuse the previous 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 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. + // However, if we're currently inside a spawned render, then we need to mark + // this as an update to prevent the fiber from bailing out. + // + // `baseState` is true when the current value is different from the rendered + // value. The name doesn't really match how we use it because we're reusing + // a state hook field instead of creating a new one. + if (hook.baseState) { + // Flip this back to false. + hook.baseState = false; + markWorkInProgressReceivedUpdate(); } + + hook.memoizedState = value; + return value; } + } - lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx); + function startTransition(setPending, callback, options) { + var previousPriority = getCurrentUpdatePriority(); + setCurrentUpdatePriority( + higherEventPriority(previousPriority, ContinuousEventPriority) + ); + setPending(true); + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = {}; + var currentTransition = ReactCurrentBatchConfig$1.transition; - 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; + { + ReactCurrentBatchConfig$1.transition._updatedFibers = new Set(); } - previousNewFiber = newFiber; - oldFiber = nextOldFiber; + try { + setPending(false); + callback(); + } finally { + setCurrentUpdatePriority(previousPriority); + ReactCurrentBatchConfig$1.transition = prevTransition; + + { + if (prevTransition === null && currentTransition._updatedFibers) { + var updatedFibersCount = currentTransition._updatedFibers.size; + + 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." + ); + } + + currentTransition._updatedFibers.clear(); + } + } + } } - if (step.done) { - // We've reached the end of the new children. We can delete the rest. - deleteRemainingChildren(returnFiber, oldFiber); + function mountTransition() { + var _mountState = mountState(false), + isPending = _mountState[0], + setPending = _mountState[1]; // The `start` method never changes. - return resultingFirstChild; + var start = startTransition.bind(null, setPending); + var hook = mountWorkInProgressHook(); + hook.memoizedState = start; + return [isPending, start]; } - 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 updateTransition() { + var _updateState = updateState(), + isPending = _updateState[0]; - if (_newFiber3 === null) { - continue; - } + var hook = updateWorkInProgressHook(); + var start = hook.memoizedState; + return [isPending, start]; + } - lastPlacedIndex = placeChild(_newFiber3, lastPlacedIndex, newIdx); + function rerenderTransition() { + var _rerenderState = rerenderState(), + isPending = _rerenderState[0]; - if (previousNewFiber === null) { - // TODO: Move out of the loop. This only happens for the first run. - resultingFirstChild = _newFiber3; - } else { - previousNewFiber.sibling = _newFiber3; - } + var hook = updateWorkInProgressHook(); + var start = hook.memoizedState; + return [isPending, start]; + } - previousNewFiber = _newFiber3; + var isUpdatingOpaqueValueInRenderPhase = false; + function getIsUpdatingOpaqueValueInRenderPhaseInDEV() { + { + return isUpdatingOpaqueValueInRenderPhase; } + } - return resultingFirstChild; - } // Add all children to a key map for quick lookups. + 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 existingChildren = mapRemainingChildren(returnFiber, oldFiber); // Keep scanning and use the map to restore deleted items as moves. + var identifierPrefix = root.identifierPrefix; + var id; - for (; !step.done; newIdx++, step = newChildren.next()) { - var _newFiber4 = updateFromMap( - existingChildren, - returnFiber, - newIdx, - step.value, - lanes - ); + { + // Use a lowercase r prefix for client-generated ids. + var globalClientId = globalClientIdCounter++; + id = ":" + identifierPrefix + "r" + globalClientId.toString(32) + ":"; + } - 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 - ); - } - } + hook.memoizedState = id; + return id; + } - lastPlacedIndex = placeChild(_newFiber4, lastPlacedIndex, newIdx); + function updateId() { + var hook = updateWorkInProgressHook(); + var id = hook.memoizedState; + return id; + } - if (previousNewFiber === null) { - resultingFirstChild = _newFiber4; - } else { - previousNewFiber.sibling = _newFiber4; + 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()." + ); } - - 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); - }); - } + var lane = requestUpdateLane(fiber); + var update = { + lane: lane, + action: action, + hasEagerState: false, + eagerState: null, + next: null + }; - 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 (isRenderPhaseUpdate(fiber)) { + enqueueRenderPhaseUpdate(queue, update); + } else { + var root = enqueueConcurrentHookUpdate(fiber, queue, update, lane); - if (elementType === REACT_FRAGMENT_TYPE) { - if (child.tag === Fragment) { - deleteRemainingChildren(returnFiber, child.sibling); - var existing = useFiber(child, element.props.children); - existing.return = returnFiber; + if (root !== null) { + var eventTime = requestEventTime(); + scheduleUpdateOnFiber(root, fiber, lane, eventTime); + entangleTransitionUpdate(root, queue, lane); + } + } + } + + 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()." + ); + } + } - { - existing._debugSource = element._source; - existing._debugOwner = element._owner; - } + var lane = requestUpdateLane(fiber); + var update = { + lane: lane, + action: action, + hasEagerState: false, + eagerState: null, + next: null + }; - 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 (isRenderPhaseUpdate(fiber)) { + enqueueRenderPhaseUpdate(queue, update); + } else { + var alternate = fiber.alternate; - var _existing = useFiber(child, element.props); + 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; - _existing.ref = coerceRef(returnFiber, child, element); - _existing.return = returnFiber; + if (lastRenderedReducer !== null) { + var prevDispatcher; { - _existing._debugSource = element._source; - _existing._debugOwner = element._owner; + prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV; } - return _existing; + 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, + lane + ); + return; + } + } catch (error) { + // Suppress the error. It will throw again in the render phase. + } finally { + { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + } } - } // Didn't match. + } - deleteRemainingChildren(returnFiber, child); - break; - } else { - deleteChild(returnFiber, child); - } + var root = enqueueConcurrentHookUpdate(fiber, queue, update, lane); - child = child.sibling; + if (root !== null) { + var eventTime = requestEventTime(); + scheduleUpdateOnFiber(root, fiber, lane, eventTime); + entangleTransitionUpdate(root, queue, lane); + } + } } - if (element.type === REACT_FRAGMENT_TYPE) { - var created = createFiberFromFragment( - element.props.children, - returnFiber.mode, - lanes, - element.key + function isRenderPhaseUpdate(fiber) { + var alternate = fiber.alternate; + return ( + fiber === currentlyRenderingFiber$1 || + (alternate !== null && alternate === currentlyRenderingFiber$1) ); - 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 reconcileChildFibers( - 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. - 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 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; - case REACT_LAZY_TYPE: - var payload = newChild._payload; - var init = newChild._init; // TODO: This function is supposed to be non-recursive. + 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); + } + } + + var ContextOnlyDispatcher = { + readContext: readContext, + 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, + useMutableSource: throwInvalidHookError, + useSyncExternalStore: throwInvalidHookError, + useId: throwInvalidHookError, + unstable_isNewReconciler: enableNewReconciler + }; - return reconcileChildFibers( - returnFiber, - currentFirstChild, - init(payload), - lanes - ); - } + var HooksDispatcherOnMountInDEV = null; + var HooksDispatcherOnMountWithHookTypesInDEV = null; + var HooksDispatcherOnUpdateInDEV = null; + var HooksDispatcherOnRerenderInDEV = null; + var InvalidNestedHooksDispatcherOnMountInDEV = null; + var InvalidNestedHooksDispatcherOnUpdateInDEV = null; + var InvalidNestedHooksDispatcherOnRerenderInDEV = null; - if (isArray(newChild)) { - return reconcileChildrenArray( - returnFiber, - currentFirstChild, - newChild, - lanes + { + 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()." ); - } + }; - if (getIteratorFn(newChild)) { - return reconcileChildrenIterator( - returnFiber, - currentFirstChild, - newChild, - lanes + 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://react.dev/link/rules-of-hooks" ); - } + }; - throwOnInvalidObjectType(returnFiber, newChild); - } + HooksDispatcherOnMountInDEV = { + readContext: function (context) { + return readContext(context); + }, + 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 ( - (typeof newChild === "string" && newChild !== "") || - typeof newChild === "number" - ) { - return placeSingleChild( - reconcileSingleTextNode( - returnFiber, - currentFirstChild, - "" + newChild, - lanes - ) - ); - } + 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; - { - if (typeof newChild === "function") { - warnOnFunctionType(returnFiber); - } - } // Remaining cases are all treated as empty. + 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; - return deleteRemainingChildren(returnFiber, currentFirstChild); - } + try { + return mountState(initialState); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useDebugValue: function (value, formatterFn) { + currentHookNameInDev = "useDebugValue"; + mountHookTypesDev(); + return mountDebugValue(); + }, + useDeferredValue: function (value) { + currentHookNameInDev = "useDeferredValue"; + mountHookTypesDev(); + return mountDeferredValue(value); + }, + useTransition: function () { + currentHookNameInDev = "useTransition"; + mountHookTypesDev(); + return mountTransition(); + }, + useMutableSource: function (source, getSnapshot, subscribe) { + currentHookNameInDev = "useMutableSource"; + mountHookTypesDev(); + return mountMutableSource(); + }, + useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { + currentHookNameInDev = "useSyncExternalStore"; + mountHookTypesDev(); + return mountSyncExternalStore(subscribe, getSnapshot); + }, + useId: function () { + currentHookNameInDev = "useId"; + mountHookTypesDev(); + return mountId(); + }, + unstable_isNewReconciler: enableNewReconciler + }; - return reconcileChildFibers; -} + HooksDispatcherOnMountWithHookTypesInDEV = { + readContext: function (context) { + return readContext(context); + }, + 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 reconcileChildFibers = ChildReconciler(true); -var mountChildFibers = ChildReconciler(false); -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; - } + 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; - newChild.sibling = null; -} // Reset a workInProgress child set to prepare it for a second pass. + 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; -function resetChildFibers(workInProgress, lanes) { - var child = workInProgress.child; + try { + return mountState(initialState); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useDebugValue: function (value, formatterFn) { + currentHookNameInDev = "useDebugValue"; + updateHookTypesDev(); + return mountDebugValue(); + }, + useDeferredValue: function (value) { + currentHookNameInDev = "useDeferredValue"; + updateHookTypesDev(); + return mountDeferredValue(value); + }, + useTransition: function () { + currentHookNameInDev = "useTransition"; + updateHookTypesDev(); + return mountTransition(); + }, + useMutableSource: function (source, getSnapshot, subscribe) { + currentHookNameInDev = "useMutableSource"; + updateHookTypesDev(); + return mountMutableSource(); + }, + useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { + currentHookNameInDev = "useSyncExternalStore"; + updateHookTypesDev(); + return mountSyncExternalStore(subscribe, getSnapshot); + }, + useId: function () { + currentHookNameInDev = "useId"; + updateHookTypesDev(); + return mountId(); + }, + unstable_isNewReconciler: enableNewReconciler + }; - while (child !== null) { - resetWorkInProgress(child, lanes); - child = child.sibling; - } -} + HooksDispatcherOnUpdateInDEV = { + readContext: function (context) { + return readContext(context); + }, + 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; -var NO_CONTEXT = {}; -var contextStackCursor$1 = createCursor(NO_CONTEXT); -var contextFiberStackCursor = createCursor(NO_CONTEXT); -var rootInstanceStackCursor = createCursor(NO_CONTEXT); + 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; -function requiredContext(c) { - if (c === NO_CONTEXT) { - throw new Error( - "Expected host context to exist. This error is likely caused by a bug " + - "in React. Please file an issue." - ); - } + 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 c; -} + try { + return updateState(initialState); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useDebugValue: function (value, formatterFn) { + currentHookNameInDev = "useDebugValue"; + updateHookTypesDev(); + return updateDebugValue(); + }, + useDeferredValue: function (value) { + currentHookNameInDev = "useDeferredValue"; + updateHookTypesDev(); + return updateDeferredValue(value); + }, + useTransition: function () { + currentHookNameInDev = "useTransition"; + updateHookTypesDev(); + return updateTransition(); + }, + useMutableSource: function (source, getSnapshot, subscribe) { + currentHookNameInDev = "useMutableSource"; + updateHookTypesDev(); + return updateMutableSource(); + }, + useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { + currentHookNameInDev = "useSyncExternalStore"; + updateHookTypesDev(); + return updateSyncExternalStore(subscribe, getSnapshot); + }, + useId: function () { + currentHookNameInDev = "useId"; + updateHookTypesDev(); + return updateId(); + }, + unstable_isNewReconciler: enableNewReconciler + }; -function getRootHostContainer() { - var rootInstance = requiredContext(rootInstanceStackCursor.current); - return rootInstance; -} + HooksDispatcherOnRerenderInDEV = { + readContext: function (context) { + return readContext(context); + }, + 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; -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. + 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; - 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. + try { + return rerenderState(initialState); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useDebugValue: function (value, formatterFn) { + currentHookNameInDev = "useDebugValue"; + updateHookTypesDev(); + return updateDebugValue(); + }, + useDeferredValue: function (value) { + currentHookNameInDev = "useDeferredValue"; + updateHookTypesDev(); + return rerenderDeferredValue(value); + }, + useTransition: function () { + currentHookNameInDev = "useTransition"; + updateHookTypesDev(); + return rerenderTransition(); + }, + useMutableSource: function (source, getSnapshot, subscribe) { + currentHookNameInDev = "useMutableSource"; + updateHookTypesDev(); + return updateMutableSource(); + }, + useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { + currentHookNameInDev = "useSyncExternalStore"; + updateHookTypesDev(); + return updateSyncExternalStore(subscribe, getSnapshot); + }, + useId: function () { + currentHookNameInDev = "useId"; + updateHookTypesDev(); + return updateId(); + }, + unstable_isNewReconciler: enableNewReconciler + }; - push(contextStackCursor$1, NO_CONTEXT, fiber); - var nextRootContext = getRootHostContext(); // Now that we know this function doesn't throw, replace it. + InvalidNestedHooksDispatcherOnMountInDEV = { + readContext: function (context) { + warnInvalidContextAccess(); + return readContext(context); + }, + 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; - pop(contextStackCursor$1, fiber); - push(contextStackCursor$1, nextRootContext, fiber); -} + 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; -function popHostContainer(fiber) { - pop(contextStackCursor$1, fiber); - pop(contextFiberStackCursor, fiber); - pop(rootInstanceStackCursor, fiber); -} + 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; -function getHostContext() { - var context = requiredContext(contextStackCursor$1.current); - return context; -} + try { + return mountState(initialState); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useDebugValue: function (value, formatterFn) { + currentHookNameInDev = "useDebugValue"; + warnInvalidHookAccess(); + mountHookTypesDev(); + return mountDebugValue(); + }, + useDeferredValue: function (value) { + currentHookNameInDev = "useDeferredValue"; + warnInvalidHookAccess(); + mountHookTypesDev(); + return mountDeferredValue(value); + }, + useTransition: function () { + currentHookNameInDev = "useTransition"; + warnInvalidHookAccess(); + mountHookTypesDev(); + return mountTransition(); + }, + useMutableSource: function (source, getSnapshot, subscribe) { + currentHookNameInDev = "useMutableSource"; + warnInvalidHookAccess(); + mountHookTypesDev(); + return mountMutableSource(); + }, + useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { + currentHookNameInDev = "useSyncExternalStore"; + warnInvalidHookAccess(); + mountHookTypesDev(); + return mountSyncExternalStore(subscribe, getSnapshot); + }, + useId: function () { + currentHookNameInDev = "useId"; + warnInvalidHookAccess(); + mountHookTypesDev(); + return mountId(); + }, + unstable_isNewReconciler: enableNewReconciler + }; -function pushHostContext(fiber) { - var rootInstance = requiredContext(rootInstanceStackCursor.current); - var context = requiredContext(contextStackCursor$1.current); - var nextContext = getChildHostContext(context, fiber.type); // Don't push this Fiber's context unless it's unique. + InvalidNestedHooksDispatcherOnUpdateInDEV = { + readContext: function (context) { + warnInvalidContextAccess(); + return readContext(context); + }, + 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 (context === nextContext) { - return; - } // Track the context and the Fiber that provided it. - // This enables us to pop only Fibers that provide unique contexts. + 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; - push(contextFiberStackCursor, fiber, fiber); - push(contextStackCursor$1, nextContext, fiber); -} + 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; -function popHostContext(fiber) { - // Do not pop unless this Fiber provided the current context. - // pushHostContext() only pushes Fibers that provide unique contexts. - if (contextFiberStackCursor.current !== fiber) { - return; - } + try { + return updateState(initialState); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useDebugValue: function (value, formatterFn) { + currentHookNameInDev = "useDebugValue"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateDebugValue(); + }, + useDeferredValue: function (value) { + currentHookNameInDev = "useDeferredValue"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateDeferredValue(value); + }, + useTransition: function () { + currentHookNameInDev = "useTransition"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateTransition(); + }, + useMutableSource: function (source, getSnapshot, subscribe) { + currentHookNameInDev = "useMutableSource"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateMutableSource(); + }, + useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { + currentHookNameInDev = "useSyncExternalStore"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateSyncExternalStore(subscribe, getSnapshot); + }, + useId: function () { + currentHookNameInDev = "useId"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateId(); + }, + unstable_isNewReconciler: enableNewReconciler + }; - pop(contextStackCursor$1, fiber); - pop(contextFiberStackCursor, fiber); -} + InvalidNestedHooksDispatcherOnRerenderInDEV = { + readContext: function (context) { + warnInvalidContextAccess(); + return readContext(context); + }, + 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; -var DefaultSuspenseContext = 0; // The Suspense Context is split into two parts. The lower bits is -// inherited deeply down the subtree. The upper bits only affect -// this immediate suspense boundary and gets reset each new -// boundary or suspense list. - -var SubtreeSuspenseContextMask = 1; // Subtree Flags: -// InvisibleParentSuspenseContext indicates that one of our parent Suspense -// boundaries is not currently showing visible main content. -// Either because it is already showing a fallback or is not mounted at all. -// We can use this to determine if it is desirable to trigger a fallback at -// the parent. If not, then we might need to trigger undesirable boundaries -// and/or suspend the commit to avoid hiding the parent content. - -var InvisibleParentSuspenseContext = 1; // Shallow Flags: -// 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 hasSuspenseContext(parentContext, flag) { - return (parentContext & flag) !== 0; -} -function setDefaultShallowSuspenseContext(parentContext) { - return parentContext & SubtreeSuspenseContextMask; -} -function setShallowSuspenseContext(parentContext, shallowContext) { - return (parentContext & SubtreeSuspenseContextMask) | shallowContext; -} -function addSubtreeSuspenseContext(parentContext, subtreeContext) { - return parentContext | subtreeContext; -} -function pushSuspenseContext(fiber, newContext) { - push(suspenseStackCursor, newContext, fiber); -} -function popSuspenseContext(fiber) { - pop(suspenseStackCursor, fiber); -} + 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; -function shouldCaptureSuspense(workInProgress, hasInvisibleParent) { - // If it was the primary children that just suspended, capture and render the - // fallback. Otherwise, don't capture and bubble to the next boundary. - var nextState = workInProgress.memoizedState; + 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; - if (nextState !== null) { - if (nextState.dehydrated !== null) { - // A dehydrated boundary always captures. - return true; + try { + return rerenderState(initialState); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useDebugValue: function (value, formatterFn) { + currentHookNameInDev = "useDebugValue"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateDebugValue(); + }, + useDeferredValue: function (value) { + currentHookNameInDev = "useDeferredValue"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return rerenderDeferredValue(value); + }, + useTransition: function () { + currentHookNameInDev = "useTransition"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return rerenderTransition(); + }, + useMutableSource: function (source, getSnapshot, subscribe) { + currentHookNameInDev = "useMutableSource"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateMutableSource(); + }, + useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { + currentHookNameInDev = "useSyncExternalStore"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateSyncExternalStore(subscribe, getSnapshot); + }, + useId: function () { + currentHookNameInDev = "useId"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateId(); + }, + unstable_isNewReconciler: enableNewReconciler + }; } - return false; - } - - var props = workInProgress.memoizedProps; // Regular boundaries always capture. + var now$1 = 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. + */ - { - return true; - } // If it's a boundary we should avoid, then we prefer to bubble up to the -} -function findFirstSuspended(row) { - var node = row; + var currentUpdateIsNested = false; + var nestedUpdateScheduled = false; - while (node !== null) { - if (node.tag === SuspenseComponent) { - var state = node.memoizedState; + function isCurrentUpdateNested() { + return currentUpdateIsNested; + } - if (state !== null) { - var dehydrated = state.dehydrated; + function markNestedUpdateScheduled() { + { + nestedUpdateScheduled = true; + } + } - if ( - dehydrated === null || - isSuspenseInstancePending() || - isSuspenseInstanceFallback() - ) { - return node; - } + function resetNestedUpdateFlag() { + { + currentUpdateIsNested = false; + nestedUpdateScheduled = false; } - } 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; + } - if (didSuspend) { - return node; + function syncNestedUpdateFlag() { + { + currentUpdateIsNested = nestedUpdateScheduled; + nestedUpdateScheduled = false; } - } else if (node.child !== null) { - node.child.return = node; - node = node.child; - continue; } - if (node === row) { - return null; + function getCommitTime() { + return commitTime; } - while (node.sibling === null) { - if (node.return === null || node.return === row) { - return null; + function recordCommitTime() { + commitTime = now$1(); + } + + function startProfilerTimer(fiber) { + profilerStartTime = now$1(); + + if (fiber.actualStartTime < 0) { + fiber.actualStartTime = now$1(); } + } - node = node.return; + function stopProfilerTimerIfRunning(fiber) { + profilerStartTime = -1; } - node.sibling.return = node.return; - node = node.sibling; - } + function stopProfilerTimerIfRunningAndRecordDelta(fiber, overrideBaseTime) { + if (profilerStartTime >= 0) { + var elapsedTime = now$1() - profilerStartTime; + fiber.actualDuration += elapsedTime; - return null; -} + if (overrideBaseTime) { + fiber.selfBaseDuration = elapsedTime; + } -var NoFlags$1 = - /* */ - 0; // Represents whether effect should fire. + profilerStartTime = -1; + } + } -var HasEffect = - /* */ - 1; // Represents the phase in which the effect (not the clean-up) fires. + function recordLayoutEffectDuration(fiber) { + if (layoutEffectStartTime >= 0) { + var elapsedTime = now$1() - layoutEffectStartTime; + layoutEffectStartTime = -1; // Store duration on the next nearest Profiler ancestor + // Or the root (for the DevTools Profiler to read) -var Insertion = - /* */ - 2; -var Layout = - /* */ - 4; -var Passive$1 = - /* */ - 8; + var parentFiber = fiber.return; -// and should be reset before starting a new render. -// This tracks which mutable sources need to be reset after a render. + while (parentFiber !== null) { + switch (parentFiber.tag) { + case HostRoot: + var root = parentFiber.stateNode; + root.effectDuration += elapsedTime; + return; -var workInProgressSources = []; -function resetWorkInProgressVersions() { - for (var i = 0; i < workInProgressSources.length; i++) { - var mutableSource = workInProgressSources[i]; + case Profiler: + var parentStateNode = parentFiber.stateNode; + parentStateNode.effectDuration += elapsedTime; + return; + } - { - mutableSource._workInProgressVersionSecondary = null; + parentFiber = parentFiber.return; + } + } } - } - workInProgressSources.length = 0; -} + function recordPassiveEffectDuration(fiber) { + if (passiveEffectStartTime >= 0) { + var elapsedTime = now$1() - passiveEffectStartTime; + passiveEffectStartTime = -1; // Store duration on the next nearest Profiler ancestor + // Or the root (for the DevTools Profiler to read) -var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, - ReactCurrentBatchConfig$1 = ReactSharedInternals.ReactCurrentBatchConfig; -var didWarnAboutMismatchedHooksForComponent; -var didWarnUncachedGetSnapshot; + var parentFiber = fiber.return; -{ - didWarnAboutMismatchedHooksForComponent = new Set(); -} + while (parentFiber !== null) { + switch (parentFiber.tag) { + case HostRoot: + var root = parentFiber.stateNode; -// 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. + if (root !== null) { + root.passiveEffectDuration += elapsedTime; + } -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. + return; -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. + case Profiler: + var parentStateNode = parentFiber.stateNode; -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`. + 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; + } -var didScheduleRenderPhaseUpdateDuringThisPass = false; // Counts the number of useId hooks in this component. -// hydration). This counter is global, so client ids are not stable across -// render attempts. + return; + } -var globalClientIdCounter = 0; -var RE_RENDER_LIMIT = 25; // In DEV, this is the name of the currently executing primitive hook + parentFiber = parentFiber.return; + } + } + } -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. + function startLayoutEffectTimer() { + layoutEffectStartTime = now$1(); + } -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. + function startPassiveEffectTimer() { + passiveEffectStartTime = now$1(); + } -var ignorePreviousDependencies = false; + 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; -function mountHookTypesDev() { - { - var hookName = currentHookNameInDev; + while (child) { + fiber.actualDuration += child.actualDuration; + child = child.sibling; + } + } - if (hookTypesDev === null) { - hookTypesDev = [hookName]; - } else { - hookTypesDev.push(hookName); + 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 + }; } - } -} - -function updateHookTypesDev() { - { - var hookName = currentHookNameInDev; - if (hookTypesDev !== null) { - hookTypesUpdateIndexDev++; - - if (hookTypesDev[hookTypesUpdateIndexDev] !== hookName) { - warnOnHookMismatchInDev(hookName); - } + if ( + typeof ReactNativePrivateInterface.ReactFiberErrorDialog.showErrorDialog !== + "function" + ) { + throw new Error( + "Expected ReactFiberErrorDialog.showErrorDialog to be a function." + ); } - } -} -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 showErrorDialog(boundary, errorInfo) { + var capturedError = { + componentStack: errorInfo.stack !== null ? errorInfo.stack : "", + error: errorInfo.value, + errorBoundary: + boundary !== null && boundary.tag === ClassComponent + ? boundary.stateNode + : null + }; + return ReactNativePrivateInterface.ReactFiberErrorDialog.showErrorDialog( + capturedError ); } - } -} -function warnOnHookMismatchInDev(currentHookName) { - { - var componentName = getComponentNameFromFiber(currentlyRenderingFiber$1); + 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 (!didWarnAboutMismatchedHooksForComponent.has(componentName)) { - didWarnAboutMismatchedHooksForComponent.add(componentName); + if (logError === false) { + return; + } - if (hookTypesDev !== null) { - var table = ""; - var secondColumnStart = 30; + var error = errorInfo.value; + + 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 (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 + } - 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 + 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; - while (row.length < secondColumnStart) { - row += " "; + if (boundary.tag === HostRoot) { + errorBoundaryMessage = + "Consider adding an error boundary to your tree to customize error handling behavior.\n" + + "Visit https://react.dev/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 + "."); } - row += newHookName + "\n"; - table += row; + 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 + } else { + // In production, we print the error directly. + // This will include the message, the JS stack, and anything the browser wants to show. + // We pass the error object instead of custom message so that the browser displays the error natively. + console["error"](error); // Don't transform to our wrapper } - - 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://react.dev/link/rules-of-hooks\n\n" + - " Previous render Next render\n" + - " ------------------------------------------------------\n" + - "%s" + - " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", - componentName, - table - ); + } 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; + }); } } - } -} - -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://react.dev/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 - ); - } + var PossiblyWeakMap$1 = typeof WeakMap === "function" ? WeakMap : Map; - 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(", ") + "]" - ); - } - } + function createRootErrorUpdate(fiber, errorInfo, lane) { + var update = createUpdate(NoTimestamp, lane); // Unmount the root by rendering null. - for (var i = 0; i < prevDeps.length && i < nextDeps.length; i++) { - if (objectIs(nextDeps[i], prevDeps[i])) { - continue; - } + update.tag = CaptureUpdate; // Caution: React DevTools currently depends on this property + // being called "element". - return false; - } + update.payload = { + element: null + }; + var error = errorInfo.value; - return true; -} + update.callback = function () { + onUncaughtError(error); + logCapturedError(fiber, errorInfo); + }; -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; - // 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; - } - } - - var children = Component(props, secondArg); // Check if there was a render phase update - - if (didScheduleRenderPhaseUpdateDuringThisPass) { - // Keep rendering in a loop for as long as render phase updates continue to - // be scheduled. Use a counter to prevent infinite loops. - var numberOfReRenders = 0; - - do { - didScheduleRenderPhaseUpdateDuringThisPass = false; + return update; + } - if (numberOfReRenders >= RE_RENDER_LIMIT) { - throw new Error( - "Too many re-renders. React limits the number of renders to prevent " + - "an infinite loop." - ); - } + function createClassErrorUpdate(fiber, errorInfo, lane) { + var update = createUpdate(NoTimestamp, lane); + update.tag = CaptureUpdate; + var getDerivedStateFromError = fiber.type.getDerivedStateFromError; - numberOfReRenders += 1; + if (typeof getDerivedStateFromError === "function") { + var error$1 = errorInfo.value; - { - // 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 + update.payload = function () { + return getDerivedStateFromError(error$1); + }; - currentHook = null; - workInProgressHook = null; - workInProgress.updateQueue = null; + update.callback = function () { + { + markFailedErrorBoundaryForHotReloading(fiber); + } - { - // Also validate hook order for cascading updates. - hookTypesUpdateIndexDev = -1; + logCapturedError(fiber, errorInfo); + }; } - ReactCurrentDispatcher$1.current = HooksDispatcherOnRerenderInDEV; - children = Component(props, secondArg); - } while (didScheduleRenderPhaseUpdateDuringThisPass); - } // 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. + var inst = fiber.stateNode; - ReactCurrentDispatcher$1.current = ContextOnlyDispatcher; + if (inst !== null && typeof inst.componentDidCatch === "function") { + update.callback = function callback() { + { + markFailedErrorBoundaryForHotReloading(fiber); + } - { - workInProgress._debugHookTypes = hookTypesDev; - } // 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. + logCapturedError(fiber, errorInfo); - var didRenderTooFewHooks = currentHook !== null && currentHook.next !== null; - renderLanes = NoLanes; - currentlyRenderingFiber$1 = null; - currentHook = null; - workInProgressHook = 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); + } - { - 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. + var error$1 = errorInfo.value; + var stack = errorInfo.stack; + this.componentDidCatch(error$1, { + componentStack: stack !== null ? stack : "" + }); - 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." - ); - } - } + { + 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" + ); + } + } + } + }; + } - didScheduleRenderPhaseUpdate = false; // This is reset by checkDidRenderIdHook - // localIdCounter = 0; + return update; + } - if (didRenderTooFewHooks) { - throw new Error( - "Rendered fewer hooks than expected. This may be caused by an accidental " + - "early return statement." - ); - } + 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; - 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 (pingCache === null) { + pingCache = root.pingCache = new PossiblyWeakMap$1(); + threadIDs = new Set(); + pingCache.set(wakeable, threadIDs); + } else { + threadIDs = pingCache.get(wakeable); - { - workInProgress.flags &= ~(Passive | Update); - } + if (threadIDs === undefined) { + threadIDs = new Set(); + pingCache.set(wakeable, threadIDs); + } + } - current.lanes = removeLanes(current.lanes, lanes); -} -function resetHooksAfterThrow() { - // 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; - - 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 = currentlyRenderingFiber$1.memoizedState; + if (!threadIDs.has(lanes)) { + // Memoize using the thread ID to prevent redundant listeners. + threadIDs.add(lanes); + var ping = pingSuspendedRoot.bind(null, root, wakeable, lanes); - while (hook !== null) { - var queue = hook.queue; + { + if (isDevToolsPresent) { + // If we have pending work still, restore the original updaters + restorePendingUpdaters(root, lanes); + } + } - if (queue !== null) { - queue.pending = null; + wakeable.then(ping, ping); } - - hook = hook.next; } - didScheduleRenderPhaseUpdate = false; - } + function attachRetryListener(suspenseBoundary, root, wakeable, lanes) { + // 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"). + var wakeables = suspenseBoundary.updateQueue; + + if (wakeables === null) { + var updateQueue = new Set(); + updateQueue.add(wakeable); + suspenseBoundary.updateQueue = updateQueue; + } else { + wakeables.add(wakeable); + } + } - renderLanes = NoLanes; - currentlyRenderingFiber$1 = null; - currentHook = null; - workInProgressHook = null; + function resetSuspendedComponent(sourceFiber, rootRenderLanes) { + // A legacy mode Suspense quirk, only relevant to hook components. - { - hookTypesDev = null; - hookTypesUpdateIndexDev = -1; - currentHookNameInDev = null; - isUpdatingOpaqueValueInRenderPhase = false; - } + var tag = sourceFiber.tag; - didScheduleRenderPhaseUpdateDuringThisPass = false; -} + if ( + (sourceFiber.mode & ConcurrentMode) === NoMode && + (tag === FunctionComponent || + tag === ForwardRef || + tag === SimpleMemoComponent) + ) { + var currentSource = sourceFiber.alternate; -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; -} + if (currentSource) { + sourceFiber.updateQueue = currentSource.updateQueue; + sourceFiber.memoizedState = currentSource.memoizedState; + sourceFiber.lanes = currentSource.lanes; + } else { + sourceFiber.updateQueue = null; + sourceFiber.memoizedState = null; + } + } + } -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. When we reach the end of the base list, we must switch to - // the dispatcher used for mounts. - 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) { - 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 - }; + function getNearestSuspenseBoundaryToCapture(returnFiber) { + var node = returnFiber; - 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; - } - } + do { + if (node.tag === SuspenseComponent && shouldCaptureSuspense(node)) { + return node; + } // This boundary already captured during this render. Continue to the next + // boundary. - return workInProgressHook; -} + node = node.return; + } while (node !== null); -function createFunctionComponentUpdateQueue() { - return { - lastEffect: null, - stores: null - }; -} + return null; + } -function basicStateReducer(state, action) { - // $FlowFixMe: Flow doesn't like mixed types - return typeof action === "function" ? action(state) : action; -} + 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 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, - interleaved: 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]; -} + sourceFiber.flags &= ~(LifecycleEffectMask | Incomplete); -function updateReducer(reducer, initialArg, init) { - var hook = updateWorkInProgressHook(); - var queue = hook.queue; + if (sourceFiber.tag === ClassComponent) { + var currentSourceFiber = sourceFiber.alternate; - if (queue === null) { - throw new Error( - "Should have a queue. This is likely a bug in React. Please file an issue." - ); - } + 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(NoTimestamp, 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. - queue.lastRenderedReducer = reducer; - var current = currentHook; // The last rebase update that is NOT part of the base state. + sourceFiber.lanes = mergeLanes(sourceFiber.lanes, SyncLane); + } - var baseQueue = current.baseQueue; // The last pending update that hasn't been processed yet. + 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. - var pendingQueue = queue.pending; + suspenseBoundary.flags |= ShouldCapture; // TODO: I think we can remove this, since we now use `DidCapture` in + // the begin phase to prevent an early bailout. - 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; + suspenseBoundary.lanes = rootRenderLanes; + return suspenseBoundary; } - { - 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." - ); - } - } + function throwException( + root, + returnFiber, + sourceFiber, + value, + rootRenderLanes + ) { + // The source fiber did not complete. + sourceFiber.flags |= Incomplete; - current.baseQueue = baseQueue = pendingQueue; - queue.pending = null; - } + { + if (isDevToolsPresent) { + // If we have pending work still, restore the original updaters + restorePendingUpdaters(root, rootRenderLanes); + } + } - if (baseQueue !== null) { - // We have a queue to process. - var first = baseQueue.next; - var newState = current.baseState; - var newBaseState = null; - var newBaseQueueFirst = null; - var newBaseQueueLast = null; - var update = first; + if ( + value !== null && + typeof value === "object" && + typeof value.then === "function" + ) { + // This is a wakeable. The component suspended. + var wakeable = value; + resetSuspendedComponent(sourceFiber); - do { - var updateLane = update.lane; + var suspenseBoundary = getNearestSuspenseBoundaryToCapture(returnFiber); - if (!isSubsetOfLanes(renderLanes, updateLane)) { - // 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, - action: update.action, - hasEagerState: update.hasEagerState, - eagerState: update.eagerState, - next: null - }; + if (suspenseBoundary !== null) { + suspenseBoundary.flags &= ~ForceClientRender; + markSuspenseBoundaryShouldCapture( + suspenseBoundary, + returnFiber, + sourceFiber, + root, + rootRenderLanes + ); // We only attach ping listeners in concurrent mode. Legacy Suspense always + // commits fallbacks synchronously, so there are no pings. - 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. - 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, - action: update.action, - hasEagerState: update.hasEagerState, - eagerState: update.eagerState, - next: null - }; - newBaseQueueLast = newBaseQueueLast.next = _clone; - } // Process this update. + if (suspenseBoundary.mode & ConcurrentMode) { + attachPingListener(root, wakeable, rootRenderLanes); + } - 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; + attachRetryListener(suspenseBoundary, root, wakeable); + return; } else { - var action = update.action; - newState = reducer(newState, action); + // No boundary was found. Unless this is a sync update, this is OK. + // We can suspend and wait for more data to arrive. + if (!includesSyncLane(rootRenderLanes)) { + // This is not a sync update. Suspend. Since we're not activating a + // Suspense boundary, this will unwind all the way to the root without + // performing a second pass to render a fallback. (This is arguably how + // refresh transitions should work, too, since we're not going to commit + // the fallbacks anyway.) + // + // This case also applies to initial hydration. + attachPingListener(root, wakeable, rootRenderLanes); + renderDidSuspendDelayIfPossible(); + return; + } // This is a sync/discrete update. We treat this case like an error + // because discrete renders are expected to produce a complete tree + // synchronously to maintain consistency with external state. + + var uncaughtSuspenseError = new Error( + "A component suspended while responding to synchronous input. This " + + "will cause the UI to be replaced with a loading indicator. To " + + "fix, updates that suspend should be wrapped " + + "with startTransition." + ); // If we're outside a transition, fall through to the regular error path. + // The error will be caught by the nearest suspense boundary. + + value = uncaughtSuspenseError; } } - 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; - } // Interleaved updates are stored on a separate queue. We aren't going to - // process them during this render, but we do need to track which lanes - // are remaining. + 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. - var lastInterleaved = queue.interleaved; + var workInProgress = returnFiber; - if (lastInterleaved !== null) { - var interleaved = lastInterleaved; + 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; + } - do { - var interleavedLane = interleaved.lane; - currentlyRenderingFiber$1.lanes = mergeLanes( - currentlyRenderingFiber$1.lanes, - interleavedLane - ); - markSkippedUpdateLanes(interleavedLane); - interleaved = interleaved.next; - } while (interleaved !== lastInterleaved); - } else 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]; -} + case ClassComponent: + // Capture and retry + var errorInfo = value; + var ctor = workInProgress.type; + var instance = workInProgress.stateNode; -function rerenderReducer(reducer, initialArg, init) { - var hook = updateWorkInProgressHook(); - var queue = hook.queue; + if ( + (workInProgress.flags & DidCapture) === NoFlags && + (typeof ctor.getDerivedStateFromError === "function" || + (instance !== null && + typeof instance.componentDidCatch === "function" && + !isAlreadyFailedLegacyErrorBoundary(instance))) + ) { + workInProgress.flags |= ShouldCapture; - if (queue === null) { - throw new Error( - "Should have a queue. This is likely a bug in React. Please file an issue." - ); - } + var _lane = pickArbitraryLane(rootRenderLanes); - queue.lastRenderedReducer = reducer; // This is a re-render. Apply the new render phase updates to the previous - // work-in-progress hook. + workInProgress.lanes = mergeLanes(workInProgress.lanes, _lane); // Schedule the error boundary to re-render using updated state - var dispatch = queue.dispatch; - var lastRenderPhaseUpdate = queue.pending; - var newState = hook.memoizedState; + var _update = createClassErrorUpdate( + workInProgress, + errorInfo, + _lane + ); - if (lastRenderPhaseUpdate !== null) { - // The queue doesn't persist past this render pass. - queue.pending = null; - var firstRenderPhaseUpdate = lastRenderPhaseUpdate.next; - var update = firstRenderPhaseUpdate; + enqueueCapturedUpdate(workInProgress, _update); + return; + } - 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. + break; + } - if (!objectIs(newState, hook.memoizedState)) { - markWorkInProgressReceivedUpdate(); + workInProgress = workInProgress.return; + } while (workInProgress !== null); } - 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; + function getSuspendedCache() { + { + return null; + } // This function is called when a Suspense boundary suspends. It returns the } - queue.lastRenderedState = newState; - } - - return [newState, dispatch]; -} - -function mountMutableSource(source, getSnapshot, subscribe) { - { - return undefined; - } -} - -function updateMutableSource(source, getSnapshot, subscribe) { - { - return undefined; - } -} - -function mountSyncExternalStore(subscribe, getSnapshot, getServerSnapshot) { - var fiber = currentlyRenderingFiber$1; - var hook = mountWorkInProgressHook(); - var nextSnapshot; - - { - nextSnapshot = getSnapshot(); + var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner; + var didReceiveUpdate = false; + var didWarnAboutBadClass; + var didWarnAboutModulePatternComponent; + var didWarnAboutContextTypeOnFunctionComponent; + var didWarnAboutGetDerivedStateOnFunctionComponent; + var didWarnAboutFunctionRefs; + var didWarnAboutReassigningProps; + var didWarnAboutRevealOrder; + var didWarnAboutTailOptions; { - if (!didWarnUncachedGetSnapshot) { - var cachedSnapshot = getSnapshot(); - - if (!objectIs(nextSnapshot, cachedSnapshot)) { - error( - "The result of getSnapshot should be cached to avoid an infinite loop" - ); + didWarnAboutBadClass = {}; + didWarnAboutModulePatternComponent = {}; + didWarnAboutContextTypeOnFunctionComponent = {}; + didWarnAboutGetDerivedStateOnFunctionComponent = {}; + didWarnAboutFunctionRefs = {}; + didWarnAboutReassigningProps = false; + didWarnAboutRevealOrder = {}; + didWarnAboutTailOptions = {}; + } - didWarnUncachedGetSnapshot = true; - } + 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 + ); } - } // 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 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. - if (root === null) { - throw new Error( - "Expected a work-in-progress root. This is a bug in React. Please file an issue." + workInProgress.child = reconcileChildFibers( + workInProgress, + null, + nextChildren, + renderLanes ); } - if (!includesBlockingLane(root, renderLanes)) { - 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. - // TODO: We can move this to the passive phase once we add a pre-commit - // consistency check. See the next comment. - - fiber.flags |= Passive; - pushEffect( - HasEffect | Passive$1, - updateStoreInstance.bind(null, fiber, inst, nextSnapshot, getSnapshot), - undefined, - null - ); - return nextSnapshot; -} + 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; -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 (innerPropTypes) { + checkPropTypes( + innerPropTypes, + nextProps, // Resolved props + "prop", + getComponentNameFromType(Component) + ); + } + } + } - var nextSnapshot = getSnapshot(); + var render = Component.render; + var ref = workInProgress.ref; // The rest is a fork of updateFunctionComponent - { - if (!didWarnUncachedGetSnapshot) { - var cachedSnapshot = getSnapshot(); + var nextChildren; + prepareToReadContext(workInProgress, renderLanes); - if (!objectIs(nextSnapshot, cachedSnapshot)) { - error( - "The result of getSnapshot should be cached to avoid an infinite loop" + { + ReactCurrentOwner$1.current = workInProgress; + setIsRendering(true); + nextChildren = renderWithHooks( + current, + workInProgress, + render, + nextProps, + ref, + renderLanes ); - didWarnUncachedGetSnapshot = true; - } - } - } - - var prevSnapshot = 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 susbcribe 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; - pushEffect( - HasEffect | Passive$1, - updateStoreInstance.bind(null, fiber, inst, nextSnapshot, getSnapshot), - undefined, - 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." - ); - } + setIsRendering(false); + } + + if (current !== null && !didReceiveUpdate) { + bailoutHooks(current, workInProgress, renderLanes); + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); + } - if (!includesBlockingLane(root, renderLanes)) { - pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot); + workInProgress.flags |= PerformedWork; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; } - } - return nextSnapshot; -} + function updateMemoComponent( + current, + workInProgress, + Component, + nextProps, + renderLanes + ) { + if (current === null) { + var type = Component.type; -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 ( + isSimpleFunctionComponent(type) && + Component.compare === null && // SimpleMemoComponent codepath doesn't resolve outer props either. + Component.defaultProps === undefined + ) { + var resolvedType = type; -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); - } -} + { + 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. -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. + workInProgress.tag = SimpleMemoComponent; + workInProgress.type = resolvedType; - return subscribe(handleStoreChange); -} + { + validateFunctionComponentInDev(workInProgress, type); + } -function checkIfSnapshotChanged(inst) { - var latestGetSnapshot = inst.getSnapshot; - var prevValue = inst.value; + return updateSimpleMemoComponent( + current, + workInProgress, + resolvedType, + nextProps, + renderLanes + ); + } - try { - var nextValue = latestGetSnapshot(); - return !objectIs(prevValue, nextValue); - } catch (error) { - return true; - } -} + { + var innerPropTypes = type.propTypes; -function forceStoreRerender(fiber) { - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + 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 (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); - } -} + var child = createFiberFromTypeAndProps( + Component.type, + null, + nextProps, + workInProgress, + workInProgress.mode, + renderLanes + ); + child.ref = workInProgress.ref; + child.return = workInProgress; + workInProgress.child = child; + return child; + } -function mountState(initialState) { - var hook = mountWorkInProgressHook(); - - if (typeof initialState === "function") { - // $FlowFixMe: Flow doesn't like mixed types - initialState = initialState(); - } - - hook.memoizedState = hook.baseState = initialState; - var queue = { - pending: null, - interleaved: null, - lanes: NoLanes, - dispatch: null, - lastRenderedReducer: basicStateReducer, - lastRenderedState: initialState - }; - hook.queue = queue; - var dispatch = (queue.dispatch = dispatchSetState.bind( - null, - currentlyRenderingFiber$1, - queue - )); - return [hook.memoizedState, dispatch]; -} + { + var _type = Component.type; + var _innerPropTypes = _type.propTypes; -function updateState(initialState) { - return updateReducer(basicStateReducer); -} + 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 rerenderState(initialState) { - return rerenderReducer(basicStateReducer); -} + var currentChild = current.child; // This is always exactly one child -function pushEffect(tag, create, destroy, deps) { - var effect = { - tag: tag, - create: create, - destroy: destroy, - 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; -} + var hasScheduledUpdateOrContext = checkScheduledUpdateOrContext( + current, + renderLanes + ); -function mountRef(initialValue) { - var hook = mountWorkInProgressHook(); + 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 _ref2 = { - current: initialValue - }; - hook.memoizedState = _ref2; - return _ref2; - } -} + var compare = Component.compare; + compare = compare !== null ? compare : shallowEqual; -function updateRef(initialValue) { - var hook = updateWorkInProgressHook(); - return hook.memoizedState; -} + if (compare(prevProps, nextProps) && current.ref === workInProgress.ref) { + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); + } + } // React DevTools reads this flag. -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, - undefined, - nextDeps - ); -} + workInProgress.flags |= PerformedWork; + var newChild = createWorkInProgress(currentChild, nextProps); + newChild.ref = workInProgress.ref; + newChild.return = workInProgress; + workInProgress.child = newChild; + return newChild; + } -function updateEffectImpl(fiberFlags, hookFlags, create, deps) { - var hook = updateWorkInProgressHook(); - var nextDeps = deps === undefined ? null : deps; - var destroy = undefined; + 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; - if (currentHook !== null) { - var prevEffect = currentHook.memoizedState; - destroy = prevEffect.destroy; + 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) + ); + } + } + } + } - if (nextDeps !== null) { - var prevDeps = prevEffect.deps; + if (current !== null) { + var prevProps = current.memoizedProps; - if (areHookInputsEqual(nextDeps, prevDeps)) { - hook.memoizedState = pushEffect(hookFlags, create, destroy, nextDeps); - 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) { + // This is a special case that only exists for legacy mode. + // See https://github.com/facebook/react/pull/19216. + didReceiveUpdate = true; + } + } } + + return updateFunctionComponent( + current, + workInProgress, + Component, + nextProps, + renderLanes + ); } - } - currentlyRenderingFiber$1.flags |= fiberFlags; - hook.memoizedState = pushEffect( - HasEffect | hookFlags, - create, - destroy, - nextDeps - ); -} + function updateOffscreenComponent(current, workInProgress, renderLanes) { + var nextProps = workInProgress.pendingProps; + var nextChildren = nextProps.children; + var prevState = current !== null ? current.memoizedState : null; + + if (nextProps.mode === "hidden" || enableLegacyHidden) { + // Rendering a hidden tree. + 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, + transitions: null + }; + workInProgress.memoizedState = nextState; -function mountEffect(create, deps) { - { - return mountEffectImpl(Passive | PassiveStatic, Passive$1, create, deps); - } -} + pushRenderLanes(workInProgress, renderLanes); + } else if (!includesSomeLane(renderLanes, OffscreenLane)) { + var spawnedCachePool = null; // We're hidden, and we're not rendering at Offscreen. We will bail out + // and resume this tree later. -function updateEffect(create, deps) { - return updateEffectImpl(Passive, Passive$1, create, deps); -} + var nextBaseLanes; -function mountInsertionEffect(create, deps) { - return mountEffectImpl(Update, Insertion, create, deps); -} + if (prevState !== null) { + var prevBaseLanes = prevState.baseLanes; + nextBaseLanes = mergeLanes(prevBaseLanes, renderLanes); + } else { + nextBaseLanes = renderLanes; + } // Schedule this fiber to re-render at offscreen priority. Then bailout. -function updateInsertionEffect(create, deps) { - return updateEffectImpl(Update, Insertion, create, deps); -} + workInProgress.lanes = workInProgress.childLanes = laneToLanes( + OffscreenLane + ); + var _nextState = { + baseLanes: nextBaseLanes, + cachePool: spawnedCachePool, + transitions: null + }; + workInProgress.memoizedState = _nextState; + workInProgress.updateQueue = null; + // to avoid a push/pop misalignment. -function mountLayoutEffect(create, deps) { - var fiberFlags = Update; + pushRenderLanes(workInProgress, nextBaseLanes); - return mountEffectImpl(fiberFlags, Layout, create, deps); -} + return null; + } 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 _nextState2 = { + baseLanes: NoLanes, + cachePool: null, + transitions: null + }; + workInProgress.memoizedState = _nextState2; // Push the lanes that were skipped when we bailed out. -function updateLayoutEffect(create, deps) { - return updateEffectImpl(Update, Layout, create, deps); -} + var subtreeRenderLanes = + prevState !== null ? prevState.baseLanes : renderLanes; -function imperativeHandleEffect(create, ref) { - if (typeof ref === "function") { - var refCallback = ref; + pushRenderLanes(workInProgress, subtreeRenderLanes); + } + } else { + // Rendering a visible tree. + var _subtreeRenderLanes; - var _inst = create(); + if (prevState !== null) { + // We're going from hidden -> visible. + _subtreeRenderLanes = mergeLanes(prevState.baseLanes, renderLanes); - refCallback(_inst); - return function() { - refCallback(null); - }; - } else if (ref !== null && ref !== undefined) { - var refObject = ref; + 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. + _subtreeRenderLanes = renderLanes; + } - { - 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(", ") + "}" - ); + pushRenderLanes(workInProgress, _subtreeRenderLanes); } - } - - var _inst2 = create(); - refObject.current = _inst2; - return function() { - refObject.current = null; - }; - } -} + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; + } // Note: These happen to have identical begin phases, for now. We shouldn't hold -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" - ); + function updateFragment(current, workInProgress, renderLanes) { + var nextChildren = workInProgress.pendingProps; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; } - } // 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; - return 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 updateMode(current, workInProgress, renderLanes) { + var nextChildren = workInProgress.pendingProps.children; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; } - } // TODO: If deps are provided, should we skip comparing the ref itself? - - var effectDeps = - deps !== null && deps !== undefined ? deps.concat([ref]) : null; - return 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 updateProfiler(current, workInProgress, renderLanes) { + { + workInProgress.flags |= Update; -function mountCallback(callback, deps) { - var hook = mountWorkInProgressHook(); - var nextDeps = deps === undefined ? null : deps; - hook.memoizedState = [callback, nextDeps]; - return callback; -} + { + // 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; + } + } -function updateCallback(callback, deps) { - var hook = updateWorkInProgressHook(); - var nextDeps = deps === undefined ? null : deps; - var prevState = hook.memoizedState; + var nextProps = workInProgress.pendingProps; + var nextChildren = nextProps.children; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; + } - if (prevState !== null) { - if (nextDeps !== null) { - var prevDeps = prevState[1]; + function markRef(current, workInProgress) { + var ref = workInProgress.ref; - if (areHookInputsEqual(nextDeps, prevDeps)) { - return prevState[0]; + if ( + (current === null && ref !== null) || + (current !== null && current.ref !== ref) + ) { + // Schedule a Ref effect + workInProgress.flags |= Ref; } } - } - - hook.memoizedState = [callback, nextDeps]; - return callback; -} -function mountMemo(nextCreate, deps) { - var hook = mountWorkInProgressHook(); - var nextDeps = deps === undefined ? null : deps; - var nextValue = nextCreate(); - hook.memoizedState = [nextValue, nextDeps]; - return nextValue; -} + 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 updateMemo(nextCreate, deps) { - var hook = updateWorkInProgressHook(); - var nextDeps = deps === undefined ? null : deps; - var prevState = hook.memoizedState; + if (innerPropTypes) { + checkPropTypes( + innerPropTypes, + nextProps, // Resolved props + "prop", + getComponentNameFromType(Component) + ); + } + } + } - if (prevState !== null) { - // Assume these are defined. If they're not, areHookInputsEqual will warn. - if (nextDeps !== null) { - var prevDeps = prevState[1]; + var context; - if (areHookInputsEqual(nextDeps, prevDeps)) { - return prevState[0]; + { + var unmaskedContext = getUnmaskedContext(workInProgress, Component, true); + context = getMaskedContext(workInProgress, unmaskedContext); } - } - } - var nextValue = nextCreate(); - hook.memoizedState = [nextValue, nextDeps]; - return nextValue; -} + var nextChildren; + prepareToReadContext(workInProgress, renderLanes); -function mountDeferredValue(value) { - var hook = mountWorkInProgressHook(); - hook.memoizedState = value; - return value; -} + { + ReactCurrentOwner$1.current = workInProgress; + setIsRendering(true); + nextChildren = renderWithHooks( + current, + workInProgress, + Component, + nextProps, + context, + renderLanes + ); -function updateDeferredValue(value) { - var hook = updateWorkInProgressHook(); - var resolvedCurrentHook = currentHook; - var prevValue = resolvedCurrentHook.memoizedState; - return updateDeferredValueImpl(hook, prevValue, value); -} + setIsRendering(false); + } -function rerenderDeferredValue(value) { - var hook = updateWorkInProgressHook(); - - if (currentHook === null) { - // This is a rerender during a mount. - hook.memoizedState = value; - return value; - } else { - // This is a rerender during an update. - var prevValue = currentHook.memoizedState; - return updateDeferredValueImpl(hook, prevValue, value); - } -} + if (current !== null && !didReceiveUpdate) { + bailoutHooks(current, workInProgress, renderLanes); + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); + } -function updateDeferredValueImpl(hook, prevValue, value) { - var shouldDeferValue = !includesOnlyNonUrgentLanes(renderLanes); - - if (shouldDeferValue) { - // This is an urgent update. If the value has changed, keep using the - // previous value and spawn a deferred render to update it later. - if (!objectIs(value, prevValue)) { - // Schedule a deferred render - var deferredLane = claimNextTransitionLane(); - currentlyRenderingFiber$1.lanes = mergeLanes( - currentlyRenderingFiber$1.lanes, - deferredLane - ); - markSkippedUpdateLanes(deferredLane); // Set this to true to indicate that the rendered value is inconsistent - // from the latest value. The name "baseState" doesn't really match how we - // use it because we're reusing a state hook field instead of creating a - // new one. - - hook.baseState = true; - } // Reuse the previous 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. - // However, if we're currently inside a spawned render, then we need to mark - // this as an update to prevent the fiber from bailing out. - // - // `baseState` is true when the current value is different from the rendered - // value. The name doesn't really match how we use it because we're reusing - // a state hook field instead of creating a new one. - if (hook.baseState) { - // Flip this back to false. - hook.baseState = false; - markWorkInProgressReceivedUpdate(); - } - - hook.memoizedState = value; - return value; - } -} + workInProgress.flags |= PerformedWork; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; + } -function startTransition(setPending, callback, options) { - var previousPriority = getCurrentUpdatePriority(); - setCurrentUpdatePriority( - higherEventPriority(previousPriority, ContinuousEventPriority) - ); - setPending(true); - var prevTransition = ReactCurrentBatchConfig$1.transition; - ReactCurrentBatchConfig$1.transition = {}; - var currentTransition = ReactCurrentBatchConfig$1.transition; - - { - ReactCurrentBatchConfig$1.transition._updatedFibers = new Set(); - } - - try { - setPending(false); - callback(); - } finally { - setCurrentUpdatePriority(previousPriority); - ReactCurrentBatchConfig$1.transition = prevTransition; + 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 (prevTransition === null && currentTransition._updatedFibers) { - var updatedFibersCount = currentTransition._updatedFibers.size; + _instance.updater.enqueueSetState(_instance, state, null); - 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." - ); - } + break; + } - currentTransition._updatedFibers.clear(); - } - } - } -} + case true: { + workInProgress.flags |= DidCapture; + workInProgress.flags |= ShouldCapture; // eslint-disable-next-line react-internal/prod-error-codes -function mountTransition() { - var _mountState = mountState(false), - isPending = _mountState[0], - setPending = _mountState[1]; // The `start` method never changes. + 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 start = startTransition.bind(null, setPending); - var hook = mountWorkInProgressHook(); - hook.memoizedState = start; - return [isPending, start]; -} + var update = createClassErrorUpdate( + workInProgress, + createCapturedValueAtFiber(error$1, workInProgress), + lane + ); + enqueueCapturedUpdate(workInProgress, update); + break; + } + } -function updateTransition() { - var _updateState = updateState(), - isPending = _updateState[0]; + 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 hook = updateWorkInProgressHook(); - var start = hook.memoizedState; - return [isPending, start]; -} + 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. -function rerenderTransition() { - var _rerenderState = rerenderState(), - isPending = _rerenderState[0]; + var hasContext; - var hook = updateWorkInProgressHook(); - var start = hook.memoizedState; - return [isPending, start]; -} + if (isContextProvider(Component)) { + hasContext = true; + pushContextProvider(workInProgress); + } else { + hasContext = false; + } -var isUpdatingOpaqueValueInRenderPhase = false; -function getIsUpdatingOpaqueValueInRenderPhaseInDEV() { - { - return isUpdatingOpaqueValueInRenderPhase; - } -} + prepareToReadContext(workInProgress, renderLanes); + var instance = workInProgress.stateNode; + var shouldUpdate; -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 (instance === null) { + resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress); // In the initial pass we might need to construct the instance. -function updateId() { - var hook = updateWorkInProgressHook(); - var id = hook.memoizedState; - return id; -} + 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 + ); + } -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 nextUnitOfWork = finishClassComponent( + current, + workInProgress, + Component, + shouldUpdate, + hasContext, + renderLanes ); - } - } - var lane = requestUpdateLane(fiber); - var update = { - lane: lane, - action: action, - hasEagerState: false, - eagerState: null, - next: null - }; + { + var inst = workInProgress.stateNode; - if (isRenderPhaseUpdate(fiber)) { - enqueueRenderPhaseUpdate(queue, update); - } else { - var root = enqueueConcurrentHookUpdate(fiber, queue, update, lane); + 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 (root !== null) { - var eventTime = requestEventTime(); - scheduleUpdateOnFiber(root, fiber, lane, eventTime); - entangleTransitionUpdate(root, queue, lane); - } - } -} + didWarnAboutReassigningProps = true; + } + } -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()." - ); + return nextUnitOfWork; } - } - var lane = requestUpdateLane(fiber); - var update = { - lane: lane, - action: action, - hasEagerState: false, - eagerState: null, - next: null - }; + function finishClassComponent( + current, + workInProgress, + Component, + shouldUpdate, + hasContext, + renderLanes + ) { + // Refs should update even if shouldComponentUpdate returns false + markRef(current, workInProgress); + var didCaptureError = (workInProgress.flags & DidCapture) !== NoFlags; + + if (!shouldUpdate && !didCaptureError) { + // Context providers should defer to sCU for rendering + if (hasContext) { + invalidateContextProvider(workInProgress, Component, false); + } + + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); + } - if (isRenderPhaseUpdate(fiber)) { - enqueueRenderPhaseUpdate(queue, update); - } else { - var alternate = fiber.alternate; + var instance = workInProgress.stateNode; // Rerender - 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; + ReactCurrentOwner$1.current = workInProgress; + var nextChildren; - if (lastRenderedReducer !== null) { - var prevDispatcher; + 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; { - prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV; + stopProfilerTimerIfRunning(); } + } else { + { + setIsRendering(true); + nextChildren = instance.render(); - 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, - lane - ); - return; - } - } catch (error) { - // Suppress the error. It will throw again in the render phase. - } finally { - { - ReactCurrentDispatcher$1.current = prevDispatcher; - } + setIsRendering(false); } - } - } + } // React DevTools reads this flag. + + workInProgress.flags |= PerformedWork; - var root = enqueueConcurrentHookUpdate(fiber, queue, update, lane); + 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 (root !== null) { - var eventTime = requestEventTime(); - scheduleUpdateOnFiber(root, fiber, lane, eventTime); - entangleTransitionUpdate(root, queue, lane); - } - } -} + workInProgress.memoizedState = instance.state; // The context might have changed so we need to recalculate it. -function isRenderPhaseUpdate(fiber) { - var alternate = fiber.alternate; - return ( - fiber === currentlyRenderingFiber$1 || - (alternate !== null && alternate === currentlyRenderingFiber$1) - ); -} + if (hasContext) { + invalidateContextProvider(workInProgress, Component, true); + } -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); - } -} + return workInProgress.child; + } -var ContextOnlyDispatcher = { - readContext: readContext, - 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, - useMutableSource: throwInvalidHookError, - useSyncExternalStore: throwInvalidHookError, - useId: throwInvalidHookError, - unstable_isNewReconciler: enableNewReconciler -}; - -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://react.dev/link/rules-of-hooks" - ); - }; - - HooksDispatcherOnMountInDEV = { - readContext: function(context) { - return readContext(context); - }, - 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; + function pushHostRootContext(workInProgress) { + var root = workInProgress.stateNode; - try { - return mountMemo(create, deps); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; + if (root.pendingContext) { + pushTopLevelContextObject( + workInProgress, + root.pendingContext, + root.pendingContext !== root.context + ); + } else if (root.context) { + // Should always be set + pushTopLevelContextObject(workInProgress, root.context, false); } - }, - 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; + pushHostContainer(workInProgress, root.containerInfo); + } - try { - return mountState(initialState); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useDebugValue: function(value, formatterFn) { - currentHookNameInDev = "useDebugValue"; - mountHookTypesDev(); - return mountDebugValue(); - }, - useDeferredValue: function(value) { - currentHookNameInDev = "useDeferredValue"; - mountHookTypesDev(); - return mountDeferredValue(value); - }, - useTransition: function() { - currentHookNameInDev = "useTransition"; - mountHookTypesDev(); - return mountTransition(); - }, - useMutableSource: function(source, getSnapshot, subscribe) { - currentHookNameInDev = "useMutableSource"; - mountHookTypesDev(); - return mountMutableSource(); - }, - useSyncExternalStore: function(subscribe, getSnapshot, getServerSnapshot) { - currentHookNameInDev = "useSyncExternalStore"; - mountHookTypesDev(); - return mountSyncExternalStore(subscribe, getSnapshot); - }, - useId: function() { - currentHookNameInDev = "useId"; - mountHookTypesDev(); - return mountId(); - }, - unstable_isNewReconciler: enableNewReconciler - }; - - HooksDispatcherOnMountWithHookTypesInDEV = { - readContext: function(context) { - return readContext(context); - }, - 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; + function updateHostRoot(current, workInProgress, renderLanes) { + pushHostRootContext(workInProgress); - try { - return mountMemo(create, deps); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; + if (current === null) { + throw new Error("Should have a current fiber. This is a bug in React."); } - }, - 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; + var nextProps = workInProgress.pendingProps; + var prevState = workInProgress.memoizedState; + var prevChildren = prevState.element; + cloneUpdateQueue(current, workInProgress); + processUpdateQueue(workInProgress, nextProps, null, renderLanes); + var nextState = workInProgress.memoizedState; + var root = workInProgress.stateNode; + // being called "element". - try { - return mountState(initialState); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useDebugValue: function(value, formatterFn) { - currentHookNameInDev = "useDebugValue"; - updateHookTypesDev(); - return mountDebugValue(); - }, - useDeferredValue: function(value) { - currentHookNameInDev = "useDeferredValue"; - updateHookTypesDev(); - return mountDeferredValue(value); - }, - useTransition: function() { - currentHookNameInDev = "useTransition"; - updateHookTypesDev(); - return mountTransition(); - }, - useMutableSource: function(source, getSnapshot, subscribe) { - currentHookNameInDev = "useMutableSource"; - updateHookTypesDev(); - return mountMutableSource(); - }, - useSyncExternalStore: function(subscribe, getSnapshot, getServerSnapshot) { - currentHookNameInDev = "useSyncExternalStore"; - updateHookTypesDev(); - return mountSyncExternalStore(subscribe, getSnapshot); - }, - useId: function() { - currentHookNameInDev = "useId"; - updateHookTypesDev(); - return mountId(); - }, - unstable_isNewReconciler: enableNewReconciler - }; - - HooksDispatcherOnUpdateInDEV = { - readContext: function(context) { - return readContext(context); - }, - 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; + var nextChildren = nextState.element; - try { - return updateMemo(create, deps); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; + { + if (nextChildren === prevChildren) { + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); + } + + reconcileChildren(current, workInProgress, nextChildren, renderLanes); } - }, - 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 workInProgress.child; + } - try { - return updateState(initialState); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useDebugValue: function(value, formatterFn) { - currentHookNameInDev = "useDebugValue"; - updateHookTypesDev(); - return updateDebugValue(); - }, - useDeferredValue: function(value) { - currentHookNameInDev = "useDeferredValue"; - updateHookTypesDev(); - return updateDeferredValue(value); - }, - useTransition: function() { - currentHookNameInDev = "useTransition"; - updateHookTypesDev(); - return updateTransition(); - }, - useMutableSource: function(source, getSnapshot, subscribe) { - currentHookNameInDev = "useMutableSource"; - updateHookTypesDev(); - return updateMutableSource(); - }, - useSyncExternalStore: function(subscribe, getSnapshot, getServerSnapshot) { - currentHookNameInDev = "useSyncExternalStore"; - updateHookTypesDev(); - return updateSyncExternalStore(subscribe, getSnapshot); - }, - useId: function() { - currentHookNameInDev = "useId"; - updateHookTypesDev(); - return updateId(); - }, - unstable_isNewReconciler: enableNewReconciler - }; - - HooksDispatcherOnRerenderInDEV = { - readContext: function(context) { - return readContext(context); - }, - 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; + function updateHostComponent(current, workInProgress, renderLanes) { + pushHostContext(workInProgress); - try { - return updateMemo(create, deps); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; + var type = workInProgress.type; + var nextProps = workInProgress.pendingProps; + var prevProps = current !== null ? current.memoizedProps : null; + var nextChildren = nextProps.children; + + if (prevProps !== null && shouldSetTextContent()) { + // 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; } - }, - 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; + markRef(current, workInProgress); + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; + } - try { - return rerenderState(initialState); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useDebugValue: function(value, formatterFn) { - currentHookNameInDev = "useDebugValue"; - updateHookTypesDev(); - return updateDebugValue(); - }, - useDeferredValue: function(value) { - currentHookNameInDev = "useDeferredValue"; - updateHookTypesDev(); - return rerenderDeferredValue(value); - }, - useTransition: function() { - currentHookNameInDev = "useTransition"; - updateHookTypesDev(); - return rerenderTransition(); - }, - useMutableSource: function(source, getSnapshot, subscribe) { - currentHookNameInDev = "useMutableSource"; - updateHookTypesDev(); - return updateMutableSource(); - }, - useSyncExternalStore: function(subscribe, getSnapshot, getServerSnapshot) { - currentHookNameInDev = "useSyncExternalStore"; - updateHookTypesDev(); - return updateSyncExternalStore(subscribe, getSnapshot); - }, - useId: function() { - currentHookNameInDev = "useId"; - updateHookTypesDev(); - return updateId(); - }, - unstable_isNewReconciler: enableNewReconciler - }; - - InvalidNestedHooksDispatcherOnMountInDEV = { - readContext: function(context) { - warnInvalidContextAccess(); - return readContext(context); - }, - 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; + function updateHostText(current, workInProgress) { + // immediately after. - 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; + return null; + } - 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; + 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 + ); + } - try { - return mountState(initialState); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useDebugValue: function(value, formatterFn) { - currentHookNameInDev = "useDebugValue"; - warnInvalidHookAccess(); - mountHookTypesDev(); - return mountDebugValue(); - }, - useDeferredValue: function(value) { - currentHookNameInDev = "useDeferredValue"; - warnInvalidHookAccess(); - mountHookTypesDev(); - return mountDeferredValue(value); - }, - useTransition: function() { - currentHookNameInDev = "useTransition"; - warnInvalidHookAccess(); - mountHookTypesDev(); - return mountTransition(); - }, - useMutableSource: function(source, getSnapshot, subscribe) { - currentHookNameInDev = "useMutableSource"; - warnInvalidHookAccess(); - mountHookTypesDev(); - return mountMutableSource(); - }, - useSyncExternalStore: function(subscribe, getSnapshot, getServerSnapshot) { - currentHookNameInDev = "useSyncExternalStore"; - warnInvalidHookAccess(); - mountHookTypesDev(); - return mountSyncExternalStore(subscribe, getSnapshot); - }, - useId: function() { - currentHookNameInDev = "useId"; - warnInvalidHookAccess(); - mountHookTypesDev(); - return mountId(); - }, - unstable_isNewReconciler: enableNewReconciler - }; - - InvalidNestedHooksDispatcherOnUpdateInDEV = { - readContext: function(context) { - warnInvalidContextAccess(); - return readContext(context); - }, - 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; + child = updateFunctionComponent( + null, + workInProgress, + Component, + resolvedProps, + renderLanes + ); + return child; + } - 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; + case ClassComponent: { + { + workInProgress.type = Component = resolveClassForHotReloading( + Component + ); + } - 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; + child = updateClassComponent( + null, + workInProgress, + Component, + resolvedProps, + renderLanes + ); + return child; + } - try { - return updateState(initialState); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useDebugValue: function(value, formatterFn) { - currentHookNameInDev = "useDebugValue"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateDebugValue(); - }, - useDeferredValue: function(value) { - currentHookNameInDev = "useDeferredValue"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateDeferredValue(value); - }, - useTransition: function() { - currentHookNameInDev = "useTransition"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateTransition(); - }, - useMutableSource: function(source, getSnapshot, subscribe) { - currentHookNameInDev = "useMutableSource"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateMutableSource(); - }, - useSyncExternalStore: function(subscribe, getSnapshot, getServerSnapshot) { - currentHookNameInDev = "useSyncExternalStore"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateSyncExternalStore(subscribe, getSnapshot); - }, - useId: function() { - currentHookNameInDev = "useId"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateId(); - }, - unstable_isNewReconciler: enableNewReconciler - }; - - InvalidNestedHooksDispatcherOnRerenderInDEV = { - readContext: function(context) { - warnInvalidContextAccess(); - return readContext(context); - }, - 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; + case ForwardRef: { + { + workInProgress.type = Component = resolveForwardRefForHotReloading( + Component + ); + } - try { - return updateMemo(create, deps); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; + child = updateForwardRef( + null, + workInProgress, + Component, + resolvedProps, + renderLanes + ); + return child; + } + + case MemoComponent: { + { + if (workInProgress.type !== workInProgress.elementType) { + var outerPropTypes = Component.propTypes; + + if (outerPropTypes) { + checkPropTypes( + outerPropTypes, + resolvedProps, // Resolved for outer only + "prop", + getComponentNameFromType(Component) + ); + } + } + } + + child = updateMemoComponent( + null, + workInProgress, + Component, + resolveDefaultProps(Component.type, resolvedProps), // The inner type can have defaults too + renderLanes + ); + return child; + } } - }, - 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; + var hint = ""; - try { - return rerenderState(initialState); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useDebugValue: function(value, formatterFn) { - currentHookNameInDev = "useDebugValue"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateDebugValue(); - }, - useDeferredValue: function(value) { - currentHookNameInDev = "useDeferredValue"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return rerenderDeferredValue(value); - }, - useTransition: function() { - currentHookNameInDev = "useTransition"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return rerenderTransition(); - }, - useMutableSource: function(source, getSnapshot, subscribe) { - currentHookNameInDev = "useMutableSource"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateMutableSource(); - }, - useSyncExternalStore: function(subscribe, getSnapshot, getServerSnapshot) { - currentHookNameInDev = "useSyncExternalStore"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateSyncExternalStore(subscribe, getSnapshot); - }, - useId: function() { - currentHookNameInDev = "useId"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateId(); - }, - unstable_isNewReconciler: enableNewReconciler - }; -} + { + 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. -var now$1 = 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. - */ + 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) + ); + } -var currentUpdateIsNested = false; -var nestedUpdateScheduled = false; + function mountIncompleteClassComponent( + _current, + workInProgress, + Component, + nextProps, + renderLanes + ) { + resetSuspendedCurrentOnMountInLegacyMode(_current, workInProgress); // Promote the fiber to a class and try rendering again. -function isCurrentUpdateNested() { - return currentUpdateIsNested; -} + 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. -function markNestedUpdateScheduled() { - { - nestedUpdateScheduled = true; - } -} + var hasContext; -function resetNestedUpdateFlag() { - { - currentUpdateIsNested = false; - nestedUpdateScheduled = false; - } -} + if (isContextProvider(Component)) { + hasContext = true; + pushContextProvider(workInProgress); + } else { + hasContext = false; + } -function syncNestedUpdateFlag() { - { - currentUpdateIsNested = nestedUpdateScheduled; - nestedUpdateScheduled = false; - } -} + prepareToReadContext(workInProgress, renderLanes); + constructClassInstance(workInProgress, Component, nextProps); + mountClassInstance(workInProgress, Component, nextProps, renderLanes); + return finishClassComponent( + null, + workInProgress, + Component, + true, + hasContext, + renderLanes + ); + } -function getCommitTime() { - return commitTime; -} + function mountIndeterminateComponent( + _current, + workInProgress, + Component, + renderLanes + ) { + resetSuspendedCurrentOnMountInLegacyMode(_current, workInProgress); + var props = workInProgress.pendingProps; + var context; -function recordCommitTime() { - commitTime = now$1(); -} + { + var unmaskedContext = getUnmaskedContext(workInProgress, Component, false); + context = getMaskedContext(workInProgress, unmaskedContext); + } -function startProfilerTimer(fiber) { - profilerStartTime = now$1(); + prepareToReadContext(workInProgress, renderLanes); + var value; - if (fiber.actualStartTime < 0) { - fiber.actualStartTime = now$1(); - } -} + { + if ( + Component.prototype && + typeof Component.prototype.render === "function" + ) { + var componentName = getComponentNameFromType(Component) || "Unknown"; -function stopProfilerTimerIfRunning(fiber) { - profilerStartTime = -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 + ); -function stopProfilerTimerIfRunningAndRecordDelta(fiber, overrideBaseTime) { - if (profilerStartTime >= 0) { - var elapsedTime = now$1() - profilerStartTime; - fiber.actualDuration += elapsedTime; + didWarnAboutBadClass[componentName] = true; + } + } - if (overrideBaseTime) { - fiber.selfBaseDuration = elapsedTime; - } + if (workInProgress.mode & StrictLegacyMode) { + ReactStrictModeWarnings.recordLegacyContextWarning(workInProgress, null); + } - profilerStartTime = -1; - } -} + setIsRendering(true); + ReactCurrentOwner$1.current = workInProgress; + value = renderWithHooks( + null, + workInProgress, + Component, + props, + context, + renderLanes + ); + setIsRendering(false); + } -function recordLayoutEffectDuration(fiber) { - if (layoutEffectStartTime >= 0) { - var elapsedTime = now$1() - layoutEffectStartTime; - layoutEffectStartTime = -1; // Store duration on the next nearest Profiler ancestor - // Or the root (for the DevTools Profiler to read) + workInProgress.flags |= PerformedWork; - var parentFiber = fiber.return; + { + // 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"; - while (parentFiber !== null) { - switch (parentFiber.tag) { - case HostRoot: - var root = parentFiber.stateNode; - root.effectDuration += elapsedTime; - return; + 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 Profiler: - var parentStateNode = parentFiber.stateNode; - parentStateNode.effectDuration += elapsedTime; - return; + didWarnAboutModulePatternComponent[_componentName] = true; + } + } } - parentFiber = parentFiber.return; - } - } -} + if ( + // Run these checks in production only if the flag is off. + // Eventually we'll delete this branch altogether. + typeof value === "object" && + value !== null && + typeof value.render === "function" && + value.$$typeof === undefined + ) { + { + var _componentName2 = getComponentNameFromType(Component) || "Unknown"; -function recordPassiveEffectDuration(fiber) { - if (passiveEffectStartTime >= 0) { - var elapsedTime = now$1() - passiveEffectStartTime; - passiveEffectStartTime = -1; // Store duration on the next nearest Profiler ancestor - // Or the root (for the DevTools Profiler to read) + if (!didWarnAboutModulePatternComponent[_componentName2]) { + error( + "The <%s /> component appears to be a function component that returns a class instance. " + + "Change %s to a class that extends React.Component instead. " + + "If you can't use a class try assigning the prototype on the function as a workaround. " + + "`%s.prototype = React.Component.prototype`. Don't use an arrow function since it " + + "cannot be called with `new` by React.", + _componentName2, + _componentName2, + _componentName2 + ); - var parentFiber = fiber.return; + didWarnAboutModulePatternComponent[_componentName2] = true; + } + } // Proceed under the assumption that this is a class instance - while (parentFiber !== null) { - switch (parentFiber.tag) { - case HostRoot: - var root = parentFiber.stateNode; + workInProgress.tag = ClassComponent; // Throw out any hooks that were used. - if (root !== null) { - root.passiveEffectDuration += elapsedTime; - } + workInProgress.memoizedState = null; + workInProgress.updateQueue = null; // 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. - return; + var hasContext = false; - case Profiler: - var parentStateNode = parentFiber.stateNode; + if (isContextProvider(Component)) { + hasContext = true; + pushContextProvider(workInProgress); + } else { + hasContext = false; + } - 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; - } + workInProgress.memoizedState = + value.state !== null && value.state !== undefined ? value.state : null; + initializeUpdateQueue(workInProgress); + adoptClassInstance(workInProgress, value); + mountClassInstance(workInProgress, Component, props, renderLanes); + return finishClassComponent( + null, + workInProgress, + Component, + true, + hasContext, + renderLanes + ); + } else { + // Proceed under the assumption that this is a function component + workInProgress.tag = FunctionComponent; - return; - } + reconcileChildren(null, workInProgress, value, renderLanes); + + { + validateFunctionComponentInDev(workInProgress, Component); + } - parentFiber = parentFiber.return; + return workInProgress.child; + } } - } -} -function startLayoutEffectTimer() { - layoutEffectStartTime = now$1(); -} + 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 startPassiveEffectTimer() { - passiveEffectStartTime = now$1(); -} + if (workInProgress.ref !== null) { + var info = ""; + var ownerName = getCurrentFiberOwnerNameInDevOrNull(); -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 (ownerName) { + info += "\n\nCheck the render method of `" + ownerName + "`."; + } - while (child) { - fiber.actualDuration += child.actualDuration; - child = child.sibling; - } -} + var warningKey = ownerName || ""; + var debugSource = workInProgress._debugSource; -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 (debugSource) { + warningKey = debugSource.fileName + ":" + debugSource.lineNumber; + } -if ( - typeof ReactNativePrivateInterface.ReactFiberErrorDialog.showErrorDialog !== - "function" -) { - throw new Error( - "Expected ReactFiberErrorDialog.showErrorDialog to be a function." - ); -} + if (!didWarnAboutFunctionRefs[warningKey]) { + didWarnAboutFunctionRefs[warningKey] = true; -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 ReactNativePrivateInterface.ReactFiberErrorDialog.showErrorDialog( - capturedError - ); -} + error( + "Function components cannot be given refs. " + + "Attempts to access this ref will fail. " + + "Did you mean to use React.forwardRef()?%s", + info + ); + } + } -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 (typeof Component.getDerivedStateFromProps === "function") { + var _componentName3 = getComponentNameFromType(Component) || "Unknown"; - if (logError === false) { - return; - } + if (!didWarnAboutGetDerivedStateOnFunctionComponent[_componentName3]) { + error( + "%s: Function components do not support getDerivedStateFromProps.", + _componentName3 + ); + + didWarnAboutGetDerivedStateOnFunctionComponent[_componentName3] = true; + } + } + + if ( + typeof Component.contextType === "object" && + Component.contextType !== null + ) { + var _componentName4 = getComponentNameFromType(Component) || "Unknown"; - var error = errorInfo.value; + if (!didWarnAboutContextTypeOnFunctionComponent[_componentName4]) { + error( + "%s: Function components do not support contextType.", + _componentName4 + ); - 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. + didWarnAboutContextTypeOnFunctionComponent[_componentName4] = 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://react.dev/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 - } else { - // In production, we print the error directly. - // This will include the message, the JS stack, and anything the browser wants to show. - // We pass the error object instead of custom message so that the browser displays the error natively. - console["error"](error); // 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; - }); - } -} + var SUSPENDED_MARKER = { + dehydrated: null, + treeContext: null, + retryLane: NoLane + }; -var PossiblyWeakMap$1 = typeof WeakMap === "function" ? WeakMap : Map; + function mountSuspenseOffscreenState(renderLanes) { + return { + baseLanes: renderLanes, + cachePool: getSuspendedCache(), + transitions: null + }; + } -function createRootErrorUpdate(fiber, errorInfo, lane) { - var update = createUpdate(NoTimestamp, lane); // Unmount the root by rendering null. + function updateSuspenseOffscreenState(prevOffscreenState, renderLanes) { + var cachePool = null; - update.tag = CaptureUpdate; // Caution: React DevTools currently depends on this property - // being called "element". + return { + baseLanes: mergeLanes(prevOffscreenState.baseLanes, renderLanes), + cachePool: cachePool, + transitions: prevOffscreenState.transitions + }; + } // TODO: Probably should inline this back - update.payload = { - element: null - }; - var error = errorInfo.value; + function shouldRemainOnFallback( + suspenseContext, + 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. + 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. - update.callback = function() { - onUncaughtError(error); - logCapturedError(fiber, errorInfo); - }; + return hasSuspenseContext(suspenseContext, ForceSuspenseFallback); + } - return update; -} + function getRemainingWorkInPrimaryTree(current, renderLanes) { + // TODO: Should not remove render lanes that were pinged during this render + return removeLanes(current.childLanes, renderLanes); + } -function createClassErrorUpdate(fiber, errorInfo, lane) { - var update = createUpdate(NoTimestamp, lane); - update.tag = CaptureUpdate; - var getDerivedStateFromError = fiber.type.getDerivedStateFromError; + function updateSuspenseComponent(current, workInProgress, renderLanes) { + var nextProps = workInProgress.pendingProps; // This is used by DevTools to force a boundary to suspend. - if (typeof getDerivedStateFromError === "function") { - var error$1 = errorInfo.value; + { + if (shouldSuspend(workInProgress)) { + workInProgress.flags |= DidCapture; + } + } - update.payload = function() { - return getDerivedStateFromError(error$1); - }; + var suspenseContext = suspenseStackCursor.current; + var showFallback = false; + var didSuspend = (workInProgress.flags & DidCapture) !== NoFlags; - update.callback = function() { - { - markFailedErrorBoundaryForHotReloading(fiber); + if (didSuspend || shouldRemainOnFallback(suspenseContext, current)) { + // Something in this boundary's subtree already suspended. Switch to + // rendering the fallback children. + showFallback = true; + workInProgress.flags &= ~DidCapture; + } else { + // Attempting the main content + if (current === null || current.memoizedState !== null) { + // This is a new mount or this boundary is already showing a fallback state. + // Mark this subtree context as having at least one invisible parent that could + // handle the fallback state. + // Avoided boundaries are not considered since they cannot handle preferred fallback states. + { + suspenseContext = addSubtreeSuspenseContext( + suspenseContext, + InvisibleParentSuspenseContext + ); + } + } } - logCapturedError(fiber, errorInfo); - }; - } + suspenseContext = setDefaultShallowSuspenseContext(suspenseContext); + pushSuspenseContext(workInProgress, suspenseContext); // 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. - var inst = fiber.stateNode; + if (current === null) { + var suspenseState = workInProgress.memoizedState; - if (inst !== null && typeof inst.componentDidCatch === "function") { - update.callback = function callback() { - { - markFailedErrorBoundaryForHotReloading(fiber); - } + if (suspenseState !== null) { + var dehydrated = suspenseState.dehydrated; - logCapturedError(fiber, errorInfo); + if (dehydrated !== null) { + return mountDehydratedSuspenseComponent(workInProgress); + } + } - 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 nextPrimaryChildren = nextProps.children; + var nextFallbackChildren = nextProps.fallback; - var error$1 = errorInfo.value; - var stack = errorInfo.stack; - this.componentDidCatch(error$1, { - componentStack: stack !== null ? stack : "" - }); + if (showFallback) { + var fallbackFragment = mountSuspenseFallbackChildren( + workInProgress, + nextPrimaryChildren, + nextFallbackChildren, + renderLanes + ); + var primaryChildFragment = workInProgress.child; + primaryChildFragment.memoizedState = mountSuspenseOffscreenState( + renderLanes + ); + workInProgress.memoizedState = SUSPENDED_MARKER; - { - 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 fallbackFragment; + } else { + return mountSuspensePrimaryChildren(workInProgress, nextPrimaryChildren); + } + } else { + // This is an update. + // Special path for hydration + var prevState = current.memoizedState; + + if (prevState !== null) { + var _dehydrated = prevState.dehydrated; + + if (_dehydrated !== null) { + return updateDehydratedSuspenseComponent( + current, + workInProgress, + didSuspend, + nextProps, + _dehydrated, + prevState, + renderLanes ); } } - } - }; - } - return update; -} + if (showFallback) { + 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); + + _primaryChildFragment2.childLanes = getRemainingWorkInPrimaryTree( + current, + renderLanes + ); + workInProgress.memoizedState = SUSPENDED_MARKER; + return fallbackChildFragment; + } else { + var _nextPrimaryChildren2 = nextProps.children; -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$1(); - 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)) { - // Memoize using the thread ID to prevent redundant listeners. - threadIDs.add(lanes); - var ping = pingSuspendedRoot.bind(null, root, wakeable, lanes); + var _primaryChildFragment3 = updateSuspensePrimaryChildren( + current, + workInProgress, + _nextPrimaryChildren2, + renderLanes + ); - { - if (isDevToolsPresent) { - // If we have pending work still, restore the original updaters - restorePendingUpdaters(root, lanes); + workInProgress.memoizedState = null; + return _primaryChildFragment3; + } } } - wakeable.then(ping, ping); - } -} - -function attachRetryListener(suspenseBoundary, root, wakeable, lanes) { - // 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"). - var wakeables = suspenseBoundary.updateQueue; - - if (wakeables === null) { - var updateQueue = new Set(); - updateQueue.add(wakeable); - suspenseBoundary.updateQueue = updateQueue; - } else { - wakeables.add(wakeable); - } -} + 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; + } -function resetSuspendedComponent(sourceFiber, rootRenderLanes) { - // A legacy mode Suspense quirk, only relevant to hook components. + function mountSuspenseFallbackChildren( + workInProgress, + primaryChildren, + fallbackChildren, + renderLanes + ) { + var mode = workInProgress.mode; + var progressedPrimaryFragment = workInProgress.child; + var primaryChildProps = { + mode: "hidden", + children: primaryChildren + }; + var primaryChildFragment; + var fallbackChildFragment; - var tag = sourceFiber.tag; + 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; + } - if ( - (sourceFiber.mode & ConcurrentMode) === NoMode && - (tag === FunctionComponent || - tag === ForwardRef || - tag === SimpleMemoComponent) - ) { - var currentSource = sourceFiber.alternate; + fallbackChildFragment = createFiberFromFragment( + fallbackChildren, + mode, + renderLanes, + null + ); + } else { + primaryChildFragment = mountWorkInProgressOffscreenFiber( + primaryChildProps, + mode + ); + fallbackChildFragment = createFiberFromFragment( + fallbackChildren, + mode, + renderLanes, + null + ); + } - if (currentSource) { - sourceFiber.updateQueue = currentSource.updateQueue; - sourceFiber.memoizedState = currentSource.memoizedState; - sourceFiber.lanes = currentSource.lanes; - } else { - sourceFiber.updateQueue = null; - sourceFiber.memoizedState = null; + primaryChildFragment.return = workInProgress; + fallbackChildFragment.return = workInProgress; + primaryChildFragment.sibling = fallbackChildFragment; + workInProgress.child = primaryChildFragment; + return fallbackChildFragment; } - } -} -function getNearestSuspenseBoundaryToCapture(returnFiber) { - var node = returnFiber; + 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); + } - do { - if (node.tag === SuspenseComponent && shouldCaptureSuspense(node)) { - return node; - } // This boundary already captured during this render. Continue to the next - // boundary. + 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); + } - node = node.return; - } while (node !== null); + function updateSuspensePrimaryChildren( + current, + workInProgress, + primaryChildren, + renderLanes + ) { + var currentPrimaryChildFragment = current.child; + var currentFallbackChildFragment = currentPrimaryChildFragment.sibling; + var primaryChildFragment = updateWorkInProgressOffscreenFiber( + currentPrimaryChildFragment, + { + mode: "visible", + children: primaryChildren + } + ); - return null; -} + if ((workInProgress.mode & ConcurrentMode) === NoMode) { + primaryChildFragment.lanes = 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(NoTimestamp, 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; -} + primaryChildFragment.return = workInProgress; + primaryChildFragment.sibling = null; -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" && - typeof value.then === "function" - ) { - // This is a wakeable. The component suspended. - var wakeable = value; - resetSuspendedComponent(sourceFiber); - - var suspenseBoundary = getNearestSuspenseBoundaryToCapture(returnFiber); - - if (suspenseBoundary !== null) { - suspenseBoundary.flags &= ~ForceClientRender; - markSuspenseBoundaryShouldCapture( - suspenseBoundary, - returnFiber, - sourceFiber, - root, - rootRenderLanes - ); // We only attach ping listeners in concurrent mode. Legacy Suspense always - // commits fallbacks synchronously, so there are no pings. + if (currentFallbackChildFragment !== null) { + // Delete the fallback child fragment + var deletions = workInProgress.deletions; - if (suspenseBoundary.mode & ConcurrentMode) { - attachPingListener(root, wakeable, rootRenderLanes); - } - - attachRetryListener(suspenseBoundary, root, wakeable); - return; - } 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 (!includesSyncLane(rootRenderLanes)) { - // This is not a sync update. Suspend. Since we're not activating a - // Suspense boundary, this will unwind all the way to the root without - // performing a second pass to render a fallback. (This is arguably how - // refresh transitions should work, too, since we're not going to commit - // the fallbacks anyway.) - // - // This case also applies to initial hydration. - attachPingListener(root, wakeable, rootRenderLanes); - renderDidSuspendDelayIfPossible(); - return; - } // This is a sync/discrete update. We treat this case like an error - // because discrete renders are expected to produce a complete tree - // synchronously to maintain consistency with external state. - - var uncaughtSuspenseError = new Error( - "A component suspended while responding to synchronous input. This " + - "will cause the UI to be replaced with a loading indicator. To " + - "fix, updates that suspend should be wrapped " + - "with startTransition." - ); // If we're outside a transition, fall through to the regular error path. - // The error will be caught by the nearest suspense boundary. - - value = uncaughtSuspenseError; - } - } - - 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. - - var workInProgress = returnFiber; - - 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 (deletions === null) { + workInProgress.deletions = [currentFallbackChildFragment]; + workInProgress.flags |= ChildDeletion; + } else { + deletions.push(currentFallbackChildFragment); + } } - case ClassComponent: - // Capture and retry - var errorInfo = value; - var ctor = workInProgress.type; - var instance = workInProgress.stateNode; + workInProgress.child = primaryChildFragment; + return primaryChildFragment; + } - if ( - (workInProgress.flags & DidCapture) === NoFlags && - (typeof ctor.getDerivedStateFromError === "function" || - (instance !== null && - typeof instance.componentDidCatch === "function" && - !isAlreadyFailedLegacyErrorBoundary(instance))) - ) { - workInProgress.flags |= ShouldCapture; + 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.) - var _lane = pickArbitraryLane(rootRenderLanes); + primaryChildFragment.subtreeFlags = + currentPrimaryChildFragment.subtreeFlags & StaticMask; + } - workInProgress.lanes = mergeLanes(workInProgress.lanes, _lane); // Schedule the error boundary to re-render using updated state + var fallbackChildFragment; - var _update = createClassErrorUpdate( - workInProgress, - errorInfo, - _lane - ); + 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. - enqueueCapturedUpdate(workInProgress, _update); - return; - } + fallbackChildFragment.flags |= Placement; + } - break; + fallbackChildFragment.return = workInProgress; + primaryChildFragment.return = workInProgress; + primaryChildFragment.sibling = fallbackChildFragment; + workInProgress.child = primaryChildFragment; + return fallbackChildFragment; } - workInProgress = workInProgress.return; - } while (workInProgress !== null); -} + 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 -function getSuspendedCache() { - { - return null; - } // This function is called when a Suspense boundary suspends. It returns the -} + reconcileChildFibers(workInProgress, current.child, null, renderLanes); // We're now not suspended nor dehydrated. -var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner; -var didReceiveUpdate = false; -var didWarnAboutBadClass; -var didWarnAboutModulePatternComponent; -var didWarnAboutContextTypeOnFunctionComponent; -var didWarnAboutGetDerivedStateOnFunctionComponent; -var didWarnAboutFunctionRefs; -var didWarnAboutReassigningProps; -var didWarnAboutRevealOrder; -var didWarnAboutTailOptions; - -{ - didWarnAboutBadClass = {}; - didWarnAboutModulePatternComponent = {}; - didWarnAboutContextTypeOnFunctionComponent = {}; - didWarnAboutGetDerivedStateOnFunctionComponent = {}; - didWarnAboutFunctionRefs = {}; - didWarnAboutReassigningProps = false; - didWarnAboutRevealOrder = {}; - didWarnAboutTailOptions = {}; -} + 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. -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( + primaryChildFragment.flags |= Placement; + workInProgress.memoizedState = null; + return primaryChildFragment; + } + + 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); } + + return fallbackChildFragment; } - } - var render = Component.render; - var ref = workInProgress.ref; // The rest is a fork of updateFunctionComponent + function mountDehydratedSuspenseComponent( + workInProgress, + suspenseInstance, + renderLanes + ) { + // During the first pass, we'll bail out and not drill into the children. + // Instead, we'll leave the content in place and try to hydrate it later. + if ((workInProgress.mode & ConcurrentMode) === NoMode) { + { + error( + "Cannot hydrate Suspense in legacy mode. Switch from " + + "ReactDOM.hydrate(element, container) to " + + "ReactDOMClient.hydrateRoot(container, )" + + ".render(element) or remove the Suspense components from " + + "the server rendered components." + ); + } + + workInProgress.lanes = laneToLanes(SyncLane); + } else if (isSuspenseInstanceFallback()) { + // This is a client-only boundary. Since we won't get any content from the server + // for this, we need to schedule that at a higher priority based on when it would + // have timed out. In theory we could render it in this pass but it would have the + // wrong priority associated with it and will prevent hydration of parent path. + // Instead, we'll leave work left on it to render it in a separate commit. + // TODO This time should be the time at which the server rendered response that is + // a parent to this boundary was displayed. However, since we currently don't have + // a protocol to transfer that time, we'll just estimate it by using the current + // time. This will mean that Suspense timeouts are slightly shifted to later than + // they should be. + // Schedule a normal pri update to render this content. + workInProgress.lanes = laneToLanes(DefaultHydrationLane); + } else { + // We'll continue hydrating the rest at offscreen priority since we'll already + // be showing the right content coming from the server, it is no rush. + workInProgress.lanes = laneToLanes(OffscreenLane); + } - var nextChildren; - prepareToReadContext(workInProgress, renderLanes); + return null; + } - { - ReactCurrentOwner$1.current = workInProgress; - setIsRendering(true); - nextChildren = renderWithHooks( + function updateDehydratedSuspenseComponent( current, workInProgress, - render, + didSuspend, nextProps, - ref, + suspenseInstance, + suspenseState, renderLanes - ); + ) { + if (!didSuspend) { + if ((workInProgress.mode & ConcurrentMode) === NoMode) { + return retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, // TODO: When we delete legacy mode, we should make this error argument + // required — every concurrent mode path that causes hydration to + // de-opt to client rendering should have an error message. + null + ); + } - setIsRendering(false); - } + 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, message, stack; - if (current !== null && !didReceiveUpdate) { - bailoutHooks(current, workInProgress, renderLanes); - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); - } + { + var _getSuspenseInstanceF = getSuspenseInstanceFallbackErrorDetails(); - workInProgress.flags |= PerformedWork; - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; -} + digest = _getSuspenseInstanceF.digest; + message = _getSuspenseInstanceF.message; + stack = _getSuspenseInstanceF.stack; + } -function updateMemoComponent( - current, - workInProgress, - Component, - nextProps, - renderLanes -) { - if (current === null) { - var type = Component.type; + var error; - if ( - isSimpleFunctionComponent(type) && - Component.compare === null && // SimpleMemoComponent codepath doesn't resolve outer props either. - Component.defaultProps === undefined - ) { - var resolvedType = type; + 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." + ); + } - { - 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 capturedValue = createCapturedValue(error, digest, stack); + return retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, + capturedValue + ); + } + // any context has changed, we need to treat is as if the input might have changed. - workInProgress.tag = SimpleMemoComponent; - workInProgress.type = resolvedType; + var hasContextChanged = includesSomeLane(renderLanes, current.childLanes); - { - validateFunctionComponentInDev(workInProgress, type); - } + 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(); - return updateSimpleMemoComponent( - current, - workInProgress, - resolvedType, - nextProps, - renderLanes - ); + 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; // TODO: Ideally this would inherit the event time of the current render + + var eventTime = NoTimestamp; + enqueueConcurrentRenderForLane(current, attemptHydrationAtLane); + scheduleUpdateOnFiber( + root, + current, + attemptHydrationAtLane, + eventTime + ); + } + } // If we have scheduled higher pri work above, this will probably just abort the render + // since we now have higher priority work, but in case it doesn't, we need to prepare to + // render something, if we time out. Even if that requires us to delete everything and + // skip hydration. + // Delay having to do this as long as the suspense timeout allows us. + + renderDidSuspendDelayIfPossible(); + + var _capturedValue = createCapturedValue( + new Error( + "This Suspense boundary received an update before it finished " + + "hydrating. This caused the boundary to switch to client rendering. " + + "The usual way to fix this is to wrap the original update " + + "in startTransition." + ) + ); + + return retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, + _capturedValue + ); + } 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. + + var retry = retryDehydratedSuspenseBoundary.bind(null, current); + registerSuspenseInstanceRetry(); + return null; + } else { + // This is the first attempt. + reenterHydrationStateFromDehydratedSuspenseInstance( + workInProgress, + suspenseInstance, + suspenseState.treeContext + ); + 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. + workInProgress.flags &= ~ForceClientRender; + + var _capturedValue2 = createCapturedValue( + new Error( + "There was an error while hydrating this Suspense boundary. " + + "Switched to client rendering." + ) + ); + + return retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, + _capturedValue2 + ); + } else if (workInProgress.memoizedState !== null) { + // Something suspended and we should still be in dehydrated mode. + // Leave the existing child in place. + 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. + 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 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 child = createFiberFromTypeAndProps( - Component.type, - null, - nextProps, + function propagateSuspenseContextChange( workInProgress, - workInProgress.mode, + firstChild, 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) - ); - } - } - - var currentChild = current.child; // This is always exactly one child + ) { + // 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; + } - if (compare(prevProps, nextProps) && current.ref === workInProgress.ref) { - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); - } - } // React DevTools reads this flag. + while (node.sibling === null) { + 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; + } -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; } - } - } - } - if (current !== null) { - var prevProps = current.memoizedProps; - - 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) { - // This is a special case that only exists for legacy mode. - // See https://github.com/facebook/react/pull/19216. - didReceiveUpdate = true; + row = row.sibling; } + + return lastContentRow; } - } - return updateFunctionComponent( - current, - workInProgress, - Component, - nextProps, - renderLanes - ); -} + function validateRevealOrder(revealOrder) { + { + if ( + revealOrder !== undefined && + revealOrder !== "forwards" && + revealOrder !== "backwards" && + revealOrder !== "together" && + !didWarnAboutRevealOrder[revealOrder] + ) { + didWarnAboutRevealOrder[revealOrder] = true; -function updateOffscreenComponent(current, workInProgress, renderLanes) { - var nextProps = workInProgress.pendingProps; - var nextChildren = nextProps.children; - var prevState = current !== null ? current.memoizedState : null; - - if (nextProps.mode === "hidden" || enableLegacyHidden) { - // Rendering a hidden tree. - 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, - transitions: 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() + ); - pushRenderLanes(workInProgress, renderLanes); - } else if (!includesSomeLane(renderLanes, OffscreenLane)) { - var spawnedCachePool = null; // We're hidden, and we're not rendering at Offscreen. We will bail out - // and resume this tree later. + break; + } - var nextBaseLanes; + 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) { - var prevBaseLanes = prevState.baseLanes; - nextBaseLanes = mergeLanes(prevBaseLanes, renderLanes); - } else { - nextBaseLanes = renderLanes; - } // Schedule this fiber to re-render at offscreen priority. Then bailout. + break; + } - workInProgress.lanes = workInProgress.childLanes = laneToLanes( - OffscreenLane - ); - var _nextState = { - baseLanes: nextBaseLanes, - cachePool: spawnedCachePool, - transitions: null - }; - workInProgress.memoizedState = _nextState; - workInProgress.updateQueue = null; - // to avoid a push/pop misalignment. + default: + error( + '"%s" is not a supported revealOrder on . ' + + 'Did you mean "together", "forwards" or "backwards"?', + revealOrder + ); - pushRenderLanes(workInProgress, nextBaseLanes); + break; + } + } else { + error( + "%s is not a supported value for revealOrder on . " + + 'Did you mean "together", "forwards" or "backwards"?', + revealOrder + ); + } + } + } + } - return null; - } 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 _nextState2 = { - baseLanes: NoLanes, - cachePool: null, - transitions: null - }; - workInProgress.memoizedState = _nextState2; // Push the lanes that were skipped when we bailed out. + function validateTailOptions(tailMode, revealOrder) { + { + if (tailMode !== undefined && !didWarnAboutTailOptions[tailMode]) { + if (tailMode !== "collapsed" && tailMode !== "hidden") { + didWarnAboutTailOptions[tailMode] = true; - var subtreeRenderLanes = - prevState !== null ? prevState.baseLanes : renderLanes; + 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; - pushRenderLanes(workInProgress, subtreeRenderLanes); + error( + ' is only valid if revealOrder is ' + + '"forwards" or "backwards". ' + + 'Did you mean to specify revealOrder="forwards"?', + tailMode + ); + } + } + } } - } else { - // Rendering a visible tree. - var _subtreeRenderLanes; - if (prevState !== null) { - // We're going from hidden -> visible. - _subtreeRenderLanes = mergeLanes(prevState.baseLanes, renderLanes); - - 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. - _subtreeRenderLanes = renderLanes; - } + function validateSuspenseListNestedChild(childSlot, index) { + { + var isAnArray = isArray(childSlot); + var isIterable = + !isAnArray && typeof getIteratorFn(childSlot) === "function"; - pushRenderLanes(workInProgress, _subtreeRenderLanes); - } + if (isAnArray || isIterable) { + var type = isAnArray ? "array" : "iterable"; - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; -} // Note: These happen to have identical begin phases, for now. We shouldn't hold + error( + "A nested %s was passed to row #%s in . Wrap it in " + + "an additional SuspenseList to configure its revealOrder: " + + " ... " + + "{%s} ... " + + "", + type, + index, + type + ); -function updateFragment(current, workInProgress, renderLanes) { - var nextChildren = workInProgress.pendingProps; - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; -} + return false; + } + } -function updateMode(current, workInProgress, renderLanes) { - var nextChildren = workInProgress.pendingProps.children; - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; -} + return true; + } -function updateProfiler(current, workInProgress, renderLanes) { - { - workInProgress.flags |= Update; + 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); - { - // 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; -} + if (typeof iteratorFn === "function") { + var childrenIterator = iteratorFn.call(children); -function markRef(current, workInProgress) { - var ref = workInProgress.ref; + if (childrenIterator) { + var step = childrenIterator.next(); + var _i = 0; - if ( - (current === null && ref !== null) || - (current !== null && current.ref !== ref) - ) { - // Schedule a Ref effect - workInProgress.flags |= Ref; - } -} + for (; !step.done; step = childrenIterator.next()) { + if (!validateSuspenseListNestedChild(step.value, _i)) { + return; + } -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) - ); + _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 context; - - { - var unmaskedContext = getUnmaskedContext(workInProgress, Component, true); - context = getMaskedContext(workInProgress, unmaskedContext); - } - - var nextChildren; - prepareToReadContext(workInProgress, renderLanes); - { - ReactCurrentOwner$1.current = workInProgress; - setIsRendering(true); - nextChildren = renderWithHooks( - current, + function initSuspenseListRenderState( workInProgress, - Component, - nextProps, - context, - renderLanes - ); - - setIsRendering(false); - } - - if (current !== null && !didReceiveUpdate) { - bailoutHooks(current, workInProgress, renderLanes); - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); - } + isBackwards, + tail, + lastContentRow, + tailMode + ) { + var renderState = workInProgress.memoizedState; - workInProgress.flags |= PerformedWork; - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; -} + 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 = hasSuspenseContext( + suspenseContext, + ForceSuspenseFallback + ); -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 + if (shouldForceFallback) { + suspenseContext = setShallowSuspenseContext( + suspenseContext, + ForceSuspenseFallback ); - var state = tempInstance.state; - - _instance.updater.enqueueSetState(_instance, state, null); + workInProgress.flags |= DidCapture; + } else { + var didSuspendBefore = + current !== null && (current.flags & DidCapture) !== NoFlags; + + 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 + ); + } - break; + suspenseContext = setDefaultShallowSuspenseContext(suspenseContext); } - 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 + pushSuspenseContext(workInProgress, suspenseContext); - var update = createClassErrorUpdate( - workInProgress, - createCapturedValueAtFiber(error$1, workInProgress), - lane - ); - enqueueCapturedUpdate(workInProgress, update); - break; - } - } + 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; + } - 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; + initSuspenseListRenderState( + workInProgress, + false, // isBackwards + tail, + lastContentRow, + tailMode + ); + break; + } - 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. + 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 hasContext; + while (row !== null) { + var currentRow = row.alternate; // New rows can't be content rows. - if (isContextProvider(Component)) { - hasContext = true; - pushContextProvider(workInProgress); - } else { - hasContext = false; - } + if (currentRow !== null && findFirstSuspended(currentRow) === null) { + // This is the beginning of the main content. + workInProgress.child = row; + break; + } - prepareToReadContext(workInProgress, renderLanes); - var instance = workInProgress.stateNode; - var shouldUpdate; + 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; + } - if (instance === null) { - resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress); // In the initial pass we might need to construct the instance. + case "together": { + initSuspenseListRenderState( + workInProgress, + false, // isBackwards + null, // tail + null, // last + undefined + ); + break; + } - 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" - ); + default: { + // The default reveal order is the same as not having + // a boundary. + workInProgress.memoizedState = null; + } + } } - didWarnAboutReassigningProps = true; + return workInProgress.child; } - } - - return nextUnitOfWork; -} -function finishClassComponent( - current, - workInProgress, - Component, - shouldUpdate, - hasContext, - renderLanes -) { - // Refs should update even if shouldComponentUpdate returns false - markRef(current, workInProgress); - var didCaptureError = (workInProgress.flags & DidCapture) !== NoFlags; - - 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 updatePortalComponent(current, workInProgress, renderLanes) { + pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); + var nextChildren = workInProgress.pendingProps; - { - stopProfilerTimerIfRunning(); - } - } else { - { - setIsRendering(true); - nextChildren = instance.render(); + 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); + } - setIsRendering(false); + return workInProgress.child; } - } // 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( - 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. - - workInProgress.memoizedState = instance.state; // The context might have changed so we need to recalculate it. - if (hasContext) { - invalidateContextProvider(workInProgress, Component, true); - } - - return workInProgress.child; -} + var hasWarnedAboutUsingNoValuePropOnContextProvider = false; -function pushHostRootContext(workInProgress) { - var root = workInProgress.stateNode; + 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 (root.pendingContext) { - pushTopLevelContextObject( - workInProgress, - root.pendingContext, - root.pendingContext !== root.context - ); - } else if (root.context) { - // Should always be set - pushTopLevelContextObject(workInProgress, root.context, false); - } + { + if (!("value" in newProps)) { + if (!hasWarnedAboutUsingNoValuePropOnContextProvider) { + hasWarnedAboutUsingNoValuePropOnContextProvider = true; - pushHostContainer(workInProgress, root.containerInfo); -} + error( + "The `value` prop is required for the ``. Did you misspell it or forget to pass it?" + ); + } + } -function updateHostRoot(current, workInProgress, renderLanes) { - pushHostRootContext(workInProgress); + var providerPropTypes = workInProgress.type.propTypes; - if (current === null) { - throw new Error("Should have a current fiber. This is a bug in React."); - } + if (providerPropTypes) { + checkPropTypes(providerPropTypes, newProps, "prop", "Context.Provider"); + } + } - var nextProps = workInProgress.pendingProps; - var prevState = workInProgress.memoizedState; - var prevChildren = prevState.element; - cloneUpdateQueue(current, workInProgress); - processUpdateQueue(workInProgress, nextProps, null, renderLanes); - var nextState = workInProgress.memoizedState; - var root = workInProgress.stateNode; - // being called "element". + pushProvider(workInProgress, context, newValue); - var nextChildren = nextState.element; + { + if (oldProps !== null) { + var oldValue = oldProps.value; + + 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); + } + } + } - { - if (nextChildren === prevChildren) { - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); + var newChildren = newProps.children; + reconcileChildren(current, workInProgress, newChildren, renderLanes); + return workInProgress.child; } - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - } + var hasWarnedAboutUsingContextAsConsumer = false; - return workInProgress.child; -} + 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. -function updateHostComponent(current, workInProgress, renderLanes) { - pushHostContext(workInProgress); + { + 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 type = workInProgress.type; - var nextProps = workInProgress.pendingProps; - var prevProps = current !== null ? current.memoizedProps : null; - var nextChildren = nextProps.children; + 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 (prevProps !== null && shouldSetTextContent()) { - // 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; - } + var newProps = workInProgress.pendingProps; + var render = newProps.children; - markRef(current, workInProgress); - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; -} + { + 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." + ); + } + } -function updateHostText(current, workInProgress) { - // immediately after. + prepareToReadContext(workInProgress, renderLanes); + var newValue = readContext(context); - return null; -} + var newChildren; -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 - ); + ReactCurrentOwner$1.current = workInProgress; + setIsRendering(true); + newChildren = render(newValue); + setIsRendering(false); } - child = updateFunctionComponent( - null, - workInProgress, - Component, - resolvedProps, - renderLanes - ); - return child; + workInProgress.flags |= PerformedWork; + reconcileChildren(current, workInProgress, newChildren, renderLanes); + return workInProgress.child; + } + + function markWorkInProgressReceivedUpdate() { + didReceiveUpdate = 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 + + workInProgress.flags |= Placement; + } + } } - case ClassComponent: { - { - workInProgress.type = Component = resolveClassForHotReloading( - Component - ); + function bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) { + if (current !== null) { + // Reuse previous dependencies + workInProgress.dependencies = current.dependencies; } - child = updateClassComponent( - null, - workInProgress, - Component, - resolvedProps, - renderLanes - ); - return child; - } - - case ForwardRef: { { - workInProgress.type = Component = resolveForwardRefForHotReloading( - Component - ); + // Don't update "base" render times for bailouts. + stopProfilerTimerIfRunning(); } - child = updateForwardRef( - null, - workInProgress, - Component, - resolvedProps, - renderLanes - ); - return child; + markSkippedUpdateLanes(workInProgress.lanes); // Check if the children have any pending work. + + 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. + { + return null; + } + } // This fiber doesn't have work, but its subtree does. Clone the child + // fibers and continue. + + cloneChildFibers(current, workInProgress); + return workInProgress.child; } - case MemoComponent: { + function remountFiber(current, oldWorkInProgress, newWorkInProgress) { { - if (workInProgress.type !== workInProgress.elementType) { - var outerPropTypes = Component.propTypes; + var returnFiber = oldWorkInProgress.return; - if (outerPropTypes) { - checkPropTypes( - outerPropTypes, - resolvedProps, // Resolved for outer only - "prop", - getComponentNameFromType(Component) - ); + 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. + + current.alternate = null; + oldWorkInProgress.alternate = null; // Connect to the new tree. + + newWorkInProgress.index = oldWorkInProgress.index; + newWorkInProgress.sibling = oldWorkInProgress.sibling; + newWorkInProgress.return = oldWorkInProgress.return; + newWorkInProgress.ref = oldWorkInProgress.ref; // Replace the child/sibling pointers above it. + + if (oldWorkInProgress === returnFiber.child) { + returnFiber.child = newWorkInProgress; + } else { + var prevSibling = returnFiber.child; + + if (prevSibling === null) { + // eslint-disable-next-line react-internal/prod-error-codes + throw new Error("Expected parent to have a child."); } - } - } - child = updateMemoComponent( - null, - workInProgress, - Component, - resolveDefaultProps(Component.type, resolvedProps), // The inner type can have defaults too - renderLanes - ); - return child; - } - } + while (prevSibling.sibling !== oldWorkInProgress) { + prevSibling = prevSibling.sibling; - var hint = ""; + if (prevSibling === null) { + // eslint-disable-next-line react-internal/prod-error-codes + throw new Error("Expected to find the previous sibling."); + } + } - { - 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) - ); -} + prevSibling.sibling = newWorkInProgress; + } // Delete the old fiber and place the new one. + // Since the old fiber is disconnected, we have to schedule it manually. -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 - ); -} + var deletions = returnFiber.deletions; -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 ( - Component.prototype && - typeof Component.prototype.render === "function" - ) { - var componentName = getComponentNameFromType(Component) || "Unknown"; + if (deletions === null) { + returnFiber.deletions = [current]; + returnFiber.flags |= ChildDeletion; + } else { + deletions.push(current); + } - 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 - ); + newWorkInProgress.flags |= Placement; // Restart work from the new fiber. - didWarnAboutBadClass[componentName] = true; + return newWorkInProgress; } } - if (workInProgress.mode & StrictLegacyMode) { - ReactStrictModeWarnings.recordLegacyContextWarning(workInProgress, null); + 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 + + return false; } - setIsRendering(true); - ReactCurrentOwner$1.current = workInProgress; - value = renderWithHooks( - null, + function attemptEarlyBailoutIfNoScheduledUpdate( + current, workInProgress, - Component, - props, - context, renderLanes - ); - setIsRendering(false); - } + ) { + // 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); + var root = workInProgress.stateNode; + break; - workInProgress.flags |= PerformedWork; + case HostComponent: + pushHostContext(workInProgress); + 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 ClassComponent: { + var Component = workInProgress.type; - 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 (isContextProvider(Component)) { + pushContextProvider(workInProgress); + } - didWarnAboutModulePatternComponent[_componentName] = true; - } - } - } + break; + } - if ( - // Run these checks in production only if the flag is off. - // Eventually we'll delete this branch altogether. - typeof value === "object" && - value !== null && - typeof value.render === "function" && - value.$$typeof === undefined - ) { - { - var _componentName2 = getComponentNameFromType(Component) || "Unknown"; + case HostPortal: + pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); + break; - if (!didWarnAboutModulePatternComponent[_componentName2]) { - error( - "The <%s /> component appears to be a function component that returns a class instance. " + - "Change %s to a class that extends React.Component instead. " + - "If you can't use a class try assigning the prototype on the function as a workaround. " + - "`%s.prototype = React.Component.prototype`. Don't use an arrow function since it " + - "cannot be called with `new` by React.", - _componentName2, - _componentName2, - _componentName2 - ); + case ContextProvider: { + var newValue = workInProgress.memoizedProps.value; + var context = workInProgress.type._context; + pushProvider(workInProgress, context, newValue); + break; + } - didWarnAboutModulePatternComponent[_componentName2] = true; - } - } // Proceed under the assumption that this is a class instance + case Profiler: + { + // Profiler should only call onRender when one of its descendants actually rendered. + var hasChildWork = includesSomeLane( + renderLanes, + workInProgress.childLanes + ); - workInProgress.tag = ClassComponent; // Throw out any hooks that were used. + if (hasChildWork) { + workInProgress.flags |= Update; + } - workInProgress.memoizedState = null; - workInProgress.updateQueue = null; // 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. + { + // 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 hasContext = false; + break; - if (isContextProvider(Component)) { - hasContext = true; - pushContextProvider(workInProgress); - } else { - hasContext = false; - } + case SuspenseComponent: { + var state = workInProgress.memoizedState; - workInProgress.memoizedState = - value.state !== null && value.state !== undefined ? value.state : null; - initializeUpdateQueue(workInProgress); - adoptClassInstance(workInProgress, value); - mountClassInstance(workInProgress, Component, props, renderLanes); - return finishClassComponent( - null, - workInProgress, - Component, - true, - hasContext, - renderLanes - ); - } else { - // Proceed under the assumption that this is a function component - workInProgress.tag = FunctionComponent; + if (state !== null) { + if (state.dehydrated !== null) { + pushSuspenseContext( + workInProgress, + setDefaultShallowSuspenseContext(suspenseStackCursor.current) + ); // 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. - reconcileChildren(null, workInProgress, value, renderLanes); + workInProgress.flags |= DidCapture; // We should never render the children of a dehydrated boundary until we + // upgrade it. We return null instead of bailoutOnAlreadyFinishedWork. - { - validateFunctionComponentInDev(workInProgress, Component); - } + 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 workInProgress.child; - } -} + var primaryChildFragment = workInProgress.child; + var primaryChildLanes = primaryChildFragment.childLanes; -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 (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 + pushSuspenseContext( + workInProgress, + setDefaultShallowSuspenseContext(suspenseStackCursor.current) + ); // The primary children do not have pending work with sufficient + // priority. Bailout. + + var child = bailoutOnAlreadyFinishedWork( + current, + workInProgress, + renderLanes + ); - if (workInProgress.ref !== null) { - var info = ""; - var ownerName = getCurrentFiberOwnerNameInDevOrNull(); + 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 { + pushSuspenseContext( + workInProgress, + setDefaultShallowSuspenseContext(suspenseStackCursor.current) + ); + } - if (ownerName) { - info += "\n\nCheck the render method of `" + ownerName + "`."; - } + break; + } - var warningKey = ownerName || ""; - var debugSource = workInProgress._debugSource; + case SuspenseListComponent: { + var didSuspendBefore = (current.flags & DidCapture) !== NoFlags; - if (debugSource) { - warningKey = debugSource.fileName + ":" + debugSource.lineNumber; - } + var _hasChildWork = includesSomeLane( + renderLanes, + workInProgress.childLanes + ); - if (!didWarnAboutFunctionRefs[warningKey]) { - didWarnAboutFunctionRefs[warningKey] = true; + 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. - error( - "Function components cannot be given refs. " + - "Attempts to access this ref will fail. " + - "Did you mean to use React.forwardRef()?%s", - info - ); - } - } + 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 (typeof Component.getDerivedStateFromProps === "function") { - var _componentName3 = getComponentNameFromType(Component) || "Unknown"; + pushSuspenseContext(workInProgress, suspenseStackCursor.current); - if (!didWarnAboutGetDerivedStateOnFunctionComponent[_componentName3]) { - error( - "%s: Function components do not support getDerivedStateFromProps.", - _componentName3 - ); + 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; + } + } - didWarnAboutGetDerivedStateOnFunctionComponent[_componentName3] = true; + 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); + } } + + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); } - if ( - typeof Component.contextType === "object" && - Component.contextType !== null - ) { - var _componentName4 = getComponentNameFromType(Component) || "Unknown"; + function beginWork(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._debugOwner || null, + workInProgress.mode, + workInProgress.lanes + ) + ); + } + } - if (!didWarnAboutContextTypeOnFunctionComponent[_componentName4]) { - error( - "%s: Function components do not support contextType.", - _componentName4 - ); + if (current !== null) { + var oldProps = current.memoizedProps; + var newProps = workInProgress.pendingProps; - didWarnAboutContextTypeOnFunctionComponent[_componentName4] = true; - } - } - } -} + 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 SUSPENDED_MARKER = { - dehydrated: null, - treeContext: null, - retryLane: NoLane -}; - -function mountSuspenseOffscreenState(renderLanes) { - return { - baseLanes: renderLanes, - cachePool: getSuspendedCache(), - transitions: null - }; -} + 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 + ) { + // No pending updates or context. Bail out now. + didReceiveUpdate = false; + return attemptEarlyBailoutIfNoScheduledUpdate( + current, + workInProgress, + renderLanes + ); + } -function updateSuspenseOffscreenState(prevOffscreenState, renderLanes) { - var cachePool = null; - - return { - baseLanes: mergeLanes(prevOffscreenState.baseLanes, renderLanes), - cachePool: cachePool, - transitions: prevOffscreenState.transitions - }; -} // TODO: Probably should inline this back - -function shouldRemainOnFallback( - suspenseContext, - 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. - 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. + if ((current.flags & ForceUpdateForLegacySuspense) !== NoFlags) { + // 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. - return hasSuspenseContext(suspenseContext, ForceSuspenseFallback); -} + workInProgress.lanes = NoLanes; -function getRemainingWorkInPrimaryTree(current, renderLanes) { - // TODO: Should not remove render lanes that were pinged during this render - return removeLanes(current.childLanes, renderLanes); -} + switch (workInProgress.tag) { + case IndeterminateComponent: { + return mountIndeterminateComponent( + current, + workInProgress, + workInProgress.type, + 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 suspenseContext = suspenseStackCursor.current; - var showFallback = false; - var didSuspend = (workInProgress.flags & DidCapture) !== NoFlags; - - if (didSuspend || shouldRemainOnFallback(suspenseContext, current)) { - // Something in this boundary's subtree already suspended. Switch to - // rendering the fallback children. - showFallback = true; - workInProgress.flags &= ~DidCapture; - } else { - // Attempting the main content - if (current === null || current.memoizedState !== null) { - // This is a new mount or this boundary is already showing a fallback state. - // Mark this subtree context as having at least one invisible parent that could - // handle the fallback state. - // Avoided boundaries are not considered since they cannot handle preferred fallback states. - { - suspenseContext = addSubtreeSuspenseContext( - suspenseContext, - InvisibleParentSuspenseContext - ); - } - } - } - - suspenseContext = setDefaultShallowSuspenseContext(suspenseContext); - pushSuspenseContext(workInProgress, suspenseContext); // 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 suspenseState = workInProgress.memoizedState; - - if (suspenseState !== null) { - var dehydrated = suspenseState.dehydrated; - - if (dehydrated !== null) { - return mountDehydratedSuspenseComponent(workInProgress); - } - } - - var nextPrimaryChildren = nextProps.children; - var nextFallbackChildren = nextProps.fallback; - - if (showFallback) { - var fallbackFragment = mountSuspenseFallbackChildren( - workInProgress, - nextPrimaryChildren, - nextFallbackChildren, - renderLanes - ); - var primaryChildFragment = workInProgress.child; - primaryChildFragment.memoizedState = mountSuspenseOffscreenState( - renderLanes - ); - workInProgress.memoizedState = SUSPENDED_MARKER; + case LazyComponent: { + var elementType = workInProgress.elementType; + return mountLazyComponent( + current, + workInProgress, + elementType, + renderLanes + ); + } - return fallbackFragment; - } else { - return mountSuspensePrimaryChildren(workInProgress, nextPrimaryChildren); - } - } else { - // This is an update. - // Special path for hydration - var prevState = current.memoizedState; + 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 (prevState !== null) { - var _dehydrated = prevState.dehydrated; + case ClassComponent: { + var _Component = workInProgress.type; + var _unresolvedProps = workInProgress.pendingProps; - if (_dehydrated !== null) { - return updateDehydratedSuspenseComponent( - current, - workInProgress, - didSuspend, - nextProps, - _dehydrated, - prevState, - renderLanes - ); - } - } + var _resolvedProps = + workInProgress.elementType === _Component + ? _unresolvedProps + : resolveDefaultProps(_Component, _unresolvedProps); - if (showFallback) { - 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); - - _primaryChildFragment2.childLanes = getRemainingWorkInPrimaryTree( - current, - renderLanes - ); - workInProgress.memoizedState = SUSPENDED_MARKER; - return fallbackChildFragment; - } else { - var _nextPrimaryChildren2 = nextProps.children; + return updateClassComponent( + current, + workInProgress, + _Component, + _resolvedProps, + renderLanes + ); + } - var _primaryChildFragment3 = updateSuspensePrimaryChildren( - current, - workInProgress, - _nextPrimaryChildren2, - renderLanes - ); + case HostRoot: + return updateHostRoot(current, workInProgress, renderLanes); - workInProgress.memoizedState = null; - return _primaryChildFragment3; - } - } -} + case HostComponent: + return updateHostComponent(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 HostText: + return updateHostText(); -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 SuspenseComponent: + return updateSuspenseComponent(current, workInProgress, renderLanes); - primaryChildFragment.return = workInProgress; - fallbackChildFragment.return = workInProgress; - primaryChildFragment.sibling = fallbackChildFragment; - workInProgress.child = primaryChildFragment; - return fallbackChildFragment; -} + case HostPortal: + return updatePortalComponent(current, workInProgress, renderLanes); -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); -} + case ForwardRef: { + var type = workInProgress.type; + var _unresolvedProps2 = workInProgress.pendingProps; + + var _resolvedProps2 = + workInProgress.elementType === type + ? _unresolvedProps2 + : resolveDefaultProps(type, _unresolvedProps2); + + return updateForwardRef( + current, + workInProgress, + type, + _resolvedProps2, + 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 Fragment: + return updateFragment(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 Mode: + return updateMode(current, workInProgress, renderLanes); - if ((workInProgress.mode & ConcurrentMode) === NoMode) { - primaryChildFragment.lanes = renderLanes; - } + case Profiler: + return updateProfiler(current, workInProgress, renderLanes); - primaryChildFragment.return = workInProgress; - primaryChildFragment.sibling = null; + case ContextProvider: + return updateContextProvider(current, workInProgress, renderLanes); - if (currentFallbackChildFragment !== null) { - // Delete the fallback child fragment - var deletions = workInProgress.deletions; + case ContextConsumer: + return updateContextConsumer(current, workInProgress, renderLanes); - if (deletions === null) { - workInProgress.deletions = [currentFallbackChildFragment]; - workInProgress.flags |= ChildDeletion; - } else { - deletions.push(currentFallbackChildFragment); - } - } + case MemoComponent: { + var _type2 = workInProgress.type; + var _unresolvedProps3 = workInProgress.pendingProps; // Resolve outer props first, then resolve inner props. - workInProgress.child = primaryChildFragment; - return primaryChildFragment; -} + var _resolvedProps3 = resolveDefaultProps(_type2, _unresolvedProps3); -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; -} + { + if (workInProgress.type !== workInProgress.elementType) { + var outerPropTypes = _type2.propTypes; + + if (outerPropTypes) { + checkPropTypes( + outerPropTypes, + _resolvedProps3, // Resolved for outer only + "prop", + getComponentNameFromType(_type2) + ); + } + } + } -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; -} + _resolvedProps3 = resolveDefaultProps(_type2.type, _resolvedProps3); + return updateMemoComponent( + current, + workInProgress, + _type2, + _resolvedProps3, + renderLanes + ); + } -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; -} + case SimpleMemoComponent: { + return updateSimpleMemoComponent( + current, + workInProgress, + workInProgress.type, + workInProgress.pendingProps, + renderLanes + ); + } -function mountDehydratedSuspenseComponent( - workInProgress, - suspenseInstance, - renderLanes -) { - // During the first pass, we'll bail out and not drill into the children. - // Instead, we'll leave the content in place and try to hydrate it later. - if ((workInProgress.mode & ConcurrentMode) === NoMode) { - { - error( - "Cannot hydrate Suspense in legacy mode. Switch from " + - "ReactDOM.hydrate(element, container) to " + - "ReactDOMClient.hydrateRoot(container, )" + - ".render(element) or remove the Suspense components from " + - "the server rendered components." - ); - } + case IncompleteClassComponent: { + var _Component2 = workInProgress.type; + var _unresolvedProps4 = workInProgress.pendingProps; - workInProgress.lanes = laneToLanes(SyncLane); - } else if (isSuspenseInstanceFallback()) { - // This is a client-only boundary. Since we won't get any content from the server - // for this, we need to schedule that at a higher priority based on when it would - // have timed out. In theory we could render it in this pass but it would have the - // wrong priority associated with it and will prevent hydration of parent path. - // Instead, we'll leave work left on it to render it in a separate commit. - // TODO This time should be the time at which the server rendered response that is - // a parent to this boundary was displayed. However, since we currently don't have - // a protocol to transfer that time, we'll just estimate it by using the current - // time. This will mean that Suspense timeouts are slightly shifted to later than - // they should be. - // Schedule a normal pri update to render this content. - workInProgress.lanes = laneToLanes(DefaultHydrationLane); - } else { - // We'll continue hydrating the rest at offscreen priority since we'll already - // be showing the right content coming from the server, it is no rush. - workInProgress.lanes = laneToLanes(OffscreenLane); - } - - return null; -} + var _resolvedProps4 = + workInProgress.elementType === _Component2 + ? _unresolvedProps4 + : resolveDefaultProps(_Component2, _unresolvedProps4); -function updateDehydratedSuspenseComponent( - current, - workInProgress, - didSuspend, - nextProps, - suspenseInstance, - suspenseState, - renderLanes -) { - if (!didSuspend) { - if ((workInProgress.mode & ConcurrentMode) === NoMode) { - return retrySuspenseComponentWithoutHydrating( - current, - workInProgress, - renderLanes, // TODO: When we delete legacy mode, we should make this error argument - // required — every concurrent mode path that causes hydration to - // de-opt to client rendering should have an error message. - null - ); - } + return mountIncompleteClassComponent( + current, + workInProgress, + _Component2, + _resolvedProps4, + 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, message, stack; + case SuspenseListComponent: { + return updateSuspenseListComponent(current, workInProgress, renderLanes); + } - { - var _getSuspenseInstanceF = getSuspenseInstanceFallbackErrorDetails(); + case ScopeComponent: { + break; + } - digest = _getSuspenseInstanceF.digest; - message = _getSuspenseInstanceF.message; - stack = _getSuspenseInstanceF.stack; + case OffscreenComponent: { + return updateOffscreenComponent(current, workInProgress, renderLanes); + } } - var error; + 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 (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." - ); - } + function markUpdate(workInProgress) { + // Tag the fiber with an update effect. This turns a Placement into + // a PlacementAndUpdate. + workInProgress.flags |= Update; + } - var capturedValue = createCapturedValue(error, digest, stack); - return retrySuspenseComponentWithoutHydrating( - current, - workInProgress, - renderLanes, - capturedValue - ); + function markRef$1(workInProgress) { + workInProgress.flags |= Ref; } - // any context has changed, we need to treat is as if the input might have changed. - var hasContextChanged = includesSomeLane(renderLanes, current.childLanes); + function hadNoMutationsEffects(current, completedWork) { + var didBailout = current !== null && current.child === completedWork.child; - 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 (didBailout) { + return true; + } - if (root !== null) { - var attemptHydrationAtLane = getBumpedLaneForHydration( - root, - renderLanes - ); + if ((completedWork.flags & ChildDeletion) !== NoFlags) { + return false; + } // TODO: If we move the `hadNoMutationsEffects` call after `bubbleProperties` + // then we only have to check the `completedWork.subtreeFlags`. + + var child = completedWork.child; + while (child !== null) { if ( - attemptHydrationAtLane !== NoLane && - attemptHydrationAtLane !== suspenseState.retryLane + (child.flags & MutationMask) !== NoFlags || + (child.subtreeFlags & MutationMask) !== NoFlags ) { - // 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; // TODO: Ideally this would inherit the event time of the current render - - var eventTime = NoTimestamp; - enqueueConcurrentRenderForLane(current, attemptHydrationAtLane); - scheduleUpdateOnFiber( - root, - current, - attemptHydrationAtLane, - eventTime - ); + return false; } - } // If we have scheduled higher pri work above, this will probably just abort the render - // since we now have higher priority work, but in case it doesn't, we need to prepare to - // render something, if we time out. Even if that requires us to delete everything and - // skip hydration. - // Delay having to do this as long as the suspense timeout allows us. - - renderDidSuspendDelayIfPossible(); - var _capturedValue = createCapturedValue( - new Error( - "This Suspense boundary received an update before it finished " + - "hydrating. This caused the boundary to switch to client rendering. " + - "The usual way to fix this is to wrap the original update " + - "in startTransition." - ) - ); + child = child.sibling; + } - return retrySuspenseComponentWithoutHydrating( - current, - workInProgress, - renderLanes, - _capturedValue - ); - } 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. - - var retry = retryDehydratedSuspenseBoundary.bind(null, current); - registerSuspenseInstanceRetry(); - return null; - } else { - // This is the first attempt. - reenterHydrationStateFromDehydratedSuspenseInstance( - workInProgress, - suspenseInstance, - suspenseState.treeContext - ); - 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; + return true; } - } 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. - workInProgress.flags &= ~ForceClientRender; - - var _capturedValue2 = createCapturedValue( - new Error( - "There was an error while hydrating this Suspense boundary. " + - "Switched to client rendering." - ) - ); - return retrySuspenseComponentWithoutHydrating( - current, - workInProgress, - renderLanes, - _capturedValue2 - ); - } else if (workInProgress.memoizedState !== null) { - // Something suspended and we should still be in dehydrated mode. - // Leave the existing child in place. - workInProgress.child = current.child; // The dehydrated completion pass expects this flag to be there - // but the normal suspense pass doesn't. + var appendAllChildren; + var updateHostContainer; + var updateHostComponent$1; + var updateHostText$1; - workInProgress.flags |= DidCapture; - return null; - } else { - // Suspended but we should no longer be in dehydrated mode. - // Therefore we now have to render the fallback. - var nextPrimaryChildren = nextProps.children; - var nextFallbackChildren = nextProps.fallback; - var fallbackChildFragment = mountSuspenseFallbackAfterRetryWithoutHydrating( - current, + { + // Persistent host tree mode + appendAllChildren = function ( + parent, workInProgress, - nextPrimaryChildren, - nextFallbackChildren, - renderLanes - ); - var _primaryChildFragment4 = workInProgress.child; - _primaryChildFragment4.memoizedState = mountSuspenseOffscreenState( - renderLanes - ); - workInProgress.memoizedState = SUSPENDED_MARKER; - return fallbackChildFragment; - } - } -} + 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) { + // eslint-disable-next-line no-labels + if (node.tag === HostComponent) { + var instance = node.stateNode; + + if (needsVisibilityToggle && isHidden) { + // This child is inside a timed out tree. Hide it. + var props = node.memoizedProps; + var type = node.type; + instance = cloneHiddenInstance(instance); + } -function scheduleSuspenseWorkOnFiber(fiber, renderLanes, propagationRoot) { - fiber.lanes = mergeLanes(fiber.lanes, renderLanes); - var alternate = fiber.alternate; + appendInitialChild(parent, instance); + } else if (node.tag === HostText) { + var _instance = node.stateNode; - if (alternate !== null) { - alternate.lanes = mergeLanes(alternate.lanes, renderLanes); - } + if (needsVisibilityToggle && isHidden) { + // This child is inside a timed out tree. Hide it. + var text = node.memoizedProps; + _instance = cloneHiddenTextInstance(); + } - scheduleContextWorkOnParentPath(fiber.return, renderLanes, propagationRoot); -} + appendInitialChild(parent, _instance); + } else if (node.tag === HostPortal); + else if (node.tag === OffscreenComponent && node.memoizedState !== null) { + // The children in this boundary are hidden. Toggle their visibility + // before appending. + var child = node.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; - } - - while (node.sibling === null) { - if (node.return === null || node.return === workInProgress) { - return; - } + if (child !== null) { + child.return = node; + } - node = node.return; - } + appendAllChildren(parent, node, true, true); + } else if (node.child !== null) { + node.child.return = node; + node = node.child; + continue; + } // $FlowFixMe This is correct but Flow is confused by the labeled break. - node.sibling.return = node.return; - node = node.sibling; - } -} + node = node; -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 (node === workInProgress) { + return; + } - while (row !== null) { - var currentRow = row.alternate; // New rows can't be content rows. + while (node.sibling === null) { + if (node.return === null || node.return === workInProgress) { + return; + } - if (currentRow !== null && findFirstSuspended(currentRow) === null) { - lastContentRow = row; - } + node = node.return; + } - row = row.sibling; - } + node.sibling.return = node.return; + node = node.sibling; + } + }; // An unfortunate fork of appendAllChildren because we have two different parent types. - return lastContentRow; -} + var appendAllChildrenToContainer = function ( + containerChildSet, + 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) { + // eslint-disable-next-line no-labels + if (node.tag === HostComponent) { + var instance = node.stateNode; + + if (needsVisibilityToggle && isHidden) { + // This child is inside a timed out tree. Hide it. + var props = node.memoizedProps; + var type = node.type; + instance = cloneHiddenInstance(instance); + } -function validateRevealOrder(revealOrder) { - { - if ( - revealOrder !== undefined && - revealOrder !== "forwards" && - revealOrder !== "backwards" && - revealOrder !== "together" && - !didWarnAboutRevealOrder[revealOrder] - ) { - didWarnAboutRevealOrder[revealOrder] = true; + appendChildToContainerChildSet(containerChildSet, instance); + } else if (node.tag === HostText) { + var _instance2 = node.stateNode; - 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 (needsVisibilityToggle && isHidden) { + // This child is inside a timed out tree. Hide it. + var text = node.memoizedProps; + _instance2 = cloneHiddenTextInstance(); + } - break; - } + appendChildToContainerChildSet(containerChildSet, _instance2); + } else if (node.tag === HostPortal); + else if (node.tag === OffscreenComponent && node.memoizedState !== null) { + // The children in this boundary are hidden. Toggle their visibility + // before appending. + var child = node.child; - 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 (child !== null) { + child.return = node; + } - break; + appendAllChildrenToContainer(containerChildSet, node, true, true); + } else if (node.child !== null) { + node.child.return = node; + node = node.child; + continue; + } // $FlowFixMe This is correct but Flow is confused by the labeled break. + + node = node; + + if (node === workInProgress) { + return; } - default: - error( - '"%s" is not a supported revealOrder on . ' + - 'Did you mean "together", "forwards" or "backwards"?', - revealOrder - ); + while (node.sibling === null) { + if (node.return === null || node.return === workInProgress) { + return; + } - break; + node = node.return; + } + + node.sibling.return = node.return; + node = node.sibling; } - } else { - error( - "%s is not a supported value for revealOrder on . " + - 'Did you mean "together", "forwards" or "backwards"?', - revealOrder - ); - } - } - } -} + }; -function validateTailOptions(tailMode, revealOrder) { - { - if (tailMode !== undefined && !didWarnAboutTailOptions[tailMode]) { - if (tailMode !== "collapsed" && tailMode !== "hidden") { - didWarnAboutTailOptions[tailMode] = true; + updateHostContainer = function (current, workInProgress) { + var portalOrRoot = workInProgress.stateNode; + var childrenUnchanged = hadNoMutationsEffects(current, workInProgress); - 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 (childrenUnchanged); + else { + var container = portalOrRoot.containerInfo; + var newChildSet = createContainerChildSet(container); // If children might have changed, we have to add them all to the set. - error( - ' is only valid if revealOrder is ' + - '"forwards" or "backwards". ' + - 'Did you mean to specify revealOrder="forwards"?', - tailMode - ); - } - } - } -} + appendAllChildrenToContainer(newChildSet, workInProgress, false, false); + portalOrRoot.pendingChildren = newChildSet; // Schedule an update on the container to swap out the container. + + markUpdate(workInProgress); + finalizeContainerChildren(container, newChildSet); + } + }; -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} ... " + - "", + updateHostComponent$1 = function ( + current, + workInProgress, type, - index, - type - ); + newProps, + rootContainerInstance + ) { + var currentInstance = current.stateNode; + var oldProps = current.memoizedProps; // If there are no effects associated with this node, then none of our children had any updates. + // This guarantees that we can reuse all of them. - return false; - } - } + var childrenUnchanged = hadNoMutationsEffects(current, workInProgress); - return true; -} + if (childrenUnchanged && oldProps === newProps) { + // No changes, just reuse the existing instance. + // Note that this might release a previous clone. + workInProgress.stateNode = currentInstance; + return; + } -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; - } + var recyclableInstance = workInProgress.stateNode; + var currentHostContext = getHostContext(); + var updatePayload = null; + + if (oldProps !== newProps) { + updatePayload = prepareUpdate( + recyclableInstance, + type, + oldProps, + newProps + ); } - } else { - var iteratorFn = getIteratorFn(children); - if (typeof iteratorFn === "function") { - var childrenIterator = iteratorFn.call(children); + if (childrenUnchanged && updatePayload === null) { + // No changes, just reuse the existing instance. + // Note that this might release a previous clone. + workInProgress.stateNode = currentInstance; + return; + } - if (childrenIterator) { - var step = childrenIterator.next(); - var _i = 0; + var newInstance = cloneInstance( + currentInstance, + updatePayload, + type, + oldProps, + newProps, + workInProgress, + childrenUnchanged + ); - for (; !step.done; step = childrenIterator.next()) { - if (!validateSuspenseListNestedChild(step.value, _i)) { - return; - } + workInProgress.stateNode = newInstance; - _i++; - } - } + if (childrenUnchanged) { + // If there are no other effects in this tree, we need to flag this node as having one. + // Even though we're not going to use it for anything. + // Otherwise parents won't know that there are new children to propagate upwards. + markUpdate(workInProgress); } 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 - ); + // If children might have changed, we have to add them all to the set. + appendAllChildren(newInstance, workInProgress, false, false); } - } - } - } -} + }; -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 = hasSuspenseContext( - suspenseContext, - ForceSuspenseFallback - ); - - if (shouldForceFallback) { - suspenseContext = setShallowSuspenseContext( - suspenseContext, - ForceSuspenseFallback - ); - workInProgress.flags |= DidCapture; - } else { - var didSuspendBefore = - current !== null && (current.flags & DidCapture) !== NoFlags; - - 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 - ); + updateHostText$1 = function (current, workInProgress, oldText, newText) { + if (oldText !== newText) { + // If the text content differs, we'll create a new text instance for it. + var rootContainerInstance = getRootHostContainer(); + var currentHostContext = getHostContext(); + workInProgress.stateNode = createTextInstance( + newText, + rootContainerInstance, + currentHostContext, + workInProgress + ); // We'll have to mark it as having an effect, even though we won't use the effect for anything. + // This lets the parents know that at least one of their children has changed. + + markUpdate(workInProgress); + } else { + workInProgress.stateNode = current.stateNode; + } + }; } - suspenseContext = setDefaultShallowSuspenseContext(suspenseContext); - } + 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; + } - pushSuspenseContext(workInProgress, suspenseContext); + tailNode = tailNode.sibling; + } // Next we're simply going to delete all insertions after the + // last rendered item. - 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 (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; + } - 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; + break; } - initSuspenseListRenderState( - workInProgress, - false, // isBackwards - tail, - lastContentRow, - tailMode - ); - 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; + } + + _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. + 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; + } } + } - 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; + function bubbleProperties(completedWork) { + var didBailout = + completedWork.alternate !== null && + completedWork.alternate.child === completedWork.child; + var newChildLanes = NoLanes; + var subtreeFlags = NoFlags; - while (row !== null) { - var currentRow = row.alternate; // New rows can't be content rows. + 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; - if (currentRow !== null && findFirstSuspended(currentRow) === null) { - // This is the beginning of the main content. - workInProgress.child = row; - 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. + + actualDuration += child.actualDuration; + treeBaseDuration += child.treeBaseDuration; + child = child.sibling; } - var nextRow = row.sibling; - row.sibling = _tail; - _tail = row; - row = nextRow; - } // TODO: If workInProgress.child is null, we can continue on the tail immediately. + completedWork.actualDuration = actualDuration; + completedWork.treeBaseDuration = treeBaseDuration; + } else { + var _child = completedWork.child; - initSuspenseListRenderState( - workInProgress, - true, // isBackwards - _tail, - null, // last - tailMode - ); - 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 "together": { - initSuspenseListRenderState( - workInProgress, - false, // isBackwards - null, // tail - null, // last - undefined - ); - break; - } + _child.return = completedWork; + _child = _child.sibling; + } + } + + 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; + _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; + } + } - default: { - // The default reveal order is the same as not having - // a boundary. - workInProgress.memoizedState = null; + completedWork.subtreeFlags |= subtreeFlags; } - } - } - return workInProgress.child; -} + completedWork.childLanes = newChildLanes; + return didBailout; + } -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( + function completeDehydratedSuspenseBoundary( + current, workInProgress, - null, - nextChildren, - renderLanes - ); - } else { - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - } + nextState + ) { + var wasHydrated = popHydrationState(); - return workInProgress.child; -} + 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 hasWarnedAboutUsingNoValuePropOnContextProvider = false; + prepareToHydrateHostSuspenseInstance(); + bubbleProperties(workInProgress); -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 ((workInProgress.mode & ProfileMode) !== NoMode) { + var isTimedOutSuspense = nextState !== null; - { - if (!("value" in newProps)) { - if (!hasWarnedAboutUsingNoValuePropOnContextProvider) { - hasWarnedAboutUsingNoValuePropOnContextProvider = true; + if (isTimedOutSuspense) { + // Don't count time spent in a timed out Suspense subtree as part of the base duration. + var primaryChildFragment = workInProgress.child; - error( - "The `value` prop is required for the ``. Did you misspell it or forget to pass it?" - ); - } - } + if (primaryChildFragment !== null) { + // $FlowFixMe Flow doesn't support type casting in combination with the -= operator + workInProgress.treeBaseDuration -= + primaryChildFragment.treeBaseDuration; + } + } + } + } - var providerPropTypes = workInProgress.type.propTypes; + return false; + } else { + if ((workInProgress.flags & DidCapture) === NoFlags) { + // 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. - if (providerPropTypes) { - checkPropTypes(providerPropTypes, newProps, "prop", "Context.Provider"); - } - } + workInProgress.flags |= Update; + bubbleProperties(workInProgress); - pushProvider(workInProgress, context, newValue); + { + if ((workInProgress.mode & ProfileMode) !== NoMode) { + var _isTimedOutSuspense = nextState !== null; - { - if (oldProps !== null) { - var oldValue = oldProps.value; + if (_isTimedOutSuspense) { + // Don't count time spent in a timed out Suspense subtree as part of the base duration. + var _primaryChildFragment = workInProgress.child; - if (objectIs(oldValue, newValue)) { - // No change. Bailout early if children are the same. - if (oldProps.children === newProps.children && !hasContextChanged()) { - return bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderLanes - ); + if (_primaryChildFragment !== null) { + // $FlowFixMe Flow doesn't support type casting in combination with the -= operator + workInProgress.treeBaseDuration -= + _primaryChildFragment.treeBaseDuration; + } + } + } + } + + return false; } } else { - // The context value changed. Search for matching consumers and schedule - // them to update. - propagateContextChange(workInProgress, context, renderLanes); - } - } - } + // 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 - 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; - - error( - "Rendering directly is not supported and will be removed in " + - "a future major release. Did you mean to render instead?" - ); - } + return true; } - } 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." - ); } - } - prepareToReadContext(workInProgress, renderLanes); - var newValue = readContext(context); + function completeWork(current, workInProgress, renderLanes) { + var newProps = workInProgress.pendingProps; // Note: This intentionally doesn't check if we're hydrating because comparing + // to the current tree provider fiber is just as fast and less error-prone. + // Ideally we would have a special version of the work loop only + // for hydration. - var newChildren; + popTreeContext(workInProgress); + if (workInProgress.flags & 1 && (workInProgress.type?.displayName || workInProgress.type?.name) !== "View") + insertUpdateComponents( + getComponentNameFromFiber(workInProgress), + workInProgress.flags, + workInProgress.key, + ); + 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; - { - ReactCurrentOwner$1.current = workInProgress; - setIsRendering(true); - newChildren = render(newValue); - setIsRendering(false); - } + case ClassComponent: { + var Component = workInProgress.type; - workInProgress.flags |= PerformedWork; - reconcileChildren(current, workInProgress, newChildren, renderLanes); - return workInProgress.child; -} + if (isContextProvider(Component)) { + popContext(workInProgress); + } -function markWorkInProgressReceivedUpdate() { - didReceiveUpdate = true; -} + bubbleProperties(workInProgress); + return null; + } -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 + case HostRoot: { + var fiberRoot = workInProgress.stateNode; + popHostContainer(workInProgress); + popTopLevelContextObject(workInProgress); + resetWorkInProgressVersions(); - workInProgress.flags |= Placement; - } - } -} + if (fiberRoot.pendingContext) { + fiberRoot.context = fiberRoot.pendingContext; + fiberRoot.pendingContext = null; + } -function bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) { - if (current !== null) { - // Reuse previous dependencies - workInProgress.dependencies = current.dependencies; - } + 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(); - { - // Don't update "base" render times for bailouts. - stopProfilerTimerIfRunning(); - } + 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; - markSkippedUpdateLanes(workInProgress.lanes); // Check if the children have any pending work. + 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 + ) { + // 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(); + } + } + } + } - 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. - { - return null; - } - } // This fiber doesn't have work, but its subtree does. Clone the child - // fibers and continue. + updateHostContainer(current, workInProgress); + bubbleProperties(workInProgress); - cloneChildFibers(current, workInProgress); - return workInProgress.child; -} + return null; + } -function remountFiber(current, oldWorkInProgress, newWorkInProgress) { - { - var returnFiber = oldWorkInProgress.return; + case HostComponent: { + popHostContext(workInProgress); + var rootContainerInstance = getRootHostContainer(); + var type = workInProgress.type; + + if (current !== null && workInProgress.stateNode != null) { + updateHostComponent$1( + current, + workInProgress, + type, + newProps, + rootContainerInstance + ); - 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.ref !== workInProgress.ref) { + markRef$1(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. - current.alternate = null; - oldWorkInProgress.alternate = null; // Connect to the new tree. + bubbleProperties(workInProgress); + return null; + } - newWorkInProgress.index = oldWorkInProgress.index; - newWorkInProgress.sibling = oldWorkInProgress.sibling; - newWorkInProgress.return = oldWorkInProgress.return; - newWorkInProgress.ref = oldWorkInProgress.ref; // Replace the child/sibling pointers above it. + var currentHostContext = 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 (oldWorkInProgress === returnFiber.child) { - returnFiber.child = newWorkInProgress; - } else { - var prevSibling = returnFiber.child; + var _wasHydrated = popHydrationState(); - if (prevSibling === null) { - // eslint-disable-next-line react-internal/prod-error-codes - throw new Error("Expected parent to have a child."); - } + if (_wasHydrated) { + // TODO: Move this and createInstance step into the beginPhase + // to consolidate. + if (prepareToHydrateHostInstance()) { + // If changes to the hydrated node need to be applied at the + // commit-phase we mark this as such. + markUpdate(workInProgress); + } + } else { + var instance = createInstance( + type, + newProps, + rootContainerInstance, + currentHostContext, + workInProgress + ); + appendAllChildren(instance, workInProgress, false, false); + workInProgress.stateNode = instance; // Certain renderers require commit-time effects for initial mount. + } - while (prevSibling.sibling !== oldWorkInProgress) { - prevSibling = prevSibling.sibling; + if (workInProgress.ref !== null) { + // If there is a ref on a host node we need to schedule a callback + markRef$1(workInProgress); + } + } - if (prevSibling === null) { - // eslint-disable-next-line react-internal/prod-error-codes - throw new Error("Expected to find the previous sibling."); + bubbleProperties(workInProgress); + return null; } - } - prevSibling.sibling = newWorkInProgress; - } // Delete the old fiber and place the new one. - // Since the old fiber is disconnected, we have to schedule it manually. + case HostText: { + var newText = newProps; - var deletions = returnFiber.deletions; + 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 (deletions === null) { - returnFiber.deletions = [current]; - returnFiber.flags |= ChildDeletion; - } else { - deletions.push(current); - } + updateHostText$1(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. + } - newWorkInProgress.flags |= Placement; // Restart work from the new fiber. + var _rootContainerInstance = getRootHostContainer(); - return newWorkInProgress; - } -} + var _currentHostContext = getHostContext(); -function checkScheduledUpdateOrContext(current, renderLanes) { - // Before performing an early bailout, we must check if there are pending - // updates or context. - var updateLanes = current.lanes; + var _wasHydrated2 = popHydrationState(); - if (includesSomeLane(updateLanes, renderLanes)) { - return true; - } // No pending update, but because context is propagated lazily, we need + if (_wasHydrated2) { + if (prepareToHydrateHostTextInstance()) { + markUpdate(workInProgress); + } + } else { + workInProgress.stateNode = createTextInstance( + newText, + _rootContainerInstance, + _currentHostContext, + workInProgress + ); + } + } - return false; -} + bubbleProperties(workInProgress); + return null; + } -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); - var root = workInProgress.stateNode; - break; + case SuspenseComponent: { + popSuspenseContext(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. - case HostComponent: - pushHostContext(workInProgress); - break; + if ( + current === null || + (current.memoizedState !== null && + current.memoizedState.dehydrated !== null) + ) { + var fallthroughToNormalSuspensePath = completeDehydratedSuspenseBoundary( + current, + workInProgress, + nextState + ); - case ClassComponent: { - var Component = workInProgress.type; + if (!fallthroughToNormalSuspensePath) { + if (workInProgress.flags & ShouldCapture) { + // 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 (isContextProvider(Component)) { - pushContextProvider(workInProgress); - } + if ((workInProgress.flags & DidCapture) !== NoFlags) { + // Something suspended. Re-render with the fallback children. + workInProgress.lanes = renderLanes; // Do not reset the effect list. - break; - } + if ((workInProgress.mode & ProfileMode) !== NoMode) { + transferActualDuration(workInProgress); + } // Don't bubble properties in this case. - case HostPortal: - pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); - break; + return workInProgress; + } - case ContextProvider: { - var newValue = workInProgress.memoizedProps.value; - var context = workInProgress.type._context; - pushProvider(workInProgress, context, newValue); - break; - } + var nextDidTimeout = nextState !== null; + var prevDidTimeout = current !== null && current.memoizedState !== null; + // a passive effect, which is when we process the transitions + + if (nextDidTimeout !== prevDidTimeout) { + // 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; // TODO: This will still suspend a synchronous tree if anything + // in the concurrent tree already suspended during this render. + // This is a known bug. + + if ((workInProgress.mode & ConcurrentMode) !== NoMode) { + // TODO: Move this back to throwException because this is too late + // if this is a large tree which is common for initial loads. We + // don't know if we should restart a render or not until we get + // this marker, and this is too late. + // If this render already had a ping or lower pri updates, + // and this is the first time we know we're going to suspend we + // should be able to immediately restart from within throwException. + var hasInvisibleChildContext = + current === null && + (workInProgress.memoizedProps.unstable_avoidThisFallback !== + true || + !enableSuspenseAvoidThisFallback); - case Profiler: - { - // Profiler should only call onRender when one of its descendants actually rendered. - var hasChildWork = includesSomeLane( - renderLanes, - workInProgress.childLanes - ); + if ( + hasInvisibleChildContext || + hasSuspenseContext( + suspenseStackCursor.current, + InvisibleParentSuspenseContext + ) + ) { + // If this was in an invisible tree or a new render, then showing + // this boundary is ok. + renderDidSuspend(); + } else { + // Otherwise, we're going to have to hide content so we should + // suspend for longer if possible. + renderDidSuspendDelayIfPossible(); + } + } + } + } - if (hasChildWork) { - workInProgress.flags |= Update; - } + var wakeables = workInProgress.updateQueue; - { - // 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 (wakeables !== null) { + // Schedule an effect to attach a retry listener to the promise. + // TODO: Move to passive phase + workInProgress.flags |= Update; + } - break; + bubbleProperties(workInProgress); + + { + 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 Flow doesn't support type casting in combination with the -= operator + workInProgress.treeBaseDuration -= + primaryChildFragment.treeBaseDuration; + } + } + } + } - case SuspenseComponent: { - var state = workInProgress.memoizedState; + return null; + } - if (state !== null) { - if (state.dehydrated !== null) { - pushSuspenseContext( - workInProgress, - setDefaultShallowSuspenseContext(suspenseStackCursor.current) - ); // 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. + case HostPortal: + popHostContainer(workInProgress); + updateHostContainer(current, workInProgress); - workInProgress.flags |= DidCapture; // We should never render the children of a dehydrated boundary until we - // upgrade it. We return null instead of bailoutOnAlreadyFinishedWork. + if (current === null) { + preparePortalMount(workInProgress.stateNode.containerInfo); + } + bubbleProperties(workInProgress); 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); - } else { - // The primary child fragment does not have pending work marked - // on it - pushSuspenseContext( - workInProgress, - setDefaultShallowSuspenseContext(suspenseStackCursor.current) - ); // The primary children do not have pending work with sufficient - // priority. Bailout. + case ContextProvider: + // Pop provider fiber + var context = workInProgress.type._context; + popProvider(context, workInProgress); + bubbleProperties(workInProgress); + return null; - var child = bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderLanes - ); + 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 (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; + if (isContextProvider(_Component)) { + popContext(workInProgress); } - } - } else { - pushSuspenseContext( - workInProgress, - setDefaultShallowSuspenseContext(suspenseStackCursor.current) - ); - } - break; - } + bubbleProperties(workInProgress); + return null; + } - case SuspenseListComponent: { - var didSuspendBefore = (current.flags & DidCapture) !== NoFlags; + case SuspenseListComponent: { + popSuspenseContext(workInProgress); + var renderState = workInProgress.memoizedState; - var _hasChildWork = includesSomeLane( - renderLanes, - workInProgress.childLanes - ); + if (renderState === null) { + // We're running in the default, "independent" mode. + // We don't do anything in this mode. + bubbleProperties(workInProgress); + 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. + var didSuspendAlready = (workInProgress.flags & DidCapture) !== NoFlags; + 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); + + 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 newThenables = suspended.updateQueue; + + if (newThenables !== null) { + workInProgress.updateQueue = newThenables; + workInProgress.flags |= Update; + } // 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; + resetChildFibers(workInProgress, renderLanes); // Set up the Suspense Context to force suspense and immediately + // rerender the children. + + pushSuspenseContext( + workInProgress, + setShallowSuspenseContext( + suspenseStackCursor.current, + ForceSuspenseFallback + ) + ); // Don't bubble properties in this case. + + return workInProgress.child; + } - 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. + row = row.sibling; + } + } - var renderState = workInProgress.memoizedState; + if (renderState.tail !== null && now() > 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 (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 (_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. - pushSuspenseContext(workInProgress, suspenseStackCursor.current); + var _newThenables = _suspended.updateQueue; - 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; - } - } + if (_newThenables !== null) { + workInProgress.updateQueue = _newThenables; + workInProgress.flags |= Update; + } - 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); - } - } + cutOffTailIfNeeded(renderState, true); // This might have been modified. - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); -} + 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() * 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; + } + } -function beginWork(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._debugOwner || null, - workInProgress.mode, - workInProgress.lanes - ) - ); - } - } + 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 (current !== null) { - var oldProps = current.memoizedProps; - var newProps = workInProgress.pendingProps; + if (previousSibling !== null) { + previousSibling.sibling = renderedTail; + } else { + workInProgress.child = renderedTail; + } - 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 - ); + renderState.last = renderedTail; + } + } - 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 - ) { - // No pending updates or context. Bail out now. - didReceiveUpdate = false; - return attemptEarlyBailoutIfNoScheduledUpdate( - current, - workInProgress, - 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(); + 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 = setShallowSuspenseContext( + suspenseContext, + ForceSuspenseFallback + ); + } else { + suspenseContext = setDefaultShallowSuspenseContext(suspenseContext); + } - if ((current.flags & ForceUpdateForLegacySuspense) !== NoFlags) { - // 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. + pushSuspenseContext(workInProgress, suspenseContext); // Do a pass over the next row. + // Don't bubble properties in this case. - workInProgress.lanes = NoLanes; + return next; + } - switch (workInProgress.tag) { - case IndeterminateComponent: { - return mountIndeterminateComponent( - current, - workInProgress, - workInProgress.type, - renderLanes - ); - } + bubbleProperties(workInProgress); + return null; + } - case LazyComponent: { - var elementType = workInProgress.elementType; - return mountLazyComponent( - current, - workInProgress, - elementType, - renderLanes - ); - } + case ScopeComponent: { + break; + } - 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 - ); - } + case OffscreenComponent: + case LegacyHiddenComponent: { + popRenderLanes(workInProgress); + var _nextState = workInProgress.memoizedState; + var nextIsHidden = _nextState !== null; + + if (current !== null) { + var _prevState = current.memoizedState; + var prevIsHidden = _prevState !== null; + + if ( + prevIsHidden !== nextIsHidden && // LegacyHidden doesn't do any hiding — it only pre-renders. + !enableLegacyHidden + ) { + workInProgress.flags |= Visibility; + } + } - case ClassComponent: { - var _Component = workInProgress.type; - var _unresolvedProps = workInProgress.pendingProps; + 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(subtreeRenderLanes, OffscreenLane)) { + bubbleProperties(workInProgress); + } + } + return null; + } - var _resolvedProps = - workInProgress.elementType === _Component - ? _unresolvedProps - : resolveDefaultProps(_Component, _unresolvedProps); + case CacheComponent: { + return null; + } - return updateClassComponent( - current, - workInProgress, - _Component, - _resolvedProps, - renderLanes + case TracingMarkerComponent: { + 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." ); } - case HostRoot: - return updateHostRoot(current, workInProgress, renderLanes); + function unwindWork(current, workInProgress, renderLanes) { + // Note: This intentionally doesn't check if we're hydrating because comparing + // to the current tree provider fiber is just as fast and less error-prone. + // Ideally we would have a special version of the work loop only + // for hydration. + popTreeContext(workInProgress); - case HostComponent: - return updateHostComponent(current, workInProgress, renderLanes); + switch (workInProgress.tag) { + case ClassComponent: { + var Component = workInProgress.type; - case HostText: - return updateHostText(); + if (isContextProvider(Component)) { + popContext(workInProgress); + } - case SuspenseComponent: - return updateSuspenseComponent(current, workInProgress, renderLanes); + var flags = workInProgress.flags; - case HostPortal: - return updatePortalComponent(current, workInProgress, renderLanes); + if (flags & ShouldCapture) { + workInProgress.flags = (flags & ~ShouldCapture) | DidCapture; - case ForwardRef: { - var type = workInProgress.type; - var _unresolvedProps2 = workInProgress.pendingProps; + if ((workInProgress.mode & ProfileMode) !== NoMode) { + transferActualDuration(workInProgress); + } - var _resolvedProps2 = - workInProgress.elementType === type - ? _unresolvedProps2 - : resolveDefaultProps(type, _unresolvedProps2); + return workInProgress; + } - return updateForwardRef( - current, - workInProgress, - type, - _resolvedProps2, - renderLanes - ); - } + return null; + } - case Fragment: - return updateFragment(current, workInProgress, renderLanes); + case HostRoot: { + var root = workInProgress.stateNode; + popHostContainer(workInProgress); + popTopLevelContextObject(workInProgress); + resetWorkInProgressVersions(); + var _flags = workInProgress.flags; - case Mode: - return updateMode(current, workInProgress, renderLanes); + if ( + (_flags & ShouldCapture) !== NoFlags && + (_flags & DidCapture) === NoFlags + ) { + // 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 Profiler: - return updateProfiler(current, workInProgress, renderLanes); + return null; + } - case ContextProvider: - return updateContextProvider(current, workInProgress, renderLanes); + case HostComponent: { + // TODO: popHydrationState + popHostContext(workInProgress); + return null; + } - case ContextConsumer: - return updateContextConsumer(current, workInProgress, renderLanes); + case SuspenseComponent: { + popSuspenseContext(workInProgress); + var suspenseState = workInProgress.memoizedState; - case MemoComponent: { - var _type2 = workInProgress.type; - var _unresolvedProps3 = workInProgress.pendingProps; // Resolve outer props first, then resolve inner props. + 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." + ); + } + } - var _resolvedProps3 = resolveDefaultProps(_type2, _unresolvedProps3); + var _flags2 = workInProgress.flags; - { - if (workInProgress.type !== workInProgress.elementType) { - var outerPropTypes = _type2.propTypes; + if (_flags2 & ShouldCapture) { + workInProgress.flags = (_flags2 & ~ShouldCapture) | DidCapture; // Captured a suspense effect. Re-render the boundary. - if (outerPropTypes) { - checkPropTypes( - outerPropTypes, - _resolvedProps3, // Resolved for outer only - "prop", - getComponentNameFromType(_type2) - ); + if ((workInProgress.mode & ProfileMode) !== NoMode) { + transferActualDuration(workInProgress); + } + + return workInProgress; } + + return null; } - } - _resolvedProps3 = resolveDefaultProps(_type2.type, _resolvedProps3); - return updateMemoComponent( - current, - workInProgress, - _type2, - _resolvedProps3, - renderLanes - ); - } + case SuspenseListComponent: { + popSuspenseContext(workInProgress); // SuspenseList doesn't actually catch anything. It should've been + // caught by a nested boundary. If not, it should bubble through. - case SimpleMemoComponent: { - return updateSimpleMemoComponent( - current, - workInProgress, - workInProgress.type, - workInProgress.pendingProps, - renderLanes - ); - } + return null; + } - case IncompleteClassComponent: { - var _Component2 = workInProgress.type; - var _unresolvedProps4 = workInProgress.pendingProps; + case HostPortal: + popHostContainer(workInProgress); + return null; - var _resolvedProps4 = - workInProgress.elementType === _Component2 - ? _unresolvedProps4 - : resolveDefaultProps(_Component2, _unresolvedProps4); + case ContextProvider: + var context = workInProgress.type._context; + popProvider(context, workInProgress); + return null; - return mountIncompleteClassComponent( - current, - workInProgress, - _Component2, - _resolvedProps4, - renderLanes - ); - } + case OffscreenComponent: + case LegacyHiddenComponent: + popRenderLanes(workInProgress); + return null; - case SuspenseListComponent: { - return updateSuspenseListComponent(current, workInProgress, renderLanes); - } + case CacheComponent: + return null; - case ScopeComponent: { - break; + default: + return null; + } } - case OffscreenComponent: { - return updateOffscreenComponent(current, workInProgress, renderLanes); - } - } + function unwindInterruptedWork(current, interruptedWork, renderLanes) { + // Note: This intentionally doesn't check if we're hydrating because comparing + // to the current tree provider fiber is just as fast and less error-prone. + // Ideally we would have a special version of the work loop only + // for hydration. + popTreeContext(interruptedWork); - throw new Error( - "Unknown unit of work tag (" + - workInProgress.tag + - "). This error is likely caused by a bug in " + - "React. Please file an issue." - ); -} + switch (interruptedWork.tag) { + case ClassComponent: { + var childContextTypes = interruptedWork.type.childContextTypes; -function markUpdate(workInProgress) { - // Tag the fiber with an update effect. This turns a Placement into - // a PlacementAndUpdate. - workInProgress.flags |= Update; -} + if (childContextTypes !== null && childContextTypes !== undefined) { + popContext(interruptedWork); + } -function markRef$1(workInProgress) { - workInProgress.flags |= Ref; -} + break; + } + + case HostRoot: { + var root = interruptedWork.stateNode; + popHostContainer(interruptedWork); + popTopLevelContextObject(interruptedWork); + resetWorkInProgressVersions(); + break; + } -function hadNoMutationsEffects(current, completedWork) { - var didBailout = current !== null && current.child === completedWork.child; + case HostComponent: { + popHostContext(interruptedWork); + break; + } + + case HostPortal: + popHostContainer(interruptedWork); + break; - if (didBailout) { - return true; - } + case SuspenseComponent: + popSuspenseContext(interruptedWork); + break; - if ((completedWork.flags & ChildDeletion) !== NoFlags) { - return false; - } // TODO: If we move the `hadNoMutationsEffects` call after `bubbleProperties` - // then we only have to check the `completedWork.subtreeFlags`. + case SuspenseListComponent: + popSuspenseContext(interruptedWork); + break; - var child = completedWork.child; + case ContextProvider: + var context = interruptedWork.type._context; + popProvider(context, interruptedWork); + break; - while (child !== null) { - if ( - (child.flags & MutationMask) !== NoFlags || - (child.subtreeFlags & MutationMask) !== NoFlags - ) { - return false; + case OffscreenComponent: + case LegacyHiddenComponent: + popRenderLanes(interruptedWork); + break; + } } - child = child.sibling; - } + var didWarnAboutUndefinedSnapshotBeforeUpdate = null; - return true; -} + { + didWarnAboutUndefinedSnapshotBeforeUpdate = new Set(); + } // Used during the commit phase to track the state of the Offscreen component stack. + var PossiblyWeakSet = typeof WeakSet === "function" ? WeakSet : Set; + var nextEffect = null; // Used for Profiling builds to track updaters. + + var inProgressLanes = null; + var inProgressRoot = null; + 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(); + } + } -var appendAllChildren; -var updateHostContainer; -var updateHostComponent$1; -var updateHostText$1; - -{ - // Persistent host tree mode - appendAllChildren = function( - 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) { - // eslint-disable-next-line no-labels - if (node.tag === HostComponent) { - var instance = node.stateNode; - - if (needsVisibilityToggle && isHidden) { - // This child is inside a timed out tree. Hide it. - var props = node.memoizedProps; - var type = node.type; - instance = cloneHiddenInstance(instance); - } - - appendInitialChild(parent, instance); - } else if (node.tag === HostText) { - var _instance = node.stateNode; - - if (needsVisibilityToggle && isHidden) { - // This child is inside a timed out tree. Hide it. - var text = node.memoizedProps; - _instance = cloneHiddenTextInstance(); - } - - appendInitialChild(parent, _instance); - } else if (node.tag === HostPortal); - else if (node.tag === OffscreenComponent && node.memoizedState !== null) { - // The children in this boundary are hidden. Toggle their visibility - // before appending. - var child = node.child; + var callComponentWillUnmountWithTimer = function (current, instance) { + instance.props = current.memoizedProps; + instance.state = current.memoizedState; - if (child !== null) { - child.return = node; + if (current.mode & ProfileMode) { + try { + startLayoutEffectTimer(); + instance.componentWillUnmount(); + } finally { + recordLayoutEffectDuration(current); } + } else { + instance.componentWillUnmount(); + } + }; // Capture errors so they don't interrupt mounting. - appendAllChildren(parent, node, true, true); - } else if (node.child !== null) { - node.child.return = node; - node = node.child; - continue; - } // $FlowFixMe This is correct but Flow is confused by the labeled break. + function safelyCallComponentWillUnmount( + current, + nearestMountedAncestor, + instance + ) { + try { + callComponentWillUnmountWithTimer(current, instance); + } catch (error) { + captureCommitPhaseError(current, nearestMountedAncestor, error); + } + } // Capture errors so they don't interrupt mounting. - node = node; + function safelyDetachRef(current, nearestMountedAncestor) { + var ref = current.ref; - if (node === workInProgress) { - return; - } + if (ref !== null) { + if (typeof ref === "function") { + var retVal; - while (node.sibling === null) { - if (node.return === null || node.return === workInProgress) { - return; - } + try { + if ( + enableProfilerTimer && + enableProfilerCommitHooks && + current.mode & ProfileMode + ) { + try { + startLayoutEffectTimer(); + retVal = ref(null); + } finally { + recordLayoutEffectDuration(current); + } + } else { + retVal = ref(null); + } + } catch (error) { + captureCommitPhaseError(current, nearestMountedAncestor, error); + } - node = node.return; + { + 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 { + ref.current = null; + } } + } - node.sibling.return = node.return; - node = node.sibling; + function safelyCallDestroy(current, nearestMountedAncestor, destroy) { + try { + destroy(); + } catch (error) { + captureCommitPhaseError(current, nearestMountedAncestor, error); + } } - }; // An unfortunate fork of appendAllChildren because we have two different parent types. - var appendAllChildrenToContainer = function( - containerChildSet, - 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; + var focusedInstanceHandle = null; + var shouldFireAfterActiveInstanceBlur = false; + function commitBeforeMutationEffects(root, firstChild) { + focusedInstanceHandle = prepareForCommit(root.containerInfo); + nextEffect = firstChild; + commitBeforeMutationEffects_begin(); // We no longer need to track the active instance fiber - while (node !== null) { - // eslint-disable-next-line no-labels - if (node.tag === HostComponent) { - var instance = node.stateNode; + var shouldFire = shouldFireAfterActiveInstanceBlur; + shouldFireAfterActiveInstanceBlur = false; + focusedInstanceHandle = null; + return shouldFire; + } - if (needsVisibilityToggle && isHidden) { - // This child is inside a timed out tree. Hide it. - var props = node.memoizedProps; - var type = node.type; - instance = cloneHiddenInstance(instance); - } + function commitBeforeMutationEffects_begin() { + while (nextEffect !== null) { + var fiber = nextEffect; // This phase is only used for beforeActiveInstanceBlur. - appendChildToContainerChildSet(containerChildSet, instance); - } else if (node.tag === HostText) { - var _instance2 = node.stateNode; + var child = fiber.child; - if (needsVisibilityToggle && isHidden) { - // This child is inside a timed out tree. Hide it. - var text = node.memoizedProps; - _instance2 = cloneHiddenTextInstance(); + if ( + (fiber.subtreeFlags & BeforeMutationMask) !== NoFlags && + child !== null + ) { + child.return = fiber; + nextEffect = child; + } else { + commitBeforeMutationEffects_complete(); } + } + } - appendChildToContainerChildSet(containerChildSet, _instance2); - } else if (node.tag === HostPortal); - else if (node.tag === OffscreenComponent && node.memoizedState !== null) { - // The children in this boundary are hidden. Toggle their visibility - // before appending. - var child = node.child; + function commitBeforeMutationEffects_complete() { + while (nextEffect !== null) { + var fiber = nextEffect; + setCurrentFiber(fiber); - if (child !== null) { - child.return = node; + try { + commitBeforeMutationEffectsOnFiber(fiber); + } catch (error) { + captureCommitPhaseError(fiber, fiber.return, error); } - appendAllChildrenToContainer(containerChildSet, node, true, true); - } else if (node.child !== null) { - node.child.return = node; - node = node.child; - continue; - } // $FlowFixMe This is correct but Flow is confused by the labeled break. - - node = node; - - if (node === workInProgress) { - return; - } + resetCurrentFiber(); + var sibling = fiber.sibling; - while (node.sibling === null) { - if (node.return === null || node.return === workInProgress) { + if (sibling !== null) { + sibling.return = fiber.return; + nextEffect = sibling; return; } - node = node.return; + nextEffect = fiber.return; } - - node.sibling.return = node.return; - node = node.sibling; } - }; - - updateHostContainer = function(current, workInProgress) { - var portalOrRoot = workInProgress.stateNode; - var childrenUnchanged = hadNoMutationsEffects(current, workInProgress); - if (childrenUnchanged); - else { - var container = portalOrRoot.containerInfo; - var newChildSet = createContainerChildSet(container); // If children might have changed, we have to add them all to the set. + function commitBeforeMutationEffectsOnFiber(finishedWork) { + var current = finishedWork.alternate; + var flags = finishedWork.flags; - appendAllChildrenToContainer(newChildSet, workInProgress, false, false); - portalOrRoot.pendingChildren = newChildSet; // Schedule an update on the container to swap out the container. + if ((flags & Snapshot) !== NoFlags) { + setCurrentFiber(finishedWork); - markUpdate(workInProgress); - finalizeContainerChildren(container, newChildSet); - } - }; + switch (finishedWork.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { + break; + } - updateHostComponent$1 = function( - current, - workInProgress, - type, - newProps, - rootContainerInstance - ) { - var currentInstance = current.stateNode; - var oldProps = current.memoizedProps; // If there are no effects associated with this node, then none of our children had any updates. - // This guarantees that we can reuse all of them. + case ClassComponent: { + 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 childrenUnchanged = hadNoMutationsEffects(current, workInProgress); + { + 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 (childrenUnchanged && oldProps === newProps) { - // No changes, just reuse the existing instance. - // Note that this might release a previous clone. - workInProgress.stateNode = currentInstance; - return; - } + 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" + ); + } + } + } - var recyclableInstance = workInProgress.stateNode; - var currentHostContext = getHostContext(); - var updatePayload = null; + var snapshot = instance.getSnapshotBeforeUpdate( + finishedWork.elementType === finishedWork.type + ? prevProps + : resolveDefaultProps(finishedWork.type, prevProps), + prevState + ); - if (oldProps !== newProps) { - updatePayload = prepareUpdate( - recyclableInstance, - type, - oldProps, - newProps - ); - } + { + var didWarnSet = didWarnAboutUndefinedSnapshotBeforeUpdate; - if (childrenUnchanged && updatePayload === null) { - // No changes, just reuse the existing instance. - // Note that this might release a previous clone. - workInProgress.stateNode = currentInstance; - return; - } + if (snapshot === undefined && !didWarnSet.has(finishedWork.type)) { + didWarnSet.add(finishedWork.type); - var newInstance = cloneInstance( - currentInstance, - updatePayload, - type, - oldProps, - newProps, - workInProgress, - childrenUnchanged - ); + error( + "%s.getSnapshotBeforeUpdate(): A snapshot value (or null) " + + "must be returned. You have returned undefined.", + getComponentNameFromFiber(finishedWork) + ); + } + } - workInProgress.stateNode = newInstance; - - if (childrenUnchanged) { - // If there are no other effects in this tree, we need to flag this node as having one. - // Even though we're not going to use it for anything. - // Otherwise parents won't know that there are new children to propagate upwards. - markUpdate(workInProgress); - } else { - // If children might have changed, we have to add them all to the set. - appendAllChildren(newInstance, workInProgress, false, false); - } - }; - - updateHostText$1 = function(current, workInProgress, oldText, newText) { - if (oldText !== newText) { - // If the text content differs, we'll create a new text instance for it. - var rootContainerInstance = getRootHostContainer(); - var currentHostContext = getHostContext(); - workInProgress.stateNode = createTextInstance( - newText, - rootContainerInstance, - currentHostContext, - workInProgress - ); // We'll have to mark it as having an effect, even though we won't use the effect for anything. - // This lets the parents know that at least one of their children has changed. - - markUpdate(workInProgress); - } else { - workInProgress.stateNode = current.stateNode; - } - }; -} + instance.__reactInternalSnapshotBeforeUpdate = snapshot; + } -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 HostRoot: { + 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; + case HostComponent: + case HostText: + case HostPortal: + case IncompleteClassComponent: + // Nothing to do for these component types + break; - while (_tailNode !== null) { - if (_tailNode.alternate !== null) { - _lastTailNode = _tailNode; + default: { + 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." + ); + } } - _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. - 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; + resetCurrentFiber(); } - - break; } - } -} - -function bubbleProperties(completedWork) { - var didBailout = - completedWork.alternate !== null && - completedWork.alternate.child === completedWork.child; - var newChildLanes = NoLanes; - var subtreeFlags = NoFlags; - - 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. - - actualDuration += child.actualDuration; - treeBaseDuration += child.treeBaseDuration; - child = child.sibling; - } + function commitHookEffectListUnmount( + flags, + finishedWork, + nearestMountedAncestor + ) { + var updateQueue = finishedWork.updateQueue; + var lastEffect = updateQueue !== null ? updateQueue.lastEffect : null; - completedWork.actualDuration = actualDuration; - completedWork.treeBaseDuration = treeBaseDuration; - } else { - var _child = completedWork.child; + if (lastEffect !== null) { + var firstEffect = lastEffect.next; + var effect = firstEffect; - 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. + do { + if ((effect.tag & flags) === flags) { + // Unmount + var destroy = effect.destroy; + effect.destroy = undefined; - _child.return = completedWork; - _child = _child.sibling; - } - } + if (destroy !== undefined) { + { + if ((flags & Insertion) !== NoFlags$1) { + setIsRunningInsertionEffect(true); + } + } - 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; + safelyCallDestroy(finishedWork, nearestMountedAncestor, destroy); - 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 ((flags & Insertion) !== NoFlags$1) { + setIsRunningInsertionEffect(false); + } + } + } + } - subtreeFlags |= _child2.subtreeFlags & StaticMask; - subtreeFlags |= _child2.flags & StaticMask; - _treeBaseDuration += _child2.treeBaseDuration; - _child2 = _child2.sibling; + effect = effect.next; + } while (effect !== firstEffect); } + } - completedWork.treeBaseDuration = _treeBaseDuration; - } else { - var _child3 = completedWork.child; + function commitHookEffectListMount(flags, finishedWork) { + var updateQueue = finishedWork.updateQueue; + var lastEffect = updateQueue !== null ? updateQueue.lastEffect : 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. + if (lastEffect !== null) { + var firstEffect = lastEffect.next; + var effect = firstEffect; - 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. + do { + if ((effect.tag & flags) === flags) { + var create = effect.create; - _child3.return = completedWork; - _child3 = _child3.sibling; - } - } + { + if ((flags & Insertion) !== NoFlags$1) { + setIsRunningInsertionEffect(true); + } + } - completedWork.subtreeFlags |= subtreeFlags; - } + effect.destroy = create(); - completedWork.childLanes = newChildLanes; - return didBailout; -} + { + if ((flags & Insertion) !== NoFlags$1) { + setIsRunningInsertionEffect(false); + } + } -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." - ); - } + { + var destroy = effect.destroy; - prepareToHydrateHostSuspenseInstance(); - bubbleProperties(workInProgress); + if (destroy !== undefined && typeof destroy !== "function") { + var hookName = void 0; - { - if ((workInProgress.mode & ProfileMode) !== NoMode) { - var isTimedOutSuspense = nextState !== null; + if ((effect.tag & Layout) !== NoFlags) { + hookName = "useLayoutEffect"; + } else if ((effect.tag & Insertion) !== NoFlags) { + hookName = "useInsertionEffect"; + } else { + hookName = "useEffect"; + } - if (isTimedOutSuspense) { - // Don't count time spent in a timed out Suspense subtree as part of the base duration. - var primaryChildFragment = workInProgress.child; + 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://react.dev/link/hooks-data-fetching"; + } else { + addendum = " You returned: " + destroy; + } - if (primaryChildFragment !== null) { - // $FlowFixMe Flow doesn't support type casting in combination with the -= operator - workInProgress.treeBaseDuration -= - primaryChildFragment.treeBaseDuration; + error( + "%s must not return anything besides a function, " + + "which is used for clean-up.%s", + hookName, + addendum + ); + } } } - } + + effect = effect.next; + } while (effect !== firstEffect); } + } - return false; - } else { - if ((workInProgress.flags & DidCapture) === NoFlags) { - // 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 commitPassiveEffectDurations(finishedRoot, finishedWork) { + { + // Only Profilers with work in their subtree will have an Update effect scheduled. + if ((finishedWork.flags & Update) !== NoFlags) { + 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. + + var commitTime = getCommitTime(); + var phase = finishedWork.alternate === null ? "mount" : "update"; - workInProgress.flags |= Update; - bubbleProperties(workInProgress); + { + if (isCurrentUpdateNested()) { + phase = "nested-update"; + } + } - { - if ((workInProgress.mode & ProfileMode) !== NoMode) { - var _isTimedOutSuspense = nextState !== null; + 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. - if (_isTimedOutSuspense) { - // Don't count time spent in a timed out Suspense subtree as part of the base duration. - var _primaryChildFragment = workInProgress.child; + var parentFiber = finishedWork.return; - if (_primaryChildFragment !== null) { - // $FlowFixMe Flow doesn't support type casting in combination with the -= operator - workInProgress.treeBaseDuration -= - _primaryChildFragment.treeBaseDuration; + 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; + } + + parentFiber = parentFiber.return; + } + + 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 - return true; - } -} + function commitLayoutEffectOnFiber( + finishedRoot, + current, + finishedWork, + committedLanes + ) { + if ((finishedWork.flags & LayoutMask) !== NoFlags) { + switch (finishedWork.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { + { + // 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 (finishedWork.mode & ProfileMode) { + try { + startLayoutEffectTimer(); + commitHookEffectListMount(Layout | HasEffect, finishedWork); + } finally { + recordLayoutEffectDuration(finishedWork); + } + } else { + commitHookEffectListMount(Layout | HasEffect, finishedWork); + } + } -function completeWork(current, workInProgress, renderLanes) { - var newProps = workInProgress.pendingProps; // Note: This intentionally doesn't check if we're hydrating because comparing - // to the current tree provider fiber is just as fast and less error-prone. - // Ideally we would have a special version of the work loop only - // for hydration. - - popTreeContext(workInProgress); - - 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: { - var Component = workInProgress.type; + case ClassComponent: { + var instance = finishedWork.stateNode; - if (isContextProvider(Component)) { - popContext(workInProgress); - } + if (finishedWork.flags & Update) { + { + 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" + ); + } + } + } - bubbleProperties(workInProgress); - return null; - } + if (finishedWork.mode & ProfileMode) { + try { + startLayoutEffectTimer(); + instance.componentDidMount(); + } finally { + recordLayoutEffectDuration(finishedWork); + } + } else { + instance.componentDidMount(); + } + } 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 ( + 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" + ); + } + } + } - case HostRoot: { - var fiberRoot = workInProgress.stateNode; - popHostContainer(workInProgress); - popTopLevelContextObject(workInProgress); - resetWorkInProgressVersions(); + if (finishedWork.mode & ProfileMode) { + try { + startLayoutEffectTimer(); + instance.componentDidUpdate( + prevProps, + prevState, + instance.__reactInternalSnapshotBeforeUpdate + ); + } finally { + recordLayoutEffectDuration(finishedWork); + } + } else { + instance.componentDidUpdate( + prevProps, + prevState, + instance.__reactInternalSnapshotBeforeUpdate + ); + } + } + } + } // TODO: I think this is now always non-null by the time it reaches the + // commit phase. Consider removing the type check. - if (fiberRoot.pendingContext) { - fiberRoot.context = fiberRoot.pendingContext; - fiberRoot.pendingContext = null; - } + var updateQueue = finishedWork.updateQueue; - 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 (updateQueue !== null) { + { + 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 (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 (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. - 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 - ) { - // 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(); + commitUpdateQueue(finishedWork, updateQueue, instance); } + + break; } - } - } - updateHostContainer(current, workInProgress); - bubbleProperties(workInProgress); + case HostRoot: { + // 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 null; - } + if (_updateQueue !== null) { + var _instance = null; - case HostComponent: { - popHostContext(workInProgress); - var rootContainerInstance = getRootHostContainer(); - var type = workInProgress.type; + if (finishedWork.child !== null) { + switch (finishedWork.child.tag) { + case HostComponent: + _instance = getPublicInstance(finishedWork.child.stateNode); + break; - if (current !== null && workInProgress.stateNode != null) { - updateHostComponent$1( - current, - workInProgress, - type, - newProps, - rootContainerInstance - ); + case ClassComponent: + _instance = finishedWork.child.stateNode; + break; + } + } - if (current.ref !== workInProgress.ref) { - markRef$1(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. + commitUpdateQueue(finishedWork, _updateQueue, _instance); + } - bubbleProperties(workInProgress); - return null; - } + break; + } - var currentHostContext = 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. + case HostComponent: { + var _instance2 = finishedWork.stateNode; // 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 _wasHydrated = popHydrationState(); + if (current === null && finishedWork.flags & Update) { + var type = finishedWork.type; + var props = finishedWork.memoizedProps; + commitMount(); + } - if (_wasHydrated) { - // TODO: Move this and createInstance step into the beginPhase - // to consolidate. - if (prepareToHydrateHostInstance()) { - // If changes to the hydrated node need to be applied at the - // commit-phase we mark this as such. - markUpdate(workInProgress); + break; } - } else { - var instance = createInstance( - type, - newProps, - rootContainerInstance, - currentHostContext, - workInProgress - ); - appendAllChildren(instance, workInProgress, false, false); - workInProgress.stateNode = instance; // Certain renderers require commit-time effects for initial mount. - } - - if (workInProgress.ref !== null) { - // If there is a ref on a host node we need to schedule a callback - markRef$1(workInProgress); - } - } - bubbleProperties(workInProgress); - return null; - } + case HostText: { + // We have no life-cycles associated with text. + break; + } - case HostText: { - var newText = newProps; + case HostPortal: { + // We have no life-cycles associated with portals. + break; + } - 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. + case Profiler: { + { + 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"; - updateHostText$1(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. - } + { + if (isCurrentUpdateNested()) { + phase = "nested-update"; + } + } - var _rootContainerInstance = getRootHostContainer(); + if (typeof onRender === "function") { + onRender( + finishedWork.memoizedProps.id, + phase, + finishedWork.actualDuration, + finishedWork.treeBaseDuration, + finishedWork.actualStartTime, + commitTime + ); + } - var _currentHostContext = getHostContext(); + { + 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; + } - var _wasHydrated2 = popHydrationState(); + parentFiber = parentFiber.return; + } + } + } - if (_wasHydrated2) { - if (prepareToHydrateHostTextInstance()) { - markUpdate(workInProgress); + break; } - } else { - workInProgress.stateNode = createTextInstance( - newText, - _rootContainerInstance, - _currentHostContext, - workInProgress - ); - } - } - bubbleProperties(workInProgress); - return null; - } + case SuspenseComponent: { + break; + } - case SuspenseComponent: { - popSuspenseContext(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. + case SuspenseListComponent: + case IncompleteClassComponent: + case ScopeComponent: + case OffscreenComponent: + case LegacyHiddenComponent: + case TracingMarkerComponent: { + break; + } - if ( - current === null || - (current.memoizedState !== null && - current.memoizedState.dehydrated !== null) - ) { - var fallthroughToNormalSuspensePath = completeDehydratedSuspenseBoundary( - current, - workInProgress, - nextState - ); + default: + 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." + ); + } + } - if (!fallthroughToNormalSuspensePath) { - if (workInProgress.flags & ShouldCapture) { - // 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; + { + { + if (finishedWork.flags & Ref) { + commitAttachRef(finishedWork); } - } // Continue with the normal Suspense path. + } } + } - if ((workInProgress.flags & DidCapture) !== NoFlags) { - // Something suspended. Re-render with the fallback children. - workInProgress.lanes = renderLanes; // Do not reset the effect list. + function commitAttachRef(finishedWork) { + var ref = finishedWork.ref; - if ((workInProgress.mode & ProfileMode) !== NoMode) { - transferActualDuration(workInProgress); - } // Don't bubble properties in this case. + if (ref !== null) { + var instance = finishedWork.stateNode; + var instanceToUse; - return workInProgress; - } + switch (finishedWork.tag) { + case HostComponent: + instanceToUse = getPublicInstance(instance); + break; - var nextDidTimeout = nextState !== null; - var prevDidTimeout = current !== null && current.memoizedState !== null; - // a passive effect, which is when we process the transitions + default: + instanceToUse = instance; + } // Moved outside to ensure DCE works with this flag - if (nextDidTimeout !== prevDidTimeout) { - // 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; // TODO: This will still suspend a synchronous tree if anything - // in the concurrent tree already suspended during this render. - // This is a known bug. - - if ((workInProgress.mode & ConcurrentMode) !== NoMode) { - // TODO: Move this back to throwException because this is too late - // if this is a large tree which is common for initial loads. We - // don't know if we should restart a render or not until we get - // this marker, and this is too late. - // If this render already had a ping or lower pri updates, - // and this is the first time we know we're going to suspend we - // should be able to immediately restart from within throwException. - var hasInvisibleChildContext = - current === null && - (workInProgress.memoizedProps.unstable_avoidThisFallback !== - true || - !enableSuspenseAvoidThisFallback); + if (typeof ref === "function") { + var retVal; - if ( - hasInvisibleChildContext || - hasSuspenseContext( - suspenseStackCursor.current, - InvisibleParentSuspenseContext - ) - ) { - // If this was in an invisible tree or a new render, then showing - // this boundary is ok. - renderDidSuspend(); - } else { - // Otherwise, we're going to have to hide content so we should - // suspend for longer if possible. - renderDidSuspendDelayIfPossible(); + if (finishedWork.mode & ProfileMode) { + try { + startLayoutEffectTimer(); + retVal = ref(instanceToUse); + } finally { + recordLayoutEffectDuration(finishedWork); + } + } else { + retVal = ref(instanceToUse); + } + + { + if (typeof retVal === "function") { + error( + "Unexpected return value from a callback ref in %s. " + + "A callback ref should not return a function.", + getComponentNameFromFiber(finishedWork) + ); + } + } + } else { + { + if (!ref.hasOwnProperty("current")) { + error( + "Unexpected ref object provided for %s. " + + "Use either a ref-setter function or React.createRef().", + getComponentNameFromFiber(finishedWork) + ); } } + + ref.current = instanceToUse; } } + } - var wakeables = workInProgress.updateQueue; + 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 (wakeables !== null) { - // Schedule an effect to attach a retry listener to the promise. - // TODO: Move to passive phase - workInProgress.flags |= Update; + if (alternate !== null) { + alternate.return = null; } - bubbleProperties(workInProgress); + fiber.return = null; + } + + function detachFiberAfterEffects(fiber) { + var alternate = fiber.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 (alternate !== null) { + fiber.alternate = null; + detachFiberAfterEffects(alternate); + } // Note: Defensively using negation instead of < in case + // `deletedTreeCleanUpLevel` is undefined. - if (primaryChildFragment !== null) { - // $FlowFixMe Flow doesn't support type casting in combination with the -= operator - workInProgress.treeBaseDuration -= - primaryChildFragment.treeBaseDuration; - } - } + { + // 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 + // tree, which has its own pointers to children, parents, and siblings. + // The other host nodes also point back to fibers, so we should detach that + // one, too. + + if (fiber.tag === HostComponent) { + var hostInstance = fiber.stateNode; } - } - return null; - } + fiber.stateNode = null; // I'm intentionally not clearing the `return` field in this level. We + // already disconnect the `return` pointer at the root of the deleted + // subtree (in `detachFiberMutation`). Besides, `return` by itself is not + // cyclical — it's only cyclical when combined with `child`, `sibling`, and + // `alternate`. But we'll clear it in the next level anyway, just in case. - case HostPortal: - popHostContainer(workInProgress); - updateHostContainer(current, workInProgress); + { + fiber._debugOwner = null; + } - if (current === null) { - preparePortalMount(workInProgress.stateNode.containerInfo); + { + // 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 + // + // The purpose of this branch is to be super aggressive so we can measure + // if there's any difference in memory impact. If there is, that could + // indicate a React leak we don't know about. + 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; + } } + } - bubbleProperties(workInProgress); - return null; - - case ContextProvider: - // Pop provider fiber - var context = workInProgress.type._context; - popProvider(context, workInProgress); - bubbleProperties(workInProgress); - return null; + function emptyPortalContainer(current) { + var portal = current.stateNode; + var containerInfo = portal.containerInfo; + var emptyChildSet = createContainerChildSet(containerInfo); + } - 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 commitPlacement(finishedWork) { + { + return; + } // Recursively insert all host nodes into the parent. + } - if (isContextProvider(_Component)) { - popContext(workInProgress); + function commitDeletionEffects(root, returnFiber, deletedFiber) { + { + // Detach refs and call componentWillUnmount() on the whole subtree. + commitDeletionEffectsOnFiber(root, returnFiber, deletedFiber); } - bubbleProperties(workInProgress); - return null; + detachFiberMutation(deletedFiber); } - case SuspenseListComponent: { - popSuspenseContext(workInProgress); - var renderState = workInProgress.memoizedState; + function recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + parent + ) { + // TODO: Use a static flag to skip trees that don't have unmount effects + var child = parent.child; - if (renderState === null) { - // We're running in the default, "independent" mode. - // We don't do anything in this mode. - bubbleProperties(workInProgress); - return null; + while (child !== null) { + commitDeletionEffectsOnFiber(finishedRoot, nearestMountedAncestor, child); + child = child.sibling; } + } - var didSuspendAlready = (workInProgress.flags & DidCapture) !== NoFlags; - 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); - - if (!cannotBeSuspended) { - var row = workInProgress.child; + 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. - while (row !== null) { - var suspended = findFirstSuspended(row); + switch (deletedFiber.tag) { + case HostComponent: { + { + safelyDetachRef(deletedFiber, nearestMountedAncestor); + } // Intentional fallthrough to next branch + } + // eslint-disable-next-line-no-fallthrough - 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 newThenables = suspended.updateQueue; - - if (newThenables !== null) { - workInProgress.updateQueue = newThenables; - workInProgress.flags |= Update; - } // 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; - resetChildFibers(workInProgress, renderLanes); // Set up the Suspense Context to force suspense and immediately - // rerender the children. - - pushSuspenseContext( - workInProgress, - setShallowSuspenseContext( - suspenseStackCursor.current, - ForceSuspenseFallback - ) - ); // Don't bubble properties in this case. + 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. + { + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + } - return workInProgress.child; - } + return; + } - row = row.sibling; - } - } + case DehydratedFragment: { + return; + } - if (renderState.tail !== null && now() > 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; + case HostPortal: { + { + emptyPortalContainer(deletedFiber); + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); } - } 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. + return; + } - var _newThenables = _suspended.updateQueue; + case FunctionComponent: + case ForwardRef: + case MemoComponent: + case SimpleMemoComponent: { + { + var updateQueue = deletedFiber.updateQueue; + + if (updateQueue !== null) { + var lastEffect = updateQueue.lastEffect; + + if (lastEffect !== null) { + var firstEffect = lastEffect.next; + var effect = firstEffect; + + do { + var _effect = effect, + destroy = _effect.destroy, + tag = _effect.tag; + + if (destroy !== undefined) { + if ((tag & Insertion) !== NoFlags$1) { + safelyCallDestroy( + deletedFiber, + nearestMountedAncestor, + destroy + ); + } else if ((tag & Layout) !== NoFlags$1) { + if (deletedFiber.mode & ProfileMode) { + startLayoutEffectTimer(); + safelyCallDestroy( + deletedFiber, + nearestMountedAncestor, + destroy + ); + recordLayoutEffectDuration(deletedFiber); + } else { + safelyCallDestroy( + deletedFiber, + nearestMountedAncestor, + destroy + ); + } + } + } - if (_newThenables !== null) { - workInProgress.updateQueue = _newThenables; - workInProgress.flags |= Update; + effect = effect.next; + } while (effect !== firstEffect); + } } + } - cutOffTailIfNeeded(renderState, true); // This might have been modified. + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + 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; + case ClassComponent: { + { + safelyDetachRef(deletedFiber, nearestMountedAncestor); + var instance = deletedFiber.stateNode; + + if (typeof instance.componentWillUnmount === "function") { + safelyCallComponentWillUnmount( + deletedFiber, + nearestMountedAncestor, + instance + ); } - } 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() * 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; + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + return; } - } - - 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(); - 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 = setShallowSuspenseContext( - suspenseContext, - ForceSuspenseFallback + case ScopeComponent: { + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber ); - } else { - suspenseContext = setDefaultShallowSuspenseContext(suspenseContext); + return; } - pushSuspenseContext(workInProgress, suspenseContext); // Do a pass over the next row. - // Don't bubble properties in this case. + case OffscreenComponent: { + { + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + } + + break; + } - return next; + default: { + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + return; + } } - - bubbleProperties(workInProgress); - return null; } - case ScopeComponent: { - break; + function commitSuspenseCallback(finishedWork) { + // TODO: Move this to passive phase + var newState = finishedWork.memoizedState; } - case OffscreenComponent: - case LegacyHiddenComponent: { - popRenderLanes(workInProgress); - var _nextState = workInProgress.memoizedState; - var nextIsHidden = _nextState !== null; + function attachSuspenseRetryListeners(finishedWork) { + // 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 wakeables = finishedWork.updateQueue; - if (current !== null) { - var _prevState = current.memoizedState; - var prevIsHidden = _prevState !== null; + if (wakeables !== null) { + finishedWork.updateQueue = null; + var retryCache = finishedWork.stateNode; - if ( - prevIsHidden !== nextIsHidden && // LegacyHidden doesn't do any hiding — it only pre-renders. - !enableLegacyHidden - ) { - workInProgress.flags |= Visibility; + if (retryCache === null) { + retryCache = finishedWork.stateNode = new PossiblyWeakSet(); } - } - 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(subtreeRenderLanes, OffscreenLane)) { - bubbleProperties(workInProgress); - } - } - return null; - } + wakeables.forEach(function (wakeable) { + // Memoize using the boundary fiber to prevent redundant listeners. + var retry = resolveRetryWakeable.bind(null, finishedWork, wakeable); - case CacheComponent: { - return null; - } + if (!retryCache.has(wakeable)) { + retryCache.add(wakeable); - case TracingMarkerComponent: { - return null; - } - } + { + 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." + ); + } + } + } - throw new Error( - "Unknown unit of work tag (" + - workInProgress.tag + - "). This error is likely caused by a bug in " + - "React. Please file an issue." - ); -} + wakeable.then(retry, retry); + } + }); + } + } // This function detects when a Suspense boundary goes from visible to hidden. + function commitMutationEffects(root, finishedWork, committedLanes) { + inProgressLanes = committedLanes; + inProgressRoot = root; + setCurrentFiber(finishedWork); + commitMutationEffectsOnFiber(finishedWork, root); + setCurrentFiber(finishedWork); + inProgressLanes = null; + inProgressRoot = null; + } -function unwindWork(current, workInProgress, renderLanes) { - // Note: This intentionally doesn't check if we're hydrating because comparing - // to the current tree provider fiber is just as fast and less error-prone. - // Ideally we would have a special version of the work loop only - // for hydration. - popTreeContext(workInProgress); + 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; - switch (workInProgress.tag) { - case ClassComponent: { - var Component = workInProgress.type; + if (deletions !== null) { + for (var i = 0; i < deletions.length; i++) { + var childToDelete = deletions[i]; - if (isContextProvider(Component)) { - popContext(workInProgress); + try { + commitDeletionEffects(root, parentFiber, childToDelete); + } catch (error) { + captureCommitPhaseError(childToDelete, parentFiber, error); + } + } } - var flags = workInProgress.flags; + var prevDebugFiber = getCurrentFiber(); - if (flags & ShouldCapture) { - workInProgress.flags = (flags & ~ShouldCapture) | DidCapture; + if (parentFiber.subtreeFlags & MutationMask) { + var child = parentFiber.child; - if ((workInProgress.mode & ProfileMode) !== NoMode) { - transferActualDuration(workInProgress); + while (child !== null) { + setCurrentFiber(child); + commitMutationEffectsOnFiber(child, root); + child = child.sibling; } - - return workInProgress; } - return null; + setCurrentFiber(prevDebugFiber); } - case HostRoot: { - var root = workInProgress.stateNode; - popHostContainer(workInProgress); - popTopLevelContextObject(workInProgress); - resetWorkInProgressVersions(); - var _flags = workInProgress.flags; - - if ( - (_flags & ShouldCapture) !== NoFlags && - (_flags & DidCapture) === NoFlags - ) { - // 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 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 reconcilation, because those can be set on all fiber types. - return null; - } + switch (finishedWork.tag) { + case FunctionComponent: + case ForwardRef: + case MemoComponent: + case SimpleMemoComponent: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); - case HostComponent: { - // TODO: popHydrationState - popHostContext(workInProgress); - return null; - } + 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 (finishedWork.mode & ProfileMode) { + try { + startLayoutEffectTimer(); + commitHookEffectListUnmount( + Layout | HasEffect, + finishedWork, + finishedWork.return + ); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } - case SuspenseComponent: { - popSuspenseContext(workInProgress); - var suspenseState = workInProgress.memoizedState; + recordLayoutEffectDuration(finishedWork); + } else { + try { + commitHookEffectListUnmount( + Layout | HasEffect, + finishedWork, + finishedWork.return + ); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } + } + } - 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." - ); + return; } - } - var _flags2 = workInProgress.flags; + case ClassComponent: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); - if (_flags2 & ShouldCapture) { - workInProgress.flags = (_flags2 & ~ShouldCapture) | DidCapture; // Captured a suspense effect. Re-render the boundary. + if (flags & Ref) { + if (current !== null) { + safelyDetachRef(current, current.return); + } + } - if ((workInProgress.mode & ProfileMode) !== NoMode) { - transferActualDuration(workInProgress); + return; } - return workInProgress; - } - - return null; - } + case HostComponent: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); - case SuspenseListComponent: { - popSuspenseContext(workInProgress); // SuspenseList doesn't actually catch anything. It should've been - // caught by a nested boundary. If not, it should bubble through. + if (flags & Ref) { + if (current !== null) { + safelyDetachRef(current, current.return); + } + } - return null; - } + return; + } - case HostPortal: - popHostContainer(workInProgress); - return null; + case HostText: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); - case ContextProvider: - var context = workInProgress.type._context; - popProvider(context, workInProgress); - return null; + return; + } - case OffscreenComponent: - case LegacyHiddenComponent: - popRenderLanes(workInProgress); - return null; + case HostRoot: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); - case CacheComponent: - return null; + if (flags & Update) { + { + var containerInfo = root.containerInfo; + var pendingChildren = root.pendingChildren; - default: - return null; - } -} + try { + replaceContainerChildren(containerInfo, pendingChildren); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } + } + } -function unwindInterruptedWork(current, interruptedWork, renderLanes) { - // Note: This intentionally doesn't check if we're hydrating because comparing - // to the current tree provider fiber is just as fast and less error-prone. - // Ideally we would have a special version of the work loop only - // for hydration. - popTreeContext(interruptedWork); + return; + } - switch (interruptedWork.tag) { - case ClassComponent: { - var childContextTypes = interruptedWork.type.childContextTypes; + case HostPortal: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); - if (childContextTypes !== null && childContextTypes !== undefined) { - popContext(interruptedWork); - } + if (flags & Update) { + { + var portal = finishedWork.stateNode; + var _containerInfo = portal.containerInfo; + var _pendingChildren = portal.pendingChildren; + + try { + replaceContainerChildren(_containerInfo, _pendingChildren); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } + } + } - break; - } + return; + } - case HostRoot: { - var root = interruptedWork.stateNode; - popHostContainer(interruptedWork); - popTopLevelContextObject(interruptedWork); - resetWorkInProgressVersions(); - break; - } + case SuspenseComponent: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + var offscreenFiber = finishedWork.child; - case HostComponent: { - popHostContext(interruptedWork); - break; - } + if (offscreenFiber.flags & Visibility) { + var offscreenInstance = offscreenFiber.stateNode; + var newState = offscreenFiber.memoizedState; + var isHidden = newState !== null; // Track the current state on the Offscreen instance so we can + // read it during an event - case HostPortal: - popHostContainer(interruptedWork); - break; + offscreenInstance.isHidden = isHidden; - case SuspenseComponent: - popSuspenseContext(interruptedWork); - break; + if (isHidden) { + var wasHidden = + offscreenFiber.alternate !== null && + offscreenFiber.alternate.memoizedState !== null; - case SuspenseListComponent: - popSuspenseContext(interruptedWork); - break; + if (!wasHidden) { + // TODO: Move to passive phase + markCommitTimeOfFallback(); + } + } + } - case ContextProvider: - var context = interruptedWork.type._context; - popProvider(context, interruptedWork); - break; + if (flags & Update) { + try { + commitSuspenseCallback(finishedWork); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } - case OffscreenComponent: - case LegacyHiddenComponent: - popRenderLanes(interruptedWork); - break; - } -} + attachSuspenseRetryListeners(finishedWork); + } -var didWarnAboutUndefinedSnapshotBeforeUpdate = null; - -{ - didWarnAboutUndefinedSnapshotBeforeUpdate = new Set(); -} // Used during the commit phase to track the state of the Offscreen component stack. -var PossiblyWeakSet = typeof WeakSet === "function" ? WeakSet : Set; -var nextEffect = null; // Used for Profiling builds to track updaters. - -var inProgressLanes = null; -var inProgressRoot = null; -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(); - } -} + return; + } -var callComponentWillUnmountWithTimer = function(current, instance) { - instance.props = current.memoizedProps; - instance.state = current.memoizedState; - - if (current.mode & ProfileMode) { - try { - startLayoutEffectTimer(); - instance.componentWillUnmount(); - } finally { - recordLayoutEffectDuration(current); - } - } else { - instance.componentWillUnmount(); - } -}; // Capture errors so they don't interrupt mounting. - -function safelyCallComponentWillUnmount( - current, - nearestMountedAncestor, - instance -) { - try { - callComponentWillUnmountWithTimer(current, instance); - } catch (error) { - captureCommitPhaseError(current, nearestMountedAncestor, error); - } -} // Capture errors so they don't interrupt mounting. - -function safelyDetachRef(current, nearestMountedAncestor) { - var ref = current.ref; - - if (ref !== null) { - if (typeof ref === "function") { - var retVal; + case OffscreenComponent: { + var _wasHidden = current !== null && current.memoizedState !== null; - try { - if ( - enableProfilerTimer && - enableProfilerCommitHooks && - current.mode & ProfileMode - ) { - try { - startLayoutEffectTimer(); - retVal = ref(null); - } finally { - recordLayoutEffectDuration(current); + { + recursivelyTraverseMutationEffects(root, finishedWork); } - } 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) - ); - } - } - } else { - ref.current = null; - } - } -} + commitReconciliationEffects(finishedWork); -function safelyCallDestroy(current, nearestMountedAncestor, destroy) { - try { - destroy(); - } catch (error) { - captureCommitPhaseError(current, nearestMountedAncestor, error); - } -} + if (flags & Visibility) { + var _offscreenInstance = finishedWork.stateNode; + var _newState = finishedWork.memoizedState; -var focusedInstanceHandle = null; -var shouldFireAfterActiveInstanceBlur = false; -function commitBeforeMutationEffects(root, firstChild) { - focusedInstanceHandle = prepareForCommit(root.containerInfo); - nextEffect = firstChild; - commitBeforeMutationEffects_begin(); // We no longer need to track the active instance fiber - - var shouldFire = shouldFireAfterActiveInstanceBlur; - shouldFireAfterActiveInstanceBlur = false; - focusedInstanceHandle = null; - return shouldFire; -} + var _isHidden = _newState !== null; + // read it during an event -function commitBeforeMutationEffects_begin() { - while (nextEffect !== null) { - var fiber = nextEffect; // This phase is only used for beforeActiveInstanceBlur. + _offscreenInstance.isHidden = _isHidden; + } - var child = fiber.child; + return; + } - if ( - (fiber.subtreeFlags & BeforeMutationMask) !== NoFlags && - child !== null - ) { - child.return = fiber; - nextEffect = child; - } else { - commitBeforeMutationEffects_complete(); - } - } -} + case SuspenseListComponent: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); -function commitBeforeMutationEffects_complete() { - while (nextEffect !== null) { - var fiber = nextEffect; - setCurrentFiber(fiber); + if (flags & Update) { + attachSuspenseRetryListeners(finishedWork); + } - try { - commitBeforeMutationEffectsOnFiber(fiber); - } catch (error) { - captureCommitPhaseError(fiber, fiber.return, error); - } + return; + } - resetCurrentFiber(); - var sibling = fiber.sibling; + case ScopeComponent: { + return; + } - if (sibling !== null) { - sibling.return = fiber.return; - nextEffect = sibling; - return; + default: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + return; + } + } } - nextEffect = fiber.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; -function commitBeforeMutationEffectsOnFiber(finishedWork) { - var current = finishedWork.alternate; - 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. - if ((flags & Snapshot) !== NoFlags) { - setCurrentFiber(finishedWork); + finishedWork.flags &= ~Placement; + } - switch (finishedWork.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - break; + if (flags & Hydrating) { + finishedWork.flags &= ~Hydrating; } + } - case ClassComponent: { - 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 commitLayoutEffects(finishedWork, root, committedLanes) { + inProgressLanes = committedLanes; + inProgressRoot = root; + nextEffect = finishedWork; + commitLayoutEffects_begin(finishedWork, root, committedLanes); + inProgressLanes = null; + inProgressRoot = 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" - ); - } + function commitLayoutEffects_begin(subtreeRoot, root, committedLanes) { + // Suspense layout effects semantics don't change for legacy roots. + var isModernRoot = (subtreeRoot.mode & ConcurrentMode) !== NoMode; - 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" - ); - } - } - } + while (nextEffect !== null) { + var fiber = nextEffect; + var firstChild = fiber.child; - var snapshot = instance.getSnapshotBeforeUpdate( - finishedWork.elementType === finishedWork.type - ? prevProps - : resolveDefaultProps(finishedWork.type, prevProps), - prevState - ); + if ((fiber.subtreeFlags & LayoutMask) !== NoFlags && firstChild !== null) { + firstChild.return = fiber; + nextEffect = firstChild; + } else { + commitLayoutMountEffects_complete(subtreeRoot, root, committedLanes); + } + } + } - { - var didWarnSet = didWarnAboutUndefinedSnapshotBeforeUpdate; + function commitLayoutMountEffects_complete(subtreeRoot, root, committedLanes) { + while (nextEffect !== null) { + var fiber = nextEffect; - if (snapshot === undefined && !didWarnSet.has(finishedWork.type)) { - didWarnSet.add(finishedWork.type); + if ((fiber.flags & LayoutMask) !== NoFlags) { + var current = fiber.alternate; + setCurrentFiber(fiber); - error( - "%s.getSnapshotBeforeUpdate(): A snapshot value (or null) " + - "must be returned. You have returned undefined.", - getComponentNameFromFiber(finishedWork) - ); - } + try { + commitLayoutEffectOnFiber(root, current, fiber, committedLanes); + } catch (error) { + captureCommitPhaseError(fiber, fiber.return, error); } - instance.__reactInternalSnapshotBeforeUpdate = snapshot; + resetCurrentFiber(); } - break; - } + if (fiber === subtreeRoot) { + nextEffect = null; + return; + } - case HostRoot: { - break; - } + var sibling = fiber.sibling; - case HostComponent: - case HostText: - case HostPortal: - case IncompleteClassComponent: - // Nothing to do for these component types - break; + if (sibling !== null) { + sibling.return = fiber.return; + nextEffect = sibling; + return; + } - default: { - 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." - ); + nextEffect = fiber.return; } } - resetCurrentFiber(); - } -} - -function commitHookEffectListUnmount( - flags, - finishedWork, - nearestMountedAncestor -) { - var updateQueue = finishedWork.updateQueue; - var lastEffect = updateQueue !== null ? updateQueue.lastEffect : null; - - if (lastEffect !== null) { - var firstEffect = lastEffect.next; - var effect = firstEffect; - - do { - if ((effect.tag & flags) === flags) { - // Unmount - var destroy = effect.destroy; - effect.destroy = undefined; - - if (destroy !== undefined) { - { - if ((flags & Insertion) !== NoFlags$1) { - setIsRunningInsertionEffect(true); - } - } + function commitPassiveMountEffects( + root, + finishedWork, + committedLanes, + committedTransitions + ) { + nextEffect = finishedWork; + commitPassiveMountEffects_begin( + finishedWork, + root, + committedLanes, + committedTransitions + ); + } - safelyCallDestroy(finishedWork, nearestMountedAncestor, destroy); + function commitPassiveMountEffects_begin( + subtreeRoot, + root, + committedLanes, + committedTransitions + ) { + while (nextEffect !== null) { + var fiber = nextEffect; + var firstChild = fiber.child; - { - if ((flags & Insertion) !== NoFlags$1) { - setIsRunningInsertionEffect(false); - } - } + if ((fiber.subtreeFlags & PassiveMask) !== NoFlags && firstChild !== null) { + firstChild.return = fiber; + nextEffect = firstChild; + } else { + commitPassiveMountEffects_complete( + subtreeRoot, + root, + committedLanes, + committedTransitions + ); } } + } - 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; + function commitPassiveMountEffects_complete( + subtreeRoot, + root, + committedLanes, + committedTransitions + ) { + while (nextEffect !== null) { + var fiber = nextEffect; - do { - if ((effect.tag & flags) === flags) { - var create = effect.create; + if ((fiber.flags & Passive) !== NoFlags) { + setCurrentFiber(fiber); - { - if ((flags & Insertion) !== NoFlags$1) { - setIsRunningInsertionEffect(true); + try { + commitPassiveMountOnFiber( + root, + fiber, + committedLanes, + committedTransitions + ); + } catch (error) { + captureCommitPhaseError(fiber, fiber.return, error); } - } - effect.destroy = create(); + resetCurrentFiber(); + } - { - if ((flags & Insertion) !== NoFlags$1) { - setIsRunningInsertionEffect(false); - } + if (fiber === subtreeRoot) { + nextEffect = null; + return; } - { - var destroy = effect.destroy; + var sibling = fiber.sibling; - if (destroy !== undefined && typeof destroy !== "function") { - var hookName = void 0; + if (sibling !== null) { + sibling.return = fiber.return; + nextEffect = sibling; + return; + } - if ((effect.tag & Layout) !== NoFlags) { - hookName = "useLayoutEffect"; - } else if ((effect.tag & Insertion) !== NoFlags) { - hookName = "useInsertionEffect"; - } else { - hookName = "useEffect"; - } + nextEffect = fiber.return; + } + } - var addendum = void 0; + function commitPassiveMountOnFiber( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions + ) { + switch (finishedWork.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { + if (finishedWork.mode & ProfileMode) { + startPassiveEffectTimer(); - 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://react.dev/link/hooks-data-fetching"; - } else { - addendum = " You returned: " + destroy; + try { + commitHookEffectListMount(Passive$1 | HasEffect, finishedWork); + } finally { + recordPassiveEffectDuration(finishedWork); } - - error( - "%s must not return anything besides a function, " + - "which is used for clean-up.%s", - hookName, - addendum - ); + } else { + commitHookEffectListMount(Passive$1 | HasEffect, finishedWork); } + + break; } } + } - effect = effect.next; - } while (effect !== firstEffect); - } -} + function commitPassiveUnmountEffects(firstChild) { + nextEffect = firstChild; + commitPassiveUnmountEffects_begin(); + } -function commitPassiveEffectDurations(finishedRoot, finishedWork) { - { - // Only Profilers with work in their subtree will have an Update effect scheduled. - if ((finishedWork.flags & Update) !== NoFlags) { - 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. + function commitPassiveUnmountEffects_begin() { + while (nextEffect !== null) { + var fiber = nextEffect; + var child = fiber.child; - var commitTime = getCommitTime(); - var phase = finishedWork.alternate === null ? "mount" : "update"; + if ((nextEffect.flags & ChildDeletion) !== NoFlags) { + var deletions = fiber.deletions; - { - if (isCurrentUpdateNested()) { - phase = "nested-update"; + if (deletions !== null) { + for (var i = 0; i < deletions.length; i++) { + var fiberToDelete = deletions[i]; + nextEffect = fiberToDelete; + commitPassiveUnmountEffectsInsideOfDeletedTree_begin( + fiberToDelete, + fiber + ); } - } - 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. + { + // 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 = fiber.alternate; + + if (previousFiber !== null) { + var detachedChild = previousFiber.child; + + if (detachedChild !== null) { + previousFiber.child = null; + + do { + var detachedSibling = detachedChild.sibling; + detachedChild.sibling = null; + detachedChild = detachedSibling; + } while (detachedChild !== null); + } + } + } - var parentFiber = finishedWork.return; + nextEffect = fiber; + } + } - outer: while (parentFiber !== null) { - switch (parentFiber.tag) { - case HostRoot: - var root = parentFiber.stateNode; - root.passiveEffectDuration += passiveEffectDuration; - break outer; + if ((fiber.subtreeFlags & PassiveMask) !== NoFlags && child !== null) { + child.return = fiber; + nextEffect = child; + } else { + commitPassiveUnmountEffects_complete(); + } + } + } - case Profiler: - var parentStateNode = parentFiber.stateNode; - parentStateNode.passiveEffectDuration += passiveEffectDuration; - break outer; - } + function commitPassiveUnmountEffects_complete() { + while (nextEffect !== null) { + var fiber = nextEffect; - parentFiber = parentFiber.return; - } + if ((fiber.flags & Passive) !== NoFlags) { + setCurrentFiber(fiber); + commitPassiveUnmountOnFiber(fiber); + resetCurrentFiber(); + } - break; + var sibling = fiber.sibling; + + if (sibling !== null) { + sibling.return = fiber.return; + nextEffect = sibling; + return; } + + nextEffect = fiber.return; } } - } -} -function commitLayoutEffectOnFiber( - finishedRoot, - current, - finishedWork, - committedLanes -) { - if ((finishedWork.flags & LayoutMask) !== NoFlags) { - switch (finishedWork.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - { - // 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. + function commitPassiveUnmountOnFiber(finishedWork) { + switch (finishedWork.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { if (finishedWork.mode & ProfileMode) { - try { - startLayoutEffectTimer(); - commitHookEffectListMount(Layout | HasEffect, finishedWork); - } finally { - recordLayoutEffectDuration(finishedWork); - } + startPassiveEffectTimer(); + commitHookEffectListUnmount( + Passive$1 | HasEffect, + finishedWork, + finishedWork.return + ); + recordPassiveEffectDuration(finishedWork); } else { - commitHookEffectListMount(Layout | HasEffect, finishedWork); + commitHookEffectListUnmount( + Passive$1 | HasEffect, + finishedWork, + finishedWork.return + ); } - } - break; + break; + } } + } - case ClassComponent: { - var instance = finishedWork.stateNode; - - if (finishedWork.flags & Update) { - { - 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" - ); - } + 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 (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" - ); - } - } - } + setCurrentFiber(fiber); + commitPassiveUnmountInsideDeletedTreeOnFiber(fiber, nearestMountedAncestor); + resetCurrentFiber(); + var child = fiber.child; // TODO: Only traverse subtree if it has a PassiveStatic flag. (But, if we + // do this, still need to handle `deletedTreeCleanUpLevel` correctly.) - if (finishedWork.mode & ProfileMode) { - try { - startLayoutEffectTimer(); - instance.componentDidMount(); - } finally { - recordLayoutEffectDuration(finishedWork); - } - } else { - instance.componentDidMount(); - } - } 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 (child !== null) { + child.return = fiber; + nextEffect = child; + } else { + commitPassiveUnmountEffectsInsideOfDeletedTree_complete( + deletedSubtreeRoot + ); + } + } + } - { - 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" - ); - } + function commitPassiveUnmountEffectsInsideOfDeletedTree_complete( + deletedSubtreeRoot + ) { + while (nextEffect !== null) { + var fiber = nextEffect; + var sibling = fiber.sibling; + var returnFiber = fiber.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" - ); - } - } - } + { + // 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 (finishedWork.mode & ProfileMode) { - try { - startLayoutEffectTimer(); - instance.componentDidUpdate( - prevProps, - prevState, - instance.__reactInternalSnapshotBeforeUpdate - ); - } finally { - recordLayoutEffectDuration(finishedWork); - } - } else { - instance.componentDidUpdate( - prevProps, - prevState, - instance.__reactInternalSnapshotBeforeUpdate - ); - } - } + if (fiber === deletedSubtreeRoot) { + nextEffect = null; + return; } - } // 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 (sibling !== null) { + sibling.return = returnFiber; + nextEffect = sibling; + return; + } - if (updateQueue !== null) { - { - 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" - ); - } + nextEffect = returnFiber; + } + } - 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. + function commitPassiveUnmountInsideDeletedTreeOnFiber( + current, + nearestMountedAncestor + ) { + switch (current.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { + if (current.mode & ProfileMode) { + startPassiveEffectTimer(); + commitHookEffectListUnmount(Passive$1, current, nearestMountedAncestor); + recordPassiveEffectDuration(current); + } else { + commitHookEffectListUnmount(Passive$1, current, nearestMountedAncestor); + } - commitUpdateQueue(finishedWork, updateQueue, instance); + break; } - - break; } + } // TODO: Reuse reappearLayoutEffects traversal here? - case HostRoot: { - // 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; + var COMPONENT_TYPE = 0; + var HAS_PSEUDO_CLASS_TYPE = 1; + var ROLE_TYPE = 2; + var TEST_NAME_TYPE = 3; + var TEXT_TYPE = 4; - if (finishedWork.child !== null) { - switch (finishedWork.child.tag) { - case HostComponent: - _instance = getPublicInstance(finishedWork.child.stateNode); - break; + if (typeof Symbol === "function" && Symbol.for) { + var symbolFor = Symbol.for; + COMPONENT_TYPE = symbolFor("selector.component"); + HAS_PSEUDO_CLASS_TYPE = symbolFor("selector.has_pseudo_class"); + ROLE_TYPE = symbolFor("selector.role"); + TEST_NAME_TYPE = symbolFor("selector.test_id"); + TEXT_TYPE = symbolFor("selector.text"); + } - case ClassComponent: - _instance = finishedWork.child.stateNode; - break; - } - } + var ReactCurrentActQueue = 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. + var isReactActEnvironmentGlobal = // $FlowExpectedError – Flow doesn't know about IS_REACT_ACT_ENVIRONMENT global + typeof IS_REACT_ACT_ENVIRONMENT !== "undefined" + ? IS_REACT_ACT_ENVIRONMENT + : undefined; // $FlowExpectedError - Flow doesn't know about jest + return warnsIfNotActing; + } + } + function isConcurrentActEnvironment() { + { + var isReactActEnvironmentGlobal = // $FlowExpectedError – Flow doesn't know about IS_REACT_ACT_ENVIRONMENT global + typeof IS_REACT_ACT_ENVIRONMENT !== "undefined" + ? IS_REACT_ACT_ENVIRONMENT + : undefined; - commitUpdateQueue(finishedWork, _updateQueue, _instance); + if (!isReactActEnvironmentGlobal && ReactCurrentActQueue.current !== null) { + // TODO: Include link to relevant documentation page. + error( + "The current testing environment is not configured to support " + + "act(...)" + ); } - break; - } - - case HostComponent: { - var _instance2 = finishedWork.stateNode; // 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. + return isReactActEnvironmentGlobal; + } + } + + var ceil = Math.ceil; + var ReactCurrentDispatcher$2 = ReactSharedInternals.ReactCurrentDispatcher, + ReactCurrentOwner$2 = ReactSharedInternals.ReactCurrentOwner, + ReactCurrentBatchConfig$2 = ReactSharedInternals.ReactCurrentBatchConfig, + ReactCurrentActQueue$1 = 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; // Stack that allows components to change the render lanes for its subtree + // This is a superset of the lanes we started working on at the root. The only + // case where it's different from `workInProgressRootRenderLanes` is when we + // enter a subtree that is hidden and needs to be unhidden: Suspense and + // Offscreen component. + // + // Most things in the work loop should deal with workInProgressRootRenderLanes. + // Most things in begin/complete phases should deal with subtreeRenderLanes. - if (current === null && finishedWork.flags & Update) { - var type = finishedWork.type; - var props = finishedWork.memoizedProps; - commitMount(); - } + var subtreeRenderLanes = NoLanes; + var subtreeRenderLanesCursor = createCursor(NoLanes); // Whether to root completed, errored, suspended, etc. - break; - } + var workInProgressRootExitStatus = RootInProgress; // A fatal error, if one is thrown - case HostText: { - // We have no life-cycles associated with text. - break; - } + var workInProgressRootFatalError = null; // "Included" lanes refer to lanes that were worked on during this render. It's + // slightly different than `renderLanes` because `renderLanes` can change as you + // enter and exit an Offscreen tree. This value is the combination of all render + // lanes for the entire render phase. - case HostPortal: { - // We have no life-cycles associated with portals. - break; - } + var workInProgressRootIncludedLanes = NoLanes; // The work left over by components that were visited during this render. Only + // includes unprocessed updates, not work in bailed out children. - case Profiler: { - { - 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"; + var workInProgressRootSkippedLanes = NoLanes; // Lanes that were updated (in an interleaved event) during this render. - { - if (isCurrentUpdateNested()) { - phase = "nested-update"; - } - } + var workInProgressRootInterleavedUpdatedLanes = NoLanes; // Lanes that were updated during the render phase (*not* an interleaved event). - if (typeof onRender === "function") { - onRender( - finishedWork.memoizedProps.id, - phase, - finishedWork.actualDuration, - finishedWork.treeBaseDuration, - finishedWork.actualStartTime, - commitTime - ); - } + var workInProgressRootPingedLanes = NoLanes; // Errors that are thrown during the render phase. - { - 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; - } + var workInProgressRootConcurrentErrors = null; // These are errors that we recovered from without surfacing them to the UI. + // We will log them once the tree commits. - parentFiber = parentFiber.return; - } - } - } + var workInProgressRootRecoverableErrors = null; // The most recent time we committed a fallback. This lets us ensure a train + // model where we don't commit new loading states in too quick succession. - break; - } + var globalMostRecentFallbackTime = 0; + var FALLBACK_THROTTLE_MS = 500; // The absolute time for when we should start giving up on rendering + // more and prefer CPU suspense heuristics instead. - case SuspenseComponent: { - 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. - case SuspenseListComponent: - case IncompleteClassComponent: - case ScopeComponent: - case OffscreenComponent: - case LegacyHiddenComponent: - case TracingMarkerComponent: { - break; - } + var RENDER_TIMEOUT_MS = 500; + var workInProgressTransitions = null; - default: - 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." - ); + function resetRenderTimer() { + workInProgressRootRenderTargetTime = now() + RENDER_TIMEOUT_MS; } - } - { - { - if (finishedWork.flags & Ref) { - commitAttachRef(finishedWork); - } + function getRenderTargetTime() { + return workInProgressRootRenderTargetTime; } - } -} + var hasUncaughtError = false; + var firstUncaughtError = null; + var legacyErrorBoundariesThatAlreadyFailed = null; // Only used when enableProfilerNestedUpdateScheduledHook is true; + var rootDoesHavePassiveEffects = false; + var rootWithPendingPassiveEffects = null; + var pendingPassiveEffectsLanes = NoLanes; + var pendingPassiveProfilerEffects = []; + var pendingPassiveTransitions = null; // Use these to prevent an infinite loop of nested updates -function commitAttachRef(finishedWork) { - var ref = finishedWork.ref; + 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; // If two updates are scheduled within the same event, we should treat their + // event times as simultaneous, even if the actual clock time has advanced + // between the first and second call. - if (ref !== null) { - var instance = finishedWork.stateNode; - var instanceToUse; + var currentEventTime = NoTimestamp; + var currentEventTransitionLane = NoLanes; + var isRunningInsertionEffect = false; + function getWorkInProgressRoot() { + return workInProgressRoot; + } + function requestEventTime() { + if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { + // We're inside React, so it's fine to read the actual time. + return now(); + } // We're not inside React, so we may be in the middle of a browser event. + + if (currentEventTime !== NoTimestamp) { + // Use the same start time for all updates until we enter React again. + return currentEventTime; + } // This is the first update since React yielded. Compute a new start time. - switch (finishedWork.tag) { - case HostComponent: - instanceToUse = getPublicInstance(instance); - break; + currentEventTime = now(); + return currentEventTime; + } + function requestUpdateLane(fiber) { + // Special cases + var mode = fiber.mode; - default: - instanceToUse = instance; - } // Moved outside to ensure DCE works with this flag + 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$2.transition !== null) { + var transition = ReactCurrentBatchConfig$2.transition; + + if (!transition._updatedFibers) { + transition._updatedFibers = new Set(); + } - if (typeof ref === "function") { - var retVal; + transition._updatedFibers.add(fiber); + } // 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 (finishedWork.mode & ProfileMode) { - try { - startLayoutEffectTimer(); - retVal = ref(instanceToUse); - } finally { - recordLayoutEffectDuration(finishedWork); + if (currentEventTransitionLane === NoLane) { + // All transitions within the same event are assigned the same lane. + currentEventTransitionLane = claimNextTransitionLane(); } - } else { - retVal = ref(instanceToUse); + + return currentEventTransitionLane; + } // 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; + } + + 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 scheduleUpdateOnFiber(root, fiber, lane, eventTime) { + updatedComponentForProfiler = { + name: getComponentNameFromFiber(fiber), + key: fiber.key, + }; + checkForNestedUpdates(); + { - if (typeof retVal === "function") { - error( - "Unexpected return value from a callback ref in %s. " + - "A callback ref should not return a function.", - getComponentNameFromFiber(finishedWork) - ); + if (isRunningInsertionEffect) { + error("useInsertionEffect must not schedule updates."); } } - } else { + { - if (!ref.hasOwnProperty("current")) { - error( - "Unexpected ref object provided for %s. " + - "Use either a ref-setter function or React.createRef().", - getComponentNameFromFiber(finishedWork) - ); + if (isFlushingPassiveEffects) { + didScheduleUpdateDuringPassiveEffects = true; } - } + } // Mark that the root has a pending update. - ref.current = instanceToUse; - } - } -} + markRootUpdated(root, lane, eventTime); -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; -} + 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 detachFiberAfterEffects(fiber) { - var alternate = fiber.alternate; - - if (alternate !== null) { - fiber.alternate = null; - detachFiberAfterEffects(alternate); - } // Note: Defensively using negation instead of < in case - // `deletedTreeCleanUpLevel` is undefined. - - { - // 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 - // tree, which has its own pointers to children, parents, and siblings. - // The other host nodes also point back to fibers, so we should detach that - // one, too. - - if (fiber.tag === HostComponent) { - var hostInstance = fiber.stateNode; - } - - fiber.stateNode = null; // I'm intentionally not clearing the `return` field in this level. We - // already disconnect the `return` pointer at the root of the deleted - // subtree (in `detachFiberMutation`). Besides, `return` by itself is not - // cyclical — it's only cyclical when combined with `child`, `sibling`, and - // `alternate`. But we'll clear it in the next level anyway, just in case. + warnIfUpdatesNotWrappedWithActDEV(fiber); + + 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. Unless the + // `deferRenderPhaseUpdateToNextBatch` flag is off and this is a render + // phase update. In that case, we don't treat render phase updates as if + // they were interleaved, for backwards compat reasons. + if ((executionContext & RenderContext) === NoContext) { + workInProgressRootInterleavedUpdatedLanes = mergeLanes( + workInProgressRootInterleavedUpdatedLanes, + lane + ); + } - { - fiber._debugOwner = null; - } + 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$1(root, workInProgressRootRenderLanes); + } + } - { - // 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 - // - // The purpose of this branch is to be super aggressive so we can measure - // if there's any difference in memory impact. If there is, that could - // indicate a React leak we don't know about. - fiber.return = null; - fiber.dependencies = null; - fiber.memoizedProps = null; - fiber.memoizedState = null; - fiber.pendingProps = null; - fiber.stateNode = null; // TODO: Move to `commitPassiveUnmountInsideDeletedTreeOnFiber` instead. + ensureRootIsScheduled(root, eventTime); - fiber.updateQueue = null; + if ( + lane === SyncLane && + executionContext === NoContext && + (fiber.mode & ConcurrentMode) === NoMode && // Treat `act` as if it's inside `batchedUpdates`, even in legacy mode. + !ReactCurrentActQueue$1.isBatchingLegacy + ) { + // 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(); + flushSyncCallbacksOnlyInLegacyMode(); + } + } } - } -} - -function emptyPortalContainer(current) { - var portal = current.stateNode; - var containerInfo = portal.containerInfo; - var emptyChildSet = createContainerChildSet(containerInfo); -} + 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 ( + // TODO: Remove outdated deferRenderPhaseUpdateToNextBatch experiment. We + // decided not to enable it. + (executionContext & RenderContext) !== NoContext + ); + } // Use this function to schedule a task for a root. There's only one task per + // root; if a task was already scheduled, we'll check to make sure the priority + // of the existing task is the same as the priority of the next level that the + // root has work on. This function is called on every update, and right before + // exiting a task. -function commitPlacement(finishedWork) { - { - return; - } // Recursively insert all host nodes into the parent. -} + function ensureRootIsScheduled(root, currentTime) { + var existingCallbackNode = root.callbackNode; // Check if any lanes are being starved by other work. If so, mark them as + // expired so we know to work on those next. -function commitDeletionEffects(root, returnFiber, deletedFiber) { - { - // Detach refs and call componentWillUnmount() on the whole subtree. - commitDeletionEffectsOnFiber(root, returnFiber, deletedFiber); - } + markStarvedLanesAsExpired(root, currentTime); // Determine the next lanes to work on, and their priority. - detachFiberMutation(deletedFiber); -} + var nextLanes = getNextLanes( + root, + root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes + ); -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 (nextLanes === NoLanes) { + // Special case: There's nothing to work on. + if (existingCallbackNode !== null) { + cancelCallback$1(existingCallbackNode); + } -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. - - switch (deletedFiber.tag) { - case HostComponent: { - { - safelyDetachRef(deletedFiber, nearestMountedAncestor); - } // Intentional fallthrough to next branch - } - // eslint-disable-next-line-no-fallthrough + root.callbackNode = null; + root.callbackPriority = NoLane; + return; + } // We use the highest priority lane to represent the priority of the callback. - 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. - { - recursivelyTraverseDeletionEffects( - finishedRoot, - nearestMountedAncestor, - deletedFiber - ); - } + var newCallbackPriority = getHighestPriorityLane(nextLanes); // Check if there's an existing task. We may be able to reuse it. - return; - } + var existingCallbackPriority = root.callbackPriority; - case DehydratedFragment: { - return; - } + if ( + existingCallbackPriority === newCallbackPriority && // Special case related to `act`. If the currently scheduled task is a + // Scheduler task, rather than an `act` task, cancel it and re-scheduled + // on the `act` queue. + !( + ReactCurrentActQueue$1.current !== null && + existingCallbackNode !== fakeActCallbackNode + ) + ) { + { + // If we're going to re-use an existing task, it needs to exist. + // Assume that discrete update microtasks are non-cancellable and null. + // TODO: Temporary until we confirm this warning is not fired. + if ( + existingCallbackNode == null && + existingCallbackPriority !== SyncLane + ) { + error( + "Expected scheduled callback to exist. This error is likely caused by a bug in React. Please file an issue." + ); + } + } // The priority hasn't changed. We can reuse the existing task. Exit. - case HostPortal: { - { - emptyPortalContainer(deletedFiber); - recursivelyTraverseDeletionEffects( - finishedRoot, - nearestMountedAncestor, - deletedFiber - ); + return; } - return; - } - - case FunctionComponent: - case ForwardRef: - case MemoComponent: - case SimpleMemoComponent: { - { - var updateQueue = deletedFiber.updateQueue; + if (existingCallbackNode != null) { + // Cancel the existing callback. We'll schedule a new one below. + cancelCallback$1(existingCallbackNode); + } // Schedule a new callback. - if (updateQueue !== null) { - var lastEffect = updateQueue.lastEffect; + var newCallbackNode; - if (lastEffect !== null) { - var firstEffect = lastEffect.next; - var effect = firstEffect; + if (newCallbackPriority === SyncLane) { + // Special case: Sync React callbacks are scheduled on a special + // internal queue + if (root.tag === LegacyRoot) { + if (ReactCurrentActQueue$1.isBatchingLegacy !== null) { + ReactCurrentActQueue$1.didScheduleLegacyUpdate = true; + } - do { - var _effect = effect, - destroy = _effect.destroy, - tag = _effect.tag; - - if (destroy !== undefined) { - if ((tag & Insertion) !== NoFlags$1) { - safelyCallDestroy( - deletedFiber, - nearestMountedAncestor, - destroy - ); - } else if ((tag & Layout) !== NoFlags$1) { - if (deletedFiber.mode & ProfileMode) { - startLayoutEffectTimer(); - safelyCallDestroy( - deletedFiber, - nearestMountedAncestor, - destroy - ); - recordLayoutEffectDuration(deletedFiber); - } else { - safelyCallDestroy( - deletedFiber, - nearestMountedAncestor, - destroy - ); - } - } - } + scheduleLegacySyncCallback(performSyncWorkOnRoot.bind(null, root)); + } else { + scheduleSyncCallback(performSyncWorkOnRoot.bind(null, root)); + } - effect = effect.next; - } while (effect !== firstEffect); - } + { + // Flush the queue in an Immediate task. + scheduleCallback$1(ImmediatePriority, flushSyncCallbacks); } - } - recursivelyTraverseDeletionEffects( - finishedRoot, - nearestMountedAncestor, - deletedFiber - ); - return; - } + newCallbackNode = null; + } else { + var schedulerPriorityLevel; - case ClassComponent: { - { - safelyDetachRef(deletedFiber, nearestMountedAncestor); - var instance = deletedFiber.stateNode; + switch (lanesToEventPriority(nextLanes)) { + case DiscreteEventPriority: + schedulerPriorityLevel = ImmediatePriority; + break; - if (typeof instance.componentWillUnmount === "function") { - safelyCallComponentWillUnmount( - deletedFiber, - nearestMountedAncestor, - instance - ); - } - } + case ContinuousEventPriority: + schedulerPriorityLevel = UserBlockingPriority; + break; - recursivelyTraverseDeletionEffects( - finishedRoot, - nearestMountedAncestor, - deletedFiber - ); - return; - } + case DefaultEventPriority: + schedulerPriorityLevel = NormalPriority; + break; - case ScopeComponent: { - recursivelyTraverseDeletionEffects( - finishedRoot, - nearestMountedAncestor, - deletedFiber - ); - return; - } + case IdleEventPriority: + schedulerPriorityLevel = IdlePriority; + break; - case OffscreenComponent: { - { - recursivelyTraverseDeletionEffects( - finishedRoot, - nearestMountedAncestor, - deletedFiber + default: + schedulerPriorityLevel = NormalPriority; + break; + } + + newCallbackNode = scheduleCallback$1( + schedulerPriorityLevel, + performConcurrentWorkOnRoot.bind(null, root) ); } - break; - } + root.callbackPriority = newCallbackPriority; + root.callbackNode = newCallbackNode; + } // This is the entry point for every concurrent task, i.e. anything that + // goes through Scheduler. + + function performConcurrentWorkOnRoot(root, didTimeout) { + { + resetNestedUpdateFlag(); + } // Since we know we're in a React event, we can clear the current + // event time. The next update will compute a new event time. + + currentEventTime = NoTimestamp; + currentEventTransitionLane = NoLanes; + + 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. - default: { - recursivelyTraverseDeletionEffects( - finishedRoot, - nearestMountedAncestor, - deletedFiber + var lanes = getNextLanes( + root, + root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes ); - return; - } - } -} -function commitSuspenseCallback(finishedWork) { - // TODO: Move this to passive phase - var newState = finishedWork.memoizedState; -} + 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) && + !didTimeout; + var exitStatus = shouldTimeSlice + ? renderRootConcurrent(root, lanes) + : renderRootSync(root, lanes); + + if (exitStatus !== RootInProgress) { + if (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 errorRetryLanes = getLanesToRetrySynchronouslyOnError(root); + + if (errorRetryLanes !== NoLanes) { + lanes = errorRetryLanes; + exitStatus = recoverFromConcurrentError(root, errorRetryLanes); + } + } -function attachSuspenseRetryListeners(finishedWork) { - // 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 wakeables = finishedWork.updateQueue; + if (exitStatus === RootFatalErrored) { + var fatalError = workInProgressRootFatalError; + prepareFreshStack(root, NoLanes); + markRootSuspended$1(root, lanes); + ensureRootIsScheduled(root, now()); + throw fatalError; + } - if (wakeables !== null) { - finishedWork.updateQueue = null; - var retryCache = finishedWork.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. + // + // This should only happen during a concurrent render, not a discrete or + // synchronous update. We should have already checked for this when we + // unwound the stack. + markRootSuspended$1(root, lanes); + } 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 renderWasConcurrent = !includesBlockingLane(root, lanes); + var finishedWork = root.current.alternate; - if (retryCache === null) { - retryCache = finishedWork.stateNode = new PossiblyWeakSet(); - } + if ( + renderWasConcurrent && + !isRenderConsistentWithExternalStores(finishedWork) + ) { + // A store was mutated in an interleaved event. Render again, + // synchronously, to block further mutations. + exitStatus = renderRootSync(root, lanes); // We need to check again if something threw - wakeables.forEach(function(wakeable) { - // Memoize using the boundary fiber to prevent redundant listeners. - var retry = resolveRetryWakeable.bind(null, finishedWork, wakeable); + if (exitStatus === RootErrored) { + var _errorRetryLanes = getLanesToRetrySynchronouslyOnError(root); - if (!retryCache.has(wakeable)) { - retryCache.add(wakeable); + if (_errorRetryLanes !== NoLanes) { + lanes = _errorRetryLanes; + exitStatus = recoverFromConcurrentError(root, _errorRetryLanes); // We assume the tree is now consistent because we didn't yield to any + // concurrent events. + } + } - { - 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 (exitStatus === RootFatalErrored) { + var _fatalError = workInProgressRootFatalError; + prepareFreshStack(root, NoLanes); + markRootSuspended$1(root, lanes); + ensureRootIsScheduled(root, now()); + 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, lanes); } + } + + ensureRootIsScheduled(root, now()); - wakeable.then(retry, retry); + 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); } - }); - } -} // This function detects when a Suspense boundary goes from visible to hidden. -function commitMutationEffects(root, finishedWork, committedLanes) { - inProgressLanes = committedLanes; - inProgressRoot = root; - setCurrentFiber(finishedWork); - commitMutationEffectsOnFiber(finishedWork, root); - setCurrentFiber(finishedWork); - inProgressLanes = null; - inProgressRoot = null; -} -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; + return null; + } + + function recoverFromConcurrentError(root, 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; - if (deletions !== null) { - for (var i = 0; i < deletions.length; i++) { - var childToDelete = deletions[i]; + if (isRootDehydrated(root)) { + // 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 { - commitDeletionEffects(root, parentFiber, childToDelete); - } catch (error) { - captureCommitPhaseError(childToDelete, parentFiber, error); + { + errorHydratingContainer(root.containerInfo); + } } - } - } - var prevDebugFiber = getCurrentFiber(); + var exitStatus = renderRootSync(root, errorRetryLanes); + + if (exitStatus !== RootErrored) { + // Successfully finished rendering on retry + // 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 (parentFiber.subtreeFlags & MutationMask) { - var child = parentFiber.child; + if (errorsFromSecondAttempt !== null) { + queueRecoverableErrors(errorsFromSecondAttempt); + } + } - while (child !== null) { - setCurrentFiber(child); - commitMutationEffectsOnFiber(child, root); - child = child.sibling; + return exitStatus; } - } - setCurrentFiber(prevDebugFiber); -} + function queueRecoverableErrors(errors) { + if (workInProgressRootRecoverableErrors === null) { + workInProgressRootRecoverableErrors = errors; + } else { + workInProgressRootRecoverableErrors.push.apply( + workInProgressRootRecoverableErrors, + errors + ); + } + } -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 reconcilation, 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 + function finishConcurrentRender(root, exitStatus, lanes) { + switch (exitStatus) { + case RootInProgress: + case RootFatalErrored: { + throw new Error("Root did not complete. This is a bug in React."); + } + // Flow knows about invariant, so it complains if I add a break + // statement, but eslint doesn't know about invariant, so it complains + // if I do. eslint-disable-next-line no-fallthrough + + case RootErrored: { + // We should have already attempted to retry this tree. If we reached + // this point, it errored again. Commit it. + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions ); - 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. + break; + } - if (finishedWork.mode & ProfileMode) { - try { - startLayoutEffectTimer(); - commitHookEffectListUnmount( - Layout | HasEffect, - finishedWork, - finishedWork.return - ); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } + case RootSuspended: { + markRootSuspended$1(root, lanes); // We have an acceptable loading state. We need to figure out if we + // should immediately commit it or wait a bit. - recordLayoutEffectDuration(finishedWork); - } else { - try { - commitHookEffectListUnmount( - Layout | HasEffect, - finishedWork, - finishedWork.return - ); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } - } - } + if ( + includesOnlyRetries(lanes) && // do not delay if we're inside an act() scope + !shouldForceFlushFallbacksInDEV() + ) { + // 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(); // Don't bother with a very short suspense time. + + if (msUntilTimeout > 10) { + var nextLanes = getNextLanes(root, NoLanes); + + if (nextLanes !== NoLanes) { + // There's additional work on this root. + break; + } - return; - } + var suspendedLanes = root.suspendedLanes; - case ClassComponent: { - recursivelyTraverseMutationEffects(root, finishedWork); - commitReconciliationEffects(finishedWork); + if (!isSubsetOfLanes(suspendedLanes, lanes)) { + // We should prefer to render the fallback of at the last + // suspended level. Ping the last suspended level to try + // rendering it again. + // FIXME: What if the suspended lanes are Idle? Should not restart. + var eventTime = requestEventTime(); + markRootPinged(root, suspendedLanes); + break; + } // 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. + + root.timeoutHandle = scheduleTimeout( + commitRoot.bind( + null, + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ), + msUntilTimeout + ); + break; + } + } // The work expired. Commit immediately. - if (flags & Ref) { - if (current !== null) { - safelyDetachRef(current, current.return); + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); + break; } - } - return; - } + case RootSuspendedWithDelay: { + markRootSuspended$1(root, lanes); - case HostComponent: { - recursivelyTraverseMutationEffects(root, finishedWork); - commitReconciliationEffects(finishedWork); + 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. + break; + } - if (flags & Ref) { - if (current !== null) { - safelyDetachRef(current, current.return); + if (!shouldForceFlushFallbacksInDEV()) { + // This is not a transition, but we did trigger an avoided state. + // Schedule a placeholder to display after a short delay, using the Just + // Noticeable Difference. + // TODO: Is the JND optimization worth the added complexity? If this is + // the only reason we track the event time, then probably not. + // Consider removing. + var mostRecentEventTime = getMostRecentEventTime(root, lanes); + var eventTimeMs = mostRecentEventTime; + var timeElapsedMs = now() - eventTimeMs; + + var _msUntilTimeout = jnd(timeElapsedMs) - timeElapsedMs; // Don't bother with a very short suspense time. + + if (_msUntilTimeout > 10) { + // Instead of committing the fallback immediately, wait for more data + // to arrive. + root.timeoutHandle = scheduleTimeout( + commitRoot.bind( + null, + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ), + _msUntilTimeout + ); + break; + } + } // Commit the placeholder. + + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); + break; + } + + case RootCompleted: { + // The work completed. Ready to commit. + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); + break; } - } - return; + default: { + throw new Error("Unknown root exit status."); + } + } } - case HostText: { - recursivelyTraverseMutationEffects(root, finishedWork); - commitReconciliationEffects(finishedWork); + 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; - return; - } + while (true) { + if (node.flags & StoreConsistency) { + var updateQueue = node.updateQueue; - case HostRoot: { - recursivelyTraverseMutationEffects(root, finishedWork); - commitReconciliationEffects(finishedWork); + if (updateQueue !== null) { + var checks = updateQueue.stores; - if (flags & Update) { - { - var containerInfo = root.containerInfo; - var pendingChildren = root.pendingChildren; + if (checks !== null) { + for (var i = 0; i < checks.length; i++) { + var check = checks[i]; + var getSnapshot = check.getSnapshot; + var renderedValue = check.value; - try { - replaceContainerChildren(containerInfo, pendingChildren); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); + 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; + } + } + } } } - } - return; - } + var child = node.child; - case HostPortal: { - recursivelyTraverseMutationEffects(root, finishedWork); - commitReconciliationEffects(finishedWork); + if (node.subtreeFlags & StoreConsistency && child !== null) { + child.return = node; + node = child; + continue; + } - if (flags & Update) { - { - var portal = finishedWork.stateNode; - var _containerInfo = portal.containerInfo; - var _pendingChildren = portal.pendingChildren; + if (node === finishedWork) { + return true; + } - try { - replaceContainerChildren(_containerInfo, _pendingChildren); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); + while (node.sibling === null) { + if (node.return === null || node.return === finishedWork) { + return true; } + + node = node.return; } - } - return; + 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 SuspenseComponent: { - recursivelyTraverseMutationEffects(root, finishedWork); - commitReconciliationEffects(finishedWork); - var offscreenFiber = finishedWork.child; + function markRootSuspended$1(root, suspendedLanes) { + // 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(root, suspendedLanes); + } // This is the entry point for synchronous tasks that don't go + // through Scheduler - if (offscreenFiber.flags & Visibility) { - var offscreenInstance = offscreenFiber.stateNode; - var newState = offscreenFiber.memoizedState; - var isHidden = newState !== null; // Track the current state on the Offscreen instance so we can - // read it during an event + function performSyncWorkOnRoot(root) { + { + syncNestedUpdateFlag(); + } - offscreenInstance.isHidden = isHidden; + if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { + throw new Error("Should not already be working."); + } - if (isHidden) { - var wasHidden = - offscreenFiber.alternate !== null && - offscreenFiber.alternate.memoizedState !== null; + flushPassiveEffects(); + var lanes = getNextLanes(root, NoLanes); - if (!wasHidden) { - // TODO: Move to passive phase - markCommitTimeOfFallback(); - } - } + if (!includesSomeLane(lanes, SyncLane)) { + // There's no remaining sync work left. + ensureRootIsScheduled(root, now()); + return null; } - if (flags & Update) { - try { - commitSuspenseCallback(finishedWork); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } + var exitStatus = renderRootSync(root, lanes); - attachSuspenseRetryListeners(finishedWork); + 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 errorRetryLanes = getLanesToRetrySynchronouslyOnError(root); + + if (errorRetryLanes !== NoLanes) { + lanes = errorRetryLanes; + exitStatus = recoverFromConcurrentError(root, errorRetryLanes); + } } - return; - } + if (exitStatus === RootFatalErrored) { + var fatalError = workInProgressRootFatalError; + prepareFreshStack(root, NoLanes); + markRootSuspended$1(root, lanes); + ensureRootIsScheduled(root, now()); + throw fatalError; + } - case OffscreenComponent: { - var _wasHidden = current !== null && current.memoizedState !== null; + if (exitStatus === RootDidNotComplete) { + throw new Error("Root did not complete. This is a bug in React."); + } // We now have a consistent tree. Because this is a sync render, we + // will commit it even if something suspended. - { - recursivelyTraverseMutationEffects(root, finishedWork); - } + var finishedWork = root.current.alternate; + root.finishedWork = finishedWork; + root.finishedLanes = lanes; + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); // Before exiting, make sure there's a callback scheduled for the next + // pending level. - commitReconciliationEffects(finishedWork); + ensureRootIsScheduled(root, now()); + return null; + } + function batchedUpdates$1(fn, a) { + var prevExecutionContext = executionContext; + executionContext |= BatchedContext; - if (flags & Visibility) { - var _offscreenInstance = finishedWork.stateNode; - var _newState = finishedWork.memoizedState; + try { + return fn(a); + } finally { + executionContext = prevExecutionContext; // If there were legacy sync updates, flush them at the end of the outer + // most batchedUpdates-like method. - var _isHidden = _newState !== null; - // read it during an event + if ( + executionContext === NoContext && // Treat `act` as if it's inside `batchedUpdates`, even in legacy mode. + !ReactCurrentActQueue$1.isBatchingLegacy + ) { + resetRenderTimer(); + flushSyncCallbacksOnlyInLegacyMode(); + } + } + } + // Warning, this opts-out of checking the function body. - _offscreenInstance.isHidden = _isHidden; + // 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(); } - return; - } + var prevExecutionContext = executionContext; + executionContext |= BatchedContext; + var prevTransition = ReactCurrentBatchConfig$2.transition; + var previousPriority = getCurrentUpdatePriority(); - case SuspenseListComponent: { - recursivelyTraverseMutationEffects(root, finishedWork); - commitReconciliationEffects(finishedWork); + try { + ReactCurrentBatchConfig$2.transition = null; + setCurrentUpdatePriority(DiscreteEventPriority); - if (flags & Update) { - attachSuspenseRetryListeners(finishedWork); + if (fn) { + return fn(); + } else { + return undefined; + } + } finally { + setCurrentUpdatePriority(previousPriority); + ReactCurrentBatchConfig$2.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) { + flushSyncCallbacks(); + } } - - return; } - - case ScopeComponent: { - return; + function pushRenderLanes(fiber, lanes) { + push(subtreeRenderLanesCursor, subtreeRenderLanes, fiber); + subtreeRenderLanes = mergeLanes(subtreeRenderLanes, lanes); + workInProgressRootIncludedLanes = mergeLanes( + workInProgressRootIncludedLanes, + lanes + ); } - - default: { - recursivelyTraverseMutationEffects(root, finishedWork); - commitReconciliationEffects(finishedWork); - return; + function popRenderLanes(fiber) { + subtreeRenderLanes = subtreeRenderLanesCursor.current; + pop(subtreeRenderLanesCursor, fiber); } - } -} - -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; - nextEffect = finishedWork; - commitLayoutEffects_begin(finishedWork, root, committedLanes); - inProgressLanes = null; - inProgressRoot = null; -} + function prepareFreshStack(root, lanes) { + root.finishedWork = null; + root.finishedLanes = NoLanes; + var timeoutHandle = root.timeoutHandle; -function commitLayoutEffects_begin(subtreeRoot, root, committedLanes) { - // Suspense layout effects semantics don't change for legacy roots. - var isModernRoot = (subtreeRoot.mode & ConcurrentMode) !== NoMode; + 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 Complains noTimeout is not a TimeoutID, despite the check above - while (nextEffect !== null) { - var fiber = nextEffect; - var firstChild = fiber.child; + cancelTimeout(timeoutHandle); + } - if ((fiber.subtreeFlags & LayoutMask) !== NoFlags && firstChild !== null) { - firstChild.return = fiber; - nextEffect = firstChild; - } else { - commitLayoutMountEffects_complete(subtreeRoot, root, committedLanes); - } - } -} + if (workInProgress !== null) { + var interruptedWork = workInProgress.return; -function commitLayoutMountEffects_complete(subtreeRoot, root, committedLanes) { - while (nextEffect !== null) { - var fiber = nextEffect; + while (interruptedWork !== null) { + var current = interruptedWork.alternate; + unwindInterruptedWork(current, interruptedWork); + interruptedWork = interruptedWork.return; + } + } - if ((fiber.flags & LayoutMask) !== NoFlags) { - var current = fiber.alternate; - setCurrentFiber(fiber); + workInProgressRoot = root; + var rootWorkInProgress = createWorkInProgress(root.current, null); + workInProgress = rootWorkInProgress; + workInProgressRootRenderLanes = subtreeRenderLanes = workInProgressRootIncludedLanes = lanes; + workInProgressRootExitStatus = RootInProgress; + workInProgressRootFatalError = null; + workInProgressRootSkippedLanes = NoLanes; + workInProgressRootInterleavedUpdatedLanes = NoLanes; + workInProgressRootPingedLanes = NoLanes; + workInProgressRootConcurrentErrors = null; + workInProgressRootRecoverableErrors = null; + finishQueueingConcurrentUpdates(); - try { - commitLayoutEffectOnFiber(root, current, fiber, committedLanes); - } catch (error) { - captureCommitPhaseError(fiber, fiber.return, error); + { + ReactStrictModeWarnings.discardPendingWarnings(); } - resetCurrentFiber(); + return rootWorkInProgress; } - if (fiber === subtreeRoot) { - nextEffect = null; - return; - } + function handleError(root, thrownValue) { + do { + var erroredWork = workInProgress; - var sibling = fiber.sibling; + try { + // Reset module-level state that was set during the render phase. + resetContextDependencies(); + resetHooksAfterThrow(); + resetCurrentFiber(); // TODO: I found and added this missing line while investigating a + // separate issue. Write a regression test using string refs. + + ReactCurrentOwner$2.current = null; + + if (erroredWork === null || erroredWork.return === 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; + } - if (sibling !== null) { - sibling.return = fiber.return; - nextEffect = sibling; - return; - } + if (enableProfilerTimer && 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); + } - nextEffect = fiber.return; - } -} + if (enableSchedulingProfiler) { + markComponentRenderStopped(); -function commitPassiveMountEffects( - root, - finishedWork, - committedLanes, - committedTransitions -) { - nextEffect = finishedWork; - commitPassiveMountEffects_begin( - finishedWork, - root, - committedLanes, - committedTransitions - ); -} + if ( + thrownValue !== null && + typeof thrownValue === "object" && + typeof thrownValue.then === "function" + ) { + var wakeable = thrownValue; + markComponentSuspended( + erroredWork, + wakeable, + workInProgressRootRenderLanes + ); + } else { + markComponentErrored( + erroredWork, + thrownValue, + workInProgressRootRenderLanes + ); + } + } -function commitPassiveMountEffects_begin( - subtreeRoot, - root, - committedLanes, - committedTransitions -) { - while (nextEffect !== null) { - var fiber = nextEffect; - var firstChild = fiber.child; - - if ((fiber.subtreeFlags & PassiveMask) !== NoFlags && firstChild !== null) { - firstChild.return = fiber; - nextEffect = firstChild; - } else { - commitPassiveMountEffects_complete( - subtreeRoot, - root, - committedLanes, - committedTransitions - ); - } - } -} + throwException( + root, + erroredWork.return, + erroredWork, + thrownValue, + workInProgressRootRenderLanes + ); + completeUnitOfWork(erroredWork); + } catch (yetAnotherThrownValue) { + // Something in the return path also threw. + thrownValue = yetAnotherThrownValue; + + if (workInProgress === erroredWork && erroredWork !== null) { + // If this boundary has already errored, then we had trouble processing + // the error. Bubble it to the next boundary. + erroredWork = erroredWork.return; + workInProgress = erroredWork; + } else { + erroredWork = workInProgress; + } -function commitPassiveMountEffects_complete( - subtreeRoot, - root, - committedLanes, - committedTransitions -) { - while (nextEffect !== null) { - var fiber = nextEffect; + continue; + } // Return to the normal work loop. - if ((fiber.flags & Passive) !== NoFlags) { - setCurrentFiber(fiber); + return; + } while (true); + } - try { - commitPassiveMountOnFiber( - root, - fiber, - committedLanes, - committedTransitions - ); - } catch (error) { - captureCommitPhaseError(fiber, fiber.return, error); - } + function pushDispatcher() { + var prevDispatcher = ReactCurrentDispatcher$2.current; + ReactCurrentDispatcher$2.current = ContextOnlyDispatcher; - resetCurrentFiber(); + 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 (fiber === subtreeRoot) { - nextEffect = null; - return; + function popDispatcher(prevDispatcher) { + ReactCurrentDispatcher$2.current = prevDispatcher; } - var sibling = fiber.sibling; - - if (sibling !== null) { - sibling.return = fiber.return; - nextEffect = sibling; - return; + function markCommitTimeOfFallback() { + globalMostRecentFallbackTime = now(); } + function markSkippedUpdateLanes(lane) { + workInProgressRootSkippedLanes = mergeLanes( + lane, + workInProgressRootSkippedLanes + ); + } + function renderDidSuspend() { + if (workInProgressRootExitStatus === RootInProgress) { + workInProgressRootExitStatus = RootSuspended; + } + } + function renderDidSuspendDelayIfPossible() { + if ( + workInProgressRootExitStatus === RootInProgress || + workInProgressRootExitStatus === RootSuspended || + workInProgressRootExitStatus === RootErrored + ) { + workInProgressRootExitStatus = RootSuspendedWithDelay; + } // Check if there are updates that we skipped tree that might have unblocked + // this render. - nextEffect = fiber.return; - } -} - -function commitPassiveMountOnFiber( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions -) { - switch (finishedWork.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - if (finishedWork.mode & ProfileMode) { - startPassiveEffectTimer(); + if ( + workInProgressRoot !== null && + (includesNonIdleWork(workInProgressRootSkippedLanes) || + includesNonIdleWork(workInProgressRootInterleavedUpdatedLanes)) + ) { + // 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. + markRootSuspended$1(workInProgressRoot, workInProgressRootRenderLanes); + } + } + function renderDidError(error) { + if (workInProgressRootExitStatus !== RootSuspendedWithDelay) { + workInProgressRootExitStatus = RootErrored; + } - try { - commitHookEffectListMount(Passive$1 | HasEffect, finishedWork); - } finally { - recordPassiveEffectDuration(finishedWork); - } + if (workInProgressRootConcurrentErrors === null) { + workInProgressRootConcurrentErrors = [error]; } else { - commitHookEffectListMount(Passive$1 | HasEffect, finishedWork); + workInProgressRootConcurrentErrors.push(error); } + } // Called during render to determine if anything has suspended. + // Returns false if we're not sure. - break; + function renderHasNotSuspendedYet() { + // If something errored or completed, we can't really be sure, + // so those are false. + return workInProgressRootExitStatus === RootInProgress; } - } -} -function commitPassiveUnmountEffects(firstChild) { - nextEffect = firstChild; - commitPassiveUnmountEffects_begin(); -} + function renderRootSync(root, lanes) { + var prevExecutionContext = executionContext; + executionContext |= RenderContext; + var prevDispatcher = pushDispatcher(); // 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. -function commitPassiveUnmountEffects_begin() { - while (nextEffect !== null) { - var fiber = nextEffect; - var child = fiber.child; + if (workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes) { + { + if (isDevToolsPresent) { + var memoizedUpdaters = root.memoizedUpdaters; - if ((nextEffect.flags & ChildDeletion) !== NoFlags) { - var deletions = fiber.deletions; + 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 (deletions !== null) { - for (var i = 0; i < deletions.length; i++) { - var fiberToDelete = deletions[i]; - nextEffect = fiberToDelete; - commitPassiveUnmountEffectsInsideOfDeletedTree_begin( - fiberToDelete, - fiber - ); + movePendingFibersToMemoized(root, lanes); + } } - { - // 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 = fiber.alternate; - - if (previousFiber !== null) { - var detachedChild = previousFiber.child; - - if (detachedChild !== null) { - previousFiber.child = null; + workInProgressTransitions = getTransitionsForLanes(); + prepareFreshStack(root, lanes); + } - do { - var detachedSibling = detachedChild.sibling; - detachedChild.sibling = null; - detachedChild = detachedSibling; - } while (detachedChild !== null); - } - } + do { + try { + workLoopSync(); + break; + } catch (thrownValue) { + handleError(root, thrownValue); } + } while (true); + + resetContextDependencies(); + executionContext = prevExecutionContext; + popDispatcher(prevDispatcher); - nextEffect = fiber; + 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." + ); } - } - if ((fiber.subtreeFlags & PassiveMask) !== NoFlags && child !== null) { - child.return = fiber; - nextEffect = child; - } else { - commitPassiveUnmountEffects_complete(); - } - } -} + workInProgressRoot = null; + workInProgressRootRenderLanes = NoLanes; + return workInProgressRootExitStatus; + } // The work loop is an extremely hot path. Tell Closure not to inline it. -function commitPassiveUnmountEffects_complete() { - while (nextEffect !== null) { - var fiber = nextEffect; + /** @noinline */ - if ((fiber.flags & Passive) !== NoFlags) { - setCurrentFiber(fiber); - commitPassiveUnmountOnFiber(fiber); - resetCurrentFiber(); + function workLoopSync() { + // Already timed out, so perform work without checking if we need to yield. + while (workInProgress !== null) { + performUnitOfWork(workInProgress); + } } - var sibling = fiber.sibling; + function renderRootConcurrent(root, lanes) { + var prevExecutionContext = executionContext; + executionContext |= RenderContext; + var prevDispatcher = pushDispatcher(); // 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 (sibling !== null) { - sibling.return = fiber.return; - nextEffect = sibling; - return; - } + if (workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes) { + { + if (isDevToolsPresent) { + var memoizedUpdaters = root.memoizedUpdaters; - nextEffect = fiber.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. -function commitPassiveUnmountOnFiber(finishedWork) { - switch (finishedWork.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - if (finishedWork.mode & ProfileMode) { - startPassiveEffectTimer(); - commitHookEffectListUnmount( - Passive$1 | HasEffect, - finishedWork, - finishedWork.return - ); - recordPassiveEffectDuration(finishedWork); - } else { - commitHookEffectListUnmount( - Passive$1 | HasEffect, - finishedWork, - finishedWork.return - ); - } + movePendingFibersToMemoized(root, lanes); + } + } - break; - } - } -} + workInProgressTransitions = getTransitionsForLanes(); + resetRenderTimer(); + prepareFreshStack(root, lanes); + } -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. (But, if we - // do this, still need to handle `deletedTreeCleanUpLevel` correctly.) - - if (child !== null) { - child.return = fiber; - nextEffect = child; - } else { - commitPassiveUnmountEffectsInsideOfDeletedTree_complete( - deletedSubtreeRoot - ); - } - } -} + do { + try { + workLoopConcurrent(); + break; + } catch (thrownValue) { + handleError(root, thrownValue); + } + } while (true); -function commitPassiveUnmountEffectsInsideOfDeletedTree_complete( - deletedSubtreeRoot -) { - while (nextEffect !== null) { - var fiber = nextEffect; - var sibling = fiber.sibling; - var returnFiber = fiber.return; + resetContextDependencies(); + popDispatcher(prevDispatcher); + executionContext = prevExecutionContext; - { - // 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 (workInProgress !== null) { + return RootInProgress; + } else { + workInProgressRoot = null; + workInProgressRootRenderLanes = NoLanes; // Return the final exit status. - if (fiber === deletedSubtreeRoot) { - nextEffect = null; - return; + return workInProgressRootExitStatus; } } + /** @noinline */ - if (sibling !== null) { - sibling.return = returnFiber; - nextEffect = sibling; - return; + function workLoopConcurrent() { + // Perform work until Scheduler asks us to yield + while (workInProgress !== null && !shouldYield()) { + performUnitOfWork(workInProgress); + } } - nextEffect = returnFiber; - } -} + 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; -function commitPassiveUnmountInsideDeletedTreeOnFiber( - current, - nearestMountedAncestor -) { - switch (current.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - if (current.mode & ProfileMode) { - startPassiveEffectTimer(); - commitHookEffectListUnmount(Passive$1, current, nearestMountedAncestor); - recordPassiveEffectDuration(current); + if ((unitOfWork.mode & ProfileMode) !== NoMode) { + startProfilerTimer(unitOfWork); + next = beginWork$1(current, unitOfWork, subtreeRenderLanes); + stopProfilerTimerIfRunningAndRecordDelta(unitOfWork, true); } else { - commitHookEffectListUnmount(Passive$1, current, nearestMountedAncestor); + next = beginWork$1(current, unitOfWork, subtreeRenderLanes); } - break; - } - } -} // TODO: Reuse reappearLayoutEffects traversal here? - -var COMPONENT_TYPE = 0; -var HAS_PSEUDO_CLASS_TYPE = 1; -var ROLE_TYPE = 2; -var TEST_NAME_TYPE = 3; -var TEXT_TYPE = 4; + resetCurrentFiber(); + unitOfWork.memoizedProps = unitOfWork.pendingProps; -if (typeof Symbol === "function" && Symbol.for) { - var symbolFor = Symbol.for; - COMPONENT_TYPE = symbolFor("selector.component"); - HAS_PSEUDO_CLASS_TYPE = symbolFor("selector.has_pseudo_class"); - ROLE_TYPE = symbolFor("selector.role"); - TEST_NAME_TYPE = symbolFor("selector.test_id"); - TEXT_TYPE = symbolFor("selector.text"); -} + if (next === null) { + // If this doesn't spawn new work, complete the current work. + completeUnitOfWork(unitOfWork); + } else { + workInProgress = next; + } -var ReactCurrentActQueue = 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. - var isReactActEnvironmentGlobal = // $FlowExpectedError – Flow doesn't know about IS_REACT_ACT_ENVIRONMENT global - typeof IS_REACT_ACT_ENVIRONMENT !== "undefined" - ? IS_REACT_ACT_ENVIRONMENT - : undefined; // $FlowExpectedError - Flow doesn't know about jest - return warnsIfNotActing; - } -} -function isConcurrentActEnvironment() { - { - var isReactActEnvironmentGlobal = // $FlowExpectedError – Flow doesn't know about IS_REACT_ACT_ENVIRONMENT global - typeof IS_REACT_ACT_ENVIRONMENT !== "undefined" - ? IS_REACT_ACT_ENVIRONMENT - : undefined; - - if (!isReactActEnvironmentGlobal && ReactCurrentActQueue.current !== null) { - // TODO: Include link to relevant documentation page. - error( - "The current testing environment is not configured to support " + - "act(...)" - ); + ReactCurrentOwner$2.current = null; } - return isReactActEnvironmentGlobal; - } -} + 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; -var ceil = Math.ceil; -var ReactCurrentDispatcher$2 = ReactSharedInternals.ReactCurrentDispatcher, - ReactCurrentOwner$2 = ReactSharedInternals.ReactCurrentOwner, - ReactCurrentBatchConfig$2 = ReactSharedInternals.ReactCurrentBatchConfig, - ReactCurrentActQueue$1 = 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; // Stack that allows components to change the render lanes for its subtree -// This is a superset of the lanes we started working on at the root. The only -// case where it's different from `workInProgressRootRenderLanes` is when we -// enter a subtree that is hidden and needs to be unhidden: Suspense and -// Offscreen component. -// -// Most things in the work loop should deal with workInProgressRootRenderLanes. -// Most things in begin/complete phases should deal with subtreeRenderLanes. - -var subtreeRenderLanes = NoLanes; -var subtreeRenderLanesCursor = createCursor(NoLanes); // Whether to root completed, errored, suspended, etc. - -var workInProgressRootExitStatus = RootInProgress; // A fatal error, if one is thrown - -var workInProgressRootFatalError = null; // "Included" lanes refer to lanes that were worked on during this render. It's -// slightly different than `renderLanes` because `renderLanes` can change as you -// enter and exit an Offscreen tree. This value is the combination of all render -// lanes for the entire render phase. - -var workInProgressRootIncludedLanes = NoLanes; // 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; // 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 committed a fallback. This lets us ensure a train -// model where we don't commit new loading states in too quick succession. - -var globalMostRecentFallbackTime = 0; -var FALLBACK_THROTTLE_MS = 500; // 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 resetRenderTimer() { - workInProgressRootRenderTargetTime = now() + RENDER_TIMEOUT_MS; -} + 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 = completedWork.alternate; + var returnFiber = completedWork.return; // Check if the work completed or if something threw. + + if ((completedWork.flags & Incomplete) === NoFlags) { + setCurrentFiber(completedWork); + var next = void 0; + + if ((completedWork.mode & ProfileMode) === NoMode) { + next = completeWork(current, completedWork, subtreeRenderLanes); + } else { + startProfilerTimer(completedWork); + next = completeWork(current, completedWork, subtreeRenderLanes); // Update render duration assuming we didn't error. -function getRenderTargetTime() { - return workInProgressRootRenderTargetTime; -} -var hasUncaughtError = false; -var firstUncaughtError = null; -var legacyErrorBoundariesThatAlreadyFailed = null; // Only used when enableProfilerNestedUpdateScheduledHook is true; -var rootDoesHavePassiveEffects = false; -var rootWithPendingPassiveEffects = null; -var pendingPassiveEffectsLanes = NoLanes; -var pendingPassiveProfilerEffects = []; -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; // If two updates are scheduled within the same event, we should treat their -// event times as simultaneous, even if the actual clock time has advanced -// between the first and second call. - -var currentEventTime = NoTimestamp; -var currentEventTransitionLane = NoLanes; -var isRunningInsertionEffect = false; -function getWorkInProgressRoot() { - return workInProgressRoot; -} -function requestEventTime() { - if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { - // We're inside React, so it's fine to read the actual time. - return now(); - } // We're not inside React, so we may be in the middle of a browser event. - - if (currentEventTime !== NoTimestamp) { - // Use the same start time for all updates until we enter React again. - return currentEventTime; - } // This is the first update since React yielded. Compute a new start time. - - currentEventTime = now(); - return currentEventTime; -} -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$2.transition !== null) { - var transition = ReactCurrentBatchConfig$2.transition; - - if (!transition._updatedFibers) { - transition._updatedFibers = new Set(); - } - - transition._updatedFibers.add(fiber); - } // 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; - } // 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; -} + stopProfilerTimerIfRunningAndRecordDelta(completedWork, false); + } + + resetCurrentFiber(); -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 (next !== null) { + // Completing this fiber spawned new work. Work on that next. + workInProgress = next; + return; + } + } else { + // 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, completedWork); // Because this fiber did not complete, don't reset its lanes. + + if (_next !== null) { + // If completing this work spawned new work, do that next. We'll come + // back here again. + // Since we're restarting, remove anything that is not a host effect + // from the effect tag. + _next.flags &= HostEffectMask; + workInProgress = _next; + return; + } - if ((mode & ConcurrentMode) === NoMode) { - return SyncLane; - } + if ((completedWork.mode & ProfileMode) !== NoMode) { + // Record the render duration for the fiber that errored. + stopProfilerTimerIfRunningAndRecordDelta(completedWork, false); // Include the time spent working on failed children before continuing. - return claimNextRetryLane(); -} + var actualDuration = completedWork.actualDuration; + var child = completedWork.child; -function scheduleUpdateOnFiber(root, fiber, lane, eventTime) { - checkForNestedUpdates(); + while (child !== null) { + actualDuration += child.actualDuration; + child = child.sibling; + } - { - if (isRunningInsertionEffect) { - error("useInsertionEffect must not schedule updates."); - } - } + completedWork.actualDuration = actualDuration; + } - { - if (isFlushingPassiveEffects) { - didScheduleUpdateDuringPassiveEffects = true; - } - } // Mark that the root has a pending update. + if (returnFiber !== null) { + // Mark the parent fiber as incomplete and clear its subtree flags. + returnFiber.flags |= Incomplete; + returnFiber.subtreeFlags = NoFlags; + returnFiber.deletions = null; + } else { + // We've unwound all the way to the root. + workInProgressRootExitStatus = RootDidNotComplete; + workInProgress = null; + return; + } + } - markRootUpdated(root, lane, eventTime); + var siblingFiber = completedWork.sibling; - 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); - } - } + if (siblingFiber !== null) { + // If there is more work to do in this returnFiber, do that next. + workInProgress = siblingFiber; + return; + } // Otherwise, return to the parent - warnIfUpdatesNotWrappedWithActDEV(fiber); + completedWork = returnFiber; // Update the next thing we're working on in case something throws. - 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. Unless the - // `deferRenderPhaseUpdateToNextBatch` flag is off and this is a render - // phase update. In that case, we don't treat render phase updates as if - // they were interleaved, for backwards compat reasons. - if ((executionContext & RenderContext) === NoContext) { - workInProgressRootInterleavedUpdatedLanes = mergeLanes( - workInProgressRootInterleavedUpdatedLanes, - lane - ); - } + workInProgress = completedWork; + } while (completedWork !== null); // We've reached the root. - 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$1(root, workInProgressRootRenderLanes); + if (workInProgressRootExitStatus === RootInProgress) { + workInProgressRootExitStatus = RootCompleted; } } - ensureRootIsScheduled(root, eventTime); - - if ( - lane === SyncLane && - executionContext === NoContext && - (fiber.mode & ConcurrentMode) === NoMode && // Treat `act` as if it's inside `batchedUpdates`, even in legacy mode. - !ReactCurrentActQueue$1.isBatchingLegacy - ) { - // 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(); - flushSyncCallbacksOnlyInLegacyMode(); - } - } -} -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 ( - // TODO: Remove outdated deferRenderPhaseUpdateToNextBatch experiment. We - // decided not to enable it. - (executionContext & RenderContext) !== NoContext - ); -} // Use this function to schedule a task for a root. There's only one task per -// root; if a task was already scheduled, we'll check to make sure the priority -// of the existing task is the same as the priority of the next level that the -// root has work on. This function is called on every update, and right before -// exiting a task. - -function ensureRootIsScheduled(root, currentTime) { - var existingCallbackNode = root.callbackNode; // 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 nextLanes = getNextLanes( - root, - root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes - ); - - if (nextLanes === NoLanes) { - // Special case: There's nothing to work on. - if (existingCallbackNode !== null) { - cancelCallback$1(existingCallbackNode); - } - - root.callbackNode = null; - root.callbackPriority = NoLane; - return; - } // We use the highest priority lane to represent the priority of the callback. - - var newCallbackPriority = getHighestPriorityLane(nextLanes); // Check if there's an existing task. We may be able to reuse it. - - var existingCallbackPriority = root.callbackPriority; - - if ( - existingCallbackPriority === newCallbackPriority && // Special case related to `act`. If the currently scheduled task is a - // Scheduler task, rather than an `act` task, cancel it and re-scheduled - // on the `act` queue. - !( - ReactCurrentActQueue$1.current !== null && - existingCallbackNode !== fakeActCallbackNode - ) - ) { - { - // If we're going to re-use an existing task, it needs to exist. - // Assume that discrete update microtasks are non-cancellable and null. - // TODO: Temporary until we confirm this warning is not fired. - if ( - existingCallbackNode == null && - existingCallbackPriority !== SyncLane - ) { - error( - "Expected scheduled callback to exist. This error is likely caused by a bug in React. Please file an issue." + function commitRoot(root, recoverableErrors, transitions) { + // 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$2.transition; + defrost.writeInLogFiles(Date.now() + "", { list: updatedComponents, change: updatedComponentForProfiler }) + updatedComponents = [] + updatedComponentForProfiler = null + try { + ReactCurrentBatchConfig$2.transition = null; + setCurrentUpdatePriority(DiscreteEventPriority); + commitRootImpl( + root, + recoverableErrors, + transitions, + previousUpdateLanePriority ); + } finally { + ReactCurrentBatchConfig$2.transition = prevTransition; + setCurrentUpdatePriority(previousUpdateLanePriority); } - } // The priority hasn't changed. We can reuse the existing task. Exit. - return; - } + return null; + } - if (existingCallbackNode != null) { - // Cancel the existing callback. We'll schedule a new one below. - cancelCallback$1(existingCallbackNode); - } // Schedule a new callback. + function commitRootImpl( + root, + recoverableErrors, + transitions, + renderPriorityLevel + ) { + 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); - var newCallbackNode; + flushRenderPhaseStrictModeWarningsInDEV(); - if (newCallbackPriority === SyncLane) { - // Special case: Sync React callbacks are scheduled on a special - // internal queue - if (root.tag === LegacyRoot) { - if (ReactCurrentActQueue$1.isBatchingLegacy !== null) { - ReactCurrentActQueue$1.didScheduleLegacyUpdate = true; + if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { + throw new Error("Should not already be working."); } - scheduleLegacySyncCallback(performSyncWorkOnRoot.bind(null, root)); - } else { - scheduleSyncCallback(performSyncWorkOnRoot.bind(null, root)); - } - - { - // Flush the queue in an Immediate task. - scheduleCallback$1(ImmediatePriority, flushSyncCallbacks); - } - - newCallbackNode = null; - } else { - var schedulerPriorityLevel; - - switch (lanesToEventPriority(nextLanes)) { - case DiscreteEventPriority: - schedulerPriorityLevel = ImmediatePriority; - break; + var finishedWork = root.finishedWork; + var lanes = root.finishedLanes; - case ContinuousEventPriority: - schedulerPriorityLevel = UserBlockingPriority; - break; + if (finishedWork === null) { + return null; + } else { + { + if (lanes === NoLanes) { + error( + "root.finishedLanes should not be empty during a commit. This is a " + + "bug in React." + ); + } + } + } - case DefaultEventPriority: - schedulerPriorityLevel = NormalPriority; - break; + root.finishedWork = null; + root.finishedLanes = NoLanes; - case IdleEventPriority: - schedulerPriorityLevel = IdlePriority; - break; + 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. - default: - schedulerPriorityLevel = NormalPriority; - break; - } + root.callbackNode = null; + root.callbackPriority = NoLane; // Update the first and last pending times on this root. The new first + // pending time is whatever is left on the root fiber. - newCallbackNode = scheduleCallback$1( - schedulerPriorityLevel, - performConcurrentWorkOnRoot.bind(null, root) - ); - } - - root.callbackPriority = newCallbackPriority; - root.callbackNode = newCallbackNode; -} // This is the entry point for every concurrent task, i.e. anything that -// goes through Scheduler. - -function performConcurrentWorkOnRoot(root, didTimeout) { - { - resetNestedUpdateFlag(); - } // Since we know we're in a React event, we can clear the current - // event time. The next update will compute a new event time. - - currentEventTime = NoTimestamp; - currentEventTransitionLane = NoLanes; - - 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. - - 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) && - !didTimeout; - var exitStatus = shouldTimeSlice - ? renderRootConcurrent(root, lanes) - : renderRootSync(root, lanes); - - if (exitStatus !== RootInProgress) { - if (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 errorRetryLanes = getLanesToRetrySynchronouslyOnError(root); - - if (errorRetryLanes !== NoLanes) { - lanes = errorRetryLanes; - exitStatus = recoverFromConcurrentError(root, errorRetryLanes); - } - } - - if (exitStatus === RootFatalErrored) { - var fatalError = workInProgressRootFatalError; - prepareFreshStack(root, NoLanes); - markRootSuspended$1(root, lanes); - ensureRootIsScheduled(root, now()); - throw fatalError; - } + var remainingLanes = mergeLanes(finishedWork.lanes, finishedWork.childLanes); + markRootFinished(root, remainingLanes); - 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. - // - // This should only happen during a concurrent render, not a discrete or - // synchronous update. We should have already checked for this when we - // unwound the stack. - markRootSuspended$1(root, lanes); - } 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 renderWasConcurrent = !includesBlockingLane(root, lanes); - var finishedWork = root.current.alternate; + 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 ( - renderWasConcurrent && - !isRenderConsistentWithExternalStores(finishedWork) + (finishedWork.subtreeFlags & PassiveMask) !== NoFlags || + (finishedWork.flags & PassiveMask) !== NoFlags ) { - // A store was mutated in an interleaved event. Render again, - // synchronously, to block further mutations. - exitStatus = renderRootSync(root, lanes); // We need to check again if something threw - - if (exitStatus === RootErrored) { - var _errorRetryLanes = getLanesToRetrySynchronouslyOnError(root); + if (!rootDoesHavePassiveEffects) { + rootDoesHavePassiveEffects = true; + // 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$1(NormalPriority, 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 (_errorRetryLanes !== NoLanes) { - lanes = _errorRetryLanes; - exitStatus = recoverFromConcurrentError(root, _errorRetryLanes); // We assume the tree is now consistent because we didn't yield to any - // concurrent events. - } + 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; + var rootHasEffect = + (finishedWork.flags & + (BeforeMutationMask | MutationMask | LayoutMask | PassiveMask)) !== + NoFlags; + + if (subtreeHasEffects || rootHasEffect) { + var prevTransition = ReactCurrentBatchConfig$2.transition; + ReactCurrentBatchConfig$2.transition = null; + var previousPriority = getCurrentUpdatePriority(); + setCurrentUpdatePriority(DiscreteEventPriority); + var prevExecutionContext = executionContext; + executionContext |= CommitContext; // Reset this to null before calling lifecycles + + ReactCurrentOwner$2.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. + + var shouldFireAfterActiveInstanceBlur = commitBeforeMutationEffects( + root, + finishedWork + ); - if (exitStatus === RootFatalErrored) { - var _fatalError = workInProgressRootFatalError; - prepareFreshStack(root, NoLanes); - markRootSuspended$1(root, lanes); - ensureRootIsScheduled(root, now()); - throw _fatalError; + { + // Mark the current commit time to be shared by all Profilers in this + // batch. This enables them to be grouped later. + recordCommitTime(); } - } // 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, lanes); - } - } + commitMutationEffects(root, finishedWork, lanes); - ensureRootIsScheduled(root, now()); + resetAfterCommit(root.containerInfo); // The work-in-progress tree is now the current tree. This must come after + // 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 (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); - } + root.current = finishedWork; // The next phase is the layout phase, where we call effects that read - return null; -} + commitLayoutEffects(finishedWork, root, lanes); + // opportunity to paint. -function recoverFromConcurrentError(root, 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; - - if (isRootDehydrated(root)) { - // 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; + requestPaint(); + executionContext = prevExecutionContext; // Reset the priority to the previous non-sync value. - { - errorHydratingContainer(root.containerInfo); - } - } + setCurrentUpdatePriority(previousPriority); + ReactCurrentBatchConfig$2.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. - var exitStatus = renderRootSync(root, errorRetryLanes); + { + recordCommitTime(); + } + } - if (exitStatus !== RootErrored) { - // Successfully finished rendering on retry - // 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 (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 { + { + nestedPassiveUpdateCount = 0; + rootWithPassiveNestedUpdates = null; + } + } // Read this again, since an effect might have updated it - if (errorsFromSecondAttempt !== null) { - queueRecoverableErrors(errorsFromSecondAttempt); - } - } + 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. - return exitStatus; -} + if (remainingLanes === NoLanes) { + // If there's no remaining work, we can clear the set of already failed + // error boundaries. + legacyErrorBoundariesThatAlreadyFailed = null; + } -function queueRecoverableErrors(errors) { - if (workInProgressRootRecoverableErrors === null) { - workInProgressRootRecoverableErrors = errors; - } else { - workInProgressRootRecoverableErrors.push.apply( - workInProgressRootRecoverableErrors, - errors - ); - } -} + onCommitRoot(finishedWork.stateNode, renderPriorityLevel); -function finishConcurrentRender(root, exitStatus, lanes) { - switch (exitStatus) { - case RootInProgress: - case RootFatalErrored: { - throw new Error("Root did not complete. This is a bug in React."); - } - // Flow knows about invariant, so it complains if I add a break - // statement, but eslint doesn't know about invariant, so it complains - // if I do. eslint-disable-next-line no-fallthrough + { + if (isDevToolsPresent) { + root.memoizedUpdaters.clear(); + } + } + // additional work on this root is scheduled. - case RootErrored: { - // We should have already attempted to retry this tree. If we reached - // this point, it errored again. Commit it. - commitRoot( - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ); - break; - } + ensureRootIsScheduled(root, now()); + + 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 componentStack = recoverableError.stack; + var digest = recoverableError.digest; + onRecoverableError(recoverableError.value, { + componentStack: componentStack, + digest: digest + }); + } + } - case RootSuspended: { - markRootSuspended$1(root, lanes); // We have an acceptable loading state. We need to figure out if we - // should immediately commit it or wait a bit. + 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 ( - includesOnlyRetries(lanes) && // do not delay if we're inside an act() scope - !shouldForceFlushFallbacksInDEV() + includesSomeLane(pendingPassiveEffectsLanes, SyncLane) && + root.tag !== LegacyRoot ) { - // 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(); // Don't bother with a very short suspense time. + flushPassiveEffects(); + } // Read this again, since a passive effect might have updated it - if (msUntilTimeout > 10) { - var nextLanes = getNextLanes(root, NoLanes); + remainingLanes = root.pendingLanes; - if (nextLanes !== NoLanes) { - // There's additional work on this root. - break; - } + if (includesSomeLane(remainingLanes, SyncLane)) { + { + markNestedUpdateScheduled(); + } // Count the number of times the root synchronously re-renders without + // finishing. If there are too many, it indicates an infinite update loop. - var suspendedLanes = root.suspendedLanes; + if (root === rootWithNestedUpdates) { + nestedUpdateCount++; + } else { + nestedUpdateCount = 0; + rootWithNestedUpdates = root; + } + } else { + nestedUpdateCount = 0; + } // If layout work was scheduled, flush it now. - if (!isSubsetOfLanes(suspendedLanes, lanes)) { - // We should prefer to render the fallback of at the last - // suspended level. Ping the last suspended level to try - // rendering it again. - // FIXME: What if the suspended lanes are Idle? Should not restart. - var eventTime = requestEventTime(); - markRootPinged(root, suspendedLanes); - break; - } // 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. + flushSyncCallbacks(); - root.timeoutHandle = scheduleTimeout( - commitRoot.bind( - null, - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ), - msUntilTimeout - ); - break; - } - } // The work expired. Commit immediately. + return null; + } - commitRoot( - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ); - break; - } - - case RootSuspendedWithDelay: { - markRootSuspended$1(root, lanes); - - 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. - break; - } - - if (!shouldForceFlushFallbacksInDEV()) { - // This is not a transition, but we did trigger an avoided state. - // Schedule a placeholder to display after a short delay, using the Just - // Noticeable Difference. - // TODO: Is the JND optimization worth the added complexity? If this is - // the only reason we track the event time, then probably not. - // Consider removing. - var mostRecentEventTime = getMostRecentEventTime(root, lanes); - var eventTimeMs = mostRecentEventTime; - var timeElapsedMs = now() - eventTimeMs; - - var _msUntilTimeout = jnd(timeElapsedMs) - timeElapsedMs; // Don't bother with a very short suspense time. - - if (_msUntilTimeout > 10) { - // Instead of committing the fallback immediately, wait for more data - // to arrive. - root.timeoutHandle = scheduleTimeout( - commitRoot.bind( - null, - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ), - _msUntilTimeout - ); - break; + 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) { + var renderPriority = lanesToEventPriority(pendingPassiveEffectsLanes); + var priority = lowerEventPriority(DefaultEventPriority, renderPriority); + var prevTransition = ReactCurrentBatchConfig$2.transition; + var previousPriority = getCurrentUpdatePriority(); + + try { + ReactCurrentBatchConfig$2.transition = null; + setCurrentUpdatePriority(priority); + return flushPassiveEffectsImpl(); + } finally { + setCurrentUpdatePriority(previousPriority); + ReactCurrentBatchConfig$2.transition = prevTransition; // Once passive effects have run for the tree - giving components a } - } // Commit the placeholder. + } - commitRoot( - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ); - break; + return false; } + function enqueuePendingPassiveProfilerEffect(fiber) { + { + pendingPassiveProfilerEffects.push(fiber); - case RootCompleted: { - // The work completed. Ready to commit. - commitRoot( - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ); - break; + if (!rootDoesHavePassiveEffects) { + rootDoesHavePassiveEffects = true; + scheduleCallback$1(NormalPriority, function () { + flushPassiveEffects(); + return null; + }); + } + } } - default: { - throw new Error("Unknown root exit status."); - } - } -} + function flushPassiveEffectsImpl() { + if (rootWithPendingPassiveEffects === null) { + return false; + } // Cache and clear the transitions flag + + 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. -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; + pendingPassiveEffectsLanes = NoLanes; - while (true) { - if (node.flags & StoreConsistency) { - var updateQueue = node.updateQueue; + if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { + throw new Error("Cannot flush passive effects while already rendering."); + } - if (updateQueue !== null) { - var checks = updateQueue.stores; + { + isFlushingPassiveEffects = true; + didScheduleUpdateDuringPassiveEffects = false; + } - if (checks !== null) { - for (var i = 0; i < checks.length; i++) { - var check = checks[i]; - var getSnapshot = check.getSnapshot; - var renderedValue = check.value; + var prevExecutionContext = executionContext; + executionContext |= CommitContext; + commitPassiveUnmountEffects(root.current); + commitPassiveMountEffects(root, root.current, lanes, transitions); // TODO: Move to commitPassiveMountEffects - 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; - } - } + { + var profilerEffects = pendingPassiveProfilerEffects; + pendingPassiveProfilerEffects = []; + + for (var i = 0; i < profilerEffects.length; i++) { + var _fiber = profilerEffects[i]; + commitPassiveEffectDurations(root, _fiber); } } - } - var child = node.child; + executionContext = prevExecutionContext; + flushSyncCallbacks(); - if (node.subtreeFlags & StoreConsistency && child !== null) { - child.return = node; - node = child; - continue; - } + { + // 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; + } + + isFlushingPassiveEffects = false; + didScheduleUpdateDuringPassiveEffects = false; + } // TODO: Move to commitPassiveMountEffects + + onPostCommitRoot(root); + + { + var stateNode = root.current.stateNode; + stateNode.effectDuration = 0; + stateNode.passiveEffectDuration = 0; + } - if (node === finishedWork) { return true; } - while (node.sibling === null) { - if (node.return === null || node.return === finishedWork) { - return true; + function isAlreadyFailedLegacyErrorBoundary(instance) { + return ( + legacyErrorBoundariesThatAlreadyFailed !== null && + legacyErrorBoundariesThatAlreadyFailed.has(instance) + ); + } + function markLegacyErrorBoundaryAsFailed(instance) { + if (legacyErrorBoundariesThatAlreadyFailed === null) { + legacyErrorBoundariesThatAlreadyFailed = new Set([instance]); + } else { + legacyErrorBoundariesThatAlreadyFailed.add(instance); } + } - node = node.return; + function prepareToThrowUncaughtError(error) { + if (!hasUncaughtError) { + hasUncaughtError = true; + firstUncaughtError = error; + } } - node.sibling.return = node.return; - node = node.sibling; - } // Flow doesn't know this is unreachable, but eslint does - // eslint-disable-next-line no-unreachable + var onUncaughtError = prepareToThrowUncaughtError; - return true; -} + function captureCommitPhaseErrorOnRoot(rootFiber, sourceFiber, error) { + var errorInfo = createCapturedValueAtFiber(error, sourceFiber); + var update = createRootErrorUpdate(rootFiber, errorInfo, SyncLane); + var root = enqueueUpdate(rootFiber, update, SyncLane); + var eventTime = requestEventTime(); -function markRootSuspended$1(root, suspendedLanes) { - // 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(root, suspendedLanes); -} // This is the entry point for synchronous tasks that don't go -// through Scheduler - -function performSyncWorkOnRoot(root) { - { - syncNestedUpdateFlag(); - } - - if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { - throw new Error("Should not already be working."); - } - - flushPassiveEffects(); - var lanes = getNextLanes(root, NoLanes); - - if (!includesSomeLane(lanes, SyncLane)) { - // There's no remaining sync work left. - ensureRootIsScheduled(root, now()); - return null; - } - - 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 errorRetryLanes = getLanesToRetrySynchronouslyOnError(root); - - if (errorRetryLanes !== NoLanes) { - lanes = errorRetryLanes; - exitStatus = recoverFromConcurrentError(root, errorRetryLanes); - } - } - - if (exitStatus === RootFatalErrored) { - var fatalError = workInProgressRootFatalError; - prepareFreshStack(root, NoLanes); - markRootSuspended$1(root, lanes); - ensureRootIsScheduled(root, now()); - throw fatalError; - } - - if (exitStatus === RootDidNotComplete) { - throw new Error("Root did not complete. This is a bug in React."); - } // 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 - ); // Before exiting, make sure there's a callback scheduled for the next - // pending level. - - ensureRootIsScheduled(root, now()); - return null; -} -function batchedUpdates$1(fn, a) { - var prevExecutionContext = executionContext; - executionContext |= BatchedContext; + if (root !== null) { + markRootUpdated(root, SyncLane, eventTime); + ensureRootIsScheduled(root, eventTime); + } + } - try { - return fn(a); - } finally { - executionContext = prevExecutionContext; // If there were legacy sync updates, flush them at the end of the outer - // most batchedUpdates-like method. + function captureCommitPhaseError(sourceFiber, nearestMountedAncestor, error$1) { + { + reportUncaughtErrorInDEV(error$1); + setIsRunningInsertionEffect(false); + } - if ( - executionContext === NoContext && // Treat `act` as if it's inside `batchedUpdates`, even in legacy mode. - !ReactCurrentActQueue$1.isBatchingLegacy - ) { - resetRenderTimer(); - flushSyncCallbacksOnlyInLegacyMode(); - } - } -} -// Warning, this opts-out of checking the function body. - -// 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$2.transition; - var previousPriority = getCurrentUpdatePriority(); - - try { - ReactCurrentBatchConfig$2.transition = null; - setCurrentUpdatePriority(DiscreteEventPriority); - - if (fn) { - return fn(); - } else { - return undefined; - } - } finally { - setCurrentUpdatePriority(previousPriority); - ReactCurrentBatchConfig$2.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) { - flushSyncCallbacks(); - } - } -} -function pushRenderLanes(fiber, lanes) { - push(subtreeRenderLanesCursor, subtreeRenderLanes, fiber); - subtreeRenderLanes = mergeLanes(subtreeRenderLanes, lanes); - workInProgressRootIncludedLanes = mergeLanes( - workInProgressRootIncludedLanes, - lanes - ); -} -function popRenderLanes(fiber) { - subtreeRenderLanes = subtreeRenderLanesCursor.current; - pop(subtreeRenderLanesCursor, fiber); -} + 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; + } -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 Complains noTimeout is not a TimeoutID, despite the check above - - cancelTimeout(timeoutHandle); - } - - if (workInProgress !== null) { - var interruptedWork = workInProgress.return; - - while (interruptedWork !== null) { - var current = interruptedWork.alternate; - unwindInterruptedWork(current, interruptedWork); - interruptedWork = interruptedWork.return; - } - } - - workInProgressRoot = root; - var rootWorkInProgress = createWorkInProgress(root.current, null); - workInProgress = rootWorkInProgress; - workInProgressRootRenderLanes = subtreeRenderLanes = workInProgressRootIncludedLanes = lanes; - workInProgressRootExitStatus = RootInProgress; - workInProgressRootFatalError = null; - workInProgressRootSkippedLanes = NoLanes; - workInProgressRootInterleavedUpdatedLanes = NoLanes; - workInProgressRootPingedLanes = NoLanes; - workInProgressRootConcurrentErrors = null; - workInProgressRootRecoverableErrors = null; - finishQueueingConcurrentUpdates(); - - { - ReactStrictModeWarnings.discardPendingWarnings(); - } - - return rootWorkInProgress; -} + var fiber = null; -function handleError(root, thrownValue) { - do { - var erroredWork = workInProgress; + { + fiber = sourceFiber.return; + } - try { - // Reset module-level state that was set during the render phase. - resetContextDependencies(); - resetHooksAfterThrow(); - resetCurrentFiber(); // TODO: I found and added this missing line while investigating a - // separate issue. Write a regression test using string refs. + 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; - ReactCurrentOwner$2.current = null; + 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); + var eventTime = requestEventTime(); - if (erroredWork === null || erroredWork.return === 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. + if (root !== null) { + markRootUpdated(root, SyncLane, eventTime); + ensureRootIsScheduled(root, eventTime); + } - workInProgress = null; - return; + return; + } + } + + fiber = fiber.return; + } + + { + // TODO: Until we re-land skipUnmountedBoundaries (see #20147), this warning + // will fire for errors that are thrown by destroy functions inside deleted + // trees. What it should instead do is propagate the error to the parent of + // the deleted tree. In the meantime, do not add this warning to the + // allowlist; this is only for our internal use. + error( + "Internal React error: Attempted to capture a commit phase error " + + "inside a detached tree. This indicates a bug in React. Likely " + + "causes include deleting the same fiber more than once, committing an " + + "already-finished tree, or an inconsistent return pointer.\n\n" + + "Error message:\n\n%s", + error$1 + ); } + } + function pingSuspendedRoot(root, wakeable, pingedLanes) { + var pingCache = root.pingCache; - if (enableProfilerTimer && 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 (pingCache !== null) { + // The wakeable resolved, so we no longer need to memoize, because it will + // never be thrown again. + pingCache.delete(wakeable); } - if (enableSchedulingProfiler) { - markComponentRenderStopped(); + var eventTime = requestEventTime(); + 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 ( - thrownValue !== null && - typeof thrownValue === "object" && - typeof thrownValue.then === "function" + workInProgressRootExitStatus === RootSuspendedWithDelay || + (workInProgressRootExitStatus === RootSuspended && + includesOnlyRetries(workInProgressRootRenderLanes) && + now() - globalMostRecentFallbackTime < FALLBACK_THROTTLE_MS) ) { - var wakeable = thrownValue; - markComponentSuspended( - erroredWork, - wakeable, - workInProgressRootRenderLanes - ); + // Restart from the root. + prepareFreshStack(root, NoLanes); } else { - markComponentErrored( - erroredWork, - thrownValue, - workInProgressRootRenderLanes + // 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 ); } } - throwException( - root, - erroredWork.return, - erroredWork, - thrownValue, - workInProgressRootRenderLanes - ); - completeUnitOfWork(erroredWork); - } catch (yetAnotherThrownValue) { - // Something in the return path also threw. - thrownValue = yetAnotherThrownValue; - - if (workInProgress === erroredWork && erroredWork !== null) { - // If this boundary has already errored, then we had trouble processing - // the error. Bubble it to the next boundary. - erroredWork = erroredWork.return; - workInProgress = erroredWork; - } else { - erroredWork = workInProgress; + ensureRootIsScheduled(root, eventTime); + } + + 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 eventTime = requestEventTime(); + var root = enqueueConcurrentRenderForLane(boundaryFiber, retryLane); + + if (root !== null) { + markRootUpdated(root, retryLane, eventTime); + ensureRootIsScheduled(root, eventTime); } + } - continue; - } // Return to the normal work loop. + function retryDehydratedSuspenseBoundary(boundaryFiber) { + var suspenseState = boundaryFiber.memoizedState; + var retryLane = NoLane; - return; - } while (true); -} + if (suspenseState !== null) { + retryLane = suspenseState.retryLane; + } -function pushDispatcher() { - var prevDispatcher = ReactCurrentDispatcher$2.current; - ReactCurrentDispatcher$2.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; - } -} + retryTimedOutBoundary(boundaryFiber, retryLane); + } + function resolveRetryWakeable(boundaryFiber, wakeable) { + var retryLane = NoLane; // Default -function popDispatcher(prevDispatcher) { - ReactCurrentDispatcher$2.current = prevDispatcher; -} + var retryCache; + + switch (boundaryFiber.tag) { + case SuspenseComponent: + retryCache = boundaryFiber.stateNode; + var suspenseState = boundaryFiber.memoizedState; + + if (suspenseState !== null) { + retryLane = suspenseState.retryLane; + } + + break; -function markCommitTimeOfFallback() { - globalMostRecentFallbackTime = now(); -} -function markSkippedUpdateLanes(lane) { - workInProgressRootSkippedLanes = mergeLanes( - lane, - workInProgressRootSkippedLanes - ); -} -function renderDidSuspend() { - if (workInProgressRootExitStatus === RootInProgress) { - workInProgressRootExitStatus = RootSuspended; - } -} -function renderDidSuspendDelayIfPossible() { - if ( - workInProgressRootExitStatus === RootInProgress || - workInProgressRootExitStatus === RootSuspended || - workInProgressRootExitStatus === RootErrored - ) { - workInProgressRootExitStatus = RootSuspendedWithDelay; - } // Check if there are updates that we skipped tree that might have unblocked - // this render. - - if ( - workInProgressRoot !== null && - (includesNonIdleWork(workInProgressRootSkippedLanes) || - includesNonIdleWork(workInProgressRootInterleavedUpdatedLanes)) - ) { - // 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. - markRootSuspended$1(workInProgressRoot, workInProgressRootRenderLanes); - } -} -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; -} + case SuspenseListComponent: + retryCache = boundaryFiber.stateNode; + break; -function renderRootSync(root, lanes) { - var prevExecutionContext = executionContext; - executionContext |= RenderContext; - var prevDispatcher = pushDispatcher(); // 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. + default: + throw new Error( + "Pinged unknown suspense boundary type. " + + "This is probably a bug in React." + ); + } - if (workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes) { - { - if (isDevToolsPresent) { - var memoizedUpdaters = root.memoizedUpdaters; + 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); + } // Computes the next Just Noticeable Difference (JND) boundary. + // The theory is that a person can't tell the difference between small differences in time. + // Therefore, if we wait a bit longer than necessary that won't translate to a noticeable + // difference in the experience. However, waiting for longer might mean that we can avoid + // showing an intermediate loading state. The longer we have already waited, the harder it + // is to tell small differences in time. Therefore, the longer we've already waited, + // the longer we can wait additionally. At some point we have to give up though. + // We pick a train model where the next boundary commits at a consistent schedule. + // These particular numbers are vague estimates. We expect to adjust them based on research. + + function jnd(timeElapsed) { + return timeElapsed < 120 + ? 120 + : timeElapsed < 480 + ? 480 + : timeElapsed < 1080 + ? 1080 + : timeElapsed < 1920 + ? 1920 + : timeElapsed < 3000 + ? 3000 + : timeElapsed < 4320 + ? 4320 + : ceil(timeElapsed / 1960) * 1960; + } + + function checkForNestedUpdates() { + if (nestedUpdateCount > NESTED_UPDATE_LIMIT) { + nestedUpdateCount = 0; + rootWithNestedUpdates = 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 (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 (nestedPassiveUpdateCount > NESTED_PASSIVE_UPDATE_LIMIT) { + nestedPassiveUpdateCount = 0; + rootWithPassiveNestedUpdates = null; - movePendingFibersToMemoized(root, lanes); + 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." + ); + } } } - workInProgressTransitions = getTransitionsForLanes(); - prepareFreshStack(root, lanes); - } + function flushRenderPhaseStrictModeWarningsInDEV() { + { + ReactStrictModeWarnings.flushLegacyContextWarning(); - do { - try { - workLoopSync(); - break; - } catch (thrownValue) { - handleError(root, thrownValue); + { + ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings(); + } + } } - } while (true); - resetContextDependencies(); - executionContext = prevExecutionContext; - popDispatcher(prevDispatcher); + 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 (!(fiber.mode & ConcurrentMode)) { + return; + } - 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." - ); - } + var tag = fiber.tag; - workInProgressRoot = null; - workInProgressRootRenderLanes = NoLanes; - return workInProgressRootExitStatus; -} // The work loop is an extremely hot path. Tell Closure not to inline it. + 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. -/** @noinline */ + var componentName = getComponentNameFromFiber(fiber) || "ReactComponent"; -function workLoopSync() { - // Already timed out, so perform work without checking if we need to yield. - while (workInProgress !== null) { - performUnitOfWork(workInProgress); - } -} + if (didWarnStateUpdateForNotYetMountedComponent !== null) { + if (didWarnStateUpdateForNotYetMountedComponent.has(componentName)) { + return; + } -function renderRootConcurrent(root, lanes) { - var prevExecutionContext = executionContext; - executionContext |= RenderContext; - var prevDispatcher = pushDispatcher(); // 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. + didWarnStateUpdateForNotYetMountedComponent.add(componentName); + } else { + didWarnStateUpdateForNotYetMountedComponent = new Set([componentName]); + } - if (workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes) { - { - if (isDevToolsPresent) { - var memoizedUpdaters = root.memoizedUpdaters; + var previousFiber = current; - 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. + try { + setCurrentFiber(fiber); - movePendingFibersToMemoized(root, 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(); + } + } } } + var beginWork$1; - workInProgressTransitions = getTransitionsForLanes(); - resetRenderTimer(); - prepareFreshStack(root, lanes); - } + { + var dummyFiber = null; + + beginWork$1 = 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 + ); - do { - try { - workLoopConcurrent(); - break; - } catch (thrownValue) { - handleError(root, thrownValue); - } - } while (true); + try { + return beginWork(current, unitOfWork, lanes); + } catch (originalError) { + if ( + didSuspendOrErrorWhileHydratingDEV() || + (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; + } // Keep this code in sync with handleError; any changes here must have + // corresponding changes there. - resetContextDependencies(); - popDispatcher(prevDispatcher); - executionContext = prevExecutionContext; + resetContextDependencies(); + resetHooksAfterThrow(); // Don't reset current debug fiber, since we're about to work on the + // same fiber again. + // Unwind the failed stack frame - if (workInProgress !== null) { - return RootInProgress; - } else { - workInProgressRoot = null; - workInProgressRootRenderLanes = NoLanes; // Return the final exit status. + unwindInterruptedWork(current, unitOfWork); // Restore the original properties of the fiber. - return workInProgressRootExitStatus; - } -} -/** @noinline */ + assignFiberPropertiesInDEV(unitOfWork, originalWorkInProgressCopy); -function workLoopConcurrent() { - // Perform work until Scheduler asks us to yield - while (workInProgress !== null && !shouldYield()) { - performUnitOfWork(workInProgress); - } -} + if (unitOfWork.mode & ProfileMode) { + // Reset the profiler timer. + startProfilerTimer(unitOfWork); + } // Run beginWork again. -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$1(current, unitOfWork, subtreeRenderLanes); - stopProfilerTimerIfRunningAndRecordDelta(unitOfWork, true); - } else { - next = beginWork$1(current, unitOfWork, subtreeRenderLanes); - } - - 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$2.current = null; -} + invokeGuardedCallback(null, beginWork, null, current, unitOfWork, lanes); -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 (hasCaughtError()) { + var replayError = clearCaughtError(); + + 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. - 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 = completedWork.alternate; - var returnFiber = completedWork.return; // Check if the work completed or if something threw. + throw originalError; + } + }; + } - if ((completedWork.flags & Incomplete) === NoFlags) { - setCurrentFiber(completedWork); - var next = void 0; + var didWarnAboutUpdateInRender = false; + var didWarnAboutUpdateInRenderForAnotherComponent; - if ((completedWork.mode & ProfileMode) === NoMode) { - next = completeWork(current, completedWork, subtreeRenderLanes); - } else { - startProfilerTimer(completedWork); - next = completeWork(current, completedWork, subtreeRenderLanes); // Update render duration assuming we didn't error. + { + didWarnAboutUpdateInRenderForAnotherComponent = new Set(); + } - stopProfilerTimerIfRunningAndRecordDelta(completedWork, false); - } + function warnAboutRenderPhaseUpdatesInDEV(fiber) { + { + if (isRendering && !getIsUpdatingOpaqueValueInRenderPhaseInDEV()) { + 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 dedupeKey = renderingComponentName; + + if (!didWarnAboutUpdateInRenderForAnotherComponent.has(dedupeKey)) { + didWarnAboutUpdateInRenderForAnotherComponent.add(dedupeKey); + var setStateComponentName = + getComponentNameFromFiber(fiber) || "Unknown"; - resetCurrentFiber(); + 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://react.dev/link/setstate-in-render", + setStateComponentName, + renderingComponentName, + renderingComponentName + ); + } - if (next !== null) { - // Completing this fiber spawned new work. Work on that next. - workInProgress = next; - return; - } - } else { - // 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, completedWork); // Because this fiber did not complete, don't reset its lanes. - - if (_next !== null) { - // If completing this work spawned new work, do that next. We'll come - // back here again. - // Since we're restarting, remove anything that is not a host effect - // from the effect tag. - _next.flags &= HostEffectMask; - workInProgress = _next; - return; - } + break; + } - if ((completedWork.mode & ProfileMode) !== NoMode) { - // Record the render duration for the fiber that errored. - stopProfilerTimerIfRunningAndRecordDelta(completedWork, false); // Include the time spent working on failed children before continuing. + 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." + ); - var actualDuration = completedWork.actualDuration; - var child = completedWork.child; + didWarnAboutUpdateInRender = true; + } - while (child !== null) { - actualDuration += child.actualDuration; - child = child.sibling; + break; + } + } } + } + } - completedWork.actualDuration = actualDuration; + 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 = {}; - if (returnFiber !== null) { - // Mark the parent fiber as incomplete and clear its subtree flags. - returnFiber.flags |= Incomplete; - returnFiber.subtreeFlags = NoFlags; - returnFiber.deletions = null; - } else { - // We've unwound all the way to the root. - workInProgressRootExitStatus = RootDidNotComplete; - workInProgress = null; - return; + function scheduleCallback$1(priorityLevel, callback) { + { + // If we're currently inside an `act` scope, bypass Scheduler and push to + // the `act` queue instead. + var actQueue = ReactCurrentActQueue$1.current; + + if (actQueue !== null) { + actQueue.push(callback); + return fakeActCallbackNode; + } else { + return scheduleCallback(priorityLevel, callback); + } } } - var siblingFiber = completedWork.sibling; + function cancelCallback$1(callbackNode) { + if (callbackNode === fakeActCallbackNode) { + return; + } // In production, always call Scheduler. This function will be stripped out. - if (siblingFiber !== null) { - // If there is more work to do in this returnFiber, do that next. - workInProgress = siblingFiber; - return; - } // Otherwise, return to the parent + return cancelCallback(callbackNode); + } - completedWork = returnFiber; // Update the next thing we're working on in case something throws. + function shouldForceFlushFallbacksInDEV() { + // Never force flush in production. This function should get stripped out. + return ReactCurrentActQueue$1.current !== null; + } - workInProgress = completedWork; - } while (completedWork !== null); // We've reached the root. + 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 (workInProgressRootExitStatus === RootInProgress) { - workInProgressRootExitStatus = RootCompleted; - } -} + if (executionContext !== NoContext) { + // Legacy mode doesn't warn if the update is batched, i.e. + // batchedUpdates or flushSync. + return; + } -function commitRoot(root, recoverableErrors, transitions) { - // 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$2.transition; + 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; + } + } - try { - ReactCurrentBatchConfig$2.transition = null; - setCurrentUpdatePriority(DiscreteEventPriority); - commitRootImpl( - root, - recoverableErrors, - transitions, - previousUpdateLanePriority - ); - } finally { - ReactCurrentBatchConfig$2.transition = prevTransition; - setCurrentUpdatePriority(previousUpdateLanePriority); - } + if (ReactCurrentActQueue$1.current === null) { + var previousFiber = current; - return null; -} + try { + setCurrentFiber(fiber); -function commitRootImpl( - root, - recoverableErrors, - transitions, - renderPriorityLevel -) { - 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 (finishedWork === null) { - return null; - } else { - { - if (lanes === NoLanes) { - error( - "root.finishedLanes should not be empty during a commit. This is a " + - "bug in React." - ); + 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://react.dev/link/wrap-tests-with-act", + getComponentNameFromFiber(fiber) + ); + } finally { + if (previousFiber) { + setCurrentFiber(fiber); + } else { + resetCurrentFiber(); + } + } + } } } - } - - 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; // Update the first and last pending times on this root. The new first - // pending time is whatever is left on the root fiber. - - var remainingLanes = mergeLanes(finishedWork.lanes, finishedWork.childLanes); - markRootFinished(root, remainingLanes); - - 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 || - (finishedWork.flags & PassiveMask) !== NoFlags - ) { - if (!rootDoesHavePassiveEffects) { - rootDoesHavePassiveEffects = true; - // 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$1(NormalPriority, 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) - - return null; - }); + function warnIfSuspenseResolutionNotWrappedWithActDEV(root) { + { + if ( + root.tag !== LegacyRoot && + isConcurrentActEnvironment() && + ReactCurrentActQueue$1.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://react.dev/link/wrap-tests-with-act" + ); + } + } } - } // 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; - var rootHasEffect = - (finishedWork.flags & - (BeforeMutationMask | MutationMask | LayoutMask | PassiveMask)) !== - NoFlags; - - if (subtreeHasEffects || rootHasEffect) { - var prevTransition = ReactCurrentBatchConfig$2.transition; - ReactCurrentBatchConfig$2.transition = null; - var previousPriority = getCurrentUpdatePriority(); - setCurrentUpdatePriority(DiscreteEventPriority); - var prevExecutionContext = executionContext; - executionContext |= CommitContext; // Reset this to null before calling lifecycles - - ReactCurrentOwner$2.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. - - var shouldFireAfterActiveInstanceBlur = commitBeforeMutationEffects( - root, - finishedWork - ); - { - // Mark the current commit time to be shared by all Profilers in this - // batch. This enables them to be grouped later. - recordCommitTime(); + function setIsRunningInsertionEffect(isRunning) { + { + isRunningInsertionEffect = isRunning; + } } - commitMutationEffects(root, finishedWork, lanes); - - resetAfterCommit(root.containerInfo); // The work-in-progress tree is now the current tree. This must come after - // 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. - - root.current = finishedWork; // The next phase is the layout phase, where we call effects that read - - commitLayoutEffects(finishedWork, root, lanes); - // opportunity to paint. + /* eslint-disable react-internal/prod-error-codes */ + var resolveFamily = null; // $FlowFixMe Flow gets confused by a WeakSet feature check below. - requestPaint(); - executionContext = prevExecutionContext; // Reset the priority to the previous non-sync value. + var failedBoundaries = null; + var setRefreshHandler = function (handler) { + { + resolveFamily = handler; + } + }; + function resolveFunctionForHotReloading(type) { + { + if (resolveFamily === null) { + // Hot reloading is disabled. + return type; + } - setCurrentUpdatePriority(previousPriority); - ReactCurrentBatchConfig$2.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. + var family = resolveFamily(type); - { - recordCommitTime(); - } - } + if (family === undefined) { + return type; + } // Use the latest known implementation. - 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 { - { - 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; - } - - onCommitRoot(finishedWork.stateNode, renderPriorityLevel); - - { - if (isDevToolsPresent) { - root.memoizedUpdaters.clear(); - } - } - // additional work on this root is scheduled. - - ensureRootIsScheduled(root, now()); - - 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 componentStack = recoverableError.stack; - var digest = recoverableError.digest; - onRecoverableError(recoverableError.value, { - componentStack: componentStack, - digest: digest - }); + return family.current; + } } - } - - 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 ( - includesSomeLane(pendingPassiveEffectsLanes, SyncLane) && - root.tag !== LegacyRoot - ) { - flushPassiveEffects(); - } // Read this again, since a passive effect might have updated it - - remainingLanes = root.pendingLanes; - - if (includesSomeLane(remainingLanes, SyncLane)) { - { - 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 (root === rootWithNestedUpdates) { - nestedUpdateCount++; - } else { - nestedUpdateCount = 0; - rootWithNestedUpdates = root; + function resolveClassForHotReloading(type) { + // No implementation differences. + return resolveFunctionForHotReloading(type); } - } else { - nestedUpdateCount = 0; - } // If layout work was scheduled, flush it now. + function resolveForwardRefForHotReloading(type) { + { + if (resolveFamily === null) { + // Hot reloading is disabled. + return type; + } - flushSyncCallbacks(); + var family = resolveFamily(type); - return null; -} + 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; + } -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) { - var renderPriority = lanesToEventPriority(pendingPassiveEffectsLanes); - var priority = lowerEventPriority(DefaultEventPriority, renderPriority); - var prevTransition = ReactCurrentBatchConfig$2.transition; - var previousPriority = getCurrentUpdatePriority(); - - try { - ReactCurrentBatchConfig$2.transition = null; - setCurrentUpdatePriority(priority); - return flushPassiveEffectsImpl(); - } finally { - setCurrentUpdatePriority(previousPriority); - ReactCurrentBatchConfig$2.transition = prevTransition; // Once passive effects have run for the tree - giving components a - } - } - - return false; -} -function enqueuePendingPassiveProfilerEffect(fiber) { - { - pendingPassiveProfilerEffects.push(fiber); + return syntheticType; + } + } - if (!rootDoesHavePassiveEffects) { - rootDoesHavePassiveEffects = true; - scheduleCallback$1(NormalPriority, function() { - flushPassiveEffects(); - return null; - }); - } - } -} + return type; + } // Use the latest known implementation. -function flushPassiveEffectsImpl() { - if (rootWithPendingPassiveEffects === null) { - return false; - } // Cache and clear the transitions flag - - 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."); - } - - { - isFlushingPassiveEffects = true; - didScheduleUpdateDuringPassiveEffects = false; - } - - var prevExecutionContext = executionContext; - executionContext |= CommitContext; - commitPassiveUnmountEffects(root.current); - commitPassiveMountEffects(root, root.current, lanes, transitions); // TODO: Move to commitPassiveMountEffects - - { - var profilerEffects = pendingPassiveProfilerEffects; - pendingPassiveProfilerEffects = []; - - for (var i = 0; i < profilerEffects.length; i++) { - var _fiber = profilerEffects[i]; - commitPassiveEffectDurations(root, _fiber); - } - } - - executionContext = prevExecutionContext; - flushSyncCallbacks(); - - { - // 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; + return family.current; } - } else { - nestedPassiveUpdateCount = 0; } + function isCompatibleFamilyForHotReloading(fiber, element) { + { + if (resolveFamily === null) { + // Hot reloading is disabled. + return false; + } - isFlushingPassiveEffects = false; - didScheduleUpdateDuringPassiveEffects = false; - } // TODO: Move to commitPassiveMountEffects - - onPostCommitRoot(root); + var prevType = fiber.elementType; + var nextType = element.type; // If we got here, we know types aren't === equal. - { - var stateNode = root.current.stateNode; - stateNode.effectDuration = 0; - stateNode.passiveEffectDuration = 0; - } + var needsCompareFamilies = false; + var $$typeofNextType = + typeof nextType === "object" && nextType !== null + ? nextType.$$typeof + : null; - return true; -} + switch (fiber.tag) { + case ClassComponent: { + if (typeof nextType === "function") { + needsCompareFamilies = true; + } -function isAlreadyFailedLegacyErrorBoundary(instance) { - return ( - legacyErrorBoundariesThatAlreadyFailed !== null && - legacyErrorBoundariesThatAlreadyFailed.has(instance) - ); -} -function markLegacyErrorBoundaryAsFailed(instance) { - if (legacyErrorBoundariesThatAlreadyFailed === null) { - legacyErrorBoundariesThatAlreadyFailed = new Set([instance]); - } else { - legacyErrorBoundariesThatAlreadyFailed.add(instance); - } -} + break; + } -function prepareToThrowUncaughtError(error) { - if (!hasUncaughtError) { - hasUncaughtError = true; - firstUncaughtError = error; - } -} + 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; + } -var onUncaughtError = prepareToThrowUncaughtError; + break; + } -function captureCommitPhaseErrorOnRoot(rootFiber, sourceFiber, error) { - var errorInfo = createCapturedValueAtFiber(error, sourceFiber); - var update = createRootErrorUpdate(rootFiber, errorInfo, SyncLane); - var root = enqueueUpdate(rootFiber, update, SyncLane); - var eventTime = requestEventTime(); + case ForwardRef: { + if ($$typeofNextType === REACT_FORWARD_REF_TYPE) { + needsCompareFamilies = true; + } else if ($$typeofNextType === REACT_LAZY_TYPE) { + needsCompareFamilies = true; + } - if (root !== null) { - markRootUpdated(root, SyncLane, eventTime); - ensureRootIsScheduled(root, eventTime); - } -} + 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 = null; - - { - fiber = sourceFiber.return; - } - - 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 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 ( - 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); - var eventTime = requestEventTime(); + break; + } - if (root !== null) { - markRootUpdated(root, SyncLane, eventTime); - ensureRootIsScheduled(root, eventTime); + default: + return false; + } // Check if both types have a family and it's the same one. + + 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); + + if (prevFamily !== undefined && prevFamily === resolveFamily(nextType)) { + return true; + } } - return; + return false; } } + function markFailedErrorBoundaryForHotReloading(fiber) { + { + if (resolveFamily === null) { + // Hot reloading is disabled. + return; + } - fiber = fiber.return; - } - - { - // TODO: Until we re-land skipUnmountedBoundaries (see #20147), this warning - // will fire for errors that are thrown by destroy functions inside deleted - // trees. What it should instead do is propagate the error to the parent of - // the deleted tree. In the meantime, do not add this warning to the - // allowlist; this is only for our internal use. - error( - "Internal React error: Attempted to capture a commit phase error " + - "inside a detached tree. This indicates a bug in React. Likely " + - "causes include deleting the same fiber more than once, committing an " + - "already-finished tree, or an inconsistent return pointer.\n\n" + - "Error message:\n\n%s", - error$1 - ); - } -} -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); - } - - var eventTime = requestEventTime(); - 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() - globalMostRecentFallbackTime < FALLBACK_THROTTLE_MS) - ) { - // Restart from the root. - 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 (typeof WeakSet !== "function") { + return; + } - ensureRootIsScheduled(root, eventTime); -} + if (failedBoundaries === null) { + failedBoundaries = new WeakSet(); + } -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 eventTime = requestEventTime(); - var root = enqueueConcurrentRenderForLane(boundaryFiber, retryLane); - - if (root !== null) { - markRootUpdated(root, retryLane, eventTime); - ensureRootIsScheduled(root, eventTime); - } -} + failedBoundaries.add(fiber); + } + } + var scheduleRefresh = function (root, update) { + { + if (resolveFamily === null) { + // Hot reloading is disabled. + return; + } -function retryDehydratedSuspenseBoundary(boundaryFiber) { - var suspenseState = boundaryFiber.memoizedState; - var retryLane = NoLane; + 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; + } - if (suspenseState !== null) { - retryLane = suspenseState.retryLane; - } + flushPassiveEffects(); + flushSync(function () { + updateContainer(element, root, null, null); + }); + } + }; - retryTimedOutBoundary(boundaryFiber, retryLane); -} -function resolveRetryWakeable(boundaryFiber, wakeable) { - var retryLane = NoLane; // Default + 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; - var retryCache; + case ForwardRef: + candidateType = type.render; + break; + } - switch (boundaryFiber.tag) { - case SuspenseComponent: - retryCache = boundaryFiber.stateNode; - var suspenseState = boundaryFiber.memoizedState; + if (resolveFamily === null) { + throw new Error("Expected resolveFamily to be set during hot reload."); + } - if (suspenseState !== null) { - retryLane = suspenseState.retryLane; - } + var needsRender = false; + var needsRemount = false; - break; + if (candidateType !== null) { + var family = resolveFamily(candidateType); - case SuspenseListComponent: - retryCache = boundaryFiber.stateNode; - break; + if (family !== undefined) { + if (staleFamilies.has(family)) { + needsRemount = true; + } else if (updatedFamilies.has(family)) { + if (tag === ClassComponent) { + needsRemount = true; + } else { + needsRender = true; + } + } + } + } - default: - throw new Error( - "Pinged unknown suspense boundary type. " + - "This is probably a bug in React." - ); - } - - 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); -} // Computes the next Just Noticeable Difference (JND) boundary. -// The theory is that a person can't tell the difference between small differences in time. -// Therefore, if we wait a bit longer than necessary that won't translate to a noticeable -// difference in the experience. However, waiting for longer might mean that we can avoid -// showing an intermediate loading state. The longer we have already waited, the harder it -// is to tell small differences in time. Therefore, the longer we've already waited, -// the longer we can wait additionally. At some point we have to give up though. -// We pick a train model where the next boundary commits at a consistent schedule. -// These particular numbers are vague estimates. We expect to adjust them based on research. - -function jnd(timeElapsed) { - return timeElapsed < 120 - ? 120 - : timeElapsed < 480 - ? 480 - : timeElapsed < 1080 - ? 1080 - : timeElapsed < 1920 - ? 1920 - : timeElapsed < 3000 - ? 3000 - : timeElapsed < 4320 - ? 4320 - : ceil(timeElapsed / 1960) * 1960; -} + if (failedBoundaries !== null) { + if ( + failedBoundaries.has(fiber) || + (alternate !== null && failedBoundaries.has(alternate)) + ) { + needsRemount = true; + } + } -function checkForNestedUpdates() { - if (nestedUpdateCount > NESTED_UPDATE_LIMIT) { - nestedUpdateCount = 0; - rootWithNestedUpdates = 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." - ); - } - } -} + if (needsRemount) { + fiber._debugNeedsRemount = true; + } -function flushRenderPhaseStrictModeWarningsInDEV() { - { - ReactStrictModeWarnings.flushLegacyContextWarning(); + if (needsRemount || needsRender) { + var _root = enqueueConcurrentRenderForLane(fiber, SyncLane); - { - ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings(); - } - } -} + if (_root !== null) { + scheduleUpdateOnFiber(_root, fiber, SyncLane, NoTimestamp); + } + } -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 (child !== null && !needsRemount) { + scheduleFibersWithFamiliesRecursively( + child, + updatedFamilies, + staleFamilies + ); + } - if (!(fiber.mode & ConcurrentMode)) { - return; + if (sibling !== null) { + scheduleFibersWithFamiliesRecursively( + sibling, + updatedFamilies, + staleFamilies + ); + } + } } - var tag = fiber.tag; + 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 ( - tag !== IndeterminateComponent && - tag !== HostRoot && - tag !== ClassComponent && - tag !== FunctionComponent && - tag !== ForwardRef && - tag !== MemoComponent && - tag !== SimpleMemoComponent + function findHostInstancesForMatchingFibersRecursively( + fiber, + types, + hostInstances ) { - // 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. - - var componentName = getComponentNameFromFiber(fiber) || "ReactComponent"; + { + 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 (didWarnStateUpdateForNotYetMountedComponent !== null) { - if (didWarnStateUpdateForNotYetMountedComponent.has(componentName)) { - return; - } + case ForwardRef: + candidateType = type.render; + break; + } - didWarnStateUpdateForNotYetMountedComponent.add(componentName); - } else { - didWarnStateUpdateForNotYetMountedComponent = new Set([componentName]); - } + var didMatch = false; - var previousFiber = current; + if (candidateType !== null) { + if (types.has(candidateType)) { + didMatch = true; + } + } - try { - 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 { + // If there's no match, maybe there will be one further down in the child tree. + if (child !== null) { + findHostInstancesForMatchingFibersRecursively( + child, + types, + hostInstances + ); + } + } - 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 (sibling !== null) { + findHostInstancesForMatchingFibersRecursively( + sibling, + types, + hostInstances + ); + } } } - } -} -var beginWork$1; - -{ - var dummyFiber = null; - - beginWork$1 = 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 - ); - try { - return beginWork(current, unitOfWork, lanes); - } catch (originalError) { - if ( - didSuspendOrErrorWhileHydratingDEV() || - (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; - } // Keep this code in sync with handleError; any changes here must have - // corresponding changes there. + function findHostInstancesForFiberShallowly(fiber, hostInstances) { + { + var foundHostInstances = findChildHostInstancesForFiberShallowly( + fiber, + hostInstances + ); - resetContextDependencies(); - resetHooksAfterThrow(); // Don't reset current debug fiber, since we're about to work on the - // same fiber again. - // Unwind the failed stack frame + if (foundHostInstances) { + return; + } // If we didn't find any host children, fallback to closest host parent. - unwindInterruptedWork(current, unitOfWork); // Restore the original properties of the fiber. + var node = fiber; - assignFiberPropertiesInDEV(unitOfWork, originalWorkInProgressCopy); + while (true) { + switch (node.tag) { + case HostComponent: + hostInstances.add(node.stateNode); + return; - if (unitOfWork.mode & ProfileMode) { - // Reset the profiler timer. - startProfilerTimer(unitOfWork); - } // Run beginWork again. + case HostPortal: + hostInstances.add(node.stateNode.containerInfo); + return; - invokeGuardedCallback(null, beginWork, null, current, unitOfWork, lanes); + case HostRoot: + hostInstances.add(node.stateNode.containerInfo); + return; + } - if (hasCaughtError()) { - var replayError = clearCaughtError(); + if (node.return === null) { + throw new Error("Expected to reach root first."); + } - 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; + node = node.return; } - } // 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; + } } - }; -} - -var didWarnAboutUpdateInRender = false; -var didWarnAboutUpdateInRenderForAnotherComponent; - -{ - didWarnAboutUpdateInRenderForAnotherComponent = new Set(); -} - -function warnAboutRenderPhaseUpdatesInDEV(fiber) { - { - if (isRendering && !getIsUpdatingOpaqueValueInRenderPhaseInDEV()) { - 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 dedupeKey = renderingComponentName; - if (!didWarnAboutUpdateInRenderForAnotherComponent.has(dedupeKey)) { - didWarnAboutUpdateInRenderForAnotherComponent.add(dedupeKey); - var setStateComponentName = - getComponentNameFromFiber(fiber) || "Unknown"; - - 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://react.dev/link/setstate-in-render", - setStateComponentName, - renderingComponentName, - renderingComponentName - ); + function findChildHostInstancesForFiberShallowly(fiber, hostInstances) { + { + var node = fiber; + var foundHostInstances = false; + + while (true) { + if (node.tag === HostComponent) { + // 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; } - break; - } + if (node === fiber) { + return foundHostInstances; + } - 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." - ); + while (node.sibling === null) { + if (node.return === null || node.return === fiber) { + return foundHostInstances; + } - didWarnAboutUpdateInRender = true; + node = node.return; } - break; + node.sibling.return = node.return; + node = node.sibling; } } - } - } -} - -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 = {}; -function scheduleCallback$1(priorityLevel, callback) { - { - // If we're currently inside an `act` scope, bypass Scheduler and push to - // the `act` queue instead. - var actQueue = ReactCurrentActQueue$1.current; - - if (actQueue !== null) { - actQueue.push(callback); - return fakeActCallbackNode; - } else { - return scheduleCallback(priorityLevel, callback); + return false; } - } -} -function cancelCallback$1(callbackNode) { - if (callbackNode === fakeActCallbackNode) { - return; - } // In production, always call Scheduler. This function will be stripped out. + var hasBadMapPolyfill; - return cancelCallback(callbackNode); -} + { + hasBadMapPolyfill = false; -function shouldForceFlushFallbacksInDEV() { - // Never force flush in production. This function should get stripped out. - return ReactCurrentActQueue$1.current !== null; -} + 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.pendingProps = pendingProps; + this.memoizedProps = null; + this.updateQueue = null; + this.memoizedState = null; + this.dependencies = null; + this.mode = mode; // Effects + + this.flags = NoFlags; + this.subtreeFlags = NoFlags; + this.deletions = null; + this.lanes = NoLanes; + this.childLanes = NoLanes; + this.alternate = 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; + { + // 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; } - if (executionContext !== NoContext) { - // Legacy mode doesn't warn if the update is batched, i.e. - // batchedUpdates or flushSync. - return; + { + // 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. + + var createFiber = function (tag, pendingProps, key, mode) { + // $FlowFixMe: the shapes are exact here but Flow doesn't like constructors + return new FiberNode(tag, pendingProps, key, mode); + }; - 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; - } + function shouldConstruct(Component) { + var prototype = Component.prototype; + return !!(prototype && prototype.isReactComponent); } - if (ReactCurrentActQueue$1.current === null) { - var previousFiber = current; + 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; - try { - setCurrentFiber(fiber); + if ($$typeof === REACT_FORWARD_REF_TYPE) { + return ForwardRef; + } - 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://react.dev/link/wrap-tests-with-act", - getComponentNameFromFiber(fiber) - ); - } finally { - if (previousFiber) { - setCurrentFiber(fiber); - } else { - resetCurrentFiber(); + if ($$typeof === REACT_MEMO_TYPE) { + return MemoComponent; } } - } - } -} -function warnIfSuspenseResolutionNotWrappedWithActDEV(root) { - { - if ( - root.tag !== LegacyRoot && - isConcurrentActEnvironment() && - ReactCurrentActQueue$1.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://react.dev/link/wrap-tests-with-act" - ); - } - } -} + return IndeterminateComponent; + } // This is used to create an alternate fiber to do work on. -function setIsRunningInsertionEffect(isRunning) { - { - isRunningInsertionEffect = isRunning; - } -} + function createWorkInProgress(current, pendingProps) { + var workInProgress = current.alternate; -/* eslint-disable react-internal/prod-error-codes */ -var resolveFamily = null; // $FlowFixMe Flow gets confused by a WeakSet feature check below. + 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; -var failedBoundaries = null; -var setRefreshHandler = function(handler) { - { - resolveFamily = handler; - } -}; -function resolveFunctionForHotReloading(type) { - { - if (resolveFamily === null) { - // Hot reloading is disabled. - return type; - } + { + // DEV-only fields + workInProgress._debugSource = current._debugSource; + workInProgress._debugOwner = current._debugOwner; + workInProgress._debugHookTypes = current._debugHookTypes; + } - var family = resolveFamily(type); + workInProgress.alternate = current; + current.alternate = workInProgress; + } else { + workInProgress.pendingProps = pendingProps; // Needed because Blocks store data on type. - if (family === undefined) { - return type; - } // Use the latest known implementation. + workInProgress.type = current.type; // We already have an alternate. + // Reset the effect tag. - return family.current; - } -} -function resolveClassForHotReloading(type) { - // No implementation differences. - return resolveFunctionForHotReloading(type); -} -function resolveForwardRefForHotReloading(type) { - { - if (resolveFamily === null) { - // Hot reloading is disabled. - return type; - } + workInProgress.flags = NoFlags; // The effects are no longer valid. - var family = resolveFamily(type); + workInProgress.subtreeFlags = NoFlags; + workInProgress.deletions = null; - 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 - }; + { + // 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 - if (type.displayName !== undefined) { - syntheticType.displayName = type.displayName; - } + workInProgress.sibling = current.sibling; + workInProgress.index = current.index; + workInProgress.ref = current.ref; - return syntheticType; - } + { + workInProgress.selfBaseDuration = current.selfBaseDuration; + workInProgress.treeBaseDuration = current.treeBaseDuration; } - return type; - } // Use the latest known implementation. - - return family.current; - } -} -function isCompatibleFamilyForHotReloading(fiber, element) { - { - if (resolveFamily === null) { - // Hot reloading is disabled. - return false; - } + { + workInProgress._debugNeedsRemount = current._debugNeedsRemount; - var prevType = fiber.elementType; - var nextType = element.type; // If we got here, we know types aren't === equal. + switch (workInProgress.tag) { + case IndeterminateComponent: + case FunctionComponent: + case SimpleMemoComponent: + workInProgress.type = resolveFunctionForHotReloading(current.type); + break; - var needsCompareFamilies = false; - var $$typeofNextType = - typeof nextType === "object" && nextType !== null - ? nextType.$$typeof - : null; + case ClassComponent: + workInProgress.type = resolveClassForHotReloading(current.type); + break; - switch (fiber.tag) { - case ClassComponent: { - if (typeof nextType === "function") { - needsCompareFamilies = true; + case ForwardRef: + workInProgress.type = resolveForwardRefForHotReloading(current.type); + break; } - - break; } - 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; - } + return workInProgress; + } // Used to reuse a Fiber for a second pass. - break; - } + 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. - case ForwardRef: { - if ($$typeofNextType === REACT_FORWARD_REF_TYPE) { - needsCompareFamilies = true; - } else if ($$typeofNextType === REACT_LAZY_TYPE) { - needsCompareFamilies = true; - } + var current = workInProgress.alternate; - break; - } + if (current === null) { + // Reset to createFiber's initial values. + workInProgress.childLanes = NoLanes; + workInProgress.lanes = renderLanes; + workInProgress.child = null; + workInProgress.subtreeFlags = NoFlags; + workInProgress.memoizedProps = null; + workInProgress.memoizedState = null; + workInProgress.updateQueue = null; + workInProgress.dependencies = null; + workInProgress.stateNode = null; - 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; + { + // 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; + 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 + }; - break; - } - - default: - return false; - } // Check if both types have a family and it's the same one. - - 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); - - if (prevFamily !== undefined && prevFamily === resolveFamily(nextType)) { - return true; + { + // 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; + } } - } - - return false; - } -} -function markFailedErrorBoundaryForHotReloading(fiber) { - { - if (resolveFamily === null) { - // Hot reloading is disabled. - return; - } - if (typeof WeakSet !== "function") { - return; + return workInProgress; } + function createHostRootFiber( + tag, + isStrictMode, + concurrentUpdatesByDefaultOverride + ) { + var mode; - if (failedBoundaries === null) { - failedBoundaries = new WeakSet(); - } + if (tag === ConcurrentRoot) { + mode = ConcurrentMode; - 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; - } + if (isStrictMode === true) { + mode |= StrictLegacyMode; } + } else { + mode = NoMode; } - } - if (failedBoundaries !== null) { - if ( - failedBoundaries.has(fiber) || - (alternate !== null && failedBoundaries.has(alternate)) - ) { - needsRemount = true; + 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; } - } - if (needsRemount) { - fiber._debugNeedsRemount = true; - } - - if (needsRemount || needsRender) { - var _root = enqueueConcurrentRenderForLane(fiber, SyncLane); - - if (_root !== null) { - scheduleUpdateOnFiber(_root, fiber, SyncLane, NoTimestamp); - } + return createFiber(HostRoot, null, null, mode); } + function createFiberFromTypeAndProps( + type, // React$ElementType + key, + pendingProps, + 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. - if (child !== null && !needsRemount) { - scheduleFibersWithFamiliesRecursively( - child, - updatedFamilies, - staleFamilies - ); - } + var resolvedType = type; - if (sibling !== null) { - scheduleFibersWithFamiliesRecursively( - sibling, - updatedFamilies, - staleFamilies - ); - } - } -} + if (typeof type === "function") { + if (shouldConstruct(type)) { + fiberTag = ClassComponent; -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 - ); - } - } + { + 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); - if (sibling !== null) { - findHostInstancesForMatchingFibersRecursively( - sibling, - types, - hostInstances - ); - } - } -} + case REACT_STRICT_MODE_TYPE: + fiberTag = Mode; + mode |= StrictLegacyMode; -function findHostInstancesForFiberShallowly(fiber, hostInstances) { - { - var foundHostInstances = findChildHostInstancesForFiberShallowly( - fiber, - hostInstances - ); + break; - if (foundHostInstances) { - return; - } // If we didn't find any host children, fallback to closest host parent. + case REACT_PROFILER_TYPE: + return createFiberFromProfiler(pendingProps, mode, lanes, key); - var node = fiber; + case REACT_SUSPENSE_TYPE: + return createFiberFromSuspense(pendingProps, mode, lanes, key); - while (true) { - switch (node.tag) { - case HostComponent: - hostInstances.add(node.stateNode); - return; + case REACT_SUSPENSE_LIST_TYPE: + return createFiberFromSuspenseList(pendingProps, mode, lanes, key); - case HostPortal: - hostInstances.add(node.stateNode.containerInfo); - return; + case REACT_OFFSCREEN_TYPE: + return createFiberFromOffscreen(pendingProps, mode, lanes, key); - case HostRoot: - hostInstances.add(node.stateNode.containerInfo); - return; - } + case REACT_LEGACY_HIDDEN_TYPE: - if (node.return === null) { - throw new Error("Expected to reach root first."); - } + // eslint-disable-next-line no-fallthrough - node = node.return; - } - } -} + case REACT_SCOPE_TYPE: -function findChildHostInstancesForFiberShallowly(fiber, hostInstances) { - { - var node = fiber; - var foundHostInstances = false; + // eslint-disable-next-line no-fallthrough - while (true) { - if (node.tag === HostComponent) { - // 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; - } + case REACT_CACHE_TYPE: - if (node === fiber) { - return foundHostInstances; - } + // eslint-disable-next-line no-fallthrough - while (node.sibling === null) { - if (node.return === null || node.return === fiber) { - return foundHostInstances; - } + case REACT_TRACING_MARKER_TYPE: - node = node.return; - } + // eslint-disable-next-line no-fallthrough - node.sibling.return = node.return; - node = node.sibling; - } - } + case REACT_DEBUG_TRACING_MODE_TYPE: - return false; -} + // eslint-disable-next-line no-fallthrough -var hasBadMapPolyfill; + default: { + if (typeof type === "object" && type !== null) { + switch (type.$$typeof) { + case REACT_PROVIDER_TYPE: + fiberTag = ContextProvider; + break getTag; -{ - hasBadMapPolyfill = false; + case REACT_CONTEXT_TYPE: + // This is a consumer + fiberTag = ContextConsumer; + break getTag; - try { - var nonExtensibleObject = Object.preventExtensions({}); - /* eslint-disable no-new */ + case REACT_FORWARD_REF_TYPE: + fiberTag = ForwardRef; - new Map([[nonExtensibleObject, null]]); - new Set([nonExtensibleObject]); - /* eslint-enable no-new */ - } catch (e) { - // TODO: Consider warning about bad polyfills - hasBadMapPolyfill = true; - } -} + { + resolvedType = resolveForwardRefForHotReloading(resolvedType); + } -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.pendingProps = pendingProps; - this.memoizedProps = null; - this.updateQueue = null; - this.memoizedState = null; - this.dependencies = null; - this.mode = mode; // Effects - - this.flags = NoFlags; - this.subtreeFlags = NoFlags; - 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. - -var createFiber = function(tag, pendingProps, key, mode) { - // $FlowFixMe: 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); -} + break getTag; -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_MEMO_TYPE: + fiberTag = MemoComponent; + break getTag; - if ($$typeof === REACT_FORWARD_REF_TYPE) { - return ForwardRef; - } + case REACT_LAZY_TYPE: + fiberTag = LazyComponent; + resolvedType = null; + break getTag; + } + } - if ($$typeof === REACT_MEMO_TYPE) { - return MemoComponent; - } - } + var info = ""; - return IndeterminateComponent; -} // This is used to create an alternate fiber to do work on. + { + 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."; + } -function createWorkInProgress(current, pendingProps) { - var workInProgress = current.alternate; + var ownerName = owner ? getComponentNameFromFiber(owner) : null; - 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; + if (ownerName) { + info += "\n\nCheck the render method of `" + ownerName + "`."; + } + } - { - // DEV-only fields - workInProgress._debugSource = current._debugSource; - workInProgress._debugOwner = current._debugOwner; - workInProgress._debugHookTypes = current._debugHookTypes; - } + 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) + ); + } + } + } - workInProgress.alternate = current; - current.alternate = workInProgress; - } else { - workInProgress.pendingProps = pendingProps; // Needed because Blocks store data on type. + var fiber = createFiber(fiberTag, pendingProps, key, mode); + fiber.elementType = type; + fiber.type = resolvedType; + fiber.lanes = lanes; - workInProgress.type = current.type; // We already have an alternate. - // Reset the effect tag. + { + fiber._debugOwner = owner; + } - workInProgress.flags = NoFlags; // The effects are no longer valid. + return fiber; + } + function createFiberFromElement(element, mode, lanes) { + var owner = null; - workInProgress.subtreeFlags = NoFlags; - workInProgress.deletions = null; + { + owner = element._owner; + } - { - // 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.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; - workInProgress.memoizedProps = null; - workInProgress.memoizedState = null; - workInProgress.updateQueue = null; - workInProgress.dependencies = null; - workInProgress.stateNode = null; + var type = element.type; + var key = element.key; + var pendingProps = element.props; + var fiber = createFiberFromTypeAndProps( + type, + key, + pendingProps, + owner, + mode, + lanes + ); - { - // 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; - 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 - }; + { + fiber._debugSource = element._source; + fiber._debugOwner = element._owner; + } - { - // 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; + return fiber; + } + function createFiberFromFragment(elements, mode, lanes, key) { + var fiber = createFiber(Fragment, elements, key, mode); + fiber.lanes = lanes; + return fiber; } - } - return workInProgress; -} -function createHostRootFiber( - tag, - isStrictMode, - concurrentUpdatesByDefaultOverride -) { - var mode; - - if (tag === ConcurrentRoot) { - mode = ConcurrentMode; - - if (isStrictMode === true) { - mode |= StrictLegacyMode; - } - } else { - mode = NoMode; - } - - 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; - } - - return createFiber(HostRoot, null, null, mode); -} -function createFiberFromTypeAndProps( - type, // React$ElementType - key, - pendingProps, - 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; + 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; { - resolvedType = resolveClassForHotReloading(resolvedType); + fiber.stateNode = { + effectDuration: 0, + passiveEffectDuration: 0 + }; } - } else { + + 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 = { + isHidden: false + }; + fiber.stateNode = primaryChildInstance; + 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.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; + { - resolvedType = resolveFunctionForHotReloading(resolvedType); + 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; } - } else if (typeof type === "string") { - fiberTag = HostComponent; - } else { - getTag: switch (type) { - case REACT_FRAGMENT_TYPE: - return createFiberFromFragment(pendingProps.children, mode, lanes, key); - case REACT_STRICT_MODE_TYPE: - fiberTag = Mode; - mode |= StrictLegacyMode; + function FiberRootNode( + containerInfo, + tag, + hydrate, + identifierPrefix, + onRecoverableError + ) { + this.tag = tag; + this.containerInfo = containerInfo; + this.pendingChildren = null; + this.current = null; + this.pingCache = null; + this.finishedWork = null; + this.timeoutHandle = noTimeout; + this.context = null; + this.pendingContext = null; + this.callbackNode = null; + this.callbackPriority = NoLane; + this.eventTimes = createLaneMap(NoLanes); + this.expirationTimes = createLaneMap(NoTimestamp); + this.pendingLanes = NoLanes; + this.suspendedLanes = NoLanes; + this.pingedLanes = NoLanes; + this.expiredLanes = NoLanes; + this.mutableReadLanes = NoLanes; + this.finishedLanes = NoLanes; + this.entangledLanes = NoLanes; + this.entanglements = createLaneMap(NoLanes); + this.identifierPrefix = identifierPrefix; + this.onRecoverableError = onRecoverableError; - break; + { + this.effectDuration = 0; + this.passiveEffectDuration = 0; + } - case REACT_PROFILER_TYPE: - return createFiberFromProfiler(pendingProps, mode, lanes, key); + { + this.memoizedUpdaters = new Set(); + var pendingUpdatersLaneMap = (this.pendingUpdatersLaneMap = []); - case REACT_SUSPENSE_TYPE: - return createFiberFromSuspense(pendingProps, mode, lanes, key); + for (var _i = 0; _i < TotalLanes; _i++) { + pendingUpdatersLaneMap.push(new Set()); + } + } - case REACT_SUSPENSE_LIST_TYPE: - return createFiberFromSuspenseList(pendingProps, mode, lanes, key); + { + switch (tag) { + case ConcurrentRoot: + this._debugRootType = hydrate ? "hydrateRoot()" : "createRoot()"; + break; - case REACT_OFFSCREEN_TYPE: - return createFiberFromOffscreen(pendingProps, mode, lanes, key); + case LegacyRoot: + this._debugRootType = hydrate ? "hydrate()" : "render()"; + break; + } + } + } - case REACT_LEGACY_HIDDEN_TYPE: + 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 + ) { + var root = new FiberRootNode( + containerInfo, + tag, + hydrate, + identifierPrefix, + onRecoverableError + ); + // stateNode is any. - // eslint-disable-next-line no-fallthrough + var uninitializedFiber = createHostRootFiber(tag, isStrictMode); + root.current = uninitializedFiber; + uninitializedFiber.stateNode = root; - case REACT_SCOPE_TYPE: + { + var _initialState = { + element: initialChildren, + isDehydrated: hydrate, + cache: null, + // not enabled yet + transitions: null, + pendingSuspenseBoundaries: null + }; + uninitializedFiber.memoizedState = _initialState; + } - // eslint-disable-next-line no-fallthrough + initializeUpdateQueue(uninitializedFiber); + return root; + } - case REACT_CACHE_TYPE: + var ReactVersion = "18.2.0-next-9e3b772b8-20220608"; - // eslint-disable-next-line no-fallthrough + function createPortal( + children, + containerInfo, // TODO: figure out the API for cross-renderer implementation. + implementation + ) { + var key = + arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; - case REACT_TRACING_MARKER_TYPE: + { + checkKeyStringCoercion(key); + } - // eslint-disable-next-line no-fallthrough + return { + // This tag allow us to uniquely identify this as a React Portal + $$typeof: REACT_PORTAL_TYPE, + key: key == null ? null : "" + key, + children: children, + containerInfo: containerInfo, + implementation: implementation + }; + } - case REACT_DEBUG_TRACING_MODE_TYPE: + var didWarnAboutNestedUpdates; + var didWarnAboutFindNodeInStrictMode; - // eslint-disable-next-line no-fallthrough + { + didWarnAboutNestedUpdates = false; + didWarnAboutFindNodeInStrictMode = {}; + } - default: { - if (typeof type === "object" && type !== null) { - switch (type.$$typeof) { - case REACT_PROVIDER_TYPE: - fiberTag = ContextProvider; - break getTag; + function getContextForSubtree(parentComponent) { + if (!parentComponent) { + return emptyContextObject; + } - case REACT_CONTEXT_TYPE: - // This is a consumer - fiberTag = ContextConsumer; - break getTag; + var fiber = get(parentComponent); + var parentContext = findCurrentUnmaskedContext(fiber); - case REACT_FORWARD_REF_TYPE: - fiberTag = ForwardRef; + if (fiber.tag === ClassComponent) { + var Component = fiber.type; - { - resolvedType = resolveForwardRefForHotReloading(resolvedType); - } + if (isContextProvider(Component)) { + return processChildContext(fiber, Component, parentContext); + } + } - break getTag; + return parentContext; + } - case REACT_MEMO_TYPE: - fiberTag = MemoComponent; - break getTag; + function findHostInstanceWithWarning(component, methodName) { + { + var fiber = get(component); - case REACT_LAZY_TYPE: - fiberTag = LazyComponent; - resolvedType = null; - break getTag; + if (fiber === undefined) { + if (typeof component.render === "function") { + throw new Error("Unable to find node on an unmounted component."); + } else { + var keys = Object.keys(component).join(","); + throw new Error( + "Argument appears to not be a ReactComponent. Keys: " + keys + ); } } - var info = ""; + var hostFiber = findCurrentHostFiber(fiber); - { - 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 (hostFiber === null) { + return null; + } - var ownerName = owner ? getComponentNameFromFiber(owner) : null; + if (hostFiber.mode & StrictLegacyMode) { + var componentName = getComponentNameFromFiber(fiber) || "Component"; - if (ownerName) { - info += "\n\nCheck the render method of `" + ownerName + "`."; + if (!didWarnAboutFindNodeInStrictMode[componentName]) { + didWarnAboutFindNodeInStrictMode[componentName] = true; + var previousFiber = current; + + try { + setCurrentFiber(hostFiber); + + if (fiber.mode & StrictLegacyMode) { + error( + "%s is deprecated in StrictMode. " + + "%s was passed an instance of %s which is inside StrictMode. " + + "Instead, add a ref directly to the element you want to reference. " + + "Learn more about using refs safely here: " + + "https://react.dev/link/strict-mode-find-node", + methodName, + methodName, + componentName + ); + } else { + error( + "%s is deprecated in StrictMode. " + + "%s was passed an instance of %s which renders StrictMode children. " + + "Instead, add a ref directly to the element you want to reference. " + + "Learn more about using refs safely here: " + + "https://react.dev/link/strict-mode-find-node", + methodName, + methodName, + componentName + ); + } + } finally { + // Ideally this should reset to previous but this shouldn't be called in + // render and there's another warning for that anyway. + if (previousFiber) { + setCurrentFiber(previousFiber); + } else { + resetCurrentFiber(); + } + } } } - 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 hostFiber.stateNode; } } - } - - var fiber = createFiber(fiberTag, pendingProps, key, mode); - fiber.elementType = type; - fiber.type = resolvedType; - fiber.lanes = lanes; - - { - fiber._debugOwner = owner; - } - - return fiber; -} -function createFiberFromElement(element, mode, lanes) { - var owner = null; - - { - owner = element._owner; - } - - var type = element.type; - var key = element.key; - var pendingProps = element.props; - var fiber = createFiberFromTypeAndProps( - type, - key, - pendingProps, - 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 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 ); } - } - - var fiber = createFiber(Profiler, pendingProps, key, mode | ProfileMode); - fiber.elementType = REACT_PROFILER_TYPE; - fiber.lanes = lanes; - - { - fiber.stateNode = { - effectDuration: 0, - passiveEffectDuration: 0 - }; - } + function updateContainer(element, container, parentComponent, callback) { + { + onScheduleRoot(container, element); + } - return fiber; -} + var current$1 = container.current; + var eventTime = requestEventTime(); + var lane = requestUpdateLane(current$1); -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 = { - isHidden: false - }; - fiber.stateNode = primaryChildInstance; - 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.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, - tag, - hydrate, - identifierPrefix, - onRecoverableError -) { - this.tag = tag; - this.containerInfo = containerInfo; - this.pendingChildren = null; - this.current = null; - this.pingCache = null; - this.finishedWork = null; - this.timeoutHandle = noTimeout; - this.context = null; - this.pendingContext = null; - this.callbackNode = null; - this.callbackPriority = NoLane; - this.eventTimes = createLaneMap(NoLanes); - this.expirationTimes = createLaneMap(NoTimestamp); - this.pendingLanes = NoLanes; - this.suspendedLanes = NoLanes; - this.pingedLanes = NoLanes; - this.expiredLanes = NoLanes; - this.mutableReadLanes = NoLanes; - this.finishedLanes = NoLanes; - this.entangledLanes = NoLanes; - this.entanglements = createLaneMap(NoLanes); - this.identifierPrefix = identifierPrefix; - this.onRecoverableError = onRecoverableError; - - { - 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 -) { - var root = new FiberRootNode( - containerInfo, - tag, - hydrate, - identifierPrefix, - onRecoverableError - ); - // stateNode is any. - - var uninitializedFiber = createHostRootFiber(tag, isStrictMode); - root.current = uninitializedFiber; - uninitializedFiber.stateNode = root; - - { - var _initialState = { - element: initialChildren, - isDehydrated: hydrate, - cache: null, - // not enabled yet - transitions: null, - pendingSuspenseBoundaries: null - }; - 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" + ); + } + } -var ReactVersion = "18.2.0-next-9e3b772b8-20220608"; - -function createPortal( - children, - containerInfo, // TODO: figure out the API for cross-renderer implementation. - implementation -) { - var key = - arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; - - { - checkKeyStringCoercion(key); - } - - return { - // This tag allow us to uniquely identify this as a React Portal - $$typeof: REACT_PORTAL_TYPE, - key: key == null ? null : "" + key, - children: children, - containerInfo: containerInfo, - implementation: implementation - }; -} + var update = createUpdate(eventTime, lane); // Caution: React DevTools currently depends on this property + // being called "element". -var didWarnAboutNestedUpdates; -var didWarnAboutFindNodeInStrictMode; + update.payload = { + element: element + }; + callback = callback === undefined ? null : callback; -{ - didWarnAboutNestedUpdates = false; - didWarnAboutFindNodeInStrictMode = {}; -} + 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, eventTime); + entangleTransitions(root, current$1, lane); + } - if (isContextProvider(Component)) { - return processChildContext(fiber, Component, parentContext); + return lane; } - } + function getPublicRootInstance(container) { + var containerFiber = container.current; - return parentContext; -} + if (!containerFiber.child) { + return null; + } -function findHostInstanceWithWarning(component, methodName) { - { - var fiber = get(component); + switch (containerFiber.child.tag) { + case HostComponent: + return getPublicInstance(containerFiber.child.stateNode); - if (fiber === undefined) { - if (typeof component.render === "function") { - throw new Error("Unable to find node on an unmounted component."); - } else { - var keys = Object.keys(component).join(","); - throw new Error( - "Argument appears to not be a ReactComponent. Keys: " + keys - ); + default: + return containerFiber.child.stateNode; } } - var hostFiber = findCurrentHostFiber(fiber); - - if (hostFiber === null) { + var shouldErrorImpl = function (fiber) { return null; - } - - if (hostFiber.mode & StrictLegacyMode) { - var componentName = getComponentNameFromFiber(fiber) || "Component"; - - if (!didWarnAboutFindNodeInStrictMode[componentName]) { - didWarnAboutFindNodeInStrictMode[componentName] = true; - var previousFiber = current; - - try { - setCurrentFiber(hostFiber); + }; - if (fiber.mode & StrictLegacyMode) { - error( - "%s is deprecated in StrictMode. " + - "%s was passed an instance of %s which is inside StrictMode. " + - "Instead, add a ref directly to the element you want to reference. " + - "Learn more about using refs safely here: " + - "https://react.dev/link/strict-mode-find-node", - methodName, - methodName, - componentName - ); - } else { - error( - "%s is deprecated in StrictMode. " + - "%s was passed an instance of %s which renders StrictMode children. " + - "Instead, add a ref directly to the element you want to reference. " + - "Learn more about using refs safely here: " + - "https://react.dev/link/strict-mode-find-node", - methodName, - methodName, - componentName - ); - } - } finally { - // Ideally this should reset to previous but this shouldn't be called in - // render and there's another warning for that anyway. - if (previousFiber) { - setCurrentFiber(previousFiber); - } else { - resetCurrentFiber(); - } - } - } + function shouldError(fiber) { + return shouldErrorImpl(fiber); } - return hostFiber.stateNode; - } -} + var shouldSuspendImpl = function (fiber) { + return false; + }; -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 - ); -} -function updateContainer(element, container, parentComponent, callback) { - { - onScheduleRoot(container, element); - } - - var current$1 = container.current; - var eventTime = requestEventTime(); - var lane = requestUpdateLane(current$1); - - 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 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 update = createUpdate(eventTime, lane); // Caution: React DevTools currently depends on this property - // being called "element". + { + var copyWithDeleteImpl = function (obj, path, index) { + var key = path[index]; + var updated = isArray(obj) ? obj.slice() : assign({}, obj); - update.payload = { - element: element - }; - callback = callback === undefined ? null : callback; + if (index + 1 === path.length) { + if (isArray(updated)) { + updated.splice(key, 1); + } else { + delete updated[key]; + } - if (callback !== null) { - { - if (typeof callback !== "function") { - error( - "render(...): Expected the last optional `callback` argument to be a " + - "function. Instead received: %s.", - callback - ); - } - } + return updated; + } // $FlowFixMe number or string is fine here - update.callback = callback; - } + updated[key] = copyWithDeleteImpl(obj[key], path, index + 1); + return updated; + }; - var root = enqueueUpdate(current$1, update, lane); + var copyWithDelete = function (obj, path) { + return copyWithDeleteImpl(obj, path, 0); + }; - if (root !== null) { - scheduleUpdateOnFiber(root, current$1, lane, eventTime); - entangleTransitions(root, current$1, lane); - } + var copyWithRenameImpl = function (obj, oldPath, newPath, index) { + var oldKey = oldPath[index]; + var updated = isArray(obj) ? obj.slice() : assign({}, obj); - return lane; -} -function getPublicRootInstance(container) { - var containerFiber = container.current; + if (index + 1 === oldPath.length) { + var newKey = newPath[index]; // $FlowFixMe number or string is fine here - if (!containerFiber.child) { - return null; - } + updated[newKey] = updated[oldKey]; - switch (containerFiber.child.tag) { - case HostComponent: - return getPublicInstance(containerFiber.child.stateNode); + if (isArray(updated)) { + updated.splice(oldKey, 1); + } else { + delete updated[oldKey]; + } + } else { + // $FlowFixMe number or string is fine here + updated[oldKey] = copyWithRenameImpl( + // $FlowFixMe number or string is fine here + obj[oldKey], + oldPath, + newPath, + index + 1 + ); + } - default: - return containerFiber.child.stateNode; - } -} + return updated; + }; -var shouldErrorImpl = function(fiber) { - return null; -}; + var copyWithRename = function (obj, oldPath, newPath) { + if (oldPath.length !== newPath.length) { + warn("copyWithRename() expects paths of the same length"); -function shouldError(fiber) { - return shouldErrorImpl(fiber); -} + 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 shouldSuspendImpl = function(fiber) { - return false; -}; + return; + } + } + } -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]; - } + return copyWithRenameImpl(obj, oldPath, newPath, 0); + }; - return updated; - } // $FlowFixMe number or string is fine here + var copyWithSetImpl = function (obj, path, index, value) { + if (index >= path.length) { + return value; + } - updated[key] = copyWithDeleteImpl(obj[key], path, index + 1); - return updated; - }; + var key = path[index]; + var updated = isArray(obj) ? obj.slice() : assign({}, obj); // $FlowFixMe number or string is fine here - var copyWithDelete = function(obj, path) { - return copyWithDeleteImpl(obj, path, 0); - }; + updated[key] = copyWithSetImpl(obj[key], path, index + 1, value); + return updated; + }; - var copyWithRenameImpl = function(obj, oldPath, newPath, index) { - var oldKey = oldPath[index]; - var updated = isArray(obj) ? obj.slice() : assign({}, obj); + var copyWithSet = function (obj, path, value) { + return copyWithSetImpl(obj, path, 0, value); + }; - if (index + 1 === oldPath.length) { - var newKey = newPath[index]; // $FlowFixMe number or string is fine here + 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; - updated[newKey] = updated[oldKey]; + while (currentHook !== null && id > 0) { + currentHook = currentHook.next; + id--; + } - if (isArray(updated)) { - updated.splice(oldKey, 1); - } else { - delete updated[oldKey]; - } - } else { - // $FlowFixMe number or string is fine here - updated[oldKey] = copyWithRenameImpl( - // $FlowFixMe number or string is fine here - obj[oldKey], - oldPath, - newPath, - index + 1 - ); - } + return currentHook; + }; // Support DevTools editable values for useState and useReducer. - return updated; - }; + overrideHookState = function (fiber, id, path, value) { + var hook = findHook(fiber, id); - var copyWithRename = function(obj, oldPath, newPath) { - if (oldPath.length !== newPath.length) { - warn("copyWithRename() expects paths of the same length"); + 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. - 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" - ); + fiber.memoizedProps = assign({}, fiber.memoizedProps); + var root = enqueueConcurrentRenderForLane(fiber, SyncLane); - return; + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + } } - } - } + }; - return copyWithRenameImpl(obj, oldPath, newPath, 0); - }; + overrideHookStateDeletePath = function (fiber, id, path) { + var hook = findHook(fiber, id); - var copyWithSetImpl = function(obj, path, index, value) { - if (index >= path.length) { - return value; - } + 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. - var key = path[index]; - var updated = isArray(obj) ? obj.slice() : assign({}, obj); // $FlowFixMe number or string is fine here + fiber.memoizedProps = assign({}, fiber.memoizedProps); + var root = enqueueConcurrentRenderForLane(fiber, SyncLane); - updated[key] = copyWithSetImpl(obj[key], path, index + 1, value); - return updated; - }; + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + } + } + }; - var copyWithSet = function(obj, path, value) { - return copyWithSetImpl(obj, path, 0, value); - }; + overrideHookStateRenamePath = function (fiber, id, oldPath, newPath) { + var hook = findHook(fiber, id); - 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 (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. - while (currentHook !== null && id > 0) { - currentHook = currentHook.next; - id--; - } + fiber.memoizedProps = assign({}, fiber.memoizedProps); + var root = enqueueConcurrentRenderForLane(fiber, SyncLane); - return currentHook; - }; // Support DevTools editable values for useState and useReducer. + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + } + } + }; // Support DevTools props for function components, forwardRef, memo, host components, etc. - overrideHookState = function(fiber, id, path, value) { - var hook = findHook(fiber, id); + overrideProps = function (fiber, path, value) { + fiber.pendingProps = copyWithSet(fiber.memoizedProps, path, value); - 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 (fiber.alternate) { + fiber.alternate.pendingProps = fiber.pendingProps; + } - fiber.memoizedProps = assign({}, fiber.memoizedProps); - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + var root = enqueueConcurrentRenderForLane(fiber, SyncLane); - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); - } - } - }; + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + } + }; - overrideHookStateDeletePath = function(fiber, id, path) { - var hook = findHook(fiber, id); + overridePropsDeletePath = function (fiber, path) { + fiber.pendingProps = copyWithDelete(fiber.memoizedProps, path); - 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 (fiber.alternate) { + fiber.alternate.pendingProps = fiber.pendingProps; + } - fiber.memoizedProps = assign({}, fiber.memoizedProps); - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + var root = enqueueConcurrentRenderForLane(fiber, SyncLane); - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); - } - } - }; + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + } + }; - overrideHookStateRenamePath = function(fiber, id, oldPath, newPath) { - var hook = findHook(fiber, id); + overridePropsRenamePath = function (fiber, oldPath, newPath) { + fiber.pendingProps = copyWithRename(fiber.memoizedProps, oldPath, newPath); - 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 (fiber.alternate) { + fiber.alternate.pendingProps = fiber.pendingProps; + } - fiber.memoizedProps = assign({}, fiber.memoizedProps); - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + var root = enqueueConcurrentRenderForLane(fiber, SyncLane); - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); - } - } - }; // Support DevTools props for function components, forwardRef, memo, host components, etc. + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + } + }; - overrideProps = function(fiber, path, value) { - fiber.pendingProps = copyWithSet(fiber.memoizedProps, path, value); + scheduleUpdate = function (fiber) { + var root = enqueueConcurrentRenderForLane(fiber, SyncLane); - if (fiber.alternate) { - fiber.alternate.pendingProps = fiber.pendingProps; - } + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + } + }; - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + setErrorHandler = function (newShouldErrorImpl) { + shouldErrorImpl = newShouldErrorImpl; + }; - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + setSuspenseHandler = function (newShouldSuspendImpl) { + shouldSuspendImpl = newShouldSuspendImpl; + }; } - }; - - overridePropsDeletePath = function(fiber, path) { - fiber.pendingProps = copyWithDelete(fiber.memoizedProps, path); - if (fiber.alternate) { - fiber.alternate.pendingProps = fiber.pendingProps; - } + function findHostInstanceByFiber(fiber) { + var hostFiber = findCurrentHostFiber(fiber); - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + if (hostFiber === null) { + return null; + } - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + return hostFiber.stateNode; } - }; - - overridePropsRenamePath = function(fiber, oldPath, newPath) { - fiber.pendingProps = copyWithRename(fiber.memoizedProps, oldPath, newPath); - if (fiber.alternate) { - fiber.alternate.pendingProps = fiber.pendingProps; + function emptyFindFiberByHostInstance(instance) { + return null; } - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + function getCurrentFiberForDevTools() { + return current; + } - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + 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 + }); } - }; - scheduleUpdate = function(fiber) { - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + var instanceCache = new Map(); - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + function getInstanceFromTag(tag) { + return instanceCache.get(tag) || null; } - }; - setErrorHandler = function(newShouldErrorImpl) { - shouldErrorImpl = newShouldErrorImpl; - }; - - setSuspenseHandler = function(newShouldSuspendImpl) { - shouldSuspendImpl = newShouldSuspendImpl; - }; -} + var emptyObject$1 = {}; -function findHostInstanceByFiber(fiber) { - var hostFiber = findCurrentHostFiber(fiber); + { + Object.freeze(emptyObject$1); + } - if (hostFiber === null) { - return null; - } + var createHierarchy; + var getHostNode; + var getHostProps; + var lastNonHostInstance; - return hostFiber.stateNode; -} + var getOwnerHierarchy; + var traverseOwnerTreeUp; -function emptyFindFiberByHostInstance(instance) { - return null; -} + { + createHierarchy = function (fiberHierarchy) { + return fiberHierarchy.map(function (fiber) { + return { + name: getComponentNameFromType(fiber.type), + getInspectorData: function (findNodeHandle) { + return { + props: getHostProps(fiber), + source: fiber._debugSource, + measure: function (callback) { + // If this is Fabric, we'll find a ShadowNode and use that to measure. + var hostFiber = findCurrentHostFiber(fiber); + var shadowNode = + hostFiber != null && + hostFiber.stateNode !== null && + hostFiber.stateNode.node; + + if (shadowNode) { + nativeFabricUIManager.measure(shadowNode, callback); + } else { + return ReactNativePrivateInterface.UIManager.measure( + getHostNode(fiber, findNodeHandle), + callback + ); + } + } + }; + } + }; + }); + }; -function getCurrentFiberForDevTools() { - return current; -} + getHostNode = function (fiber, findNodeHandle) { + var hostNode; // look for children first for the hostNode + // as composite fibers do not have a hostNode -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 - }); -} + while (fiber) { + if (fiber.stateNode !== null && fiber.tag === HostComponent) { + hostNode = findNodeHandle(fiber.stateNode); + } -var instanceCache = new Map(); + if (hostNode) { + return hostNode; + } -function getInstanceFromTag(tag) { - return instanceCache.get(tag) || null; -} + fiber = fiber.child; + } -var emptyObject$1 = {}; + return null; + }; -{ - Object.freeze(emptyObject$1); -} + getHostProps = function (fiber) { + var host = findCurrentHostFiber(fiber); -var createHierarchy; -var getHostNode; -var getHostProps; -var lastNonHostInstance; + if (host) { + return host.memoizedProps || emptyObject$1; + } -var getOwnerHierarchy; -var traverseOwnerTreeUp; + return emptyObject$1; + }; -{ - createHierarchy = function(fiberHierarchy) { - return fiberHierarchy.map(function(fiber) { - return { - name: getComponentNameFromType(fiber.type), - getInspectorData: function(findNodeHandle) { + exports.getInspectorDataForInstance = function (closestInstance) { + // Handle case where user clicks outside of ReactNative + if (!closestInstance) { return { - props: getHostProps(fiber), - source: fiber._debugSource, - measure: function(callback) { - // If this is Fabric, we'll find a ShadowNode and use that to measure. - var hostFiber = findCurrentHostFiber(fiber); - var shadowNode = - hostFiber != null && - hostFiber.stateNode !== null && - hostFiber.stateNode.node; - - if (shadowNode) { - nativeFabricUIManager.measure(shadowNode, callback); - } else { - return ReactNativePrivateInterface.UIManager.measure( - getHostNode(fiber, findNodeHandle), - callback - ); - } - } + hierarchy: [], + props: emptyObject$1, + selectedIndex: null, + source: null }; } - }; - }); - }; - - getHostNode = function(fiber, findNodeHandle) { - var hostNode; // look for children first for the hostNode - // as composite fibers do not have a hostNode - - while (fiber) { - if (fiber.stateNode !== null && fiber.tag === HostComponent) { - hostNode = findNodeHandle(fiber.stateNode); - } - - if (hostNode) { - return hostNode; - } - - fiber = fiber.child; - } - - return null; - }; - getHostProps = function(fiber) { - var host = findCurrentHostFiber(fiber); - - if (host) { - return host.memoizedProps || emptyObject$1; - } - - return emptyObject$1; - }; + var fiber = findCurrentFiberUsingSlowPath(closestInstance); + var fiberHierarchy = getOwnerHierarchy(fiber); + var instance = lastNonHostInstance(fiberHierarchy); + var hierarchy = createHierarchy(fiberHierarchy); + var props = getHostProps(instance); + var source = instance._debugSource; + var selectedIndex = fiberHierarchy.indexOf(instance); + return { + hierarchy: hierarchy, + props: props, + selectedIndex: selectedIndex, + source: source + }; + }; - exports.getInspectorDataForInstance = function(closestInstance) { - // Handle case where user clicks outside of ReactNative - if (!closestInstance) { - return { - hierarchy: [], - props: emptyObject$1, - selectedIndex: null, - source: null + getOwnerHierarchy = function (instance) { + var hierarchy = []; + traverseOwnerTreeUp(hierarchy, instance); + return hierarchy; }; - } - var fiber = findCurrentFiberUsingSlowPath(closestInstance); - var fiberHierarchy = getOwnerHierarchy(fiber); - var instance = lastNonHostInstance(fiberHierarchy); - var hierarchy = createHierarchy(fiberHierarchy); - var props = getHostProps(instance); - var source = instance._debugSource; - var selectedIndex = fiberHierarchy.indexOf(instance); - return { - hierarchy: hierarchy, - props: props, - selectedIndex: selectedIndex, - source: source - }; - }; + lastNonHostInstance = function (hierarchy) { + for (var i = hierarchy.length - 1; i > 1; i--) { + var instance = hierarchy[i]; - getOwnerHierarchy = function(instance) { - var hierarchy = []; - traverseOwnerTreeUp(hierarchy, instance); - return hierarchy; - }; + if (instance.tag !== HostComponent) { + return instance; + } + } - lastNonHostInstance = function(hierarchy) { - for (var i = hierarchy.length - 1; i > 1; i--) { - var instance = hierarchy[i]; + return hierarchy[0]; + }; - if (instance.tag !== HostComponent) { - return instance; - } + traverseOwnerTreeUp = function (hierarchy, instance) { + if (instance) { + hierarchy.unshift(instance); + traverseOwnerTreeUp(hierarchy, instance._debugOwner); + } + }; } - return hierarchy[0]; - }; - - traverseOwnerTreeUp = function(hierarchy, instance) { - if (instance) { - hierarchy.unshift(instance); - traverseOwnerTreeUp(hierarchy, instance._debugOwner); - } - }; -} + var getInspectorDataForViewTag; + var getInspectorDataForViewAtPoint; -var getInspectorDataForViewTag; -var getInspectorDataForViewAtPoint; + { + getInspectorDataForViewTag = function (viewTag) { + var closestInstance = getInstanceFromTag(viewTag); // Handle case where user clicks outside of ReactNative -{ - getInspectorDataForViewTag = function(viewTag) { - var closestInstance = getInstanceFromTag(viewTag); // Handle case where user clicks outside of ReactNative + if (!closestInstance) { + return { + hierarchy: [], + props: emptyObject$1, + selectedIndex: null, + source: null + }; + } - if (!closestInstance) { - return { - hierarchy: [], - props: emptyObject$1, - selectedIndex: null, - source: null + var fiber = findCurrentFiberUsingSlowPath(closestInstance); + var fiberHierarchy = getOwnerHierarchy(fiber); + var instance = lastNonHostInstance(fiberHierarchy); + var hierarchy = createHierarchy(fiberHierarchy); + var props = getHostProps(instance); + var source = instance._debugSource; + var selectedIndex = fiberHierarchy.indexOf(instance); + return { + hierarchy: hierarchy, + props: props, + selectedIndex: selectedIndex, + source: source + }; }; - } - var fiber = findCurrentFiberUsingSlowPath(closestInstance); - var fiberHierarchy = getOwnerHierarchy(fiber); - var instance = lastNonHostInstance(fiberHierarchy); - var hierarchy = createHierarchy(fiberHierarchy); - var props = getHostProps(instance); - var source = instance._debugSource; - var selectedIndex = fiberHierarchy.indexOf(instance); - return { - hierarchy: hierarchy, - props: props, - selectedIndex: selectedIndex, - source: source - }; - }; - - getInspectorDataForViewAtPoint = function( - findNodeHandle, - inspectedView, - locationX, - locationY, - callback - ) { - var closestInstance = null; - - if (inspectedView._internalInstanceHandle != null) { - // For Fabric we can look up the instance handle directly and measure it. - nativeFabricUIManager.findNodeAtPoint( - inspectedView._internalInstanceHandle.stateNode.node, + getInspectorDataForViewAtPoint = function ( + findNodeHandle, + inspectedView, locationX, locationY, - function(internalInstanceHandle) { - if (internalInstanceHandle == null) { - callback( - assign( - { - pointerY: locationY, - frame: { - left: 0, - top: 0, - width: 0, - height: 0 - } - }, - exports.getInspectorDataForInstance(closestInstance) - ) - ); - } + callback + ) { + var closestInstance = null; + + if (inspectedView._internalInstanceHandle != null) { + // For Fabric we can look up the instance handle directly and measure it. + nativeFabricUIManager.findNodeAtPoint( + inspectedView._internalInstanceHandle.stateNode.node, + locationX, + locationY, + function (internalInstanceHandle) { + if (internalInstanceHandle == null) { + callback( + assign( + { + pointerY: locationY, + frame: { + left: 0, + top: 0, + width: 0, + height: 0 + } + }, + exports.getInspectorDataForInstance(closestInstance) + ) + ); + } - closestInstance = - internalInstanceHandle.stateNode.canonical._internalInstanceHandle; // Note: this is deprecated and we want to remove it ASAP. Keeping it here for React DevTools compatibility for now. + closestInstance = + internalInstanceHandle.stateNode.canonical._internalInstanceHandle; // Note: this is deprecated and we want to remove it ASAP. Keeping it here for React DevTools compatibility for now. - var nativeViewTag = - internalInstanceHandle.stateNode.canonical._nativeTag; - nativeFabricUIManager.measure( - internalInstanceHandle.stateNode.node, - function(x, y, width, height, pageX, pageY) { + var nativeViewTag = + internalInstanceHandle.stateNode.canonical._nativeTag; + nativeFabricUIManager.measure( + internalInstanceHandle.stateNode.node, + function (x, y, width, height, pageX, pageY) { + var inspectorData = exports.getInspectorDataForInstance( + closestInstance + ); + callback( + assign({}, inspectorData, { + pointerY: locationY, + frame: { + left: pageX, + top: pageY, + width: width, + height: height + }, + touchedViewTag: nativeViewTag + }) + ); + } + ); + } + ); + } else if (inspectedView._internalFiberInstanceHandleDEV != null) { + // For Paper we fall back to the old strategy using the React tag. + ReactNativePrivateInterface.UIManager.findSubviewIn( + findNodeHandle(inspectedView), + [locationX, locationY], + function (nativeViewTag, left, top, width, height) { var inspectorData = exports.getInspectorDataForInstance( - closestInstance + getInstanceFromTag(nativeViewTag) ); callback( assign({}, inspectorData, { pointerY: locationY, frame: { - left: pageX, - top: pageY, + left: left, + top: top, width: width, height: height }, @@ -24127,293 +24169,268 @@ var getInspectorDataForViewAtPoint; ); } ); - } - ); - } else if (inspectedView._internalFiberInstanceHandleDEV != null) { - // For Paper we fall back to the old strategy using the React tag. - ReactNativePrivateInterface.UIManager.findSubviewIn( - findNodeHandle(inspectedView), - [locationX, locationY], - function(nativeViewTag, left, top, width, height) { - var inspectorData = exports.getInspectorDataForInstance( - getInstanceFromTag(nativeViewTag) - ); - callback( - assign({}, inspectorData, { - pointerY: locationY, - frame: { - left: left, - top: top, - width: width, - height: height - }, - touchedViewTag: nativeViewTag - }) + } else { + error( + "getInspectorDataForViewAtPoint expects to receive a host component" ); - } - ); - } else { - error( - "getInspectorDataForViewAtPoint expects to receive a host component" - ); - return; + return; + } + }; } - }; -} -var ReactCurrentOwner$3 = ReactSharedInternals.ReactCurrentOwner; + var ReactCurrentOwner$3 = ReactSharedInternals.ReactCurrentOwner; -function findHostInstance_DEPRECATED(componentOrHandle) { - { - var owner = ReactCurrentOwner$3.current; + function findHostInstance_DEPRECATED(componentOrHandle) { + { + var owner = ReactCurrentOwner$3.current; - if (owner !== null && owner.stateNode !== null) { - if (!owner.stateNode._warnedAboutRefsInRender) { - error( - "%s is accessing findNodeHandle inside its render(). " + - "render() should be a pure function of props and state. It should " + - "never access something that requires stale data from the previous " + - "render, such as refs. Move this logic to componentDidMount and " + - "componentDidUpdate instead.", - getComponentNameFromType(owner.type) || "A component" - ); + if (owner !== null && owner.stateNode !== null) { + if (!owner.stateNode._warnedAboutRefsInRender) { + error( + "%s is accessing findNodeHandle inside its render(). " + + "render() should be a pure function of props and state. It should " + + "never access something that requires stale data from the previous " + + "render, such as refs. Move this logic to componentDidMount and " + + "componentDidUpdate instead.", + getComponentNameFromType(owner.type) || "A component" + ); + } + + owner.stateNode._warnedAboutRefsInRender = true; + } } - owner.stateNode._warnedAboutRefsInRender = true; - } - } + if (componentOrHandle == null) { + return null; + } // $FlowIssue Flow has hardcoded values for React DOM that don't work with RN + + if (componentOrHandle._nativeTag) { + // $FlowIssue Flow has hardcoded values for React DOM that don't work with RN + return componentOrHandle; + } // $FlowIssue Flow has hardcoded values for React DOM that don't work with RN - if (componentOrHandle == null) { - return null; - } // $FlowIssue Flow has hardcoded values for React DOM that don't work with RN + if (componentOrHandle.canonical && componentOrHandle.canonical._nativeTag) { + // $FlowIssue Flow has hardcoded values for React DOM that don't work with RN + return componentOrHandle.canonical; + } - if (componentOrHandle._nativeTag) { - // $FlowIssue Flow has hardcoded values for React DOM that don't work with RN - return componentOrHandle; - } // $FlowIssue Flow has hardcoded values for React DOM that don't work with RN + var hostInstance; - if (componentOrHandle.canonical && componentOrHandle.canonical._nativeTag) { - // $FlowIssue Flow has hardcoded values for React DOM that don't work with RN - return componentOrHandle.canonical; - } + { + hostInstance = findHostInstanceWithWarning( + componentOrHandle, + "findHostInstance_DEPRECATED" + ); + } - var hostInstance; + if (hostInstance == null) { + return hostInstance; + } - { - hostInstance = findHostInstanceWithWarning( - componentOrHandle, - "findHostInstance_DEPRECATED" - ); - } + if (hostInstance.canonical) { + // Fabric + return hostInstance.canonical; + } // $FlowFixMe[incompatible-return] - if (hostInstance == null) { - return hostInstance; - } + return hostInstance; + } - if (hostInstance.canonical) { - // Fabric - return hostInstance.canonical; - } // $FlowFixMe[incompatible-return] + function findNodeHandle(componentOrHandle) { + { + var owner = ReactCurrentOwner$3.current; - return hostInstance; -} + if (owner !== null && owner.stateNode !== null) { + if (!owner.stateNode._warnedAboutRefsInRender) { + error( + "%s is accessing findNodeHandle inside its render(). " + + "render() should be a pure function of props and state. It should " + + "never access something that requires stale data from the previous " + + "render, such as refs. Move this logic to componentDidMount and " + + "componentDidUpdate instead.", + getComponentNameFromType(owner.type) || "A component" + ); + } -function findNodeHandle(componentOrHandle) { - { - var owner = ReactCurrentOwner$3.current; + owner.stateNode._warnedAboutRefsInRender = true; + } + } - if (owner !== null && owner.stateNode !== null) { - if (!owner.stateNode._warnedAboutRefsInRender) { - error( - "%s is accessing findNodeHandle inside its render(). " + - "render() should be a pure function of props and state. It should " + - "never access something that requires stale data from the previous " + - "render, such as refs. Move this logic to componentDidMount and " + - "componentDidUpdate instead.", - getComponentNameFromType(owner.type) || "A component" - ); + if (componentOrHandle == null) { + return null; } - owner.stateNode._warnedAboutRefsInRender = true; - } - } + if (typeof componentOrHandle === "number") { + // Already a node handle + return componentOrHandle; + } - if (componentOrHandle == null) { - return null; - } + if (componentOrHandle._nativeTag) { + return componentOrHandle._nativeTag; + } - if (typeof componentOrHandle === "number") { - // Already a node handle - return componentOrHandle; - } + if (componentOrHandle.canonical && componentOrHandle.canonical._nativeTag) { + return componentOrHandle.canonical._nativeTag; + } - if (componentOrHandle._nativeTag) { - return componentOrHandle._nativeTag; - } + var hostInstance; - if (componentOrHandle.canonical && componentOrHandle.canonical._nativeTag) { - return componentOrHandle.canonical._nativeTag; - } + { + hostInstance = findHostInstanceWithWarning( + componentOrHandle, + "findNodeHandle" + ); + } - var hostInstance; + if (hostInstance == null) { + return hostInstance; + } // TODO: the code is right but the types here are wrong. + // https://github.com/facebook/react/pull/12863 - { - hostInstance = findHostInstanceWithWarning( - componentOrHandle, - "findNodeHandle" - ); - } + if (hostInstance.canonical) { + // Fabric + return hostInstance.canonical._nativeTag; + } - if (hostInstance == null) { - return hostInstance; - } // TODO: the code is right but the types here are wrong. - // https://github.com/facebook/react/pull/12863 + return hostInstance._nativeTag; + } - if (hostInstance.canonical) { - // Fabric - return hostInstance.canonical._nativeTag; - } + function dispatchCommand(handle, command, args) { + if (handle._nativeTag == null) { + { + error( + "dispatchCommand was called with a ref that isn't a " + + "native component. Use React.forwardRef to get access to the underlying native component" + ); + } - return hostInstance._nativeTag; -} + return; + } -function dispatchCommand(handle, command, args) { - if (handle._nativeTag == null) { - { - error( - "dispatchCommand was called with a ref that isn't a " + - "native component. Use React.forwardRef to get access to the underlying native component" - ); + if (handle._internalInstanceHandle != null) { + var stateNode = handle._internalInstanceHandle.stateNode; + + if (stateNode != null) { + nativeFabricUIManager.dispatchCommand(stateNode.node, command, args); + } + } else { + ReactNativePrivateInterface.UIManager.dispatchViewManagerCommand( + handle._nativeTag, + command, + args + ); + } } - return; - } + function sendAccessibilityEvent(handle, eventType) { + if (handle._nativeTag == null) { + { + error( + "sendAccessibilityEvent was called with a ref that isn't a " + + "native component. Use React.forwardRef to get access to the underlying native component" + ); + } - if (handle._internalInstanceHandle != null) { - var stateNode = handle._internalInstanceHandle.stateNode; + return; + } - if (stateNode != null) { - nativeFabricUIManager.dispatchCommand(stateNode.node, command, args); - } - } else { - ReactNativePrivateInterface.UIManager.dispatchViewManagerCommand( - handle._nativeTag, - command, - args - ); - } -} + if (handle._internalInstanceHandle != null) { + var stateNode = handle._internalInstanceHandle.stateNode; -function sendAccessibilityEvent(handle, eventType) { - if (handle._nativeTag == null) { - { - error( - "sendAccessibilityEvent was called with a ref that isn't a " + - "native component. Use React.forwardRef to get access to the underlying native component" - ); + if (stateNode != null) { + nativeFabricUIManager.sendAccessibilityEvent(stateNode.node, eventType); + } + } else { + ReactNativePrivateInterface.legacySendAccessibilityEvent( + handle._nativeTag, + eventType + ); + } } - return; - } + function onRecoverableError(error$1) { + // TODO: Expose onRecoverableError option to userspace + // eslint-disable-next-line react-internal/no-production-logging, react-internal/warning-args + error(error$1); + } - if (handle._internalInstanceHandle != null) { - var stateNode = handle._internalInstanceHandle.stateNode; + function render(element, containerTag, callback, concurrentRoot) { + var root = roots.get(containerTag); - if (stateNode != null) { - nativeFabricUIManager.sendAccessibilityEvent(stateNode.node, eventType); - } - } else { - ReactNativePrivateInterface.legacySendAccessibilityEvent( - handle._nativeTag, - eventType - ); - } -} + if (!root) { + // TODO (bvaughn): If we decide to keep the wrapper component, + // We could create a wrapper for containerTag as well to reduce special casing. + root = createContainer( + containerTag, + concurrentRoot ? ConcurrentRoot : LegacyRoot, + null, + false, + null, + "", + onRecoverableError + ); + roots.set(containerTag, root); + } -function onRecoverableError(error$1) { - // TODO: Expose onRecoverableError option to userspace - // eslint-disable-next-line react-internal/no-production-logging, react-internal/warning-args - error(error$1); -} + updateContainer(element, root, null, callback); // $FlowIssue Flow has hardcoded values for React DOM that don't work with RN -function render(element, containerTag, callback, concurrentRoot) { - var root = roots.get(containerTag); - - if (!root) { - // TODO (bvaughn): If we decide to keep the wrapper component, - // We could create a wrapper for containerTag as well to reduce special casing. - root = createContainer( - containerTag, - concurrentRoot ? ConcurrentRoot : LegacyRoot, - null, - false, - null, - "", - onRecoverableError - ); - roots.set(containerTag, root); - } + return getPublicRootInstance(root); + } - updateContainer(element, root, null, callback); // $FlowIssue Flow has hardcoded values for React DOM that don't work with RN + function unmountComponentAtNode(containerTag) { + this.stopSurface(containerTag); + } - return getPublicRootInstance(root); -} + function stopSurface(containerTag) { + var root = roots.get(containerTag); -function unmountComponentAtNode(containerTag) { - this.stopSurface(containerTag); -} + if (root) { + // TODO: Is it safe to reset this now or should I wait since this unmount could be deferred? + updateContainer(null, root, null, function () { + roots.delete(containerTag); + }); + } + } -function stopSurface(containerTag) { - var root = roots.get(containerTag); + function createPortal$1(children, containerTag) { + var key = + arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; + return createPortal(children, containerTag, null, key); + } - if (root) { - // TODO: Is it safe to reset this now or should I wait since this unmount could be deferred? - updateContainer(null, root, null, function() { - roots.delete(containerTag); + setBatchingImplementation(batchedUpdates$1); + var roots = new Map(); + injectIntoDevTools({ + findFiberByHostInstance: getInstanceFromInstance, + bundleType: 1, + version: ReactVersion, + rendererPackageName: "react-native-renderer", + rendererConfig: { + getInspectorDataForViewTag: getInspectorDataForViewTag, + getInspectorDataForViewAtPoint: getInspectorDataForViewAtPoint.bind( + null, + findNodeHandle + ) + } }); - } -} -function createPortal$1(children, containerTag) { - var key = - arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; - return createPortal(children, containerTag, null, key); -} + exports.createPortal = createPortal$1; + exports.dispatchCommand = dispatchCommand; + exports.findHostInstance_DEPRECATED = findHostInstance_DEPRECATED; + exports.findNodeHandle = findNodeHandle; + exports.render = render; + exports.sendAccessibilityEvent = sendAccessibilityEvent; + exports.stopSurface = stopSurface; + exports.unmountComponentAtNode = unmountComponentAtNode; -setBatchingImplementation(batchedUpdates$1); -var roots = new Map(); -injectIntoDevTools({ - findFiberByHostInstance: getInstanceFromInstance, - bundleType: 1, - version: ReactVersion, - rendererPackageName: "react-native-renderer", - rendererConfig: { - getInspectorDataForViewTag: getInspectorDataForViewTag, - getInspectorDataForViewAtPoint: getInspectorDataForViewAtPoint.bind( - null, - findNodeHandle - ) - } -}); - -exports.createPortal = createPortal$1; -exports.dispatchCommand = dispatchCommand; -exports.findHostInstance_DEPRECATED = findHostInstance_DEPRECATED; -exports.findNodeHandle = findNodeHandle; -exports.render = render; -exports.sendAccessibilityEvent = sendAccessibilityEvent; -exports.stopSurface = stopSurface; -exports.unmountComponentAtNode = unmountComponentAtNode; - - /* 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()); -} + /* 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/node_modules/react-native/Libraries/Renderer/implementations/ReactFabric-prod.js b/node_modules/react-native/Libraries/Renderer/implementations/ReactFabric-prod.js index b85648d..2377069 100644 --- a/node_modules/react-native/Libraries/Renderer/implementations/ReactFabric-prod.js +++ b/node_modules/react-native/Libraries/Renderer/implementations/ReactFabric-prod.js @@ -12,7 +12,14 @@ */ "use strict"; +import defrost from '@d11/de-frost' + require("react-native/Libraries/ReactPrivate/ReactNativePrivateInitializeCore"); +var updatedComponents = []; +var updatedComponentForProfiler = null; +function insertUpdateComponents(componentName, flags, key) { + updatedComponents.push({ componentName, flags, key }); +} var ReactNativePrivateInterface = require("react-native/Libraries/ReactPrivate/ReactNativePrivateInterface"), React = require("react"), Scheduler = require("scheduler"); @@ -29,7 +36,7 @@ var hasError = !1, hasRethrowError = !1, rethrowError = null, reporter = { - onError: function(error) { + onError: function (error) { hasError = !0; caughtError = error; } @@ -110,39 +117,39 @@ function SyntheticEvent( ((targetInst = dispatchConfig[propName]) ? (this[propName] = targetInst(nativeEvent)) : "target" === propName - ? (this.target = nativeEventTarget) - : (this[propName] = nativeEvent[propName])); + ? (this.target = nativeEventTarget) + : (this[propName] = nativeEvent[propName])); this.isDefaultPrevented = (null != nativeEvent.defaultPrevented - ? nativeEvent.defaultPrevented - : !1 === nativeEvent.returnValue) + ? nativeEvent.defaultPrevented + : !1 === nativeEvent.returnValue) ? functionThatReturnsTrue : functionThatReturnsFalse; this.isPropagationStopped = functionThatReturnsFalse; return this; } assign(SyntheticEvent.prototype, { - preventDefault: function() { + preventDefault: function () { this.defaultPrevented = !0; var event = this.nativeEvent; event && (event.preventDefault ? event.preventDefault() : "unknown" !== typeof event.returnValue && (event.returnValue = !1), - (this.isDefaultPrevented = functionThatReturnsTrue)); + (this.isDefaultPrevented = functionThatReturnsTrue)); }, - stopPropagation: function() { + stopPropagation: function () { var event = this.nativeEvent; event && (event.stopPropagation ? event.stopPropagation() : "unknown" !== typeof event.cancelBubble && (event.cancelBubble = !0), - (this.isPropagationStopped = functionThatReturnsTrue)); + (this.isPropagationStopped = functionThatReturnsTrue)); }, - persist: function() { + persist: function () { this.isPersistent = functionThatReturnsTrue; }, isPersistent: functionThatReturnsFalse, - destructor: function() { + destructor: function () { var Interface = this.constructor.Interface, propName; for (propName in Interface) this[propName] = null; @@ -154,20 +161,20 @@ assign(SyntheticEvent.prototype, { SyntheticEvent.Interface = { type: null, target: null, - currentTarget: function() { + currentTarget: function () { return null; }, eventPhase: null, bubbles: null, cancelable: null, - timeStamp: function(event) { + timeStamp: function (event) { return event.timeStamp || Date.now(); }, defaultPrevented: null, isTrusted: null }; -SyntheticEvent.extend = function(Interface) { - function E() {} +SyntheticEvent.extend = function (Interface) { + function E() { } function Class() { return Super.apply(this, arguments); } @@ -210,7 +217,7 @@ function addEventPoolingTo(EventConstructor) { EventConstructor.release = releasePooledEvent; } var ResponderSyntheticEvent = SyntheticEvent.extend({ - touchHistory: function() { + touchHistory: function () { return null; } }); @@ -253,17 +260,17 @@ function recordTouchStart(touch) { (touchRecord.previousPageY = touch.pageY), (touchRecord.previousTimeStamp = timestampForTouch(touch))) : ((touchRecord = { - touchActive: !0, - startPageX: touch.pageX, - startPageY: touch.pageY, - startTimeStamp: timestampForTouch(touch), - currentPageX: touch.pageX, - currentPageY: touch.pageY, - currentTimeStamp: timestampForTouch(touch), - previousPageX: touch.pageX, - previousPageY: touch.pageY, - previousTimeStamp: timestampForTouch(touch) - }), + touchActive: !0, + startPageX: touch.pageX, + startPageY: touch.pageY, + startTimeStamp: timestampForTouch(touch), + currentPageX: touch.pageX, + currentPageY: touch.pageY, + currentTimeStamp: timestampForTouch(touch), + previousPageX: touch.pageX, + previousPageY: touch.pageY, + previousTimeStamp: timestampForTouch(touch) + }), (touchBank[identifier] = touchRecord)); touchHistory.mostRecentTimeStamp = timestampForTouch(touch); } @@ -271,32 +278,32 @@ function recordTouchMove(touch) { var touchRecord = touchBank[getTouchIdentifier(touch)]; touchRecord && ((touchRecord.touchActive = !0), - (touchRecord.previousPageX = touchRecord.currentPageX), - (touchRecord.previousPageY = touchRecord.currentPageY), - (touchRecord.previousTimeStamp = touchRecord.currentTimeStamp), - (touchRecord.currentPageX = touch.pageX), - (touchRecord.currentPageY = touch.pageY), - (touchRecord.currentTimeStamp = timestampForTouch(touch)), - (touchHistory.mostRecentTimeStamp = timestampForTouch(touch))); + (touchRecord.previousPageX = touchRecord.currentPageX), + (touchRecord.previousPageY = touchRecord.currentPageY), + (touchRecord.previousTimeStamp = touchRecord.currentTimeStamp), + (touchRecord.currentPageX = touch.pageX), + (touchRecord.currentPageY = touch.pageY), + (touchRecord.currentTimeStamp = timestampForTouch(touch)), + (touchHistory.mostRecentTimeStamp = timestampForTouch(touch))); } function recordTouchEnd(touch) { var touchRecord = touchBank[getTouchIdentifier(touch)]; touchRecord && ((touchRecord.touchActive = !1), - (touchRecord.previousPageX = touchRecord.currentPageX), - (touchRecord.previousPageY = touchRecord.currentPageY), - (touchRecord.previousTimeStamp = touchRecord.currentTimeStamp), - (touchRecord.currentPageX = touch.pageX), - (touchRecord.currentPageY = touch.pageY), - (touchRecord.currentTimeStamp = timestampForTouch(touch)), - (touchHistory.mostRecentTimeStamp = timestampForTouch(touch))); + (touchRecord.previousPageX = touchRecord.currentPageX), + (touchRecord.previousPageY = touchRecord.currentPageY), + (touchRecord.previousTimeStamp = touchRecord.currentTimeStamp), + (touchRecord.currentPageX = touch.pageX), + (touchRecord.currentPageY = touch.pageY), + (touchRecord.currentTimeStamp = timestampForTouch(touch)), + (touchHistory.mostRecentTimeStamp = timestampForTouch(touch))); } var instrumentationCallback, ResponderTouchHistoryStore = { - instrument: function(callback) { + instrument: function (callback) { instrumentationCallback = callback; }, - recordTouchTrack: function(topLevelType, nativeEvent) { + recordTouchTrack: function (topLevelType, nativeEvent) { null != instrumentationCallback && instrumentationCallback(topLevelType, nativeEvent); if (isMoveish(topLevelType)) @@ -305,16 +312,16 @@ var instrumentationCallback, nativeEvent.changedTouches.forEach(recordTouchStart), (touchHistory.numberActiveTouches = nativeEvent.touches.length), 1 === touchHistory.numberActiveTouches && - (touchHistory.indexOfSingleActiveTouch = - nativeEvent.touches[0].identifier); + (touchHistory.indexOfSingleActiveTouch = + nativeEvent.touches[0].identifier); else if ( "topTouchEnd" === topLevelType || "topTouchCancel" === topLevelType ) if ( (nativeEvent.changedTouches.forEach(recordTouchEnd), - (touchHistory.numberActiveTouches = nativeEvent.touches.length), - 1 === touchHistory.numberActiveTouches) + (touchHistory.numberActiveTouches = nativeEvent.touches.length), + 1 === touchHistory.numberActiveTouches) ) for ( topLevelType = 0; @@ -323,7 +330,7 @@ var instrumentationCallback, ) if ( ((nativeEvent = touchBank[topLevelType]), - null != nativeEvent && nativeEvent.touchActive) + null != nativeEvent && nativeEvent.touchActive) ) { touchHistory.indexOfSingleActiveTouch = topLevelType; break; @@ -339,10 +346,10 @@ function accumulate(current, next) { return null == current ? next : isArrayImpl(current) - ? current.concat(next) - : isArrayImpl(next) - ? [current].concat(next) - : [current, next]; + ? current.concat(next) + : isArrayImpl(next) + ? [current].concat(next) + : [current, next]; } function accumulateInto(current, next) { if (null == next) @@ -434,8 +441,8 @@ function getParent(inst) { return inst ? inst : null; } function traverseTwoPhase(inst, fn, arg) { - for (var path = []; inst; ) path.push(inst), (inst = getParent(inst)); - for (inst = path.length; 0 < inst--; ) fn(path[inst], "captured", arg); + for (var path = []; inst;) path.push(inst), (inst = getParent(inst)); + for (inst = path.length; 0 < inst--;) fn(path[inst], "captured", arg); for (inst = 0; inst < path.length; inst++) fn(path[inst], "bubbled", arg); } function getListener(inst, registrationName) { @@ -446,10 +453,10 @@ function getListener(inst, registrationName) { if ((inst = inst[registrationName]) && "function" !== typeof inst) throw Error( "Expected `" + - registrationName + - "` listener to be a function, instead got a value of `" + - typeof inst + - "` type." + registrationName + + "` listener to be a function, instead got a value of `" + + typeof inst + + "` type." ); return inst; } @@ -479,10 +486,10 @@ function accumulateDirectDispatchesSingle(event) { event._dispatchListeners, listener )), - (event._dispatchInstances = accumulateInto( - event._dispatchInstances, - inst - ))); + (event._dispatchInstances = accumulateInto( + event._dispatchInstances, + inst + ))); } } } @@ -499,123 +506,123 @@ function accumulateTwoPhaseDispatchesSingle(event) { traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event); } var ResponderEventPlugin = { - _getResponder: function() { - return responderInst; - }, - eventTypes: eventTypes, - extractEvents: function( - topLevelType, - targetInst, - nativeEvent, - nativeEventTarget + _getResponder: function () { + return responderInst; + }, + eventTypes: eventTypes, + extractEvents: function ( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget + ) { + if (isStartish(topLevelType)) trackedTouchCount += 1; + else if ( + "topTouchEnd" === topLevelType || + "topTouchCancel" === topLevelType + ) + if (0 <= trackedTouchCount) --trackedTouchCount; + else return null; + ResponderTouchHistoryStore.recordTouchTrack(topLevelType, nativeEvent); + if ( + targetInst && + (("topScroll" === topLevelType && !nativeEvent.responderIgnoreScroll) || + (0 < trackedTouchCount && "topSelectionChange" === topLevelType) || + isStartish(topLevelType) || + isMoveish(topLevelType)) ) { - if (isStartish(topLevelType)) trackedTouchCount += 1; - else if ( - "topTouchEnd" === topLevelType || - "topTouchCancel" === topLevelType - ) - if (0 <= trackedTouchCount) --trackedTouchCount; - else return null; - ResponderTouchHistoryStore.recordTouchTrack(topLevelType, nativeEvent); - if ( - targetInst && - (("topScroll" === topLevelType && !nativeEvent.responderIgnoreScroll) || - (0 < trackedTouchCount && "topSelectionChange" === topLevelType) || - isStartish(topLevelType) || - isMoveish(topLevelType)) - ) { - var shouldSetEventType = isStartish(topLevelType) - ? eventTypes.startShouldSetResponder - : isMoveish(topLevelType) + var shouldSetEventType = isStartish(topLevelType) + ? eventTypes.startShouldSetResponder + : isMoveish(topLevelType) ? eventTypes.moveShouldSetResponder : "topSelectionChange" === topLevelType - ? eventTypes.selectionChangeShouldSetResponder - : eventTypes.scrollShouldSetResponder; - if (responderInst) - b: { - var JSCompiler_temp = responderInst; - for ( - var depthA = 0, tempA = JSCompiler_temp; - tempA; - tempA = getParent(tempA) + ? eventTypes.selectionChangeShouldSetResponder + : eventTypes.scrollShouldSetResponder; + if (responderInst) + b: { + var JSCompiler_temp = responderInst; + for ( + var depthA = 0, tempA = JSCompiler_temp; + tempA; + tempA = getParent(tempA) + ) + depthA++; + tempA = 0; + for (var tempB = targetInst; tempB; tempB = getParent(tempB)) + tempA++; + for (; 0 < depthA - tempA;) + (JSCompiler_temp = getParent(JSCompiler_temp)), depthA--; + for (; 0 < tempA - depthA;) + (targetInst = getParent(targetInst)), tempA--; + for (; depthA--;) { + if ( + JSCompiler_temp === targetInst || + JSCompiler_temp === targetInst.alternate ) - depthA++; - tempA = 0; - for (var tempB = targetInst; tempB; tempB = getParent(tempB)) - tempA++; - for (; 0 < depthA - tempA; ) - (JSCompiler_temp = getParent(JSCompiler_temp)), depthA--; - for (; 0 < tempA - depthA; ) - (targetInst = getParent(targetInst)), tempA--; - for (; depthA--; ) { - if ( - JSCompiler_temp === targetInst || - JSCompiler_temp === targetInst.alternate - ) - break b; - JSCompiler_temp = getParent(JSCompiler_temp); - targetInst = getParent(targetInst); - } - JSCompiler_temp = null; + break b; + JSCompiler_temp = getParent(JSCompiler_temp); + targetInst = getParent(targetInst); } - else JSCompiler_temp = targetInst; - targetInst = JSCompiler_temp; - JSCompiler_temp = targetInst === responderInst; - shouldSetEventType = ResponderSyntheticEvent.getPooled( + JSCompiler_temp = null; + } + else JSCompiler_temp = targetInst; + targetInst = JSCompiler_temp; + JSCompiler_temp = targetInst === responderInst; + shouldSetEventType = ResponderSyntheticEvent.getPooled( + shouldSetEventType, + targetInst, + nativeEvent, + nativeEventTarget + ); + shouldSetEventType.touchHistory = + ResponderTouchHistoryStore.touchHistory; + JSCompiler_temp + ? forEachAccumulated( shouldSetEventType, - targetInst, - nativeEvent, - nativeEventTarget + accumulateTwoPhaseDispatchesSingleSkipTarget + ) + : forEachAccumulated( + shouldSetEventType, + accumulateTwoPhaseDispatchesSingle ); - shouldSetEventType.touchHistory = - ResponderTouchHistoryStore.touchHistory; - JSCompiler_temp - ? forEachAccumulated( - shouldSetEventType, - accumulateTwoPhaseDispatchesSingleSkipTarget - ) - : forEachAccumulated( - shouldSetEventType, - accumulateTwoPhaseDispatchesSingle - ); - b: { - JSCompiler_temp = shouldSetEventType._dispatchListeners; - targetInst = shouldSetEventType._dispatchInstances; - if (isArrayImpl(JSCompiler_temp)) - for ( - depthA = 0; - depthA < JSCompiler_temp.length && - !shouldSetEventType.isPropagationStopped(); - depthA++ + b: { + JSCompiler_temp = shouldSetEventType._dispatchListeners; + targetInst = shouldSetEventType._dispatchInstances; + if (isArrayImpl(JSCompiler_temp)) + for ( + depthA = 0; + depthA < JSCompiler_temp.length && + !shouldSetEventType.isPropagationStopped(); + depthA++ + ) { + if ( + JSCompiler_temp[depthA](shouldSetEventType, targetInst[depthA]) ) { - if ( - JSCompiler_temp[depthA](shouldSetEventType, targetInst[depthA]) - ) { - JSCompiler_temp = targetInst[depthA]; - break b; - } + JSCompiler_temp = targetInst[depthA]; + break b; } - else if ( - JSCompiler_temp && - JSCompiler_temp(shouldSetEventType, targetInst) - ) { - JSCompiler_temp = targetInst; - break b; } - JSCompiler_temp = null; + else if ( + JSCompiler_temp && + JSCompiler_temp(shouldSetEventType, targetInst) + ) { + JSCompiler_temp = targetInst; + break b; } - shouldSetEventType._dispatchInstances = null; - shouldSetEventType._dispatchListeners = null; - shouldSetEventType.isPersistent() || - shouldSetEventType.constructor.release(shouldSetEventType); - if (JSCompiler_temp && JSCompiler_temp !== responderInst) - if ( - ((shouldSetEventType = ResponderSyntheticEvent.getPooled( - eventTypes.responderGrant, - JSCompiler_temp, - nativeEvent, - nativeEventTarget - )), + JSCompiler_temp = null; + } + shouldSetEventType._dispatchInstances = null; + shouldSetEventType._dispatchListeners = null; + shouldSetEventType.isPersistent() || + shouldSetEventType.constructor.release(shouldSetEventType); + if (JSCompiler_temp && JSCompiler_temp !== responderInst) + if ( + ((shouldSetEventType = ResponderSyntheticEvent.getPooled( + eventTypes.responderGrant, + JSCompiler_temp, + nativeEvent, + nativeEventTarget + )), (shouldSetEventType.touchHistory = ResponderTouchHistoryStore.touchHistory), forEachAccumulated( @@ -624,159 +631,159 @@ var ResponderEventPlugin = { ), (targetInst = !0 === executeDirectDispatch(shouldSetEventType)), responderInst) - ) - if ( - ((depthA = ResponderSyntheticEvent.getPooled( - eventTypes.responderTerminationRequest, - responderInst, - nativeEvent, - nativeEventTarget - )), + ) + if ( + ((depthA = ResponderSyntheticEvent.getPooled( + eventTypes.responderTerminationRequest, + responderInst, + nativeEvent, + nativeEventTarget + )), (depthA.touchHistory = ResponderTouchHistoryStore.touchHistory), forEachAccumulated(depthA, accumulateDirectDispatchesSingle), (tempA = !depthA._dispatchListeners || executeDirectDispatch(depthA)), depthA.isPersistent() || depthA.constructor.release(depthA), tempA) - ) { - depthA = ResponderSyntheticEvent.getPooled( - eventTypes.responderTerminate, - responderInst, - nativeEvent, - nativeEventTarget - ); - depthA.touchHistory = ResponderTouchHistoryStore.touchHistory; - forEachAccumulated(depthA, accumulateDirectDispatchesSingle); - var JSCompiler_temp$jscomp$0 = accumulate( - JSCompiler_temp$jscomp$0, - [shouldSetEventType, depthA] - ); - changeResponder(JSCompiler_temp, targetInst); - } else - (shouldSetEventType = ResponderSyntheticEvent.getPooled( - eventTypes.responderReject, - JSCompiler_temp, - nativeEvent, - nativeEventTarget - )), - (shouldSetEventType.touchHistory = - ResponderTouchHistoryStore.touchHistory), - forEachAccumulated( - shouldSetEventType, - accumulateDirectDispatchesSingle - ), - (JSCompiler_temp$jscomp$0 = accumulate( - JSCompiler_temp$jscomp$0, - shouldSetEventType - )); - else - (JSCompiler_temp$jscomp$0 = accumulate( + ) { + depthA = ResponderSyntheticEvent.getPooled( + eventTypes.responderTerminate, + responderInst, + nativeEvent, + nativeEventTarget + ); + depthA.touchHistory = ResponderTouchHistoryStore.touchHistory; + forEachAccumulated(depthA, accumulateDirectDispatchesSingle); + var JSCompiler_temp$jscomp$0 = accumulate( JSCompiler_temp$jscomp$0, - shouldSetEventType + [shouldSetEventType, depthA] + ); + changeResponder(JSCompiler_temp, targetInst); + } else + (shouldSetEventType = ResponderSyntheticEvent.getPooled( + eventTypes.responderReject, + JSCompiler_temp, + nativeEvent, + nativeEventTarget )), - changeResponder(JSCompiler_temp, targetInst); - else JSCompiler_temp$jscomp$0 = null; - } else JSCompiler_temp$jscomp$0 = null; - shouldSetEventType = responderInst && isStartish(topLevelType); - JSCompiler_temp = responderInst && isMoveish(topLevelType); - targetInst = - responderInst && - ("topTouchEnd" === topLevelType || "topTouchCancel" === topLevelType); - if ( - (shouldSetEventType = shouldSetEventType - ? eventTypes.responderStart - : JSCompiler_temp - ? eventTypes.responderMove - : targetInst - ? eventTypes.responderEnd - : null) - ) - (shouldSetEventType = ResponderSyntheticEvent.getPooled( - shouldSetEventType, - responderInst, - nativeEvent, - nativeEventTarget - )), - (shouldSetEventType.touchHistory = - ResponderTouchHistoryStore.touchHistory), - forEachAccumulated( - shouldSetEventType, - accumulateDirectDispatchesSingle - ), + (shouldSetEventType.touchHistory = + ResponderTouchHistoryStore.touchHistory), + forEachAccumulated( + shouldSetEventType, + accumulateDirectDispatchesSingle + ), + (JSCompiler_temp$jscomp$0 = accumulate( + JSCompiler_temp$jscomp$0, + shouldSetEventType + )); + else (JSCompiler_temp$jscomp$0 = accumulate( JSCompiler_temp$jscomp$0, shouldSetEventType - )); - shouldSetEventType = responderInst && "topTouchCancel" === topLevelType; - if ( - (topLevelType = - responderInst && - !shouldSetEventType && - ("topTouchEnd" === topLevelType || "topTouchCancel" === topLevelType)) - ) - a: { - if ((topLevelType = nativeEvent.touches) && 0 !== topLevelType.length) - for ( - JSCompiler_temp = 0; - JSCompiler_temp < topLevelType.length; - JSCompiler_temp++ - ) - if ( - ((targetInst = topLevelType[JSCompiler_temp].target), + )), + changeResponder(JSCompiler_temp, targetInst); + else JSCompiler_temp$jscomp$0 = null; + } else JSCompiler_temp$jscomp$0 = null; + shouldSetEventType = responderInst && isStartish(topLevelType); + JSCompiler_temp = responderInst && isMoveish(topLevelType); + targetInst = + responderInst && + ("topTouchEnd" === topLevelType || "topTouchCancel" === topLevelType); + if ( + (shouldSetEventType = shouldSetEventType + ? eventTypes.responderStart + : JSCompiler_temp + ? eventTypes.responderMove + : targetInst + ? eventTypes.responderEnd + : null) + ) + (shouldSetEventType = ResponderSyntheticEvent.getPooled( + shouldSetEventType, + responderInst, + nativeEvent, + nativeEventTarget + )), + (shouldSetEventType.touchHistory = + ResponderTouchHistoryStore.touchHistory), + forEachAccumulated( + shouldSetEventType, + accumulateDirectDispatchesSingle + ), + (JSCompiler_temp$jscomp$0 = accumulate( + JSCompiler_temp$jscomp$0, + shouldSetEventType + )); + shouldSetEventType = responderInst && "topTouchCancel" === topLevelType; + if ( + (topLevelType = + responderInst && + !shouldSetEventType && + ("topTouchEnd" === topLevelType || "topTouchCancel" === topLevelType)) + ) + a: { + if ((topLevelType = nativeEvent.touches) && 0 !== topLevelType.length) + for ( + JSCompiler_temp = 0; + JSCompiler_temp < topLevelType.length; + JSCompiler_temp++ + ) + if ( + ((targetInst = topLevelType[JSCompiler_temp].target), null !== targetInst && - void 0 !== targetInst && - 0 !== targetInst) - ) { - depthA = getInstanceFromNode(targetInst); - b: { - for (targetInst = responderInst; depthA; ) { - if ( - targetInst === depthA || - targetInst === depthA.alternate - ) { - targetInst = !0; - break b; - } - depthA = getParent(depthA); + void 0 !== targetInst && + 0 !== targetInst) + ) { + depthA = getInstanceFromNode(targetInst); + b: { + for (targetInst = responderInst; depthA;) { + if ( + targetInst === depthA || + targetInst === depthA.alternate + ) { + targetInst = !0; + break b; } - targetInst = !1; - } - if (targetInst) { - topLevelType = !1; - break a; + depthA = getParent(depthA); } + targetInst = !1; } - topLevelType = !0; - } - if ( - (topLevelType = shouldSetEventType - ? eventTypes.responderTerminate - : topLevelType + if (targetInst) { + topLevelType = !1; + break a; + } + } + topLevelType = !0; + } + if ( + (topLevelType = shouldSetEventType + ? eventTypes.responderTerminate + : topLevelType ? eventTypes.responderRelease : null) - ) - (nativeEvent = ResponderSyntheticEvent.getPooled( - topLevelType, - responderInst, - nativeEvent, - nativeEventTarget + ) + (nativeEvent = ResponderSyntheticEvent.getPooled( + topLevelType, + responderInst, + nativeEvent, + nativeEventTarget + )), + (nativeEvent.touchHistory = ResponderTouchHistoryStore.touchHistory), + forEachAccumulated(nativeEvent, accumulateDirectDispatchesSingle), + (JSCompiler_temp$jscomp$0 = accumulate( + JSCompiler_temp$jscomp$0, + nativeEvent )), - (nativeEvent.touchHistory = ResponderTouchHistoryStore.touchHistory), - forEachAccumulated(nativeEvent, accumulateDirectDispatchesSingle), - (JSCompiler_temp$jscomp$0 = accumulate( - JSCompiler_temp$jscomp$0, - nativeEvent - )), - changeResponder(null); - return JSCompiler_temp$jscomp$0; - }, - GlobalResponderHandler: null, - injection: { - injectGlobalResponderHandler: function(GlobalResponderHandler) { - ResponderEventPlugin.GlobalResponderHandler = GlobalResponderHandler; - } - } + changeResponder(null); + return JSCompiler_temp$jscomp$0; }, + GlobalResponderHandler: null, + injection: { + injectGlobalResponderHandler: function (GlobalResponderHandler) { + ResponderEventPlugin.GlobalResponderHandler = GlobalResponderHandler; + } + } +}, eventPluginOrder = null, namesToPlugins = {}; function recomputePluginOrdering() { @@ -787,13 +794,13 @@ function recomputePluginOrdering() { if (-1 >= pluginIndex) throw Error( "EventPluginRegistry: Cannot inject event plugins that do not exist in the plugin ordering, `" + - (pluginName + "`.") + (pluginName + "`.") ); if (!plugins[pluginIndex]) { if (!pluginModule.extractEvents) throw Error( "EventPluginRegistry: Event plugins must implement an `extractEvents` method, but `" + - (pluginName + "` does not.") + (pluginName + "` does not.") ); plugins[pluginIndex] = pluginModule; pluginIndex = pluginModule.eventTypes; @@ -804,7 +811,7 @@ function recomputePluginOrdering() { if (eventNameDispatchConfigs.hasOwnProperty(eventName$jscomp$0)) throw Error( "EventPluginRegistry: More than one plugin attempted to publish the same event name, `" + - (eventName$jscomp$0 + "`.") + (eventName$jscomp$0 + "`.") ); eventNameDispatchConfigs[eventName$jscomp$0] = dispatchConfig; var phasedRegistrationNames = dispatchConfig.phasedRegistrationNames; @@ -822,19 +829,19 @@ function recomputePluginOrdering() { } else dispatchConfig.registrationName ? (publishRegistrationName( - dispatchConfig.registrationName, - pluginModule, - eventName$jscomp$0 - ), + dispatchConfig.registrationName, + pluginModule, + eventName$jscomp$0 + ), (JSCompiler_inline_result = !0)) : (JSCompiler_inline_result = !1); if (!JSCompiler_inline_result) throw Error( "EventPluginRegistry: Failed to publish event `" + - eventName + - "` for plugin `" + - pluginName + - "`." + eventName + + "` for plugin `" + + pluginName + + "`." ); } } @@ -844,7 +851,7 @@ function publishRegistrationName(registrationName, pluginModule) { if (registrationNameModules[registrationName]) throw Error( "EventPluginRegistry: More than one plugin attempted to publish the same registration name, `" + - (registrationName + "`.") + (registrationName + "`.") ); registrationNameModules[registrationName] = pluginModule; } @@ -864,10 +871,10 @@ function getListeners( if ((inst = inst[registrationName]) && "function" !== typeof inst) throw Error( "Expected `" + - registrationName + - "` listener to be a function, instead got a value of `" + - typeof inst + - "` type." + registrationName + + "` listener to be a function, instead got a value of `" + + typeof inst + + "` type." ); if ( !( @@ -885,16 +892,16 @@ function getListeners( : "rn:" + registrationName; stateNode.canonical._eventListeners[mangledImperativeRegistrationName] && 0 < - stateNode.canonical._eventListeners[mangledImperativeRegistrationName] - .length && + stateNode.canonical._eventListeners[mangledImperativeRegistrationName] + .length && stateNode.canonical._eventListeners[ mangledImperativeRegistrationName - ].forEach(function(listenerObj) { + ].forEach(function (listenerObj) { if ( (null != listenerObj.options.capture && listenerObj.options.capture) === requestedPhaseIsCapture ) { - var listenerFnWrapper = function(syntheticEvent) { + var listenerFnWrapper = function (syntheticEvent) { var eventInst = new ReactNativePrivateInterface.CustomEvent( mangledImperativeRegistrationName, { detail: syntheticEvent.nativeEvent } @@ -903,8 +910,8 @@ function getListeners( eventInst.setSyntheticEvent(syntheticEvent); for ( var _len = arguments.length, - args = Array(1 < _len ? _len - 1 : 0), - _key = 1; + args = Array(1 < _len ? _len - 1 : 0), + _key = 1; _key < _len; _key++ ) @@ -912,28 +919,28 @@ function getListeners( listenerObj.listener.apply(listenerObj, [eventInst].concat(args)); }; listenerObj.options.once - ? listeners.push(function() { - stateNode.canonical.removeEventListener_unstable( - mangledImperativeRegistrationName, - listenerObj.listener, - listenerObj.capture - ); - listenerObj.invalidated || - ((listenerObj.invalidated = !0), + ? listeners.push(function () { + stateNode.canonical.removeEventListener_unstable( + mangledImperativeRegistrationName, + listenerObj.listener, + listenerObj.capture + ); + listenerObj.invalidated || + ((listenerObj.invalidated = !0), listenerObj.listener.apply(listenerObj, arguments)); - }) + }) : listeners.push(listenerFnWrapper); } }); return 0 === listeners.length ? null : 1 === listeners.length - ? listeners[0] - : listeners; + ? listeners[0] + : listeners; } var customBubblingEventTypes = - ReactNativePrivateInterface.ReactNativeViewConfigRegistry - .customBubblingEventTypes, + ReactNativePrivateInterface.ReactNativeViewConfigRegistry + .customBubblingEventTypes, customDirectEventTypes = ReactNativePrivateInterface.ReactNativeViewConfigRegistry .customDirectEventTypes; @@ -949,15 +956,15 @@ function accumulateListenersAndInstances(inst, event, listeners) { event._dispatchListeners, listeners )), - null == event._dispatchInstances && 1 === listenersLength) + null == event._dispatchInstances && 1 === listenersLength) ) event._dispatchInstances = inst; else for ( event._dispatchInstances = event._dispatchInstances || [], - isArrayImpl(event._dispatchInstances) || - (event._dispatchInstances = [event._dispatchInstances]), - listeners = 0; + isArrayImpl(event._dispatchInstances) || + (event._dispatchInstances = [event._dispatchInstances]), + listeners = 0; listeners < listenersLength; listeners++ ) @@ -973,13 +980,13 @@ function accumulateDirectionalDispatches$1(inst, phase, event) { accumulateListenersAndInstances(inst, event, phase); } function traverseTwoPhase$1(inst, fn, arg, skipBubbling) { - for (var path = []; inst; ) { + for (var path = []; inst;) { path.push(inst); do inst = inst.return; while (inst && 5 !== inst.tag); inst = inst ? inst : null; } - for (inst = path.length; 0 < inst--; ) fn(path[inst], "captured", arg); + for (inst = path.length; 0 < inst--;) fn(path[inst], "captured", arg); if (skipBubbling) fn(path[0], "bubbled", arg); else for (inst = 0; inst < path.length; inst++) fn(path[inst], "bubbled", arg); @@ -1018,51 +1025,51 @@ eventPluginOrder = Array.prototype.slice.call([ ]); recomputePluginOrdering(); var injectedNamesToPlugins$jscomp$inline_223 = { - ResponderEventPlugin: ResponderEventPlugin, - ReactNativeBridgeEventPlugin: { - eventTypes: {}, - extractEvents: function( - topLevelType, + ResponderEventPlugin: ResponderEventPlugin, + ReactNativeBridgeEventPlugin: { + eventTypes: {}, + extractEvents: function ( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget + ) { + if (null == targetInst) return null; + var bubbleDispatchConfig = customBubblingEventTypes[topLevelType], + directDispatchConfig = customDirectEventTypes[topLevelType]; + if (!bubbleDispatchConfig && !directDispatchConfig) + throw Error( + 'Unsupported top level event type "' + topLevelType + '" dispatched' + ); + topLevelType = SyntheticEvent.getPooled( + bubbleDispatchConfig || directDispatchConfig, targetInst, nativeEvent, nativeEventTarget - ) { - if (null == targetInst) return null; - var bubbleDispatchConfig = customBubblingEventTypes[topLevelType], - directDispatchConfig = customDirectEventTypes[topLevelType]; - if (!bubbleDispatchConfig && !directDispatchConfig) - throw Error( - 'Unsupported top level event type "' + topLevelType + '" dispatched' - ); - topLevelType = SyntheticEvent.getPooled( - bubbleDispatchConfig || directDispatchConfig, - targetInst, - nativeEvent, - nativeEventTarget - ); - if (bubbleDispatchConfig) - null != topLevelType && + ); + if (bubbleDispatchConfig) + null != topLevelType && null != topLevelType.dispatchConfig.phasedRegistrationNames && topLevelType.dispatchConfig.phasedRegistrationNames.skipBubbling - ? topLevelType && - topLevelType.dispatchConfig.phasedRegistrationNames && - traverseTwoPhase$1( - topLevelType._targetInst, - accumulateDirectionalDispatches$1, - topLevelType, - !0 - ) - : forEachAccumulated( - topLevelType, - accumulateTwoPhaseDispatchesSingle$1 - ); - else if (directDispatchConfig) - forEachAccumulated(topLevelType, accumulateDirectDispatchesSingle$1); - else return null; - return topLevelType; - } + ? topLevelType && + topLevelType.dispatchConfig.phasedRegistrationNames && + traverseTwoPhase$1( + topLevelType._targetInst, + accumulateDirectionalDispatches$1, + topLevelType, + !0 + ) + : forEachAccumulated( + topLevelType, + accumulateTwoPhaseDispatchesSingle$1 + ); + else if (directDispatchConfig) + forEachAccumulated(topLevelType, accumulateDirectDispatchesSingle$1); + else return null; + return topLevelType; } - }, + } +}, isOrderingDirty$jscomp$inline_224 = !1, pluginName$jscomp$inline_225; for (pluginName$jscomp$inline_225 in injectedNamesToPlugins$jscomp$inline_223) @@ -1076,12 +1083,12 @@ for (pluginName$jscomp$inline_225 in injectedNamesToPlugins$jscomp$inline_223) if ( !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_225) || namesToPlugins[pluginName$jscomp$inline_225] !== - pluginModule$jscomp$inline_226 + pluginModule$jscomp$inline_226 ) { if (namesToPlugins[pluginName$jscomp$inline_225]) throw Error( "EventPluginRegistry: Cannot inject two different event plugins using the same name, `" + - (pluginName$jscomp$inline_225 + "`.") + (pluginName$jscomp$inline_225 + "`.") ); namesToPlugins[ pluginName$jscomp$inline_225 @@ -1093,42 +1100,42 @@ isOrderingDirty$jscomp$inline_224 && recomputePluginOrdering(); function getInstanceFromInstance(instanceHandle) { return instanceHandle; } -getFiberCurrentPropsFromNode = function(inst) { +getFiberCurrentPropsFromNode = function (inst) { return inst.canonical.currentProps; }; getInstanceFromNode = getInstanceFromInstance; -getNodeFromInstance = function(inst) { +getNodeFromInstance = function (inst) { inst = inst.stateNode.canonical; if (!inst._nativeTag) throw Error("All native instances should have a tag."); return inst; }; ResponderEventPlugin.injection.injectGlobalResponderHandler({ - onChange: function(from, to, blockNativeResponder) { + onChange: function (from, to, blockNativeResponder) { var fromOrTo = from || to; (fromOrTo = fromOrTo && fromOrTo.stateNode) && - fromOrTo.canonical._internalInstanceHandle + fromOrTo.canonical._internalInstanceHandle ? (from && - nativeFabricUIManager.setIsJSResponder( - from.stateNode.node, - !1, - blockNativeResponder || !1 - ), + nativeFabricUIManager.setIsJSResponder( + from.stateNode.node, + !1, + blockNativeResponder || !1 + ), to && - nativeFabricUIManager.setIsJSResponder( - to.stateNode.node, - !0, - blockNativeResponder || !1 - )) + nativeFabricUIManager.setIsJSResponder( + to.stateNode.node, + !0, + blockNativeResponder || !1 + )) : null !== to - ? ReactNativePrivateInterface.UIManager.setJSResponder( + ? ReactNativePrivateInterface.UIManager.setJSResponder( to.stateNode.canonical._nativeTag, blockNativeResponder ) - : ReactNativePrivateInterface.UIManager.clearJSResponder(); + : ReactNativePrivateInterface.UIManager.clearJSResponder(); } }); var ReactSharedInternals = - React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, + React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, REACT_ELEMENT_TYPE = Symbol.for("react.element"), REACT_PORTAL_TYPE = Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"), @@ -1184,7 +1191,7 @@ function getComponentNameFromType(type) { type = type.displayName; type || ((type = innerType.displayName || innerType.name || ""), - (type = "" !== type ? "ForwardRef(" + type + ")" : "ForwardRef")); + (type = "" !== type ? "ForwardRef(" + type + ")" : "ForwardRef")); return type; case REACT_MEMO_TYPE: return ( @@ -1198,7 +1205,7 @@ function getComponentNameFromType(type) { type = type._init; try { return getComponentNameFromType(type(innerType)); - } catch (x) {} + } catch (x) { } } return null; } @@ -1218,7 +1225,7 @@ function getComponentNameFromFiber(fiber) { (fiber = type.render), (fiber = fiber.displayName || fiber.name || ""), type.displayName || - ("" !== fiber ? "ForwardRef(" + fiber + ")" : "ForwardRef") + ("" !== fiber ? "ForwardRef(" + fiber + ")" : "ForwardRef") ); case 7: return "Fragment"; @@ -1261,7 +1268,7 @@ function getComponentNameFromFiber(fiber) { function getNearestMountedFiber(fiber) { var node = fiber, nearestMounted = fiber; - if (fiber.alternate) for (; node.return; ) node = node.return; + if (fiber.alternate) for (; node.return;) node = node.return; else { fiber = node; do @@ -1284,7 +1291,7 @@ function findCurrentFiberUsingSlowPath(fiber) { throw Error("Unable to find node on an unmounted component."); return alternate !== fiber ? null : fiber; } - for (var a = fiber, b = alternate; ; ) { + for (var a = fiber, b = alternate; ;) { var parentA = a.return; if (null === parentA) break; var parentB = parentA.alternate; @@ -1297,7 +1304,7 @@ function findCurrentFiberUsingSlowPath(fiber) { break; } if (parentA.child === parentB.child) { - for (parentB = parentA.child; parentB; ) { + for (parentB = parentA.child; parentB;) { if (parentB === a) return assertIsMounted(parentA), fiber; if (parentB === b) return assertIsMounted(parentA), alternate; parentB = parentB.sibling; @@ -1306,7 +1313,7 @@ function findCurrentFiberUsingSlowPath(fiber) { } if (a.return !== b.return) (a = parentA), (b = parentB); else { - for (var didFindChild = !1, child$0 = parentA.child; child$0; ) { + for (var didFindChild = !1, child$0 = parentA.child; child$0;) { if (child$0 === a) { didFindChild = !0; a = parentA; @@ -1322,7 +1329,7 @@ function findCurrentFiberUsingSlowPath(fiber) { child$0 = child$0.sibling; } if (!didFindChild) { - for (child$0 = parentB.child; child$0; ) { + for (child$0 = parentB.child; child$0;) { if (child$0 === a) { didFindChild = !0; a = parentB; @@ -1358,7 +1365,7 @@ function findCurrentHostFiber(parent) { } function findCurrentHostFiberImpl(node) { if (5 === node.tag || 6 === node.tag) return node; - for (node = node.child; null !== node; ) { + for (node = node.child; null !== node;) { var match = findCurrentHostFiberImpl(node); if (null !== match) return match; node = node.sibling; @@ -1366,7 +1373,7 @@ function findCurrentHostFiberImpl(node) { return null; } function mountSafeCallback_NOT_REALLY_SAFE(context, callback) { - return function() { + return function () { if ( callback && ("boolean" !== typeof context.__isMounted || context.__isMounted) @@ -1382,10 +1389,10 @@ function defaultDiffer(prevProp, nextProp) { return "object" !== typeof nextProp || null === nextProp ? !0 : ReactNativePrivateInterface.deepDiffer( - prevProp, - nextProp, - deepDifferOptions - ); + prevProp, + nextProp, + deepDifferOptions + ); } function restoreDeletedValuesInNestedArray( updatePayload, @@ -1393,7 +1400,7 @@ function restoreDeletedValuesInNestedArray( validAttributes ) { if (isArrayImpl(node)) - for (var i = node.length; i-- && 0 < removedKeyCount; ) + for (var i = node.length; i-- && 0 < removedKeyCount;) restoreDeletedValuesInNestedArray( updatePayload, node[i], @@ -1436,13 +1443,13 @@ function diffNestedProperty( return nextProp ? addNestedProperty(updatePayload, nextProp, validAttributes) : prevProp - ? clearNestedProperty(updatePayload, prevProp, validAttributes) - : updatePayload; + ? clearNestedProperty(updatePayload, prevProp, validAttributes) + : updatePayload; if (!isArrayImpl(prevProp) && !isArrayImpl(nextProp)) return diffProperties(updatePayload, prevProp, nextProp, validAttributes); if (isArrayImpl(prevProp) && isArrayImpl(nextProp)) { var minLength = - prevProp.length < nextProp.length ? prevProp.length : nextProp.length, + prevProp.length < nextProp.length ? prevProp.length : nextProp.length, i; for (i = 0; i < minLength; i++) updatePayload = diffNestedProperty( @@ -1467,17 +1474,17 @@ function diffNestedProperty( } return isArrayImpl(prevProp) ? diffProperties( - updatePayload, - ReactNativePrivateInterface.flattenStyle(prevProp), - nextProp, - validAttributes - ) + updatePayload, + ReactNativePrivateInterface.flattenStyle(prevProp), + nextProp, + validAttributes + ) : diffProperties( - updatePayload, - prevProp, - ReactNativePrivateInterface.flattenStyle(nextProp), - validAttributes - ); + updatePayload, + prevProp, + ReactNativePrivateInterface.flattenStyle(nextProp), + validAttributes + ); } function addNestedProperty(updatePayload, nextProp, validAttributes) { if (!nextProp) return updatePayload; @@ -1523,7 +1530,7 @@ function diffProperties(updatePayload, prevProps, nextProps, validAttributes) { ((nextProp = !0), "function" === typeof prevProp && (prevProp = !0)); "undefined" === typeof nextProp && ((nextProp = null), - "undefined" === typeof prevProp && (prevProp = null)); + "undefined" === typeof prevProp && (prevProp = null)); removedKeys && (removedKeys[propKey] = !1); if (updatePayload && void 0 !== updatePayload[propKey]) if ("object" !== typeof attributeConfig) @@ -1570,12 +1577,12 @@ function diffProperties(updatePayload, prevProps, nextProps, validAttributes) { attributeConfig )), 0 < removedKeyCount && - updatePayload && - (restoreDeletedValuesInNestedArray( - updatePayload, - nextProp, - attributeConfig - ), + updatePayload && + (restoreDeletedValuesInNestedArray( + updatePayload, + nextProp, + attributeConfig + ), (removedKeys = null)); } for (var propKey$2 in prevProps) @@ -1583,19 +1590,19 @@ function diffProperties(updatePayload, prevProps, nextProps, validAttributes) { (!(attributeConfig = validAttributes[propKey$2]) || (updatePayload && void 0 !== updatePayload[propKey$2]) || ((prevProp = prevProps[propKey$2]), - void 0 !== prevProp && + void 0 !== prevProp && ("object" !== typeof attributeConfig || - "function" === typeof attributeConfig.diff || - "function" === typeof attributeConfig.process + "function" === typeof attributeConfig.diff || + "function" === typeof attributeConfig.process ? (((updatePayload || (updatePayload = {}))[propKey$2] = null), removedKeys || (removedKeys = {}), removedKeys[propKey$2] || - ((removedKeys[propKey$2] = !0), removedKeyCount++)) + ((removedKeys[propKey$2] = !0), removedKeyCount++)) : (updatePayload = clearNestedProperty( - updatePayload, - prevProp, - attributeConfig - ))))); + updatePayload, + prevProp, + attributeConfig + ))))); return updatePayload; } function batchedUpdatesImpl(fn, bookkeeping) { @@ -1637,7 +1644,7 @@ function dispatchEvent(target, topLevelType, nativeEvent) { var stateNode = target.stateNode; null != stateNode && (eventTarget = stateNode.canonical); } - batchedUpdates(function() { + batchedUpdates(function () { var event = { eventName: topLevelType, nativeEvent: nativeEvent }; ReactNativePrivateInterface.RawEventEmitter.emit(topLevelType, event); ReactNativePrivateInterface.RawEventEmitter.emit("*", event); @@ -1669,9 +1676,9 @@ function dispatchEvent(target, topLevelType, nativeEvent) { ); if (hasRethrowError) throw ((event = rethrowError), - (hasRethrowError = !1), - (rethrowError = null), - event); + (hasRethrowError = !1), + (rethrowError = null), + event); } }); } @@ -1695,7 +1702,7 @@ function onCommitRoot(root) { void 0, 128 === (root.current.flags & 128) ); - } catch (err) {} + } catch (err) { } } var clz32 = Math.clz32 ? Math.clz32 : clz32Fallback, log = Math.log, @@ -1768,28 +1775,28 @@ function getNextLanes(root, wipLanes) { ? (nextLanes = getHighestPriorityLanes(nonIdleUnblockedLanes)) : ((pingedLanes &= nonIdlePendingLanes), 0 !== pingedLanes && - (nextLanes = getHighestPriorityLanes(pingedLanes))); + (nextLanes = getHighestPriorityLanes(pingedLanes))); } else (nonIdlePendingLanes = pendingLanes & ~suspendedLanes), 0 !== nonIdlePendingLanes ? (nextLanes = getHighestPriorityLanes(nonIdlePendingLanes)) : 0 !== pingedLanes && - (nextLanes = getHighestPriorityLanes(pingedLanes)); + (nextLanes = getHighestPriorityLanes(pingedLanes)); if (0 === nextLanes) return 0; if ( 0 !== wipLanes && wipLanes !== nextLanes && 0 === (wipLanes & suspendedLanes) && ((suspendedLanes = nextLanes & -nextLanes), - (pingedLanes = wipLanes & -wipLanes), - suspendedLanes >= pingedLanes || + (pingedLanes = wipLanes & -wipLanes), + suspendedLanes >= pingedLanes || (16 === suspendedLanes && 0 !== (pingedLanes & 4194240))) ) return wipLanes; 0 !== (nextLanes & 4) && (nextLanes |= pendingLanes & 16); wipLanes = root.entangledLanes; if (0 !== wipLanes) - for (root = root.entanglements, wipLanes &= nextLanes; 0 < wipLanes; ) + for (root = root.entanglements, wipLanes &= nextLanes; 0 < wipLanes;) (pendingLanes = 31 - clz32(wipLanes)), (suspendedLanes = 1 << pendingLanes), (nextLanes |= root[pendingLanes]), @@ -1869,7 +1876,7 @@ function markRootFinished(root, remainingLanes) { root.entangledLanes &= remainingLanes; remainingLanes = root.entanglements; var eventTimes = root.eventTimes; - for (root = root.expirationTimes; 0 < noLongerPendingLanes; ) { + for (root = root.expirationTimes; 0 < noLongerPendingLanes;) { var index$7 = 31 - clz32(noLongerPendingLanes), lane = 1 << index$7; remainingLanes[index$7] = 0; @@ -1880,7 +1887,7 @@ function markRootFinished(root, remainingLanes) { } function markRootEntangled(root, entangledLanes) { var rootEntangledLanes = (root.entangledLanes |= entangledLanes); - for (root = root.entanglements; rootEntangledLanes; ) { + for (root = root.entanglements; rootEntangledLanes;) { var index$8 = 31 - clz32(rootEntangledLanes), lane = 1 << index$8; (lane & entangledLanes) | (root[index$8] & entangledLanes) && @@ -1927,7 +1934,7 @@ var _nativeFabricUIManage = nativeFabricUIManager, ReactNativePrivateInterface.ReactNativeViewConfigRegistry.get, nextReactTag = 2; registerEventHandler && registerEventHandler(dispatchEvent); -var ReactFabricHostComponent = (function() { +var ReactFabricHostComponent = (function () { function ReactFabricHostComponent( tag, viewConfig, @@ -1940,13 +1947,13 @@ var ReactFabricHostComponent = (function() { this._internalInstanceHandle = internalInstanceHandle; } var _proto = ReactFabricHostComponent.prototype; - _proto.blur = function() { + _proto.blur = function () { ReactNativePrivateInterface.TextInputState.blurTextInput(this); }; - _proto.focus = function() { + _proto.focus = function () { ReactNativePrivateInterface.TextInputState.focusTextInput(this); }; - _proto.measure = function(callback) { + _proto.measure = function (callback) { var stateNode = this._internalInstanceHandle.stateNode; null != stateNode && fabricMeasure( @@ -1954,7 +1961,7 @@ var ReactFabricHostComponent = (function() { mountSafeCallback_NOT_REALLY_SAFE(this, callback) ); }; - _proto.measureInWindow = function(callback) { + _proto.measureInWindow = function (callback) { var stateNode = this._internalInstanceHandle.stateNode; null != stateNode && fabricMeasureInWindow( @@ -1962,7 +1969,7 @@ var ReactFabricHostComponent = (function() { mountSafeCallback_NOT_REALLY_SAFE(this, callback) ); }; - _proto.measureLayout = function(relativeToNativeNode, onSuccess, onFail) { + _proto.measureLayout = function (relativeToNativeNode, onSuccess, onFail) { if ( "number" !== typeof relativeToNativeNode && relativeToNativeNode instanceof ReactFabricHostComponent @@ -1980,7 +1987,7 @@ var ReactFabricHostComponent = (function() { ); } }; - _proto.setNativeProps = function(nativeProps) { + _proto.setNativeProps = function (nativeProps) { nativeProps = diffProperties( null, emptyObject, @@ -1992,7 +1999,7 @@ var ReactFabricHostComponent = (function() { null != nativeProps && _setNativeProps(stateNode.node, nativeProps); }; - _proto.addEventListener_unstable = function(eventType, listener, options) { + _proto.addEventListener_unstable = function (eventType, listener, options) { if ("string" !== typeof eventType) throw Error("addEventListener_unstable eventType must be a string"); if ("function" !== typeof listener) @@ -2019,14 +2026,14 @@ var ReactFabricHostComponent = (function() { } }); }; - _proto.removeEventListener_unstable = function(eventType, listener, options) { + _proto.removeEventListener_unstable = function (eventType, listener, options) { var optionsObj = - "object" === typeof options && null !== options ? options : {}, + "object" === typeof options && null !== options ? options : {}, capture = ("boolean" === typeof options ? options : optionsObj.capture) || !1; (options = this._eventListeners) && (optionsObj = options[eventType]) && - (options[eventType] = optionsObj.filter(function(listenerObj) { + (options[eventType] = optionsObj.filter(function (listenerObj) { return !( listenerObj.listener === listener && listenerObj.options.capture === capture @@ -2111,8 +2118,8 @@ function getMaskedContext(workInProgress, unmaskedContext) { for (key in contextTypes) context[key] = unmaskedContext[key]; instance && ((workInProgress = workInProgress.stateNode), - (workInProgress.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext), - (workInProgress.__reactInternalMemoizedMaskedChildContext = context)); + (workInProgress.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext), + (workInProgress.__reactInternalMemoizedMaskedChildContext = context)); return context; } function isContextProvider(type) { @@ -2140,9 +2147,9 @@ function processChildContext(fiber, type, parentContext) { if (!(contextKey in type)) throw Error( (getComponentNameFromFiber(fiber) || "Unknown") + - '.getChildContext(): key "' + - contextKey + - '" is not defined in childContextTypes.' + '.getChildContext(): key "' + + contextKey + + '" is not defined in childContextTypes.' ); return assign({}, parentContext, instance); } @@ -2164,10 +2171,10 @@ function invalidateContextProvider(workInProgress, type, didChange) { ); didChange ? ((workInProgress = processChildContext( - workInProgress, - type, - previousContext - )), + workInProgress, + type, + previousContext + )), (instance.__reactInternalMemoizedMergedChildContext = workInProgress), pop(didPerformWorkStackCursor), pop(contextStackCursor), @@ -2198,8 +2205,8 @@ function flushSyncCallbacks() { includesLegacySyncCallbacks = !1; } catch (error) { throw (null !== syncQueue && (syncQueue = syncQueue.slice(i + 1)), - scheduleCallback(ImmediatePriority, flushSyncCallbacks), - error); + scheduleCallback(ImmediatePriority, flushSyncCallbacks), + error); } finally { (currentUpdatePriority = previousUpdatePriority), (isFlushingSyncQueue = !1); @@ -2214,12 +2221,12 @@ var forkStack = [], idStackIndex = 0, treeContextProvider = null; function popTreeContext(workInProgress) { - for (; workInProgress === treeForkProvider; ) + for (; workInProgress === treeForkProvider;) (treeForkProvider = forkStack[--forkStackIndex]), (forkStack[forkStackIndex] = null), --forkStackIndex, (forkStack[forkStackIndex] = null); - for (; workInProgress === treeContextProvider; ) + for (; workInProgress === treeContextProvider;) (treeContextProvider = idStack[--idStackIndex]), (idStack[idStackIndex] = null), --idStackIndex, @@ -2297,14 +2304,14 @@ function popProvider(context) { context._currentValue2 = currentValue; } function scheduleContextWorkOnParentPath(parent, renderLanes, propagationRoot) { - for (; null !== parent; ) { + for (; null !== parent;) { var alternate = parent.alternate; (parent.childLanes & renderLanes) !== renderLanes ? ((parent.childLanes |= renderLanes), null !== alternate && (alternate.childLanes |= renderLanes)) : null !== alternate && - (alternate.childLanes & renderLanes) !== renderLanes && - (alternate.childLanes |= renderLanes); + (alternate.childLanes & renderLanes) !== renderLanes && + (alternate.childLanes |= renderLanes); if (parent === propagationRoot) break; parent = parent.return; } @@ -2316,14 +2323,14 @@ function prepareToReadContext(workInProgress, renderLanes) { null !== workInProgress && null !== workInProgress.firstContext && (0 !== (workInProgress.lanes & renderLanes) && (didReceiveUpdate = !0), - (workInProgress.firstContext = null)); + (workInProgress.firstContext = null)); } function readContext(context) { var value = context._currentValue2; if (lastFullyObservedContext !== context) if ( ((context = { context: context, memoizedValue: value, next: null }), - null === lastContextDependency) + null === lastContextDependency) ) { if (null === currentlyRenderingFiber) throw Error( @@ -2356,7 +2363,7 @@ function markUpdateLaneFromFiberToRoot(sourceFiber, lane) { var alternate = sourceFiber.alternate; null !== alternate && (alternate.lanes |= lane); alternate = sourceFiber; - for (sourceFiber = sourceFiber.return; null !== sourceFiber; ) + for (sourceFiber = sourceFiber.return; null !== sourceFiber;) (sourceFiber.childLanes |= lane), (alternate = sourceFiber.alternate), null !== alternate && (alternate.childLanes |= lane), @@ -2492,12 +2499,12 @@ function processUpdateQueue( var current = workInProgress$jscomp$0.alternate; null !== current && ((current = current.updateQueue), - (pendingQueue = current.lastBaseUpdate), - pendingQueue !== lastBaseUpdate && + (pendingQueue = current.lastBaseUpdate), + pendingQueue !== lastBaseUpdate && (null === pendingQueue ? (current.firstBaseUpdate = firstPendingUpdate) : (pendingQueue.next = firstPendingUpdate), - (current.lastBaseUpdate = lastPendingUpdate))); + (current.lastBaseUpdate = lastPendingUpdate))); } if (null !== firstBaseUpdate) { var newState = queue.baseState; @@ -2553,10 +2560,10 @@ function processUpdateQueue( null !== pendingQueue.callback && 0 !== pendingQueue.lane && ((workInProgress$jscomp$0.flags |= 64), - (updateLane = queue.effects), - null === updateLane - ? (queue.effects = [pendingQueue]) - : updateLane.push(pendingQueue)); + (updateLane = queue.effects), + null === updateLane + ? (queue.effects = [pendingQueue]) + : updateLane.push(pendingQueue)); } else (updateEventTime = { eventTime: updateEventTime, @@ -2613,7 +2620,7 @@ function commitUpdateQueue(finishedWork, finishedQueue, instance) { if ("function" !== typeof callback) throw Error( "Invalid argument passed as callback. Expected a function. Instead received: " + - callback + callback ); callback.call(instance); } @@ -2637,12 +2644,12 @@ function applyDerivedStateFromProps( (workInProgress.updateQueue.baseState = getDerivedStateFromProps); } var classComponentUpdater = { - isMounted: function(component) { + isMounted: function (component) { return (component = component._reactInternals) ? getNearestMountedFiber(component) === component : !1; }, - enqueueSetState: function(inst, payload, callback) { + enqueueSetState: function (inst, payload, callback) { inst = inst._reactInternals; var eventTime = requestEventTime(), lane = requestUpdateLane(inst), @@ -2652,9 +2659,9 @@ var classComponentUpdater = { payload = enqueueUpdate(inst, update, lane); null !== payload && (scheduleUpdateOnFiber(payload, inst, lane, eventTime), - entangleTransitions(payload, inst, lane)); + entangleTransitions(payload, inst, lane)); }, - enqueueReplaceState: function(inst, payload, callback) { + enqueueReplaceState: function (inst, payload, callback) { inst = inst._reactInternals; var eventTime = requestEventTime(), lane = requestUpdateLane(inst), @@ -2665,9 +2672,9 @@ var classComponentUpdater = { payload = enqueueUpdate(inst, update, lane); null !== payload && (scheduleUpdateOnFiber(payload, inst, lane, eventTime), - entangleTransitions(payload, inst, lane)); + entangleTransitions(payload, inst, lane)); }, - enqueueForceUpdate: function(inst, callback) { + enqueueForceUpdate: function (inst, callback) { inst = inst._reactInternals; var eventTime = requestEventTime(), lane = requestUpdateLane(inst), @@ -2677,7 +2684,7 @@ var classComponentUpdater = { callback = enqueueUpdate(inst, update, lane); null !== callback && (scheduleUpdateOnFiber(callback, inst, lane, eventTime), - entangleTransitions(callback, inst, lane)); + entangleTransitions(callback, inst, lane)); } }; function checkShouldComponentUpdate( @@ -2693,8 +2700,8 @@ function checkShouldComponentUpdate( return "function" === typeof workInProgress.shouldComponentUpdate ? workInProgress.shouldComponentUpdate(newProps, newState, nextContext) : ctor.prototype && ctor.prototype.isPureReactComponent - ? !shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState) - : !0; + ? !shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState) + : !0; } function constructClassInstance(workInProgress, ctor, props) { var isLegacyContextConsumer = !1, @@ -2703,8 +2710,8 @@ function constructClassInstance(workInProgress, ctor, props) { "object" === typeof context && null !== context ? (context = readContext(context)) : ((unmaskedContext = isContextProvider(ctor) - ? previousContext - : contextStackCursor.current), + ? previousContext + : contextStackCursor.current), (isLegacyContextConsumer = ctor.contextTypes), (context = (isLegacyContextConsumer = null !== isLegacyContextConsumer && void 0 !== isLegacyContextConsumer) @@ -2718,8 +2725,8 @@ function constructClassInstance(workInProgress, ctor, props) { ctor._reactInternals = workInProgress; isLegacyContextConsumer && ((workInProgress = workInProgress.stateNode), - (workInProgress.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext), - (workInProgress.__reactInternalMemoizedMaskedChildContext = context)); + (workInProgress.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext), + (workInProgress.__reactInternalMemoizedMaskedChildContext = context)); return ctor; } function callComponentWillReceiveProps( @@ -2746,27 +2753,27 @@ function mountClassInstance(workInProgress, ctor, newProps, renderLanes) { "object" === typeof contextType && null !== contextType ? (instance.context = readContext(contextType)) : ((contextType = isContextProvider(ctor) - ? previousContext - : contextStackCursor.current), + ? previousContext + : contextStackCursor.current), (instance.context = getMaskedContext(workInProgress, contextType))); instance.state = workInProgress.memoizedState; contextType = ctor.getDerivedStateFromProps; "function" === typeof contextType && (applyDerivedStateFromProps(workInProgress, ctor, contextType, newProps), - (instance.state = workInProgress.memoizedState)); + (instance.state = workInProgress.memoizedState)); "function" === typeof ctor.getDerivedStateFromProps || "function" === typeof instance.getSnapshotBeforeUpdate || ("function" !== typeof instance.UNSAFE_componentWillMount && "function" !== typeof instance.componentWillMount) || ((ctor = instance.state), - "function" === typeof instance.componentWillMount && + "function" === typeof instance.componentWillMount && instance.componentWillMount(), - "function" === typeof instance.UNSAFE_componentWillMount && + "function" === typeof instance.UNSAFE_componentWillMount && instance.UNSAFE_componentWillMount(), - ctor !== instance.state && + ctor !== instance.state && classComponentUpdater.enqueueReplaceState(instance, instance.state, null), - processUpdateQueue(workInProgress, newProps, instance, renderLanes), - (instance.state = workInProgress.memoizedState)); + processUpdateQueue(workInProgress, newProps, instance, renderLanes), + (instance.state = workInProgress.memoizedState)); "function" === typeof instance.componentDidMount && (workInProgress.flags |= 4); } @@ -2789,8 +2796,8 @@ function coerceRef(returnFiber, current, element) { if (!inst) throw Error( "Missing owner for string ref " + - returnFiber + - ". This error is likely caused by a bug in React. Please file an issue." + returnFiber + + ". This error is likely caused by a bug in React. Please file an issue." ); var resolvedInst = inst, stringRef = "" + returnFiber; @@ -2801,7 +2808,7 @@ function coerceRef(returnFiber, current, element) { current.ref._stringRef === stringRef ) return current.ref; - current = function(value) { + current = function (value) { var refs = resolvedInst.refs; refs === emptyRefsObject && (refs = resolvedInst.refs = {}); null === value ? delete refs[stringRef] : (refs[stringRef] = value); @@ -2816,8 +2823,8 @@ function coerceRef(returnFiber, current, element) { if (!element._owner) throw Error( "Element ref was specified as a string (" + - returnFiber + - ") but no owner was set. This could happen for one of the following reasons:\n1. You may be adding a ref to a function component\n2. You may be adding a ref to a component that was not created inside a component's render method\n3. You have multiple copies of React loaded\nSee https://react.dev/link/refs-must-have-owner for more information." + returnFiber + + ") but no owner was set. This could happen for one of the following reasons:\n1. You may be adding a ref to a function component\n2. You may be adding a ref to a component that was not created inside a component's render method\n3. You have multiple copies of React loaded\nSee https://react.dev/link/refs-must-have-owner for more information." ); } return returnFiber; @@ -2826,10 +2833,10 @@ function throwOnInvalidObjectType(returnFiber, newChild) { returnFiber = Object.prototype.toString.call(newChild); throw Error( "Objects are not valid as a React child (found: " + - ("[object Object]" === returnFiber - ? "object with keys {" + Object.keys(newChild).join(", ") + "}" - : returnFiber) + - "). If you meant to render a collection of children, use an array instead." + ("[object Object]" === returnFiber + ? "object with keys {" + Object.keys(newChild).join(", ") + "}" + : returnFiber) + + "). If you meant to render a collection of children, use an array instead." ); } function resolveLazy(lazyType) { @@ -2847,13 +2854,13 @@ function ChildReconciler(shouldTrackSideEffects) { } function deleteRemainingChildren(returnFiber, currentFirstChild) { if (!shouldTrackSideEffects) return null; - for (; null !== currentFirstChild; ) + for (; null !== currentFirstChild;) deleteChild(returnFiber, currentFirstChild), (currentFirstChild = currentFirstChild.sibling); return null; } function mapRemainingChildren(returnFiber, currentFirstChild) { - for (returnFiber = new Map(); null !== currentFirstChild; ) + for (returnFiber = new Map(); null !== currentFirstChild;) null !== currentFirstChild.key ? returnFiber.set(currentFirstChild.key, currentFirstChild) : returnFiber.set(currentFirstChild.index, currentFirstChild), @@ -3118,10 +3125,10 @@ function ChildReconciler(shouldTrackSideEffects) { ) { for ( var resultingFirstChild = null, - previousNewFiber = null, - oldFiber = currentFirstChild, - newIdx = (currentFirstChild = 0), - nextOldFiber = null; + previousNewFiber = null, + oldFiber = currentFirstChild, + newIdx = (currentFirstChild = 0), + nextOldFiber = null; null !== oldFiber && newIdx < newChildren.length; newIdx++ ) { @@ -3157,11 +3164,11 @@ function ChildReconciler(shouldTrackSideEffects) { for (; newIdx < newChildren.length; newIdx++) (oldFiber = createChild(returnFiber, newChildren[newIdx], lanes)), null !== oldFiber && - ((currentFirstChild = placeChild( - oldFiber, - currentFirstChild, - newIdx - )), + ((currentFirstChild = placeChild( + oldFiber, + currentFirstChild, + newIdx + )), null === previousNewFiber ? (resultingFirstChild = oldFiber) : (previousNewFiber.sibling = oldFiber), @@ -3181,11 +3188,11 @@ function ChildReconciler(shouldTrackSideEffects) { lanes )), null !== nextOldFiber && - (shouldTrackSideEffects && - null !== nextOldFiber.alternate && - oldFiber.delete( - null === nextOldFiber.key ? newIdx : nextOldFiber.key - ), + (shouldTrackSideEffects && + null !== nextOldFiber.alternate && + oldFiber.delete( + null === nextOldFiber.key ? newIdx : nextOldFiber.key + ), (currentFirstChild = placeChild( nextOldFiber, currentFirstChild, @@ -3196,7 +3203,7 @@ function ChildReconciler(shouldTrackSideEffects) { : (previousNewFiber.sibling = nextOldFiber), (previousNewFiber = nextOldFiber)); shouldTrackSideEffects && - oldFiber.forEach(function(child) { + oldFiber.forEach(function (child) { return deleteChild(returnFiber, child); }); return resultingFirstChild; @@ -3217,10 +3224,10 @@ function ChildReconciler(shouldTrackSideEffects) { throw Error("An iterable object provided no iterator."); for ( var previousNewFiber = (iteratorFn = null), - oldFiber = currentFirstChild, - newIdx = (currentFirstChild = 0), - nextOldFiber = null, - step = newChildrenIterable.next(); + oldFiber = currentFirstChild, + newIdx = (currentFirstChild = 0), + nextOldFiber = null, + step = newChildrenIterable.next(); null !== oldFiber && !step.done; newIdx++, step = newChildrenIterable.next() ) { @@ -3249,7 +3256,7 @@ function ChildReconciler(shouldTrackSideEffects) { for (; !step.done; newIdx++, step = newChildrenIterable.next()) (step = createChild(returnFiber, step.value, lanes)), null !== step && - ((currentFirstChild = placeChild(step, currentFirstChild, newIdx)), + ((currentFirstChild = placeChild(step, currentFirstChild, newIdx)), null === previousNewFiber ? (iteratorFn = step) : (previousNewFiber.sibling = step), @@ -3263,16 +3270,16 @@ function ChildReconciler(shouldTrackSideEffects) { ) (step = updateFromMap(oldFiber, returnFiber, newIdx, step.value, lanes)), null !== step && - (shouldTrackSideEffects && - null !== step.alternate && - oldFiber.delete(null === step.key ? newIdx : step.key), + (shouldTrackSideEffects && + null !== step.alternate && + oldFiber.delete(null === step.key ? newIdx : step.key), (currentFirstChild = placeChild(step, currentFirstChild, newIdx)), null === previousNewFiber ? (iteratorFn = step) : (previousNewFiber.sibling = step), (previousNewFiber = step)); shouldTrackSideEffects && - oldFiber.forEach(function(child) { + oldFiber.forEach(function (child) { return deleteChild(returnFiber, child); }); return iteratorFn; @@ -3335,21 +3342,21 @@ function ChildReconciler(shouldTrackSideEffects) { } newChild.type === REACT_FRAGMENT_TYPE ? ((currentFirstChild = createFiberFromFragment( - newChild.props.children, - returnFiber.mode, - lanes, - newChild.key - )), + newChild.props.children, + returnFiber.mode, + lanes, + newChild.key + )), (currentFirstChild.return = returnFiber), (returnFiber = currentFirstChild)) : ((lanes = createFiberFromTypeAndProps( - newChild.type, - newChild.key, - newChild.props, - null, - returnFiber.mode, - lanes - )), + newChild.type, + newChild.key, + newChild.props, + null, + returnFiber.mode, + lanes + )), (lanes.ref = coerceRef( returnFiber, currentFirstChild, @@ -3361,14 +3368,14 @@ function ChildReconciler(shouldTrackSideEffects) { return placeSingleChild(returnFiber); case REACT_PORTAL_TYPE: a: { - for (child = newChild.key; null !== currentFirstChild; ) { + for (child = newChild.key; null !== currentFirstChild;) { if (currentFirstChild.key === child) if ( 4 === currentFirstChild.tag && currentFirstChild.stateNode.containerInfo === - newChild.containerInfo && + newChild.containerInfo && currentFirstChild.stateNode.implementation === - newChild.implementation + newChild.implementation ) { deleteRemainingChildren( returnFiber, @@ -3486,7 +3493,7 @@ function pushHostContext(fiber) { : context; context !== JSCompiler_inline_result && (push(contextFiberStackCursor, fiber), - push(contextStackCursor$1, JSCompiler_inline_result)); + push(contextStackCursor$1, JSCompiler_inline_result)); } function popHostContext(fiber) { contextFiberStackCursor.current === fiber && @@ -3494,7 +3501,7 @@ function popHostContext(fiber) { } var suspenseStackCursor = createCursor(0); function findFirstSuspended(row) { - for (var node = row; null !== node; ) { + for (var node = row; null !== node;) { if (13 === node.tag) { var state = node.memoizedState; if (null !== state && (null === state.dehydrated || shim$1() || shim$1())) @@ -3507,7 +3514,7 @@ function findFirstSuspended(row) { continue; } if (node === row) break; - for (; null === node.sibling; ) { + for (; null === node.sibling;) { if (null === node.return || node.return === row) return null; node = node.return; } @@ -3733,7 +3740,7 @@ function rerenderReducer(reducer) { } return [newState, dispatch]; } -function updateMutableSource() {} +function updateMutableSource() { } function updateSyncExternalStore(subscribe, getSnapshot) { var fiber = currentlyRenderingFiber$1, hook = updateWorkInProgressHook(), @@ -3785,7 +3792,7 @@ function updateStoreInstance(fiber, inst, nextSnapshot, getSnapshot) { checkIfSnapshotChanged(inst) && forceStoreRerender(fiber); } function subscribeToStore(fiber, inst, subscribe) { - return subscribe(function() { + return subscribe(function () { checkIfSnapshotChanged(inst) && forceStoreRerender(fiber); }); } @@ -3884,7 +3891,7 @@ function imperativeHandleEffect(create, ref) { return ( (create = create()), ref(create), - function() { + function () { ref(null); } ); @@ -3892,7 +3899,7 @@ function imperativeHandleEffect(create, ref) { return ( (create = create()), (ref.current = create), - function() { + function () { ref.current = null; } ); @@ -3906,7 +3913,7 @@ function updateImperativeHandle(ref, create, deps) { deps ); } -function mountDebugValue() {} +function mountDebugValue() { } function updateCallback(callback, deps) { var hook = updateWorkInProgressHook(); deps = void 0 === deps ? null : deps; @@ -3942,9 +3949,9 @@ function updateDeferredValueImpl(hook, prevValue, value) { ); objectIs(value, prevValue) || ((value = claimNextTransitionLane()), - (currentlyRenderingFiber$1.lanes |= value), - (workInProgressRootSkippedLanes |= value), - (hook.baseState = !0)); + (currentlyRenderingFiber$1.lanes |= value), + (workInProgressRootSkippedLanes |= value), + (hook.baseState = !0)); return prevValue; } function startTransition(setPending, callback) { @@ -3976,7 +3983,7 @@ function dispatchReducerAction(fiber, queue, action) { if (isRenderPhaseUpdate(fiber)) enqueueRenderPhaseUpdate(queue, action); else if ( ((action = enqueueConcurrentHookUpdate(fiber, queue, action, lane)), - null !== action) + null !== action) ) { var eventTime = requestEventTime(); scheduleUpdateOnFiber(action, fiber, lane, eventTime); @@ -4019,8 +4026,8 @@ function dispatchSetState(fiber, queue, action) { action = enqueueConcurrentHookUpdate(fiber, queue, update, lane); null !== action && ((update = requestEventTime()), - scheduleUpdateOnFiber(action, fiber, lane, update), - entangleTransitionUpdate(action, queue, lane)); + scheduleUpdateOnFiber(action, fiber, lane, update), + entangleTransitionUpdate(action, queue, lane)); } } function isRenderPhaseUpdate(fiber) { @@ -4048,28 +4055,28 @@ function entangleTransitionUpdate(root, queue, lane) { } } var ContextOnlyDispatcher = { - readContext: readContext, - 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, - useMutableSource: throwInvalidHookError, - useSyncExternalStore: throwInvalidHookError, - useId: throwInvalidHookError, - unstable_isNewReconciler: !1 - }, + readContext: readContext, + 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, + useMutableSource: throwInvalidHookError, + useSyncExternalStore: throwInvalidHookError, + useId: throwInvalidHookError, + unstable_isNewReconciler: !1 +}, HooksDispatcherOnMount = { readContext: readContext, - useCallback: function(callback, deps) { + useCallback: function (callback, deps) { mountWorkInProgressHook().memoizedState = [ callback, void 0 === deps ? null : deps @@ -4078,7 +4085,7 @@ var ContextOnlyDispatcher = { }, useContext: readContext, useEffect: mountEffect, - useImperativeHandle: function(ref, create, deps) { + useImperativeHandle: function (ref, create, deps) { deps = null !== deps && void 0 !== deps ? deps.concat([ref]) : null; return mountEffectImpl( 4, @@ -4087,20 +4094,20 @@ var ContextOnlyDispatcher = { deps ); }, - useLayoutEffect: function(create, deps) { + useLayoutEffect: function (create, deps) { return mountEffectImpl(4, 4, create, deps); }, - useInsertionEffect: function(create, deps) { + useInsertionEffect: function (create, deps) { return mountEffectImpl(4, 2, create, deps); }, - useMemo: function(nextCreate, deps) { + useMemo: function (nextCreate, deps) { var hook = mountWorkInProgressHook(); deps = void 0 === deps ? null : deps; nextCreate = nextCreate(); hook.memoizedState = [nextCreate, deps]; return nextCreate; }, - useReducer: function(reducer, initialArg, init) { + useReducer: function (reducer, initialArg, init) { var hook = mountWorkInProgressHook(); initialArg = void 0 !== init ? init(initialArg) : initialArg; hook.memoizedState = hook.baseState = initialArg; @@ -4120,25 +4127,25 @@ var ContextOnlyDispatcher = { ); return [hook.memoizedState, reducer]; }, - useRef: function(initialValue) { + useRef: function (initialValue) { var hook = mountWorkInProgressHook(); initialValue = { current: initialValue }; return (hook.memoizedState = initialValue); }, useState: mountState, useDebugValue: mountDebugValue, - useDeferredValue: function(value) { + useDeferredValue: function (value) { return (mountWorkInProgressHook().memoizedState = value); }, - useTransition: function() { + useTransition: function () { var _mountState = mountState(!1), isPending = _mountState[0]; _mountState = startTransition.bind(null, _mountState[1]); mountWorkInProgressHook().memoizedState = _mountState; return [isPending, _mountState]; }, - useMutableSource: function() {}, - useSyncExternalStore: function(subscribe, getSnapshot) { + useMutableSource: function () { }, + useSyncExternalStore: function (subscribe, getSnapshot) { var fiber = currentlyRenderingFiber$1, hook = mountWorkInProgressHook(); var nextSnapshot = getSnapshot(); @@ -4163,7 +4170,7 @@ var ContextOnlyDispatcher = { ); return nextSnapshot; }, - useId: function() { + useId: function () { var hook = mountWorkInProgressHook(), identifierPrefix = workInProgressRoot.identifierPrefix, globalClientId = globalClientIdCounter++; @@ -4184,15 +4191,15 @@ var ContextOnlyDispatcher = { useMemo: updateMemo, useReducer: updateReducer, useRef: updateRef, - useState: function() { + useState: function () { return updateReducer(basicStateReducer); }, useDebugValue: mountDebugValue, - useDeferredValue: function(value) { + useDeferredValue: function (value) { var hook = updateWorkInProgressHook(); return updateDeferredValueImpl(hook, currentHook.memoizedState, value); }, - useTransition: function() { + useTransition: function () { var isPending = updateReducer(basicStateReducer)[0], start = updateWorkInProgressHook().memoizedState; return [isPending, start]; @@ -4213,17 +4220,17 @@ var ContextOnlyDispatcher = { useMemo: updateMemo, useReducer: rerenderReducer, useRef: updateRef, - useState: function() { + useState: function () { return rerenderReducer(basicStateReducer); }, useDebugValue: mountDebugValue, - useDeferredValue: function(value) { + useDeferredValue: function (value) { var hook = updateWorkInProgressHook(); return null === currentHook ? (hook.memoizedState = value) : updateDeferredValueImpl(hook, currentHook.memoizedState, value); }, - useTransition: function() { + useTransition: function () { var isPending = rerenderReducer(basicStateReducer)[0], start = updateWorkInProgressHook().memoizedState; return [isPending, start]; @@ -4276,7 +4283,7 @@ function logCapturedError(boundary, errorInfo) { null !== boundary && 1 === boundary.tag ? boundary.stateNode : null }) && console.error(errorInfo.value); } catch (e) { - setTimeout(function() { + setTimeout(function () { throw e; }); } @@ -4287,7 +4294,7 @@ function createRootErrorUpdate(fiber, errorInfo, lane) { lane.tag = 3; lane.payload = { element: null }; var error = errorInfo.value; - lane.callback = function() { + lane.callback = function () { hasUncaughtError || ((hasUncaughtError = !0), (firstUncaughtError = error)); logCapturedError(fiber, errorInfo); }; @@ -4299,17 +4306,17 @@ function createClassErrorUpdate(fiber, errorInfo, lane) { var getDerivedStateFromError = fiber.type.getDerivedStateFromError; if ("function" === typeof getDerivedStateFromError) { var error = errorInfo.value; - lane.payload = function() { + lane.payload = function () { return getDerivedStateFromError(error); }; - lane.callback = function() { + lane.callback = function () { logCapturedError(fiber, errorInfo); }; } var inst = fiber.stateNode; null !== inst && "function" === typeof inst.componentDidCatch && - (lane.callback = function() { + (lane.callback = function () { logCapturedError(fiber, errorInfo); "function" !== typeof getDerivedStateFromError && (null === legacyErrorBoundariesThatAlreadyFailed @@ -4331,11 +4338,11 @@ function attachPingListener(root, wakeable, lanes) { } else (threadIDs = pingCache.get(wakeable)), void 0 === threadIDs && - ((threadIDs = new Set()), pingCache.set(wakeable, threadIDs)); + ((threadIDs = new Set()), pingCache.set(wakeable, threadIDs)); threadIDs.has(lanes) || (threadIDs.add(lanes), - (root = pingSuspendedRoot.bind(null, root, wakeable, lanes)), - wakeable.then(root, root)); + (root = pingSuspendedRoot.bind(null, root, wakeable, lanes)), + wakeable.then(root, root)); } var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner, didReceiveUpdate = !1; @@ -4344,11 +4351,11 @@ function reconcileChildren(current, workInProgress, nextChildren, renderLanes) { null === current ? mountChildFibers(workInProgress, null, nextChildren, renderLanes) : reconcileChildFibers( - workInProgress, - current.child, - nextChildren, - renderLanes - ); + workInProgress, + current.child, + nextChildren, + renderLanes + ); } function updateForwardRef( current, @@ -4447,8 +4454,8 @@ function updateSimpleMemoComponent( ) if ( ((didReceiveUpdate = !1), - (workInProgress.pendingProps = nextProps = prevProps), - 0 !== (current.lanes & renderLanes)) + (workInProgress.pendingProps = nextProps = prevProps), + 0 !== (current.lanes & renderLanes)) ) 0 !== (current.flags & 131072) && (didReceiveUpdate = !0); else @@ -4580,8 +4587,8 @@ function updateClassComponent( "object" === typeof contextType && null !== contextType ? (contextType = readContext(contextType)) : ((contextType = isContextProvider(Component) - ? previousContext - : contextStackCursor.current), + ? previousContext + : contextStackCursor.current), (contextType = getMaskedContext(workInProgress, contextType))); var getDerivedStateFromProps = Component.getDerivedStateFromProps, hasNewLifecycles = @@ -4603,16 +4610,16 @@ function updateClassComponent( processUpdateQueue(workInProgress, nextProps, instance, renderLanes); oldContext = workInProgress.memoizedState; oldProps !== nextProps || - oldState !== oldContext || - didPerformWorkStackCursor.current || - hasForceUpdate + oldState !== oldContext || + didPerformWorkStackCursor.current || + hasForceUpdate ? ("function" === typeof getDerivedStateFromProps && - (applyDerivedStateFromProps( - workInProgress, - Component, - getDerivedStateFromProps, - nextProps - ), + (applyDerivedStateFromProps( + workInProgress, + Component, + getDerivedStateFromProps, + nextProps + ), (oldContext = workInProgress.memoizedState)), (oldProps = hasForceUpdate || @@ -4626,16 +4633,16 @@ function updateClassComponent( contextType )) ? (hasNewLifecycles || - ("function" !== typeof instance.UNSAFE_componentWillMount && - "function" !== typeof instance.componentWillMount) || - ("function" === typeof instance.componentWillMount && - instance.componentWillMount(), + ("function" !== typeof instance.UNSAFE_componentWillMount && + "function" !== typeof instance.componentWillMount) || + ("function" === typeof instance.componentWillMount && + instance.componentWillMount(), "function" === typeof instance.UNSAFE_componentWillMount && - instance.UNSAFE_componentWillMount()), + instance.UNSAFE_componentWillMount()), "function" === typeof instance.componentDidMount && - (workInProgress.flags |= 4)) + (workInProgress.flags |= 4)) : ("function" === typeof instance.componentDidMount && - (workInProgress.flags |= 4), + (workInProgress.flags |= 4), (workInProgress.memoizedProps = nextProps), (workInProgress.memoizedState = oldContext)), (instance.props = nextProps), @@ -4643,7 +4650,7 @@ function updateClassComponent( (instance.context = contextType), (nextProps = oldProps)) : ("function" === typeof instance.componentDidMount && - (workInProgress.flags |= 4), + (workInProgress.flags |= 4), (nextProps = !1)); } else { instance = workInProgress.stateNode; @@ -4660,8 +4667,8 @@ function updateClassComponent( "object" === typeof oldContext && null !== oldContext ? (oldContext = readContext(oldContext)) : ((oldContext = isContextProvider(Component) - ? previousContext - : contextStackCursor.current), + ? previousContext + : contextStackCursor.current), (oldContext = getMaskedContext(workInProgress, oldContext))); var getDerivedStateFromProps$jscomp$0 = Component.getDerivedStateFromProps; (getDerivedStateFromProps = @@ -4682,16 +4689,16 @@ function updateClassComponent( processUpdateQueue(workInProgress, nextProps, instance, renderLanes); var newState = workInProgress.memoizedState; oldProps !== hasNewLifecycles || - oldState !== newState || - didPerformWorkStackCursor.current || - hasForceUpdate + oldState !== newState || + didPerformWorkStackCursor.current || + hasForceUpdate ? ("function" === typeof getDerivedStateFromProps$jscomp$0 && - (applyDerivedStateFromProps( - workInProgress, - Component, - getDerivedStateFromProps$jscomp$0, - nextProps - ), + (applyDerivedStateFromProps( + workInProgress, + Component, + getDerivedStateFromProps$jscomp$0, + nextProps + ), (newState = workInProgress.memoizedState)), (contextType = hasForceUpdate || @@ -4706,28 +4713,28 @@ function updateClassComponent( ) || !1) ? (getDerivedStateFromProps || - ("function" !== typeof instance.UNSAFE_componentWillUpdate && - "function" !== typeof instance.componentWillUpdate) || - ("function" === typeof instance.componentWillUpdate && - instance.componentWillUpdate(nextProps, newState, oldContext), + ("function" !== typeof instance.UNSAFE_componentWillUpdate && + "function" !== typeof instance.componentWillUpdate) || + ("function" === typeof instance.componentWillUpdate && + instance.componentWillUpdate(nextProps, newState, oldContext), "function" === typeof instance.UNSAFE_componentWillUpdate && - instance.UNSAFE_componentWillUpdate( - nextProps, - newState, - oldContext - )), + instance.UNSAFE_componentWillUpdate( + nextProps, + newState, + oldContext + )), "function" === typeof instance.componentDidUpdate && - (workInProgress.flags |= 4), + (workInProgress.flags |= 4), "function" === typeof instance.getSnapshotBeforeUpdate && - (workInProgress.flags |= 1024)) + (workInProgress.flags |= 1024)) : ("function" !== typeof instance.componentDidUpdate || - (oldProps === current.memoizedProps && - oldState === current.memoizedState) || - (workInProgress.flags |= 4), + (oldProps === current.memoizedProps && + oldState === current.memoizedState) || + (workInProgress.flags |= 4), "function" !== typeof instance.getSnapshotBeforeUpdate || - (oldProps === current.memoizedProps && - oldState === current.memoizedState) || - (workInProgress.flags |= 1024), + (oldProps === current.memoizedProps && + oldState === current.memoizedState) || + (workInProgress.flags |= 1024), (workInProgress.memoizedProps = nextProps), (workInProgress.memoizedState = newState)), (instance.props = nextProps), @@ -4735,13 +4742,13 @@ function updateClassComponent( (instance.context = oldContext), (nextProps = contextType)) : ("function" !== typeof instance.componentDidUpdate || - (oldProps === current.memoizedProps && - oldState === current.memoizedState) || - (workInProgress.flags |= 4), + (oldProps === current.memoizedProps && + oldState === current.memoizedState) || + (workInProgress.flags |= 4), "function" !== typeof instance.getSnapshotBeforeUpdate || - (oldProps === current.memoizedProps && - oldState === current.memoizedState) || - (workInProgress.flags |= 1024), + (oldProps === current.memoizedProps && + oldState === current.memoizedState) || + (workInProgress.flags |= 1024), (nextProps = !1)); } return finishClassComponent( @@ -4777,11 +4784,11 @@ function finishClassComponent( workInProgress.flags |= 1; null !== current && didCaptureError ? ((workInProgress.child = reconcileChildFibers( - workInProgress, - current.child, - null, - renderLanes - )), + workInProgress, + current.child, + null, + renderLanes + )), (workInProgress.child = reconcileChildFibers( workInProgress, null, @@ -4797,12 +4804,12 @@ function pushHostRootContext(workInProgress) { var root = workInProgress.stateNode; root.pendingContext ? pushTopLevelContextObject( - workInProgress, - root.pendingContext, - root.pendingContext !== root.context - ) + workInProgress, + root.pendingContext, + root.pendingContext !== root.context + ) : root.context && - pushTopLevelContextObject(workInProgress, root.context, !1); + pushTopLevelContextObject(workInProgress, root.context, !1); pushHostContainer(workInProgress, root.containerInfo); } var SUSPENDED_MARKER = { dehydrated: null, treeContext: null, retryLane: 0 }; @@ -4831,8 +4838,8 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { 0 === (workInProgress.mode & 1) ? (workInProgress.lanes = 1) : shim$1() - ? (workInProgress.lanes = 8) - : (workInProgress.lanes = 1073741824), + ? (workInProgress.lanes = 8) + : (workInProgress.lanes = 1073741824), null ); didSuspend = nextProps.children; @@ -4845,11 +4852,11 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { ? ((showFallback.childLanes = 0), (showFallback.pendingProps = didSuspend)) : (showFallback = createFiberFromOffscreen( - didSuspend, - nextProps, - 0, - null - )), + didSuspend, + nextProps, + 0, + null + )), (current = createFiberFromFragment( current, nextProps, @@ -4897,11 +4904,11 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { null !== JSCompiler_temp ? (showFallback = createWorkInProgress(JSCompiler_temp, showFallback)) : ((showFallback = createFiberFromFragment( - showFallback, - didSuspend, - renderLanes, - null - )), + showFallback, + didSuspend, + renderLanes, + null + )), (showFallback.flags |= 2)); showFallback.return = workInProgress; nextProps.return = workInProgress; @@ -4914,10 +4921,10 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { null === didSuspend ? mountSuspenseOffscreenState(renderLanes) : { - baseLanes: didSuspend.baseLanes | renderLanes, - cachePool: null, - transitions: didSuspend.transitions - }; + baseLanes: didSuspend.baseLanes | renderLanes, + cachePool: null, + transitions: didSuspend.transitions + }; showFallback.memoizedState = didSuspend; showFallback.childLanes = current.childLanes & ~renderLanes; workInProgress.memoizedState = SUSPENDED_MARKER; @@ -4934,9 +4941,9 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { nextProps.sibling = null; null !== current && ((renderLanes = workInProgress.deletions), - null === renderLanes - ? ((workInProgress.deletions = [current]), (workInProgress.flags |= 16)) - : renderLanes.push(current)); + null === renderLanes + ? ((workInProgress.deletions = [current]), (workInProgress.flags |= 16)) + : renderLanes.push(current)); workInProgress.child = nextProps; workInProgress.memoizedState = null; return nextProps; @@ -5099,8 +5106,8 @@ function updateDehydratedSuspenseComponent( 0 !== didSuspend && didSuspend !== suspenseState.retryLane && ((suspenseState.retryLane = didSuspend), - markUpdateLaneFromFiberToRoot(current, didSuspend), - scheduleUpdateOnFiber(nextProps, current, didSuspend, -1)); + markUpdateLaneFromFiberToRoot(current, didSuspend), + scheduleUpdateOnFiber(nextProps, current, didSuspend, -1)); } renderDidSuspendDelayIfPossible(); suspenseState = createCapturedValue( @@ -5143,13 +5150,13 @@ function initSuspenseListRenderState( var renderState = workInProgress.memoizedState; null === renderState ? (workInProgress.memoizedState = { - isBackwards: isBackwards, - rendering: null, - renderingStartTime: 0, - last: lastContentRow, - tail: tail, - tailMode: tailMode - }) + isBackwards: isBackwards, + rendering: null, + renderingStartTime: 0, + last: lastContentRow, + tail: tail, + tailMode: tailMode + }) : ((renderState.isBackwards = isBackwards), (renderState.rendering = null), (renderState.renderingStartTime = 0), @@ -5167,7 +5174,7 @@ function updateSuspenseListComponent(current, workInProgress, renderLanes) { (nextProps = (nextProps & 1) | 2), (workInProgress.flags |= 128); else { if (null !== current && 0 !== (current.flags & 128)) - a: for (current = workInProgress.child; null !== current; ) { + a: for (current = workInProgress.child; null !== current;) { if (13 === current.tag) null !== current.memoizedState && scheduleSuspenseWorkOnFiber(current, renderLanes, workInProgress); @@ -5179,7 +5186,7 @@ function updateSuspenseListComponent(current, workInProgress, renderLanes) { continue; } if (current === workInProgress) break a; - for (; null === current.sibling; ) { + for (; null === current.sibling;) { if (null === current.return || current.return === workInProgress) break a; current = current.return; @@ -5195,11 +5202,11 @@ function updateSuspenseListComponent(current, workInProgress, renderLanes) { switch (revealOrder) { case "forwards": renderLanes = workInProgress.child; - for (revealOrder = null; null !== renderLanes; ) + for (revealOrder = null; null !== renderLanes;) (current = renderLanes.alternate), null !== current && - null === findFirstSuspended(current) && - (revealOrder = renderLanes), + null === findFirstSuspended(current) && + (revealOrder = renderLanes), (renderLanes = renderLanes.sibling); renderLanes = revealOrder; null === renderLanes @@ -5217,7 +5224,7 @@ function updateSuspenseListComponent(current, workInProgress, renderLanes) { case "backwards": renderLanes = null; revealOrder = workInProgress.child; - for (workInProgress.child = null; null !== revealOrder; ) { + for (workInProgress.child = null; null !== revealOrder;) { current = revealOrder.alternate; if (null !== current && null === findFirstSuspended(current)) { workInProgress.child = revealOrder; @@ -5248,8 +5255,8 @@ function resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress) { 0 === (workInProgress.mode & 1) && null !== current && ((current.alternate = null), - (workInProgress.alternate = null), - (workInProgress.flags |= 2)); + (workInProgress.alternate = null), + (workInProgress.flags |= 2)); } function bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) { null !== current && (workInProgress.dependencies = current.dependencies); @@ -5261,7 +5268,7 @@ function bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) { current = workInProgress.child; renderLanes = createWorkInProgress(current, current.pendingProps); workInProgress.child = renderLanes; - for (renderLanes.return = workInProgress; null !== current.sibling; ) + for (renderLanes.return = workInProgress; null !== current.sibling;) (current = current.sibling), (renderLanes = renderLanes.sibling = createWorkInProgress( current, @@ -5332,8 +5339,8 @@ function attemptEarlyBailoutIfNoScheduledUpdate( nextValue = workInProgress.memoizedState; null !== nextValue && ((nextValue.rendering = null), - (nextValue.tail = null), - (nextValue.lastEffect = null)); + (nextValue.tail = null), + (nextValue.lastEffect = null)); push(suspenseStackCursor, suspenseStackCursor.current); if (context) break; else return null; @@ -5349,7 +5356,7 @@ function attemptEarlyBailoutIfNoScheduledUpdate( function hadNoMutationsEffects(current, completedWork) { if (null !== current && current.child === completedWork.child) return !0; if (0 !== (completedWork.flags & 16)) return !1; - for (current = completedWork.child; null !== current; ) { + for (current = completedWork.child; null !== current;) { if (0 !== (current.flags & 12854) || 0 !== (current.subtreeFlags & 12854)) return !1; current = current.sibling; @@ -5360,13 +5367,13 @@ var appendAllChildren, updateHostContainer, updateHostComponent$1, updateHostText$1; -appendAllChildren = function( +appendAllChildren = function ( parent, workInProgress, needsVisibilityToggle, isHidden ) { - for (var node = workInProgress.child; null !== node; ) { + for (var node = workInProgress.child; null !== node;) { if (5 === node.tag) { var instance = node.stateNode; needsVisibilityToggle && @@ -5389,7 +5396,7 @@ appendAllChildren = function( continue; } if (node === workInProgress) break; - for (; null === node.sibling; ) { + for (; null === node.sibling;) { if (null === node.return || node.return === workInProgress) return; node = node.return; } @@ -5403,7 +5410,7 @@ function appendAllChildrenToContainer( needsVisibilityToggle, isHidden ) { - for (var node = workInProgress.child; null !== node; ) { + for (var node = workInProgress.child; null !== node;) { if (5 === node.tag) { var instance = node.stateNode; needsVisibilityToggle && @@ -5426,7 +5433,7 @@ function appendAllChildrenToContainer( continue; } if (node === workInProgress) break; - for (; null === node.sibling; ) { + for (; null === node.sibling;) { if (null === node.return || node.return === workInProgress) return; node = node.return; } @@ -5434,7 +5441,7 @@ function appendAllChildrenToContainer( node = node.sibling; } } -updateHostContainer = function(current, workInProgress) { +updateHostContainer = function (current, workInProgress) { var portalOrRoot = workInProgress.stateNode; if (!hadNoMutationsEffects(current, workInProgress)) { current = portalOrRoot.containerInfo; @@ -5445,7 +5452,7 @@ updateHostContainer = function(current, workInProgress) { completeRoot(current, newChildSet); } }; -updateHostComponent$1 = function(current, workInProgress, type, newProps) { +updateHostComponent$1 = function (current, workInProgress, type, newProps) { type = current.stateNode; var oldProps = current.memoizedProps; if ( @@ -5464,8 +5471,8 @@ updateHostComponent$1 = function(current, workInProgress, type, newProps) { newProps, recyclableInstance.canonical.viewConfig.validAttributes )), - (recyclableInstance.canonical.currentProps = newProps), - (updatePayload = oldProps)); + (recyclableInstance.canonical.currentProps = newProps), + (updatePayload = oldProps)); current && null === updatePayload ? (workInProgress.stateNode = type) : ((newProps = updatePayload), @@ -5476,8 +5483,8 @@ updateHostComponent$1 = function(current, workInProgress, type, newProps) { ? cloneNodeWithNewProps(oldProps, newProps) : cloneNode(oldProps) : null !== newProps - ? cloneNodeWithNewChildrenAndProps(oldProps, newProps) - : cloneNodeWithNewChildren(oldProps), + ? cloneNodeWithNewChildrenAndProps(oldProps, newProps) + : cloneNodeWithNewChildren(oldProps), canonical: type.canonical }), (workInProgress.stateNode = type), @@ -5486,7 +5493,7 @@ updateHostComponent$1 = function(current, workInProgress, type, newProps) { : appendAllChildren(type, workInProgress, !1, !1)); } }; -updateHostText$1 = function(current, workInProgress, oldText, newText) { +updateHostText$1 = function (current, workInProgress, oldText, newText) { oldText !== newText ? ((current = requiredContext(rootInstanceStackCursor.current)), (oldText = requiredContext(contextStackCursor$1.current)), @@ -5503,7 +5510,7 @@ function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { switch (renderState.tailMode) { case "hidden": hasRenderedATailFallback = renderState.tail; - for (var lastTailNode = null; null !== hasRenderedATailFallback; ) + for (var lastTailNode = null; null !== hasRenderedATailFallback;) null !== hasRenderedATailFallback.alternate && (lastTailNode = hasRenderedATailFallback), (hasRenderedATailFallback = hasRenderedATailFallback.sibling); @@ -5513,7 +5520,7 @@ function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { break; case "collapsed": lastTailNode = renderState.tail; - for (var lastTailNode$62 = null; null !== lastTailNode; ) + for (var lastTailNode$62 = null; null !== lastTailNode;) null !== lastTailNode.alternate && (lastTailNode$62 = lastTailNode), (lastTailNode = lastTailNode.sibling); null === lastTailNode$62 @@ -5525,19 +5532,19 @@ function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { } function bubbleProperties(completedWork) { var didBailout = - null !== completedWork.alternate && - completedWork.alternate.child === completedWork.child, + null !== completedWork.alternate && + completedWork.alternate.child === completedWork.child, newChildLanes = 0, subtreeFlags = 0; if (didBailout) - for (var child$63 = completedWork.child; null !== child$63; ) + for (var child$63 = completedWork.child; null !== child$63;) (newChildLanes |= child$63.lanes | child$63.childLanes), (subtreeFlags |= child$63.subtreeFlags & 14680064), (subtreeFlags |= child$63.flags & 14680064), (child$63.return = completedWork), (child$63 = child$63.sibling); else - for (child$63 = completedWork.child; null !== child$63; ) + for (child$63 = completedWork.child; null !== child$63;) (newChildLanes |= child$63.lanes | child$63.childLanes), (subtreeFlags |= child$63.subtreeFlags), (subtreeFlags |= child$63.flags), @@ -5550,6 +5557,12 @@ function bubbleProperties(completedWork) { function completeWork(current, workInProgress, renderLanes) { var newProps = workInProgress.pendingProps; popTreeContext(workInProgress); + if (workInProgress.flags & 1 && (workInProgress.type?.displayName || workInProgress.type?.name) !== "View") + insertUpdateComponents( + getComponentNameFromFiber(workInProgress), + workInProgress.flags, + workInProgress.key, + ); switch (workInProgress.tag) { case 2: case 16: @@ -5576,15 +5589,15 @@ function completeWork(current, workInProgress, renderLanes) { pop(contextStackCursor), resetWorkInProgressVersions(), renderLanes.pendingContext && - ((renderLanes.context = renderLanes.pendingContext), + ((renderLanes.context = renderLanes.pendingContext), (renderLanes.pendingContext = null)), (null !== current && null !== current.child) || - null === current || - (current.memoizedState.isDehydrated && - 0 === (workInProgress.flags & 256)) || - ((workInProgress.flags |= 1024), + null === current || + (current.memoizedState.isDehydrated && + 0 === (workInProgress.flags & 256)) || + ((workInProgress.flags |= 1024), null !== hydrationErrors && - (queueRecoverableErrors(hydrationErrors), + (queueRecoverableErrors(hydrationErrors), (hydrationErrors = null))), updateHostContainer(current, workInProgress), bubbleProperties(workInProgress), @@ -5700,10 +5713,10 @@ function completeWork(current, workInProgress, renderLanes) { renderLanes !== (null !== current && null !== current.memoizedState) && renderLanes && ((workInProgress.child.flags |= 8192), - 0 !== (workInProgress.mode & 1) && + 0 !== (workInProgress.mode & 1) && (null === current || 0 !== (suspenseStackCursor.current & 1) ? 0 === workInProgressRootExitStatus && - (workInProgressRootExitStatus = 3) + (workInProgressRootExitStatus = 3) : renderDidSuspendDelayIfPossible())); null !== workInProgress.updateQueue && (workInProgress.flags |= 4); bubbleProperties(workInProgress); @@ -5740,7 +5753,7 @@ function completeWork(current, workInProgress, renderLanes) { 0 !== workInProgressRootExitStatus || (null !== current && 0 !== (current.flags & 128)) ) - for (current = workInProgress.child; null !== current; ) { + for (current = workInProgress.child; null !== current;) { updatePayload = findFirstSuspended(current); if (null !== updatePayload) { workInProgress.flags |= 128; @@ -5748,10 +5761,10 @@ function completeWork(current, workInProgress, renderLanes) { current = updatePayload.updateQueue; null !== current && ((workInProgress.updateQueue = current), - (workInProgress.flags |= 4)); + (workInProgress.flags |= 4)); workInProgress.subtreeFlags = 0; current = renderLanes; - for (renderLanes = workInProgress.child; null !== renderLanes; ) + for (renderLanes = workInProgress.child; null !== renderLanes;) (newProps = renderLanes), (type = current), (newProps.flags &= 14680066), @@ -5780,9 +5793,9 @@ function completeWork(current, workInProgress, renderLanes) { null === type ? null : { - lanes: type.lanes, - firstContext: type.firstContext - })), + lanes: type.lanes, + firstContext: type.firstContext + })), (renderLanes = renderLanes.sibling); push( suspenseStackCursor, @@ -5795,9 +5808,9 @@ function completeWork(current, workInProgress, renderLanes) { null !== type.tail && now() > workInProgressRootRenderTargetTime && ((workInProgress.flags |= 128), - (newProps = !0), - cutOffTailIfNeeded(type, !1), - (workInProgress.lanes = 4194304)); + (newProps = !0), + cutOffTailIfNeeded(type, !1), + (workInProgress.lanes = 4194304)); } else { if (!newProps) @@ -5806,13 +5819,13 @@ function completeWork(current, workInProgress, renderLanes) { ) { if ( ((workInProgress.flags |= 128), - (newProps = !0), - (current = current.updateQueue), - null !== current && + (newProps = !0), + (current = current.updateQueue), + null !== current && ((workInProgress.updateQueue = current), - (workInProgress.flags |= 4)), - cutOffTailIfNeeded(type, !0), - null === type.tail && + (workInProgress.flags |= 4)), + cutOffTailIfNeeded(type, !0), + null === type.tail && "hidden" === type.tailMode && !updatePayload.alternate) ) @@ -5822,9 +5835,9 @@ function completeWork(current, workInProgress, renderLanes) { workInProgressRootRenderTargetTime && 1073741824 !== renderLanes && ((workInProgress.flags |= 128), - (newProps = !0), - cutOffTailIfNeeded(type, !1), - (workInProgress.lanes = 4194304)); + (newProps = !0), + cutOffTailIfNeeded(type, !1), + (workInProgress.lanes = 4194304)); type.isBackwards ? ((updatePayload.sibling = workInProgress.child), (workInProgress.child = updatePayload)) @@ -5853,11 +5866,11 @@ function completeWork(current, workInProgress, renderLanes) { popRenderLanes(), (renderLanes = null !== workInProgress.memoizedState), null !== current && - (null !== current.memoizedState) !== renderLanes && - (workInProgress.flags |= 8192), + (null !== current.memoizedState) !== renderLanes && + (workInProgress.flags |= 8192), renderLanes && 0 !== (workInProgress.mode & 1) ? 0 !== (subtreeRenderLanes & 1073741824) && - bubbleProperties(workInProgress) + bubbleProperties(workInProgress) : bubbleProperties(workInProgress), null ); @@ -5868,8 +5881,8 @@ function completeWork(current, workInProgress, renderLanes) { } throw Error( "Unknown unit of work tag (" + - workInProgress.tag + - "). This error is likely caused by a bug in React. Please file an issue." + workInProgress.tag + + "). This error is likely caused by a bug in React. Please file an issue." ); } function unwindWork(current, workInProgress) { @@ -5948,15 +5961,15 @@ function safelyCallDestroy(current, nearestMountedAncestor, destroy) { } var shouldFireAfterActiveInstanceBlur = !1; function commitBeforeMutationEffects(root, firstChild) { - for (nextEffect = firstChild; null !== nextEffect; ) + for (nextEffect = firstChild; null !== nextEffect;) if ( ((root = nextEffect), - (firstChild = root.child), - 0 !== (root.subtreeFlags & 1028) && null !== firstChild) + (firstChild = root.child), + 0 !== (root.subtreeFlags & 1028) && null !== firstChild) ) (firstChild.return = root), (nextEffect = firstChild); else - for (; null !== nextEffect; ) { + for (; null !== nextEffect;) { root = nextEffect; try { var current = root.alternate; @@ -6062,7 +6075,7 @@ function recursivelyTraverseDeletionEffects( nearestMountedAncestor, parent ) { - for (parent = parent.child; null !== parent; ) + for (parent = parent.child; null !== parent;) commitDeletionEffectsOnFiber(finishedRoot, nearestMountedAncestor, parent), (parent = parent.sibling); } @@ -6074,7 +6087,7 @@ function commitDeletionEffectsOnFiber( if (injectedHook && "function" === typeof injectedHook.onCommitFiberUnmount) try { injectedHook.onCommitFiberUnmount(rendererID, deletedFiber); - } catch (err) {} + } catch (err) { } switch (deletedFiber.tag) { case 5: safelyDetachRef(deletedFiber, nearestMountedAncestor); @@ -6113,11 +6126,11 @@ function commitDeletionEffectsOnFiber( (0 !== (_effect & 2) ? safelyCallDestroy(deletedFiber, nearestMountedAncestor, destroy) : 0 !== (_effect & 4) && - safelyCallDestroy( - deletedFiber, - nearestMountedAncestor, - destroy - )); + safelyCallDestroy( + deletedFiber, + nearestMountedAncestor, + destroy + )); effect = effect.next; } while (effect !== updateQueue); } @@ -6173,7 +6186,7 @@ function attachSuspenseRetryListeners(finishedWork) { var retryCache = finishedWork.stateNode; null === retryCache && (retryCache = finishedWork.stateNode = new PossiblyWeakSet()); - wakeables.forEach(function(wakeable) { + wakeables.forEach(function (wakeable) { var retry = resolveRetryWakeable.bind(null, finishedWork, wakeable); retryCache.has(wakeable) || (retryCache.add(wakeable), wakeable.then(retry, retry)); @@ -6195,7 +6208,7 @@ function recursivelyTraverseMutationEffects(root, parentFiber) { } } if (parentFiber.subtreeFlags & 12854) - for (parentFiber = parentFiber.child; null !== parentFiber; ) + for (parentFiber = parentFiber.child; null !== parentFiber;) commitMutationEffectsOnFiber(parentFiber, root), (parentFiber = parentFiber.sibling); } @@ -6255,8 +6268,8 @@ function commitMutationEffectsOnFiber(finishedWork, root) { root = finishedWork.child; root.flags & 8192 && ((current = null !== root.memoizedState), - (root.stateNode.isHidden = current), - !current || + (root.stateNode.isHidden = current), + !current || (null !== root.alternate && null !== root.alternate.memoizedState) || (globalMostRecentFallbackTime = now())); flags & 4 && attachSuspenseRetryListeners(finishedWork); @@ -6285,13 +6298,13 @@ function commitReconciliationEffects(finishedWork) { flags & 4096 && (finishedWork.flags &= -4097); } function commitLayoutEffects(finishedWork) { - for (nextEffect = finishedWork; null !== nextEffect; ) { + for (nextEffect = finishedWork; null !== nextEffect;) { var fiber = nextEffect, firstChild = fiber.child; if (0 !== (fiber.subtreeFlags & 8772) && null !== firstChild) (firstChild.return = fiber), (nextEffect = firstChild); else - for (fiber = finishedWork; null !== nextEffect; ) { + for (fiber = finishedWork; null !== nextEffect;) { firstChild = nextEffect; if (0 !== (firstChild.flags & 8772)) { var current = firstChild.alternate; @@ -6312,9 +6325,9 @@ function commitLayoutEffects(finishedWork) { firstChild.elementType === firstChild.type ? current.memoizedProps : resolveDefaultProps( - firstChild.type, - current.memoizedProps - ); + firstChild.type, + current.memoizedProps + ); instance.componentDidUpdate( prevProps, current.memoizedState, @@ -6435,8 +6448,8 @@ function requestEventTime() { return 0 !== (executionContext & 6) ? now() : -1 !== currentEventTime - ? currentEventTime - : (currentEventTime = now()); + ? currentEventTime + : (currentEventTime = now()); } function requestUpdateLane(fiber) { if (0 === (fiber.mode & 1)) return 1; @@ -6445,7 +6458,7 @@ function requestUpdateLane(fiber) { if (null !== ReactCurrentBatchConfig.transition) return ( 0 === currentEventTransitionLane && - (currentEventTransitionLane = claimNextTransitionLane()), + (currentEventTransitionLane = claimNextTransitionLane()), currentEventTransitionLane ); fiber = currentUpdatePriority; @@ -6465,33 +6478,37 @@ function requestUpdateLane(fiber) { return fiber; } function scheduleUpdateOnFiber(root, fiber, lane, eventTime) { + updatedComponentForProfiler = { + name: getComponentNameFromFiber(fiber), + key: fiber.key, + }; if (50 < nestedUpdateCount) throw ((nestedUpdateCount = 0), - (rootWithNestedUpdates = null), - 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." - )); + (rootWithNestedUpdates = null), + 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." + )); markRootUpdated(root, lane, eventTime); if (0 === (executionContext & 2) || root !== workInProgressRoot) root === workInProgressRoot && (0 === (executionContext & 2) && (workInProgressRootInterleavedUpdatedLanes |= lane), - 4 === workInProgressRootExitStatus && + 4 === workInProgressRootExitStatus && markRootSuspended$1(root, workInProgressRootRenderLanes)), ensureRootIsScheduled(root, eventTime), 1 === lane && - 0 === executionContext && - 0 === (fiber.mode & 1) && - ((workInProgressRootRenderTargetTime = now() + 500), + 0 === executionContext && + 0 === (fiber.mode & 1) && + ((workInProgressRootRenderTargetTime = now() + 500), includesLegacySyncCallbacks && flushSyncCallbacks()); } function ensureRootIsScheduled(root, currentTime) { for ( var existingCallbackNode = root.callbackNode, - suspendedLanes = root.suspendedLanes, - pingedLanes = root.pingedLanes, - expirationTimes = root.expirationTimes, - lanes = root.pendingLanes; + suspendedLanes = root.suspendedLanes, + pingedLanes = root.pingedLanes, + expirationTimes = root.expirationTimes, + lanes = root.pendingLanes; 0 < lanes; ) { @@ -6514,7 +6531,7 @@ function ensureRootIsScheduled(root, currentTime) { (root.callbackPriority = 0); else if ( ((currentTime = suspendedLanes & -suspendedLanes), - root.callbackPriority !== currentTime) + root.callbackPriority !== currentTime) ) { null != existingCallbackNode && cancelCallback(existingCallbackNode); if (1 === currentTime) @@ -6603,15 +6620,15 @@ function performConcurrentWorkOnRoot(root, didTimeout) { if (0 !== didTimeout) { 2 === didTimeout && ((prevExecutionContext = getLanesToRetrySynchronouslyOnError(root)), - 0 !== prevExecutionContext && + 0 !== prevExecutionContext && ((lanes = prevExecutionContext), - (didTimeout = recoverFromConcurrentError(root, prevExecutionContext)))); + (didTimeout = recoverFromConcurrentError(root, prevExecutionContext)))); if (1 === didTimeout) throw ((originalCallbackNode = workInProgressRootFatalError), - prepareFreshStack(root, 0), - markRootSuspended$1(root, lanes), - ensureRootIsScheduled(root, now()), - originalCallbackNode); + prepareFreshStack(root, 0), + markRootSuspended$1(root, lanes), + ensureRootIsScheduled(root, now()), + originalCallbackNode); if (6 === didTimeout) markRootSuspended$1(root, lanes); else { prevExecutionContext = root.current.alternate; @@ -6619,18 +6636,18 @@ function performConcurrentWorkOnRoot(root, didTimeout) { 0 === (lanes & 30) && !isRenderConsistentWithExternalStores(prevExecutionContext) && ((didTimeout = renderRootSync(root, lanes)), - 2 === didTimeout && + 2 === didTimeout && ((prevDispatcher = getLanesToRetrySynchronouslyOnError(root)), - 0 !== prevDispatcher && + 0 !== prevDispatcher && ((lanes = prevDispatcher), - (didTimeout = recoverFromConcurrentError(root, prevDispatcher)))), - 1 === didTimeout) + (didTimeout = recoverFromConcurrentError(root, prevDispatcher)))), + 1 === didTimeout) ) throw ((originalCallbackNode = workInProgressRootFatalError), - prepareFreshStack(root, 0), - markRootSuspended$1(root, lanes), - ensureRootIsScheduled(root, now()), - originalCallbackNode); + prepareFreshStack(root, 0), + markRootSuspended$1(root, lanes), + ensureRootIsScheduled(root, now()), + originalCallbackNode); root.finishedWork = prevExecutionContext; root.finishedLanes = lanes; switch (didTimeout) { @@ -6649,7 +6666,7 @@ function performConcurrentWorkOnRoot(root, didTimeout) { if ( (lanes & 130023424) === lanes && ((didTimeout = globalMostRecentFallbackTime + 500 - now()), - 10 < didTimeout) + 10 < didTimeout) ) { if (0 !== getNextLanes(root, 0)) break; prevExecutionContext = root.suspendedLanes; @@ -6679,7 +6696,7 @@ function performConcurrentWorkOnRoot(root, didTimeout) { markRootSuspended$1(root, lanes); if ((lanes & 4194240) === lanes) break; didTimeout = root.eventTimes; - for (prevExecutionContext = -1; 0 < lanes; ) { + for (prevExecutionContext = -1; 0 < lanes;) { var index$4 = 31 - clz32(lanes); prevDispatcher = 1 << index$4; index$4 = didTimeout[index$4]; @@ -6692,16 +6709,16 @@ function performConcurrentWorkOnRoot(root, didTimeout) { (120 > lanes ? 120 : 480 > lanes - ? 480 - : 1080 > lanes - ? 1080 - : 1920 > lanes - ? 1920 - : 3e3 > lanes - ? 3e3 - : 4320 > lanes - ? 4320 - : 1960 * ceil(lanes / 1960)) - lanes; + ? 480 + : 1080 > lanes + ? 1080 + : 1920 > lanes + ? 1920 + : 3e3 > lanes + ? 3e3 + : 4320 > lanes + ? 4320 + : 1960 * ceil(lanes / 1960)) - lanes; if (10 < lanes) { root.timeoutHandle = scheduleTimeout( commitRoot.bind( @@ -6744,20 +6761,20 @@ function recoverFromConcurrentError(root, errorRetryLanes) { root = renderRootSync(root, errorRetryLanes); 2 !== root && ((errorRetryLanes = workInProgressRootRecoverableErrors), - (workInProgressRootRecoverableErrors = errorsFromFirstAttempt), - null !== errorRetryLanes && queueRecoverableErrors(errorRetryLanes)); + (workInProgressRootRecoverableErrors = errorsFromFirstAttempt), + null !== errorRetryLanes && queueRecoverableErrors(errorRetryLanes)); return root; } function queueRecoverableErrors(errors) { null === workInProgressRootRecoverableErrors ? (workInProgressRootRecoverableErrors = errors) : workInProgressRootRecoverableErrors.push.apply( - workInProgressRootRecoverableErrors, - errors - ); + workInProgressRootRecoverableErrors, + errors + ); } function isRenderConsistentWithExternalStores(finishedWork) { - for (var node = finishedWork; ; ) { + for (var node = finishedWork; ;) { if (node.flags & 16384) { var updateQueue = node.updateQueue; if ( @@ -6780,7 +6797,7 @@ function isRenderConsistentWithExternalStores(finishedWork) { (updateQueue.return = node), (node = updateQueue); else { if (node === finishedWork) break; - for (; null === node.sibling; ) { + for (; null === node.sibling;) { if (null === node.return || node.return === finishedWork) return !0; node = node.return; } @@ -6795,7 +6812,7 @@ function markRootSuspended$1(root, suspendedLanes) { suspendedLanes &= ~workInProgressRootInterleavedUpdatedLanes; root.suspendedLanes |= suspendedLanes; root.pingedLanes &= ~suspendedLanes; - for (root = root.expirationTimes; 0 < suspendedLanes; ) { + for (root = root.expirationTimes; 0 < suspendedLanes;) { var index$6 = 31 - clz32(suspendedLanes), lane = 1 << index$6; root[index$6] = -1; @@ -6813,14 +6830,14 @@ function performSyncWorkOnRoot(root) { var errorRetryLanes = getLanesToRetrySynchronouslyOnError(root); 0 !== errorRetryLanes && ((lanes = errorRetryLanes), - (exitStatus = recoverFromConcurrentError(root, errorRetryLanes))); + (exitStatus = recoverFromConcurrentError(root, errorRetryLanes))); } if (1 === exitStatus) throw ((exitStatus = workInProgressRootFatalError), - prepareFreshStack(root, 0), - markRootSuspended$1(root, lanes), - ensureRootIsScheduled(root, now()), - exitStatus); + prepareFreshStack(root, 0), + markRootSuspended$1(root, lanes), + ensureRootIsScheduled(root, now()), + exitStatus); if (6 === exitStatus) throw Error("Root did not complete. This is a bug in React."); root.finishedWork = root.current.alternate; @@ -6844,7 +6861,7 @@ function prepareFreshStack(root, lanes) { -1 !== timeoutHandle && ((root.timeoutHandle = -1), cancelTimeout(timeoutHandle)); if (null !== workInProgress) - for (timeoutHandle = workInProgress.return; null !== timeoutHandle; ) { + for (timeoutHandle = workInProgress.return; null !== timeoutHandle;) { var interruptedWork = timeoutHandle; popTreeContext(interruptedWork); switch (interruptedWork.tag) { @@ -6892,8 +6909,8 @@ function prepareFreshStack(root, lanes) { for (lanes = 0; lanes < concurrentQueues.length; lanes++) if ( ((timeoutHandle = concurrentQueues[lanes]), - (interruptedWork = timeoutHandle.interleaved), - null !== interruptedWork) + (interruptedWork = timeoutHandle.interleaved), + null !== interruptedWork) ) { timeoutHandle.interleaved = null; var firstInterleavedUpdate = interruptedWork.next, @@ -7130,10 +7147,10 @@ function renderRootSync(root, lanes) { return workInProgressRootExitStatus; } function workLoopSync() { - for (; null !== workInProgress; ) performUnitOfWork(workInProgress); + for (; null !== workInProgress;) performUnitOfWork(workInProgress); } function workLoopConcurrent() { - for (; null !== workInProgress && !shouldYield(); ) + for (; null !== workInProgress && !shouldYield();) performUnitOfWork(workInProgress); } function performUnitOfWork(unitOfWork) { @@ -7150,7 +7167,7 @@ function completeUnitOfWork(unitOfWork) { if (0 === (completedWork.flags & 32768)) { if ( ((current = completeWork(current, completedWork, subtreeRenderLanes)), - null !== current) + null !== current) ) { workInProgress = current; return; @@ -7184,6 +7201,9 @@ function completeUnitOfWork(unitOfWork) { function commitRoot(root, recoverableErrors, transitions) { var previousUpdateLanePriority = currentUpdatePriority, prevTransition = ReactCurrentBatchConfig$2.transition; + defrost.writeInLogFiles(Date.now() + "", { list: updatedComponents, change: updatedComponentForProfiler }) + updatedComponents = [] + updatedComponentForProfiler = null try { (ReactCurrentBatchConfig$2.transition = null), (currentUpdatePriority = 1), @@ -7224,15 +7244,15 @@ function commitRootImpl( markRootFinished(root, remainingLanes); root === workInProgressRoot && ((workInProgress = workInProgressRoot = null), - (workInProgressRootRenderLanes = 0)); + (workInProgressRootRenderLanes = 0)); (0 === (transitions.subtreeFlags & 2064) && 0 === (transitions.flags & 2064)) || rootDoesHavePassiveEffects || ((rootDoesHavePassiveEffects = !0), - scheduleCallback$1(NormalPriority, function() { - flushPassiveEffects(); - return null; - })); + scheduleCallback$1(NormalPriority, function () { + flushPassiveEffects(); + return null; + })); remainingLanes = 0 !== (transitions.flags & 15990); if (0 !== (transitions.subtreeFlags & 15990) || remainingLanes) { remainingLanes = ReactCurrentBatchConfig$2.transition; @@ -7253,8 +7273,8 @@ function commitRootImpl( } else root.current = transitions; rootDoesHavePassiveEffects && ((rootDoesHavePassiveEffects = !1), - (rootWithPendingPassiveEffects = root), - (pendingPassiveEffectsLanes = lanes)); + (rootWithPendingPassiveEffects = root), + (pendingPassiveEffectsLanes = lanes)); remainingLanes = root.pendingLanes; 0 === remainingLanes && (legacyErrorBoundariesThatAlreadyFailed = null); onCommitRoot(transitions.stateNode, renderPriorityLevel); @@ -7272,9 +7292,9 @@ function commitRootImpl( }); if (hasUncaughtError) throw ((hasUncaughtError = !1), - (root = firstUncaughtError), - (firstUncaughtError = null), - root); + (root = firstUncaughtError), + (firstUncaughtError = null), + root); 0 !== (pendingPassiveEffectsLanes & 1) && 0 !== root.tag && flushPassiveEffects(); @@ -7305,7 +7325,7 @@ function flushPassiveEffects() { throw Error("Cannot flush passive effects while already rendering."); var prevExecutionContext = executionContext; executionContext |= 4; - for (nextEffect = renderPriority.current; null !== nextEffect; ) { + for (nextEffect = renderPriority.current; null !== nextEffect;) { var fiber = nextEffect, child = fiber.child; if (0 !== (nextEffect.flags & 16)) { @@ -7313,7 +7333,7 @@ function flushPassiveEffects() { if (null !== deletions) { for (var i = 0; i < deletions.length; i++) { var fiberToDelete = deletions[i]; - for (nextEffect = fiberToDelete; null !== nextEffect; ) { + for (nextEffect = fiberToDelete; null !== nextEffect;) { var fiber$jscomp$0 = nextEffect; switch (fiber$jscomp$0.tag) { case 0: @@ -7326,7 +7346,7 @@ function flushPassiveEffects() { (child$jscomp$0.return = fiber$jscomp$0), (nextEffect = child$jscomp$0); else - for (; null !== nextEffect; ) { + for (; null !== nextEffect;) { fiber$jscomp$0 = nextEffect; var sibling = fiber$jscomp$0.sibling, returnFiber = fiber$jscomp$0.return; @@ -7362,7 +7382,7 @@ function flushPassiveEffects() { if (0 !== (fiber.subtreeFlags & 2064) && null !== child) (child.return = fiber), (nextEffect = child); else - b: for (; null !== nextEffect; ) { + b: for (; null !== nextEffect;) { fiber = nextEffect; if (0 !== (fiber.flags & 2048)) switch (fiber.tag) { @@ -7381,13 +7401,13 @@ function flushPassiveEffects() { } } var finishedWork = renderPriority.current; - for (nextEffect = finishedWork; null !== nextEffect; ) { + for (nextEffect = finishedWork; null !== nextEffect;) { child = nextEffect; var firstChild = child.child; if (0 !== (child.subtreeFlags & 2064) && null !== firstChild) (firstChild.return = child), (nextEffect = firstChild); else - b: for (child = finishedWork; null !== nextEffect; ) { + b: for (child = finishedWork; null !== nextEffect;) { deletions = nextEffect; if (0 !== (deletions.flags & 2048)) try { @@ -7421,7 +7441,7 @@ function flushPassiveEffects() { ) try { injectedHook.onPostCommitFiberRoot(rendererID, renderPriority); - } catch (err) {} + } catch (err) { } JSCompiler_inline_result = !0; } return JSCompiler_inline_result; @@ -7439,7 +7459,7 @@ function captureCommitPhaseErrorOnRoot(rootFiber, sourceFiber, error) { sourceFiber = requestEventTime(); null !== rootFiber && (markRootUpdated(rootFiber, 1, sourceFiber), - ensureRootIsScheduled(rootFiber, sourceFiber)); + ensureRootIsScheduled(rootFiber, sourceFiber)); } function captureCommitPhaseError(sourceFiber, nearestMountedAncestor, error) { if (3 === sourceFiber.tag) @@ -7461,7 +7481,7 @@ function captureCommitPhaseError(sourceFiber, nearestMountedAncestor, error) { var instance = nearestMountedAncestor.stateNode; if ( "function" === - typeof nearestMountedAncestor.type.getDerivedStateFromError || + typeof nearestMountedAncestor.type.getDerivedStateFromError || ("function" === typeof instance.componentDidCatch && (null === legacyErrorBoundariesThatAlreadyFailed || !legacyErrorBoundariesThatAlreadyFailed.has(instance))) @@ -7480,7 +7500,7 @@ function captureCommitPhaseError(sourceFiber, nearestMountedAncestor, error) { sourceFiber = requestEventTime(); null !== nearestMountedAncestor && (markRootUpdated(nearestMountedAncestor, 1, sourceFiber), - ensureRootIsScheduled(nearestMountedAncestor, sourceFiber)); + ensureRootIsScheduled(nearestMountedAncestor, sourceFiber)); break; } } @@ -7495,10 +7515,10 @@ function pingSuspendedRoot(root, wakeable, pingedLanes) { workInProgressRoot === root && (workInProgressRootRenderLanes & pingedLanes) === pingedLanes && (4 === workInProgressRootExitStatus || - (3 === workInProgressRootExitStatus && - (workInProgressRootRenderLanes & 130023424) === + (3 === workInProgressRootExitStatus && + (workInProgressRootRenderLanes & 130023424) === workInProgressRootRenderLanes && - 500 > now() - globalMostRecentFallbackTime) + 500 > now() - globalMostRecentFallbackTime) ? prepareFreshStack(root, 0) : (workInProgressRootPingedLanes |= pingedLanes)); ensureRootIsScheduled(root, wakeable); @@ -7514,7 +7534,7 @@ function retryTimedOutBoundary(boundaryFiber, retryLane) { boundaryFiber = markUpdateLaneFromFiberToRoot(boundaryFiber, retryLane); null !== boundaryFiber && (markRootUpdated(boundaryFiber, retryLane, eventTime), - ensureRootIsScheduled(boundaryFiber, eventTime)); + ensureRootIsScheduled(boundaryFiber, eventTime)); } function retryDehydratedSuspenseBoundary(boundaryFiber) { var suspenseState = boundaryFiber.memoizedState, @@ -7542,7 +7562,7 @@ function resolveRetryWakeable(boundaryFiber, wakeable) { retryTimedOutBoundary(boundaryFiber, retryLane); } var beginWork$1; -beginWork$1 = function(current, workInProgress, renderLanes) { +beginWork$1 = function (current, workInProgress, renderLanes) { if (null !== current) if ( current.memoizedProps !== workInProgress.pendingProps || @@ -7670,8 +7690,8 @@ beginWork$1 = function(current, workInProgress, renderLanes) { } throw Error( "Element type is invalid. Received a promise that resolves to: " + - Component + - ". Lazy element type must resolve to a class or function." + Component + + ". Lazy element type must resolve to a class or function." ); } return workInProgress; @@ -7718,10 +7738,10 @@ beginWork$1 = function(current, workInProgress, renderLanes) { context = workInProgress.memoizedState.element; context === Component ? (workInProgress = bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderLanes - )) + current, + workInProgress, + renderLanes + )) : (reconcileChildren(current, workInProgress, context, renderLanes), (workInProgress = workInProgress.child)); return workInProgress; @@ -7746,11 +7766,11 @@ beginWork$1 = function(current, workInProgress, renderLanes) { (Component = workInProgress.pendingProps), null === current ? (workInProgress.child = reconcileChildFibers( - workInProgress, - null, - Component, - renderLanes - )) + workInProgress, + null, + Component, + renderLanes + )) : reconcileChildren(current, workInProgress, Component, renderLanes), workInProgress.child ); @@ -7824,7 +7844,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { } else for ( hasContext = workInProgress.child, - null !== hasContext && (hasContext.return = workInProgress); + null !== hasContext && (hasContext.return = workInProgress); null !== hasContext; ) { @@ -7887,7 +7907,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { } else newValue = hasContext.child; if (null !== newValue) newValue.return = hasContext; else - for (newValue = hasContext; null !== newValue; ) { + for (newValue = hasContext; null !== newValue;) { if (newValue === workInProgress) { newValue = null; break; @@ -7975,8 +7995,8 @@ beginWork$1 = function(current, workInProgress, renderLanes) { } throw Error( "Unknown unit of work tag (" + - workInProgress.tag + - "). This error is likely caused by a bug in React. Please file an issue." + workInProgress.tag + + "). This error is likely caused by a bug in React. Please file an issue." ); }; function scheduleCallback$1(priorityLevel, callback) { @@ -8017,11 +8037,11 @@ function createWorkInProgress(current, pendingProps) { var workInProgress = current.alternate; null === workInProgress ? ((workInProgress = createFiber( - current.tag, - pendingProps, - current.key, - current.mode - )), + current.tag, + pendingProps, + current.key, + current.mode + )), (workInProgress.elementType = current.elementType), (workInProgress.type = current.type), (workInProgress.stateNode = current.stateNode), @@ -8114,7 +8134,7 @@ function createFiberFromTypeAndProps( } throw Error( "Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: " + - ((null == type ? type : typeof type) + ".") + ((null == type ? type : typeof type) + ".") ); } key = createFiber(fiberTag, pendingProps, key, mode); @@ -8257,7 +8277,7 @@ function updateContainer(element, container, parentComponent, callback) { element = enqueueUpdate(current, container, lane); null !== element && (scheduleUpdateOnFiber(element, current, lane, eventTime), - entangleTransitions(element, current, lane)); + entangleTransitions(element, current, lane)); return lane; } function emptyFindFiberByHostInstance() { @@ -8273,13 +8293,13 @@ function findNodeHandle(componentOrHandle) { return null == componentOrHandle ? componentOrHandle : componentOrHandle.canonical - ? componentOrHandle.canonical._nativeTag - : componentOrHandle._nativeTag; + ? componentOrHandle.canonical._nativeTag + : componentOrHandle._nativeTag; } function onRecoverableError(error) { console.error(error); } -batchedUpdatesImpl = function(fn, a) { +batchedUpdatesImpl = function (fn, a) { var prevExecutionContext = executionContext; executionContext |= 1; try { @@ -8287,7 +8307,7 @@ batchedUpdatesImpl = function(fn, a) { } finally { (executionContext = prevExecutionContext), 0 === executionContext && - ((workInProgressRootRenderTargetTime = now() + 500), + ((workInProgressRootRenderTargetTime = now() + 500), includesLegacySyncCallbacks && flushSyncCallbacks()); } }; @@ -8298,12 +8318,12 @@ var roots = new Map(), version: "18.2.0-next-9e3b772b8-20220608", rendererPackageName: "react-native-renderer", rendererConfig: { - getInspectorDataForViewTag: function() { + getInspectorDataForViewTag: function () { throw Error( "getInspectorDataForViewTag() is not available in production" ); }, - getInspectorDataForViewAtPoint: function() { + getInspectorDataForViewAtPoint: function () { throw Error( "getInspectorDataForViewAtPoint() is not available in production." ); @@ -8325,7 +8345,7 @@ var internals$jscomp$inline_1180 = { setSuspenseHandler: null, scheduleUpdate: null, currentDispatcherRef: ReactSharedInternals.ReactCurrentDispatcher, - findHostInstanceByFiber: function(fiber) { + findHostInstanceByFiber: function (fiber) { fiber = findCurrentHostFiber(fiber); return null === fiber ? null : fiber.stateNode; }, @@ -8350,9 +8370,9 @@ if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { internals$jscomp$inline_1180 )), (injectedHook = hook$jscomp$inline_1181); - } catch (err) {} + } catch (err) { } } -exports.createPortal = function(children, containerTag) { +exports.createPortal = function (children, containerTag) { return createPortal( children, containerTag, @@ -8360,19 +8380,19 @@ exports.createPortal = function(children, containerTag) { 2 < arguments.length && void 0 !== arguments[2] ? arguments[2] : null ); }; -exports.dispatchCommand = function(handle, command, args) { +exports.dispatchCommand = function (handle, command, args) { null != handle._nativeTag && (null != handle._internalInstanceHandle ? ((handle = handle._internalInstanceHandle.stateNode), null != handle && - nativeFabricUIManager.dispatchCommand(handle.node, command, args)) + nativeFabricUIManager.dispatchCommand(handle.node, command, args)) : ReactNativePrivateInterface.UIManager.dispatchViewManagerCommand( - handle._nativeTag, - command, - args - )); + handle._nativeTag, + command, + args + )); }; -exports.findHostInstance_DEPRECATED = function(componentOrHandle) { +exports.findHostInstance_DEPRECATED = function (componentOrHandle) { if (null == componentOrHandle) return null; if (componentOrHandle._nativeTag) return componentOrHandle; if (componentOrHandle.canonical && componentOrHandle.canonical._nativeTag) @@ -8381,35 +8401,35 @@ exports.findHostInstance_DEPRECATED = function(componentOrHandle) { return null == componentOrHandle ? componentOrHandle : componentOrHandle.canonical - ? componentOrHandle.canonical - : componentOrHandle; + ? componentOrHandle.canonical + : componentOrHandle; }; exports.findNodeHandle = findNodeHandle; exports.getInspectorDataForInstance = void 0; -exports.render = function(element, containerTag, callback, concurrentRoot) { +exports.render = function (element, containerTag, callback, concurrentRoot) { var root = roots.get(containerTag); root || ((root = concurrentRoot ? 1 : 0), - (concurrentRoot = new FiberRootNode( - containerTag, - root, - !1, - "", - onRecoverableError - )), - (root = createFiber(3, null, null, 1 === root ? 1 : 0)), - (concurrentRoot.current = root), - (root.stateNode = concurrentRoot), - (root.memoizedState = { - element: null, - isDehydrated: !1, - cache: null, - transitions: null, - pendingSuspenseBoundaries: null - }), - initializeUpdateQueue(root), - (root = concurrentRoot), - roots.set(containerTag, root)); + (concurrentRoot = new FiberRootNode( + containerTag, + root, + !1, + "", + onRecoverableError + )), + (root = createFiber(3, null, null, 1 === root ? 1 : 0)), + (concurrentRoot.current = root), + (root.stateNode = concurrentRoot), + (root.memoizedState = { + element: null, + isDehydrated: !1, + cache: null, + transitions: null, + pendingSuspenseBoundaries: null + }), + initializeUpdateQueue(root), + (root = concurrentRoot), + roots.set(containerTag, root)); updateContainer(element, root, null, callback); a: if (((element = root.current), element.child)) switch (element.child.tag) { @@ -8422,24 +8442,24 @@ exports.render = function(element, containerTag, callback, concurrentRoot) { else element = null; return element; }; -exports.sendAccessibilityEvent = function(handle, eventType) { +exports.sendAccessibilityEvent = function (handle, eventType) { null != handle._nativeTag && (null != handle._internalInstanceHandle ? ((handle = handle._internalInstanceHandle.stateNode), null != handle && - nativeFabricUIManager.sendAccessibilityEvent(handle.node, eventType)) + nativeFabricUIManager.sendAccessibilityEvent(handle.node, eventType)) : ReactNativePrivateInterface.legacySendAccessibilityEvent( - handle._nativeTag, - eventType - )); + handle._nativeTag, + eventType + )); }; -exports.stopSurface = function(containerTag) { +exports.stopSurface = function (containerTag) { var root = roots.get(containerTag); root && - updateContainer(null, root, null, function() { + updateContainer(null, root, null, function () { roots.delete(containerTag); }); }; -exports.unmountComponentAtNode = function(containerTag) { +exports.unmountComponentAtNode = function (containerTag) { this.stopSurface(containerTag); }; diff --git a/node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js b/node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js index 1680f6c..3fe1bf8 100644 --- a/node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js +++ b/node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js @@ -12,3292 +12,3141 @@ */ 'use strict'; - +import defrost from '@d11/de-frost' 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"; + /* 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 React = require("react"); -require("react-native/Libraries/ReactPrivate/ReactNativePrivateInitializeCore"); -var ReactNativePrivateInterface = require("react-native/Libraries/ReactPrivate/ReactNativePrivateInterface"); -var Scheduler = require("scheduler"); + var React = require("react"); + require("react-native/Libraries/ReactPrivate/ReactNativePrivateInitializeCore"); + var updatedComponents = []; + var updatedComponentForProfiler = null; + function insertUpdateComponents(componentName, flags, key) { + updatedComponents.push({ componentName, flags, key }); + } + var ReactNativePrivateInterface = require("react-native/Libraries/ReactPrivate/ReactNativePrivateInterface"); + var Scheduler = require("scheduler"); -var ReactSharedInternals = - React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; + var ReactSharedInternals = + React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; -// by calls to these methods by a Babel plugin. -// -// In PROD (or in packages without access to React internals), -// they are left as they are instead. + // by calls to these methods by a Babel plugin. + // + // In PROD (or in packages without access to React internals), + // they are left as they are instead. -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]; - } + 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("warn", format, args); + } } - - printWarning("error", format, args); } - } -} - -function printWarning(level, format, args) { - // When changing this logic, you might want to also - // update consoleWithStackDev.www.js as well. - { - var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; - var stack = ReactDebugCurrentFrame.getStackAddendum(); - - if (stack !== "") { - format += "%s"; - args = args.concat([stack]); - } // eslint-disable-next-line react-internal/safe-string-coercion + 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 argsWithFormat = args.map(function(item) { - return String(item); - }); // Careful: RN currently depends on this prefix + printWarning("error", format, args); + } + } + } - argsWithFormat.unshift("Warning: " + format); // We intentionally don't use spread (or .apply) directly because it - // breaks IE9: https://github.com/facebook/react/issues/13610 - // eslint-disable-next-line react-internal/no-production-logging + function printWarning(level, format, args) { + // When changing this logic, you might want to also + // update consoleWithStackDev.www.js as well. + { + var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; + var stack = ReactDebugCurrentFrame.getStackAddendum(); - Function.prototype.apply.call(console[level], console, argsWithFormat); - } -} + if (stack !== "") { + format += "%s"; + args = args.concat([stack]); + } // eslint-disable-next-line react-internal/safe-string-coercion -function invokeGuardedCallbackProd(name, func, context, a, b, c, d, e, f) { - var funcArgs = Array.prototype.slice.call(arguments, 3); + var argsWithFormat = args.map(function (item) { + return String(item); + }); // Careful: RN currently depends on this prefix - try { - func.apply(context, funcArgs); - } catch (error) { - this.onError(error); - } -} + argsWithFormat.unshift("Warning: " + format); // We intentionally don't use spread (or .apply) directly because it + // breaks IE9: https://github.com/facebook/react/issues/13610 + // eslint-disable-next-line react-internal/no-production-logging -var invokeGuardedCallbackImpl = invokeGuardedCallbackProd; - -{ - // In DEV mode, we swap out invokeGuardedCallback for a special version - // that plays more nicely with the browser's DevTools. The idea is to preserve - // "Pause on exceptions" behavior. Because React wraps all user-provided - // functions in invokeGuardedCallback, and the production version of - // invokeGuardedCallback uses a try-catch, all user exceptions are treated - // like caught exceptions, and the DevTools won't pause unless the developer - // takes the extra step of enabling pause on caught exceptions. This is - // unintuitive, though, because even though React has caught the error, from - // the developer's perspective, the error is uncaught. - // - // To preserve the expected "Pause on exceptions" behavior, we don't use a - // try-catch in DEV. Instead, we synchronously dispatch a fake event to a fake - // DOM node, and call the user-provided callback from inside an event handler - // for that fake event. If the callback throws, the error is "captured" using - // a global event handler. But because the error happens in a different - // event loop context, it does not interrupt the normal program flow. - // Effectively, this gives us try-catch behavior without actually using - // try-catch. Neat! - // Check that the browser supports the APIs we need to implement our special - // DEV version of invokeGuardedCallback - if ( - typeof window !== "undefined" && - typeof window.dispatchEvent === "function" && - typeof document !== "undefined" && - typeof document.createEvent === "function" - ) { - var fakeNode = document.createElement("react"); - - invokeGuardedCallbackImpl = function invokeGuardedCallbackDev( - name, - func, - context, - a, - b, - c, - d, - e, - f - ) { - // If document doesn't exist we know for sure we will crash in this method - // when we call document.createEvent(). However this can cause confusing - // errors: https://github.com/facebook/create-react-app/issues/3482 - // So we preemptively throw with a better message instead. - if (typeof document === "undefined" || document === null) { - throw new Error( - "The `document` global was defined when React was initialized, but is not " + - "defined anymore. This can happen in a test environment if a component " + - "schedules an update from an asynchronous callback, but the test has already " + - "finished running. To solve this, you can either unmount the component at " + - "the end of your test (and ensure that any asynchronous operations get " + - "canceled in `componentWillUnmount`), or you can change the test itself " + - "to be asynchronous." - ); + Function.prototype.apply.call(console[level], console, argsWithFormat); } + } - var evt = document.createEvent("Event"); - var didCall = false; // Keeps track of whether the user-provided callback threw an error. We - // set this to true at the beginning, then set it to false right after - // calling the function. If the function errors, `didError` will never be - // set to false. This strategy works even if the browser is flaky and - // fails to call our global error handler, because it doesn't rely on - // the error event at all. - - var didError = true; // Keeps track of the value of window.event so that we can reset it - // during the callback to let user code access window.event in the - // browsers that support it. - - var windowEvent = window.event; // Keeps track of the descriptor of window.event to restore it after event - // dispatching: https://github.com/facebook/react/issues/13688 + function invokeGuardedCallbackProd(name, func, context, a, b, c, d, e, f) { + var funcArgs = Array.prototype.slice.call(arguments, 3); - var windowEventDescriptor = Object.getOwnPropertyDescriptor( - window, - "event" - ); + try { + func.apply(context, funcArgs); + } catch (error) { + this.onError(error); + } + } - function restoreAfterDispatch() { - // We immediately remove the callback from event listeners so that - // nested `invokeGuardedCallback` calls do not clash. Otherwise, a - // nested call would trigger the fake event handlers of any call higher - // in the stack. - fakeNode.removeEventListener(evtType, callCallback, false); // We check for window.hasOwnProperty('event') to prevent the - // window.event assignment in both IE <= 10 as they throw an error - // "Member not found" in strict mode, and in Firefox which does not - // support window.event. + var invokeGuardedCallbackImpl = invokeGuardedCallbackProd; - if ( - typeof window.event !== "undefined" && - window.hasOwnProperty("event") + { + // In DEV mode, we swap out invokeGuardedCallback for a special version + // that plays more nicely with the browser's DevTools. The idea is to preserve + // "Pause on exceptions" behavior. Because React wraps all user-provided + // functions in invokeGuardedCallback, and the production version of + // invokeGuardedCallback uses a try-catch, all user exceptions are treated + // like caught exceptions, and the DevTools won't pause unless the developer + // takes the extra step of enabling pause on caught exceptions. This is + // unintuitive, though, because even though React has caught the error, from + // the developer's perspective, the error is uncaught. + // + // To preserve the expected "Pause on exceptions" behavior, we don't use a + // try-catch in DEV. Instead, we synchronously dispatch a fake event to a fake + // DOM node, and call the user-provided callback from inside an event handler + // for that fake event. If the callback throws, the error is "captured" using + // a global event handler. But because the error happens in a different + // event loop context, it does not interrupt the normal program flow. + // Effectively, this gives us try-catch behavior without actually using + // try-catch. Neat! + // Check that the browser supports the APIs we need to implement our special + // DEV version of invokeGuardedCallback + if ( + typeof window !== "undefined" && + typeof window.dispatchEvent === "function" && + typeof document !== "undefined" && + typeof document.createEvent === "function" + ) { + var fakeNode = document.createElement("react"); + + invokeGuardedCallbackImpl = function invokeGuardedCallbackDev( + name, + func, + context, + a, + b, + c, + d, + e, + f ) { - window.event = windowEvent; - } - } // Create an event handler for our fake event. We will synchronously - // dispatch our fake event using `dispatchEvent`. Inside the handler, we - // call the user-provided callback. - - var funcArgs = Array.prototype.slice.call(arguments, 3); - - function callCallback() { - didCall = true; - restoreAfterDispatch(); - func.apply(context, funcArgs); - didError = false; - } // Create a global error event handler. We use this to capture the value - // that was thrown. It's possible that this error handler will fire more - // than once; for example, if non-React code also calls `dispatchEvent` - // and a handler for that event throws. We should be resilient to most of - // those cases. Even if our error event handler fires more than once, the - // last error event is always used. If the callback actually does error, - // we know that the last error event is the correct one, because it's not - // possible for anything else to have happened in between our callback - // erroring and the code that follows the `dispatchEvent` call below. If - // the callback doesn't error, but the error event was fired, we know to - // ignore it because `didError` will be false, as described above. - - var error; // Use this to track whether the error event is ever called. - - var didSetError = false; - var isCrossOriginError = false; - - function handleWindowError(event) { - error = event.error; - didSetError = true; - - if (error === null && event.colno === 0 && event.lineno === 0) { - isCrossOriginError = true; - } - - if (event.defaultPrevented) { - // Some other error handler has prevented default. - // Browsers silence the error report if this happens. - // We'll remember this to later decide whether to log it or not. - if (error != null && typeof error === "object") { - try { - error._suppressLogging = true; - } catch (inner) { - // Ignore. - } + // If document doesn't exist we know for sure we will crash in this method + // when we call document.createEvent(). However this can cause confusing + // errors: https://github.com/facebook/create-react-app/issues/3482 + // So we preemptively throw with a better message instead. + if (typeof document === "undefined" || document === null) { + throw new Error( + "The `document` global was defined when React was initialized, but is not " + + "defined anymore. This can happen in a test environment if a component " + + "schedules an update from an asynchronous callback, but the test has already " + + "finished running. To solve this, you can either unmount the component at " + + "the end of your test (and ensure that any asynchronous operations get " + + "canceled in `componentWillUnmount`), or you can change the test itself " + + "to be asynchronous." + ); } - } - } // Create a fake event type. - var evtType = "react-" + (name ? name : "invokeguardedcallback"); // Attach our event handlers + var evt = document.createEvent("Event"); + var didCall = false; // Keeps track of whether the user-provided callback threw an error. We + // set this to true at the beginning, then set it to false right after + // calling the function. If the function errors, `didError` will never be + // set to false. This strategy works even if the browser is flaky and + // fails to call our global error handler, because it doesn't rely on + // the error event at all. - window.addEventListener("error", handleWindowError); - fakeNode.addEventListener(evtType, callCallback, false); // Synchronously dispatch our fake event. If the user-provided function - // errors, it will trigger our global error handler. + var didError = true; // Keeps track of the value of window.event so that we can reset it + // during the callback to let user code access window.event in the + // browsers that support it. - evt.initEvent(evtType, false, false); - fakeNode.dispatchEvent(evt); - - if (windowEventDescriptor) { - Object.defineProperty(window, "event", windowEventDescriptor); - } + var windowEvent = window.event; // Keeps track of the descriptor of window.event to restore it after event + // dispatching: https://github.com/facebook/react/issues/13688 - if (didCall && didError) { - if (!didSetError) { - // The callback errored, but the error event never fired. - // eslint-disable-next-line react-internal/prod-error-codes - error = new Error( - "An error was thrown inside one of your components, but React " + - "doesn't know what it was. This is likely due to browser " + - 'flakiness. React does its best to preserve the "Pause on ' + - 'exceptions" behavior of the DevTools, which requires some ' + - "DEV-mode only tricks. It's possible that these don't work in " + - "your browser. Try triggering the error in production mode, " + - "or switching to a modern browser. If you suspect that this is " + - "actually an issue with React, please file an issue." - ); - } else if (isCrossOriginError) { - // eslint-disable-next-line react-internal/prod-error-codes - error = new Error( - "A cross-origin error was thrown. React doesn't have access to " + - "the actual error object in development. " + - "See https://react.dev/link/crossorigin-error for more information." + var windowEventDescriptor = Object.getOwnPropertyDescriptor( + window, + "event" ); - } - this.onError(error); - } // Remove our event listeners - - window.removeEventListener("error", handleWindowError); + function restoreAfterDispatch() { + // We immediately remove the callback from event listeners so that + // nested `invokeGuardedCallback` calls do not clash. Otherwise, a + // nested call would trigger the fake event handlers of any call higher + // in the stack. + fakeNode.removeEventListener(evtType, callCallback, false); // We check for window.hasOwnProperty('event') to prevent the + // window.event assignment in both IE <= 10 as they throw an error + // "Member not found" in strict mode, and in Firefox which does not + // support window.event. - if (!didCall) { - // Something went really wrong, and our event was not dispatched. - // https://github.com/facebook/react/issues/16734 - // https://github.com/facebook/react/issues/16585 - // Fall back to the production implementation. - restoreAfterDispatch(); - return invokeGuardedCallbackProd.apply(this, arguments); - } - }; - } -} + if ( + typeof window.event !== "undefined" && + window.hasOwnProperty("event") + ) { + window.event = windowEvent; + } + } // Create an event handler for our fake event. We will synchronously + // dispatch our fake event using `dispatchEvent`. Inside the handler, we + // call the user-provided callback. + + var funcArgs = Array.prototype.slice.call(arguments, 3); + + function callCallback() { + didCall = true; + restoreAfterDispatch(); + func.apply(context, funcArgs); + didError = false; + } // Create a global error event handler. We use this to capture the value + // that was thrown. It's possible that this error handler will fire more + // than once; for example, if non-React code also calls `dispatchEvent` + // and a handler for that event throws. We should be resilient to most of + // those cases. Even if our error event handler fires more than once, the + // last error event is always used. If the callback actually does error, + // we know that the last error event is the correct one, because it's not + // possible for anything else to have happened in between our callback + // erroring and the code that follows the `dispatchEvent` call below. If + // the callback doesn't error, but the error event was fired, we know to + // ignore it because `didError` will be false, as described above. + + var error; // Use this to track whether the error event is ever called. + + var didSetError = false; + var isCrossOriginError = false; + + function handleWindowError(event) { + error = event.error; + didSetError = true; + + if (error === null && event.colno === 0 && event.lineno === 0) { + isCrossOriginError = true; + } -var invokeGuardedCallbackImpl$1 = invokeGuardedCallbackImpl; + if (event.defaultPrevented) { + // Some other error handler has prevented default. + // Browsers silence the error report if this happens. + // We'll remember this to later decide whether to log it or not. + if (error != null && typeof error === "object") { + try { + error._suppressLogging = true; + } catch (inner) { + // Ignore. + } + } + } + } // Create a fake event type. -var hasError = false; -var caughtError = null; // Used by event system to capture/rethrow the first error. + var evtType = "react-" + (name ? name : "invokeguardedcallback"); // Attach our event handlers -var hasRethrowError = false; -var rethrowError = null; -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 - */ + window.addEventListener("error", handleWindowError); + fakeNode.addEventListener(evtType, callCallback, false); // Synchronously dispatch our fake event. If the user-provided function + // errors, it will trigger our global error handler. -function invokeGuardedCallback(name, func, context, a, b, c, d, e, f) { - hasError = false; - caughtError = null; - invokeGuardedCallbackImpl$1.apply(reporter, arguments); -} -/** - * Same as invokeGuardedCallback, but instead of returning an error, it stores - * it in a global so it can be rethrown by `rethrowCaughtError` later. - * TODO: See if caughtError and rethrowError can be unified. - * - * @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 - */ + evt.initEvent(evtType, false, false); + fakeNode.dispatchEvent(evt); -function invokeGuardedCallbackAndCatchFirstError( - name, - func, - context, - a, - b, - c, - d, - e, - f -) { - invokeGuardedCallback.apply(this, arguments); - - if (hasError) { - var error = clearCaughtError(); - - if (!hasRethrowError) { - hasRethrowError = true; - rethrowError = error; - } - } -} -/** - * During execution of guarded functions we will capture the first error which - * we will rethrow to be handled by the top level error handler. - */ + if (windowEventDescriptor) { + Object.defineProperty(window, "event", windowEventDescriptor); + } -function rethrowCaughtError() { - if (hasRethrowError) { - var error = rethrowError; - hasRethrowError = false; - rethrowError = null; - throw error; - } -} -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." - ); - } -} + if (didCall && didError) { + if (!didSetError) { + // The callback errored, but the error event never fired. + // eslint-disable-next-line react-internal/prod-error-codes + error = new Error( + "An error was thrown inside one of your components, but React " + + "doesn't know what it was. This is likely due to browser " + + 'flakiness. React does its best to preserve the "Pause on ' + + 'exceptions" behavior of the DevTools, which requires some ' + + "DEV-mode only tricks. It's possible that these don't work in " + + "your browser. Try triggering the error in production mode, " + + "or switching to a modern browser. If you suspect that this is " + + "actually an issue with React, please file an issue." + ); + } else if (isCrossOriginError) { + // eslint-disable-next-line react-internal/prod-error-codes + error = new Error( + "A cross-origin error was thrown. React doesn't have access to " + + "the actual error object in development. " + + "See https://react.dev/link/crossorigin-error for more information." + ); + } -var isArrayImpl = Array.isArray; // eslint-disable-next-line no-redeclare + this.onError(error); + } // Remove our event listeners -function isArray(a) { - return isArrayImpl(a); -} + window.removeEventListener("error", handleWindowError); -var getFiberCurrentPropsFromNode = null; -var getInstanceFromNode = null; -var getNodeFromInstance = null; -function setComponentTree( - getFiberCurrentPropsFromNodeImpl, - getInstanceFromNodeImpl, - getNodeFromInstanceImpl -) { - getFiberCurrentPropsFromNode = getFiberCurrentPropsFromNodeImpl; - getInstanceFromNode = getInstanceFromNodeImpl; - getNodeFromInstance = getNodeFromInstanceImpl; - - { - if (!getNodeFromInstance || !getInstanceFromNode) { - error( - "EventPluginUtils.setComponentTree(...): Injected " + - "module is missing getNodeFromInstance or getInstanceFromNode." - ); + if (!didCall) { + // Something went really wrong, and our event was not dispatched. + // https://github.com/facebook/react/issues/16734 + // https://github.com/facebook/react/issues/16585 + // Fall back to the production implementation. + restoreAfterDispatch(); + return invokeGuardedCallbackProd.apply(this, arguments); + } + }; + } } - } -} -var validateEventDispatches; - -{ - validateEventDispatches = function(event) { - var dispatchListeners = event._dispatchListeners; - var dispatchInstances = event._dispatchInstances; - var listenersIsArr = isArray(dispatchListeners); - var listenersLen = listenersIsArr - ? dispatchListeners.length - : dispatchListeners - ? 1 - : 0; - var instancesIsArr = isArray(dispatchInstances); - var instancesLen = instancesIsArr - ? dispatchInstances.length - : dispatchInstances - ? 1 - : 0; - - if (instancesIsArr !== listenersIsArr || instancesLen !== listenersLen) { - error("EventPluginUtils: Invalid `event`."); - } - }; -} -/** - * Dispatch the event to the listener. - * @param {SyntheticEvent} event SyntheticEvent to handle - * @param {function} listener Application-level callback - * @param {*} inst Internal component instance - */ - -function executeDispatch(event, listener, inst) { - var type = event.type || "unknown-event"; - event.currentTarget = getNodeFromInstance(inst); - invokeGuardedCallbackAndCatchFirstError(type, listener, undefined, event); - event.currentTarget = null; -} -/** - * Standard/simple iteration through an event's collected dispatches. - */ -function executeDispatchesInOrder(event) { - var dispatchListeners = event._dispatchListeners; - var dispatchInstances = event._dispatchInstances; + var invokeGuardedCallbackImpl$1 = invokeGuardedCallbackImpl; - { - validateEventDispatches(event); - } + var hasError = false; + var caughtError = null; // Used by event system to capture/rethrow the first error. - if (isArray(dispatchListeners)) { - for (var i = 0; i < dispatchListeners.length; i++) { - if (event.isPropagationStopped()) { - break; - } // Listeners and Instances are two parallel arrays that are always in sync. + var hasRethrowError = false; + var rethrowError = null; + 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 + */ - executeDispatch(event, dispatchListeners[i], dispatchInstances[i]); + function invokeGuardedCallback(name, func, context, a, b, c, d, e, f) { + hasError = false; + caughtError = null; + invokeGuardedCallbackImpl$1.apply(reporter, arguments); } - } else if (dispatchListeners) { - executeDispatch(event, dispatchListeners, dispatchInstances); - } - - event._dispatchListeners = null; - event._dispatchInstances = null; -} -/** - * Standard/simple iteration through an event's collected dispatches, but stops - * at the first dispatch execution returning true, and returns that id. - * - * @return {?string} id of the first dispatch execution who's listener returns - * true, or null if no listener returned true. - */ + /** + * Same as invokeGuardedCallback, but instead of returning an error, it stores + * it in a global so it can be rethrown by `rethrowCaughtError` later. + * TODO: See if caughtError and rethrowError can be unified. + * + * @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 executeDispatchesInOrderStopAtTrueImpl(event) { - var dispatchListeners = event._dispatchListeners; - var dispatchInstances = event._dispatchInstances; + function invokeGuardedCallbackAndCatchFirstError( + name, + func, + context, + a, + b, + c, + d, + e, + f + ) { + invokeGuardedCallback.apply(this, arguments); - { - validateEventDispatches(event); - } + if (hasError) { + var error = clearCaughtError(); - if (isArray(dispatchListeners)) { - for (var i = 0; i < dispatchListeners.length; i++) { - if (event.isPropagationStopped()) { - break; - } // Listeners and Instances are two parallel arrays that are always in sync. + if (!hasRethrowError) { + hasRethrowError = true; + rethrowError = error; + } + } + } + /** + * During execution of guarded functions we will capture the first error which + * we will rethrow to be handled by the top level error handler. + */ - if (dispatchListeners[i](event, dispatchInstances[i])) { - return dispatchInstances[i]; + function rethrowCaughtError() { + if (hasRethrowError) { + var error = rethrowError; + hasRethrowError = false; + rethrowError = null; + throw error; } } - } else if (dispatchListeners) { - if (dispatchListeners(event, dispatchInstances)) { - return dispatchInstances; + 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." + ); + } } - } - return null; -} -/** - * @see executeDispatchesInOrderStopAtTrueImpl - */ + var isArrayImpl = Array.isArray; // eslint-disable-next-line no-redeclare -function executeDispatchesInOrderStopAtTrue(event) { - var ret = executeDispatchesInOrderStopAtTrueImpl(event); - event._dispatchInstances = null; - event._dispatchListeners = null; - return ret; -} -/** - * Execution of a "direct" dispatch - there must be at most one dispatch - * accumulated on the event or it is considered an error. It doesn't really make - * sense for an event with multiple dispatches (bubbled) to keep track of the - * return values at each dispatch execution, but it does tend to make sense when - * dealing with "direct" dispatches. - * - * @return {*} The return value of executing the single dispatch. - */ + function isArray(a) { + return isArrayImpl(a); + } -function executeDirectDispatch(event) { - { - validateEventDispatches(event); - } - - var dispatchListener = event._dispatchListeners; - var dispatchInstance = event._dispatchInstances; - - if (isArray(dispatchListener)) { - throw new Error("executeDirectDispatch(...): Invalid `event`."); - } - - event.currentTarget = dispatchListener - ? getNodeFromInstance(dispatchInstance) - : null; - var res = dispatchListener ? dispatchListener(event) : null; - event.currentTarget = null; - event._dispatchListeners = null; - event._dispatchInstances = null; - return res; -} -/** - * @param {SyntheticEvent} event - * @return {boolean} True iff number of dispatches accumulated is greater than 0. - */ + var getFiberCurrentPropsFromNode = null; + var getInstanceFromNode = null; + var getNodeFromInstance = null; + function setComponentTree( + getFiberCurrentPropsFromNodeImpl, + getInstanceFromNodeImpl, + getNodeFromInstanceImpl + ) { + getFiberCurrentPropsFromNode = getFiberCurrentPropsFromNodeImpl; + getInstanceFromNode = getInstanceFromNodeImpl; + getNodeFromInstance = getNodeFromInstanceImpl; -function hasDispatches(event) { - return !!event._dispatchListeners; -} + { + if (!getNodeFromInstance || !getInstanceFromNode) { + error( + "EventPluginUtils.setComponentTree(...): Injected " + + "module is missing getNodeFromInstance or getInstanceFromNode." + ); + } + } + } + var validateEventDispatches; -var assign = Object.assign; + { + validateEventDispatches = function (event) { + var dispatchListeners = event._dispatchListeners; + var dispatchInstances = event._dispatchInstances; + var listenersIsArr = isArray(dispatchListeners); + var listenersLen = listenersIsArr + ? dispatchListeners.length + : dispatchListeners + ? 1 + : 0; + var instancesIsArr = isArray(dispatchInstances); + var instancesLen = instancesIsArr + ? dispatchInstances.length + : dispatchInstances + ? 1 + : 0; + + if (instancesIsArr !== listenersIsArr || instancesLen !== listenersLen) { + error("EventPluginUtils: Invalid `event`."); + } + }; + } + /** + * Dispatch the event to the listener. + * @param {SyntheticEvent} event SyntheticEvent to handle + * @param {function} listener Application-level callback + * @param {*} inst Internal component instance + */ -var EVENT_POOL_SIZE = 10; -/** - * @interface Event - * @see http://www.w3.org/TR/DOM-Level-3-Events/ - */ + function executeDispatch(event, listener, inst) { + var type = event.type || "unknown-event"; + event.currentTarget = getNodeFromInstance(inst); + invokeGuardedCallbackAndCatchFirstError(type, listener, undefined, event); + event.currentTarget = null; + } + /** + * Standard/simple iteration through an event's collected dispatches. + */ -var EventInterface = { - type: null, - target: null, - // currentTarget is set when dispatching; no use in copying it here - currentTarget: function() { - return null; - }, - eventPhase: null, - bubbles: null, - cancelable: null, - timeStamp: function(event) { - return event.timeStamp || Date.now(); - }, - defaultPrevented: null, - isTrusted: null -}; - -function functionThatReturnsTrue() { - return true; -} + function executeDispatchesInOrder(event) { + var dispatchListeners = event._dispatchListeners; + var dispatchInstances = event._dispatchInstances; -function functionThatReturnsFalse() { - return false; -} -/** - * Synthetic events are dispatched by event plugins, typically in response to a - * top-level event delegation handler. - * - * These systems should generally use pooling to reduce the frequency of garbage - * collection. The system should check `isPersistent` to determine whether the - * event should be released into the pool after being dispatched. Users that - * need a persisted event should invoke `persist`. - * - * Synthetic events (and subclasses) implement the DOM Level 3 Events API by - * normalizing browser quirks. Subclasses do not necessarily have to implement a - * DOM interface; custom application-specific events can also subclass this. - * - * @param {object} dispatchConfig Configuration used to dispatch this event. - * @param {*} targetInst Marker identifying the event target. - * @param {object} nativeEvent Native browser event. - * @param {DOMEventTarget} nativeEventTarget Target node. - */ + { + validateEventDispatches(event); + } -function SyntheticEvent( - dispatchConfig, - targetInst, - nativeEvent, - nativeEventTarget -) { - { - // these have a getter/setter for warnings - delete this.nativeEvent; - delete this.preventDefault; - delete this.stopPropagation; - delete this.isDefaultPrevented; - delete this.isPropagationStopped; - } - - this.dispatchConfig = dispatchConfig; - this._targetInst = targetInst; - this.nativeEvent = nativeEvent; - this._dispatchListeners = null; - this._dispatchInstances = null; - var Interface = this.constructor.Interface; - - for (var propName in Interface) { - if (!Interface.hasOwnProperty(propName)) { - continue; - } + if (isArray(dispatchListeners)) { + for (var i = 0; i < dispatchListeners.length; i++) { + if (event.isPropagationStopped()) { + break; + } // Listeners and Instances are two parallel arrays that are always in sync. - { - delete this[propName]; // this has a getter/setter for warnings + executeDispatch(event, dispatchListeners[i], dispatchInstances[i]); + } + } else if (dispatchListeners) { + executeDispatch(event, dispatchListeners, dispatchInstances); + } + + event._dispatchListeners = null; + event._dispatchInstances = null; } + /** + * Standard/simple iteration through an event's collected dispatches, but stops + * at the first dispatch execution returning true, and returns that id. + * + * @return {?string} id of the first dispatch execution who's listener returns + * true, or null if no listener returned true. + */ - var normalize = Interface[propName]; + function executeDispatchesInOrderStopAtTrueImpl(event) { + var dispatchListeners = event._dispatchListeners; + var dispatchInstances = event._dispatchInstances; - if (normalize) { - this[propName] = normalize(nativeEvent); - } else { - if (propName === "target") { - this.target = nativeEventTarget; - } else { - this[propName] = nativeEvent[propName]; + { + validateEventDispatches(event); + } + + if (isArray(dispatchListeners)) { + for (var i = 0; i < dispatchListeners.length; i++) { + if (event.isPropagationStopped()) { + break; + } // Listeners and Instances are two parallel arrays that are always in sync. + + if (dispatchListeners[i](event, dispatchInstances[i])) { + return dispatchInstances[i]; + } + } + } else if (dispatchListeners) { + if (dispatchListeners(event, dispatchInstances)) { + return dispatchInstances; + } } + + return null; } - } + /** + * @see executeDispatchesInOrderStopAtTrueImpl + */ - var defaultPrevented = - nativeEvent.defaultPrevented != null - ? nativeEvent.defaultPrevented - : nativeEvent.returnValue === false; + function executeDispatchesInOrderStopAtTrue(event) { + var ret = executeDispatchesInOrderStopAtTrueImpl(event); + event._dispatchInstances = null; + event._dispatchListeners = null; + return ret; + } + /** + * Execution of a "direct" dispatch - there must be at most one dispatch + * accumulated on the event or it is considered an error. It doesn't really make + * sense for an event with multiple dispatches (bubbled) to keep track of the + * return values at each dispatch execution, but it does tend to make sense when + * dealing with "direct" dispatches. + * + * @return {*} The return value of executing the single dispatch. + */ - if (defaultPrevented) { - this.isDefaultPrevented = functionThatReturnsTrue; - } else { - this.isDefaultPrevented = functionThatReturnsFalse; - } + function executeDirectDispatch(event) { + { + validateEventDispatches(event); + } - this.isPropagationStopped = functionThatReturnsFalse; - return this; -} + var dispatchListener = event._dispatchListeners; + var dispatchInstance = event._dispatchInstances; -assign(SyntheticEvent.prototype, { - preventDefault: function() { - this.defaultPrevented = true; - var event = this.nativeEvent; + if (isArray(dispatchListener)) { + throw new Error("executeDirectDispatch(...): Invalid `event`."); + } - if (!event) { - return; + event.currentTarget = dispatchListener + ? getNodeFromInstance(dispatchInstance) + : null; + var res = dispatchListener ? dispatchListener(event) : null; + event.currentTarget = null; + event._dispatchListeners = null; + event._dispatchInstances = null; + return res; } + /** + * @param {SyntheticEvent} event + * @return {boolean} True iff number of dispatches accumulated is greater than 0. + */ - if (event.preventDefault) { - event.preventDefault(); - } else if (typeof event.returnValue !== "unknown") { - event.returnValue = false; + function hasDispatches(event) { + return !!event._dispatchListeners; } - this.isDefaultPrevented = functionThatReturnsTrue; - }, - stopPropagation: function() { - var event = this.nativeEvent; + var assign = Object.assign; + + var EVENT_POOL_SIZE = 10; + /** + * @interface Event + * @see http://www.w3.org/TR/DOM-Level-3-Events/ + */ + + var EventInterface = { + type: null, + target: null, + // currentTarget is set when dispatching; no use in copying it here + currentTarget: function () { + return null; + }, + eventPhase: null, + bubbles: null, + cancelable: null, + timeStamp: function (event) { + return event.timeStamp || Date.now(); + }, + defaultPrevented: null, + isTrusted: null + }; - if (!event) { - return; + function functionThatReturnsTrue() { + return true; } - if (event.stopPropagation) { - event.stopPropagation(); - } else if (typeof event.cancelBubble !== "unknown") { - // The ChangeEventPlugin registers a "propertychange" event for - // IE. This event does not support bubbling or cancelling, and - // any references to cancelBubble throw "Member not found". A - // typeof check of "unknown" circumvents this issue (and is also - // IE specific). - event.cancelBubble = true; + function functionThatReturnsFalse() { + return false; } + /** + * Synthetic events are dispatched by event plugins, typically in response to a + * top-level event delegation handler. + * + * These systems should generally use pooling to reduce the frequency of garbage + * collection. The system should check `isPersistent` to determine whether the + * event should be released into the pool after being dispatched. Users that + * need a persisted event should invoke `persist`. + * + * Synthetic events (and subclasses) implement the DOM Level 3 Events API by + * normalizing browser quirks. Subclasses do not necessarily have to implement a + * DOM interface; custom application-specific events can also subclass this. + * + * @param {object} dispatchConfig Configuration used to dispatch this event. + * @param {*} targetInst Marker identifying the event target. + * @param {object} nativeEvent Native browser event. + * @param {DOMEventTarget} nativeEventTarget Target node. + */ + + function SyntheticEvent( + dispatchConfig, + targetInst, + nativeEvent, + nativeEventTarget + ) { + { + // these have a getter/setter for warnings + delete this.nativeEvent; + delete this.preventDefault; + delete this.stopPropagation; + delete this.isDefaultPrevented; + delete this.isPropagationStopped; + } + + this.dispatchConfig = dispatchConfig; + this._targetInst = targetInst; + this.nativeEvent = nativeEvent; + this._dispatchListeners = null; + this._dispatchInstances = null; + var Interface = this.constructor.Interface; + + for (var propName in Interface) { + if (!Interface.hasOwnProperty(propName)) { + continue; + } - this.isPropagationStopped = functionThatReturnsTrue; - }, + { + delete this[propName]; // this has a getter/setter for warnings + } - /** - * We release all dispatched `SyntheticEvent`s after each event loop, adding - * them back into the pool. This allows a way to hold onto a reference that - * won't be added back into the pool. - */ - persist: function() { - this.isPersistent = functionThatReturnsTrue; - }, + var normalize = Interface[propName]; - /** - * Checks if this event should be released back into the pool. - * - * @return {boolean} True if this should not be released, false otherwise. - */ - isPersistent: functionThatReturnsFalse, + if (normalize) { + this[propName] = normalize(nativeEvent); + } else { + if (propName === "target") { + this.target = nativeEventTarget; + } else { + this[propName] = nativeEvent[propName]; + } + } + } - /** - * `PooledClass` looks for `destructor` on each instance it releases. - */ - destructor: function() { - var Interface = this.constructor.Interface; + var defaultPrevented = + nativeEvent.defaultPrevented != null + ? nativeEvent.defaultPrevented + : nativeEvent.returnValue === false; - for (var propName in Interface) { - { - Object.defineProperty( - this, - propName, - getPooledWarningPropertyDefinition(propName, Interface[propName]) - ); + if (defaultPrevented) { + this.isDefaultPrevented = functionThatReturnsTrue; + } else { + this.isDefaultPrevented = functionThatReturnsFalse; } + + this.isPropagationStopped = functionThatReturnsFalse; + return this; } - this.dispatchConfig = null; - this._targetInst = null; - this.nativeEvent = null; - this.isDefaultPrevented = functionThatReturnsFalse; - this.isPropagationStopped = functionThatReturnsFalse; - this._dispatchListeners = null; - this._dispatchInstances = null; + assign(SyntheticEvent.prototype, { + preventDefault: function () { + this.defaultPrevented = true; + var event = this.nativeEvent; - { - Object.defineProperty( - this, - "nativeEvent", - getPooledWarningPropertyDefinition("nativeEvent", null) - ); - Object.defineProperty( - this, - "isDefaultPrevented", - getPooledWarningPropertyDefinition( - "isDefaultPrevented", - functionThatReturnsFalse - ) - ); - Object.defineProperty( - this, - "isPropagationStopped", - getPooledWarningPropertyDefinition( - "isPropagationStopped", - functionThatReturnsFalse - ) - ); - Object.defineProperty( - this, - "preventDefault", - getPooledWarningPropertyDefinition("preventDefault", function() {}) - ); - Object.defineProperty( - this, - "stopPropagation", - getPooledWarningPropertyDefinition("stopPropagation", function() {}) - ); - } - } -}); -SyntheticEvent.Interface = EventInterface; -/** - * Helper to reduce boilerplate when creating subclasses. - */ + if (!event) { + return; + } -SyntheticEvent.extend = function(Interface) { - var Super = this; + if (event.preventDefault) { + event.preventDefault(); + } else if (typeof event.returnValue !== "unknown") { + event.returnValue = false; + } - var E = function() {}; + this.isDefaultPrevented = functionThatReturnsTrue; + }, + stopPropagation: function () { + var event = this.nativeEvent; - E.prototype = Super.prototype; - var prototype = new E(); + if (!event) { + return; + } - function Class() { - return Super.apply(this, arguments); - } + if (event.stopPropagation) { + event.stopPropagation(); + } else if (typeof event.cancelBubble !== "unknown") { + // The ChangeEventPlugin registers a "propertychange" event for + // IE. This event does not support bubbling or cancelling, and + // any references to cancelBubble throw "Member not found". A + // typeof check of "unknown" circumvents this issue (and is also + // IE specific). + event.cancelBubble = true; + } - assign(prototype, Class.prototype); - Class.prototype = prototype; - Class.prototype.constructor = Class; - Class.Interface = assign({}, Super.Interface, Interface); - Class.extend = Super.extend; - addEventPoolingTo(Class); - return Class; -}; + this.isPropagationStopped = functionThatReturnsTrue; + }, + + /** + * We release all dispatched `SyntheticEvent`s after each event loop, adding + * them back into the pool. This allows a way to hold onto a reference that + * won't be added back into the pool. + */ + persist: function () { + this.isPersistent = functionThatReturnsTrue; + }, + + /** + * Checks if this event should be released back into the pool. + * + * @return {boolean} True if this should not be released, false otherwise. + */ + isPersistent: functionThatReturnsFalse, + + /** + * `PooledClass` looks for `destructor` on each instance it releases. + */ + destructor: function () { + var Interface = this.constructor.Interface; + + for (var propName in Interface) { + { + Object.defineProperty( + this, + propName, + getPooledWarningPropertyDefinition(propName, Interface[propName]) + ); + } + } -addEventPoolingTo(SyntheticEvent); -/** - * Helper to nullify syntheticEvent instance properties when destructing - * - * @param {String} propName - * @param {?object} getVal - * @return {object} defineProperty object - */ + this.dispatchConfig = null; + this._targetInst = null; + this.nativeEvent = null; + this.isDefaultPrevented = functionThatReturnsFalse; + this.isPropagationStopped = functionThatReturnsFalse; + this._dispatchListeners = null; + this._dispatchInstances = null; -function getPooledWarningPropertyDefinition(propName, getVal) { - function set(val) { - var action = isFunction ? "setting the method" : "setting the property"; - warn(action, "This is effectively a no-op"); - return val; - } - - function get() { - var action = isFunction ? "accessing the method" : "accessing the property"; - var result = isFunction - ? "This is a no-op function" - : "This is set to null"; - warn(action, result); - return getVal; - } - - function warn(action, result) { - { - error( - "This synthetic event is reused for performance reasons. If you're seeing this, " + - "you're %s `%s` on a released/nullified synthetic event. %s. " + - "If you must keep the original synthetic event around, use event.persist(). " + - "See https://react.dev/link/event-pooling for more information.", - action, - propName, - result - ); - } - } + { + Object.defineProperty( + this, + "nativeEvent", + getPooledWarningPropertyDefinition("nativeEvent", null) + ); + Object.defineProperty( + this, + "isDefaultPrevented", + getPooledWarningPropertyDefinition( + "isDefaultPrevented", + functionThatReturnsFalse + ) + ); + Object.defineProperty( + this, + "isPropagationStopped", + getPooledWarningPropertyDefinition( + "isPropagationStopped", + functionThatReturnsFalse + ) + ); + Object.defineProperty( + this, + "preventDefault", + getPooledWarningPropertyDefinition("preventDefault", function () { }) + ); + Object.defineProperty( + this, + "stopPropagation", + getPooledWarningPropertyDefinition("stopPropagation", function () { }) + ); + } + } + }); + SyntheticEvent.Interface = EventInterface; + /** + * Helper to reduce boilerplate when creating subclasses. + */ - var isFunction = typeof getVal === "function"; - return { - configurable: true, - set: set, - get: get - }; -} + SyntheticEvent.extend = function (Interface) { + var Super = this; -function createOrGetPooledEvent( - dispatchConfig, - targetInst, - nativeEvent, - nativeInst -) { - var EventConstructor = this; - - if (EventConstructor.eventPool.length) { - var instance = EventConstructor.eventPool.pop(); - EventConstructor.call( - instance, + var E = function () { }; + + E.prototype = Super.prototype; + var prototype = new E(); + + function Class() { + return Super.apply(this, arguments); + } + + assign(prototype, Class.prototype); + Class.prototype = prototype; + Class.prototype.constructor = Class; + Class.Interface = assign({}, Super.Interface, Interface); + Class.extend = Super.extend; + addEventPoolingTo(Class); + return Class; + }; + + addEventPoolingTo(SyntheticEvent); + /** + * Helper to nullify syntheticEvent instance properties when destructing + * + * @param {String} propName + * @param {?object} getVal + * @return {object} defineProperty object + */ + + function getPooledWarningPropertyDefinition(propName, getVal) { + function set(val) { + var action = isFunction ? "setting the method" : "setting the property"; + warn(action, "This is effectively a no-op"); + return val; + } + + function get() { + var action = isFunction ? "accessing the method" : "accessing the property"; + var result = isFunction + ? "This is a no-op function" + : "This is set to null"; + warn(action, result); + return getVal; + } + + function warn(action, result) { + { + error( + "This synthetic event is reused for performance reasons. If you're seeing this, " + + "you're %s `%s` on a released/nullified synthetic event. %s. " + + "If you must keep the original synthetic event around, use event.persist(). " + + "See https://react.dev/link/event-pooling for more information.", + action, + propName, + result + ); + } + } + + var isFunction = typeof getVal === "function"; + return { + configurable: true, + set: set, + get: get + }; + } + + function createOrGetPooledEvent( dispatchConfig, targetInst, nativeEvent, nativeInst - ); - return instance; - } - - return new EventConstructor( - dispatchConfig, - targetInst, - nativeEvent, - nativeInst - ); -} - -function releasePooledEvent(event) { - var EventConstructor = this; + ) { + var EventConstructor = this; - if (!(event instanceof EventConstructor)) { - throw new Error( - "Trying to release an event instance into a pool of a different type." - ); - } + if (EventConstructor.eventPool.length) { + var instance = EventConstructor.eventPool.pop(); + EventConstructor.call( + instance, + dispatchConfig, + targetInst, + nativeEvent, + nativeInst + ); + return instance; + } - event.destructor(); + return new EventConstructor( + dispatchConfig, + targetInst, + nativeEvent, + nativeInst + ); + } - if (EventConstructor.eventPool.length < EVENT_POOL_SIZE) { - EventConstructor.eventPool.push(event); - } -} + function releasePooledEvent(event) { + var EventConstructor = this; -function addEventPoolingTo(EventConstructor) { - EventConstructor.getPooled = createOrGetPooledEvent; - EventConstructor.eventPool = []; - EventConstructor.release = releasePooledEvent; -} + if (!(event instanceof EventConstructor)) { + throw new Error( + "Trying to release an event instance into a pool of a different type." + ); + } -/** - * `touchHistory` isn't actually on the native event, but putting it in the - * interface will ensure that it is cleaned up when pooled/destroyed. The - * `ResponderEventPlugin` will populate it appropriately. - */ + event.destructor(); -var ResponderSyntheticEvent = SyntheticEvent.extend({ - touchHistory: function(nativeEvent) { - return null; // Actually doesn't even look at the native event. - } -}); - -var TOP_TOUCH_START = "topTouchStart"; -var TOP_TOUCH_MOVE = "topTouchMove"; -var TOP_TOUCH_END = "topTouchEnd"; -var TOP_TOUCH_CANCEL = "topTouchCancel"; -var TOP_SCROLL = "topScroll"; -var TOP_SELECTION_CHANGE = "topSelectionChange"; -function isStartish(topLevelType) { - return topLevelType === TOP_TOUCH_START; -} -function isMoveish(topLevelType) { - return topLevelType === TOP_TOUCH_MOVE; -} -function isEndish(topLevelType) { - return topLevelType === TOP_TOUCH_END || topLevelType === TOP_TOUCH_CANCEL; -} -var startDependencies = [TOP_TOUCH_START]; -var moveDependencies = [TOP_TOUCH_MOVE]; -var endDependencies = [TOP_TOUCH_CANCEL, TOP_TOUCH_END]; + if (EventConstructor.eventPool.length < EVENT_POOL_SIZE) { + EventConstructor.eventPool.push(event); + } + } -/** - * Tracks the position and time of each active touch by `touch.identifier`. We - * should typically only see IDs in the range of 1-20 because IDs get recycled - * when touches end and start again. - */ + function addEventPoolingTo(EventConstructor) { + EventConstructor.getPooled = createOrGetPooledEvent; + EventConstructor.eventPool = []; + EventConstructor.release = releasePooledEvent; + } -var MAX_TOUCH_BANK = 20; -var touchBank = []; -var touchHistory = { - touchBank: touchBank, - numberActiveTouches: 0, - // If there is only one active touch, we remember its location. This prevents - // us having to loop through all of the touches all the time in the most - // common case. - indexOfSingleActiveTouch: -1, - mostRecentTimeStamp: 0 -}; - -function timestampForTouch(touch) { - // The legacy internal implementation provides "timeStamp", which has been - // renamed to "timestamp". Let both work for now while we iron it out - // TODO (evv): rename timeStamp to timestamp in internal code - return touch.timeStamp || touch.timestamp; -} -/** - * TODO: Instead of making gestures recompute filtered velocity, we could - * include a built in velocity computation that can be reused globally. - */ + /** + * `touchHistory` isn't actually on the native event, but putting it in the + * interface will ensure that it is cleaned up when pooled/destroyed. The + * `ResponderEventPlugin` will populate it appropriately. + */ -function createTouchRecord(touch) { - return { - touchActive: true, - startPageX: touch.pageX, - startPageY: touch.pageY, - startTimeStamp: timestampForTouch(touch), - currentPageX: touch.pageX, - currentPageY: touch.pageY, - currentTimeStamp: timestampForTouch(touch), - previousPageX: touch.pageX, - previousPageY: touch.pageY, - previousTimeStamp: timestampForTouch(touch) - }; -} + var ResponderSyntheticEvent = SyntheticEvent.extend({ + touchHistory: function (nativeEvent) { + return null; // Actually doesn't even look at the native event. + } + }); -function resetTouchRecord(touchRecord, touch) { - touchRecord.touchActive = true; - touchRecord.startPageX = touch.pageX; - touchRecord.startPageY = touch.pageY; - touchRecord.startTimeStamp = timestampForTouch(touch); - touchRecord.currentPageX = touch.pageX; - touchRecord.currentPageY = touch.pageY; - touchRecord.currentTimeStamp = timestampForTouch(touch); - touchRecord.previousPageX = touch.pageX; - touchRecord.previousPageY = touch.pageY; - touchRecord.previousTimeStamp = timestampForTouch(touch); -} + var TOP_TOUCH_START = "topTouchStart"; + var TOP_TOUCH_MOVE = "topTouchMove"; + var TOP_TOUCH_END = "topTouchEnd"; + var TOP_TOUCH_CANCEL = "topTouchCancel"; + var TOP_SCROLL = "topScroll"; + var TOP_SELECTION_CHANGE = "topSelectionChange"; + function isStartish(topLevelType) { + return topLevelType === TOP_TOUCH_START; + } + function isMoveish(topLevelType) { + return topLevelType === TOP_TOUCH_MOVE; + } + function isEndish(topLevelType) { + return topLevelType === TOP_TOUCH_END || topLevelType === TOP_TOUCH_CANCEL; + } + var startDependencies = [TOP_TOUCH_START]; + var moveDependencies = [TOP_TOUCH_MOVE]; + var endDependencies = [TOP_TOUCH_CANCEL, TOP_TOUCH_END]; -function getTouchIdentifier(_ref) { - var identifier = _ref.identifier; + /** + * Tracks the position and time of each active touch by `touch.identifier`. We + * should typically only see IDs in the range of 1-20 because IDs get recycled + * when touches end and start again. + */ - if (identifier == null) { - throw new Error("Touch object is missing identifier."); - } + var MAX_TOUCH_BANK = 20; + var touchBank = []; + var touchHistory = { + touchBank: touchBank, + numberActiveTouches: 0, + // If there is only one active touch, we remember its location. This prevents + // us having to loop through all of the touches all the time in the most + // common case. + indexOfSingleActiveTouch: -1, + mostRecentTimeStamp: 0 + }; - { - if (identifier > MAX_TOUCH_BANK) { - error( - "Touch identifier %s is greater than maximum supported %s which causes " + - "performance issues backfilling array locations for all of the indices.", - identifier, - MAX_TOUCH_BANK - ); + function timestampForTouch(touch) { + // The legacy internal implementation provides "timeStamp", which has been + // renamed to "timestamp". Let both work for now while we iron it out + // TODO (evv): rename timeStamp to timestamp in internal code + return touch.timeStamp || touch.timestamp; } - } + /** + * TODO: Instead of making gestures recompute filtered velocity, we could + * include a built in velocity computation that can be reused globally. + */ - return identifier; -} + function createTouchRecord(touch) { + return { + touchActive: true, + startPageX: touch.pageX, + startPageY: touch.pageY, + startTimeStamp: timestampForTouch(touch), + currentPageX: touch.pageX, + currentPageY: touch.pageY, + currentTimeStamp: timestampForTouch(touch), + previousPageX: touch.pageX, + previousPageY: touch.pageY, + previousTimeStamp: timestampForTouch(touch) + }; + } -function recordTouchStart(touch) { - var identifier = getTouchIdentifier(touch); - var touchRecord = touchBank[identifier]; + function resetTouchRecord(touchRecord, touch) { + touchRecord.touchActive = true; + touchRecord.startPageX = touch.pageX; + touchRecord.startPageY = touch.pageY; + touchRecord.startTimeStamp = timestampForTouch(touch); + touchRecord.currentPageX = touch.pageX; + touchRecord.currentPageY = touch.pageY; + touchRecord.currentTimeStamp = timestampForTouch(touch); + touchRecord.previousPageX = touch.pageX; + touchRecord.previousPageY = touch.pageY; + touchRecord.previousTimeStamp = timestampForTouch(touch); + } - if (touchRecord) { - resetTouchRecord(touchRecord, touch); - } else { - touchBank[identifier] = createTouchRecord(touch); - } + function getTouchIdentifier(_ref) { + var identifier = _ref.identifier; - touchHistory.mostRecentTimeStamp = timestampForTouch(touch); -} + if (identifier == null) { + throw new Error("Touch object is missing identifier."); + } -function recordTouchMove(touch) { - var touchRecord = touchBank[getTouchIdentifier(touch)]; - - if (touchRecord) { - touchRecord.touchActive = true; - touchRecord.previousPageX = touchRecord.currentPageX; - touchRecord.previousPageY = touchRecord.currentPageY; - touchRecord.previousTimeStamp = touchRecord.currentTimeStamp; - touchRecord.currentPageX = touch.pageX; - touchRecord.currentPageY = touch.pageY; - touchRecord.currentTimeStamp = timestampForTouch(touch); - touchHistory.mostRecentTimeStamp = timestampForTouch(touch); - } else { - { - warn( - "Cannot record touch move without a touch start.\n" + - "Touch Move: %s\n" + - "Touch Bank: %s", - printTouch(touch), - printTouchBank() - ); - } - } -} + { + if (identifier > MAX_TOUCH_BANK) { + error( + "Touch identifier %s is greater than maximum supported %s which causes " + + "performance issues backfilling array locations for all of the indices.", + identifier, + MAX_TOUCH_BANK + ); + } + } -function recordTouchEnd(touch) { - var touchRecord = touchBank[getTouchIdentifier(touch)]; - - if (touchRecord) { - touchRecord.touchActive = false; - touchRecord.previousPageX = touchRecord.currentPageX; - touchRecord.previousPageY = touchRecord.currentPageY; - touchRecord.previousTimeStamp = touchRecord.currentTimeStamp; - touchRecord.currentPageX = touch.pageX; - touchRecord.currentPageY = touch.pageY; - touchRecord.currentTimeStamp = timestampForTouch(touch); - touchHistory.mostRecentTimeStamp = timestampForTouch(touch); - } else { - { - warn( - "Cannot record touch end without a touch start.\n" + - "Touch End: %s\n" + - "Touch Bank: %s", - printTouch(touch), - printTouchBank() - ); + return identifier; } - } -} -function printTouch(touch) { - return JSON.stringify({ - identifier: touch.identifier, - pageX: touch.pageX, - pageY: touch.pageY, - timestamp: timestampForTouch(touch) - }); -} + function recordTouchStart(touch) { + var identifier = getTouchIdentifier(touch); + var touchRecord = touchBank[identifier]; -function printTouchBank() { - var printed = JSON.stringify(touchBank.slice(0, MAX_TOUCH_BANK)); + if (touchRecord) { + resetTouchRecord(touchRecord, touch); + } else { + touchBank[identifier] = createTouchRecord(touch); + } - if (touchBank.length > MAX_TOUCH_BANK) { - printed += " (original size: " + touchBank.length + ")"; - } + touchHistory.mostRecentTimeStamp = timestampForTouch(touch); + } - return printed; -} + function recordTouchMove(touch) { + var touchRecord = touchBank[getTouchIdentifier(touch)]; -var instrumentationCallback; -var ResponderTouchHistoryStore = { - /** - * Registers a listener which can be used to instrument every touch event. - */ - instrument: function(callback) { - instrumentationCallback = callback; - }, - recordTouchTrack: function(topLevelType, nativeEvent) { - if (instrumentationCallback != null) { - instrumentationCallback(topLevelType, nativeEvent); - } - - if (isMoveish(topLevelType)) { - nativeEvent.changedTouches.forEach(recordTouchMove); - } else if (isStartish(topLevelType)) { - nativeEvent.changedTouches.forEach(recordTouchStart); - touchHistory.numberActiveTouches = nativeEvent.touches.length; - - if (touchHistory.numberActiveTouches === 1) { - touchHistory.indexOfSingleActiveTouch = - nativeEvent.touches[0].identifier; - } - } else if (isEndish(topLevelType)) { - nativeEvent.changedTouches.forEach(recordTouchEnd); - touchHistory.numberActiveTouches = nativeEvent.touches.length; - - if (touchHistory.numberActiveTouches === 1) { - for (var i = 0; i < touchBank.length; i++) { - var touchTrackToCheck = touchBank[i]; - - if (touchTrackToCheck != null && touchTrackToCheck.touchActive) { - touchHistory.indexOfSingleActiveTouch = i; - break; - } + if (touchRecord) { + touchRecord.touchActive = true; + touchRecord.previousPageX = touchRecord.currentPageX; + touchRecord.previousPageY = touchRecord.currentPageY; + touchRecord.previousTimeStamp = touchRecord.currentTimeStamp; + touchRecord.currentPageX = touch.pageX; + touchRecord.currentPageY = touch.pageY; + touchRecord.currentTimeStamp = timestampForTouch(touch); + touchHistory.mostRecentTimeStamp = timestampForTouch(touch); + } else { + { + warn( + "Cannot record touch move without a touch start.\n" + + "Touch Move: %s\n" + + "Touch Bank: %s", + printTouch(touch), + printTouchBank() + ); } + } + } - { - var activeRecord = touchBank[touchHistory.indexOfSingleActiveTouch]; + function recordTouchEnd(touch) { + var touchRecord = touchBank[getTouchIdentifier(touch)]; - if (activeRecord == null || !activeRecord.touchActive) { - error("Cannot find single active touch."); - } + if (touchRecord) { + touchRecord.touchActive = false; + touchRecord.previousPageX = touchRecord.currentPageX; + touchRecord.previousPageY = touchRecord.currentPageY; + touchRecord.previousTimeStamp = touchRecord.currentTimeStamp; + touchRecord.currentPageX = touch.pageX; + touchRecord.currentPageY = touch.pageY; + touchRecord.currentTimeStamp = timestampForTouch(touch); + touchHistory.mostRecentTimeStamp = timestampForTouch(touch); + } else { + { + warn( + "Cannot record touch end without a touch start.\n" + + "Touch End: %s\n" + + "Touch Bank: %s", + printTouch(touch), + printTouchBank() + ); } } } - }, - touchHistory: touchHistory -}; - -/** - * Accumulates items that must not be null or undefined. - * - * This is used to conserve memory by avoiding array allocations. - * - * @return {*|array<*>} An accumulation of items. - */ -function accumulate(current, next) { - if (next == null) { - throw new Error( - "accumulate(...): Accumulated items must not be null or undefined." - ); - } + function printTouch(touch) { + return JSON.stringify({ + identifier: touch.identifier, + pageX: touch.pageX, + pageY: touch.pageY, + timestamp: timestampForTouch(touch) + }); + } - if (current == null) { - return next; - } // Both are not empty. Warning: Never call x.concat(y) when you are not - // certain that x is an Array (x could be a string with concat method). + function printTouchBank() { + var printed = JSON.stringify(touchBank.slice(0, MAX_TOUCH_BANK)); - if (isArray(current)) { - return current.concat(next); - } + if (touchBank.length > MAX_TOUCH_BANK) { + printed += " (original size: " + touchBank.length + ")"; + } - if (isArray(next)) { - return [current].concat(next); - } + return printed; + } - return [current, next]; -} + var instrumentationCallback; + var ResponderTouchHistoryStore = { + /** + * Registers a listener which can be used to instrument every touch event. + */ + instrument: function (callback) { + instrumentationCallback = callback; + }, + recordTouchTrack: function (topLevelType, nativeEvent) { + if (instrumentationCallback != null) { + instrumentationCallback(topLevelType, nativeEvent); + } -/** - * Accumulates items that must not be null or undefined into the first one. This - * is used to conserve memory by avoiding array allocations, and thus sacrifices - * API cleanness. Since `current` can be null before being passed in and not - * null after this function, make sure to assign it back to `current`: - * - * `a = accumulateInto(a, b);` - * - * This API should be sparingly used. Try `accumulate` for something cleaner. - * - * @return {*|array<*>} An accumulation of items. - */ + if (isMoveish(topLevelType)) { + nativeEvent.changedTouches.forEach(recordTouchMove); + } else if (isStartish(topLevelType)) { + nativeEvent.changedTouches.forEach(recordTouchStart); + touchHistory.numberActiveTouches = nativeEvent.touches.length; -function accumulateInto(current, next) { - if (next == null) { - throw new Error( - "accumulateInto(...): Accumulated items must not be null or undefined." - ); - } + if (touchHistory.numberActiveTouches === 1) { + touchHistory.indexOfSingleActiveTouch = + nativeEvent.touches[0].identifier; + } + } else if (isEndish(topLevelType)) { + nativeEvent.changedTouches.forEach(recordTouchEnd); + touchHistory.numberActiveTouches = nativeEvent.touches.length; - if (current == null) { - return next; - } // Both are not empty. Warning: Never call x.concat(y) when you are not - // certain that x is an Array (x could be a string with concat method). + if (touchHistory.numberActiveTouches === 1) { + for (var i = 0; i < touchBank.length; i++) { + var touchTrackToCheck = touchBank[i]; - if (isArray(current)) { - if (isArray(next)) { - current.push.apply(current, next); - return current; - } + if (touchTrackToCheck != null && touchTrackToCheck.touchActive) { + touchHistory.indexOfSingleActiveTouch = i; + break; + } + } - current.push(next); - return current; - } + { + var activeRecord = touchBank[touchHistory.indexOfSingleActiveTouch]; - if (isArray(next)) { - // A bit too dangerous to mutate `next`. - return [current].concat(next); - } + if (activeRecord == null || !activeRecord.touchActive) { + error("Cannot find single active touch."); + } + } + } + } + }, + touchHistory: touchHistory + }; - return [current, next]; -} + /** + * Accumulates items that must not be null or undefined. + * + * This is used to conserve memory by avoiding array allocations. + * + * @return {*|array<*>} An accumulation of items. + */ -/** - * @param {array} arr an "accumulation" of items which is either an Array or - * a single item. Useful when paired with the `accumulate` module. This is a - * simple utility that allows us to reason about a collection of items, but - * handling the case when there is exactly one item (and we do not need to - * allocate an array). - * @param {function} cb Callback invoked with each element or a collection. - * @param {?} [scope] Scope used as `this` in a callback. - */ -function forEachAccumulated(arr, cb, scope) { - if (Array.isArray(arr)) { - arr.forEach(cb, scope); - } else if (arr) { - cb.call(scope, arr); - } -} + function accumulate(current, next) { + if (next == null) { + throw new Error( + "accumulate(...): Accumulated items must not be null or undefined." + ); + } -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; + if (current == null) { + return next; + } // Both are not empty. Warning: Never call x.concat(y) when you are not + // certain that x is an Array (x could be a string with concat method). -/** - * Instance of element that should respond to touch/move types of interactions, - * as indicated explicitly by relevant callbacks. - */ + if (isArray(current)) { + return current.concat(next); + } -var responderInst = null; -/** - * Count of current touches. A textInput should become responder iff the - * selection changes while there is a touch on the screen. - */ + if (isArray(next)) { + return [current].concat(next); + } -var trackedTouchCount = 0; + return [current, next]; + } -var changeResponder = function(nextResponderInst, blockHostResponder) { - var oldResponderInst = responderInst; - responderInst = nextResponderInst; + /** + * Accumulates items that must not be null or undefined into the first one. This + * is used to conserve memory by avoiding array allocations, and thus sacrifices + * API cleanness. Since `current` can be null before being passed in and not + * null after this function, make sure to assign it back to `current`: + * + * `a = accumulateInto(a, b);` + * + * This API should be sparingly used. Try `accumulate` for something cleaner. + * + * @return {*|array<*>} An accumulation of items. + */ - if (ResponderEventPlugin.GlobalResponderHandler !== null) { - ResponderEventPlugin.GlobalResponderHandler.onChange( - oldResponderInst, - nextResponderInst, - blockHostResponder - ); - } -}; - -var eventTypes = { - /** - * On a `touchStart`/`mouseDown`, is it desired that this element become the - * responder? - */ - startShouldSetResponder: { - phasedRegistrationNames: { - bubbled: "onStartShouldSetResponder", - captured: "onStartShouldSetResponderCapture" - }, - dependencies: startDependencies - }, - - /** - * On a `scroll`, is it desired that this element become the responder? This - * is usually not needed, but should be used to retroactively infer that a - * `touchStart` had occurred during momentum scroll. During a momentum scroll, - * a touch start will be immediately followed by a scroll event if the view is - * currently scrolling. - * - * TODO: This shouldn't bubble. - */ - scrollShouldSetResponder: { - phasedRegistrationNames: { - bubbled: "onScrollShouldSetResponder", - captured: "onScrollShouldSetResponderCapture" - }, - dependencies: [TOP_SCROLL] - }, - - /** - * On text selection change, should this element become the responder? This - * is needed for text inputs or other views with native selection, so the - * JS view can claim the responder. - * - * TODO: This shouldn't bubble. - */ - selectionChangeShouldSetResponder: { - phasedRegistrationNames: { - bubbled: "onSelectionChangeShouldSetResponder", - captured: "onSelectionChangeShouldSetResponderCapture" - }, - dependencies: [TOP_SELECTION_CHANGE] - }, - - /** - * On a `touchMove`/`mouseMove`, is it desired that this element become the - * responder? - */ - moveShouldSetResponder: { - phasedRegistrationNames: { - bubbled: "onMoveShouldSetResponder", - captured: "onMoveShouldSetResponderCapture" - }, - dependencies: moveDependencies - }, - - /** - * Direct responder events dispatched directly to responder. Do not bubble. - */ - responderStart: { - registrationName: "onResponderStart", - dependencies: startDependencies - }, - responderMove: { - registrationName: "onResponderMove", - dependencies: moveDependencies - }, - responderEnd: { - registrationName: "onResponderEnd", - dependencies: endDependencies - }, - responderRelease: { - registrationName: "onResponderRelease", - dependencies: endDependencies - }, - responderTerminationRequest: { - registrationName: "onResponderTerminationRequest", - dependencies: [] - }, - responderGrant: { - registrationName: "onResponderGrant", - dependencies: [] - }, - responderReject: { - registrationName: "onResponderReject", - dependencies: [] - }, - responderTerminate: { - registrationName: "onResponderTerminate", - dependencies: [] - } -}; // Start of inline: the below functions were inlined from -// EventPropagator.js, as they deviated from ReactDOM's newer -// implementations. - -function getParent(inst) { - do { - inst = inst.return; // TODO: If this is a HostRoot we might want to bail out. - // That is depending on if we want nested subtrees (layers) to bubble - // events to their parent. We could also go through parentNode on the - // host node but that wouldn't work for React Native and doesn't let us - // do the portal feature. - } while (inst && inst.tag !== HostComponent); - - if (inst) { - return inst; - } - - return null; -} -/** - * Return the lowest common ancestor of A and B, or null if they are in - * different trees. - */ + function accumulateInto(current, next) { + if (next == null) { + throw new Error( + "accumulateInto(...): Accumulated items must not be null or undefined." + ); + } -function getLowestCommonAncestor(instA, instB) { - var depthA = 0; + if (current == null) { + return next; + } // Both are not empty. Warning: Never call x.concat(y) when you are not + // certain that x is an Array (x could be a string with concat method). - for (var tempA = instA; tempA; tempA = getParent(tempA)) { - depthA++; - } + if (isArray(current)) { + if (isArray(next)) { + current.push.apply(current, next); + return current; + } - var depthB = 0; + current.push(next); + return current; + } - for (var tempB = instB; tempB; tempB = getParent(tempB)) { - depthB++; - } // If A is deeper, crawl up. + if (isArray(next)) { + // A bit too dangerous to mutate `next`. + return [current].concat(next); + } - while (depthA - depthB > 0) { - instA = getParent(instA); - depthA--; - } // If B is deeper, crawl up. + return [current, next]; + } - while (depthB - depthA > 0) { - instB = getParent(instB); - depthB--; - } // Walk in lockstep until we find a match. + /** + * @param {array} arr an "accumulation" of items which is either an Array or + * a single item. Useful when paired with the `accumulate` module. This is a + * simple utility that allows us to reason about a collection of items, but + * handling the case when there is exactly one item (and we do not need to + * allocate an array). + * @param {function} cb Callback invoked with each element or a collection. + * @param {?} [scope] Scope used as `this` in a callback. + */ + function forEachAccumulated(arr, cb, scope) { + if (Array.isArray(arr)) { + arr.forEach(cb, scope); + } else if (arr) { + cb.call(scope, arr); + } + } + + 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 depth = depthA; + /** + * Instance of element that should respond to touch/move types of interactions, + * as indicated explicitly by relevant callbacks. + */ - while (depth--) { - if (instA === instB || instA === instB.alternate) { - return instA; - } + var responderInst = null; + /** + * Count of current touches. A textInput should become responder iff the + * selection changes while there is a touch on the screen. + */ - instA = getParent(instA); - instB = getParent(instB); - } + var trackedTouchCount = 0; - return null; -} -/** - * Return if A is an ancestor of B. - */ + var changeResponder = function (nextResponderInst, blockHostResponder) { + var oldResponderInst = responderInst; + responderInst = nextResponderInst; -function isAncestor(instA, instB) { - while (instB) { - if (instA === instB || instA === instB.alternate) { - return true; - } + if (ResponderEventPlugin.GlobalResponderHandler !== null) { + ResponderEventPlugin.GlobalResponderHandler.onChange( + oldResponderInst, + nextResponderInst, + blockHostResponder + ); + } + }; - instB = getParent(instB); - } + var eventTypes = { + /** + * On a `touchStart`/`mouseDown`, is it desired that this element become the + * responder? + */ + startShouldSetResponder: { + phasedRegistrationNames: { + bubbled: "onStartShouldSetResponder", + captured: "onStartShouldSetResponderCapture" + }, + dependencies: startDependencies + }, + + /** + * On a `scroll`, is it desired that this element become the responder? This + * is usually not needed, but should be used to retroactively infer that a + * `touchStart` had occurred during momentum scroll. During a momentum scroll, + * a touch start will be immediately followed by a scroll event if the view is + * currently scrolling. + * + * TODO: This shouldn't bubble. + */ + scrollShouldSetResponder: { + phasedRegistrationNames: { + bubbled: "onScrollShouldSetResponder", + captured: "onScrollShouldSetResponderCapture" + }, + dependencies: [TOP_SCROLL] + }, + + /** + * On text selection change, should this element become the responder? This + * is needed for text inputs or other views with native selection, so the + * JS view can claim the responder. + * + * TODO: This shouldn't bubble. + */ + selectionChangeShouldSetResponder: { + phasedRegistrationNames: { + bubbled: "onSelectionChangeShouldSetResponder", + captured: "onSelectionChangeShouldSetResponderCapture" + }, + dependencies: [TOP_SELECTION_CHANGE] + }, + + /** + * On a `touchMove`/`mouseMove`, is it desired that this element become the + * responder? + */ + moveShouldSetResponder: { + phasedRegistrationNames: { + bubbled: "onMoveShouldSetResponder", + captured: "onMoveShouldSetResponderCapture" + }, + dependencies: moveDependencies + }, + + /** + * Direct responder events dispatched directly to responder. Do not bubble. + */ + responderStart: { + registrationName: "onResponderStart", + dependencies: startDependencies + }, + responderMove: { + registrationName: "onResponderMove", + dependencies: moveDependencies + }, + responderEnd: { + registrationName: "onResponderEnd", + dependencies: endDependencies + }, + responderRelease: { + registrationName: "onResponderRelease", + dependencies: endDependencies + }, + responderTerminationRequest: { + registrationName: "onResponderTerminationRequest", + dependencies: [] + }, + responderGrant: { + registrationName: "onResponderGrant", + dependencies: [] + }, + responderReject: { + registrationName: "onResponderReject", + dependencies: [] + }, + responderTerminate: { + registrationName: "onResponderTerminate", + dependencies: [] + } + }; // Start of inline: the below functions were inlined from + // EventPropagator.js, as they deviated from ReactDOM's newer + // implementations. + + function getParent(inst) { + do { + inst = inst.return; // TODO: If this is a HostRoot we might want to bail out. + // That is depending on if we want nested subtrees (layers) to bubble + // events to their parent. We could also go through parentNode on the + // host node but that wouldn't work for React Native and doesn't let us + // do the portal feature. + } while (inst && inst.tag !== HostComponent); - return false; -} -/** - * Simulates the traversal of a two-phase, capture/bubble event dispatch. - */ + if (inst) { + return inst; + } -function traverseTwoPhase(inst, fn, arg) { - var path = []; + return null; + } + /** + * Return the lowest common ancestor of A and B, or null if they are in + * different trees. + */ - while (inst) { - path.push(inst); - inst = getParent(inst); - } + function getLowestCommonAncestor(instA, instB) { + var depthA = 0; - var i; + for (var tempA = instA; tempA; tempA = getParent(tempA)) { + depthA++; + } - for (i = path.length; i-- > 0; ) { - fn(path[i], "captured", arg); - } + var depthB = 0; - for (i = 0; i < path.length; i++) { - fn(path[i], "bubbled", arg); - } -} + for (var tempB = instB; tempB; tempB = getParent(tempB)) { + depthB++; + } // If A is deeper, crawl up. -function getListener(inst, registrationName) { - var stateNode = inst.stateNode; + while (depthA - depthB > 0) { + instA = getParent(instA); + depthA--; + } // If B is deeper, crawl up. - if (stateNode === null) { - // Work in progress (ex: onload events in incremental mode). - return null; - } + while (depthB - depthA > 0) { + instB = getParent(instB); + depthB--; + } // Walk in lockstep until we find a match. - var props = getFiberCurrentPropsFromNode(stateNode); + var depth = depthA; - if (props === null) { - // Work in progress. - return null; - } + while (depth--) { + if (instA === instB || instA === instB.alternate) { + return instA; + } - var listener = props[registrationName]; + instA = getParent(instA); + instB = getParent(instB); + } - if (listener && typeof listener !== "function") { - throw new Error( - "Expected `" + - registrationName + - "` listener to be a function, instead got a value of `" + - typeof listener + - "` type." - ); - } + return null; + } + /** + * Return if A is an ancestor of B. + */ - return listener; -} + function isAncestor(instA, instB) { + while (instB) { + if (instA === instB || instA === instB.alternate) { + return true; + } -function listenerAtPhase(inst, event, propagationPhase) { - var registrationName = - event.dispatchConfig.phasedRegistrationNames[propagationPhase]; - return getListener(inst, registrationName); -} + instB = getParent(instB); + } -function accumulateDirectionalDispatches(inst, phase, event) { - { - if (!inst) { - error("Dispatching inst must not be null"); + return false; } - } + /** + * Simulates the traversal of a two-phase, capture/bubble event dispatch. + */ - var listener = listenerAtPhase(inst, event, phase); + function traverseTwoPhase(inst, fn, arg) { + var path = []; - if (listener) { - event._dispatchListeners = accumulateInto( - event._dispatchListeners, - listener - ); - event._dispatchInstances = accumulateInto(event._dispatchInstances, inst); - } -} -/** - * Accumulates without regard to direction, does not look for phased - * registration names. Same as `accumulateDirectDispatchesSingle` but without - * requiring that the `dispatchMarker` be the same as the dispatched ID. - */ + while (inst) { + path.push(inst); + inst = getParent(inst); + } -function accumulateDispatches(inst, ignoredDirection, event) { - if (inst && event && event.dispatchConfig.registrationName) { - var registrationName = event.dispatchConfig.registrationName; - var listener = getListener(inst, registrationName); + var i; - if (listener) { - event._dispatchListeners = accumulateInto( - event._dispatchListeners, - listener - ); - event._dispatchInstances = accumulateInto(event._dispatchInstances, inst); - } - } -} -/** - * Accumulates dispatches on an `SyntheticEvent`, but only for the - * `dispatchMarker`. - * @param {SyntheticEvent} event - */ + for (i = path.length; i-- > 0;) { + fn(path[i], "captured", arg); + } -function accumulateDirectDispatchesSingle(event) { - if (event && event.dispatchConfig.registrationName) { - accumulateDispatches(event._targetInst, null, event); - } -} + for (i = 0; i < path.length; i++) { + fn(path[i], "bubbled", arg); + } + } -function accumulateDirectDispatches(events) { - forEachAccumulated(events, accumulateDirectDispatchesSingle); -} + function getListener(inst, registrationName) { + var stateNode = inst.stateNode; -function accumulateTwoPhaseDispatchesSingleSkipTarget(event) { - if (event && event.dispatchConfig.phasedRegistrationNames) { - var targetInst = event._targetInst; - var parentInst = targetInst ? getParent(targetInst) : null; - traverseTwoPhase(parentInst, accumulateDirectionalDispatches, event); - } -} + if (stateNode === null) { + // Work in progress (ex: onload events in incremental mode). + return null; + } -function accumulateTwoPhaseDispatchesSkipTarget(events) { - forEachAccumulated(events, accumulateTwoPhaseDispatchesSingleSkipTarget); -} + var props = getFiberCurrentPropsFromNode(stateNode); -function accumulateTwoPhaseDispatchesSingle(event) { - if (event && event.dispatchConfig.phasedRegistrationNames) { - traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event); - } -} + if (props === null) { + // Work in progress. + return null; + } -function accumulateTwoPhaseDispatches(events) { - forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle); -} // End of inline + var listener = props[registrationName]; -/** - * - * Responder System: - * ---------------- - * - * - A global, solitary "interaction lock" on a view. - * - If a node becomes the responder, it should convey visual feedback - * immediately to indicate so, either by highlighting or moving accordingly. - * - To be the responder means, that touches are exclusively important to that - * responder view, and no other view. - * - While touches are still occurring, the responder lock can be transferred to - * a new view, but only to increasingly "higher" views (meaning ancestors of - * the current responder). - * - * Responder being granted: - * ------------------------ - * - * - Touch starts, moves, and scrolls can cause an ID to become the responder. - * - We capture/bubble `startShouldSetResponder`/`moveShouldSetResponder` to - * the "appropriate place". - * - If nothing is currently the responder, the "appropriate place" is the - * initiating event's `targetID`. - * - If something *is* already the responder, the "appropriate place" is the - * first common ancestor of the event target and the current `responderInst`. - * - Some negotiation happens: See the timing diagram below. - * - Scrolled views automatically become responder. The reasoning is that a - * platform scroll view that isn't built on top of the responder system has - * began scrolling, and the active responder must now be notified that the - * interaction is no longer locked to it - the system has taken over. - * - * - Responder being released: - * As soon as no more touches that *started* inside of descendants of the - * *current* responderInst, an `onResponderRelease` event is dispatched to the - * current responder, and the responder lock is released. - * - * TODO: - * - on "end", a callback hook for `onResponderEndShouldRemainResponder` that - * determines if the responder lock should remain. - * - If a view shouldn't "remain" the responder, any active touches should by - * default be considered "dead" and do not influence future negotiations or - * bubble paths. It should be as if those touches do not exist. - * -- For multitouch: Usually a translate-z will choose to "remain" responder - * after one out of many touches ended. For translate-y, usually the view - * doesn't wish to "remain" responder after one of many touches end. - * - Consider building this on top of a `stopPropagation` model similar to - * `W3C` events. - * - Ensure that `onResponderTerminate` is called on touch cancels, whether or - * not `onResponderTerminationRequest` returns `true` or `false`. - * - */ + if (listener && typeof listener !== "function") { + throw new Error( + "Expected `" + + registrationName + + "` listener to be a function, instead got a value of `" + + typeof listener + + "` type." + ); + } -/* Negotiation Performed - +-----------------------+ - / \ -Process low level events to + Current Responder + wantsResponderID -determine who to perform negot-| (if any exists at all) | -iation/transition | Otherwise just pass through| --------------------------------+----------------------------+------------------+ -Bubble to find first ID | | -to return true:wantsResponderID| | - | | - +-------------+ | | - | onTouchStart| | | - +------+------+ none | | - | return| | -+-----------v-------------+true| +------------------------+ | -|onStartShouldSetResponder|----->|onResponderStart (cur) |<-----------+ -+-----------+-------------+ | +------------------------+ | | - | | | +--------+-------+ - | returned true for| false:REJECT +-------->|onResponderReject - | wantsResponderID | | | +----------------+ - | (now attempt | +------------------+-----+ | - | handoff) | | onResponder | | - +------------------->| TerminationRequest| | - | +------------------+-----+ | - | | | +----------------+ - | true:GRANT +-------->|onResponderGrant| - | | +--------+-------+ - | +------------------------+ | | - | | onResponderTerminate |<-----------+ - | +------------------+-----+ | - | | | +----------------+ - | +-------->|onResponderStart| - | | +----------------+ -Bubble to find first ID | | -to return true:wantsResponderID| | - | | - +-------------+ | | - | onTouchMove | | | - +------+------+ none | | - | return| | -+-----------v-------------+true| +------------------------+ | -|onMoveShouldSetResponder |----->|onResponderMove (cur) |<-----------+ -+-----------+-------------+ | +------------------------+ | | - | | | +--------+-------+ - | returned true for| false:REJECT +-------->|onResponderRejec| - | wantsResponderID | | | +----------------+ - | (now attempt | +------------------+-----+ | - | handoff) | | onResponder | | - +------------------->| TerminationRequest| | - | +------------------+-----+ | - | | | +----------------+ - | true:GRANT +-------->|onResponderGrant| - | | +--------+-------+ - | +------------------------+ | | - | | onResponderTerminate |<-----------+ - | +------------------+-----+ | - | | | +----------------+ - | +-------->|onResponderMove | - | | +----------------+ - | | - | | - Some active touch started| | - inside current responder | +------------------------+ | - +------------------------->| onResponderEnd | | - | | +------------------------+ | - +---+---------+ | | - | onTouchEnd | | | - +---+---------+ | | - | | +------------------------+ | - +------------------------->| onResponderEnd | | - No active touches started| +-----------+------------+ | - inside current responder | | | - | v | - | +------------------------+ | - | | onResponderRelease | | - | +------------------------+ | - | | - + + */ + return listener; + } -/** - * A note about event ordering in the `EventPluginRegistry`. - * - * Suppose plugins are injected in the following order: - * - * `[R, S, C]` - * - * To help illustrate the example, assume `S` is `SimpleEventPlugin` (for - * `onClick` etc) and `R` is `ResponderEventPlugin`. - * - * "Deferred-Dispatched Events": - * - * - The current event plugin system will traverse the list of injected plugins, - * in order, and extract events by collecting the plugin's return value of - * `extractEvents()`. - * - These events that are returned from `extractEvents` are "deferred - * dispatched events". - * - When returned from `extractEvents`, deferred-dispatched events contain an - * "accumulation" of deferred dispatches. - * - These deferred dispatches are accumulated/collected before they are - * returned, but processed at a later time by the `EventPluginRegistry` (hence the - * name deferred). - * - * In the process of returning their deferred-dispatched events, event plugins - * themselves can dispatch events on-demand without returning them from - * `extractEvents`. Plugins might want to do this, so that they can use event - * dispatching as a tool that helps them decide which events should be extracted - * in the first place. - * - * "On-Demand-Dispatched Events": - * - * - On-demand-dispatched events are not returned from `extractEvents`. - * - On-demand-dispatched events are dispatched during the process of returning - * the deferred-dispatched events. - * - They should not have side effects. - * - They should be avoided, and/or eventually be replaced with another - * abstraction that allows event plugins to perform multiple "rounds" of event - * extraction. - * - * Therefore, the sequence of event dispatches becomes: - * - * - `R`s on-demand events (if any) (dispatched by `R` on-demand) - * - `S`s on-demand events (if any) (dispatched by `S` on-demand) - * - `C`s on-demand events (if any) (dispatched by `C` on-demand) - * - `R`s extracted events (if any) (dispatched by `EventPluginRegistry`) - * - `S`s extracted events (if any) (dispatched by `EventPluginRegistry`) - * - `C`s extracted events (if any) (dispatched by `EventPluginRegistry`) - * - * In the case of `ResponderEventPlugin`: If the `startShouldSetResponder` - * on-demand dispatch returns `true` (and some other details are satisfied) the - * `onResponderGrant` deferred dispatched event is returned from - * `extractEvents`. The sequence of dispatch executions in this case - * will appear as follows: - * - * - `startShouldSetResponder` (`ResponderEventPlugin` dispatches on-demand) - * - `touchStartCapture` (`EventPluginRegistry` dispatches as usual) - * - `touchStart` (`EventPluginRegistry` dispatches as usual) - * - `responderGrant/Reject` (`EventPluginRegistry` dispatches as usual) - */ + function listenerAtPhase(inst, event, propagationPhase) { + var registrationName = + event.dispatchConfig.phasedRegistrationNames[propagationPhase]; + return getListener(inst, registrationName); + } -function setResponderAndExtractTransfer( - topLevelType, - targetInst, - nativeEvent, - nativeEventTarget -) { - var shouldSetEventType = isStartish(topLevelType) - ? eventTypes.startShouldSetResponder - : isMoveish(topLevelType) - ? eventTypes.moveShouldSetResponder - : topLevelType === TOP_SELECTION_CHANGE - ? eventTypes.selectionChangeShouldSetResponder - : eventTypes.scrollShouldSetResponder; // TODO: stop one short of the current responder. - - var bubbleShouldSetFrom = !responderInst - ? targetInst - : getLowestCommonAncestor(responderInst, targetInst); // When capturing/bubbling the "shouldSet" event, we want to skip the target - // (deepest ID) if it happens to be the current responder. The reasoning: - // It's strange to get an `onMoveShouldSetResponder` when you're *already* - // the responder. - - var skipOverBubbleShouldSetFrom = bubbleShouldSetFrom === responderInst; - var shouldSetEvent = ResponderSyntheticEvent.getPooled( - shouldSetEventType, - bubbleShouldSetFrom, - nativeEvent, - nativeEventTarget - ); - shouldSetEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; - - if (skipOverBubbleShouldSetFrom) { - accumulateTwoPhaseDispatchesSkipTarget(shouldSetEvent); - } else { - accumulateTwoPhaseDispatches(shouldSetEvent); - } - - var wantsResponderInst = executeDispatchesInOrderStopAtTrue(shouldSetEvent); - - if (!shouldSetEvent.isPersistent()) { - shouldSetEvent.constructor.release(shouldSetEvent); - } - - if (!wantsResponderInst || wantsResponderInst === responderInst) { - return null; - } - - var extracted; - var grantEvent = ResponderSyntheticEvent.getPooled( - eventTypes.responderGrant, - wantsResponderInst, - nativeEvent, - nativeEventTarget - ); - grantEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; - accumulateDirectDispatches(grantEvent); - var blockHostResponder = executeDirectDispatch(grantEvent) === true; - - if (responderInst) { - var terminationRequestEvent = ResponderSyntheticEvent.getPooled( - eventTypes.responderTerminationRequest, - responderInst, - nativeEvent, - nativeEventTarget - ); - terminationRequestEvent.touchHistory = - ResponderTouchHistoryStore.touchHistory; - accumulateDirectDispatches(terminationRequestEvent); - var shouldSwitch = - !hasDispatches(terminationRequestEvent) || - executeDirectDispatch(terminationRequestEvent); + function accumulateDirectionalDispatches(inst, phase, event) { + { + if (!inst) { + error("Dispatching inst must not be null"); + } + } - if (!terminationRequestEvent.isPersistent()) { - terminationRequestEvent.constructor.release(terminationRequestEvent); - } + var listener = listenerAtPhase(inst, event, phase); - if (shouldSwitch) { - var terminateEvent = ResponderSyntheticEvent.getPooled( - eventTypes.responderTerminate, - responderInst, - nativeEvent, - nativeEventTarget - ); - terminateEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; - accumulateDirectDispatches(terminateEvent); - extracted = accumulate(extracted, [grantEvent, terminateEvent]); - changeResponder(wantsResponderInst, blockHostResponder); - } else { - var rejectEvent = ResponderSyntheticEvent.getPooled( - eventTypes.responderReject, - wantsResponderInst, - nativeEvent, - nativeEventTarget - ); - rejectEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; - accumulateDirectDispatches(rejectEvent); - extracted = accumulate(extracted, rejectEvent); + if (listener) { + event._dispatchListeners = accumulateInto( + event._dispatchListeners, + listener + ); + event._dispatchInstances = accumulateInto(event._dispatchInstances, inst); + } } - } else { - extracted = accumulate(extracted, grantEvent); - changeResponder(wantsResponderInst, blockHostResponder); - } + /** + * Accumulates without regard to direction, does not look for phased + * registration names. Same as `accumulateDirectDispatchesSingle` but without + * requiring that the `dispatchMarker` be the same as the dispatched ID. + */ - return extracted; -} -/** - * A transfer is a negotiation between a currently set responder and the next - * element to claim responder status. Any start event could trigger a transfer - * of responderInst. Any move event could trigger a transfer. - * - * @param {string} topLevelType Record from `BrowserEventConstants`. - * @return {boolean} True if a transfer of responder could possibly occur. - */ + function accumulateDispatches(inst, ignoredDirection, event) { + if (inst && event && event.dispatchConfig.registrationName) { + var registrationName = event.dispatchConfig.registrationName; + var listener = getListener(inst, registrationName); -function canTriggerTransfer(topLevelType, topLevelInst, nativeEvent) { - return ( - topLevelInst && // responderIgnoreScroll: We are trying to migrate away from specifically - // tracking native scroll events here and responderIgnoreScroll indicates we - // will send topTouchCancel to handle canceling touch events instead - ((topLevelType === TOP_SCROLL && !nativeEvent.responderIgnoreScroll) || - (trackedTouchCount > 0 && topLevelType === TOP_SELECTION_CHANGE) || - isStartish(topLevelType) || - isMoveish(topLevelType)) - ); -} -/** - * Returns whether or not this touch end event makes it such that there are no - * longer any touches that started inside of the current `responderInst`. - * - * @param {NativeEvent} nativeEvent Native touch end event. - * @return {boolean} Whether or not this touch end event ends the responder. - */ + if (listener) { + event._dispatchListeners = accumulateInto( + event._dispatchListeners, + listener + ); + event._dispatchInstances = accumulateInto(event._dispatchInstances, inst); + } + } + } + /** + * Accumulates dispatches on an `SyntheticEvent`, but only for the + * `dispatchMarker`. + * @param {SyntheticEvent} event + */ -function noResponderTouches(nativeEvent) { - var touches = nativeEvent.touches; + function accumulateDirectDispatchesSingle(event) { + if (event && event.dispatchConfig.registrationName) { + accumulateDispatches(event._targetInst, null, event); + } + } - if (!touches || touches.length === 0) { - return true; - } + function accumulateDirectDispatches(events) { + forEachAccumulated(events, accumulateDirectDispatchesSingle); + } - for (var i = 0; i < touches.length; i++) { - var activeTouch = touches[i]; - var target = activeTouch.target; + function accumulateTwoPhaseDispatchesSingleSkipTarget(event) { + if (event && event.dispatchConfig.phasedRegistrationNames) { + var targetInst = event._targetInst; + var parentInst = targetInst ? getParent(targetInst) : null; + traverseTwoPhase(parentInst, accumulateDirectionalDispatches, event); + } + } - if (target !== null && target !== undefined && target !== 0) { - // Is the original touch location inside of the current responder? - var targetInst = getInstanceFromNode(target); + function accumulateTwoPhaseDispatchesSkipTarget(events) { + forEachAccumulated(events, accumulateTwoPhaseDispatchesSingleSkipTarget); + } - if (isAncestor(responderInst, targetInst)) { - return false; + function accumulateTwoPhaseDispatchesSingle(event) { + if (event && event.dispatchConfig.phasedRegistrationNames) { + traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event); } } - } - return true; -} + function accumulateTwoPhaseDispatches(events) { + forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle); + } // End of inline -var ResponderEventPlugin = { - /* For unit testing only */ - _getResponder: function() { - return responderInst; - }, - eventTypes: eventTypes, - - /** - * We must be resilient to `targetInst` being `null` on `touchMove` or - * `touchEnd`. On certain platforms, this means that a native scroll has - * assumed control and the original touch targets are destroyed. - */ - extractEvents: function( - topLevelType, - targetInst, - nativeEvent, - nativeEventTarget, - eventSystemFlags - ) { - if (isStartish(topLevelType)) { - trackedTouchCount += 1; - } else if (isEndish(topLevelType)) { - if (trackedTouchCount >= 0) { - trackedTouchCount -= 1; - } else { - { - warn( - "Ended a touch event which was not counted in `trackedTouchCount`." - ); - } + /** + * + * Responder System: + * ---------------- + * + * - A global, solitary "interaction lock" on a view. + * - If a node becomes the responder, it should convey visual feedback + * immediately to indicate so, either by highlighting or moving accordingly. + * - To be the responder means, that touches are exclusively important to that + * responder view, and no other view. + * - While touches are still occurring, the responder lock can be transferred to + * a new view, but only to increasingly "higher" views (meaning ancestors of + * the current responder). + * + * Responder being granted: + * ------------------------ + * + * - Touch starts, moves, and scrolls can cause an ID to become the responder. + * - We capture/bubble `startShouldSetResponder`/`moveShouldSetResponder` to + * the "appropriate place". + * - If nothing is currently the responder, the "appropriate place" is the + * initiating event's `targetID`. + * - If something *is* already the responder, the "appropriate place" is the + * first common ancestor of the event target and the current `responderInst`. + * - Some negotiation happens: See the timing diagram below. + * - Scrolled views automatically become responder. The reasoning is that a + * platform scroll view that isn't built on top of the responder system has + * began scrolling, and the active responder must now be notified that the + * interaction is no longer locked to it - the system has taken over. + * + * - Responder being released: + * As soon as no more touches that *started* inside of descendants of the + * *current* responderInst, an `onResponderRelease` event is dispatched to the + * current responder, and the responder lock is released. + * + * TODO: + * - on "end", a callback hook for `onResponderEndShouldRemainResponder` that + * determines if the responder lock should remain. + * - If a view shouldn't "remain" the responder, any active touches should by + * default be considered "dead" and do not influence future negotiations or + * bubble paths. It should be as if those touches do not exist. + * -- For multitouch: Usually a translate-z will choose to "remain" responder + * after one out of many touches ended. For translate-y, usually the view + * doesn't wish to "remain" responder after one of many touches end. + * - Consider building this on top of a `stopPropagation` model similar to + * `W3C` events. + * - Ensure that `onResponderTerminate` is called on touch cancels, whether or + * not `onResponderTerminationRequest` returns `true` or `false`. + * + */ - return null; - } - } + /* Negotiation Performed + +-----------------------+ + / \ + Process low level events to + Current Responder + wantsResponderID + determine who to perform negot-| (if any exists at all) | + iation/transition | Otherwise just pass through| + -------------------------------+----------------------------+------------------+ + Bubble to find first ID | | + to return true:wantsResponderID| | + | | + +-------------+ | | + | onTouchStart| | | + +------+------+ none | | + | return| | + +-----------v-------------+true| +------------------------+ | + |onStartShouldSetResponder|----->|onResponderStart (cur) |<-----------+ + +-----------+-------------+ | +------------------------+ | | + | | | +--------+-------+ + | returned true for| false:REJECT +-------->|onResponderReject + | wantsResponderID | | | +----------------+ + | (now attempt | +------------------+-----+ | + | handoff) | | onResponder | | + +------------------->| TerminationRequest| | + | +------------------+-----+ | + | | | +----------------+ + | true:GRANT +-------->|onResponderGrant| + | | +--------+-------+ + | +------------------------+ | | + | | onResponderTerminate |<-----------+ + | +------------------+-----+ | + | | | +----------------+ + | +-------->|onResponderStart| + | | +----------------+ + Bubble to find first ID | | + to return true:wantsResponderID| | + | | + +-------------+ | | + | onTouchMove | | | + +------+------+ none | | + | return| | + +-----------v-------------+true| +------------------------+ | + |onMoveShouldSetResponder |----->|onResponderMove (cur) |<-----------+ + +-----------+-------------+ | +------------------------+ | | + | | | +--------+-------+ + | returned true for| false:REJECT +-------->|onResponderRejec| + | wantsResponderID | | | +----------------+ + | (now attempt | +------------------+-----+ | + | handoff) | | onResponder | | + +------------------->| TerminationRequest| | + | +------------------+-----+ | + | | | +----------------+ + | true:GRANT +-------->|onResponderGrant| + | | +--------+-------+ + | +------------------------+ | | + | | onResponderTerminate |<-----------+ + | +------------------+-----+ | + | | | +----------------+ + | +-------->|onResponderMove | + | | +----------------+ + | | + | | + Some active touch started| | + inside current responder | +------------------------+ | + +------------------------->| onResponderEnd | | + | | +------------------------+ | + +---+---------+ | | + | onTouchEnd | | | + +---+---------+ | | + | | +------------------------+ | + +------------------------->| onResponderEnd | | + No active touches started| +-----------+------------+ | + inside current responder | | | + | v | + | +------------------------+ | + | | onResponderRelease | | + | +------------------------+ | + | | + + + */ - ResponderTouchHistoryStore.recordTouchTrack(topLevelType, nativeEvent); - var extracted = canTriggerTransfer(topLevelType, targetInst, nativeEvent) - ? setResponderAndExtractTransfer( - topLevelType, - targetInst, - nativeEvent, - nativeEventTarget - ) - : null; // Responder may or may not have transferred on a new touch start/move. - // Regardless, whoever is the responder after any potential transfer, we - // direct all touch start/move/ends to them in the form of - // `onResponderMove/Start/End`. These will be called for *every* additional - // finger that move/start/end, dispatched directly to whoever is the - // current responder at that moment, until the responder is "released". - // - // These multiple individual change touch events are are always bookended - // by `onResponderGrant`, and one of - // (`onResponderRelease/onResponderTerminate`). - - var isResponderTouchStart = responderInst && isStartish(topLevelType); - var isResponderTouchMove = responderInst && isMoveish(topLevelType); - var isResponderTouchEnd = responderInst && isEndish(topLevelType); - var incrementalTouch = isResponderTouchStart - ? eventTypes.responderStart - : isResponderTouchMove - ? eventTypes.responderMove - : isResponderTouchEnd - ? eventTypes.responderEnd - : null; - - if (incrementalTouch) { - var gesture = ResponderSyntheticEvent.getPooled( - incrementalTouch, - responderInst, - nativeEvent, - nativeEventTarget - ); - gesture.touchHistory = ResponderTouchHistoryStore.touchHistory; - accumulateDirectDispatches(gesture); - extracted = accumulate(extracted, gesture); - } - - var isResponderTerminate = - responderInst && topLevelType === TOP_TOUCH_CANCEL; - var isResponderRelease = - responderInst && - !isResponderTerminate && - isEndish(topLevelType) && - noResponderTouches(nativeEvent); - var finalTouch = isResponderTerminate - ? eventTypes.responderTerminate - : isResponderRelease - ? eventTypes.responderRelease - : null; - - if (finalTouch) { - var finalEvent = ResponderSyntheticEvent.getPooled( - finalTouch, - responderInst, + /** + * A note about event ordering in the `EventPluginRegistry`. + * + * Suppose plugins are injected in the following order: + * + * `[R, S, C]` + * + * To help illustrate the example, assume `S` is `SimpleEventPlugin` (for + * `onClick` etc) and `R` is `ResponderEventPlugin`. + * + * "Deferred-Dispatched Events": + * + * - The current event plugin system will traverse the list of injected plugins, + * in order, and extract events by collecting the plugin's return value of + * `extractEvents()`. + * - These events that are returned from `extractEvents` are "deferred + * dispatched events". + * - When returned from `extractEvents`, deferred-dispatched events contain an + * "accumulation" of deferred dispatches. + * - These deferred dispatches are accumulated/collected before they are + * returned, but processed at a later time by the `EventPluginRegistry` (hence the + * name deferred). + * + * In the process of returning their deferred-dispatched events, event plugins + * themselves can dispatch events on-demand without returning them from + * `extractEvents`. Plugins might want to do this, so that they can use event + * dispatching as a tool that helps them decide which events should be extracted + * in the first place. + * + * "On-Demand-Dispatched Events": + * + * - On-demand-dispatched events are not returned from `extractEvents`. + * - On-demand-dispatched events are dispatched during the process of returning + * the deferred-dispatched events. + * - They should not have side effects. + * - They should be avoided, and/or eventually be replaced with another + * abstraction that allows event plugins to perform multiple "rounds" of event + * extraction. + * + * Therefore, the sequence of event dispatches becomes: + * + * - `R`s on-demand events (if any) (dispatched by `R` on-demand) + * - `S`s on-demand events (if any) (dispatched by `S` on-demand) + * - `C`s on-demand events (if any) (dispatched by `C` on-demand) + * - `R`s extracted events (if any) (dispatched by `EventPluginRegistry`) + * - `S`s extracted events (if any) (dispatched by `EventPluginRegistry`) + * - `C`s extracted events (if any) (dispatched by `EventPluginRegistry`) + * + * In the case of `ResponderEventPlugin`: If the `startShouldSetResponder` + * on-demand dispatch returns `true` (and some other details are satisfied) the + * `onResponderGrant` deferred dispatched event is returned from + * `extractEvents`. The sequence of dispatch executions in this case + * will appear as follows: + * + * - `startShouldSetResponder` (`ResponderEventPlugin` dispatches on-demand) + * - `touchStartCapture` (`EventPluginRegistry` dispatches as usual) + * - `touchStart` (`EventPluginRegistry` dispatches as usual) + * - `responderGrant/Reject` (`EventPluginRegistry` dispatches as usual) + */ + + function setResponderAndExtractTransfer( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget + ) { + var shouldSetEventType = isStartish(topLevelType) + ? eventTypes.startShouldSetResponder + : isMoveish(topLevelType) + ? eventTypes.moveShouldSetResponder + : topLevelType === TOP_SELECTION_CHANGE + ? eventTypes.selectionChangeShouldSetResponder + : eventTypes.scrollShouldSetResponder; // TODO: stop one short of the current responder. + + var bubbleShouldSetFrom = !responderInst + ? targetInst + : getLowestCommonAncestor(responderInst, targetInst); // When capturing/bubbling the "shouldSet" event, we want to skip the target + // (deepest ID) if it happens to be the current responder. The reasoning: + // It's strange to get an `onMoveShouldSetResponder` when you're *already* + // the responder. + + var skipOverBubbleShouldSetFrom = bubbleShouldSetFrom === responderInst; + var shouldSetEvent = ResponderSyntheticEvent.getPooled( + shouldSetEventType, + bubbleShouldSetFrom, nativeEvent, nativeEventTarget ); - finalEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; - accumulateDirectDispatches(finalEvent); - extracted = accumulate(extracted, finalEvent); - changeResponder(null); - } - - return extracted; - }, - GlobalResponderHandler: null, - injection: { - /** - * @param {{onChange: (ReactID, ReactID) => void} GlobalResponderHandler - * Object that handles any change in responder. Use this to inject - * integration with an existing touch handling system etc. - */ - injectGlobalResponderHandler: function(GlobalResponderHandler) { - ResponderEventPlugin.GlobalResponderHandler = GlobalResponderHandler; - } - } -}; + shouldSetEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; -/** - * Injectable ordering of event plugins. - */ -var eventPluginOrder = null; -/** - * Injectable mapping from names to event plugin modules. - */ + if (skipOverBubbleShouldSetFrom) { + accumulateTwoPhaseDispatchesSkipTarget(shouldSetEvent); + } else { + accumulateTwoPhaseDispatches(shouldSetEvent); + } -var namesToPlugins = {}; -/** - * Recomputes the plugin list using the injected plugins and plugin ordering. - * - * @private - */ + var wantsResponderInst = executeDispatchesInOrderStopAtTrue(shouldSetEvent); -function recomputePluginOrdering() { - if (!eventPluginOrder) { - // Wait until an `eventPluginOrder` is injected. - return; - } + if (!shouldSetEvent.isPersistent()) { + shouldSetEvent.constructor.release(shouldSetEvent); + } - for (var pluginName in namesToPlugins) { - var pluginModule = namesToPlugins[pluginName]; - var pluginIndex = eventPluginOrder.indexOf(pluginName); + if (!wantsResponderInst || wantsResponderInst === responderInst) { + return null; + } - if (pluginIndex <= -1) { - throw new Error( - "EventPluginRegistry: Cannot inject event plugins that do not exist in " + - ("the plugin ordering, `" + pluginName + "`.") + var extracted; + var grantEvent = ResponderSyntheticEvent.getPooled( + eventTypes.responderGrant, + wantsResponderInst, + nativeEvent, + nativeEventTarget ); - } + grantEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; + accumulateDirectDispatches(grantEvent); + var blockHostResponder = executeDirectDispatch(grantEvent) === true; + + if (responderInst) { + var terminationRequestEvent = ResponderSyntheticEvent.getPooled( + eventTypes.responderTerminationRequest, + responderInst, + nativeEvent, + nativeEventTarget + ); + terminationRequestEvent.touchHistory = + ResponderTouchHistoryStore.touchHistory; + accumulateDirectDispatches(terminationRequestEvent); + var shouldSwitch = + !hasDispatches(terminationRequestEvent) || + executeDirectDispatch(terminationRequestEvent); + + if (!terminationRequestEvent.isPersistent()) { + terminationRequestEvent.constructor.release(terminationRequestEvent); + } - if (plugins[pluginIndex]) { - continue; + if (shouldSwitch) { + var terminateEvent = ResponderSyntheticEvent.getPooled( + eventTypes.responderTerminate, + responderInst, + nativeEvent, + nativeEventTarget + ); + terminateEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; + accumulateDirectDispatches(terminateEvent); + extracted = accumulate(extracted, [grantEvent, terminateEvent]); + changeResponder(wantsResponderInst, blockHostResponder); + } else { + var rejectEvent = ResponderSyntheticEvent.getPooled( + eventTypes.responderReject, + wantsResponderInst, + nativeEvent, + nativeEventTarget + ); + rejectEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; + accumulateDirectDispatches(rejectEvent); + extracted = accumulate(extracted, rejectEvent); + } + } else { + extracted = accumulate(extracted, grantEvent); + changeResponder(wantsResponderInst, blockHostResponder); + } + + return extracted; } + /** + * A transfer is a negotiation between a currently set responder and the next + * element to claim responder status. Any start event could trigger a transfer + * of responderInst. Any move event could trigger a transfer. + * + * @param {string} topLevelType Record from `BrowserEventConstants`. + * @return {boolean} True if a transfer of responder could possibly occur. + */ - if (!pluginModule.extractEvents) { - throw new Error( - "EventPluginRegistry: Event plugins must implement an `extractEvents` " + - ("method, but `" + pluginName + "` does not.") + function canTriggerTransfer(topLevelType, topLevelInst, nativeEvent) { + return ( + topLevelInst && // responderIgnoreScroll: We are trying to migrate away from specifically + // tracking native scroll events here and responderIgnoreScroll indicates we + // will send topTouchCancel to handle canceling touch events instead + ((topLevelType === TOP_SCROLL && !nativeEvent.responderIgnoreScroll) || + (trackedTouchCount > 0 && topLevelType === TOP_SELECTION_CHANGE) || + isStartish(topLevelType) || + isMoveish(topLevelType)) ); } + /** + * Returns whether or not this touch end event makes it such that there are no + * longer any touches that started inside of the current `responderInst`. + * + * @param {NativeEvent} nativeEvent Native touch end event. + * @return {boolean} Whether or not this touch end event ends the responder. + */ - plugins[pluginIndex] = pluginModule; - var publishedEvents = pluginModule.eventTypes; + function noResponderTouches(nativeEvent) { + var touches = nativeEvent.touches; - for (var eventName in publishedEvents) { - if ( - !publishEventForPlugin( - publishedEvents[eventName], - pluginModule, - eventName - ) - ) { - throw new Error( - "EventPluginRegistry: Failed to publish event `" + - eventName + - "` for plugin `" + - pluginName + - "`." - ); + if (!touches || touches.length === 0) { + return true; } - } - } -} -/** - * Publishes an event so that it can be dispatched by the supplied plugin. - * - * @param {object} dispatchConfig Dispatch configuration for the event. - * @param {object} PluginModule Plugin publishing the event. - * @return {boolean} True if the event was successfully published. - * @private - */ -function publishEventForPlugin(dispatchConfig, pluginModule, eventName) { - if (eventNameDispatchConfigs.hasOwnProperty(eventName)) { - throw new Error( - "EventPluginRegistry: More than one plugin attempted to publish the same " + - ("event name, `" + eventName + "`.") - ); - } + for (var i = 0; i < touches.length; i++) { + var activeTouch = touches[i]; + var target = activeTouch.target; - eventNameDispatchConfigs[eventName] = dispatchConfig; - var phasedRegistrationNames = dispatchConfig.phasedRegistrationNames; + if (target !== null && target !== undefined && target !== 0) { + // Is the original touch location inside of the current responder? + var targetInst = getInstanceFromNode(target); - if (phasedRegistrationNames) { - for (var phaseName in phasedRegistrationNames) { - if (phasedRegistrationNames.hasOwnProperty(phaseName)) { - var phasedRegistrationName = phasedRegistrationNames[phaseName]; - publishRegistrationName( - phasedRegistrationName, - pluginModule, - eventName - ); + if (isAncestor(responderInst, targetInst)) { + return false; + } + } } + + return true; } - return true; - } else if (dispatchConfig.registrationName) { - publishRegistrationName( - dispatchConfig.registrationName, - pluginModule, - eventName - ); - return true; - } + var ResponderEventPlugin = { + /* For unit testing only */ + _getResponder: function () { + return responderInst; + }, + eventTypes: eventTypes, - return false; -} -/** - * Publishes a registration name that is used to identify dispatched events. - * - * @param {string} registrationName Registration name to add. - * @param {object} PluginModule Plugin publishing the event. - * @private - */ + /** + * We must be resilient to `targetInst` being `null` on `touchMove` or + * `touchEnd`. On certain platforms, this means that a native scroll has + * assumed control and the original touch targets are destroyed. + */ + extractEvents: function ( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget, + eventSystemFlags + ) { + if (isStartish(topLevelType)) { + trackedTouchCount += 1; + } else if (isEndish(topLevelType)) { + if (trackedTouchCount >= 0) { + trackedTouchCount -= 1; + } else { + { + warn( + "Ended a touch event which was not counted in `trackedTouchCount`." + ); + } -function publishRegistrationName(registrationName, pluginModule, eventName) { - if (registrationNameModules[registrationName]) { - throw new Error( - "EventPluginRegistry: More than one plugin attempted to publish the same " + - ("registration name, `" + registrationName + "`.") - ); - } + return null; + } + } - registrationNameModules[registrationName] = pluginModule; - registrationNameDependencies[registrationName] = - pluginModule.eventTypes[eventName].dependencies; + ResponderTouchHistoryStore.recordTouchTrack(topLevelType, nativeEvent); + var extracted = canTriggerTransfer(topLevelType, targetInst, nativeEvent) + ? setResponderAndExtractTransfer( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget + ) + : null; // Responder may or may not have transferred on a new touch start/move. + // Regardless, whoever is the responder after any potential transfer, we + // direct all touch start/move/ends to them in the form of + // `onResponderMove/Start/End`. These will be called for *every* additional + // finger that move/start/end, dispatched directly to whoever is the + // current responder at that moment, until the responder is "released". + // + // These multiple individual change touch events are are always bookended + // by `onResponderGrant`, and one of + // (`onResponderRelease/onResponderTerminate`). + + var isResponderTouchStart = responderInst && isStartish(topLevelType); + var isResponderTouchMove = responderInst && isMoveish(topLevelType); + var isResponderTouchEnd = responderInst && isEndish(topLevelType); + var incrementalTouch = isResponderTouchStart + ? eventTypes.responderStart + : isResponderTouchMove + ? eventTypes.responderMove + : isResponderTouchEnd + ? eventTypes.responderEnd + : null; + + if (incrementalTouch) { + var gesture = ResponderSyntheticEvent.getPooled( + incrementalTouch, + responderInst, + nativeEvent, + nativeEventTarget + ); + gesture.touchHistory = ResponderTouchHistoryStore.touchHistory; + accumulateDirectDispatches(gesture); + extracted = accumulate(extracted, gesture); + } - { - var lowerCasedName = registrationName.toLowerCase(); - } -} -/** - * Registers plugins so that they can extract and dispatch events. - */ + var isResponderTerminate = + responderInst && topLevelType === TOP_TOUCH_CANCEL; + var isResponderRelease = + responderInst && + !isResponderTerminate && + isEndish(topLevelType) && + noResponderTouches(nativeEvent); + var finalTouch = isResponderTerminate + ? eventTypes.responderTerminate + : isResponderRelease + ? eventTypes.responderRelease + : null; + + if (finalTouch) { + var finalEvent = ResponderSyntheticEvent.getPooled( + finalTouch, + responderInst, + nativeEvent, + nativeEventTarget + ); + finalEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; + accumulateDirectDispatches(finalEvent); + extracted = accumulate(extracted, finalEvent); + changeResponder(null); + } -/** - * Ordered list of injected plugins. - */ + return extracted; + }, + GlobalResponderHandler: null, + injection: { + /** + * @param {{onChange: (ReactID, ReactID) => void} GlobalResponderHandler + * Object that handles any change in responder. Use this to inject + * integration with an existing touch handling system etc. + */ + injectGlobalResponderHandler: function (GlobalResponderHandler) { + ResponderEventPlugin.GlobalResponderHandler = GlobalResponderHandler; + } + } + }; -var plugins = []; -/** - * Mapping from event name to dispatch config - */ + /** + * Injectable ordering of event plugins. + */ + var eventPluginOrder = null; + /** + * Injectable mapping from names to event plugin modules. + */ -var eventNameDispatchConfigs = {}; -/** - * Mapping from registration name to plugin module - */ + var namesToPlugins = {}; + /** + * Recomputes the plugin list using the injected plugins and plugin ordering. + * + * @private + */ -var registrationNameModules = {}; -/** - * Mapping from registration name to event name - */ + function recomputePluginOrdering() { + if (!eventPluginOrder) { + // Wait until an `eventPluginOrder` is injected. + return; + } -var registrationNameDependencies = {}; + for (var pluginName in namesToPlugins) { + var pluginModule = namesToPlugins[pluginName]; + var pluginIndex = eventPluginOrder.indexOf(pluginName); -/** - * Injects an ordering of plugins (by plugin name). This allows the ordering - * to be decoupled from injection of the actual plugins so that ordering is - * always deterministic regardless of packaging, on-the-fly injection, etc. - * - * @param {array} InjectedEventPluginOrder - * @internal - */ + if (pluginIndex <= -1) { + throw new Error( + "EventPluginRegistry: Cannot inject event plugins that do not exist in " + + ("the plugin ordering, `" + pluginName + "`.") + ); + } -function injectEventPluginOrder(injectedEventPluginOrder) { - if (eventPluginOrder) { - throw new Error( - "EventPluginRegistry: Cannot inject event plugin ordering more than " + - "once. You are likely trying to load more than one copy of React." - ); - } // Clone the ordering so it cannot be dynamically mutated. + if (plugins[pluginIndex]) { + continue; + } - eventPluginOrder = Array.prototype.slice.call(injectedEventPluginOrder); - recomputePluginOrdering(); -} -/** - * Injects plugins to be used by plugin event system. The plugin names must be - * in the ordering injected by `injectEventPluginOrder`. - * - * Plugins can be injected as part of page initialization or on-the-fly. - * - * @param {object} injectedNamesToPlugins Map from names to plugin modules. - * @internal - */ + if (!pluginModule.extractEvents) { + throw new Error( + "EventPluginRegistry: Event plugins must implement an `extractEvents` " + + ("method, but `" + pluginName + "` does not.") + ); + } -function injectEventPluginsByName(injectedNamesToPlugins) { - var isOrderingDirty = false; + plugins[pluginIndex] = pluginModule; + var publishedEvents = pluginModule.eventTypes; - for (var pluginName in injectedNamesToPlugins) { - if (!injectedNamesToPlugins.hasOwnProperty(pluginName)) { - continue; + for (var eventName in publishedEvents) { + if ( + !publishEventForPlugin( + publishedEvents[eventName], + pluginModule, + eventName + ) + ) { + throw new Error( + "EventPluginRegistry: Failed to publish event `" + + eventName + + "` for plugin `" + + pluginName + + "`." + ); + } + } + } } + /** + * Publishes an event so that it can be dispatched by the supplied plugin. + * + * @param {object} dispatchConfig Dispatch configuration for the event. + * @param {object} PluginModule Plugin publishing the event. + * @return {boolean} True if the event was successfully published. + * @private + */ - var pluginModule = injectedNamesToPlugins[pluginName]; - - if ( - !namesToPlugins.hasOwnProperty(pluginName) || - namesToPlugins[pluginName] !== pluginModule - ) { - if (namesToPlugins[pluginName]) { + function publishEventForPlugin(dispatchConfig, pluginModule, eventName) { + if (eventNameDispatchConfigs.hasOwnProperty(eventName)) { throw new Error( - "EventPluginRegistry: Cannot inject two different event plugins " + - ("using the same name, `" + pluginName + "`.") + "EventPluginRegistry: More than one plugin attempted to publish the same " + + ("event name, `" + eventName + "`.") ); } - namesToPlugins[pluginName] = pluginModule; - isOrderingDirty = true; - } - } - - if (isOrderingDirty) { - recomputePluginOrdering(); - } -} + eventNameDispatchConfigs[eventName] = dispatchConfig; + var phasedRegistrationNames = dispatchConfig.phasedRegistrationNames; -/** - * Get a list of listeners for a specific event, in-order. - * For React Native we treat the props-based function handlers - * as the first-class citizens, and they are always executed first - * for both capture and bubbling phase. - * - * We need "phase" propagated to this point to support the HostComponent - * EventEmitter API, which does not mutate the name of the handler based - * on phase (whereas prop handlers are registered as `onMyEvent` and `onMyEvent_Capture`). - * - * Native system events emitted into React Native - * will be emitted both to the prop handler function and to imperative event - * listeners. - * - * This will either return null, a single Function without an array, or - * an array of 2+ items. - */ + if (phasedRegistrationNames) { + for (var phaseName in phasedRegistrationNames) { + if (phasedRegistrationNames.hasOwnProperty(phaseName)) { + var phasedRegistrationName = phasedRegistrationNames[phaseName]; + publishRegistrationName( + phasedRegistrationName, + pluginModule, + eventName + ); + } + } -function getListeners( - inst, - registrationName, - phase, - dispatchToImperativeListeners -) { - var stateNode = inst.stateNode; - - if (stateNode === null) { - return null; - } // If null: Work in progress (ex: onload events in incremental mode). - - var props = getFiberCurrentPropsFromNode(stateNode); - - if (props === null) { - // Work in progress. - return null; - } - - var listener = props[registrationName]; - - if (listener && typeof listener !== "function") { - throw new Error( - "Expected `" + - registrationName + - "` listener to be a function, instead got a value of `" + - typeof listener + - "` type." - ); - } // If there are no imperative listeners, early exit. - - if ( - !( - dispatchToImperativeListeners && - stateNode.canonical && - stateNode.canonical._eventListeners - ) - ) { - return listener; - } // Below this is the de-optimized path. - // If you are using _eventListeners, we do not (yet) - // expect this to be as performant as the props-only path. - // If/when this becomes a bottleneck, it can be refactored - // to avoid unnecessary closures and array allocations. - // - // Previously, there was only one possible listener for an event: - // the onEventName property in props. - // Now, it is also possible to have N listeners - // for a specific event on a node. Thus, we accumulate all of the listeners, - // including the props listener, and return a function that calls them all in - // order, starting with the handler prop and then the listeners in order. - // We return either a non-empty array or null. - - var listeners = []; - - if (listener) { - listeners.push(listener); - } // TODO: for now, all of these events get an `rn:` prefix to enforce - // that the user knows they're only getting non-W3C-compliant events - // through this imperative event API. - // Events might not necessarily be noncompliant, but we currently have - // no verification that /any/ events are compliant. - // Thus, we prefix to ensure no collision with W3C event names. - - var requestedPhaseIsCapture = phase === "captured"; - var mangledImperativeRegistrationName = requestedPhaseIsCapture - ? "rn:" + registrationName.replace(/Capture$/, "") - : "rn:" + registrationName; // Get imperative event listeners for this event - - if ( - stateNode.canonical._eventListeners[mangledImperativeRegistrationName] && - stateNode.canonical._eventListeners[mangledImperativeRegistrationName] - .length > 0 - ) { - var eventListeners = - stateNode.canonical._eventListeners[mangledImperativeRegistrationName]; - eventListeners.forEach(function(listenerObj) { - // Make sure phase of listener matches requested phase - var isCaptureEvent = - listenerObj.options.capture != null && listenerObj.options.capture; - - if (isCaptureEvent !== requestedPhaseIsCapture) { - return; - } // For now (this is an area of future optimization) we must wrap - // all imperative event listeners in a function to unwrap the SyntheticEvent - // and pass them an Event. - // When this API is more stable and used more frequently, we can revisit. - - var listenerFnWrapper = function(syntheticEvent) { - var eventInst = new ReactNativePrivateInterface.CustomEvent( - mangledImperativeRegistrationName, - { - detail: syntheticEvent.nativeEvent - } + return true; + } else if (dispatchConfig.registrationName) { + publishRegistrationName( + dispatchConfig.registrationName, + pluginModule, + eventName ); - eventInst.isTrusted = true; // setSyntheticEvent is present on the React Native Event shim. - // It is used to forward method calls on Event to the underlying SyntheticEvent. - // $FlowFixMe + return true; + } - eventInst.setSyntheticEvent(syntheticEvent); + return false; + } + /** + * Publishes a registration name that is used to identify dispatched events. + * + * @param {string} registrationName Registration name to add. + * @param {object} PluginModule Plugin publishing the event. + * @private + */ - for ( - var _len = arguments.length, - args = new Array(_len > 1 ? _len - 1 : 0), - _key = 1; - _key < _len; - _key++ - ) { - args[_key - 1] = arguments[_key]; - } - - listenerObj.listener.apply(listenerObj, [eventInst].concat(args)); - }; // Only call once? - // If so, we ensure that it's only called once by setting a flag - // and by removing it from eventListeners once it is called (but only - // when it's actually been executed). - - if (listenerObj.options.once) { - listeners.push(function() { - // Remove from the event listener once it's been called - stateNode.canonical.removeEventListener_unstable( - mangledImperativeRegistrationName, - listenerObj.listener, - listenerObj.capture - ); // Guard against function being called more than once in - // case there are somehow multiple in-flight references to - // it being processed - - if (!listenerObj.invalidated) { - listenerObj.invalidated = true; - listenerObj.listener.apply(listenerObj, arguments); - } - }); - } else { - listeners.push(listenerFnWrapper); + function publishRegistrationName(registrationName, pluginModule, eventName) { + if (registrationNameModules[registrationName]) { + throw new Error( + "EventPluginRegistry: More than one plugin attempted to publish the same " + + ("registration name, `" + registrationName + "`.") + ); } - }); - } - if (listeners.length === 0) { - return null; - } + registrationNameModules[registrationName] = pluginModule; + registrationNameDependencies[registrationName] = + pluginModule.eventTypes[eventName].dependencies; - if (listeners.length === 1) { - return listeners[0]; - } + { + var lowerCasedName = registrationName.toLowerCase(); + } + } + /** + * Registers plugins so that they can extract and dispatch events. + */ - return listeners; -} + /** + * Ordered list of injected plugins. + */ -var customBubblingEventTypes = - ReactNativePrivateInterface.ReactNativeViewConfigRegistry - .customBubblingEventTypes, - customDirectEventTypes = - ReactNativePrivateInterface.ReactNativeViewConfigRegistry - .customDirectEventTypes; // Start of inline: the below functions were inlined from -// EventPropagator.js, as they deviated from ReactDOM's newer -// implementations. - -function listenersAtPhase(inst, event, propagationPhase) { - var registrationName = - event.dispatchConfig.phasedRegistrationNames[propagationPhase]; - return getListeners(inst, registrationName, propagationPhase, true); -} + var plugins = []; + /** + * Mapping from event name to dispatch config + */ + + var eventNameDispatchConfigs = {}; + /** + * Mapping from registration name to plugin module + */ + + var registrationNameModules = {}; + /** + * Mapping from registration name to event name + */ + + var registrationNameDependencies = {}; + + /** + * Injects an ordering of plugins (by plugin name). This allows the ordering + * to be decoupled from injection of the actual plugins so that ordering is + * always deterministic regardless of packaging, on-the-fly injection, etc. + * + * @param {array} InjectedEventPluginOrder + * @internal + */ + + function injectEventPluginOrder(injectedEventPluginOrder) { + if (eventPluginOrder) { + throw new Error( + "EventPluginRegistry: Cannot inject event plugin ordering more than " + + "once. You are likely trying to load more than one copy of React." + ); + } // Clone the ordering so it cannot be dynamically mutated. + + eventPluginOrder = Array.prototype.slice.call(injectedEventPluginOrder); + recomputePluginOrdering(); + } + /** + * Injects plugins to be used by plugin event system. The plugin names must be + * in the ordering injected by `injectEventPluginOrder`. + * + * Plugins can be injected as part of page initialization or on-the-fly. + * + * @param {object} injectedNamesToPlugins Map from names to plugin modules. + * @internal + */ + + function injectEventPluginsByName(injectedNamesToPlugins) { + var isOrderingDirty = false; -function accumulateListenersAndInstances(inst, event, listeners) { - var listenersLength = listeners - ? isArray(listeners) - ? listeners.length - : 1 - : 0; + for (var pluginName in injectedNamesToPlugins) { + if (!injectedNamesToPlugins.hasOwnProperty(pluginName)) { + continue; + } - if (listenersLength > 0) { - event._dispatchListeners = accumulateInto( - event._dispatchListeners, - listeners - ); // Avoid allocating additional arrays here + var pluginModule = injectedNamesToPlugins[pluginName]; - if (event._dispatchInstances == null && listenersLength === 1) { - event._dispatchInstances = inst; - } else { - event._dispatchInstances = event._dispatchInstances || []; + if ( + !namesToPlugins.hasOwnProperty(pluginName) || + namesToPlugins[pluginName] !== pluginModule + ) { + if (namesToPlugins[pluginName]) { + throw new Error( + "EventPluginRegistry: Cannot inject two different event plugins " + + ("using the same name, `" + pluginName + "`.") + ); + } - if (!isArray(event._dispatchInstances)) { - event._dispatchInstances = [event._dispatchInstances]; + namesToPlugins[pluginName] = pluginModule; + isOrderingDirty = true; + } } - for (var i = 0; i < listenersLength; i++) { - event._dispatchInstances.push(inst); + if (isOrderingDirty) { + recomputePluginOrdering(); } } - } -} -function accumulateDirectionalDispatches$1(inst, phase, event) { - { - if (!inst) { - error("Dispatching inst must not be null"); - } - } + /** + * Get a list of listeners for a specific event, in-order. + * For React Native we treat the props-based function handlers + * as the first-class citizens, and they are always executed first + * for both capture and bubbling phase. + * + * We need "phase" propagated to this point to support the HostComponent + * EventEmitter API, which does not mutate the name of the handler based + * on phase (whereas prop handlers are registered as `onMyEvent` and `onMyEvent_Capture`). + * + * Native system events emitted into React Native + * will be emitted both to the prop handler function and to imperative event + * listeners. + * + * This will either return null, a single Function without an array, or + * an array of 2+ items. + */ - var listeners = listenersAtPhase(inst, event, phase); - accumulateListenersAndInstances(inst, event, listeners); -} + function getListeners( + inst, + registrationName, + phase, + dispatchToImperativeListeners + ) { + var stateNode = inst.stateNode; -function getParent$1(inst) { - do { - inst = inst.return; // TODO: If this is a HostRoot we might want to bail out. - // That is depending on if we want nested subtrees (layers) to bubble - // events to their parent. We could also go through parentNode on the - // host node but that wouldn't work for React Native and doesn't let us - // do the portal feature. - } while (inst && inst.tag !== HostComponent); + if (stateNode === null) { + return null; + } // If null: Work in progress (ex: onload events in incremental mode). - if (inst) { - return inst; - } + var props = getFiberCurrentPropsFromNode(stateNode); - return null; -} -/** - * Simulates the traversal of a two-phase, capture/bubble event dispatch. - */ + if (props === null) { + // Work in progress. + return null; + } + + var listener = props[registrationName]; + + if (listener && typeof listener !== "function") { + throw new Error( + "Expected `" + + registrationName + + "` listener to be a function, instead got a value of `" + + typeof listener + + "` type." + ); + } // If there are no imperative listeners, early exit. + + if ( + !( + dispatchToImperativeListeners && + stateNode.canonical && + stateNode.canonical._eventListeners + ) + ) { + return listener; + } // Below this is the de-optimized path. + // If you are using _eventListeners, we do not (yet) + // expect this to be as performant as the props-only path. + // If/when this becomes a bottleneck, it can be refactored + // to avoid unnecessary closures and array allocations. + // + // Previously, there was only one possible listener for an event: + // the onEventName property in props. + // Now, it is also possible to have N listeners + // for a specific event on a node. Thus, we accumulate all of the listeners, + // including the props listener, and return a function that calls them all in + // order, starting with the handler prop and then the listeners in order. + // We return either a non-empty array or null. + + var listeners = []; + + if (listener) { + listeners.push(listener); + } // TODO: for now, all of these events get an `rn:` prefix to enforce + // that the user knows they're only getting non-W3C-compliant events + // through this imperative event API. + // Events might not necessarily be noncompliant, but we currently have + // no verification that /any/ events are compliant. + // Thus, we prefix to ensure no collision with W3C event names. + + var requestedPhaseIsCapture = phase === "captured"; + var mangledImperativeRegistrationName = requestedPhaseIsCapture + ? "rn:" + registrationName.replace(/Capture$/, "") + : "rn:" + registrationName; // Get imperative event listeners for this event -function traverseTwoPhase$1(inst, fn, arg, skipBubbling) { - var path = []; + if ( + stateNode.canonical._eventListeners[mangledImperativeRegistrationName] && + stateNode.canonical._eventListeners[mangledImperativeRegistrationName] + .length > 0 + ) { + var eventListeners = + stateNode.canonical._eventListeners[mangledImperativeRegistrationName]; + eventListeners.forEach(function (listenerObj) { + // Make sure phase of listener matches requested phase + var isCaptureEvent = + listenerObj.options.capture != null && listenerObj.options.capture; + + if (isCaptureEvent !== requestedPhaseIsCapture) { + return; + } // For now (this is an area of future optimization) we must wrap + // all imperative event listeners in a function to unwrap the SyntheticEvent + // and pass them an Event. + // When this API is more stable and used more frequently, we can revisit. + + var listenerFnWrapper = function (syntheticEvent) { + var eventInst = new ReactNativePrivateInterface.CustomEvent( + mangledImperativeRegistrationName, + { + detail: syntheticEvent.nativeEvent + } + ); + eventInst.isTrusted = true; // setSyntheticEvent is present on the React Native Event shim. + // It is used to forward method calls on Event to the underlying SyntheticEvent. + // $FlowFixMe + + eventInst.setSyntheticEvent(syntheticEvent); + + for ( + var _len = arguments.length, + args = new Array(_len > 1 ? _len - 1 : 0), + _key = 1; + _key < _len; + _key++ + ) { + args[_key - 1] = arguments[_key]; + } - while (inst) { - path.push(inst); - inst = getParent$1(inst); - } + listenerObj.listener.apply(listenerObj, [eventInst].concat(args)); + }; // Only call once? + // If so, we ensure that it's only called once by setting a flag + // and by removing it from eventListeners once it is called (but only + // when it's actually been executed). + + if (listenerObj.options.once) { + listeners.push(function () { + // Remove from the event listener once it's been called + stateNode.canonical.removeEventListener_unstable( + mangledImperativeRegistrationName, + listenerObj.listener, + listenerObj.capture + ); // Guard against function being called more than once in + // case there are somehow multiple in-flight references to + // it being processed + + if (!listenerObj.invalidated) { + listenerObj.invalidated = true; + listenerObj.listener.apply(listenerObj, arguments); + } + }); + } else { + listeners.push(listenerFnWrapper); + } + }); + } - var i; + if (listeners.length === 0) { + return null; + } - for (i = path.length; i-- > 0; ) { - fn(path[i], "captured", arg); - } + if (listeners.length === 1) { + return listeners[0]; + } - if (skipBubbling) { - // Dispatch on target only - fn(path[0], "bubbled", arg); - } else { - for (i = 0; i < path.length; i++) { - fn(path[i], "bubbled", arg); + return listeners; } - } -} -function accumulateTwoPhaseDispatchesSingle$1(event) { - if (event && event.dispatchConfig.phasedRegistrationNames) { - traverseTwoPhase$1( - event._targetInst, - accumulateDirectionalDispatches$1, - event, - false - ); - } -} + var customBubblingEventTypes = + ReactNativePrivateInterface.ReactNativeViewConfigRegistry + .customBubblingEventTypes, + customDirectEventTypes = + ReactNativePrivateInterface.ReactNativeViewConfigRegistry + .customDirectEventTypes; // Start of inline: the below functions were inlined from + // EventPropagator.js, as they deviated from ReactDOM's newer + // implementations. -function accumulateTwoPhaseDispatches$1(events) { - forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle$1); -} + function listenersAtPhase(inst, event, propagationPhase) { + var registrationName = + event.dispatchConfig.phasedRegistrationNames[propagationPhase]; + return getListeners(inst, registrationName, propagationPhase, true); + } -function accumulateCapturePhaseDispatches(event) { - if (event && event.dispatchConfig.phasedRegistrationNames) { - traverseTwoPhase$1( - event._targetInst, - accumulateDirectionalDispatches$1, - event, - true - ); - } -} -/** - * Accumulates without regard to direction, does not look for phased - * registration names. Same as `accumulateDirectDispatchesSingle` but without - * requiring that the `dispatchMarker` be the same as the dispatched ID. - */ + function accumulateListenersAndInstances(inst, event, listeners) { + var listenersLength = listeners + ? isArray(listeners) + ? listeners.length + : 1 + : 0; -function accumulateDispatches$1(inst, ignoredDirection, event) { - if (inst && event && event.dispatchConfig.registrationName) { - var registrationName = event.dispatchConfig.registrationName; - var listeners = getListeners(inst, registrationName, "bubbled", false); - accumulateListenersAndInstances(inst, event, listeners); - } -} -/** - * Accumulates dispatches on an `SyntheticEvent`, but only for the - * `dispatchMarker`. - * @param {SyntheticEvent} event - */ + if (listenersLength > 0) { + event._dispatchListeners = accumulateInto( + event._dispatchListeners, + listeners + ); // Avoid allocating additional arrays here -function accumulateDirectDispatchesSingle$1(event) { - if (event && event.dispatchConfig.registrationName) { - accumulateDispatches$1(event._targetInst, null, event); - } -} + if (event._dispatchInstances == null && listenersLength === 1) { + event._dispatchInstances = inst; + } else { + event._dispatchInstances = event._dispatchInstances || []; -function accumulateDirectDispatches$1(events) { - forEachAccumulated(events, accumulateDirectDispatchesSingle$1); -} // End of inline - -var ReactNativeBridgeEventPlugin = { - eventTypes: {}, - extractEvents: function( - topLevelType, - targetInst, - nativeEvent, - nativeEventTarget - ) { - if (targetInst == null) { - // Probably a node belonging to another renderer's tree. - return null; + if (!isArray(event._dispatchInstances)) { + event._dispatchInstances = [event._dispatchInstances]; + } + + for (var i = 0; i < listenersLength; i++) { + event._dispatchInstances.push(inst); + } + } + } } - var bubbleDispatchConfig = customBubblingEventTypes[topLevelType]; - var directDispatchConfig = customDirectEventTypes[topLevelType]; + function accumulateDirectionalDispatches$1(inst, phase, event) { + { + if (!inst) { + error("Dispatching inst must not be null"); + } + } - if (!bubbleDispatchConfig && !directDispatchConfig) { - throw new Error( // $FlowFixMe - Flow doesn't like this string coercion because DOMTopLevelEventType is opaque - 'Unsupported top level event type "' + topLevelType + '" dispatched' - ); + var listeners = listenersAtPhase(inst, event, phase); + accumulateListenersAndInstances(inst, event, listeners); } - var event = SyntheticEvent.getPooled( - bubbleDispatchConfig || directDispatchConfig, - targetInst, - nativeEvent, - nativeEventTarget - ); - - if (bubbleDispatchConfig) { - var skipBubbling = - event != null && - event.dispatchConfig.phasedRegistrationNames != null && - event.dispatchConfig.phasedRegistrationNames.skipBubbling; + function getParent$1(inst) { + do { + inst = inst.return; // TODO: If this is a HostRoot we might want to bail out. + // That is depending on if we want nested subtrees (layers) to bubble + // events to their parent. We could also go through parentNode on the + // host node but that wouldn't work for React Native and doesn't let us + // do the portal feature. + } while (inst && inst.tag !== HostComponent); - if (skipBubbling) { - accumulateCapturePhaseDispatches(event); - } else { - accumulateTwoPhaseDispatches$1(event); + if (inst) { + return inst; } - } else if (directDispatchConfig) { - accumulateDirectDispatches$1(event); - } else { + return null; } + /** + * Simulates the traversal of a two-phase, capture/bubble event dispatch. + */ - return event; - } -}; + function traverseTwoPhase$1(inst, fn, arg, skipBubbling) { + var path = []; -var ReactNativeEventPluginOrder = [ - "ResponderEventPlugin", - "ReactNativeBridgeEventPlugin" -]; + while (inst) { + path.push(inst); + inst = getParent$1(inst); + } -/** - * Make sure essential globals are available and are patched correctly. Please don't remove this - * line. Bundles created by react-packager `require` it before executing any application code. This - * ensures it exists in the dependency graph and can be `require`d. - * TODO: require this in packager, not in React #10932517 - */ -/** - * Inject module for resolving DOM hierarchy and plugin ordering. - */ + var i; -injectEventPluginOrder(ReactNativeEventPluginOrder); -/** - * Some important event plugins included by default (without having to require - * them). - */ + for (i = path.length; i-- > 0;) { + fn(path[i], "captured", arg); + } -injectEventPluginsByName({ - ResponderEventPlugin: ResponderEventPlugin, - ReactNativeBridgeEventPlugin: ReactNativeBridgeEventPlugin -}); + if (skipBubbling) { + // Dispatch on target only + fn(path[0], "bubbled", arg); + } else { + for (i = 0; i < path.length; i++) { + fn(path[i], "bubbled", arg); + } + } + } -var instanceCache = new Map(); -var instanceProps = new Map(); -function precacheFiberNode(hostInst, tag) { - instanceCache.set(tag, hostInst); -} -function uncacheFiberNode(tag) { - instanceCache.delete(tag); - instanceProps.delete(tag); -} + function accumulateTwoPhaseDispatchesSingle$1(event) { + if (event && event.dispatchConfig.phasedRegistrationNames) { + traverseTwoPhase$1( + event._targetInst, + accumulateDirectionalDispatches$1, + event, + false + ); + } + } -function getInstanceFromTag(tag) { - return instanceCache.get(tag) || null; -} + function accumulateTwoPhaseDispatches$1(events) { + forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle$1); + } -function getTagFromInstance(inst) { - var nativeInstance = inst.stateNode; - var tag = nativeInstance._nativeTag; + function accumulateCapturePhaseDispatches(event) { + if (event && event.dispatchConfig.phasedRegistrationNames) { + traverseTwoPhase$1( + event._targetInst, + accumulateDirectionalDispatches$1, + event, + true + ); + } + } + /** + * Accumulates without regard to direction, does not look for phased + * registration names. Same as `accumulateDirectDispatchesSingle` but without + * requiring that the `dispatchMarker` be the same as the dispatched ID. + */ - if (tag === undefined) { - nativeInstance = nativeInstance.canonical; - tag = nativeInstance._nativeTag; - } + function accumulateDispatches$1(inst, ignoredDirection, event) { + if (inst && event && event.dispatchConfig.registrationName) { + var registrationName = event.dispatchConfig.registrationName; + var listeners = getListeners(inst, registrationName, "bubbled", false); + accumulateListenersAndInstances(inst, event, listeners); + } + } + /** + * Accumulates dispatches on an `SyntheticEvent`, but only for the + * `dispatchMarker`. + * @param {SyntheticEvent} event + */ - if (!tag) { - throw new Error("All native instances should have a tag."); - } + function accumulateDirectDispatchesSingle$1(event) { + if (event && event.dispatchConfig.registrationName) { + accumulateDispatches$1(event._targetInst, null, event); + } + } - return nativeInstance; -} -function getFiberCurrentPropsFromNode$1(stateNode) { - return instanceProps.get(stateNode._nativeTag) || null; -} -function updateFiberProps(tag, props) { - instanceProps.set(tag, props); -} + function accumulateDirectDispatches$1(events) { + forEachAccumulated(events, accumulateDirectDispatchesSingle$1); + } // End of inline -// Used as a way to call batchedUpdates when we don't have a reference to -// the renderer. Such as when we're dispatching events or if third party -// libraries need to call batchedUpdates. Eventually, this API will go away when -// everything is batched by default. We'll then have a similar API to opt-out of -// scheduled work and instead do synchronous work. -// Defaults -var batchedUpdatesImpl = function(fn, bookkeeping) { - return fn(bookkeeping); -}; - -var isInsideEventHandler = false; -function batchedUpdates(fn, bookkeeping) { - if (isInsideEventHandler) { - // If we are currently inside another batch, we need to wait until it - // fully completes before restoring state. - return fn(bookkeeping); - } - - isInsideEventHandler = true; - - try { - return batchedUpdatesImpl(fn, bookkeeping); - } finally { - isInsideEventHandler = false; - } -} -function setBatchingImplementation(_batchedUpdatesImpl, _discreteUpdatesImpl) { - batchedUpdatesImpl = _batchedUpdatesImpl; -} + var ReactNativeBridgeEventPlugin = { + eventTypes: {}, + extractEvents: function ( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget + ) { + if (targetInst == null) { + // Probably a node belonging to another renderer's tree. + return null; + } -/** - * Internal queue of events that have accumulated their dispatches and are - * waiting to have their dispatches executed. - */ + var bubbleDispatchConfig = customBubblingEventTypes[topLevelType]; + var directDispatchConfig = customDirectEventTypes[topLevelType]; -var eventQueue = null; -/** - * Dispatches an event and releases it back into the pool, unless persistent. - * - * @param {?object} event Synthetic event to be dispatched. - * @private - */ + if (!bubbleDispatchConfig && !directDispatchConfig) { + throw new Error( // $FlowFixMe - Flow doesn't like this string coercion because DOMTopLevelEventType is opaque + 'Unsupported top level event type "' + topLevelType + '" dispatched' + ); + } -var executeDispatchesAndRelease = function(event) { - if (event) { - executeDispatchesInOrder(event); + var event = SyntheticEvent.getPooled( + bubbleDispatchConfig || directDispatchConfig, + targetInst, + nativeEvent, + nativeEventTarget + ); - if (!event.isPersistent()) { - event.constructor.release(event); - } - } -}; + if (bubbleDispatchConfig) { + var skipBubbling = + event != null && + event.dispatchConfig.phasedRegistrationNames != null && + event.dispatchConfig.phasedRegistrationNames.skipBubbling; -var executeDispatchesAndReleaseTopLevel = function(e) { - return executeDispatchesAndRelease(e); -}; + if (skipBubbling) { + accumulateCapturePhaseDispatches(event); + } else { + accumulateTwoPhaseDispatches$1(event); + } + } else if (directDispatchConfig) { + accumulateDirectDispatches$1(event); + } else { + return null; + } -function runEventsInBatch(events) { - if (events !== null) { - eventQueue = accumulateInto(eventQueue, events); - } // Set `eventQueue` to null before processing it so that we can tell if more - // events get enqueued while processing. + return event; + } + }; - var processingEventQueue = eventQueue; - eventQueue = null; + var ReactNativeEventPluginOrder = [ + "ResponderEventPlugin", + "ReactNativeBridgeEventPlugin" + ]; - if (!processingEventQueue) { - return; - } + /** + * Make sure essential globals are available and are patched correctly. Please don't remove this + * line. Bundles created by react-packager `require` it before executing any application code. This + * ensures it exists in the dependency graph and can be `require`d. + * TODO: require this in packager, not in React #10932517 + */ + /** + * Inject module for resolving DOM hierarchy and plugin ordering. + */ - forEachAccumulated(processingEventQueue, executeDispatchesAndReleaseTopLevel); + injectEventPluginOrder(ReactNativeEventPluginOrder); + /** + * Some important event plugins included by default (without having to require + * them). + */ - if (eventQueue) { - throw new Error( - "processEventQueue(): Additional events were enqueued while processing " + - "an event queue. Support for this has not yet been implemented." - ); - } // This would be a good time to rethrow if any of the event handlers threw. + injectEventPluginsByName({ + ResponderEventPlugin: ResponderEventPlugin, + ReactNativeBridgeEventPlugin: ReactNativeBridgeEventPlugin + }); - rethrowCaughtError(); -} + var instanceCache = new Map(); + var instanceProps = new Map(); + function precacheFiberNode(hostInst, tag) { + instanceCache.set(tag, hostInst); + } + function uncacheFiberNode(tag) { + instanceCache.delete(tag); + instanceProps.delete(tag); + } -/** - * Version of `ReactBrowserEventEmitter` that works on the receiving side of a - * serialized worker boundary. - */ -// Shared default empty native event - conserve memory. + function getInstanceFromTag(tag) { + return instanceCache.get(tag) || null; + } -var EMPTY_NATIVE_EVENT = {}; -/** - * Selects a subsequence of `Touch`es, without destroying `touches`. - * - * @param {Array} touches Deserialized touch objects. - * @param {Array} indices Indices by which to pull subsequence. - * @return {Array} Subsequence of touch objects. - */ + function getTagFromInstance(inst) { + var nativeInstance = inst.stateNode; + var tag = nativeInstance._nativeTag; -var touchSubsequence = function(touches, indices) { - var ret = []; + if (tag === undefined) { + nativeInstance = nativeInstance.canonical; + tag = nativeInstance._nativeTag; + } - for (var i = 0; i < indices.length; i++) { - ret.push(touches[indices[i]]); - } + if (!tag) { + throw new Error("All native instances should have a tag."); + } - return ret; -}; -/** - * TODO: Pool all of this. - * - * Destroys `touches` by removing touch objects at indices `indices`. This is - * to maintain compatibility with W3C touch "end" events, where the active - * touches don't include the set that has just been "ended". - * - * @param {Array} touches Deserialized touch objects. - * @param {Array} indices Indices to remove from `touches`. - * @return {Array} Subsequence of removed touch objects. - */ + return nativeInstance; + } + function getFiberCurrentPropsFromNode$1(stateNode) { + return instanceProps.get(stateNode._nativeTag) || null; + } + function updateFiberProps(tag, props) { + instanceProps.set(tag, props); + } -var removeTouchesAtIndices = function(touches, indices) { - var rippedOut = []; // use an unsafe downcast to alias to nullable elements, - // so we can delete and then compact. + // Used as a way to call batchedUpdates when we don't have a reference to + // the renderer. Such as when we're dispatching events or if third party + // libraries need to call batchedUpdates. Eventually, this API will go away when + // everything is batched by default. We'll then have a similar API to opt-out of + // scheduled work and instead do synchronous work. + // Defaults + var batchedUpdatesImpl = function (fn, bookkeeping) { + return fn(bookkeeping); + }; - var temp = touches; + var isInsideEventHandler = false; + function batchedUpdates(fn, bookkeeping) { + if (isInsideEventHandler) { + // If we are currently inside another batch, we need to wait until it + // fully completes before restoring state. + return fn(bookkeeping); + } - for (var i = 0; i < indices.length; i++) { - var index = indices[i]; - rippedOut.push(touches[index]); - temp[index] = null; - } + isInsideEventHandler = true; - var fillAt = 0; + try { + return batchedUpdatesImpl(fn, bookkeeping); + } finally { + isInsideEventHandler = false; + } + } + function setBatchingImplementation(_batchedUpdatesImpl, _discreteUpdatesImpl) { + batchedUpdatesImpl = _batchedUpdatesImpl; + } - for (var j = 0; j < temp.length; j++) { - var cur = temp[j]; + /** + * Internal queue of events that have accumulated their dispatches and are + * waiting to have their dispatches executed. + */ - if (cur !== null) { - temp[fillAt++] = cur; - } - } + var eventQueue = null; + /** + * Dispatches an event and releases it back into the pool, unless persistent. + * + * @param {?object} event Synthetic event to be dispatched. + * @private + */ - temp.length = fillAt; - return rippedOut; -}; -/** - * Internal version of `receiveEvent` in terms of normalized (non-tag) - * `rootNodeID`. - * - * @see receiveEvent. - * - * @param {rootNodeID} rootNodeID React root node ID that event occurred on. - * @param {TopLevelType} topLevelType Top level type of event. - * @param {?object} nativeEventParam Object passed from native. - */ + var executeDispatchesAndRelease = function (event) { + if (event) { + executeDispatchesInOrder(event); -function _receiveRootNodeIDEvent(rootNodeID, topLevelType, nativeEventParam) { - var nativeEvent = nativeEventParam || EMPTY_NATIVE_EVENT; - var inst = getInstanceFromTag(rootNodeID); - var target = null; + if (!event.isPersistent()) { + event.constructor.release(event); + } + } + }; - if (inst != null) { - target = inst.stateNode; - } + var executeDispatchesAndReleaseTopLevel = function (e) { + return executeDispatchesAndRelease(e); + }; - batchedUpdates(function() { - runExtractedPluginEventsInBatch(topLevelType, inst, nativeEvent, target); - }); // React Native doesn't use ReactControlledComponent but if it did, here's - // where it would do it. -} -/** - * Allows registered plugins an opportunity to extract events from top-level - * native browser events. - * - * @return {*} An accumulation of synthetic events. - * @internal - */ + function runEventsInBatch(events) { + if (events !== null) { + eventQueue = accumulateInto(eventQueue, events); + } // Set `eventQueue` to null before processing it so that we can tell if more + // events get enqueued while processing. -function extractPluginEvents( - topLevelType, - targetInst, - nativeEvent, - nativeEventTarget -) { - var events = null; - var legacyPlugins = plugins; - - for (var i = 0; i < legacyPlugins.length; i++) { - // Not every plugin in the ordering may be loaded at runtime. - var possiblePlugin = legacyPlugins[i]; - - if (possiblePlugin) { - var extractedEvents = possiblePlugin.extractEvents( - topLevelType, - targetInst, - nativeEvent, - nativeEventTarget - ); + var processingEventQueue = eventQueue; + eventQueue = null; - if (extractedEvents) { - events = accumulateInto(events, extractedEvents); + if (!processingEventQueue) { + return; } - } - } - return events; -} + forEachAccumulated(processingEventQueue, executeDispatchesAndReleaseTopLevel); -function runExtractedPluginEventsInBatch( - topLevelType, - targetInst, - nativeEvent, - nativeEventTarget -) { - var events = extractPluginEvents( - topLevelType, - targetInst, - nativeEvent, - nativeEventTarget - ); - runEventsInBatch(events); -} -/** - * Publicly exposed method on module for native objc to invoke when a top - * level event is extracted. - * @param {rootNodeID} rootNodeID React root node ID that event occurred on. - * @param {TopLevelType} topLevelType Top level type of event. - * @param {object} nativeEventParam Object passed from native. - */ - -function receiveEvent(rootNodeID, topLevelType, nativeEventParam) { - _receiveRootNodeIDEvent(rootNodeID, topLevelType, nativeEventParam); -} -/** - * Simple multi-wrapper around `receiveEvent` that is intended to receive an - * efficient representation of `Touch` objects, and other information that - * can be used to construct W3C compliant `Event` and `Touch` lists. - * - * This may create dispatch behavior that differs than web touch handling. We - * loop through each of the changed touches and receive it as a single event. - * So two `touchStart`/`touchMove`s that occur simultaneously are received as - * two separate touch event dispatches - when they arguably should be one. - * - * This implementation reuses the `Touch` objects themselves as the `Event`s - * since we dispatch an event for each touch (though that might not be spec - * compliant). The main purpose of reusing them is to save allocations. - * - * TODO: Dispatch multiple changed touches in one event. The bubble path - * could be the first common ancestor of all the `changedTouches`. - * - * One difference between this behavior and W3C spec: cancelled touches will - * not appear in `.touches`, or in any future `.touches`, though they may - * still be "actively touching the surface". - * - * Web desktop polyfills only need to construct a fake touch event with - * identifier 0, also abandoning traditional click handlers. - */ - -function receiveTouches(eventTopLevelType, touches, changedIndices) { - var changedTouches = - eventTopLevelType === "topTouchEnd" || - eventTopLevelType === "topTouchCancel" - ? removeTouchesAtIndices(touches, changedIndices) - : touchSubsequence(touches, changedIndices); - - for (var jj = 0; jj < changedTouches.length; jj++) { - var touch = changedTouches[jj]; // Touch objects can fulfill the role of `DOM` `Event` objects if we set - // the `changedTouches`/`touches`. This saves allocations. - - touch.changedTouches = changedTouches; - touch.touches = touches; - var nativeEvent = touch; - var rootNodeID = null; - var target = nativeEvent.target; - - if (target !== null && target !== undefined) { - if (target < 1) { - { - error("A view is reporting that a touch occurred on tag zero."); - } - } else { - rootNodeID = target; - } - } // $FlowFixMe Shouldn't we *not* call it if rootNodeID is null? - - _receiveRootNodeIDEvent(rootNodeID, eventTopLevelType, nativeEvent); - } -} - -// Module provided by RN: -var ReactNativeGlobalResponderHandler = { - onChange: function(from, to, blockNativeResponder) { - if (to !== null) { - var tag = to.stateNode._nativeTag; - ReactNativePrivateInterface.UIManager.setJSResponder( - tag, - blockNativeResponder - ); - } else { - ReactNativePrivateInterface.UIManager.clearJSResponder(); - } - } -}; - -/** - * Register the event emitter with the native bridge - */ - -ReactNativePrivateInterface.RCTEventEmitter.register({ - receiveEvent: receiveEvent, - receiveTouches: receiveTouches -}); -setComponentTree( - getFiberCurrentPropsFromNode$1, - getInstanceFromTag, - getTagFromInstance -); -ResponderEventPlugin.injection.injectGlobalResponderHandler( - ReactNativeGlobalResponderHandler -); - -/** - * `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 enableSchedulingProfiler = false; -var enableProfilerTimer = true; -var enableProfilerCommitHooks = true; -var warnAboutStringRefs = false; -var enableSuspenseAvoidThisFallback = false; -var enableNewReconciler = false; -var enableLazyContextPropagation = false; -var enableLegacyHidden = false; - -// 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; -} + if (eventQueue) { + throw new Error( + "processEventQueue(): Additional events were enqueued while processing " + + "an event queue. Support for this has not yet been implemented." + ); + } // This would be a good time to rethrow if any of the event handlers threw. -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." - ); + rethrowCaughtError(); } - } - - if (typeof type === "function") { - return type.displayName || type.name || null; - } - if (typeof type === "string") { - return type; - } - - switch (type) { - case REACT_FRAGMENT_TYPE: - return "Fragment"; + /** + * Version of `ReactBrowserEventEmitter` that works on the receiving side of a + * serialized worker boundary. + */ + // Shared default empty native event - conserve memory. - case REACT_PORTAL_TYPE: - return "Portal"; + var EMPTY_NATIVE_EVENT = {}; + /** + * Selects a subsequence of `Touch`es, without destroying `touches`. + * + * @param {Array} touches Deserialized touch objects. + * @param {Array} indices Indices by which to pull subsequence. + * @return {Array} Subsequence of touch objects. + */ - case REACT_PROFILER_TYPE: - return "Profiler"; + var touchSubsequence = function (touches, indices) { + var ret = []; - case REACT_STRICT_MODE_TYPE: - return "StrictMode"; + for (var i = 0; i < indices.length; i++) { + ret.push(touches[indices[i]]); + } - case REACT_SUSPENSE_TYPE: - return "Suspense"; + return ret; + }; + /** + * TODO: Pool all of this. + * + * Destroys `touches` by removing touch objects at indices `indices`. This is + * to maintain compatibility with W3C touch "end" events, where the active + * touches don't include the set that has just been "ended". + * + * @param {Array} touches Deserialized touch objects. + * @param {Array} indices Indices to remove from `touches`. + * @return {Array} Subsequence of removed touch objects. + */ - case REACT_SUSPENSE_LIST_TYPE: - return "SuspenseList"; - } + var removeTouchesAtIndices = function (touches, indices) { + var rippedOut = []; // use an unsafe downcast to alias to nullable elements, + // so we can delete and then compact. - if (typeof type === "object") { - switch (type.$$typeof) { - case REACT_CONTEXT_TYPE: - var context = type; - return getContextName(context) + ".Consumer"; + var temp = touches; - case REACT_PROVIDER_TYPE: - var provider = type; - return getContextName(provider._context) + ".Provider"; + for (var i = 0; i < indices.length; i++) { + var index = indices[i]; + rippedOut.push(touches[index]); + temp[index] = null; + } - case REACT_FORWARD_REF_TYPE: - return getWrappedName(type, type.render, "ForwardRef"); + var fillAt = 0; - case REACT_MEMO_TYPE: - var outerName = type.displayName || null; + for (var j = 0; j < temp.length; j++) { + var cur = temp[j]; - if (outerName !== null) { - return outerName; + if (cur !== null) { + temp[fillAt++] = cur; } + } - return getComponentNameFromType(type.type) || "Memo"; + temp.length = fillAt; + return rippedOut; + }; + /** + * Internal version of `receiveEvent` in terms of normalized (non-tag) + * `rootNodeID`. + * + * @see receiveEvent. + * + * @param {rootNodeID} rootNodeID React root node ID that event occurred on. + * @param {TopLevelType} topLevelType Top level type of event. + * @param {?object} nativeEventParam Object passed from native. + */ - case REACT_LAZY_TYPE: { - var lazyComponent = type; - var payload = lazyComponent._payload; - var init = lazyComponent._init; + function _receiveRootNodeIDEvent(rootNodeID, topLevelType, nativeEventParam) { + var nativeEvent = nativeEventParam || EMPTY_NATIVE_EVENT; + var inst = getInstanceFromTag(rootNodeID); + var target = null; - try { - return getComponentNameFromType(init(payload)); - } catch (x) { - return null; - } + if (inst != null) { + target = inst.stateNode; } - // eslint-disable-next-line no-fallthrough + batchedUpdates(function () { + runExtractedPluginEventsInBatch(topLevelType, inst, nativeEvent, target); + }); // React Native doesn't use ReactControlledComponent but if it did, here's + // where it would do it. } - } - - return null; -} - -function getWrappedName$1(outerType, innerType, wrapperName) { - var functionName = innerType.displayName || innerType.name || ""; - return ( - outerType.displayName || - (functionName !== "" ? wrapperName + "(" + functionName + ")" : wrapperName) - ); -} // Keep in sync with shared/getComponentNameFromType - -function getContextName$1(type) { - return type.displayName || "Context"; -} + /** + * Allows registered plugins an opportunity to extract events from top-level + * native browser events. + * + * @return {*} An accumulation of synthetic events. + * @internal + */ -function getComponentNameFromFiber(fiber) { - var tag = fiber.tag, - type = fiber.type; + function extractPluginEvents( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget + ) { + var events = null; + var legacyPlugins = plugins; + + for (var i = 0; i < legacyPlugins.length; i++) { + // Not every plugin in the ordering may be loaded at runtime. + var possiblePlugin = legacyPlugins[i]; + + if (possiblePlugin) { + var extractedEvents = possiblePlugin.extractEvents( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget + ); - switch (tag) { - case CacheComponent: - return "Cache"; + if (extractedEvents) { + events = accumulateInto(events, extractedEvents); + } + } + } - case ContextConsumer: - var context = type; - return getContextName$1(context) + ".Consumer"; + return events; + } - case ContextProvider: - var provider = type; - return getContextName$1(provider._context) + ".Provider"; + function runExtractedPluginEventsInBatch( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget + ) { + var events = extractPluginEvents( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget + ); + runEventsInBatch(events); + } + /** + * Publicly exposed method on module for native objc to invoke when a top + * level event is extracted. + * @param {rootNodeID} rootNodeID React root node ID that event occurred on. + * @param {TopLevelType} topLevelType Top level type of event. + * @param {object} nativeEventParam Object passed from native. + */ - case DehydratedFragment: - return "DehydratedFragment"; + function receiveEvent(rootNodeID, topLevelType, nativeEventParam) { + _receiveRootNodeIDEvent(rootNodeID, topLevelType, nativeEventParam); + } + /** + * Simple multi-wrapper around `receiveEvent` that is intended to receive an + * efficient representation of `Touch` objects, and other information that + * can be used to construct W3C compliant `Event` and `Touch` lists. + * + * This may create dispatch behavior that differs than web touch handling. We + * loop through each of the changed touches and receive it as a single event. + * So two `touchStart`/`touchMove`s that occur simultaneously are received as + * two separate touch event dispatches - when they arguably should be one. + * + * This implementation reuses the `Touch` objects themselves as the `Event`s + * since we dispatch an event for each touch (though that might not be spec + * compliant). The main purpose of reusing them is to save allocations. + * + * TODO: Dispatch multiple changed touches in one event. The bubble path + * could be the first common ancestor of all the `changedTouches`. + * + * One difference between this behavior and W3C spec: cancelled touches will + * not appear in `.touches`, or in any future `.touches`, though they may + * still be "actively touching the surface". + * + * Web desktop polyfills only need to construct a fake touch event with + * identifier 0, also abandoning traditional click handlers. + */ - case ForwardRef: - return getWrappedName$1(type, type.render, "ForwardRef"); + function receiveTouches(eventTopLevelType, touches, changedIndices) { + var changedTouches = + eventTopLevelType === "topTouchEnd" || + eventTopLevelType === "topTouchCancel" + ? removeTouchesAtIndices(touches, changedIndices) + : touchSubsequence(touches, changedIndices); + + for (var jj = 0; jj < changedTouches.length; jj++) { + var touch = changedTouches[jj]; // Touch objects can fulfill the role of `DOM` `Event` objects if we set + // the `changedTouches`/`touches`. This saves allocations. + + touch.changedTouches = changedTouches; + touch.touches = touches; + var nativeEvent = touch; + var rootNodeID = null; + var target = nativeEvent.target; + + if (target !== null && target !== undefined) { + if (target < 1) { + { + error("A view is reporting that a touch occurred on tag zero."); + } + } else { + rootNodeID = target; + } + } // $FlowFixMe Shouldn't we *not* call it if rootNodeID is null? - case Fragment: - return "Fragment"; + _receiveRootNodeIDEvent(rootNodeID, eventTopLevelType, nativeEvent); + } + } - case HostComponent: - // Host component type is the display name (e.g. "div", "View") - return type; + // Module provided by RN: + var ReactNativeGlobalResponderHandler = { + onChange: function (from, to, blockNativeResponder) { + if (to !== null) { + var tag = to.stateNode._nativeTag; + ReactNativePrivateInterface.UIManager.setJSResponder( + tag, + blockNativeResponder + ); + } else { + ReactNativePrivateInterface.UIManager.clearJSResponder(); + } + } + }; - case HostPortal: - return "Portal"; + /** + * Register the event emitter with the native bridge + */ - case HostRoot: - return "Root"; + ReactNativePrivateInterface.RCTEventEmitter.register({ + receiveEvent: receiveEvent, + receiveTouches: receiveTouches + }); + setComponentTree( + getFiberCurrentPropsFromNode$1, + getInstanceFromTag, + getTagFromInstance + ); + ResponderEventPlugin.injection.injectGlobalResponderHandler( + ReactNativeGlobalResponderHandler + ); - case HostText: - return "Text"; + /** + * `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 enableSchedulingProfiler = false; + var enableProfilerTimer = true; + var enableProfilerCommitHooks = true; + var warnAboutStringRefs = false; + var enableSuspenseAvoidThisFallback = false; + var enableNewReconciler = false; + var enableLazyContextPropagation = false; + var enableLegacyHidden = false; + + // 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; + } - case LazyComponent: - // Name comes from the type in this case; we don't have a tag. - return getComponentNameFromType(type); + var maybeIterator = + (MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL]) || + maybeIterable[FAUX_ITERATOR_SYMBOL]; - case Mode: - if (type === REACT_STRICT_MODE_TYPE) { - // Don't be less specific than shared/getComponentNameFromType - return "StrictMode"; + if (typeof maybeIterator === "function") { + return maybeIterator; } - return "Mode"; + return null; + } - case OffscreenComponent: - return "Offscreen"; + function getWrappedName(outerType, innerType, wrapperName) { + var displayName = outerType.displayName; - case Profiler: - return "Profiler"; + if (displayName) { + return displayName; + } - case ScopeComponent: - return "Scope"; + var functionName = innerType.displayName || innerType.name || ""; + return functionName !== "" + ? wrapperName + "(" + functionName + ")" + : wrapperName; + } // Keep in sync with react-reconciler/getComponentNameFromFiber - case SuspenseComponent: - return "Suspense"; + function getContextName(type) { + return type.displayName || "Context"; + } // Note that the reconciler package should generally prefer to use getComponentNameFromFiber() instead. - case SuspenseListComponent: - return "SuspenseList"; + function getComponentNameFromType(type) { + if (type == null) { + // Host root, text node or just invalid type. + return null; + } - case TracingMarkerComponent: - return "TracingMarker"; - // The display name for this tags come from the user-provided type: + { + if (typeof type.tag === "number") { + error( + "Received an unexpected object in getComponentNameFromType(). " + + "This is likely a bug in React. Please file an issue." + ); + } + } - case ClassComponent: - case FunctionComponent: - case IncompleteClassComponent: - case IndeterminateComponent: - case MemoComponent: - case SimpleMemoComponent: if (typeof type === "function") { return type.displayName || type.name || null; } @@ -3306,21142 +3155,21333 @@ function getComponentNameFromFiber(fiber) { return type; } - break; - } + switch (type) { + case REACT_FRAGMENT_TYPE: + return "Fragment"; - return null; -} + case REACT_PORTAL_TYPE: + return "Portal"; -// Don't change these two values. They're used by React Dev Tools. -var NoFlags = - /* */ - 0; -var PerformedWork = - /* */ - 1; // You can change the rest (and add more). - -var Placement = - /* */ - 2; -var Update = - /* */ - 4; -var ChildDeletion = - /* */ - 16; -var ContentReset = - /* */ - 32; -var Callback = - /* */ - 64; -var DidCapture = - /* */ - 128; -var ForceClientRender = - /* */ - 256; -var Ref = - /* */ - 512; -var Snapshot = - /* */ - 1024; -var Passive = - /* */ - 2048; -var Hydrating = - /* */ - 4096; -var Visibility = - /* */ - 8192; -var StoreConsistency = - /* */ - 16384; -var LifecycleEffectMask = - Passive | 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 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; // These flags allow us to traverse to fibers that have effects on mount -// 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 | 0; -var MutationMask = - Placement | - Update | - ChildDeletion | - ContentReset | - Ref | - Hydrating | - Visibility; -var LayoutMask = Update | Callback | Ref | Visibility; // TODO: Split into PassiveMountMask and PassiveUnmountMask - -var PassiveMask = Passive | 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; - -var ReactCurrentOwner = 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) { - // 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; - } - - 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.current; + case REACT_PROFILER_TYPE: + return "Profiler"; - if (owner !== null && owner.tag === ClassComponent) { - var ownerFiber = owner; - var instance = ownerFiber.stateNode; + case REACT_STRICT_MODE_TYPE: + return "StrictMode"; - 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 REACT_SUSPENSE_TYPE: + return "Suspense"; + + case REACT_SUSPENSE_LIST_TYPE: + return "SuspenseList"; } - instance._warnedAboutRefsInRender = true; - } - } + if (typeof type === "object") { + switch (type.$$typeof) { + case REACT_CONTEXT_TYPE: + var context = type; + return getContextName(context) + ".Consumer"; - var fiber = get(component); + case REACT_PROVIDER_TYPE: + var provider = type; + return getContextName(provider._context) + ".Provider"; - if (!fiber) { - return false; - } + case REACT_FORWARD_REF_TYPE: + return getWrappedName(type, type.render, "ForwardRef"); - return getNearestMountedFiber(fiber) === fiber; -} + case REACT_MEMO_TYPE: + var outerName = type.displayName || null; -function assertIsMounted(fiber) { - if (getNearestMountedFiber(fiber) !== fiber) { - throw new Error("Unable to find node on an unmounted component."); - } -} + if (outerName !== null) { + return outerName; + } -function findCurrentFiberUsingSlowPath(fiber) { - var alternate = fiber.alternate; + return getComponentNameFromType(type.type) || "Memo"; - if (!alternate) { - // If there is no alternate, then we only need to check if it is mounted. - var nearestMounted = getNearestMountedFiber(fiber); + case REACT_LAZY_TYPE: { + var lazyComponent = type; + var payload = lazyComponent._payload; + var init = lazyComponent._init; - if (nearestMounted === null) { - throw new Error("Unable to find node on an unmounted component."); - } + try { + return getComponentNameFromType(init(payload)); + } catch (x) { + return null; + } + } + + // eslint-disable-next-line no-fallthrough + } + } - if (nearestMounted !== fiber) { return null; } - 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. - - var a = fiber; - var b = alternate; - - while (true) { - var parentA = a.return; + function getWrappedName$1(outerType, innerType, wrapperName) { + var functionName = innerType.displayName || innerType.name || ""; + return ( + outerType.displayName || + (functionName !== "" ? wrapperName + "(" + functionName + ")" : wrapperName) + ); + } // Keep in sync with shared/getComponentNameFromType - if (parentA === null) { - // We're at the root. - break; + function getContextName$1(type) { + return type.displayName || "Context"; } - var parentB = parentA.alternate; + function getComponentNameFromFiber(fiber) { + var tag = fiber.tag, + type = fiber.type; - 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; + switch (tag) { + case CacheComponent: + return "Cache"; - if (nextParent !== null) { - a = b = nextParent; - continue; - } // If there's no parent, we're at the root. + case ContextConsumer: + var context = type; + return getContextName$1(context) + ".Consumer"; - 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. + case ContextProvider: + var provider = type; + return getContextName$1(provider._context) + ".Provider"; - if (parentA.child === parentB.child) { - var child = parentA.child; + case DehydratedFragment: + return "DehydratedFragment"; - while (child) { - if (child === a) { - // We've determined that A is the current branch. - assertIsMounted(parentA); - return fiber; - } + case ForwardRef: + return getWrappedName$1(type, type.render, "ForwardRef"); - if (child === b) { - // We've determined that B is the current branch. - assertIsMounted(parentA); - return alternate; - } + case Fragment: + return "Fragment"; - 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. - - 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; + case HostComponent: + // Host component type is the display name (e.g. "div", "View") + return type; - while (_child) { - if (_child === a) { - didFindChild = true; - a = parentA; - b = parentB; - break; - } + case HostPortal: + return "Portal"; - if (_child === b) { - didFindChild = true; - b = parentA; - a = parentB; - break; - } + case HostRoot: + return "Root"; - _child = _child.sibling; - } + case HostText: + return "Text"; - if (!didFindChild) { - // Search parent B's child set - _child = parentB.child; + case LazyComponent: + // Name comes from the type in this case; we don't have a tag. + return getComponentNameFromType(type); - while (_child) { - if (_child === a) { - didFindChild = true; - a = parentB; - b = parentA; - break; + case Mode: + if (type === REACT_STRICT_MODE_TYPE) { + // Don't be less specific than shared/getComponentNameFromType + return "StrictMode"; } - if (_child === b) { - didFindChild = true; - b = parentB; - a = parentA; - break; - } + return "Mode"; - _child = _child.sibling; - } + case OffscreenComponent: + return "Offscreen"; - 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." - ); - } - } - } + case Profiler: + return "Profiler"; - 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. + case ScopeComponent: + return "Scope"; - if (a.tag !== HostRoot) { - throw new Error("Unable to find node on an unmounted component."); - } + case SuspenseComponent: + return "Suspense"; - if (a.stateNode.current === a) { - // We've determined that A is the current branch. - return fiber; - } // Otherwise B has to be current branch. + case SuspenseListComponent: + return "SuspenseList"; - return alternate; -} -function findCurrentHostFiber(parent) { - var currentParent = findCurrentFiberUsingSlowPath(parent); - return currentParent !== null - ? findCurrentHostFiberImpl(currentParent) - : null; -} + case TracingMarkerComponent: + return "TracingMarker"; + // The display name for this tags come from the user-provided type: -function findCurrentHostFiberImpl(node) { - // Next we'll drill down this component to find the first HostComponent/Text. - if (node.tag === HostComponent || node.tag === HostText) { - return node; - } + case ClassComponent: + case FunctionComponent: + case IncompleteClassComponent: + case IndeterminateComponent: + case MemoComponent: + case SimpleMemoComponent: + if (typeof type === "function") { + return type.displayName || type.name || null; + } - var child = node.child; + if (typeof type === "string") { + return type; + } - while (child !== null) { - var match = findCurrentHostFiberImpl(child); + break; + } - if (match !== null) { - return match; + return null; } - child = child.sibling; - } + // Don't change these two values. They're used by React Dev Tools. + var NoFlags = + /* */ + 0; + var PerformedWork = + /* */ + 1; // You can change the rest (and add more). + + var Placement = + /* */ + 2; + var Update = + /* */ + 4; + var ChildDeletion = + /* */ + 16; + var ContentReset = + /* */ + 32; + var Callback = + /* */ + 64; + var DidCapture = + /* */ + 128; + var ForceClientRender = + /* */ + 256; + var Ref = + /* */ + 512; + var Snapshot = + /* */ + 1024; + var Passive = + /* */ + 2048; + var Hydrating = + /* */ + 4096; + var Visibility = + /* */ + 8192; + var StoreConsistency = + /* */ + 16384; + var LifecycleEffectMask = + Passive | 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 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; // These flags allow us to traverse to fibers that have effects on mount + // 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 | 0; + var MutationMask = + Placement | + Update | + ChildDeletion | + ContentReset | + Ref | + Hydrating | + Visibility; + var LayoutMask = Update | Callback | Ref | Visibility; // TODO: Split into PassiveMountMask and PassiveUnmountMask + + var PassiveMask = Passive | 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; + + var ReactCurrentOwner = 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; - return null; -} + do { + node = nextNode; -// Modules provided by RN: -var emptyObject = {}; -/** - * Create a payload that contains all the updates between two sets of props. - * - * These helpers are all encapsulated into a single module, because they use - * mutation as a performance optimization which leads to subtle shared - * dependencies between the code paths. To avoid this mutable state leaking - * across modules, I've kept them isolated to this module. - */ + if ((node.flags & (Placement | Hydrating)) !== NoFlags) { + // 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; + } -// Tracks removed keys -var removedKeys = null; -var removedKeyCount = 0; -var deepDifferOptions = { - unsafelyIgnoreFunctions: true -}; - -function defaultDiffer(prevProp, nextProp) { - if (typeof nextProp !== "object" || nextProp === null) { - // Scalars have already been checked for equality - return true; - } else { - // For objects and arrays, the default diffing algorithm is a deep compare - return ReactNativePrivateInterface.deepDiffer( - prevProp, - nextProp, - deepDifferOptions - ); - } -} + nextNode = node.return; + } while (nextNode); + } else { + while (node.return) { + node = node.return; + } + } -function restoreDeletedValuesInNestedArray( - updatePayload, - node, - validAttributes -) { - if (isArray(node)) { - var i = node.length; + 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. - while (i-- && removedKeyCount > 0) { - restoreDeletedValuesInNestedArray( - updatePayload, - node[i], - validAttributes - ); + return null; + } + function isFiberMounted(fiber) { + return getNearestMountedFiber(fiber) === fiber; } - } else if (node && removedKeyCount > 0) { - var obj = node; + function isMounted(component) { + { + var owner = ReactCurrentOwner.current; - for (var propKey in removedKeys) { - if (!removedKeys[propKey]) { - continue; - } + if (owner !== null && owner.tag === ClassComponent) { + var ownerFiber = owner; + var instance = ownerFiber.stateNode; - var nextProp = obj[propKey]; + 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 (nextProp === undefined) { - continue; + instance._warnedAboutRefsInRender = true; + } } - var attributeConfig = validAttributes[propKey]; + var fiber = get(component); - if (!attributeConfig) { - continue; // not a valid native prop + if (!fiber) { + return false; } - if (typeof nextProp === "function") { - nextProp = true; - } + return getNearestMountedFiber(fiber) === fiber; + } - if (typeof nextProp === "undefined") { - nextProp = null; + function assertIsMounted(fiber) { + if (getNearestMountedFiber(fiber) !== fiber) { + throw new Error("Unable to find node on an unmounted component."); } + } - if (typeof attributeConfig !== "object") { - // case: !Object is the default case - updatePayload[propKey] = nextProp; - } else if ( - typeof attributeConfig.diff === "function" || - typeof attributeConfig.process === "function" - ) { - // case: CustomAttributeConfiguration - var nextValue = - typeof attributeConfig.process === "function" - ? attributeConfig.process(nextProp) - : nextProp; - updatePayload[propKey] = nextValue; - } + function findCurrentFiberUsingSlowPath(fiber) { + var alternate = fiber.alternate; - removedKeys[propKey] = false; - removedKeyCount--; - } - } -} + if (!alternate) { + // If there is no alternate, then we only need to check if it is mounted. + var nearestMounted = getNearestMountedFiber(fiber); -function diffNestedArrayProperty( - updatePayload, - prevArray, - nextArray, - validAttributes -) { - var minLength = - prevArray.length < nextArray.length ? prevArray.length : nextArray.length; - var i; - - for (i = 0; i < minLength; i++) { - // Diff any items in the array in the forward direction. Repeated keys - // will be overwritten by later values. - updatePayload = diffNestedProperty( - updatePayload, - prevArray[i], - nextArray[i], - validAttributes - ); - } + if (nearestMounted === null) { + throw new Error("Unable to find node on an unmounted component."); + } - for (; i < prevArray.length; i++) { - // Clear out all remaining properties. - updatePayload = clearNestedProperty( - updatePayload, - prevArray[i], - validAttributes - ); - } + if (nearestMounted !== fiber) { + return null; + } - for (; i < nextArray.length; i++) { - // Add all remaining properties. - updatePayload = addNestedProperty( - updatePayload, - nextArray[i], - validAttributes - ); - } + 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. - return updatePayload; -} + var a = fiber; + var b = alternate; -function diffNestedProperty( - updatePayload, - prevProp, - nextProp, - validAttributes -) { - if (!updatePayload && prevProp === nextProp) { - // If no properties have been added, then we can bail out quickly on object - // equality. - return updatePayload; - } + while (true) { + var parentA = a.return; - if (!prevProp || !nextProp) { - if (nextProp) { - return addNestedProperty(updatePayload, nextProp, validAttributes); - } + if (parentA === null) { + // We're at the root. + break; + } - if (prevProp) { - return clearNestedProperty(updatePayload, prevProp, validAttributes); - } + var parentB = parentA.alternate; - return updatePayload; - } + 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 (!isArray(prevProp) && !isArray(nextProp)) { - // Both are leaves, we can diff the leaves. - return diffProperties(updatePayload, prevProp, nextProp, validAttributes); - } + if (nextParent !== null) { + a = b = nextParent; + continue; + } // If there's no parent, we're at the root. - if (isArray(prevProp) && isArray(nextProp)) { - // Both are arrays, we can diff the arrays. - return diffNestedArrayProperty( - updatePayload, - prevProp, - nextProp, - validAttributes - ); - } + 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 (isArray(prevProp)) { - return diffProperties( - updatePayload, // $FlowFixMe - We know that this is always an object when the input is. - ReactNativePrivateInterface.flattenStyle(prevProp), // $FlowFixMe - We know that this isn't an array because of above flow. - nextProp, - validAttributes - ); - } - - return diffProperties( - updatePayload, - prevProp, // $FlowFixMe - We know that this is always an object when the input is. - ReactNativePrivateInterface.flattenStyle(nextProp), - validAttributes - ); -} -/** - * addNestedProperty takes a single set of props and valid attribute - * attribute configurations. It processes each prop and adds it to the - * updatePayload. - */ + if (child === b) { + // We've determined that B is the current branch. + assertIsMounted(parentA); + return alternate; + } -function addNestedProperty(updatePayload, nextProp, validAttributes) { - if (!nextProp) { - return updatePayload; - } + 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 (!isArray(nextProp)) { - // Add each property of the leaf. - return addProperties(updatePayload, nextProp, validAttributes); - } + throw new Error("Unable to find node on an unmounted component."); + } - for (var i = 0; i < nextProp.length; i++) { - // Add all the properties of the array. - updatePayload = addNestedProperty( - updatePayload, - nextProp[i], - validAttributes - ); - } + 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; + } - return updatePayload; -} -/** - * clearNestedProperty takes a single set of props and valid attributes. It - * adds a null sentinel to the updatePayload, for each prop key. - */ + if (_child === b) { + didFindChild = true; + b = parentA; + a = parentB; + break; + } -function clearNestedProperty(updatePayload, prevProp, validAttributes) { - if (!prevProp) { - return updatePayload; - } + _child = _child.sibling; + } - if (!isArray(prevProp)) { - // Add each property of the leaf. - return clearProperties(updatePayload, prevProp, validAttributes); - } + if (!didFindChild) { + // Search parent B's child set + _child = parentB.child; - for (var i = 0; i < prevProp.length; i++) { - // Add all the properties of the array. - updatePayload = clearNestedProperty( - updatePayload, - prevProp[i], - validAttributes - ); - } - - return updatePayload; -} -/** - * diffProperties takes two sets of props and a set of valid attributes - * and write to updatePayload the values that changed or were deleted. - * If no updatePayload is provided, a new one is created and returned if - * anything changed. - */ - -function diffProperties(updatePayload, prevProps, nextProps, validAttributes) { - var attributeConfig; - var nextProp; - var prevProp; + while (_child) { + if (_child === a) { + didFindChild = true; + a = parentB; + b = parentA; + break; + } - for (var propKey in nextProps) { - attributeConfig = validAttributes[propKey]; + if (_child === b) { + didFindChild = true; + b = parentB; + a = parentA; + break; + } - if (!attributeConfig) { - continue; // not a valid native prop - } + _child = _child.sibling; + } - prevProp = prevProps[propKey]; - nextProp = nextProps[propKey]; // functions are converted to booleans as markers that the associated - // events should be sent from native. + 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 (typeof nextProp === "function") { - nextProp = true; // If nextProp is not a function, then don't bother changing prevProp - // since nextProp will win and go into the updatePayload regardless. + 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 (typeof prevProp === "function") { - prevProp = true; + if (a.tag !== HostRoot) { + throw new Error("Unable to find node on an unmounted component."); } - } // An explicit value of undefined is treated as a null because it overrides - // any other preceding value. - if (typeof nextProp === "undefined") { - nextProp = null; + if (a.stateNode.current === a) { + // We've determined that A is the current branch. + return fiber; + } // Otherwise B has to be current branch. - if (typeof prevProp === "undefined") { - prevProp = null; - } + return alternate; } - - if (removedKeys) { - removedKeys[propKey] = false; + function findCurrentHostFiber(parent) { + var currentParent = findCurrentFiberUsingSlowPath(parent); + return currentParent !== null + ? findCurrentHostFiberImpl(currentParent) + : null; } - if (updatePayload && updatePayload[propKey] !== undefined) { - // Something else already triggered an update to this key because another - // value diffed. Since we're now later in the nested arrays our value is - // more important so we need to calculate it and override the existing - // value. It doesn't matter if nothing changed, we'll set it anyway. - // Pattern match on: attributeConfig - if (typeof attributeConfig !== "object") { - // case: !Object is the default case - updatePayload[propKey] = nextProp; - } else if ( - typeof attributeConfig.diff === "function" || - typeof attributeConfig.process === "function" - ) { - // case: CustomAttributeConfiguration - var nextValue = - typeof attributeConfig.process === "function" - ? attributeConfig.process(nextProp) - : nextProp; - updatePayload[propKey] = nextValue; + function findCurrentHostFiberImpl(node) { + // Next we'll drill down this component to find the first HostComponent/Text. + if (node.tag === HostComponent || node.tag === HostText) { + return node; } - continue; - } + var child = node.child; + + while (child !== null) { + var match = findCurrentHostFiberImpl(child); - if (prevProp === nextProp) { - continue; // nothing changed - } // Pattern match on: attributeConfig + if (match !== null) { + return match; + } - if (typeof attributeConfig !== "object") { - // case: !Object is the default case - if (defaultDiffer(prevProp, nextProp)) { - // a normal leaf has changed - (updatePayload || (updatePayload = {}))[propKey] = nextProp; + child = child.sibling; } - } else if ( - typeof attributeConfig.diff === "function" || - typeof attributeConfig.process === "function" - ) { - // case: CustomAttributeConfiguration - var shouldUpdate = - prevProp === undefined || - (typeof attributeConfig.diff === "function" - ? attributeConfig.diff(prevProp, nextProp) - : defaultDiffer(prevProp, nextProp)); - if (shouldUpdate) { - var _nextValue = - typeof attributeConfig.process === "function" - ? attributeConfig.process(nextProp) - : nextProp; + return null; + } - (updatePayload || (updatePayload = {}))[propKey] = _nextValue; - } - } else { - // default: fallthrough case when nested properties are defined - removedKeys = null; - removedKeyCount = 0; // We think that attributeConfig is not CustomAttributeConfiguration at - // this point so we assume it must be AttributeConfiguration. + // Modules provided by RN: + var emptyObject = {}; + /** + * Create a payload that contains all the updates between two sets of props. + * + * These helpers are all encapsulated into a single module, because they use + * mutation as a performance optimization which leads to subtle shared + * dependencies between the code paths. To avoid this mutable state leaking + * across modules, I've kept them isolated to this module. + */ - updatePayload = diffNestedProperty( - updatePayload, - prevProp, - nextProp, - attributeConfig - ); + // Tracks removed keys + var removedKeys = null; + var removedKeyCount = 0; + var deepDifferOptions = { + unsafelyIgnoreFunctions: true + }; - if (removedKeyCount > 0 && updatePayload) { - restoreDeletedValuesInNestedArray( - updatePayload, + function defaultDiffer(prevProp, nextProp) { + if (typeof nextProp !== "object" || nextProp === null) { + // Scalars have already been checked for equality + return true; + } else { + // For objects and arrays, the default diffing algorithm is a deep compare + return ReactNativePrivateInterface.deepDiffer( + prevProp, nextProp, - attributeConfig + deepDifferOptions ); - removedKeys = null; } } - } // Also iterate through all the previous props to catch any that have been - // removed and make sure native gets the signal so it can reset them to the - // default. - for (var _propKey in prevProps) { - if (nextProps[_propKey] !== undefined) { - continue; // we've already covered this key in the previous pass - } + function restoreDeletedValuesInNestedArray( + updatePayload, + node, + validAttributes + ) { + if (isArray(node)) { + var i = node.length; + + while (i-- && removedKeyCount > 0) { + restoreDeletedValuesInNestedArray( + updatePayload, + node[i], + validAttributes + ); + } + } else if (node && removedKeyCount > 0) { + var obj = node; - attributeConfig = validAttributes[_propKey]; + for (var propKey in removedKeys) { + if (!removedKeys[propKey]) { + continue; + } - if (!attributeConfig) { - continue; // not a valid native prop - } + var nextProp = obj[propKey]; - if (updatePayload && updatePayload[_propKey] !== undefined) { - // This was already updated to a diff result earlier. - continue; - } + if (nextProp === undefined) { + continue; + } - prevProp = prevProps[_propKey]; + var attributeConfig = validAttributes[propKey]; - if (prevProp === undefined) { - continue; // was already empty anyway - } // Pattern match on: attributeConfig + if (!attributeConfig) { + continue; // not a valid native prop + } - if ( - typeof attributeConfig !== "object" || - typeof attributeConfig.diff === "function" || - typeof attributeConfig.process === "function" - ) { - // case: CustomAttributeConfiguration | !Object - // Flag the leaf property for removal by sending a sentinel. - (updatePayload || (updatePayload = {}))[_propKey] = null; + if (typeof nextProp === "function") { + nextProp = true; + } - if (!removedKeys) { - removedKeys = {}; - } + if (typeof nextProp === "undefined") { + nextProp = null; + } - if (!removedKeys[_propKey]) { - removedKeys[_propKey] = true; - removedKeyCount++; + if (typeof attributeConfig !== "object") { + // case: !Object is the default case + updatePayload[propKey] = nextProp; + } else if ( + typeof attributeConfig.diff === "function" || + typeof attributeConfig.process === "function" + ) { + // case: CustomAttributeConfiguration + var nextValue = + typeof attributeConfig.process === "function" + ? attributeConfig.process(nextProp) + : nextProp; + updatePayload[propKey] = nextValue; + } + + removedKeys[propKey] = false; + removedKeyCount--; + } } - } else { - // default: - // This is a nested attribute configuration where all the properties - // were removed so we need to go through and clear out all of them. - updatePayload = clearNestedProperty( - updatePayload, - prevProp, - attributeConfig - ); } - } - - return updatePayload; -} -/** - * addProperties adds all the valid props to the payload after being processed. - */ - -function addProperties(updatePayload, props, validAttributes) { - // TODO: Fast path - return diffProperties(updatePayload, emptyObject, props, validAttributes); -} -/** - * clearProperties clears all the previous props by adding a null sentinel - * to the payload for each valid key. - */ - -function clearProperties(updatePayload, prevProps, validAttributes) { - // TODO: Fast path - return diffProperties(updatePayload, prevProps, emptyObject, validAttributes); -} -function create(props, validAttributes) { - return addProperties( - null, // updatePayload - props, - validAttributes - ); -} -function diff(prevProps, nextProps, validAttributes) { - return diffProperties( - null, // updatePayload - prevProps, - nextProps, - validAttributes - ); -} + function diffNestedArrayProperty( + updatePayload, + prevArray, + nextArray, + validAttributes + ) { + var minLength = + prevArray.length < nextArray.length ? prevArray.length : nextArray.length; + var i; + + for (i = 0; i < minLength; i++) { + // Diff any items in the array in the forward direction. Repeated keys + // will be overwritten by later values. + updatePayload = diffNestedProperty( + updatePayload, + prevArray[i], + nextArray[i], + validAttributes + ); + } -/** - * In the future, we should cleanup callbacks by cancelling them instead of - * using this. - */ -function mountSafeCallback_NOT_REALLY_SAFE(context, callback) { - return function() { - if (!callback) { - return undefined; - } // This protects against createClass() components. - // We don't know if there is code depending on it. - // We intentionally don't use isMounted() because even accessing - // isMounted property on a React ES6 class will trigger a warning. - - if (typeof context.__isMounted === "boolean") { - if (!context.__isMounted) { - return undefined; + for (; i < prevArray.length; i++) { + // Clear out all remaining properties. + updatePayload = clearNestedProperty( + updatePayload, + prevArray[i], + validAttributes + ); } - } // FIXME: there used to be other branches that protected - // against unmounted host components. But RN host components don't - // define isMounted() anymore, so those checks didn't do anything. - // They caused false positive warning noise so we removed them: - // https://github.com/facebook/react-native/issues/18868#issuecomment-413579095 - // However, this means that the callback is NOT guaranteed to be safe - // for host components. The solution we should implement is to make - // UIManager.measure() and similar calls truly cancelable. Then we - // can change our own code calling them to cancel when something unmounts. - - return callback.apply(context, arguments); - }; -} -function warnForStyleProps(props, validAttributes) { - { - for (var key in validAttributes.style) { - if (!(validAttributes[key] || props[key] === undefined)) { - error( - "You are setting the style `{ %s" + - ": ... }` as a prop. You " + - "should nest it in a style object. " + - "E.g. `{ style: { %s" + - ": ... } }`", - key, - key + + for (; i < nextArray.length; i++) { + // Add all remaining properties. + updatePayload = addNestedProperty( + updatePayload, + nextArray[i], + validAttributes ); } + + return updatePayload; } - } -} -var ReactNativeFiberHostComponent = /*#__PURE__*/ (function() { - function ReactNativeFiberHostComponent( - tag, - viewConfig, - internalInstanceHandleDEV - ) { - this._nativeTag = tag; - this._children = []; - this.viewConfig = viewConfig; + function diffNestedProperty( + updatePayload, + prevProp, + nextProp, + validAttributes + ) { + if (!updatePayload && prevProp === nextProp) { + // If no properties have been added, then we can bail out quickly on object + // equality. + return updatePayload; + } - { - this._internalFiberInstanceHandleDEV = internalInstanceHandleDEV; - } - } + if (!prevProp || !nextProp) { + if (nextProp) { + return addNestedProperty(updatePayload, nextProp, validAttributes); + } - var _proto = ReactNativeFiberHostComponent.prototype; + if (prevProp) { + return clearNestedProperty(updatePayload, prevProp, validAttributes); + } - _proto.blur = function blur() { - ReactNativePrivateInterface.TextInputState.blurTextInput(this); - }; + return updatePayload; + } - _proto.focus = function focus() { - ReactNativePrivateInterface.TextInputState.focusTextInput(this); - }; + if (!isArray(prevProp) && !isArray(nextProp)) { + // Both are leaves, we can diff the leaves. + return diffProperties(updatePayload, prevProp, nextProp, validAttributes); + } - _proto.measure = function measure(callback) { - ReactNativePrivateInterface.UIManager.measure( - this._nativeTag, - mountSafeCallback_NOT_REALLY_SAFE(this, callback) - ); - }; + if (isArray(prevProp) && isArray(nextProp)) { + // Both are arrays, we can diff the arrays. + return diffNestedArrayProperty( + updatePayload, + prevProp, + nextProp, + validAttributes + ); + } - _proto.measureInWindow = function measureInWindow(callback) { - ReactNativePrivateInterface.UIManager.measureInWindow( - this._nativeTag, - mountSafeCallback_NOT_REALLY_SAFE(this, callback) - ); - }; + if (isArray(prevProp)) { + return diffProperties( + updatePayload, // $FlowFixMe - We know that this is always an object when the input is. + ReactNativePrivateInterface.flattenStyle(prevProp), // $FlowFixMe - We know that this isn't an array because of above flow. + nextProp, + validAttributes + ); + } - _proto.measureLayout = function measureLayout( - relativeToNativeNode, - onSuccess, - onFail - ) /* currently unused */ - { - var relativeNode; + return diffProperties( + updatePayload, + prevProp, // $FlowFixMe - We know that this is always an object when the input is. + ReactNativePrivateInterface.flattenStyle(nextProp), + validAttributes + ); + } + /** + * addNestedProperty takes a single set of props and valid attribute + * attribute configurations. It processes each prop and adds it to the + * updatePayload. + */ - if (typeof relativeToNativeNode === "number") { - // Already a node handle - relativeNode = relativeToNativeNode; - } else { - var nativeNode = relativeToNativeNode; + function addNestedProperty(updatePayload, nextProp, validAttributes) { + if (!nextProp) { + return updatePayload; + } - if (nativeNode._nativeTag) { - relativeNode = nativeNode._nativeTag; + if (!isArray(nextProp)) { + // Add each property of the leaf. + return addProperties(updatePayload, nextProp, validAttributes); } - } - if (relativeNode == null) { - { - error( - "Warning: ref.measureLayout must be called with a node handle or a ref to a native component." + for (var i = 0; i < nextProp.length; i++) { + // Add all the properties of the array. + updatePayload = addNestedProperty( + updatePayload, + nextProp[i], + validAttributes ); } - return; + return updatePayload; } + /** + * clearNestedProperty takes a single set of props and valid attributes. It + * adds a null sentinel to the updatePayload, for each prop key. + */ - ReactNativePrivateInterface.UIManager.measureLayout( - this._nativeTag, - relativeNode, - mountSafeCallback_NOT_REALLY_SAFE(this, onFail), - mountSafeCallback_NOT_REALLY_SAFE(this, onSuccess) - ); - }; + function clearNestedProperty(updatePayload, prevProp, validAttributes) { + if (!prevProp) { + return updatePayload; + } - _proto.setNativeProps = function setNativeProps(nativeProps) { - { - warnForStyleProps(nativeProps, this.viewConfig.validAttributes); - } + if (!isArray(prevProp)) { + // Add each property of the leaf. + return clearProperties(updatePayload, prevProp, validAttributes); + } - var updatePayload = create(nativeProps, this.viewConfig.validAttributes); // Avoid the overhead of bridge calls if there's no update. - // This is an expensive no-op for Android, and causes an unnecessary - // view invalidation for certain components (eg RCTTextInput) on iOS. + for (var i = 0; i < prevProp.length; i++) { + // Add all the properties of the array. + updatePayload = clearNestedProperty( + updatePayload, + prevProp[i], + validAttributes + ); + } - if (updatePayload != null) { - ReactNativePrivateInterface.UIManager.updateView( - this._nativeTag, - this.viewConfig.uiViewClassName, - updatePayload - ); - } - }; - - return ReactNativeFiberHostComponent; -})(); // eslint-disable-next-line no-unused-expressions - -// This module only exists as an ESM wrapper around the external CommonJS -var scheduleCallback = Scheduler.unstable_scheduleCallback; -var cancelCallback = Scheduler.unstable_cancelCallback; -var shouldYield = Scheduler.unstable_shouldYield; -var requestPaint = Scheduler.unstable_requestPaint; -var now = Scheduler.unstable_now; -var ImmediatePriority = Scheduler.unstable_ImmediatePriority; -var UserBlockingPriority = Scheduler.unstable_UserBlockingPriority; -var NormalPriority = Scheduler.unstable_NormalPriority; -var IdlePriority = Scheduler.unstable_IdlePriority; - -var rendererID = null; -var injectedHook = 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://react.dev/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 - }); + return updatePayload; } + /** + * diffProperties takes two sets of props and a set of valid attributes + * and write to updatePayload the values that changed or were deleted. + * If no updatePayload is provided, a new one is created and returned if + * anything changed. + */ - 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); - } - } + function diffProperties(updatePayload, prevProps, nextProps, validAttributes) { + var attributeConfig; + var nextProp; + var prevProp; - 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; + for (var propKey in nextProps) { + attributeConfig = validAttributes[propKey]; - error("React instrumentation encountered an error: %s", err); + if (!attributeConfig) { + continue; // not a valid native prop } - } - } - } -} -function onCommitRoot(root, eventPriority) { - if (injectedHook && typeof injectedHook.onCommitFiberRoot === "function") { - try { - var didError = (root.current.flags & DidCapture) === DidCapture; - if (enableProfilerTimer) { - var schedulerPriority; + prevProp = prevProps[propKey]; + nextProp = nextProps[propKey]; // functions are converted to booleans as markers that the associated + // events should be sent from native. - switch (eventPriority) { - case DiscreteEventPriority: - schedulerPriority = ImmediatePriority; - break; + if (typeof nextProp === "function") { + nextProp = true; // If nextProp is not a function, then don't bother changing prevProp + // since nextProp will win and go into the updatePayload regardless. - case ContinuousEventPriority: - schedulerPriority = UserBlockingPriority; - break; + if (typeof prevProp === "function") { + prevProp = true; + } + } // An explicit value of undefined is treated as a null because it overrides + // any other preceding value. - case DefaultEventPriority: - schedulerPriority = NormalPriority; - break; + if (typeof nextProp === "undefined") { + nextProp = null; - case IdleEventPriority: - schedulerPriority = IdlePriority; - break; + if (typeof prevProp === "undefined") { + prevProp = null; + } + } - default: - schedulerPriority = NormalPriority; - break; + if (removedKeys) { + removedKeys[propKey] = false; } - injectedHook.onCommitFiberRoot( - rendererID, - root, - schedulerPriority, - didError - ); - } else { - injectedHook.onCommitFiberRoot(rendererID, root, undefined, didError); - } - } catch (err) { - { - if (!hasLoggedError) { - hasLoggedError = true; + if (updatePayload && updatePayload[propKey] !== undefined) { + // Something else already triggered an update to this key because another + // value diffed. Since we're now later in the nested arrays our value is + // more important so we need to calculate it and override the existing + // value. It doesn't matter if nothing changed, we'll set it anyway. + // Pattern match on: attributeConfig + if (typeof attributeConfig !== "object") { + // case: !Object is the default case + updatePayload[propKey] = nextProp; + } else if ( + typeof attributeConfig.diff === "function" || + typeof attributeConfig.process === "function" + ) { + // case: CustomAttributeConfiguration + var nextValue = + typeof attributeConfig.process === "function" + ? attributeConfig.process(nextProp) + : nextProp; + updatePayload[propKey] = nextValue; + } - error("React instrumentation encountered an error: %s", err); + continue; } - } - } - } -} -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); + if (prevProp === nextProp) { + continue; // nothing changed + } // Pattern match on: attributeConfig + + if (typeof attributeConfig !== "object") { + // case: !Object is the default case + if (defaultDiffer(prevProp, nextProp)) { + // a normal leaf has changed + (updatePayload || (updatePayload = {}))[propKey] = nextProp; + } + } else if ( + typeof attributeConfig.diff === "function" || + typeof attributeConfig.process === "function" + ) { + // case: CustomAttributeConfiguration + var shouldUpdate = + prevProp === undefined || + (typeof attributeConfig.diff === "function" + ? attributeConfig.diff(prevProp, nextProp) + : defaultDiffer(prevProp, nextProp)); + + if (shouldUpdate) { + var _nextValue = + typeof attributeConfig.process === "function" + ? attributeConfig.process(nextProp) + : nextProp; + + (updatePayload || (updatePayload = {}))[propKey] = _nextValue; + } + } else { + // default: fallthrough case when nested properties are defined + removedKeys = null; + removedKeyCount = 0; // We think that attributeConfig is not CustomAttributeConfiguration at + // this point so we assume it must be AttributeConfiguration. + + updatePayload = diffNestedProperty( + updatePayload, + prevProp, + nextProp, + attributeConfig + ); + + if (removedKeyCount > 0 && updatePayload) { + restoreDeletedValuesInNestedArray( + updatePayload, + nextProp, + attributeConfig + ); + removedKeys = null; + } } - } - } - } -} -function onCommitUnmount(fiber) { - if (injectedHook && typeof injectedHook.onCommitFiberUnmount === "function") { - try { - injectedHook.onCommitFiberUnmount(rendererID, fiber); - } catch (err) { - { - if (!hasLoggedError) { - hasLoggedError = true; + } // Also iterate through all the previous props to catch any that have been + // removed and make sure native gets the signal so it can reset them to the + // default. - error("React instrumentation encountered an error: %s", err); + for (var _propKey in prevProps) { + if (nextProps[_propKey] !== undefined) { + continue; // we've already covered this key in the previous pass } - } - } - } -} -function injectProfilingHooks(profilingHooks) {} + attributeConfig = validAttributes[_propKey]; -function getLaneLabelMap() { - { - return null; - } -} -function markComponentRenderStopped() {} -function markComponentErrored(fiber, thrownValue, lanes) {} -function markComponentSuspended(fiber, wakeable, lanes) {} - -var NoMode = - /* */ - 0; // TODO: Remove ConcurrentMode by reading from the root tag instead - -var ConcurrentMode = - /* */ - 1; -var ProfileMode = - /* */ - 2; -var StrictLegacyMode = - /* */ - 8; - -// 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 = Math.log; -var LN2 = Math.LN2; - -function clz32Fallback(x) { - var asUint = x >>> 0; - - if (asUint === 0) { - return 32; - } - - return (31 - ((log(asUint) / LN2) | 0)) | 0; -} + if (!attributeConfig) { + continue; // not a valid native prop + } -// If those values are changed that package should be rebuilt and redeployed. - -var TotalLanes = 31; -var NoLanes = - /* */ - 0; -var NoLane = - /* */ - 0; -var SyncLane = - /* */ - 1; -var InputContinuousHydrationLane = - /* */ - 2; -var InputContinuousLane = - /* */ - 4; -var DefaultHydrationLane = - /* */ - 8; -var DefaultLane = - /* */ - 16; -var TransitionHydrationLane = - /* */ - 32; -var TransitionLanes = - /* */ - 4194240; -var TransitionLane1 = - /* */ - 64; -var TransitionLane2 = - /* */ - 128; -var TransitionLane3 = - /* */ - 256; -var TransitionLane4 = - /* */ - 512; -var TransitionLane5 = - /* */ - 1024; -var TransitionLane6 = - /* */ - 2048; -var TransitionLane7 = - /* */ - 4096; -var TransitionLane8 = - /* */ - 8192; -var TransitionLane9 = - /* */ - 16384; -var TransitionLane10 = - /* */ - 32768; -var TransitionLane11 = - /* */ - 65536; -var TransitionLane12 = - /* */ - 131072; -var TransitionLane13 = - /* */ - 262144; -var TransitionLane14 = - /* */ - 524288; -var TransitionLane15 = - /* */ - 1048576; -var TransitionLane16 = - /* */ - 2097152; -var RetryLanes = - /* */ - 130023424; -var RetryLane1 = - /* */ - 4194304; -var RetryLane2 = - /* */ - 8388608; -var RetryLane3 = - /* */ - 16777216; -var RetryLane4 = - /* */ - 33554432; -var RetryLane5 = - /* */ - 67108864; -var SomeRetryLane = RetryLane1; -var SelectiveHydrationLane = - /* */ - 134217728; -var NonIdleLanes = - /* */ - 268435455; -var IdleHydrationLane = - /* */ - 268435456; -var IdleLane = - /* */ - 536870912; -var OffscreenLane = - /* */ - 1073741824; // This function is used for the experimental timeline (react-devtools-timeline) -var NoTimestamp = -1; -var nextTransitionLane = TransitionLane1; -var nextRetryLane = RetryLane1; - -function getHighestPriorityLanes(lanes) { - switch (getHighestPriorityLane(lanes)) { - 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: - case TransitionLane16: - return lanes & TransitionLanes; - - case RetryLane1: - case RetryLane2: - case RetryLane3: - case RetryLane4: - case RetryLane5: - return lanes & RetryLanes; - - case SelectiveHydrationLane: - return SelectiveHydrationLane; - - case IdleHydrationLane: - return IdleHydrationLane; - - case IdleLane: - return IdleLane; - - case OffscreenLane: - return OffscreenLane; - - 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. + if (updatePayload && updatePayload[_propKey] !== undefined) { + // This was already updated to a diff result earlier. + continue; + } - return lanes; - } -} + prevProp = prevProps[_propKey]; -function getNextLanes(root, wipLanes) { - // Early bailout if there's no pending work left. - var pendingLanes = root.pendingLanes; + if (prevProp === undefined) { + continue; // was already empty anyway + } // Pattern match on: attributeConfig + + if ( + typeof attributeConfig !== "object" || + typeof attributeConfig.diff === "function" || + typeof attributeConfig.process === "function" + ) { + // case: CustomAttributeConfiguration | !Object + // Flag the leaf property for removal by sending a sentinel. + (updatePayload || (updatePayload = {}))[_propKey] = null; - if (pendingLanes === NoLanes) { - return NoLanes; - } + if (!removedKeys) { + removedKeys = {}; + } - 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 (!removedKeys[_propKey]) { + removedKeys[_propKey] = true; + removedKeyCount++; + } + } else { + // default: + // This is a nested attribute configuration where all the properties + // were removed so we need to go through and clear out all of them. + updatePayload = clearNestedProperty( + updatePayload, + prevProp, + attributeConfig + ); + } + } - var nonIdlePendingLanes = pendingLanes & NonIdleLanes; + return updatePayload; + } + /** + * addProperties adds all the valid props to the payload after being processed. + */ - if (nonIdlePendingLanes !== NoLanes) { - var nonIdleUnblockedLanes = nonIdlePendingLanes & ~suspendedLanes; + function addProperties(updatePayload, props, validAttributes) { + // TODO: Fast path + return diffProperties(updatePayload, emptyObject, props, validAttributes); + } + /** + * clearProperties clears all the previous props by adding a null sentinel + * to the payload for each valid key. + */ - if (nonIdleUnblockedLanes !== NoLanes) { - nextLanes = getHighestPriorityLanes(nonIdleUnblockedLanes); - } else { - var nonIdlePingedLanes = nonIdlePendingLanes & pingedLanes; + function clearProperties(updatePayload, prevProps, validAttributes) { + // TODO: Fast path + return diffProperties(updatePayload, prevProps, emptyObject, validAttributes); + } - if (nonIdlePingedLanes !== NoLanes) { - nextLanes = getHighestPriorityLanes(nonIdlePingedLanes); - } + function create(props, validAttributes) { + return addProperties( + null, // updatePayload + props, + validAttributes + ); + } + function diff(prevProps, nextProps, validAttributes) { + return diffProperties( + null, // updatePayload + prevProps, + nextProps, + validAttributes + ); } - } else { - // The only remaining work is Idle. - var unblockedLanes = pendingLanes & ~suspendedLanes; - if (unblockedLanes !== NoLanes) { - nextLanes = getHighestPriorityLanes(unblockedLanes); - } else { - if (pingedLanes !== NoLanes) { - nextLanes = getHighestPriorityLanes(pingedLanes); + /** + * In the future, we should cleanup callbacks by cancelling them instead of + * using this. + */ + function mountSafeCallback_NOT_REALLY_SAFE(context, callback) { + return function () { + if (!callback) { + return undefined; + } // This protects against createClass() components. + // We don't know if there is code depending on it. + // We intentionally don't use isMounted() because even accessing + // isMounted property on a React ES6 class will trigger a warning. + + if (typeof context.__isMounted === "boolean") { + if (!context.__isMounted) { + return undefined; + } + } // FIXME: there used to be other branches that protected + // against unmounted host components. But RN host components don't + // define isMounted() anymore, so those checks didn't do anything. + // They caused false positive warning noise so we removed them: + // https://github.com/facebook/react-native/issues/18868#issuecomment-413579095 + // However, this means that the callback is NOT guaranteed to be safe + // for host components. The solution we should implement is to make + // UIManager.measure() and similar calls truly cancelable. Then we + // can change our own code calling them to cancel when something unmounts. + + return callback.apply(context, arguments); + }; + } + function warnForStyleProps(props, validAttributes) { + { + for (var key in validAttributes.style) { + if (!(validAttributes[key] || props[key] === undefined)) { + error( + "You are setting the style `{ %s" + + ": ... }` as a prop. You " + + "should nest it in a style object. " + + "E.g. `{ style: { %s" + + ": ... } }`", + key, + key + ); + } + } } } - } - 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. + var ReactNativeFiberHostComponent = /*#__PURE__*/ (function () { + function ReactNativeFiberHostComponent( + tag, + viewConfig, + internalInstanceHandleDEV + ) { + this._nativeTag = tag; + this._children = []; + this.viewConfig = viewConfig; - 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); + { + this._internalFiberInstanceHandleDEV = internalInstanceHandleDEV; + } + } - 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 ((nextLanes & 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. - nextLanes |= pendingLanes & 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, like - // useMutableSource, we should ensure that there is no partial work at the - // time we apply the entanglement. - - var entangledLanes = root.entangledLanes; - - if (entangledLanes !== NoLanes) { - var entanglements = root.entanglements; - var lanes = nextLanes & entangledLanes; - - while (lanes > 0) { - var index = pickArbitraryLaneIndex(lanes); - var lane = 1 << index; - nextLanes |= entanglements[index]; - lanes &= ~lane; - } - } - - return nextLanes; -} -function getMostRecentEventTime(root, lanes) { - var eventTimes = root.eventTimes; - var mostRecentEventTime = NoTimestamp; + var _proto = ReactNativeFiberHostComponent.prototype; - while (lanes > 0) { - var index = pickArbitraryLaneIndex(lanes); - var lane = 1 << index; - var eventTime = eventTimes[index]; + _proto.blur = function blur() { + ReactNativePrivateInterface.TextInputState.blurTextInput(this); + }; - if (eventTime > mostRecentEventTime) { - mostRecentEventTime = eventTime; - } - - lanes &= ~lane; - } - - return mostRecentEventTime; -} - -function computeExpirationTime(lane, currentTime) { - switch (lane) { - 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: - case TransitionLane16: - return currentTime + 5000; - - case RetryLane1: - case RetryLane2: - case RetryLane3: - case RetryLane4: - case RetryLane5: - // 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: - // 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. - - var lanes = pendingLanes; - - 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); - } - } 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) { - var everythingButOffscreen = root.pendingLanes & ~OffscreenLane; - - if (everythingButOffscreen !== NoLanes) { - return everythingButOffscreen; - } - - if (everythingButOffscreen & OffscreenLane) { - return OffscreenLane; - } - - return NoLanes; -} -function includesSyncLane(lanes) { - return (lanes & SyncLane) !== NoLanes; -} -function includesNonIdleWork(lanes) { - return (lanes & NonIdleLanes) !== NoLanes; -} -function includesOnlyRetries(lanes) { - return (lanes & RetryLanes) === lanes; -} -function includesOnlyNonUrgentLanes(lanes) { - var UrgentLanes = SyncLane | InputContinuousLane | DefaultLane; - return (lanes & UrgentLanes) === NoLanes; -} -function includesOnlyTransitions(lanes) { - return (lanes & TransitionLanes) === lanes; -} -function includesBlockingLane(root, lanes) { - 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 ((nextRetryLane & RetryLanes) === NoLanes) { - nextRetryLane = RetryLane1; - } - - 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); -} - -function pickArbitraryLaneIndex(lanes) { - return 31 - clz32(lanes); -} + _proto.focus = function focus() { + ReactNativePrivateInterface.TextInputState.focusTextInput(this); + }; -function laneToIndex(lane) { - return pickArbitraryLaneIndex(lane); -} + _proto.measure = function measure(callback) { + ReactNativePrivateInterface.UIManager.measure( + this._nativeTag, + mountSafeCallback_NOT_REALLY_SAFE(this, callback) + ); + }; -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). + _proto.measureInWindow = function measureInWindow(callback) { + ReactNativePrivateInterface.UIManager.measureInWindow( + this._nativeTag, + mountSafeCallback_NOT_REALLY_SAFE(this, callback) + ); + }; -function laneToLanes(lane) { - return lane; -} -function createLaneMap(initial) { - // Intentionally pushing one by one. - // https://v8.dev/blog/elements-kinds#avoid-creating-holes - var laneMap = []; + _proto.measureLayout = function measureLayout( + relativeToNativeNode, + onSuccess, + onFail + ) /* currently unused */ { + var relativeNode; - for (var i = 0; i < TotalLanes; i++) { - laneMap.push(initial); - } + if (typeof relativeToNativeNode === "number") { + // Already a node handle + relativeNode = relativeToNativeNode; + } else { + var nativeNode = relativeToNativeNode; - return laneMap; -} -function markRootUpdated(root, updateLane, eventTime) { - 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; - } - - var eventTimes = root.eventTimes; - var index = laneToIndex(updateLane); // We can always overwrite an existing timestamp because we prefer the most - // recent event, and we assume time is monotonically increasing. - - eventTimes[index] = eventTime; -} -function markRootSuspended(root, suspendedLanes) { - 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; - } -} -function markRootPinged(root, pingedLanes, eventTime) { - root.pingedLanes |= root.suspendedLanes & pingedLanes; -} -function markRootFinished(root, remainingLanes) { - var noLongerPendingLanes = root.pendingLanes & ~remainingLanes; - root.pendingLanes = remainingLanes; // Let's try everything again - - root.suspendedLanes = NoLanes; - root.pingedLanes = NoLanes; - root.expiredLanes &= remainingLanes; - root.mutableReadLanes &= remainingLanes; - root.entangledLanes &= remainingLanes; - var entanglements = root.entanglements; - var eventTimes = root.eventTimes; - var expirationTimes = root.expirationTimes; // Clear the lanes that no longer have pending work - - var lanes = noLongerPendingLanes; - - while (lanes > 0) { - var index = pickArbitraryLaneIndex(lanes); - var lane = 1 << index; - entanglements[index] = NoLanes; - eventTimes[index] = NoTimestamp; - expirationTimes[index] = NoTimestamp; - lanes &= ~lane; - } -} -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 (nativeNode._nativeTag) { + relativeNode = nativeNode._nativeTag; + } + } - 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; - } + if (relativeNode == null) { + { + error( + "Warning: ref.measureLayout must be called with a node handle or a ref to a native component." + ); + } - lanes &= ~lane; - } -} -function getBumpedLaneForHydration(root, renderLanes) { - var renderLane = getHighestPriorityLane(renderLanes); - var lane; - - switch (renderLane) { - 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 TransitionLane16: - case RetryLane1: - case RetryLane2: - case RetryLane3: - case RetryLane4: - case RetryLane5: - 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; - } + return; + } - var pendingUpdatersLaneMap = root.pendingUpdatersLaneMap; - var memoizedUpdaters = root.memoizedUpdaters; + ReactNativePrivateInterface.UIManager.measureLayout( + this._nativeTag, + relativeNode, + mountSafeCallback_NOT_REALLY_SAFE(this, onFail), + mountSafeCallback_NOT_REALLY_SAFE(this, onSuccess) + ); + }; - while (lanes > 0) { - var index = laneToIndex(lanes); - var lane = 1 << index; - var updaters = pendingUpdatersLaneMap[index]; + _proto.setNativeProps = function setNativeProps(nativeProps) { + { + warnForStyleProps(nativeProps, this.viewConfig.validAttributes); + } - if (updaters.size > 0) { - updaters.forEach(function(fiber) { - var alternate = fiber.alternate; + var updatePayload = create(nativeProps, this.viewConfig.validAttributes); // Avoid the overhead of bridge calls if there's no update. + // This is an expensive no-op for Android, and causes an unnecessary + // view invalidation for certain components (eg RCTTextInput) on iOS. - if (alternate === null || !memoizedUpdaters.has(alternate)) { - memoizedUpdaters.add(fiber); + if (updatePayload != null) { + ReactNativePrivateInterface.UIManager.updateView( + this._nativeTag, + this.viewConfig.uiViewClassName, + updatePayload + ); } - }); - updaters.clear(); - } + }; - lanes &= ~lane; - } -} -function getTransitionsForLanes(root, lanes) { - { - return null; - } -} + return ReactNativeFiberHostComponent; + })(); // eslint-disable-next-line no-unused-expressions + + // This module only exists as an ESM wrapper around the external CommonJS + var scheduleCallback = Scheduler.unstable_scheduleCallback; + var cancelCallback = Scheduler.unstable_cancelCallback; + var shouldYield = Scheduler.unstable_shouldYield; + var requestPaint = Scheduler.unstable_requestPaint; + var now = Scheduler.unstable_now; + var ImmediatePriority = Scheduler.unstable_ImmediatePriority; + var UserBlockingPriority = Scheduler.unstable_UserBlockingPriority; + var NormalPriority = Scheduler.unstable_NormalPriority; + var IdlePriority = Scheduler.unstable_IdlePriority; + + var rendererID = null; + var injectedHook = 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 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); + var hook = __REACT_DEVTOOLS_GLOBAL_HOOK__; - if (!isHigherEventPriority(DiscreteEventPriority, lane)) { - return DiscreteEventPriority; - } + 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 (!isHigherEventPriority(ContinuousEventPriority, lane)) { - return ContinuousEventPriority; - } + 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://react.dev/link/react-devtools" + ); + } // DevTools exists, even though it doesn't support Fiber. - if (includesNonIdleWork(lane)) { - return DefaultEventPriority; - } + return true; + } - return IdleEventPriority; -} + 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 + }); + } -// Renderers that don't support hydration -// can re-export everything from this module. -function shim() { - 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; -var isSuspenseInstanceFallback = shim; -var getSuspenseInstanceFallbackErrorDetails = shim; -var registerSuspenseInstanceRetry = shim; -var hydrateTextInstance = shim; -var clearSuspenseBoundary = shim; -var clearSuspenseBoundaryFromContainer = shim; -var errorHydratingContainer = shim; - -var getViewConfigForType = - ReactNativePrivateInterface.ReactNativeViewConfigRegistry.get; -var UPDATE_SIGNAL = {}; - -{ - Object.freeze(UPDATE_SIGNAL); -} // Counter for uniquely identifying views. -// % 10 === 1 means it is a rootTag. -// % 2 === 0 means it is a Fabric tag. - -var nextReactTag = 3; - -function allocateTag() { - var tag = nextReactTag; - - if (tag % 10 === 1) { - tag += 2; - } - - nextReactTag = tag + 2; - return tag; -} + rendererID = hook.inject(internals); // We have successfully injected, so now it is safe to set up hooks. -function recursivelyUncacheFiberNode(node) { - if (typeof node === "number") { - // Leaf node (eg text) - uncacheFiberNode(node); - } else { - uncacheFiberNode(node._nativeTag); + injectedHook = hook; + } catch (err) { + // Catch all errors because it is unsafe to throw during initialization. + { + error("React instrumentation encountered an error: %s.", err); + } + } - node._children.forEach(recursivelyUncacheFiberNode); - } -} -function appendInitialChild(parentInstance, child) { - parentInstance._children.push(child); -} -function createInstance( - type, - props, - rootContainerInstance, - hostContext, - internalInstanceHandle -) { - var tag = allocateTag(); - var viewConfig = getViewConfigForType(type); - - { - for (var key in viewConfig.validAttributes) { - if (props.hasOwnProperty(key)) { - ReactNativePrivateInterface.deepFreezeAndThrowOnMutationInDev( - props[key] - ); + if (hook.checkDCE) { + // This is the real DevTools. + return true; + } else { + // This is likely a hook installed by Fast Refresh runtime. + return false; } } - } - - var updatePayload = create(props, viewConfig.validAttributes); - ReactNativePrivateInterface.UIManager.createView( - tag, // reactTag - viewConfig.uiViewClassName, // viewName - rootContainerInstance, // rootTag - updatePayload // props - ); - var component = new ReactNativeFiberHostComponent( - tag, - viewConfig, - internalInstanceHandle - ); - precacheFiberNode(internalInstanceHandle, tag); - updateFiberProps(tag, props); // Not sure how to avoid this cast. Flow is okay if the component is defined - // in the same file but if it's external it can't see the types. - - return component; -} -function createTextInstance( - text, - rootContainerInstance, - hostContext, - internalInstanceHandle -) { - if (!hostContext.isInAParentText) { - throw new Error("Text strings must be rendered within a component."); - } - - var tag = allocateTag(); - ReactNativePrivateInterface.UIManager.createView( - tag, // reactTag - "RCTRawText", // viewName - rootContainerInstance, // rootTag - { - text: text - } // props - ); - precacheFiberNode(internalInstanceHandle, tag); - return tag; -} -function finalizeInitialChildren( - parentInstance, - type, - props, - rootContainerInstance, - hostContext -) { - // Don't send a no-op message over the bridge. - if (parentInstance._children.length === 0) { - return false; - } // Map from child objects to native tags. - // Either way we need to pass a copy of the Array to prevent it from being frozen. - - var nativeTags = parentInstance._children.map(function(child) { - return typeof child === "number" - ? child // Leaf node (eg text) - : child._nativeTag; - }); - - ReactNativePrivateInterface.UIManager.setChildren( - parentInstance._nativeTag, // containerTag - nativeTags // reactTags - ); - return false; -} -function getRootHostContext(rootContainerInstance) { - return { - isInAParentText: false - }; -} -function getChildHostContext(parentHostContext, type, rootContainerInstance) { - var prevIsInAParentText = parentHostContext.isInAParentText; - var isInAParentText = - type === "AndroidTextInput" || // Android - type === "RCTMultilineTextInputView" || // iOS - type === "RCTSinglelineTextInputView" || // iOS - type === "RCTText" || - type === "RCTVirtualText"; - - if (prevIsInAParentText !== isInAParentText) { - return { - isInAParentText: isInAParentText - }; - } else { - return parentHostContext; - } -} -function getPublicInstance(instance) { - return instance; -} -function prepareForCommit(containerInfo) { - // Noop - return null; -} -function prepareUpdate( - instance, - type, - oldProps, - newProps, - rootContainerInstance, - hostContext -) { - return UPDATE_SIGNAL; -} -function resetAfterCommit(containerInfo) { - // Noop -} -var scheduleTimeout = setTimeout; -var cancelTimeout = clearTimeout; -var noTimeout = -1; -function shouldSetTextContent(type, props) { - // TODO (bvaughn) Revisit this decision. - // Always returning false simplifies the createInstance() implementation, - // But creates an additional child Fiber for raw text children. - // No additional native views are created though. - // It's not clear to me which is better so I'm deferring for now. - // More context @ github.com/facebook/react/pull/8560#discussion_r92111303 - return false; -} -function getCurrentEventPriority() { - return DefaultEventPriority; -} // ------------------- -function appendChild(parentInstance, child) { - var childTag = typeof child === "number" ? child : child._nativeTag; - var children = parentInstance._children; - var index = children.indexOf(child); - - if (index >= 0) { - children.splice(index, 1); - children.push(child); - ReactNativePrivateInterface.UIManager.manageChildren( - parentInstance._nativeTag, // containerTag - [index], // moveFromIndices - [children.length - 1], // moveToIndices - [], // addChildReactTags - [], // addAtIndices - [] // removeAtIndices - ); - } else { - children.push(child); - ReactNativePrivateInterface.UIManager.manageChildren( - parentInstance._nativeTag, // containerTag - [], // moveFromIndices - [], // moveToIndices - [childTag], // addChildReactTags - [children.length - 1], // addAtIndices - [] // removeAtIndices - ); - } -} -function appendChildToContainer(parentInstance, child) { - var childTag = typeof child === "number" ? child : child._nativeTag; - ReactNativePrivateInterface.UIManager.setChildren( - parentInstance, // containerTag - [childTag] // reactTags - ); -} -function commitTextUpdate(textInstance, oldText, newText) { - ReactNativePrivateInterface.UIManager.updateView( - textInstance, // reactTag - "RCTRawText", // viewName - { - text: newText - } // props - ); -} -function commitUpdate( - instance, - updatePayloadTODO, - type, - oldProps, - newProps, - internalInstanceHandle -) { - var viewConfig = instance.viewConfig; - updateFiberProps(instance._nativeTag, newProps); - var updatePayload = diff(oldProps, newProps, viewConfig.validAttributes); // Avoid the overhead of bridge calls if there's no update. - // This is an expensive no-op for Android, and causes an unnecessary - // view invalidation for certain components (eg RCTTextInput) on iOS. - - if (updatePayload != null) { - ReactNativePrivateInterface.UIManager.updateView( - instance._nativeTag, // reactTag - viewConfig.uiViewClassName, // viewName - updatePayload // props - ); - } -} -function insertBefore(parentInstance, child, beforeChild) { - var children = parentInstance._children; - var index = children.indexOf(child); // Move existing child or add new child? - - if (index >= 0) { - children.splice(index, 1); - var beforeChildIndex = children.indexOf(beforeChild); - children.splice(beforeChildIndex, 0, child); - ReactNativePrivateInterface.UIManager.manageChildren( - parentInstance._nativeTag, // containerID - [index], // moveFromIndices - [beforeChildIndex], // moveToIndices - [], // addChildReactTags - [], // addAtIndices - [] // removeAtIndices - ); - } else { - var _beforeChildIndex = children.indexOf(beforeChild); - - children.splice(_beforeChildIndex, 0, child); - var childTag = typeof child === "number" ? child : child._nativeTag; - ReactNativePrivateInterface.UIManager.manageChildren( - parentInstance._nativeTag, // containerID - [], // moveFromIndices - [], // moveToIndices - [childTag], // addChildReactTags - [_beforeChildIndex], // addAtIndices - [] // removeAtIndices - ); - } -} -function insertInContainerBefore(parentInstance, child, beforeChild) { - // TODO (bvaughn): Remove this check when... - // We create a wrapper object for the container in ReactNative render() - // Or we refactor to remove wrapper objects entirely. - // For more info on pros/cons see PR #8560 description. - if (typeof parentInstance === "number") { - throw new Error("Container does not support insertBefore operation"); - } -} -function removeChild(parentInstance, child) { - recursivelyUncacheFiberNode(child); - var children = parentInstance._children; - var index = children.indexOf(child); - children.splice(index, 1); - ReactNativePrivateInterface.UIManager.manageChildren( - parentInstance._nativeTag, // containerID - [], // moveFromIndices - [], // moveToIndices - [], // addChildReactTags - [], // addAtIndices - [index] // removeAtIndices - ); -} -function removeChildFromContainer(parentInstance, child) { - recursivelyUncacheFiberNode(child); - ReactNativePrivateInterface.UIManager.manageChildren( - parentInstance, // containerID - [], // moveFromIndices - [], // moveToIndices - [], // addChildReactTags - [], // addAtIndices - [0] // removeAtIndices - ); -} -function resetTextContent(instance) { - // Noop -} -function hideInstance(instance) { - var viewConfig = instance.viewConfig; - var updatePayload = create( - { - style: { - display: "none" - } - }, - viewConfig.validAttributes - ); - ReactNativePrivateInterface.UIManager.updateView( - instance._nativeTag, - viewConfig.uiViewClassName, - updatePayload - ); -} -function hideTextInstance(textInstance) { - throw new Error("Not yet implemented."); -} -function unhideInstance(instance, props) { - var viewConfig = instance.viewConfig; - var updatePayload = diff( - assign({}, props, { - style: [ - props.style, - { - display: "none" - } - ] - }), - props, - viewConfig.validAttributes - ); - ReactNativePrivateInterface.UIManager.updateView( - instance._nativeTag, - viewConfig.uiViewClassName, - updatePayload - ); -} -function clearContainer(container) { - // TODO Implement this for React Native - // UIManager does not expose a "remove all" type method. -} -function unhideTextInstance(textInstance, text) { - throw new Error("Not yet implemented."); -} -function preparePortalMount(portalInstance) { - // noop -} - -var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher; -function describeBuiltInComponentFrame(name, source, ownerFn) { - { - var ownerName = null; + function onScheduleRoot(root, children) { + { + if ( + injectedHook && + typeof injectedHook.onScheduleFiberRoot === "function" + ) { + try { + injectedHook.onScheduleFiberRoot(rendererID, root, children); + } catch (err) { + if (!hasLoggedError) { + hasLoggedError = true; - if (ownerFn) { - ownerName = ownerFn.displayName || ownerFn.name || null; + error("React instrumentation encountered an error: %s", err); + } + } + } + } } + function onCommitRoot(root, eventPriority) { + if (injectedHook && typeof injectedHook.onCommitFiberRoot === "function") { + try { + var didError = (root.current.flags & DidCapture) === DidCapture; - return describeComponentFrame(name, source, ownerName); - } -} -var componentFrameCache; + if (enableProfilerTimer) { + var schedulerPriority; -{ - var PossiblyWeakMap = typeof WeakMap === "function" ? WeakMap : Map; - componentFrameCache = new PossiblyWeakMap(); -} -var BEFORE_SLASH_RE = /^(.*)[\\\/]/; + switch (eventPriority) { + case DiscreteEventPriority: + schedulerPriority = ImmediatePriority; + break; + + case ContinuousEventPriority: + schedulerPriority = UserBlockingPriority; + break; -function describeComponentFrame(name, source, ownerName) { - var sourceInfo = ""; + case DefaultEventPriority: + schedulerPriority = NormalPriority; + break; - if (source) { - var path = source.fileName; - var fileName = path.replace(BEFORE_SLASH_RE, ""); // In DEV, include code for a common special case: - // prefer "folder/index.js" instead of just "index.js". + case IdleEventPriority: + schedulerPriority = IdlePriority; + break; - if (/^index\./.test(fileName)) { - var match = path.match(BEFORE_SLASH_RE); + default: + schedulerPriority = NormalPriority; + break; + } - if (match) { - var pathBeforeSlash = match[1]; + injectedHook.onCommitFiberRoot( + rendererID, + root, + schedulerPriority, + didError + ); + } else { + injectedHook.onCommitFiberRoot(rendererID, root, undefined, didError); + } + } catch (err) { + { + if (!hasLoggedError) { + hasLoggedError = true; - if (pathBeforeSlash) { - var folderName = pathBeforeSlash.replace(BEFORE_SLASH_RE, ""); - fileName = folderName + "/" + fileName; + 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; - sourceInfo = " (at " + fileName + ":" + source.lineNumber + ")"; - } else if (ownerName) { - sourceInfo = " (created by " + ownerName + ")"; - } - - return "\n in " + (name || "Unknown") + sourceInfo; -} - -function describeClassComponentFrame(ctor, source, ownerFn) { - { - return describeFunctionComponentFrame(ctor, source, ownerFn); - } -} -function describeFunctionComponentFrame(fn, source, ownerFn) { - { - if (!fn) { - return ""; + 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; - var name = fn.displayName || fn.name || null; - var ownerName = null; - - if (ownerFn) { - ownerName = ownerFn.displayName || ownerFn.name || null; + error("React instrumentation encountered an error: %s", err); + } + } + } + } } - return describeComponentFrame(name, source, ownerName); - } -} - -function describeUnknownElementTypeFrameInDEV(type, source, ownerFn) { - if (type == null) { - return ""; - } + function injectProfilingHooks(profilingHooks) { } - if (typeof type === "function") { - { - return describeFunctionComponentFrame(type, source, ownerFn); + function getLaneLabelMap() { + { + return null; + } } - } - - if (typeof type === "string") { - return describeBuiltInComponentFrame(type, source, ownerFn); - } - - switch (type) { - case REACT_SUSPENSE_TYPE: - return describeBuiltInComponentFrame("Suspense", source, ownerFn); - - case REACT_SUSPENSE_LIST_TYPE: - return describeBuiltInComponentFrame("SuspenseList", source, ownerFn); - } - - if (typeof type === "object") { - switch (type.$$typeof) { - case REACT_FORWARD_REF_TYPE: - return describeFunctionComponentFrame(type.render, source, ownerFn); - - 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; + function markComponentRenderStopped() { } + function markComponentErrored(fiber, thrownValue, lanes) { } + function markComponentSuspended(fiber, wakeable, lanes) { } + + var NoMode = + /* */ + 0; // TODO: Remove ConcurrentMode by reading from the root tag instead + + var ConcurrentMode = + /* */ + 1; + var ProfileMode = + /* */ + 2; + var StrictLegacyMode = + /* */ + 8; + + // 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 = Math.log; + var LN2 = Math.LN2; + + function clz32Fallback(x) { + var asUint = x >>> 0; + + if (asUint === 0) { + return 32; + } + + return (31 - ((log(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 SyncLane = + /* */ + 1; + var InputContinuousHydrationLane = + /* */ + 2; + var InputContinuousLane = + /* */ + 4; + var DefaultHydrationLane = + /* */ + 8; + var DefaultLane = + /* */ + 16; + var TransitionHydrationLane = + /* */ + 32; + var TransitionLanes = + /* */ + 4194240; + var TransitionLane1 = + /* */ + 64; + var TransitionLane2 = + /* */ + 128; + var TransitionLane3 = + /* */ + 256; + var TransitionLane4 = + /* */ + 512; + var TransitionLane5 = + /* */ + 1024; + var TransitionLane6 = + /* */ + 2048; + var TransitionLane7 = + /* */ + 4096; + var TransitionLane8 = + /* */ + 8192; + var TransitionLane9 = + /* */ + 16384; + var TransitionLane10 = + /* */ + 32768; + var TransitionLane11 = + /* */ + 65536; + var TransitionLane12 = + /* */ + 131072; + var TransitionLane13 = + /* */ + 262144; + var TransitionLane14 = + /* */ + 524288; + var TransitionLane15 = + /* */ + 1048576; + var TransitionLane16 = + /* */ + 2097152; + var RetryLanes = + /* */ + 130023424; + var RetryLane1 = + /* */ + 4194304; + var RetryLane2 = + /* */ + 8388608; + var RetryLane3 = + /* */ + 16777216; + var RetryLane4 = + /* */ + 33554432; + var RetryLane5 = + /* */ + 67108864; + var SomeRetryLane = RetryLane1; + var SelectiveHydrationLane = + /* */ + 134217728; + var NonIdleLanes = + /* */ + 268435455; + var IdleHydrationLane = + /* */ + 268435456; + var IdleLane = + /* */ + 536870912; + var OffscreenLane = + /* */ + 1073741824; // This function is used for the experimental timeline (react-devtools-timeline) + var NoTimestamp = -1; + var nextTransitionLane = TransitionLane1; + var nextRetryLane = RetryLane1; + + function getHighestPriorityLanes(lanes) { + switch (getHighestPriorityLane(lanes)) { + 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: + case TransitionLane16: + return lanes & TransitionLanes; + + case RetryLane1: + case RetryLane2: + case RetryLane3: + case RetryLane4: + case RetryLane5: + return lanes & RetryLanes; + + case SelectiveHydrationLane: + return SelectiveHydrationLane; + + case IdleHydrationLane: + return IdleHydrationLane; + + case IdleLane: + return IdleLane; + + case OffscreenLane: + return OffscreenLane; + + 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. - try { - // Lazy may contain any component type so we recursively resolve it. - return describeUnknownElementTypeFrameInDEV( - init(payload), - source, - ownerFn - ); - } catch (x) {} + return lanes; } } - } - return ""; -} + function getNextLanes(root, wipLanes) { + // Early bailout if there's no pending work left. + var pendingLanes = root.pendingLanes; -var hasOwnProperty = Object.prototype.hasOwnProperty; + if (pendingLanes === NoLanes) { + return NoLanes; + } -var loggedTypeFailures = {}; -var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; + 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. -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); - } - } -} + var nonIdlePendingLanes = pendingLanes & NonIdleLanes; -function checkPropTypes(typeSpecs, values, location, componentName, element) { - { - // $FlowFixMe This is okay but Flow doesn't know it. - var has = Function.call.bind(hasOwnProperty); + if (nonIdlePendingLanes !== NoLanes) { + var nonIdleUnblockedLanes = nonIdlePendingLanes & ~suspendedLanes; - 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 (nonIdleUnblockedLanes !== NoLanes) { + nextLanes = getHighestPriorityLanes(nonIdleUnblockedLanes); + } else { + var nonIdlePingedLanes = nonIdlePendingLanes & pingedLanes; - 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 (nonIdlePingedLanes !== NoLanes) { + nextLanes = getHighestPriorityLanes(nonIdlePingedLanes); } - - error$1 = typeSpecs[typeSpecName]( - values, - typeSpecName, - componentName, - location, - null, - "SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED" - ); - } catch (ex) { - error$1 = ex; } + } else { + // The only remaining work is Idle. + var unblockedLanes = pendingLanes & ~suspendedLanes; - if (error$1 && !(error$1 instanceof Error)) { - setCurrentlyValidatingElement(element); + if (unblockedLanes !== NoLanes) { + nextLanes = getHighestPriorityLanes(unblockedLanes); + } else { + if (pingedLanes !== NoLanes) { + nextLanes = getHighestPriorityLanes(pingedLanes); + } + } + } - 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 (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. - setCurrentlyValidatingElement(null); - } + 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 ( - error$1 instanceof Error && - !(error$1.message in loggedTypeFailures) + // 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) ) { - // Only monitor this failure once because there tends to be a lot of the - // same error. - loggedTypeFailures[error$1.message] = true; - setCurrentlyValidatingElement(element); - - error("Failed %s type: %s", location, error$1.message); - - setCurrentlyValidatingElement(null); + // Keep working on the existing in-progress tree. Do not interrupt. + return wipLanes; } } - } - } -} - -var valueStack = []; -var fiberStack; -{ - fiberStack = []; -} - -var index = -1; + if ((nextLanes & 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. + nextLanes |= pendingLanes & 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, like + // useMutableSource, we should ensure that there is no partial work at the + // time we apply the entanglement. -function createCursor(defaultValue) { - return { - current: defaultValue - }; -} + var entangledLanes = root.entangledLanes; -function pop(cursor, fiber) { - if (index < 0) { - { - error("Unexpected pop."); - } + if (entangledLanes !== NoLanes) { + var entanglements = root.entanglements; + var lanes = nextLanes & entangledLanes; - return; - } + while (lanes > 0) { + var index = pickArbitraryLaneIndex(lanes); + var lane = 1 << index; + nextLanes |= entanglements[index]; + lanes &= ~lane; + } + } - { - if (fiber !== fiberStack[index]) { - error("Unexpected Fiber popped."); + return nextLanes; } - } + function getMostRecentEventTime(root, lanes) { + var eventTimes = root.eventTimes; + var mostRecentEventTime = NoTimestamp; - cursor.current = valueStack[index]; - valueStack[index] = null; + while (lanes > 0) { + var index = pickArbitraryLaneIndex(lanes); + var lane = 1 << index; + var eventTime = eventTimes[index]; - { - fiberStack[index] = null; - } + if (eventTime > mostRecentEventTime) { + mostRecentEventTime = eventTime; + } - index--; -} + lanes &= ~lane; + } -function push(cursor, value, fiber) { - index++; - valueStack[index] = cursor.current; + return mostRecentEventTime; + } - { - fiberStack[index] = fiber; - } + function computeExpirationTime(lane, currentTime) { + switch (lane) { + 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: + case TransitionLane16: + return currentTime + 5000; + + case RetryLane1: + case RetryLane2: + case RetryLane3: + case RetryLane4: + case RetryLane5: + // 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: + // Anything idle priority or lower should never expire. + return NoTimestamp; + + default: + { + error("Should have found matching lanes. This is a bug in React."); + } - cursor.current = value; -} + return NoTimestamp; + } + } -var warnedAboutMissingGetChildContext; + 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. -{ - warnedAboutMissingGetChildContext = {}; -} + var lanes = pendingLanes; -var emptyContextObject = {}; + while (lanes > 0) { + var index = pickArbitraryLaneIndex(lanes); + var lane = 1 << index; + var expirationTime = expirationTimes[index]; -{ - Object.freeze(emptyContextObject); -} // A cursor to the current merged context object on the stack. + 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; + } -var contextStackCursor = createCursor(emptyContextObject); // A cursor to a boolean indicating whether the context has changed. + lanes &= ~lane; + } + } // This returns the highest priority pending lanes regardless of whether they + function getLanesToRetrySynchronouslyOnError(root) { + var everythingButOffscreen = root.pendingLanes & ~OffscreenLane; -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. + if (everythingButOffscreen !== NoLanes) { + return everythingButOffscreen; + } -var previousContext = emptyContextObject; + if (everythingButOffscreen & OffscreenLane) { + return OffscreenLane; + } -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 NoLanes; } - - return contextStackCursor.current; - } -} - -function cacheContext(workInProgress, unmaskedContext, maskedContext) { - { - var instance = workInProgress.stateNode; - instance.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext; - instance.__reactInternalMemoizedMaskedChildContext = maskedContext; - } -} - -function getMaskedContext(workInProgress, unmaskedContext) { - { - var type = workInProgress.type; - var contextTypes = type.contextTypes; - - 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. - - var instance = workInProgress.stateNode; - - if ( - instance && - instance.__reactInternalMemoizedUnmaskedChildContext === unmaskedContext - ) { - return instance.__reactInternalMemoizedMaskedChildContext; + function includesSyncLane(lanes) { + return (lanes & SyncLane) !== NoLanes; } - - var context = {}; - - for (var key in contextTypes) { - context[key] = unmaskedContext[key]; + function includesNonIdleWork(lanes) { + return (lanes & NonIdleLanes) !== NoLanes; } - - { - 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. - - if (instance) { - cacheContext(workInProgress, unmaskedContext, context); + function includesOnlyRetries(lanes) { + return (lanes & RetryLanes) === lanes; } - - return context; - } -} - -function hasContextChanged() { - { - return didPerformWorkStackCursor.current; - } -} - -function isContextProvider(type) { - { - var childContextTypes = type.childContextTypes; - return childContextTypes !== null && childContextTypes !== undefined; - } -} - -function popContext(fiber) { - { - pop(didPerformWorkStackCursor, fiber); - pop(contextStackCursor, fiber); - } -} - -function popTopLevelContextObject(fiber) { - { - pop(didPerformWorkStackCursor, fiber); - pop(contextStackCursor, fiber); - } -} - -function pushTopLevelContextObject(fiber, context, didChange) { - { - if (contextStackCursor.current !== emptyContextObject) { - throw new Error( - "Unexpected context found on stack. " + - "This error is likely caused by a bug in React. Please file an issue." - ); + function includesOnlyNonUrgentLanes(lanes) { + var UrgentLanes = SyncLane | InputContinuousLane | DefaultLane; + return (lanes & UrgentLanes) === NoLanes; } + function includesOnlyTransitions(lanes) { + return (lanes & TransitionLanes) === lanes; + } + function includesBlockingLane(root, lanes) { + 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; - push(contextStackCursor, context, fiber); - push(didPerformWorkStackCursor, didChange, fiber); - } -} - -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 (typeof instance.getChildContext !== "function") { - { - var componentName = getComponentNameFromFiber(fiber) || "Unknown"; - - if (!warnedAboutMissingGetChildContext[componentName]) { - warnedAboutMissingGetChildContext[componentName] = true; - - 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 ((nextTransitionLane & TransitionLanes) === NoLanes) { + nextTransitionLane = TransitionLane1; } - return parentContext; + return lane; } + function claimNextRetryLane() { + var lane = nextRetryLane; + nextRetryLane <<= 1; - var childContext = instance.getChildContext(); - - for (var contextKey in childContext) { - if (!(contextKey in childContextTypes)) { - throw new Error( - (getComponentNameFromFiber(fiber) || "Unknown") + - '.getChildContext(): key "' + - contextKey + - '" is not defined in childContextTypes.' - ); + if ((nextRetryLane & RetryLanes) === NoLanes) { + nextRetryLane = RetryLane1; } - } - { - var name = getComponentNameFromFiber(fiber) || "Unknown"; - checkPropTypes(childContextTypes, childContext, "child context", name); + return lane; } - - return assign({}, parentContext, childContext); - } -} - -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.current; - push(contextStackCursor, memoizedMergedChildContext, workInProgress); - push( - didPerformWorkStackCursor, - didPerformWorkStackCursor.current, - workInProgress - ); - return true; - } -} - -function invalidateContextProvider(workInProgress, type, didChange) { - { - var instance = workInProgress.stateNode; - - 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." - ); + function getHighestPriorityLane(lanes) { + return lanes & -lanes; } - - 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. - - pop(didPerformWorkStackCursor, workInProgress); - pop(contextStackCursor, workInProgress); // Now push the new context and mark that it has changed. - - push(contextStackCursor, mergedContext, workInProgress); - push(didPerformWorkStackCursor, didChange, workInProgress); - } else { - pop(didPerformWorkStackCursor, workInProgress); - push(didPerformWorkStackCursor, didChange, workInProgress); + 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); } - } -} -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 pickArbitraryLaneIndex(lanes) { + return 31 - clz32(lanes); } - var node = fiber; - - do { - switch (node.tag) { - case HostRoot: - return node.stateNode.context; + function laneToIndex(lane) { + return pickArbitraryLaneIndex(lane); + } - case ClassComponent: { - var Component = node.type; + 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 (isContextProvider(Component)) { - return node.stateNode.__reactInternalMemoizedMergedChildContext; - } + function laneToLanes(lane) { + return lane; + } + function createLaneMap(initial) { + // Intentionally pushing one by one. + // https://v8.dev/blog/elements-kinds#avoid-creating-holes + var laneMap = []; - break; - } + for (var i = 0; i < TotalLanes; i++) { + laneMap.push(initial); } - 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." - ); - } -} - -var LegacyRoot = 0; -var ConcurrentRoot = 1; - -/** - * 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; - -var syncQueue = null; -var includesLegacySyncCallbacks = false; -var isFlushingSyncQueue = false; -function scheduleSyncCallback(callback) { - // Push this callback into an internal queue. We'll flush these either in - // the next tick, or earlier if something calls `flushSyncCallbackQueue`. - if (syncQueue === null) { - syncQueue = [callback]; - } else { - // Push onto existing queue. Don't need to schedule a callback because - // we already scheduled one when we created the queue. - syncQueue.push(callback); - } -} -function scheduleLegacySyncCallback(callback) { - includesLegacySyncCallbacks = true; - scheduleSyncCallback(callback); -} -function flushSyncCallbacksOnlyInLegacyMode() { - // Only flushes the queue if there's a legacy sync callback scheduled. - // TODO: There's only a single type of callback: performSyncOnWorkOnRoot. So - // it might make more sense for the queue to be a list of roots instead of a - // list of generic callbacks. Then we can have two: one for legacy roots, one - // for concurrent roots. And this method would only flush the legacy ones. - if (includesLegacySyncCallbacks) { - flushSyncCallbacks(); - } -} -function flushSyncCallbacks() { - if (!isFlushingSyncQueue && syncQueue !== null) { - // Prevent re-entrance. - isFlushingSyncQueue = true; - var i = 0; - var previousUpdatePriority = getCurrentUpdatePriority(); - - try { - var isSync = true; - var queue = syncQueue; // TODO: Is this necessary anymore? The only user code that runs in this - // queue is in the render or commit phases. - - setCurrentUpdatePriority(DiscreteEventPriority); - - for (; i < queue.length; i++) { - var callback = queue[i]; + return laneMap; + } + function markRootUpdated(root, updateLane, eventTime) { + 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. - do { - callback = callback(isSync); - } while (callback !== null); + if (updateLane !== IdleLane) { + root.suspendedLanes = NoLanes; + root.pingedLanes = NoLanes; } - syncQueue = null; - includesLegacySyncCallbacks = false; - } catch (error) { - // If something throws, leave the remaining callbacks on the queue. - if (syncQueue !== null) { - syncQueue = syncQueue.slice(i + 1); - } // Resume flushing in the next tick + var eventTimes = root.eventTimes; + var index = laneToIndex(updateLane); // We can always overwrite an existing timestamp because we prefer the most + // recent event, and we assume time is monotonically increasing. - scheduleCallback(ImmediatePriority, flushSyncCallbacks); - throw error; - } finally { - setCurrentUpdatePriority(previousUpdatePriority); - isFlushingSyncQueue = false; + eventTimes[index] = eventTime; } - } - - 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; -} - -// TODO: Use the unified fiber stack module instead of this local one? -// Intentionally not using it yet to derisk the initial implementation, because -// the way we push/pop these values is a bit unusual. If there's a mistake, I'd -// rather the ids be wrong than crash the whole reconciler. -var forkStack = []; -var forkStackIndex = 0; -var treeForkProvider = null; -var treeForkCount = 0; -var idStack = []; -var idStackIndex = 0; -var treeContextProvider = null; -var treeContextId = 1; -var treeContextOverflow = ""; - -function popTreeContext(workInProgress) { - // Restore the previous values. - // This is a bit more complicated than other context-like modules in Fiber - // because the same Fiber may appear on the stack multiple times and for - // different reasons. We have to keep popping until the work-in-progress is - // no longer at the top of the stack. - while (workInProgress === treeForkProvider) { - treeForkProvider = forkStack[--forkStackIndex]; - forkStack[forkStackIndex] = null; - treeForkCount = forkStack[--forkStackIndex]; - forkStack[forkStackIndex] = null; - } - - while (workInProgress === treeContextProvider) { - treeContextProvider = idStack[--idStackIndex]; - idStack[idStackIndex] = null; - treeContextOverflow = idStack[--idStackIndex]; - idStack[idStackIndex] = null; - treeContextId = idStack[--idStackIndex]; - idStack[idStackIndex] = null; - } -} - -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 didSuspendOrErrorDEV = false; // Hydration errors that were thrown inside this boundary - -var hydrationErrors = null; -function didSuspendOrErrorWhileHydratingDEV() { - { - return didSuspendOrErrorDEV; - } -} - -function reenterHydrationStateFromDehydratedSuspenseInstance( - fiber, - suspenseInstance, - treeContext -) { - { - return false; - } -} - -function prepareToHydrateHostInstance( - fiber, - rootContainerInstance, - hostContext -) { - { - throw new Error( - "Expected prepareToHydrateHostInstance() to never be called. " + - "This error is likely caused by a bug in React. Please file an issue." - ); - } -} - -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 shouldUpdate = hydrateTextInstance(); -} - -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." - ); - } -} - -function popHydrationState(fiber) { - { - return false; - } -} - -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; - } -} - -function getIsHydrating() { - return isHydrating; -} - -function queueHydrationError(error) { - if (hydrationErrors === null) { - hydrationErrors = [error]; - } else { - hydrationErrors.push(error); - } -} - -var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig; -var NoTransition = null; -function requestCurrentTransition() { - return ReactCurrentBatchConfig.transition; -} - -/** - * 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 markRootSuspended(root, suspendedLanes) { + root.suspendedLanes |= suspendedLanes; + root.pingedLanes &= ~suspendedLanes; // The suspended lanes are no longer CPU-bound. Clear their expiration times. - var keysA = Object.keys(objA); - var keysB = Object.keys(objB); + var expirationTimes = root.expirationTimes; + var lanes = suspendedLanes; - if (keysA.length !== keysB.length) { - return false; - } // Test for A's keys different from B. - - for (var i = 0; i < keysA.length; i++) { - var currentKey = keysA[i]; - - if ( - !hasOwnProperty.call(objB, currentKey) || - !objectIs(objA[currentKey], objB[currentKey]) - ) { - return false; + while (lanes > 0) { + var index = pickArbitraryLaneIndex(lanes); + var lane = 1 << index; + expirationTimes[index] = NoTimestamp; + lanes &= ~lane; + } } - } - - return true; -} - -function describeFiber(fiber) { - var owner = fiber._debugOwner ? fiber._debugOwner.type : null; - var source = fiber._debugSource; - - switch (fiber.tag) { - case HostComponent: - return describeBuiltInComponentFrame(fiber.type, source, owner); - - case LazyComponent: - return describeBuiltInComponentFrame("Lazy", source, owner); - - case SuspenseComponent: - return describeBuiltInComponentFrame("Suspense", source, owner); - - case SuspenseListComponent: - return describeBuiltInComponentFrame("SuspenseList", source, owner); - - case FunctionComponent: - case IndeterminateComponent: - case SimpleMemoComponent: - return describeFunctionComponentFrame(fiber.type, source, owner); - - case ForwardRef: - return describeFunctionComponentFrame(fiber.type.render, source, owner); + function markRootPinged(root, pingedLanes, eventTime) { + root.pingedLanes |= root.suspendedLanes & pingedLanes; + } + function markRootFinished(root, remainingLanes) { + var noLongerPendingLanes = root.pendingLanes & ~remainingLanes; + root.pendingLanes = remainingLanes; // Let's try everything again - case ClassComponent: - return describeClassComponentFrame(fiber.type, source, owner); + root.suspendedLanes = NoLanes; + root.pingedLanes = NoLanes; + root.expiredLanes &= remainingLanes; + root.mutableReadLanes &= remainingLanes; + root.entangledLanes &= remainingLanes; + var entanglements = root.entanglements; + var eventTimes = root.eventTimes; + var expirationTimes = root.expirationTimes; // Clear the lanes that no longer have pending work - default: - return ""; - } -} + var lanes = noLongerPendingLanes; -function getStackByFiberInDevAndProd(workInProgress) { - try { - var info = ""; - var node = workInProgress; + while (lanes > 0) { + var index = pickArbitraryLaneIndex(lanes); + var lane = 1 << index; + entanglements[index] = NoLanes; + eventTimes[index] = NoTimestamp; + expirationTimes[index] = NoTimestamp; + lanes &= ~lane; + } + } + 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; - do { - info += describeFiber(node); - node = node.return; - } while (node); + while (lanes) { + var index = pickArbitraryLaneIndex(lanes); + var lane = 1 << index; - return info; - } catch (x) { - return "\nError generating stack: " + x.message + "\n" + x.stack; - } -} + 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; + } -var ReactDebugCurrentFrame$1 = ReactSharedInternals.ReactDebugCurrentFrame; -var current = null; -var isRendering = false; -function getCurrentFiberOwnerNameInDevOrNull() { - { - if (current === null) { - return null; + lanes &= ~lane; + } } + function getBumpedLaneForHydration(root, renderLanes) { + var renderLane = getHighestPriorityLane(renderLanes); + var lane; - var owner = current._debugOwner; + switch (renderLane) { + case InputContinuousLane: + lane = InputContinuousHydrationLane; + break; - if (owner !== null && typeof owner !== "undefined") { - return getComponentNameFromFiber(owner); - } - } + case DefaultLane: + lane = DefaultHydrationLane; + break; - return null; -} + 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 TransitionLane16: + case RetryLane1: + case RetryLane2: + case RetryLane3: + case RetryLane4: + case RetryLane5: + lane = TransitionHydrationLane; + break; -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. + case IdleLane: + lane = IdleHydrationLane; + break; - return getStackByFiberInDevAndProd(current); - } -} + 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 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 ((lane & (root.suspendedLanes | renderLanes)) !== NoLane) { + // Give up trying to hydrate and fall back to client render. + return NoLane; + } -var ReactStrictModeWarnings = { - recordUnsafeLifecycleWarnings: function(fiber, instance) {}, - flushPendingUnsafeLifecycleWarnings: function() {}, - recordLegacyContextWarning: function(fiber, instance) {}, - flushLegacyContextWarning: function() {}, - discardPendingWarnings: function() {} -}; + return lane; + } + function addFiberToLanesMap(root, fiber, lanes) { + if (!isDevToolsPresent) { + return; + } -{ - var findStrictRoot = function(fiber) { - var maybeStrictRoot = null; - var node = fiber; + var pendingUpdatersLaneMap = root.pendingUpdatersLaneMap; - while (node !== null) { - if (node.mode & StrictLegacyMode) { - maybeStrictRoot = node; + while (lanes > 0) { + var index = laneToIndex(lanes); + var lane = 1 << index; + var updaters = pendingUpdatersLaneMap[index]; + updaters.add(fiber); + lanes &= ~lane; } - - node = node.return; } + function movePendingFibersToMemoized(root, lanes) { + if (!isDevToolsPresent) { + return; + } - return maybeStrictRoot; - }; + var pendingUpdatersLaneMap = root.pendingUpdatersLaneMap; + var memoizedUpdaters = root.memoizedUpdaters; - var setToSortedString = function(set) { - var array = []; - set.forEach(function(value) { - array.push(value); - }); - return array.sort().join(", "); - }; + while (lanes > 0) { + var index = laneToIndex(lanes); + var lane = 1 << index; + var updaters = pendingUpdatersLaneMap[index]; - var pendingComponentWillMountWarnings = []; - var pendingUNSAFE_ComponentWillMountWarnings = []; - var pendingComponentWillReceivePropsWarnings = []; - var pendingUNSAFE_ComponentWillReceivePropsWarnings = []; - var pendingComponentWillUpdateWarnings = []; - var pendingUNSAFE_ComponentWillUpdateWarnings = []; // Tracks components we have already warned about. + if (updaters.size > 0) { + updaters.forEach(function (fiber) { + var alternate = fiber.alternate; - var didWarnAboutUnsafeLifecycles = new Set(); + if (alternate === null || !memoizedUpdaters.has(alternate)) { + memoizedUpdaters.add(fiber); + } + }); + updaters.clear(); + } - ReactStrictModeWarnings.recordUnsafeLifecycleWarnings = function( - fiber, - instance - ) { - // Dedupe strategy: Warn once per component. - if (didWarnAboutUnsafeLifecycles.has(fiber.type)) { - return; + lanes &= ~lane; + } } - - if ( - typeof instance.componentWillMount === "function" && // Don't warn about react-lifecycles-compat polyfilled components. - instance.componentWillMount.__suppressDeprecationWarning !== true - ) { - pendingComponentWillMountWarnings.push(fiber); + function getTransitionsForLanes(root, lanes) { + { + return null; + } } - if ( - fiber.mode & StrictLegacyMode && - typeof instance.UNSAFE_componentWillMount === "function" - ) { - pendingUNSAFE_ComponentWillMountWarnings.push(fiber); + var DiscreteEventPriority = SyncLane; + var ContinuousEventPriority = InputContinuousLane; + var DefaultEventPriority = DefaultLane; + var IdleEventPriority = IdleLane; + var currentUpdatePriority = NoLane; + function getCurrentUpdatePriority() { + return currentUpdatePriority; } - - if ( - typeof instance.componentWillReceiveProps === "function" && - instance.componentWillReceiveProps.__suppressDeprecationWarning !== true - ) { - pendingComponentWillReceivePropsWarnings.push(fiber); + function setCurrentUpdatePriority(newPriority) { + currentUpdatePriority = newPriority; } - - if ( - fiber.mode & StrictLegacyMode && - typeof instance.UNSAFE_componentWillReceiveProps === "function" - ) { - pendingUNSAFE_ComponentWillReceivePropsWarnings.push(fiber); + function higherEventPriority(a, b) { + return a !== 0 && a < b ? a : b; } - - if ( - typeof instance.componentWillUpdate === "function" && - instance.componentWillUpdate.__suppressDeprecationWarning !== true - ) { - pendingComponentWillUpdateWarnings.push(fiber); + function lowerEventPriority(a, b) { + return a === 0 || a > b ? a : b; } - - if ( - fiber.mode & StrictLegacyMode && - typeof instance.UNSAFE_componentWillUpdate === "function" - ) { - pendingUNSAFE_ComponentWillUpdateWarnings.push(fiber); + function isHigherEventPriority(a, b) { + return a !== 0 && a < b; } - }; + function lanesToEventPriority(lanes) { + var lane = getHighestPriorityLane(lanes); - ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings = function() { - // We do an initial pass to gather component names - var componentWillMountUniqueNames = new Set(); + if (!isHigherEventPriority(DiscreteEventPriority, lane)) { + return DiscreteEventPriority; + } - if (pendingComponentWillMountWarnings.length > 0) { - pendingComponentWillMountWarnings.forEach(function(fiber) { - componentWillMountUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingComponentWillMountWarnings = []; - } + if (!isHigherEventPriority(ContinuousEventPriority, lane)) { + return ContinuousEventPriority; + } - var UNSAFE_componentWillMountUniqueNames = new Set(); + if (includesNonIdleWork(lane)) { + return DefaultEventPriority; + } - if (pendingUNSAFE_ComponentWillMountWarnings.length > 0) { - pendingUNSAFE_ComponentWillMountWarnings.forEach(function(fiber) { - UNSAFE_componentWillMountUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingUNSAFE_ComponentWillMountWarnings = []; + return IdleEventPriority; } - var componentWillReceivePropsUniqueNames = new Set(); + // Renderers that don't support hydration + // can re-export everything from this module. + function shim() { + 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; + var isSuspenseInstanceFallback = shim; + var getSuspenseInstanceFallbackErrorDetails = shim; + var registerSuspenseInstanceRetry = shim; + var hydrateTextInstance = shim; + var clearSuspenseBoundary = shim; + var clearSuspenseBoundaryFromContainer = shim; + var errorHydratingContainer = shim; + + var getViewConfigForType = + ReactNativePrivateInterface.ReactNativeViewConfigRegistry.get; + var UPDATE_SIGNAL = {}; - if (pendingComponentWillReceivePropsWarnings.length > 0) { - pendingComponentWillReceivePropsWarnings.forEach(function(fiber) { - componentWillReceivePropsUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingComponentWillReceivePropsWarnings = []; - } + { + Object.freeze(UPDATE_SIGNAL); + } // Counter for uniquely identifying views. + // % 10 === 1 means it is a rootTag. + // % 2 === 0 means it is a Fabric tag. - var UNSAFE_componentWillReceivePropsUniqueNames = new Set(); + var nextReactTag = 3; - if (pendingUNSAFE_ComponentWillReceivePropsWarnings.length > 0) { - pendingUNSAFE_ComponentWillReceivePropsWarnings.forEach(function(fiber) { - UNSAFE_componentWillReceivePropsUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingUNSAFE_ComponentWillReceivePropsWarnings = []; - } + function allocateTag() { + var tag = nextReactTag; - var componentWillUpdateUniqueNames = new Set(); + if (tag % 10 === 1) { + tag += 2; + } - if (pendingComponentWillUpdateWarnings.length > 0) { - pendingComponentWillUpdateWarnings.forEach(function(fiber) { - componentWillUpdateUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingComponentWillUpdateWarnings = []; + nextReactTag = tag + 2; + return tag; } - var UNSAFE_componentWillUpdateUniqueNames = new Set(); + function recursivelyUncacheFiberNode(node) { + if (typeof node === "number") { + // Leaf node (eg text) + uncacheFiberNode(node); + } else { + uncacheFiberNode(node._nativeTag); - 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://react.dev/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 - ); + node._children.forEach(recursivelyUncacheFiberNode); + } } + function appendInitialChild(parentInstance, child) { + parentInstance._children.push(child); + } + function createInstance( + type, + props, + rootContainerInstance, + hostContext, + internalInstanceHandle + ) { + var tag = allocateTag(); + var viewConfig = getViewConfigForType(type); - if (UNSAFE_componentWillReceivePropsUniqueNames.size > 0) { - var _sortedNames = setToSortedString( - UNSAFE_componentWillReceivePropsUniqueNames - ); + { + for (var key in viewConfig.validAttributes) { + if (props.hasOwnProperty(key)) { + ReactNativePrivateInterface.deepFreezeAndThrowOnMutationInDev( + props[key] + ); + } + } + } - error( - "Using UNSAFE_componentWillReceiveProps in strict mode is not recommended " + - "and may indicate bugs in your code. " + - "See https://react.dev/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://react.dev/link/derived-state\n" + - "\nPlease update the following components: %s", - _sortedNames + var updatePayload = create(props, viewConfig.validAttributes); + ReactNativePrivateInterface.UIManager.createView( + tag, // reactTag + viewConfig.uiViewClassName, // viewName + rootContainerInstance, // rootTag + updatePayload // props ); - } - - if (UNSAFE_componentWillUpdateUniqueNames.size > 0) { - var _sortedNames2 = setToSortedString( - UNSAFE_componentWillUpdateUniqueNames + var component = new ReactNativeFiberHostComponent( + tag, + viewConfig, + internalInstanceHandle ); + precacheFiberNode(internalInstanceHandle, tag); + updateFiberProps(tag, props); // Not sure how to avoid this cast. Flow is okay if the component is defined + // in the same file but if it's external it can't see the types. - error( - "Using UNSAFE_componentWillUpdate in strict mode is not recommended " + - "and may indicate bugs in your code. " + - "See https://react.dev/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 component; } + function createTextInstance( + text, + rootContainerInstance, + hostContext, + internalInstanceHandle + ) { + if (!hostContext.isInAParentText) { + throw new Error("Text strings must be rendered within a component."); + } - if (componentWillMountUniqueNames.size > 0) { - var _sortedNames3 = setToSortedString(componentWillMountUniqueNames); - - warn( - "componentWillMount has been renamed, and is not recommended for use. " + - "See https://react.dev/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 + var tag = allocateTag(); + ReactNativePrivateInterface.UIManager.createView( + tag, // reactTag + "RCTRawText", // viewName + rootContainerInstance, // rootTag + { + text: text + } // props ); + precacheFiberNode(internalInstanceHandle, tag); + return tag; } + function finalizeInitialChildren( + parentInstance, + type, + props, + rootContainerInstance, + hostContext + ) { + // Don't send a no-op message over the bridge. + if (parentInstance._children.length === 0) { + return false; + } // Map from child objects to native tags. + // Either way we need to pass a copy of the Array to prevent it from being frozen. - if (componentWillReceivePropsUniqueNames.size > 0) { - var _sortedNames4 = setToSortedString( - componentWillReceivePropsUniqueNames - ); + var nativeTags = parentInstance._children.map(function (child) { + return typeof child === "number" + ? child // Leaf node (eg text) + : child._nativeTag; + }); - warn( - "componentWillReceiveProps has been renamed, and is not recommended for use. " + - "See https://react.dev/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://react.dev/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 + ReactNativePrivateInterface.UIManager.setChildren( + parentInstance._nativeTag, // containerTag + nativeTags // reactTags ); + return false; } - - if (componentWillUpdateUniqueNames.size > 0) { - var _sortedNames5 = setToSortedString(componentWillUpdateUniqueNames); - - warn( - "componentWillUpdate has been renamed, and is not recommended for use. " + - "See https://react.dev/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 getRootHostContext(rootContainerInstance) { + return { + isInAParentText: false + }; + } + function getChildHostContext(parentHostContext, type, rootContainerInstance) { + var prevIsInAParentText = parentHostContext.isInAParentText; + var isInAParentText = + type === "AndroidTextInput" || // Android + type === "RCTMultilineTextInputView" || // iOS + type === "RCTSinglelineTextInputView" || // iOS + type === "RCTText" || + type === "RCTVirtualText"; + + if (prevIsInAParentText !== isInAParentText) { + return { + isInAParentText: isInAParentText + }; + } else { + return parentHostContext; + } + } + function getPublicInstance(instance) { + return instance; + } + function prepareForCommit(containerInfo) { + // Noop + return null; + } + function prepareUpdate( + instance, + type, + oldProps, + newProps, + rootContainerInstance, + hostContext + ) { + return UPDATE_SIGNAL; + } + function resetAfterCommit(containerInfo) { + // Noop + } + var scheduleTimeout = setTimeout; + var cancelTimeout = clearTimeout; + var noTimeout = -1; + function shouldSetTextContent(type, props) { + // TODO (bvaughn) Revisit this decision. + // Always returning false simplifies the createInstance() implementation, + // But creates an additional child Fiber for raw text children. + // No additional native views are created though. + // It's not clear to me which is better so I'm deferring for now. + // More context @ github.com/facebook/react/pull/8560#discussion_r92111303 + return false; + } + function getCurrentEventPriority() { + return DefaultEventPriority; + } // ------------------- + function appendChild(parentInstance, child) { + var childTag = typeof child === "number" ? child : child._nativeTag; + var children = parentInstance._children; + var index = children.indexOf(child); + + if (index >= 0) { + children.splice(index, 1); + children.push(child); + ReactNativePrivateInterface.UIManager.manageChildren( + parentInstance._nativeTag, // containerTag + [index], // moveFromIndices + [children.length - 1], // moveToIndices + [], // addChildReactTags + [], // addAtIndices + [] // removeAtIndices + ); + } else { + children.push(child); + ReactNativePrivateInterface.UIManager.manageChildren( + parentInstance._nativeTag, // containerTag + [], // moveFromIndices + [], // moveToIndices + [childTag], // addChildReactTags + [children.length - 1], // addAtIndices + [] // removeAtIndices + ); + } + } + function appendChildToContainer(parentInstance, child) { + var childTag = typeof child === "number" ? child : child._nativeTag; + ReactNativePrivateInterface.UIManager.setChildren( + parentInstance, // containerTag + [childTag] // reactTags ); } - }; - - var pendingLegacyContextWarning = new Map(); // Tracks components we have already warned about. - - var didWarnAboutLegacyContext = new Set(); - - ReactStrictModeWarnings.recordLegacyContextWarning = function( - fiber, - instance - ) { - var strictRoot = findStrictRoot(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." + function commitTextUpdate(textInstance, oldText, newText) { + ReactNativePrivateInterface.UIManager.updateView( + textInstance, // reactTag + "RCTRawText", // viewName + { + text: newText + } // props ); - - return; - } // Dedup strategy: Warn once per component. - - if (didWarnAboutLegacyContext.has(fiber.type)) { - return; } - - var warningsForRoot = pendingLegacyContextWarning.get(strictRoot); - - if ( - fiber.type.contextTypes != null || - fiber.type.childContextTypes != null || - (instance !== null && typeof instance.getChildContext === "function") + function commitUpdate( + instance, + updatePayloadTODO, + type, + oldProps, + newProps, + internalInstanceHandle ) { - if (warningsForRoot === undefined) { - warningsForRoot = []; - pendingLegacyContextWarning.set(strictRoot, warningsForRoot); + var viewConfig = instance.viewConfig; + updateFiberProps(instance._nativeTag, newProps); + var updatePayload = diff(oldProps, newProps, viewConfig.validAttributes); // Avoid the overhead of bridge calls if there's no update. + // This is an expensive no-op for Android, and causes an unnecessary + // view invalidation for certain components (eg RCTTextInput) on iOS. + + if (updatePayload != null) { + ReactNativePrivateInterface.UIManager.updateView( + instance._nativeTag, // reactTag + viewConfig.uiViewClassName, // viewName + updatePayload // props + ); } - - warningsForRoot.push(fiber); } - }; - - ReactStrictModeWarnings.flushLegacyContextWarning = function() { - pendingLegacyContextWarning.forEach(function(fiberArray, strictRoot) { - if (fiberArray.length === 0) { - return; - } - - 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://react.dev/link/legacy-context", - sortedNames + function insertBefore(parentInstance, child, beforeChild) { + var children = parentInstance._children; + var index = children.indexOf(child); // Move existing child or add new child? + + if (index >= 0) { + children.splice(index, 1); + var beforeChildIndex = children.indexOf(beforeChild); + children.splice(beforeChildIndex, 0, child); + ReactNativePrivateInterface.UIManager.manageChildren( + parentInstance._nativeTag, // containerID + [index], // moveFromIndices + [beforeChildIndex], // moveToIndices + [], // addChildReactTags + [], // addAtIndices + [] // removeAtIndices + ); + } else { + var _beforeChildIndex = children.indexOf(beforeChild); + + children.splice(_beforeChildIndex, 0, child); + var childTag = typeof child === "number" ? child : child._nativeTag; + ReactNativePrivateInterface.UIManager.manageChildren( + parentInstance._nativeTag, // containerID + [], // moveFromIndices + [], // moveToIndices + [childTag], // addChildReactTags + [_beforeChildIndex], // addAtIndices + [] // removeAtIndices ); - } finally { - resetCurrentFiber(); } - }); - }; - - ReactStrictModeWarnings.discardPendingWarnings = function() { - pendingComponentWillMountWarnings = []; - pendingUNSAFE_ComponentWillMountWarnings = []; - pendingComponentWillReceivePropsWarnings = []; - pendingUNSAFE_ComponentWillReceivePropsWarnings = []; - pendingComponentWillUpdateWarnings = []; - pendingUNSAFE_ComponentWillUpdateWarnings = []; - pendingLegacyContextWarning = new Map(); - }; -} - -/* - * The `'' + value` pattern (used in 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 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"; - return type; - } -} // $FlowFixMe 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 checkKeyStringCoercion(value) { - { - if (willCoercionThrow(value)) { - error( - "The provided key is an unsupported type %s." + - " This value must be coerced to a string before before using it here.", - typeName(value) + function insertInContainerBefore(parentInstance, child, beforeChild) { + // TODO (bvaughn): Remove this check when... + // We create a wrapper object for the container in ReactNative render() + // Or we refactor to remove wrapper objects entirely. + // For more info on pros/cons see PR #8560 description. + if (typeof parentInstance === "number") { + throw new Error("Container does not support insertBefore operation"); + } + } + function removeChild(parentInstance, child) { + recursivelyUncacheFiberNode(child); + var children = parentInstance._children; + var index = children.indexOf(child); + children.splice(index, 1); + ReactNativePrivateInterface.UIManager.manageChildren( + parentInstance._nativeTag, // containerID + [], // moveFromIndices + [], // moveToIndices + [], // addChildReactTags + [], // addAtIndices + [index] // removeAtIndices ); - - 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 before using it here.", - propName, - typeName(value) + function removeChildFromContainer(parentInstance, child) { + recursivelyUncacheFiberNode(child); + ReactNativePrivateInterface.UIManager.manageChildren( + parentInstance, // containerID + [], // moveFromIndices + [], // moveToIndices + [], // addChildReactTags + [], // addAtIndices + [0] // removeAtIndices ); - - return testStringCoercion(value); // throw (to help callers find troubleshooting comments) } - } -} + function resetTextContent(instance) { + // Noop + } + function hideInstance(instance) { + var viewConfig = instance.viewConfig; + var updatePayload = create( + { + style: { + display: "none" + } + }, + viewConfig.validAttributes + ); + ReactNativePrivateInterface.UIManager.updateView( + instance._nativeTag, + viewConfig.uiViewClassName, + updatePayload + ); + } + function hideTextInstance(textInstance) { + throw new Error("Not yet implemented."); + } + function unhideInstance(instance, props) { + var viewConfig = instance.viewConfig; + var updatePayload = diff( + assign({}, props, { + style: [ + props.style, + { + display: "none" + } + ] + }), + props, + viewConfig.validAttributes + ); + ReactNativePrivateInterface.UIManager.updateView( + instance._nativeTag, + viewConfig.uiViewClassName, + updatePayload + ); + } + function clearContainer(container) { + // TODO Implement this for React Native + // UIManager does not expose a "remove all" type method. + } + function unhideTextInstance(textInstance, text) { + throw new Error("Not yet implemented."); + } + function preparePortalMount(portalInstance) { + // noop + } + + var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher; + function describeBuiltInComponentFrame(name, source, ownerFn) { + { + var ownerName = null; -function resolveDefaultProps(Component, baseProps) { - if (Component && Component.defaultProps) { - // Resolve default props. Taken from ReactElement - var props = assign({}, baseProps); - var defaultProps = Component.defaultProps; + if (ownerFn) { + ownerName = ownerFn.displayName || ownerFn.name || null; + } - for (var propName in defaultProps) { - if (props[propName] === undefined) { - props[propName] = defaultProps[propName]; + return describeComponentFrame(name, source, ownerName); } } + var componentFrameCache; - return props; - } + { + var PossiblyWeakMap = typeof WeakMap === "function" ? WeakMap : Map; + componentFrameCache = new PossiblyWeakMap(); + } + var BEFORE_SLASH_RE = /^(.*)[\\\/]/; - return baseProps; -} + function describeComponentFrame(name, source, ownerName) { + var sourceInfo = ""; -var valueCursor = createCursor(null); -var rendererSigil; + if (source) { + var path = source.fileName; + var fileName = path.replace(BEFORE_SLASH_RE, ""); // In DEV, include code for a common special case: + // prefer "folder/index.js" instead of just "index.js". -{ - // Use this to detect multiple renderers using the same context - rendererSigil = {}; -} + if (/^index\./.test(fileName)) { + var match = path.match(BEFORE_SLASH_RE); -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._currentValue, providerFiber); - context._currentValue = nextValue; + if (match) { + var pathBeforeSlash = match[1]; - { - if ( - context._currentRenderer !== undefined && - context._currentRenderer !== null && - context._currentRenderer !== rendererSigil - ) { - error( - "Detected multiple renderers concurrently rendering the " + - "same context provider. This is currently unsupported." - ); + if (pathBeforeSlash) { + var folderName = pathBeforeSlash.replace(BEFORE_SLASH_RE, ""); + fileName = folderName + "/" + fileName; + } + } + } + + sourceInfo = " (at " + fileName + ":" + source.lineNumber + ")"; + } else if (ownerName) { + sourceInfo = " (created by " + ownerName + ")"; } - context._currentRenderer = rendererSigil; + return "\n in " + (name || "Unknown") + sourceInfo; } - } -} -function popProvider(context, providerFiber) { - var currentValue = valueCursor.current; - pop(valueCursor, providerFiber); - { - { - context._currentValue = currentValue; + function describeClassComponentFrame(ctor, source, ownerFn) { + { + return describeFunctionComponentFrame(ctor, source, ownerFn); + } } - } -} -function scheduleContextWorkOnParentPath(parent, renderLanes, propagationRoot) { - // Update the child lanes of all the ancestors, including the alternates. - var node = parent; + function describeFunctionComponentFrame(fn, source, ownerFn) { + { + if (!fn) { + return ""; + } - while (node !== null) { - var alternate = node.alternate; + var name = fn.displayName || fn.name || null; + var ownerName = null; - if (!isSubsetOfLanes(node.childLanes, renderLanes)) { - node.childLanes = mergeLanes(node.childLanes, renderLanes); + if (ownerFn) { + ownerName = ownerFn.displayName || ownerFn.name || null; + } - if (alternate !== null) { - alternate.childLanes = mergeLanes(alternate.childLanes, renderLanes); + return describeComponentFrame(name, source, ownerName); } - } else if ( - alternate !== null && - !isSubsetOfLanes(alternate.childLanes, renderLanes) - ) { - alternate.childLanes = mergeLanes(alternate.childLanes, renderLanes); } - if (node === propagationRoot) { - break; - } - - node = node.return; - } + function describeUnknownElementTypeFrameInDEV(type, source, ownerFn) { + if (type == null) { + return ""; + } - { - 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) { - { - propagateContextChange_eager(workInProgress, context, renderLanes); - } -} + if (typeof type === "function") { + { + return describeFunctionComponentFrame(type, source, ownerFn); + } + } -function propagateContextChange_eager(workInProgress, context, renderLanes) { - var fiber = workInProgress.child; + if (typeof type === "string") { + return describeBuiltInComponentFrame(type, source, ownerFn); + } - if (fiber !== null) { - // Set the return pointer of the child to the work-in-progress fiber. - fiber.return = workInProgress; - } + switch (type) { + case REACT_SUSPENSE_TYPE: + return describeBuiltInComponentFrame("Suspense", source, ownerFn); - while (fiber !== null) { - var nextFiber = void 0; // Visit this fiber. + case REACT_SUSPENSE_LIST_TYPE: + return describeBuiltInComponentFrame("SuspenseList", source, ownerFn); + } - var list = fiber.dependencies; + if (typeof type === "object") { + switch (type.$$typeof) { + case REACT_FORWARD_REF_TYPE: + return describeFunctionComponentFrame(type.render, source, ownerFn); - if (list !== null) { - nextFiber = fiber.child; - var dependency = list.firstContext; + case REACT_MEMO_TYPE: + // Memo may contain any component type so we recursively resolve it. + return describeUnknownElementTypeFrameInDEV(type.type, source, ownerFn); - 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(NoTimestamp, 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 - - var updateQueue = fiber.updateQueue; - - if (updateQueue === null); - else { - var sharedQueue = updateQueue.shared; - var pending = sharedQueue.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 REACT_LAZY_TYPE: { + var lazyComponent = type; + var payload = lazyComponent._payload; + var init = lazyComponent._init; - sharedQueue.pending = update; - } + try { + // Lazy may contain any component type so we recursively resolve it. + return describeUnknownElementTypeFrameInDEV( + init(payload), + source, + ownerFn + ); + } catch (x) { } } + } + } - fiber.lanes = mergeLanes(fiber.lanes, renderLanes); - var alternate = fiber.alternate; - - if (alternate !== null) { - alternate.lanes = mergeLanes(alternate.lanes, renderLanes); - } + return ""; + } - scheduleContextWorkOnParentPath( - fiber.return, - renderLanes, - workInProgress - ); // Mark the updated lanes on the list, too. + var hasOwnProperty = Object.prototype.hasOwnProperty; - list.lanes = mergeLanes(list.lanes, renderLanes); // Since we already found a match, we can stop traversing the - // dependency list. + var loggedTypeFailures = {}; + var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; - break; + 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); } - - 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." - ); } + } - parentSuspense.lanes = mergeLanes(parentSuspense.lanes, renderLanes); - var _alternate = parentSuspense.alternate; + function checkPropTypes(typeSpecs, values, location, componentName, element) { + { + // $FlowFixMe This is okay but Flow doesn't know it. + var has = Function.call.bind(hasOwnProperty); - 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. + 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. - scheduleContextWorkOnParentPath( - parentSuspense, - renderLanes, - workInProgress - ); - nextFiber = fiber.sibling; - } 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; - } + 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; + } - var sibling = nextFiber.sibling; + 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 (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 (error$1 && !(error$1 instanceof Error)) { + setCurrentlyValidatingElement(element); - nextFiber = nextFiber.return; - } - } + 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 + ); - fiber = nextFiber; - } -} -function prepareToReadContext(workInProgress, renderLanes) { - currentlyRenderingFiber = workInProgress; - lastContextDependency = null; - lastFullyObservedContext = null; - var dependencies = workInProgress.dependencies; + setCurrentlyValidatingElement(null); + } - if (dependencies !== null) { - { - var firstContext = dependencies.firstContext; + 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 (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 + error("Failed %s type: %s", location, error$1.message); - dependencies.firstContext = null; + setCurrentlyValidatingElement(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 value = context._currentValue; + var valueStack = []; + var fiberStack; - if (lastFullyObservedContext === context); - else { - var contextItem = { - context: context, - memoizedValue: value, - next: null - }; + { + fiberStack = []; + } - if (lastContextDependency === null) { - if (currentlyRenderingFiber === 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. + var index = -1; - lastContextDependency = contextItem; - currentlyRenderingFiber.dependencies = { - lanes: NoLanes, - firstContext: contextItem + function createCursor(defaultValue) { + return { + current: defaultValue }; - } else { - // Append a new context item. - lastContextDependency = lastContextDependency.next = contextItem; } - } - return value; -} - -// render. When this render exits, either because it finishes or because it is -// interrupted, the interleaved updates will be transferred onto the main part -// of the queue. - -var concurrentQueues = null; -function pushConcurrentUpdateQueue(queue) { - if (concurrentQueues === null) { - concurrentQueues = [queue]; - } else { - concurrentQueues.push(queue); - } -} -function finishQueueingConcurrentUpdates() { - // Transfer the interleaved updates onto the main queue. Each queue has a - // `pending` field and an `interleaved` field. When they are not null, they - // point to the last node in a circular linked list. We need to append the - // interleaved list to the end of the pending list by joining them into a - // single, circular list. - if (concurrentQueues !== null) { - for (var i = 0; i < concurrentQueues.length; i++) { - var queue = concurrentQueues[i]; - var lastInterleavedUpdate = queue.interleaved; - - if (lastInterleavedUpdate !== null) { - queue.interleaved = null; - var firstInterleavedUpdate = lastInterleavedUpdate.next; - var lastPendingUpdate = queue.pending; - - if (lastPendingUpdate !== null) { - var firstPendingUpdate = lastPendingUpdate.next; - lastPendingUpdate.next = firstInterleavedUpdate; - lastInterleavedUpdate.next = firstPendingUpdate; + function pop(cursor, fiber) { + if (index < 0) { + { + error("Unexpected pop."); } - queue.pending = lastInterleavedUpdate; + return; } - } - concurrentQueues = null; - } -} -function enqueueConcurrentHookUpdate(fiber, queue, update, lane) { - var interleaved = queue.interleaved; - - if (interleaved === null) { - // This is the first update. Create a circular list. - update.next = update; // At the end of the current render, this queue's interleaved updates will - // be transferred to the pending queue. - - pushConcurrentUpdateQueue(queue); - } else { - update.next = interleaved.next; - interleaved.next = update; - } - - queue.interleaved = update; - return markUpdateLaneFromFiberToRoot(fiber, lane); -} -function enqueueConcurrentHookUpdateAndEagerlyBailout( - fiber, - queue, - update, - lane -) { - var interleaved = queue.interleaved; - - if (interleaved === null) { - // This is the first update. Create a circular list. - update.next = update; // At the end of the current render, this queue's interleaved updates will - // be transferred to the pending queue. - - pushConcurrentUpdateQueue(queue); - } else { - update.next = interleaved.next; - interleaved.next = update; - } - - queue.interleaved = update; -} -function enqueueConcurrentClassUpdate(fiber, queue, update, lane) { - var interleaved = queue.interleaved; - - if (interleaved === null) { - // This is the first update. Create a circular list. - update.next = update; // At the end of the current render, this queue's interleaved updates will - // be transferred to the pending queue. - - pushConcurrentUpdateQueue(queue); - } else { - update.next = interleaved.next; - interleaved.next = update; - } - - queue.interleaved = update; - return markUpdateLaneFromFiberToRoot(fiber, lane); -} -function enqueueConcurrentRenderForLane(fiber, lane) { - return markUpdateLaneFromFiberToRoot(fiber, lane); -} // Calling this function outside this module should only be done for backwards -// compatibility and should always be accompanied by a warning. - -var unsafe_markUpdateLaneFromFiberToRoot = markUpdateLaneFromFiberToRoot; + { + if (fiber !== fiberStack[index]) { + error("Unexpected Fiber popped."); + } + } -function markUpdateLaneFromFiberToRoot(sourceFiber, lane) { - // Update the source fiber's lanes - sourceFiber.lanes = mergeLanes(sourceFiber.lanes, lane); - var alternate = sourceFiber.alternate; + cursor.current = valueStack[index]; + valueStack[index] = null; - if (alternate !== null) { - alternate.lanes = mergeLanes(alternate.lanes, lane); - } + { + fiberStack[index] = null; + } - { - if ( - alternate === null && - (sourceFiber.flags & (Placement | Hydrating)) !== NoFlags - ) { - warnAboutUpdateOnNotYetMountedFiberInDEV(sourceFiber); + index--; } - } // Walk the parent path to the root and update the child lanes. - var node = sourceFiber; - var parent = sourceFiber.return; + function push(cursor, value, fiber) { + index++; + valueStack[index] = cursor.current; - while (parent !== null) { - parent.childLanes = mergeLanes(parent.childLanes, lane); - alternate = parent.alternate; - - if (alternate !== null) { - alternate.childLanes = mergeLanes(alternate.childLanes, lane); - } else { { - if ((parent.flags & (Placement | Hydrating)) !== NoFlags) { - warnAboutUpdateOnNotYetMountedFiberInDEV(sourceFiber); - } + fiberStack[index] = fiber; } - } - node = parent; - parent = parent.return; - } + cursor.current = value; + } - if (node.tag === HostRoot) { - var root = node.stateNode; - return root; - } else { - return null; - } -} + var warnedAboutMissingGetChildContext; -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`. + { + warnedAboutMissingGetChildContext = {}; + } -var hasForceUpdate = false; -var didWarnUpdateInsideUpdate; -var currentlyProcessingQueue; + var emptyContextObject = {}; -{ - didWarnUpdateInsideUpdate = false; - currentlyProcessingQueue = null; -} + { + Object.freeze(emptyContextObject); + } // A cursor to the current merged context object on the stack. -function initializeUpdateQueue(fiber) { - var queue = { - baseState: fiber.memoizedState, - firstBaseUpdate: null, - lastBaseUpdate: null, - shared: { - pending: null, - interleaved: null, - lanes: NoLanes - }, - effects: 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, - effects: currentQueue.effects - }; - workInProgress.updateQueue = clone; - } -} -function createUpdate(eventTime, lane) { - var update = { - eventTime: eventTime, - lane: lane, - tag: UpdateState, - payload: null, - callback: null, - next: null - }; - return update; -} -function enqueueUpdate(fiber, update, lane) { - var updateQueue = fiber.updateQueue; + var contextStackCursor = createCursor(emptyContextObject); // A cursor to a boolean indicating whether the context has changed. - if (updateQueue === null) { - // Only occurs if the fiber has been unmounted. - return null; - } + 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. - var sharedQueue = updateQueue.shared; + var previousContext = emptyContextObject; - { - if ( - currentlyProcessingQueue === sharedQueue && - !didWarnUpdateInsideUpdate + function getUnmaskedContext( + workInProgress, + Component, + didPushOwnContextIfProvider ) { - 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." - ); + { + 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; + } - didWarnUpdateInsideUpdate = true; + return contextStackCursor.current; + } } - } - - 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 (pending === null) { - // This is the first update. Create a circular list. - update.next = update; - } else { - update.next = pending.next; - pending.next = update; + function cacheContext(workInProgress, unmaskedContext, maskedContext) { + { + var instance = workInProgress.stateNode; + instance.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext; + instance.__reactInternalMemoizedMaskedChildContext = maskedContext; + } } - 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 getMaskedContext(workInProgress, unmaskedContext) { + { + var type = workInProgress.type; + var contextTypes = type.contextTypes; - return unsafe_markUpdateLaneFromFiberToRoot(fiber, lane); - } else { - return enqueueConcurrentClassUpdate(fiber, sharedQueue, update, lane); - } -} -function entangleTransitions(root, fiber, lane) { - var updateQueue = fiber.updateQueue; + 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. - if (updateQueue === null) { - // Only occurs if the fiber has been unmounted. - return; - } + var instance = workInProgress.stateNode; - var sharedQueue = updateQueue.shared; + if ( + instance && + instance.__reactInternalMemoizedUnmaskedChildContext === unmaskedContext + ) { + return instance.__reactInternalMemoizedMaskedChildContext; + } - 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 context = {}; - queueLanes = intersectLanes(queueLanes, root.pendingLanes); // Entangle the new transition lane with the other transition lanes. + for (var key in contextTypes) { + context[key] = unmaskedContext[key]; + } - 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. + { + 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. - 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 (instance) { + cacheContext(workInProgress, unmaskedContext, context); + } - if (firstBaseUpdate !== null) { - // Loop through the updates and clone them. - var update = firstBaseUpdate; + return context; + } + } - do { - var clone = { - eventTime: update.eventTime, - lane: update.lane, - tag: update.tag, - payload: update.payload, - callback: update.callback, - next: null - }; + function hasContextChanged() { + { + return didPerformWorkStackCursor.current; + } + } - if (newLast === null) { - newFirst = newLast = clone; - } else { - newLast.next = clone; - newLast = clone; - } + function isContextProvider(type) { + { + var childContextTypes = type.childContextTypes; + return childContextTypes !== null && childContextTypes !== undefined; + } + } - update = update.next; - } while (update !== null); // Append the captured update the end of the cloned list. + function popContext(fiber) { + { + pop(didPerformWorkStackCursor, fiber); + pop(contextStackCursor, fiber); + } + } - if (newLast === null) { - newFirst = newLast = capturedUpdate; - } else { - newLast.next = capturedUpdate; - newLast = capturedUpdate; - } - } else { - // There are no base updates. - newFirst = newLast = capturedUpdate; + function popTopLevelContextObject(fiber) { + { + pop(didPerformWorkStackCursor, fiber); + pop(contextStackCursor, fiber); } + } - queue = { - baseState: currentQueue.baseState, - firstBaseUpdate: newFirst, - lastBaseUpdate: newLast, - shared: currentQueue.shared, - effects: currentQueue.effects - }; - workInProgress.updateQueue = queue; - return; + function pushTopLevelContextObject(fiber, context, didChange) { + { + if (contextStackCursor.current !== emptyContextObject) { + throw new Error( + "Unexpected context found on stack. " + + "This error is likely caused by a bug in React. Please file an issue." + ); + } + + push(contextStackCursor, context, fiber); + push(didPerformWorkStackCursor, didChange, fiber); + } } - } // Append the update to the end of the list. - var lastBaseUpdate = queue.lastBaseUpdate; + 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 (typeof instance.getChildContext !== "function") { + { + var componentName = getComponentNameFromFiber(fiber) || "Unknown"; - if (lastBaseUpdate === null) { - queue.firstBaseUpdate = capturedUpdate; - } else { - lastBaseUpdate.next = capturedUpdate; - } + if (!warnedAboutMissingGetChildContext[componentName]) { + warnedAboutMissingGetChildContext[componentName] = true; - queue.lastBaseUpdate = capturedUpdate; -} + 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 + ); + } + } -function getStateFromUpdate( - workInProgress, - queue, - update, - prevState, - nextProps, - instance -) { - switch (update.tag) { - case ReplaceState: { - var payload = update.payload; - - if (typeof payload === "function") { - // Updater function - { - enterDisallowedContextReadInDEV(); + return parentContext; } - var nextState = payload.call(instance, prevState, nextProps); + var childContext = instance.getChildContext(); - { - exitDisallowedContextReadInDEV(); + for (var contextKey in childContext) { + if (!(contextKey in childContextTypes)) { + throw new Error( + (getComponentNameFromFiber(fiber) || "Unknown") + + '.getChildContext(): key "' + + contextKey + + '" is not defined in childContextTypes.' + ); + } } - return nextState; - } // State object + { + var name = getComponentNameFromFiber(fiber) || "Unknown"; + checkPropTypes(childContextTypes, childContext, "child context", name); + } - return payload; + return assign({}, parentContext, childContext); + } } - case CaptureUpdate: { - workInProgress.flags = - (workInProgress.flags & ~ShouldCapture) | DidCapture; + 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.current; + push(contextStackCursor, memoizedMergedChildContext, workInProgress); + push( + didPerformWorkStackCursor, + didPerformWorkStackCursor.current, + workInProgress + ); + return true; + } } - // Intentional fallthrough - case UpdateState: { - var _payload = update.payload; - var partialState; + function invalidateContextProvider(workInProgress, type, didChange) { + { + var instance = workInProgress.stateNode; - if (typeof _payload === "function") { - // Updater function - { - enterDisallowedContextReadInDEV(); + 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." + ); } - partialState = _payload.call(instance, prevState, nextProps); + 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. + + pop(didPerformWorkStackCursor, workInProgress); + pop(contextStackCursor, workInProgress); // Now push the new context and mark that it has changed. - { - exitDisallowedContextReadInDEV(); + push(contextStackCursor, mergedContext, workInProgress); + push(didPerformWorkStackCursor, didChange, workInProgress); + } else { + pop(didPerformWorkStackCursor, workInProgress); + push(didPerformWorkStackCursor, didChange, workInProgress); } - } 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. + 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." + ); + } - return assign({}, prevState, partialState); - } + var node = fiber; - case ForceUpdate: { - hasForceUpdate = true; - return prevState; - } - } + do { + switch (node.tag) { + case HostRoot: + return node.stateNode.context; - return prevState; -} + case ClassComponent: { + var Component = node.type; + + if (isContextProvider(Component)) { + return node.stateNode.__reactInternalMemoizedMergedChildContext; + } -function processUpdateQueue(workInProgress, props, instance, renderLanes) { - // This is always non-null on a ClassComponent or HostRoot - var queue = workInProgress.updateQueue; - hasForceUpdate = false; + break; + } + } - { - currentlyProcessingQueue = queue.shared; - } + node = node.return; + } while (node !== null); - var firstBaseUpdate = queue.firstBaseUpdate; - var lastBaseUpdate = queue.lastBaseUpdate; // Check if there are pending updates. If so, transfer them to the base queue. + throw new Error( + "Found unexpected detached subtree parent. " + + "This error is likely caused by a bug in React. Please file an issue." + ); + } + } - var pendingQueue = queue.shared.pending; + var LegacyRoot = 0; + var ConcurrentRoot = 1; - 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. + /** + * 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 lastPendingUpdate = pendingQueue; - var firstPendingUpdate = lastPendingUpdate.next; - lastPendingUpdate.next = null; // Append pending updates to base queue + var objectIs = typeof Object.is === "function" ? Object.is : is; - if (lastBaseUpdate === null) { - firstBaseUpdate = firstPendingUpdate; - } else { - lastBaseUpdate.next = firstPendingUpdate; + var syncQueue = null; + var includesLegacySyncCallbacks = false; + var isFlushingSyncQueue = false; + function scheduleSyncCallback(callback) { + // Push this callback into an internal queue. We'll flush these either in + // the next tick, or earlier if something calls `flushSyncCallbackQueue`. + if (syncQueue === null) { + syncQueue = [callback]; + } else { + // Push onto existing queue. Don't need to schedule a callback because + // we already scheduled one when we created the queue. + syncQueue.push(callback); + } } + function scheduleLegacySyncCallback(callback) { + includesLegacySyncCallbacks = true; + scheduleSyncCallback(callback); + } + function flushSyncCallbacksOnlyInLegacyMode() { + // Only flushes the queue if there's a legacy sync callback scheduled. + // TODO: There's only a single type of callback: performSyncOnWorkOnRoot. So + // it might make more sense for the queue to be a list of roots instead of a + // list of generic callbacks. Then we can have two: one for legacy roots, one + // for concurrent roots. And this method would only flush the legacy ones. + if (includesLegacySyncCallbacks) { + flushSyncCallbacks(); + } + } + function flushSyncCallbacks() { + if (!isFlushingSyncQueue && syncQueue !== null) { + // Prevent re-entrance. + isFlushingSyncQueue = true; + var i = 0; + var previousUpdatePriority = getCurrentUpdatePriority(); - 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 + try { + var isSync = true; + var queue = syncQueue; // TODO: Is this necessary anymore? The only user code that runs in this + // queue is in the render or commit phases. - var current = workInProgress.alternate; + setCurrentUpdatePriority(DiscreteEventPriority); - if (current !== null) { - // This is always non-null on a ClassComponent or HostRoot - var currentQueue = current.updateQueue; - var currentLastBaseUpdate = currentQueue.lastBaseUpdate; + for (; i < queue.length; i++) { + var callback = queue[i]; - if (currentLastBaseUpdate !== lastBaseUpdate) { - if (currentLastBaseUpdate === null) { - currentQueue.firstBaseUpdate = firstPendingUpdate; - } else { - currentLastBaseUpdate.next = firstPendingUpdate; + do { + callback = callback(isSync); + } while (callback !== null); + } + + syncQueue = null; + includesLegacySyncCallbacks = false; + } catch (error) { + // If something throws, leave the remaining callbacks on the queue. + if (syncQueue !== null) { + syncQueue = syncQueue.slice(i + 1); + } // Resume flushing in the next tick + + scheduleCallback(ImmediatePriority, flushSyncCallbacks); + throw error; + } finally { + setCurrentUpdatePriority(previousUpdatePriority); + isFlushingSyncQueue = false; } + } + + return null; + } - currentQueue.lastBaseUpdate = lastPendingUpdate; + // 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; + } + + // TODO: Use the unified fiber stack module instead of this local one? + // Intentionally not using it yet to derisk the initial implementation, because + // the way we push/pop these values is a bit unusual. If there's a mistake, I'd + // rather the ids be wrong than crash the whole reconciler. + var forkStack = []; + var forkStackIndex = 0; + var treeForkProvider = null; + var treeForkCount = 0; + var idStack = []; + var idStackIndex = 0; + var treeContextProvider = null; + var treeContextId = 1; + var treeContextOverflow = ""; + + function popTreeContext(workInProgress) { + // Restore the previous values. + // This is a bit more complicated than other context-like modules in Fiber + // because the same Fiber may appear on the stack multiple times and for + // different reasons. We have to keep popping until the work-in-progress is + // no longer at the top of the stack. + while (workInProgress === treeForkProvider) { + treeForkProvider = forkStack[--forkStackIndex]; + forkStack[forkStackIndex] = null; + treeForkCount = forkStack[--forkStackIndex]; + forkStack[forkStackIndex] = null; + } + + while (workInProgress === treeContextProvider) { + treeContextProvider = idStack[--idStackIndex]; + idStack[idStackIndex] = null; + treeContextOverflow = idStack[--idStackIndex]; + idStack[idStackIndex] = null; + treeContextId = idStack[--idStackIndex]; + idStack[idStackIndex] = null; + } + } + + 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 didSuspendOrErrorDEV = false; // Hydration errors that were thrown inside this boundary + + var hydrationErrors = null; + function didSuspendOrErrorWhileHydratingDEV() { + { + return didSuspendOrErrorDEV; } } - } // 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. + function reenterHydrationStateFromDehydratedSuspenseInstance( + fiber, + suspenseInstance, + treeContext + ) { + { + return false; + } + } - var newLanes = NoLanes; - var newBaseState = null; - var newFirstBaseUpdate = null; - var newLastBaseUpdate = null; - var update = firstBaseUpdate; + function prepareToHydrateHostInstance( + fiber, + rootContainerInstance, + hostContext + ) { + { + throw new Error( + "Expected prepareToHydrateHostInstance() to never be called. " + + "This error is likely caused by a bug in React. Please file an issue." + ); + } + } - do { - var updateLane = update.lane; - var updateEventTime = update.eventTime; + 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 shouldUpdate = hydrateTextInstance(); + } - if (!isSubsetOfLanes(renderLanes, updateLane)) { - // 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 = { - eventTime: updateEventTime, - lane: updateLane, - tag: update.tag, - payload: update.payload, - callback: update.callback, - next: null - }; + 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." + ); + } + } - if (newLastBaseUpdate === null) { - newFirstBaseUpdate = newLastBaseUpdate = clone; - newBaseState = newState; - } else { - newLastBaseUpdate = newLastBaseUpdate.next = clone; - } // Update the remaining priority in the queue. + function popHydrationState(fiber) { + { + return false; + } + } + + 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; + } + } + + function getIsHydrating() { + return isHydrating; + } - newLanes = mergeLanes(newLanes, updateLane); + function queueHydrationError(error) { + if (hydrationErrors === null) { + hydrationErrors = [error]; } else { - // This update does have sufficient priority. - if (newLastBaseUpdate !== null) { - var _clone = { - eventTime: updateEventTime, - // 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, - callback: update.callback, - next: null - }; - newLastBaseUpdate = newLastBaseUpdate.next = _clone; - } // Process this update. + hydrationErrors.push(error); + } + } - newState = getStateFromUpdate( - workInProgress, - queue, - update, - newState, - props, - instance - ); - var callback = update.callback; + var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig; + var NoTransition = null; + function requestCurrentTransition() { + return ReactCurrentBatchConfig.transition; + } - if ( - callback !== null && // If the update was already committed, we should not queue its - // callback again. - update.lane !== NoLane - ) { - workInProgress.flags |= Callback; - var effects = queue.effects; + /** + * 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 (effects === null) { - queue.effects = [update]; - } else { - effects.push(update); - } - } + function shallowEqual(objA, objB) { + if (objectIs(objA, objB)) { + return true; } - update = update.next; + if ( + typeof objA !== "object" || + objA === null || + typeof objB !== "object" || + objB === null + ) { + return false; + } - if (update === null) { - pendingQueue = queue.shared.pending; + var keysA = Object.keys(objA); + var keysB = Object.keys(objB); - 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. + if (keysA.length !== keysB.length) { + return false; + } // Test for A's keys different from B. - var _firstPendingUpdate = _lastPendingUpdate.next; - _lastPendingUpdate.next = null; - update = _firstPendingUpdate; - queue.lastBaseUpdate = _lastPendingUpdate; - queue.shared.pending = null; + for (var i = 0; i < keysA.length; i++) { + var currentKey = keysA[i]; + + if ( + !hasOwnProperty.call(objB, currentKey) || + !objectIs(objA[currentKey], objB[currentKey]) + ) { + return false; } } - } while (true); - if (newLastBaseUpdate === null) { - newBaseState = newState; + return true; } - queue.baseState = newBaseState; - queue.firstBaseUpdate = newFirstBaseUpdate; - queue.lastBaseUpdate = newLastBaseUpdate; // Interleaved updates are stored on a separate queue. We aren't going to - // process them during this render, but we do need to track which lanes - // are remaining. + function describeFiber(fiber) { + var owner = fiber._debugOwner ? fiber._debugOwner.type : null; + var source = fiber._debugSource; - var lastInterleaved = queue.shared.interleaved; + switch (fiber.tag) { + case HostComponent: + return describeBuiltInComponentFrame(fiber.type, source, owner); - if (lastInterleaved !== null) { - var interleaved = lastInterleaved; + case LazyComponent: + return describeBuiltInComponentFrame("Lazy", source, owner); - do { - newLanes = mergeLanes(newLanes, interleaved.lane); - interleaved = interleaved.next; - } while (interleaved !== lastInterleaved); - } else 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; - } -} + case SuspenseComponent: + return describeBuiltInComponentFrame("Suspense", source, owner); -function callCallback(callback, context) { - if (typeof callback !== "function") { - throw new Error( - "Invalid argument passed as callback. Expected a function. Instead " + - ("received: " + callback) - ); - } + case SuspenseListComponent: + return describeBuiltInComponentFrame("SuspenseList", source, owner); - callback.call(context); -} + case FunctionComponent: + case IndeterminateComponent: + case SimpleMemoComponent: + return describeFunctionComponentFrame(fiber.type, source, owner); -function resetHasForceUpdateBeforeProcessing() { - hasForceUpdate = false; -} -function checkHasForceUpdateAfterProcessing() { - return hasForceUpdate; -} -function commitUpdateQueue(finishedWork, finishedQueue, instance) { - // Commit the effects - var effects = finishedQueue.effects; - finishedQueue.effects = null; + case ForwardRef: + return describeFunctionComponentFrame(fiber.type.render, source, owner); - if (effects !== null) { - for (var i = 0; i < effects.length; i++) { - var effect = effects[i]; - var callback = effect.callback; + case ClassComponent: + return describeClassComponentFrame(fiber.type, source, owner); - if (callback !== null) { - effect.callback = null; - callCallback(callback, instance); + default: + return ""; } } - } -} - -var fakeInternalInstance = {}; // React.Component uses a shared frozen object by default. -// We'll use it to determine whether we need to initialize legacy refs. - -var emptyRefsObject = new React.Component().refs; -var didWarnAboutStateAssignmentForComponent; -var didWarnAboutUninitializedState; -var didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate; -var didWarnAboutLegacyLifecyclesAndDerivedState; -var didWarnAboutUndefinedDerivedState; -var warnOnUndefinedDerivedState; -var warnOnInvalidCallback; -var didWarnAboutDirectlyAssigningPropsToState; -var didWarnAboutContextTypeAndContextTypes; -var didWarnAboutInvalidateContextType; - -{ - didWarnAboutStateAssignmentForComponent = new Set(); - didWarnAboutUninitializedState = new Set(); - didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate = new Set(); - didWarnAboutLegacyLifecyclesAndDerivedState = new Set(); - didWarnAboutDirectlyAssigningPropsToState = new Set(); - didWarnAboutUndefinedDerivedState = new Set(); - didWarnAboutContextTypeAndContextTypes = new Set(); - didWarnAboutInvalidateContextType = new Set(); - var didWarnOnInvalidCallback = new Set(); - - warnOnInvalidCallback = function(callback, callerName) { - if (callback === null || typeof callback === "function") { - return; - } - - var key = callerName + "_" + callback; - - if (!didWarnOnInvalidCallback.has(key)) { - didWarnOnInvalidCallback.add(key); - - error( - "%s(...): Expected the last optional `callback` argument to be a " + - "function. Instead received: %s.", - callerName, - callback - ); - } - }; - warnOnUndefinedDerivedState = function(type, partialState) { - if (partialState === undefined) { - var componentName = getComponentNameFromType(type) || "Component"; + function getStackByFiberInDevAndProd(workInProgress) { + try { + var info = ""; + var node = workInProgress; - if (!didWarnAboutUndefinedDerivedState.has(componentName)) { - didWarnAboutUndefinedDerivedState.add(componentName); + do { + info += describeFiber(node); + node = node.return; + } while (node); - error( - "%s.getDerivedStateFromProps(): A valid state object (or null) must be returned. " + - "You have returned undefined.", - componentName - ); + return info; + } catch (x) { + return "\nError generating stack: " + x.message + "\n" + x.stack; } } - }; // 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); -} -function applyDerivedStateFromProps( - workInProgress, - ctor, - getDerivedStateFromProps, - nextProps -) { - var prevState = workInProgress.memoizedState; - var partialState = getDerivedStateFromProps(nextProps, prevState); - - { - 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; - } -} + var ReactDebugCurrentFrame$1 = ReactSharedInternals.ReactDebugCurrentFrame; + var current = null; + var isRendering = false; + function getCurrentFiberOwnerNameInDevOrNull() { + { + if (current === null) { + return null; + } -var classComponentUpdater = { - isMounted: isMounted, - enqueueSetState: function(inst, payload, callback) { - var fiber = get(inst); - var eventTime = requestEventTime(); - var lane = requestUpdateLane(fiber); - var update = createUpdate(eventTime, lane); - update.payload = payload; + var owner = current._debugOwner; - if (callback !== undefined && callback !== null) { - { - warnOnInvalidCallback(callback, "setState"); + if (owner !== null && typeof owner !== "undefined") { + return getComponentNameFromFiber(owner); + } } - update.callback = callback; + return null; } - var root = enqueueUpdate(fiber, update, lane); + 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 (root !== null) { - scheduleUpdateOnFiber(root, fiber, lane, eventTime); - entangleTransitions(root, fiber, lane); + return getStackByFiberInDevAndProd(current); + } } - }, - enqueueReplaceState: function(inst, payload, callback) { - var fiber = get(inst); - var eventTime = requestEventTime(); - var lane = requestUpdateLane(fiber); - var update = createUpdate(eventTime, lane); - update.tag = ReplaceState; - update.payload = payload; - if (callback !== undefined && callback !== null) { + function resetCurrentFiber() { { - warnOnInvalidCallback(callback, "replaceState"); + ReactDebugCurrentFrame$1.getCurrentStack = null; + current = null; + isRendering = false; } - - update.callback = callback; } - - var root = enqueueUpdate(fiber, update, lane); - - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, lane, eventTime); - entangleTransitions(root, fiber, lane); + function setCurrentFiber(fiber) { + { + ReactDebugCurrentFrame$1.getCurrentStack = + fiber === null ? null : getCurrentFiberStackInDev; + current = fiber; + isRendering = false; + } } - }, - enqueueForceUpdate: function(inst, callback) { - var fiber = get(inst); - var eventTime = requestEventTime(); - var lane = requestUpdateLane(fiber); - var update = createUpdate(eventTime, lane); - update.tag = ForceUpdate; - - if (callback !== undefined && callback !== null) { + function getCurrentFiber() { { - warnOnInvalidCallback(callback, "forceUpdate"); + return current; } - - update.callback = callback; } - - var root = enqueueUpdate(fiber, update, lane); - - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, lane, eventTime); - entangleTransitions(root, fiber, lane); + function setIsRendering(rendering) { + { + isRendering = rendering; + } } - } -}; -function checkShouldComponentUpdate( - workInProgress, - ctor, - oldProps, - newProps, - oldState, - newState, - nextContext -) { - var instance = workInProgress.stateNode; - - if (typeof instance.shouldComponentUpdate === "function") { - var shouldUpdate = instance.shouldComponentUpdate( - newProps, - newState, - nextContext - ); + var ReactStrictModeWarnings = { + recordUnsafeLifecycleWarnings: function (fiber, instance) { }, + flushPendingUnsafeLifecycleWarnings: function () { }, + recordLegacyContextWarning: function (fiber, instance) { }, + flushLegacyContextWarning: function () { }, + discardPendingWarnings: function () { } + }; { - if (shouldUpdate === undefined) { - error( - "%s.shouldComponentUpdate(): Returned undefined instead of a " + - "boolean value. Make sure to return true or false.", - getComponentNameFromType(ctor) || "Component" - ); - } - } + var findStrictRoot = function (fiber) { + var maybeStrictRoot = null; + var node = fiber; - return shouldUpdate; - } + while (node !== null) { + if (node.mode & StrictLegacyMode) { + maybeStrictRoot = node; + } - if (ctor.prototype && ctor.prototype.isPureReactComponent) { - return ( - !shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState) - ); - } + node = node.return; + } - return true; -} + return maybeStrictRoot; + }; -function checkClassInstance(workInProgress, ctor, newProps) { - var instance = workInProgress.stateNode; + var setToSortedString = function (set) { + var array = []; + set.forEach(function (value) { + array.push(value); + }); + return array.sort().join(", "); + }; - { - var name = getComponentNameFromType(ctor) || "Component"; - var renderPresent = instance.render; + var pendingComponentWillMountWarnings = []; + var pendingUNSAFE_ComponentWillMountWarnings = []; + var pendingComponentWillReceivePropsWarnings = []; + var pendingUNSAFE_ComponentWillReceivePropsWarnings = []; + var pendingComponentWillUpdateWarnings = []; + var pendingUNSAFE_ComponentWillUpdateWarnings = []; // Tracks components we have already warned about. - 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 - ); - } - } + var didWarnAboutUnsafeLifecycles = new Set(); - 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 - ); - } + ReactStrictModeWarnings.recordUnsafeLifecycleWarnings = function ( + fiber, + instance + ) { + // Dedupe strategy: Warn once per component. + if (didWarnAboutUnsafeLifecycles.has(fiber.type)) { + return; + } - 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 ( + typeof instance.componentWillMount === "function" && // Don't warn about react-lifecycles-compat polyfilled components. + instance.componentWillMount.__suppressDeprecationWarning !== true + ) { + pendingComponentWillMountWarnings.push(fiber); + } - if (instance.propTypes) { - error( - "propTypes was defined as an instance property on %s. Use a static " + - "property to define propTypes instead.", - name - ); - } + if ( + fiber.mode & StrictLegacyMode && + typeof instance.UNSAFE_componentWillMount === "function" + ) { + pendingUNSAFE_ComponentWillMountWarnings.push(fiber); + } - if (instance.contextType) { - error( - "contextType was defined as an instance property on %s. Use a static " + - "property to define contextType instead.", - name - ); - } + if ( + typeof instance.componentWillReceiveProps === "function" && + instance.componentWillReceiveProps.__suppressDeprecationWarning !== true + ) { + pendingComponentWillReceivePropsWarnings.push(fiber); + } - { - if (instance.contextTypes) { - error( - "contextTypes was defined as an instance property on %s. Use a static " + - "property to define contextTypes instead.", - name - ); - } + if ( + fiber.mode & StrictLegacyMode && + typeof instance.UNSAFE_componentWillReceiveProps === "function" + ) { + pendingUNSAFE_ComponentWillReceivePropsWarnings.push(fiber); + } - if ( - ctor.contextType && - ctor.contextTypes && - !didWarnAboutContextTypeAndContextTypes.has(ctor) - ) { - didWarnAboutContextTypeAndContextTypes.add(ctor); + if ( + typeof instance.componentWillUpdate === "function" && + instance.componentWillUpdate.__suppressDeprecationWarning !== true + ) { + pendingComponentWillUpdateWarnings.push(fiber); + } - error( - "%s declares both contextTypes and contextType static properties. " + - "The legacy contextTypes property will be ignored.", - name - ); - } - } + if ( + fiber.mode & StrictLegacyMode && + typeof instance.UNSAFE_componentWillUpdate === "function" + ) { + pendingUNSAFE_ComponentWillUpdateWarnings.push(fiber); + } + }; - 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 - ); - } + ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings = function () { + // We do an initial pass to gather component names + var componentWillMountUniqueNames = new Set(); - 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" - ); - } + if (pendingComponentWillMountWarnings.length > 0) { + pendingComponentWillMountWarnings.forEach(function (fiber) { + componentWillMountUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingComponentWillMountWarnings = []; + } - if (typeof instance.componentDidUnmount === "function") { - error( - "%s has a method called " + - "componentDidUnmount(). But there is no such lifecycle method. " + - "Did you mean componentWillUnmount()?", - name - ); - } + var UNSAFE_componentWillMountUniqueNames = new Set(); - 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 - ); - } + if (pendingUNSAFE_ComponentWillMountWarnings.length > 0) { + pendingUNSAFE_ComponentWillMountWarnings.forEach(function (fiber) { + UNSAFE_componentWillMountUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingUNSAFE_ComponentWillMountWarnings = []; + } - if (typeof instance.componentWillRecieveProps === "function") { - error( - "%s has a method called " + - "componentWillRecieveProps(). Did you mean componentWillReceiveProps()?", - name - ); - } + var componentWillReceivePropsUniqueNames = new Set(); - if (typeof instance.UNSAFE_componentWillRecieveProps === "function") { - error( - "%s has a method called " + - "UNSAFE_componentWillRecieveProps(). Did you mean UNSAFE_componentWillReceiveProps()?", - name - ); - } + if (pendingComponentWillReceivePropsWarnings.length > 0) { + pendingComponentWillReceivePropsWarnings.forEach(function (fiber) { + componentWillReceivePropsUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingComponentWillReceivePropsWarnings = []; + } - var hasMutatedProps = instance.props !== newProps; + var UNSAFE_componentWillReceivePropsUniqueNames = new Set(); - 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 (pendingUNSAFE_ComponentWillReceivePropsWarnings.length > 0) { + pendingUNSAFE_ComponentWillReceivePropsWarnings.forEach(function (fiber) { + UNSAFE_componentWillReceivePropsUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingUNSAFE_ComponentWillReceivePropsWarnings = []; + } - 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 componentWillUpdateUniqueNames = new Set(); - if ( - typeof instance.getSnapshotBeforeUpdate === "function" && - typeof instance.componentDidUpdate !== "function" && - !didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate.has(ctor) - ) { - didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate.add(ctor); + if (pendingComponentWillUpdateWarnings.length > 0) { + pendingComponentWillUpdateWarnings.forEach(function (fiber) { + componentWillUpdateUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingComponentWillUpdateWarnings = []; + } - error( - "%s: getSnapshotBeforeUpdate() should be used with componentDidUpdate(). " + - "This component defines getSnapshotBeforeUpdate() only.", - getComponentNameFromType(ctor) - ); - } + var UNSAFE_componentWillUpdateUniqueNames = new Set(); - 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 (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 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 (UNSAFE_componentWillMountUniqueNames.size > 0) { + var sortedNames = setToSortedString(UNSAFE_componentWillMountUniqueNames); - 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 - ); - } + error( + "Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code. " + + "See https://react.dev/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 + ); + } - var _state = instance.state; + if (UNSAFE_componentWillReceivePropsUniqueNames.size > 0) { + var _sortedNames = setToSortedString( + UNSAFE_componentWillReceivePropsUniqueNames + ); - if (_state && (typeof _state !== "object" || isArray(_state))) { - error("%s.state: must be set to an object or null", name); - } + error( + "Using UNSAFE_componentWillReceiveProps in strict mode is not recommended " + + "and may indicate bugs in your code. " + + "See https://react.dev/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://react.dev/link/derived-state\n" + + "\nPlease update the following components: %s", + _sortedNames + ); + } - if ( - typeof instance.getChildContext === "function" && - typeof ctor.childContextTypes !== "object" - ) { - error( - "%s.getChildContext(): childContextTypes must be defined in order to " + - "use getChildContext().", - name - ); - } - } -} + if (UNSAFE_componentWillUpdateUniqueNames.size > 0) { + var _sortedNames2 = setToSortedString( + UNSAFE_componentWillUpdateUniqueNames + ); + + error( + "Using UNSAFE_componentWillUpdate in strict mode is not recommended " + + "and may indicate bugs in your code. " + + "See https://react.dev/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 adoptClassInstance(workInProgress, instance) { - instance.updater = classComponentUpdater; - workInProgress.stateNode = instance; // The instance needs access to the fiber so that it can schedule updates + if (componentWillMountUniqueNames.size > 0) { + var _sortedNames3 = setToSortedString(componentWillMountUniqueNames); - set(instance, workInProgress); + warn( + "componentWillMount has been renamed, and is not recommended for use. " + + "See https://react.dev/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 + ); + } - { - instance._reactInternalInstance = fakeInternalInstance; - } -} + if (componentWillReceivePropsUniqueNames.size > 0) { + var _sortedNames4 = setToSortedString( + componentWillReceivePropsUniqueNames + ); -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(", ") + - "}."; + warn( + "componentWillReceiveProps has been renamed, and is not recommended for use. " + + "See https://react.dev/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://react.dev/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 + ); } - error( - "%s defines an invalid contextType. " + - "contextType should point to the Context object returned by React.createContext().%s", - getComponentNameFromType(ctor) || "Component", - addendum - ); - } - } - } + if (componentWillUpdateUniqueNames.size > 0) { + var _sortedNames5 = setToSortedString(componentWillUpdateUniqueNames); - 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; - } + warn( + "componentWillUpdate has been renamed, and is not recommended for use. " + + "See https://react.dev/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 instance = new ctor(props, context); // Instantiate twice to help detect side-effects. + var pendingLegacyContextWarning = new Map(); // Tracks components we have already warned about. - var state = (workInProgress.memoizedState = - instance.state !== null && instance.state !== undefined - ? instance.state - : null); - adoptClassInstance(workInProgress, instance); + var didWarnAboutLegacyContext = new Set(); - { - if (typeof ctor.getDerivedStateFromProps === "function" && state === null) { - var componentName = getComponentNameFromType(ctor) || "Component"; + ReactStrictModeWarnings.recordLegacyContextWarning = function ( + fiber, + instance + ) { + var strictRoot = findStrictRoot(fiber); - if (!didWarnAboutUninitializedState.has(componentName)) { - didWarnAboutUninitializedState.add(componentName); + 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." + ); - 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. + return; + } // Dedup strategy: Warn once per component. - if ( - typeof ctor.getDerivedStateFromProps === "function" || - typeof instance.getSnapshotBeforeUpdate === "function" - ) { - var foundWillMountName = null; - var foundWillReceivePropsName = null; - var foundWillUpdateName = null; + if (didWarnAboutLegacyContext.has(fiber.type)) { + return; + } - if ( - typeof instance.componentWillMount === "function" && - instance.componentWillMount.__suppressDeprecationWarning !== true - ) { - foundWillMountName = "componentWillMount"; - } else if (typeof instance.UNSAFE_componentWillMount === "function") { - foundWillMountName = "UNSAFE_componentWillMount"; - } + var warningsForRoot = pendingLegacyContextWarning.get(strictRoot); - if ( - typeof instance.componentWillReceiveProps === "function" && - instance.componentWillReceiveProps.__suppressDeprecationWarning !== true - ) { - foundWillReceivePropsName = "componentWillReceiveProps"; - } else if ( - typeof instance.UNSAFE_componentWillReceiveProps === "function" - ) { - foundWillReceivePropsName = "UNSAFE_componentWillReceiveProps"; - } + if ( + fiber.type.contextTypes != null || + fiber.type.childContextTypes != null || + (instance !== null && typeof instance.getChildContext === "function") + ) { + if (warningsForRoot === undefined) { + warningsForRoot = []; + pendingLegacyContextWarning.set(strictRoot, warningsForRoot); + } - if ( - typeof instance.componentWillUpdate === "function" && - instance.componentWillUpdate.__suppressDeprecationWarning !== true - ) { - foundWillUpdateName = "componentWillUpdate"; - } else if (typeof instance.UNSAFE_componentWillUpdate === "function") { - foundWillUpdateName = "UNSAFE_componentWillUpdate"; - } + warningsForRoot.push(fiber); + } + }; - if ( - foundWillMountName !== null || - foundWillReceivePropsName !== null || - foundWillUpdateName !== null - ) { - var _componentName = getComponentNameFromType(ctor) || "Component"; + ReactStrictModeWarnings.flushLegacyContextWarning = function () { + pendingLegacyContextWarning.forEach(function (fiberArray, strictRoot) { + if (fiberArray.length === 0) { + return; + } + + 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://react.dev/link/legacy-context", + sortedNames + ); + } finally { + resetCurrentFiber(); + } + }); + }; + + ReactStrictModeWarnings.discardPendingWarnings = function () { + pendingComponentWillMountWarnings = []; + pendingUNSAFE_ComponentWillMountWarnings = []; + pendingComponentWillReceivePropsWarnings = []; + pendingUNSAFE_ComponentWillReceivePropsWarnings = []; + pendingComponentWillUpdateWarnings = []; + pendingUNSAFE_ComponentWillUpdateWarnings = []; + pendingLegacyContextWarning = new Map(); + }; + } - var newApiName = - typeof ctor.getDerivedStateFromProps === "function" - ? "getDerivedStateFromProps()" - : "getSnapshotBeforeUpdate()"; + /* + * The `'' + value` pattern (used in 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 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"; + return type; + } + } // $FlowFixMe only called in DEV, so void return is not possible. + + function willCoercionThrow(value) { + { + try { + testStringCoercion(value); + return false; + } catch (e) { + return true; + } + } + } - if (!didWarnAboutLegacyLifecyclesAndDerivedState.has(_componentName)) { - didWarnAboutLegacyLifecyclesAndDerivedState.add(_componentName); + 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 before using it here.", + typeName(value) + ); + return testStringCoercion(value); // throw (to help callers find troubleshooting comments) + } + } + } + function checkPropStringCoercion(value, propName) { + { + if (willCoercionThrow(value)) { 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://react.dev/link/unsafe-component-lifecycles", - _componentName, - newApiName, - foundWillMountName !== null ? "\n " + foundWillMountName : "", - foundWillReceivePropsName !== null - ? "\n " + foundWillReceivePropsName - : "", - foundWillUpdateName !== null ? "\n " + foundWillUpdateName : "" + "The provided `%s` prop is an unsupported type %s." + + " This value must be coerced to a string before before using it here.", + propName, + typeName(value) ); + + return testStringCoercion(value); // throw (to help callers find troubleshooting comments) } } } - } // 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); - } + function resolveDefaultProps(Component, baseProps) { + if (Component && Component.defaultProps) { + // Resolve default props. Taken from ReactElement + var props = assign({}, baseProps); + var defaultProps = Component.defaultProps; - return instance; -} + for (var propName in defaultProps) { + if (props[propName] === undefined) { + props[propName] = defaultProps[propName]; + } + } -function callComponentWillMount(workInProgress, instance) { - var oldState = instance.state; + return props; + } - if (typeof instance.componentWillMount === "function") { - instance.componentWillMount(); - } + return baseProps; + } - if (typeof instance.UNSAFE_componentWillMount === "function") { - instance.UNSAFE_componentWillMount(); - } + var valueCursor = createCursor(null); + var rendererSigil; - 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" - ); + // Use this to detect multiple renderers using the same context + rendererSigil = {}; } - classComponentUpdater.enqueueReplaceState(instance, instance.state, null); - } -} - -function callComponentWillReceiveProps( - workInProgress, - instance, - newProps, - nextContext -) { - var oldState = instance.state; - - if (typeof instance.componentWillReceiveProps === "function") { - instance.componentWillReceiveProps(newProps, nextContext); - } + 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; - if (typeof instance.UNSAFE_componentWillReceiveProps === "function") { - instance.UNSAFE_componentWillReceiveProps(newProps, nextContext); - } - - if (instance.state !== oldState) { - { - var componentName = - getComponentNameFromFiber(workInProgress) || "Component"; + { + isDisallowedContextReadInDEV = false; + } + } + function enterDisallowedContextReadInDEV() { + { + isDisallowedContextReadInDEV = true; + } + } + function exitDisallowedContextReadInDEV() { + { + isDisallowedContextReadInDEV = false; + } + } + function pushProvider(providerFiber, context, nextValue) { + { + push(valueCursor, context._currentValue, providerFiber); + context._currentValue = nextValue; - if (!didWarnAboutStateAssignmentForComponent.has(componentName)) { - didWarnAboutStateAssignmentForComponent.add(componentName); + { + if ( + context._currentRenderer !== undefined && + context._currentRenderer !== null && + context._currentRenderer !== rendererSigil + ) { + error( + "Detected multiple renderers concurrently rendering the " + + "same context provider. This is currently unsupported." + ); + } - error( - "%s.componentWillReceiveProps(): Assigning directly to " + - "this.state is deprecated (except inside a component's " + - "constructor). Use setState instead.", - componentName - ); + context._currentRenderer = rendererSigil; + } } } + function popProvider(context, providerFiber) { + var currentValue = valueCursor.current; + pop(valueCursor, providerFiber); - classComponentUpdater.enqueueReplaceState(instance, instance.state, null); - } -} // Invokes the mount life-cycles on a previously never rendered instance. + { + { + context._currentValue = currentValue; + } + } + } + function scheduleContextWorkOnParentPath(parent, renderLanes, propagationRoot) { + // Update the child lanes of all the ancestors, including the alternates. + var node = parent; -function mountClassInstance(workInProgress, ctor, newProps, renderLanes) { - { - checkClassInstance(workInProgress, ctor, newProps); - } + while (node !== null) { + var alternate = node.alternate; - var instance = workInProgress.stateNode; - instance.props = newProps; - instance.state = workInProgress.memoizedState; - instance.refs = emptyRefsObject; - initializeUpdateQueue(workInProgress); - var contextType = ctor.contextType; + if (!isSubsetOfLanes(node.childLanes, renderLanes)) { + node.childLanes = mergeLanes(node.childLanes, renderLanes); - if (typeof contextType === "object" && contextType !== null) { - instance.context = readContext(contextType); - } else { - var unmaskedContext = getUnmaskedContext(workInProgress, ctor, true); - instance.context = getMaskedContext(workInProgress, unmaskedContext); - } + if (alternate !== null) { + alternate.childLanes = mergeLanes(alternate.childLanes, renderLanes); + } + } else if ( + alternate !== null && + !isSubsetOfLanes(alternate.childLanes, renderLanes) + ) { + alternate.childLanes = mergeLanes(alternate.childLanes, renderLanes); + } - { - if (instance.state === newProps) { - var componentName = getComponentNameFromType(ctor) || "Component"; + if (node === propagationRoot) { + break; + } - if (!didWarnAboutDirectlyAssigningPropsToState.has(componentName)) { - didWarnAboutDirectlyAssigningPropsToState.add(componentName); + node = node.return; + } - 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 (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." + ); + } } } - - if (workInProgress.mode & StrictLegacyMode) { - ReactStrictModeWarnings.recordLegacyContextWarning( - workInProgress, - instance - ); + function propagateContextChange(workInProgress, context, renderLanes) { + { + propagateContextChange_eager(workInProgress, context, renderLanes); + } } - { - ReactStrictModeWarnings.recordUnsafeLifecycleWarnings( - workInProgress, - instance - ); - } - } + function propagateContextChange_eager(workInProgress, context, renderLanes) { + var fiber = workInProgress.child; - instance.state = workInProgress.memoizedState; - var getDerivedStateFromProps = ctor.getDerivedStateFromProps; + if (fiber !== null) { + // Set the return pointer of the child to the work-in-progress fiber. + fiber.return = workInProgress; + } - 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") { - var fiberFlags = Update; - - workInProgress.flags |= fiberFlags; - } -} + while (fiber !== null) { + var nextFiber = void 0; // Visit this fiber. -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 - ); - } - } - - 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") { - var fiberFlags = Update; + var list = fiber.dependencies; - workInProgress.flags |= fiberFlags; - } + if (list !== null) { + nextFiber = fiber.child; + var dependency = list.firstContext; - return false; - } + 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(NoTimestamp, 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 (typeof getDerivedStateFromProps === "function") { - applyDerivedStateFromProps( - workInProgress, - ctor, - getDerivedStateFromProps, - newProps - ); - newState = workInProgress.memoizedState; - } + var updateQueue = fiber.updateQueue; - var shouldUpdate = - checkHasForceUpdateAfterProcessing() || - checkShouldComponentUpdate( - workInProgress, - ctor, - oldProps, - newProps, - oldState, - newState, - nextContext - ); + if (updateQueue === null); + else { + var sharedQueue = updateQueue.shared; + var pending = sharedQueue.pending; - 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(); - } + if (pending === null) { + // This is the first update. Create a circular list. + update.next = update; + } else { + update.next = pending.next; + pending.next = update; + } - if (typeof instance.UNSAFE_componentWillMount === "function") { - instance.UNSAFE_componentWillMount(); - } - } + sharedQueue.pending = update; + } + } - if (typeof instance.componentDidMount === "function") { - var _fiberFlags = Update; - - workInProgress.flags |= _fiberFlags; - } - } 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") { - var _fiberFlags2 = Update; - - workInProgress.flags |= _fiberFlags2; - } // 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( - 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 - ) { - // 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; - } - } + fiber.lanes = mergeLanes(fiber.lanes, renderLanes); + var alternate = fiber.alternate; - if (typeof instance.getSnapshotBeforeUpdate === "function") { - if ( - unresolvedOldProps !== current.memoizedProps || - oldState !== current.memoizedState - ) { - workInProgress.flags |= Snapshot; - } - } + if (alternate !== null) { + alternate.lanes = mergeLanes(alternate.lanes, renderLanes); + } - return false; - } + scheduleContextWorkOnParentPath( + fiber.return, + renderLanes, + workInProgress + ); // Mark the updated lanes on the list, too. - if (typeof getDerivedStateFromProps === "function") { - applyDerivedStateFromProps( - workInProgress, - ctor, - getDerivedStateFromProps, - newProps - ); - newState = workInProgress.memoizedState; - } + list.lanes = mergeLanes(list.lanes, renderLanes); // Since we already found a match, we can stop traversing the + // dependency list. - 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; - - 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); - } + break; + } - if (typeof instance.UNSAFE_componentWillUpdate === "function") { - instance.UNSAFE_componentWillUpdate(newProps, newState, nextContext); - } - } + 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." + ); + } - if (typeof instance.componentDidUpdate === "function") { - workInProgress.flags |= Update; - } + parentSuspense.lanes = mergeLanes(parentSuspense.lanes, renderLanes); + var _alternate = parentSuspense.alternate; - 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 (_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. - 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. + scheduleContextWorkOnParentPath( + parentSuspense, + renderLanes, + workInProgress + ); + nextFiber = fiber.sibling; + } else { + // Traverse down. + nextFiber = fiber.child; + } - workInProgress.memoizedProps = newProps; - workInProgress.memoizedState = newState; - } // Update the existing instance's state, props, and context pointers even - // if shouldComponentUpdate returns false. + 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; + } - instance.props = newProps; - instance.state = newState; - instance.context = nextContext; - return shouldUpdate; -} + var sibling = nextFiber.sibling; -var didWarnAboutMaps; -var didWarnAboutGenerators; -var didWarnAboutStringRefs; -var ownerHasKeyUseWarning; -var ownerHasFunctionTypeWarning; + 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. -var warnForMissingKey = function(child, returnFiber) {}; + nextFiber = nextFiber.return; + } + } -{ - 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. - */ + fiber = nextFiber; + } + } + function prepareToReadContext(workInProgress, renderLanes) { + currentlyRenderingFiber = workInProgress; + lastContextDependency = null; + lastFullyObservedContext = null; + var dependencies = workInProgress.dependencies; - ownerHasKeyUseWarning = {}; - ownerHasFunctionTypeWarning = {}; + if (dependencies !== null) { + { + var firstContext = dependencies.firstContext; - warnForMissingKey = function(child, returnFiber) { - if (child === null || typeof child !== "object") { - return; - } + 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 (!child._store || child._store.validated || child.key != null) { - return; + 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()." + ); + } + } - 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." - ); - } + var value = context._currentValue; - child._store.validated = true; - var componentName = getComponentNameFromFiber(returnFiber) || "Component"; + if (lastFullyObservedContext === context); + else { + var contextItem = { + context: context, + memoizedValue: value, + next: null + }; - if (ownerHasKeyUseWarning[componentName]) { - return; - } + if (lastContextDependency === null) { + if (currentlyRenderingFiber === 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. - ownerHasKeyUseWarning[componentName] = true; + lastContextDependency = contextItem; + currentlyRenderingFiber.dependencies = { + lanes: NoLanes, + firstContext: contextItem + }; + } else { + // Append a new context item. + lastContextDependency = lastContextDependency.next = contextItem; + } + } - error( - "Each child in a list should have a unique " + - '"key" prop. See https://react.dev/link/warning-keys for ' + - "more information." - ); - }; -} + return value; + } -function coerceRef(returnFiber, current, element) { - var mixedRef = element.ref; + // render. When this render exits, either because it finishes or because it is + // interrupted, the interleaved updates will be transferred onto the main part + // of the queue. - if ( - mixedRef !== null && - typeof mixedRef !== "function" && - typeof mixedRef !== "object" - ) { - { - // TODO: Clean this up once we turn on the string ref warning for - // everyone, because the strict mode case will no longer be relevant - if ( - (returnFiber.mode & StrictLegacyMode || warnAboutStringRefs) && // 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 - ) - ) { - var componentName = - getComponentNameFromFiber(returnFiber) || "Component"; + var concurrentQueues = null; + function pushConcurrentUpdateQueue(queue) { + if (concurrentQueues === null) { + concurrentQueues = [queue]; + } else { + concurrentQueues.push(queue); + } + } + function finishQueueingConcurrentUpdates() { + // Transfer the interleaved updates onto the main queue. Each queue has a + // `pending` field and an `interleaved` field. When they are not null, they + // point to the last node in a circular linked list. We need to append the + // interleaved list to the end of the pending list by joining them into a + // single, circular list. + if (concurrentQueues !== null) { + for (var i = 0; i < concurrentQueues.length; i++) { + var queue = concurrentQueues[i]; + var lastInterleavedUpdate = queue.interleaved; + + if (lastInterleavedUpdate !== null) { + queue.interleaved = null; + var firstInterleavedUpdate = lastInterleavedUpdate.next; + var lastPendingUpdate = queue.pending; + + if (lastPendingUpdate !== null) { + var firstPendingUpdate = lastPendingUpdate.next; + lastPendingUpdate.next = firstInterleavedUpdate; + lastInterleavedUpdate.next = firstPendingUpdate; + } - if (!didWarnAboutStringRefs[componentName]) { - { - error( - 'A string ref, "%s", has been found within a strict mode tree. ' + - "String refs are a source of potential bugs and should be avoided. " + - "We recommend using useRef() or createRef() instead. " + - "Learn more about using refs safely here: " + - "https://react.dev/link/strict-mode-string-ref", - mixedRef - ); + queue.pending = lastInterleavedUpdate; } - - didWarnAboutStringRefs[componentName] = true; } + + concurrentQueues = null; } } + function enqueueConcurrentHookUpdate(fiber, queue, update, lane) { + var interleaved = queue.interleaved; - if (element._owner) { - var owner = element._owner; - var inst; + if (interleaved === null) { + // This is the first update. Create a circular list. + update.next = update; // At the end of the current render, this queue's interleaved updates will + // be transferred to the pending queue. - if (owner) { - var ownerFiber = owner; + pushConcurrentUpdateQueue(queue); + } else { + update.next = interleaved.next; + interleaved.next = update; + } - 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://react.dev/link/strict-mode-string-ref" - ); - } + queue.interleaved = update; + return markUpdateLaneFromFiberToRoot(fiber, lane); + } + function enqueueConcurrentHookUpdateAndEagerlyBailout( + fiber, + queue, + update, + lane + ) { + var interleaved = queue.interleaved; - inst = ownerFiber.stateNode; + if (interleaved === null) { + // This is the first update. Create a circular list. + update.next = update; // At the end of the current render, this queue's interleaved updates will + // be transferred to the pending queue. + + pushConcurrentUpdateQueue(queue); + } else { + update.next = interleaved.next; + interleaved.next = update; } - 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 + queue.interleaved = update; + } + function enqueueConcurrentClassUpdate(fiber, queue, update, lane) { + var interleaved = queue.interleaved; - var resolvedInst = inst; + if (interleaved === null) { + // This is the first update. Create a circular list. + update.next = update; // At the end of the current render, this queue's interleaved updates will + // be transferred to the pending queue. - { - checkPropStringCoercion(mixedRef, "ref"); + pushConcurrentUpdateQueue(queue); + } else { + update.next = interleaved.next; + interleaved.next = update; } - var stringRef = "" + mixedRef; // Check if previous string ref matches new string ref + queue.interleaved = update; + return markUpdateLaneFromFiberToRoot(fiber, lane); + } + function enqueueConcurrentRenderForLane(fiber, lane) { + return markUpdateLaneFromFiberToRoot(fiber, lane); + } // Calling this function outside this module should only be done for backwards + // compatibility and should always be accompanied by a warning. + + var unsafe_markUpdateLaneFromFiberToRoot = markUpdateLaneFromFiberToRoot; - if ( - current !== null && - current.ref !== null && - typeof current.ref === "function" && - current.ref._stringRef === stringRef - ) { - return current.ref; - } + function markUpdateLaneFromFiberToRoot(sourceFiber, lane) { + // Update the source fiber's lanes + sourceFiber.lanes = mergeLanes(sourceFiber.lanes, lane); + var alternate = sourceFiber.alternate; - var ref = function(value) { - var refs = resolvedInst.refs; + if (alternate !== null) { + alternate.lanes = mergeLanes(alternate.lanes, lane); + } - if (refs === emptyRefsObject) { - // This is a lazy pooled frozen object, so we need to initialize. - refs = resolvedInst.refs = {}; + { + if ( + alternate === null && + (sourceFiber.flags & (Placement | Hydrating)) !== NoFlags + ) { + warnAboutUpdateOnNotYetMountedFiberInDEV(sourceFiber); } + } // Walk the parent path to the root and update the child lanes. + + var node = sourceFiber; + var parent = sourceFiber.return; + + while (parent !== null) { + parent.childLanes = mergeLanes(parent.childLanes, lane); + alternate = parent.alternate; - if (value === null) { - delete refs[stringRef]; + if (alternate !== null) { + alternate.childLanes = mergeLanes(alternate.childLanes, lane); } else { - refs[stringRef] = value; + { + if ((parent.flags & (Placement | Hydrating)) !== NoFlags) { + warnAboutUpdateOnNotYetMountedFiberInDEV(sourceFiber); + } + } } - }; - 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." - ); + node = parent; + parent = parent.return; } - 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://react.dev/link/refs-must-have-owner for more information." - ); + if (node.tag === HostRoot) { + var root = node.stateNode; + return root; + } else { + return null; } } - } - return mixedRef; -} + 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`. -function throwOnInvalidObjectType(returnFiber, newChild) { - 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." - ); -} + var hasForceUpdate = false; + var didWarnUpdateInsideUpdate; + var currentlyProcessingQueue; -function warnOnFunctionType(returnFiber) { - { - var componentName = getComponentNameFromFiber(returnFiber) || "Component"; + { + didWarnUpdateInsideUpdate = false; + currentlyProcessingQueue = null; + } + + function initializeUpdateQueue(fiber) { + var queue = { + baseState: fiber.memoizedState, + firstBaseUpdate: null, + lastBaseUpdate: null, + shared: { + pending: null, + interleaved: null, + lanes: NoLanes + }, + effects: 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 (ownerHasFunctionTypeWarning[componentName]) { - return; + if (queue === currentQueue) { + var clone = { + baseState: currentQueue.baseState, + firstBaseUpdate: currentQueue.firstBaseUpdate, + lastBaseUpdate: currentQueue.lastBaseUpdate, + shared: currentQueue.shared, + effects: currentQueue.effects + }; + workInProgress.updateQueue = clone; + } + } + function createUpdate(eventTime, lane) { + var update = { + eventTime: eventTime, + lane: lane, + tag: UpdateState, + payload: null, + callback: null, + next: null + }; + return update; } + function enqueueUpdate(fiber, update, lane) { + var updateQueue = fiber.updateQueue; - ownerHasFunctionTypeWarning[componentName] = true; + if (updateQueue === null) { + // Only occurs if the fiber has been unmounted. + return null; + } - 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." - ); - } -} + var sharedQueue = updateQueue.shared; -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 ( + currentlyProcessingQueue === sharedQueue && + !didWarnUpdateInsideUpdate + ) { + 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." + ); -function ChildReconciler(shouldTrackSideEffects) { - function deleteChild(returnFiber, childToDelete) { - if (!shouldTrackSideEffects) { - // Noop. - return; - } + didWarnUpdateInsideUpdate = true; + } + } + + 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 (pending === null) { + // This is the first update. Create a circular list. + update.next = update; + } else { + update.next = pending.next; + pending.next = update; + } - var deletions = returnFiber.deletions; + 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 (deletions === null) { - returnFiber.deletions = [childToDelete]; - returnFiber.flags |= ChildDeletion; - } else { - deletions.push(childToDelete); + return unsafe_markUpdateLaneFromFiberToRoot(fiber, lane); + } else { + return enqueueConcurrentClassUpdate(fiber, sharedQueue, update, lane); + } } - } + function entangleTransitions(root, fiber, lane) { + var updateQueue = fiber.updateQueue; - 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. + if (updateQueue === null) { + // Only occurs if the fiber has been unmounted. + return; + } - var childToDelete = currentFirstChild; + var sharedQueue = updateQueue.shared; - while (childToDelete !== null) { - deleteChild(returnFiber, childToDelete); - childToDelete = childToDelete.sibling; - } + 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. - return null; - } + queueLanes = intersectLanes(queueLanes, root.pendingLanes); // Entangle the new transition lane with the other transition lanes. - 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 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. - while (existingChild !== null) { - if (existingChild.key !== null) { - existingChildren.set(existingChild.key, existingChild); - } else { - existingChildren.set(existingChild.index, existingChild); + markRootEntangled(root, newQueueLanes); } - - existingChild = existingChild.sibling; } + 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; - return existingChildren; - } + 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 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; - } + do { + var clone = { + eventTime: update.eventTime, + lane: update.lane, + tag: update.tag, + payload: update.payload, + callback: update.callback, + next: null + }; + + if (newLast === null) { + newFirst = newLast = clone; + } else { + newLast.next = clone; + newLast = clone; + } - function placeChild(newFiber, lastPlacedIndex, newIndex) { - newFiber.index = newIndex; + update = update.next; + } while (update !== null); // Append the captured update the end of the cloned list. - 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; - } + if (newLast === null) { + newFirst = newLast = capturedUpdate; + } else { + newLast.next = capturedUpdate; + newLast = capturedUpdate; + } + } else { + // There are no base updates. + newFirst = newLast = capturedUpdate; + } - var current = newFiber.alternate; + queue = { + baseState: currentQueue.baseState, + firstBaseUpdate: newFirst, + lastBaseUpdate: newLast, + shared: currentQueue.shared, + effects: currentQueue.effects + }; + workInProgress.updateQueue = queue; + return; + } + } // Append the update to the end of the list. - if (current !== null) { - var oldIndex = current.index; + var lastBaseUpdate = queue.lastBaseUpdate; - if (oldIndex < lastPlacedIndex) { - // This is a move. - newFiber.flags |= Placement; - return lastPlacedIndex; + if (lastBaseUpdate === null) { + queue.firstBaseUpdate = capturedUpdate; } else { - // This item can stay in place. - return oldIndex; + lastBaseUpdate.next = capturedUpdate; } - } else { - // This is an insertion. - newFiber.flags |= Placement; - 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; + queue.lastBaseUpdate = capturedUpdate; } - return newFiber; - } + function getStateFromUpdate( + workInProgress, + queue, + update, + prevState, + nextProps, + instance + ) { + switch (update.tag) { + case ReplaceState: { + var payload = update.payload; - 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; + var nextState = payload.call(instance, prevState, nextProps); - if (elementType === REACT_FRAGMENT_TYPE) { - return updateFragment( - returnFiber, - current, - element.props.children, - lanes, - element.key - ); - } + { + exitDisallowedContextReadInDEV(); + } - 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; + return nextState; + } // State object - { - existing._debugSource = element._source; - existing._debugOwner = element._owner; + return payload; } - return existing; - } - } // Insert + case CaptureUpdate: { + workInProgress.flags = + (workInProgress.flags & ~ShouldCapture) | DidCapture; + } + // Intentional fallthrough - var created = createFiberFromElement(element, returnFiber.mode, lanes); - created.ref = coerceRef(returnFiber, current, element); - created.return = returnFiber; - return created; - } + case UpdateState: { + var _payload = update.payload; + var partialState; - 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; - } - } + if (typeof _payload === "function") { + // Updater function + { + enterDisallowedContextReadInDEV(); + } - 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 - ); + partialState = _payload.call(instance, prevState, nextProps); - _created.ref = coerceRef(returnFiber, null, newChild); - _created.return = returnFiber; - return _created; - } + { + exitDisallowedContextReadInDEV(); + } + } else { + // Partial state object + partialState = _payload; + } - case REACT_PORTAL_TYPE: { - var _created2 = createFiberFromPortal( - newChild, - returnFiber.mode, - lanes - ); + if (partialState === null || partialState === undefined) { + // Null and undefined are treated as no-ops. + return prevState; + } // Merge the partial state and the previous state. - _created2.return = returnFiber; - return _created2; + return assign({}, prevState, partialState); } - case REACT_LAZY_TYPE: { - var payload = newChild._payload; - var init = newChild._init; - return createChild(returnFiber, init(payload), lanes); + case ForceUpdate: { + hasForceUpdate = true; + return prevState; } } - if (isArray(newChild) || getIteratorFn(newChild)) { - var _created3 = createFiberFromFragment( - newChild, - returnFiber.mode, - lanes, - null - ); + return prevState; + } + + function processUpdateQueue(workInProgress, props, instance, renderLanes) { + // This is always non-null on a ClassComponent or HostRoot + var queue = workInProgress.updateQueue; + hasForceUpdate = false; - _created3.return = returnFiber; - return _created3; + { + currentlyProcessingQueue = queue.shared; } - throwOnInvalidObjectType(returnFiber, newChild); - } + var firstBaseUpdate = queue.firstBaseUpdate; + var lastBaseUpdate = queue.lastBaseUpdate; // Check if there are pending updates. If so, transfer them to the base queue. - { - if (typeof newChild === "function") { - warnOnFunctionType(returnFiber); - } - } + var pendingQueue = queue.shared.pending; - return null; - } + 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. - function updateSlot(returnFiber, oldFiber, newChild, lanes) { - // Update the fiber if the keys match, otherwise return null. - var key = oldFiber !== null ? oldFiber.key : null; + var lastPendingUpdate = pendingQueue; + var firstPendingUpdate = lastPendingUpdate.next; + lastPendingUpdate.next = null; // Append pending updates to base queue - 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 (lastBaseUpdate === null) { + firstBaseUpdate = firstPendingUpdate; + } else { + lastBaseUpdate.next = firstPendingUpdate; + } - return updateTextNode(returnFiber, oldFiber, "" + newChild, 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 - 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; - } - } + var current = workInProgress.alternate; - case REACT_PORTAL_TYPE: { - if (newChild.key === key) { - return updatePortal(returnFiber, oldFiber, newChild, lanes); - } else { - return null; - } - } + if (current !== null) { + // This is always non-null on a ClassComponent or HostRoot + var currentQueue = current.updateQueue; + var currentLastBaseUpdate = currentQueue.lastBaseUpdate; - case REACT_LAZY_TYPE: { - var payload = newChild._payload; - var init = newChild._init; - return updateSlot(returnFiber, oldFiber, init(payload), lanes); - } - } + if (currentLastBaseUpdate !== lastBaseUpdate) { + if (currentLastBaseUpdate === null) { + currentQueue.firstBaseUpdate = firstPendingUpdate; + } else { + currentLastBaseUpdate.next = firstPendingUpdate; + } - if (isArray(newChild) || getIteratorFn(newChild)) { - if (key !== null) { - return null; + currentQueue.lastBaseUpdate = lastPendingUpdate; + } } + } // These values may change as we process the queue. - return updateFragment(returnFiber, oldFiber, newChild, 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; - throwOnInvalidObjectType(returnFiber, newChild); - } + do { + var updateLane = update.lane; + var updateEventTime = update.eventTime; + + if (!isSubsetOfLanes(renderLanes, updateLane)) { + // 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 = { + eventTime: updateEventTime, + 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. - { - if (typeof newChild === "function") { - warnOnFunctionType(returnFiber); - } - } + newLanes = mergeLanes(newLanes, updateLane); + } else { + // This update does have sufficient priority. + if (newLastBaseUpdate !== null) { + var _clone = { + eventTime: updateEventTime, + // 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, + callback: update.callback, + next: null + }; + newLastBaseUpdate = newLastBaseUpdate.next = _clone; + } // Process this update. + + newState = getStateFromUpdate( + workInProgress, + queue, + update, + newState, + props, + instance + ); + var callback = update.callback; - return null; - } + if ( + callback !== null && // If the update was already committed, we should not queue its + // callback again. + update.lane !== NoLane + ) { + workInProgress.flags |= Callback; + var effects = queue.effects; - 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 (effects === null) { + queue.effects = [update]; + } else { + effects.push(update); + } + } + } - if (typeof newChild === "object" && newChild !== null) { - switch (newChild.$$typeof) { - case REACT_ELEMENT_TYPE: { - var _matchedFiber = - existingChildren.get( - newChild.key === null ? newIdx : newChild.key - ) || null; + update = update.next; - return updateElement(returnFiber, _matchedFiber, newChild, lanes); - } + if (update === null) { + pendingQueue = queue.shared.pending; - case REACT_PORTAL_TYPE: { - var _matchedFiber2 = - existingChildren.get( - newChild.key === null ? newIdx : newChild.key - ) || 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); - return updatePortal(returnFiber, _matchedFiber2, newChild, lanes); + if (newLastBaseUpdate === null) { + newBaseState = newState; } - case REACT_LAZY_TYPE: - var payload = newChild._payload; - var init = newChild._init; - return updateFromMap( - existingChildren, - returnFiber, - newIdx, - init(payload), - lanes - ); + queue.baseState = newBaseState; + queue.firstBaseUpdate = newFirstBaseUpdate; + queue.lastBaseUpdate = newLastBaseUpdate; // Interleaved updates are stored on a separate queue. We aren't going to + // process them during this render, but we do need to track which lanes + // are remaining. + + var lastInterleaved = queue.shared.interleaved; + + if (lastInterleaved !== null) { + var interleaved = lastInterleaved; + + do { + newLanes = mergeLanes(newLanes, interleaved.lane); + interleaved = interleaved.next; + } while (interleaved !== lastInterleaved); + } else 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; } - if (isArray(newChild) || getIteratorFn(newChild)) { - var _matchedFiber3 = existingChildren.get(newIdx) || null; + { + currentlyProcessingQueue = null; + } + } - return updateFragment( - returnFiber, - _matchedFiber3, - newChild, - lanes, - null + 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 commitUpdateQueue(finishedWork, finishedQueue, instance) { + // Commit the effects + var effects = finishedQueue.effects; + finishedQueue.effects = null; - return null; - } - /** - * Warns if there is a duplicate or missing key - */ + if (effects !== null) { + for (var i = 0; i < effects.length; i++) { + var effect = effects[i]; + var callback = effect.callback; - function warnOnInvalidKey(child, knownKeys, returnFiber) { - { - if (typeof child !== "object" || child === null) { - return knownKeys; + if (callback !== null) { + effect.callback = null; + callCallback(callback, instance); + } + } } + } - switch (child.$$typeof) { - case REACT_ELEMENT_TYPE: - case REACT_PORTAL_TYPE: - warnForMissingKey(child, returnFiber); - var key = child.key; + var fakeInternalInstance = {}; // React.Component uses a shared frozen object by default. + // We'll use it to determine whether we need to initialize legacy refs. - if (typeof key !== "string") { - break; - } + var emptyRefsObject = new React.Component().refs; + var didWarnAboutStateAssignmentForComponent; + var didWarnAboutUninitializedState; + var didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate; + var didWarnAboutLegacyLifecyclesAndDerivedState; + var didWarnAboutUndefinedDerivedState; + var warnOnUndefinedDerivedState; + var warnOnInvalidCallback; + var didWarnAboutDirectlyAssigningPropsToState; + var didWarnAboutContextTypeAndContextTypes; + var didWarnAboutInvalidateContextType; - if (knownKeys === null) { - knownKeys = new Set(); - knownKeys.add(key); - break; - } + { + didWarnAboutStateAssignmentForComponent = new Set(); + didWarnAboutUninitializedState = new Set(); + didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate = new Set(); + didWarnAboutLegacyLifecyclesAndDerivedState = new Set(); + didWarnAboutDirectlyAssigningPropsToState = new Set(); + didWarnAboutUndefinedDerivedState = new Set(); + didWarnAboutContextTypeAndContextTypes = new Set(); + didWarnAboutInvalidateContextType = new Set(); + var didWarnOnInvalidCallback = new Set(); + + warnOnInvalidCallback = function (callback, callerName) { + if (callback === null || typeof callback === "function") { + return; + } - if (!knownKeys.has(key)) { - knownKeys.add(key); - break; - } + var key = callerName + "_" + callback; + + if (!didWarnOnInvalidCallback.has(key)) { + didWarnOnInvalidCallback.add(key); 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 + "%s(...): Expected the last optional `callback` argument to be a " + + "function. Instead received: %s.", + callerName, + callback ); + } + }; - break; + warnOnUndefinedDerivedState = function (type, partialState) { + if (partialState === undefined) { + var componentName = getComponentNameFromType(type) || "Component"; - case REACT_LAZY_TYPE: - var payload = child._payload; - var init = child._init; - warnOnInvalidKey(init(payload), knownKeys, returnFiber); - break; - } + if (!didWarnAboutUndefinedDerivedState.has(componentName)) { + didWarnAboutUndefinedDerivedState.add(componentName); + + error( + "%s.getDerivedStateFromProps(): A valid state object (or null) must be returned. " + + "You have returned undefined.", + componentName + ); + } + } + }; // 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); } - 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; + function applyDerivedStateFromProps( + workInProgress, + ctor, + getDerivedStateFromProps, + nextProps + ) { + var prevState = workInProgress.memoizedState; + var partialState = getDerivedStateFromProps(nextProps, prevState); - for (var i = 0; i < newChildren.length; i++) { - var child = newChildren[i]; - knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); - } - } + { + warnOnUndefinedDerivedState(ctor, partialState); + } // Merge the partial state and the previous state. - var resultingFirstChild = null; - var previousNewFiber = null; - var oldFiber = currentFirstChild; - var lastPlacedIndex = 0; - var newIdx = 0; - var nextOldFiber = null; + 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. - for (; oldFiber !== null && newIdx < newChildren.length; newIdx++) { - if (oldFiber.index > newIdx) { - nextOldFiber = oldFiber; - oldFiber = null; - } else { - nextOldFiber = oldFiber.sibling; + if (workInProgress.lanes === NoLanes) { + // Queue is always non-null for classes + var updateQueue = workInProgress.updateQueue; + updateQueue.baseState = memoizedState; } + } - var newFiber = updateSlot( - returnFiber, - oldFiber, - newChildren[newIdx], - lanes - ); + var classComponentUpdater = { + isMounted: isMounted, + enqueueSetState: function (inst, payload, callback) { + var fiber = get(inst); + var eventTime = requestEventTime(); + var lane = requestUpdateLane(fiber); + var update = createUpdate(eventTime, lane); + update.payload = payload; - 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 (callback !== undefined && callback !== null) { + { + warnOnInvalidCallback(callback, "setState"); + } + + update.callback = callback; } - break; - } + var root = enqueueUpdate(fiber, update, lane); - 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 (root !== null) { + scheduleUpdateOnFiber(root, fiber, lane, eventTime); + entangleTransitions(root, fiber, lane); } - } - - lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx); + }, + enqueueReplaceState: function (inst, payload, callback) { + var fiber = get(inst); + var eventTime = requestEventTime(); + var lane = requestUpdateLane(fiber); + var update = createUpdate(eventTime, lane); + update.tag = ReplaceState; + update.payload = payload; - 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 (callback !== undefined && callback !== null) { + { + warnOnInvalidCallback(callback, "replaceState"); + } - previousNewFiber = newFiber; - oldFiber = nextOldFiber; - } + update.callback = callback; + } - if (newIdx === newChildren.length) { - // We've reached the end of the new children. We can delete the rest. - deleteRemainingChildren(returnFiber, oldFiber); + var root = enqueueUpdate(fiber, update, lane); - return resultingFirstChild; - } + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, lane, eventTime); + entangleTransitions(root, fiber, lane); + } + }, + enqueueForceUpdate: function (inst, callback) { + var fiber = get(inst); + var eventTime = requestEventTime(); + var lane = requestUpdateLane(fiber); + var update = createUpdate(eventTime, lane); + update.tag = ForceUpdate; - 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 (callback !== undefined && callback !== null) { + { + warnOnInvalidCallback(callback, "forceUpdate"); + } - if (_newFiber === null) { - continue; + update.callback = callback; } - lastPlacedIndex = placeChild(_newFiber, lastPlacedIndex, newIdx); + var root = enqueueUpdate(fiber, update, lane); - if (previousNewFiber === null) { - // TODO: Move out of the loop. This only happens for the first run. - resultingFirstChild = _newFiber; - } else { - previousNewFiber.sibling = _newFiber; + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, lane, eventTime); + entangleTransitions(root, fiber, lane); } - - 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. + function checkShouldComponentUpdate( + workInProgress, + ctor, + oldProps, + newProps, + oldState, + newState, + nextContext + ) { + var instance = workInProgress.stateNode; - for (; newIdx < newChildren.length; newIdx++) { - var _newFiber2 = updateFromMap( - existingChildren, - returnFiber, - newIdx, - newChildren[newIdx], - lanes - ); + if (typeof instance.shouldComponentUpdate === "function") { + var shouldUpdate = instance.shouldComponentUpdate( + newProps, + newState, + nextContext + ); - 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 + { + if (shouldUpdate === undefined) { + error( + "%s.shouldComponentUpdate(): Returned undefined instead of a " + + "boolean value. Make sure to return true or false.", + getComponentNameFromType(ctor) || "Component" ); } } - lastPlacedIndex = placeChild(_newFiber2, lastPlacedIndex, newIdx); - - if (previousNewFiber === null) { - resultingFirstChild = _newFiber2; - } else { - previousNewFiber.sibling = _newFiber2; - } + return shouldUpdate; + } - previousNewFiber = _newFiber2; + if (ctor.prototype && ctor.prototype.isPureReactComponent) { + return ( + !shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState) + ); } - } - 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 true; } - return resultingFirstChild; - } + function checkClassInstance(workInProgress, ctor, newProps) { + var instance = workInProgress.stateNode; - function reconcileChildrenIterator( - returnFiber, - currentFirstChild, - newChildrenIterable, - lanes - ) { - // This is the same implementation as reconcileChildrenArray(), - // but using the iterator instead. - var iteratorFn = getIteratorFn(newChildrenIterable); + { + var name = getComponentNameFromType(ctor) || "Component"; + var renderPresent = instance.render; - 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." - ); - } + 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 + ); + } + } - { - // We don't support rendering Generators because it's a mutation. - // See https://github.com/facebook/react/issues/12995 - if ( - typeof Symbol === "function" && // $FlowFixMe Flow doesn't know about toStringTag - newChildrenIterable[Symbol.toStringTag] === "Generator" - ) { - if (!didWarnAboutGenerators) { + if ( + instance.getInitialState && + !instance.getInitialState.isReactClassApproved && + !instance.state + ) { 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." + "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 ); } - didWarnAboutGenerators = true; - } // Warn about using Maps as children - - if (newChildrenIterable.entries === iteratorFn) { - if (!didWarnAboutMaps) { + if ( + instance.getDefaultProps && + !instance.getDefaultProps.isReactClassApproved + ) { error( - "Using Maps as children is not supported. " + - "Use an array of keyed ReactElements instead." + "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 ); } - 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); + if (instance.propTypes) { + error( + "propTypes was defined as an instance property on %s. Use a static " + + "property to define propTypes instead.", + name + ); } - } - } - var newChildren = iteratorFn.call(newChildrenIterable); + if (instance.contextType) { + error( + "contextType was defined as an instance property on %s. Use a static " + + "property to define contextType instead.", + name + ); + } - if (newChildren == null) { - throw new Error("An iterable object provided no iterator."); - } + { + if (instance.contextTypes) { + error( + "contextTypes was defined as an instance property on %s. Use a static " + + "property to define contextTypes instead.", + name + ); + } - var resultingFirstChild = null; - var previousNewFiber = null; - var oldFiber = currentFirstChild; - var lastPlacedIndex = 0; - var newIdx = 0; - var nextOldFiber = null; - var step = newChildren.next(); + if ( + ctor.contextType && + ctor.contextTypes && + !didWarnAboutContextTypeAndContextTypes.has(ctor) + ) { + didWarnAboutContextTypeAndContextTypes.add(ctor); - for ( - ; - oldFiber !== null && !step.done; - newIdx++, step = newChildren.next() - ) { - if (oldFiber.index > newIdx) { - nextOldFiber = oldFiber; - oldFiber = null; - } else { - nextOldFiber = oldFiber.sibling; - } + error( + "%s declares both contextTypes and contextType static properties. " + + "The legacy contextTypes property will be ignored.", + name + ); + } + } - var newFiber = updateSlot(returnFiber, oldFiber, step.value, lanes); + 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 + ); + } - 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 ( + 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" + ); } - break; - } + 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 (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 (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 + ); } - } - lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx); + if (typeof instance.componentWillRecieveProps === "function") { + error( + "%s has a method called " + + "componentWillRecieveProps(). Did you mean componentWillReceiveProps()?", + name + ); + } - 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 (typeof instance.UNSAFE_componentWillRecieveProps === "function") { + error( + "%s has a method called " + + "UNSAFE_componentWillRecieveProps(). Did you mean UNSAFE_componentWillReceiveProps()?", + name + ); + } - previousNewFiber = newFiber; - oldFiber = nextOldFiber; - } + var hasMutatedProps = instance.props !== newProps; - if (step.done) { - // We've reached the end of the new children. We can delete the rest. - deleteRemainingChildren(returnFiber, oldFiber); + 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 + ); + } - return resultingFirstChild; - } + 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 (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 ( + typeof instance.getSnapshotBeforeUpdate === "function" && + typeof instance.componentDidUpdate !== "function" && + !didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate.has(ctor) + ) { + didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate.add(ctor); - if (_newFiber3 === null) { - continue; + error( + "%s: getSnapshotBeforeUpdate() should be used with componentDidUpdate(). " + + "This component defines getSnapshotBeforeUpdate() only.", + getComponentNameFromType(ctor) + ); } - 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; + 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 + ); } - previousNewFiber = _newFiber3; + 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 (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 _state = instance.state; + + if (_state && (typeof _state !== "object" || isArray(_state))) { + error("%s.state: must be set to an object or null", name); + } + + if ( + typeof instance.getChildContext === "function" && + typeof ctor.childContextTypes !== "object" + ) { + error( + "%s.getChildContext(): childContextTypes must be defined in order to " + + "use getChildContext().", + name + ); + } } + } - return resultingFirstChild; - } // Add all children to a key map for quick lookups. + function adoptClassInstance(workInProgress, instance) { + instance.updater = classComponentUpdater; + workInProgress.stateNode = instance; // The instance needs access to the fiber so that it can schedule updates - var existingChildren = mapRemainingChildren(returnFiber, oldFiber); // Keep scanning and use the map to restore deleted items as moves. + set(instance, workInProgress); - for (; !step.done; newIdx++, step = newChildren.next()) { - var _newFiber4 = updateFromMap( - existingChildren, - returnFiber, - newIdx, - step.value, - lanes - ); + { + instance._reactInternalInstance = fakeInternalInstance; + } + } - 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 + 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(", ") + + "}."; + } + + error( + "%s defines an invalid contextType. " + + "contextType should point to the Context object returned by React.createContext().%s", + getComponentNameFromType(ctor) || "Component", + addendum ); } } + } - lastPlacedIndex = placeChild(_newFiber4, lastPlacedIndex, newIdx); + 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 (previousNewFiber === null) { - resultingFirstChild = _newFiber4; - } else { - previousNewFiber.sibling = _newFiber4; - } + var instance = new ctor(props, context); // Instantiate twice to help detect side-effects. - previousNewFiber = _newFiber4; - } - } + var state = (workInProgress.memoizedState = + instance.state !== null && instance.state !== undefined + ? instance.state + : null); + adoptClassInstance(workInProgress, instance); - 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); - }); - } + { + if (typeof ctor.getDerivedStateFromProps === "function" && state === null) { + var componentName = getComponentNameFromType(ctor) || "Component"; - 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 (!didWarnAboutUninitializedState.has(componentName)) { + didWarnAboutUninitializedState.add(componentName); - if (elementType === REACT_FRAGMENT_TYPE) { - if (child.tag === Fragment) { - deleteRemainingChildren(returnFiber, child.sibling); - var existing = useFiber(child, element.props.children); - existing.return = returnFiber; + 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. - { - existing._debugSource = element._source; - existing._debugOwner = element._owner; - } + if ( + typeof ctor.getDerivedStateFromProps === "function" || + typeof instance.getSnapshotBeforeUpdate === "function" + ) { + var foundWillMountName = null; + var foundWillReceivePropsName = null; + var foundWillUpdateName = null; - return existing; + if ( + typeof instance.componentWillMount === "function" && + instance.componentWillMount.__suppressDeprecationWarning !== true + ) { + foundWillMountName = "componentWillMount"; + } else if (typeof instance.UNSAFE_componentWillMount === "function") { + foundWillMountName = "UNSAFE_componentWillMount"; } - } 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) + typeof instance.componentWillReceiveProps === "function" && + instance.componentWillReceiveProps.__suppressDeprecationWarning !== true + ) { + foundWillReceivePropsName = "componentWillReceiveProps"; + } else if ( + typeof instance.UNSAFE_componentWillReceiveProps === "function" + ) { + foundWillReceivePropsName = "UNSAFE_componentWillReceiveProps"; + } + + if ( + typeof instance.componentWillUpdate === "function" && + instance.componentWillUpdate.__suppressDeprecationWarning !== true ) { - deleteRemainingChildren(returnFiber, child.sibling); + foundWillUpdateName = "componentWillUpdate"; + } else if (typeof instance.UNSAFE_componentWillUpdate === "function") { + foundWillUpdateName = "UNSAFE_componentWillUpdate"; + } - var _existing = useFiber(child, element.props); + if ( + foundWillMountName !== null || + foundWillReceivePropsName !== null || + foundWillUpdateName !== null + ) { + var _componentName = getComponentNameFromType(ctor) || "Component"; - _existing.ref = coerceRef(returnFiber, child, element); - _existing.return = returnFiber; + var newApiName = + typeof ctor.getDerivedStateFromProps === "function" + ? "getDerivedStateFromProps()" + : "getSnapshotBeforeUpdate()"; - { - _existing._debugSource = element._source; - _existing._debugOwner = element._owner; - } + if (!didWarnAboutLegacyLifecyclesAndDerivedState.has(_componentName)) { + didWarnAboutLegacyLifecyclesAndDerivedState.add(_componentName); - return _existing; + 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://react.dev/link/unsafe-component-lifecycles", + _componentName, + newApiName, + foundWillMountName !== null ? "\n " + foundWillMountName : "", + foundWillReceivePropsName !== null + ? "\n " + foundWillReceivePropsName + : "", + foundWillUpdateName !== null ? "\n " + foundWillUpdateName : "" + ); + } } - } // Didn't match. + } + } // Cache unmasked context so we can avoid recreating masked context unless necessary. + // ReactFiberContext usually updates this cache but can't for newly-created instances. - deleteRemainingChildren(returnFiber, child); - break; - } else { - deleteChild(returnFiber, child); + if (isLegacyContextConsumer) { + cacheContext(workInProgress, unmaskedContext, context); } - child = child.sibling; + return instance; } - 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 reconcileChildFibers( - 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. - 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. + function callComponentWillMount(workInProgress, instance) { + var oldState = instance.state; - return reconcileChildFibers( - returnFiber, - currentFirstChild, - init(payload), - lanes - ); + if (typeof instance.componentWillMount === "function") { + instance.componentWillMount(); } - if (isArray(newChild)) { - return reconcileChildrenArray( - returnFiber, - currentFirstChild, - newChild, - lanes - ); + if (typeof instance.UNSAFE_componentWillMount === "function") { + instance.UNSAFE_componentWillMount(); } - if (getIteratorFn(newChild)) { - return reconcileChildrenIterator( - returnFiber, - currentFirstChild, - newChild, - lanes - ); - } + 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" + ); + } - throwOnInvalidObjectType(returnFiber, newChild); + classComponentUpdater.enqueueReplaceState(instance, instance.state, null); + } } - if ( - (typeof newChild === "string" && newChild !== "") || - typeof newChild === "number" + function callComponentWillReceiveProps( + workInProgress, + instance, + newProps, + nextContext ) { - return placeSingleChild( - reconcileSingleTextNode( - returnFiber, - currentFirstChild, - "" + newChild, - lanes - ) - ); - } + var oldState = instance.state; - { - if (typeof newChild === "function") { - warnOnFunctionType(returnFiber); + if (typeof instance.componentWillReceiveProps === "function") { + instance.componentWillReceiveProps(newProps, nextContext); } - } // Remaining cases are all treated as empty. - return deleteRemainingChildren(returnFiber, currentFirstChild); - } + if (typeof instance.UNSAFE_componentWillReceiveProps === "function") { + instance.UNSAFE_componentWillReceiveProps(newProps, nextContext); + } - return reconcileChildFibers; -} + if (instance.state !== oldState) { + { + var componentName = + getComponentNameFromFiber(workInProgress) || "Component"; -var reconcileChildFibers = ChildReconciler(true); -var mountChildFibers = ChildReconciler(false); -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 (!didWarnAboutStateAssignmentForComponent.has(componentName)) { + didWarnAboutStateAssignmentForComponent.add(componentName); - newChild.sibling = null; -} // Reset a workInProgress child set to prepare it for a second pass. + error( + "%s.componentWillReceiveProps(): Assigning directly to " + + "this.state is deprecated (except inside a component's " + + "constructor). Use setState instead.", + componentName + ); + } + } -function resetChildFibers(workInProgress, lanes) { - var child = workInProgress.child; + classComponentUpdater.enqueueReplaceState(instance, instance.state, null); + } + } // Invokes the mount life-cycles on a previously never rendered instance. - while (child !== null) { - resetWorkInProgress(child, lanes); - child = child.sibling; - } -} + function mountClassInstance(workInProgress, ctor, newProps, renderLanes) { + { + checkClassInstance(workInProgress, ctor, newProps); + } -var NO_CONTEXT = {}; -var contextStackCursor$1 = createCursor(NO_CONTEXT); -var contextFiberStackCursor = createCursor(NO_CONTEXT); -var rootInstanceStackCursor = createCursor(NO_CONTEXT); + var instance = workInProgress.stateNode; + instance.props = newProps; + instance.state = workInProgress.memoizedState; + instance.refs = emptyRefsObject; + initializeUpdateQueue(workInProgress); + var contextType = ctor.contextType; -function requiredContext(c) { - if (c === NO_CONTEXT) { - throw new Error( - "Expected host context to exist. This error is likely caused by a bug " + - "in React. Please file an issue." - ); - } + if (typeof contextType === "object" && contextType !== null) { + instance.context = readContext(contextType); + } else { + var unmaskedContext = getUnmaskedContext(workInProgress, ctor, true); + instance.context = getMaskedContext(workInProgress, unmaskedContext); + } - return c; -} + { + if (instance.state === newProps) { + var componentName = getComponentNameFromType(ctor) || "Component"; -function getRootHostContainer() { - var rootInstance = requiredContext(rootInstanceStackCursor.current); - return rootInstance; -} + if (!didWarnAboutDirectlyAssigningPropsToState.has(componentName)) { + didWarnAboutDirectlyAssigningPropsToState.add(componentName); -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. + 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 + ); + } + } - 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 (workInProgress.mode & StrictLegacyMode) { + ReactStrictModeWarnings.recordLegacyContextWarning( + workInProgress, + instance + ); + } - push(contextStackCursor$1, NO_CONTEXT, fiber); - var nextRootContext = getRootHostContext(); // Now that we know this function doesn't throw, replace it. + { + ReactStrictModeWarnings.recordUnsafeLifecycleWarnings( + workInProgress, + instance + ); + } + } - pop(contextStackCursor$1, fiber); - push(contextStackCursor$1, nextRootContext, fiber); -} + instance.state = workInProgress.memoizedState; + var getDerivedStateFromProps = ctor.getDerivedStateFromProps; -function popHostContainer(fiber) { - pop(contextStackCursor$1, fiber); - pop(contextFiberStackCursor, fiber); - pop(rootInstanceStackCursor, fiber); -} + 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 getHostContext() { - var context = requiredContext(contextStackCursor$1.current); - return context; -} + 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. -function pushHostContext(fiber) { - var rootInstance = requiredContext(rootInstanceStackCursor.current); - var context = requiredContext(contextStackCursor$1.current); - var nextContext = getChildHostContext(context, fiber.type); // Don't push this Fiber's context unless it's unique. + processUpdateQueue(workInProgress, newProps, instance, renderLanes); + instance.state = workInProgress.memoizedState; + } - if (context === nextContext) { - return; - } // Track the context and the Fiber that provided it. - // This enables us to pop only Fibers that provide unique contexts. + if (typeof instance.componentDidMount === "function") { + var fiberFlags = Update; - push(contextFiberStackCursor, fiber, fiber); - push(contextStackCursor$1, nextContext, fiber); -} + workInProgress.flags |= fiberFlags; + } + } -function popHostContext(fiber) { - // Do not pop unless this Fiber provided the current context. - // pushHostContext() only pushes Fibers that provide unique contexts. - if (contextFiberStackCursor.current !== fiber) { - return; - } + 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; - pop(contextStackCursor$1, fiber); - pop(contextFiberStackCursor, fiber); -} + if (typeof contextType === "object" && contextType !== null) { + nextContext = readContext(contextType); + } else { + var nextLegacyUnmaskedContext = getUnmaskedContext( + workInProgress, + ctor, + true + ); + nextContext = getMaskedContext(workInProgress, nextLegacyUnmaskedContext); + } -var DefaultSuspenseContext = 0; // The Suspense Context is split into two parts. The lower bits is -// inherited deeply down the subtree. The upper bits only affect -// this immediate suspense boundary and gets reset each new -// boundary or suspense list. - -var SubtreeSuspenseContextMask = 1; // Subtree Flags: -// InvisibleParentSuspenseContext indicates that one of our parent Suspense -// boundaries is not currently showing visible main content. -// Either because it is already showing a fallback or is not mounted at all. -// We can use this to determine if it is desirable to trigger a fallback at -// the parent. If not, then we might need to trigger undesirable boundaries -// and/or suspend the commit to avoid hiding the parent content. - -var InvisibleParentSuspenseContext = 1; // Shallow Flags: -// 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 hasSuspenseContext(parentContext, flag) { - return (parentContext & flag) !== 0; -} -function setDefaultShallowSuspenseContext(parentContext) { - return parentContext & SubtreeSuspenseContextMask; -} -function setShallowSuspenseContext(parentContext, shallowContext) { - return (parentContext & SubtreeSuspenseContextMask) | shallowContext; -} -function addSubtreeSuspenseContext(parentContext, subtreeContext) { - return parentContext | subtreeContext; -} -function pushSuspenseContext(fiber, newContext) { - push(suspenseStackCursor, newContext, fiber); -} -function popSuspenseContext(fiber) { - pop(suspenseStackCursor, fiber); -} + 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 shouldCaptureSuspense(workInProgress, hasInvisibleParent) { - // If it was the primary children that just suspended, capture and render the - // fallback. Otherwise, don't capture and bubble to the next boundary. - var nextState = workInProgress.memoizedState; + if ( + !hasNewLifecycles && + (typeof instance.UNSAFE_componentWillReceiveProps === "function" || + typeof instance.componentWillReceiveProps === "function") + ) { + if (oldProps !== newProps || oldContext !== nextContext) { + callComponentWillReceiveProps( + workInProgress, + instance, + newProps, + nextContext + ); + } + } - if (nextState !== null) { - if (nextState.dehydrated !== null) { - // A dehydrated boundary always captures. - return true; - } + resetHasForceUpdateBeforeProcessing(); + var oldState = workInProgress.memoizedState; + var newState = (instance.state = oldState); + processUpdateQueue(workInProgress, newProps, instance, renderLanes); + newState = workInProgress.memoizedState; - return false; - } + 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") { + var fiberFlags = Update; - var props = workInProgress.memoizedProps; // Regular boundaries always capture. + workInProgress.flags |= fiberFlags; + } - { - return true; - } // If it's a boundary we should avoid, then we prefer to bubble up to the -} -function findFirstSuspended(row) { - var node = row; + return false; + } - while (node !== null) { - if (node.tag === SuspenseComponent) { - var state = node.memoizedState; + if (typeof getDerivedStateFromProps === "function") { + applyDerivedStateFromProps( + workInProgress, + ctor, + getDerivedStateFromProps, + newProps + ); + newState = workInProgress.memoizedState; + } - if (state !== null) { - var dehydrated = state.dehydrated; + var shouldUpdate = + checkHasForceUpdateAfterProcessing() || + checkShouldComponentUpdate( + 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 ( - dehydrated === null || - isSuspenseInstancePending() || - isSuspenseInstanceFallback() + !hasNewLifecycles && + (typeof instance.UNSAFE_componentWillMount === "function" || + typeof instance.componentWillMount === "function") ) { - 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; + if (typeof instance.componentWillMount === "function") { + instance.componentWillMount(); + } - if (didSuspend) { - return node; - } - } else if (node.child !== null) { - node.child.return = node; - node = node.child; - continue; - } + if (typeof instance.UNSAFE_componentWillMount === "function") { + instance.UNSAFE_componentWillMount(); + } + } - if (node === row) { - return null; - } + if (typeof instance.componentDidMount === "function") { + var _fiberFlags = Update; - while (node.sibling === null) { - if (node.return === null || node.return === row) { - return null; + workInProgress.flags |= _fiberFlags; + } + } 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") { + var _fiberFlags2 = Update; + + workInProgress.flags |= _fiberFlags2; + } // 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); } - node = node.return; - } + 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. - node.sibling.return = node.return; - node = node.sibling; - } + if ( + !hasNewLifecycles && + (typeof instance.UNSAFE_componentWillReceiveProps === "function" || + typeof instance.componentWillReceiveProps === "function") + ) { + if ( + unresolvedOldProps !== unresolvedNewProps || + oldContext !== nextContext + ) { + callComponentWillReceiveProps( + workInProgress, + instance, + newProps, + nextContext + ); + } + } - return null; -} + resetHasForceUpdateBeforeProcessing(); + var oldState = workInProgress.memoizedState; + var newState = (instance.state = oldState); + processUpdateQueue(workInProgress, newProps, instance, renderLanes); + newState = workInProgress.memoizedState; -var NoFlags$1 = - /* */ - 0; // Represents whether effect should fire. + if ( + unresolvedOldProps === unresolvedNewProps && + oldState === newState && + !hasContextChanged() && + !checkHasForceUpdateAfterProcessing() && + !enableLazyContextPropagation + ) { + // 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; + } + } -var HasEffect = - /* */ - 1; // Represents the phase in which the effect (not the clean-up) fires. - -var Insertion = - /* */ - 2; -var Layout = - /* */ - 4; -var Passive$1 = - /* */ - 8; - -// and should be reset before starting a new render. -// This tracks which mutable sources need to be reset after a render. - -var workInProgressSources = []; -function resetWorkInProgressVersions() { - for (var i = 0; i < workInProgressSources.length; i++) { - var mutableSource = workInProgressSources[i]; + if (typeof instance.getSnapshotBeforeUpdate === "function") { + if ( + unresolvedOldProps !== current.memoizedProps || + oldState !== current.memoizedState + ) { + workInProgress.flags |= Snapshot; + } + } - { - mutableSource._workInProgressVersionPrimary = null; - } - } + return false; + } - workInProgressSources.length = 0; -} + if (typeof getDerivedStateFromProps === "function") { + applyDerivedStateFromProps( + workInProgress, + ctor, + getDerivedStateFromProps, + newProps + ); + newState = workInProgress.memoizedState; + } -var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, - ReactCurrentBatchConfig$1 = ReactSharedInternals.ReactCurrentBatchConfig; -var didWarnAboutMismatchedHooksForComponent; -var didWarnUncachedGetSnapshot; + 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; -{ - didWarnAboutMismatchedHooksForComponent = new Set(); -} + 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); + } -// 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. + if (typeof instance.UNSAFE_componentWillUpdate === "function") { + instance.UNSAFE_componentWillUpdate(newProps, newState, nextContext); + } + } -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. + if (typeof instance.componentDidUpdate === "function") { + workInProgress.flags |= Update; + } -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. + 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; + } + } -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`. + 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. -var didScheduleRenderPhaseUpdateDuringThisPass = false; // Counts the number of useId hooks in this component. -// hydration). This counter is global, so client ids are not stable across -// render attempts. + workInProgress.memoizedProps = newProps; + workInProgress.memoizedState = newState; + } // Update the existing instance's state, props, and context pointers even + // if shouldComponentUpdate returns false. -var globalClientIdCounter = 0; -var RE_RENDER_LIMIT = 25; // In DEV, this is the name of the currently executing primitive hook + instance.props = newProps; + instance.state = newState; + instance.context = nextContext; + return shouldUpdate; + } -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 didWarnAboutMaps; + var didWarnAboutGenerators; + var didWarnAboutStringRefs; + var ownerHasKeyUseWarning; + var ownerHasFunctionTypeWarning; -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 warnForMissingKey = function (child, returnFiber) { }; -var ignorePreviousDependencies = false; + { + 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 mountHookTypesDev() { - { - var hookName = currentHookNameInDev; + if (!child._store || child._store.validated || child.key != null) { + return; + } - if (hookTypesDev === null) { - hookTypesDev = [hookName]; - } else { - hookTypesDev.push(hookName); - } - } -} + 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." + ); + } -function updateHookTypesDev() { - { - var hookName = currentHookNameInDev; + child._store.validated = true; + var componentName = getComponentNameFromFiber(returnFiber) || "Component"; - if (hookTypesDev !== null) { - hookTypesUpdateIndexDev++; + if (ownerHasKeyUseWarning[componentName]) { + return; + } - if (hookTypesDev[hookTypesUpdateIndexDev] !== hookName) { - warnOnHookMismatchInDev(hookName); - } - } - } -} + ownerHasKeyUseWarning[componentName] = true; -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 - ); + error( + "Each child in a list should have a unique " + + '"key" prop. See https://react.dev/link/warning-keys for ' + + "more information." + ); + }; } - } -} -function warnOnHookMismatchInDev(currentHookName) { - { - var componentName = getComponentNameFromFiber(currentlyRenderingFiber$1); + function coerceRef(returnFiber, current, element) { + var mixedRef = element.ref; - if (!didWarnAboutMismatchedHooksForComponent.has(componentName)) { - didWarnAboutMismatchedHooksForComponent.add(componentName); - - if (hookTypesDev !== null) { - var table = ""; - var secondColumnStart = 30; + if ( + mixedRef !== null && + typeof mixedRef !== "function" && + typeof mixedRef !== "object" + ) { + { + // TODO: Clean this up once we turn on the string ref warning for + // everyone, because the strict mode case will no longer be relevant + if ( + (returnFiber.mode & StrictLegacyMode || warnAboutStringRefs) && // 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 + ) + ) { + var componentName = + getComponentNameFromFiber(returnFiber) || "Component"; - 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 + if (!didWarnAboutStringRefs[componentName]) { + { + error( + 'A string ref, "%s", has been found within a strict mode tree. ' + + "String refs are a source of potential bugs and should be avoided. " + + "We recommend using useRef() or createRef() instead. " + + "Learn more about using refs safely here: " + + "https://react.dev/link/strict-mode-string-ref", + mixedRef + ); + } - while (row.length < secondColumnStart) { - row += " "; + didWarnAboutStringRefs[componentName] = true; + } } - - 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://react.dev/link/rules-of-hooks\n\n" + - " Previous render Next render\n" + - " ------------------------------------------------------\n" + - "%s" + - " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", - componentName, - table - ); - } - } - } -} + if (element._owner) { + var owner = element._owner; + var inst; -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://react.dev/link/invalid-hook-call for tips about how to debug and fix this problem." - ); -} + if (owner) { + var ownerFiber = owner; -function areHookInputsEqual(nextDeps, prevDeps) { - { - if (ignorePreviousDependencies) { - // Only true when this component is being hot reloaded. - return false; - } - } + 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://react.dev/link/strict-mode-string-ref" + ); + } - 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 - ); - } + inst = ownerFiber.stateNode; + } - 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(", ") + "]" - ); - } - } + 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 - for (var i = 0; i < prevDeps.length && i < nextDeps.length; i++) { - if (objectIs(nextDeps[i], prevDeps[i])) { - continue; - } + var resolvedInst = inst; - return false; - } + { + checkPropStringCoercion(mixedRef, "ref"); + } - return true; -} + var stringRef = "" + mixedRef; // Check if previous string ref matches new string ref -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; - // 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; - } - } - - var children = Component(props, secondArg); // Check if there was a render phase update - - if (didScheduleRenderPhaseUpdateDuringThisPass) { - // Keep rendering in a loop for as long as render phase updates continue to - // be scheduled. Use a counter to prevent infinite loops. - var numberOfReRenders = 0; - - do { - didScheduleRenderPhaseUpdateDuringThisPass = false; + if ( + current !== null && + current.ref !== null && + typeof current.ref === "function" && + current.ref._stringRef === stringRef + ) { + return current.ref; + } - if (numberOfReRenders >= RE_RENDER_LIMIT) { - throw new Error( - "Too many re-renders. React limits the number of renders to prevent " + - "an infinite loop." - ); - } + var ref = function (value) { + var refs = resolvedInst.refs; - numberOfReRenders += 1; + if (refs === emptyRefsObject) { + // This is a lazy pooled frozen object, so we need to initialize. + refs = resolvedInst.refs = {}; + } - { - // 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 + if (value === null) { + delete refs[stringRef]; + } else { + refs[stringRef] = value; + } + }; - currentHook = null; - workInProgressHook = null; - workInProgress.updateQueue = null; + 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." + ); + } - { - // Also validate hook order for cascading updates. - hookTypesUpdateIndexDev = -1; + 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://react.dev/link/refs-must-have-owner for more information." + ); + } + } } - ReactCurrentDispatcher$1.current = HooksDispatcherOnRerenderInDEV; - children = Component(props, secondArg); - } while (didScheduleRenderPhaseUpdateDuringThisPass); - } // 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; - - { - workInProgress._debugHookTypes = hookTypesDev; - } // 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. + return mixedRef; + } - 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 throwOnInvalidObjectType(returnFiber, newChild) { + 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." ); } - } - didScheduleRenderPhaseUpdate = false; // This is reset by checkDidRenderIdHook - // localIdCounter = 0; + function warnOnFunctionType(returnFiber) { + { + var componentName = getComponentNameFromFiber(returnFiber) || "Component"; + + if (ownerHasFunctionTypeWarning[componentName]) { + return; + } - if (didRenderTooFewHooks) { - throw new Error( - "Rendered fewer hooks than expected. This may be caused by an accidental " + - "early return statement." - ); - } + ownerHasFunctionTypeWarning[componentName] = true; - 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). + 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." + ); + } + } - { - workInProgress.flags &= ~(Passive | Update); - } + 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. - current.lanes = removeLanes(current.lanes, lanes); -} -function resetHooksAfterThrow() { - // 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; - - 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 = currentlyRenderingFiber$1.memoizedState; + function ChildReconciler(shouldTrackSideEffects) { + function deleteChild(returnFiber, childToDelete) { + if (!shouldTrackSideEffects) { + // Noop. + return; + } - while (hook !== null) { - var queue = hook.queue; + var deletions = returnFiber.deletions; - if (queue !== null) { - queue.pending = null; + if (deletions === null) { + returnFiber.deletions = [childToDelete]; + returnFiber.flags |= ChildDeletion; + } else { + deletions.push(childToDelete); + } } - hook = hook.next; - } + 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. - didScheduleRenderPhaseUpdate = false; - } + var childToDelete = currentFirstChild; - renderLanes = NoLanes; - currentlyRenderingFiber$1 = null; - currentHook = null; - workInProgressHook = null; + while (childToDelete !== null) { + deleteChild(returnFiber, childToDelete); + childToDelete = childToDelete.sibling; + } - { - hookTypesDev = null; - hookTypesUpdateIndexDev = -1; - currentHookNameInDev = null; - isUpdatingOpaqueValueInRenderPhase = false; - } + return null; + } - didScheduleRenderPhaseUpdateDuringThisPass = false; -} + 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; -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; -} + while (existingChild !== null) { + if (existingChild.key !== null) { + existingChildren.set(existingChild.key, existingChild); + } else { + existingChildren.set(existingChild.index, existingChild); + } -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. When we reach the end of the base list, we must switch to - // the dispatcher used for mounts. - 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) { - 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 - }; + existingChild = existingChild.sibling; + } - 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 existingChildren; + } - return workInProgressHook; -} + 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 createFunctionComponentUpdateQueue() { - return { - lastEffect: null, - stores: null - }; -} + function placeChild(newFiber, lastPlacedIndex, newIndex) { + newFiber.index = newIndex; -function basicStateReducer(state, action) { - // $FlowFixMe: Flow doesn't like mixed types - return typeof action === "function" ? action(state) : action; -} + 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 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, - interleaved: 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]; -} + var current = newFiber.alternate; -function updateReducer(reducer, initialArg, init) { - var hook = updateWorkInProgressHook(); - var queue = hook.queue; + if (current !== null) { + var oldIndex = current.index; - if (queue === null) { - throw new Error( - "Should have a queue. This is likely a bug in React. Please file an issue." - ); - } + if (oldIndex < lastPlacedIndex) { + // This is a move. + newFiber.flags |= Placement; + return lastPlacedIndex; + } else { + // This item can stay in place. + return oldIndex; + } + } else { + // This is an insertion. + newFiber.flags |= Placement; + return lastPlacedIndex; + } + } - queue.lastRenderedReducer = reducer; - var current = currentHook; // The last rebase update that is NOT part of the base state. + 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; + } - var baseQueue = current.baseQueue; // The last pending update that hasn't been processed yet. + return newFiber; + } - var pendingQueue = queue.pending; + 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 (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; - } + function updateElement(returnFiber, current, element, lanes) { + var elementType = element.type; - { - 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 (elementType === REACT_FRAGMENT_TYPE) { + return updateFragment( + returnFiber, + current, + element.props.children, + lanes, + element.key + ); + } - current.baseQueue = baseQueue = pendingQueue; - queue.pending = null; - } + 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; - if (baseQueue !== null) { - // We have a queue to process. - var first = baseQueue.next; - var newState = current.baseState; - var newBaseState = null; - var newBaseQueueFirst = null; - var newBaseQueueLast = null; - var update = first; + { + existing._debugSource = element._source; + existing._debugOwner = element._owner; + } - do { - var updateLane = update.lane; + return existing; + } + } // Insert - if (!isSubsetOfLanes(renderLanes, updateLane)) { - // 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, - action: update.action, - hasEagerState: update.hasEagerState, - eagerState: update.eagerState, - next: null - }; + var created = createFiberFromElement(element, returnFiber.mode, lanes); + created.ref = coerceRef(returnFiber, current, element); + created.return = returnFiber; + return created; + } - if (newBaseQueueLast === null) { - newBaseQueueFirst = newBaseQueueLast = clone; - newBaseState = newState; + 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 { - 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. - 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, - action: update.action, - hasEagerState: update.hasEagerState, - eagerState: update.eagerState, - next: null - }; - newBaseQueueLast = newBaseQueueLast.next = _clone; - } // Process this update. + // Update + var existing = useFiber(current, portal.children || []); + existing.return = returnFiber; + return existing; + } + } - 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; + 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 { - var action = update.action; - newState = reducer(newState, action); + // Update + var existing = useFiber(current, fragment); + existing.return = returnFiber; + return existing; } } - update = update.next; - } while (update !== null && update !== first); + 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 (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 (typeof newChild === "object" && newChild !== null) { + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE: { + var _created = createFiberFromElement( + newChild, + returnFiber.mode, + lanes + ); - if (!objectIs(newState, hook.memoizedState)) { - markWorkInProgressReceivedUpdate(); - } + _created.ref = coerceRef(returnFiber, null, newChild); + _created.return = returnFiber; + return _created; + } - hook.memoizedState = newState; - hook.baseState = newBaseState; - hook.baseQueue = newBaseQueueLast; - queue.lastRenderedState = newState; - } // Interleaved updates are stored on a separate queue. We aren't going to - // process them during this render, but we do need to track which lanes - // are remaining. + case REACT_PORTAL_TYPE: { + var _created2 = createFiberFromPortal( + newChild, + returnFiber.mode, + lanes + ); - var lastInterleaved = queue.interleaved; + _created2.return = returnFiber; + return _created2; + } - if (lastInterleaved !== null) { - var interleaved = lastInterleaved; + case REACT_LAZY_TYPE: { + var payload = newChild._payload; + var init = newChild._init; + return createChild(returnFiber, init(payload), lanes); + } + } - do { - var interleavedLane = interleaved.lane; - currentlyRenderingFiber$1.lanes = mergeLanes( - currentlyRenderingFiber$1.lanes, - interleavedLane - ); - markSkippedUpdateLanes(interleavedLane); - interleaved = interleaved.next; - } while (interleaved !== lastInterleaved); - } else 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]; -} + if (isArray(newChild) || getIteratorFn(newChild)) { + var _created3 = createFiberFromFragment( + newChild, + returnFiber.mode, + lanes, + null + ); -function rerenderReducer(reducer, initialArg, init) { - var hook = updateWorkInProgressHook(); - var queue = hook.queue; + _created3.return = returnFiber; + return _created3; + } - if (queue === null) { - throw new Error( - "Should have a queue. This is likely a bug in React. Please file an issue." - ); - } + throwOnInvalidObjectType(returnFiber, newChild); + } - queue.lastRenderedReducer = reducer; // This is a re-render. Apply the new render phase updates to the previous - // work-in-progress hook. + { + if (typeof newChild === "function") { + warnOnFunctionType(returnFiber); + } + } - var dispatch = queue.dispatch; - var lastRenderPhaseUpdate = queue.pending; - var newState = hook.memoizedState; + return null; + } - if (lastRenderPhaseUpdate !== null) { - // The queue doesn't persist past this render pass. - queue.pending = null; - var firstRenderPhaseUpdate = lastRenderPhaseUpdate.next; - var update = firstRenderPhaseUpdate; + function updateSlot(returnFiber, oldFiber, newChild, lanes) { + // Update the fiber if the keys match, otherwise return null. + var key = oldFiber !== null ? oldFiber.key : null; - 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 ( + (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 (!objectIs(newState, hook.memoizedState)) { - markWorkInProgressReceivedUpdate(); - } + return updateTextNode(returnFiber, oldFiber, "" + newChild, lanes); + } - 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; - } + 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; + } + } - return [newState, dispatch]; -} + case REACT_PORTAL_TYPE: { + if (newChild.key === key) { + return updatePortal(returnFiber, oldFiber, newChild, lanes); + } else { + return null; + } + } -function mountMutableSource(source, getSnapshot, subscribe) { - { - return undefined; - } -} + case REACT_LAZY_TYPE: { + var payload = newChild._payload; + var init = newChild._init; + return updateSlot(returnFiber, oldFiber, init(payload), lanes); + } + } -function updateMutableSource(source, getSnapshot, subscribe) { - { - return undefined; - } -} + if (isArray(newChild) || getIteratorFn(newChild)) { + if (key !== null) { + return null; + } -function mountSyncExternalStore(subscribe, getSnapshot, getServerSnapshot) { - var fiber = currentlyRenderingFiber$1; - var hook = mountWorkInProgressHook(); - var nextSnapshot; + return updateFragment(returnFiber, oldFiber, newChild, lanes, null); + } - { - nextSnapshot = getSnapshot(); + throwOnInvalidObjectType(returnFiber, newChild); + } - { - if (!didWarnUncachedGetSnapshot) { - var cachedSnapshot = getSnapshot(); + { + if (typeof newChild === "function") { + warnOnFunctionType(returnFiber); + } + } - if (!objectIs(nextSnapshot, cachedSnapshot)) { - error( - "The result of getSnapshot should be cached to avoid an infinite loop" - ); + return null; + } - didWarnUncachedGetSnapshot = true; + 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); } - } - } // 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 (typeof newChild === "object" && newChild !== null) { + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE: { + var _matchedFiber = + existingChildren.get( + newChild.key === null ? newIdx : newChild.key + ) || null; - if (root === null) { - throw new Error( - "Expected a work-in-progress root. This is a bug in React. Please file an issue." - ); - } + return updateElement(returnFiber, _matchedFiber, newChild, lanes); + } - if (!includesBlockingLane(root, renderLanes)) { - 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. - // TODO: We can move this to the passive phase once we add a pre-commit - // consistency check. See the next comment. - - fiber.flags |= Passive; - pushEffect( - HasEffect | Passive$1, - updateStoreInstance.bind(null, fiber, inst, nextSnapshot, getSnapshot), - undefined, - null - ); - return nextSnapshot; -} + case REACT_PORTAL_TYPE: { + var _matchedFiber2 = + existingChildren.get( + newChild.key === null ? newIdx : newChild.key + ) || null; -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. + return updatePortal(returnFiber, _matchedFiber2, newChild, lanes); + } - var nextSnapshot = getSnapshot(); + case REACT_LAZY_TYPE: + var payload = newChild._payload; + var init = newChild._init; + return updateFromMap( + existingChildren, + returnFiber, + newIdx, + init(payload), + lanes + ); + } - { - if (!didWarnUncachedGetSnapshot) { - var cachedSnapshot = getSnapshot(); + if (isArray(newChild) || getIteratorFn(newChild)) { + var _matchedFiber3 = existingChildren.get(newIdx) || null; - if (!objectIs(nextSnapshot, cachedSnapshot)) { - error( - "The result of getSnapshot should be cached to avoid an infinite loop" - ); + return updateFragment( + returnFiber, + _matchedFiber3, + newChild, + lanes, + null + ); + } - didWarnUncachedGetSnapshot = true; - } - } - } - - var prevSnapshot = 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 susbcribe 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; - pushEffect( - HasEffect | Passive$1, - updateStoreInstance.bind(null, fiber, inst, nextSnapshot, getSnapshot), - undefined, - 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." - ); - } + throwOnInvalidObjectType(returnFiber, newChild); + } - if (!includesBlockingLane(root, renderLanes)) { - pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot); - } - } + { + if (typeof newChild === "function") { + warnOnFunctionType(returnFiber); + } + } - return nextSnapshot; -} + return null; + } + /** + * Warns if there is a duplicate or missing key + */ -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 warnOnInvalidKey(child, knownKeys, returnFiber) { + { + if (typeof child !== "object" || child === null) { + return knownKeys; + } -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); - } -} + switch (child.$$typeof) { + case REACT_ELEMENT_TYPE: + case REACT_PORTAL_TYPE: + warnForMissingKey(child, returnFiber); + var key = child.key; -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 key !== "string") { + break; + } - return subscribe(handleStoreChange); -} + if (knownKeys === null) { + knownKeys = new Set(); + knownKeys.add(key); + break; + } -function checkIfSnapshotChanged(inst) { - var latestGetSnapshot = inst.getSnapshot; - var prevValue = inst.value; + if (!knownKeys.has(key)) { + knownKeys.add(key); + break; + } - try { - var nextValue = latestGetSnapshot(); - return !objectIs(prevValue, nextValue); - } catch (error) { - return true; - } -} + 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 + ); -function forceStoreRerender(fiber) { - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + break; - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); - } -} + case REACT_LAZY_TYPE: + var payload = child._payload; + var init = child._init; + warnOnInvalidKey(init(payload), knownKeys, returnFiber); + break; + } + } -function mountState(initialState) { - var hook = mountWorkInProgressHook(); - - if (typeof initialState === "function") { - // $FlowFixMe: Flow doesn't like mixed types - initialState = initialState(); - } - - hook.memoizedState = hook.baseState = initialState; - var queue = { - pending: null, - interleaved: null, - lanes: NoLanes, - dispatch: null, - lastRenderedReducer: basicStateReducer, - lastRenderedState: initialState - }; - hook.queue = queue; - var dispatch = (queue.dispatch = dispatchSetState.bind( - null, - currentlyRenderingFiber$1, - queue - )); - return [hook.memoizedState, dispatch]; -} + return knownKeys; + } -function updateState(initialState) { - return updateReducer(basicStateReducer); -} + 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; -function rerenderState(initialState) { - return rerenderReducer(basicStateReducer); -} + for (var i = 0; i < newChildren.length; i++) { + var child = newChildren[i]; + knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); + } + } -function pushEffect(tag, create, destroy, deps) { - var effect = { - tag: tag, - create: create, - destroy: destroy, - 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; -} + 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 mountRef(initialValue) { - var hook = mountWorkInProgressHook(); + var newFiber = updateSlot( + returnFiber, + oldFiber, + newChildren[newIdx], + lanes + ); - { - var _ref2 = { - current: initialValue - }; - hook.memoizedState = _ref2; - return _ref2; - } -} + 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 updateRef(initialValue) { - var hook = updateWorkInProgressHook(); - return hook.memoizedState; -} + break; + } -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, - undefined, - nextDeps - ); -} + 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); + } + } -function updateEffectImpl(fiberFlags, hookFlags, create, deps) { - var hook = updateWorkInProgressHook(); - var nextDeps = deps === undefined ? null : deps; - var destroy = undefined; + lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx); - if (currentHook !== null) { - var prevEffect = currentHook.memoizedState; - destroy = prevEffect.destroy; + 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 (nextDeps !== null) { - var prevDeps = prevEffect.deps; + previousNewFiber = newFiber; + oldFiber = nextOldFiber; + } - if (areHookInputsEqual(nextDeps, prevDeps)) { - hook.memoizedState = pushEffect(hookFlags, create, destroy, nextDeps); - return; - } - } - } + if (newIdx === newChildren.length) { + // We've reached the end of the new children. We can delete the rest. + deleteRemainingChildren(returnFiber, oldFiber); - currentlyRenderingFiber$1.flags |= fiberFlags; - hook.memoizedState = pushEffect( - HasEffect | hookFlags, - create, - destroy, - nextDeps - ); -} + return resultingFirstChild; + } -function mountEffect(create, deps) { - { - return mountEffectImpl(Passive | PassiveStatic, Passive$1, create, deps); - } -} + 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); -function updateEffect(create, deps) { - return updateEffectImpl(Passive, Passive$1, create, deps); -} + if (_newFiber === null) { + continue; + } -function mountInsertionEffect(create, deps) { - return mountEffectImpl(Update, Insertion, create, deps); -} + lastPlacedIndex = placeChild(_newFiber, lastPlacedIndex, newIdx); -function updateInsertionEffect(create, deps) { - return updateEffectImpl(Update, Insertion, create, deps); -} + if (previousNewFiber === null) { + // TODO: Move out of the loop. This only happens for the first run. + resultingFirstChild = _newFiber; + } else { + previousNewFiber.sibling = _newFiber; + } -function mountLayoutEffect(create, deps) { - var fiberFlags = Update; + previousNewFiber = _newFiber; + } - return mountEffectImpl(fiberFlags, Layout, create, deps); -} + return resultingFirstChild; + } // Add all children to a key map for quick lookups. -function updateLayoutEffect(create, deps) { - return updateEffectImpl(Update, Layout, create, deps); -} + var existingChildren = mapRemainingChildren(returnFiber, oldFiber); // Keep scanning and use the map to restore deleted items as moves. -function imperativeHandleEffect(create, ref) { - if (typeof ref === "function") { - var refCallback = ref; + for (; newIdx < newChildren.length; newIdx++) { + var _newFiber2 = updateFromMap( + existingChildren, + returnFiber, + newIdx, + newChildren[newIdx], + lanes + ); - var _inst = create(); + 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 + ); + } + } - refCallback(_inst); - return function() { - refCallback(null); - }; - } else if (ref !== null && ref !== undefined) { - var refObject = ref; + lastPlacedIndex = placeChild(_newFiber2, lastPlacedIndex, newIdx); - { - 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 (previousNewFiber === null) { + resultingFirstChild = _newFiber2; + } else { + previousNewFiber.sibling = _newFiber2; + } - var _inst2 = create(); + previousNewFiber = _newFiber2; + } + } - refObject.current = _inst2; - return function() { - refObject.current = null; - }; - } -} + 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 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? + return resultingFirstChild; + } - var effectDeps = - deps !== null && deps !== undefined ? deps.concat([ref]) : null; - var fiberFlags = Update; + function reconcileChildrenIterator( + returnFiber, + currentFirstChild, + newChildrenIterable, + lanes + ) { + // This is the same implementation as reconcileChildrenArray(), + // but using the iterator instead. + var iteratorFn = getIteratorFn(newChildrenIterable); - return mountEffectImpl( - fiberFlags, - Layout, - imperativeHandleEffect.bind(null, create, ref), - effectDeps - ); -} + 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." + ); + } -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? + { + // We don't support rendering Generators because it's a mutation. + // See https://github.com/facebook/react/issues/12995 + if ( + typeof Symbol === "function" && // $FlowFixMe 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 effectDeps = - deps !== null && deps !== undefined ? deps.concat([ref]) : null; - return updateEffectImpl( - Update, - Layout, - imperativeHandleEffect.bind(null, create, ref), - effectDeps - ); -} + didWarnAboutGenerators = true; + } // Warn about using Maps as children -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 (newChildrenIterable.entries === iteratorFn) { + if (!didWarnAboutMaps) { + error( + "Using Maps as children is not supported. " + + "Use an array of keyed ReactElements instead." + ); + } -var updateDebugValue = mountDebugValue; + didWarnAboutMaps = true; + } // First, validate keys. + // We'll get a different iterator later for the main pass. -function mountCallback(callback, deps) { - var hook = mountWorkInProgressHook(); - var nextDeps = deps === undefined ? null : deps; - hook.memoizedState = [callback, nextDeps]; - return callback; -} + var _newChildren = iteratorFn.call(newChildrenIterable); -function updateCallback(callback, deps) { - var hook = updateWorkInProgressHook(); - var nextDeps = deps === undefined ? null : deps; - var prevState = hook.memoizedState; + if (_newChildren) { + var knownKeys = null; - if (prevState !== null) { - if (nextDeps !== null) { - var prevDeps = prevState[1]; + var _step = _newChildren.next(); - if (areHookInputsEqual(nextDeps, prevDeps)) { - return prevState[0]; - } - } - } + for (; !_step.done; _step = _newChildren.next()) { + var child = _step.value; + knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); + } + } + } - hook.memoizedState = [callback, nextDeps]; - return callback; -} + var newChildren = iteratorFn.call(newChildrenIterable); -function mountMemo(nextCreate, deps) { - var hook = mountWorkInProgressHook(); - var nextDeps = deps === undefined ? null : deps; - var nextValue = nextCreate(); - hook.memoizedState = [nextValue, nextDeps]; - return nextValue; -} + if (newChildren == null) { + throw new Error("An iterable object provided no iterator."); + } -function updateMemo(nextCreate, deps) { - var hook = updateWorkInProgressHook(); - var nextDeps = deps === undefined ? null : deps; - var prevState = hook.memoizedState; + var resultingFirstChild = null; + var previousNewFiber = null; + var oldFiber = currentFirstChild; + var lastPlacedIndex = 0; + var newIdx = 0; + var nextOldFiber = null; + var step = newChildren.next(); - if (prevState !== null) { - // Assume these are defined. If they're not, areHookInputsEqual will warn. - if (nextDeps !== null) { - var prevDeps = prevState[1]; + for ( + ; + oldFiber !== null && !step.done; + newIdx++, step = newChildren.next() + ) { + if (oldFiber.index > newIdx) { + nextOldFiber = oldFiber; + oldFiber = null; + } else { + nextOldFiber = oldFiber.sibling; + } - if (areHookInputsEqual(nextDeps, prevDeps)) { - return prevState[0]; - } - } - } + var newFiber = updateSlot(returnFiber, oldFiber, step.value, lanes); - var nextValue = nextCreate(); - hook.memoizedState = [nextValue, nextDeps]; - return nextValue; -} + 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 mountDeferredValue(value) { - var hook = mountWorkInProgressHook(); - hook.memoizedState = value; - return value; -} + break; + } -function updateDeferredValue(value) { - var hook = updateWorkInProgressHook(); - var resolvedCurrentHook = currentHook; - var prevValue = resolvedCurrentHook.memoizedState; - return updateDeferredValueImpl(hook, prevValue, 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); + } + } -function rerenderDeferredValue(value) { - var hook = updateWorkInProgressHook(); - - if (currentHook === null) { - // This is a rerender during a mount. - hook.memoizedState = value; - return value; - } else { - // This is a rerender during an update. - var prevValue = currentHook.memoizedState; - return updateDeferredValueImpl(hook, prevValue, value); - } -} + lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx); -function updateDeferredValueImpl(hook, prevValue, value) { - var shouldDeferValue = !includesOnlyNonUrgentLanes(renderLanes); - - if (shouldDeferValue) { - // This is an urgent update. If the value has changed, keep using the - // previous value and spawn a deferred render to update it later. - if (!objectIs(value, prevValue)) { - // Schedule a deferred render - var deferredLane = claimNextTransitionLane(); - currentlyRenderingFiber$1.lanes = mergeLanes( - currentlyRenderingFiber$1.lanes, - deferredLane - ); - markSkippedUpdateLanes(deferredLane); // Set this to true to indicate that the rendered value is inconsistent - // from the latest value. The name "baseState" doesn't really match how we - // use it because we're reusing a state hook field instead of creating a - // new one. - - hook.baseState = true; - } // Reuse the previous 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. - // However, if we're currently inside a spawned render, then we need to mark - // this as an update to prevent the fiber from bailing out. - // - // `baseState` is true when the current value is different from the rendered - // value. The name doesn't really match how we use it because we're reusing - // a state hook field instead of creating a new one. - if (hook.baseState) { - // Flip this back to false. - hook.baseState = false; - markWorkInProgressReceivedUpdate(); - } - - hook.memoizedState = value; - return value; - } -} + 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; + } -function startTransition(setPending, callback, options) { - var previousPriority = getCurrentUpdatePriority(); - setCurrentUpdatePriority( - higherEventPriority(previousPriority, ContinuousEventPriority) - ); - setPending(true); - var prevTransition = ReactCurrentBatchConfig$1.transition; - ReactCurrentBatchConfig$1.transition = {}; - var currentTransition = ReactCurrentBatchConfig$1.transition; - - { - ReactCurrentBatchConfig$1.transition._updatedFibers = new Set(); - } - - try { - setPending(false); - callback(); - } finally { - setCurrentUpdatePriority(previousPriority); - ReactCurrentBatchConfig$1.transition = prevTransition; + previousNewFiber = newFiber; + oldFiber = nextOldFiber; + } - { - if (prevTransition === null && currentTransition._updatedFibers) { - var updatedFibersCount = currentTransition._updatedFibers.size; + if (step.done) { + // We've reached the end of the new children. We can delete the rest. + deleteRemainingChildren(returnFiber, oldFiber); - 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 resultingFirstChild; } - currentTransition._updatedFibers.clear(); - } - } - } -} + 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 mountTransition() { - var _mountState = mountState(false), - isPending = _mountState[0], - setPending = _mountState[1]; // The `start` method never changes. + if (_newFiber3 === null) { + continue; + } - var start = startTransition.bind(null, setPending); - var hook = mountWorkInProgressHook(); - hook.memoizedState = start; - return [isPending, start]; -} + lastPlacedIndex = placeChild(_newFiber3, lastPlacedIndex, newIdx); -function updateTransition() { - var _updateState = updateState(), - isPending = _updateState[0]; + if (previousNewFiber === null) { + // TODO: Move out of the loop. This only happens for the first run. + resultingFirstChild = _newFiber3; + } else { + previousNewFiber.sibling = _newFiber3; + } - var hook = updateWorkInProgressHook(); - var start = hook.memoizedState; - return [isPending, start]; -} + previousNewFiber = _newFiber3; + } -function rerenderTransition() { - var _rerenderState = rerenderState(), - isPending = _rerenderState[0]; + return resultingFirstChild; + } // Add all children to a key map for quick lookups. - var hook = updateWorkInProgressHook(); - var start = hook.memoizedState; - return [isPending, start]; -} + var existingChildren = mapRemainingChildren(returnFiber, oldFiber); // Keep scanning and use the map to restore deleted items as moves. -var isUpdatingOpaqueValueInRenderPhase = false; -function getIsUpdatingOpaqueValueInRenderPhaseInDEV() { - { - return isUpdatingOpaqueValueInRenderPhase; - } -} + for (; !step.done; newIdx++, step = newChildren.next()) { + var _newFiber4 = updateFromMap( + existingChildren, + returnFiber, + newIdx, + step.value, + lanes + ); -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 (_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 + ); + } + } -function updateId() { - var hook = updateWorkInProgressHook(); - var id = hook.memoizedState; - return id; -} + lastPlacedIndex = placeChild(_newFiber4, lastPlacedIndex, newIdx); -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 (previousNewFiber === null) { + resultingFirstChild = _newFiber4; + } else { + previousNewFiber.sibling = _newFiber4; + } - var lane = requestUpdateLane(fiber); - var update = { - lane: lane, - action: action, - hasEagerState: false, - eagerState: null, - next: null - }; + previousNewFiber = _newFiber4; + } + } - if (isRenderPhaseUpdate(fiber)) { - enqueueRenderPhaseUpdate(queue, update); - } else { - var root = enqueueConcurrentHookUpdate(fiber, queue, update, lane); + 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); + }); + } - if (root !== null) { - var eventTime = requestEventTime(); - scheduleUpdateOnFiber(root, fiber, lane, eventTime); - entangleTransitionUpdate(root, queue, lane); - } - } -} + return resultingFirstChild; + } -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()." - ); - } - } + 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. - var lane = requestUpdateLane(fiber); - var update = { - lane: lane, - action: action, - hasEagerState: false, - eagerState: null, - next: null - }; + deleteRemainingChildren(returnFiber, currentFirstChild); + var created = createFiberFromText(textContent, returnFiber.mode, lanes); + created.return = returnFiber; + return created; + } - if (isRenderPhaseUpdate(fiber)) { - enqueueRenderPhaseUpdate(queue, update); - } else { - var alternate = fiber.alternate; + function reconcileSingleElement( + returnFiber, + currentFirstChild, + element, + lanes + ) { + var key = element.key; + var child = currentFirstChild; - 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; + 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 (lastRenderedReducer !== null) { - var prevDispatcher; + if (elementType === REACT_FRAGMENT_TYPE) { + if (child.tag === Fragment) { + deleteRemainingChildren(returnFiber, child.sibling); + var existing = useFiber(child, element.props.children); + existing.return = returnFiber; - { - prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV; - } + { + existing._debugSource = element._source; + existing._debugOwner = element._owner; + } - 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, - lane - ); - return; - } - } catch (error) { - // Suppress the error. It will throw again in the render phase. - } finally { - { - ReactCurrentDispatcher$1.current = prevDispatcher; + 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; } - } - } - var root = enqueueConcurrentHookUpdate(fiber, queue, update, lane); + 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); - if (root !== null) { - var eventTime = requestEventTime(); - scheduleUpdateOnFiber(root, fiber, lane, eventTime); - entangleTransitionUpdate(root, queue, lane); - } - } -} + _created4.ref = coerceRef(returnFiber, currentFirstChild, element); + _created4.return = returnFiber; + return _created4; + } + } -function isRenderPhaseUpdate(fiber) { - var alternate = fiber.alternate; - return ( - fiber === currentlyRenderingFiber$1 || - (alternate !== null && alternate === currentlyRenderingFiber$1) - ); -} + function reconcileSinglePortal( + returnFiber, + currentFirstChild, + portal, + lanes + ) { + var key = portal.key; + var child = currentFirstChild; -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); - } -} + 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); + } -var ContextOnlyDispatcher = { - readContext: readContext, - 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, - useMutableSource: throwInvalidHookError, - useSyncExternalStore: throwInvalidHookError, - useId: throwInvalidHookError, - unstable_isNewReconciler: enableNewReconciler -}; - -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://react.dev/link/rules-of-hooks" - ); - }; - - HooksDispatcherOnMountInDEV = { - readContext: function(context) { - return readContext(context); - }, - 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; + child = child.sibling; + } - 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 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. - 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; + function reconcileChildFibers( + 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. + 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 + ) + ); - try { - return mountState(initialState); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useDebugValue: function(value, formatterFn) { - currentHookNameInDev = "useDebugValue"; - mountHookTypesDev(); - return mountDebugValue(); - }, - useDeferredValue: function(value) { - currentHookNameInDev = "useDeferredValue"; - mountHookTypesDev(); - return mountDeferredValue(value); - }, - useTransition: function() { - currentHookNameInDev = "useTransition"; - mountHookTypesDev(); - return mountTransition(); - }, - useMutableSource: function(source, getSnapshot, subscribe) { - currentHookNameInDev = "useMutableSource"; - mountHookTypesDev(); - return mountMutableSource(); - }, - useSyncExternalStore: function(subscribe, getSnapshot, getServerSnapshot) { - currentHookNameInDev = "useSyncExternalStore"; - mountHookTypesDev(); - return mountSyncExternalStore(subscribe, getSnapshot); - }, - useId: function() { - currentHookNameInDev = "useId"; - mountHookTypesDev(); - return mountId(); - }, - unstable_isNewReconciler: enableNewReconciler - }; - - HooksDispatcherOnMountWithHookTypesInDEV = { - readContext: function(context) { - return readContext(context); - }, - 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; + case REACT_PORTAL_TYPE: + return placeSingleChild( + reconcileSinglePortal( + returnFiber, + currentFirstChild, + newChild, + lanes + ) + ); - 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; + 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 + ); + } - 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; + if (isArray(newChild)) { + return reconcileChildrenArray( + returnFiber, + currentFirstChild, + newChild, + lanes + ); + } - try { - return mountState(initialState); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useDebugValue: function(value, formatterFn) { - currentHookNameInDev = "useDebugValue"; - updateHookTypesDev(); - return mountDebugValue(); - }, - useDeferredValue: function(value) { - currentHookNameInDev = "useDeferredValue"; - updateHookTypesDev(); - return mountDeferredValue(value); - }, - useTransition: function() { - currentHookNameInDev = "useTransition"; - updateHookTypesDev(); - return mountTransition(); - }, - useMutableSource: function(source, getSnapshot, subscribe) { - currentHookNameInDev = "useMutableSource"; - updateHookTypesDev(); - return mountMutableSource(); - }, - useSyncExternalStore: function(subscribe, getSnapshot, getServerSnapshot) { - currentHookNameInDev = "useSyncExternalStore"; - updateHookTypesDev(); - return mountSyncExternalStore(subscribe, getSnapshot); - }, - useId: function() { - currentHookNameInDev = "useId"; - updateHookTypesDev(); - return mountId(); - }, - unstable_isNewReconciler: enableNewReconciler - }; - - HooksDispatcherOnUpdateInDEV = { - readContext: function(context) { - return readContext(context); - }, - 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 (getIteratorFn(newChild)) { + return reconcileChildrenIterator( + returnFiber, + currentFirstChild, + newChild, + lanes + ); + } - 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; + throwOnInvalidObjectType(returnFiber, newChild); + } - 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; + if ( + (typeof newChild === "string" && newChild !== "") || + typeof newChild === "number" + ) { + return placeSingleChild( + reconcileSingleTextNode( + returnFiber, + currentFirstChild, + "" + newChild, + lanes + ) + ); + } - try { - return updateState(initialState); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useDebugValue: function(value, formatterFn) { - currentHookNameInDev = "useDebugValue"; - updateHookTypesDev(); - return updateDebugValue(); - }, - useDeferredValue: function(value) { - currentHookNameInDev = "useDeferredValue"; - updateHookTypesDev(); - return updateDeferredValue(value); - }, - useTransition: function() { - currentHookNameInDev = "useTransition"; - updateHookTypesDev(); - return updateTransition(); - }, - useMutableSource: function(source, getSnapshot, subscribe) { - currentHookNameInDev = "useMutableSource"; - updateHookTypesDev(); - return updateMutableSource(); - }, - useSyncExternalStore: function(subscribe, getSnapshot, getServerSnapshot) { - currentHookNameInDev = "useSyncExternalStore"; - updateHookTypesDev(); - return updateSyncExternalStore(subscribe, getSnapshot); - }, - useId: function() { - currentHookNameInDev = "useId"; - updateHookTypesDev(); - return updateId(); - }, - unstable_isNewReconciler: enableNewReconciler - }; - - HooksDispatcherOnRerenderInDEV = { - readContext: function(context) { - return readContext(context); - }, - 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; + { + if (typeof newChild === "function") { + warnOnFunctionType(returnFiber); + } + } // Remaining cases are all treated as empty. - try { - return updateMemo(create, deps); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; + return deleteRemainingChildren(returnFiber, currentFirstChild); } - }, - 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) { - currentHookNameInDev = "useDeferredValue"; - updateHookTypesDev(); - return rerenderDeferredValue(value); - }, - useTransition: function() { - currentHookNameInDev = "useTransition"; - updateHookTypesDev(); - return rerenderTransition(); - }, - useMutableSource: function(source, getSnapshot, subscribe) { - currentHookNameInDev = "useMutableSource"; - updateHookTypesDev(); - return updateMutableSource(); - }, - useSyncExternalStore: function(subscribe, getSnapshot, getServerSnapshot) { - currentHookNameInDev = "useSyncExternalStore"; - updateHookTypesDev(); - return updateSyncExternalStore(subscribe, getSnapshot); - }, - useId: function() { - currentHookNameInDev = "useId"; - updateHookTypesDev(); - return updateId(); - }, - unstable_isNewReconciler: enableNewReconciler - }; - - InvalidNestedHooksDispatcherOnMountInDEV = { - readContext: function(context) { - warnInvalidContextAccess(); - return readContext(context); - }, - 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; + return reconcileChildFibers; + } - try { - return mountMemo(create, deps); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; + var reconcileChildFibers = ChildReconciler(true); + var mountChildFibers = ChildReconciler(false); + function cloneChildFibers(current, workInProgress) { + if (current !== null && workInProgress.child !== current.child) { + throw new Error("Resuming work not yet implemented."); } - }, - 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; + if (workInProgress.child === null) { + return; + } - try { - return mountState(initialState); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useDebugValue: function(value, formatterFn) { - currentHookNameInDev = "useDebugValue"; - warnInvalidHookAccess(); - mountHookTypesDev(); - return mountDebugValue(); - }, - useDeferredValue: function(value) { - currentHookNameInDev = "useDeferredValue"; - warnInvalidHookAccess(); - mountHookTypesDev(); - return mountDeferredValue(value); - }, - useTransition: function() { - currentHookNameInDev = "useTransition"; - warnInvalidHookAccess(); - mountHookTypesDev(); - return mountTransition(); - }, - useMutableSource: function(source, getSnapshot, subscribe) { - currentHookNameInDev = "useMutableSource"; - warnInvalidHookAccess(); - mountHookTypesDev(); - return mountMutableSource(); - }, - useSyncExternalStore: function(subscribe, getSnapshot, getServerSnapshot) { - currentHookNameInDev = "useSyncExternalStore"; - warnInvalidHookAccess(); - mountHookTypesDev(); - return mountSyncExternalStore(subscribe, getSnapshot); - }, - useId: function() { - currentHookNameInDev = "useId"; - warnInvalidHookAccess(); - mountHookTypesDev(); - return mountId(); - }, - unstable_isNewReconciler: enableNewReconciler - }; - - InvalidNestedHooksDispatcherOnUpdateInDEV = { - readContext: function(context) { - warnInvalidContextAccess(); - return readContext(context); - }, - 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; + var currentChild = workInProgress.child; + var newChild = createWorkInProgress(currentChild, currentChild.pendingProps); + workInProgress.child = newChild; + newChild.return = workInProgress; - try { - return updateMemo(create, deps); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; + while (currentChild.sibling !== null) { + currentChild = currentChild.sibling; + newChild = newChild.sibling = createWorkInProgress( + currentChild, + currentChild.pendingProps + ); + newChild.return = workInProgress; } - }, - 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; + newChild.sibling = null; + } // Reset a workInProgress child set to prepare it for a second pass. - try { - return updateState(initialState); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useDebugValue: function(value, formatterFn) { - currentHookNameInDev = "useDebugValue"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateDebugValue(); - }, - useDeferredValue: function(value) { - currentHookNameInDev = "useDeferredValue"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateDeferredValue(value); - }, - useTransition: function() { - currentHookNameInDev = "useTransition"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateTransition(); - }, - useMutableSource: function(source, getSnapshot, subscribe) { - currentHookNameInDev = "useMutableSource"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateMutableSource(); - }, - useSyncExternalStore: function(subscribe, getSnapshot, getServerSnapshot) { - currentHookNameInDev = "useSyncExternalStore"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateSyncExternalStore(subscribe, getSnapshot); - }, - useId: function() { - currentHookNameInDev = "useId"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateId(); - }, - unstable_isNewReconciler: enableNewReconciler - }; - - InvalidNestedHooksDispatcherOnRerenderInDEV = { - readContext: function(context) { - warnInvalidContextAccess(); - return readContext(context); - }, - 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; + function resetChildFibers(workInProgress, lanes) { + var child = workInProgress.child; - try { - return updateMemo(create, deps); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; + while (child !== null) { + resetWorkInProgress(child, lanes); + child = child.sibling; } - }, - 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; + var NO_CONTEXT = {}; + var contextStackCursor$1 = createCursor(NO_CONTEXT); + var contextFiberStackCursor = createCursor(NO_CONTEXT); + var rootInstanceStackCursor = createCursor(NO_CONTEXT); - try { - return rerenderState(initialState); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useDebugValue: function(value, formatterFn) { - currentHookNameInDev = "useDebugValue"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateDebugValue(); - }, - useDeferredValue: function(value) { - currentHookNameInDev = "useDeferredValue"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return rerenderDeferredValue(value); - }, - useTransition: function() { - currentHookNameInDev = "useTransition"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return rerenderTransition(); - }, - useMutableSource: function(source, getSnapshot, subscribe) { - currentHookNameInDev = "useMutableSource"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateMutableSource(); - }, - useSyncExternalStore: function(subscribe, getSnapshot, getServerSnapshot) { - currentHookNameInDev = "useSyncExternalStore"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateSyncExternalStore(subscribe, getSnapshot); - }, - useId: function() { - currentHookNameInDev = "useId"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateId(); - }, - unstable_isNewReconciler: enableNewReconciler - }; -} + function requiredContext(c) { + if (c === NO_CONTEXT) { + throw new Error( + "Expected host context to exist. This error is likely caused by a bug " + + "in React. Please file an issue." + ); + } -var now$1 = 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. - */ + return c; + } -var currentUpdateIsNested = false; -var nestedUpdateScheduled = false; + function getRootHostContainer() { + var rootInstance = requiredContext(rootInstanceStackCursor.current); + return rootInstance; + } -function isCurrentUpdateNested() { - return currentUpdateIsNested; -} + 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 markNestedUpdateScheduled() { - { - nestedUpdateScheduled = true; - } -} + 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 resetNestedUpdateFlag() { - { - currentUpdateIsNested = false; - nestedUpdateScheduled = false; - } -} + push(contextStackCursor$1, NO_CONTEXT, fiber); + var nextRootContext = getRootHostContext(); // Now that we know this function doesn't throw, replace it. -function syncNestedUpdateFlag() { - { - currentUpdateIsNested = nestedUpdateScheduled; - nestedUpdateScheduled = false; - } -} + pop(contextStackCursor$1, fiber); + push(contextStackCursor$1, nextRootContext, fiber); + } -function getCommitTime() { - return commitTime; -} + function popHostContainer(fiber) { + pop(contextStackCursor$1, fiber); + pop(contextFiberStackCursor, fiber); + pop(rootInstanceStackCursor, fiber); + } -function recordCommitTime() { - commitTime = now$1(); -} + function getHostContext() { + var context = requiredContext(contextStackCursor$1.current); + return context; + } -function startProfilerTimer(fiber) { - profilerStartTime = now$1(); + function pushHostContext(fiber) { + var rootInstance = requiredContext(rootInstanceStackCursor.current); + var context = requiredContext(contextStackCursor$1.current); + var nextContext = getChildHostContext(context, fiber.type); // Don't push this Fiber's context unless it's unique. - if (fiber.actualStartTime < 0) { - fiber.actualStartTime = now$1(); - } -} + if (context === nextContext) { + return; + } // Track the context and the Fiber that provided it. + // This enables us to pop only Fibers that provide unique contexts. -function stopProfilerTimerIfRunning(fiber) { - profilerStartTime = -1; -} + push(contextFiberStackCursor, fiber, fiber); + push(contextStackCursor$1, nextContext, fiber); + } -function stopProfilerTimerIfRunningAndRecordDelta(fiber, overrideBaseTime) { - if (profilerStartTime >= 0) { - var elapsedTime = now$1() - profilerStartTime; - fiber.actualDuration += elapsedTime; + function popHostContext(fiber) { + // Do not pop unless this Fiber provided the current context. + // pushHostContext() only pushes Fibers that provide unique contexts. + if (contextFiberStackCursor.current !== fiber) { + return; + } - if (overrideBaseTime) { - fiber.selfBaseDuration = elapsedTime; + pop(contextStackCursor$1, fiber); + pop(contextFiberStackCursor, fiber); } - profilerStartTime = -1; - } -} + var DefaultSuspenseContext = 0; // The Suspense Context is split into two parts. The lower bits is + // inherited deeply down the subtree. The upper bits only affect + // this immediate suspense boundary and gets reset each new + // boundary or suspense list. -function recordLayoutEffectDuration(fiber) { - if (layoutEffectStartTime >= 0) { - var elapsedTime = now$1() - layoutEffectStartTime; - layoutEffectStartTime = -1; // Store duration on the next nearest Profiler ancestor - // Or the root (for the DevTools Profiler to read) + var SubtreeSuspenseContextMask = 1; // Subtree Flags: + // InvisibleParentSuspenseContext indicates that one of our parent Suspense + // boundaries is not currently showing visible main content. + // Either because it is already showing a fallback or is not mounted at all. + // We can use this to determine if it is desirable to trigger a fallback at + // the parent. If not, then we might need to trigger undesirable boundaries + // and/or suspend the commit to avoid hiding the parent content. - var parentFiber = fiber.return; + var InvisibleParentSuspenseContext = 1; // Shallow Flags: + // ForceSuspenseFallback can be used by SuspenseList to force newly added + // items into their fallback state during one of the render passes. - while (parentFiber !== null) { - switch (parentFiber.tag) { - case HostRoot: - var root = parentFiber.stateNode; - root.effectDuration += elapsedTime; - return; + var ForceSuspenseFallback = 2; + var suspenseStackCursor = createCursor(DefaultSuspenseContext); + function hasSuspenseContext(parentContext, flag) { + return (parentContext & flag) !== 0; + } + function setDefaultShallowSuspenseContext(parentContext) { + return parentContext & SubtreeSuspenseContextMask; + } + function setShallowSuspenseContext(parentContext, shallowContext) { + return (parentContext & SubtreeSuspenseContextMask) | shallowContext; + } + function addSubtreeSuspenseContext(parentContext, subtreeContext) { + return parentContext | subtreeContext; + } + function pushSuspenseContext(fiber, newContext) { + push(suspenseStackCursor, newContext, fiber); + } + function popSuspenseContext(fiber) { + pop(suspenseStackCursor, fiber); + } - case Profiler: - var parentStateNode = parentFiber.stateNode; - parentStateNode.effectDuration += elapsedTime; - return; + function shouldCaptureSuspense(workInProgress, hasInvisibleParent) { + // If it was the primary children that just suspended, capture and render the + // fallback. Otherwise, don't capture and bubble to the next boundary. + var nextState = workInProgress.memoizedState; + + if (nextState !== null) { + if (nextState.dehydrated !== null) { + // A dehydrated boundary always captures. + return true; + } + + return false; } - parentFiber = parentFiber.return; - } - } -} + var props = workInProgress.memoizedProps; // Regular boundaries always capture. -function recordPassiveEffectDuration(fiber) { - if (passiveEffectStartTime >= 0) { - var elapsedTime = now$1() - passiveEffectStartTime; - passiveEffectStartTime = -1; // Store duration on the next nearest Profiler ancestor - // Or the root (for the DevTools Profiler to read) + { + return true; + } // If it's a boundary we should avoid, then we prefer to bubble up to the + } + function findFirstSuspended(row) { + var node = row; - var parentFiber = fiber.return; + while (node !== null) { + if (node.tag === SuspenseComponent) { + var state = node.memoizedState; - while (parentFiber !== null) { - switch (parentFiber.tag) { - case HostRoot: - var root = parentFiber.stateNode; + if (state !== null) { + var dehydrated = state.dehydrated; - if (root !== null) { - root.passiveEffectDuration += elapsedTime; + 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; - return; + if (didSuspend) { + return node; + } + } else if (node.child !== null) { + node.child.return = node; + node = node.child; + continue; + } - case Profiler: - var parentStateNode = parentFiber.stateNode; + if (node === row) { + return null; + } - 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; + while (node.sibling === null) { + if (node.return === null || node.return === row) { + return null; } - return; + node = node.return; + } + + node.sibling.return = node.return; + node = node.sibling; } - parentFiber = parentFiber.return; + return null; } - } -} -function startLayoutEffectTimer() { - layoutEffectStartTime = now$1(); -} + var NoFlags$1 = + /* */ + 0; // Represents whether effect should fire. -function startPassiveEffectTimer() { - passiveEffectStartTime = now$1(); -} + var HasEffect = + /* */ + 1; // Represents the phase in which the effect (not the clean-up) fires. -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; + var Insertion = + /* */ + 2; + var Layout = + /* */ + 4; + var Passive$1 = + /* */ + 8; - while (child) { - fiber.actualDuration += child.actualDuration; - child = child.sibling; - } -} + // and should be reset before starting a new render. + // This tracks which mutable sources need to be reset after a render. -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 workInProgressSources = []; + function resetWorkInProgressVersions() { + for (var i = 0; i < workInProgressSources.length; i++) { + var mutableSource = workInProgressSources[i]; -if ( - typeof ReactNativePrivateInterface.ReactFiberErrorDialog.showErrorDialog !== - "function" -) { - throw new Error( - "Expected ReactFiberErrorDialog.showErrorDialog to be a function." - ); -} + { + mutableSource._workInProgressVersionPrimary = 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 ReactNativePrivateInterface.ReactFiberErrorDialog.showErrorDialog( - capturedError - ); -} + workInProgressSources.length = 0; + } -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. + var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, + ReactCurrentBatchConfig$1 = ReactSharedInternals.ReactCurrentBatchConfig; + var didWarnAboutMismatchedHooksForComponent; + var didWarnUncachedGetSnapshot; - if (logError === false) { - return; + { + didWarnAboutMismatchedHooksForComponent = new Set(); } - var error = errorInfo.value; + // 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. - 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. + 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. - 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://react.dev/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 - } else { - // In production, we print the error directly. - // This will include the message, the JS stack, and anything the browser wants to show. - // We pass the error object instead of custom message so that the browser displays the error natively. - console["error"](error); // 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; - }); - } -} + 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 PossiblyWeakMap$1 = typeof WeakMap === "function" ? WeakMap : Map; + 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`. -function createRootErrorUpdate(fiber, errorInfo, lane) { - var update = createUpdate(NoTimestamp, lane); // Unmount the root by rendering null. + var didScheduleRenderPhaseUpdateDuringThisPass = false; // Counts the number of useId hooks in this component. + // hydration). This counter is global, so client ids are not stable across + // render attempts. - update.tag = CaptureUpdate; // Caution: React DevTools currently depends on this property - // being called "element". + var globalClientIdCounter = 0; + var RE_RENDER_LIMIT = 25; // In DEV, this is the name of the currently executing primitive hook - update.payload = { - element: null - }; - var error = errorInfo.value; + 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. - update.callback = function() { - onUncaughtError(error); - logCapturedError(fiber, errorInfo); - }; + 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. - return update; -} - -function createClassErrorUpdate(fiber, errorInfo, lane) { - var update = createUpdate(NoTimestamp, lane); - update.tag = CaptureUpdate; - var getDerivedStateFromError = fiber.type.getDerivedStateFromError; + var ignorePreviousDependencies = false; - if (typeof getDerivedStateFromError === "function") { - var error$1 = errorInfo.value; + function mountHookTypesDev() { + { + var hookName = currentHookNameInDev; - update.payload = function() { - return getDerivedStateFromError(error$1); - }; + if (hookTypesDev === null) { + hookTypesDev = [hookName]; + } else { + hookTypesDev.push(hookName); + } + } + } - update.callback = function() { + function updateHookTypesDev() { { - markFailedErrorBoundaryForHotReloading(fiber); - } + var hookName = currentHookNameInDev; - logCapturedError(fiber, errorInfo); - }; - } + if (hookTypesDev !== null) { + hookTypesUpdateIndexDev++; - var inst = fiber.stateNode; + if (hookTypesDev[hookTypesUpdateIndexDev] !== hookName) { + warnOnHookMismatchInDev(hookName); + } + } + } + } - if (inst !== null && typeof inst.componentDidCatch === "function") { - update.callback = function callback() { + function checkDepsAreArrayDev(deps) { { - markFailedErrorBoundaryForHotReloading(fiber); + 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 + ); + } } + } - logCapturedError(fiber, errorInfo); + function warnOnHookMismatchInDev(currentHookName) { + { + var componentName = getComponentNameFromFiber(currentlyRenderingFiber$1); - 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); - } + if (!didWarnAboutMismatchedHooksForComponent.has(componentName)) { + didWarnAboutMismatchedHooksForComponent.add(componentName); - var error$1 = errorInfo.value; - var stack = errorInfo.stack; - this.componentDidCatch(error$1, { - componentStack: stack !== null ? stack : "" - }); + 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; + } - { - 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" + "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://react.dev/link/rules-of-hooks\n\n" + + " Previous render Next render\n" + + " ------------------------------------------------------\n" + + "%s" + + " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + componentName, + table ); } } } - }; - } + } - return update; -} + 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://react.dev/link/invalid-hook-call for tips about how to debug and fix this problem." + ); + } -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$1(); - 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)) { - // Memoize using the thread ID to prevent redundant listeners. - threadIDs.add(lanes); - var ping = pingSuspendedRoot.bind(null, root, wakeable, lanes); + function areHookInputsEqual(nextDeps, prevDeps) { + { + if (ignorePreviousDependencies) { + // Only true when this component is being hot reloaded. + return false; + } + } - { - if (isDevToolsPresent) { - // If we have pending work still, restore the original updaters - restorePendingUpdaters(root, lanes); - } - } - - wakeable.then(ping, ping); - } -} + 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 + ); + } -function attachRetryListener(suspenseBoundary, root, wakeable, lanes) { - // 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"). - var wakeables = suspenseBoundary.updateQueue; - - if (wakeables === null) { - var updateQueue = new Set(); - updateQueue.add(wakeable); - suspenseBoundary.updateQueue = updateQueue; - } else { - wakeables.add(wakeable); - } -} + return false; + } -function resetSuspendedComponent(sourceFiber, rootRenderLanes) { - // A legacy mode Suspense quirk, only relevant to hook components. + { + // 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(", ") + "]" + ); + } + } - var tag = sourceFiber.tag; + for (var i = 0; i < prevDeps.length && i < nextDeps.length; i++) { + if (objectIs(nextDeps[i], prevDeps[i])) { + continue; + } - if ( - (sourceFiber.mode & ConcurrentMode) === NoMode && - (tag === FunctionComponent || - tag === ForwardRef || - tag === SimpleMemoComponent) - ) { - var currentSource = sourceFiber.alternate; + return false; + } - if (currentSource) { - sourceFiber.updateQueue = currentSource.updateQueue; - sourceFiber.memoizedState = currentSource.memoizedState; - sourceFiber.lanes = currentSource.lanes; - } else { - sourceFiber.updateQueue = null; - sourceFiber.memoizedState = null; + return true; } - } -} -function getNearestSuspenseBoundaryToCapture(returnFiber) { - var node = returnFiber; + function renderWithHooks( + current, + workInProgress, + Component, + props, + secondArg, + nextRenderLanes + ) { + renderLanes = nextRenderLanes; + currentlyRenderingFiber$1 = workInProgress; - do { - if (node.tag === SuspenseComponent && shouldCaptureSuspense(node)) { - return node; - } // This boundary already captured during this render. Continue to the next - // boundary. + { + hookTypesDev = current !== null ? current._debugHookTypes : null; + hookTypesUpdateIndexDev = -1; // Used for hot reloading: - node = node.return; - } while (node !== null); + ignorePreviousDependencies = + current !== null && current.type !== workInProgress.type; + } - return null; -} + workInProgress.memoizedState = null; + workInProgress.updateQueue = null; + workInProgress.lanes = NoLanes; // The following should have already been reset + // currentHook = null; + // workInProgressHook = null; + // didScheduleRenderPhaseUpdate = false; + // localIdCounter = 0; + // 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. -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; + { + 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 { - // 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(NoTimestamp, 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; -} + ReactCurrentDispatcher$1.current = HooksDispatcherOnMountInDEV; + } + } -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" && - typeof value.then === "function" - ) { - // This is a wakeable. The component suspended. - var wakeable = value; - resetSuspendedComponent(sourceFiber); - - var suspenseBoundary = getNearestSuspenseBoundaryToCapture(returnFiber); - - if (suspenseBoundary !== null) { - suspenseBoundary.flags &= ~ForceClientRender; - markSuspenseBoundaryShouldCapture( - suspenseBoundary, - returnFiber, - sourceFiber, - root, - rootRenderLanes - ); // We only attach ping listeners in concurrent mode. Legacy Suspense always - // commits fallbacks synchronously, so there are no pings. + var children = Component(props, secondArg); // Check if there was a render phase update - if (suspenseBoundary.mode & ConcurrentMode) { - attachPingListener(root, wakeable, rootRenderLanes); - } - - attachRetryListener(suspenseBoundary, root, wakeable); - return; - } 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 (!includesSyncLane(rootRenderLanes)) { - // This is not a sync update. Suspend. Since we're not activating a - // Suspense boundary, this will unwind all the way to the root without - // performing a second pass to render a fallback. (This is arguably how - // refresh transitions should work, too, since we're not going to commit - // the fallbacks anyway.) - // - // This case also applies to initial hydration. - attachPingListener(root, wakeable, rootRenderLanes); - renderDidSuspendDelayIfPossible(); - return; - } // This is a sync/discrete update. We treat this case like an error - // because discrete renders are expected to produce a complete tree - // synchronously to maintain consistency with external state. - - var uncaughtSuspenseError = new Error( - "A component suspended while responding to synchronous input. This " + - "will cause the UI to be replaced with a loading indicator. To " + - "fix, updates that suspend should be wrapped " + - "with startTransition." - ); // If we're outside a transition, fall through to the regular error path. - // The error will be caught by the nearest suspense boundary. - - value = uncaughtSuspenseError; - } - } - - 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. - - var workInProgress = returnFiber; - - 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 (didScheduleRenderPhaseUpdateDuringThisPass) { + // Keep rendering in a loop for as long as render phase updates continue to + // be scheduled. Use a counter to prevent infinite loops. + var numberOfReRenders = 0; - case ClassComponent: - // Capture and retry - var errorInfo = value; - var ctor = workInProgress.type; - var instance = workInProgress.stateNode; + do { + didScheduleRenderPhaseUpdateDuringThisPass = false; - if ( - (workInProgress.flags & DidCapture) === NoFlags && - (typeof ctor.getDerivedStateFromError === "function" || - (instance !== null && - typeof instance.componentDidCatch === "function" && - !isAlreadyFailedLegacyErrorBoundary(instance))) - ) { - workInProgress.flags |= ShouldCapture; + if (numberOfReRenders >= RE_RENDER_LIMIT) { + throw new Error( + "Too many re-renders. React limits the number of renders to prevent " + + "an infinite loop." + ); + } - var _lane = pickArbitraryLane(rootRenderLanes); + numberOfReRenders += 1; - workInProgress.lanes = mergeLanes(workInProgress.lanes, _lane); // Schedule the error boundary to re-render using updated state + { + // 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 - var _update = createClassErrorUpdate( - workInProgress, - errorInfo, - _lane - ); + currentHook = null; + workInProgressHook = null; + workInProgress.updateQueue = null; - enqueueCapturedUpdate(workInProgress, _update); - return; - } + { + // Also validate hook order for cascading updates. + hookTypesUpdateIndexDev = -1; + } - break; - } + ReactCurrentDispatcher$1.current = HooksDispatcherOnRerenderInDEV; + children = Component(props, secondArg); + } while (didScheduleRenderPhaseUpdateDuringThisPass); + } // 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. - workInProgress = workInProgress.return; - } while (workInProgress !== null); -} + ReactCurrentDispatcher$1.current = ContextOnlyDispatcher; -function getSuspendedCache() { - { - return null; - } // This function is called when a Suspense boundary suspends. It returns the -} + { + workInProgress._debugHookTypes = hookTypesDev; + } // 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 ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner; -var didReceiveUpdate = false; -var didWarnAboutBadClass; -var didWarnAboutModulePatternComponent; -var didWarnAboutContextTypeOnFunctionComponent; -var didWarnAboutGetDerivedStateOnFunctionComponent; -var didWarnAboutFunctionRefs; -var didWarnAboutReassigningProps; -var didWarnAboutRevealOrder; -var didWarnAboutTailOptions; - -{ - didWarnAboutBadClass = {}; - didWarnAboutModulePatternComponent = {}; - didWarnAboutContextTypeOnFunctionComponent = {}; - didWarnAboutGetDerivedStateOnFunctionComponent = {}; - didWarnAboutFunctionRefs = {}; - didWarnAboutReassigningProps = false; - didWarnAboutRevealOrder = {}; - didWarnAboutTailOptions = {}; -} + var didRenderTooFewHooks = currentHook !== null && currentHook.next !== null; + renderLanes = NoLanes; + currentlyRenderingFiber$1 = null; + currentHook = null; + workInProgressHook = null; -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 - ); - } -} + { + 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. -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 - ); -} + 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 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) + didScheduleRenderPhaseUpdate = false; // This is reset by checkDidRenderIdHook + // localIdCounter = 0; + + if (didRenderTooFewHooks) { + throw new Error( + "Rendered fewer hooks than expected. This may be caused by an accidental " + + "early return statement." ); } - } - } - - var render = Component.render; - var ref = workInProgress.ref; // The rest is a fork of updateFunctionComponent - var nextChildren; - prepareToReadContext(workInProgress, renderLanes); + 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). - { - ReactCurrentOwner$1.current = workInProgress; - setIsRendering(true); - nextChildren = renderWithHooks( - current, - workInProgress, - render, - nextProps, - ref, - renderLanes - ); + { + workInProgress.flags &= ~(Passive | Update); + } - setIsRendering(false); - } + current.lanes = removeLanes(current.lanes, lanes); + } + function resetHooksAfterThrow() { + // 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; - if (current !== null && !didReceiveUpdate) { - bailoutHooks(current, workInProgress, renderLanes); - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); - } + 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 = currentlyRenderingFiber$1.memoizedState; - workInProgress.flags |= PerformedWork; - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; -} + while (hook !== null) { + var queue = hook.queue; -function updateMemoComponent( - current, - workInProgress, - Component, - nextProps, - renderLanes -) { - if (current === null) { - var type = Component.type; + if (queue !== null) { + queue.pending = null; + } - if ( - isSimpleFunctionComponent(type) && - Component.compare === null && // SimpleMemoComponent codepath doesn't resolve outer props either. - Component.defaultProps === undefined - ) { - var resolvedType = type; + hook = hook.next; + } - { - 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. + didScheduleRenderPhaseUpdate = false; + } - workInProgress.tag = SimpleMemoComponent; - workInProgress.type = resolvedType; + renderLanes = NoLanes; + currentlyRenderingFiber$1 = null; + currentHook = null; + workInProgressHook = null; { - validateFunctionComponentInDev(workInProgress, type); + hookTypesDev = null; + hookTypesUpdateIndexDev = -1; + currentHookNameInDev = null; + isUpdatingOpaqueValueInRenderPhase = false; } - return updateSimpleMemoComponent( - current, - workInProgress, - resolvedType, - nextProps, - renderLanes - ); + didScheduleRenderPhaseUpdateDuringThisPass = false; } - { - 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 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; } - } - var child = createFiberFromTypeAndProps( - Component.type, - null, - nextProps, - 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 workInProgressHook; } - } - var currentChild = current.child; // This is always exactly one child + 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. When we reach the end of the base list, we must switch to + // the dispatcher used for mounts. + var nextCurrentHook; - var hasScheduledUpdateOrContext = checkScheduledUpdateOrContext( - current, - renderLanes - ); + if (currentHook === null) { + var current = currentlyRenderingFiber$1.alternate; - 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 (compare(prevProps, nextProps) && current.ref === workInProgress.ref) { - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); - } - } // React DevTools reads this flag. + if (current !== null) { + nextCurrentHook = current.memoizedState; + } else { + nextCurrentHook = null; + } + } else { + nextCurrentHook = currentHook.next; + } - workInProgress.flags |= PerformedWork; - var newChild = createWorkInProgress(currentChild, nextProps); - newChild.ref = workInProgress.ref; - newChild.return = workInProgress; - workInProgress.child = newChild; - return newChild; -} + var nextWorkInProgressHook; -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; + if (workInProgressHook === null) { + nextWorkInProgressHook = currentlyRenderingFiber$1.memoizedState; + } else { + nextWorkInProgressHook = workInProgressHook.next; + } - try { - outerMemoType = init(payload); - } catch (x) { - outerMemoType = null; - } // Inner propTypes will be validated in the function component path. + 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) { + throw new Error("Rendered more hooks than during the previous render."); + } - var outerPropTypes = outerMemoType && outerMemoType.propTypes; + currentHook = nextCurrentHook; + var newHook = { + memoizedState: currentHook.memoizedState, + baseState: currentHook.baseState, + baseQueue: currentHook.baseQueue, + queue: currentHook.queue, + next: null + }; - if (outerPropTypes) { - checkPropTypes( - outerPropTypes, - nextProps, // Resolved (SimpleMemoComponent has no defaultProps) - "prop", - getComponentNameFromType(outerMemoType) - ); + 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; } } - } - } - if (current !== null) { - var prevProps = current.memoizedProps; - - 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) { - // This is a special case that only exists for legacy mode. - // See https://github.com/facebook/react/pull/19216. - didReceiveUpdate = true; - } + return workInProgressHook; } - } - - return updateFunctionComponent( - current, - workInProgress, - Component, - nextProps, - renderLanes - ); -} -function updateOffscreenComponent(current, workInProgress, renderLanes) { - var nextProps = workInProgress.pendingProps; - var nextChildren = nextProps.children; - var prevState = current !== null ? current.memoizedState : null; - - if (nextProps.mode === "hidden" || enableLegacyHidden) { - // Rendering a hidden tree. - 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, - transitions: null + function createFunctionComponentUpdateQueue() { + return { + lastEffect: null, + stores: null }; - workInProgress.memoizedState = nextState; + } - pushRenderLanes(workInProgress, renderLanes); - } else if (!includesSomeLane(renderLanes, OffscreenLane)) { - var spawnedCachePool = null; // We're hidden, and we're not rendering at Offscreen. We will bail out - // and resume this tree later. + function basicStateReducer(state, action) { + // $FlowFixMe: Flow doesn't like mixed types + return typeof action === "function" ? action(state) : action; + } - var nextBaseLanes; + function mountReducer(reducer, initialArg, init) { + var hook = mountWorkInProgressHook(); + var initialState; - if (prevState !== null) { - var prevBaseLanes = prevState.baseLanes; - nextBaseLanes = mergeLanes(prevBaseLanes, renderLanes); + if (init !== undefined) { + initialState = init(initialArg); } else { - nextBaseLanes = renderLanes; - } // Schedule this fiber to re-render at offscreen priority. Then bailout. + initialState = initialArg; + } - workInProgress.lanes = workInProgress.childLanes = laneToLanes( - OffscreenLane - ); - var _nextState = { - baseLanes: nextBaseLanes, - cachePool: spawnedCachePool, - transitions: null + hook.memoizedState = hook.baseState = initialState; + var queue = { + pending: null, + interleaved: null, + lanes: NoLanes, + dispatch: null, + lastRenderedReducer: reducer, + lastRenderedState: initialState }; - workInProgress.memoizedState = _nextState; - workInProgress.updateQueue = null; - // to avoid a push/pop misalignment. + 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(); + var queue = hook.queue; - pushRenderLanes(workInProgress, nextBaseLanes); + if (queue === null) { + throw new Error( + "Should have a queue. This is likely a bug in React. Please file an issue." + ); + } - return null; - } 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 _nextState2 = { - baseLanes: NoLanes, - cachePool: null, - transitions: null - }; - workInProgress.memoizedState = _nextState2; // Push the lanes that were skipped when we bailed out. + queue.lastRenderedReducer = reducer; + var current = currentHook; // The last rebase update that is NOT part of the base state. - var subtreeRenderLanes = - prevState !== null ? prevState.baseLanes : renderLanes; + var baseQueue = current.baseQueue; // The last pending update that hasn't been processed yet. - pushRenderLanes(workInProgress, subtreeRenderLanes); - } - } else { - // Rendering a visible tree. - var _subtreeRenderLanes; + var pendingQueue = queue.pending; - if (prevState !== null) { - // We're going from hidden -> visible. - _subtreeRenderLanes = mergeLanes(prevState.baseLanes, renderLanes); + 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; + } - 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. - _subtreeRenderLanes = renderLanes; - } + { + 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." + ); + } + } - pushRenderLanes(workInProgress, _subtreeRenderLanes); - } + current.baseQueue = baseQueue = pendingQueue; + queue.pending = null; + } - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; -} // Note: These happen to have identical begin phases, for now. We shouldn't hold + if (baseQueue !== null) { + // We have a queue to process. + var first = baseQueue.next; + var newState = current.baseState; + var newBaseState = null; + var newBaseQueueFirst = null; + var newBaseQueueLast = null; + var update = first; -function updateFragment(current, workInProgress, renderLanes) { - var nextChildren = workInProgress.pendingProps; - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; -} + do { + var updateLane = update.lane; + + if (!isSubsetOfLanes(renderLanes, updateLane)) { + // 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, + 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. + 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, + action: update.action, + hasEagerState: update.hasEagerState, + eagerState: update.eagerState, + next: null + }; + newBaseQueueLast = newBaseQueueLast.next = _clone; + } // Process this update. + + 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 { + var action = update.action; + newState = reducer(newState, action); + } + } -function updateMode(current, workInProgress, renderLanes) { - var nextChildren = workInProgress.pendingProps.children; - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; -} + update = update.next; + } while (update !== null && update !== first); -function updateProfiler(current, workInProgress, renderLanes) { - { - workInProgress.flags |= Update; + 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. - { - // 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; -} + if (!objectIs(newState, hook.memoizedState)) { + markWorkInProgressReceivedUpdate(); + } -function markRef(current, workInProgress) { - var ref = workInProgress.ref; + hook.memoizedState = newState; + hook.baseState = newBaseState; + hook.baseQueue = newBaseQueueLast; + queue.lastRenderedState = newState; + } // Interleaved updates are stored on a separate queue. We aren't going to + // process them during this render, but we do need to track which lanes + // are remaining. - if ( - (current === null && ref !== null) || - (current !== null && current.ref !== ref) - ) { - // Schedule a Ref effect - workInProgress.flags |= Ref; - } -} + var lastInterleaved = queue.interleaved; -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 (lastInterleaved !== null) { + var interleaved = lastInterleaved; + + do { + var interleavedLane = interleaved.lane; + currentlyRenderingFiber$1.lanes = mergeLanes( + currentlyRenderingFiber$1.lanes, + interleavedLane + ); + markSkippedUpdateLanes(interleavedLane); + interleaved = interleaved.next; + } while (interleaved !== lastInterleaved); + } else 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]; } - } - var context; + function rerenderReducer(reducer, initialArg, init) { + var hook = updateWorkInProgressHook(); + var queue = hook.queue; - { - var unmaskedContext = getUnmaskedContext(workInProgress, Component, true); - context = getMaskedContext(workInProgress, unmaskedContext); - } + if (queue === null) { + throw new Error( + "Should have a queue. This is likely a bug in React. Please file an issue." + ); + } - var nextChildren; - prepareToReadContext(workInProgress, renderLanes); + queue.lastRenderedReducer = reducer; // This is a re-render. Apply the new render phase updates to the previous + // work-in-progress hook. - { - ReactCurrentOwner$1.current = workInProgress; - setIsRendering(true); - nextChildren = renderWithHooks( - current, - workInProgress, - Component, - nextProps, - context, - renderLanes - ); + var dispatch = queue.dispatch; + var lastRenderPhaseUpdate = queue.pending; + var newState = hook.memoizedState; - setIsRendering(false); - } + if (lastRenderPhaseUpdate !== null) { + // The queue doesn't persist past this render pass. + queue.pending = null; + var firstRenderPhaseUpdate = lastRenderPhaseUpdate.next; + var update = firstRenderPhaseUpdate; - if (current !== null && !didReceiveUpdate) { - bailoutHooks(current, workInProgress, renderLanes); - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); - } + 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. - workInProgress.flags |= PerformedWork; - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; -} + if (!objectIs(newState, hook.memoizedState)) { + markWorkInProgressReceivedUpdate(); + } -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; + 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. - _instance.updater.enqueueSetState(_instance, state, null); + if (hook.baseQueue === null) { + hook.baseState = newState; + } - break; + queue.lastRenderedState = newState; } - 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 + return [newState, dispatch]; + } - var update = createClassErrorUpdate( - workInProgress, - createCapturedValueAtFiber(error$1, workInProgress), - lane - ); - enqueueCapturedUpdate(workInProgress, update); - break; + function mountMutableSource(source, getSnapshot, subscribe) { + { + return undefined; } } - 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 updateMutableSource(source, getSnapshot, subscribe) { + { + return undefined; } } - } // 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 mountSyncExternalStore(subscribe, getSnapshot, getServerSnapshot) { + var fiber = currentlyRenderingFiber$1; + var hook = mountWorkInProgressHook(); + var nextSnapshot; - if (isContextProvider(Component)) { - hasContext = true; - pushContextProvider(workInProgress); - } else { - hasContext = false; - } + { + nextSnapshot = getSnapshot(); - prepareToReadContext(workInProgress, renderLanes); - var instance = workInProgress.stateNode; - var shouldUpdate; + { + if (!didWarnUncachedGetSnapshot) { + var cachedSnapshot = getSnapshot(); - if (instance === null) { - resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress); // In the initial pass we might need to construct the instance. + if (!objectIs(nextSnapshot, cachedSnapshot)) { + error( + "The result of getSnapshot should be cached to avoid an infinite loop" + ); - 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" - ); - } - - didWarnAboutReassigningProps = true; - } - } + 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. - return nextUnitOfWork; -} + var root = getWorkInProgressRoot(); -function finishClassComponent( - current, - workInProgress, - Component, - shouldUpdate, - hasContext, - renderLanes -) { - // Refs should update even if shouldComponentUpdate returns false - markRef(current, workInProgress); - var didCaptureError = (workInProgress.flags & DidCapture) !== NoFlags; - - 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; + if (root === null) { + throw new Error( + "Expected a work-in-progress root. This is a bug in React. Please file an issue." + ); + } - { - stopProfilerTimerIfRunning(); + if (!includesBlockingLane(root, renderLanes)) { + 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. + // TODO: We can move this to the passive phase once we add a pre-commit + // consistency check. See the next comment. + + fiber.flags |= Passive; + pushEffect( + HasEffect | Passive$1, + updateStoreInstance.bind(null, fiber, inst, nextSnapshot, getSnapshot), + undefined, + null + ); + return nextSnapshot; } - } else { - { - setIsRendering(true); - nextChildren = instance.render(); - setIsRendering(false); - } - } // React DevTools reads this flag. + 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. - workInProgress.flags |= PerformedWork; + var nextSnapshot = getSnapshot(); - 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 (!didWarnUncachedGetSnapshot) { + var cachedSnapshot = getSnapshot(); + + if (!objectIs(nextSnapshot, cachedSnapshot)) { + error( + "The result of getSnapshot should be cached to avoid an infinite loop" + ); - workInProgress.memoizedState = instance.state; // The context might have changed so we need to recalculate it. + didWarnUncachedGetSnapshot = true; + } + } + } - if (hasContext) { - invalidateContextProvider(workInProgress, Component, true); - } + var prevSnapshot = hook.memoizedState; + var snapshotChanged = !objectIs(prevSnapshot, nextSnapshot); - return workInProgress.child; -} + if (snapshotChanged) { + hook.memoizedState = nextSnapshot; + markWorkInProgressReceivedUpdate(); + } -function pushHostRootContext(workInProgress) { - var root = workInProgress.stateNode; + 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 (root.pendingContext) { - pushTopLevelContextObject( - workInProgress, - root.pendingContext, - root.pendingContext !== root.context - ); - } else if (root.context) { - // Should always be set - pushTopLevelContextObject(workInProgress, root.context, false); - } + if ( + inst.getSnapshot !== getSnapshot || + snapshotChanged || // Check if the susbcribe 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; + pushEffect( + HasEffect | Passive$1, + updateStoreInstance.bind(null, fiber, inst, nextSnapshot, getSnapshot), + undefined, + 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. - pushHostContainer(workInProgress, root.containerInfo); -} + 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." + ); + } -function updateHostRoot(current, workInProgress, renderLanes) { - pushHostRootContext(workInProgress); + if (!includesBlockingLane(root, renderLanes)) { + pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot); + } + } - if (current === null) { - throw new Error("Should have a current fiber. This is a bug in React."); - } + return nextSnapshot; + } - var nextProps = workInProgress.pendingProps; - var prevState = workInProgress.memoizedState; - var prevChildren = prevState.element; - cloneUpdateQueue(current, workInProgress); - processUpdateQueue(workInProgress, nextProps, null, renderLanes); - var nextState = workInProgress.memoizedState; - var root = workInProgress.stateNode; - // being called "element". + function pushStoreConsistencyCheck(fiber, getSnapshot, renderedSnapshot) { + fiber.flags |= StoreConsistency; + var check = { + getSnapshot: getSnapshot, + value: renderedSnapshot + }; + var componentUpdateQueue = currentlyRenderingFiber$1.updateQueue; - var nextChildren = nextState.element; + if (componentUpdateQueue === null) { + componentUpdateQueue = createFunctionComponentUpdateQueue(); + currentlyRenderingFiber$1.updateQueue = componentUpdateQueue; + componentUpdateQueue.stores = [check]; + } else { + var stores = componentUpdateQueue.stores; - { - if (nextChildren === prevChildren) { - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); + if (stores === null) { + componentUpdateQueue.stores = [check]; + } else { + stores.push(check); + } + } } - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - } + 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. - return workInProgress.child; -} + 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. -function updateHostComponent(current, workInProgress, renderLanes) { - pushHostContext(workInProgress); + return subscribe(handleStoreChange); + } - var type = workInProgress.type; - var nextProps = workInProgress.pendingProps; - var prevProps = current !== null ? current.memoizedProps : null; - var nextChildren = nextProps.children; + function checkIfSnapshotChanged(inst) { + var latestGetSnapshot = inst.getSnapshot; + var prevValue = inst.value; - if (prevProps !== null && shouldSetTextContent()) { - // 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; - } + try { + var nextValue = latestGetSnapshot(); + return !objectIs(prevValue, nextValue); + } catch (error) { + return true; + } + } - markRef(current, workInProgress); - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; -} + function forceStoreRerender(fiber) { + var root = enqueueConcurrentRenderForLane(fiber, SyncLane); -function updateHostText(current, workInProgress) { - // immediately after. + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + } + } - return null; -} + function mountState(initialState) { + var hook = mountWorkInProgressHook(); -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 (typeof initialState === "function") { + // $FlowFixMe: Flow doesn't like mixed types + initialState = initialState(); } - child = updateFunctionComponent( + hook.memoizedState = hook.baseState = initialState; + var queue = { + pending: null, + interleaved: null, + lanes: NoLanes, + dispatch: null, + lastRenderedReducer: basicStateReducer, + lastRenderedState: initialState + }; + hook.queue = queue; + var dispatch = (queue.dispatch = dispatchSetState.bind( null, - workInProgress, - Component, - resolvedProps, - renderLanes - ); - return child; + currentlyRenderingFiber$1, + queue + )); + return [hook.memoizedState, dispatch]; } - case ClassComponent: { - { - workInProgress.type = Component = resolveClassForHotReloading( - Component - ); + function updateState(initialState) { + return updateReducer(basicStateReducer); + } + + function rerenderState(initialState) { + return rerenderReducer(basicStateReducer); + } + + function pushEffect(tag, create, destroy, deps) { + var effect = { + tag: tag, + create: create, + destroy: destroy, + 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; + } } - child = updateClassComponent( - null, - workInProgress, - Component, - resolvedProps, - renderLanes - ); - return child; + return effect; } - case ForwardRef: { + function mountRef(initialValue) { + var hook = mountWorkInProgressHook(); + { - workInProgress.type = Component = resolveForwardRefForHotReloading( - Component - ); + var _ref2 = { + current: initialValue + }; + hook.memoizedState = _ref2; + return _ref2; } + } - child = updateForwardRef( - null, - workInProgress, - Component, - resolvedProps, - renderLanes + 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, + undefined, + nextDeps ); - return child; } - case MemoComponent: { - { - if (workInProgress.type !== workInProgress.elementType) { - var outerPropTypes = Component.propTypes; + function updateEffectImpl(fiberFlags, hookFlags, create, deps) { + var hook = updateWorkInProgressHook(); + var nextDeps = deps === undefined ? null : deps; + var destroy = undefined; - if (outerPropTypes) { - checkPropTypes( - outerPropTypes, - resolvedProps, // Resolved for outer only - "prop", - getComponentNameFromType(Component) - ); + if (currentHook !== null) { + var prevEffect = currentHook.memoizedState; + destroy = prevEffect.destroy; + + if (nextDeps !== null) { + var prevDeps = prevEffect.deps; + + if (areHookInputsEqual(nextDeps, prevDeps)) { + hook.memoizedState = pushEffect(hookFlags, create, destroy, nextDeps); + return; } } } - child = updateMemoComponent( - null, - workInProgress, - Component, - resolveDefaultProps(Component.type, resolvedProps), // The inner type can have defaults too - renderLanes + currentlyRenderingFiber$1.flags |= fiberFlags; + hook.memoizedState = pushEffect( + HasEffect | hookFlags, + create, + destroy, + nextDeps ); - return child; } - } - var hint = ""; + function mountEffect(create, deps) { + { + return mountEffectImpl(Passive | PassiveStatic, Passive$1, create, deps); + } + } - { - 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) - ); -} + function updateEffect(create, deps) { + return updateEffectImpl(Passive, Passive$1, create, deps); + } -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 - ); -} + function mountInsertionEffect(create, deps) { + return mountEffectImpl(Update, Insertion, create, deps); + } -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 ( - Component.prototype && - typeof Component.prototype.render === "function" - ) { - var componentName = getComponentNameFromType(Component) || "Unknown"; + function updateInsertionEffect(create, deps) { + return updateEffectImpl(Update, Insertion, create, deps); + } - 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 - ); + function mountLayoutEffect(create, deps) { + var fiberFlags = Update; - didWarnAboutBadClass[componentName] = true; - } + return mountEffectImpl(fiberFlags, Layout, create, deps); } - if (workInProgress.mode & StrictLegacyMode) { - ReactStrictModeWarnings.recordLegacyContextWarning(workInProgress, null); + function updateLayoutEffect(create, deps) { + return updateEffectImpl(Update, Layout, create, deps); } - setIsRendering(true); - ReactCurrentOwner$1.current = workInProgress; - value = renderWithHooks( - null, - workInProgress, - Component, - props, - context, - renderLanes - ); - setIsRendering(false); - } + function imperativeHandleEffect(create, ref) { + if (typeof ref === "function") { + var refCallback = ref; - workInProgress.flags |= PerformedWork; + var _inst = create(); - { - // 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"; + refCallback(_inst); + return function () { + refCallback(null); + }; + } else if (ref !== null && ref !== undefined) { + var refObject = ref; - 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 (!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(", ") + "}" + ); + } + } - didWarnAboutModulePatternComponent[_componentName] = true; + var _inst2 = create(); + + refObject.current = _inst2; + return function () { + refObject.current = null; + }; } } - } - if ( - // Run these checks in production only if the flag is off. - // Eventually we'll delete this branch altogether. - typeof value === "object" && - value !== null && - typeof value.render === "function" && - value.$$typeof === undefined - ) { - { - var _componentName2 = getComponentNameFromType(Component) || "Unknown"; + 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 (!didWarnAboutModulePatternComponent[_componentName2]) { - error( - "The <%s /> component appears to be a function component that returns a class instance. " + - "Change %s to a class that extends React.Component instead. " + - "If you can't use a class try assigning the prototype on the function as a workaround. " + - "`%s.prototype = React.Component.prototype`. Don't use an arrow function since it " + - "cannot be called with `new` by React.", - _componentName2, - _componentName2, - _componentName2 - ); + var effectDeps = + deps !== null && deps !== undefined ? deps.concat([ref]) : null; + var fiberFlags = Update; - didWarnAboutModulePatternComponent[_componentName2] = true; - } - } // Proceed under the assumption that this is a class instance + return mountEffectImpl( + fiberFlags, + Layout, + imperativeHandleEffect.bind(null, create, ref), + effectDeps + ); + } - workInProgress.tag = ClassComponent; // Throw out any hooks that were used. + 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; + return updateEffectImpl( + Update, + Layout, + imperativeHandleEffect.bind(null, create, ref), + effectDeps + ); + } - workInProgress.memoizedState = null; - workInProgress.updateQueue = null; // 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. + 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 hasContext = false; + var updateDebugValue = mountDebugValue; - if (isContextProvider(Component)) { - hasContext = true; - pushContextProvider(workInProgress); - } else { - hasContext = false; + function mountCallback(callback, deps) { + var hook = mountWorkInProgressHook(); + var nextDeps = deps === undefined ? null : deps; + hook.memoizedState = [callback, nextDeps]; + return callback; } - workInProgress.memoizedState = - value.state !== null && value.state !== undefined ? value.state : null; - initializeUpdateQueue(workInProgress); - adoptClassInstance(workInProgress, value); - mountClassInstance(workInProgress, Component, props, renderLanes); - return finishClassComponent( - null, - workInProgress, - Component, - true, - hasContext, - renderLanes - ); - } else { - // Proceed under the assumption that this is a function component - workInProgress.tag = FunctionComponent; + function updateCallback(callback, deps) { + var hook = updateWorkInProgressHook(); + var nextDeps = deps === undefined ? null : deps; + var prevState = hook.memoizedState; + + if (prevState !== null) { + if (nextDeps !== null) { + var prevDeps = prevState[1]; - reconcileChildren(null, workInProgress, value, renderLanes); + if (areHookInputsEqual(nextDeps, prevDeps)) { + return prevState[0]; + } + } + } - { - validateFunctionComponentInDev(workInProgress, Component); + hook.memoizedState = [callback, nextDeps]; + return callback; } - return workInProgress.child; - } -} - -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 mountMemo(nextCreate, deps) { + var hook = mountWorkInProgressHook(); + var nextDeps = deps === undefined ? null : deps; + var nextValue = nextCreate(); + hook.memoizedState = [nextValue, nextDeps]; + return nextValue; } - if (workInProgress.ref !== null) { - var info = ""; - var ownerName = getCurrentFiberOwnerNameInDevOrNull(); + function updateMemo(nextCreate, deps) { + var hook = updateWorkInProgressHook(); + var nextDeps = deps === undefined ? null : deps; + var prevState = hook.memoizedState; + + if (prevState !== null) { + // Assume these are defined. If they're not, areHookInputsEqual will warn. + if (nextDeps !== null) { + var prevDeps = prevState[1]; - if (ownerName) { - info += "\n\nCheck the render method of `" + ownerName + "`."; + if (areHookInputsEqual(nextDeps, prevDeps)) { + return prevState[0]; + } + } } - var warningKey = ownerName || ""; - var debugSource = workInProgress._debugSource; + var nextValue = nextCreate(); + hook.memoizedState = [nextValue, nextDeps]; + return nextValue; + } - if (debugSource) { - warningKey = debugSource.fileName + ":" + debugSource.lineNumber; - } + function mountDeferredValue(value) { + var hook = mountWorkInProgressHook(); + hook.memoizedState = value; + return value; + } - if (!didWarnAboutFunctionRefs[warningKey]) { - didWarnAboutFunctionRefs[warningKey] = true; + function updateDeferredValue(value) { + var hook = updateWorkInProgressHook(); + var resolvedCurrentHook = currentHook; + var prevValue = resolvedCurrentHook.memoizedState; + return updateDeferredValueImpl(hook, prevValue, value); + } - error( - "Function components cannot be given refs. " + - "Attempts to access this ref will fail. " + - "Did you mean to use React.forwardRef()?%s", - info - ); + function rerenderDeferredValue(value) { + var hook = updateWorkInProgressHook(); + + if (currentHook === null) { + // This is a rerender during a mount. + hook.memoizedState = value; + return value; + } else { + // This is a rerender during an update. + var prevValue = currentHook.memoizedState; + return updateDeferredValueImpl(hook, prevValue, value); } } - if (typeof Component.getDerivedStateFromProps === "function") { - var _componentName3 = getComponentNameFromType(Component) || "Unknown"; + function updateDeferredValueImpl(hook, prevValue, value) { + var shouldDeferValue = !includesOnlyNonUrgentLanes(renderLanes); - if (!didWarnAboutGetDerivedStateOnFunctionComponent[_componentName3]) { - error( - "%s: Function components do not support getDerivedStateFromProps.", - _componentName3 - ); + if (shouldDeferValue) { + // This is an urgent update. If the value has changed, keep using the + // previous value and spawn a deferred render to update it later. + if (!objectIs(value, prevValue)) { + // Schedule a deferred render + var deferredLane = claimNextTransitionLane(); + currentlyRenderingFiber$1.lanes = mergeLanes( + currentlyRenderingFiber$1.lanes, + deferredLane + ); + markSkippedUpdateLanes(deferredLane); // Set this to true to indicate that the rendered value is inconsistent + // from the latest value. The name "baseState" doesn't really match how we + // use it because we're reusing a state hook field instead of creating a + // new one. + + hook.baseState = true; + } // Reuse the previous 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. + // However, if we're currently inside a spawned render, then we need to mark + // this as an update to prevent the fiber from bailing out. + // + // `baseState` is true when the current value is different from the rendered + // value. The name doesn't really match how we use it because we're reusing + // a state hook field instead of creating a new one. + if (hook.baseState) { + // Flip this back to false. + hook.baseState = false; + markWorkInProgressReceivedUpdate(); + } - didWarnAboutGetDerivedStateOnFunctionComponent[_componentName3] = true; + hook.memoizedState = value; + return value; } } - if ( - typeof Component.contextType === "object" && - Component.contextType !== null - ) { - var _componentName4 = getComponentNameFromType(Component) || "Unknown"; + function startTransition(setPending, callback, options) { + var previousPriority = getCurrentUpdatePriority(); + setCurrentUpdatePriority( + higherEventPriority(previousPriority, ContinuousEventPriority) + ); + setPending(true); + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = {}; + var currentTransition = ReactCurrentBatchConfig$1.transition; - if (!didWarnAboutContextTypeOnFunctionComponent[_componentName4]) { - error( - "%s: Function components do not support contextType.", - _componentName4 - ); + { + ReactCurrentBatchConfig$1.transition._updatedFibers = new Set(); + } + + try { + setPending(false); + callback(); + } finally { + setCurrentUpdatePriority(previousPriority); + ReactCurrentBatchConfig$1.transition = prevTransition; + + { + if (prevTransition === null && currentTransition._updatedFibers) { + var updatedFibersCount = currentTransition._updatedFibers.size; + + 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." + ); + } - didWarnAboutContextTypeOnFunctionComponent[_componentName4] = true; + currentTransition._updatedFibers.clear(); + } + } } } - } -} -var SUSPENDED_MARKER = { - dehydrated: null, - treeContext: null, - retryLane: NoLane -}; - -function mountSuspenseOffscreenState(renderLanes) { - return { - baseLanes: renderLanes, - cachePool: getSuspendedCache(), - transitions: null - }; -} + function mountTransition() { + var _mountState = mountState(false), + isPending = _mountState[0], + setPending = _mountState[1]; // The `start` method never changes. -function updateSuspenseOffscreenState(prevOffscreenState, renderLanes) { - var cachePool = null; - - return { - baseLanes: mergeLanes(prevOffscreenState.baseLanes, renderLanes), - cachePool: cachePool, - transitions: prevOffscreenState.transitions - }; -} // TODO: Probably should inline this back - -function shouldRemainOnFallback( - suspenseContext, - 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. - 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; + var start = startTransition.bind(null, setPending); + var hook = mountWorkInProgressHook(); + hook.memoizedState = start; + return [isPending, start]; } - } // Not currently showing content. Consult the Suspense context. - return hasSuspenseContext(suspenseContext, ForceSuspenseFallback); -} + function updateTransition() { + var _updateState = updateState(), + isPending = _updateState[0]; -function getRemainingWorkInPrimaryTree(current, renderLanes) { - // TODO: Should not remove render lanes that were pinged during this render - return removeLanes(current.childLanes, renderLanes); -} + var hook = updateWorkInProgressHook(); + var start = hook.memoizedState; + return [isPending, start]; + } + + function rerenderTransition() { + var _rerenderState = rerenderState(), + isPending = _rerenderState[0]; + + var hook = updateWorkInProgressHook(); + var start = hook.memoizedState; + return [isPending, start]; + } -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 suspenseContext = suspenseStackCursor.current; - var showFallback = false; - var didSuspend = (workInProgress.flags & DidCapture) !== NoFlags; - - if (didSuspend || shouldRemainOnFallback(suspenseContext, current)) { - // Something in this boundary's subtree already suspended. Switch to - // rendering the fallback children. - showFallback = true; - workInProgress.flags &= ~DidCapture; - } else { - // Attempting the main content - if (current === null || current.memoizedState !== null) { - // This is a new mount or this boundary is already showing a fallback state. - // Mark this subtree context as having at least one invisible parent that could - // handle the fallback state. - // Avoided boundaries are not considered since they cannot handle preferred fallback states. + var isUpdatingOpaqueValueInRenderPhase = false; + function getIsUpdatingOpaqueValueInRenderPhaseInDEV() { { - suspenseContext = addSubtreeSuspenseContext( - suspenseContext, - InvisibleParentSuspenseContext - ); + return isUpdatingOpaqueValueInRenderPhase; } } - } - - suspenseContext = setDefaultShallowSuspenseContext(suspenseContext); - pushSuspenseContext(workInProgress, suspenseContext); // 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 suspenseState = workInProgress.memoizedState; - - if (suspenseState !== null) { - var dehydrated = suspenseState.dehydrated; - - if (dehydrated !== null) { - return mountDehydratedSuspenseComponent(workInProgress); - } - } - - var nextPrimaryChildren = nextProps.children; - var nextFallbackChildren = nextProps.fallback; - - if (showFallback) { - var fallbackFragment = mountSuspenseFallbackChildren( - workInProgress, - nextPrimaryChildren, - nextFallbackChildren, - renderLanes - ); - var primaryChildFragment = workInProgress.child; - primaryChildFragment.memoizedState = mountSuspenseOffscreenState( - renderLanes - ); - workInProgress.memoizedState = SUSPENDED_MARKER; - return fallbackFragment; - } else { - return mountSuspensePrimaryChildren(workInProgress, nextPrimaryChildren); - } - } else { - // This is an update. - // Special path for hydration - var prevState = current.memoizedState; + 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. - if (prevState !== null) { - var _dehydrated = prevState.dehydrated; + var identifierPrefix = root.identifierPrefix; + var id; - if (_dehydrated !== null) { - return updateDehydratedSuspenseComponent( - current, - workInProgress, - didSuspend, - nextProps, - _dehydrated, - prevState, - renderLanes - ); + { + // Use a lowercase r prefix for client-generated ids. + var globalClientId = globalClientIdCounter++; + id = ":" + identifierPrefix + "r" + globalClientId.toString(32) + ":"; } + + hook.memoizedState = id; + return id; } - if (showFallback) { - var _nextFallbackChildren = nextProps.fallback; - var _nextPrimaryChildren = nextProps.children; - var fallbackChildFragment = updateSuspenseFallbackChildren( + function updateId() { + var hook = updateWorkInProgressHook(); + var id = hook.memoizedState; + return id; + } + + 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, + 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) { + var eventTime = requestEventTime(); + scheduleUpdateOnFiber(root, fiber, lane, eventTime); + entangleTransitionUpdate(root, queue, lane); + } + } + } + + 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, + 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, + lane + ); + 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) { + var eventTime = requestEventTime(); + scheduleUpdateOnFiber(root, fiber, lane, eventTime); + entangleTransitionUpdate(root, queue, lane); + } + } + } + + 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); + } + } + + var ContextOnlyDispatcher = { + readContext: readContext, + 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, + useMutableSource: throwInvalidHookError, + useSyncExternalStore: throwInvalidHookError, + useId: throwInvalidHookError, + unstable_isNewReconciler: enableNewReconciler + }; + + 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://react.dev/link/rules-of-hooks" + ); + }; + + HooksDispatcherOnMountInDEV = { + readContext: function (context) { + return readContext(context); + }, + 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) { + currentHookNameInDev = "useDeferredValue"; + mountHookTypesDev(); + return mountDeferredValue(value); + }, + useTransition: function () { + currentHookNameInDev = "useTransition"; + mountHookTypesDev(); + return mountTransition(); + }, + useMutableSource: function (source, getSnapshot, subscribe) { + currentHookNameInDev = "useMutableSource"; + mountHookTypesDev(); + return mountMutableSource(); + }, + useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { + currentHookNameInDev = "useSyncExternalStore"; + mountHookTypesDev(); + return mountSyncExternalStore(subscribe, getSnapshot); + }, + useId: function () { + currentHookNameInDev = "useId"; + mountHookTypesDev(); + return mountId(); + }, + unstable_isNewReconciler: enableNewReconciler + }; + + HooksDispatcherOnMountWithHookTypesInDEV = { + readContext: function (context) { + return readContext(context); + }, + 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) { + currentHookNameInDev = "useDeferredValue"; + updateHookTypesDev(); + return mountDeferredValue(value); + }, + useTransition: function () { + currentHookNameInDev = "useTransition"; + updateHookTypesDev(); + return mountTransition(); + }, + useMutableSource: function (source, getSnapshot, subscribe) { + currentHookNameInDev = "useMutableSource"; + updateHookTypesDev(); + return mountMutableSource(); + }, + useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { + currentHookNameInDev = "useSyncExternalStore"; + updateHookTypesDev(); + return mountSyncExternalStore(subscribe, getSnapshot); + }, + useId: function () { + currentHookNameInDev = "useId"; + updateHookTypesDev(); + return mountId(); + }, + unstable_isNewReconciler: enableNewReconciler + }; + + HooksDispatcherOnUpdateInDEV = { + readContext: function (context) { + return readContext(context); + }, + 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) { + currentHookNameInDev = "useDeferredValue"; + updateHookTypesDev(); + return updateDeferredValue(value); + }, + useTransition: function () { + currentHookNameInDev = "useTransition"; + updateHookTypesDev(); + return updateTransition(); + }, + useMutableSource: function (source, getSnapshot, subscribe) { + currentHookNameInDev = "useMutableSource"; + updateHookTypesDev(); + return updateMutableSource(); + }, + useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { + currentHookNameInDev = "useSyncExternalStore"; + updateHookTypesDev(); + return updateSyncExternalStore(subscribe, getSnapshot); + }, + useId: function () { + currentHookNameInDev = "useId"; + updateHookTypesDev(); + return updateId(); + }, + unstable_isNewReconciler: enableNewReconciler + }; + + HooksDispatcherOnRerenderInDEV = { + readContext: function (context) { + return readContext(context); + }, + 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) { + currentHookNameInDev = "useDeferredValue"; + updateHookTypesDev(); + return rerenderDeferredValue(value); + }, + useTransition: function () { + currentHookNameInDev = "useTransition"; + updateHookTypesDev(); + return rerenderTransition(); + }, + useMutableSource: function (source, getSnapshot, subscribe) { + currentHookNameInDev = "useMutableSource"; + updateHookTypesDev(); + return updateMutableSource(); + }, + useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { + currentHookNameInDev = "useSyncExternalStore"; + updateHookTypesDev(); + return updateSyncExternalStore(subscribe, getSnapshot); + }, + useId: function () { + currentHookNameInDev = "useId"; + updateHookTypesDev(); + return updateId(); + }, + unstable_isNewReconciler: enableNewReconciler + }; + + InvalidNestedHooksDispatcherOnMountInDEV = { + readContext: function (context) { + warnInvalidContextAccess(); + return readContext(context); + }, + 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) { + currentHookNameInDev = "useDeferredValue"; + warnInvalidHookAccess(); + mountHookTypesDev(); + return mountDeferredValue(value); + }, + useTransition: function () { + currentHookNameInDev = "useTransition"; + warnInvalidHookAccess(); + mountHookTypesDev(); + return mountTransition(); + }, + useMutableSource: function (source, getSnapshot, subscribe) { + currentHookNameInDev = "useMutableSource"; + warnInvalidHookAccess(); + mountHookTypesDev(); + return mountMutableSource(); + }, + useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { + currentHookNameInDev = "useSyncExternalStore"; + warnInvalidHookAccess(); + mountHookTypesDev(); + return mountSyncExternalStore(subscribe, getSnapshot); + }, + useId: function () { + currentHookNameInDev = "useId"; + warnInvalidHookAccess(); + mountHookTypesDev(); + return mountId(); + }, + unstable_isNewReconciler: enableNewReconciler + }; + + InvalidNestedHooksDispatcherOnUpdateInDEV = { + readContext: function (context) { + warnInvalidContextAccess(); + return readContext(context); + }, + 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) { + currentHookNameInDev = "useDeferredValue"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateDeferredValue(value); + }, + useTransition: function () { + currentHookNameInDev = "useTransition"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateTransition(); + }, + useMutableSource: function (source, getSnapshot, subscribe) { + currentHookNameInDev = "useMutableSource"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateMutableSource(); + }, + useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { + currentHookNameInDev = "useSyncExternalStore"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateSyncExternalStore(subscribe, getSnapshot); + }, + useId: function () { + currentHookNameInDev = "useId"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateId(); + }, + unstable_isNewReconciler: enableNewReconciler + }; + + InvalidNestedHooksDispatcherOnRerenderInDEV = { + readContext: function (context) { + warnInvalidContextAccess(); + return readContext(context); + }, + 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) { + currentHookNameInDev = "useDeferredValue"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return rerenderDeferredValue(value); + }, + useTransition: function () { + currentHookNameInDev = "useTransition"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return rerenderTransition(); + }, + useMutableSource: function (source, getSnapshot, subscribe) { + currentHookNameInDev = "useMutableSource"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateMutableSource(); + }, + useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { + currentHookNameInDev = "useSyncExternalStore"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateSyncExternalStore(subscribe, getSnapshot); + }, + useId: function () { + currentHookNameInDev = "useId"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateId(); + }, + unstable_isNewReconciler: enableNewReconciler + }; + } + + var now$1 = 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; + } + } + + function resetNestedUpdateFlag() { + { + currentUpdateIsNested = false; + nestedUpdateScheduled = false; + } + } + + function syncNestedUpdateFlag() { + { + currentUpdateIsNested = nestedUpdateScheduled; + nestedUpdateScheduled = false; + } + } + + function getCommitTime() { + return commitTime; + } + + function recordCommitTime() { + commitTime = now$1(); + } + + function startProfilerTimer(fiber) { + profilerStartTime = now$1(); + + if (fiber.actualStartTime < 0) { + fiber.actualStartTime = now$1(); + } + } + + function stopProfilerTimerIfRunning(fiber) { + profilerStartTime = -1; + } + + function stopProfilerTimerIfRunningAndRecordDelta(fiber, overrideBaseTime) { + if (profilerStartTime >= 0) { + var elapsedTime = now$1() - profilerStartTime; + fiber.actualDuration += elapsedTime; + + if (overrideBaseTime) { + fiber.selfBaseDuration = elapsedTime; + } + + profilerStartTime = -1; + } + } + + function recordLayoutEffectDuration(fiber) { + if (layoutEffectStartTime >= 0) { + var elapsedTime = now$1() - layoutEffectStartTime; + layoutEffectStartTime = -1; // Store duration on the next nearest Profiler ancestor + // Or the root (for the DevTools Profiler to read) + + var parentFiber = fiber.return; + + 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 recordPassiveEffectDuration(fiber) { + if (passiveEffectStartTime >= 0) { + var elapsedTime = now$1() - passiveEffectStartTime; + passiveEffectStartTime = -1; // Store duration on the next nearest Profiler ancestor + // Or the root (for the DevTools Profiler to read) + + var parentFiber = fiber.return; + + while (parentFiber !== null) { + switch (parentFiber.tag) { + case HostRoot: + var root = parentFiber.stateNode; + + if (root !== null) { + root.passiveEffectDuration += elapsedTime; + } + + return; + + case Profiler: + var parentStateNode = parentFiber.stateNode; + + 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; + } + + return; + } + + parentFiber = parentFiber.return; + } + } + } + + function startLayoutEffectTimer() { + layoutEffectStartTime = now$1(); + } + + function startPassiveEffectTimer() { + passiveEffectStartTime = now$1(); + } + + 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) { + fiber.actualDuration += child.actualDuration; + child = child.sibling; + } + } + + 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 ( + typeof ReactNativePrivateInterface.ReactFiberErrorDialog.showErrorDialog !== + "function" + ) { + throw new Error( + "Expected ReactFiberErrorDialog.showErrorDialog to be a function." + ); + } + + 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 ReactNativePrivateInterface.ReactFiberErrorDialog.showErrorDialog( + capturedError + ); + } + + 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 (logError === false) { + return; + } + + var error = errorInfo.value; + + 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 (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://react.dev/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 + } else { + // In production, we print the error directly. + // This will include the message, the JS stack, and anything the browser wants to show. + // We pass the error object instead of custom message so that the browser displays the error natively. + console["error"](error); // 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; + }); + } + } + + var PossiblyWeakMap$1 = typeof WeakMap === "function" ? WeakMap : Map; + + function createRootErrorUpdate(fiber, errorInfo, lane) { + var update = createUpdate(NoTimestamp, lane); // Unmount the root by rendering null. + + update.tag = CaptureUpdate; // Caution: React DevTools currently depends on this property + // being called "element". + + update.payload = { + element: null + }; + var error = errorInfo.value; + + update.callback = function () { + onUncaughtError(error); + logCapturedError(fiber, errorInfo); + }; + + return update; + } + + function createClassErrorUpdate(fiber, errorInfo, lane) { + var update = createUpdate(NoTimestamp, lane); + update.tag = CaptureUpdate; + var getDerivedStateFromError = fiber.type.getDerivedStateFromError; + + if (typeof getDerivedStateFromError === "function") { + var error$1 = errorInfo.value; + + update.payload = function () { + return getDerivedStateFromError(error$1); + }; + + update.callback = function () { + { + markFailedErrorBoundaryForHotReloading(fiber); + } + + logCapturedError(fiber, errorInfo); + }; + } + + var inst = fiber.stateNode; + + if (inst !== null && typeof inst.componentDidCatch === "function") { + update.callback = function callback() { + { + markFailedErrorBoundaryForHotReloading(fiber); + } + + logCapturedError(fiber, errorInfo); + + 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 update; + } + + 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$1(); + 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)) { + // 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); + } + } + + wakeable.then(ping, ping); + } + } + + function attachRetryListener(suspenseBoundary, root, wakeable, lanes) { + // 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"). + var wakeables = suspenseBoundary.updateQueue; + + if (wakeables === null) { + var updateQueue = new Set(); + updateQueue.add(wakeable); + suspenseBoundary.updateQueue = updateQueue; + } else { + wakeables.add(wakeable); + } + } + + function resetSuspendedComponent(sourceFiber, rootRenderLanes) { + // 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 getNearestSuspenseBoundaryToCapture(returnFiber) { + var node = returnFiber; + + do { + if (node.tag === SuspenseComponent && shouldCaptureSuspense(node)) { + return node; + } // This boundary already captured during this render. Continue to the next + // boundary. + + node = node.return; + } while (node !== null); + + return null; + } + + 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(NoTimestamp, 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" && + typeof value.then === "function" + ) { + // This is a wakeable. The component suspended. + var wakeable = value; + resetSuspendedComponent(sourceFiber); + + var suspenseBoundary = getNearestSuspenseBoundaryToCapture(returnFiber); + + if (suspenseBoundary !== null) { + suspenseBoundary.flags &= ~ForceClientRender; + markSuspenseBoundaryShouldCapture( + suspenseBoundary, + returnFiber, + sourceFiber, + root, + rootRenderLanes + ); // 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); + } + + attachRetryListener(suspenseBoundary, root, wakeable); + return; + } 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 (!includesSyncLane(rootRenderLanes)) { + // This is not a sync update. Suspend. Since we're not activating a + // Suspense boundary, this will unwind all the way to the root without + // performing a second pass to render a fallback. (This is arguably how + // refresh transitions should work, too, since we're not going to commit + // the fallbacks anyway.) + // + // This case also applies to initial hydration. + attachPingListener(root, wakeable, rootRenderLanes); + renderDidSuspendDelayIfPossible(); + return; + } // This is a sync/discrete update. We treat this case like an error + // because discrete renders are expected to produce a complete tree + // synchronously to maintain consistency with external state. + + var uncaughtSuspenseError = new Error( + "A component suspended while responding to synchronous input. This " + + "will cause the UI to be replaced with a loading indicator. To " + + "fix, updates that suspend should be wrapped " + + "with startTransition." + ); // If we're outside a transition, fall through to the regular error path. + // The error will be caught by the nearest suspense boundary. + + value = uncaughtSuspenseError; + } + } + + 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. + + var workInProgress = returnFiber; + + 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; + } + + case ClassComponent: + // Capture and retry + var errorInfo = value; + var ctor = workInProgress.type; + var instance = workInProgress.stateNode; + + if ( + (workInProgress.flags & DidCapture) === NoFlags && + (typeof ctor.getDerivedStateFromError === "function" || + (instance !== null && + typeof instance.componentDidCatch === "function" && + !isAlreadyFailedLegacyErrorBoundary(instance))) + ) { + workInProgress.flags |= ShouldCapture; + + var _lane = pickArbitraryLane(rootRenderLanes); + + workInProgress.lanes = mergeLanes(workInProgress.lanes, _lane); // Schedule the error boundary to re-render using updated state + + var _update = createClassErrorUpdate( + workInProgress, + errorInfo, + _lane + ); + + enqueueCapturedUpdate(workInProgress, _update); + return; + } + + break; + } + + workInProgress = workInProgress.return; + } while (workInProgress !== null); + } + + function getSuspendedCache() { + { + return null; + } // This function is called when a Suspense boundary suspends. It returns the + } + + var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner; + var didReceiveUpdate = false; + var didWarnAboutBadClass; + var didWarnAboutModulePatternComponent; + var didWarnAboutContextTypeOnFunctionComponent; + var didWarnAboutGetDerivedStateOnFunctionComponent; + var didWarnAboutFunctionRefs; + var didWarnAboutReassigningProps; + var didWarnAboutRevealOrder; + var didWarnAboutTailOptions; + + { + didWarnAboutBadClass = {}; + didWarnAboutModulePatternComponent = {}; + didWarnAboutContextTypeOnFunctionComponent = {}; + didWarnAboutGetDerivedStateOnFunctionComponent = {}; + didWarnAboutFunctionRefs = {}; + didWarnAboutReassigningProps = false; + didWarnAboutRevealOrder = {}; + didWarnAboutTailOptions = {}; + } + + 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 + ); + } + } + + 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 + ); + } + + 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) + ); + } + } + } + + var render = Component.render; + var ref = workInProgress.ref; // The rest is a fork of updateFunctionComponent + + var nextChildren; + prepareToReadContext(workInProgress, renderLanes); + + { + ReactCurrentOwner$1.current = workInProgress; + setIsRendering(true); + nextChildren = renderWithHooks( + current, + workInProgress, + render, + nextProps, + ref, + renderLanes + ); + + setIsRendering(false); + } + + if (current !== null && !didReceiveUpdate) { + bailoutHooks(current, workInProgress, renderLanes); + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); + } + + workInProgress.flags |= PerformedWork; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; + } + + function updateMemoComponent( + current, + workInProgress, + Component, + nextProps, + renderLanes + ) { + if (current === null) { + var type = Component.type; + + if ( + isSimpleFunctionComponent(type) && + Component.compare === null && // SimpleMemoComponent codepath doesn't resolve outer props either. + Component.defaultProps === undefined + ) { + var resolvedType = type; + + { + 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. + + workInProgress.tag = SimpleMemoComponent; + workInProgress.type = resolvedType; + + { + validateFunctionComponentInDev(workInProgress, type); + } + + return updateSimpleMemoComponent( + current, + workInProgress, + resolvedType, + nextProps, + renderLanes + ); + } + + { + 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) + ); + } + } + + var child = createFiberFromTypeAndProps( + Component.type, + null, + nextProps, + 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) + ); + } + } + + var currentChild = current.child; // This is always exactly one child + + 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 (compare(prevProps, nextProps) && current.ref === workInProgress.ref) { + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); + } + } // 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 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; + + 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) + ); + } + } + } + } + + if (current !== null) { + var prevProps = current.memoizedProps; + + 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) { + // This is a special case that only exists for legacy mode. + // See https://github.com/facebook/react/pull/19216. + didReceiveUpdate = true; + } + } + } + + return updateFunctionComponent( + current, + workInProgress, + Component, + nextProps, + renderLanes + ); + } + + function updateOffscreenComponent(current, workInProgress, renderLanes) { + var nextProps = workInProgress.pendingProps; + var nextChildren = nextProps.children; + var prevState = current !== null ? current.memoizedState : null; + + if (nextProps.mode === "hidden" || enableLegacyHidden) { + // Rendering a hidden tree. + 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, + transitions: null + }; + workInProgress.memoizedState = nextState; + + pushRenderLanes(workInProgress, renderLanes); + } else if (!includesSomeLane(renderLanes, OffscreenLane)) { + var spawnedCachePool = null; // We're hidden, and we're not rendering at Offscreen. We will bail out + // and resume this tree later. + + var nextBaseLanes; + + if (prevState !== null) { + var prevBaseLanes = prevState.baseLanes; + nextBaseLanes = mergeLanes(prevBaseLanes, renderLanes); + } else { + nextBaseLanes = renderLanes; + } // Schedule this fiber to re-render at offscreen priority. Then bailout. + + workInProgress.lanes = workInProgress.childLanes = laneToLanes( + OffscreenLane + ); + var _nextState = { + baseLanes: nextBaseLanes, + cachePool: spawnedCachePool, + transitions: null + }; + workInProgress.memoizedState = _nextState; + workInProgress.updateQueue = null; + // to avoid a push/pop misalignment. + + pushRenderLanes(workInProgress, nextBaseLanes); + + return null; + } 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 _nextState2 = { + baseLanes: NoLanes, + cachePool: null, + transitions: null + }; + workInProgress.memoizedState = _nextState2; // Push the lanes that were skipped when we bailed out. + + var subtreeRenderLanes = + prevState !== null ? prevState.baseLanes : renderLanes; + + pushRenderLanes(workInProgress, subtreeRenderLanes); + } + } else { + // Rendering a visible tree. + var _subtreeRenderLanes; + + if (prevState !== null) { + // We're going from hidden -> visible. + _subtreeRenderLanes = mergeLanes(prevState.baseLanes, renderLanes); + + 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. + _subtreeRenderLanes = renderLanes; + } + + pushRenderLanes(workInProgress, _subtreeRenderLanes); + } + + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; + } // Note: These happen to have identical begin phases, for now. We shouldn't hold + + function updateFragment(current, workInProgress, renderLanes) { + var nextChildren = workInProgress.pendingProps; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; + } + + function updateMode(current, workInProgress, renderLanes) { + var nextChildren = workInProgress.pendingProps.children; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; + } + + 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; + } + } + + var nextProps = workInProgress.pendingProps; + var nextChildren = nextProps.children; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; + } + + function markRef(current, workInProgress) { + var ref = workInProgress.ref; + + if ( + (current === null && ref !== null) || + (current !== null && current.ref !== ref) + ) { + // Schedule a Ref effect + workInProgress.flags |= Ref; + } + } + + 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) + ); + } + } + } + + var context; + + { + var unmaskedContext = getUnmaskedContext(workInProgress, Component, true); + context = getMaskedContext(workInProgress, unmaskedContext); + } + + var nextChildren; + prepareToReadContext(workInProgress, renderLanes); + + { + ReactCurrentOwner$1.current = workInProgress; + setIsRendering(true); + nextChildren = renderWithHooks( + current, + workInProgress, + Component, + nextProps, + context, + renderLanes + ); + + setIsRendering(false); + } + + if (current !== null && !didReceiveUpdate) { + bailoutHooks(current, workInProgress, renderLanes); + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); + } + + workInProgress.flags |= PerformedWork; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; + } + + 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; + + _instance.updater.enqueueSetState(_instance, state, null); + + break; + } + + 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 update = createClassErrorUpdate( + workInProgress, + createCapturedValueAtFiber(error$1, workInProgress), + lane + ); + enqueueCapturedUpdate(workInProgress, update); + break; + } + } + + 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) + ); + } + } + } // 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 instance = workInProgress.stateNode; + var shouldUpdate; + + 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 + ); + } + + var nextUnitOfWork = finishClassComponent( current, workInProgress, - _nextPrimaryChildren, - _nextFallbackChildren, - renderLanes + 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" + ); + } + + didWarnAboutReassigningProps = true; + } + } + + return nextUnitOfWork; + } + + function finishClassComponent( + current, + workInProgress, + Component, + shouldUpdate, + hasContext, + renderLanes + ) { + // Refs should update even if shouldComponentUpdate returns false + markRef(current, workInProgress); + var didCaptureError = (workInProgress.flags & DidCapture) !== NoFlags; + + 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; + + { + stopProfilerTimerIfRunning(); + } + } else { + { + setIsRendering(true); + nextChildren = instance.render(); + + setIsRendering(false); + } + } // 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( + 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. + + workInProgress.memoizedState = instance.state; // The context might have changed so we need to recalculate it. + + if (hasContext) { + invalidateContextProvider(workInProgress, Component, true); + } + + return workInProgress.child; + } + + function pushHostRootContext(workInProgress) { + var root = workInProgress.stateNode; + + if (root.pendingContext) { + pushTopLevelContextObject( + workInProgress, + root.pendingContext, + root.pendingContext !== root.context + ); + } else if (root.context) { + // Should always be set + pushTopLevelContextObject(workInProgress, root.context, false); + } + + pushHostContainer(workInProgress, root.containerInfo); + } + + function updateHostRoot(current, workInProgress, renderLanes) { + pushHostRootContext(workInProgress); + + if (current === null) { + throw new Error("Should have a current fiber. This is a bug in React."); + } + + var nextProps = workInProgress.pendingProps; + var prevState = workInProgress.memoizedState; + var prevChildren = prevState.element; + cloneUpdateQueue(current, workInProgress); + processUpdateQueue(workInProgress, nextProps, null, renderLanes); + var nextState = workInProgress.memoizedState; + var root = workInProgress.stateNode; + // being called "element". + + var nextChildren = nextState.element; + + { + if (nextChildren === prevChildren) { + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); + } + + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + } + + return workInProgress.child; + } + + function updateHostComponent(current, workInProgress, renderLanes) { + pushHostContext(workInProgress); + + var type = workInProgress.type; + var nextProps = workInProgress.pendingProps; + var prevProps = current !== null ? current.memoizedProps : null; + var nextChildren = nextProps.children; + + if (prevProps !== null && shouldSetTextContent()) { + // 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(current, workInProgress); + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; + } + + function updateHostText(current, workInProgress) { + // immediately after. + + return null; + } + + 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; + } + + case ClassComponent: { + { + workInProgress.type = Component = resolveClassForHotReloading( + Component + ); + } + + child = updateClassComponent( + null, + workInProgress, + Component, + resolvedProps, + renderLanes + ); + return child; + } + + case ForwardRef: { + { + workInProgress.type = Component = resolveForwardRefForHotReloading( + Component + ); + } + + child = updateForwardRef( + null, + workInProgress, + Component, + resolvedProps, + renderLanes + ); + return child; + } + + case MemoComponent: { + { + if (workInProgress.type !== workInProgress.elementType) { + var outerPropTypes = Component.propTypes; + + if (outerPropTypes) { + checkPropTypes( + outerPropTypes, + resolvedProps, // Resolved for outer only + "prop", + getComponentNameFromType(Component) + ); + } + } + } + + child = updateMemoComponent( + null, + workInProgress, + Component, + resolveDefaultProps(Component.type, resolvedProps), // The inner type can have defaults too + renderLanes + ); + return child; + } + } + + var hint = ""; + + { + 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) + ); + } + + 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 + ); + } + + 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 ( + Component.prototype && + typeof Component.prototype.render === "function" + ) { + var componentName = getComponentNameFromType(Component) || "Unknown"; + + 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 + ); + + didWarnAboutBadClass[componentName] = true; + } + } + + if (workInProgress.mode & StrictLegacyMode) { + ReactStrictModeWarnings.recordLegacyContextWarning(workInProgress, null); + } + + setIsRendering(true); + ReactCurrentOwner$1.current = workInProgress; + value = renderWithHooks( + null, + workInProgress, + Component, + props, + context, + renderLanes + ); + setIsRendering(false); + } + + workInProgress.flags |= PerformedWork; + + { + // 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 ( + // Run these checks in production only if the flag is off. + // Eventually we'll delete this branch altogether. + typeof value === "object" && + value !== null && + typeof value.render === "function" && + value.$$typeof === undefined + ) { + { + var _componentName2 = getComponentNameFromType(Component) || "Unknown"; + + if (!didWarnAboutModulePatternComponent[_componentName2]) { + error( + "The <%s /> component appears to be a function component that returns a class instance. " + + "Change %s to a class that extends React.Component instead. " + + "If you can't use a class try assigning the prototype on the function as a workaround. " + + "`%s.prototype = React.Component.prototype`. Don't use an arrow function since it " + + "cannot be called with `new` by React.", + _componentName2, + _componentName2, + _componentName2 + ); + + didWarnAboutModulePatternComponent[_componentName2] = true; + } + } // Proceed under the assumption that this is a class instance + + workInProgress.tag = ClassComponent; // Throw out any hooks that were used. + + workInProgress.memoizedState = null; + workInProgress.updateQueue = null; // 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 = false; + + if (isContextProvider(Component)) { + hasContext = true; + pushContextProvider(workInProgress); + } else { + hasContext = false; + } + + workInProgress.memoizedState = + value.state !== null && value.state !== undefined ? value.state : null; + initializeUpdateQueue(workInProgress); + adoptClassInstance(workInProgress, value); + mountClassInstance(workInProgress, Component, props, renderLanes); + return finishClassComponent( + null, + workInProgress, + Component, + true, + hasContext, + renderLanes + ); + } else { + // Proceed under the assumption that this is a function component + workInProgress.tag = FunctionComponent; + + reconcileChildren(null, workInProgress, value, renderLanes); + + { + validateFunctionComponentInDev(workInProgress, Component); + } + + return workInProgress.child; + } + } + + 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 (workInProgress.ref !== null) { + var info = ""; + var ownerName = getCurrentFiberOwnerNameInDevOrNull(); + + if (ownerName) { + info += "\n\nCheck the render method of `" + ownerName + "`."; + } + + var warningKey = ownerName || ""; + var debugSource = workInProgress._debugSource; + + if (debugSource) { + warningKey = debugSource.fileName + ":" + debugSource.lineNumber; + } + + if (!didWarnAboutFunctionRefs[warningKey]) { + didWarnAboutFunctionRefs[warningKey] = true; + + error( + "Function components cannot be given refs. " + + "Attempts to access this ref will fail. " + + "Did you mean to use React.forwardRef()?%s", + info + ); + } + } + + if (typeof Component.getDerivedStateFromProps === "function") { + var _componentName3 = getComponentNameFromType(Component) || "Unknown"; + + if (!didWarnAboutGetDerivedStateOnFunctionComponent[_componentName3]) { + error( + "%s: Function components do not support getDerivedStateFromProps.", + _componentName3 + ); + + didWarnAboutGetDerivedStateOnFunctionComponent[_componentName3] = true; + } + } + + if ( + typeof Component.contextType === "object" && + Component.contextType !== null + ) { + var _componentName4 = getComponentNameFromType(Component) || "Unknown"; + + if (!didWarnAboutContextTypeOnFunctionComponent[_componentName4]) { + error( + "%s: Function components do not support contextType.", + _componentName4 + ); + + didWarnAboutContextTypeOnFunctionComponent[_componentName4] = true; + } + } + } + } + + var SUSPENDED_MARKER = { + dehydrated: null, + treeContext: null, + retryLane: NoLane + }; + + function mountSuspenseOffscreenState(renderLanes) { + return { + baseLanes: renderLanes, + cachePool: getSuspendedCache(), + transitions: null + }; + } + + function updateSuspenseOffscreenState(prevOffscreenState, renderLanes) { + var cachePool = null; + + return { + baseLanes: mergeLanes(prevOffscreenState.baseLanes, renderLanes), + cachePool: cachePool, + transitions: prevOffscreenState.transitions + }; + } // TODO: Probably should inline this back + + function shouldRemainOnFallback( + suspenseContext, + 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. + 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 hasSuspenseContext(suspenseContext, ForceSuspenseFallback); + } + + function getRemainingWorkInPrimaryTree(current, renderLanes) { + // TODO: Should not remove render lanes that were pinged during this render + return removeLanes(current.childLanes, 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 suspenseContext = suspenseStackCursor.current; + var showFallback = false; + var didSuspend = (workInProgress.flags & DidCapture) !== NoFlags; + + if (didSuspend || shouldRemainOnFallback(suspenseContext, current)) { + // Something in this boundary's subtree already suspended. Switch to + // rendering the fallback children. + showFallback = true; + workInProgress.flags &= ~DidCapture; + } else { + // Attempting the main content + if (current === null || current.memoizedState !== null) { + // This is a new mount or this boundary is already showing a fallback state. + // Mark this subtree context as having at least one invisible parent that could + // handle the fallback state. + // Avoided boundaries are not considered since they cannot handle preferred fallback states. + { + suspenseContext = addSubtreeSuspenseContext( + suspenseContext, + InvisibleParentSuspenseContext + ); + } + } + } + + suspenseContext = setDefaultShallowSuspenseContext(suspenseContext); + pushSuspenseContext(workInProgress, suspenseContext); // 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 suspenseState = workInProgress.memoizedState; + + if (suspenseState !== null) { + var dehydrated = suspenseState.dehydrated; + + if (dehydrated !== null) { + return mountDehydratedSuspenseComponent(workInProgress); + } + } + + var nextPrimaryChildren = nextProps.children; + var nextFallbackChildren = nextProps.fallback; + + if (showFallback) { + var fallbackFragment = mountSuspenseFallbackChildren( + workInProgress, + nextPrimaryChildren, + nextFallbackChildren, + renderLanes + ); + var primaryChildFragment = workInProgress.child; + primaryChildFragment.memoizedState = mountSuspenseOffscreenState( + renderLanes + ); + workInProgress.memoizedState = SUSPENDED_MARKER; + + return fallbackFragment; + } else { + return mountSuspensePrimaryChildren(workInProgress, nextPrimaryChildren); + } + } else { + // This is an update. + // Special path for hydration + var prevState = current.memoizedState; + + if (prevState !== null) { + var _dehydrated = prevState.dehydrated; + + if (_dehydrated !== null) { + return updateDehydratedSuspenseComponent( + current, + workInProgress, + didSuspend, + nextProps, + _dehydrated, + prevState, + renderLanes + ); + } + } + + if (showFallback) { + 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); + + _primaryChildFragment2.childLanes = getRemainingWorkInPrimaryTree( + current, + renderLanes + ); + workInProgress.memoizedState = SUSPENDED_MARKER; + return fallbackChildFragment; + } else { + var _nextPrimaryChildren2 = nextProps.children; + + var _primaryChildFragment3 = updateSuspensePrimaryChildren( + current, + workInProgress, + _nextPrimaryChildren2, + renderLanes + ); + + workInProgress.memoizedState = null; + return _primaryChildFragment3; + } + } + } + + 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; + } + + 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 + ); + } + + primaryChildFragment.return = workInProgress; + fallbackChildFragment.return = workInProgress; + primaryChildFragment.sibling = fallbackChildFragment; + workInProgress.child = primaryChildFragment; + return fallbackChildFragment; + } + + 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); + } + + 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); + } + + function updateSuspensePrimaryChildren( + current, + workInProgress, + primaryChildren, + renderLanes + ) { + var currentPrimaryChildFragment = current.child; + var currentFallbackChildFragment = currentPrimaryChildFragment.sibling; + var primaryChildFragment = updateWorkInProgressOffscreenFiber( + currentPrimaryChildFragment, + { + mode: "visible", + children: primaryChildren + } + ); + + 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; + + if (deletions === null) { + workInProgress.deletions = [currentFallbackChildFragment]; + workInProgress.flags |= ChildDeletion; + } else { + deletions.push(currentFallbackChildFragment); + } + } + + 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 _primaryChildFragment2 = workInProgress.child; - var prevOffscreenState = current.child.memoizedState; - _primaryChildFragment2.memoizedState = - prevOffscreenState === null - ? mountSuspenseOffscreenState(renderLanes) - : updateSuspenseOffscreenState(prevOffscreenState, renderLanes); - - _primaryChildFragment2.childLanes = getRemainingWorkInPrimaryTree( - current, - renderLanes + 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; + } + + function mountDehydratedSuspenseComponent( + workInProgress, + suspenseInstance, + renderLanes + ) { + // During the first pass, we'll bail out and not drill into the children. + // Instead, we'll leave the content in place and try to hydrate it later. + if ((workInProgress.mode & ConcurrentMode) === NoMode) { + { + error( + "Cannot hydrate Suspense in legacy mode. Switch from " + + "ReactDOM.hydrate(element, container) to " + + "ReactDOMClient.hydrateRoot(container, )" + + ".render(element) or remove the Suspense components from " + + "the server rendered components." + ); + } + + workInProgress.lanes = laneToLanes(SyncLane); + } else if (isSuspenseInstanceFallback()) { + // This is a client-only boundary. Since we won't get any content from the server + // for this, we need to schedule that at a higher priority based on when it would + // have timed out. In theory we could render it in this pass but it would have the + // wrong priority associated with it and will prevent hydration of parent path. + // Instead, we'll leave work left on it to render it in a separate commit. + // TODO This time should be the time at which the server rendered response that is + // a parent to this boundary was displayed. However, since we currently don't have + // a protocol to transfer that time, we'll just estimate it by using the current + // time. This will mean that Suspense timeouts are slightly shifted to later than + // they should be. + // Schedule a normal pri update to render this content. + workInProgress.lanes = laneToLanes(DefaultHydrationLane); + } else { + // We'll continue hydrating the rest at offscreen priority since we'll already + // be showing the right content coming from the server, it is no rush. + workInProgress.lanes = laneToLanes(OffscreenLane); + } + + return null; + } + + function updateDehydratedSuspenseComponent( + current, + workInProgress, + didSuspend, + nextProps, + suspenseInstance, + suspenseState, + renderLanes + ) { + if (!didSuspend) { + if ((workInProgress.mode & ConcurrentMode) === NoMode) { + return retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, // TODO: When we delete legacy mode, we should make this error argument + // required — every concurrent mode path that causes hydration to + // de-opt to client rendering should have an error message. + 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, message, stack; + + { + var _getSuspenseInstanceF = getSuspenseInstanceFallbackErrorDetails(); + + digest = _getSuspenseInstanceF.digest; + message = _getSuspenseInstanceF.message; + stack = _getSuspenseInstanceF.stack; + } + + 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." + ); + } + + var capturedValue = createCapturedValue(error, digest, stack); + return retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, + capturedValue + ); + } + // any context has changed, we need to treat is as if the input might have changed. + + var hasContextChanged = includesSomeLane(renderLanes, current.childLanes); + + 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 (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; // TODO: Ideally this would inherit the event time of the current render + + var eventTime = NoTimestamp; + enqueueConcurrentRenderForLane(current, attemptHydrationAtLane); + scheduleUpdateOnFiber( + root, + current, + attemptHydrationAtLane, + eventTime + ); + } + } // If we have scheduled higher pri work above, this will probably just abort the render + // since we now have higher priority work, but in case it doesn't, we need to prepare to + // render something, if we time out. Even if that requires us to delete everything and + // skip hydration. + // Delay having to do this as long as the suspense timeout allows us. + + renderDidSuspendDelayIfPossible(); + + var _capturedValue = createCapturedValue( + new Error( + "This Suspense boundary received an update before it finished " + + "hydrating. This caused the boundary to switch to client rendering. " + + "The usual way to fix this is to wrap the original update " + + "in startTransition." + ) + ); + + return retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, + _capturedValue + ); + } 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. + + var retry = retryDehydratedSuspenseBoundary.bind(null, current); + registerSuspenseInstanceRetry(); + return null; + } else { + // This is the first attempt. + reenterHydrationStateFromDehydratedSuspenseInstance( + workInProgress, + suspenseInstance, + suspenseState.treeContext + ); + 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. + workInProgress.flags &= ~ForceClientRender; + + var _capturedValue2 = createCapturedValue( + new Error( + "There was an error while hydrating this Suspense boundary. " + + "Switched to client rendering." + ) + ); + + return retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, + _capturedValue2 + ); + } else if (workInProgress.memoizedState !== null) { + // Something suspended and we should still be in dehydrated mode. + // Leave the existing child in place. + 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. + 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; + } + } + } + + 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); + } + + 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; + } + + while (node.sibling === null) { + if (node.return === null || node.return === workInProgress) { + return; + } + + node = node.return; + } + + node.sibling.return = node.return; + node = node.sibling; + } + } + + 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; + + while (row !== null) { + var currentRow = row.alternate; // New rows can't be content rows. + + if (currentRow !== null && findFirstSuspended(currentRow) === null) { + lastContentRow = row; + } + + row = row.sibling; + } + + return lastContentRow; + } + + function validateRevealOrder(revealOrder) { + { + if ( + revealOrder !== undefined && + revealOrder !== "forwards" && + revealOrder !== "backwards" && + revealOrder !== "together" && + !didWarnAboutRevealOrder[revealOrder] + ) { + didWarnAboutRevealOrder[revealOrder] = 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() + ); + + break; + } + + 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() + ); + + break; + } + + default: + error( + '"%s" is not a supported revealOrder on . ' + + 'Did you mean "together", "forwards" or "backwards"?', + revealOrder + ); + + break; + } + } else { + error( + "%s is not a supported value for revealOrder on . " + + 'Did you mean "together", "forwards" or "backwards"?', + revealOrder + ); + } + } + } + } + + function validateTailOptions(tailMode, revealOrder) { + { + 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 + ); + } + } + } + } + + 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 + ); + + return false; + } + } + + return true; + } + + 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); + + if (typeof iteratorFn === "function") { + var childrenIterator = iteratorFn.call(children); + + if (childrenIterator) { + var step = childrenIterator.next(); + var _i = 0; + + for (; !step.done; step = childrenIterator.next()) { + if (!validateSuspenseListNestedChild(step.value, _i)) { + return; + } + + _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 + ); + } + } + } + } + } + + 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 = hasSuspenseContext( + suspenseContext, + ForceSuspenseFallback ); - workInProgress.memoizedState = SUSPENDED_MARKER; - return fallbackChildFragment; - } else { - var _nextPrimaryChildren2 = nextProps.children; - var _primaryChildFragment3 = updateSuspensePrimaryChildren( - current, - workInProgress, - _nextPrimaryChildren2, - renderLanes - ); + if (shouldForceFallback) { + suspenseContext = setShallowSuspenseContext( + suspenseContext, + ForceSuspenseFallback + ); + workInProgress.flags |= DidCapture; + } else { + var didSuspendBefore = + current !== null && (current.flags & DidCapture) !== NoFlags; + + 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 + ); + } + + suspenseContext = setDefaultShallowSuspenseContext(suspenseContext); + } + + pushSuspenseContext(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; + + 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; + } + + initSuspenseListRenderState( + workInProgress, + false, // isBackwards + tail, + lastContentRow, + tailMode + ); + break; + } + + 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; + + while (row !== null) { + var currentRow = row.alternate; // New rows can't be content rows. + + if (currentRow !== null && findFirstSuspended(currentRow) === null) { + // This is the beginning of the main content. + workInProgress.child = row; + break; + } + + 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; + } + + case "together": { + initSuspenseListRenderState( + workInProgress, + false, // isBackwards + null, // tail + null, // last + undefined + ); + break; + } + + default: { + // The default reveal order is the same as not having + // a boundary. + workInProgress.memoizedState = null; + } + } + } + + 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; + } + + var hasWarnedAboutUsingNoValuePropOnContextProvider = false; + + 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 (!("value" in newProps)) { + if (!hasWarnedAboutUsingNoValuePropOnContextProvider) { + hasWarnedAboutUsingNoValuePropOnContextProvider = true; + + error( + "The `value` prop is required for the ``. Did you misspell it or forget to pass it?" + ); + } + } + + var providerPropTypes = workInProgress.type.propTypes; + + if (providerPropTypes) { + checkPropTypes(providerPropTypes, newProps, "prop", "Context.Provider"); + } + } + + pushProvider(workInProgress, context, newValue); + + { + if (oldProps !== null) { + var oldValue = oldProps.value; + + 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 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; + + 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; + } + } + + 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." + ); + } + } + + prepareToReadContext(workInProgress, renderLanes); + var newValue = readContext(context); + + var newChildren; + + { + ReactCurrentOwner$1.current = workInProgress; + setIsRendering(true); + newChildren = render(newValue); + setIsRendering(false); + } + + workInProgress.flags |= PerformedWork; + reconcileChildren(current, workInProgress, newChildren, renderLanes); + return workInProgress.child; + } + + function markWorkInProgressReceivedUpdate() { + didReceiveUpdate = 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 + + workInProgress.flags |= Placement; + } + } + } + + function bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) { + if (current !== null) { + // Reuse previous dependencies + workInProgress.dependencies = current.dependencies; + } + + { + // Don't update "base" render times for bailouts. + stopProfilerTimerIfRunning(); + } + + markSkippedUpdateLanes(workInProgress.lanes); // Check if the children have any pending work. + + 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. + { + 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; + + 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. + + current.alternate = null; + oldWorkInProgress.alternate = null; // Connect to the new tree. + + newWorkInProgress.index = oldWorkInProgress.index; + newWorkInProgress.sibling = oldWorkInProgress.sibling; + newWorkInProgress.return = oldWorkInProgress.return; + newWorkInProgress.ref = oldWorkInProgress.ref; // Replace the child/sibling pointers above it. + + if (oldWorkInProgress === returnFiber.child) { + returnFiber.child = newWorkInProgress; + } else { + var prevSibling = returnFiber.child; + + if (prevSibling === null) { + // eslint-disable-next-line react-internal/prod-error-codes + throw new Error("Expected parent to have a child."); + } + + while (prevSibling.sibling !== oldWorkInProgress) { + prevSibling = prevSibling.sibling; + + if (prevSibling === null) { + // eslint-disable-next-line react-internal/prod-error-codes + throw new Error("Expected to find the previous sibling."); + } + } + + prevSibling.sibling = newWorkInProgress; + } // Delete the old fiber and place the new one. + // Since the old fiber is disconnected, we have to schedule it manually. - workInProgress.memoizedState = null; - return _primaryChildFragment3; - } - } -} + var deletions = returnFiber.deletions; -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; -} + if (deletions === null) { + returnFiber.deletions = [current]; + returnFiber.flags |= ChildDeletion; + } else { + deletions.push(current); + } -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 - ); - } + newWorkInProgress.flags |= Placement; // Restart work from the new fiber. - primaryChildFragment.return = workInProgress; - fallbackChildFragment.return = workInProgress; - primaryChildFragment.sibling = fallbackChildFragment; - workInProgress.child = primaryChildFragment; - return fallbackChildFragment; -} + return newWorkInProgress; + } + } -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); -} + function checkScheduledUpdateOrContext(current, renderLanes) { + // Before performing an early bailout, we must check if there are pending + // updates or context. + var updateLanes = current.lanes; -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); -} + if (includesSomeLane(updateLanes, renderLanes)) { + return true; + } // No pending update, but because context is propagated lazily, we need -function updateSuspensePrimaryChildren( - current, - workInProgress, - primaryChildren, - renderLanes -) { - var currentPrimaryChildFragment = current.child; - var currentFallbackChildFragment = currentPrimaryChildFragment.sibling; - var primaryChildFragment = updateWorkInProgressOffscreenFiber( - currentPrimaryChildFragment, - { - mode: "visible", - children: primaryChildren + return false; } - ); - if ((workInProgress.mode & ConcurrentMode) === NoMode) { - primaryChildFragment.lanes = renderLanes; - } + 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); + var root = workInProgress.stateNode; + break; - primaryChildFragment.return = workInProgress; - primaryChildFragment.sibling = null; + case HostComponent: + pushHostContext(workInProgress); + break; - if (currentFallbackChildFragment !== null) { - // Delete the fallback child fragment - var deletions = workInProgress.deletions; + case ClassComponent: { + var Component = workInProgress.type; - if (deletions === null) { - workInProgress.deletions = [currentFallbackChildFragment]; - workInProgress.flags |= ChildDeletion; - } else { - deletions.push(currentFallbackChildFragment); - } - } + if (isContextProvider(Component)) { + pushContextProvider(workInProgress); + } - 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; -} + case HostPortal: + pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); + break; -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; -} + case ContextProvider: { + var newValue = workInProgress.memoizedProps.value; + var context = workInProgress.type._context; + pushProvider(workInProgress, context, newValue); + break; + } -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; -} + case Profiler: + { + // Profiler should only call onRender when one of its descendants actually rendered. + var hasChildWork = includesSomeLane( + renderLanes, + workInProgress.childLanes + ); -function mountDehydratedSuspenseComponent( - workInProgress, - suspenseInstance, - renderLanes -) { - // During the first pass, we'll bail out and not drill into the children. - // Instead, we'll leave the content in place and try to hydrate it later. - if ((workInProgress.mode & ConcurrentMode) === NoMode) { - { - error( - "Cannot hydrate Suspense in legacy mode. Switch from " + - "ReactDOM.hydrate(element, container) to " + - "ReactDOMClient.hydrateRoot(container, )" + - ".render(element) or remove the Suspense components from " + - "the server rendered components." - ); - } + if (hasChildWork) { + workInProgress.flags |= Update; + } - workInProgress.lanes = laneToLanes(SyncLane); - } else if (isSuspenseInstanceFallback()) { - // This is a client-only boundary. Since we won't get any content from the server - // for this, we need to schedule that at a higher priority based on when it would - // have timed out. In theory we could render it in this pass but it would have the - // wrong priority associated with it and will prevent hydration of parent path. - // Instead, we'll leave work left on it to render it in a separate commit. - // TODO This time should be the time at which the server rendered response that is - // a parent to this boundary was displayed. However, since we currently don't have - // a protocol to transfer that time, we'll just estimate it by using the current - // time. This will mean that Suspense timeouts are slightly shifted to later than - // they should be. - // Schedule a normal pri update to render this content. - workInProgress.lanes = laneToLanes(DefaultHydrationLane); - } else { - // We'll continue hydrating the rest at offscreen priority since we'll already - // be showing the right content coming from the server, it is no rush. - workInProgress.lanes = laneToLanes(OffscreenLane); - } - - return null; -} + { + // 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; + } + } -function updateDehydratedSuspenseComponent( - current, - workInProgress, - didSuspend, - nextProps, - suspenseInstance, - suspenseState, - renderLanes -) { - if (!didSuspend) { - if ((workInProgress.mode & ConcurrentMode) === NoMode) { - return retrySuspenseComponentWithoutHydrating( - current, - workInProgress, - renderLanes, // TODO: When we delete legacy mode, we should make this error argument - // required — every concurrent mode path that causes hydration to - // de-opt to client rendering should have an error message. - null - ); - } + break; - 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, message, stack; + case SuspenseComponent: { + var state = workInProgress.memoizedState; - { - var _getSuspenseInstanceF = getSuspenseInstanceFallbackErrorDetails(); + if (state !== null) { + if (state.dehydrated !== null) { + pushSuspenseContext( + workInProgress, + setDefaultShallowSuspenseContext(suspenseStackCursor.current) + ); // 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. - digest = _getSuspenseInstanceF.digest; - message = _getSuspenseInstanceF.message; - stack = _getSuspenseInstanceF.stack; - } + workInProgress.flags |= DidCapture; // We should never render the children of a dehydrated boundary until we + // upgrade it. We return null instead of bailoutOnAlreadyFinishedWork. - var error; + 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 (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." - ); + 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 + pushSuspenseContext( + workInProgress, + setDefaultShallowSuspenseContext(suspenseStackCursor.current) + ); // 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 { + pushSuspenseContext( + workInProgress, + setDefaultShallowSuspenseContext(suspenseStackCursor.current) + ); + } + + break; + } + + case SuspenseListComponent: { + var didSuspendBefore = (current.flags & DidCapture) !== NoFlags; + + var _hasChildWork = includesSomeLane( + renderLanes, + workInProgress.childLanes + ); + + 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; + + 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; + } + + pushSuspenseContext(workInProgress, suspenseStackCursor.current); + + 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; + } + } + + 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 capturedValue = createCapturedValue(error, digest, stack); - return retrySuspenseComponentWithoutHydrating( - current, - workInProgress, - renderLanes, - capturedValue - ); + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); } - // any context has changed, we need to treat is as if the input might have changed. - - var hasContextChanged = includesSomeLane(renderLanes, current.childLanes); - 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(); + function beginWork(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._debugOwner || null, + workInProgress.mode, + workInProgress.lanes + ) + ); + } + } - if (root !== null) { - var attemptHydrationAtLane = getBumpedLaneForHydration( - root, - renderLanes - ); + if (current !== null) { + var oldProps = current.memoizedProps; + var newProps = workInProgress.pendingProps; if ( - attemptHydrationAtLane !== NoLane && - attemptHydrationAtLane !== suspenseState.retryLane + oldProps !== newProps || + hasContextChanged() || // Force a re-render if the implementation changed due to hot reload: + workInProgress.type !== current.type ) { - // 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; // TODO: Ideally this would inherit the event time of the current render - - var eventTime = NoTimestamp; - enqueueConcurrentRenderForLane(current, attemptHydrationAtLane); - scheduleUpdateOnFiber( - root, + // 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, - attemptHydrationAtLane, - eventTime + renderLanes ); + + 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 + ) { + // No pending updates or context. Bail out now. + didReceiveUpdate = false; + return attemptEarlyBailoutIfNoScheduledUpdate( + current, + workInProgress, + renderLanes + ); + } + + if ((current.flags & ForceUpdateForLegacySuspense) !== NoFlags) { + // 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 we have scheduled higher pri work above, this will probably just abort the render - // since we now have higher priority work, but in case it doesn't, we need to prepare to - // render something, if we time out. Even if that requires us to delete everything and - // skip hydration. - // Delay having to do this as long as the suspense timeout allows us. + } 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. - renderDidSuspendDelayIfPossible(); + workInProgress.lanes = NoLanes; - var _capturedValue = createCapturedValue( - new Error( - "This Suspense boundary received an update before it finished " + - "hydrating. This caused the boundary to switch to client rendering. " + - "The usual way to fix this is to wrap the original update " + - "in startTransition." - ) - ); + switch (workInProgress.tag) { + case IndeterminateComponent: { + return mountIndeterminateComponent( + current, + workInProgress, + workInProgress.type, + renderLanes + ); + } - return retrySuspenseComponentWithoutHydrating( - current, - workInProgress, - renderLanes, - _capturedValue - ); - } 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. - - var retry = retryDehydratedSuspenseBoundary.bind(null, current); - registerSuspenseInstanceRetry(); - return null; - } else { - // This is the first attempt. - reenterHydrationStateFromDehydratedSuspenseInstance( - workInProgress, - suspenseInstance, - suspenseState.treeContext - ); - 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. - workInProgress.flags &= ~ForceClientRender; - - var _capturedValue2 = createCapturedValue( - new Error( - "There was an error while hydrating this Suspense boundary. " + - "Switched to client rendering." - ) - ); + case LazyComponent: { + var elementType = workInProgress.elementType; + return mountLazyComponent( + current, + workInProgress, + elementType, + renderLanes + ); + } - return retrySuspenseComponentWithoutHydrating( - current, - workInProgress, - renderLanes, - _capturedValue2 - ); - } else if (workInProgress.memoizedState !== null) { - // Something suspended and we should still be in dehydrated mode. - // Leave the existing child in place. - workInProgress.child = current.child; // The dehydrated completion pass expects this flag to be there - // but the normal suspense pass doesn't. + 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 + ); + } - workInProgress.flags |= DidCapture; - return null; - } else { - // Suspended but we should no longer be in dehydrated mode. - // Therefore we now have to render the fallback. - 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; - } - } -} + case ClassComponent: { + var _Component = workInProgress.type; + var _unresolvedProps = workInProgress.pendingProps; + + var _resolvedProps = + workInProgress.elementType === _Component + ? _unresolvedProps + : resolveDefaultProps(_Component, _unresolvedProps); + + return updateClassComponent( + current, + workInProgress, + _Component, + _resolvedProps, + renderLanes + ); + } -function scheduleSuspenseWorkOnFiber(fiber, renderLanes, propagationRoot) { - fiber.lanes = mergeLanes(fiber.lanes, renderLanes); - var alternate = fiber.alternate; + case HostRoot: + return updateHostRoot(current, workInProgress, renderLanes); - if (alternate !== null) { - alternate.lanes = mergeLanes(alternate.lanes, renderLanes); - } + case HostComponent: + return updateHostComponent(current, workInProgress, renderLanes); - scheduleContextWorkOnParentPath(fiber.return, renderLanes, propagationRoot); -} + case HostText: + return updateHostText(); -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; - } - - while (node.sibling === null) { - if (node.return === null || node.return === workInProgress) { - return; - } + case SuspenseComponent: + return updateSuspenseComponent(current, workInProgress, renderLanes); - node = node.return; - } + case HostPortal: + return updatePortalComponent(current, workInProgress, renderLanes); - node.sibling.return = node.return; - node = node.sibling; - } -} + case ForwardRef: { + var type = workInProgress.type; + var _unresolvedProps2 = workInProgress.pendingProps; + + var _resolvedProps2 = + workInProgress.elementType === type + ? _unresolvedProps2 + : resolveDefaultProps(type, _unresolvedProps2); + + return updateForwardRef( + current, + workInProgress, + type, + _resolvedProps2, + renderLanes + ); + } + + case Fragment: + return updateFragment(current, workInProgress, renderLanes); + + case Mode: + return updateMode(current, workInProgress, renderLanes); + + case Profiler: + return updateProfiler(current, workInProgress, renderLanes); + + case ContextProvider: + return updateContextProvider(current, workInProgress, renderLanes); + + case ContextConsumer: + return updateContextConsumer(current, workInProgress, renderLanes); + + case MemoComponent: { + var _type2 = workInProgress.type; + var _unresolvedProps3 = workInProgress.pendingProps; // Resolve outer props first, then resolve inner props. + + var _resolvedProps3 = resolveDefaultProps(_type2, _unresolvedProps3); + + { + if (workInProgress.type !== workInProgress.elementType) { + var outerPropTypes = _type2.propTypes; + + if (outerPropTypes) { + checkPropTypes( + outerPropTypes, + _resolvedProps3, // Resolved for outer only + "prop", + getComponentNameFromType(_type2) + ); + } + } + } + + _resolvedProps3 = resolveDefaultProps(_type2.type, _resolvedProps3); + return updateMemoComponent( + current, + workInProgress, + _type2, + _resolvedProps3, + renderLanes + ); + } + + case SimpleMemoComponent: { + return updateSimpleMemoComponent( + current, + workInProgress, + workInProgress.type, + workInProgress.pendingProps, + renderLanes + ); + } + + case IncompleteClassComponent: { + var _Component2 = workInProgress.type; + var _unresolvedProps4 = workInProgress.pendingProps; + + var _resolvedProps4 = + workInProgress.elementType === _Component2 + ? _unresolvedProps4 + : resolveDefaultProps(_Component2, _unresolvedProps4); -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; + return mountIncompleteClassComponent( + current, + workInProgress, + _Component2, + _resolvedProps4, + renderLanes + ); + } + + case SuspenseListComponent: { + return updateSuspenseListComponent(current, workInProgress, renderLanes); + } + + case ScopeComponent: { + break; + } + + case OffscreenComponent: { + return updateOffscreenComponent(current, workInProgress, renderLanes); + } + } + + throw new Error( + "Unknown unit of work tag (" + + workInProgress.tag + + "). This error is likely caused by a bug in " + + "React. Please file an issue." + ); + } - while (row !== null) { - var currentRow = row.alternate; // New rows can't be content rows. + function markUpdate(workInProgress) { + // Tag the fiber with an update effect. This turns a Placement into + // a PlacementAndUpdate. + workInProgress.flags |= Update; + } - if (currentRow !== null && findFirstSuspended(currentRow) === null) { - lastContentRow = row; + function markRef$1(workInProgress) { + workInProgress.flags |= Ref; } - row = row.sibling; - } + var appendAllChildren; + var updateHostContainer; + var updateHostComponent$1; + var updateHostText$1; - return lastContentRow; -} + { + // Mutation mode + appendAllChildren = function ( + 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); + else if (node.child !== null) { + node.child.return = node; + node = node.child; + continue; + } -function validateRevealOrder(revealOrder) { - { - if ( - revealOrder !== undefined && - revealOrder !== "forwards" && - revealOrder !== "backwards" && - revealOrder !== "together" && - !didWarnAboutRevealOrder[revealOrder] - ) { - didWarnAboutRevealOrder[revealOrder] = true; + if (node === workInProgress) { + return; + } - 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() - ); + while (node.sibling === null) { + if (node.return === null || node.return === workInProgress) { + return; + } - break; + node = node.return; } - 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() - ); + node.sibling.return = node.return; + node = node.sibling; + } + }; - break; - } + updateHostContainer = function (current, workInProgress) { + // Noop + }; - default: - error( - '"%s" is not a supported revealOrder on . ' + - 'Did you mean "together", "forwards" or "backwards"?', - revealOrder - ); + updateHostComponent$1 = function ( + current, + workInProgress, + type, + newProps, + rootContainerInstance + ) { + // 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; - break; - } - } else { - error( - "%s is not a supported value for revealOrder on . " + - 'Did you mean "together", "forwards" or "backwards"?', - revealOrder - ); - } - } - } -} + if (oldProps === newProps) { + // In mutation mode, this is sufficient for a bailout because + // we won't touch this node even if children changed. + return; + } // If we get updated because one of our children updated, we don't + // have newProps so we'll have to reuse them. + // TODO: Split the update API as separate for the props vs. children. + // Even better would be if children weren't special cased at all tho. -function validateTailOptions(tailMode, revealOrder) { - { - if (tailMode !== undefined && !didWarnAboutTailOptions[tailMode]) { - if (tailMode !== "collapsed" && tailMode !== "hidden") { - didWarnAboutTailOptions[tailMode] = true; + var instance = workInProgress.stateNode; + var currentHostContext = getHostContext(); // TODO: Experiencing an error where oldProps is null. Suggests a host + // component is hitting the resume path. Figure out why. Possibly + // related to `hidden`. - 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 updatePayload = prepareUpdate(); // TODO: Type this specific to this type of component. - error( - ' is only valid if revealOrder is ' + - '"forwards" or "backwards". ' + - 'Did you mean to specify revealOrder="forwards"?', - tailMode - ); - } - } - } -} + workInProgress.updateQueue = updatePayload; // If the update payload indicates that there is a change or if there + // is a new ref we mark this as an update. All the work is done in commitWork. -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 - ); + if (updatePayload) { + markUpdate(workInProgress); + } + }; - return false; + updateHostText$1 = function (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 true; -} + 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; + } -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; + 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; } - } - } else { - var iteratorFn = getIteratorFn(children); - if (typeof iteratorFn === "function") { - var childrenIterator = iteratorFn.call(children); + break; + } - if (childrenIterator) { - var step = childrenIterator.next(); - var _i = 0; + 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; + } - for (; !step.done; step = childrenIterator.next()) { - if (!validateSuspenseListNestedChild(step.value, _i)) { - return; - } + _tailNode = _tailNode.sibling; + } // Next we're simply going to delete all insertions after the + // last rendered item. - _i++; + 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; } - } 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 - ); + + break; } } } - } -} -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 = hasSuspenseContext( - suspenseContext, - ForceSuspenseFallback - ); - - if (shouldForceFallback) { - suspenseContext = setShallowSuspenseContext( - suspenseContext, - ForceSuspenseFallback - ); - workInProgress.flags |= DidCapture; - } else { - var didSuspendBefore = - current !== null && (current.flags & DidCapture) !== NoFlags; - - 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 - ); - } + function bubbleProperties(completedWork) { + var didBailout = + completedWork.alternate !== null && + completedWork.alternate.child === completedWork.child; + var newChildLanes = NoLanes; + var subtreeFlags = NoFlags; - suspenseContext = setDefaultShallowSuspenseContext(suspenseContext); - } + 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; - pushSuspenseContext(workInProgress, suspenseContext); + 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. + + actualDuration += child.actualDuration; + treeBaseDuration += child.treeBaseDuration; + child = child.sibling; + } + + completedWork.actualDuration = actualDuration; + completedWork.treeBaseDuration = treeBaseDuration; + } else { + var _child = completedWork.child; + + 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. + + _child.return = completedWork; + _child = _child.sibling; + } + } - 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; + 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; + _treeBaseDuration += _child2.treeBaseDuration; + _child2 = _child2.sibling; + } - 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; + completedWork.treeBaseDuration = _treeBaseDuration; } else { - // Disconnect the tail rows after the content row. - // We're going to render them separately later. - tail = lastContentRow.sibling; - lastContentRow.sibling = null; + 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; + } } - initSuspenseListRenderState( - workInProgress, - false, // isBackwards - tail, - lastContentRow, - tailMode - ); - break; + completedWork.subtreeFlags |= subtreeFlags; } - 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; + completedWork.childLanes = newChildLanes; + return didBailout; + } - while (row !== null) { - var currentRow = row.alternate; // New rows can't be content rows. + function completeDehydratedSuspenseBoundary( + current, + workInProgress, + nextState + ) { + var wasHydrated = popHydrationState(); - if (currentRow !== null && findFirstSuspended(currentRow) === null) { - // This is the beginning of the main content. - workInProgress.child = row; - 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." + ); } - var nextRow = row.sibling; - row.sibling = _tail; - _tail = row; - row = nextRow; - } // TODO: If workInProgress.child is null, we can continue on the tail immediately. + prepareToHydrateHostSuspenseInstance(); + bubbleProperties(workInProgress); - initSuspenseListRenderState( - workInProgress, - true, // isBackwards - _tail, - null, // last - tailMode - ); - break; - } + { + if ((workInProgress.mode & ProfileMode) !== NoMode) { + var isTimedOutSuspense = nextState !== null; - case "together": { - initSuspenseListRenderState( - workInProgress, - false, // isBackwards - null, // tail - null, // last - undefined - ); - break; - } + if (isTimedOutSuspense) { + // Don't count time spent in a timed out Suspense subtree as part of the base duration. + var primaryChildFragment = workInProgress.child; - default: { - // The default reveal order is the same as not having - // a boundary. - workInProgress.memoizedState = null; - } - } - } + if (primaryChildFragment !== null) { + // $FlowFixMe Flow doesn't support type casting in combination with the -= operator + workInProgress.treeBaseDuration -= + primaryChildFragment.treeBaseDuration; + } + } + } + } - return workInProgress.child; -} + return false; + } else { + if ((workInProgress.flags & DidCapture) === NoFlags) { + // 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 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); - } + workInProgress.flags |= Update; + bubbleProperties(workInProgress); - return workInProgress.child; -} + { + if ((workInProgress.mode & ProfileMode) !== NoMode) { + var _isTimedOutSuspense = nextState !== null; -var hasWarnedAboutUsingNoValuePropOnContextProvider = false; + if (_isTimedOutSuspense) { + // Don't count time spent in a timed out Suspense subtree as part of the base duration. + var _primaryChildFragment = workInProgress.child; -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 (_primaryChildFragment !== null) { + // $FlowFixMe Flow doesn't support type casting in combination with the -= operator + workInProgress.treeBaseDuration -= + _primaryChildFragment.treeBaseDuration; + } + } + } + } - { - if (!("value" in newProps)) { - if (!hasWarnedAboutUsingNoValuePropOnContextProvider) { - hasWarnedAboutUsingNoValuePropOnContextProvider = true; + 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 - error( - "The `value` prop is required for the ``. Did you misspell it or forget to pass it?" - ); + return true; } } - var providerPropTypes = workInProgress.type.propTypes; + function completeWork(current, workInProgress, renderLanes) { + var newProps = workInProgress.pendingProps; // Note: This intentionally doesn't check if we're hydrating because comparing + // to the current tree provider fiber is just as fast and less error-prone. + // Ideally we would have a special version of the work loop only + // for hydration. - if (providerPropTypes) { - checkPropTypes(providerPropTypes, newProps, "prop", "Context.Provider"); - } - } + popTreeContext(workInProgress); + if (workInProgress.flags & 1 && (workInProgress.type?.displayName || workInProgress.type?.name) !== "View") + insertUpdateComponents( + getComponentNameFromFiber(workInProgress), + workInProgress.flags, + workInProgress.key, + ); + 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; - pushProvider(workInProgress, context, newValue); + case ClassComponent: { + var Component = workInProgress.type; - { - if (oldProps !== null) { - var oldValue = oldProps.value; + if (isContextProvider(Component)) { + popContext(workInProgress); + } - if (objectIs(oldValue, newValue)) { - // No change. Bailout early if children are the same. - if (oldProps.children === newProps.children && !hasContextChanged()) { - return bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderLanes - ); + bubbleProperties(workInProgress); + return 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; -} + case HostRoot: { + var fiberRoot = workInProgress.stateNode; + popHostContainer(workInProgress); + popTopLevelContextObject(workInProgress); + resetWorkInProgressVersions(); + + if (fiberRoot.pendingContext) { + fiberRoot.context = fiberRoot.pendingContext; + fiberRoot.pendingContext = null; + } -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; + 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(); - error( - "Rendering directly is not supported and will be removed in " + - "a future major release. Did you mean to render instead?" - ); + 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 + ) { + // 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(); + } + } + } + } + + updateHostContainer(current, workInProgress); + bubbleProperties(workInProgress); + + return null; } - } - } else { - context = context._context; - } - } - var newProps = workInProgress.pendingProps; - var render = newProps.children; + case HostComponent: { + popHostContext(workInProgress); + var rootContainerInstance = getRootHostContainer(); + var type = workInProgress.type; + + if (current !== null && workInProgress.stateNode != null) { + updateHostComponent$1( + current, + workInProgress, + type, + newProps, + rootContainerInstance + ); + + if (current.ref !== workInProgress.ref) { + markRef$1(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 (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." - ); - } - } + bubbleProperties(workInProgress); + return null; + } - prepareToReadContext(workInProgress, renderLanes); - var newValue = readContext(context); + var currentHostContext = 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 newChildren; + var _wasHydrated = popHydrationState(); - { - ReactCurrentOwner$1.current = workInProgress; - setIsRendering(true); - newChildren = render(newValue); - setIsRendering(false); - } + if (_wasHydrated) { + // TODO: Move this and createInstance step into the beginPhase + // to consolidate. + if (prepareToHydrateHostInstance()) { + // If changes to the hydrated node need to be applied at the + // commit-phase we mark this as such. + markUpdate(workInProgress); + } + } else { + var instance = createInstance( + type, + newProps, + rootContainerInstance, + currentHostContext, + workInProgress + ); + appendAllChildren(instance, workInProgress, false, false); + workInProgress.stateNode = instance; // Certain renderers require commit-time effects for initial mount. + // (eg DOM renderer supports auto-focus for certain elements). + // Make sure such renderers get scheduled for later work. - workInProgress.flags |= PerformedWork; - reconcileChildren(current, workInProgress, newChildren, renderLanes); - return workInProgress.child; -} + if (finalizeInitialChildren(instance)) { + markUpdate(workInProgress); + } + } -function markWorkInProgressReceivedUpdate() { - didReceiveUpdate = true; -} + if (workInProgress.ref !== null) { + // If there is a ref on a host node we need to schedule a callback + markRef$1(workInProgress); + } + } -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 + bubbleProperties(workInProgress); + return null; + } - workInProgress.flags |= Placement; - } - } -} + case HostText: { + var newText = newProps; -function bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) { - if (current !== null) { - // Reuse previous dependencies - workInProgress.dependencies = current.dependencies; - } + 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. - { - // Don't update "base" render times for bailouts. - stopProfilerTimerIfRunning(); - } + updateHostText$1(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. + } - markSkippedUpdateLanes(workInProgress.lanes); // Check if the children have any pending work. + var _rootContainerInstance = getRootHostContainer(); - 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. - { - return null; - } - } // This fiber doesn't have work, but its subtree does. Clone the child - // fibers and continue. + var _currentHostContext = getHostContext(); - cloneChildFibers(current, workInProgress); - return workInProgress.child; -} + var _wasHydrated2 = popHydrationState(); + + if (_wasHydrated2) { + if (prepareToHydrateHostTextInstance()) { + markUpdate(workInProgress); + } + } else { + workInProgress.stateNode = createTextInstance( + newText, + _rootContainerInstance, + _currentHostContext, + workInProgress + ); + } + } + + bubbleProperties(workInProgress); + return null; + } -function remountFiber(current, oldWorkInProgress, newWorkInProgress) { - { - var returnFiber = oldWorkInProgress.return; + case SuspenseComponent: { + popSuspenseContext(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 (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 || + (current.memoizedState !== null && + current.memoizedState.dehydrated !== null) + ) { + var fallthroughToNormalSuspensePath = completeDehydratedSuspenseBoundary( + current, + workInProgress, + nextState + ); - current.alternate = null; - oldWorkInProgress.alternate = null; // Connect to the new tree. + if (!fallthroughToNormalSuspensePath) { + if (workInProgress.flags & ShouldCapture) { + // 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. + } - newWorkInProgress.index = oldWorkInProgress.index; - newWorkInProgress.sibling = oldWorkInProgress.sibling; - newWorkInProgress.return = oldWorkInProgress.return; - newWorkInProgress.ref = oldWorkInProgress.ref; // Replace the child/sibling pointers above it. + if ((workInProgress.flags & DidCapture) !== NoFlags) { + // Something suspended. Re-render with the fallback children. + workInProgress.lanes = renderLanes; // Do not reset the effect list. - if (oldWorkInProgress === returnFiber.child) { - returnFiber.child = newWorkInProgress; - } else { - var prevSibling = returnFiber.child; + if ((workInProgress.mode & ProfileMode) !== NoMode) { + transferActualDuration(workInProgress); + } // Don't bubble properties in this case. - if (prevSibling === null) { - // eslint-disable-next-line react-internal/prod-error-codes - throw new Error("Expected parent to have a child."); - } + return workInProgress; + } - while (prevSibling.sibling !== oldWorkInProgress) { - prevSibling = prevSibling.sibling; + var nextDidTimeout = nextState !== null; + var prevDidTimeout = current !== null && current.memoizedState !== null; + // a passive effect, which is when we process the transitions + + if (nextDidTimeout !== prevDidTimeout) { + // 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; // TODO: This will still suspend a synchronous tree if anything + // in the concurrent tree already suspended during this render. + // This is a known bug. + + if ((workInProgress.mode & ConcurrentMode) !== NoMode) { + // TODO: Move this back to throwException because this is too late + // if this is a large tree which is common for initial loads. We + // don't know if we should restart a render or not until we get + // this marker, and this is too late. + // If this render already had a ping or lower pri updates, + // and this is the first time we know we're going to suspend we + // should be able to immediately restart from within throwException. + var hasInvisibleChildContext = + current === null && + (workInProgress.memoizedProps.unstable_avoidThisFallback !== + true || + !enableSuspenseAvoidThisFallback); - if (prevSibling === null) { - // eslint-disable-next-line react-internal/prod-error-codes - throw new Error("Expected to find the previous sibling."); - } - } + if ( + hasInvisibleChildContext || + hasSuspenseContext( + suspenseStackCursor.current, + InvisibleParentSuspenseContext + ) + ) { + // If this was in an invisible tree or a new render, then showing + // this boundary is ok. + renderDidSuspend(); + } else { + // Otherwise, we're going to have to hide content so we should + // suspend for longer if possible. + renderDidSuspendDelayIfPossible(); + } + } + } + } - 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 wakeables = workInProgress.updateQueue; - var deletions = returnFiber.deletions; + if (wakeables !== null) { + // Schedule an effect to attach a retry listener to the promise. + // TODO: Move to passive phase + workInProgress.flags |= Update; + } - if (deletions === null) { - returnFiber.deletions = [current]; - returnFiber.flags |= ChildDeletion; - } else { - deletions.push(current); - } + bubbleProperties(workInProgress); + + { + 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 Flow doesn't support type casting in combination with the -= operator + workInProgress.treeBaseDuration -= + primaryChildFragment.treeBaseDuration; + } + } + } + } - newWorkInProgress.flags |= Placement; // Restart work from the new fiber. + return null; + } - return newWorkInProgress; - } -} + case HostPortal: + popHostContainer(workInProgress); + updateHostContainer(current, workInProgress); -function checkScheduledUpdateOrContext(current, renderLanes) { - // Before performing an early bailout, we must check if there are pending - // updates or context. - var updateLanes = current.lanes; + if (current === null) { + preparePortalMount(workInProgress.stateNode.containerInfo); + } - if (includesSomeLane(updateLanes, renderLanes)) { - return true; - } // No pending update, but because context is propagated lazily, we need + bubbleProperties(workInProgress); + return null; - return false; -} + case ContextProvider: + // Pop provider fiber + var context = workInProgress.type._context; + popProvider(context, workInProgress); + bubbleProperties(workInProgress); + return null; -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); - var root = workInProgress.stateNode; - break; + 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; - case HostComponent: - pushHostContext(workInProgress); - break; + if (isContextProvider(_Component)) { + popContext(workInProgress); + } - case ClassComponent: { - var Component = workInProgress.type; + bubbleProperties(workInProgress); + return null; + } - if (isContextProvider(Component)) { - pushContextProvider(workInProgress); - } + case SuspenseListComponent: { + popSuspenseContext(workInProgress); + var renderState = workInProgress.memoizedState; - break; - } + if (renderState === null) { + // We're running in the default, "independent" mode. + // We don't do anything in this mode. + bubbleProperties(workInProgress); + return null; + } - case HostPortal: - pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); - break; + var didSuspendAlready = (workInProgress.flags & DidCapture) !== NoFlags; + 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); + + 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 newThenables = suspended.updateQueue; + + if (newThenables !== null) { + workInProgress.updateQueue = newThenables; + workInProgress.flags |= Update; + } // 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; + resetChildFibers(workInProgress, renderLanes); // Set up the Suspense Context to force suspense and immediately + // rerender the children. + + pushSuspenseContext( + workInProgress, + setShallowSuspenseContext( + suspenseStackCursor.current, + ForceSuspenseFallback + ) + ); // Don't bubble properties in this case. + + return workInProgress.child; + } - case ContextProvider: { - var newValue = workInProgress.memoizedProps.value; - var context = workInProgress.type._context; - pushProvider(workInProgress, context, newValue); - break; - } + row = row.sibling; + } + } - case Profiler: - { - // Profiler should only call onRender when one of its descendants actually rendered. - var hasChildWork = includesSomeLane( - renderLanes, - workInProgress.childLanes - ); + if (renderState.tail !== null && now() > 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 (hasChildWork) { - workInProgress.flags |= Update; - } + 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. - { - // 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 _newThenables = _suspended.updateQueue; - break; + if (_newThenables !== null) { + workInProgress.updateQueue = _newThenables; + workInProgress.flags |= Update; + } - case SuspenseComponent: { - var state = workInProgress.memoizedState; + cutOffTailIfNeeded(renderState, true); // This might have been modified. - if (state !== null) { - if (state.dehydrated !== null) { - pushSuspenseContext( - workInProgress, - setDefaultShallowSuspenseContext(suspenseStackCursor.current) - ); // 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 ( + 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() * 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; + } + } - workInProgress.flags |= DidCapture; // We should never render the children of a dehydrated boundary until we - // upgrade it. We return null instead of bailoutOnAlreadyFinishedWork. + 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; - 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 (previousSibling !== null) { + previousSibling.sibling = renderedTail; + } else { + workInProgress.child = renderedTail; + } - var primaryChildFragment = workInProgress.child; - var primaryChildLanes = primaryChildFragment.childLanes; + renderState.last = renderedTail; + } + } - 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 - pushSuspenseContext( - workInProgress, - setDefaultShallowSuspenseContext(suspenseStackCursor.current) - ); // The primary children do not have pending work with sufficient - // priority. Bailout. + 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(); + 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 = setShallowSuspenseContext( + suspenseContext, + ForceSuspenseFallback + ); + } else { + suspenseContext = setDefaultShallowSuspenseContext(suspenseContext); + } - var child = bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderLanes - ); + pushSuspenseContext(workInProgress, suspenseContext); // Do a pass over the next row. + // Don't bubble properties in this case. - 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; + return next; } - } - } else { - pushSuspenseContext( - workInProgress, - setDefaultShallowSuspenseContext(suspenseStackCursor.current) - ); - } - break; - } + bubbleProperties(workInProgress); + return null; + } - case SuspenseListComponent: { - var didSuspendBefore = (current.flags & DidCapture) !== NoFlags; + case ScopeComponent: { + break; + } - var _hasChildWork = includesSomeLane( - renderLanes, - workInProgress.childLanes - ); + case OffscreenComponent: + case LegacyHiddenComponent: { + popRenderLanes(workInProgress); + var _nextState = workInProgress.memoizedState; + var nextIsHidden = _nextState !== 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. + if (current !== null) { + var _prevState = current.memoizedState; + var prevIsHidden = _prevState !== null; - 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. + if ( + prevIsHidden !== nextIsHidden && // LegacyHidden doesn't do any hiding — it only pre-renders. + !enableLegacyHidden + ) { + workInProgress.flags |= Visibility; + } + } - var renderState = workInProgress.memoizedState; + 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(subtreeRenderLanes, OffscreenLane)) { + bubbleProperties(workInProgress); - 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; - } + { + // 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. + if (workInProgress.subtreeFlags & (Placement | Update)) { + workInProgress.flags |= Visibility; + } + } + } + } + return null; + } - pushSuspenseContext(workInProgress, suspenseStackCursor.current); + case CacheComponent: { + return null; + } - 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; + case TracingMarkerComponent: { + 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); - } - } - - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); -} -function beginWork(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._debugOwner || null, - workInProgress.mode, - workInProgress.lanes - ) + 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 (current !== null) { - var oldProps = current.memoizedProps; - var newProps = workInProgress.pendingProps; - - 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 - ); - 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 - ) { - // No pending updates or context. Bail out now. - didReceiveUpdate = false; - return attemptEarlyBailoutIfNoScheduledUpdate( - current, - workInProgress, - renderLanes - ); - } + function unwindWork(current, workInProgress, renderLanes) { + // Note: This intentionally doesn't check if we're hydrating because comparing + // to the current tree provider fiber is just as fast and less error-prone. + // Ideally we would have a special version of the work loop only + // for hydration. + popTreeContext(workInProgress); - if ((current.flags & ForceUpdateForLegacySuspense) !== NoFlags) { - // 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. + switch (workInProgress.tag) { + case ClassComponent: { + var Component = workInProgress.type; - workInProgress.lanes = NoLanes; + if (isContextProvider(Component)) { + popContext(workInProgress); + } - switch (workInProgress.tag) { - case IndeterminateComponent: { - return mountIndeterminateComponent( - current, - workInProgress, - workInProgress.type, - renderLanes - ); - } + var flags = workInProgress.flags; - case LazyComponent: { - var elementType = workInProgress.elementType; - return mountLazyComponent( - current, - workInProgress, - elementType, - renderLanes - ); - } + if (flags & ShouldCapture) { + workInProgress.flags = (flags & ~ShouldCapture) | DidCapture; - 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 ((workInProgress.mode & ProfileMode) !== NoMode) { + transferActualDuration(workInProgress); + } - case ClassComponent: { - var _Component = workInProgress.type; - var _unresolvedProps = workInProgress.pendingProps; + return workInProgress; + } - var _resolvedProps = - workInProgress.elementType === _Component - ? _unresolvedProps - : resolveDefaultProps(_Component, _unresolvedProps); + return null; + } - return updateClassComponent( - current, - workInProgress, - _Component, - _resolvedProps, - renderLanes - ); - } + case HostRoot: { + var root = workInProgress.stateNode; + popHostContainer(workInProgress); + popTopLevelContextObject(workInProgress); + resetWorkInProgressVersions(); + var _flags = workInProgress.flags; - case HostRoot: - return updateHostRoot(current, workInProgress, renderLanes); + if ( + (_flags & ShouldCapture) !== NoFlags && + (_flags & DidCapture) === NoFlags + ) { + // 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 HostComponent: - return updateHostComponent(current, workInProgress, renderLanes); + return null; + } - case HostText: - return updateHostText(); + case HostComponent: { + // TODO: popHydrationState + popHostContext(workInProgress); + return null; + } - case SuspenseComponent: - return updateSuspenseComponent(current, workInProgress, renderLanes); + case SuspenseComponent: { + popSuspenseContext(workInProgress); + var suspenseState = workInProgress.memoizedState; - case HostPortal: - return updatePortalComponent(current, workInProgress, renderLanes); + 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." + ); + } + } - case ForwardRef: { - var type = workInProgress.type; - var _unresolvedProps2 = workInProgress.pendingProps; + var _flags2 = workInProgress.flags; - var _resolvedProps2 = - workInProgress.elementType === type - ? _unresolvedProps2 - : resolveDefaultProps(type, _unresolvedProps2); + if (_flags2 & ShouldCapture) { + workInProgress.flags = (_flags2 & ~ShouldCapture) | DidCapture; // Captured a suspense effect. Re-render the boundary. - return updateForwardRef( - current, - workInProgress, - type, - _resolvedProps2, - renderLanes - ); - } + if ((workInProgress.mode & ProfileMode) !== NoMode) { + transferActualDuration(workInProgress); + } - case Fragment: - return updateFragment(current, workInProgress, renderLanes); + return workInProgress; + } - case Mode: - return updateMode(current, workInProgress, renderLanes); + return null; + } - case Profiler: - return updateProfiler(current, workInProgress, renderLanes); + case SuspenseListComponent: { + popSuspenseContext(workInProgress); // SuspenseList doesn't actually catch anything. It should've been + // caught by a nested boundary. If not, it should bubble through. - case ContextProvider: - return updateContextProvider(current, workInProgress, renderLanes); + return null; + } - case ContextConsumer: - return updateContextConsumer(current, workInProgress, renderLanes); + case HostPortal: + popHostContainer(workInProgress); + return null; - case MemoComponent: { - var _type2 = workInProgress.type; - var _unresolvedProps3 = workInProgress.pendingProps; // Resolve outer props first, then resolve inner props. + case ContextProvider: + var context = workInProgress.type._context; + popProvider(context, workInProgress); + return null; - var _resolvedProps3 = resolveDefaultProps(_type2, _unresolvedProps3); + case OffscreenComponent: + case LegacyHiddenComponent: + popRenderLanes(workInProgress); + return null; - { - if (workInProgress.type !== workInProgress.elementType) { - var outerPropTypes = _type2.propTypes; + case CacheComponent: + return null; - if (outerPropTypes) { - checkPropTypes( - outerPropTypes, - _resolvedProps3, // Resolved for outer only - "prop", - getComponentNameFromType(_type2) - ); - } - } + default: + return null; } - - _resolvedProps3 = resolveDefaultProps(_type2.type, _resolvedProps3); - return updateMemoComponent( - current, - workInProgress, - _type2, - _resolvedProps3, - renderLanes - ); - } - - case SimpleMemoComponent: { - return updateSimpleMemoComponent( - current, - workInProgress, - workInProgress.type, - workInProgress.pendingProps, - renderLanes - ); } - case IncompleteClassComponent: { - var _Component2 = workInProgress.type; - var _unresolvedProps4 = workInProgress.pendingProps; + function unwindInterruptedWork(current, interruptedWork, renderLanes) { + // Note: This intentionally doesn't check if we're hydrating because comparing + // to the current tree provider fiber is just as fast and less error-prone. + // Ideally we would have a special version of the work loop only + // for hydration. + popTreeContext(interruptedWork); - var _resolvedProps4 = - workInProgress.elementType === _Component2 - ? _unresolvedProps4 - : resolveDefaultProps(_Component2, _unresolvedProps4); + switch (interruptedWork.tag) { + case ClassComponent: { + var childContextTypes = interruptedWork.type.childContextTypes; - return mountIncompleteClassComponent( - current, - workInProgress, - _Component2, - _resolvedProps4, - renderLanes - ); - } + if (childContextTypes !== null && childContextTypes !== undefined) { + popContext(interruptedWork); + } - case SuspenseListComponent: { - return updateSuspenseListComponent(current, workInProgress, renderLanes); - } + break; + } - case ScopeComponent: { - break; - } + case HostRoot: { + var root = interruptedWork.stateNode; + popHostContainer(interruptedWork); + popTopLevelContextObject(interruptedWork); + resetWorkInProgressVersions(); + break; + } - case OffscreenComponent: { - return updateOffscreenComponent(current, workInProgress, renderLanes); - } - } + case HostComponent: { + popHostContext(interruptedWork); + break; + } - throw new Error( - "Unknown unit of work tag (" + - workInProgress.tag + - "). This error is likely caused by a bug in " + - "React. Please file an issue." - ); -} + 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: + popSuspenseContext(interruptedWork); + break; -function markRef$1(workInProgress) { - workInProgress.flags |= Ref; -} + case SuspenseListComponent: + popSuspenseContext(interruptedWork); + break; -var appendAllChildren; -var updateHostContainer; -var updateHostComponent$1; -var updateHostText$1; - -{ - // Mutation mode - appendAllChildren = function( - 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); - else if (node.child !== null) { - node.child.return = node; - node = node.child; - continue; - } + case ContextProvider: + var context = interruptedWork.type._context; + popProvider(context, interruptedWork); + break; - if (node === workInProgress) { - return; + case OffscreenComponent: + case LegacyHiddenComponent: + popRenderLanes(interruptedWork); + break; } + } - while (node.sibling === null) { - if (node.return === null || node.return === workInProgress) { - return; - } + var didWarnAboutUndefinedSnapshotBeforeUpdate = null; - node = node.return; + { + didWarnAboutUndefinedSnapshotBeforeUpdate = new Set(); + } // Used during the commit phase to track the state of the Offscreen component stack. + var PossiblyWeakSet = typeof WeakSet === "function" ? WeakSet : Set; + var nextEffect = null; // Used for Profiling builds to track updaters. + + var inProgressLanes = null; + var inProgressRoot = null; + 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(); } - - node.sibling.return = node.return; - node = node.sibling; } - }; - updateHostContainer = function(current, workInProgress) { - // Noop - }; + var callComponentWillUnmountWithTimer = function (current, instance) { + instance.props = current.memoizedProps; + instance.state = current.memoizedState; - updateHostComponent$1 = function( - current, - workInProgress, - type, - newProps, - rootContainerInstance - ) { - // 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 (current.mode & ProfileMode) { + try { + startLayoutEffectTimer(); + instance.componentWillUnmount(); + } finally { + recordLayoutEffectDuration(current); + } + } else { + instance.componentWillUnmount(); + } + }; // Capture errors so they don't interrupt mounting. - if (oldProps === newProps) { - // In mutation mode, this is sufficient for a bailout because - // we won't touch this node even if children changed. - return; - } // If we get updated because one of our children updated, we don't - // have newProps so we'll have to reuse them. - // TODO: Split the update API as separate for the props vs. children. - // Even better would be if children weren't special cased at all tho. + function safelyCallComponentWillUnmount( + current, + nearestMountedAncestor, + instance + ) { + try { + callComponentWillUnmountWithTimer(current, instance); + } catch (error) { + captureCommitPhaseError(current, nearestMountedAncestor, error); + } + } // Capture errors so they don't interrupt mounting. - var instance = workInProgress.stateNode; - var currentHostContext = getHostContext(); // TODO: Experiencing an error where oldProps is null. Suggests a host - // component is hitting the resume path. Figure out why. Possibly - // related to `hidden`. + function safelyDetachRef(current, nearestMountedAncestor) { + var ref = current.ref; - var updatePayload = prepareUpdate(); // TODO: Type this specific to this type of component. + if (ref !== null) { + if (typeof ref === "function") { + var retVal; - workInProgress.updateQueue = updatePayload; // If the update payload indicates that there is a change or if there - // is a new ref we mark this as an update. All the work is done in commitWork. + try { + if ( + enableProfilerTimer && + enableProfilerCommitHooks && + current.mode & ProfileMode + ) { + try { + startLayoutEffectTimer(); + retVal = ref(null); + } finally { + recordLayoutEffectDuration(current); + } + } else { + retVal = ref(null); + } + } catch (error) { + captureCommitPhaseError(current, nearestMountedAncestor, error); + } - if (updatePayload) { - markUpdate(workInProgress); + { + 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 { + ref.current = null; + } + } } - }; - updateHostText$1 = function(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); + function safelyCallDestroy(current, nearestMountedAncestor, destroy) { + try { + destroy(); + } catch (error) { + captureCommitPhaseError(current, nearestMountedAncestor, error); + } } - }; -} -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; - } + var focusedInstanceHandle = null; + var shouldFireAfterActiveInstanceBlur = false; + function commitBeforeMutationEffects(root, firstChild) { + focusedInstanceHandle = prepareForCommit(root.containerInfo); + nextEffect = firstChild; + commitBeforeMutationEffects_begin(); // We no longer need to track the active instance fiber - break; + var shouldFire = shouldFireAfterActiveInstanceBlur; + shouldFireAfterActiveInstanceBlur = false; + focusedInstanceHandle = null; + return shouldFire; } - 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 commitBeforeMutationEffects_begin() { + while (nextEffect !== null) { + var fiber = nextEffect; // This phase is only used for beforeActiveInstanceBlur. - _tailNode = _tailNode.sibling; - } // Next we're simply going to delete all insertions after the - // last rendered item. + var child = fiber.child; - 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; + if ( + (fiber.subtreeFlags & BeforeMutationMask) !== NoFlags && + child !== null + ) { + child.return = fiber; + nextEffect = child; } else { - renderState.tail = null; + commitBeforeMutationEffects_complete(); } - } else { - // Detach the insertion after the last node that was already - // inserted. - _lastTailNode.sibling = null; } - - break; } - } -} -function bubbleProperties(completedWork) { - var didBailout = - completedWork.alternate !== null && - completedWork.alternate.child === completedWork.child; - var newChildLanes = NoLanes; - var subtreeFlags = NoFlags; - - 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; + function commitBeforeMutationEffects_complete() { + while (nextEffect !== null) { + var fiber = nextEffect; + setCurrentFiber(fiber); - 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. - - actualDuration += child.actualDuration; - treeBaseDuration += child.treeBaseDuration; - child = child.sibling; - } + try { + commitBeforeMutationEffectsOnFiber(fiber); + } catch (error) { + captureCommitPhaseError(fiber, fiber.return, error); + } - completedWork.actualDuration = actualDuration; - completedWork.treeBaseDuration = treeBaseDuration; - } else { - var _child = completedWork.child; + resetCurrentFiber(); + var sibling = fiber.sibling; - 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 (sibling !== null) { + sibling.return = fiber.return; + nextEffect = sibling; + return; + } - _child.return = completedWork; - _child = _child.sibling; + nextEffect = fiber.return; } } - 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. + function commitBeforeMutationEffectsOnFiber(finishedWork) { + var current = finishedWork.alternate; + var flags = finishedWork.flags; - subtreeFlags |= _child2.subtreeFlags & StaticMask; - subtreeFlags |= _child2.flags & StaticMask; - _treeBaseDuration += _child2.treeBaseDuration; - _child2 = _child2.sibling; - } + if ((flags & Snapshot) !== NoFlags) { + setCurrentFiber(finishedWork); - completedWork.treeBaseDuration = _treeBaseDuration; - } else { - var _child3 = completedWork.child; + switch (finishedWork.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { + break; + } - 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. + case ClassComponent: { + 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. - 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. + { + 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" + ); + } - _child3.return = completedWork; - _child3 = _child3.sibling; - } - } + 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" + ); + } + } + } - completedWork.subtreeFlags |= subtreeFlags; - } + var snapshot = instance.getSnapshotBeforeUpdate( + finishedWork.elementType === finishedWork.type + ? prevProps + : resolveDefaultProps(finishedWork.type, prevProps), + prevState + ); - completedWork.childLanes = newChildLanes; - return didBailout; -} + { + var didWarnSet = didWarnAboutUndefinedSnapshotBeforeUpdate; -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 (snapshot === undefined && !didWarnSet.has(finishedWork.type)) { + didWarnSet.add(finishedWork.type); - prepareToHydrateHostSuspenseInstance(); - bubbleProperties(workInProgress); + error( + "%s.getSnapshotBeforeUpdate(): A snapshot value (or null) " + + "must be returned. You have returned undefined.", + getComponentNameFromFiber(finishedWork) + ); + } + } - { - if ((workInProgress.mode & ProfileMode) !== NoMode) { - var isTimedOutSuspense = nextState !== null; + instance.__reactInternalSnapshotBeforeUpdate = snapshot; + } - if (isTimedOutSuspense) { - // Don't count time spent in a timed out Suspense subtree as part of the base duration. - var primaryChildFragment = workInProgress.child; + break; + } - if (primaryChildFragment !== null) { - // $FlowFixMe Flow doesn't support type casting in combination with the -= operator - workInProgress.treeBaseDuration -= - primaryChildFragment.treeBaseDuration; + case HostRoot: { + { + var root = finishedWork.stateNode; + clearContainer(root.containerInfo); } + + break; + } + + case HostComponent: + case HostText: + case HostPortal: + case IncompleteClassComponent: + // Nothing to do for these component types + break; + + default: { + 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." + ); } } + + resetCurrentFiber(); } + } - return false; - } else { - if ((workInProgress.flags & DidCapture) === NoFlags) { - // 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 commitHookEffectListUnmount( + flags, + finishedWork, + nearestMountedAncestor + ) { + var updateQueue = finishedWork.updateQueue; + var lastEffect = updateQueue !== null ? updateQueue.lastEffect : null; - workInProgress.flags |= Update; - bubbleProperties(workInProgress); + if (lastEffect !== null) { + var firstEffect = lastEffect.next; + var effect = firstEffect; - { - if ((workInProgress.mode & ProfileMode) !== NoMode) { - var _isTimedOutSuspense = nextState !== null; + do { + if ((effect.tag & flags) === flags) { + // Unmount + var destroy = effect.destroy; + effect.destroy = undefined; + + if (destroy !== undefined) { + { + if ((flags & Insertion) !== NoFlags$1) { + setIsRunningInsertionEffect(true); + } + } - if (_isTimedOutSuspense) { - // Don't count time spent in a timed out Suspense subtree as part of the base duration. - var _primaryChildFragment = workInProgress.child; + safelyCallDestroy(finishedWork, nearestMountedAncestor, destroy); - if (_primaryChildFragment !== null) { - // $FlowFixMe Flow doesn't support type casting in combination with the -= operator - workInProgress.treeBaseDuration -= - _primaryChildFragment.treeBaseDuration; + { + if ((flags & Insertion) !== NoFlags$1) { + setIsRunningInsertionEffect(false); + } + } } } - } - } - return false; + effect = effect.next; + } while (effect !== firstEffect); + } } - } 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 commitHookEffectListMount(flags, finishedWork) { + var updateQueue = finishedWork.updateQueue; + var lastEffect = updateQueue !== null ? updateQueue.lastEffect : null; -function completeWork(current, workInProgress, renderLanes) { - var newProps = workInProgress.pendingProps; // Note: This intentionally doesn't check if we're hydrating because comparing - // to the current tree provider fiber is just as fast and less error-prone. - // Ideally we would have a special version of the work loop only - // for hydration. - - popTreeContext(workInProgress); - - 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 (lastEffect !== null) { + var firstEffect = lastEffect.next; + var effect = firstEffect; - case ClassComponent: { - var Component = workInProgress.type; + do { + if ((effect.tag & flags) === flags) { + var create = effect.create; - if (isContextProvider(Component)) { - popContext(workInProgress); - } + { + if ((flags & Insertion) !== NoFlags$1) { + setIsRunningInsertionEffect(true); + } + } - bubbleProperties(workInProgress); - return null; - } + effect.destroy = create(); - case HostRoot: { - var fiberRoot = workInProgress.stateNode; - popHostContainer(workInProgress); - popTopLevelContextObject(workInProgress); - resetWorkInProgressVersions(); + { + if ((flags & Insertion) !== NoFlags$1) { + setIsRunningInsertionEffect(false); + } + } - if (fiberRoot.pendingContext) { - fiberRoot.context = fiberRoot.pendingContext; - fiberRoot.pendingContext = null; - } + { + var destroy = effect.destroy; - 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 (destroy !== undefined && typeof destroy !== "function") { + var hookName = void 0; - 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 ((effect.tag & Layout) !== NoFlags) { + hookName = "useLayoutEffect"; + } else if ((effect.tag & Insertion) !== NoFlags) { + hookName = "useInsertionEffect"; + } else { + hookName = "useEffect"; + } - 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 - ) { - // 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(); + 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://react.dev/link/hooks-data-fetching"; + } else { + addendum = " You returned: " + destroy; + } + + error( + "%s must not return anything besides a function, " + + "which is used for clean-up.%s", + hookName, + addendum + ); + } } } - } - } - - updateHostContainer(current, workInProgress); - bubbleProperties(workInProgress); - return null; + effect = effect.next; + } while (effect !== firstEffect); + } } - case HostComponent: { - popHostContext(workInProgress); - var rootContainerInstance = getRootHostContainer(); - var type = workInProgress.type; + function commitPassiveEffectDurations(finishedRoot, finishedWork) { + { + // Only Profilers with work in their subtree will have an Update effect scheduled. + if ((finishedWork.flags & Update) !== NoFlags) { + 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. + + var commitTime = getCommitTime(); + var phase = finishedWork.alternate === null ? "mount" : "update"; - if (current !== null && workInProgress.stateNode != null) { - updateHostComponent$1( - current, - workInProgress, - type, - newProps, - rootContainerInstance - ); + { + if (isCurrentUpdateNested()) { + phase = "nested-update"; + } + } - if (current.ref !== workInProgress.ref) { - markRef$1(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 (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. - bubbleProperties(workInProgress); - return null; - } + var parentFiber = finishedWork.return; - var currentHostContext = 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. + outer: while (parentFiber !== null) { + switch (parentFiber.tag) { + case HostRoot: + var root = parentFiber.stateNode; + root.passiveEffectDuration += passiveEffectDuration; + break outer; - var _wasHydrated = popHydrationState(); + case Profiler: + var parentStateNode = parentFiber.stateNode; + parentStateNode.passiveEffectDuration += passiveEffectDuration; + break outer; + } - if (_wasHydrated) { - // TODO: Move this and createInstance step into the beginPhase - // to consolidate. - if (prepareToHydrateHostInstance()) { - // If changes to the hydrated node need to be applied at the - // commit-phase we mark this as such. - markUpdate(workInProgress); - } - } else { - var instance = createInstance( - type, - newProps, - rootContainerInstance, - currentHostContext, - workInProgress - ); - appendAllChildren(instance, workInProgress, false, false); - workInProgress.stateNode = instance; // Certain renderers require commit-time effects for initial mount. - // (eg DOM renderer supports auto-focus for certain elements). - // Make sure such renderers get scheduled for later work. + parentFiber = parentFiber.return; + } - if (finalizeInitialChildren(instance)) { - markUpdate(workInProgress); + break; + } } } - - if (workInProgress.ref !== null) { - // If there is a ref on a host node we need to schedule a callback - markRef$1(workInProgress); - } } - - bubbleProperties(workInProgress); - return null; } - case HostText: { - var newText = newProps; + function commitLayoutEffectOnFiber( + finishedRoot, + current, + finishedWork, + committedLanes + ) { + if ((finishedWork.flags & LayoutMask) !== NoFlags) { + switch (finishedWork.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { + { + // 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 (finishedWork.mode & ProfileMode) { + try { + startLayoutEffectTimer(); + commitHookEffectListMount(Layout | HasEffect, finishedWork); + } finally { + recordLayoutEffectDuration(finishedWork); + } + } else { + commitHookEffectListMount(Layout | HasEffect, 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. + break; + } - updateHostText$1(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. - } + case ClassComponent: { + var instance = finishedWork.stateNode; - var _rootContainerInstance = getRootHostContainer(); + if (finishedWork.flags & Update) { + { + 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" + ); + } + } + } - var _currentHostContext = getHostContext(); + if (finishedWork.mode & ProfileMode) { + try { + startLayoutEffectTimer(); + instance.componentDidMount(); + } finally { + recordLayoutEffectDuration(finishedWork); + } + } else { + instance.componentDidMount(); + } + } 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 ( + 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" + ); + } + } + } - var _wasHydrated2 = popHydrationState(); + if (finishedWork.mode & ProfileMode) { + try { + startLayoutEffectTimer(); + instance.componentDidUpdate( + prevProps, + prevState, + instance.__reactInternalSnapshotBeforeUpdate + ); + } finally { + recordLayoutEffectDuration(finishedWork); + } + } else { + instance.componentDidUpdate( + prevProps, + prevState, + instance.__reactInternalSnapshotBeforeUpdate + ); + } + } + } + } // TODO: I think this is now always non-null by the time it reaches the + // commit phase. Consider removing the type check. - if (_wasHydrated2) { - if (prepareToHydrateHostTextInstance()) { - markUpdate(workInProgress); - } - } else { - workInProgress.stateNode = createTextInstance( - newText, - _rootContainerInstance, - _currentHostContext, - workInProgress - ); - } - } + var updateQueue = finishedWork.updateQueue; - bubbleProperties(workInProgress); - return null; - } + if (updateQueue !== null) { + { + 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" + ); + } - case SuspenseComponent: { - popSuspenseContext(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 (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. - if ( - current === null || - (current.memoizedState !== null && - current.memoizedState.dehydrated !== null) - ) { - var fallthroughToNormalSuspensePath = completeDehydratedSuspenseBoundary( - current, - workInProgress, - nextState - ); + commitUpdateQueue(finishedWork, updateQueue, instance); + } - if (!fallthroughToNormalSuspensePath) { - if (workInProgress.flags & ShouldCapture) { - // 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; + break; } - } // Continue with the normal Suspense path. - } - - if ((workInProgress.flags & DidCapture) !== NoFlags) { - // 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. + case HostRoot: { + // 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 workInProgress; - } + if (_updateQueue !== null) { + var _instance = null; - var nextDidTimeout = nextState !== null; - var prevDidTimeout = current !== null && current.memoizedState !== null; - // a passive effect, which is when we process the transitions + if (finishedWork.child !== null) { + switch (finishedWork.child.tag) { + case HostComponent: + _instance = getPublicInstance(finishedWork.child.stateNode); + break; - if (nextDidTimeout !== prevDidTimeout) { - // 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; // TODO: This will still suspend a synchronous tree if anything - // in the concurrent tree already suspended during this render. - // This is a known bug. - - if ((workInProgress.mode & ConcurrentMode) !== NoMode) { - // TODO: Move this back to throwException because this is too late - // if this is a large tree which is common for initial loads. We - // don't know if we should restart a render or not until we get - // this marker, and this is too late. - // If this render already had a ping or lower pri updates, - // and this is the first time we know we're going to suspend we - // should be able to immediately restart from within throwException. - var hasInvisibleChildContext = - current === null && - (workInProgress.memoizedProps.unstable_avoidThisFallback !== - true || - !enableSuspenseAvoidThisFallback); + case ClassComponent: + _instance = finishedWork.child.stateNode; + break; + } + } - if ( - hasInvisibleChildContext || - hasSuspenseContext( - suspenseStackCursor.current, - InvisibleParentSuspenseContext - ) - ) { - // If this was in an invisible tree or a new render, then showing - // this boundary is ok. - renderDidSuspend(); - } else { - // Otherwise, we're going to have to hide content so we should - // suspend for longer if possible. - renderDidSuspendDelayIfPossible(); + commitUpdateQueue(finishedWork, _updateQueue, _instance); } + + break; } - } - } - var wakeables = workInProgress.updateQueue; + case HostComponent: { + var _instance2 = finishedWork.stateNode; // 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 (wakeables !== null) { - // Schedule an effect to attach a retry listener to the promise. - // TODO: Move to passive phase - workInProgress.flags |= Update; - } + if (current === null && finishedWork.flags & Update) { + var type = finishedWork.type; + var props = finishedWork.memoizedProps; + } - bubbleProperties(workInProgress); + break; + } - { - 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; + case HostText: { + // We have no life-cycles associated with text. + break; + } - if (primaryChildFragment !== null) { - // $FlowFixMe Flow doesn't support type casting in combination with the -= operator - workInProgress.treeBaseDuration -= - primaryChildFragment.treeBaseDuration; - } + case HostPortal: { + // We have no life-cycles associated with portals. + break; } - } - } - return null; - } + case Profiler: { + { + 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"; - case HostPortal: - popHostContainer(workInProgress); - updateHostContainer(current, workInProgress); + { + if (isCurrentUpdateNested()) { + phase = "nested-update"; + } + } - if (current === null) { - preparePortalMount(workInProgress.stateNode.containerInfo); - } + if (typeof onRender === "function") { + onRender( + finishedWork.memoizedProps.id, + phase, + finishedWork.actualDuration, + finishedWork.treeBaseDuration, + finishedWork.actualStartTime, + commitTime + ); + } - bubbleProperties(workInProgress); - return null; + { + 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; + } - case ContextProvider: - // Pop provider fiber - var context = workInProgress.type._context; - popProvider(context, workInProgress); - bubbleProperties(workInProgress); - return null; + parentFiber = parentFiber.return; + } + } + } - 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; + break; + } - if (isContextProvider(_Component)) { - popContext(workInProgress); - } + case SuspenseComponent: { + break; + } - bubbleProperties(workInProgress); - return null; - } + case SuspenseListComponent: + case IncompleteClassComponent: + case ScopeComponent: + case OffscreenComponent: + case LegacyHiddenComponent: + case TracingMarkerComponent: { + break; + } - case SuspenseListComponent: { - popSuspenseContext(workInProgress); - var renderState = workInProgress.memoizedState; + default: + 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." + ); + } + } - if (renderState === null) { - // We're running in the default, "independent" mode. - // We don't do anything in this mode. - bubbleProperties(workInProgress); - return null; + { + { + if (finishedWork.flags & Ref) { + commitAttachRef(finishedWork); + } + } } + } - var didSuspendAlready = (workInProgress.flags & DidCapture) !== NoFlags; - 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); - - if (!cannotBeSuspended) { - var row = workInProgress.child; + function hideOrUnhideAllChildren(finishedWork, isHidden) { + // Only hide or unhide the top-most host nodes. + var hostSubtreeRoot = null; - while (row !== null) { - var suspended = findFirstSuspended(row); + { + // 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 (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 newThenables = suspended.updateQueue; - - if (newThenables !== null) { - workInProgress.updateQueue = newThenables; - workInProgress.flags |= Update; - } // 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; - resetChildFibers(workInProgress, renderLanes); // Set up the Suspense Context to force suspense and immediately - // rerender the children. - - pushSuspenseContext( - workInProgress, - setShallowSuspenseContext( - suspenseStackCursor.current, - ForceSuspenseFallback - ) - ); // Don't bubble properties in this case. + while (true) { + if (node.tag === HostComponent) { + if (hostSubtreeRoot === null) { + hostSubtreeRoot = node; + + try { + var instance = node.stateNode; - return workInProgress.child; + 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 _instance3 = node.stateNode; - row = row.sibling; + if (isHidden) { + hideTextInstance(_instance3); + } else { + unhideTextInstance(_instance3, 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; } - if (renderState.tail !== null && now() > 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; + if (node === finishedWork) { + return; } - } 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. - - var _newThenables = _suspended.updateQueue; - - if (_newThenables !== null) { - workInProgress.updateQueue = _newThenables; - workInProgress.flags |= Update; + while (node.sibling === null) { + if (node.return === null || node.return === finishedWork) { + return; } - 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; + if (hostSubtreeRoot === node) { + hostSubtreeRoot = 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() * 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; + node = node.return; } - 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(); - 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 (hostSubtreeRoot === node) { + hostSubtreeRoot = null; + } - if (didSuspendAlready) { - suspenseContext = setShallowSuspenseContext( - suspenseContext, - ForceSuspenseFallback - ); - } else { - suspenseContext = setDefaultShallowSuspenseContext(suspenseContext); + node.sibling.return = node.return; + node = node.sibling; } - - pushSuspenseContext(workInProgress, suspenseContext); // Do a pass over the next row. - // Don't bubble properties in this case. - - return next; } - - bubbleProperties(workInProgress); - return null; } - case ScopeComponent: { - break; - } + function commitAttachRef(finishedWork) { + var ref = finishedWork.ref; - case OffscreenComponent: - case LegacyHiddenComponent: { - popRenderLanes(workInProgress); - var _nextState = workInProgress.memoizedState; - var nextIsHidden = _nextState !== null; + if (ref !== null) { + var instance = finishedWork.stateNode; + var instanceToUse; - if (current !== null) { - var _prevState = current.memoizedState; - var prevIsHidden = _prevState !== null; + switch (finishedWork.tag) { + case HostComponent: + instanceToUse = getPublicInstance(instance); + break; - if ( - prevIsHidden !== nextIsHidden && // LegacyHidden doesn't do any hiding — it only pre-renders. - !enableLegacyHidden - ) { - workInProgress.flags |= Visibility; - } - } + default: + instanceToUse = instance; + } // Moved outside to ensure DCE works with this flag - 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(subtreeRenderLanes, OffscreenLane)) { - bubbleProperties(workInProgress); + if (typeof ref === "function") { + var retVal; - { - // 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. - if (workInProgress.subtreeFlags & (Placement | Update)) { - workInProgress.flags |= Visibility; + if (finishedWork.mode & ProfileMode) { + try { + startLayoutEffectTimer(); + retVal = ref(instanceToUse); + } finally { + recordLayoutEffectDuration(finishedWork); } + } else { + retVal = ref(instanceToUse); } - } - } - return null; - } - - case CacheComponent: { - return null; - } - - case TracingMarkerComponent: { - 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 unwindWork(current, workInProgress, renderLanes) { - // Note: This intentionally doesn't check if we're hydrating because comparing - // to the current tree provider fiber is just as fast and less error-prone. - // Ideally we would have a special version of the work loop only - // for hydration. - popTreeContext(workInProgress); - - switch (workInProgress.tag) { - case ClassComponent: { - var Component = workInProgress.type; - - if (isContextProvider(Component)) { - popContext(workInProgress); - } - var flags = workInProgress.flags; - - if (flags & ShouldCapture) { - workInProgress.flags = (flags & ~ShouldCapture) | DidCapture; + { + if (typeof retVal === "function") { + error( + "Unexpected return value from a callback ref in %s. " + + "A callback ref should not return a function.", + getComponentNameFromFiber(finishedWork) + ); + } + } + } else { + { + if (!ref.hasOwnProperty("current")) { + error( + "Unexpected ref object provided for %s. " + + "Use either a ref-setter function or React.createRef().", + getComponentNameFromFiber(finishedWork) + ); + } + } - if ((workInProgress.mode & ProfileMode) !== NoMode) { - transferActualDuration(workInProgress); + ref.current = instanceToUse; } - - return workInProgress; } - - return null; } - case HostRoot: { - var root = workInProgress.stateNode; - popHostContainer(workInProgress); - popTopLevelContextObject(workInProgress); - resetWorkInProgressVersions(); - var _flags = workInProgress.flags; + 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 ( - (_flags & ShouldCapture) !== NoFlags && - (_flags & DidCapture) === NoFlags - ) { - // 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 (alternate !== null) { + alternate.return = null; + } - return null; + fiber.return = null; } - case HostComponent: { - // TODO: popHydrationState - popHostContext(workInProgress); - return null; - } + function detachFiberAfterEffects(fiber) { + var alternate = fiber.alternate; - case SuspenseComponent: { - popSuspenseContext(workInProgress); - var suspenseState = workInProgress.memoizedState; + if (alternate !== null) { + fiber.alternate = null; + detachFiberAfterEffects(alternate); + } // Note: Defensively using negation instead of < in case + // `deletedTreeCleanUpLevel` is undefined. - 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." - ); + { + // 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 + // tree, which has its own pointers to children, parents, and siblings. + // The other host nodes also point back to fibers, so we should detach that + // one, too. + + if (fiber.tag === HostComponent) { + var hostInstance = fiber.stateNode; } - } - var _flags2 = workInProgress.flags; + fiber.stateNode = null; // I'm intentionally not clearing the `return` field in this level. We + // already disconnect the `return` pointer at the root of the deleted + // subtree (in `detachFiberMutation`). Besides, `return` by itself is not + // cyclical — it's only cyclical when combined with `child`, `sibling`, and + // `alternate`. But we'll clear it in the next level anyway, just in case. - if (_flags2 & ShouldCapture) { - workInProgress.flags = (_flags2 & ~ShouldCapture) | DidCapture; // Captured a suspense effect. Re-render the boundary. - - if ((workInProgress.mode & ProfileMode) !== NoMode) { - transferActualDuration(workInProgress); + { + fiber._debugOwner = null; } - return workInProgress; + { + // 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 + // + // The purpose of this branch is to be super aggressive so we can measure + // if there's any difference in memory impact. If there is, that could + // indicate a React leak we don't know about. + 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; + } } - - return null; - } - - case SuspenseListComponent: { - popSuspenseContext(workInProgress); // SuspenseList doesn't actually catch anything. It should've been - // caught by a nested boundary. If not, it should bubble through. - - return null; } - case HostPortal: - popHostContainer(workInProgress); - return null; - - case ContextProvider: - var context = workInProgress.type._context; - popProvider(context, workInProgress); - return null; - - case OffscreenComponent: - case LegacyHiddenComponent: - popRenderLanes(workInProgress); - return null; - - case CacheComponent: - return null; - - default: - return null; - } -} - -function unwindInterruptedWork(current, interruptedWork, renderLanes) { - // Note: This intentionally doesn't check if we're hydrating because comparing - // to the current tree provider fiber is just as fast and less error-prone. - // Ideally we would have a special version of the work loop only - // for hydration. - popTreeContext(interruptedWork); + function getHostParentFiber(fiber) { + var parent = fiber.return; - switch (interruptedWork.tag) { - case ClassComponent: { - var childContextTypes = interruptedWork.type.childContextTypes; + while (parent !== null) { + if (isHostParent(parent)) { + return parent; + } - if (childContextTypes !== null && childContextTypes !== undefined) { - popContext(interruptedWork); + parent = parent.return; } - break; - } - - case HostRoot: { - var root = interruptedWork.stateNode; - popHostContainer(interruptedWork); - popTopLevelContextObject(interruptedWork); - resetWorkInProgressVersions(); - 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 HostComponent: { - popHostContext(interruptedWork); - break; + function isHostParent(fiber) { + return ( + fiber.tag === HostComponent || + fiber.tag === HostRoot || + fiber.tag === HostPortal + ); } - case HostPortal: - popHostContainer(interruptedWork); - break; - - case SuspenseComponent: - popSuspenseContext(interruptedWork); - break; - - case SuspenseListComponent: - popSuspenseContext(interruptedWork); - break; - - case ContextProvider: - var context = interruptedWork.type._context; - popProvider(context, 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 OffscreenComponent: - case LegacyHiddenComponent: - popRenderLanes(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; + } -var didWarnAboutUndefinedSnapshotBeforeUpdate = null; - -{ - didWarnAboutUndefinedSnapshotBeforeUpdate = new Set(); -} // Used during the commit phase to track the state of the Offscreen component stack. -var PossiblyWeakSet = typeof WeakSet === "function" ? WeakSet : Set; -var nextEffect = null; // Used for Profiling builds to track updaters. - -var inProgressLanes = null; -var inProgressRoot = null; -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(); - } -} + node = node.return; + } -var callComponentWillUnmountWithTimer = function(current, instance) { - instance.props = current.memoizedProps; - instance.state = current.memoizedState; - - if (current.mode & ProfileMode) { - try { - startLayoutEffectTimer(); - instance.componentWillUnmount(); - } finally { - recordLayoutEffectDuration(current); - } - } else { - instance.componentWillUnmount(); - } -}; // Capture errors so they don't interrupt mounting. - -function safelyCallComponentWillUnmount( - current, - nearestMountedAncestor, - instance -) { - try { - callComponentWillUnmountWithTimer(current, instance); - } catch (error) { - captureCommitPhaseError(current, nearestMountedAncestor, error); - } -} // Capture errors so they don't interrupt mounting. - -function safelyDetachRef(current, nearestMountedAncestor) { - var ref = current.ref; - - if (ref !== null) { - if (typeof ref === "function") { - var retVal; + node.sibling.return = node.return; + node = node.sibling; - try { - if ( - enableProfilerTimer && - enableProfilerCommitHooks && - current.mode & ProfileMode + while ( + node.tag !== HostComponent && + node.tag !== HostText && + node.tag !== DehydratedFragment ) { - try { - startLayoutEffectTimer(); - retVal = ref(null); - } finally { - recordLayoutEffectDuration(current); + // 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; } - } else { - retVal = ref(null); - } - } catch (error) { - captureCommitPhaseError(current, nearestMountedAncestor, error); - } + } // Check if this host node is stable or about to be placed. - { - if (typeof retVal === "function") { - error( - "Unexpected return value from a callback ref in %s. " + - "A callback ref should not return a function.", - getComponentNameFromFiber(current) - ); + if (!(node.flags & Placement)) { + // Found it! + return node.stateNode; } } - } else { - ref.current = null; } - } -} -function safelyCallDestroy(current, nearestMountedAncestor, destroy) { - try { - destroy(); - } catch (error) { - captureCommitPhaseError(current, nearestMountedAncestor, error); - } -} + function commitPlacement(finishedWork) { + var parentFiber = getHostParentFiber(finishedWork); // Note: these two variables *must* always be updated together. -var focusedInstanceHandle = null; -var shouldFireAfterActiveInstanceBlur = false; -function commitBeforeMutationEffects(root, firstChild) { - focusedInstanceHandle = prepareForCommit(root.containerInfo); - nextEffect = firstChild; - commitBeforeMutationEffects_begin(); // We no longer need to track the active instance fiber - - var shouldFire = shouldFireAfterActiveInstanceBlur; - shouldFireAfterActiveInstanceBlur = false; - focusedInstanceHandle = null; - return shouldFire; -} + switch (parentFiber.tag) { + case HostComponent: { + var parent = parentFiber.stateNode; -function commitBeforeMutationEffects_begin() { - while (nextEffect !== null) { - var fiber = nextEffect; // This phase is only used for beforeActiveInstanceBlur. + if (parentFiber.flags & ContentReset) { + parentFiber.flags &= ~ContentReset; + } - var child = fiber.child; + 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 ( - (fiber.subtreeFlags & BeforeMutationMask) !== NoFlags && - child !== null - ) { - child.return = fiber; - nextEffect = child; - } else { - commitBeforeMutationEffects_complete(); - } - } -} + insertOrAppendPlacementNode(finishedWork, before, parent); + break; + } -function commitBeforeMutationEffects_complete() { - while (nextEffect !== null) { - var fiber = nextEffect; - setCurrentFiber(fiber); + case HostRoot: + case HostPortal: { + var _parent = parentFiber.stateNode.containerInfo; - try { - commitBeforeMutationEffectsOnFiber(fiber); - } catch (error) { - captureCommitPhaseError(fiber, fiber.return, error); - } + var _before = getHostSibling(finishedWork); - resetCurrentFiber(); - var sibling = fiber.sibling; + insertOrAppendPlacementNodeIntoContainer(finishedWork, _before, _parent); + break; + } + // eslint-disable-next-line-no-fallthrough - if (sibling !== null) { - sibling.return = fiber.return; - nextEffect = sibling; - return; + default: + throw new Error( + "Invalid host parent fiber. This error is likely caused by a bug " + + "in React. Please file an issue." + ); + } } - nextEffect = fiber.return; - } -} + function insertOrAppendPlacementNodeIntoContainer(node, before, parent) { + var tag = node.tag; + var isHost = tag === HostComponent || tag === HostText; -function commitBeforeMutationEffectsOnFiber(finishedWork) { - var current = finishedWork.alternate; - var flags = finishedWork.flags; + if (isHost) { + var stateNode = node.stateNode; - if ((flags & Snapshot) !== NoFlags) { - setCurrentFiber(finishedWork); + if (before) { + insertInContainerBefore(parent); + } else { + appendChildToContainer(parent, stateNode); + } + } else if (tag === HostPortal); + else { + var child = node.child; - switch (finishedWork.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - break; + if (child !== null) { + insertOrAppendPlacementNodeIntoContainer(child, before, parent); + var sibling = child.sibling; + + while (sibling !== null) { + insertOrAppendPlacementNodeIntoContainer(sibling, before, parent); + sibling = sibling.sibling; + } + } } + } - case ClassComponent: { - 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 insertOrAppendPlacementNode(node, before, parent) { + var tag = node.tag; + var isHost = tag === HostComponent || tag === HostText; - { - 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 (isHost) { + var stateNode = node.stateNode; - 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 (before) { + insertBefore(parent, stateNode, before); + } else { + appendChild(parent, stateNode); + } + } else if (tag === HostPortal); + 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 snapshot = instance.getSnapshotBeforeUpdate( - finishedWork.elementType === finishedWork.type - ? prevProps - : resolveDefaultProps(finishedWork.type, prevProps), - prevState - ); + var hostParent = null; + var hostParentIsContainer = false; - { - var didWarnSet = didWarnAboutUndefinedSnapshotBeforeUpdate; + 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 HostComponent: { + hostParent = parent.stateNode; + hostParentIsContainer = false; + break findParent; + } - if (snapshot === undefined && !didWarnSet.has(finishedWork.type)) { - didWarnSet.add(finishedWork.type); + case HostRoot: { + hostParent = parent.stateNode.containerInfo; + hostParentIsContainer = true; + break findParent; + } - error( - "%s.getSnapshotBeforeUpdate(): A snapshot value (or null) " + - "must be returned. You have returned undefined.", - getComponentNameFromFiber(finishedWork) - ); + case HostPortal: { + hostParent = parent.stateNode.containerInfo; + hostParentIsContainer = true; + break findParent; } } - instance.__reactInternalSnapshotBeforeUpdate = snapshot; + parent = parent.return; } - break; - } - - case HostRoot: { - { - var root = finishedWork.stateNode; - clearContainer(root.containerInfo); + 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." + ); } - break; + commitDeletionEffectsOnFiber(root, returnFiber, deletedFiber); + hostParent = null; + hostParentIsContainer = false; } - case HostComponent: - case HostText: - case HostPortal: - case IncompleteClassComponent: - // Nothing to do for these component types - break; + detachFiberMutation(deletedFiber); + } - default: { - 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." - ); + 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; } } - resetCurrentFiber(); - } -} + 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. -function commitHookEffectListUnmount( - flags, - finishedWork, - nearestMountedAncestor -) { - var updateQueue = finishedWork.updateQueue; - var lastEffect = updateQueue !== null ? updateQueue.lastEffect : null; - - if (lastEffect !== null) { - var firstEffect = lastEffect.next; - var effect = firstEffect; - - do { - if ((effect.tag & flags) === flags) { - // Unmount - var destroy = effect.destroy; - effect.destroy = undefined; - - if (destroy !== undefined) { + switch (deletedFiber.tag) { + case HostComponent: { { - if ((flags & Insertion) !== NoFlags$1) { - setIsRunningInsertionEffect(true); - } - } - - safelyCallDestroy(finishedWork, nearestMountedAncestor, destroy); + safelyDetachRef(deletedFiber, nearestMountedAncestor); + } // Intentional fallthrough to next branch + } + // eslint-disable-next-line-no-fallthrough + 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. { - if ((flags & Insertion) !== NoFlags$1) { - setIsRunningInsertionEffect(false); + 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); + } } } - } - } - effect = effect.next; - } while (effect !== firstEffect); - } -} + return; + } -function commitHookEffectListMount(flags, finishedWork) { - var updateQueue = finishedWork.updateQueue; - var lastEffect = updateQueue !== null ? updateQueue.lastEffect : null; + case DehydratedFragment: { + // Delete the dehydrated suspense boundary and all of its content. - if (lastEffect !== null) { - var firstEffect = lastEffect.next; - var effect = firstEffect; + { + if (hostParent !== null) { + if (hostParentIsContainer) { + clearSuspenseBoundaryFromContainer( + hostParent, + deletedFiber.stateNode + ); + } else { + clearSuspenseBoundary(hostParent, deletedFiber.stateNode); + } + } + } - do { - if ((effect.tag & flags) === flags) { - var create = effect.create; + return; + } - { - if ((flags & Insertion) !== NoFlags$1) { - setIsRunningInsertionEffect(true); + case HostPortal: { + { + // When we go into a portal, it becomes the parent to remove from. + var _prevHostParent = hostParent; + var _prevHostParentIsContainer = hostParentIsContainer; + hostParent = deletedFiber.stateNode.containerInfo; + hostParentIsContainer = true; + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + hostParent = _prevHostParent; + hostParentIsContainer = _prevHostParentIsContainer; } + + return; } - effect.destroy = create(); + case FunctionComponent: + case ForwardRef: + case MemoComponent: + case SimpleMemoComponent: { + { + var updateQueue = deletedFiber.updateQueue; + + if (updateQueue !== null) { + var lastEffect = updateQueue.lastEffect; + + if (lastEffect !== null) { + var firstEffect = lastEffect.next; + var effect = firstEffect; + + do { + var _effect = effect, + destroy = _effect.destroy, + tag = _effect.tag; + + if (destroy !== undefined) { + if ((tag & Insertion) !== NoFlags$1) { + safelyCallDestroy( + deletedFiber, + nearestMountedAncestor, + destroy + ); + } else if ((tag & Layout) !== NoFlags$1) { + if (deletedFiber.mode & ProfileMode) { + startLayoutEffectTimer(); + safelyCallDestroy( + deletedFiber, + nearestMountedAncestor, + destroy + ); + recordLayoutEffectDuration(deletedFiber); + } else { + safelyCallDestroy( + deletedFiber, + nearestMountedAncestor, + destroy + ); + } + } + } - { - if ((flags & Insertion) !== NoFlags$1) { - setIsRunningInsertionEffect(false); + effect = effect.next; + } while (effect !== firstEffect); + } + } } - } - - { - var destroy = effect.destroy; - if (destroy !== undefined && typeof destroy !== "function") { - var hookName = void 0; + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + return; + } - if ((effect.tag & Layout) !== NoFlags) { - hookName = "useLayoutEffect"; - } else if ((effect.tag & Insertion) !== NoFlags) { - hookName = "useInsertionEffect"; - } else { - hookName = "useEffect"; + case ClassComponent: { + { + safelyDetachRef(deletedFiber, nearestMountedAncestor); + var instance = deletedFiber.stateNode; + + if (typeof instance.componentWillUnmount === "function") { + safelyCallComponentWillUnmount( + deletedFiber, + nearestMountedAncestor, + instance + ); } + } - var addendum = void 0; + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + return; + } - 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://react.dev/link/hooks-data-fetching"; - } else { - addendum = " You returned: " + destroy; - } + case ScopeComponent: { + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + return; + } - error( - "%s must not return anything besides a function, " + - "which is used for clean-up.%s", - hookName, - addendum + case OffscreenComponent: { + { + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber ); } + + break; + } + + default: { + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + return; } } + } - effect = effect.next; - } while (effect !== firstEffect); - } -} + function commitSuspenseCallback(finishedWork) { + // TODO: Move this to passive phase + var newState = finishedWork.memoizedState; + } -function commitPassiveEffectDurations(finishedRoot, finishedWork) { - { - // Only Profilers with work in their subtree will have an Update effect scheduled. - if ((finishedWork.flags & Update) !== NoFlags) { - 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. + function attachSuspenseRetryListeners(finishedWork) { + // 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 wakeables = finishedWork.updateQueue; + + if (wakeables !== null) { + finishedWork.updateQueue = null; + var retryCache = finishedWork.stateNode; + + if (retryCache === null) { + retryCache = finishedWork.stateNode = new PossiblyWeakSet(); + } - var commitTime = getCommitTime(); - var phase = finishedWork.alternate === null ? "mount" : "update"; + wakeables.forEach(function (wakeable) { + // Memoize using the boundary fiber to prevent redundant listeners. + var retry = resolveRetryWakeable.bind(null, finishedWork, wakeable); - { - if (isCurrentUpdateNested()) { - phase = "nested-update"; + if (!retryCache.has(wakeable)) { + retryCache.add(wakeable); + + { + 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." + ); + } + } } + + wakeable.then(retry, retry); } + }); + } + } // This function detects when a Suspense boundary goes from visible to hidden. + function commitMutationEffects(root, finishedWork, committedLanes) { + inProgressLanes = committedLanes; + inProgressRoot = root; + setCurrentFiber(finishedWork); + commitMutationEffectsOnFiber(finishedWork, root); + setCurrentFiber(finishedWork); + inProgressLanes = null; + inProgressRoot = null; + } - 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. + 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 parentFiber = finishedWork.return; + if (deletions !== null) { + for (var i = 0; i < deletions.length; i++) { + var childToDelete = deletions[i]; - outer: while (parentFiber !== null) { - switch (parentFiber.tag) { - case HostRoot: - var root = parentFiber.stateNode; - root.passiveEffectDuration += passiveEffectDuration; - break outer; + try { + commitDeletionEffects(root, parentFiber, childToDelete); + } catch (error) { + captureCommitPhaseError(childToDelete, parentFiber, error); + } + } + } - case Profiler: - var parentStateNode = parentFiber.stateNode; - parentStateNode.passiveEffectDuration += passiveEffectDuration; - break outer; - } + var prevDebugFiber = getCurrentFiber(); - parentFiber = parentFiber.return; - } + if (parentFiber.subtreeFlags & MutationMask) { + var child = parentFiber.child; - break; + while (child !== null) { + setCurrentFiber(child); + commitMutationEffectsOnFiber(child, root); + child = child.sibling; } } + + setCurrentFiber(prevDebugFiber); } - } -} -function commitLayoutEffectOnFiber( - finishedRoot, - current, - finishedWork, - committedLanes -) { - if ((finishedWork.flags & LayoutMask) !== NoFlags) { - switch (finishedWork.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - { - // 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 (finishedWork.mode & ProfileMode) { + 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 reconcilation, 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 { - startLayoutEffectTimer(); - commitHookEffectListMount(Layout | HasEffect, finishedWork); - } finally { + 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 (finishedWork.mode & ProfileMode) { + try { + startLayoutEffectTimer(); + commitHookEffectListUnmount( + Layout | HasEffect, + finishedWork, + finishedWork.return + ); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } + recordLayoutEffectDuration(finishedWork); + } else { + try { + commitHookEffectListUnmount( + Layout | HasEffect, + finishedWork, + finishedWork.return + ); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } } - } else { - commitHookEffectListMount(Layout | HasEffect, finishedWork); } + + return; } - break; - } + case ClassComponent: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); - case ClassComponent: { - var instance = finishedWork.stateNode; + if (flags & Ref) { + if (current !== null) { + safelyDetachRef(current, current.return); + } + } - if (finishedWork.flags & Update) { - { - 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" - ); - } + return; + } - 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" - ); - } - } - } + case HostComponent: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); - if (finishedWork.mode & ProfileMode) { - try { - startLayoutEffectTimer(); - instance.componentDidMount(); - } finally { - recordLayoutEffectDuration(finishedWork); - } - } else { - instance.componentDidMount(); - } - } 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 & Ref) { + if (current !== null) { + safelyDetachRef(current, current.return); + } + } - { - 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" - ); - } + { + // 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; - 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" - ); - } - } + try { + resetTextContent(instance); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); } + } - if (finishedWork.mode & ProfileMode) { - try { - startLayoutEffectTimer(); - instance.componentDidUpdate( - prevProps, - prevState, - instance.__reactInternalSnapshotBeforeUpdate - ); - } finally { - recordLayoutEffectDuration(finishedWork); + if (flags & Update) { + var _instance4 = finishedWork.stateNode; + + if (_instance4 != 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; + + if (updatePayload !== null) { + try { + commitUpdate( + _instance4, + updatePayload, + type, + oldProps, + newProps, + finishedWork + ); + } catch (error) { + captureCommitPhaseError( + finishedWork, + finishedWork.return, + error + ); + } } - } else { - instance.componentDidUpdate( - prevProps, - prevState, - instance.__reactInternalSnapshotBeforeUpdate - ); } } } - } // 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; + } - if (updateQueue !== null) { - { - 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" + case HostText: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + + 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." ); } - 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" - ); + 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. + + var oldText = current !== null ? current.memoizedProps : newText; + + try { + commitTextUpdate(textInstance, oldText, newText); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); } } - } // 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. + } - commitUpdateQueue(finishedWork, updateQueue, instance); + return; } - break; - } + case HostRoot: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + + return; + } + + case HostPortal: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + + return; + } - case HostRoot: { - // 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; + case SuspenseComponent: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + var offscreenFiber = finishedWork.child; - if (_updateQueue !== null) { - var _instance = null; + if (offscreenFiber.flags & Visibility) { + var offscreenInstance = offscreenFiber.stateNode; + var newState = offscreenFiber.memoizedState; + var isHidden = newState !== null; // Track the current state on the Offscreen instance so we can + // read it during an event - if (finishedWork.child !== null) { - switch (finishedWork.child.tag) { - case HostComponent: - _instance = getPublicInstance(finishedWork.child.stateNode); - break; + offscreenInstance.isHidden = isHidden; - case ClassComponent: - _instance = finishedWork.child.stateNode; - break; + if (isHidden) { + var wasHidden = + offscreenFiber.alternate !== null && + offscreenFiber.alternate.memoizedState !== null; + + if (!wasHidden) { + // TODO: Move to passive phase + markCommitTimeOfFallback(); + } + } + } + + if (flags & Update) { + try { + commitSuspenseCallback(finishedWork); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); } + + attachSuspenseRetryListeners(finishedWork); } - commitUpdateQueue(finishedWork, _updateQueue, _instance); + return; } - break; - } + case OffscreenComponent: { + var _wasHidden = current !== null && current.memoizedState !== null; - case HostComponent: { - var _instance2 = finishedWork.stateNode; // 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. + { + recursivelyTraverseMutationEffects(root, finishedWork); + } - if (current === null && finishedWork.flags & Update) { - var type = finishedWork.type; - var props = finishedWork.memoizedProps; - } + commitReconciliationEffects(finishedWork); - break; - } + if (flags & Visibility) { + var _offscreenInstance = finishedWork.stateNode; + var _newState = finishedWork.memoizedState; - case HostText: { - // We have no life-cycles associated with text. - break; - } + var _isHidden = _newState !== null; - case HostPortal: { - // We have no life-cycles associated with portals. - break; - } + var offscreenBoundary = finishedWork; // Track the current state on the Offscreen instance so we can + // read it during an event - case Profiler: { - { - 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"; + _offscreenInstance.isHidden = _isHidden; - { - if (isCurrentUpdateNested()) { - phase = "nested-update"; + { + // TODO: This needs to run whenever there's an insertion or update + // inside a hidden Offscreen tree. + hideOrUnhideAllChildren(offscreenBoundary, _isHidden); } } - if (typeof onRender === "function") { - onRender( - finishedWork.memoizedProps.id, - phase, - finishedWork.actualDuration, - finishedWork.treeBaseDuration, - finishedWork.actualStartTime, - commitTime - ); - } + return; + } - { - 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; - } + case SuspenseListComponent: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); - parentFiber = parentFiber.return; - } + if (flags & Update) { + attachSuspenseRetryListeners(finishedWork); } + + return; + } + + case ScopeComponent: { + return; } - break; + 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. - case SuspenseComponent: { - break; + finishedWork.flags &= ~Placement; } - case SuspenseListComponent: - case IncompleteClassComponent: - case ScopeComponent: - case OffscreenComponent: - case LegacyHiddenComponent: - case TracingMarkerComponent: { - break; + if (flags & Hydrating) { + finishedWork.flags &= ~Hydrating; } + } - default: - 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." - ); + function commitLayoutEffects(finishedWork, root, committedLanes) { + inProgressLanes = committedLanes; + inProgressRoot = root; + nextEffect = finishedWork; + commitLayoutEffects_begin(finishedWork, root, committedLanes); + inProgressLanes = null; + inProgressRoot = null; } - } - { - { - if (finishedWork.flags & Ref) { - commitAttachRef(finishedWork); + function commitLayoutEffects_begin(subtreeRoot, root, committedLanes) { + // Suspense layout effects semantics don't change for legacy roots. + var isModernRoot = (subtreeRoot.mode & ConcurrentMode) !== NoMode; + + while (nextEffect !== null) { + var fiber = nextEffect; + var firstChild = fiber.child; + + if ((fiber.subtreeFlags & LayoutMask) !== NoFlags && firstChild !== null) { + firstChild.return = fiber; + nextEffect = firstChild; + } else { + commitLayoutMountEffects_complete(subtreeRoot, root, committedLanes); + } } } - } -} -function hideOrUnhideAllChildren(finishedWork, isHidden) { - // Only hide or unhide the top-most host nodes. - var hostSubtreeRoot = null; + function commitLayoutMountEffects_complete(subtreeRoot, root, committedLanes) { + while (nextEffect !== null) { + var fiber = nextEffect; - { - // 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; - - while (true) { - if (node.tag === HostComponent) { - if (hostSubtreeRoot === null) { - hostSubtreeRoot = node; + if ((fiber.flags & LayoutMask) !== NoFlags) { + var current = fiber.alternate; + setCurrentFiber(fiber); try { - var instance = node.stateNode; - - if (isHidden) { - hideInstance(instance); - } else { - unhideInstance(node.stateNode, node.memoizedProps); - } + commitLayoutEffectOnFiber(root, current, fiber, committedLanes); } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); + captureCommitPhaseError(fiber, fiber.return, error); } + + resetCurrentFiber(); } - } else if (node.tag === HostText) { - if (hostSubtreeRoot === null) { - try { - var _instance3 = node.stateNode; - if (isHidden) { - hideTextInstance(_instance3); - } else { - unhideTextInstance(_instance3, node.memoizedProps); - } - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } + if (fiber === subtreeRoot) { + nextEffect = null; + 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; + + var sibling = fiber.sibling; + + if (sibling !== null) { + sibling.return = fiber.return; + nextEffect = sibling; + return; + } + + nextEffect = fiber.return; } + } - if (node === finishedWork) { - return; + function commitPassiveMountEffects( + root, + finishedWork, + committedLanes, + committedTransitions + ) { + nextEffect = finishedWork; + commitPassiveMountEffects_begin( + finishedWork, + root, + committedLanes, + committedTransitions + ); + } + + function commitPassiveMountEffects_begin( + subtreeRoot, + root, + committedLanes, + committedTransitions + ) { + while (nextEffect !== null) { + var fiber = nextEffect; + var firstChild = fiber.child; + + if ((fiber.subtreeFlags & PassiveMask) !== NoFlags && firstChild !== null) { + firstChild.return = fiber; + nextEffect = firstChild; + } else { + commitPassiveMountEffects_complete( + subtreeRoot, + root, + committedLanes, + committedTransitions + ); + } } + } + + function commitPassiveMountEffects_complete( + subtreeRoot, + root, + committedLanes, + committedTransitions + ) { + while (nextEffect !== null) { + var fiber = nextEffect; + + if ((fiber.flags & Passive) !== NoFlags) { + setCurrentFiber(fiber); + + try { + commitPassiveMountOnFiber( + root, + fiber, + committedLanes, + committedTransitions + ); + } catch (error) { + captureCommitPhaseError(fiber, fiber.return, error); + } + + resetCurrentFiber(); + } - while (node.sibling === null) { - if (node.return === null || node.return === finishedWork) { + if (fiber === subtreeRoot) { + nextEffect = null; return; } - if (hostSubtreeRoot === node) { - hostSubtreeRoot = null; + var sibling = fiber.sibling; + + if (sibling !== null) { + sibling.return = fiber.return; + nextEffect = sibling; + return; } - node = node.return; + nextEffect = fiber.return; } + } + + function commitPassiveMountOnFiber( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions + ) { + switch (finishedWork.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { + if (finishedWork.mode & ProfileMode) { + startPassiveEffectTimer(); + + try { + commitHookEffectListMount(Passive$1 | HasEffect, finishedWork); + } finally { + recordPassiveEffectDuration(finishedWork); + } + } else { + commitHookEffectListMount(Passive$1 | HasEffect, finishedWork); + } - if (hostSubtreeRoot === node) { - hostSubtreeRoot = null; + break; + } } + } - node.sibling.return = node.return; - node = node.sibling; + function commitPassiveUnmountEffects(firstChild) { + nextEffect = firstChild; + commitPassiveUnmountEffects_begin(); } - } -} -function commitAttachRef(finishedWork) { - var ref = finishedWork.ref; + function commitPassiveUnmountEffects_begin() { + while (nextEffect !== null) { + var fiber = nextEffect; + var child = fiber.child; - if (ref !== null) { - var instance = finishedWork.stateNode; - var instanceToUse; + if ((nextEffect.flags & ChildDeletion) !== NoFlags) { + var deletions = fiber.deletions; - switch (finishedWork.tag) { - case HostComponent: - instanceToUse = getPublicInstance(instance); - break; + if (deletions !== null) { + for (var i = 0; i < deletions.length; i++) { + var fiberToDelete = deletions[i]; + nextEffect = fiberToDelete; + commitPassiveUnmountEffectsInsideOfDeletedTree_begin( + fiberToDelete, + fiber + ); + } - default: - instanceToUse = instance; - } // Moved outside to ensure DCE works with this flag + { + // 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 = fiber.alternate; + + if (previousFiber !== null) { + var detachedChild = previousFiber.child; + + if (detachedChild !== null) { + previousFiber.child = null; + + do { + var detachedSibling = detachedChild.sibling; + detachedChild.sibling = null; + detachedChild = detachedSibling; + } while (detachedChild !== null); + } + } + } - if (typeof ref === "function") { - var retVal; + nextEffect = fiber; + } + } - if (finishedWork.mode & ProfileMode) { - try { - startLayoutEffectTimer(); - retVal = ref(instanceToUse); - } finally { - recordLayoutEffectDuration(finishedWork); + if ((fiber.subtreeFlags & PassiveMask) !== NoFlags && child !== null) { + child.return = fiber; + nextEffect = child; + } else { + commitPassiveUnmountEffects_complete(); } - } else { - retVal = ref(instanceToUse); } + } - { - if (typeof retVal === "function") { - error( - "Unexpected return value from a callback ref in %s. " + - "A callback ref should not return a function.", - getComponentNameFromFiber(finishedWork) - ); + function commitPassiveUnmountEffects_complete() { + while (nextEffect !== null) { + var fiber = nextEffect; + + if ((fiber.flags & Passive) !== NoFlags) { + setCurrentFiber(fiber); + commitPassiveUnmountOnFiber(fiber); + resetCurrentFiber(); + } + + var sibling = fiber.sibling; + + if (sibling !== null) { + sibling.return = fiber.return; + nextEffect = sibling; + return; } + + nextEffect = fiber.return; } - } else { - { - if (!ref.hasOwnProperty("current")) { - error( - "Unexpected ref object provided for %s. " + - "Use either a ref-setter function or React.createRef().", - getComponentNameFromFiber(finishedWork) - ); + } + + function commitPassiveUnmountOnFiber(finishedWork) { + switch (finishedWork.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { + if (finishedWork.mode & ProfileMode) { + startPassiveEffectTimer(); + commitHookEffectListUnmount( + Passive$1 | HasEffect, + finishedWork, + finishedWork.return + ); + recordPassiveEffectDuration(finishedWork); + } else { + commitHookEffectListUnmount( + Passive$1 | HasEffect, + finishedWork, + finishedWork.return + ); + } + + break; } } + } + + 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 - ref.current = instanceToUse; + setCurrentFiber(fiber); + commitPassiveUnmountInsideDeletedTreeOnFiber(fiber, nearestMountedAncestor); + resetCurrentFiber(); + var child = fiber.child; // TODO: Only traverse subtree if it has a PassiveStatic flag. (But, if we + // do this, still need to handle `deletedTreeCleanUpLevel` correctly.) + + if (child !== null) { + child.return = fiber; + nextEffect = child; + } else { + commitPassiveUnmountEffectsInsideOfDeletedTree_complete( + deletedSubtreeRoot + ); + } + } } - } -} -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 commitPassiveUnmountEffectsInsideOfDeletedTree_complete( + deletedSubtreeRoot + ) { + while (nextEffect !== null) { + var fiber = nextEffect; + var sibling = fiber.sibling; + var returnFiber = fiber.return; -function detachFiberAfterEffects(fiber) { - var alternate = fiber.alternate; - - if (alternate !== null) { - fiber.alternate = null; - detachFiberAfterEffects(alternate); - } // Note: Defensively using negation instead of < in case - // `deletedTreeCleanUpLevel` is undefined. - - { - // 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 - // tree, which has its own pointers to children, parents, and siblings. - // The other host nodes also point back to fibers, so we should detach that - // one, too. - - if (fiber.tag === HostComponent) { - var hostInstance = fiber.stateNode; - } - - fiber.stateNode = null; // I'm intentionally not clearing the `return` field in this level. We - // already disconnect the `return` pointer at the root of the deleted - // subtree (in `detachFiberMutation`). Besides, `return` by itself is not - // cyclical — it's only cyclical when combined with `child`, `sibling`, and - // `alternate`. But we'll clear it in the next level anyway, just in case. + { + // 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); - { - fiber._debugOwner = null; + if (fiber === deletedSubtreeRoot) { + nextEffect = null; + return; + } + } + + if (sibling !== null) { + sibling.return = returnFiber; + nextEffect = sibling; + return; + } + + nextEffect = returnFiber; + } } - { - // 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 - // - // The purpose of this branch is to be super aggressive so we can measure - // if there's any difference in memory impact. If there is, that could - // indicate a React leak we don't know about. - fiber.return = null; - fiber.dependencies = null; - fiber.memoizedProps = null; - fiber.memoizedState = null; - fiber.pendingProps = null; - fiber.stateNode = null; // TODO: Move to `commitPassiveUnmountInsideDeletedTreeOnFiber` instead. + function commitPassiveUnmountInsideDeletedTreeOnFiber( + current, + nearestMountedAncestor + ) { + switch (current.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { + if (current.mode & ProfileMode) { + startPassiveEffectTimer(); + commitHookEffectListUnmount(Passive$1, current, nearestMountedAncestor); + recordPassiveEffectDuration(current); + } else { + commitHookEffectListUnmount(Passive$1, current, nearestMountedAncestor); + } + + break; + } + } + } // TODO: Reuse reappearLayoutEffects traversal here? + + var COMPONENT_TYPE = 0; + var HAS_PSEUDO_CLASS_TYPE = 1; + var ROLE_TYPE = 2; + var TEST_NAME_TYPE = 3; + var TEXT_TYPE = 4; - fiber.updateQueue = null; + if (typeof Symbol === "function" && Symbol.for) { + var symbolFor = Symbol.for; + COMPONENT_TYPE = symbolFor("selector.component"); + HAS_PSEUDO_CLASS_TYPE = symbolFor("selector.has_pseudo_class"); + ROLE_TYPE = symbolFor("selector.role"); + TEST_NAME_TYPE = symbolFor("selector.test_id"); + TEXT_TYPE = symbolFor("selector.text"); } - } -} -function getHostParentFiber(fiber) { - var parent = fiber.return; + var ReactCurrentActQueue = 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. + var isReactActEnvironmentGlobal = // $FlowExpectedError – Flow doesn't know about IS_REACT_ACT_ENVIRONMENT global + typeof IS_REACT_ACT_ENVIRONMENT !== "undefined" + ? IS_REACT_ACT_ENVIRONMENT + : undefined; // $FlowExpectedError - Flow doesn't know about jest - while (parent !== null) { - if (isHostParent(parent)) { - return parent; + var jestIsDefined = typeof jest !== "undefined"; + return jestIsDefined && isReactActEnvironmentGlobal !== false; + } } + function isConcurrentActEnvironment() { + { + var isReactActEnvironmentGlobal = // $FlowExpectedError – Flow doesn't know about IS_REACT_ACT_ENVIRONMENT global + typeof IS_REACT_ACT_ENVIRONMENT !== "undefined" + ? IS_REACT_ACT_ENVIRONMENT + : undefined; - parent = parent.return; - } + if (!isReactActEnvironmentGlobal && ReactCurrentActQueue.current !== null) { + // TODO: Include link to relevant documentation page. + error( + "The current testing environment is not configured to support " + + "act(...)" + ); + } - throw new Error( - "Expected to find a host parent. This error is likely caused by a bug " + - "in React. Please file an issue." - ); -} + return isReactActEnvironmentGlobal; + } + } + + var ceil = Math.ceil; + var ReactCurrentDispatcher$2 = ReactSharedInternals.ReactCurrentDispatcher, + ReactCurrentOwner$2 = ReactSharedInternals.ReactCurrentOwner, + ReactCurrentBatchConfig$2 = ReactSharedInternals.ReactCurrentBatchConfig, + ReactCurrentActQueue$1 = 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; // Stack that allows components to change the render lanes for its subtree + // This is a superset of the lanes we started working on at the root. The only + // case where it's different from `workInProgressRootRenderLanes` is when we + // enter a subtree that is hidden and needs to be unhidden: Suspense and + // Offscreen component. + // + // Most things in the work loop should deal with workInProgressRootRenderLanes. + // Most things in begin/complete phases should deal with subtreeRenderLanes. -function isHostParent(fiber) { - return ( - fiber.tag === HostComponent || - fiber.tag === HostRoot || - fiber.tag === HostPortal - ); -} + var subtreeRenderLanes = NoLanes; + var subtreeRenderLanesCursor = createCursor(NoLanes); // Whether to root completed, errored, suspended, etc. -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; - } + var workInProgressRootExitStatus = RootInProgress; // A fatal error, if one is thrown - node = node.return; - } + var workInProgressRootFatalError = null; // "Included" lanes refer to lanes that were worked on during this render. It's + // slightly different than `renderLanes` because `renderLanes` can change as you + // enter and exit an Offscreen tree. This value is the combination of all render + // lanes for the entire render phase. - node.sibling.return = node.return; - node = node.sibling; + var workInProgressRootIncludedLanes = NoLanes; // The work left over by components that were visited during this render. Only + // includes unprocessed updates, not work in bailed out children. - while ( - node.tag !== HostComponent && - node.tag !== HostText && - 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 workInProgressRootSkippedLanes = NoLanes; // Lanes that were updated (in an interleaved event) during this render. - if (!(node.flags & Placement)) { - // Found it! - return node.stateNode; - } - } -} + var workInProgressRootInterleavedUpdatedLanes = NoLanes; // Lanes that were updated during the render phase (*not* an interleaved event). -function commitPlacement(finishedWork) { - var parentFiber = getHostParentFiber(finishedWork); // Note: these two variables *must* always be updated together. + var workInProgressRootPingedLanes = NoLanes; // Errors that are thrown during the render phase. - switch (parentFiber.tag) { - case HostComponent: { - var parent = parentFiber.stateNode; + var workInProgressRootConcurrentErrors = null; // These are errors that we recovered from without surfacing them to the UI. + // We will log them once the tree commits. - if (parentFiber.flags & ContentReset) { - parentFiber.flags &= ~ContentReset; - } + var workInProgressRootRecoverableErrors = null; // The most recent time we committed a fallback. This lets us ensure a train + // model where we don't commit new loading states in too quick succession. - 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. + var globalMostRecentFallbackTime = 0; + var FALLBACK_THROTTLE_MS = 500; // The absolute time for when we should start giving up on rendering + // more and prefer CPU suspense heuristics instead. - insertOrAppendPlacementNode(finishedWork, before, parent); - 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. - case HostRoot: - case HostPortal: { - var _parent = parentFiber.stateNode.containerInfo; + var RENDER_TIMEOUT_MS = 500; + var workInProgressTransitions = null; - var _before = getHostSibling(finishedWork); + function resetRenderTimer() { + workInProgressRootRenderTargetTime = now() + RENDER_TIMEOUT_MS; + } - insertOrAppendPlacementNodeIntoContainer(finishedWork, _before, _parent); - break; + function getRenderTargetTime() { + return workInProgressRootRenderTargetTime; } - // eslint-disable-next-line-no-fallthrough + var hasUncaughtError = false; + var firstUncaughtError = null; + var legacyErrorBoundariesThatAlreadyFailed = null; // Only used when enableProfilerNestedUpdateScheduledHook is true; + var rootDoesHavePassiveEffects = false; + var rootWithPendingPassiveEffects = null; + var pendingPassiveEffectsLanes = NoLanes; + var pendingPassiveProfilerEffects = []; + var pendingPassiveTransitions = null; // Use these to prevent an infinite loop of nested updates - default: - throw new Error( - "Invalid host parent fiber. This error is likely caused by a bug " + - "in React. Please file an issue." - ); - } -} + 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; // If two updates are scheduled within the same event, we should treat their + // event times as simultaneous, even if the actual clock time has advanced + // between the first and second call. -function insertOrAppendPlacementNodeIntoContainer(node, before, parent) { - var tag = node.tag; - var isHost = tag === HostComponent || tag === HostText; + var currentEventTime = NoTimestamp; + var currentEventTransitionLane = NoLanes; + var isRunningInsertionEffect = false; + function getWorkInProgressRoot() { + return workInProgressRoot; + } + function requestEventTime() { + if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { + // We're inside React, so it's fine to read the actual time. + return now(); + } // We're not inside React, so we may be in the middle of a browser event. - if (isHost) { - var stateNode = node.stateNode; + if (currentEventTime !== NoTimestamp) { + // Use the same start time for all updates until we enter React again. + return currentEventTime; + } // This is the first update since React yielded. Compute a new start time. - if (before) { - insertInContainerBefore(parent); - } else { - appendChildToContainer(parent, stateNode); + currentEventTime = now(); + return currentEventTime; } - } else if (tag === HostPortal); - else { - var child = node.child; + function requestUpdateLane(fiber) { + // Special cases + var mode = fiber.mode; - if (child !== null) { - insertOrAppendPlacementNodeIntoContainer(child, before, parent); - var sibling = child.sibling; + 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$2.transition !== null) { + var transition = ReactCurrentBatchConfig$2.transition; + + if (!transition._updatedFibers) { + transition._updatedFibers = new Set(); + } - while (sibling !== null) { - insertOrAppendPlacementNodeIntoContainer(sibling, before, parent); - sibling = sibling.sibling; - } - } - } -} + transition._updatedFibers.add(fiber); + } // 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. -function insertOrAppendPlacementNode(node, before, parent) { - var tag = node.tag; - var isHost = tag === HostComponent || tag === HostText; - - if (isHost) { - var stateNode = node.stateNode; - - if (before) { - insertBefore(parent, stateNode, before); - } else { - appendChild(parent, stateNode); - } - } else if (tag === HostPortal); - 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 HostComponent: { - hostParent = parent.stateNode; - hostParentIsContainer = false; - break findParent; + if (currentEventTransitionLane === NoLane) { + // All transitions within the same event are assigned the same lane. + currentEventTransitionLane = claimNextTransitionLane(); } - case HostRoot: { - hostParent = parent.stateNode.containerInfo; - hostParentIsContainer = true; - break findParent; - } + return currentEventTransitionLane; + } // 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 HostPortal: { - hostParent = parent.stateNode.containerInfo; - hostParentIsContainer = true; - break findParent; - } - } + var updateLane = getCurrentUpdatePriority(); - parent = parent.return; - } + 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. - 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 eventLane = getCurrentEventPriority(); + return eventLane; } - commitDeletionEffectsOnFiber(root, returnFiber, deletedFiber); - hostParent = null; - hostParentIsContainer = false; - } - - detachFiberMutation(deletedFiber); -} + 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 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 ((mode & ConcurrentMode) === NoMode) { + return SyncLane; + } -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. - - switch (deletedFiber.tag) { - case HostComponent: { - { - safelyDetachRef(deletedFiber, nearestMountedAncestor); - } // Intentional fallthrough to next branch + return claimNextRetryLane(); } - // eslint-disable-next-line-no-fallthrough - 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. + function scheduleUpdateOnFiber(root, fiber, lane, eventTime) { + updatedComponentForProfiler = { + name: getComponentNameFromFiber(fiber), + key: fiber.key, + }; + checkForNestedUpdates(); + { - 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 (isRunningInsertionEffect) { + error("useInsertionEffect must not schedule updates."); } } - return; - } + { + if (isFlushingPassiveEffects) { + didScheduleUpdateDuringPassiveEffects = true; + } + } // Mark that the root has a pending update. - case DehydratedFragment: { - // Delete the dehydrated suspense boundary and all of its content. + markRootUpdated(root, lane, eventTime); - { - if (hostParent !== null) { - if (hostParentIsContainer) { - clearSuspenseBoundaryFromContainer( - hostParent, - deletedFiber.stateNode + 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); + } + } + + warnIfUpdatesNotWrappedWithActDEV(fiber); + + 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. Unless the + // `deferRenderPhaseUpdateToNextBatch` flag is off and this is a render + // phase update. In that case, we don't treat render phase updates as if + // they were interleaved, for backwards compat reasons. + if ((executionContext & RenderContext) === NoContext) { + workInProgressRootInterleavedUpdatedLanes = mergeLanes( + workInProgressRootInterleavedUpdatedLanes, + lane ); - } else { - clearSuspenseBoundary(hostParent, deletedFiber.stateNode); + } + + 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$1(root, workInProgressRootRenderLanes); } } - } - return; - } + ensureRootIsScheduled(root, eventTime); - case HostPortal: { - { - // When we go into a portal, it becomes the parent to remove from. - var _prevHostParent = hostParent; - var _prevHostParentIsContainer = hostParentIsContainer; - hostParent = deletedFiber.stateNode.containerInfo; - hostParentIsContainer = true; - recursivelyTraverseDeletionEffects( - finishedRoot, - nearestMountedAncestor, - deletedFiber - ); - hostParent = _prevHostParent; - hostParentIsContainer = _prevHostParentIsContainer; + if ( + lane === SyncLane && + executionContext === NoContext && + (fiber.mode & ConcurrentMode) === NoMode && // Treat `act` as if it's inside `batchedUpdates`, even in legacy mode. + !ReactCurrentActQueue$1.isBatchingLegacy + ) { + // 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(); + flushSyncCallbacksOnlyInLegacyMode(); + } } - - return; } + 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 ( + // TODO: Remove outdated deferRenderPhaseUpdateToNextBatch experiment. We + // decided not to enable it. + (executionContext & RenderContext) !== NoContext + ); + } // Use this function to schedule a task for a root. There's only one task per + // root; if a task was already scheduled, we'll check to make sure the priority + // of the existing task is the same as the priority of the next level that the + // root has work on. This function is called on every update, and right before + // exiting a task. - case FunctionComponent: - case ForwardRef: - case MemoComponent: - case SimpleMemoComponent: { - { - var updateQueue = deletedFiber.updateQueue; + function ensureRootIsScheduled(root, currentTime) { + var existingCallbackNode = root.callbackNode; // Check if any lanes are being starved by other work. If so, mark them as + // expired so we know to work on those next. - if (updateQueue !== null) { - var lastEffect = updateQueue.lastEffect; + markStarvedLanesAsExpired(root, currentTime); // Determine the next lanes to work on, and their priority. - if (lastEffect !== null) { - var firstEffect = lastEffect.next; - var effect = firstEffect; + var nextLanes = getNextLanes( + root, + root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes + ); - do { - var _effect = effect, - destroy = _effect.destroy, - tag = _effect.tag; - - if (destroy !== undefined) { - if ((tag & Insertion) !== NoFlags$1) { - safelyCallDestroy( - deletedFiber, - nearestMountedAncestor, - destroy - ); - } else if ((tag & Layout) !== NoFlags$1) { - if (deletedFiber.mode & ProfileMode) { - startLayoutEffectTimer(); - safelyCallDestroy( - deletedFiber, - nearestMountedAncestor, - destroy - ); - recordLayoutEffectDuration(deletedFiber); - } else { - safelyCallDestroy( - deletedFiber, - nearestMountedAncestor, - destroy - ); - } - } - } + if (nextLanes === NoLanes) { + // Special case: There's nothing to work on. + if (existingCallbackNode !== null) { + cancelCallback$1(existingCallbackNode); + } + + root.callbackNode = null; + root.callbackPriority = NoLane; + return; + } // We use the highest priority lane to represent the priority of the callback. + + var newCallbackPriority = getHighestPriorityLane(nextLanes); // Check if there's an existing task. We may be able to reuse it. - effect = effect.next; - } while (effect !== firstEffect); + var existingCallbackPriority = root.callbackPriority; + + if ( + existingCallbackPriority === newCallbackPriority && // Special case related to `act`. If the currently scheduled task is a + // Scheduler task, rather than an `act` task, cancel it and re-scheduled + // on the `act` queue. + !( + ReactCurrentActQueue$1.current !== null && + existingCallbackNode !== fakeActCallbackNode + ) + ) { + { + // If we're going to re-use an existing task, it needs to exist. + // Assume that discrete update microtasks are non-cancellable and null. + // TODO: Temporary until we confirm this warning is not fired. + if ( + existingCallbackNode == null && + existingCallbackPriority !== SyncLane + ) { + error( + "Expected scheduled callback to exist. This error is likely caused by a bug in React. Please file an issue." + ); } - } + } // The priority hasn't changed. We can reuse the existing task. Exit. + + return; } - recursivelyTraverseDeletionEffects( - finishedRoot, - nearestMountedAncestor, - deletedFiber - ); - return; - } + if (existingCallbackNode != null) { + // Cancel the existing callback. We'll schedule a new one below. + cancelCallback$1(existingCallbackNode); + } // Schedule a new callback. - case ClassComponent: { - { - safelyDetachRef(deletedFiber, nearestMountedAncestor); - var instance = deletedFiber.stateNode; + var newCallbackNode; - if (typeof instance.componentWillUnmount === "function") { - safelyCallComponentWillUnmount( - deletedFiber, - nearestMountedAncestor, - instance - ); + if (newCallbackPriority === SyncLane) { + // Special case: Sync React callbacks are scheduled on a special + // internal queue + if (root.tag === LegacyRoot) { + if (ReactCurrentActQueue$1.isBatchingLegacy !== null) { + ReactCurrentActQueue$1.didScheduleLegacyUpdate = true; + } + + scheduleLegacySyncCallback(performSyncWorkOnRoot.bind(null, root)); + } else { + scheduleSyncCallback(performSyncWorkOnRoot.bind(null, root)); } - } - recursivelyTraverseDeletionEffects( - finishedRoot, - nearestMountedAncestor, - deletedFiber - ); - return; - } + { + // Flush the queue in an Immediate task. + scheduleCallback$1(ImmediatePriority, flushSyncCallbacks); + } - case ScopeComponent: { - recursivelyTraverseDeletionEffects( - finishedRoot, - nearestMountedAncestor, - deletedFiber - ); - return; - } + newCallbackNode = null; + } else { + var schedulerPriorityLevel; - case OffscreenComponent: { - { - recursivelyTraverseDeletionEffects( - finishedRoot, - nearestMountedAncestor, - deletedFiber - ); - } + switch (lanesToEventPriority(nextLanes)) { + case DiscreteEventPriority: + schedulerPriorityLevel = ImmediatePriority; + break; - break; - } + case ContinuousEventPriority: + schedulerPriorityLevel = UserBlockingPriority; + break; - default: { - recursivelyTraverseDeletionEffects( - finishedRoot, - nearestMountedAncestor, - deletedFiber - ); - return; - } - } -} + case DefaultEventPriority: + schedulerPriorityLevel = NormalPriority; + break; -function commitSuspenseCallback(finishedWork) { - // TODO: Move this to passive phase - var newState = finishedWork.memoizedState; -} + case IdleEventPriority: + schedulerPriorityLevel = IdlePriority; + break; -function attachSuspenseRetryListeners(finishedWork) { - // 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 wakeables = finishedWork.updateQueue; + default: + schedulerPriorityLevel = NormalPriority; + break; + } - if (wakeables !== null) { - finishedWork.updateQueue = null; - var retryCache = finishedWork.stateNode; + newCallbackNode = scheduleCallback$1( + schedulerPriorityLevel, + performConcurrentWorkOnRoot.bind(null, root) + ); + } - if (retryCache === null) { - retryCache = finishedWork.stateNode = new PossiblyWeakSet(); - } + root.callbackPriority = newCallbackPriority; + root.callbackNode = newCallbackNode; + } // This is the entry point for every concurrent task, i.e. anything that + // goes through Scheduler. - wakeables.forEach(function(wakeable) { - // Memoize using the boundary fiber to prevent redundant listeners. - var retry = resolveRetryWakeable.bind(null, finishedWork, wakeable); + function performConcurrentWorkOnRoot(root, didTimeout) { + { + resetNestedUpdateFlag(); + } // Since we know we're in a React event, we can clear the current + // event time. The next update will compute a new event time. + + currentEventTime = NoTimestamp; + currentEventTransitionLane = NoLanes; + + 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. - if (!retryCache.has(wakeable)) { - retryCache.add(wakeable); + var lanes = getNextLanes( + root, + root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes + ); - { - 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 (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) && + !didTimeout; + var exitStatus = shouldTimeSlice + ? renderRootConcurrent(root, lanes) + : renderRootSync(root, lanes); + + if (exitStatus !== RootInProgress) { + if (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 errorRetryLanes = getLanesToRetrySynchronouslyOnError(root); + + if (errorRetryLanes !== NoLanes) { + lanes = errorRetryLanes; + exitStatus = recoverFromConcurrentError(root, errorRetryLanes); } } - wakeable.then(retry, retry); - } - }); - } -} // This function detects when a Suspense boundary goes from visible to hidden. -function commitMutationEffects(root, finishedWork, committedLanes) { - inProgressLanes = committedLanes; - inProgressRoot = root; - setCurrentFiber(finishedWork); - commitMutationEffectsOnFiber(finishedWork, root); - setCurrentFiber(finishedWork); - inProgressLanes = null; - inProgressRoot = null; -} + if (exitStatus === RootFatalErrored) { + var fatalError = workInProgressRootFatalError; + prepareFreshStack(root, NoLanes); + markRootSuspended$1(root, lanes); + ensureRootIsScheduled(root, now()); + throw fatalError; + } -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 (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. + // + // This should only happen during a concurrent render, not a discrete or + // synchronous update. We should have already checked for this when we + // unwound the stack. + markRootSuspended$1(root, lanes); + } 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 renderWasConcurrent = !includesBlockingLane(root, lanes); + var finishedWork = root.current.alternate; - if (deletions !== null) { - for (var i = 0; i < deletions.length; i++) { - var childToDelete = deletions[i]; + if ( + renderWasConcurrent && + !isRenderConsistentWithExternalStores(finishedWork) + ) { + // A store was mutated in an interleaved event. Render again, + // synchronously, to block further mutations. + exitStatus = renderRootSync(root, lanes); // We need to check again if something threw - try { - commitDeletionEffects(root, parentFiber, childToDelete); - } catch (error) { - captureCommitPhaseError(childToDelete, parentFiber, error); + if (exitStatus === RootErrored) { + var _errorRetryLanes = getLanesToRetrySynchronouslyOnError(root); + + if (_errorRetryLanes !== NoLanes) { + lanes = _errorRetryLanes; + exitStatus = recoverFromConcurrentError(root, _errorRetryLanes); // We assume the tree is now consistent because we didn't yield to any + // concurrent events. + } + } + + if (exitStatus === RootFatalErrored) { + var _fatalError = workInProgressRootFatalError; + prepareFreshStack(root, NoLanes); + markRootSuspended$1(root, lanes); + ensureRootIsScheduled(root, now()); + 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, lanes); + } } - } - } - var prevDebugFiber = getCurrentFiber(); + ensureRootIsScheduled(root, now()); - if (parentFiber.subtreeFlags & MutationMask) { - var child = parentFiber.child; + 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); + } - while (child !== null) { - setCurrentFiber(child); - commitMutationEffectsOnFiber(child, root); - child = child.sibling; + return null; } - } - - 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 reconcilation, 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 recoverFromConcurrentError(root, 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; - if (finishedWork.mode & ProfileMode) { - try { - startLayoutEffectTimer(); - commitHookEffectListUnmount( - Layout | HasEffect, - finishedWork, - finishedWork.return - ); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } + if (isRootDehydrated(root)) { + // 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; - recordLayoutEffectDuration(finishedWork); - } else { - try { - commitHookEffectListUnmount( - Layout | HasEffect, - finishedWork, - finishedWork.return - ); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } + { + errorHydratingContainer(root.containerInfo); } } - return; - } + var exitStatus = renderRootSync(root, errorRetryLanes); - case ClassComponent: { - recursivelyTraverseMutationEffects(root, finishedWork); - commitReconciliationEffects(finishedWork); + if (exitStatus !== RootErrored) { + // Successfully finished rendering on retry + // 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 (flags & Ref) { - if (current !== null) { - safelyDetachRef(current, current.return); + if (errorsFromSecondAttempt !== null) { + queueRecoverableErrors(errorsFromSecondAttempt); } } - return; + return exitStatus; } - case HostComponent: { - recursivelyTraverseMutationEffects(root, finishedWork); - commitReconciliationEffects(finishedWork); - - if (flags & Ref) { - if (current !== null) { - safelyDetachRef(current, current.return); - } + function queueRecoverableErrors(errors) { + if (workInProgressRootRecoverableErrors === null) { + workInProgressRootRecoverableErrors = errors; + } else { + workInProgressRootRecoverableErrors.push.apply( + workInProgressRootRecoverableErrors, + errors + ); } + } - { - // 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); - } + function finishConcurrentRender(root, exitStatus, lanes) { + switch (exitStatus) { + case RootInProgress: + case RootFatalErrored: { + throw new Error("Root did not complete. This is a bug in React."); + } + // Flow knows about invariant, so it complains if I add a break + // statement, but eslint doesn't know about invariant, so it complains + // if I do. eslint-disable-next-line no-fallthrough + + case RootErrored: { + // We should have already attempted to retry this tree. If we reached + // this point, it errored again. Commit it. + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); + break; } - if (flags & Update) { - var _instance4 = finishedWork.stateNode; - - if (_instance4 != 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. + case RootSuspended: { + markRootSuspended$1(root, lanes); // We have an acceptable loading state. We need to figure out if we + // should immediately commit it or wait a bit. - var oldProps = current !== null ? current.memoizedProps : newProps; - var type = finishedWork.type; // TODO: Type the updateQueue to be specific to host components. + if ( + includesOnlyRetries(lanes) && // do not delay if we're inside an act() scope + !shouldForceFlushFallbacksInDEV() + ) { + // 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(); // Don't bother with a very short suspense time. - var updatePayload = finishedWork.updateQueue; - finishedWork.updateQueue = null; + if (msUntilTimeout > 10) { + var nextLanes = getNextLanes(root, NoLanes); - if (updatePayload !== null) { - try { - commitUpdate( - _instance4, - updatePayload, - type, - oldProps, - newProps, - finishedWork - ); - } catch (error) { - captureCommitPhaseError( - finishedWork, - finishedWork.return, - error - ); + if (nextLanes !== NoLanes) { + // There's additional work on this root. + break; } + + var suspendedLanes = root.suspendedLanes; + + if (!isSubsetOfLanes(suspendedLanes, lanes)) { + // We should prefer to render the fallback of at the last + // suspended level. Ping the last suspended level to try + // rendering it again. + // FIXME: What if the suspended lanes are Idle? Should not restart. + var eventTime = requestEventTime(); + markRootPinged(root, suspendedLanes); + break; + } // 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. + + root.timeoutHandle = scheduleTimeout( + commitRoot.bind( + null, + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ), + msUntilTimeout + ); + break; } - } - } - } + } // The work expired. Commit immediately. - return; - } + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); + break; + } - case HostText: { - recursivelyTraverseMutationEffects(root, finishedWork); - commitReconciliationEffects(finishedWork); + case RootSuspendedWithDelay: { + markRootSuspended$1(root, lanes); - 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." - ); + 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. + break; } - 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 (!shouldForceFlushFallbacksInDEV()) { + // This is not a transition, but we did trigger an avoided state. + // Schedule a placeholder to display after a short delay, using the Just + // Noticeable Difference. + // TODO: Is the JND optimization worth the added complexity? If this is + // the only reason we track the event time, then probably not. + // Consider removing. + var mostRecentEventTime = getMostRecentEventTime(root, lanes); + var eventTimeMs = mostRecentEventTime; + var timeElapsedMs = now() - eventTimeMs; + + var _msUntilTimeout = jnd(timeElapsedMs) - timeElapsedMs; // Don't bother with a very short suspense time. + + if (_msUntilTimeout > 10) { + // Instead of committing the fallback immediately, wait for more data + // to arrive. + root.timeoutHandle = scheduleTimeout( + commitRoot.bind( + null, + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ), + _msUntilTimeout + ); + break; + } + } // Commit the placeholder. + + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); + break; + } - var oldText = current !== null ? current.memoizedProps : newText; + case RootCompleted: { + // The work completed. Ready to commit. + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); + break; + } - try { - commitTextUpdate(textInstance, oldText, newText); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } + default: { + throw new Error("Unknown root exit status."); } } - - return; } - case HostRoot: { - recursivelyTraverseMutationEffects(root, finishedWork); - commitReconciliationEffects(finishedWork); + 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; - return; - } + while (true) { + if (node.flags & StoreConsistency) { + var updateQueue = node.updateQueue; - case HostPortal: { - recursivelyTraverseMutationEffects(root, finishedWork); - commitReconciliationEffects(finishedWork); + if (updateQueue !== null) { + var checks = updateQueue.stores; - return; - } + if (checks !== null) { + for (var i = 0; i < checks.length; i++) { + var check = checks[i]; + var getSnapshot = check.getSnapshot; + var renderedValue = check.value; - case SuspenseComponent: { - recursivelyTraverseMutationEffects(root, finishedWork); - commitReconciliationEffects(finishedWork); - var offscreenFiber = finishedWork.child; + 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; + } + } + } + } + } - if (offscreenFiber.flags & Visibility) { - var offscreenInstance = offscreenFiber.stateNode; - var newState = offscreenFiber.memoizedState; - var isHidden = newState !== null; // Track the current state on the Offscreen instance so we can - // read it during an event + var child = node.child; - offscreenInstance.isHidden = isHidden; + if (node.subtreeFlags & StoreConsistency && child !== null) { + child.return = node; + node = child; + continue; + } - if (isHidden) { - var wasHidden = - offscreenFiber.alternate !== null && - offscreenFiber.alternate.memoizedState !== null; + if (node === finishedWork) { + return true; + } - if (!wasHidden) { - // TODO: Move to passive phase - markCommitTimeOfFallback(); + while (node.sibling === null) { + if (node.return === null || node.return === finishedWork) { + return true; } - } - } - if (flags & Update) { - try { - commitSuspenseCallback(finishedWork); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); + node = node.return; } - attachSuspenseRetryListeners(finishedWork); - } + 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; + return true; } - case OffscreenComponent: { - var _wasHidden = current !== null && current.memoizedState !== null; + function markRootSuspended$1(root, suspendedLanes) { + // 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(root, suspendedLanes); + } // This is the entry point for synchronous tasks that don't go + // through Scheduler + function performSyncWorkOnRoot(root) { { - recursivelyTraverseMutationEffects(root, finishedWork); + syncNestedUpdateFlag(); } - commitReconciliationEffects(finishedWork); + if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { + throw new Error("Should not already be working."); + } - if (flags & Visibility) { - var _offscreenInstance = finishedWork.stateNode; - var _newState = finishedWork.memoizedState; + flushPassiveEffects(); + var lanes = getNextLanes(root, NoLanes); - var _isHidden = _newState !== null; + if (!includesSomeLane(lanes, SyncLane)) { + // There's no remaining sync work left. + ensureRootIsScheduled(root, now()); + return null; + } - var offscreenBoundary = finishedWork; // Track the current state on the Offscreen instance so we can - // read it during an event + var exitStatus = renderRootSync(root, lanes); - _offscreenInstance.isHidden = _isHidden; + 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 errorRetryLanes = getLanesToRetrySynchronouslyOnError(root); - { - // TODO: This needs to run whenever there's an insertion or update - // inside a hidden Offscreen tree. - hideOrUnhideAllChildren(offscreenBoundary, _isHidden); + if (errorRetryLanes !== NoLanes) { + lanes = errorRetryLanes; + exitStatus = recoverFromConcurrentError(root, errorRetryLanes); } } - return; - } - - case SuspenseListComponent: { - recursivelyTraverseMutationEffects(root, finishedWork); - commitReconciliationEffects(finishedWork); - - if (flags & Update) { - attachSuspenseRetryListeners(finishedWork); + if (exitStatus === RootFatalErrored) { + var fatalError = workInProgressRootFatalError; + prepareFreshStack(root, NoLanes); + markRootSuspended$1(root, lanes); + ensureRootIsScheduled(root, now()); + throw fatalError; } - return; - } + if (exitStatus === RootDidNotComplete) { + throw new Error("Root did not complete. This is a bug in React."); + } // We now have a consistent tree. Because this is a sync render, we + // will commit it even if something suspended. - case ScopeComponent: { - return; - } + var finishedWork = root.current.alternate; + root.finishedWork = finishedWork; + root.finishedLanes = lanes; + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); // Before exiting, make sure there's a callback scheduled for the next + // pending level. - default: { - recursivelyTraverseMutationEffects(root, finishedWork); - commitReconciliationEffects(finishedWork); - return; + ensureRootIsScheduled(root, now()); + return null; } - } -} - -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; - nextEffect = finishedWork; - commitLayoutEffects_begin(finishedWork, root, committedLanes); - inProgressLanes = null; - inProgressRoot = null; -} + function batchedUpdates$1(fn, a) { + var prevExecutionContext = executionContext; + executionContext |= BatchedContext; -function commitLayoutEffects_begin(subtreeRoot, root, committedLanes) { - // Suspense layout effects semantics don't change for legacy roots. - var isModernRoot = (subtreeRoot.mode & ConcurrentMode) !== NoMode; - - while (nextEffect !== null) { - var fiber = nextEffect; - var firstChild = fiber.child; + try { + return fn(a); + } finally { + executionContext = prevExecutionContext; // If there were legacy sync updates, flush them at the end of the outer + // most batchedUpdates-like method. - if ((fiber.subtreeFlags & LayoutMask) !== NoFlags && firstChild !== null) { - firstChild.return = fiber; - nextEffect = firstChild; - } else { - commitLayoutMountEffects_complete(subtreeRoot, root, committedLanes); + if ( + executionContext === NoContext && // Treat `act` as if it's inside `batchedUpdates`, even in legacy mode. + !ReactCurrentActQueue$1.isBatchingLegacy + ) { + resetRenderTimer(); + flushSyncCallbacksOnlyInLegacyMode(); + } + } } - } -} + // Warning, this opts-out of checking the function body. -function commitLayoutMountEffects_complete(subtreeRoot, root, committedLanes) { - while (nextEffect !== null) { - var fiber = nextEffect; + // 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(); + } - if ((fiber.flags & LayoutMask) !== NoFlags) { - var current = fiber.alternate; - setCurrentFiber(fiber); + var prevExecutionContext = executionContext; + executionContext |= BatchedContext; + var prevTransition = ReactCurrentBatchConfig$2.transition; + var previousPriority = getCurrentUpdatePriority(); try { - commitLayoutEffectOnFiber(root, current, fiber, committedLanes); - } catch (error) { - captureCommitPhaseError(fiber, fiber.return, error); - } + ReactCurrentBatchConfig$2.transition = null; + setCurrentUpdatePriority(DiscreteEventPriority); - resetCurrentFiber(); + if (fn) { + return fn(); + } else { + return undefined; + } + } finally { + setCurrentUpdatePriority(previousPriority); + ReactCurrentBatchConfig$2.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) { + flushSyncCallbacks(); + } + } } - - if (fiber === subtreeRoot) { - nextEffect = null; - return; + function pushRenderLanes(fiber, lanes) { + push(subtreeRenderLanesCursor, subtreeRenderLanes, fiber); + subtreeRenderLanes = mergeLanes(subtreeRenderLanes, lanes); + workInProgressRootIncludedLanes = mergeLanes( + workInProgressRootIncludedLanes, + lanes + ); } - - var sibling = fiber.sibling; - - if (sibling !== null) { - sibling.return = fiber.return; - nextEffect = sibling; - return; + function popRenderLanes(fiber) { + subtreeRenderLanes = subtreeRenderLanesCursor.current; + pop(subtreeRenderLanesCursor, fiber); } - nextEffect = fiber.return; - } -} - -function commitPassiveMountEffects( - root, - finishedWork, - committedLanes, - committedTransitions -) { - nextEffect = finishedWork; - commitPassiveMountEffects_begin( - finishedWork, - root, - committedLanes, - committedTransitions - ); -} + function prepareFreshStack(root, lanes) { + root.finishedWork = null; + root.finishedLanes = NoLanes; + var timeoutHandle = root.timeoutHandle; -function commitPassiveMountEffects_begin( - subtreeRoot, - root, - committedLanes, - committedTransitions -) { - while (nextEffect !== null) { - var fiber = nextEffect; - var firstChild = fiber.child; - - if ((fiber.subtreeFlags & PassiveMask) !== NoFlags && firstChild !== null) { - firstChild.return = fiber; - nextEffect = firstChild; - } else { - commitPassiveMountEffects_complete( - subtreeRoot, - root, - committedLanes, - committedTransitions - ); - } - } -} + 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 Complains noTimeout is not a TimeoutID, despite the check above -function commitPassiveMountEffects_complete( - subtreeRoot, - root, - committedLanes, - committedTransitions -) { - while (nextEffect !== null) { - var fiber = nextEffect; + cancelTimeout(timeoutHandle); + } - if ((fiber.flags & Passive) !== NoFlags) { - setCurrentFiber(fiber); + if (workInProgress !== null) { + var interruptedWork = workInProgress.return; - try { - commitPassiveMountOnFiber( - root, - fiber, - committedLanes, - committedTransitions - ); - } catch (error) { - captureCommitPhaseError(fiber, fiber.return, error); + while (interruptedWork !== null) { + var current = interruptedWork.alternate; + unwindInterruptedWork(current, interruptedWork); + interruptedWork = interruptedWork.return; + } } - resetCurrentFiber(); - } - - if (fiber === subtreeRoot) { - nextEffect = null; - return; - } + workInProgressRoot = root; + var rootWorkInProgress = createWorkInProgress(root.current, null); + workInProgress = rootWorkInProgress; + workInProgressRootRenderLanes = subtreeRenderLanes = workInProgressRootIncludedLanes = lanes; + workInProgressRootExitStatus = RootInProgress; + workInProgressRootFatalError = null; + workInProgressRootSkippedLanes = NoLanes; + workInProgressRootInterleavedUpdatedLanes = NoLanes; + workInProgressRootPingedLanes = NoLanes; + workInProgressRootConcurrentErrors = null; + workInProgressRootRecoverableErrors = null; + finishQueueingConcurrentUpdates(); - var sibling = fiber.sibling; + { + ReactStrictModeWarnings.discardPendingWarnings(); + } - if (sibling !== null) { - sibling.return = fiber.return; - nextEffect = sibling; - return; + return rootWorkInProgress; } - nextEffect = fiber.return; - } -} - -function commitPassiveMountOnFiber( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions -) { - switch (finishedWork.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - if (finishedWork.mode & ProfileMode) { - startPassiveEffectTimer(); + function handleError(root, thrownValue) { + do { + var erroredWork = workInProgress; try { - commitHookEffectListMount(Passive$1 | HasEffect, finishedWork); - } finally { - recordPassiveEffectDuration(finishedWork); - } - } else { - commitHookEffectListMount(Passive$1 | HasEffect, finishedWork); - } - - break; - } - } -} + // Reset module-level state that was set during the render phase. + resetContextDependencies(); + resetHooksAfterThrow(); + resetCurrentFiber(); // TODO: I found and added this missing line while investigating a + // separate issue. Write a regression test using string refs. + + ReactCurrentOwner$2.current = null; + + if (erroredWork === null || erroredWork.return === 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 commitPassiveUnmountEffects(firstChild) { - nextEffect = firstChild; - commitPassiveUnmountEffects_begin(); -} + if (enableProfilerTimer && 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 commitPassiveUnmountEffects_begin() { - while (nextEffect !== null) { - var fiber = nextEffect; - var child = fiber.child; + if (enableSchedulingProfiler) { + markComponentRenderStopped(); - if ((nextEffect.flags & ChildDeletion) !== NoFlags) { - var deletions = fiber.deletions; + if ( + thrownValue !== null && + typeof thrownValue === "object" && + typeof thrownValue.then === "function" + ) { + var wakeable = thrownValue; + markComponentSuspended( + erroredWork, + wakeable, + workInProgressRootRenderLanes + ); + } else { + markComponentErrored( + erroredWork, + thrownValue, + workInProgressRootRenderLanes + ); + } + } - if (deletions !== null) { - for (var i = 0; i < deletions.length; i++) { - var fiberToDelete = deletions[i]; - nextEffect = fiberToDelete; - commitPassiveUnmountEffectsInsideOfDeletedTree_begin( - fiberToDelete, - fiber + throwException( + root, + erroredWork.return, + erroredWork, + thrownValue, + workInProgressRootRenderLanes ); - } - - { - // 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 = fiber.alternate; + completeUnitOfWork(erroredWork); + } catch (yetAnotherThrownValue) { + // Something in the return path also threw. + thrownValue = yetAnotherThrownValue; + + if (workInProgress === erroredWork && erroredWork !== null) { + // If this boundary has already errored, then we had trouble processing + // the error. Bubble it to the next boundary. + erroredWork = erroredWork.return; + workInProgress = erroredWork; + } else { + erroredWork = workInProgress; + } - if (previousFiber !== null) { - var detachedChild = previousFiber.child; + continue; + } // Return to the normal work loop. - if (detachedChild !== null) { - previousFiber.child = null; + return; + } while (true); + } - do { - var detachedSibling = detachedChild.sibling; - detachedChild.sibling = null; - detachedChild = detachedSibling; - } while (detachedChild !== null); - } - } - } + function pushDispatcher() { + var prevDispatcher = ReactCurrentDispatcher$2.current; + ReactCurrentDispatcher$2.current = ContextOnlyDispatcher; - nextEffect = fiber; + 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 ((fiber.subtreeFlags & PassiveMask) !== NoFlags && child !== null) { - child.return = fiber; - nextEffect = child; - } else { - commitPassiveUnmountEffects_complete(); + function popDispatcher(prevDispatcher) { + ReactCurrentDispatcher$2.current = prevDispatcher; } - } -} - -function commitPassiveUnmountEffects_complete() { - while (nextEffect !== null) { - var fiber = nextEffect; - if ((fiber.flags & Passive) !== NoFlags) { - setCurrentFiber(fiber); - commitPassiveUnmountOnFiber(fiber); - resetCurrentFiber(); + function markCommitTimeOfFallback() { + globalMostRecentFallbackTime = now(); } - - var sibling = fiber.sibling; - - if (sibling !== null) { - sibling.return = fiber.return; - nextEffect = sibling; - return; + function markSkippedUpdateLanes(lane) { + workInProgressRootSkippedLanes = mergeLanes( + lane, + workInProgressRootSkippedLanes + ); } + function renderDidSuspend() { + if (workInProgressRootExitStatus === RootInProgress) { + workInProgressRootExitStatus = RootSuspended; + } + } + function renderDidSuspendDelayIfPossible() { + if ( + workInProgressRootExitStatus === RootInProgress || + workInProgressRootExitStatus === RootSuspended || + workInProgressRootExitStatus === RootErrored + ) { + workInProgressRootExitStatus = RootSuspendedWithDelay; + } // Check if there are updates that we skipped tree that might have unblocked + // this render. - nextEffect = fiber.return; - } -} + if ( + workInProgressRoot !== null && + (includesNonIdleWork(workInProgressRootSkippedLanes) || + includesNonIdleWork(workInProgressRootInterleavedUpdatedLanes)) + ) { + // 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. + markRootSuspended$1(workInProgressRoot, workInProgressRootRenderLanes); + } + } + function renderDidError(error) { + if (workInProgressRootExitStatus !== RootSuspendedWithDelay) { + workInProgressRootExitStatus = RootErrored; + } -function commitPassiveUnmountOnFiber(finishedWork) { - switch (finishedWork.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - if (finishedWork.mode & ProfileMode) { - startPassiveEffectTimer(); - commitHookEffectListUnmount( - Passive$1 | HasEffect, - finishedWork, - finishedWork.return - ); - recordPassiveEffectDuration(finishedWork); + if (workInProgressRootConcurrentErrors === null) { + workInProgressRootConcurrentErrors = [error]; } else { - commitHookEffectListUnmount( - Passive$1 | HasEffect, - finishedWork, - finishedWork.return - ); + workInProgressRootConcurrentErrors.push(error); } + } // Called during render to determine if anything has suspended. + // Returns false if we're not sure. - break; + function renderHasNotSuspendedYet() { + // If something errored or completed, we can't really be sure, + // so those are false. + return workInProgressRootExitStatus === RootInProgress; } - } -} -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. (But, if we - // do this, still need to handle `deletedTreeCleanUpLevel` correctly.) - - if (child !== null) { - child.return = fiber; - nextEffect = child; - } else { - commitPassiveUnmountEffectsInsideOfDeletedTree_complete( - deletedSubtreeRoot - ); - } - } -} + function renderRootSync(root, lanes) { + var prevExecutionContext = executionContext; + executionContext |= RenderContext; + var prevDispatcher = pushDispatcher(); // 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. -function commitPassiveUnmountEffectsInsideOfDeletedTree_complete( - deletedSubtreeRoot -) { - while (nextEffect !== null) { - var fiber = nextEffect; - var sibling = fiber.sibling; - var returnFiber = fiber.return; + if (workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes) { + { + if (isDevToolsPresent) { + var memoizedUpdaters = root.memoizedUpdaters; - { - // 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 (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 (fiber === deletedSubtreeRoot) { - nextEffect = null; - return; + movePendingFibersToMemoized(root, lanes); + } + } + + workInProgressTransitions = getTransitionsForLanes(); + prepareFreshStack(root, lanes); } - } - if (sibling !== null) { - sibling.return = returnFiber; - nextEffect = sibling; - return; - } + do { + try { + workLoopSync(); + break; + } catch (thrownValue) { + handleError(root, thrownValue); + } + } while (true); - nextEffect = returnFiber; - } -} + resetContextDependencies(); + executionContext = prevExecutionContext; + popDispatcher(prevDispatcher); -function commitPassiveUnmountInsideDeletedTreeOnFiber( - current, - nearestMountedAncestor -) { - switch (current.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - if (current.mode & ProfileMode) { - startPassiveEffectTimer(); - commitHookEffectListUnmount(Passive$1, current, nearestMountedAncestor); - recordPassiveEffectDuration(current); - } else { - commitHookEffectListUnmount(Passive$1, current, nearestMountedAncestor); + 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; - } - } -} // TODO: Reuse reappearLayoutEffects traversal here? - -var COMPONENT_TYPE = 0; -var HAS_PSEUDO_CLASS_TYPE = 1; -var ROLE_TYPE = 2; -var TEST_NAME_TYPE = 3; -var TEXT_TYPE = 4; + workInProgressRoot = null; + workInProgressRootRenderLanes = NoLanes; + return workInProgressRootExitStatus; + } // The work loop is an extremely hot path. Tell Closure not to inline it. -if (typeof Symbol === "function" && Symbol.for) { - var symbolFor = Symbol.for; - COMPONENT_TYPE = symbolFor("selector.component"); - HAS_PSEUDO_CLASS_TYPE = symbolFor("selector.has_pseudo_class"); - ROLE_TYPE = symbolFor("selector.role"); - TEST_NAME_TYPE = symbolFor("selector.test_id"); - TEXT_TYPE = symbolFor("selector.text"); -} + /** @noinline */ -var ReactCurrentActQueue = 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. - var isReactActEnvironmentGlobal = // $FlowExpectedError – Flow doesn't know about IS_REACT_ACT_ENVIRONMENT global - typeof IS_REACT_ACT_ENVIRONMENT !== "undefined" - ? IS_REACT_ACT_ENVIRONMENT - : undefined; // $FlowExpectedError - Flow doesn't know about jest - - var jestIsDefined = typeof jest !== "undefined"; - return jestIsDefined && isReactActEnvironmentGlobal !== false; - } -} -function isConcurrentActEnvironment() { - { - var isReactActEnvironmentGlobal = // $FlowExpectedError – Flow doesn't know about IS_REACT_ACT_ENVIRONMENT global - typeof IS_REACT_ACT_ENVIRONMENT !== "undefined" - ? IS_REACT_ACT_ENVIRONMENT - : undefined; - - if (!isReactActEnvironmentGlobal && ReactCurrentActQueue.current !== null) { - // TODO: Include link to relevant documentation page. - error( - "The current testing environment is not configured to support " + - "act(...)" - ); + function workLoopSync() { + // Already timed out, so perform work without checking if we need to yield. + while (workInProgress !== null) { + performUnitOfWork(workInProgress); + } } - return isReactActEnvironmentGlobal; - } -} + function renderRootConcurrent(root, lanes) { + var prevExecutionContext = executionContext; + executionContext |= RenderContext; + var prevDispatcher = pushDispatcher(); // 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. -var ceil = Math.ceil; -var ReactCurrentDispatcher$2 = ReactSharedInternals.ReactCurrentDispatcher, - ReactCurrentOwner$2 = ReactSharedInternals.ReactCurrentOwner, - ReactCurrentBatchConfig$2 = ReactSharedInternals.ReactCurrentBatchConfig, - ReactCurrentActQueue$1 = 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; // Stack that allows components to change the render lanes for its subtree -// This is a superset of the lanes we started working on at the root. The only -// case where it's different from `workInProgressRootRenderLanes` is when we -// enter a subtree that is hidden and needs to be unhidden: Suspense and -// Offscreen component. -// -// Most things in the work loop should deal with workInProgressRootRenderLanes. -// Most things in begin/complete phases should deal with subtreeRenderLanes. - -var subtreeRenderLanes = NoLanes; -var subtreeRenderLanesCursor = createCursor(NoLanes); // Whether to root completed, errored, suspended, etc. - -var workInProgressRootExitStatus = RootInProgress; // A fatal error, if one is thrown - -var workInProgressRootFatalError = null; // "Included" lanes refer to lanes that were worked on during this render. It's -// slightly different than `renderLanes` because `renderLanes` can change as you -// enter and exit an Offscreen tree. This value is the combination of all render -// lanes for the entire render phase. - -var workInProgressRootIncludedLanes = NoLanes; // 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; // 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 committed a fallback. This lets us ensure a train -// model where we don't commit new loading states in too quick succession. - -var globalMostRecentFallbackTime = 0; -var FALLBACK_THROTTLE_MS = 500; // 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 resetRenderTimer() { - workInProgressRootRenderTargetTime = now() + RENDER_TIMEOUT_MS; -} + if (workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes) { + { + if (isDevToolsPresent) { + var memoizedUpdaters = root.memoizedUpdaters; -function getRenderTargetTime() { - return workInProgressRootRenderTargetTime; -} -var hasUncaughtError = false; -var firstUncaughtError = null; -var legacyErrorBoundariesThatAlreadyFailed = null; // Only used when enableProfilerNestedUpdateScheduledHook is true; -var rootDoesHavePassiveEffects = false; -var rootWithPendingPassiveEffects = null; -var pendingPassiveEffectsLanes = NoLanes; -var pendingPassiveProfilerEffects = []; -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; // If two updates are scheduled within the same event, we should treat their -// event times as simultaneous, even if the actual clock time has advanced -// between the first and second call. - -var currentEventTime = NoTimestamp; -var currentEventTransitionLane = NoLanes; -var isRunningInsertionEffect = false; -function getWorkInProgressRoot() { - return workInProgressRoot; -} -function requestEventTime() { - if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { - // We're inside React, so it's fine to read the actual time. - return now(); - } // We're not inside React, so we may be in the middle of a browser event. - - if (currentEventTime !== NoTimestamp) { - // Use the same start time for all updates until we enter React again. - return currentEventTime; - } // This is the first update since React yielded. Compute a new start time. - - currentEventTime = now(); - return currentEventTime; -} -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$2.transition !== null) { - var transition = ReactCurrentBatchConfig$2.transition; - - if (!transition._updatedFibers) { - transition._updatedFibers = new Set(); - } - - transition._updatedFibers.add(fiber); - } // 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; - } // 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 (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. -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; + movePendingFibersToMemoized(root, lanes); + } + } - if ((mode & ConcurrentMode) === NoMode) { - return SyncLane; - } + workInProgressTransitions = getTransitionsForLanes(); + resetRenderTimer(); + prepareFreshStack(root, lanes); + } - return claimNextRetryLane(); -} + do { + try { + workLoopConcurrent(); + break; + } catch (thrownValue) { + handleError(root, thrownValue); + } + } while (true); -function scheduleUpdateOnFiber(root, fiber, lane, eventTime) { - checkForNestedUpdates(); + resetContextDependencies(); + popDispatcher(prevDispatcher); + executionContext = prevExecutionContext; - { - if (isRunningInsertionEffect) { - error("useInsertionEffect must not schedule updates."); - } - } + if (workInProgress !== null) { + return RootInProgress; + } else { + workInProgressRoot = null; + workInProgressRootRenderLanes = NoLanes; // Return the final exit status. - { - if (isFlushingPassiveEffects) { - didScheduleUpdateDuringPassiveEffects = true; + return workInProgressRootExitStatus; + } } - } // Mark that the root has a pending update. + /** @noinline */ - markRootUpdated(root, lane, eventTime); - - 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()) { + performUnitOfWork(workInProgress); } } - warnIfUpdatesNotWrappedWithActDEV(fiber); + 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 (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. Unless the - // `deferRenderPhaseUpdateToNextBatch` flag is off and this is a render - // phase update. In that case, we don't treat render phase updates as if - // they were interleaved, for backwards compat reasons. - if ((executionContext & RenderContext) === NoContext) { - workInProgressRootInterleavedUpdatedLanes = mergeLanes( - workInProgressRootInterleavedUpdatedLanes, - lane - ); + if ((unitOfWork.mode & ProfileMode) !== NoMode) { + startProfilerTimer(unitOfWork); + next = beginWork$1(current, unitOfWork, subtreeRenderLanes); + stopProfilerTimerIfRunningAndRecordDelta(unitOfWork, true); + } else { + next = beginWork$1(current, unitOfWork, subtreeRenderLanes); } - 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$1(root, workInProgressRootRenderLanes); + 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$2.current = null; } - ensureRootIsScheduled(root, eventTime); + 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 ( - lane === SyncLane && - executionContext === NoContext && - (fiber.mode & ConcurrentMode) === NoMode && // Treat `act` as if it's inside `batchedUpdates`, even in legacy mode. - !ReactCurrentActQueue$1.isBatchingLegacy - ) { - // 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(); - flushSyncCallbacksOnlyInLegacyMode(); - } - } -} -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 ( - // TODO: Remove outdated deferRenderPhaseUpdateToNextBatch experiment. We - // decided not to enable it. - (executionContext & RenderContext) !== NoContext - ); -} // Use this function to schedule a task for a root. There's only one task per -// root; if a task was already scheduled, we'll check to make sure the priority -// of the existing task is the same as the priority of the next level that the -// root has work on. This function is called on every update, and right before -// exiting a task. - -function ensureRootIsScheduled(root, currentTime) { - var existingCallbackNode = root.callbackNode; // 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 nextLanes = getNextLanes( - root, - root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes - ); - - if (nextLanes === NoLanes) { - // Special case: There's nothing to work on. - if (existingCallbackNode !== null) { - cancelCallback$1(existingCallbackNode); - } - - root.callbackNode = null; - root.callbackPriority = NoLane; - return; - } // We use the highest priority lane to represent the priority of the callback. - - var newCallbackPriority = getHighestPriorityLane(nextLanes); // Check if there's an existing task. We may be able to reuse it. - - var existingCallbackPriority = root.callbackPriority; - - if ( - existingCallbackPriority === newCallbackPriority && // Special case related to `act`. If the currently scheduled task is a - // Scheduler task, rather than an `act` task, cancel it and re-scheduled - // on the `act` queue. - !( - ReactCurrentActQueue$1.current !== null && - existingCallbackNode !== fakeActCallbackNode - ) - ) { - { - // If we're going to re-use an existing task, it needs to exist. - // Assume that discrete update microtasks are non-cancellable and null. - // TODO: Temporary until we confirm this warning is not fired. - if ( - existingCallbackNode == null && - existingCallbackPriority !== SyncLane - ) { - error( - "Expected scheduled callback to exist. This error is likely caused by a bug in React. Please file an issue." - ); - } - } // The priority hasn't changed. We can reuse the existing task. Exit. + 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 = completedWork.alternate; + var returnFiber = completedWork.return; // Check if the work completed or if something threw. + + if ((completedWork.flags & Incomplete) === NoFlags) { + setCurrentFiber(completedWork); + var next = void 0; + + if ((completedWork.mode & ProfileMode) === NoMode) { + next = completeWork(current, completedWork, subtreeRenderLanes); + } else { + startProfilerTimer(completedWork); + next = completeWork(current, completedWork, subtreeRenderLanes); // 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; + } + } else { + // 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, completedWork); // Because this fiber did not complete, don't reset its lanes. + + if (_next !== null) { + // If completing this work spawned new work, do that next. We'll come + // back here again. + // Since we're restarting, remove anything that is not a host effect + // from the effect tag. + _next.flags &= HostEffectMask; + workInProgress = _next; + return; + } + + if ((completedWork.mode & ProfileMode) !== NoMode) { + // Record the render duration for the fiber that errored. + stopProfilerTimerIfRunningAndRecordDelta(completedWork, false); // Include the time spent working on failed children before continuing. + + var actualDuration = completedWork.actualDuration; + var child = completedWork.child; + + while (child !== null) { + actualDuration += child.actualDuration; + child = child.sibling; + } + + completedWork.actualDuration = actualDuration; + } + + if (returnFiber !== null) { + // Mark the parent fiber as incomplete and clear its subtree flags. + returnFiber.flags |= Incomplete; + returnFiber.subtreeFlags = NoFlags; + returnFiber.deletions = null; + } else { + // We've unwound all the way to the root. + workInProgressRootExitStatus = RootDidNotComplete; + workInProgress = null; + return; + } + } - return; - } + var siblingFiber = completedWork.sibling; - if (existingCallbackNode != null) { - // Cancel the existing callback. We'll schedule a new one below. - cancelCallback$1(existingCallbackNode); - } // Schedule a new callback. + if (siblingFiber !== null) { + // If there is more work to do in this returnFiber, do that next. + workInProgress = siblingFiber; + return; + } // Otherwise, return to the parent - var newCallbackNode; + completedWork = returnFiber; // Update the next thing we're working on in case something throws. - if (newCallbackPriority === SyncLane) { - // Special case: Sync React callbacks are scheduled on a special - // internal queue - if (root.tag === LegacyRoot) { - if (ReactCurrentActQueue$1.isBatchingLegacy !== null) { - ReactCurrentActQueue$1.didScheduleLegacyUpdate = true; - } + workInProgress = completedWork; + } while (completedWork !== null); // We've reached the root. - scheduleLegacySyncCallback(performSyncWorkOnRoot.bind(null, root)); - } else { - scheduleSyncCallback(performSyncWorkOnRoot.bind(null, root)); + if (workInProgressRootExitStatus === RootInProgress) { + workInProgressRootExitStatus = RootCompleted; + } } - { - // Flush the queue in an Immediate task. - scheduleCallback$1(ImmediatePriority, flushSyncCallbacks); + function commitRoot(root, recoverableErrors, transitions) { + // 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$2.transition; + defrost.writeInLogFiles(Date.now() + "", { list: updatedComponents, change: updatedComponentForProfiler }) + updatedComponents = [] + updatedComponentForProfiler = null + try { + ReactCurrentBatchConfig$2.transition = null; + setCurrentUpdatePriority(DiscreteEventPriority); + commitRootImpl( + root, + recoverableErrors, + transitions, + previousUpdateLanePriority + ); + } finally { + ReactCurrentBatchConfig$2.transition = prevTransition; + setCurrentUpdatePriority(previousUpdateLanePriority); + } + + return null; } - newCallbackNode = null; - } else { - var schedulerPriorityLevel; + function commitRootImpl( + root, + recoverableErrors, + transitions, + renderPriorityLevel + ) { + 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); - switch (lanesToEventPriority(nextLanes)) { - case DiscreteEventPriority: - schedulerPriorityLevel = ImmediatePriority; - break; + flushRenderPhaseStrictModeWarningsInDEV(); - case ContinuousEventPriority: - schedulerPriorityLevel = UserBlockingPriority; - break; + if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { + throw new Error("Should not already be working."); + } - case DefaultEventPriority: - schedulerPriorityLevel = NormalPriority; - break; + var finishedWork = root.finishedWork; + var lanes = root.finishedLanes; - case IdleEventPriority: - schedulerPriorityLevel = IdlePriority; - break; + if (finishedWork === null) { + return null; + } else { + { + if (lanes === NoLanes) { + error( + "root.finishedLanes should not be empty during a commit. This is a " + + "bug in React." + ); + } + } + } - default: - schedulerPriorityLevel = NormalPriority; - break; - } + root.finishedWork = null; + root.finishedLanes = NoLanes; - newCallbackNode = scheduleCallback$1( - schedulerPriorityLevel, - performConcurrentWorkOnRoot.bind(null, root) - ); - } - - root.callbackPriority = newCallbackPriority; - root.callbackNode = newCallbackNode; -} // This is the entry point for every concurrent task, i.e. anything that -// goes through Scheduler. - -function performConcurrentWorkOnRoot(root, didTimeout) { - { - resetNestedUpdateFlag(); - } // Since we know we're in a React event, we can clear the current - // event time. The next update will compute a new event time. - - currentEventTime = NoTimestamp; - currentEventTransitionLane = NoLanes; - - 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. - - 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) && - !didTimeout; - var exitStatus = shouldTimeSlice - ? renderRootConcurrent(root, lanes) - : renderRootSync(root, lanes); - - if (exitStatus !== RootInProgress) { - if (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 errorRetryLanes = getLanesToRetrySynchronouslyOnError(root); - - if (errorRetryLanes !== NoLanes) { - lanes = errorRetryLanes; - exitStatus = recoverFromConcurrentError(root, errorRetryLanes); - } - } - - if (exitStatus === RootFatalErrored) { - var fatalError = workInProgressRootFatalError; - prepareFreshStack(root, NoLanes); - markRootSuspended$1(root, lanes); - ensureRootIsScheduled(root, now()); - throw fatalError; - } + 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. - 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. - // - // This should only happen during a concurrent render, not a discrete or - // synchronous update. We should have already checked for this when we - // unwound the stack. - markRootSuspended$1(root, lanes); - } 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 renderWasConcurrent = !includesBlockingLane(root, lanes); - var finishedWork = root.current.alternate; + root.callbackNode = null; + root.callbackPriority = NoLane; // Update the first and last pending times on this root. The new first + // pending time is whatever is left on the root fiber. + + var remainingLanes = mergeLanes(finishedWork.lanes, finishedWork.childLanes); + markRootFinished(root, remainingLanes); + + 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 ( - renderWasConcurrent && - !isRenderConsistentWithExternalStores(finishedWork) + (finishedWork.subtreeFlags & PassiveMask) !== NoFlags || + (finishedWork.flags & PassiveMask) !== NoFlags ) { - // A store was mutated in an interleaved event. Render again, - // synchronously, to block further mutations. - exitStatus = renderRootSync(root, lanes); // We need to check again if something threw - - if (exitStatus === RootErrored) { - var _errorRetryLanes = getLanesToRetrySynchronouslyOnError(root); + if (!rootDoesHavePassiveEffects) { + rootDoesHavePassiveEffects = true; + // 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$1(NormalPriority, 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 (_errorRetryLanes !== NoLanes) { - lanes = _errorRetryLanes; - exitStatus = recoverFromConcurrentError(root, _errorRetryLanes); // We assume the tree is now consistent because we didn't yield to any - // concurrent events. - } + 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; + var rootHasEffect = + (finishedWork.flags & + (BeforeMutationMask | MutationMask | LayoutMask | PassiveMask)) !== + NoFlags; + + if (subtreeHasEffects || rootHasEffect) { + var prevTransition = ReactCurrentBatchConfig$2.transition; + ReactCurrentBatchConfig$2.transition = null; + var previousPriority = getCurrentUpdatePriority(); + setCurrentUpdatePriority(DiscreteEventPriority); + var prevExecutionContext = executionContext; + executionContext |= CommitContext; // Reset this to null before calling lifecycles + + ReactCurrentOwner$2.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. + + var shouldFireAfterActiveInstanceBlur = commitBeforeMutationEffects( + root, + finishedWork + ); - if (exitStatus === RootFatalErrored) { - var _fatalError = workInProgressRootFatalError; - prepareFreshStack(root, NoLanes); - markRootSuspended$1(root, lanes); - ensureRootIsScheduled(root, now()); - throw _fatalError; + { + // Mark the current commit time to be shared by all Profilers in this + // batch. This enables them to be grouped later. + recordCommitTime(); } - } // 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, lanes); - } - } + commitMutationEffects(root, finishedWork, lanes); - ensureRootIsScheduled(root, now()); + resetAfterCommit(root.containerInfo); // The work-in-progress tree is now the current tree. This must come after + // 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 (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); - } + root.current = finishedWork; // The next phase is the layout phase, where we call effects that read - return null; -} + commitLayoutEffects(finishedWork, root, lanes); + // opportunity to paint. -function recoverFromConcurrentError(root, 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; - - if (isRootDehydrated(root)) { - // 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; + requestPaint(); + executionContext = prevExecutionContext; // Reset the priority to the previous non-sync value. - { - errorHydratingContainer(root.containerInfo); - } - } + setCurrentUpdatePriority(previousPriority); + ReactCurrentBatchConfig$2.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(); + } + } - var exitStatus = renderRootSync(root, errorRetryLanes); + 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 { + { + nestedPassiveUpdateCount = 0; + rootWithPassiveNestedUpdates = null; + } + } // Read this again, since an effect might have updated it - if (exitStatus !== RootErrored) { - // Successfully finished rendering on retry - // 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. + 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 (errorsFromSecondAttempt !== null) { - queueRecoverableErrors(errorsFromSecondAttempt); - } - } + if (remainingLanes === NoLanes) { + // If there's no remaining work, we can clear the set of already failed + // error boundaries. + legacyErrorBoundariesThatAlreadyFailed = null; + } - return exitStatus; -} + onCommitRoot(finishedWork.stateNode, renderPriorityLevel); -function queueRecoverableErrors(errors) { - if (workInProgressRootRecoverableErrors === null) { - workInProgressRootRecoverableErrors = errors; - } else { - workInProgressRootRecoverableErrors.push.apply( - workInProgressRootRecoverableErrors, - errors - ); - } -} + { + if (isDevToolsPresent) { + root.memoizedUpdaters.clear(); + } + } + // additional work on this root is scheduled. -function finishConcurrentRender(root, exitStatus, lanes) { - switch (exitStatus) { - case RootInProgress: - case RootFatalErrored: { - throw new Error("Root did not complete. This is a bug in React."); - } - // Flow knows about invariant, so it complains if I add a break - // statement, but eslint doesn't know about invariant, so it complains - // if I do. eslint-disable-next-line no-fallthrough + ensureRootIsScheduled(root, now()); - case RootErrored: { - // We should have already attempted to retry this tree. If we reached - // this point, it errored again. Commit it. - commitRoot( - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ); - break; - } + 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 componentStack = recoverableError.stack; + var digest = recoverableError.digest; + onRecoverableError(recoverableError.value, { + componentStack: componentStack, + digest: digest + }); + } + } - case RootSuspended: { - markRootSuspended$1(root, lanes); // We have an acceptable loading state. We need to figure out if we - // should immediately commit it or wait a bit. + 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 ( - includesOnlyRetries(lanes) && // do not delay if we're inside an act() scope - !shouldForceFlushFallbacksInDEV() + includesSomeLane(pendingPassiveEffectsLanes, SyncLane) && + root.tag !== LegacyRoot ) { - // 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(); // Don't bother with a very short suspense time. - - if (msUntilTimeout > 10) { - var nextLanes = getNextLanes(root, NoLanes); - - if (nextLanes !== NoLanes) { - // There's additional work on this root. - break; - } - - var suspendedLanes = root.suspendedLanes; + flushPassiveEffects(); + } // Read this again, since a passive effect might have updated it - if (!isSubsetOfLanes(suspendedLanes, lanes)) { - // We should prefer to render the fallback of at the last - // suspended level. Ping the last suspended level to try - // rendering it again. - // FIXME: What if the suspended lanes are Idle? Should not restart. - var eventTime = requestEventTime(); - markRootPinged(root, suspendedLanes); - break; - } // 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. + remainingLanes = root.pendingLanes; - root.timeoutHandle = scheduleTimeout( - commitRoot.bind( - null, - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ), - msUntilTimeout - ); - break; - } - } // The work expired. Commit immediately. + if (includesSomeLane(remainingLanes, SyncLane)) { + { + markNestedUpdateScheduled(); + } // Count the number of times the root synchronously re-renders without + // finishing. If there are too many, it indicates an infinite update loop. - commitRoot( - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ); - break; - } - - case RootSuspendedWithDelay: { - markRootSuspended$1(root, lanes); - - 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. - break; - } - - if (!shouldForceFlushFallbacksInDEV()) { - // This is not a transition, but we did trigger an avoided state. - // Schedule a placeholder to display after a short delay, using the Just - // Noticeable Difference. - // TODO: Is the JND optimization worth the added complexity? If this is - // the only reason we track the event time, then probably not. - // Consider removing. - var mostRecentEventTime = getMostRecentEventTime(root, lanes); - var eventTimeMs = mostRecentEventTime; - var timeElapsedMs = now() - eventTimeMs; - - var _msUntilTimeout = jnd(timeElapsedMs) - timeElapsedMs; // Don't bother with a very short suspense time. - - if (_msUntilTimeout > 10) { - // Instead of committing the fallback immediately, wait for more data - // to arrive. - root.timeoutHandle = scheduleTimeout( - commitRoot.bind( - null, - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ), - _msUntilTimeout - ); - break; + if (root === rootWithNestedUpdates) { + nestedUpdateCount++; + } else { + nestedUpdateCount = 0; + rootWithNestedUpdates = root; } - } // Commit the placeholder. - - commitRoot( - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ); - break; - } + } else { + nestedUpdateCount = 0; + } // If layout work was scheduled, flush it now. - case RootCompleted: { - // The work completed. Ready to commit. - commitRoot( - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ); - break; - } + flushSyncCallbacks(); - default: { - throw new Error("Unknown root exit status."); + return null; } - } -} - -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 (true) { - if (node.flags & StoreConsistency) { - var updateQueue = node.updateQueue; + 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) { + var renderPriority = lanesToEventPriority(pendingPassiveEffectsLanes); + var priority = lowerEventPriority(DefaultEventPriority, renderPriority); + var prevTransition = ReactCurrentBatchConfig$2.transition; + var previousPriority = getCurrentUpdatePriority(); - if (updateQueue !== null) { - var checks = updateQueue.stores; + try { + ReactCurrentBatchConfig$2.transition = null; + setCurrentUpdatePriority(priority); + return flushPassiveEffectsImpl(); + } finally { + setCurrentUpdatePriority(previousPriority); + ReactCurrentBatchConfig$2.transition = prevTransition; // Once passive effects have run for the tree - giving components a + } + } - if (checks !== null) { - for (var i = 0; i < checks.length; i++) { - var check = checks[i]; - var getSnapshot = check.getSnapshot; - var renderedValue = check.value; + return false; + } + function enqueuePendingPassiveProfilerEffect(fiber) { + { + pendingPassiveProfilerEffects.push(fiber); - 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; - } - } + if (!rootDoesHavePassiveEffects) { + rootDoesHavePassiveEffects = true; + scheduleCallback$1(NormalPriority, function () { + flushPassiveEffects(); + return null; + }); } } } - var child = node.child; + function flushPassiveEffectsImpl() { + if (rootWithPendingPassiveEffects === null) { + return false; + } // Cache and clear the transitions flag - if (node.subtreeFlags & StoreConsistency && child !== null) { - child.return = node; - node = child; - continue; - } + 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 (node === finishedWork) { - return true; - } + pendingPassiveEffectsLanes = NoLanes; - while (node.sibling === null) { - if (node.return === null || node.return === finishedWork) { - return true; + if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { + throw new Error("Cannot flush passive effects while already rendering."); } - node = node.return; - } - - node.sibling.return = node.return; - node = node.sibling; - } // Flow doesn't know this is unreachable, but eslint does - // eslint-disable-next-line no-unreachable + { + isFlushingPassiveEffects = true; + didScheduleUpdateDuringPassiveEffects = false; + } - return true; -} + var prevExecutionContext = executionContext; + executionContext |= CommitContext; + commitPassiveUnmountEffects(root.current); + commitPassiveMountEffects(root, root.current, lanes, transitions); // TODO: Move to commitPassiveMountEffects -function markRootSuspended$1(root, suspendedLanes) { - // 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(root, suspendedLanes); -} // This is the entry point for synchronous tasks that don't go -// through Scheduler - -function performSyncWorkOnRoot(root) { - { - syncNestedUpdateFlag(); - } - - if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { - throw new Error("Should not already be working."); - } - - flushPassiveEffects(); - var lanes = getNextLanes(root, NoLanes); - - if (!includesSomeLane(lanes, SyncLane)) { - // There's no remaining sync work left. - ensureRootIsScheduled(root, now()); - return null; - } - - 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 errorRetryLanes = getLanesToRetrySynchronouslyOnError(root); - - if (errorRetryLanes !== NoLanes) { - lanes = errorRetryLanes; - exitStatus = recoverFromConcurrentError(root, errorRetryLanes); - } - } - - if (exitStatus === RootFatalErrored) { - var fatalError = workInProgressRootFatalError; - prepareFreshStack(root, NoLanes); - markRootSuspended$1(root, lanes); - ensureRootIsScheduled(root, now()); - throw fatalError; - } - - if (exitStatus === RootDidNotComplete) { - throw new Error("Root did not complete. This is a bug in React."); - } // 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 - ); // Before exiting, make sure there's a callback scheduled for the next - // pending level. - - ensureRootIsScheduled(root, now()); - return null; -} -function batchedUpdates$1(fn, a) { - var prevExecutionContext = executionContext; - executionContext |= BatchedContext; + { + var profilerEffects = pendingPassiveProfilerEffects; + pendingPassiveProfilerEffects = []; - try { - return fn(a); - } finally { - executionContext = prevExecutionContext; // If there were legacy sync updates, flush them at the end of the outer - // most batchedUpdates-like method. + for (var i = 0; i < profilerEffects.length; i++) { + var _fiber = profilerEffects[i]; + commitPassiveEffectDurations(root, _fiber); + } + } - if ( - executionContext === NoContext && // Treat `act` as if it's inside `batchedUpdates`, even in legacy mode. - !ReactCurrentActQueue$1.isBatchingLegacy - ) { - resetRenderTimer(); - flushSyncCallbacksOnlyInLegacyMode(); - } - } -} -// Warning, this opts-out of checking the function body. - -// 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$2.transition; - var previousPriority = getCurrentUpdatePriority(); - - try { - ReactCurrentBatchConfig$2.transition = null; - setCurrentUpdatePriority(DiscreteEventPriority); - - if (fn) { - return fn(); - } else { - return undefined; - } - } finally { - setCurrentUpdatePriority(previousPriority); - ReactCurrentBatchConfig$2.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) { + executionContext = prevExecutionContext; flushSyncCallbacks(); - } - } -} -function pushRenderLanes(fiber, lanes) { - push(subtreeRenderLanesCursor, subtreeRenderLanes, fiber); - subtreeRenderLanes = mergeLanes(subtreeRenderLanes, lanes); - workInProgressRootIncludedLanes = mergeLanes( - workInProgressRootIncludedLanes, - lanes - ); -} -function popRenderLanes(fiber) { - subtreeRenderLanes = subtreeRenderLanesCursor.current; - pop(subtreeRenderLanesCursor, fiber); -} - -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 Complains noTimeout is not a TimeoutID, despite the check above - - cancelTimeout(timeoutHandle); - } - - if (workInProgress !== null) { - var interruptedWork = workInProgress.return; - - while (interruptedWork !== null) { - var current = interruptedWork.alternate; - unwindInterruptedWork(current, interruptedWork); - interruptedWork = interruptedWork.return; - } - } - - workInProgressRoot = root; - var rootWorkInProgress = createWorkInProgress(root.current, null); - workInProgress = rootWorkInProgress; - workInProgressRootRenderLanes = subtreeRenderLanes = workInProgressRootIncludedLanes = lanes; - workInProgressRootExitStatus = RootInProgress; - workInProgressRootFatalError = null; - workInProgressRootSkippedLanes = NoLanes; - workInProgressRootInterleavedUpdatedLanes = NoLanes; - workInProgressRootPingedLanes = NoLanes; - workInProgressRootConcurrentErrors = null; - workInProgressRootRecoverableErrors = null; - finishQueueingConcurrentUpdates(); - - { - ReactStrictModeWarnings.discardPendingWarnings(); - } - - return rootWorkInProgress; -} - -function handleError(root, thrownValue) { - do { - var erroredWork = workInProgress; - try { - // Reset module-level state that was set during the render phase. - resetContextDependencies(); - resetHooksAfterThrow(); - resetCurrentFiber(); // TODO: I found and added this missing line while investigating a - // separate issue. Write a regression test using string refs. - - ReactCurrentOwner$2.current = null; + { + // 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; + } - if (erroredWork === null || erroredWork.return === 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. + isFlushingPassiveEffects = false; + didScheduleUpdateDuringPassiveEffects = false; + } // TODO: Move to commitPassiveMountEffects - workInProgress = null; - return; - } + onPostCommitRoot(root); - if (enableProfilerTimer && 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); + { + var stateNode = root.current.stateNode; + stateNode.effectDuration = 0; + stateNode.passiveEffectDuration = 0; } - if (enableSchedulingProfiler) { - markComponentRenderStopped(); - - if ( - thrownValue !== null && - typeof thrownValue === "object" && - typeof thrownValue.then === "function" - ) { - var wakeable = thrownValue; - markComponentSuspended( - erroredWork, - wakeable, - workInProgressRootRenderLanes - ); - } else { - markComponentErrored( - erroredWork, - thrownValue, - workInProgressRootRenderLanes - ); - } - } + return true; + } - throwException( - root, - erroredWork.return, - erroredWork, - thrownValue, - workInProgressRootRenderLanes + function isAlreadyFailedLegacyErrorBoundary(instance) { + return ( + legacyErrorBoundariesThatAlreadyFailed !== null && + legacyErrorBoundariesThatAlreadyFailed.has(instance) ); - completeUnitOfWork(erroredWork); - } catch (yetAnotherThrownValue) { - // Something in the return path also threw. - thrownValue = yetAnotherThrownValue; - - if (workInProgress === erroredWork && erroredWork !== null) { - // If this boundary has already errored, then we had trouble processing - // the error. Bubble it to the next boundary. - erroredWork = erroredWork.return; - workInProgress = erroredWork; + } + function markLegacyErrorBoundaryAsFailed(instance) { + if (legacyErrorBoundariesThatAlreadyFailed === null) { + legacyErrorBoundariesThatAlreadyFailed = new Set([instance]); } else { - erroredWork = workInProgress; + legacyErrorBoundariesThatAlreadyFailed.add(instance); } + } - continue; - } // Return to the normal work loop. - - return; - } while (true); -} - -function pushDispatcher() { - var prevDispatcher = ReactCurrentDispatcher$2.current; - ReactCurrentDispatcher$2.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; - } -} - -function popDispatcher(prevDispatcher) { - ReactCurrentDispatcher$2.current = prevDispatcher; -} - -function markCommitTimeOfFallback() { - globalMostRecentFallbackTime = now(); -} -function markSkippedUpdateLanes(lane) { - workInProgressRootSkippedLanes = mergeLanes( - lane, - workInProgressRootSkippedLanes - ); -} -function renderDidSuspend() { - if (workInProgressRootExitStatus === RootInProgress) { - workInProgressRootExitStatus = RootSuspended; - } -} -function renderDidSuspendDelayIfPossible() { - if ( - workInProgressRootExitStatus === RootInProgress || - workInProgressRootExitStatus === RootSuspended || - workInProgressRootExitStatus === RootErrored - ) { - workInProgressRootExitStatus = RootSuspendedWithDelay; - } // Check if there are updates that we skipped tree that might have unblocked - // this render. - - if ( - workInProgressRoot !== null && - (includesNonIdleWork(workInProgressRootSkippedLanes) || - includesNonIdleWork(workInProgressRootInterleavedUpdatedLanes)) - ) { - // 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. - markRootSuspended$1(workInProgressRoot, workInProgressRootRenderLanes); - } -} -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; -} - -function renderRootSync(root, lanes) { - var prevExecutionContext = executionContext; - executionContext |= RenderContext; - var prevDispatcher = pushDispatcher(); // 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. + function prepareToThrowUncaughtError(error) { + if (!hasUncaughtError) { + hasUncaughtError = true; + firstUncaughtError = error; + } + } - if (workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes) { - { - if (isDevToolsPresent) { - var memoizedUpdaters = root.memoizedUpdaters; + var onUncaughtError = prepareToThrowUncaughtError; - 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. + function captureCommitPhaseErrorOnRoot(rootFiber, sourceFiber, error) { + var errorInfo = createCapturedValueAtFiber(error, sourceFiber); + var update = createRootErrorUpdate(rootFiber, errorInfo, SyncLane); + var root = enqueueUpdate(rootFiber, update, SyncLane); + var eventTime = requestEventTime(); - movePendingFibersToMemoized(root, lanes); + if (root !== null) { + markRootUpdated(root, SyncLane, eventTime); + ensureRootIsScheduled(root, eventTime); } } - workInProgressTransitions = getTransitionsForLanes(); - prepareFreshStack(root, lanes); - } - - do { - try { - workLoopSync(); - break; - } catch (thrownValue) { - handleError(root, thrownValue); - } - } while (true); + function captureCommitPhaseError(sourceFiber, nearestMountedAncestor, error$1) { + { + reportUncaughtErrorInDEV(error$1); + setIsRunningInsertionEffect(false); + } - resetContextDependencies(); - executionContext = prevExecutionContext; - popDispatcher(prevDispatcher); + 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; + } - 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." - ); - } + var fiber = null; - workInProgressRoot = null; - workInProgressRootRenderLanes = NoLanes; - return workInProgressRootExitStatus; -} // The work loop is an extremely hot path. Tell Closure not to inline it. + { + fiber = sourceFiber.return; + } -/** @noinline */ + 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; -function workLoopSync() { - // Already timed out, so perform work without checking if we need to yield. - while (workInProgress !== null) { - performUnitOfWork(workInProgress); - } -} + 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); + var eventTime = requestEventTime(); -function renderRootConcurrent(root, lanes) { - var prevExecutionContext = executionContext; - executionContext |= RenderContext; - var prevDispatcher = pushDispatcher(); // 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 (root !== null) { + markRootUpdated(root, SyncLane, eventTime); + ensureRootIsScheduled(root, eventTime); + } - if (workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes) { - { - if (isDevToolsPresent) { - var memoizedUpdaters = root.memoizedUpdaters; + 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. + fiber = fiber.return; + } - movePendingFibersToMemoized(root, lanes); + { + // TODO: Until we re-land skipUnmountedBoundaries (see #20147), this warning + // will fire for errors that are thrown by destroy functions inside deleted + // trees. What it should instead do is propagate the error to the parent of + // the deleted tree. In the meantime, do not add this warning to the + // allowlist; this is only for our internal use. + error( + "Internal React error: Attempted to capture a commit phase error " + + "inside a detached tree. This indicates a bug in React. Likely " + + "causes include deleting the same fiber more than once, committing an " + + "already-finished tree, or an inconsistent return pointer.\n\n" + + "Error message:\n\n%s", + error$1 + ); } } + 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); + } - workInProgressTransitions = getTransitionsForLanes(); - resetRenderTimer(); - prepareFreshStack(root, lanes); - } + var eventTime = requestEventTime(); + 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() - globalMostRecentFallbackTime < FALLBACK_THROTTLE_MS) + ) { + // Restart from the root. + 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 + ); + } + } - do { - try { - workLoopConcurrent(); - break; - } catch (thrownValue) { - handleError(root, thrownValue); + ensureRootIsScheduled(root, eventTime); } - } while (true); - resetContextDependencies(); - popDispatcher(prevDispatcher); - executionContext = prevExecutionContext; + 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 (workInProgress !== null) { - return RootInProgress; - } else { - workInProgressRoot = null; - workInProgressRootRenderLanes = NoLanes; // Return the final exit status. + var eventTime = requestEventTime(); + var root = enqueueConcurrentRenderForLane(boundaryFiber, retryLane); - return workInProgressRootExitStatus; - } -} -/** @noinline */ + if (root !== null) { + markRootUpdated(root, retryLane, eventTime); + ensureRootIsScheduled(root, eventTime); + } + } -function workLoopConcurrent() { - // Perform work until Scheduler asks us to yield - while (workInProgress !== null && !shouldYield()) { - performUnitOfWork(workInProgress); - } -} + function retryDehydratedSuspenseBoundary(boundaryFiber) { + var suspenseState = boundaryFiber.memoizedState; + var retryLane = NoLane; -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$1(current, unitOfWork, subtreeRenderLanes); - stopProfilerTimerIfRunningAndRecordDelta(unitOfWork, true); - } else { - next = beginWork$1(current, unitOfWork, subtreeRenderLanes); - } - - 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$2.current = null; -} + if (suspenseState !== null) { + retryLane = suspenseState.retryLane; + } -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; + retryTimedOutBoundary(boundaryFiber, retryLane); + } + function resolveRetryWakeable(boundaryFiber, wakeable) { + var retryLane = NoLane; // Default - 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 = completedWork.alternate; - var returnFiber = completedWork.return; // Check if the work completed or if something threw. + var retryCache; - if ((completedWork.flags & Incomplete) === NoFlags) { - setCurrentFiber(completedWork); - var next = void 0; + switch (boundaryFiber.tag) { + case SuspenseComponent: + retryCache = boundaryFiber.stateNode; + var suspenseState = boundaryFiber.memoizedState; - if ((completedWork.mode & ProfileMode) === NoMode) { - next = completeWork(current, completedWork, subtreeRenderLanes); - } else { - startProfilerTimer(completedWork); - next = completeWork(current, completedWork, subtreeRenderLanes); // Update render duration assuming we didn't error. + if (suspenseState !== null) { + retryLane = suspenseState.retryLane; + } - stopProfilerTimerIfRunningAndRecordDelta(completedWork, false); - } + break; - resetCurrentFiber(); + case SuspenseListComponent: + retryCache = boundaryFiber.stateNode; + break; - if (next !== null) { - // Completing this fiber spawned new work. Work on that next. - workInProgress = next; - return; - } - } else { - // 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, completedWork); // Because this fiber did not complete, don't reset its lanes. - - if (_next !== null) { - // If completing this work spawned new work, do that next. We'll come - // back here again. - // Since we're restarting, remove anything that is not a host effect - // from the effect tag. - _next.flags &= HostEffectMask; - workInProgress = _next; - return; + default: + throw new Error( + "Pinged unknown suspense boundary type. " + + "This is probably a bug in React." + ); } - if ((completedWork.mode & ProfileMode) !== NoMode) { - // Record the render duration for the fiber that errored. - stopProfilerTimerIfRunningAndRecordDelta(completedWork, false); // Include the time spent working on failed children before continuing. + 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); + } // Computes the next Just Noticeable Difference (JND) boundary. + // The theory is that a person can't tell the difference between small differences in time. + // Therefore, if we wait a bit longer than necessary that won't translate to a noticeable + // difference in the experience. However, waiting for longer might mean that we can avoid + // showing an intermediate loading state. The longer we have already waited, the harder it + // is to tell small differences in time. Therefore, the longer we've already waited, + // the longer we can wait additionally. At some point we have to give up though. + // We pick a train model where the next boundary commits at a consistent schedule. + // These particular numbers are vague estimates. We expect to adjust them based on research. + + function jnd(timeElapsed) { + return timeElapsed < 120 + ? 120 + : timeElapsed < 480 + ? 480 + : timeElapsed < 1080 + ? 1080 + : timeElapsed < 1920 + ? 1920 + : timeElapsed < 3000 + ? 3000 + : timeElapsed < 4320 + ? 4320 + : ceil(timeElapsed / 1960) * 1960; + } + + function checkForNestedUpdates() { + if (nestedUpdateCount > NESTED_UPDATE_LIMIT) { + nestedUpdateCount = 0; + rootWithNestedUpdates = 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." + ); + } - var actualDuration = completedWork.actualDuration; - var child = completedWork.child; + { + if (nestedPassiveUpdateCount > NESTED_PASSIVE_UPDATE_LIMIT) { + nestedPassiveUpdateCount = 0; + rootWithPassiveNestedUpdates = null; - while (child !== null) { - actualDuration += child.actualDuration; - child = child.sibling; + 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." + ); } - - completedWork.actualDuration = actualDuration; } + } - if (returnFiber !== null) { - // Mark the parent fiber as incomplete and clear its subtree flags. - returnFiber.flags |= Incomplete; - returnFiber.subtreeFlags = NoFlags; - returnFiber.deletions = null; - } else { - // We've unwound all the way to the root. - workInProgressRootExitStatus = RootDidNotComplete; - workInProgress = null; - return; + function flushRenderPhaseStrictModeWarningsInDEV() { + { + ReactStrictModeWarnings.flushLegacyContextWarning(); + + { + ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings(); + } } } - var siblingFiber = completedWork.sibling; + 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 (!(fiber.mode & ConcurrentMode)) { + return; + } - if (siblingFiber !== null) { - // If there is more work to do in this returnFiber, do that next. - workInProgress = siblingFiber; - return; - } // Otherwise, return to the parent + var tag = fiber.tag; - completedWork = returnFiber; // Update the next thing we're working on in case something throws. + 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. - workInProgress = completedWork; - } while (completedWork !== null); // We've reached the root. + var componentName = getComponentNameFromFiber(fiber) || "ReactComponent"; - if (workInProgressRootExitStatus === RootInProgress) { - workInProgressRootExitStatus = RootCompleted; - } -} + if (didWarnStateUpdateForNotYetMountedComponent !== null) { + if (didWarnStateUpdateForNotYetMountedComponent.has(componentName)) { + return; + } -function commitRoot(root, recoverableErrors, transitions) { - // 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$2.transition; + didWarnStateUpdateForNotYetMountedComponent.add(componentName); + } else { + didWarnStateUpdateForNotYetMountedComponent = new Set([componentName]); + } - try { - ReactCurrentBatchConfig$2.transition = null; - setCurrentUpdatePriority(DiscreteEventPriority); - commitRootImpl( - root, - recoverableErrors, - transitions, - previousUpdateLanePriority - ); - } finally { - ReactCurrentBatchConfig$2.transition = prevTransition; - setCurrentUpdatePriority(previousUpdateLanePriority); - } + var previousFiber = current; - return null; -} + try { + setCurrentFiber(fiber); -function commitRootImpl( - root, - recoverableErrors, - transitions, - renderPriorityLevel -) { - 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 (finishedWork === null) { - return null; - } else { - { - if (lanes === NoLanes) { - error( - "root.finishedLanes should not be empty during a commit. This is a " + - "bug in React." - ); + 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(); + } + } } } - } - - root.finishedWork = null; - root.finishedLanes = NoLanes; + var beginWork$1; - 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; // Update the first and last pending times on this root. The new first - // pending time is whatever is left on the root fiber. - - var remainingLanes = mergeLanes(finishedWork.lanes, finishedWork.childLanes); - markRootFinished(root, remainingLanes); - - 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 || - (finishedWork.flags & PassiveMask) !== NoFlags - ) { - if (!rootDoesHavePassiveEffects) { - rootDoesHavePassiveEffects = true; - // 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$1(NormalPriority, 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) + { + var dummyFiber = null; + + beginWork$1 = 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 + ); - 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; - var rootHasEffect = - (finishedWork.flags & - (BeforeMutationMask | MutationMask | LayoutMask | PassiveMask)) !== - NoFlags; - - if (subtreeHasEffects || rootHasEffect) { - var prevTransition = ReactCurrentBatchConfig$2.transition; - ReactCurrentBatchConfig$2.transition = null; - var previousPriority = getCurrentUpdatePriority(); - setCurrentUpdatePriority(DiscreteEventPriority); - var prevExecutionContext = executionContext; - executionContext |= CommitContext; // Reset this to null before calling lifecycles - - ReactCurrentOwner$2.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. - - var shouldFireAfterActiveInstanceBlur = commitBeforeMutationEffects( - root, - finishedWork - ); + try { + return beginWork(current, unitOfWork, lanes); + } catch (originalError) { + if ( + didSuspendOrErrorWhileHydratingDEV() || + (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; + } // Keep this code in sync with handleError; any changes here must have + // corresponding changes there. - { - // Mark the current commit time to be shared by all Profilers in this - // batch. This enables them to be grouped later. - recordCommitTime(); - } + resetContextDependencies(); + resetHooksAfterThrow(); // Don't reset current debug fiber, since we're about to work on the + // same fiber again. + // Unwind the failed stack frame - commitMutationEffects(root, finishedWork, lanes); + unwindInterruptedWork(current, unitOfWork); // Restore the original properties of the fiber. - resetAfterCommit(root.containerInfo); // The work-in-progress tree is now the current tree. This must come after - // 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. + assignFiberPropertiesInDEV(unitOfWork, originalWorkInProgressCopy); - root.current = finishedWork; // The next phase is the layout phase, where we call effects that read + if (unitOfWork.mode & ProfileMode) { + // Reset the profiler timer. + startProfilerTimer(unitOfWork); + } // Run beginWork again. - commitLayoutEffects(finishedWork, root, lanes); - // opportunity to paint. + invokeGuardedCallback(null, beginWork, null, current, unitOfWork, lanes); - requestPaint(); - executionContext = prevExecutionContext; // Reset the priority to the previous non-sync value. + if (hasCaughtError()) { + var replayError = clearCaughtError(); - setCurrentUpdatePriority(previousPriority); - ReactCurrentBatchConfig$2.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 ( + 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. - { - recordCommitTime(); + throw originalError; + } + }; } - } - 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 { + var didWarnAboutUpdateInRender = false; + var didWarnAboutUpdateInRenderForAnotherComponent; + { - 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; - } - - onCommitRoot(finishedWork.stateNode, renderPriorityLevel); - - { - if (isDevToolsPresent) { - root.memoizedUpdaters.clear(); - } - } - // additional work on this root is scheduled. - - ensureRootIsScheduled(root, now()); - - 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 componentStack = recoverableError.stack; - var digest = recoverableError.digest; - onRecoverableError(recoverableError.value, { - componentStack: componentStack, - digest: digest - }); + didWarnAboutUpdateInRenderForAnotherComponent = new Set(); } - } - - 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 ( - includesSomeLane(pendingPassiveEffectsLanes, SyncLane) && - root.tag !== LegacyRoot - ) { - flushPassiveEffects(); - } // Read this again, since a passive effect might have updated it - - remainingLanes = root.pendingLanes; - - if (includesSomeLane(remainingLanes, SyncLane)) { - { - 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 (root === rootWithNestedUpdates) { - nestedUpdateCount++; - } else { - nestedUpdateCount = 0; - rootWithNestedUpdates = root; - } - } else { - nestedUpdateCount = 0; - } // If layout work was scheduled, flush it now. + function warnAboutRenderPhaseUpdatesInDEV(fiber) { + { + if (isRendering && !getIsUpdatingOpaqueValueInRenderPhaseInDEV()) { + 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 dedupeKey = renderingComponentName; + + if (!didWarnAboutUpdateInRenderForAnotherComponent.has(dedupeKey)) { + didWarnAboutUpdateInRenderForAnotherComponent.add(dedupeKey); + var setStateComponentName = + getComponentNameFromFiber(fiber) || "Unknown"; - flushSyncCallbacks(); + 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://react.dev/link/setstate-in-render", + setStateComponentName, + renderingComponentName, + renderingComponentName + ); + } - return null; -} + break; + } -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) { - var renderPriority = lanesToEventPriority(pendingPassiveEffectsLanes); - var priority = lowerEventPriority(DefaultEventPriority, renderPriority); - var prevTransition = ReactCurrentBatchConfig$2.transition; - var previousPriority = getCurrentUpdatePriority(); - - try { - ReactCurrentBatchConfig$2.transition = null; - setCurrentUpdatePriority(priority); - return flushPassiveEffectsImpl(); - } finally { - setCurrentUpdatePriority(previousPriority); - ReactCurrentBatchConfig$2.transition = prevTransition; // Once passive effects have run for the tree - giving components a - } - } - - return false; -} -function enqueuePendingPassiveProfilerEffect(fiber) { - { - pendingPassiveProfilerEffects.push(fiber); + 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 (!rootDoesHavePassiveEffects) { - rootDoesHavePassiveEffects = true; - scheduleCallback$1(NormalPriority, function() { - flushPassiveEffects(); - return null; - }); + didWarnAboutUpdateInRender = true; + } + + break; + } + } + } + } } - } -} -function flushPassiveEffectsImpl() { - if (rootWithPendingPassiveEffects === null) { - return false; - } // Cache and clear the transitions flag - - 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."); - } - - { - isFlushingPassiveEffects = true; - didScheduleUpdateDuringPassiveEffects = false; - } - - var prevExecutionContext = executionContext; - executionContext |= CommitContext; - commitPassiveUnmountEffects(root.current); - commitPassiveMountEffects(root, root.current, lanes, transitions); // TODO: Move to commitPassiveMountEffects - - { - var profilerEffects = pendingPassiveProfilerEffects; - pendingPassiveProfilerEffects = []; - - for (var i = 0; i < profilerEffects.length; i++) { - var _fiber = profilerEffects[i]; - commitPassiveEffectDurations(root, _fiber); - } - } - - executionContext = prevExecutionContext; - flushSyncCallbacks(); - - { - // 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; + 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). + } } - } else { - nestedPassiveUpdateCount = 0; } + var fakeActCallbackNode = {}; - isFlushingPassiveEffects = false; - didScheduleUpdateDuringPassiveEffects = false; - } // TODO: Move to commitPassiveMountEffects + function scheduleCallback$1(priorityLevel, callback) { + { + // If we're currently inside an `act` scope, bypass Scheduler and push to + // the `act` queue instead. + var actQueue = ReactCurrentActQueue$1.current; - onPostCommitRoot(root); + if (actQueue !== null) { + actQueue.push(callback); + return fakeActCallbackNode; + } else { + return scheduleCallback(priorityLevel, callback); + } + } + } - { - var stateNode = root.current.stateNode; - stateNode.effectDuration = 0; - stateNode.passiveEffectDuration = 0; - } + function cancelCallback$1(callbackNode) { + if (callbackNode === fakeActCallbackNode) { + return; + } // In production, always call Scheduler. This function will be stripped out. - return true; -} + return cancelCallback(callbackNode); + } -function isAlreadyFailedLegacyErrorBoundary(instance) { - return ( - legacyErrorBoundariesThatAlreadyFailed !== null && - legacyErrorBoundariesThatAlreadyFailed.has(instance) - ); -} -function markLegacyErrorBoundaryAsFailed(instance) { - if (legacyErrorBoundariesThatAlreadyFailed === null) { - legacyErrorBoundariesThatAlreadyFailed = new Set([instance]); - } else { - legacyErrorBoundariesThatAlreadyFailed.add(instance); - } -} + function shouldForceFlushFallbacksInDEV() { + // Never force flush in production. This function should get stripped out. + return ReactCurrentActQueue$1.current !== null; + } -function prepareToThrowUncaughtError(error) { - if (!hasUncaughtError) { - hasUncaughtError = true; - firstUncaughtError = error; - } -} + 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 onUncaughtError = prepareToThrowUncaughtError; + if (executionContext !== NoContext) { + // Legacy mode doesn't warn if the update is batched, i.e. + // batchedUpdates or flushSync. + return; + } -function captureCommitPhaseErrorOnRoot(rootFiber, sourceFiber, error) { - var errorInfo = createCapturedValueAtFiber(error, sourceFiber); - var update = createRootErrorUpdate(rootFiber, errorInfo, SyncLane); - var root = enqueueUpdate(rootFiber, update, SyncLane); - var eventTime = requestEventTime(); + 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; + } + } - if (root !== null) { - markRootUpdated(root, SyncLane, eventTime); - ensureRootIsScheduled(root, eventTime); - } -} + if (ReactCurrentActQueue$1.current === null) { + var previousFiber = current; -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 = null; - - { - fiber = sourceFiber.return; - } - - 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 { + setCurrentFiber(fiber); - 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); - var eventTime = requestEventTime(); + 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://react.dev/link/wrap-tests-with-act", + getComponentNameFromFiber(fiber) + ); + } finally { + if (previousFiber) { + setCurrentFiber(fiber); + } else { + resetCurrentFiber(); + } + } + } + } + } - if (root !== null) { - markRootUpdated(root, SyncLane, eventTime); - ensureRootIsScheduled(root, eventTime); + function warnIfSuspenseResolutionNotWrappedWithActDEV(root) { + { + if ( + root.tag !== LegacyRoot && + isConcurrentActEnvironment() && + ReactCurrentActQueue$1.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://react.dev/link/wrap-tests-with-act" + ); } + } + } - return; + function setIsRunningInsertionEffect(isRunning) { + { + isRunningInsertionEffect = isRunning; } } - fiber = fiber.return; - } + /* eslint-disable react-internal/prod-error-codes */ + var resolveFamily = null; // $FlowFixMe Flow gets confused by a WeakSet feature check below. - { - // TODO: Until we re-land skipUnmountedBoundaries (see #20147), this warning - // will fire for errors that are thrown by destroy functions inside deleted - // trees. What it should instead do is propagate the error to the parent of - // the deleted tree. In the meantime, do not add this warning to the - // allowlist; this is only for our internal use. - error( - "Internal React error: Attempted to capture a commit phase error " + - "inside a detached tree. This indicates a bug in React. Likely " + - "causes include deleting the same fiber more than once, committing an " + - "already-finished tree, or an inconsistent return pointer.\n\n" + - "Error message:\n\n%s", - error$1 - ); - } -} -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); - } - - var eventTime = requestEventTime(); - 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() - globalMostRecentFallbackTime < FALLBACK_THROTTLE_MS) - ) { - // Restart from the root. - 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 - ); - } - } + var failedBoundaries = null; + var setRefreshHandler = function (handler) { + { + resolveFamily = handler; + } + }; + function resolveFunctionForHotReloading(type) { + { + if (resolveFamily === null) { + // Hot reloading is disabled. + return type; + } - ensureRootIsScheduled(root, eventTime); -} + var family = resolveFamily(type); -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 eventTime = requestEventTime(); - var root = enqueueConcurrentRenderForLane(boundaryFiber, retryLane); - - if (root !== null) { - markRootUpdated(root, retryLane, eventTime); - ensureRootIsScheduled(root, eventTime); - } -} + if (family === undefined) { + return type; + } // Use the latest known implementation. -function retryDehydratedSuspenseBoundary(boundaryFiber) { - var suspenseState = boundaryFiber.memoizedState; - var retryLane = NoLane; + 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 (suspenseState !== null) { - retryLane = suspenseState.retryLane; - } + var family = resolveFamily(type); - retryTimedOutBoundary(boundaryFiber, retryLane); -} -function resolveRetryWakeable(boundaryFiber, wakeable) { - var retryLane = NoLane; // Default + 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; + } - var retryCache; + return syntheticType; + } + } - switch (boundaryFiber.tag) { - case SuspenseComponent: - retryCache = boundaryFiber.stateNode; - var suspenseState = boundaryFiber.memoizedState; + return type; + } // Use the latest known implementation. - if (suspenseState !== null) { - retryLane = suspenseState.retryLane; + return family.current; } + } + function isCompatibleFamilyForHotReloading(fiber, element) { + { + if (resolveFamily === null) { + // Hot reloading is disabled. + return false; + } - break; + var prevType = fiber.elementType; + var nextType = element.type; // If we got here, we know types aren't === equal. - case SuspenseListComponent: - retryCache = boundaryFiber.stateNode; - break; + var needsCompareFamilies = false; + var $$typeofNextType = + typeof nextType === "object" && nextType !== null + ? nextType.$$typeof + : null; - default: - throw new Error( - "Pinged unknown suspense boundary type. " + - "This is probably a bug in React." - ); - } - - 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); -} // Computes the next Just Noticeable Difference (JND) boundary. -// The theory is that a person can't tell the difference between small differences in time. -// Therefore, if we wait a bit longer than necessary that won't translate to a noticeable -// difference in the experience. However, waiting for longer might mean that we can avoid -// showing an intermediate loading state. The longer we have already waited, the harder it -// is to tell small differences in time. Therefore, the longer we've already waited, -// the longer we can wait additionally. At some point we have to give up though. -// We pick a train model where the next boundary commits at a consistent schedule. -// These particular numbers are vague estimates. We expect to adjust them based on research. - -function jnd(timeElapsed) { - return timeElapsed < 120 - ? 120 - : timeElapsed < 480 - ? 480 - : timeElapsed < 1080 - ? 1080 - : timeElapsed < 1920 - ? 1920 - : timeElapsed < 3000 - ? 3000 - : timeElapsed < 4320 - ? 4320 - : ceil(timeElapsed / 1960) * 1960; -} + switch (fiber.tag) { + case ClassComponent: { + if (typeof nextType === "function") { + needsCompareFamilies = true; + } -function checkForNestedUpdates() { - if (nestedUpdateCount > NESTED_UPDATE_LIMIT) { - nestedUpdateCount = 0; - rootWithNestedUpdates = 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." - ); - } - } -} + break; + } -function flushRenderPhaseStrictModeWarningsInDEV() { - { - ReactStrictModeWarnings.flushLegacyContextWarning(); + 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; + } - { - ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings(); - } - } -} + 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 ForwardRef: { + if ($$typeofNextType === REACT_FORWARD_REF_TYPE) { + needsCompareFamilies = true; + } else if ($$typeofNextType === REACT_LAZY_TYPE) { + needsCompareFamilies = true; + } + + break; + } - if (!(fiber.mode & ConcurrentMode)) { - return; + 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; + } + + break; + } + + default: + return false; + } // Check if both types have a family and it's the same one. + + 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); + + if (prevFamily !== undefined && prevFamily === resolveFamily(nextType)) { + return true; + } + } + + return false; + } } + function markFailedErrorBoundaryForHotReloading(fiber) { + { + if (resolveFamily === null) { + // Hot reloading is disabled. + return; + } - var tag = fiber.tag; + if (typeof WeakSet !== "function") { + return; + } - 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. + if (failedBoundaries === null) { + failedBoundaries = new WeakSet(); + } - var componentName = getComponentNameFromFiber(fiber) || "ReactComponent"; + failedBoundaries.add(fiber); + } + } + var scheduleRefresh = function (root, update) { + { + if (resolveFamily === null) { + // Hot reloading is disabled. + return; + } - if (didWarnStateUpdateForNotYetMountedComponent !== null) { - if (didWarnStateUpdateForNotYetMountedComponent.has(componentName)) { - 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; + } - didWarnStateUpdateForNotYetMountedComponent.add(componentName); - } else { - didWarnStateUpdateForNotYetMountedComponent = new Set([componentName]); - } + flushPassiveEffects(); + flushSync(function () { + updateContainer(element, root, null, null); + }); + } + }; - var previousFiber = current; + 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; - try { - setCurrentFiber(fiber); + case ForwardRef: + candidateType = type.render; + break; + } - 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$1; - -{ - var dummyFiber = null; - - beginWork$1 = 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 - ); + if (resolveFamily === null) { + throw new Error("Expected resolveFamily to be set during hot reload."); + } - try { - return beginWork(current, unitOfWork, lanes); - } catch (originalError) { - if ( - didSuspendOrErrorWhileHydratingDEV() || - (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; - } // Keep this code in sync with handleError; any changes here must have - // corresponding changes there. + var needsRender = false; + var needsRemount = false; - resetContextDependencies(); - resetHooksAfterThrow(); // Don't reset current debug fiber, since we're about to work on the - // same fiber again. - // Unwind the failed stack frame + if (candidateType !== null) { + var family = resolveFamily(candidateType); - unwindInterruptedWork(current, unitOfWork); // Restore the original properties of the fiber. + if (family !== undefined) { + if (staleFamilies.has(family)) { + needsRemount = true; + } else if (updatedFamilies.has(family)) { + if (tag === ClassComponent) { + needsRemount = true; + } else { + needsRender = true; + } + } + } + } - assignFiberPropertiesInDEV(unitOfWork, originalWorkInProgressCopy); + if (failedBoundaries !== null) { + if ( + failedBoundaries.has(fiber) || + (alternate !== null && failedBoundaries.has(alternate)) + ) { + needsRemount = true; + } + } - if (unitOfWork.mode & ProfileMode) { - // Reset the profiler timer. - startProfilerTimer(unitOfWork); - } // Run beginWork again. + if (needsRemount) { + fiber._debugNeedsRemount = true; + } - invokeGuardedCallback(null, beginWork, null, current, unitOfWork, lanes); + if (needsRemount || needsRender) { + var _root = enqueueConcurrentRenderForLane(fiber, SyncLane); - if (hasCaughtError()) { - var replayError = clearCaughtError(); + if (_root !== null) { + scheduleUpdateOnFiber(_root, fiber, SyncLane, NoTimestamp); + } + } - 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; + if (child !== null && !needsRemount) { + scheduleFibersWithFamiliesRecursively( + child, + updatedFamilies, + staleFamilies + ); } - } // 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; + if (sibling !== null) { + scheduleFibersWithFamiliesRecursively( + sibling, + updatedFamilies, + staleFamilies + ); + } + } } - }; -} - -var didWarnAboutUpdateInRender = false; -var didWarnAboutUpdateInRenderForAnotherComponent; -{ - didWarnAboutUpdateInRenderForAnotherComponent = new Set(); -} + 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 warnAboutRenderPhaseUpdatesInDEV(fiber) { - { - if (isRendering && !getIsUpdatingOpaqueValueInRenderPhaseInDEV()) { - 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 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; - var dedupeKey = renderingComponentName; + case ForwardRef: + candidateType = type.render; + break; + } - if (!didWarnAboutUpdateInRenderForAnotherComponent.has(dedupeKey)) { - didWarnAboutUpdateInRenderForAnotherComponent.add(dedupeKey); - var setStateComponentName = - getComponentNameFromFiber(fiber) || "Unknown"; + var didMatch = false; - 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://react.dev/link/setstate-in-render", - setStateComponentName, - renderingComponentName, - renderingComponentName - ); + if (candidateType !== null) { + if (types.has(candidateType)) { + didMatch = true; } - - break; } - 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 (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 ); - - didWarnAboutUpdateInRender = true; } + } - break; + if (sibling !== null) { + findHostInstancesForMatchingFibersRecursively( + sibling, + types, + hostInstances + ); } } } - } -} - -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 = {}; -function scheduleCallback$1(priorityLevel, callback) { - { - // If we're currently inside an `act` scope, bypass Scheduler and push to - // the `act` queue instead. - var actQueue = ReactCurrentActQueue$1.current; + function findHostInstancesForFiberShallowly(fiber, hostInstances) { + { + var foundHostInstances = findChildHostInstancesForFiberShallowly( + fiber, + hostInstances + ); - if (actQueue !== null) { - actQueue.push(callback); - return fakeActCallbackNode; - } else { - return scheduleCallback(priorityLevel, callback); - } - } -} + if (foundHostInstances) { + return; + } // If we didn't find any host children, fallback to closest host parent. -function cancelCallback$1(callbackNode) { - if (callbackNode === fakeActCallbackNode) { - return; - } // In production, always call Scheduler. This function will be stripped out. + var node = fiber; - return cancelCallback(callbackNode); -} + while (true) { + switch (node.tag) { + case HostComponent: + hostInstances.add(node.stateNode); + return; -function shouldForceFlushFallbacksInDEV() { - // Never force flush in production. This function should get stripped out. - return ReactCurrentActQueue$1.current !== null; -} + case HostPortal: + hostInstances.add(node.stateNode.containerInfo); + return; -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; - } + case HostRoot: + hostInstances.add(node.stateNode.containerInfo); + return; + } - if (executionContext !== NoContext) { - // Legacy mode doesn't warn if the update is batched, i.e. - // batchedUpdates or flushSync. - return; - } + if (node.return === null) { + throw new Error("Expected to reach root first."); + } - 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; + node = node.return; + } } } - if (ReactCurrentActQueue$1.current === null) { - var previousFiber = current; + function findChildHostInstancesForFiberShallowly(fiber, hostInstances) { + { + var node = fiber; + var foundHostInstances = false; + + while (true) { + if (node.tag === HostComponent) { + // 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; + } - try { - setCurrentFiber(fiber); + if (node === fiber) { + return foundHostInstances; + } - 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://react.dev/link/wrap-tests-with-act", - getComponentNameFromFiber(fiber) - ); - } finally { - if (previousFiber) { - setCurrentFiber(fiber); - } else { - resetCurrentFiber(); + while (node.sibling === null) { + if (node.return === null || node.return === fiber) { + return foundHostInstances; + } + + node = node.return; + } + + node.sibling.return = node.return; + node = node.sibling; } } - } - } -} -function warnIfSuspenseResolutionNotWrappedWithActDEV(root) { - { - if ( - root.tag !== LegacyRoot && - isConcurrentActEnvironment() && - ReactCurrentActQueue$1.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://react.dev/link/wrap-tests-with-act" - ); + return false; } - } -} -function setIsRunningInsertionEffect(isRunning) { - { - isRunningInsertionEffect = isRunning; - } -} + var hasBadMapPolyfill; -/* eslint-disable react-internal/prod-error-codes */ -var resolveFamily = null; // $FlowFixMe Flow gets confused by a WeakSet feature check below. + { + hasBadMapPolyfill = false; -var failedBoundaries = null; -var setRefreshHandler = function(handler) { - { - resolveFamily = handler; - } -}; -function resolveFunctionForHotReloading(type) { - { - if (resolveFamily === null) { - // Hot reloading is disabled. - return type; - } + 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.pendingProps = pendingProps; + this.memoizedProps = null; + this.updateQueue = null; + this.memoizedState = null; + this.dependencies = null; + this.mode = mode; // Effects + + this.flags = NoFlags; + this.subtreeFlags = NoFlags; + this.deletions = null; + this.lanes = NoLanes; + this.childLanes = NoLanes; + this.alternate = null; - var family = resolveFamily(type); + { + // 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; + } - if (family === undefined) { - return type; - } // Use the latest known implementation. + { + // 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. + + var createFiber = function (tag, pendingProps, key, mode) { + // $FlowFixMe: the shapes are exact here but Flow doesn't like constructors + return new FiberNode(tag, pendingProps, key, mode); + }; - 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 shouldConstruct(Component) { + var prototype = Component.prototype; + return !!(prototype && prototype.isReactComponent); } - var family = resolveFamily(type); - - 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 - }; + 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; - if (type.displayName !== undefined) { - syntheticType.displayName = type.displayName; - } + if ($$typeof === REACT_FORWARD_REF_TYPE) { + return ForwardRef; + } - return syntheticType; + if ($$typeof === REACT_MEMO_TYPE) { + return MemoComponent; } } - return type; - } // Use the latest known implementation. - - return family.current; - } -} -function isCompatibleFamilyForHotReloading(fiber, element) { - { - if (resolveFamily === null) { - // Hot reloading is disabled. - return false; - } + return IndeterminateComponent; + } // This is used to create an alternate fiber to do work on. - var prevType = fiber.elementType; - var nextType = element.type; // If we got here, we know types aren't === equal. + function createWorkInProgress(current, pendingProps) { + var workInProgress = current.alternate; - var needsCompareFamilies = false; - var $$typeofNextType = - typeof nextType === "object" && nextType !== null - ? nextType.$$typeof - : null; + 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; - switch (fiber.tag) { - case ClassComponent: { - if (typeof nextType === "function") { - needsCompareFamilies = true; + { + // DEV-only fields + workInProgress._debugSource = current._debugSource; + workInProgress._debugOwner = current._debugOwner; + workInProgress._debugHookTypes = current._debugHookTypes; } - break; - } - - 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; - } + workInProgress.alternate = current; + current.alternate = workInProgress; + } else { + workInProgress.pendingProps = pendingProps; // Needed because Blocks store data on type. - break; - } + workInProgress.type = current.type; // We already have an alternate. + // Reset the effect tag. - case ForwardRef: { - if ($$typeofNextType === REACT_FORWARD_REF_TYPE) { - needsCompareFamilies = true; - } else if ($$typeofNextType === REACT_LAZY_TYPE) { - needsCompareFamilies = true; - } + workInProgress.flags = NoFlags; // The effects are no longer valid. - break; - } + workInProgress.subtreeFlags = NoFlags; + workInProgress.deletions = null; - 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; + { + // 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 - break; + workInProgress.sibling = current.sibling; + workInProgress.index = current.index; + workInProgress.ref = current.ref; + + { + workInProgress.selfBaseDuration = current.selfBaseDuration; + workInProgress.treeBaseDuration = current.treeBaseDuration; } - default: - return false; - } // Check if both types have a family and it's the same one. + { + workInProgress._debugNeedsRemount = current._debugNeedsRemount; - 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); + switch (workInProgress.tag) { + case IndeterminateComponent: + case FunctionComponent: + case SimpleMemoComponent: + workInProgress.type = resolveFunctionForHotReloading(current.type); + break; - if (prevFamily !== undefined && prevFamily === resolveFamily(nextType)) { - return true; + case ClassComponent: + workInProgress.type = resolveClassForHotReloading(current.type); + break; + + case ForwardRef: + workInProgress.type = resolveForwardRefForHotReloading(current.type); + break; + } } - } - return false; - } -} -function markFailedErrorBoundaryForHotReloading(fiber) { - { - if (resolveFamily === null) { - // Hot reloading is disabled. - return; - } + return workInProgress; + } // Used to reuse a Fiber for a second pass. - if (typeof WeakSet !== "function") { - return; - } + 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 (failedBoundaries === null) { - failedBoundaries = new WeakSet(); - } + var current = workInProgress.alternate; - 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; - } + if (current === null) { + // Reset to createFiber's initial values. + workInProgress.childLanes = NoLanes; + workInProgress.lanes = renderLanes; + workInProgress.child = null; + workInProgress.subtreeFlags = NoFlags; + workInProgress.memoizedProps = null; + workInProgress.memoizedState = null; + workInProgress.updateQueue = null; + workInProgress.dependencies = null; + workInProgress.stateNode = null; + + { + // 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; + 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 + }; - if (failedBoundaries !== null) { - if ( - failedBoundaries.has(fiber) || - (alternate !== null && failedBoundaries.has(alternate)) - ) { - needsRemount = true; + { + // 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 (needsRemount) { - fiber._debugNeedsRemount = true; + return workInProgress; } + function createHostRootFiber( + tag, + isStrictMode, + concurrentUpdatesByDefaultOverride + ) { + var mode; - if (needsRemount || needsRender) { - var _root = enqueueConcurrentRenderForLane(fiber, SyncLane); + if (tag === ConcurrentRoot) { + mode = ConcurrentMode; - if (_root !== null) { - scheduleUpdateOnFiber(_root, fiber, SyncLane, NoTimestamp); + if (isStrictMode === true) { + mode |= StrictLegacyMode; + } + } else { + mode = NoMode; } - } - - if (child !== null && !needsRemount) { - scheduleFibersWithFamiliesRecursively( - child, - updatedFamilies, - staleFamilies - ); - } - - if (sibling !== null) { - scheduleFibersWithFamiliesRecursively( - sibling, - updatedFamilies, - staleFamilies - ); - } - } -} -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 - ); + 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; } - } - if (sibling !== null) { - findHostInstancesForMatchingFibersRecursively( - sibling, - types, - hostInstances - ); + return createFiber(HostRoot, null, null, mode); } - } -} - -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 createFiberFromTypeAndProps( + type, // React$ElementType + key, + pendingProps, + 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) { - switch (node.tag) { - case HostComponent: - hostInstances.add(node.stateNode); - return; + var resolvedType = type; - case HostPortal: - hostInstances.add(node.stateNode.containerInfo); - return; + if (typeof type === "function") { + if (shouldConstruct(type)) { + fiberTag = ClassComponent; - case HostRoot: - hostInstances.add(node.stateNode.containerInfo); - return; - } + { + 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); - if (node.return === null) { - throw new Error("Expected to reach root first."); - } + case REACT_STRICT_MODE_TYPE: + fiberTag = Mode; + mode |= StrictLegacyMode; - node = node.return; - } - } -} + break; -function findChildHostInstancesForFiberShallowly(fiber, hostInstances) { - { - var node = fiber; - var foundHostInstances = false; + case REACT_PROFILER_TYPE: + return createFiberFromProfiler(pendingProps, mode, lanes, key); - while (true) { - if (node.tag === HostComponent) { - // 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; - } + case REACT_SUSPENSE_TYPE: + return createFiberFromSuspense(pendingProps, mode, lanes, key); - if (node === fiber) { - return foundHostInstances; - } + case REACT_SUSPENSE_LIST_TYPE: + return createFiberFromSuspenseList(pendingProps, mode, lanes, key); - while (node.sibling === null) { - if (node.return === null || node.return === fiber) { - return foundHostInstances; - } + case REACT_OFFSCREEN_TYPE: + return createFiberFromOffscreen(pendingProps, mode, lanes, key); - node = node.return; - } + case REACT_LEGACY_HIDDEN_TYPE: - node.sibling.return = node.return; - node = node.sibling; - } - } + // eslint-disable-next-line no-fallthrough - return false; -} + case REACT_SCOPE_TYPE: -var hasBadMapPolyfill; + // eslint-disable-next-line no-fallthrough -{ - hasBadMapPolyfill = false; + case REACT_CACHE_TYPE: - try { - var nonExtensibleObject = Object.preventExtensions({}); - /* eslint-disable no-new */ + // eslint-disable-next-line no-fallthrough - new Map([[nonExtensibleObject, null]]); - new Set([nonExtensibleObject]); - /* eslint-enable no-new */ - } catch (e) { - // TODO: Consider warning about bad polyfills - hasBadMapPolyfill = true; - } -} + case REACT_TRACING_MARKER_TYPE: -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.pendingProps = pendingProps; - this.memoizedProps = null; - this.updateQueue = null; - this.memoizedState = null; - this.dependencies = null; - this.mode = mode; // Effects - - this.flags = NoFlags; - this.subtreeFlags = NoFlags; - 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. - -var createFiber = function(tag, pendingProps, key, mode) { - // $FlowFixMe: 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); -} + // eslint-disable-next-line no-fallthrough -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_DEBUG_TRACING_MODE_TYPE: - if ($$typeof === REACT_FORWARD_REF_TYPE) { - return ForwardRef; - } + // eslint-disable-next-line no-fallthrough - if ($$typeof === REACT_MEMO_TYPE) { - return MemoComponent; - } - } + default: { + if (typeof type === "object" && type !== null) { + switch (type.$$typeof) { + case REACT_PROVIDER_TYPE: + fiberTag = ContextProvider; + break getTag; - return IndeterminateComponent; -} // This is used to create an alternate fiber to do work on. + case REACT_CONTEXT_TYPE: + // This is a consumer + fiberTag = ContextConsumer; + break getTag; -function createWorkInProgress(current, pendingProps) { - var workInProgress = current.alternate; + case REACT_FORWARD_REF_TYPE: + fiberTag = ForwardRef; - 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; + { + resolvedType = resolveForwardRefForHotReloading(resolvedType); + } - { - // DEV-only fields - workInProgress._debugSource = current._debugSource; - workInProgress._debugOwner = current._debugOwner; - workInProgress._debugHookTypes = current._debugHookTypes; - } + break getTag; - workInProgress.alternate = current; - current.alternate = workInProgress; - } else { - workInProgress.pendingProps = pendingProps; // Needed because Blocks store data on type. + case REACT_MEMO_TYPE: + fiberTag = MemoComponent; + break getTag; - workInProgress.type = current.type; // We already have an alternate. - // Reset the effect tag. + case REACT_LAZY_TYPE: + fiberTag = LazyComponent; + resolvedType = null; + break getTag; + } + } - workInProgress.flags = NoFlags; // The effects are no longer valid. + var info = ""; - workInProgress.subtreeFlags = NoFlags; - workInProgress.deletions = null; + { + 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."; + } - { - // 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.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; - workInProgress.memoizedProps = null; - workInProgress.memoizedState = null; - workInProgress.updateQueue = null; - workInProgress.dependencies = null; - workInProgress.stateNode = null; + var ownerName = owner ? getComponentNameFromFiber(owner) : null; - { - // 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; - 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 - }; + if (ownerName) { + info += "\n\nCheck the render method of `" + ownerName + "`."; + } + } - { - // 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; - } - } + 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 workInProgress; -} -function createHostRootFiber( - tag, - isStrictMode, - concurrentUpdatesByDefaultOverride -) { - var mode; - - if (tag === ConcurrentRoot) { - mode = ConcurrentMode; - - if (isStrictMode === true) { - mode |= StrictLegacyMode; - } - } else { - mode = NoMode; - } - - 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; - } - - return createFiber(HostRoot, null, null, mode); -} -function createFiberFromTypeAndProps( - type, // React$ElementType - key, - pendingProps, - 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; + var fiber = createFiber(fiberTag, pendingProps, key, mode); + fiber.elementType = type; + fiber.type = resolvedType; + fiber.lanes = lanes; { - resolvedType = resolveClassForHotReloading(resolvedType); - } - } else { - { - resolvedType = resolveFunctionForHotReloading(resolvedType); + fiber._debugOwner = owner; } + + return fiber; } - } else if (typeof type === "string") { - fiberTag = HostComponent; - } else { - getTag: switch (type) { - case REACT_FRAGMENT_TYPE: - return createFiberFromFragment(pendingProps.children, mode, lanes, key); + function createFiberFromElement(element, mode, lanes) { + var owner = null; - case REACT_STRICT_MODE_TYPE: - fiberTag = Mode; - mode |= StrictLegacyMode; + { + owner = element._owner; + } - break; + var type = element.type; + var key = element.key; + var pendingProps = element.props; + var fiber = createFiberFromTypeAndProps( + type, + key, + pendingProps, + owner, + mode, + lanes + ); - case REACT_PROFILER_TYPE: - return createFiberFromProfiler(pendingProps, mode, lanes, key); + { + fiber._debugSource = element._source; + fiber._debugOwner = element._owner; + } - case REACT_SUSPENSE_TYPE: - return createFiberFromSuspense(pendingProps, mode, lanes, key); + return fiber; + } + function createFiberFromFragment(elements, mode, lanes, key) { + var fiber = createFiber(Fragment, elements, key, mode); + fiber.lanes = lanes; + return fiber; + } - case REACT_SUSPENSE_LIST_TYPE: - return createFiberFromSuspenseList(pendingProps, mode, lanes, key); + 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 + ); + } + } - case REACT_OFFSCREEN_TYPE: - return createFiberFromOffscreen(pendingProps, mode, lanes, key); + var fiber = createFiber(Profiler, pendingProps, key, mode | ProfileMode); + fiber.elementType = REACT_PROFILER_TYPE; + fiber.lanes = lanes; - case REACT_LEGACY_HIDDEN_TYPE: + { + fiber.stateNode = { + effectDuration: 0, + passiveEffectDuration: 0 + }; + } - // eslint-disable-next-line no-fallthrough + return fiber; + } - case REACT_SCOPE_TYPE: + 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 = { + isHidden: false + }; + fiber.stateNode = primaryChildInstance; + 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.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; - // eslint-disable-next-line no-fallthrough + { + target.actualDuration = source.actualDuration; + target.actualStartTime = source.actualStartTime; + target.selfBaseDuration = source.selfBaseDuration; + target.treeBaseDuration = source.treeBaseDuration; + } - case REACT_CACHE_TYPE: + target._debugSource = source._debugSource; + target._debugOwner = source._debugOwner; + target._debugNeedsRemount = source._debugNeedsRemount; + target._debugHookTypes = source._debugHookTypes; + return target; + } - // eslint-disable-next-line no-fallthrough + function FiberRootNode( + containerInfo, + tag, + hydrate, + identifierPrefix, + onRecoverableError + ) { + this.tag = tag; + this.containerInfo = containerInfo; + this.pendingChildren = null; + this.current = null; + this.pingCache = null; + this.finishedWork = null; + this.timeoutHandle = noTimeout; + this.context = null; + this.pendingContext = null; + this.callbackNode = null; + this.callbackPriority = NoLane; + this.eventTimes = createLaneMap(NoLanes); + this.expirationTimes = createLaneMap(NoTimestamp); + this.pendingLanes = NoLanes; + this.suspendedLanes = NoLanes; + this.pingedLanes = NoLanes; + this.expiredLanes = NoLanes; + this.mutableReadLanes = NoLanes; + this.finishedLanes = NoLanes; + this.entangledLanes = NoLanes; + this.entanglements = createLaneMap(NoLanes); + this.identifierPrefix = identifierPrefix; + this.onRecoverableError = onRecoverableError; - case REACT_TRACING_MARKER_TYPE: + { + this.effectDuration = 0; + this.passiveEffectDuration = 0; + } - // eslint-disable-next-line no-fallthrough + { + this.memoizedUpdaters = new Set(); + var pendingUpdatersLaneMap = (this.pendingUpdatersLaneMap = []); - case REACT_DEBUG_TRACING_MODE_TYPE: + for (var _i = 0; _i < TotalLanes; _i++) { + pendingUpdatersLaneMap.push(new Set()); + } + } - // eslint-disable-next-line no-fallthrough + { + switch (tag) { + case ConcurrentRoot: + this._debugRootType = hydrate ? "hydrateRoot()" : "createRoot()"; + break; - default: { - if (typeof type === "object" && type !== null) { - switch (type.$$typeof) { - case REACT_PROVIDER_TYPE: - fiberTag = ContextProvider; - break getTag; + case LegacyRoot: + this._debugRootType = hydrate ? "hydrate()" : "render()"; + break; + } + } + } - case REACT_CONTEXT_TYPE: - // This is a consumer - fiberTag = ContextConsumer; - break getTag; + 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 + ) { + var root = new FiberRootNode( + containerInfo, + tag, + hydrate, + identifierPrefix, + onRecoverableError + ); + // stateNode is any. - case REACT_FORWARD_REF_TYPE: - fiberTag = ForwardRef; + var uninitializedFiber = createHostRootFiber(tag, isStrictMode); + root.current = uninitializedFiber; + uninitializedFiber.stateNode = root; - { - resolvedType = resolveForwardRefForHotReloading(resolvedType); - } + { + var _initialState = { + element: initialChildren, + isDehydrated: hydrate, + cache: null, + // not enabled yet + transitions: null, + pendingSuspenseBoundaries: null + }; + uninitializedFiber.memoizedState = _initialState; + } - break getTag; + initializeUpdateQueue(uninitializedFiber); + return root; + } - case REACT_MEMO_TYPE: - fiberTag = MemoComponent; - break getTag; + var ReactVersion = "18.2.0-next-9e3b772b8-20220608"; - case REACT_LAZY_TYPE: - fiberTag = LazyComponent; - resolvedType = null; - break getTag; - } - } + function createPortal( + children, + containerInfo, // TODO: figure out the API for cross-renderer implementation. + implementation + ) { + var key = + arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; - var info = ""; + { + checkKeyStringCoercion(key); + } - { - 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."; - } + return { + // This tag allow us to uniquely identify this as a React Portal + $$typeof: REACT_PORTAL_TYPE, + key: key == null ? null : "" + key, + children: children, + containerInfo: containerInfo, + implementation: implementation + }; + } - var ownerName = owner ? getComponentNameFromFiber(owner) : null; + var didWarnAboutNestedUpdates; + var didWarnAboutFindNodeInStrictMode; - if (ownerName) { - info += "\n\nCheck the render method of `" + ownerName + "`."; - } - } + { + didWarnAboutNestedUpdates = false; + didWarnAboutFindNodeInStrictMode = {}; + } - 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) - ); + function getContextForSubtree(parentComponent) { + if (!parentComponent) { + return emptyContextObject; } - } - } - var fiber = createFiber(fiberTag, pendingProps, key, mode); - fiber.elementType = type; - fiber.type = resolvedType; - fiber.lanes = lanes; + var fiber = get(parentComponent); + var parentContext = findCurrentUnmaskedContext(fiber); - { - fiber._debugOwner = owner; - } + if (fiber.tag === ClassComponent) { + var Component = fiber.type; - return fiber; -} -function createFiberFromElement(element, mode, lanes) { - var owner = null; - - { - owner = element._owner; - } - - var type = element.type; - var key = element.key; - var pendingProps = element.props; - var fiber = createFiberFromTypeAndProps( - type, - key, - pendingProps, - 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; -} + if (isContextProvider(Component)) { + return processChildContext(fiber, Component, 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 - ); + return parentContext; } - } - - var fiber = createFiber(Profiler, pendingProps, key, mode | ProfileMode); - fiber.elementType = REACT_PROFILER_TYPE; - fiber.lanes = lanes; - - { - fiber.stateNode = { - effectDuration: 0, - passiveEffectDuration: 0 - }; - } - - 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 = { - isHidden: false - }; - fiber.stateNode = primaryChildInstance; - 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.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; -} -function FiberRootNode( - containerInfo, - tag, - hydrate, - identifierPrefix, - onRecoverableError -) { - this.tag = tag; - this.containerInfo = containerInfo; - this.pendingChildren = null; - this.current = null; - this.pingCache = null; - this.finishedWork = null; - this.timeoutHandle = noTimeout; - this.context = null; - this.pendingContext = null; - this.callbackNode = null; - this.callbackPriority = NoLane; - this.eventTimes = createLaneMap(NoLanes); - this.expirationTimes = createLaneMap(NoTimestamp); - this.pendingLanes = NoLanes; - this.suspendedLanes = NoLanes; - this.pingedLanes = NoLanes; - this.expiredLanes = NoLanes; - this.mutableReadLanes = NoLanes; - this.finishedLanes = NoLanes; - this.entangledLanes = NoLanes; - this.entanglements = createLaneMap(NoLanes); - this.identifierPrefix = identifierPrefix; - this.onRecoverableError = onRecoverableError; - - { - 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; - } - } -} + function findHostInstanceWithWarning(component, methodName) { + { + var fiber = get(component); -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 -) { - var root = new FiberRootNode( - containerInfo, - tag, - hydrate, - identifierPrefix, - onRecoverableError - ); - // stateNode is any. - - var uninitializedFiber = createHostRootFiber(tag, isStrictMode); - root.current = uninitializedFiber; - uninitializedFiber.stateNode = root; - - { - var _initialState = { - element: initialChildren, - isDehydrated: hydrate, - cache: null, - // not enabled yet - transitions: null, - pendingSuspenseBoundaries: null - }; - uninitializedFiber.memoizedState = _initialState; - } + if (fiber === undefined) { + if (typeof component.render === "function") { + throw new Error("Unable to find node on an unmounted component."); + } else { + var keys = Object.keys(component).join(","); + throw new Error( + "Argument appears to not be a ReactComponent. Keys: " + keys + ); + } + } - initializeUpdateQueue(uninitializedFiber); - return root; -} + var hostFiber = findCurrentHostFiber(fiber); -var ReactVersion = "18.2.0-next-9e3b772b8-20220608"; - -function createPortal( - children, - containerInfo, // TODO: figure out the API for cross-renderer implementation. - implementation -) { - var key = - arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; - - { - checkKeyStringCoercion(key); - } - - return { - // This tag allow us to uniquely identify this as a React Portal - $$typeof: REACT_PORTAL_TYPE, - key: key == null ? null : "" + key, - children: children, - containerInfo: containerInfo, - implementation: implementation - }; -} + if (hostFiber === null) { + return null; + } -var didWarnAboutNestedUpdates; -var didWarnAboutFindNodeInStrictMode; + if (hostFiber.mode & StrictLegacyMode) { + var componentName = getComponentNameFromFiber(fiber) || "Component"; -{ - didWarnAboutNestedUpdates = false; - didWarnAboutFindNodeInStrictMode = {}; -} + if (!didWarnAboutFindNodeInStrictMode[componentName]) { + didWarnAboutFindNodeInStrictMode[componentName] = true; + var previousFiber = current; -function getContextForSubtree(parentComponent) { - if (!parentComponent) { - return emptyContextObject; - } + try { + setCurrentFiber(hostFiber); - var fiber = get(parentComponent); - var parentContext = findCurrentUnmaskedContext(fiber); + if (fiber.mode & StrictLegacyMode) { + error( + "%s is deprecated in StrictMode. " + + "%s was passed an instance of %s which is inside StrictMode. " + + "Instead, add a ref directly to the element you want to reference. " + + "Learn more about using refs safely here: " + + "https://react.dev/link/strict-mode-find-node", + methodName, + methodName, + componentName + ); + } else { + error( + "%s is deprecated in StrictMode. " + + "%s was passed an instance of %s which renders StrictMode children. " + + "Instead, add a ref directly to the element you want to reference. " + + "Learn more about using refs safely here: " + + "https://react.dev/link/strict-mode-find-node", + methodName, + methodName, + componentName + ); + } + } finally { + // Ideally this should reset to previous but this shouldn't be called in + // render and there's another warning for that anyway. + if (previousFiber) { + setCurrentFiber(previousFiber); + } else { + resetCurrentFiber(); + } + } + } + } - if (fiber.tag === ClassComponent) { - var Component = fiber.type; + return hostFiber.stateNode; + } + } - if (isContextProvider(Component)) { - return processChildContext(fiber, Component, parentContext); + 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 + ); } - } + function updateContainer(element, container, parentComponent, callback) { + { + onScheduleRoot(container, element); + } - return parentContext; -} + var current$1 = container.current; + var eventTime = requestEventTime(); + var lane = requestUpdateLane(current$1); -function findHostInstanceWithWarning(component, methodName) { - { - var fiber = get(component); + var context = getContextForSubtree(parentComponent); - if (fiber === undefined) { - if (typeof component.render === "function") { - throw new Error("Unable to find node on an unmounted component."); + if (container.context === null) { + container.context = context; } else { - var keys = Object.keys(component).join(","); - throw new Error( - "Argument appears to not be a ReactComponent. Keys: " + keys - ); + container.pendingContext = context; } - } - var hostFiber = findCurrentHostFiber(fiber); - - if (hostFiber === null) { - return null; - } + { + if (isRendering && current !== null && !didWarnAboutNestedUpdates) { + didWarnAboutNestedUpdates = true; - if (hostFiber.mode & StrictLegacyMode) { - var componentName = getComponentNameFromFiber(fiber) || "Component"; + 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" + ); + } + } - if (!didWarnAboutFindNodeInStrictMode[componentName]) { - didWarnAboutFindNodeInStrictMode[componentName] = true; - var previousFiber = current; + var update = createUpdate(eventTime, lane); // Caution: React DevTools currently depends on this property + // being called "element". - try { - setCurrentFiber(hostFiber); + update.payload = { + element: element + }; + callback = callback === undefined ? null : callback; - if (fiber.mode & StrictLegacyMode) { - error( - "%s is deprecated in StrictMode. " + - "%s was passed an instance of %s which is inside StrictMode. " + - "Instead, add a ref directly to the element you want to reference. " + - "Learn more about using refs safely here: " + - "https://react.dev/link/strict-mode-find-node", - methodName, - methodName, - componentName - ); - } else { + if (callback !== null) { + { + if (typeof callback !== "function") { error( - "%s is deprecated in StrictMode. " + - "%s was passed an instance of %s which renders StrictMode children. " + - "Instead, add a ref directly to the element you want to reference. " + - "Learn more about using refs safely here: " + - "https://react.dev/link/strict-mode-find-node", - methodName, - methodName, - componentName + "render(...): Expected the last optional `callback` argument to be a " + + "function. Instead received: %s.", + callback ); } - } finally { - // Ideally this should reset to previous but this shouldn't be called in - // render and there's another warning for that anyway. - if (previousFiber) { - setCurrentFiber(previousFiber); - } else { - resetCurrentFiber(); - } } + + update.callback = callback; } - } - return hostFiber.stateNode; - } -} + var root = enqueueUpdate(current$1, update, lane); -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 - ); -} -function updateContainer(element, container, parentComponent, callback) { - { - onScheduleRoot(container, element); - } - - var current$1 = container.current; - var eventTime = requestEventTime(); - var lane = requestUpdateLane(current$1); - - 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" - ); + if (root !== null) { + scheduleUpdateOnFiber(root, current$1, lane, eventTime); + entangleTransitions(root, current$1, lane); + } + + return lane; } - } + function getPublicRootInstance(container) { + var containerFiber = container.current; - var update = createUpdate(eventTime, lane); // Caution: React DevTools currently depends on this property - // being called "element". + if (!containerFiber.child) { + return null; + } - update.payload = { - element: element - }; - callback = callback === undefined ? null : callback; + switch (containerFiber.child.tag) { + case HostComponent: + return getPublicInstance(containerFiber.child.stateNode); - if (callback !== null) { - { - if (typeof callback !== "function") { - error( - "render(...): Expected the last optional `callback` argument to be a " + - "function. Instead received: %s.", - callback - ); + default: + return containerFiber.child.stateNode; } } - update.callback = callback; - } - - var root = enqueueUpdate(current$1, update, lane); - - if (root !== null) { - scheduleUpdateOnFiber(root, current$1, lane, eventTime); - entangleTransitions(root, current$1, lane); - } - - return lane; -} -function getPublicRootInstance(container) { - var containerFiber = container.current; + var shouldErrorImpl = function (fiber) { + return null; + }; - if (!containerFiber.child) { - return null; - } + function shouldError(fiber) { + return shouldErrorImpl(fiber); + } - switch (containerFiber.child.tag) { - case HostComponent: - return getPublicInstance(containerFiber.child.stateNode); + var shouldSuspendImpl = function (fiber) { + return false; + }; - default: - return containerFiber.child.stateNode; - } -} + 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 shouldErrorImpl = function(fiber) { - return null; -}; + { + var copyWithDeleteImpl = function (obj, path, index) { + var key = path[index]; + var updated = isArray(obj) ? obj.slice() : assign({}, obj); -function shouldError(fiber) { - return shouldErrorImpl(fiber); -} + if (index + 1 === path.length) { + if (isArray(updated)) { + updated.splice(key, 1); + } else { + delete updated[key]; + } -var shouldSuspendImpl = function(fiber) { - return false; -}; + return updated; + } // $FlowFixMe number or string is fine here -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]; - } + updated[key] = copyWithDeleteImpl(obj[key], path, index + 1); + return updated; + }; - return updated; - } // $FlowFixMe number or string is fine here + var copyWithDelete = function (obj, path) { + return copyWithDeleteImpl(obj, path, 0); + }; - updated[key] = copyWithDeleteImpl(obj[key], path, index + 1); - return updated; - }; + var copyWithRenameImpl = function (obj, oldPath, newPath, index) { + var oldKey = oldPath[index]; + var updated = isArray(obj) ? obj.slice() : assign({}, obj); - var copyWithDelete = function(obj, path) { - return copyWithDeleteImpl(obj, path, 0); - }; + if (index + 1 === oldPath.length) { + var newKey = newPath[index]; // $FlowFixMe number or string is fine here - var copyWithRenameImpl = function(obj, oldPath, newPath, index) { - var oldKey = oldPath[index]; - var updated = isArray(obj) ? obj.slice() : assign({}, obj); + updated[newKey] = updated[oldKey]; - if (index + 1 === oldPath.length) { - var newKey = newPath[index]; // $FlowFixMe number or string is fine here + if (isArray(updated)) { + updated.splice(oldKey, 1); + } else { + delete updated[oldKey]; + } + } else { + // $FlowFixMe number or string is fine here + updated[oldKey] = copyWithRenameImpl( + // $FlowFixMe number or string is fine here + obj[oldKey], + oldPath, + newPath, + index + 1 + ); + } - updated[newKey] = updated[oldKey]; + return updated; + }; - if (isArray(updated)) { - updated.splice(oldKey, 1); - } else { - delete updated[oldKey]; - } - } else { - // $FlowFixMe number or string is fine here - updated[oldKey] = copyWithRenameImpl( - // $FlowFixMe number or string is fine here - obj[oldKey], - oldPath, - newPath, - index + 1 - ); - } + var copyWithRename = function (obj, oldPath, newPath) { + if (oldPath.length !== newPath.length) { + warn("copyWithRename() expects paths of the same length"); - return updated; - }; + 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 copyWithRename = function(obj, oldPath, newPath) { - if (oldPath.length !== newPath.length) { - warn("copyWithRename() expects paths of the same length"); + return; + } + } + } - 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" - ); + return copyWithRenameImpl(obj, oldPath, newPath, 0); + }; - return; + var copyWithSetImpl = function (obj, path, index, value) { + if (index >= path.length) { + return value; } - } - } - return copyWithRenameImpl(obj, oldPath, newPath, 0); - }; + var key = path[index]; + var updated = isArray(obj) ? obj.slice() : assign({}, obj); // $FlowFixMe number or string is fine here - var copyWithSetImpl = function(obj, path, index, value) { - if (index >= path.length) { - return value; - } + updated[key] = copyWithSetImpl(obj[key], path, index + 1, value); + return updated; + }; - var key = path[index]; - var updated = isArray(obj) ? obj.slice() : assign({}, obj); // $FlowFixMe number or string is fine here + var copyWithSet = function (obj, path, value) { + return copyWithSetImpl(obj, path, 0, value); + }; - updated[key] = copyWithSetImpl(obj[key], path, index + 1, value); - return updated; - }; + 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; - var copyWithSet = function(obj, path, value) { - return copyWithSetImpl(obj, path, 0, value); - }; + while (currentHook !== null && id > 0) { + currentHook = currentHook.next; + id--; + } - 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 currentHook; + }; // Support DevTools editable values for useState and useReducer. - while (currentHook !== null && id > 0) { - currentHook = currentHook.next; - id--; - } + overrideHookState = function (fiber, id, path, value) { + var hook = findHook(fiber, id); - return currentHook; - }; // Support DevTools editable values for useState and useReducer. + 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. - 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, NoTimestamp); + } + } + }; - fiber.memoizedProps = assign({}, fiber.memoizedProps); - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + overrideHookStateDeletePath = function (fiber, id, path) { + var hook = findHook(fiber, id); - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); - } - } - }; + 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. - 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, NoTimestamp); + } + } + }; - 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, NoTimestamp); - } - } - }; + 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. - overrideHookStateRenamePath = function(fiber, id, oldPath, newPath) { - var hook = findHook(fiber, id); + fiber.memoizedProps = assign({}, fiber.memoizedProps); + 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, NoTimestamp); + } + } + }; // 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, NoTimestamp); - } - } - }; // 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, NoTimestamp); + } + }; - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + overridePropsDeletePath = function (fiber, path) { + fiber.pendingProps = copyWithDelete(fiber.memoizedProps, path); - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); - } - }; + 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, NoTimestamp); + } + }; - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + overridePropsRenamePath = function (fiber, oldPath, newPath) { + fiber.pendingProps = copyWithRename(fiber.memoizedProps, oldPath, newPath); - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); - } - }; + if (fiber.alternate) { + fiber.alternate.pendingProps = fiber.pendingProps; + } - overridePropsRenamePath = function(fiber, oldPath, newPath) { - fiber.pendingProps = copyWithRename(fiber.memoizedProps, oldPath, newPath); + var root = enqueueConcurrentRenderForLane(fiber, SyncLane); - if (fiber.alternate) { - fiber.alternate.pendingProps = fiber.pendingProps; - } + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + } + }; - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + scheduleUpdate = function (fiber) { + var root = enqueueConcurrentRenderForLane(fiber, SyncLane); - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); - } - }; + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + } + }; - scheduleUpdate = function(fiber) { - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + setErrorHandler = function (newShouldErrorImpl) { + shouldErrorImpl = newShouldErrorImpl; + }; - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + setSuspenseHandler = function (newShouldSuspendImpl) { + shouldSuspendImpl = newShouldSuspendImpl; + }; } - }; - - setErrorHandler = function(newShouldErrorImpl) { - shouldErrorImpl = newShouldErrorImpl; - }; - setSuspenseHandler = function(newShouldSuspendImpl) { - shouldSuspendImpl = newShouldSuspendImpl; - }; -} - -function findHostInstanceByFiber(fiber) { - var hostFiber = findCurrentHostFiber(fiber); + function findHostInstanceByFiber(fiber) { + var hostFiber = findCurrentHostFiber(fiber); - if (hostFiber === null) { - return null; - } + if (hostFiber === null) { + return null; + } - return hostFiber.stateNode; -} + return hostFiber.stateNode; + } -function emptyFindFiberByHostInstance(instance) { - return null; -} + function emptyFindFiberByHostInstance(instance) { + return null; + } -function getCurrentFiberForDevTools() { - return current; -} + 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 - }); -} + 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 + }); + } -var emptyObject$1 = {}; + var emptyObject$1 = {}; -{ - Object.freeze(emptyObject$1); -} + { + Object.freeze(emptyObject$1); + } -var createHierarchy; -var getHostNode; -var getHostProps; -var lastNonHostInstance; + var createHierarchy; + var getHostNode; + var getHostProps; + var lastNonHostInstance; -var getOwnerHierarchy; -var traverseOwnerTreeUp; + var getOwnerHierarchy; + var traverseOwnerTreeUp; -{ - createHierarchy = function(fiberHierarchy) { - return fiberHierarchy.map(function(fiber) { - return { - name: getComponentNameFromType(fiber.type), - getInspectorData: function(findNodeHandle) { + { + createHierarchy = function (fiberHierarchy) { + return fiberHierarchy.map(function (fiber) { return { - props: getHostProps(fiber), - source: fiber._debugSource, - measure: function(callback) { - // If this is Fabric, we'll find a ShadowNode and use that to measure. - var hostFiber = findCurrentHostFiber(fiber); - var shadowNode = - hostFiber != null && - hostFiber.stateNode !== null && - hostFiber.stateNode.node; - - if (shadowNode) { - nativeFabricUIManager.measure(shadowNode, callback); - } else { - return ReactNativePrivateInterface.UIManager.measure( - getHostNode(fiber, findNodeHandle), - callback - ); - } + name: getComponentNameFromType(fiber.type), + getInspectorData: function (findNodeHandle) { + return { + props: getHostProps(fiber), + source: fiber._debugSource, + measure: function (callback) { + // If this is Fabric, we'll find a ShadowNode and use that to measure. + var hostFiber = findCurrentHostFiber(fiber); + var shadowNode = + hostFiber != null && + hostFiber.stateNode !== null && + hostFiber.stateNode.node; + + if (shadowNode) { + nativeFabricUIManager.measure(shadowNode, callback); + } else { + return ReactNativePrivateInterface.UIManager.measure( + getHostNode(fiber, findNodeHandle), + callback + ); + } + } + }; } }; - } + }); }; - }); - }; - getHostNode = function(fiber, findNodeHandle) { - var hostNode; // look for children first for the hostNode - // as composite fibers do not have a hostNode - - while (fiber) { - if (fiber.stateNode !== null && fiber.tag === HostComponent) { - hostNode = findNodeHandle(fiber.stateNode); - } + getHostNode = function (fiber, findNodeHandle) { + var hostNode; // look for children first for the hostNode + // as composite fibers do not have a hostNode - if (hostNode) { - return hostNode; - } + while (fiber) { + if (fiber.stateNode !== null && fiber.tag === HostComponent) { + hostNode = findNodeHandle(fiber.stateNode); + } - fiber = fiber.child; - } + if (hostNode) { + return hostNode; + } - return null; - }; + fiber = fiber.child; + } - getHostProps = function(fiber) { - var host = findCurrentHostFiber(fiber); + return null; + }; - if (host) { - return host.memoizedProps || emptyObject$1; - } + getHostProps = function (fiber) { + var host = findCurrentHostFiber(fiber); - return emptyObject$1; - }; + if (host) { + return host.memoizedProps || emptyObject$1; + } - exports.getInspectorDataForInstance = function(closestInstance) { - // Handle case where user clicks outside of ReactNative - if (!closestInstance) { - return { - hierarchy: [], - props: emptyObject$1, - selectedIndex: null, - source: null + return emptyObject$1; }; - } - var fiber = findCurrentFiberUsingSlowPath(closestInstance); - var fiberHierarchy = getOwnerHierarchy(fiber); - var instance = lastNonHostInstance(fiberHierarchy); - var hierarchy = createHierarchy(fiberHierarchy); - var props = getHostProps(instance); - var source = instance._debugSource; - var selectedIndex = fiberHierarchy.indexOf(instance); - return { - hierarchy: hierarchy, - props: props, - selectedIndex: selectedIndex, - source: source - }; - }; + exports.getInspectorDataForInstance = function (closestInstance) { + // Handle case where user clicks outside of ReactNative + if (!closestInstance) { + return { + hierarchy: [], + props: emptyObject$1, + selectedIndex: null, + source: null + }; + } + + var fiber = findCurrentFiberUsingSlowPath(closestInstance); + var fiberHierarchy = getOwnerHierarchy(fiber); + var instance = lastNonHostInstance(fiberHierarchy); + var hierarchy = createHierarchy(fiberHierarchy); + var props = getHostProps(instance); + var source = instance._debugSource; + var selectedIndex = fiberHierarchy.indexOf(instance); + return { + hierarchy: hierarchy, + props: props, + selectedIndex: selectedIndex, + source: source + }; + }; - getOwnerHierarchy = function(instance) { - var hierarchy = []; - traverseOwnerTreeUp(hierarchy, instance); - return hierarchy; - }; + getOwnerHierarchy = function (instance) { + var hierarchy = []; + traverseOwnerTreeUp(hierarchy, instance); + return hierarchy; + }; - lastNonHostInstance = function(hierarchy) { - for (var i = hierarchy.length - 1; i > 1; i--) { - var instance = hierarchy[i]; + lastNonHostInstance = function (hierarchy) { + for (var i = hierarchy.length - 1; i > 1; i--) { + var instance = hierarchy[i]; - if (instance.tag !== HostComponent) { - return instance; - } - } + if (instance.tag !== HostComponent) { + return instance; + } + } - return hierarchy[0]; - }; + return hierarchy[0]; + }; - traverseOwnerTreeUp = function(hierarchy, instance) { - if (instance) { - hierarchy.unshift(instance); - traverseOwnerTreeUp(hierarchy, instance._debugOwner); + traverseOwnerTreeUp = function (hierarchy, instance) { + if (instance) { + hierarchy.unshift(instance); + traverseOwnerTreeUp(hierarchy, instance._debugOwner); + } + }; } - }; -} -var getInspectorDataForViewTag; -var getInspectorDataForViewAtPoint; + var getInspectorDataForViewTag; + var getInspectorDataForViewAtPoint; -{ - getInspectorDataForViewTag = function(viewTag) { - var closestInstance = getInstanceFromTag(viewTag); // Handle case where user clicks outside of ReactNative + { + getInspectorDataForViewTag = function (viewTag) { + var closestInstance = getInstanceFromTag(viewTag); // Handle case where user clicks outside of ReactNative - if (!closestInstance) { - return { - hierarchy: [], - props: emptyObject$1, - selectedIndex: null, - source: null + if (!closestInstance) { + return { + hierarchy: [], + props: emptyObject$1, + selectedIndex: null, + source: null + }; + } + + var fiber = findCurrentFiberUsingSlowPath(closestInstance); + var fiberHierarchy = getOwnerHierarchy(fiber); + var instance = lastNonHostInstance(fiberHierarchy); + var hierarchy = createHierarchy(fiberHierarchy); + var props = getHostProps(instance); + var source = instance._debugSource; + var selectedIndex = fiberHierarchy.indexOf(instance); + return { + hierarchy: hierarchy, + props: props, + selectedIndex: selectedIndex, + source: source + }; }; - } - var fiber = findCurrentFiberUsingSlowPath(closestInstance); - var fiberHierarchy = getOwnerHierarchy(fiber); - var instance = lastNonHostInstance(fiberHierarchy); - var hierarchy = createHierarchy(fiberHierarchy); - var props = getHostProps(instance); - var source = instance._debugSource; - var selectedIndex = fiberHierarchy.indexOf(instance); - return { - hierarchy: hierarchy, - props: props, - selectedIndex: selectedIndex, - source: source - }; - }; - - getInspectorDataForViewAtPoint = function( - findNodeHandle, - inspectedView, - locationX, - locationY, - callback - ) { - var closestInstance = null; - - if (inspectedView._internalInstanceHandle != null) { - // For Fabric we can look up the instance handle directly and measure it. - nativeFabricUIManager.findNodeAtPoint( - inspectedView._internalInstanceHandle.stateNode.node, + getInspectorDataForViewAtPoint = function ( + findNodeHandle, + inspectedView, locationX, locationY, - function(internalInstanceHandle) { - if (internalInstanceHandle == null) { - callback( - assign( - { - pointerY: locationY, - frame: { - left: 0, - top: 0, - width: 0, - height: 0 - } - }, - exports.getInspectorDataForInstance(closestInstance) - ) - ); - } + callback + ) { + var closestInstance = null; + + if (inspectedView._internalInstanceHandle != null) { + // For Fabric we can look up the instance handle directly and measure it. + nativeFabricUIManager.findNodeAtPoint( + inspectedView._internalInstanceHandle.stateNode.node, + locationX, + locationY, + function (internalInstanceHandle) { + if (internalInstanceHandle == null) { + callback( + assign( + { + pointerY: locationY, + frame: { + left: 0, + top: 0, + width: 0, + height: 0 + } + }, + exports.getInspectorDataForInstance(closestInstance) + ) + ); + } - closestInstance = - internalInstanceHandle.stateNode.canonical._internalInstanceHandle; // Note: this is deprecated and we want to remove it ASAP. Keeping it here for React DevTools compatibility for now. + closestInstance = + internalInstanceHandle.stateNode.canonical._internalInstanceHandle; // Note: this is deprecated and we want to remove it ASAP. Keeping it here for React DevTools compatibility for now. - var nativeViewTag = - internalInstanceHandle.stateNode.canonical._nativeTag; - nativeFabricUIManager.measure( - internalInstanceHandle.stateNode.node, - function(x, y, width, height, pageX, pageY) { + var nativeViewTag = + internalInstanceHandle.stateNode.canonical._nativeTag; + nativeFabricUIManager.measure( + internalInstanceHandle.stateNode.node, + function (x, y, width, height, pageX, pageY) { + var inspectorData = exports.getInspectorDataForInstance( + closestInstance + ); + callback( + assign({}, inspectorData, { + pointerY: locationY, + frame: { + left: pageX, + top: pageY, + width: width, + height: height + }, + touchedViewTag: nativeViewTag + }) + ); + } + ); + } + ); + } else if (inspectedView._internalFiberInstanceHandleDEV != null) { + // For Paper we fall back to the old strategy using the React tag. + ReactNativePrivateInterface.UIManager.findSubviewIn( + findNodeHandle(inspectedView), + [locationX, locationY], + function (nativeViewTag, left, top, width, height) { var inspectorData = exports.getInspectorDataForInstance( - closestInstance + getInstanceFromTag(nativeViewTag) ); callback( assign({}, inspectorData, { pointerY: locationY, frame: { - left: pageX, - top: pageY, + left: left, + top: top, width: width, height: height }, @@ -24450,308 +24490,283 @@ var getInspectorDataForViewAtPoint; ); } ); - } - ); - } else if (inspectedView._internalFiberInstanceHandleDEV != null) { - // For Paper we fall back to the old strategy using the React tag. - ReactNativePrivateInterface.UIManager.findSubviewIn( - findNodeHandle(inspectedView), - [locationX, locationY], - function(nativeViewTag, left, top, width, height) { - var inspectorData = exports.getInspectorDataForInstance( - getInstanceFromTag(nativeViewTag) - ); - callback( - assign({}, inspectorData, { - pointerY: locationY, - frame: { - left: left, - top: top, - width: width, - height: height - }, - touchedViewTag: nativeViewTag - }) + } else { + error( + "getInspectorDataForViewAtPoint expects to receive a host component" ); - } - ); - } else { - error( - "getInspectorDataForViewAtPoint expects to receive a host component" - ); - return; + return; + } + }; } - }; -} -var ReactCurrentOwner$3 = ReactSharedInternals.ReactCurrentOwner; + var ReactCurrentOwner$3 = ReactSharedInternals.ReactCurrentOwner; -function findHostInstance_DEPRECATED(componentOrHandle) { - { - var owner = ReactCurrentOwner$3.current; + function findHostInstance_DEPRECATED(componentOrHandle) { + { + var owner = ReactCurrentOwner$3.current; - if (owner !== null && owner.stateNode !== null) { - if (!owner.stateNode._warnedAboutRefsInRender) { - error( - "%s is accessing findNodeHandle inside its render(). " + - "render() should be a pure function of props and state. It should " + - "never access something that requires stale data from the previous " + - "render, such as refs. Move this logic to componentDidMount and " + - "componentDidUpdate instead.", - getComponentNameFromType(owner.type) || "A component" - ); + if (owner !== null && owner.stateNode !== null) { + if (!owner.stateNode._warnedAboutRefsInRender) { + error( + "%s is accessing findNodeHandle inside its render(). " + + "render() should be a pure function of props and state. It should " + + "never access something that requires stale data from the previous " + + "render, such as refs. Move this logic to componentDidMount and " + + "componentDidUpdate instead.", + getComponentNameFromType(owner.type) || "A component" + ); + } + + owner.stateNode._warnedAboutRefsInRender = true; + } } - owner.stateNode._warnedAboutRefsInRender = true; - } - } + if (componentOrHandle == null) { + return null; + } - if (componentOrHandle == null) { - return null; - } + if (componentOrHandle._nativeTag) { + return componentOrHandle; + } - if (componentOrHandle._nativeTag) { - return componentOrHandle; - } + if (componentOrHandle.canonical && componentOrHandle.canonical._nativeTag) { + return componentOrHandle.canonical; + } - if (componentOrHandle.canonical && componentOrHandle.canonical._nativeTag) { - return componentOrHandle.canonical; - } + var hostInstance; - var hostInstance; + { + hostInstance = findHostInstanceWithWarning( + componentOrHandle, + "findHostInstance_DEPRECATED" + ); + } - { - hostInstance = findHostInstanceWithWarning( - componentOrHandle, - "findHostInstance_DEPRECATED" - ); - } + if (hostInstance == null) { + return hostInstance; + } - if (hostInstance == null) { - return hostInstance; - } + if (hostInstance.canonical) { + // Fabric + return hostInstance.canonical; + } // $FlowFixMe[incompatible-return] - if (hostInstance.canonical) { - // Fabric - return hostInstance.canonical; - } // $FlowFixMe[incompatible-return] + return hostInstance; + } - return hostInstance; -} + function findNodeHandle(componentOrHandle) { + { + var owner = ReactCurrentOwner$3.current; -function findNodeHandle(componentOrHandle) { - { - var owner = ReactCurrentOwner$3.current; + if (owner !== null && owner.stateNode !== null) { + if (!owner.stateNode._warnedAboutRefsInRender) { + error( + "%s is accessing findNodeHandle inside its render(). " + + "render() should be a pure function of props and state. It should " + + "never access something that requires stale data from the previous " + + "render, such as refs. Move this logic to componentDidMount and " + + "componentDidUpdate instead.", + getComponentNameFromType(owner.type) || "A component" + ); + } - if (owner !== null && owner.stateNode !== null) { - if (!owner.stateNode._warnedAboutRefsInRender) { - error( - "%s is accessing findNodeHandle inside its render(). " + - "render() should be a pure function of props and state. It should " + - "never access something that requires stale data from the previous " + - "render, such as refs. Move this logic to componentDidMount and " + - "componentDidUpdate instead.", - getComponentNameFromType(owner.type) || "A component" - ); + owner.stateNode._warnedAboutRefsInRender = true; + } } - owner.stateNode._warnedAboutRefsInRender = true; - } - } - - if (componentOrHandle == null) { - return null; - } - - if (typeof componentOrHandle === "number") { - // Already a node handle - return componentOrHandle; - } + if (componentOrHandle == null) { + return null; + } - if (componentOrHandle._nativeTag) { - return componentOrHandle._nativeTag; - } + if (typeof componentOrHandle === "number") { + // Already a node handle + return componentOrHandle; + } - if (componentOrHandle.canonical && componentOrHandle.canonical._nativeTag) { - return componentOrHandle.canonical._nativeTag; - } + if (componentOrHandle._nativeTag) { + return componentOrHandle._nativeTag; + } - var hostInstance; + if (componentOrHandle.canonical && componentOrHandle.canonical._nativeTag) { + return componentOrHandle.canonical._nativeTag; + } - { - hostInstance = findHostInstanceWithWarning( - componentOrHandle, - "findNodeHandle" - ); - } + var hostInstance; - if (hostInstance == null) { - return hostInstance; - } + { + hostInstance = findHostInstanceWithWarning( + componentOrHandle, + "findNodeHandle" + ); + } - if (hostInstance.canonical) { - // Fabric - return hostInstance.canonical._nativeTag; - } + if (hostInstance == null) { + return hostInstance; + } - return hostInstance._nativeTag; -} + if (hostInstance.canonical) { + // Fabric + return hostInstance.canonical._nativeTag; + } -function dispatchCommand(handle, command, args) { - if (handle._nativeTag == null) { - { - error( - "dispatchCommand was called with a ref that isn't a " + - "native component. Use React.forwardRef to get access to the underlying native component" - ); + return hostInstance._nativeTag; } - return; - } + function dispatchCommand(handle, command, args) { + if (handle._nativeTag == null) { + { + error( + "dispatchCommand was called with a ref that isn't a " + + "native component. Use React.forwardRef to get access to the underlying native component" + ); + } - if (handle._internalInstanceHandle != null) { - var stateNode = handle._internalInstanceHandle.stateNode; + return; + } - if (stateNode != null) { - nativeFabricUIManager.dispatchCommand(stateNode.node, command, args); - } - } else { - ReactNativePrivateInterface.UIManager.dispatchViewManagerCommand( - handle._nativeTag, - command, - args - ); - } -} + if (handle._internalInstanceHandle != null) { + var stateNode = handle._internalInstanceHandle.stateNode; -function sendAccessibilityEvent(handle, eventType) { - if (handle._nativeTag == null) { - { - error( - "sendAccessibilityEvent was called with a ref that isn't a " + - "native component. Use React.forwardRef to get access to the underlying native component" - ); + if (stateNode != null) { + nativeFabricUIManager.dispatchCommand(stateNode.node, command, args); + } + } else { + ReactNativePrivateInterface.UIManager.dispatchViewManagerCommand( + handle._nativeTag, + command, + args + ); + } } - return; - } + function sendAccessibilityEvent(handle, eventType) { + if (handle._nativeTag == null) { + { + error( + "sendAccessibilityEvent was called with a ref that isn't a " + + "native component. Use React.forwardRef to get access to the underlying native component" + ); + } + + return; + } + + if (handle._internalInstanceHandle != null) { + var stateNode = handle._internalInstanceHandle.stateNode; - if (handle._internalInstanceHandle != null) { - var stateNode = handle._internalInstanceHandle.stateNode; + if (stateNode != null) { + nativeFabricUIManager.sendAccessibilityEvent(stateNode.node, eventType); + } + } else { + ReactNativePrivateInterface.legacySendAccessibilityEvent( + handle._nativeTag, + eventType + ); + } + } - if (stateNode != null) { - nativeFabricUIManager.sendAccessibilityEvent(stateNode.node, eventType); + function onRecoverableError(error$1) { + // TODO: Expose onRecoverableError option to userspace + // eslint-disable-next-line react-internal/no-production-logging, react-internal/warning-args + error(error$1); } - } else { - ReactNativePrivateInterface.legacySendAccessibilityEvent( - handle._nativeTag, - eventType - ); - } -} -function onRecoverableError(error$1) { - // TODO: Expose onRecoverableError option to userspace - // eslint-disable-next-line react-internal/no-production-logging, react-internal/warning-args - error(error$1); -} + function render(element, containerTag, callback) { + var root = roots.get(containerTag); -function render(element, containerTag, callback) { - var root = roots.get(containerTag); - - if (!root) { - // TODO (bvaughn): If we decide to keep the wrapper component, - // We could create a wrapper for containerTag as well to reduce special casing. - root = createContainer( - containerTag, - LegacyRoot, - null, - false, - null, - "", - onRecoverableError - ); - roots.set(containerTag, root); - } + if (!root) { + // TODO (bvaughn): If we decide to keep the wrapper component, + // We could create a wrapper for containerTag as well to reduce special casing. + root = createContainer( + containerTag, + LegacyRoot, + null, + false, + null, + "", + onRecoverableError + ); + roots.set(containerTag, root); + } - updateContainer(element, root, null, callback); // $FlowIssue Flow has hardcoded values for React DOM that don't work with RN + updateContainer(element, root, null, callback); // $FlowIssue Flow has hardcoded values for React DOM that don't work with RN - return getPublicRootInstance(root); -} + return getPublicRootInstance(root); + } -function unmountComponentAtNode(containerTag) { - var root = roots.get(containerTag); + function unmountComponentAtNode(containerTag) { + var root = roots.get(containerTag); - if (root) { - // TODO: Is it safe to reset this now or should I wait since this unmount could be deferred? - updateContainer(null, root, null, function() { - roots.delete(containerTag); - }); - } -} + if (root) { + // TODO: Is it safe to reset this now or should I wait since this unmount could be deferred? + updateContainer(null, root, null, function () { + roots.delete(containerTag); + }); + } + } -function unmountComponentAtNodeAndRemoveContainer(containerTag) { - unmountComponentAtNode(containerTag); // Call back into native to remove all of the subviews from this container + function unmountComponentAtNodeAndRemoveContainer(containerTag) { + unmountComponentAtNode(containerTag); // Call back into native to remove all of the subviews from this container - ReactNativePrivateInterface.UIManager.removeRootView(containerTag); -} + ReactNativePrivateInterface.UIManager.removeRootView(containerTag); + } -function createPortal$1(children, containerTag) { - var key = - arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; - return createPortal(children, containerTag, null, key); -} + function createPortal$1(children, containerTag) { + var key = + arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; + return createPortal(children, containerTag, null, key); + } -setBatchingImplementation(batchedUpdates$1); + setBatchingImplementation(batchedUpdates$1); -function computeComponentStackForErrorReporting(reactTag) { - var fiber = getInstanceFromTag(reactTag); + function computeComponentStackForErrorReporting(reactTag) { + var fiber = getInstanceFromTag(reactTag); - if (!fiber) { - return ""; - } + if (!fiber) { + return ""; + } - return getStackByFiberInDevAndProd(fiber); -} + return getStackByFiberInDevAndProd(fiber); + } -var roots = new Map(); -var Internals = { - computeComponentStackForErrorReporting: computeComponentStackForErrorReporting -}; -injectIntoDevTools({ - findFiberByHostInstance: getInstanceFromTag, - bundleType: 1, - version: ReactVersion, - rendererPackageName: "react-native-renderer", - rendererConfig: { - getInspectorDataForViewTag: getInspectorDataForViewTag, - getInspectorDataForViewAtPoint: getInspectorDataForViewAtPoint.bind( - null, - findNodeHandle - ) - } -}); - -exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = Internals; -exports.createPortal = createPortal$1; -exports.dispatchCommand = dispatchCommand; -exports.findHostInstance_DEPRECATED = findHostInstance_DEPRECATED; -exports.findNodeHandle = findNodeHandle; -exports.render = render; -exports.sendAccessibilityEvent = sendAccessibilityEvent; -exports.unmountComponentAtNode = unmountComponentAtNode; -exports.unmountComponentAtNodeAndRemoveContainer = unmountComponentAtNodeAndRemoveContainer; -exports.unstable_batchedUpdates = batchedUpdates; - - /* 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 roots = new Map(); + var Internals = { + computeComponentStackForErrorReporting: computeComponentStackForErrorReporting + }; + injectIntoDevTools({ + findFiberByHostInstance: getInstanceFromTag, + bundleType: 1, + version: ReactVersion, + rendererPackageName: "react-native-renderer", + rendererConfig: { + getInspectorDataForViewTag: getInspectorDataForViewTag, + getInspectorDataForViewAtPoint: getInspectorDataForViewAtPoint.bind( + null, + findNodeHandle + ) + } + }); + + exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = Internals; + exports.createPortal = createPortal$1; + exports.dispatchCommand = dispatchCommand; + exports.findHostInstance_DEPRECATED = findHostInstance_DEPRECATED; + exports.findNodeHandle = findNodeHandle; + exports.render = render; + exports.sendAccessibilityEvent = sendAccessibilityEvent; + exports.unmountComponentAtNode = unmountComponentAtNode; + exports.unmountComponentAtNodeAndRemoveContainer = unmountComponentAtNodeAndRemoveContainer; + exports.unstable_batchedUpdates = batchedUpdates; + + /* 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/node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-prod.js b/node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-prod.js index d1b2a91..49f5115 100644 --- a/node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-prod.js +++ b/node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-prod.js @@ -12,7 +12,14 @@ */ "use strict"; +import defrost from '@d11/de-frost' + require("react-native/Libraries/ReactPrivate/ReactNativePrivateInitializeCore"); +var updatedComponents = []; +var updatedComponentForProfiler = null; +function insertUpdateComponents(componentName, flags, key) { + updatedComponents.push({ componentName, flags, key }); +} var ReactNativePrivateInterface = require("react-native/Libraries/ReactPrivate/ReactNativePrivateInterface"), React = require("react"), Scheduler = require("scheduler"); @@ -29,7 +36,7 @@ var hasError = !1, hasRethrowError = !1, rethrowError = null, reporter = { - onError: function(error) { + onError: function (error) { hasError = !0; caughtError = error; } @@ -110,39 +117,39 @@ function SyntheticEvent( ((targetInst = dispatchConfig[propName]) ? (this[propName] = targetInst(nativeEvent)) : "target" === propName - ? (this.target = nativeEventTarget) - : (this[propName] = nativeEvent[propName])); + ? (this.target = nativeEventTarget) + : (this[propName] = nativeEvent[propName])); this.isDefaultPrevented = (null != nativeEvent.defaultPrevented - ? nativeEvent.defaultPrevented - : !1 === nativeEvent.returnValue) + ? nativeEvent.defaultPrevented + : !1 === nativeEvent.returnValue) ? functionThatReturnsTrue : functionThatReturnsFalse; this.isPropagationStopped = functionThatReturnsFalse; return this; } assign(SyntheticEvent.prototype, { - preventDefault: function() { + preventDefault: function () { this.defaultPrevented = !0; var event = this.nativeEvent; event && (event.preventDefault ? event.preventDefault() : "unknown" !== typeof event.returnValue && (event.returnValue = !1), - (this.isDefaultPrevented = functionThatReturnsTrue)); + (this.isDefaultPrevented = functionThatReturnsTrue)); }, - stopPropagation: function() { + stopPropagation: function () { var event = this.nativeEvent; event && (event.stopPropagation ? event.stopPropagation() : "unknown" !== typeof event.cancelBubble && (event.cancelBubble = !0), - (this.isPropagationStopped = functionThatReturnsTrue)); + (this.isPropagationStopped = functionThatReturnsTrue)); }, - persist: function() { + persist: function () { this.isPersistent = functionThatReturnsTrue; }, isPersistent: functionThatReturnsFalse, - destructor: function() { + destructor: function () { var Interface = this.constructor.Interface, propName; for (propName in Interface) this[propName] = null; @@ -154,20 +161,20 @@ assign(SyntheticEvent.prototype, { SyntheticEvent.Interface = { type: null, target: null, - currentTarget: function() { + currentTarget: function () { return null; }, eventPhase: null, bubbles: null, cancelable: null, - timeStamp: function(event) { + timeStamp: function (event) { return event.timeStamp || Date.now(); }, defaultPrevented: null, isTrusted: null }; -SyntheticEvent.extend = function(Interface) { - function E() {} +SyntheticEvent.extend = function (Interface) { + function E() { } function Class() { return Super.apply(this, arguments); } @@ -210,7 +217,7 @@ function addEventPoolingTo(EventConstructor) { EventConstructor.release = releasePooledEvent; } var ResponderSyntheticEvent = SyntheticEvent.extend({ - touchHistory: function() { + touchHistory: function () { return null; } }); @@ -253,17 +260,17 @@ function recordTouchStart(touch) { (touchRecord.previousPageY = touch.pageY), (touchRecord.previousTimeStamp = timestampForTouch(touch))) : ((touchRecord = { - touchActive: !0, - startPageX: touch.pageX, - startPageY: touch.pageY, - startTimeStamp: timestampForTouch(touch), - currentPageX: touch.pageX, - currentPageY: touch.pageY, - currentTimeStamp: timestampForTouch(touch), - previousPageX: touch.pageX, - previousPageY: touch.pageY, - previousTimeStamp: timestampForTouch(touch) - }), + touchActive: !0, + startPageX: touch.pageX, + startPageY: touch.pageY, + startTimeStamp: timestampForTouch(touch), + currentPageX: touch.pageX, + currentPageY: touch.pageY, + currentTimeStamp: timestampForTouch(touch), + previousPageX: touch.pageX, + previousPageY: touch.pageY, + previousTimeStamp: timestampForTouch(touch) + }), (touchBank[identifier] = touchRecord)); touchHistory.mostRecentTimeStamp = timestampForTouch(touch); } @@ -271,32 +278,32 @@ function recordTouchMove(touch) { var touchRecord = touchBank[getTouchIdentifier(touch)]; touchRecord && ((touchRecord.touchActive = !0), - (touchRecord.previousPageX = touchRecord.currentPageX), - (touchRecord.previousPageY = touchRecord.currentPageY), - (touchRecord.previousTimeStamp = touchRecord.currentTimeStamp), - (touchRecord.currentPageX = touch.pageX), - (touchRecord.currentPageY = touch.pageY), - (touchRecord.currentTimeStamp = timestampForTouch(touch)), - (touchHistory.mostRecentTimeStamp = timestampForTouch(touch))); + (touchRecord.previousPageX = touchRecord.currentPageX), + (touchRecord.previousPageY = touchRecord.currentPageY), + (touchRecord.previousTimeStamp = touchRecord.currentTimeStamp), + (touchRecord.currentPageX = touch.pageX), + (touchRecord.currentPageY = touch.pageY), + (touchRecord.currentTimeStamp = timestampForTouch(touch)), + (touchHistory.mostRecentTimeStamp = timestampForTouch(touch))); } function recordTouchEnd(touch) { var touchRecord = touchBank[getTouchIdentifier(touch)]; touchRecord && ((touchRecord.touchActive = !1), - (touchRecord.previousPageX = touchRecord.currentPageX), - (touchRecord.previousPageY = touchRecord.currentPageY), - (touchRecord.previousTimeStamp = touchRecord.currentTimeStamp), - (touchRecord.currentPageX = touch.pageX), - (touchRecord.currentPageY = touch.pageY), - (touchRecord.currentTimeStamp = timestampForTouch(touch)), - (touchHistory.mostRecentTimeStamp = timestampForTouch(touch))); + (touchRecord.previousPageX = touchRecord.currentPageX), + (touchRecord.previousPageY = touchRecord.currentPageY), + (touchRecord.previousTimeStamp = touchRecord.currentTimeStamp), + (touchRecord.currentPageX = touch.pageX), + (touchRecord.currentPageY = touch.pageY), + (touchRecord.currentTimeStamp = timestampForTouch(touch)), + (touchHistory.mostRecentTimeStamp = timestampForTouch(touch))); } var instrumentationCallback, ResponderTouchHistoryStore = { - instrument: function(callback) { + instrument: function (callback) { instrumentationCallback = callback; }, - recordTouchTrack: function(topLevelType, nativeEvent) { + recordTouchTrack: function (topLevelType, nativeEvent) { null != instrumentationCallback && instrumentationCallback(topLevelType, nativeEvent); if (isMoveish(topLevelType)) @@ -305,16 +312,16 @@ var instrumentationCallback, nativeEvent.changedTouches.forEach(recordTouchStart), (touchHistory.numberActiveTouches = nativeEvent.touches.length), 1 === touchHistory.numberActiveTouches && - (touchHistory.indexOfSingleActiveTouch = - nativeEvent.touches[0].identifier); + (touchHistory.indexOfSingleActiveTouch = + nativeEvent.touches[0].identifier); else if ( "topTouchEnd" === topLevelType || "topTouchCancel" === topLevelType ) if ( (nativeEvent.changedTouches.forEach(recordTouchEnd), - (touchHistory.numberActiveTouches = nativeEvent.touches.length), - 1 === touchHistory.numberActiveTouches) + (touchHistory.numberActiveTouches = nativeEvent.touches.length), + 1 === touchHistory.numberActiveTouches) ) for ( topLevelType = 0; @@ -323,7 +330,7 @@ var instrumentationCallback, ) if ( ((nativeEvent = touchBank[topLevelType]), - null != nativeEvent && nativeEvent.touchActive) + null != nativeEvent && nativeEvent.touchActive) ) { touchHistory.indexOfSingleActiveTouch = topLevelType; break; @@ -339,10 +346,10 @@ function accumulate(current, next) { return null == current ? next : isArrayImpl(current) - ? current.concat(next) - : isArrayImpl(next) - ? [current].concat(next) - : [current, next]; + ? current.concat(next) + : isArrayImpl(next) + ? [current].concat(next) + : [current, next]; } function accumulateInto(current, next) { if (null == next) @@ -434,8 +441,8 @@ function getParent(inst) { return inst ? inst : null; } function traverseTwoPhase(inst, fn, arg) { - for (var path = []; inst; ) path.push(inst), (inst = getParent(inst)); - for (inst = path.length; 0 < inst--; ) fn(path[inst], "captured", arg); + for (var path = []; inst;) path.push(inst), (inst = getParent(inst)); + for (inst = path.length; 0 < inst--;) fn(path[inst], "captured", arg); for (inst = 0; inst < path.length; inst++) fn(path[inst], "bubbled", arg); } function getListener(inst, registrationName) { @@ -446,10 +453,10 @@ function getListener(inst, registrationName) { if ((inst = inst[registrationName]) && "function" !== typeof inst) throw Error( "Expected `" + - registrationName + - "` listener to be a function, instead got a value of `" + - typeof inst + - "` type." + registrationName + + "` listener to be a function, instead got a value of `" + + typeof inst + + "` type." ); return inst; } @@ -479,10 +486,10 @@ function accumulateDirectDispatchesSingle(event) { event._dispatchListeners, listener )), - (event._dispatchInstances = accumulateInto( - event._dispatchInstances, - inst - ))); + (event._dispatchInstances = accumulateInto( + event._dispatchInstances, + inst + ))); } } } @@ -499,123 +506,123 @@ function accumulateTwoPhaseDispatchesSingle(event) { traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event); } var ResponderEventPlugin = { - _getResponder: function() { - return responderInst; - }, - eventTypes: eventTypes, - extractEvents: function( - topLevelType, - targetInst, - nativeEvent, - nativeEventTarget + _getResponder: function () { + return responderInst; + }, + eventTypes: eventTypes, + extractEvents: function ( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget + ) { + if (isStartish(topLevelType)) trackedTouchCount += 1; + else if ( + "topTouchEnd" === topLevelType || + "topTouchCancel" === topLevelType + ) + if (0 <= trackedTouchCount) --trackedTouchCount; + else return null; + ResponderTouchHistoryStore.recordTouchTrack(topLevelType, nativeEvent); + if ( + targetInst && + (("topScroll" === topLevelType && !nativeEvent.responderIgnoreScroll) || + (0 < trackedTouchCount && "topSelectionChange" === topLevelType) || + isStartish(topLevelType) || + isMoveish(topLevelType)) ) { - if (isStartish(topLevelType)) trackedTouchCount += 1; - else if ( - "topTouchEnd" === topLevelType || - "topTouchCancel" === topLevelType - ) - if (0 <= trackedTouchCount) --trackedTouchCount; - else return null; - ResponderTouchHistoryStore.recordTouchTrack(topLevelType, nativeEvent); - if ( - targetInst && - (("topScroll" === topLevelType && !nativeEvent.responderIgnoreScroll) || - (0 < trackedTouchCount && "topSelectionChange" === topLevelType) || - isStartish(topLevelType) || - isMoveish(topLevelType)) - ) { - var shouldSetEventType = isStartish(topLevelType) - ? eventTypes.startShouldSetResponder - : isMoveish(topLevelType) + var shouldSetEventType = isStartish(topLevelType) + ? eventTypes.startShouldSetResponder + : isMoveish(topLevelType) ? eventTypes.moveShouldSetResponder : "topSelectionChange" === topLevelType - ? eventTypes.selectionChangeShouldSetResponder - : eventTypes.scrollShouldSetResponder; - if (responderInst) - b: { - var JSCompiler_temp = responderInst; - for ( - var depthA = 0, tempA = JSCompiler_temp; - tempA; - tempA = getParent(tempA) + ? eventTypes.selectionChangeShouldSetResponder + : eventTypes.scrollShouldSetResponder; + if (responderInst) + b: { + var JSCompiler_temp = responderInst; + for ( + var depthA = 0, tempA = JSCompiler_temp; + tempA; + tempA = getParent(tempA) + ) + depthA++; + tempA = 0; + for (var tempB = targetInst; tempB; tempB = getParent(tempB)) + tempA++; + for (; 0 < depthA - tempA;) + (JSCompiler_temp = getParent(JSCompiler_temp)), depthA--; + for (; 0 < tempA - depthA;) + (targetInst = getParent(targetInst)), tempA--; + for (; depthA--;) { + if ( + JSCompiler_temp === targetInst || + JSCompiler_temp === targetInst.alternate ) - depthA++; - tempA = 0; - for (var tempB = targetInst; tempB; tempB = getParent(tempB)) - tempA++; - for (; 0 < depthA - tempA; ) - (JSCompiler_temp = getParent(JSCompiler_temp)), depthA--; - for (; 0 < tempA - depthA; ) - (targetInst = getParent(targetInst)), tempA--; - for (; depthA--; ) { - if ( - JSCompiler_temp === targetInst || - JSCompiler_temp === targetInst.alternate - ) - break b; - JSCompiler_temp = getParent(JSCompiler_temp); - targetInst = getParent(targetInst); - } - JSCompiler_temp = null; + break b; + JSCompiler_temp = getParent(JSCompiler_temp); + targetInst = getParent(targetInst); } - else JSCompiler_temp = targetInst; - targetInst = JSCompiler_temp; - JSCompiler_temp = targetInst === responderInst; - shouldSetEventType = ResponderSyntheticEvent.getPooled( + JSCompiler_temp = null; + } + else JSCompiler_temp = targetInst; + targetInst = JSCompiler_temp; + JSCompiler_temp = targetInst === responderInst; + shouldSetEventType = ResponderSyntheticEvent.getPooled( + shouldSetEventType, + targetInst, + nativeEvent, + nativeEventTarget + ); + shouldSetEventType.touchHistory = + ResponderTouchHistoryStore.touchHistory; + JSCompiler_temp + ? forEachAccumulated( shouldSetEventType, - targetInst, - nativeEvent, - nativeEventTarget + accumulateTwoPhaseDispatchesSingleSkipTarget + ) + : forEachAccumulated( + shouldSetEventType, + accumulateTwoPhaseDispatchesSingle ); - shouldSetEventType.touchHistory = - ResponderTouchHistoryStore.touchHistory; - JSCompiler_temp - ? forEachAccumulated( - shouldSetEventType, - accumulateTwoPhaseDispatchesSingleSkipTarget - ) - : forEachAccumulated( - shouldSetEventType, - accumulateTwoPhaseDispatchesSingle - ); - b: { - JSCompiler_temp = shouldSetEventType._dispatchListeners; - targetInst = shouldSetEventType._dispatchInstances; - if (isArrayImpl(JSCompiler_temp)) - for ( - depthA = 0; - depthA < JSCompiler_temp.length && - !shouldSetEventType.isPropagationStopped(); - depthA++ + b: { + JSCompiler_temp = shouldSetEventType._dispatchListeners; + targetInst = shouldSetEventType._dispatchInstances; + if (isArrayImpl(JSCompiler_temp)) + for ( + depthA = 0; + depthA < JSCompiler_temp.length && + !shouldSetEventType.isPropagationStopped(); + depthA++ + ) { + if ( + JSCompiler_temp[depthA](shouldSetEventType, targetInst[depthA]) ) { - if ( - JSCompiler_temp[depthA](shouldSetEventType, targetInst[depthA]) - ) { - JSCompiler_temp = targetInst[depthA]; - break b; - } + JSCompiler_temp = targetInst[depthA]; + break b; } - else if ( - JSCompiler_temp && - JSCompiler_temp(shouldSetEventType, targetInst) - ) { - JSCompiler_temp = targetInst; - break b; } - JSCompiler_temp = null; + else if ( + JSCompiler_temp && + JSCompiler_temp(shouldSetEventType, targetInst) + ) { + JSCompiler_temp = targetInst; + break b; } - shouldSetEventType._dispatchInstances = null; - shouldSetEventType._dispatchListeners = null; - shouldSetEventType.isPersistent() || - shouldSetEventType.constructor.release(shouldSetEventType); - if (JSCompiler_temp && JSCompiler_temp !== responderInst) - if ( - ((shouldSetEventType = ResponderSyntheticEvent.getPooled( - eventTypes.responderGrant, - JSCompiler_temp, - nativeEvent, - nativeEventTarget - )), + JSCompiler_temp = null; + } + shouldSetEventType._dispatchInstances = null; + shouldSetEventType._dispatchListeners = null; + shouldSetEventType.isPersistent() || + shouldSetEventType.constructor.release(shouldSetEventType); + if (JSCompiler_temp && JSCompiler_temp !== responderInst) + if ( + ((shouldSetEventType = ResponderSyntheticEvent.getPooled( + eventTypes.responderGrant, + JSCompiler_temp, + nativeEvent, + nativeEventTarget + )), (shouldSetEventType.touchHistory = ResponderTouchHistoryStore.touchHistory), forEachAccumulated( @@ -624,159 +631,159 @@ var ResponderEventPlugin = { ), (targetInst = !0 === executeDirectDispatch(shouldSetEventType)), responderInst) - ) - if ( - ((depthA = ResponderSyntheticEvent.getPooled( - eventTypes.responderTerminationRequest, - responderInst, - nativeEvent, - nativeEventTarget - )), + ) + if ( + ((depthA = ResponderSyntheticEvent.getPooled( + eventTypes.responderTerminationRequest, + responderInst, + nativeEvent, + nativeEventTarget + )), (depthA.touchHistory = ResponderTouchHistoryStore.touchHistory), forEachAccumulated(depthA, accumulateDirectDispatchesSingle), (tempA = !depthA._dispatchListeners || executeDirectDispatch(depthA)), depthA.isPersistent() || depthA.constructor.release(depthA), tempA) - ) { - depthA = ResponderSyntheticEvent.getPooled( - eventTypes.responderTerminate, - responderInst, - nativeEvent, - nativeEventTarget - ); - depthA.touchHistory = ResponderTouchHistoryStore.touchHistory; - forEachAccumulated(depthA, accumulateDirectDispatchesSingle); - var JSCompiler_temp$jscomp$0 = accumulate( - JSCompiler_temp$jscomp$0, - [shouldSetEventType, depthA] - ); - changeResponder(JSCompiler_temp, targetInst); - } else - (shouldSetEventType = ResponderSyntheticEvent.getPooled( - eventTypes.responderReject, - JSCompiler_temp, - nativeEvent, - nativeEventTarget - )), - (shouldSetEventType.touchHistory = - ResponderTouchHistoryStore.touchHistory), - forEachAccumulated( - shouldSetEventType, - accumulateDirectDispatchesSingle - ), - (JSCompiler_temp$jscomp$0 = accumulate( - JSCompiler_temp$jscomp$0, - shouldSetEventType - )); - else - (JSCompiler_temp$jscomp$0 = accumulate( + ) { + depthA = ResponderSyntheticEvent.getPooled( + eventTypes.responderTerminate, + responderInst, + nativeEvent, + nativeEventTarget + ); + depthA.touchHistory = ResponderTouchHistoryStore.touchHistory; + forEachAccumulated(depthA, accumulateDirectDispatchesSingle); + var JSCompiler_temp$jscomp$0 = accumulate( JSCompiler_temp$jscomp$0, - shouldSetEventType + [shouldSetEventType, depthA] + ); + changeResponder(JSCompiler_temp, targetInst); + } else + (shouldSetEventType = ResponderSyntheticEvent.getPooled( + eventTypes.responderReject, + JSCompiler_temp, + nativeEvent, + nativeEventTarget )), - changeResponder(JSCompiler_temp, targetInst); - else JSCompiler_temp$jscomp$0 = null; - } else JSCompiler_temp$jscomp$0 = null; - shouldSetEventType = responderInst && isStartish(topLevelType); - JSCompiler_temp = responderInst && isMoveish(topLevelType); - targetInst = - responderInst && - ("topTouchEnd" === topLevelType || "topTouchCancel" === topLevelType); - if ( - (shouldSetEventType = shouldSetEventType - ? eventTypes.responderStart - : JSCompiler_temp - ? eventTypes.responderMove - : targetInst - ? eventTypes.responderEnd - : null) - ) - (shouldSetEventType = ResponderSyntheticEvent.getPooled( - shouldSetEventType, - responderInst, - nativeEvent, - nativeEventTarget - )), - (shouldSetEventType.touchHistory = - ResponderTouchHistoryStore.touchHistory), - forEachAccumulated( - shouldSetEventType, - accumulateDirectDispatchesSingle - ), + (shouldSetEventType.touchHistory = + ResponderTouchHistoryStore.touchHistory), + forEachAccumulated( + shouldSetEventType, + accumulateDirectDispatchesSingle + ), + (JSCompiler_temp$jscomp$0 = accumulate( + JSCompiler_temp$jscomp$0, + shouldSetEventType + )); + else (JSCompiler_temp$jscomp$0 = accumulate( JSCompiler_temp$jscomp$0, shouldSetEventType - )); - shouldSetEventType = responderInst && "topTouchCancel" === topLevelType; - if ( - (topLevelType = - responderInst && - !shouldSetEventType && - ("topTouchEnd" === topLevelType || "topTouchCancel" === topLevelType)) - ) - a: { - if ((topLevelType = nativeEvent.touches) && 0 !== topLevelType.length) - for ( - JSCompiler_temp = 0; - JSCompiler_temp < topLevelType.length; - JSCompiler_temp++ - ) - if ( - ((targetInst = topLevelType[JSCompiler_temp].target), + )), + changeResponder(JSCompiler_temp, targetInst); + else JSCompiler_temp$jscomp$0 = null; + } else JSCompiler_temp$jscomp$0 = null; + shouldSetEventType = responderInst && isStartish(topLevelType); + JSCompiler_temp = responderInst && isMoveish(topLevelType); + targetInst = + responderInst && + ("topTouchEnd" === topLevelType || "topTouchCancel" === topLevelType); + if ( + (shouldSetEventType = shouldSetEventType + ? eventTypes.responderStart + : JSCompiler_temp + ? eventTypes.responderMove + : targetInst + ? eventTypes.responderEnd + : null) + ) + (shouldSetEventType = ResponderSyntheticEvent.getPooled( + shouldSetEventType, + responderInst, + nativeEvent, + nativeEventTarget + )), + (shouldSetEventType.touchHistory = + ResponderTouchHistoryStore.touchHistory), + forEachAccumulated( + shouldSetEventType, + accumulateDirectDispatchesSingle + ), + (JSCompiler_temp$jscomp$0 = accumulate( + JSCompiler_temp$jscomp$0, + shouldSetEventType + )); + shouldSetEventType = responderInst && "topTouchCancel" === topLevelType; + if ( + (topLevelType = + responderInst && + !shouldSetEventType && + ("topTouchEnd" === topLevelType || "topTouchCancel" === topLevelType)) + ) + a: { + if ((topLevelType = nativeEvent.touches) && 0 !== topLevelType.length) + for ( + JSCompiler_temp = 0; + JSCompiler_temp < topLevelType.length; + JSCompiler_temp++ + ) + if ( + ((targetInst = topLevelType[JSCompiler_temp].target), null !== targetInst && - void 0 !== targetInst && - 0 !== targetInst) - ) { - depthA = getInstanceFromNode(targetInst); - b: { - for (targetInst = responderInst; depthA; ) { - if ( - targetInst === depthA || - targetInst === depthA.alternate - ) { - targetInst = !0; - break b; - } - depthA = getParent(depthA); + void 0 !== targetInst && + 0 !== targetInst) + ) { + depthA = getInstanceFromNode(targetInst); + b: { + for (targetInst = responderInst; depthA;) { + if ( + targetInst === depthA || + targetInst === depthA.alternate + ) { + targetInst = !0; + break b; } - targetInst = !1; - } - if (targetInst) { - topLevelType = !1; - break a; + depthA = getParent(depthA); } + targetInst = !1; } - topLevelType = !0; - } - if ( - (topLevelType = shouldSetEventType - ? eventTypes.responderTerminate - : topLevelType + if (targetInst) { + topLevelType = !1; + break a; + } + } + topLevelType = !0; + } + if ( + (topLevelType = shouldSetEventType + ? eventTypes.responderTerminate + : topLevelType ? eventTypes.responderRelease : null) - ) - (nativeEvent = ResponderSyntheticEvent.getPooled( - topLevelType, - responderInst, - nativeEvent, - nativeEventTarget + ) + (nativeEvent = ResponderSyntheticEvent.getPooled( + topLevelType, + responderInst, + nativeEvent, + nativeEventTarget + )), + (nativeEvent.touchHistory = ResponderTouchHistoryStore.touchHistory), + forEachAccumulated(nativeEvent, accumulateDirectDispatchesSingle), + (JSCompiler_temp$jscomp$0 = accumulate( + JSCompiler_temp$jscomp$0, + nativeEvent )), - (nativeEvent.touchHistory = ResponderTouchHistoryStore.touchHistory), - forEachAccumulated(nativeEvent, accumulateDirectDispatchesSingle), - (JSCompiler_temp$jscomp$0 = accumulate( - JSCompiler_temp$jscomp$0, - nativeEvent - )), - changeResponder(null); - return JSCompiler_temp$jscomp$0; - }, - GlobalResponderHandler: null, - injection: { - injectGlobalResponderHandler: function(GlobalResponderHandler) { - ResponderEventPlugin.GlobalResponderHandler = GlobalResponderHandler; - } - } + changeResponder(null); + return JSCompiler_temp$jscomp$0; }, + GlobalResponderHandler: null, + injection: { + injectGlobalResponderHandler: function (GlobalResponderHandler) { + ResponderEventPlugin.GlobalResponderHandler = GlobalResponderHandler; + } + } +}, eventPluginOrder = null, namesToPlugins = {}; function recomputePluginOrdering() { @@ -787,13 +794,13 @@ function recomputePluginOrdering() { if (-1 >= pluginIndex) throw Error( "EventPluginRegistry: Cannot inject event plugins that do not exist in the plugin ordering, `" + - (pluginName + "`.") + (pluginName + "`.") ); if (!plugins[pluginIndex]) { if (!pluginModule.extractEvents) throw Error( "EventPluginRegistry: Event plugins must implement an `extractEvents` method, but `" + - (pluginName + "` does not.") + (pluginName + "` does not.") ); plugins[pluginIndex] = pluginModule; pluginIndex = pluginModule.eventTypes; @@ -804,7 +811,7 @@ function recomputePluginOrdering() { if (eventNameDispatchConfigs.hasOwnProperty(eventName$jscomp$0)) throw Error( "EventPluginRegistry: More than one plugin attempted to publish the same event name, `" + - (eventName$jscomp$0 + "`.") + (eventName$jscomp$0 + "`.") ); eventNameDispatchConfigs[eventName$jscomp$0] = dispatchConfig; var phasedRegistrationNames = dispatchConfig.phasedRegistrationNames; @@ -822,19 +829,19 @@ function recomputePluginOrdering() { } else dispatchConfig.registrationName ? (publishRegistrationName( - dispatchConfig.registrationName, - pluginModule, - eventName$jscomp$0 - ), + dispatchConfig.registrationName, + pluginModule, + eventName$jscomp$0 + ), (JSCompiler_inline_result = !0)) : (JSCompiler_inline_result = !1); if (!JSCompiler_inline_result) throw Error( "EventPluginRegistry: Failed to publish event `" + - eventName + - "` for plugin `" + - pluginName + - "`." + eventName + + "` for plugin `" + + pluginName + + "`." ); } } @@ -844,7 +851,7 @@ function publishRegistrationName(registrationName, pluginModule) { if (registrationNameModules[registrationName]) throw Error( "EventPluginRegistry: More than one plugin attempted to publish the same registration name, `" + - (registrationName + "`.") + (registrationName + "`.") ); registrationNameModules[registrationName] = pluginModule; } @@ -864,10 +871,10 @@ function getListeners( if ((inst = inst[registrationName]) && "function" !== typeof inst) throw Error( "Expected `" + - registrationName + - "` listener to be a function, instead got a value of `" + - typeof inst + - "` type." + registrationName + + "` listener to be a function, instead got a value of `" + + typeof inst + + "` type." ); if ( !( @@ -885,16 +892,16 @@ function getListeners( : "rn:" + registrationName; stateNode.canonical._eventListeners[mangledImperativeRegistrationName] && 0 < - stateNode.canonical._eventListeners[mangledImperativeRegistrationName] - .length && + stateNode.canonical._eventListeners[mangledImperativeRegistrationName] + .length && stateNode.canonical._eventListeners[ mangledImperativeRegistrationName - ].forEach(function(listenerObj) { + ].forEach(function (listenerObj) { if ( (null != listenerObj.options.capture && listenerObj.options.capture) === requestedPhaseIsCapture ) { - var listenerFnWrapper = function(syntheticEvent) { + var listenerFnWrapper = function (syntheticEvent) { var eventInst = new ReactNativePrivateInterface.CustomEvent( mangledImperativeRegistrationName, { detail: syntheticEvent.nativeEvent } @@ -903,8 +910,8 @@ function getListeners( eventInst.setSyntheticEvent(syntheticEvent); for ( var _len = arguments.length, - args = Array(1 < _len ? _len - 1 : 0), - _key = 1; + args = Array(1 < _len ? _len - 1 : 0), + _key = 1; _key < _len; _key++ ) @@ -912,28 +919,28 @@ function getListeners( listenerObj.listener.apply(listenerObj, [eventInst].concat(args)); }; listenerObj.options.once - ? listeners.push(function() { - stateNode.canonical.removeEventListener_unstable( - mangledImperativeRegistrationName, - listenerObj.listener, - listenerObj.capture - ); - listenerObj.invalidated || - ((listenerObj.invalidated = !0), + ? listeners.push(function () { + stateNode.canonical.removeEventListener_unstable( + mangledImperativeRegistrationName, + listenerObj.listener, + listenerObj.capture + ); + listenerObj.invalidated || + ((listenerObj.invalidated = !0), listenerObj.listener.apply(listenerObj, arguments)); - }) + }) : listeners.push(listenerFnWrapper); } }); return 0 === listeners.length ? null : 1 === listeners.length - ? listeners[0] - : listeners; + ? listeners[0] + : listeners; } var customBubblingEventTypes = - ReactNativePrivateInterface.ReactNativeViewConfigRegistry - .customBubblingEventTypes, + ReactNativePrivateInterface.ReactNativeViewConfigRegistry + .customBubblingEventTypes, customDirectEventTypes = ReactNativePrivateInterface.ReactNativeViewConfigRegistry .customDirectEventTypes; @@ -949,15 +956,15 @@ function accumulateListenersAndInstances(inst, event, listeners) { event._dispatchListeners, listeners )), - null == event._dispatchInstances && 1 === listenersLength) + null == event._dispatchInstances && 1 === listenersLength) ) event._dispatchInstances = inst; else for ( event._dispatchInstances = event._dispatchInstances || [], - isArrayImpl(event._dispatchInstances) || - (event._dispatchInstances = [event._dispatchInstances]), - listeners = 0; + isArrayImpl(event._dispatchInstances) || + (event._dispatchInstances = [event._dispatchInstances]), + listeners = 0; listeners < listenersLength; listeners++ ) @@ -973,13 +980,13 @@ function accumulateDirectionalDispatches$1(inst, phase, event) { accumulateListenersAndInstances(inst, event, phase); } function traverseTwoPhase$1(inst, fn, arg, skipBubbling) { - for (var path = []; inst; ) { + for (var path = []; inst;) { path.push(inst); do inst = inst.return; while (inst && 5 !== inst.tag); inst = inst ? inst : null; } - for (inst = path.length; 0 < inst--; ) fn(path[inst], "captured", arg); + for (inst = path.length; 0 < inst--;) fn(path[inst], "captured", arg); if (skipBubbling) fn(path[0], "bubbled", arg); else for (inst = 0; inst < path.length; inst++) fn(path[inst], "bubbled", arg); @@ -1018,51 +1025,51 @@ eventPluginOrder = Array.prototype.slice.call([ ]); recomputePluginOrdering(); var injectedNamesToPlugins$jscomp$inline_229 = { - ResponderEventPlugin: ResponderEventPlugin, - ReactNativeBridgeEventPlugin: { - eventTypes: {}, - extractEvents: function( - topLevelType, + ResponderEventPlugin: ResponderEventPlugin, + ReactNativeBridgeEventPlugin: { + eventTypes: {}, + extractEvents: function ( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget + ) { + if (null == targetInst) return null; + var bubbleDispatchConfig = customBubblingEventTypes[topLevelType], + directDispatchConfig = customDirectEventTypes[topLevelType]; + if (!bubbleDispatchConfig && !directDispatchConfig) + throw Error( + 'Unsupported top level event type "' + topLevelType + '" dispatched' + ); + topLevelType = SyntheticEvent.getPooled( + bubbleDispatchConfig || directDispatchConfig, targetInst, nativeEvent, nativeEventTarget - ) { - if (null == targetInst) return null; - var bubbleDispatchConfig = customBubblingEventTypes[topLevelType], - directDispatchConfig = customDirectEventTypes[topLevelType]; - if (!bubbleDispatchConfig && !directDispatchConfig) - throw Error( - 'Unsupported top level event type "' + topLevelType + '" dispatched' - ); - topLevelType = SyntheticEvent.getPooled( - bubbleDispatchConfig || directDispatchConfig, - targetInst, - nativeEvent, - nativeEventTarget - ); - if (bubbleDispatchConfig) - null != topLevelType && + ); + if (bubbleDispatchConfig) + null != topLevelType && null != topLevelType.dispatchConfig.phasedRegistrationNames && topLevelType.dispatchConfig.phasedRegistrationNames.skipBubbling - ? topLevelType && - topLevelType.dispatchConfig.phasedRegistrationNames && - traverseTwoPhase$1( - topLevelType._targetInst, - accumulateDirectionalDispatches$1, - topLevelType, - !0 - ) - : forEachAccumulated( - topLevelType, - accumulateTwoPhaseDispatchesSingle$1 - ); - else if (directDispatchConfig) - forEachAccumulated(topLevelType, accumulateDirectDispatchesSingle$1); - else return null; - return topLevelType; - } + ? topLevelType && + topLevelType.dispatchConfig.phasedRegistrationNames && + traverseTwoPhase$1( + topLevelType._targetInst, + accumulateDirectionalDispatches$1, + topLevelType, + !0 + ) + : forEachAccumulated( + topLevelType, + accumulateTwoPhaseDispatchesSingle$1 + ); + else if (directDispatchConfig) + forEachAccumulated(topLevelType, accumulateDirectDispatchesSingle$1); + else return null; + return topLevelType; } - }, + } +}, isOrderingDirty$jscomp$inline_230 = !1, pluginName$jscomp$inline_231; for (pluginName$jscomp$inline_231 in injectedNamesToPlugins$jscomp$inline_229) @@ -1076,12 +1083,12 @@ for (pluginName$jscomp$inline_231 in injectedNamesToPlugins$jscomp$inline_229) if ( !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_231) || namesToPlugins[pluginName$jscomp$inline_231] !== - pluginModule$jscomp$inline_232 + pluginModule$jscomp$inline_232 ) { if (namesToPlugins[pluginName$jscomp$inline_231]) throw Error( "EventPluginRegistry: Cannot inject two different event plugins using the same name, `" + - (pluginName$jscomp$inline_231 + "`.") + (pluginName$jscomp$inline_231 + "`.") ); namesToPlugins[ pluginName$jscomp$inline_231 @@ -1134,7 +1141,7 @@ function _receiveRootNodeIDEvent(rootNodeID, topLevelType, nativeEventParam) { inst = getInstanceFromTag(rootNodeID), target = null; null != inst && (target = inst.stateNode); - batchedUpdates(function() { + batchedUpdates(function () { var JSCompiler_inline_result = target; for ( var events = null, legacyPlugins = plugins, i = 0; @@ -1167,17 +1174,17 @@ function _receiveRootNodeIDEvent(rootNodeID, topLevelType, nativeEventParam) { ); if (hasRethrowError) throw ((JSCompiler_inline_result = rethrowError), - (hasRethrowError = !1), - (rethrowError = null), - JSCompiler_inline_result); + (hasRethrowError = !1), + (rethrowError = null), + JSCompiler_inline_result); } }); } ReactNativePrivateInterface.RCTEventEmitter.register({ - receiveEvent: function(rootNodeID, topLevelType, nativeEventParam) { + receiveEvent: function (rootNodeID, topLevelType, nativeEventParam) { _receiveRootNodeIDEvent(rootNodeID, topLevelType, nativeEventParam); }, - receiveTouches: function(eventTopLevelType, touches, changedIndices) { + receiveTouches: function (eventTopLevelType, touches, changedIndices) { if ( "topTouchEnd" === eventTopLevelType || "topTouchCancel" === eventTopLevelType @@ -1210,11 +1217,11 @@ ReactNativePrivateInterface.RCTEventEmitter.register({ } } }); -getFiberCurrentPropsFromNode = function(stateNode) { +getFiberCurrentPropsFromNode = function (stateNode) { return instanceProps.get(stateNode._nativeTag) || null; }; getInstanceFromNode = getInstanceFromTag; -getNodeFromInstance = function(inst) { +getNodeFromInstance = function (inst) { inst = inst.stateNode; var tag = inst._nativeTag; void 0 === tag && ((inst = inst.canonical), (tag = inst._nativeTag)); @@ -1222,17 +1229,17 @@ getNodeFromInstance = function(inst) { return inst; }; ResponderEventPlugin.injection.injectGlobalResponderHandler({ - onChange: function(from, to, blockNativeResponder) { + onChange: function (from, to, blockNativeResponder) { null !== to ? ReactNativePrivateInterface.UIManager.setJSResponder( - to.stateNode._nativeTag, - blockNativeResponder - ) + to.stateNode._nativeTag, + blockNativeResponder + ) : ReactNativePrivateInterface.UIManager.clearJSResponder(); } }); var ReactSharedInternals = - React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, + React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, REACT_ELEMENT_TYPE = Symbol.for("react.element"), REACT_PORTAL_TYPE = Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"), @@ -1288,7 +1295,7 @@ function getComponentNameFromType(type) { type = type.displayName; type || ((type = innerType.displayName || innerType.name || ""), - (type = "" !== type ? "ForwardRef(" + type + ")" : "ForwardRef")); + (type = "" !== type ? "ForwardRef(" + type + ")" : "ForwardRef")); return type; case REACT_MEMO_TYPE: return ( @@ -1302,7 +1309,7 @@ function getComponentNameFromType(type) { type = type._init; try { return getComponentNameFromType(type(innerType)); - } catch (x) {} + } catch (x) { } } return null; } @@ -1322,7 +1329,7 @@ function getComponentNameFromFiber(fiber) { (fiber = type.render), (fiber = fiber.displayName || fiber.name || ""), type.displayName || - ("" !== fiber ? "ForwardRef(" + fiber + ")" : "ForwardRef") + ("" !== fiber ? "ForwardRef(" + fiber + ")" : "ForwardRef") ); case 7: return "Fragment"; @@ -1365,7 +1372,7 @@ function getComponentNameFromFiber(fiber) { function getNearestMountedFiber(fiber) { var node = fiber, nearestMounted = fiber; - if (fiber.alternate) for (; node.return; ) node = node.return; + if (fiber.alternate) for (; node.return;) node = node.return; else { fiber = node; do @@ -1388,7 +1395,7 @@ function findCurrentFiberUsingSlowPath(fiber) { throw Error("Unable to find node on an unmounted component."); return alternate !== fiber ? null : fiber; } - for (var a = fiber, b = alternate; ; ) { + for (var a = fiber, b = alternate; ;) { var parentA = a.return; if (null === parentA) break; var parentB = parentA.alternate; @@ -1401,7 +1408,7 @@ function findCurrentFiberUsingSlowPath(fiber) { break; } if (parentA.child === parentB.child) { - for (parentB = parentA.child; parentB; ) { + for (parentB = parentA.child; parentB;) { if (parentB === a) return assertIsMounted(parentA), fiber; if (parentB === b) return assertIsMounted(parentA), alternate; parentB = parentB.sibling; @@ -1410,7 +1417,7 @@ function findCurrentFiberUsingSlowPath(fiber) { } if (a.return !== b.return) (a = parentA), (b = parentB); else { - for (var didFindChild = !1, child$1 = parentA.child; child$1; ) { + for (var didFindChild = !1, child$1 = parentA.child; child$1;) { if (child$1 === a) { didFindChild = !0; a = parentA; @@ -1426,7 +1433,7 @@ function findCurrentFiberUsingSlowPath(fiber) { child$1 = child$1.sibling; } if (!didFindChild) { - for (child$1 = parentB.child; child$1; ) { + for (child$1 = parentB.child; child$1;) { if (child$1 === a) { didFindChild = !0; a = parentB; @@ -1462,7 +1469,7 @@ function findCurrentHostFiber(parent) { } function findCurrentHostFiberImpl(node) { if (5 === node.tag || 6 === node.tag) return node; - for (node = node.child; null !== node; ) { + for (node = node.child; null !== node;) { var match = findCurrentHostFiberImpl(node); if (null !== match) return match; node = node.sibling; @@ -1477,10 +1484,10 @@ function defaultDiffer(prevProp, nextProp) { return "object" !== typeof nextProp || null === nextProp ? !0 : ReactNativePrivateInterface.deepDiffer( - prevProp, - nextProp, - deepDifferOptions - ); + prevProp, + nextProp, + deepDifferOptions + ); } function restoreDeletedValuesInNestedArray( updatePayload, @@ -1488,7 +1495,7 @@ function restoreDeletedValuesInNestedArray( validAttributes ) { if (isArrayImpl(node)) - for (var i = node.length; i-- && 0 < removedKeyCount; ) + for (var i = node.length; i-- && 0 < removedKeyCount;) restoreDeletedValuesInNestedArray( updatePayload, node[i], @@ -1531,13 +1538,13 @@ function diffNestedProperty( return nextProp ? addNestedProperty(updatePayload, nextProp, validAttributes) : prevProp - ? clearNestedProperty(updatePayload, prevProp, validAttributes) - : updatePayload; + ? clearNestedProperty(updatePayload, prevProp, validAttributes) + : updatePayload; if (!isArrayImpl(prevProp) && !isArrayImpl(nextProp)) return diffProperties(updatePayload, prevProp, nextProp, validAttributes); if (isArrayImpl(prevProp) && isArrayImpl(nextProp)) { var minLength = - prevProp.length < nextProp.length ? prevProp.length : nextProp.length, + prevProp.length < nextProp.length ? prevProp.length : nextProp.length, i; for (i = 0; i < minLength; i++) updatePayload = diffNestedProperty( @@ -1562,17 +1569,17 @@ function diffNestedProperty( } return isArrayImpl(prevProp) ? diffProperties( - updatePayload, - ReactNativePrivateInterface.flattenStyle(prevProp), - nextProp, - validAttributes - ) + updatePayload, + ReactNativePrivateInterface.flattenStyle(prevProp), + nextProp, + validAttributes + ) : diffProperties( - updatePayload, - prevProp, - ReactNativePrivateInterface.flattenStyle(nextProp), - validAttributes - ); + updatePayload, + prevProp, + ReactNativePrivateInterface.flattenStyle(nextProp), + validAttributes + ); } function addNestedProperty(updatePayload, nextProp, validAttributes) { if (!nextProp) return updatePayload; @@ -1618,7 +1625,7 @@ function diffProperties(updatePayload, prevProps, nextProps, validAttributes) { ((nextProp = !0), "function" === typeof prevProp && (prevProp = !0)); "undefined" === typeof nextProp && ((nextProp = null), - "undefined" === typeof prevProp && (prevProp = null)); + "undefined" === typeof prevProp && (prevProp = null)); removedKeys && (removedKeys[propKey] = !1); if (updatePayload && void 0 !== updatePayload[propKey]) if ("object" !== typeof attributeConfig) @@ -1665,12 +1672,12 @@ function diffProperties(updatePayload, prevProps, nextProps, validAttributes) { attributeConfig )), 0 < removedKeyCount && - updatePayload && - (restoreDeletedValuesInNestedArray( - updatePayload, - nextProp, - attributeConfig - ), + updatePayload && + (restoreDeletedValuesInNestedArray( + updatePayload, + nextProp, + attributeConfig + ), (removedKeys = null)); } for (var propKey$3 in prevProps) @@ -1678,23 +1685,23 @@ function diffProperties(updatePayload, prevProps, nextProps, validAttributes) { (!(attributeConfig = validAttributes[propKey$3]) || (updatePayload && void 0 !== updatePayload[propKey$3]) || ((prevProp = prevProps[propKey$3]), - void 0 !== prevProp && + void 0 !== prevProp && ("object" !== typeof attributeConfig || - "function" === typeof attributeConfig.diff || - "function" === typeof attributeConfig.process + "function" === typeof attributeConfig.diff || + "function" === typeof attributeConfig.process ? (((updatePayload || (updatePayload = {}))[propKey$3] = null), removedKeys || (removedKeys = {}), removedKeys[propKey$3] || - ((removedKeys[propKey$3] = !0), removedKeyCount++)) + ((removedKeys[propKey$3] = !0), removedKeyCount++)) : (updatePayload = clearNestedProperty( - updatePayload, - prevProp, - attributeConfig - ))))); + updatePayload, + prevProp, + attributeConfig + ))))); return updatePayload; } function mountSafeCallback_NOT_REALLY_SAFE(context, callback) { - return function() { + return function () { if ( callback && ("boolean" !== typeof context.__isMounted || context.__isMounted) @@ -1702,61 +1709,61 @@ function mountSafeCallback_NOT_REALLY_SAFE(context, callback) { return callback.apply(context, arguments); }; } -var ReactNativeFiberHostComponent = (function() { - function ReactNativeFiberHostComponent(tag, viewConfig) { - this._nativeTag = tag; - this._children = []; - this.viewConfig = viewConfig; - } - var _proto = ReactNativeFiberHostComponent.prototype; - _proto.blur = function() { - ReactNativePrivateInterface.TextInputState.blurTextInput(this); - }; - _proto.focus = function() { - ReactNativePrivateInterface.TextInputState.focusTextInput(this); - }; - _proto.measure = function(callback) { - ReactNativePrivateInterface.UIManager.measure( +var ReactNativeFiberHostComponent = (function () { + function ReactNativeFiberHostComponent(tag, viewConfig) { + this._nativeTag = tag; + this._children = []; + this.viewConfig = viewConfig; + } + var _proto = ReactNativeFiberHostComponent.prototype; + _proto.blur = function () { + ReactNativePrivateInterface.TextInputState.blurTextInput(this); + }; + _proto.focus = function () { + ReactNativePrivateInterface.TextInputState.focusTextInput(this); + }; + _proto.measure = function (callback) { + ReactNativePrivateInterface.UIManager.measure( + this._nativeTag, + mountSafeCallback_NOT_REALLY_SAFE(this, callback) + ); + }; + _proto.measureInWindow = function (callback) { + ReactNativePrivateInterface.UIManager.measureInWindow( + this._nativeTag, + mountSafeCallback_NOT_REALLY_SAFE(this, callback) + ); + }; + _proto.measureLayout = function (relativeToNativeNode, onSuccess, onFail) { + if ("number" === typeof relativeToNativeNode) + var relativeNode = relativeToNativeNode; + else + relativeToNativeNode._nativeTag && + (relativeNode = relativeToNativeNode._nativeTag); + null != relativeNode && + ReactNativePrivateInterface.UIManager.measureLayout( this._nativeTag, - mountSafeCallback_NOT_REALLY_SAFE(this, callback) + relativeNode, + mountSafeCallback_NOT_REALLY_SAFE(this, onFail), + mountSafeCallback_NOT_REALLY_SAFE(this, onSuccess) ); - }; - _proto.measureInWindow = function(callback) { - ReactNativePrivateInterface.UIManager.measureInWindow( + }; + _proto.setNativeProps = function (nativeProps) { + nativeProps = diffProperties( + null, + emptyObject, + nativeProps, + this.viewConfig.validAttributes + ); + null != nativeProps && + ReactNativePrivateInterface.UIManager.updateView( this._nativeTag, - mountSafeCallback_NOT_REALLY_SAFE(this, callback) + this.viewConfig.uiViewClassName, + nativeProps ); - }; - _proto.measureLayout = function(relativeToNativeNode, onSuccess, onFail) { - if ("number" === typeof relativeToNativeNode) - var relativeNode = relativeToNativeNode; - else - relativeToNativeNode._nativeTag && - (relativeNode = relativeToNativeNode._nativeTag); - null != relativeNode && - ReactNativePrivateInterface.UIManager.measureLayout( - this._nativeTag, - relativeNode, - mountSafeCallback_NOT_REALLY_SAFE(this, onFail), - mountSafeCallback_NOT_REALLY_SAFE(this, onSuccess) - ); - }; - _proto.setNativeProps = function(nativeProps) { - nativeProps = diffProperties( - null, - emptyObject, - nativeProps, - this.viewConfig.validAttributes - ); - null != nativeProps && - ReactNativePrivateInterface.UIManager.updateView( - this._nativeTag, - this.viewConfig.uiViewClassName, - nativeProps - ); - }; - return ReactNativeFiberHostComponent; - })(), + }; + return ReactNativeFiberHostComponent; +})(), scheduleCallback = Scheduler.unstable_scheduleCallback, cancelCallback = Scheduler.unstable_cancelCallback, shouldYield = Scheduler.unstable_shouldYield, @@ -1777,7 +1784,7 @@ function onCommitRoot(root) { void 0, 128 === (root.current.flags & 128) ); - } catch (err) {} + } catch (err) { } } var clz32 = Math.clz32 ? Math.clz32 : clz32Fallback, log = Math.log, @@ -1850,28 +1857,28 @@ function getNextLanes(root, wipLanes) { ? (nextLanes = getHighestPriorityLanes(nonIdleUnblockedLanes)) : ((pingedLanes &= nonIdlePendingLanes), 0 !== pingedLanes && - (nextLanes = getHighestPriorityLanes(pingedLanes))); + (nextLanes = getHighestPriorityLanes(pingedLanes))); } else (nonIdlePendingLanes = pendingLanes & ~suspendedLanes), 0 !== nonIdlePendingLanes ? (nextLanes = getHighestPriorityLanes(nonIdlePendingLanes)) : 0 !== pingedLanes && - (nextLanes = getHighestPriorityLanes(pingedLanes)); + (nextLanes = getHighestPriorityLanes(pingedLanes)); if (0 === nextLanes) return 0; if ( 0 !== wipLanes && wipLanes !== nextLanes && 0 === (wipLanes & suspendedLanes) && ((suspendedLanes = nextLanes & -nextLanes), - (pingedLanes = wipLanes & -wipLanes), - suspendedLanes >= pingedLanes || + (pingedLanes = wipLanes & -wipLanes), + suspendedLanes >= pingedLanes || (16 === suspendedLanes && 0 !== (pingedLanes & 4194240))) ) return wipLanes; 0 !== (nextLanes & 4) && (nextLanes |= pendingLanes & 16); wipLanes = root.entangledLanes; if (0 !== wipLanes) - for (root = root.entanglements, wipLanes &= nextLanes; 0 < wipLanes; ) + for (root = root.entanglements, wipLanes &= nextLanes; 0 < wipLanes;) (pendingLanes = 31 - clz32(wipLanes)), (suspendedLanes = 1 << pendingLanes), (nextLanes |= root[pendingLanes]), @@ -1951,7 +1958,7 @@ function markRootFinished(root, remainingLanes) { root.entangledLanes &= remainingLanes; remainingLanes = root.entanglements; var eventTimes = root.eventTimes; - for (root = root.expirationTimes; 0 < noLongerPendingLanes; ) { + for (root = root.expirationTimes; 0 < noLongerPendingLanes;) { var index$8 = 31 - clz32(noLongerPendingLanes), lane = 1 << index$8; remainingLanes[index$8] = 0; @@ -1962,7 +1969,7 @@ function markRootFinished(root, remainingLanes) { } function markRootEntangled(root, entangledLanes) { var rootEntangledLanes = (root.entangledLanes |= entangledLanes); - for (root = root.entanglements; rootEntangledLanes; ) { + for (root = root.entanglements; rootEntangledLanes;) { var index$9 = 31 - clz32(rootEntangledLanes), lane = 1 << index$9; (lane & entangledLanes) | (root[index$9] & entangledLanes) && @@ -1987,7 +1994,7 @@ function shim() { ); } var getViewConfigForType = - ReactNativePrivateInterface.ReactNativeViewConfigRegistry.get, + ReactNativePrivateInterface.ReactNativeViewConfigRegistry.get, UPDATE_SIGNAL = {}, nextReactTag = 3; function allocateTag() { @@ -2008,7 +2015,7 @@ function recursivelyUncacheFiberNode(node) { } function finalizeInitialChildren(parentInstance) { if (0 === parentInstance._children.length) return !1; - var nativeTags = parentInstance._children.map(function(child) { + var nativeTags = parentInstance._children.map(function (child) { return "number" === typeof child ? child : child._nativeTag; }); ReactNativePrivateInterface.UIManager.setChildren( @@ -2062,8 +2069,8 @@ function getMaskedContext(workInProgress, unmaskedContext) { for (key in contextTypes) context[key] = unmaskedContext[key]; instance && ((workInProgress = workInProgress.stateNode), - (workInProgress.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext), - (workInProgress.__reactInternalMemoizedMaskedChildContext = context)); + (workInProgress.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext), + (workInProgress.__reactInternalMemoizedMaskedChildContext = context)); return context; } function isContextProvider(type) { @@ -2091,9 +2098,9 @@ function processChildContext(fiber, type, parentContext) { if (!(contextKey in type)) throw Error( (getComponentNameFromFiber(fiber) || "Unknown") + - '.getChildContext(): key "' + - contextKey + - '" is not defined in childContextTypes.' + '.getChildContext(): key "' + + contextKey + + '" is not defined in childContextTypes.' ); return assign({}, parentContext, instance); } @@ -2115,10 +2122,10 @@ function invalidateContextProvider(workInProgress, type, didChange) { ); didChange ? ((workInProgress = processChildContext( - workInProgress, - type, - previousContext - )), + workInProgress, + type, + previousContext + )), (instance.__reactInternalMemoizedMergedChildContext = workInProgress), pop(didPerformWorkStackCursor), pop(contextStackCursor), @@ -2149,8 +2156,8 @@ function flushSyncCallbacks() { includesLegacySyncCallbacks = !1; } catch (error) { throw (null !== syncQueue && (syncQueue = syncQueue.slice(i + 1)), - scheduleCallback(ImmediatePriority, flushSyncCallbacks), - error); + scheduleCallback(ImmediatePriority, flushSyncCallbacks), + error); } finally { (currentUpdatePriority = previousUpdatePriority), (isFlushingSyncQueue = !1); @@ -2165,12 +2172,12 @@ var forkStack = [], idStackIndex = 0, treeContextProvider = null; function popTreeContext(workInProgress) { - for (; workInProgress === treeForkProvider; ) + for (; workInProgress === treeForkProvider;) (treeForkProvider = forkStack[--forkStackIndex]), (forkStack[forkStackIndex] = null), --forkStackIndex, (forkStack[forkStackIndex] = null); - for (; workInProgress === treeContextProvider; ) + for (; workInProgress === treeContextProvider;) (treeContextProvider = idStack[--idStackIndex]), (idStack[idStackIndex] = null), --idStackIndex, @@ -2260,14 +2267,14 @@ function popProvider(context) { context._currentValue = currentValue; } function scheduleContextWorkOnParentPath(parent, renderLanes, propagationRoot) { - for (; null !== parent; ) { + for (; null !== parent;) { var alternate = parent.alternate; (parent.childLanes & renderLanes) !== renderLanes ? ((parent.childLanes |= renderLanes), null !== alternate && (alternate.childLanes |= renderLanes)) : null !== alternate && - (alternate.childLanes & renderLanes) !== renderLanes && - (alternate.childLanes |= renderLanes); + (alternate.childLanes & renderLanes) !== renderLanes && + (alternate.childLanes |= renderLanes); if (parent === propagationRoot) break; parent = parent.return; } @@ -2279,14 +2286,14 @@ function prepareToReadContext(workInProgress, renderLanes) { null !== workInProgress && null !== workInProgress.firstContext && (0 !== (workInProgress.lanes & renderLanes) && (didReceiveUpdate = !0), - (workInProgress.firstContext = null)); + (workInProgress.firstContext = null)); } function readContext(context) { var value = context._currentValue; if (lastFullyObservedContext !== context) if ( ((context = { context: context, memoizedValue: value, next: null }), - null === lastContextDependency) + null === lastContextDependency) ) { if (null === currentlyRenderingFiber) throw Error( @@ -2319,7 +2326,7 @@ function markUpdateLaneFromFiberToRoot(sourceFiber, lane) { var alternate = sourceFiber.alternate; null !== alternate && (alternate.lanes |= lane); alternate = sourceFiber; - for (sourceFiber = sourceFiber.return; null !== sourceFiber; ) + for (sourceFiber = sourceFiber.return; null !== sourceFiber;) (sourceFiber.childLanes |= lane), (alternate = sourceFiber.alternate), null !== alternate && (alternate.childLanes |= lane), @@ -2455,12 +2462,12 @@ function processUpdateQueue( var current = workInProgress$jscomp$0.alternate; null !== current && ((current = current.updateQueue), - (pendingQueue = current.lastBaseUpdate), - pendingQueue !== lastBaseUpdate && + (pendingQueue = current.lastBaseUpdate), + pendingQueue !== lastBaseUpdate && (null === pendingQueue ? (current.firstBaseUpdate = firstPendingUpdate) : (pendingQueue.next = firstPendingUpdate), - (current.lastBaseUpdate = lastPendingUpdate))); + (current.lastBaseUpdate = lastPendingUpdate))); } if (null !== firstBaseUpdate) { var newState = queue.baseState; @@ -2516,10 +2523,10 @@ function processUpdateQueue( null !== pendingQueue.callback && 0 !== pendingQueue.lane && ((workInProgress$jscomp$0.flags |= 64), - (updateLane = queue.effects), - null === updateLane - ? (queue.effects = [pendingQueue]) - : updateLane.push(pendingQueue)); + (updateLane = queue.effects), + null === updateLane + ? (queue.effects = [pendingQueue]) + : updateLane.push(pendingQueue)); } else (updateEventTime = { eventTime: updateEventTime, @@ -2576,7 +2583,7 @@ function commitUpdateQueue(finishedWork, finishedQueue, instance) { if ("function" !== typeof callback) throw Error( "Invalid argument passed as callback. Expected a function. Instead received: " + - callback + callback ); callback.call(instance); } @@ -2600,12 +2607,12 @@ function applyDerivedStateFromProps( (workInProgress.updateQueue.baseState = getDerivedStateFromProps); } var classComponentUpdater = { - isMounted: function(component) { + isMounted: function (component) { return (component = component._reactInternals) ? getNearestMountedFiber(component) === component : !1; }, - enqueueSetState: function(inst, payload, callback) { + enqueueSetState: function (inst, payload, callback) { inst = inst._reactInternals; var eventTime = requestEventTime(), lane = requestUpdateLane(inst), @@ -2615,9 +2622,9 @@ var classComponentUpdater = { payload = enqueueUpdate(inst, update, lane); null !== payload && (scheduleUpdateOnFiber(payload, inst, lane, eventTime), - entangleTransitions(payload, inst, lane)); + entangleTransitions(payload, inst, lane)); }, - enqueueReplaceState: function(inst, payload, callback) { + enqueueReplaceState: function (inst, payload, callback) { inst = inst._reactInternals; var eventTime = requestEventTime(), lane = requestUpdateLane(inst), @@ -2628,9 +2635,9 @@ var classComponentUpdater = { payload = enqueueUpdate(inst, update, lane); null !== payload && (scheduleUpdateOnFiber(payload, inst, lane, eventTime), - entangleTransitions(payload, inst, lane)); + entangleTransitions(payload, inst, lane)); }, - enqueueForceUpdate: function(inst, callback) { + enqueueForceUpdate: function (inst, callback) { inst = inst._reactInternals; var eventTime = requestEventTime(), lane = requestUpdateLane(inst), @@ -2640,7 +2647,7 @@ var classComponentUpdater = { callback = enqueueUpdate(inst, update, lane); null !== callback && (scheduleUpdateOnFiber(callback, inst, lane, eventTime), - entangleTransitions(callback, inst, lane)); + entangleTransitions(callback, inst, lane)); } }; function checkShouldComponentUpdate( @@ -2656,8 +2663,8 @@ function checkShouldComponentUpdate( return "function" === typeof workInProgress.shouldComponentUpdate ? workInProgress.shouldComponentUpdate(newProps, newState, nextContext) : ctor.prototype && ctor.prototype.isPureReactComponent - ? !shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState) - : !0; + ? !shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState) + : !0; } function constructClassInstance(workInProgress, ctor, props) { var isLegacyContextConsumer = !1, @@ -2666,8 +2673,8 @@ function constructClassInstance(workInProgress, ctor, props) { "object" === typeof context && null !== context ? (context = readContext(context)) : ((unmaskedContext = isContextProvider(ctor) - ? previousContext - : contextStackCursor.current), + ? previousContext + : contextStackCursor.current), (isLegacyContextConsumer = ctor.contextTypes), (context = (isLegacyContextConsumer = null !== isLegacyContextConsumer && void 0 !== isLegacyContextConsumer) @@ -2681,8 +2688,8 @@ function constructClassInstance(workInProgress, ctor, props) { ctor._reactInternals = workInProgress; isLegacyContextConsumer && ((workInProgress = workInProgress.stateNode), - (workInProgress.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext), - (workInProgress.__reactInternalMemoizedMaskedChildContext = context)); + (workInProgress.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext), + (workInProgress.__reactInternalMemoizedMaskedChildContext = context)); return ctor; } function callComponentWillReceiveProps( @@ -2709,27 +2716,27 @@ function mountClassInstance(workInProgress, ctor, newProps, renderLanes) { "object" === typeof contextType && null !== contextType ? (instance.context = readContext(contextType)) : ((contextType = isContextProvider(ctor) - ? previousContext - : contextStackCursor.current), + ? previousContext + : contextStackCursor.current), (instance.context = getMaskedContext(workInProgress, contextType))); instance.state = workInProgress.memoizedState; contextType = ctor.getDerivedStateFromProps; "function" === typeof contextType && (applyDerivedStateFromProps(workInProgress, ctor, contextType, newProps), - (instance.state = workInProgress.memoizedState)); + (instance.state = workInProgress.memoizedState)); "function" === typeof ctor.getDerivedStateFromProps || "function" === typeof instance.getSnapshotBeforeUpdate || ("function" !== typeof instance.UNSAFE_componentWillMount && "function" !== typeof instance.componentWillMount) || ((ctor = instance.state), - "function" === typeof instance.componentWillMount && + "function" === typeof instance.componentWillMount && instance.componentWillMount(), - "function" === typeof instance.UNSAFE_componentWillMount && + "function" === typeof instance.UNSAFE_componentWillMount && instance.UNSAFE_componentWillMount(), - ctor !== instance.state && + ctor !== instance.state && classComponentUpdater.enqueueReplaceState(instance, instance.state, null), - processUpdateQueue(workInProgress, newProps, instance, renderLanes), - (instance.state = workInProgress.memoizedState)); + processUpdateQueue(workInProgress, newProps, instance, renderLanes), + (instance.state = workInProgress.memoizedState)); "function" === typeof instance.componentDidMount && (workInProgress.flags |= 4); } @@ -2752,8 +2759,8 @@ function coerceRef(returnFiber, current, element) { if (!inst) throw Error( "Missing owner for string ref " + - returnFiber + - ". This error is likely caused by a bug in React. Please file an issue." + returnFiber + + ". This error is likely caused by a bug in React. Please file an issue." ); var resolvedInst = inst, stringRef = "" + returnFiber; @@ -2764,7 +2771,7 @@ function coerceRef(returnFiber, current, element) { current.ref._stringRef === stringRef ) return current.ref; - current = function(value) { + current = function (value) { var refs = resolvedInst.refs; refs === emptyRefsObject && (refs = resolvedInst.refs = {}); null === value ? delete refs[stringRef] : (refs[stringRef] = value); @@ -2779,8 +2786,8 @@ function coerceRef(returnFiber, current, element) { if (!element._owner) throw Error( "Element ref was specified as a string (" + - returnFiber + - ") but no owner was set. This could happen for one of the following reasons:\n1. You may be adding a ref to a function component\n2. You may be adding a ref to a component that was not created inside a component's render method\n3. You have multiple copies of React loaded\nSee https://react.dev/link/refs-must-have-owner for more information." + returnFiber + + ") but no owner was set. This could happen for one of the following reasons:\n1. You may be adding a ref to a function component\n2. You may be adding a ref to a component that was not created inside a component's render method\n3. You have multiple copies of React loaded\nSee https://react.dev/link/refs-must-have-owner for more information." ); } return returnFiber; @@ -2789,10 +2796,10 @@ function throwOnInvalidObjectType(returnFiber, newChild) { returnFiber = Object.prototype.toString.call(newChild); throw Error( "Objects are not valid as a React child (found: " + - ("[object Object]" === returnFiber - ? "object with keys {" + Object.keys(newChild).join(", ") + "}" - : returnFiber) + - "). If you meant to render a collection of children, use an array instead." + ("[object Object]" === returnFiber + ? "object with keys {" + Object.keys(newChild).join(", ") + "}" + : returnFiber) + + "). If you meant to render a collection of children, use an array instead." ); } function resolveLazy(lazyType) { @@ -2810,13 +2817,13 @@ function ChildReconciler(shouldTrackSideEffects) { } function deleteRemainingChildren(returnFiber, currentFirstChild) { if (!shouldTrackSideEffects) return null; - for (; null !== currentFirstChild; ) + for (; null !== currentFirstChild;) deleteChild(returnFiber, currentFirstChild), (currentFirstChild = currentFirstChild.sibling); return null; } function mapRemainingChildren(returnFiber, currentFirstChild) { - for (returnFiber = new Map(); null !== currentFirstChild; ) + for (returnFiber = new Map(); null !== currentFirstChild;) null !== currentFirstChild.key ? returnFiber.set(currentFirstChild.key, currentFirstChild) : returnFiber.set(currentFirstChild.index, currentFirstChild), @@ -3081,10 +3088,10 @@ function ChildReconciler(shouldTrackSideEffects) { ) { for ( var resultingFirstChild = null, - previousNewFiber = null, - oldFiber = currentFirstChild, - newIdx = (currentFirstChild = 0), - nextOldFiber = null; + previousNewFiber = null, + oldFiber = currentFirstChild, + newIdx = (currentFirstChild = 0), + nextOldFiber = null; null !== oldFiber && newIdx < newChildren.length; newIdx++ ) { @@ -3120,11 +3127,11 @@ function ChildReconciler(shouldTrackSideEffects) { for (; newIdx < newChildren.length; newIdx++) (oldFiber = createChild(returnFiber, newChildren[newIdx], lanes)), null !== oldFiber && - ((currentFirstChild = placeChild( - oldFiber, - currentFirstChild, - newIdx - )), + ((currentFirstChild = placeChild( + oldFiber, + currentFirstChild, + newIdx + )), null === previousNewFiber ? (resultingFirstChild = oldFiber) : (previousNewFiber.sibling = oldFiber), @@ -3144,11 +3151,11 @@ function ChildReconciler(shouldTrackSideEffects) { lanes )), null !== nextOldFiber && - (shouldTrackSideEffects && - null !== nextOldFiber.alternate && - oldFiber.delete( - null === nextOldFiber.key ? newIdx : nextOldFiber.key - ), + (shouldTrackSideEffects && + null !== nextOldFiber.alternate && + oldFiber.delete( + null === nextOldFiber.key ? newIdx : nextOldFiber.key + ), (currentFirstChild = placeChild( nextOldFiber, currentFirstChild, @@ -3159,7 +3166,7 @@ function ChildReconciler(shouldTrackSideEffects) { : (previousNewFiber.sibling = nextOldFiber), (previousNewFiber = nextOldFiber)); shouldTrackSideEffects && - oldFiber.forEach(function(child) { + oldFiber.forEach(function (child) { return deleteChild(returnFiber, child); }); return resultingFirstChild; @@ -3180,10 +3187,10 @@ function ChildReconciler(shouldTrackSideEffects) { throw Error("An iterable object provided no iterator."); for ( var previousNewFiber = (iteratorFn = null), - oldFiber = currentFirstChild, - newIdx = (currentFirstChild = 0), - nextOldFiber = null, - step = newChildrenIterable.next(); + oldFiber = currentFirstChild, + newIdx = (currentFirstChild = 0), + nextOldFiber = null, + step = newChildrenIterable.next(); null !== oldFiber && !step.done; newIdx++, step = newChildrenIterable.next() ) { @@ -3212,7 +3219,7 @@ function ChildReconciler(shouldTrackSideEffects) { for (; !step.done; newIdx++, step = newChildrenIterable.next()) (step = createChild(returnFiber, step.value, lanes)), null !== step && - ((currentFirstChild = placeChild(step, currentFirstChild, newIdx)), + ((currentFirstChild = placeChild(step, currentFirstChild, newIdx)), null === previousNewFiber ? (iteratorFn = step) : (previousNewFiber.sibling = step), @@ -3226,16 +3233,16 @@ function ChildReconciler(shouldTrackSideEffects) { ) (step = updateFromMap(oldFiber, returnFiber, newIdx, step.value, lanes)), null !== step && - (shouldTrackSideEffects && - null !== step.alternate && - oldFiber.delete(null === step.key ? newIdx : step.key), + (shouldTrackSideEffects && + null !== step.alternate && + oldFiber.delete(null === step.key ? newIdx : step.key), (currentFirstChild = placeChild(step, currentFirstChild, newIdx)), null === previousNewFiber ? (iteratorFn = step) : (previousNewFiber.sibling = step), (previousNewFiber = step)); shouldTrackSideEffects && - oldFiber.forEach(function(child) { + oldFiber.forEach(function (child) { return deleteChild(returnFiber, child); }); return iteratorFn; @@ -3298,21 +3305,21 @@ function ChildReconciler(shouldTrackSideEffects) { } newChild.type === REACT_FRAGMENT_TYPE ? ((currentFirstChild = createFiberFromFragment( - newChild.props.children, - returnFiber.mode, - lanes, - newChild.key - )), + newChild.props.children, + returnFiber.mode, + lanes, + newChild.key + )), (currentFirstChild.return = returnFiber), (returnFiber = currentFirstChild)) : ((lanes = createFiberFromTypeAndProps( - newChild.type, - newChild.key, - newChild.props, - null, - returnFiber.mode, - lanes - )), + newChild.type, + newChild.key, + newChild.props, + null, + returnFiber.mode, + lanes + )), (lanes.ref = coerceRef( returnFiber, currentFirstChild, @@ -3324,14 +3331,14 @@ function ChildReconciler(shouldTrackSideEffects) { return placeSingleChild(returnFiber); case REACT_PORTAL_TYPE: a: { - for (child = newChild.key; null !== currentFirstChild; ) { + for (child = newChild.key; null !== currentFirstChild;) { if (currentFirstChild.key === child) if ( 4 === currentFirstChild.tag && currentFirstChild.stateNode.containerInfo === - newChild.containerInfo && + newChild.containerInfo && currentFirstChild.stateNode.implementation === - newChild.implementation + newChild.implementation ) { deleteRemainingChildren( returnFiber, @@ -3449,7 +3456,7 @@ function pushHostContext(fiber) { : context; context !== JSCompiler_inline_result && (push(contextFiberStackCursor, fiber), - push(contextStackCursor$1, JSCompiler_inline_result)); + push(contextStackCursor$1, JSCompiler_inline_result)); } function popHostContext(fiber) { contextFiberStackCursor.current === fiber && @@ -3457,7 +3464,7 @@ function popHostContext(fiber) { } var suspenseStackCursor = createCursor(0); function findFirstSuspended(row) { - for (var node = row; null !== node; ) { + for (var node = row; null !== node;) { if (13 === node.tag) { var state = node.memoizedState; if (null !== state && (null === state.dehydrated || shim() || shim())) @@ -3470,7 +3477,7 @@ function findFirstSuspended(row) { continue; } if (node === row) break; - for (; null === node.sibling; ) { + for (; null === node.sibling;) { if (null === node.return || node.return === row) return null; node = node.return; } @@ -3696,7 +3703,7 @@ function rerenderReducer(reducer) { } return [newState, dispatch]; } -function updateMutableSource() {} +function updateMutableSource() { } function updateSyncExternalStore(subscribe, getSnapshot) { var fiber = currentlyRenderingFiber$1, hook = updateWorkInProgressHook(), @@ -3748,7 +3755,7 @@ function updateStoreInstance(fiber, inst, nextSnapshot, getSnapshot) { checkIfSnapshotChanged(inst) && forceStoreRerender(fiber); } function subscribeToStore(fiber, inst, subscribe) { - return subscribe(function() { + return subscribe(function () { checkIfSnapshotChanged(inst) && forceStoreRerender(fiber); }); } @@ -3847,7 +3854,7 @@ function imperativeHandleEffect(create, ref) { return ( (create = create()), ref(create), - function() { + function () { ref(null); } ); @@ -3855,7 +3862,7 @@ function imperativeHandleEffect(create, ref) { return ( (create = create()), (ref.current = create), - function() { + function () { ref.current = null; } ); @@ -3869,7 +3876,7 @@ function updateImperativeHandle(ref, create, deps) { deps ); } -function mountDebugValue() {} +function mountDebugValue() { } function updateCallback(callback, deps) { var hook = updateWorkInProgressHook(); deps = void 0 === deps ? null : deps; @@ -3905,9 +3912,9 @@ function updateDeferredValueImpl(hook, prevValue, value) { ); objectIs(value, prevValue) || ((value = claimNextTransitionLane()), - (currentlyRenderingFiber$1.lanes |= value), - (workInProgressRootSkippedLanes |= value), - (hook.baseState = !0)); + (currentlyRenderingFiber$1.lanes |= value), + (workInProgressRootSkippedLanes |= value), + (hook.baseState = !0)); return prevValue; } function startTransition(setPending, callback) { @@ -3939,7 +3946,7 @@ function dispatchReducerAction(fiber, queue, action) { if (isRenderPhaseUpdate(fiber)) enqueueRenderPhaseUpdate(queue, action); else if ( ((action = enqueueConcurrentHookUpdate(fiber, queue, action, lane)), - null !== action) + null !== action) ) { var eventTime = requestEventTime(); scheduleUpdateOnFiber(action, fiber, lane, eventTime); @@ -3982,8 +3989,8 @@ function dispatchSetState(fiber, queue, action) { action = enqueueConcurrentHookUpdate(fiber, queue, update, lane); null !== action && ((update = requestEventTime()), - scheduleUpdateOnFiber(action, fiber, lane, update), - entangleTransitionUpdate(action, queue, lane)); + scheduleUpdateOnFiber(action, fiber, lane, update), + entangleTransitionUpdate(action, queue, lane)); } } function isRenderPhaseUpdate(fiber) { @@ -4011,28 +4018,28 @@ function entangleTransitionUpdate(root, queue, lane) { } } var ContextOnlyDispatcher = { - readContext: readContext, - 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, - useMutableSource: throwInvalidHookError, - useSyncExternalStore: throwInvalidHookError, - useId: throwInvalidHookError, - unstable_isNewReconciler: !1 - }, + readContext: readContext, + 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, + useMutableSource: throwInvalidHookError, + useSyncExternalStore: throwInvalidHookError, + useId: throwInvalidHookError, + unstable_isNewReconciler: !1 +}, HooksDispatcherOnMount = { readContext: readContext, - useCallback: function(callback, deps) { + useCallback: function (callback, deps) { mountWorkInProgressHook().memoizedState = [ callback, void 0 === deps ? null : deps @@ -4041,7 +4048,7 @@ var ContextOnlyDispatcher = { }, useContext: readContext, useEffect: mountEffect, - useImperativeHandle: function(ref, create, deps) { + useImperativeHandle: function (ref, create, deps) { deps = null !== deps && void 0 !== deps ? deps.concat([ref]) : null; return mountEffectImpl( 4, @@ -4050,20 +4057,20 @@ var ContextOnlyDispatcher = { deps ); }, - useLayoutEffect: function(create, deps) { + useLayoutEffect: function (create, deps) { return mountEffectImpl(4, 4, create, deps); }, - useInsertionEffect: function(create, deps) { + useInsertionEffect: function (create, deps) { return mountEffectImpl(4, 2, create, deps); }, - useMemo: function(nextCreate, deps) { + useMemo: function (nextCreate, deps) { var hook = mountWorkInProgressHook(); deps = void 0 === deps ? null : deps; nextCreate = nextCreate(); hook.memoizedState = [nextCreate, deps]; return nextCreate; }, - useReducer: function(reducer, initialArg, init) { + useReducer: function (reducer, initialArg, init) { var hook = mountWorkInProgressHook(); initialArg = void 0 !== init ? init(initialArg) : initialArg; hook.memoizedState = hook.baseState = initialArg; @@ -4083,25 +4090,25 @@ var ContextOnlyDispatcher = { ); return [hook.memoizedState, reducer]; }, - useRef: function(initialValue) { + useRef: function (initialValue) { var hook = mountWorkInProgressHook(); initialValue = { current: initialValue }; return (hook.memoizedState = initialValue); }, useState: mountState, useDebugValue: mountDebugValue, - useDeferredValue: function(value) { + useDeferredValue: function (value) { return (mountWorkInProgressHook().memoizedState = value); }, - useTransition: function() { + useTransition: function () { var _mountState = mountState(!1), isPending = _mountState[0]; _mountState = startTransition.bind(null, _mountState[1]); mountWorkInProgressHook().memoizedState = _mountState; return [isPending, _mountState]; }, - useMutableSource: function() {}, - useSyncExternalStore: function(subscribe, getSnapshot) { + useMutableSource: function () { }, + useSyncExternalStore: function (subscribe, getSnapshot) { var fiber = currentlyRenderingFiber$1, hook = mountWorkInProgressHook(); var nextSnapshot = getSnapshot(); @@ -4126,7 +4133,7 @@ var ContextOnlyDispatcher = { ); return nextSnapshot; }, - useId: function() { + useId: function () { var hook = mountWorkInProgressHook(), identifierPrefix = workInProgressRoot.identifierPrefix, globalClientId = globalClientIdCounter++; @@ -4147,15 +4154,15 @@ var ContextOnlyDispatcher = { useMemo: updateMemo, useReducer: updateReducer, useRef: updateRef, - useState: function() { + useState: function () { return updateReducer(basicStateReducer); }, useDebugValue: mountDebugValue, - useDeferredValue: function(value) { + useDeferredValue: function (value) { var hook = updateWorkInProgressHook(); return updateDeferredValueImpl(hook, currentHook.memoizedState, value); }, - useTransition: function() { + useTransition: function () { var isPending = updateReducer(basicStateReducer)[0], start = updateWorkInProgressHook().memoizedState; return [isPending, start]; @@ -4176,17 +4183,17 @@ var ContextOnlyDispatcher = { useMemo: updateMemo, useReducer: rerenderReducer, useRef: updateRef, - useState: function() { + useState: function () { return rerenderReducer(basicStateReducer); }, useDebugValue: mountDebugValue, - useDeferredValue: function(value) { + useDeferredValue: function (value) { var hook = updateWorkInProgressHook(); return null === currentHook ? (hook.memoizedState = value) : updateDeferredValueImpl(hook, currentHook.memoizedState, value); }, - useTransition: function() { + useTransition: function () { var isPending = rerenderReducer(basicStateReducer)[0], start = updateWorkInProgressHook().memoizedState; return [isPending, start]; @@ -4229,7 +4236,7 @@ function logCapturedError(boundary, errorInfo) { null !== boundary && 1 === boundary.tag ? boundary.stateNode : null }) && console.error(errorInfo.value); } catch (e) { - setTimeout(function() { + setTimeout(function () { throw e; }); } @@ -4240,7 +4247,7 @@ function createRootErrorUpdate(fiber, errorInfo, lane) { lane.tag = 3; lane.payload = { element: null }; var error = errorInfo.value; - lane.callback = function() { + lane.callback = function () { hasUncaughtError || ((hasUncaughtError = !0), (firstUncaughtError = error)); logCapturedError(fiber, errorInfo); }; @@ -4252,17 +4259,17 @@ function createClassErrorUpdate(fiber, errorInfo, lane) { var getDerivedStateFromError = fiber.type.getDerivedStateFromError; if ("function" === typeof getDerivedStateFromError) { var error = errorInfo.value; - lane.payload = function() { + lane.payload = function () { return getDerivedStateFromError(error); }; - lane.callback = function() { + lane.callback = function () { logCapturedError(fiber, errorInfo); }; } var inst = fiber.stateNode; null !== inst && "function" === typeof inst.componentDidCatch && - (lane.callback = function() { + (lane.callback = function () { logCapturedError(fiber, errorInfo); "function" !== typeof getDerivedStateFromError && (null === legacyErrorBoundariesThatAlreadyFailed @@ -4284,11 +4291,11 @@ function attachPingListener(root, wakeable, lanes) { } else (threadIDs = pingCache.get(wakeable)), void 0 === threadIDs && - ((threadIDs = new Set()), pingCache.set(wakeable, threadIDs)); + ((threadIDs = new Set()), pingCache.set(wakeable, threadIDs)); threadIDs.has(lanes) || (threadIDs.add(lanes), - (root = pingSuspendedRoot.bind(null, root, wakeable, lanes)), - wakeable.then(root, root)); + (root = pingSuspendedRoot.bind(null, root, wakeable, lanes)), + wakeable.then(root, root)); } var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner, didReceiveUpdate = !1; @@ -4297,11 +4304,11 @@ function reconcileChildren(current, workInProgress, nextChildren, renderLanes) { null === current ? mountChildFibers(workInProgress, null, nextChildren, renderLanes) : reconcileChildFibers( - workInProgress, - current.child, - nextChildren, - renderLanes - ); + workInProgress, + current.child, + nextChildren, + renderLanes + ); } function updateForwardRef( current, @@ -4400,8 +4407,8 @@ function updateSimpleMemoComponent( ) if ( ((didReceiveUpdate = !1), - (workInProgress.pendingProps = nextProps = prevProps), - 0 !== (current.lanes & renderLanes)) + (workInProgress.pendingProps = nextProps = prevProps), + 0 !== (current.lanes & renderLanes)) ) 0 !== (current.flags & 131072) && (didReceiveUpdate = !0); else @@ -4533,8 +4540,8 @@ function updateClassComponent( "object" === typeof contextType && null !== contextType ? (contextType = readContext(contextType)) : ((contextType = isContextProvider(Component) - ? previousContext - : contextStackCursor.current), + ? previousContext + : contextStackCursor.current), (contextType = getMaskedContext(workInProgress, contextType))); var getDerivedStateFromProps = Component.getDerivedStateFromProps, hasNewLifecycles = @@ -4556,16 +4563,16 @@ function updateClassComponent( processUpdateQueue(workInProgress, nextProps, instance, renderLanes); oldContext = workInProgress.memoizedState; oldProps !== nextProps || - oldState !== oldContext || - didPerformWorkStackCursor.current || - hasForceUpdate + oldState !== oldContext || + didPerformWorkStackCursor.current || + hasForceUpdate ? ("function" === typeof getDerivedStateFromProps && - (applyDerivedStateFromProps( - workInProgress, - Component, - getDerivedStateFromProps, - nextProps - ), + (applyDerivedStateFromProps( + workInProgress, + Component, + getDerivedStateFromProps, + nextProps + ), (oldContext = workInProgress.memoizedState)), (oldProps = hasForceUpdate || @@ -4579,16 +4586,16 @@ function updateClassComponent( contextType )) ? (hasNewLifecycles || - ("function" !== typeof instance.UNSAFE_componentWillMount && - "function" !== typeof instance.componentWillMount) || - ("function" === typeof instance.componentWillMount && - instance.componentWillMount(), + ("function" !== typeof instance.UNSAFE_componentWillMount && + "function" !== typeof instance.componentWillMount) || + ("function" === typeof instance.componentWillMount && + instance.componentWillMount(), "function" === typeof instance.UNSAFE_componentWillMount && - instance.UNSAFE_componentWillMount()), + instance.UNSAFE_componentWillMount()), "function" === typeof instance.componentDidMount && - (workInProgress.flags |= 4)) + (workInProgress.flags |= 4)) : ("function" === typeof instance.componentDidMount && - (workInProgress.flags |= 4), + (workInProgress.flags |= 4), (workInProgress.memoizedProps = nextProps), (workInProgress.memoizedState = oldContext)), (instance.props = nextProps), @@ -4596,7 +4603,7 @@ function updateClassComponent( (instance.context = contextType), (nextProps = oldProps)) : ("function" === typeof instance.componentDidMount && - (workInProgress.flags |= 4), + (workInProgress.flags |= 4), (nextProps = !1)); } else { instance = workInProgress.stateNode; @@ -4613,8 +4620,8 @@ function updateClassComponent( "object" === typeof oldContext && null !== oldContext ? (oldContext = readContext(oldContext)) : ((oldContext = isContextProvider(Component) - ? previousContext - : contextStackCursor.current), + ? previousContext + : contextStackCursor.current), (oldContext = getMaskedContext(workInProgress, oldContext))); var getDerivedStateFromProps$jscomp$0 = Component.getDerivedStateFromProps; (getDerivedStateFromProps = @@ -4635,16 +4642,16 @@ function updateClassComponent( processUpdateQueue(workInProgress, nextProps, instance, renderLanes); var newState = workInProgress.memoizedState; oldProps !== hasNewLifecycles || - oldState !== newState || - didPerformWorkStackCursor.current || - hasForceUpdate + oldState !== newState || + didPerformWorkStackCursor.current || + hasForceUpdate ? ("function" === typeof getDerivedStateFromProps$jscomp$0 && - (applyDerivedStateFromProps( - workInProgress, - Component, - getDerivedStateFromProps$jscomp$0, - nextProps - ), + (applyDerivedStateFromProps( + workInProgress, + Component, + getDerivedStateFromProps$jscomp$0, + nextProps + ), (newState = workInProgress.memoizedState)), (contextType = hasForceUpdate || @@ -4659,28 +4666,28 @@ function updateClassComponent( ) || !1) ? (getDerivedStateFromProps || - ("function" !== typeof instance.UNSAFE_componentWillUpdate && - "function" !== typeof instance.componentWillUpdate) || - ("function" === typeof instance.componentWillUpdate && - instance.componentWillUpdate(nextProps, newState, oldContext), + ("function" !== typeof instance.UNSAFE_componentWillUpdate && + "function" !== typeof instance.componentWillUpdate) || + ("function" === typeof instance.componentWillUpdate && + instance.componentWillUpdate(nextProps, newState, oldContext), "function" === typeof instance.UNSAFE_componentWillUpdate && - instance.UNSAFE_componentWillUpdate( - nextProps, - newState, - oldContext - )), + instance.UNSAFE_componentWillUpdate( + nextProps, + newState, + oldContext + )), "function" === typeof instance.componentDidUpdate && - (workInProgress.flags |= 4), + (workInProgress.flags |= 4), "function" === typeof instance.getSnapshotBeforeUpdate && - (workInProgress.flags |= 1024)) + (workInProgress.flags |= 1024)) : ("function" !== typeof instance.componentDidUpdate || - (oldProps === current.memoizedProps && - oldState === current.memoizedState) || - (workInProgress.flags |= 4), + (oldProps === current.memoizedProps && + oldState === current.memoizedState) || + (workInProgress.flags |= 4), "function" !== typeof instance.getSnapshotBeforeUpdate || - (oldProps === current.memoizedProps && - oldState === current.memoizedState) || - (workInProgress.flags |= 1024), + (oldProps === current.memoizedProps && + oldState === current.memoizedState) || + (workInProgress.flags |= 1024), (workInProgress.memoizedProps = nextProps), (workInProgress.memoizedState = newState)), (instance.props = nextProps), @@ -4688,13 +4695,13 @@ function updateClassComponent( (instance.context = oldContext), (nextProps = contextType)) : ("function" !== typeof instance.componentDidUpdate || - (oldProps === current.memoizedProps && - oldState === current.memoizedState) || - (workInProgress.flags |= 4), + (oldProps === current.memoizedProps && + oldState === current.memoizedState) || + (workInProgress.flags |= 4), "function" !== typeof instance.getSnapshotBeforeUpdate || - (oldProps === current.memoizedProps && - oldState === current.memoizedState) || - (workInProgress.flags |= 1024), + (oldProps === current.memoizedProps && + oldState === current.memoizedState) || + (workInProgress.flags |= 1024), (nextProps = !1)); } return finishClassComponent( @@ -4730,11 +4737,11 @@ function finishClassComponent( workInProgress.flags |= 1; null !== current && didCaptureError ? ((workInProgress.child = reconcileChildFibers( - workInProgress, - current.child, - null, - renderLanes - )), + workInProgress, + current.child, + null, + renderLanes + )), (workInProgress.child = reconcileChildFibers( workInProgress, null, @@ -4750,12 +4757,12 @@ function pushHostRootContext(workInProgress) { var root = workInProgress.stateNode; root.pendingContext ? pushTopLevelContextObject( - workInProgress, - root.pendingContext, - root.pendingContext !== root.context - ) + workInProgress, + root.pendingContext, + root.pendingContext !== root.context + ) : root.context && - pushTopLevelContextObject(workInProgress, root.context, !1); + pushTopLevelContextObject(workInProgress, root.context, !1); pushHostContainer(workInProgress, root.containerInfo); } var SUSPENDED_MARKER = { dehydrated: null, treeContext: null, retryLane: 0 }; @@ -4784,8 +4791,8 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { 0 === (workInProgress.mode & 1) ? (workInProgress.lanes = 1) : shim() - ? (workInProgress.lanes = 8) - : (workInProgress.lanes = 1073741824), + ? (workInProgress.lanes = 8) + : (workInProgress.lanes = 1073741824), null ); didSuspend = nextProps.children; @@ -4798,11 +4805,11 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { ? ((showFallback.childLanes = 0), (showFallback.pendingProps = didSuspend)) : (showFallback = createFiberFromOffscreen( - didSuspend, - nextProps, - 0, - null - )), + didSuspend, + nextProps, + 0, + null + )), (current = createFiberFromFragment( current, nextProps, @@ -4850,11 +4857,11 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { null !== JSCompiler_temp ? (showFallback = createWorkInProgress(JSCompiler_temp, showFallback)) : ((showFallback = createFiberFromFragment( - showFallback, - didSuspend, - renderLanes, - null - )), + showFallback, + didSuspend, + renderLanes, + null + )), (showFallback.flags |= 2)); showFallback.return = workInProgress; nextProps.return = workInProgress; @@ -4867,10 +4874,10 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { null === didSuspend ? mountSuspenseOffscreenState(renderLanes) : { - baseLanes: didSuspend.baseLanes | renderLanes, - cachePool: null, - transitions: didSuspend.transitions - }; + baseLanes: didSuspend.baseLanes | renderLanes, + cachePool: null, + transitions: didSuspend.transitions + }; showFallback.memoizedState = didSuspend; showFallback.childLanes = current.childLanes & ~renderLanes; workInProgress.memoizedState = SUSPENDED_MARKER; @@ -4887,9 +4894,9 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { nextProps.sibling = null; null !== current && ((renderLanes = workInProgress.deletions), - null === renderLanes - ? ((workInProgress.deletions = [current]), (workInProgress.flags |= 16)) - : renderLanes.push(current)); + null === renderLanes + ? ((workInProgress.deletions = [current]), (workInProgress.flags |= 16)) + : renderLanes.push(current)); workInProgress.child = nextProps; workInProgress.memoizedState = null; return nextProps; @@ -5052,8 +5059,8 @@ function updateDehydratedSuspenseComponent( 0 !== didSuspend && didSuspend !== suspenseState.retryLane && ((suspenseState.retryLane = didSuspend), - markUpdateLaneFromFiberToRoot(current, didSuspend), - scheduleUpdateOnFiber(nextProps, current, didSuspend, -1)); + markUpdateLaneFromFiberToRoot(current, didSuspend), + scheduleUpdateOnFiber(nextProps, current, didSuspend, -1)); } renderDidSuspendDelayIfPossible(); suspenseState = createCapturedValue( @@ -5096,13 +5103,13 @@ function initSuspenseListRenderState( var renderState = workInProgress.memoizedState; null === renderState ? (workInProgress.memoizedState = { - isBackwards: isBackwards, - rendering: null, - renderingStartTime: 0, - last: lastContentRow, - tail: tail, - tailMode: tailMode - }) + isBackwards: isBackwards, + rendering: null, + renderingStartTime: 0, + last: lastContentRow, + tail: tail, + tailMode: tailMode + }) : ((renderState.isBackwards = isBackwards), (renderState.rendering = null), (renderState.renderingStartTime = 0), @@ -5120,7 +5127,7 @@ function updateSuspenseListComponent(current, workInProgress, renderLanes) { (nextProps = (nextProps & 1) | 2), (workInProgress.flags |= 128); else { if (null !== current && 0 !== (current.flags & 128)) - a: for (current = workInProgress.child; null !== current; ) { + a: for (current = workInProgress.child; null !== current;) { if (13 === current.tag) null !== current.memoizedState && scheduleSuspenseWorkOnFiber(current, renderLanes, workInProgress); @@ -5132,7 +5139,7 @@ function updateSuspenseListComponent(current, workInProgress, renderLanes) { continue; } if (current === workInProgress) break a; - for (; null === current.sibling; ) { + for (; null === current.sibling;) { if (null === current.return || current.return === workInProgress) break a; current = current.return; @@ -5148,11 +5155,11 @@ function updateSuspenseListComponent(current, workInProgress, renderLanes) { switch (revealOrder) { case "forwards": renderLanes = workInProgress.child; - for (revealOrder = null; null !== renderLanes; ) + for (revealOrder = null; null !== renderLanes;) (current = renderLanes.alternate), null !== current && - null === findFirstSuspended(current) && - (revealOrder = renderLanes), + null === findFirstSuspended(current) && + (revealOrder = renderLanes), (renderLanes = renderLanes.sibling); renderLanes = revealOrder; null === renderLanes @@ -5170,7 +5177,7 @@ function updateSuspenseListComponent(current, workInProgress, renderLanes) { case "backwards": renderLanes = null; revealOrder = workInProgress.child; - for (workInProgress.child = null; null !== revealOrder; ) { + for (workInProgress.child = null; null !== revealOrder;) { current = revealOrder.alternate; if (null !== current && null === findFirstSuspended(current)) { workInProgress.child = revealOrder; @@ -5201,8 +5208,8 @@ function resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress) { 0 === (workInProgress.mode & 1) && null !== current && ((current.alternate = null), - (workInProgress.alternate = null), - (workInProgress.flags |= 2)); + (workInProgress.alternate = null), + (workInProgress.flags |= 2)); } function bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) { null !== current && (workInProgress.dependencies = current.dependencies); @@ -5214,7 +5221,7 @@ function bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) { current = workInProgress.child; renderLanes = createWorkInProgress(current, current.pendingProps); workInProgress.child = renderLanes; - for (renderLanes.return = workInProgress; null !== current.sibling; ) + for (renderLanes.return = workInProgress; null !== current.sibling;) (current = current.sibling), (renderLanes = renderLanes.sibling = createWorkInProgress( current, @@ -5285,8 +5292,8 @@ function attemptEarlyBailoutIfNoScheduledUpdate( nextValue = workInProgress.memoizedState; null !== nextValue && ((nextValue.rendering = null), - (nextValue.tail = null), - (nextValue.lastEffect = null)); + (nextValue.tail = null), + (nextValue.lastEffect = null)); push(suspenseStackCursor, suspenseStackCursor.current); if (context) break; else return null; @@ -5303,8 +5310,8 @@ var appendAllChildren, updateHostContainer, updateHostComponent$1, updateHostText$1; -appendAllChildren = function(parent, workInProgress) { - for (var node = workInProgress.child; null !== node; ) { +appendAllChildren = function (parent, workInProgress) { + for (var node = workInProgress.child; null !== node;) { if (5 === node.tag || 6 === node.tag) parent._children.push(node.stateNode); else if (4 !== node.tag && null !== node.child) { node.child.return = node; @@ -5312,7 +5319,7 @@ appendAllChildren = function(parent, workInProgress) { continue; } if (node === workInProgress) break; - for (; null === node.sibling; ) { + for (; null === node.sibling;) { if (null === node.return || node.return === workInProgress) return; node = node.return; } @@ -5320,21 +5327,21 @@ appendAllChildren = function(parent, workInProgress) { node = node.sibling; } }; -updateHostContainer = function() {}; -updateHostComponent$1 = function(current, workInProgress, type, newProps) { +updateHostContainer = function () { }; +updateHostComponent$1 = function (current, workInProgress, type, newProps) { current.memoizedProps !== newProps && (requiredContext(contextStackCursor$1.current), - (workInProgress.updateQueue = UPDATE_SIGNAL)) && + (workInProgress.updateQueue = UPDATE_SIGNAL)) && (workInProgress.flags |= 4); }; -updateHostText$1 = function(current, workInProgress, oldText, newText) { +updateHostText$1 = function (current, workInProgress, oldText, newText) { oldText !== newText && (workInProgress.flags |= 4); }; function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { switch (renderState.tailMode) { case "hidden": hasRenderedATailFallback = renderState.tail; - for (var lastTailNode = null; null !== hasRenderedATailFallback; ) + for (var lastTailNode = null; null !== hasRenderedATailFallback;) null !== hasRenderedATailFallback.alternate && (lastTailNode = hasRenderedATailFallback), (hasRenderedATailFallback = hasRenderedATailFallback.sibling); @@ -5344,7 +5351,7 @@ function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { break; case "collapsed": lastTailNode = renderState.tail; - for (var lastTailNode$62 = null; null !== lastTailNode; ) + for (var lastTailNode$62 = null; null !== lastTailNode;) null !== lastTailNode.alternate && (lastTailNode$62 = lastTailNode), (lastTailNode = lastTailNode.sibling); null === lastTailNode$62 @@ -5356,19 +5363,19 @@ function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { } function bubbleProperties(completedWork) { var didBailout = - null !== completedWork.alternate && - completedWork.alternate.child === completedWork.child, + null !== completedWork.alternate && + completedWork.alternate.child === completedWork.child, newChildLanes = 0, subtreeFlags = 0; if (didBailout) - for (var child$63 = completedWork.child; null !== child$63; ) + for (var child$63 = completedWork.child; null !== child$63;) (newChildLanes |= child$63.lanes | child$63.childLanes), (subtreeFlags |= child$63.subtreeFlags & 14680064), (subtreeFlags |= child$63.flags & 14680064), (child$63.return = completedWork), (child$63 = child$63.sibling); else - for (child$63 = completedWork.child; null !== child$63; ) + for (child$63 = completedWork.child; null !== child$63;) (newChildLanes |= child$63.lanes | child$63.childLanes), (subtreeFlags |= child$63.subtreeFlags), (subtreeFlags |= child$63.flags), @@ -5381,6 +5388,12 @@ function bubbleProperties(completedWork) { function completeWork(current, workInProgress, renderLanes) { var newProps = workInProgress.pendingProps; popTreeContext(workInProgress); + if (workInProgress.flags & 1 && (workInProgress.type?.displayName || workInProgress.type?.name) !== "View") + insertUpdateComponents( + getComponentNameFromFiber(workInProgress), + workInProgress.flags, + workInProgress.key, + ); switch (workInProgress.tag) { case 2: case 16: @@ -5407,15 +5420,15 @@ function completeWork(current, workInProgress, renderLanes) { pop(contextStackCursor), resetWorkInProgressVersions(), renderLanes.pendingContext && - ((renderLanes.context = renderLanes.pendingContext), + ((renderLanes.context = renderLanes.pendingContext), (renderLanes.pendingContext = null)), (null !== current && null !== current.child) || - null === current || - (current.memoizedState.isDehydrated && - 0 === (workInProgress.flags & 256)) || - ((workInProgress.flags |= 1024), + null === current || + (current.memoizedState.isDehydrated && + 0 === (workInProgress.flags & 256)) || + ((workInProgress.flags |= 1024), null !== hydrationErrors && - (queueRecoverableErrors(hydrationErrors), + (queueRecoverableErrors(hydrationErrors), (hydrationErrors = null))), updateHostContainer(current, workInProgress), bubbleProperties(workInProgress), @@ -5536,10 +5549,10 @@ function completeWork(current, workInProgress, renderLanes) { renderLanes !== (null !== current && null !== current.memoizedState) && renderLanes && ((workInProgress.child.flags |= 8192), - 0 !== (workInProgress.mode & 1) && + 0 !== (workInProgress.mode & 1) && (null === current || 0 !== (suspenseStackCursor.current & 1) ? 0 === workInProgressRootExitStatus && - (workInProgressRootExitStatus = 3) + (workInProgressRootExitStatus = 3) : renderDidSuspendDelayIfPossible())); null !== workInProgress.updateQueue && (workInProgress.flags |= 4); bubbleProperties(workInProgress); @@ -5576,7 +5589,7 @@ function completeWork(current, workInProgress, renderLanes) { 0 !== workInProgressRootExitStatus || (null !== current && 0 !== (current.flags & 128)) ) - for (current = workInProgress.child; null !== current; ) { + for (current = workInProgress.child; null !== current;) { updatePayload = findFirstSuspended(current); if (null !== updatePayload) { workInProgress.flags |= 128; @@ -5584,10 +5597,10 @@ function completeWork(current, workInProgress, renderLanes) { current = updatePayload.updateQueue; null !== current && ((workInProgress.updateQueue = current), - (workInProgress.flags |= 4)); + (workInProgress.flags |= 4)); workInProgress.subtreeFlags = 0; current = renderLanes; - for (renderLanes = workInProgress.child; null !== renderLanes; ) + for (renderLanes = workInProgress.child; null !== renderLanes;) (newProps = renderLanes), (type = current), (newProps.flags &= 14680066), @@ -5616,9 +5629,9 @@ function completeWork(current, workInProgress, renderLanes) { null === type ? null : { - lanes: type.lanes, - firstContext: type.firstContext - })), + lanes: type.lanes, + firstContext: type.firstContext + })), (renderLanes = renderLanes.sibling); push( suspenseStackCursor, @@ -5631,9 +5644,9 @@ function completeWork(current, workInProgress, renderLanes) { null !== type.tail && now() > workInProgressRootRenderTargetTime && ((workInProgress.flags |= 128), - (newProps = !0), - cutOffTailIfNeeded(type, !1), - (workInProgress.lanes = 4194304)); + (newProps = !0), + cutOffTailIfNeeded(type, !1), + (workInProgress.lanes = 4194304)); } else { if (!newProps) @@ -5642,13 +5655,13 @@ function completeWork(current, workInProgress, renderLanes) { ) { if ( ((workInProgress.flags |= 128), - (newProps = !0), - (current = current.updateQueue), - null !== current && + (newProps = !0), + (current = current.updateQueue), + null !== current && ((workInProgress.updateQueue = current), - (workInProgress.flags |= 4)), - cutOffTailIfNeeded(type, !0), - null === type.tail && + (workInProgress.flags |= 4)), + cutOffTailIfNeeded(type, !0), + null === type.tail && "hidden" === type.tailMode && !updatePayload.alternate) ) @@ -5658,9 +5671,9 @@ function completeWork(current, workInProgress, renderLanes) { workInProgressRootRenderTargetTime && 1073741824 !== renderLanes && ((workInProgress.flags |= 128), - (newProps = !0), - cutOffTailIfNeeded(type, !1), - (workInProgress.lanes = 4194304)); + (newProps = !0), + cutOffTailIfNeeded(type, !1), + (workInProgress.lanes = 4194304)); type.isBackwards ? ((updatePayload.sibling = workInProgress.child), (workInProgress.child = updatePayload)) @@ -5689,11 +5702,11 @@ function completeWork(current, workInProgress, renderLanes) { popRenderLanes(), (renderLanes = null !== workInProgress.memoizedState), null !== current && - (null !== current.memoizedState) !== renderLanes && - (workInProgress.flags |= 8192), + (null !== current.memoizedState) !== renderLanes && + (workInProgress.flags |= 8192), renderLanes && 0 !== (workInProgress.mode & 1) ? 0 !== (subtreeRenderLanes & 1073741824) && - (bubbleProperties(workInProgress), + (bubbleProperties(workInProgress), workInProgress.subtreeFlags & 6 && (workInProgress.flags |= 8192)) : bubbleProperties(workInProgress), null @@ -5705,8 +5718,8 @@ function completeWork(current, workInProgress, renderLanes) { } throw Error( "Unknown unit of work tag (" + - workInProgress.tag + - "). This error is likely caused by a bug in React. Please file an issue." + workInProgress.tag + + "). This error is likely caused by a bug in React. Please file an issue." ); } function unwindWork(current, workInProgress) { @@ -5785,15 +5798,15 @@ function safelyCallDestroy(current, nearestMountedAncestor, destroy) { } var shouldFireAfterActiveInstanceBlur = !1; function commitBeforeMutationEffects(root, firstChild) { - for (nextEffect = firstChild; null !== nextEffect; ) + for (nextEffect = firstChild; null !== nextEffect;) if ( ((root = nextEffect), - (firstChild = root.child), - 0 !== (root.subtreeFlags & 1028) && null !== firstChild) + (firstChild = root.child), + 0 !== (root.subtreeFlags & 1028) && null !== firstChild) ) (firstChild.return = root), (nextEffect = firstChild); else - for (; null !== nextEffect; ) { + for (; null !== nextEffect;) { root = nextEffect; try { var current = root.alternate; @@ -5898,8 +5911,8 @@ function isHostParent(fiber) { return 5 === fiber.tag || 3 === fiber.tag || 4 === fiber.tag; } function getHostSibling(fiber) { - a: for (;;) { - for (; null === fiber.sibling; ) { + a: for (; ;) { + for (; null === fiber.sibling;) { if (null === fiber.return || isHostParent(fiber.return)) return null; fiber = fiber.return; } @@ -5929,7 +5942,7 @@ function insertOrAppendPlacementNodeIntoContainer(node, before, parent) { else if (4 !== tag && ((node = node.child), null !== node)) for ( insertOrAppendPlacementNodeIntoContainer(node, before, parent), - node = node.sibling; + node = node.sibling; null !== node; ) @@ -6003,7 +6016,7 @@ function recursivelyTraverseDeletionEffects( nearestMountedAncestor, parent ) { - for (parent = parent.child; null !== parent; ) + for (parent = parent.child; null !== parent;) commitDeletionEffectsOnFiber(finishedRoot, nearestMountedAncestor, parent), (parent = parent.sibling); } @@ -6015,7 +6028,7 @@ function commitDeletionEffectsOnFiber( if (injectedHook && "function" === typeof injectedHook.onCommitFiberUnmount) try { injectedHook.onCommitFiberUnmount(rendererID, deletedFiber); - } catch (err) {} + } catch (err) { } switch (deletedFiber.tag) { case 5: safelyDetachRef(deletedFiber, nearestMountedAncestor); @@ -6093,11 +6106,11 @@ function commitDeletionEffectsOnFiber( (0 !== (_effect & 2) ? safelyCallDestroy(deletedFiber, nearestMountedAncestor, destroy) : 0 !== (_effect & 4) && - safelyCallDestroy( - deletedFiber, - nearestMountedAncestor, - destroy - )); + safelyCallDestroy( + deletedFiber, + nearestMountedAncestor, + destroy + )); prevHostParentIsContainer = prevHostParentIsContainer.next; } while (prevHostParentIsContainer !== prevHostParent); } @@ -6153,7 +6166,7 @@ function attachSuspenseRetryListeners(finishedWork) { var retryCache = finishedWork.stateNode; null === retryCache && (retryCache = finishedWork.stateNode = new PossiblyWeakSet()); - wakeables.forEach(function(wakeable) { + wakeables.forEach(function (wakeable) { var retry = resolveRetryWakeable.bind(null, finishedWork, wakeable); retryCache.has(wakeable) || (retryCache.add(wakeable), wakeable.then(retry, retry)); @@ -6169,7 +6182,7 @@ function recursivelyTraverseMutationEffects(root$jscomp$0, parentFiber) { var root = root$jscomp$0, returnFiber = parentFiber, parent = returnFiber; - a: for (; null !== parent; ) { + a: for (; null !== parent;) { switch (parent.tag) { case 5: hostParent = parent.stateNode; @@ -6201,7 +6214,7 @@ function recursivelyTraverseMutationEffects(root$jscomp$0, parentFiber) { } } if (parentFiber.subtreeFlags & 12854) - for (parentFiber = parentFiber.child; null !== parentFiber; ) + for (parentFiber = parentFiber.child; null !== parentFiber;) commitMutationEffectsOnFiber(parentFiber, root$jscomp$0), (parentFiber = parentFiber.sibling); } @@ -6310,8 +6323,8 @@ function commitMutationEffectsOnFiber(finishedWork, root) { viewConfig = finishedWork.child; viewConfig.flags & 8192 && ((updatePayload$jscomp$0 = null !== viewConfig.memoizedState), - (viewConfig.stateNode.isHidden = updatePayload$jscomp$0), - !updatePayload$jscomp$0 || + (viewConfig.stateNode.isHidden = updatePayload$jscomp$0), + !updatePayload$jscomp$0 || (null !== viewConfig.alternate && null !== viewConfig.alternate.memoizedState) || (globalMostRecentFallbackTime = now())); @@ -6323,9 +6336,9 @@ function commitMutationEffectsOnFiber(finishedWork, root) { if (flags & 8192) a: for ( viewConfig = null !== finishedWork.memoizedState, - finishedWork.stateNode.isHidden = viewConfig, - updatePayload$jscomp$0 = null, - current = finishedWork; + finishedWork.stateNode.isHidden = viewConfig, + updatePayload$jscomp$0 = null, + current = finishedWork; ; ) { @@ -6395,7 +6408,7 @@ function commitMutationEffectsOnFiber(finishedWork, root) { continue; } if (current === finishedWork) break a; - for (; null === current.sibling; ) { + for (; null === current.sibling;) { if (null === current.return || current.return === finishedWork) break a; updatePayload$jscomp$0 === current && @@ -6424,7 +6437,7 @@ function commitReconciliationEffects(finishedWork) { if (flags & 2) { try { a: { - for (var parent = finishedWork.return; null !== parent; ) { + for (var parent = finishedWork.return; null !== parent;) { if (isHostParent(parent)) { var JSCompiler_inline_result = parent; break a; @@ -6466,13 +6479,13 @@ function commitReconciliationEffects(finishedWork) { flags & 4096 && (finishedWork.flags &= -4097); } function commitLayoutEffects(finishedWork) { - for (nextEffect = finishedWork; null !== nextEffect; ) { + for (nextEffect = finishedWork; null !== nextEffect;) { var fiber = nextEffect, firstChild = fiber.child; if (0 !== (fiber.subtreeFlags & 8772) && null !== firstChild) (firstChild.return = fiber), (nextEffect = firstChild); else - for (fiber = finishedWork; null !== nextEffect; ) { + for (fiber = finishedWork; null !== nextEffect;) { firstChild = nextEffect; if (0 !== (firstChild.flags & 8772)) { var current = firstChild.alternate; @@ -6493,9 +6506,9 @@ function commitLayoutEffects(finishedWork) { firstChild.elementType === firstChild.type ? current.memoizedProps : resolveDefaultProps( - firstChild.type, - current.memoizedProps - ); + firstChild.type, + current.memoizedProps + ); instance.componentDidUpdate( prevProps, current.memoizedState, @@ -6612,8 +6625,8 @@ function requestEventTime() { return 0 !== (executionContext & 6) ? now() : -1 !== currentEventTime - ? currentEventTime - : (currentEventTime = now()); + ? currentEventTime + : (currentEventTime = now()); } function requestUpdateLane(fiber) { if (0 === (fiber.mode & 1)) return 1; @@ -6622,40 +6635,44 @@ function requestUpdateLane(fiber) { if (null !== ReactCurrentBatchConfig.transition) return ( 0 === currentEventTransitionLane && - (currentEventTransitionLane = claimNextTransitionLane()), + (currentEventTransitionLane = claimNextTransitionLane()), currentEventTransitionLane ); fiber = currentUpdatePriority; return 0 !== fiber ? fiber : 16; } function scheduleUpdateOnFiber(root, fiber, lane, eventTime) { + updatedComponentForProfiler = { + name: getComponentNameFromFiber(fiber), + key: fiber.key, + }; if (50 < nestedUpdateCount) throw ((nestedUpdateCount = 0), - (rootWithNestedUpdates = null), - 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." - )); + (rootWithNestedUpdates = null), + 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." + )); markRootUpdated(root, lane, eventTime); if (0 === (executionContext & 2) || root !== workInProgressRoot) root === workInProgressRoot && (0 === (executionContext & 2) && (workInProgressRootInterleavedUpdatedLanes |= lane), - 4 === workInProgressRootExitStatus && + 4 === workInProgressRootExitStatus && markRootSuspended$1(root, workInProgressRootRenderLanes)), ensureRootIsScheduled(root, eventTime), 1 === lane && - 0 === executionContext && - 0 === (fiber.mode & 1) && - ((workInProgressRootRenderTargetTime = now() + 500), + 0 === executionContext && + 0 === (fiber.mode & 1) && + ((workInProgressRootRenderTargetTime = now() + 500), includesLegacySyncCallbacks && flushSyncCallbacks()); } function ensureRootIsScheduled(root, currentTime) { for ( var existingCallbackNode = root.callbackNode, - suspendedLanes = root.suspendedLanes, - pingedLanes = root.pingedLanes, - expirationTimes = root.expirationTimes, - lanes = root.pendingLanes; + suspendedLanes = root.suspendedLanes, + pingedLanes = root.pingedLanes, + expirationTimes = root.expirationTimes, + lanes = root.pendingLanes; 0 < lanes; ) { @@ -6678,7 +6695,7 @@ function ensureRootIsScheduled(root, currentTime) { (root.callbackPriority = 0); else if ( ((currentTime = suspendedLanes & -suspendedLanes), - root.callbackPriority !== currentTime) + root.callbackPriority !== currentTime) ) { null != existingCallbackNode && cancelCallback(existingCallbackNode); if (1 === currentTime) @@ -6767,15 +6784,15 @@ function performConcurrentWorkOnRoot(root, didTimeout) { if (0 !== didTimeout) { 2 === didTimeout && ((prevExecutionContext = getLanesToRetrySynchronouslyOnError(root)), - 0 !== prevExecutionContext && + 0 !== prevExecutionContext && ((lanes = prevExecutionContext), - (didTimeout = recoverFromConcurrentError(root, prevExecutionContext)))); + (didTimeout = recoverFromConcurrentError(root, prevExecutionContext)))); if (1 === didTimeout) throw ((originalCallbackNode = workInProgressRootFatalError), - prepareFreshStack(root, 0), - markRootSuspended$1(root, lanes), - ensureRootIsScheduled(root, now()), - originalCallbackNode); + prepareFreshStack(root, 0), + markRootSuspended$1(root, lanes), + ensureRootIsScheduled(root, now()), + originalCallbackNode); if (6 === didTimeout) markRootSuspended$1(root, lanes); else { prevExecutionContext = root.current.alternate; @@ -6783,18 +6800,18 @@ function performConcurrentWorkOnRoot(root, didTimeout) { 0 === (lanes & 30) && !isRenderConsistentWithExternalStores(prevExecutionContext) && ((didTimeout = renderRootSync(root, lanes)), - 2 === didTimeout && + 2 === didTimeout && ((prevDispatcher = getLanesToRetrySynchronouslyOnError(root)), - 0 !== prevDispatcher && + 0 !== prevDispatcher && ((lanes = prevDispatcher), - (didTimeout = recoverFromConcurrentError(root, prevDispatcher)))), - 1 === didTimeout) + (didTimeout = recoverFromConcurrentError(root, prevDispatcher)))), + 1 === didTimeout) ) throw ((originalCallbackNode = workInProgressRootFatalError), - prepareFreshStack(root, 0), - markRootSuspended$1(root, lanes), - ensureRootIsScheduled(root, now()), - originalCallbackNode); + prepareFreshStack(root, 0), + markRootSuspended$1(root, lanes), + ensureRootIsScheduled(root, now()), + originalCallbackNode); root.finishedWork = prevExecutionContext; root.finishedLanes = lanes; switch (didTimeout) { @@ -6813,7 +6830,7 @@ function performConcurrentWorkOnRoot(root, didTimeout) { if ( (lanes & 130023424) === lanes && ((didTimeout = globalMostRecentFallbackTime + 500 - now()), - 10 < didTimeout) + 10 < didTimeout) ) { if (0 !== getNextLanes(root, 0)) break; prevExecutionContext = root.suspendedLanes; @@ -6843,7 +6860,7 @@ function performConcurrentWorkOnRoot(root, didTimeout) { markRootSuspended$1(root, lanes); if ((lanes & 4194240) === lanes) break; didTimeout = root.eventTimes; - for (prevExecutionContext = -1; 0 < lanes; ) { + for (prevExecutionContext = -1; 0 < lanes;) { var index$5 = 31 - clz32(lanes); prevDispatcher = 1 << index$5; index$5 = didTimeout[index$5]; @@ -6856,16 +6873,16 @@ function performConcurrentWorkOnRoot(root, didTimeout) { (120 > lanes ? 120 : 480 > lanes - ? 480 - : 1080 > lanes - ? 1080 - : 1920 > lanes - ? 1920 - : 3e3 > lanes - ? 3e3 - : 4320 > lanes - ? 4320 - : 1960 * ceil(lanes / 1960)) - lanes; + ? 480 + : 1080 > lanes + ? 1080 + : 1920 > lanes + ? 1920 + : 3e3 > lanes + ? 3e3 + : 4320 > lanes + ? 4320 + : 1960 * ceil(lanes / 1960)) - lanes; if (10 < lanes) { root.timeoutHandle = scheduleTimeout( commitRoot.bind( @@ -6908,20 +6925,20 @@ function recoverFromConcurrentError(root, errorRetryLanes) { root = renderRootSync(root, errorRetryLanes); 2 !== root && ((errorRetryLanes = workInProgressRootRecoverableErrors), - (workInProgressRootRecoverableErrors = errorsFromFirstAttempt), - null !== errorRetryLanes && queueRecoverableErrors(errorRetryLanes)); + (workInProgressRootRecoverableErrors = errorsFromFirstAttempt), + null !== errorRetryLanes && queueRecoverableErrors(errorRetryLanes)); return root; } function queueRecoverableErrors(errors) { null === workInProgressRootRecoverableErrors ? (workInProgressRootRecoverableErrors = errors) : workInProgressRootRecoverableErrors.push.apply( - workInProgressRootRecoverableErrors, - errors - ); + workInProgressRootRecoverableErrors, + errors + ); } function isRenderConsistentWithExternalStores(finishedWork) { - for (var node = finishedWork; ; ) { + for (var node = finishedWork; ;) { if (node.flags & 16384) { var updateQueue = node.updateQueue; if ( @@ -6944,7 +6961,7 @@ function isRenderConsistentWithExternalStores(finishedWork) { (updateQueue.return = node), (node = updateQueue); else { if (node === finishedWork) break; - for (; null === node.sibling; ) { + for (; null === node.sibling;) { if (null === node.return || node.return === finishedWork) return !0; node = node.return; } @@ -6959,7 +6976,7 @@ function markRootSuspended$1(root, suspendedLanes) { suspendedLanes &= ~workInProgressRootInterleavedUpdatedLanes; root.suspendedLanes |= suspendedLanes; root.pingedLanes &= ~suspendedLanes; - for (root = root.expirationTimes; 0 < suspendedLanes; ) { + for (root = root.expirationTimes; 0 < suspendedLanes;) { var index$7 = 31 - clz32(suspendedLanes), lane = 1 << index$7; root[index$7] = -1; @@ -6977,14 +6994,14 @@ function performSyncWorkOnRoot(root) { var errorRetryLanes = getLanesToRetrySynchronouslyOnError(root); 0 !== errorRetryLanes && ((lanes = errorRetryLanes), - (exitStatus = recoverFromConcurrentError(root, errorRetryLanes))); + (exitStatus = recoverFromConcurrentError(root, errorRetryLanes))); } if (1 === exitStatus) throw ((exitStatus = workInProgressRootFatalError), - prepareFreshStack(root, 0), - markRootSuspended$1(root, lanes), - ensureRootIsScheduled(root, now()), - exitStatus); + prepareFreshStack(root, 0), + markRootSuspended$1(root, lanes), + ensureRootIsScheduled(root, now()), + exitStatus); if (6 === exitStatus) throw Error("Root did not complete. This is a bug in React."); root.finishedWork = root.current.alternate; @@ -7008,7 +7025,7 @@ function prepareFreshStack(root, lanes) { -1 !== timeoutHandle && ((root.timeoutHandle = -1), cancelTimeout(timeoutHandle)); if (null !== workInProgress) - for (timeoutHandle = workInProgress.return; null !== timeoutHandle; ) { + for (timeoutHandle = workInProgress.return; null !== timeoutHandle;) { var interruptedWork = timeoutHandle; popTreeContext(interruptedWork); switch (interruptedWork.tag) { @@ -7056,8 +7073,8 @@ function prepareFreshStack(root, lanes) { for (lanes = 0; lanes < concurrentQueues.length; lanes++) if ( ((timeoutHandle = concurrentQueues[lanes]), - (interruptedWork = timeoutHandle.interleaved), - null !== interruptedWork) + (interruptedWork = timeoutHandle.interleaved), + null !== interruptedWork) ) { timeoutHandle.interleaved = null; var firstInterleavedUpdate = interruptedWork.next, @@ -7294,10 +7311,10 @@ function renderRootSync(root, lanes) { return workInProgressRootExitStatus; } function workLoopSync() { - for (; null !== workInProgress; ) performUnitOfWork(workInProgress); + for (; null !== workInProgress;) performUnitOfWork(workInProgress); } function workLoopConcurrent() { - for (; null !== workInProgress && !shouldYield(); ) + for (; null !== workInProgress && !shouldYield();) performUnitOfWork(workInProgress); } function performUnitOfWork(unitOfWork) { @@ -7314,7 +7331,7 @@ function completeUnitOfWork(unitOfWork) { if (0 === (completedWork.flags & 32768)) { if ( ((current = completeWork(current, completedWork, subtreeRenderLanes)), - null !== current) + null !== current) ) { workInProgress = current; return; @@ -7348,6 +7365,9 @@ function completeUnitOfWork(unitOfWork) { function commitRoot(root, recoverableErrors, transitions) { var previousUpdateLanePriority = currentUpdatePriority, prevTransition = ReactCurrentBatchConfig$2.transition; + defrost.writeInLogFiles(Date.now() + "", { list: updatedComponents, change: updatedComponentForProfiler }) + updatedComponents = [] + updatedComponentForProfiler = null try { (ReactCurrentBatchConfig$2.transition = null), (currentUpdatePriority = 1), @@ -7388,15 +7408,15 @@ function commitRootImpl( markRootFinished(root, remainingLanes); root === workInProgressRoot && ((workInProgress = workInProgressRoot = null), - (workInProgressRootRenderLanes = 0)); + (workInProgressRootRenderLanes = 0)); (0 === (transitions.subtreeFlags & 2064) && 0 === (transitions.flags & 2064)) || rootDoesHavePassiveEffects || ((rootDoesHavePassiveEffects = !0), - scheduleCallback$1(NormalPriority, function() { - flushPassiveEffects(); - return null; - })); + scheduleCallback$1(NormalPriority, function () { + flushPassiveEffects(); + return null; + })); remainingLanes = 0 !== (transitions.flags & 15990); if (0 !== (transitions.subtreeFlags & 15990) || remainingLanes) { remainingLanes = ReactCurrentBatchConfig$2.transition; @@ -7417,8 +7437,8 @@ function commitRootImpl( } else root.current = transitions; rootDoesHavePassiveEffects && ((rootDoesHavePassiveEffects = !1), - (rootWithPendingPassiveEffects = root), - (pendingPassiveEffectsLanes = lanes)); + (rootWithPendingPassiveEffects = root), + (pendingPassiveEffectsLanes = lanes)); remainingLanes = root.pendingLanes; 0 === remainingLanes && (legacyErrorBoundariesThatAlreadyFailed = null); onCommitRoot(transitions.stateNode, renderPriorityLevel); @@ -7436,9 +7456,9 @@ function commitRootImpl( }); if (hasUncaughtError) throw ((hasUncaughtError = !1), - (root = firstUncaughtError), - (firstUncaughtError = null), - root); + (root = firstUncaughtError), + (firstUncaughtError = null), + root); 0 !== (pendingPassiveEffectsLanes & 1) && 0 !== root.tag && flushPassiveEffects(); @@ -7469,7 +7489,7 @@ function flushPassiveEffects() { throw Error("Cannot flush passive effects while already rendering."); var prevExecutionContext = executionContext; executionContext |= 4; - for (nextEffect = renderPriority.current; null !== nextEffect; ) { + for (nextEffect = renderPriority.current; null !== nextEffect;) { var fiber = nextEffect, child = fiber.child; if (0 !== (nextEffect.flags & 16)) { @@ -7477,7 +7497,7 @@ function flushPassiveEffects() { if (null !== deletions) { for (var i = 0; i < deletions.length; i++) { var fiberToDelete = deletions[i]; - for (nextEffect = fiberToDelete; null !== nextEffect; ) { + for (nextEffect = fiberToDelete; null !== nextEffect;) { var fiber$jscomp$0 = nextEffect; switch (fiber$jscomp$0.tag) { case 0: @@ -7490,7 +7510,7 @@ function flushPassiveEffects() { (child$jscomp$0.return = fiber$jscomp$0), (nextEffect = child$jscomp$0); else - for (; null !== nextEffect; ) { + for (; null !== nextEffect;) { fiber$jscomp$0 = nextEffect; var sibling = fiber$jscomp$0.sibling, returnFiber = fiber$jscomp$0.return; @@ -7526,7 +7546,7 @@ function flushPassiveEffects() { if (0 !== (fiber.subtreeFlags & 2064) && null !== child) (child.return = fiber), (nextEffect = child); else - b: for (; null !== nextEffect; ) { + b: for (; null !== nextEffect;) { fiber = nextEffect; if (0 !== (fiber.flags & 2048)) switch (fiber.tag) { @@ -7545,13 +7565,13 @@ function flushPassiveEffects() { } } var finishedWork = renderPriority.current; - for (nextEffect = finishedWork; null !== nextEffect; ) { + for (nextEffect = finishedWork; null !== nextEffect;) { child = nextEffect; var firstChild = child.child; if (0 !== (child.subtreeFlags & 2064) && null !== firstChild) (firstChild.return = child), (nextEffect = firstChild); else - b: for (child = finishedWork; null !== nextEffect; ) { + b: for (child = finishedWork; null !== nextEffect;) { deletions = nextEffect; if (0 !== (deletions.flags & 2048)) try { @@ -7585,7 +7605,7 @@ function flushPassiveEffects() { ) try { injectedHook.onPostCommitFiberRoot(rendererID, renderPriority); - } catch (err) {} + } catch (err) { } JSCompiler_inline_result = !0; } return JSCompiler_inline_result; @@ -7603,7 +7623,7 @@ function captureCommitPhaseErrorOnRoot(rootFiber, sourceFiber, error) { sourceFiber = requestEventTime(); null !== rootFiber && (markRootUpdated(rootFiber, 1, sourceFiber), - ensureRootIsScheduled(rootFiber, sourceFiber)); + ensureRootIsScheduled(rootFiber, sourceFiber)); } function captureCommitPhaseError(sourceFiber, nearestMountedAncestor, error) { if (3 === sourceFiber.tag) @@ -7625,7 +7645,7 @@ function captureCommitPhaseError(sourceFiber, nearestMountedAncestor, error) { var instance = nearestMountedAncestor.stateNode; if ( "function" === - typeof nearestMountedAncestor.type.getDerivedStateFromError || + typeof nearestMountedAncestor.type.getDerivedStateFromError || ("function" === typeof instance.componentDidCatch && (null === legacyErrorBoundariesThatAlreadyFailed || !legacyErrorBoundariesThatAlreadyFailed.has(instance))) @@ -7644,7 +7664,7 @@ function captureCommitPhaseError(sourceFiber, nearestMountedAncestor, error) { sourceFiber = requestEventTime(); null !== nearestMountedAncestor && (markRootUpdated(nearestMountedAncestor, 1, sourceFiber), - ensureRootIsScheduled(nearestMountedAncestor, sourceFiber)); + ensureRootIsScheduled(nearestMountedAncestor, sourceFiber)); break; } } @@ -7659,10 +7679,10 @@ function pingSuspendedRoot(root, wakeable, pingedLanes) { workInProgressRoot === root && (workInProgressRootRenderLanes & pingedLanes) === pingedLanes && (4 === workInProgressRootExitStatus || - (3 === workInProgressRootExitStatus && - (workInProgressRootRenderLanes & 130023424) === + (3 === workInProgressRootExitStatus && + (workInProgressRootRenderLanes & 130023424) === workInProgressRootRenderLanes && - 500 > now() - globalMostRecentFallbackTime) + 500 > now() - globalMostRecentFallbackTime) ? prepareFreshStack(root, 0) : (workInProgressRootPingedLanes |= pingedLanes)); ensureRootIsScheduled(root, wakeable); @@ -7678,7 +7698,7 @@ function retryTimedOutBoundary(boundaryFiber, retryLane) { boundaryFiber = markUpdateLaneFromFiberToRoot(boundaryFiber, retryLane); null !== boundaryFiber && (markRootUpdated(boundaryFiber, retryLane, eventTime), - ensureRootIsScheduled(boundaryFiber, eventTime)); + ensureRootIsScheduled(boundaryFiber, eventTime)); } function retryDehydratedSuspenseBoundary(boundaryFiber) { var suspenseState = boundaryFiber.memoizedState, @@ -7706,7 +7726,7 @@ function resolveRetryWakeable(boundaryFiber, wakeable) { retryTimedOutBoundary(boundaryFiber, retryLane); } var beginWork$1; -beginWork$1 = function(current, workInProgress, renderLanes) { +beginWork$1 = function (current, workInProgress, renderLanes) { if (null !== current) if ( current.memoizedProps !== workInProgress.pendingProps || @@ -7834,8 +7854,8 @@ beginWork$1 = function(current, workInProgress, renderLanes) { } throw Error( "Element type is invalid. Received a promise that resolves to: " + - Component + - ". Lazy element type must resolve to a class or function." + Component + + ". Lazy element type must resolve to a class or function." ); } return workInProgress; @@ -7882,10 +7902,10 @@ beginWork$1 = function(current, workInProgress, renderLanes) { context = workInProgress.memoizedState.element; context === Component ? (workInProgress = bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderLanes - )) + current, + workInProgress, + renderLanes + )) : (reconcileChildren(current, workInProgress, context, renderLanes), (workInProgress = workInProgress.child)); return workInProgress; @@ -7910,11 +7930,11 @@ beginWork$1 = function(current, workInProgress, renderLanes) { (Component = workInProgress.pendingProps), null === current ? (workInProgress.child = reconcileChildFibers( - workInProgress, - null, - Component, - renderLanes - )) + workInProgress, + null, + Component, + renderLanes + )) : reconcileChildren(current, workInProgress, Component, renderLanes), workInProgress.child ); @@ -7988,7 +8008,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { } else for ( hasContext = workInProgress.child, - null !== hasContext && (hasContext.return = workInProgress); + null !== hasContext && (hasContext.return = workInProgress); null !== hasContext; ) { @@ -8051,7 +8071,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { } else newValue = hasContext.child; if (null !== newValue) newValue.return = hasContext; else - for (newValue = hasContext; null !== newValue; ) { + for (newValue = hasContext; null !== newValue;) { if (newValue === workInProgress) { newValue = null; break; @@ -8139,8 +8159,8 @@ beginWork$1 = function(current, workInProgress, renderLanes) { } throw Error( "Unknown unit of work tag (" + - workInProgress.tag + - "). This error is likely caused by a bug in React. Please file an issue." + workInProgress.tag + + "). This error is likely caused by a bug in React. Please file an issue." ); }; function scheduleCallback$1(priorityLevel, callback) { @@ -8181,11 +8201,11 @@ function createWorkInProgress(current, pendingProps) { var workInProgress = current.alternate; null === workInProgress ? ((workInProgress = createFiber( - current.tag, - pendingProps, - current.key, - current.mode - )), + current.tag, + pendingProps, + current.key, + current.mode + )), (workInProgress.elementType = current.elementType), (workInProgress.type = current.type), (workInProgress.stateNode = current.stateNode), @@ -8278,7 +8298,7 @@ function createFiberFromTypeAndProps( } throw Error( "Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: " + - ((null == type ? type : typeof type) + ".") + ((null == type ? type : typeof type) + ".") ); } key = createFiber(fiberTag, pendingProps, key, mode); @@ -8421,7 +8441,7 @@ function updateContainer(element, container, parentComponent, callback) { element = enqueueUpdate(current, container, lane); null !== element && (scheduleUpdateOnFiber(element, current, lane, eventTime), - entangleTransitions(element, current, lane)); + entangleTransitions(element, current, lane)); return lane; } function emptyFindFiberByHostInstance() { @@ -8437,8 +8457,8 @@ function findNodeHandle(componentOrHandle) { return null == componentOrHandle ? componentOrHandle : componentOrHandle.canonical - ? componentOrHandle.canonical._nativeTag - : componentOrHandle._nativeTag; + ? componentOrHandle.canonical._nativeTag + : componentOrHandle._nativeTag; } function onRecoverableError(error) { console.error(error); @@ -8446,11 +8466,11 @@ function onRecoverableError(error) { function unmountComponentAtNode(containerTag) { var root = roots.get(containerTag); root && - updateContainer(null, root, null, function() { + updateContainer(null, root, null, function () { roots.delete(containerTag); }); } -batchedUpdatesImpl = function(fn, a) { +batchedUpdatesImpl = function (fn, a) { var prevExecutionContext = executionContext; executionContext |= 1; try { @@ -8458,7 +8478,7 @@ batchedUpdatesImpl = function(fn, a) { } finally { (executionContext = prevExecutionContext), 0 === executionContext && - ((workInProgressRootRenderTargetTime = now() + 500), + ((workInProgressRootRenderTargetTime = now() + 500), includesLegacySyncCallbacks && flushSyncCallbacks()); } }; @@ -8469,12 +8489,12 @@ var roots = new Map(), version: "18.2.0-next-9e3b772b8-20220608", rendererPackageName: "react-native-renderer", rendererConfig: { - getInspectorDataForViewTag: function() { + getInspectorDataForViewTag: function () { throw Error( "getInspectorDataForViewTag() is not available in production" ); }, - getInspectorDataForViewAtPoint: function() { + getInspectorDataForViewAtPoint: function () { throw Error( "getInspectorDataForViewAtPoint() is not available in production." ); @@ -8496,7 +8516,7 @@ var internals$jscomp$inline_1247 = { setSuspenseHandler: null, scheduleUpdate: null, currentDispatcherRef: ReactSharedInternals.ReactCurrentDispatcher, - findHostInstanceByFiber: function(fiber) { + findHostInstanceByFiber: function (fiber) { fiber = findCurrentHostFiber(fiber); return null === fiber ? null : fiber.stateNode; }, @@ -8521,16 +8541,16 @@ if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { internals$jscomp$inline_1247 )), (injectedHook = hook$jscomp$inline_1248); - } catch (err) {} + } catch (err) { } } exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = { - computeComponentStackForErrorReporting: function(reactTag) { + computeComponentStackForErrorReporting: function (reactTag) { return (reactTag = getInstanceFromTag(reactTag)) ? getStackByFiberInDevAndProd(reactTag) : ""; } }; -exports.createPortal = function(children, containerTag) { +exports.createPortal = function (children, containerTag) { return createPortal( children, containerTag, @@ -8538,19 +8558,19 @@ exports.createPortal = function(children, containerTag) { 2 < arguments.length && void 0 !== arguments[2] ? arguments[2] : null ); }; -exports.dispatchCommand = function(handle, command, args) { +exports.dispatchCommand = function (handle, command, args) { null != handle._nativeTag && (null != handle._internalInstanceHandle ? ((handle = handle._internalInstanceHandle.stateNode), null != handle && - nativeFabricUIManager.dispatchCommand(handle.node, command, args)) + nativeFabricUIManager.dispatchCommand(handle.node, command, args)) : ReactNativePrivateInterface.UIManager.dispatchViewManagerCommand( - handle._nativeTag, - command, - args - )); + handle._nativeTag, + command, + args + )); }; -exports.findHostInstance_DEPRECATED = function(componentOrHandle) { +exports.findHostInstance_DEPRECATED = function (componentOrHandle) { if (null == componentOrHandle) return null; if (componentOrHandle._nativeTag) return componentOrHandle; if (componentOrHandle.canonical && componentOrHandle.canonical._nativeTag) @@ -8559,12 +8579,12 @@ exports.findHostInstance_DEPRECATED = function(componentOrHandle) { return null == componentOrHandle ? componentOrHandle : componentOrHandle.canonical - ? componentOrHandle.canonical - : componentOrHandle; + ? componentOrHandle.canonical + : componentOrHandle; }; exports.findNodeHandle = findNodeHandle; exports.getInspectorDataForInstance = void 0; -exports.render = function(element, containerTag, callback) { +exports.render = function (element, containerTag, callback) { var root = roots.get(containerTag); if (!root) { root = new FiberRootNode(containerTag, 0, !1, "", onRecoverableError); @@ -8593,19 +8613,19 @@ exports.render = function(element, containerTag, callback) { else element = null; return element; }; -exports.sendAccessibilityEvent = function(handle, eventType) { +exports.sendAccessibilityEvent = function (handle, eventType) { null != handle._nativeTag && (null != handle._internalInstanceHandle ? ((handle = handle._internalInstanceHandle.stateNode), null != handle && - nativeFabricUIManager.sendAccessibilityEvent(handle.node, eventType)) + nativeFabricUIManager.sendAccessibilityEvent(handle.node, eventType)) : ReactNativePrivateInterface.legacySendAccessibilityEvent( - handle._nativeTag, - eventType - )); + handle._nativeTag, + eventType + )); }; exports.unmountComponentAtNode = unmountComponentAtNode; -exports.unmountComponentAtNodeAndRemoveContainer = function(containerTag) { +exports.unmountComponentAtNodeAndRemoveContainer = function (containerTag) { unmountComponentAtNode(containerTag); ReactNativePrivateInterface.UIManager.removeRootView(containerTag); };