diff --git a/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react-test-renderer/cjs/ReactTestRenderer-dev.js b/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react-test-renderer/cjs/ReactTestRenderer-dev.js index 12ec7bea873c2..49bc461dc4bd9 100644 --- a/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react-test-renderer/cjs/ReactTestRenderer-dev.js +++ b/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react-test-renderer/cjs/ReactTestRenderer-dev.js @@ -452,7 +452,7 @@ var Hydrating = var Update = /* */ 4; -/* Skipped value: 0b000000000000000000000001000; */ +/* Skipped value: 0b0000000000000000000000001000; */ var ChildDeletion = /* */ @@ -463,7 +463,7 @@ var ContentReset = var Callback = /* */ 64; -/* Used by DidCapture: 0b000000000000000000010000000; */ +/* Used by DidCapture: 0b0000000000000000000010000000; */ var ForceClientRender = /* */ @@ -477,20 +477,24 @@ var Snapshot = var Passive$1 = /* */ 2048; -/* Used by Hydrating: 0b000000000000001000000000000; */ +/* Used by Hydrating: 0b0000000000000001000000000000; */ var Visibility = /* */ 8192; var StoreConsistency = /* */ - 16384; + 16384; // It's OK to reuse this bit because these flags are mutually exclusive for +// different fiber types. We should really be doing this for as many flags as +// possible, because we're about to run out of bits. + +var ScheduleRetry = StoreConsistency; var LifecycleEffectMask = Passive$1 | Update | Callback | Ref | Snapshot | StoreConsistency; // Union of all commit flags (flags with the lifetime of a particular commit) var HostEffectMask = /* */ - 16383; // These are not really side effects, but we still reuse this field. + 32767; // These are not really side effects, but we still reuse this field. var Incomplete = /* */ @@ -517,17 +521,20 @@ var LayoutStatic = 4194304; var PassiveStatic = /* */ - 8388608; // Flag used to identify newly inserted fibers. It isn't reset after commit unlike `Placement`. + 8388608; +var SuspenseyCommit = + /* */ + 16777216; // Flag used to identify newly inserted fibers. It isn't reset after commit unlike `Placement`. var PlacementDEV = /* */ - 16777216; + 33554432; var MountLayoutDev = /* */ - 33554432; + 67108864; var MountPassiveDev = /* */ - 67108864; // Groups of flags that are used in the commit phase to skip over trees that + 134217728; // Groups of flags that are used in the commit phase to skip over trees that // don't contain effects, by checking subtreeFlags. var BeforeMutationMask = // TODO: Remove Update flag from before mutation phase by re-landing Visibility @@ -547,7 +554,7 @@ var PassiveMask = Passive$1 | Visibility | ChildDeletion; // Union of tags that // 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 StaticMask = LayoutStatic | PassiveStatic | RefStatic | SuspenseyCommit; var ReactCurrentOwner$2 = ReactSharedInternals.ReactCurrentOwner; function getNearestMountedFiber(fiber) { @@ -2005,6 +2012,9 @@ function unhideInstance(instance, props) { function unhideTextInstance(textInstance, text) { textInstance.isHidden = false; } +function waitForCommitToBeReady() { + return null; +} function describeBuiltInComponentFrame(name, source, ownerFn) { { @@ -2616,46 +2626,71 @@ function flushSyncCallbacksOnlyInLegacyMode() { function flushSyncCallbacks() { if (!isFlushingSyncQueue && syncQueue !== null) { // Prevent re-entrance. - isFlushingSyncQueue = true; - var i = 0; - var previousUpdatePriority = getCurrentUpdatePriority(); + isFlushingSyncQueue = true; // Set the event priority to discrete + // TODO: Is this necessary anymore? The only user code that runs in this + // queue is in the render or commit phases, which already set the + // event priority. Should be able to remove. - 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); // $FlowFixMe[incompatible-use] found when upgrading Flow + var previousUpdatePriority = getCurrentUpdatePriority(); + setCurrentUpdatePriority(DiscreteEventPriority); + var errors = null; + var queue = syncQueue; // $FlowFixMe[incompatible-use] found when upgrading Flow - for (; i < queue.length; i++) { - // $FlowFixMe[incompatible-use] found when upgrading Flow - var callback = queue[i]; + for (var i = 0; i < queue.length; i++) { + // $FlowFixMe[incompatible-use] found when upgrading Flow + var callback = queue[i]; + try { do { - // $FlowFixMe[incompatible-type] we bail out when we get a null + var isSync = true; // $FlowFixMe[incompatible-type] we bail out when we get a null + callback = callback(isSync); } while (callback !== null); + } catch (error) { + // Collect errors so we can rethrow them at the end + if (errors === null) { + errors = [error]; + } else { + errors.push(error); + } } + } - 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 + syncQueue = null; + includesLegacySyncCallbacks = false; + setCurrentUpdatePriority(previousUpdatePriority); + isFlushingSyncQueue = false; - scheduleCallback$2(ImmediatePriority, flushSyncCallbacks); - throw error; - } finally { - setCurrentUpdatePriority(previousUpdatePriority); - isFlushingSyncQueue = false; + if (errors !== null) { + if (errors.length > 1) { + if (typeof AggregateError === "function") { + // eslint-disable-next-line no-undef + throw new AggregateError(errors); + } else { + for (var _i = 1; _i < errors.length; _i++) { + scheduleCallback$2( + ImmediatePriority, + throwError.bind(null, errors[_i]) + ); + } + + var firstError = errors[0]; + throw firstError; + } + } else { + var error = errors[0]; + throw error; + } } } return null; } +function throwError(error) { + throw error; +} + // 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. @@ -4129,6 +4164,172 @@ function checkPropStringCoercion(value, propName) { } } +var ReactCurrentActQueue$2 = ReactSharedInternals.ReactCurrentActQueue; // An error that is thrown (e.g. by `use`) to trigger Suspense. If we +// detect this is caught by userspace, we'll log a warning in development. + +var SuspenseException = new Error( + "Suspense Exception: This is not a real error! It's an implementation " + + "detail of `use` to interrupt the current render. You must either " + + "rethrow it immediately, or move the `use` call outside of the " + + "`try/catch` block. Capturing without rethrowing will lead to " + + "unexpected behavior.\n\n" + + "To handle async errors, wrap your component in an error boundary, or " + + "call the promise's `.catch` method and pass the result to `use`" +); // This is a noop thenable that we use to trigger a fallback in throwException. +// TODO: It would be better to refactor throwException into multiple functions +// so we can trigger a fallback directly without having to check the type. But +// for now this will do. + +var noopSuspenseyCommitThenable = { + then: function () {} +}; +function createThenableState() { + // The ThenableState is created the first time a component suspends. If it + // suspends again, we'll reuse the same state. + return []; +} +function isThenableResolved(thenable) { + var status = thenable.status; + return status === "fulfilled" || status === "rejected"; +} + +function noop() {} + +function trackUsedThenable(thenableState, thenable, index) { + if (ReactCurrentActQueue$2.current !== null) { + ReactCurrentActQueue$2.didUsePromise = true; + } + + var previous = thenableState[index]; + + if (previous === undefined) { + thenableState.push(thenable); + } else { + if (previous !== thenable) { + // Reuse the previous thenable, and drop the new one. We can assume + // they represent the same value, because components are idempotent. + // Avoid an unhandled rejection errors for the Promises that we'll + // intentionally ignore. + thenable.then(noop, noop); + thenable = previous; + } + } // We use an expando to track the status and result of a thenable so that we + // can synchronously unwrap the value. Think of this as an extension of the + // Promise API, or a custom interface that is a superset of Thenable. + // + // If the thenable doesn't have a status, set it to "pending" and attach + // a listener that will update its status and result when it resolves. + + switch (thenable.status) { + case "fulfilled": { + var fulfilledValue = thenable.value; + return fulfilledValue; + } + + case "rejected": { + var rejectedError = thenable.reason; + throw rejectedError; + } + + default: { + if (typeof thenable.status === "string") { + // Only instrument the thenable if the status if not defined. If + // it's defined, but an unknown value, assume it's been instrumented by + // some custom userspace implementation. We treat it as "pending". + // Attach a dummy listener, to ensure that any lazy initialization can + // happen. Flight lazily parses JSON when the value is actually awaited. + thenable.then(noop, noop); + } else { + var pendingThenable = thenable; + pendingThenable.status = "pending"; + pendingThenable.then( + function (fulfilledValue) { + if (thenable.status === "pending") { + var fulfilledThenable = thenable; + fulfilledThenable.status = "fulfilled"; + fulfilledThenable.value = fulfilledValue; + } + }, + function (error) { + if (thenable.status === "pending") { + var rejectedThenable = thenable; + rejectedThenable.status = "rejected"; + rejectedThenable.reason = error; + } + } + ); + } // Check one more time in case the thenable resolved synchronously. + + switch (thenable.status) { + case "fulfilled": { + var fulfilledThenable = thenable; + return fulfilledThenable.value; + } + + case "rejected": { + var rejectedThenable = thenable; + throw rejectedThenable.reason; + } + } // Suspend. + // + // Throwing here is an implementation detail that allows us to unwind the + // call stack. But we shouldn't allow it to leak into userspace. Throw an + // opaque placeholder value instead of the actual thenable. If it doesn't + // get captured by the work loop, log a warning, because that means + // something in userspace must have caught it. + + suspendedThenable = thenable; + + { + needsToResetSuspendedThenableDEV = true; + } + + throw SuspenseException; + } + } +} +// passed to the rest of the Suspense implementation — which, for historical +// reasons, expects to receive a thenable. + +var suspendedThenable = null; +var needsToResetSuspendedThenableDEV = false; +function getSuspendedThenable() { + // This is called right after `use` suspends by throwing an exception. `use` + // throws an opaque value instead of the thenable itself so that it can't be + // caught in userspace. Then the work loop accesses the actual thenable using + // this function. + if (suspendedThenable === null) { + throw new Error( + "Expected a suspended thenable. This is a bug in React. Please file " + + "an issue." + ); + } + + var thenable = suspendedThenable; + suspendedThenable = null; + + { + needsToResetSuspendedThenableDEV = false; + } + + return thenable; +} +function checkIfUseWrappedInTryCatch() { + { + // This was set right before SuspenseException was thrown, and it should + // have been cleared when the exception was handled. If it wasn't, + // it must have been caught by userspace. + if (needsToResetSuspendedThenableDEV) { + needsToResetSuspendedThenableDEV = false; + return true; + } + } + + return false; +} + +var thenableState$1 = null; +var thenableIndexCounter$1 = 0; var didWarnAboutMaps; var didWarnAboutGenerators; var didWarnAboutStringRefs; @@ -4187,6 +4388,17 @@ function isReactClass(type) { return type.prototype && type.prototype.isReactComponent; } +function unwrapThenable(thenable) { + var index = thenableIndexCounter$1; + thenableIndexCounter$1 += 1; + + if (thenableState$1 === null) { + thenableState$1 = createThenableState(); + } + + return trackUsedThenable(thenableState$1, thenable, index); +} + function coerceRef(returnFiber, current, element) { var mixedRef = element.ref; @@ -4606,6 +4818,25 @@ function createChildReconciler(shouldTrackSideEffects) { _created3.return = returnFiber; return _created3; + } // Usable node types + // + // Unwrap the inner value and recursively call this function again. + + if (typeof newChild.then === "function") { + var thenable = newChild; + return createChild(returnFiber, unwrapThenable(thenable), lanes); + } + + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) { + var context = newChild; + return createChild( + returnFiber, + readContextDuringReconcilation(returnFiber, context, lanes), + lanes + ); } throwOnInvalidObjectType(returnFiber, newChild); @@ -4669,6 +4900,31 @@ function createChildReconciler(shouldTrackSideEffects) { } return updateFragment(returnFiber, oldFiber, newChild, lanes, null); + } // Usable node types + // + // Unwrap the inner value and recursively call this function again. + + if (typeof newChild.then === "function") { + var thenable = newChild; + return updateSlot( + returnFiber, + oldFiber, + unwrapThenable(thenable), + lanes + ); + } + + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) { + var context = newChild; + return updateSlot( + returnFiber, + oldFiber, + readContextDuringReconcilation(returnFiber, context, lanes), + lanes + ); } throwOnInvalidObjectType(returnFiber, newChild); @@ -4742,6 +4998,33 @@ function createChildReconciler(shouldTrackSideEffects) { lanes, null ); + } // Usable node types + // + // Unwrap the inner value and recursively call this function again. + + if (typeof newChild.then === "function") { + var thenable = newChild; + return updateFromMap( + existingChildren, + returnFiber, + newIdx, + unwrapThenable(thenable), + lanes + ); + } + + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) { + var context = newChild; + return updateFromMap( + existingChildren, + returnFiber, + newIdx, + readContextDuringReconcilation(returnFiber, context, lanes), + lanes + ); } throwOnInvalidObjectType(returnFiber, newChild); @@ -5331,7 +5614,7 @@ function createChildReconciler(shouldTrackSideEffects) { // itself. They will be added to the side-effect list as we pass through the // children and the parent. - function reconcileChildFibers( + function reconcileChildFibersImpl( returnFiber, currentFirstChild, newChild, @@ -5344,6 +5627,7 @@ function createChildReconciler(shouldTrackSideEffects) { // Handle top level unkeyed fragments as if they were arrays. // This leads to an ambiguity between <>{[...]} and <>.... // We treat the ambiguous cases above the same. + // TODO: Let's use recursion like we do for Usable nodes? var isUnkeyedTopLevelFragment = typeof newChild === "object" && newChild !== null && @@ -5404,6 +5688,44 @@ function createChildReconciler(shouldTrackSideEffects) { newChild, lanes ); + } // Usables are a valid React node type. When React encounters a Usable in + // a child position, it unwraps it using the same algorithm as `use`. For + // example, for promises, React will throw an exception to unwind the + // stack, then replay the component once the promise resolves. + // + // A difference from `use` is that React will keep unwrapping the value + // until it reaches a non-Usable type. + // + // e.g. Usable>> should resolve to T + // + // The structure is a bit unfortunate. Ideally, we shouldn't need to + // replay the entire begin phase of the parent fiber in order to reconcile + // the children again. This would require a somewhat significant refactor, + // because reconcilation happens deep within the begin phase, and + // depending on the type of work, not always at the end. We should + // consider as an future improvement. + + if (typeof newChild.then === "function") { + var thenable = newChild; + return reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + unwrapThenable(thenable), + lanes + ); + } + + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) { + var context = newChild; + return reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + readContextDuringReconcilation(returnFiber, context, lanes), + lanes + ); } throwOnInvalidObjectType(returnFiber, newChild); @@ -5432,11 +5754,37 @@ function createChildReconciler(shouldTrackSideEffects) { return deleteRemainingChildren(returnFiber, currentFirstChild); } + function reconcileChildFibers( + returnFiber, + currentFirstChild, + newChild, + lanes + ) { + // This indirection only exists so we can reset `thenableState` at the end. + // It should get inlined by Closure. + thenableIndexCounter$1 = 0; + var firstChildFiber = reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + newChild, + lanes + ); + thenableState$1 = null; // Don't bother to reset `thenableIndexCounter` to 0 because it always gets + // set at the beginning. + + return firstChildFiber; + } + return reconcileChildFibers; } var reconcileChildFibers = createChildReconciler(true); var mountChildFibers = createChildReconciler(false); +function resetChildReconcilerOnUnwind() { + // On unwind, clear any pending thenables that were used. + thenableState$1 = null; + thenableIndexCounter$1 = 0; +} function cloneChildFibers(current, workInProgress) { if (current !== null && workInProgress.child !== current.child) { throw new Error("Resuming work not yet implemented."); @@ -5631,241 +5979,84 @@ function findFirstSuspended(row) { if (node.tag === SuspenseComponent) { var state = node.memoizedState; - if (state !== null) { - var dehydrated = state.dehydrated; - - if ( - dehydrated === null || - isSuspenseInstancePending() || - isSuspenseInstanceFallback() - ) { - return node; - } - } - } else if ( - node.tag === SuspenseListComponent && // revealOrder undefined can't be trusted because it don't - // keep track of whether it suspended or not. - node.memoizedProps.revealOrder !== undefined - ) { - var didSuspend = (node.flags & DidCapture) !== NoFlags$1; - - if (didSuspend) { - return node; - } - } else if (node.child !== null) { - node.child.return = node; - node = node.child; - continue; - } - - if (node === row) { - return null; - } - - while (node.sibling === null) { - if (node.return === null || node.return === row) { - return null; - } - - node = node.return; - } - - node.sibling.return = node.return; - node = node.sibling; - } - - return null; -} - -var NoFlags = - /* */ - 0; // Represents whether effect should fire. - -var HasEffect = - /* */ - 1; // Represents the phase in which the effect (not the clean-up) fires. - -var Insertion = - /* */ - 2; -var Layout = - /* */ - 4; -var Passive = - /* */ - 8; - -// 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]; - - { - mutableSource._workInProgressVersionSecondary = null; - } - } - - workInProgressSources.length = 0; -} - -var ReactCurrentActQueue$2 = ReactSharedInternals.ReactCurrentActQueue; // An error that is thrown (e.g. by `use`) to trigger Suspense. If we -// detect this is caught by userspace, we'll log a warning in development. - -var SuspenseException = new Error( - "Suspense Exception: This is not a real error! It's an implementation " + - "detail of `use` to interrupt the current render. You must either " + - "rethrow it immediately, or move the `use` call outside of the " + - "`try/catch` block. Capturing without rethrowing will lead to " + - "unexpected behavior.\n\n" + - "To handle async errors, wrap your component in an error boundary, or " + - "call the promise's `.catch` method and pass the result to `use`" -); -function createThenableState() { - // The ThenableState is created the first time a component suspends. If it - // suspends again, we'll reuse the same state. - return []; -} -function isThenableResolved(thenable) { - var status = thenable.status; - return status === "fulfilled" || status === "rejected"; -} - -function noop() {} - -function trackUsedThenable(thenableState, thenable, index) { - if (ReactCurrentActQueue$2.current !== null) { - ReactCurrentActQueue$2.didUsePromise = true; - } - - var previous = thenableState[index]; - - if (previous === undefined) { - thenableState.push(thenable); - } else { - if (previous !== thenable) { - // Reuse the previous thenable, and drop the new one. We can assume - // they represent the same value, because components are idempotent. - // Avoid an unhandled rejection errors for the Promises that we'll - // intentionally ignore. - thenable.then(noop, noop); - thenable = previous; - } - } // We use an expando to track the status and result of a thenable so that we - // can synchronously unwrap the value. Think of this as an extension of the - // Promise API, or a custom interface that is a superset of Thenable. - // - // If the thenable doesn't have a status, set it to "pending" and attach - // a listener that will update its status and result when it resolves. - - switch (thenable.status) { - case "fulfilled": { - var fulfilledValue = thenable.value; - return fulfilledValue; - } - - case "rejected": { - var rejectedError = thenable.reason; - throw rejectedError; - } - - default: { - if (typeof thenable.status === "string") { - // Only instrument the thenable if the status if not defined. If - // it's defined, but an unknown value, assume it's been instrumented by - // some custom userspace implementation. We treat it as "pending". - // Attach a dummy listener, to ensure that any lazy initialization can - // happen. Flight lazily parses JSON when the value is actually awaited. - thenable.then(noop, noop); - } else { - var pendingThenable = thenable; - pendingThenable.status = "pending"; - pendingThenable.then( - function (fulfilledValue) { - if (thenable.status === "pending") { - var fulfilledThenable = thenable; - fulfilledThenable.status = "fulfilled"; - fulfilledThenable.value = fulfilledValue; - } - }, - function (error) { - if (thenable.status === "pending") { - var rejectedThenable = thenable; - rejectedThenable.status = "rejected"; - rejectedThenable.reason = error; - } - } - ); - } // Check one more time in case the thenable resolved synchronously. + if (state !== null) { + var dehydrated = state.dehydrated; - switch (thenable.status) { - case "fulfilled": { - var fulfilledThenable = thenable; - return fulfilledThenable.value; + if ( + dehydrated === null || + isSuspenseInstancePending() || + isSuspenseInstanceFallback() + ) { + return node; } + } + } else if ( + node.tag === SuspenseListComponent && // revealOrder undefined can't be trusted because it don't + // keep track of whether it suspended or not. + node.memoizedProps.revealOrder !== undefined + ) { + var didSuspend = (node.flags & DidCapture) !== NoFlags$1; - case "rejected": { - var rejectedThenable = thenable; - throw rejectedThenable.reason; - } - } // Suspend. - // - // Throwing here is an implementation detail that allows us to unwind the - // call stack. But we shouldn't allow it to leak into userspace. Throw an - // opaque placeholder value instead of the actual thenable. If it doesn't - // get captured by the work loop, log a warning, because that means - // something in userspace must have caught it. + if (didSuspend) { + return node; + } + } else if (node.child !== null) { + node.child.return = node; + node = node.child; + continue; + } - suspendedThenable = thenable; + if (node === row) { + return null; + } - { - needsToResetSuspendedThenableDEV = true; + while (node.sibling === null) { + if (node.return === null || node.return === row) { + return null; } - throw SuspenseException; + node = node.return; } - } -} // This is used to track the actual thenable that suspended so it can be -// passed to the rest of the Suspense implementation — which, for historical -// reasons, expects to receive a thenable. -var suspendedThenable = null; -var needsToResetSuspendedThenableDEV = false; -function getSuspendedThenable() { - // This is called right after `use` suspends by throwing an exception. `use` - // throws an opaque value instead of the thenable itself so that it can't be - // caught in userspace. Then the work loop accesses the actual thenable using - // this function. - if (suspendedThenable === null) { - throw new Error( - "Expected a suspended thenable. This is a bug in React. Please file " + - "an issue." - ); + node.sibling.return = node.return; + node = node.sibling; } - var thenable = suspendedThenable; - suspendedThenable = null; + return null; +} - { - needsToResetSuspendedThenableDEV = false; - } +var NoFlags = + /* */ + 0; // Represents whether effect should fire. - return thenable; -} -function checkIfUseWrappedInTryCatch() { - { - // This was set right before SuspenseException was thrown, and it should - // have been cleared when the exception was handled. If it wasn't, - // it must have been caught by userspace. - if (needsToResetSuspendedThenableDEV) { - needsToResetSuspendedThenableDEV = false; - return true; +var HasEffect = + /* */ + 1; // Represents the phase in which the effect (not the clean-up) fires. + +var Insertion = + /* */ + 2; +var Layout = + /* */ + 4; +var Passive = + /* */ + 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]; + + { + mutableSource._workInProgressVersionSecondary = null; } } - return false; + workInProgressSources.length = 0; } var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, @@ -7368,10 +7559,10 @@ function startTransition(setPending, callback, options) { setCurrentUpdatePriority( higherEventPriority(previousPriority, ContinuousEventPriority) ); - setPending(true); var prevTransition = ReactCurrentBatchConfig$2.transition; - ReactCurrentBatchConfig$2.transition = {}; - var currentTransition = ReactCurrentBatchConfig$2.transition; + ReactCurrentBatchConfig$2.transition = null; + setPending(true); + var currentTransition = (ReactCurrentBatchConfig$2.transition = {}); { ReactCurrentBatchConfig$2.transition._updatedFibers = new Set(); @@ -8851,11 +9042,10 @@ var didWarnAboutUninitializedState; var didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate; var didWarnAboutLegacyLifecyclesAndDerivedState; var didWarnAboutUndefinedDerivedState; -var warnOnUndefinedDerivedState; -var warnOnInvalidCallback; var didWarnAboutDirectlyAssigningPropsToState; var didWarnAboutContextTypeAndContextTypes; var didWarnAboutInvalidateContextType; +var didWarnOnInvalidCallback; { didWarnAboutStateAssignmentForComponent = new Set(); @@ -8866,9 +9056,30 @@ var didWarnAboutInvalidateContextType; didWarnAboutUndefinedDerivedState = new Set(); didWarnAboutContextTypeAndContextTypes = new Set(); didWarnAboutInvalidateContextType = new Set(); - var didWarnOnInvalidCallback = new Set(); + didWarnOnInvalidCallback = new Set(); // This is so gross but it's at least non-critical and can be removed if + // it causes problems. This is meant to give a nicer error message for + // ReactDOM15.unstable_renderSubtreeIntoContainer(reactDOM16Component, + // ...)) which otherwise throws a "_processChildContext is not a function" + // exception. + + Object.defineProperty(fakeInternalInstance, "_processChildContext", { + enumerable: false, + value: function () { + throw new Error( + "_processChildContext is not available in React 16+. This likely " + + "means you have multiple copies of React and are attempting to nest " + + "a React 15 tree inside a React 16 tree using " + + "unstable_renderSubtreeIntoContainer, which isn't supported. Try " + + "to make sure you have only one copy of React (and ideally, switch " + + "to ReactDOM.createPortal)." + ); + } + }); + Object.freeze(fakeInternalInstance); +} - warnOnInvalidCallback = function (callback, callerName) { +function warnOnInvalidCallback(callback, callerName) { + { if (callback === null || typeof callback === "function") { return; } @@ -8885,9 +9096,11 @@ var didWarnAboutInvalidateContextType; callback ); } - }; + } +} - warnOnUndefinedDerivedState = function (type, partialState) { +function warnOnUndefinedDerivedState(type, partialState) { + { if (partialState === undefined) { var componentName = getComponentNameFromType(type) || "Component"; @@ -8901,26 +9114,7 @@ var didWarnAboutInvalidateContextType; ); } } - }; // 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( @@ -10330,13 +10524,26 @@ function throwException( // // When the wakeable resolves, we'll attempt to render the boundary // again ("retry"). - - var wakeables = suspenseBoundary.updateQueue; - - if (wakeables === null) { - suspenseBoundary.updateQueue = new Set([wakeable]); + // Check if this is a Suspensey resource. We do not attach retry + // listeners to these, because we don't actually need them for + // rendering. Only for committing. Instead, if a fallback commits + // and the only thing that suspended was a Suspensey resource, we + // retry immediately. + // TODO: Refactor throwException so that we don't have to do this type + // check. The caller already knows what the cause was. + + var isSuspenseyResource = wakeable === noopSuspenseyCommitThenable; + + if (isSuspenseyResource) { + suspenseBoundary.flags |= ScheduleRetry; } else { - wakeables.add(wakeable); + var retryQueue = suspenseBoundary.updateQueue; + + if (retryQueue === null) { + suspenseBoundary.updateQueue = new Set([wakeable]); + } else { + retryQueue.add(wakeable); + } } break; @@ -10345,22 +10552,29 @@ function throwException( case OffscreenComponent: { if (suspenseBoundary.mode & ConcurrentMode) { suspenseBoundary.flags |= ShouldCapture; - var offscreenQueue = suspenseBoundary.updateQueue; - - if (offscreenQueue === null) { - var newOffscreenQueue = { - transitions: null, - markerInstances: null, - wakeables: new Set([wakeable]) - }; - suspenseBoundary.updateQueue = newOffscreenQueue; - } else { - var _wakeables = offscreenQueue.wakeables; - if (_wakeables === null) { - offscreenQueue.wakeables = new Set([wakeable]); + var _isSuspenseyResource = wakeable === noopSuspenseyCommitThenable; + + if (_isSuspenseyResource) { + suspenseBoundary.flags |= ScheduleRetry; + } else { + var offscreenQueue = suspenseBoundary.updateQueue; + + if (offscreenQueue === null) { + var newOffscreenQueue = { + transitions: null, + markerInstances: null, + retryQueue: new Set([wakeable]) + }; + suspenseBoundary.updateQueue = newOffscreenQueue; } else { - _wakeables.add(wakeable); + var _retryQueue = offscreenQueue.retryQueue; + + if (_retryQueue === null) { + offscreenQueue.retryQueue = new Set([wakeable]); + } else { + _retryQueue.add(wakeable); + } } } @@ -14022,6 +14236,17 @@ function readContext(context) { } } + return readContextForConsumer(currentlyRenderingFiber, context); +} +function readContextDuringReconcilation(consumer, context, renderLanes) { + if (currentlyRenderingFiber === null) { + prepareToReadContext(consumer, renderLanes); + } + + return readContextForConsumer(consumer, context); +} + +function readContextForConsumer(consumer, context) { var value = context._currentValue2; if (lastFullyObservedContext === context); @@ -14033,7 +14258,7 @@ function readContext(context) { }; if (lastContextDependency === null) { - if (currentlyRenderingFiber === null) { + if (consumer === null) { throw new Error( "Context can only be read while React is rendering. " + "In classes, you can read it in the render method or getDerivedStateFromProps. " + @@ -14043,7 +14268,7 @@ function readContext(context) { } // This is the first dependency for this component. Create a new list. lastContextDependency = contextItem; - currentlyRenderingFiber.dependencies = { + consumer.dependencies = { lanes: NoLanes, firstContext: contextItem }; @@ -14303,7 +14528,13 @@ function appendAllChildren( } } // An unfortunate fork of appendAllChildren because we have two different parent types. -function updateHostComponent(current, workInProgress, type, newProps) { +function updateHostComponent( + current, + workInProgress, + type, + newProps, + renderLanes +) { { // If we have an alternate, that means this is an update and we need to // schedule a side-effect to do the updates. @@ -14314,6 +14545,7 @@ function updateHostComponent(current, workInProgress, type, newProps) { // we won't touch this node even if children changed. return; } // If we get updated because one of our children updated, we don't + suspendHostCommitIfNeeded(workInProgress); 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`. @@ -14327,6 +14559,50 @@ function updateHostComponent(current, workInProgress, type, newProps) { markUpdate(workInProgress); } } +} // TODO: This should ideally move to begin phase, but currently the instance is +// not created until the complete phase. For our existing use cases, host nodes +// that suspend don't have children, so it doesn't matter. But that might not +// always be true in the future. + +function suspendHostCommitIfNeeded(workInProgress, type, props, renderLanes) { + // Ask the renderer if this instance should suspend the commit. + { + // If this flag was set previously, we can remove it. The flag represents + // whether this particular set of props might ever need to suspend. The + // safest thing to do is for shouldSuspendCommit to always return true, but + // if the renderer is reasonably confident that the underlying resource + // won't be evicted, it can return false as a performance optimization. + workInProgress.flags &= ~SuspenseyCommit; + return; + } // Mark this fiber with a flag. We use this right before the commit phase to +} + +function scheduleRetryEffect(workInProgress, retryQueue) { + var wakeables = retryQueue; + + if (wakeables !== null) { + // Schedule an effect to attach a retry listener to the promise. + // TODO: Move to passive phase + workInProgress.flags |= Update; + } else { + // This boundary suspended, but no wakeables were added to the retry + // queue. Check if the renderer suspended commit. If so, this means + // that once the fallback is committed, we can immediately retry + // rendering again, because rendering wasn't actually blocked. Only + // the commit phase. + // TODO: Consider a model where we always schedule an immediate retry, even + // for normal Suspense. That way the retry can partially render up to the + // first thing that suspends. + if (workInProgress.flags & ScheduleRetry) { + var retryLane = // TODO: This check should probably be moved into claimNextRetryLane + // I also suspect that we need some further consolidation of offscreen + // and retry lanes. + workInProgress.tag !== OffscreenComponent + ? claimNextRetryLane() + : OffscreenLane; + workInProgress.lanes = mergeLanes(workInProgress.lanes, retryLane); + } + } } function updateHostText(current, workInProgress, oldText, newText) { @@ -14743,17 +15019,20 @@ function completeWork(current, workInProgress, renderLanes) { } else { var _rootContainerInstance = getRootHostContainer(); - var instance = createInstance( + var _instance3 = createInstance( _type, newProps, _rootContainerInstance, _currentHostContext2, workInProgress ); - appendAllChildren(instance, workInProgress); - workInProgress.stateNode = instance; // Certain renderers require commit-time effects for initial mount. + + appendAllChildren(_instance3, workInProgress); + workInProgress.stateNode = _instance3; // Certain renderers require commit-time effects for initial mount. } + suspendHostCommitIfNeeded(workInProgress); + if (workInProgress.ref !== null) { // If there is a ref on a host node we need to schedule a callback markRef(workInProgress); @@ -14895,13 +15174,8 @@ function completeWork(current, workInProgress, renderLanes) { } } - var wakeables = workInProgress.updateQueue; - - if (wakeables !== null) { - // Schedule an effect to attach a retry listener to the promise. - // TODO: Move to passive phase - workInProgress.flags |= Update; - } + var retryQueue = workInProgress.updateQueue; + scheduleRetryEffect(workInProgress, retryQueue); bubbleProperties(workInProgress); @@ -15001,12 +15275,9 @@ function completeWork(current, workInProgress, renderLanes) { // 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 + var _retryQueue = suspended.updateQueue; + workInProgress.updateQueue = _retryQueue; + scheduleRetryEffect(workInProgress, _retryQueue); // Rerender the whole list, but this time, we'll force fallbacks // to stay in place. // Reset the effect flags before doing the second pass since that's now invalid. // Reset the child fibers to their original state. @@ -15060,13 +15331,9 @@ function completeWork(current, workInProgress, renderLanes) { 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; - } - + var _retryQueue2 = _suspended.updateQueue; + workInProgress.updateQueue = _retryQueue2; + scheduleRetryEffect(workInProgress, _retryQueue2); cutOffTailIfNeeded(renderState, true); // This might have been modified. if ( @@ -15206,10 +15473,11 @@ function completeWork(current, workInProgress, renderLanes) { } } - if (workInProgress.updateQueue !== null) { - // Schedule an effect to attach Suspense retry listeners - // TODO: Move to passive phase - workInProgress.flags |= Update; + var offscreenQueue = workInProgress.updateQueue; + + if (offscreenQueue !== null) { + var _retryQueue3 = offscreenQueue.retryQueue; + scheduleRetryEffect(workInProgress, _retryQueue3); } { @@ -15754,7 +16022,7 @@ function reportUncaughtErrorInDEV(error) { } } -var callComponentWillUnmountWithTimer = function (current, instance) { +function callComponentWillUnmountWithTimer(current, instance) { instance.props = current.memoizedProps; instance.state = current.memoizedState; @@ -15768,7 +16036,7 @@ var callComponentWillUnmountWithTimer = function (current, instance) { } else { instance.componentWillUnmount(); } -}; // Capture errors so they don't interrupt unmounting. +} // Capture errors so they don't interrupt unmounting. function safelyCallComponentWillUnmount( current, @@ -17674,11 +17942,11 @@ function commitMutationEffectsOnFiber(finishedWork, root, lanes) { captureCommitPhaseError(finishedWork, finishedWork.return, error); } - var wakeables = finishedWork.updateQueue; + var retryQueue = finishedWork.updateQueue; - if (wakeables !== null) { + if (retryQueue !== null) { finishedWork.updateQueue = null; - attachSuspenseRetryListeners(finishedWork, wakeables); + attachSuspenseRetryListeners(finishedWork, retryQueue); } } @@ -17759,11 +18027,11 @@ function commitMutationEffectsOnFiber(finishedWork, root, lanes) { var offscreenQueue = finishedWork.updateQueue; if (offscreenQueue !== null) { - var _wakeables = offscreenQueue.wakeables; + var _retryQueue = offscreenQueue.retryQueue; - if (_wakeables !== null) { - offscreenQueue.wakeables = null; - attachSuspenseRetryListeners(finishedWork, _wakeables); + if (_retryQueue !== null) { + offscreenQueue.retryQueue = null; + attachSuspenseRetryListeners(finishedWork, _retryQueue); } } } @@ -17776,11 +18044,11 @@ function commitMutationEffectsOnFiber(finishedWork, root, lanes) { commitReconciliationEffects(finishedWork); if (flags & Update) { - var _wakeables2 = finishedWork.updateQueue; + var _retryQueue2 = finishedWork.updateQueue; - if (_wakeables2 !== null) { + if (_retryQueue2 !== null) { finishedWork.updateQueue = null; - attachSuspenseRetryListeners(finishedWork, _wakeables2); + attachSuspenseRetryListeners(finishedWork, _retryQueue2); } } @@ -19464,6 +19732,19 @@ function ensureRootIsScheduled(root, currentTime) { root.callbackPriority = NoLane; root.callbackNode = null; return; + } + + var cancelPendingCommit = root.cancelPendingCommit; + + if (cancelPendingCommit !== null) { + // We should only interrupt a pending commit if the new update + // is urgent. + if (includesOnlyNonUrgentLanes(nextLanes)) { + // The new update is not urgent. Don't interrupt the pending commit. + root.callbackPriority = NoLane; + root.callbackNode = null; + 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. @@ -19695,7 +19976,7 @@ function performConcurrentWorkOnRoot(root, didTimeout) { root.finishedWork = finishedWork; root.finishedLanes = lanes; - finishConcurrentRender(root, exitStatus, lanes); + finishConcurrentRender(root, exitStatus, finishedWork, lanes); } } @@ -19796,7 +20077,7 @@ function queueRecoverableErrors(errors) { } } -function finishConcurrentRender(root, exitStatus, lanes) { +function finishConcurrentRender(root, exitStatus, finishedWork, lanes) { switch (exitStatus) { case RootInProgress: case RootFatalErrored: { @@ -19809,10 +20090,12 @@ function finishConcurrentRender(root, exitStatus, lanes) { case RootErrored: { // We should have already attempted to retry this tree. If we reached // this point, it errored again. Commit it. - commitRoot( + commitRootWhenReady( root, + finishedWork, workInProgressRootRecoverableErrors, - workInProgressTransitions + workInProgressTransitions, + lanes ); break; } @@ -19841,11 +20124,13 @@ function finishConcurrentRender(root, exitStatus, lanes) { // immediately, wait for more data to arrive. root.timeoutHandle = scheduleTimeout( - commitRoot.bind( + commitRootWhenReady.bind( null, root, + finishedWork, workInProgressRootRecoverableErrors, - workInProgressTransitions + workInProgressTransitions, + lanes ), msUntilTimeout ); @@ -19853,10 +20138,12 @@ function finishConcurrentRender(root, exitStatus, lanes) { } } // The work expired. Commit immediately. - commitRoot( + commitRootWhenReady( root, + finishedWork, workInProgressRootRecoverableErrors, - workInProgressTransitions + workInProgressTransitions, + lanes ); break; } @@ -19888,11 +20175,13 @@ function finishConcurrentRender(root, exitStatus, lanes) { // Instead of committing the fallback immediately, wait for more data // to arrive. root.timeoutHandle = scheduleTimeout( - commitRoot.bind( + commitRootWhenReady.bind( null, root, + finishedWork, workInProgressRootRecoverableErrors, - workInProgressTransitions + workInProgressTransitions, + lanes ), _msUntilTimeout ); @@ -19900,20 +20189,24 @@ function finishConcurrentRender(root, exitStatus, lanes) { } } // Commit the placeholder. - commitRoot( + commitRootWhenReady( root, + finishedWork, workInProgressRootRecoverableErrors, - workInProgressTransitions + workInProgressTransitions, + lanes ); break; } case RootCompleted: { - // The work completed. Ready to commit. - commitRoot( + // The work completed. + commitRootWhenReady( root, + finishedWork, workInProgressRootRecoverableErrors, - workInProgressTransitions + workInProgressTransitions, + lanes ); break; } @@ -19924,6 +20217,45 @@ function finishConcurrentRender(root, exitStatus, lanes) { } } +function commitRootWhenReady( + root, + finishedWork, + recoverableErrors, + transitions, + lanes +) { + if (includesOnlyNonUrgentLanes(lanes)) { + // suspend. If it's not ready, it will return a callback to subscribe to + // a ready event. + + var schedulePendingCommit = waitForCommitToBeReady(); + + if (schedulePendingCommit !== null) { + // NOTE: waitForCommitToBeReady returns a subscribe function so that we + // only allocate a function if the commit isn't ready yet. The other + // pattern would be to always pass a callback to waitForCommitToBeReady. + // Not yet ready to commit. Delay the commit until the renderer notifies + // us that it's ready. This will be canceled if we start work on the + // root again. + root.cancelPendingCommit = schedulePendingCommit( + commitRoot.bind( + null, + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ) + ); + return; + } + } // Otherwise, commit immediately. + + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); +} + 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 @@ -20184,6 +20516,13 @@ function prepareFreshStack(root, lanes) { cancelTimeout(timeoutHandle); } + var cancelPendingCommit = root.cancelPendingCommit; + + if (cancelPendingCommit !== null) { + root.cancelPendingCommit = null; + cancelPendingCommit(); + } + resetWorkInProgressStack(); workInProgressRoot = root; var rootWorkInProgress = createWorkInProgress(root.current, null); @@ -20212,6 +20551,7 @@ function resetSuspendedWorkLoopOnUnwind() { // Reset module-level state that was set during the render phase. resetContextDependencies(); resetHooksOnUnwind(); + resetChildReconcilerOnUnwind(); } function handleThrow(root, thrownValue) { @@ -20240,9 +20580,18 @@ function handleThrow(root, thrownValue) { // API for suspending. This implementation detail can change later, once we // deprecate the old API in favor of `use`. thrownValue = getSuspendedThenable(); - workInProgressSuspendedReason = shouldAttemptToSuspendUntilDataResolves() - ? SuspendedOnData - : SuspendedOnImmediate; + workInProgressSuspendedReason = + shouldRemainOnPreviousScreen() && // Check if there are other pending updates that might possibly unblock this + // component from suspending. This mirrors the check in + // renderDidSuspendDelayIfPossible. We should attempt to unify them somehow. + // TODO: Consider unwinding immediately, using the + // SuspendedOnHydration mechanism. + !includesNonIdleWork(workInProgressRootSkippedLanes) && + !includesNonIdleWork(workInProgressRootInterleavedUpdatedLanes) // Suspend work loop until data resolves + ? SuspendedOnData // Don't suspend work loop, except to check if the data has + : // immediately resolved (i.e. in a microtask). Otherwise, trigger the + // nearest Suspense fallback. + SuspendedOnImmediate; } else if (thrownValue === SelectiveHydrationException) { // An update flowed into a dehydrated boundary. Before we can apply the // update, we need to finish hydrating. Interrupt the work-in-progress @@ -20285,27 +20634,27 @@ function handleThrow(root, thrownValue) { } } -function shouldAttemptToSuspendUntilDataResolves() { - // Check if there are other pending updates that might possibly unblock this - // component from suspending. This mirrors the check in - // renderDidSuspendDelayIfPossible. We should attempt to unify them somehow. - // TODO: Consider unwinding immediately, using the - // SuspendedOnHydration mechanism. - if ( - includesNonIdleWork(workInProgressRootSkippedLanes) || - includesNonIdleWork(workInProgressRootInterleavedUpdatedLanes) - ) { - // Suspend normally. renderDidSuspendDelayIfPossible will handle - // interrupting the work loop. - return false; - } // TODO: We should be able to remove the equivalent check in - // finishConcurrentRender, and rely just on this one. - +function shouldRemainOnPreviousScreen() { + // This is asking whether it's better to suspend the transition and remain + // on the previous screen, versus showing a fallback as soon as possible. It + // takes into account both the priority of render and also whether showing a + // fallback would produce a desirable user experience. + // TODO: Once `use` has fully replaced the `throw promise` pattern, we should + // be able to remove the equivalent check in finishConcurrentRender, and rely + // just on this one. if (includesOnlyTransitions(workInProgressRootRenderLanes)) { - // If we're rendering inside the "shell" of the app, it's better to suspend - // rendering and wait for the data to resolve. Otherwise, we should switch - // to a fallback and continue rendering. - return getShellBoundary() === null; + if (getShellBoundary() === null) { + // We're rendering inside the "shell" of the app. Activating the nearest + // fallback would cause visible content to disappear. It's better to + // suspend the transition and remain on the previous screen. + return true; + } else { + // We're rendering content that wasn't part of the previous screen. + // Rather than block the transition, it's better to show a fallback as + // soon as possible. The appearance of any nested fallbacks will be + // throttled to avoid jank. + return false; + } } var handler = getSuspenseHandler(); @@ -20751,15 +21100,14 @@ function replaySuspendedUnitOfWork(unitOfWork) { } default: { - { - error( - "Unexpected type of work: %s, Currently only function " + - "components are replayed after suspending. This is a bug in React.", - unitOfWork.tag - ); - } - - resetSuspendedWorkLoopOnUnwind(); + // Other types besides function components are reset completely before + // being replayed. Currently this only happens when a Usable type is + // reconciled — the reconciler will suspend. + // + // We reset the fiber back to its original state; however, this isn't + // a full "unwind" because we're going to reuse the promises that were + // reconciled previously. So it's intentional that we don't call + // resetSuspendedWorkLoopOnUnwind here. unwindInterruptedWork(current, unitOfWork); unitOfWork = workInProgress = resetWorkInProgress( unitOfWork, @@ -21005,7 +21353,8 @@ function commitRootImpl( // So we can clear these now to allow a new callback to be scheduled. root.callbackNode = null; - root.callbackPriority = NoLane; // Check which lanes no longer have any work scheduled on them, and mark + root.callbackPriority = NoLane; + root.cancelPendingCommit = null; // Check which lanes no longer have any work scheduled on them, and mark // those as finished. var remainingLanes = mergeLanes(finishedWork.lanes, finishedWork.childLanes); // Make sure to account for lanes that were updated by a concurrent event @@ -22536,10 +22885,10 @@ function FiberNode(tag, pendingProps, key, mode) { // 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) { +function createFiber(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; @@ -23048,6 +23397,7 @@ function FiberRootNode( this.pingCache = null; this.finishedWork = null; this.timeoutHandle = noTimeout; + this.cancelPendingCommit = null; this.context = null; this.pendingContext = null; this.callbackNode = null; @@ -23149,7 +23499,7 @@ function createFiberRoot( return root; } -var ReactVersion = "18.3.0-next-ef8bdbecb-20230310"; +var ReactVersion = "18.3.0-next-c57b90f50-20230320"; // Might add PROFILE later. diff --git a/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react-test-renderer/cjs/ReactTestRenderer-prod.js b/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react-test-renderer/cjs/ReactTestRenderer-prod.js index eb7d50bb224bc..d0cc69e86d8fc 100644 --- a/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react-test-renderer/cjs/ReactTestRenderer-prod.js +++ b/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react-test-renderer/cjs/ReactTestRenderer-prod.js @@ -456,6 +456,12 @@ function claimNextTransitionLane() { 0 === (nextTransitionLane & 8388480) && (nextTransitionLane = 128); return lane; } +function claimNextRetryLane() { + var lane = nextRetryLane; + nextRetryLane <<= 1; + 0 === (nextRetryLane & 125829120) && (nextRetryLane = 8388608); + return lane; +} function createLaneMap(initial) { for (var laneMap = [], i = 0; 31 > i; i++) laneMap.push(initial); return laneMap; @@ -672,30 +678,43 @@ var objectIs = "function" === typeof Object.is ? Object.is : is, function flushSyncCallbacks() { if (!isFlushingSyncQueue && null !== syncQueue) { isFlushingSyncQueue = !0; - var i = 0, - previousUpdatePriority = currentUpdatePriority; - try { - var queue = syncQueue; - for (currentUpdatePriority = 2; i < queue.length; i++) { - var callback = queue[i]; + var previousUpdatePriority = currentUpdatePriority; + currentUpdatePriority = 2; + for (var errors = null, queue = syncQueue, i = 0; i < queue.length; i++) { + var callback = queue[i]; + try { do callback = callback(!0); while (null !== callback); + } catch (error) { + null === errors ? (errors = [error]) : errors.push(error); } - syncQueue = null; - includesLegacySyncCallbacks = !1; - } catch (error) { - throw ( - (null !== syncQueue && (syncQueue = syncQueue.slice(i + 1)), - scheduleCallback$2(ImmediatePriority, flushSyncCallbacks), - error) - ); - } finally { - (currentUpdatePriority = previousUpdatePriority), - (isFlushingSyncQueue = !1); + } + syncQueue = null; + includesLegacySyncCallbacks = !1; + currentUpdatePriority = previousUpdatePriority; + isFlushingSyncQueue = !1; + if (null !== errors) { + if (1 < errors.length) { + if ("function" === typeof AggregateError) + throw new AggregateError(errors); + for ( + previousUpdatePriority = 1; + previousUpdatePriority < errors.length; + previousUpdatePriority++ + ) + scheduleCallback$2( + ImmediatePriority, + throwError.bind(null, errors[previousUpdatePriority]) + ); + } + throw errors[0]; } } return null; } +function throwError(error) { + throw error; +} var contextStackCursor = createCursor(null), contextFiberStackCursor = createCursor(null), rootInstanceStackCursor = createCursor(null); @@ -1083,6 +1102,65 @@ function describeFiber(fiber) { return ""; } } +var SuspenseException = Error( + "Suspense Exception: This is not a real error! It's an implementation detail of `use` to interrupt the current render. You must either rethrow it immediately, or move the `use` call outside of the `try/catch` block. Capturing without rethrowing will lead to unexpected behavior.\n\nTo handle async errors, wrap your component in an error boundary, or call the promise's `.catch` method and pass the result to `use`" + ), + noopSuspenseyCommitThenable = { then: function () {} }; +function isThenableResolved(thenable) { + thenable = thenable.status; + return "fulfilled" === thenable || "rejected" === thenable; +} +function noop() {} +function trackUsedThenable(thenableState, thenable, index) { + index = thenableState[index]; + void 0 === index + ? thenableState.push(thenable) + : index !== thenable && (thenable.then(noop, noop), (thenable = index)); + switch (thenable.status) { + case "fulfilled": + return thenable.value; + case "rejected": + throw thenable.reason; + default: + "string" === typeof thenable.status + ? thenable.then(noop, noop) + : ((thenableState = thenable), + (thenableState.status = "pending"), + thenableState.then( + function (fulfilledValue) { + if ("pending" === thenable.status) { + var fulfilledThenable = thenable; + fulfilledThenable.status = "fulfilled"; + fulfilledThenable.value = fulfilledValue; + } + }, + function (error) { + if ("pending" === thenable.status) { + var rejectedThenable = thenable; + rejectedThenable.status = "rejected"; + rejectedThenable.reason = error; + } + } + )); + switch (thenable.status) { + case "fulfilled": + return thenable.value; + case "rejected": + throw thenable.reason; + } + suspendedThenable = thenable; + throw SuspenseException; + } +} +var suspendedThenable = null, + thenableState$1 = null, + thenableIndexCounter$1 = 0; +function unwrapThenable(thenable) { + var index = thenableIndexCounter$1; + thenableIndexCounter$1 += 1; + null === thenableState$1 && (thenableState$1 = []); + return trackUsedThenable(thenableState$1, thenable, index); +} function coerceRef(returnFiber, current, element) { returnFiber = element.ref; if ( @@ -1187,16 +1265,16 @@ function createChildReconciler(shouldTrackSideEffects) { return ( (newIndex = newIndex.index), newIndex < lastPlacedIndex - ? ((newFiber.flags |= 16777218), lastPlacedIndex) + ? ((newFiber.flags |= 33554434), lastPlacedIndex) : newIndex ); - newFiber.flags |= 16777218; + newFiber.flags |= 33554434; return lastPlacedIndex; } function placeSingleChild(newFiber) { shouldTrackSideEffects && null === newFiber.alternate && - (newFiber.flags |= 16777218); + (newFiber.flags |= 33554434); return newFiber; } function updateTextNode(returnFiber, current, textContent, lanes) { @@ -1333,6 +1411,17 @@ function createChildReconciler(shouldTrackSideEffects) { (newChild.return = returnFiber), newChild ); + if ("function" === typeof newChild.then) + return createChild(returnFiber, unwrapThenable(newChild), lanes); + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) + return createChild( + returnFiber, + readContextDuringReconcilation(returnFiber, newChild, lanes), + lanes + ); throwOnInvalidObjectType(returnFiber, newChild); } return null; @@ -1366,6 +1455,23 @@ function createChildReconciler(shouldTrackSideEffects) { return null !== key ? null : updateFragment(returnFiber, oldFiber, newChild, lanes, null); + if ("function" === typeof newChild.then) + return updateSlot( + returnFiber, + oldFiber, + unwrapThenable(newChild), + lanes + ); + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) + return updateSlot( + returnFiber, + oldFiber, + readContextDuringReconcilation(returnFiber, newChild, lanes), + lanes + ); throwOnInvalidObjectType(returnFiber, newChild); } return null; @@ -1418,6 +1524,25 @@ function createChildReconciler(shouldTrackSideEffects) { (existingChildren = existingChildren.get(newIdx) || null), updateFragment(returnFiber, existingChildren, newChild, lanes, null) ); + if ("function" === typeof newChild.then) + return updateFromMap( + existingChildren, + returnFiber, + newIdx, + unwrapThenable(newChild), + lanes + ); + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) + return updateFromMap( + existingChildren, + returnFiber, + newIdx, + readContextDuringReconcilation(returnFiber, newChild, lanes), + lanes + ); throwOnInvalidObjectType(returnFiber, newChild); } return null; @@ -1589,7 +1714,7 @@ function createChildReconciler(shouldTrackSideEffects) { }); return iteratorFn; } - function reconcileChildFibers( + function reconcileChildFibersImpl( returnFiber, currentFirstChild, newChild, @@ -1734,6 +1859,23 @@ function createChildReconciler(shouldTrackSideEffects) { newChild, lanes ); + if ("function" === typeof newChild.then) + return reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + unwrapThenable(newChild), + lanes + ); + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) + return reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + readContextDuringReconcilation(returnFiber, newChild, lanes), + lanes + ); throwOnInvalidObjectType(returnFiber, newChild); } return ("string" === typeof newChild && "" !== newChild) || @@ -1755,6 +1897,22 @@ function createChildReconciler(shouldTrackSideEffects) { placeSingleChild(returnFiber)) : deleteRemainingChildren(returnFiber, currentFirstChild); } + function reconcileChildFibers( + returnFiber, + currentFirstChild, + newChild, + lanes + ) { + thenableIndexCounter$1 = 0; + returnFiber = reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + newChild, + lanes + ); + thenableState$1 = null; + return returnFiber; + } return reconcileChildFibers; } var reconcileChildFibers = createChildReconciler(!0), @@ -1833,57 +1991,7 @@ function resetWorkInProgressVersions() { workInProgressSources[i]._workInProgressVersionSecondary = null; workInProgressSources.length = 0; } -var SuspenseException = Error( - "Suspense Exception: This is not a real error! It's an implementation detail of `use` to interrupt the current render. You must either rethrow it immediately, or move the `use` call outside of the `try/catch` block. Capturing without rethrowing will lead to unexpected behavior.\n\nTo handle async errors, wrap your component in an error boundary, or call the promise's `.catch` method and pass the result to `use`" -); -function isThenableResolved(thenable) { - thenable = thenable.status; - return "fulfilled" === thenable || "rejected" === thenable; -} -function noop() {} -function trackUsedThenable(thenableState, thenable, index) { - index = thenableState[index]; - void 0 === index - ? thenableState.push(thenable) - : index !== thenable && (thenable.then(noop, noop), (thenable = index)); - switch (thenable.status) { - case "fulfilled": - return thenable.value; - case "rejected": - throw thenable.reason; - default: - "string" === typeof thenable.status - ? thenable.then(noop, noop) - : ((thenableState = thenable), - (thenableState.status = "pending"), - thenableState.then( - function (fulfilledValue) { - if ("pending" === thenable.status) { - var fulfilledThenable = thenable; - fulfilledThenable.status = "fulfilled"; - fulfilledThenable.value = fulfilledValue; - } - }, - function (error) { - if ("pending" === thenable.status) { - var rejectedThenable = thenable; - rejectedThenable.status = "rejected"; - rejectedThenable.reason = error; - } - } - )); - switch (thenable.status) { - case "fulfilled": - return thenable.value; - case "rejected": - throw thenable.reason; - } - suspendedThenable = thenable; - throw SuspenseException; - } -} -var suspendedThenable = null, - ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, +var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, ReactCurrentBatchConfig$2 = ReactSharedInternals.ReactCurrentBatchConfig, renderLanes$1 = 0, currentlyRenderingFiber$1 = null, @@ -2043,10 +2151,10 @@ createFunctionComponentUpdateQueue = function () { function use(usable) { if (null !== usable && "object" === typeof usable) { if ("function" === typeof usable.then) { - var index$23 = thenableIndexCounter; + var index$25 = thenableIndexCounter; thenableIndexCounter += 1; null === thenableState && (thenableState = []); - usable = trackUsedThenable(thenableState, usable, index$23); + usable = trackUsedThenable(thenableState, usable, index$25); null === currentlyRenderingFiber$1.alternate && (null === workInProgressHook ? null === currentlyRenderingFiber$1.memoizedState @@ -2373,8 +2481,9 @@ function startTransition(setPending, callback) { var previousPriority = currentUpdatePriority; currentUpdatePriority = 0 !== previousPriority && 8 > previousPriority ? previousPriority : 8; - setPending(!0); var prevTransition = ReactCurrentBatchConfig$2.transition; + ReactCurrentBatchConfig$2.transition = null; + setPending(!0); ReactCurrentBatchConfig$2.transition = {}; try { setPending(!1), callback(); @@ -3516,7 +3625,7 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { (nextProps.pendingProps = primaryChildProps), (workInProgress.deletions = null)) : ((nextProps = createWorkInProgress(JSCompiler_temp, primaryChildProps)), - (nextProps.subtreeFlags = JSCompiler_temp.subtreeFlags & 14680064)); + (nextProps.subtreeFlags = JSCompiler_temp.subtreeFlags & 31457280)); null !== dehydrated ? (showFallback = createWorkInProgress(dehydrated, showFallback)) : ((showFallback = createFiberFromFragment( @@ -4098,21 +4207,26 @@ function prepareToReadContext(workInProgress, renderLanes) { (workInProgress.firstContext = null)); } function readContext(context) { + return readContextForConsumer(currentlyRenderingFiber, context); +} +function readContextDuringReconcilation(consumer, context, renderLanes) { + null === currentlyRenderingFiber && + prepareToReadContext(consumer, renderLanes); + return readContextForConsumer(consumer, context); +} +function readContextForConsumer(consumer, context) { var value = context._currentValue2; if (lastFullyObservedContext !== context) if ( ((context = { context: context, memoizedValue: value, next: null }), null === lastContextDependency) ) { - if (null === currentlyRenderingFiber) + if (null === consumer) throw 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()." ); lastContextDependency = context; - currentlyRenderingFiber.dependencies = { - lanes: 0, - firstContext: context - }; + consumer.dependencies = { lanes: 0, firstContext: context }; } else lastContextDependency = lastContextDependency.next = context; return value; } @@ -4179,6 +4293,14 @@ function getSuspendedCache() { ? null : { parent: CacheContext._currentValue2, pool: cacheFromPool }; } +function scheduleRetryEffect(workInProgress, retryQueue) { + null !== retryQueue + ? (workInProgress.flags |= 4) + : workInProgress.flags & 16384 && + ((retryQueue = + 22 !== workInProgress.tag ? claimNextRetryLane() : 1073741824), + (workInProgress.lanes |= retryQueue)); +} function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { switch (renderState.tailMode) { case "hidden": @@ -4193,14 +4315,14 @@ function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { break; case "collapsed": lastTailNode = renderState.tail; - for (var lastTailNode$58 = null; null !== lastTailNode; ) - null !== lastTailNode.alternate && (lastTailNode$58 = lastTailNode), + for (var lastTailNode$61 = null; null !== lastTailNode; ) + null !== lastTailNode.alternate && (lastTailNode$61 = lastTailNode), (lastTailNode = lastTailNode.sibling); - null === lastTailNode$58 + null === lastTailNode$61 ? hasRenderedATailFallback || null === renderState.tail ? (renderState.tail = null) : (renderState.tail.sibling = null) - : (lastTailNode$58.sibling = null); + : (lastTailNode$61.sibling = null); } } function bubbleProperties(completedWork) { @@ -4210,19 +4332,19 @@ function bubbleProperties(completedWork) { newChildLanes = 0, subtreeFlags = 0; if (didBailout) - for (var child$59 = completedWork.child; null !== child$59; ) - (newChildLanes |= child$59.lanes | child$59.childLanes), - (subtreeFlags |= child$59.subtreeFlags & 14680064), - (subtreeFlags |= child$59.flags & 14680064), - (child$59.return = completedWork), - (child$59 = child$59.sibling); + for (var child$62 = completedWork.child; null !== child$62; ) + (newChildLanes |= child$62.lanes | child$62.childLanes), + (subtreeFlags |= child$62.subtreeFlags & 31457280), + (subtreeFlags |= child$62.flags & 31457280), + (child$62.return = completedWork), + (child$62 = child$62.sibling); else - for (child$59 = completedWork.child; null !== child$59; ) - (newChildLanes |= child$59.lanes | child$59.childLanes), - (subtreeFlags |= child$59.subtreeFlags), - (subtreeFlags |= child$59.flags), - (child$59.return = completedWork), - (child$59 = child$59.sibling); + for (child$62 = completedWork.child; null !== child$62; ) + (newChildLanes |= child$62.lanes | child$62.childLanes), + (subtreeFlags |= child$62.subtreeFlags), + (subtreeFlags |= child$62.flags), + (child$62.return = completedWork), + (child$62 = child$62.sibling); completedWork.subtreeFlags |= subtreeFlags; completedWork.childLanes = newChildLanes; return didBailout; @@ -4280,7 +4402,8 @@ function completeWork(current, workInProgress, renderLanes) { renderLanes = workInProgress.type; if (null !== current && null != workInProgress.stateNode) current.memoizedProps !== newProps && - (workInProgress.updateQueue = UPDATE_SIGNAL) && + ((workInProgress.flags &= -16777217), + (workInProgress.updateQueue = UPDATE_SIGNAL)) && (workInProgress.flags |= 4), current.ref !== workInProgress.ref && (workInProgress.flags |= 2097664); @@ -4326,6 +4449,7 @@ function completeWork(current, workInProgress, renderLanes) { renderLanes = renderLanes.sibling; } workInProgress.stateNode = current; + workInProgress.flags &= -16777217; null !== workInProgress.ref && (workInProgress.flags |= 2097664); } bubbleProperties(workInProgress); @@ -4385,16 +4509,16 @@ function completeWork(current, workInProgress, renderLanes) { null !== newProps.alternate.memoizedState && null !== newProps.alternate.memoizedState.cachePool && (index = newProps.alternate.memoizedState.cachePool.pool); - var cache$63 = null; + var cache$66 = null; null !== newProps.memoizedState && null !== newProps.memoizedState.cachePool && - (cache$63 = newProps.memoizedState.cachePool.pool); - cache$63 !== index && (newProps.flags |= 2048); + (cache$66 = newProps.memoizedState.cachePool.pool); + cache$66 !== index && (newProps.flags |= 2048); } renderLanes !== current && renderLanes && (workInProgress.child.flags |= 8192); - null !== workInProgress.updateQueue && (workInProgress.flags |= 4); + scheduleRetryEffect(workInProgress, workInProgress.updateQueue); bubbleProperties(workInProgress); return null; case 4: @@ -4416,8 +4540,8 @@ function completeWork(current, workInProgress, renderLanes) { index = workInProgress.memoizedState; if (null === index) return bubbleProperties(workInProgress), null; newProps = 0 !== (workInProgress.flags & 128); - cache$63 = index.rendering; - if (null === cache$63) + cache$66 = index.rendering; + if (null === cache$66) if (newProps) cutOffTailIfNeeded(index, !1); else { if ( @@ -4425,14 +4549,13 @@ function completeWork(current, workInProgress, renderLanes) { (null !== current && 0 !== (current.flags & 128)) ) for (current = workInProgress.child; null !== current; ) { - cache$63 = findFirstSuspended(current); - if (null !== cache$63) { + cache$66 = findFirstSuspended(current); + if (null !== cache$66) { workInProgress.flags |= 128; cutOffTailIfNeeded(index, !1); - current = cache$63.updateQueue; - null !== current && - ((workInProgress.updateQueue = current), - (workInProgress.flags |= 4)); + current = cache$66.updateQueue; + workInProgress.updateQueue = current; + scheduleRetryEffect(workInProgress, current); workInProgress.subtreeFlags = 0; current = renderLanes; for (renderLanes = workInProgress.child; null !== renderLanes; ) @@ -4455,18 +4578,17 @@ function completeWork(current, workInProgress, renderLanes) { } else { if (!newProps) - if (((current = findFirstSuspended(cache$63)), null !== current)) { + if (((current = findFirstSuspended(cache$66)), null !== current)) { if ( ((workInProgress.flags |= 128), (newProps = !0), (current = current.updateQueue), - null !== current && - ((workInProgress.updateQueue = current), - (workInProgress.flags |= 4)), + (workInProgress.updateQueue = current), + scheduleRetryEffect(workInProgress, current), cutOffTailIfNeeded(index, !0), null === index.tail && "hidden" === index.tailMode && - !cache$63.alternate) + !cache$66.alternate) ) return bubbleProperties(workInProgress), null; } else @@ -4478,13 +4600,13 @@ function completeWork(current, workInProgress, renderLanes) { cutOffTailIfNeeded(index, !1), (workInProgress.lanes = 8388608)); index.isBackwards - ? ((cache$63.sibling = workInProgress.child), - (workInProgress.child = cache$63)) + ? ((cache$66.sibling = workInProgress.child), + (workInProgress.child = cache$66)) : ((current = index.last), null !== current - ? (current.sibling = cache$63) - : (workInProgress.child = cache$63), - (index.last = cache$63)); + ? (current.sibling = cache$66) + : (workInProgress.child = cache$66), + (index.last = cache$66)); } if (null !== index.tail) return ( @@ -4515,7 +4637,9 @@ function completeWork(current, workInProgress, renderLanes) { (bubbleProperties(workInProgress), workInProgress.subtreeFlags & 6 && (workInProgress.flags |= 8192)) : bubbleProperties(workInProgress), - null !== workInProgress.updateQueue && (workInProgress.flags |= 4), + (renderLanes = workInProgress.updateQueue), + null !== renderLanes && + scheduleRetryEffect(workInProgress, renderLanes.retryQueue), (renderLanes = null), null !== current && null !== current.memoizedState && @@ -4697,8 +4821,8 @@ function safelyDetachRef(current, nearestMountedAncestor) { else if ("function" === typeof ref) try { ref(null); - } catch (error$77) { - captureCommitPhaseError(current, nearestMountedAncestor, error$77); + } catch (error$82) { + captureCommitPhaseError(current, nearestMountedAncestor, error$82); } else ref.current = null; } @@ -4803,8 +4927,8 @@ function commitHookEffectListMount(flags, finishedWork) { var effect = (finishedWork = finishedWork.next); do { if ((effect.tag & flags) === flags) { - var create$78 = effect.create; - effect.destroy = create$78(); + var create$83 = effect.create; + effect.destroy = create$83(); } effect = effect.next; } while (effect !== finishedWork); @@ -4858,11 +4982,11 @@ function commitLayoutEffectOnFiber(finishedRoot, current, finishedWork) { current, finishedRoot.__reactInternalSnapshotBeforeUpdate ); - } catch (error$79) { + } catch (error$84) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$79 + error$84 ); } } @@ -5233,8 +5357,8 @@ function commitMutationEffectsOnFiber(finishedWork, root) { } try { commitHookEffectListUnmount(5, finishedWork, finishedWork.return); - } catch (error$87) { - captureCommitPhaseError(finishedWork, finishedWork.return, error$87); + } catch (error$92) { + captureCommitPhaseError(finishedWork, finishedWork.return, error$92); } } break; @@ -5274,11 +5398,11 @@ function commitMutationEffectsOnFiber(finishedWork, root) { if (null !== current) try { (flags.type = type), (flags.props = existingHiddenCallbacks); - } catch (error$90) { + } catch (error$95) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$90 + error$95 ); } } @@ -5295,8 +5419,8 @@ function commitMutationEffectsOnFiber(finishedWork, root) { existingHiddenCallbacks = finishedWork.memoizedProps; try { flags.text = existingHiddenCallbacks; - } catch (error$91) { - captureCommitPhaseError(finishedWork, finishedWork.return, error$91); + } catch (error$96) { + captureCommitPhaseError(finishedWork, finishedWork.return, error$96); } } break; @@ -5328,14 +5452,14 @@ function commitMutationEffectsOnFiber(finishedWork, root) { null !== current && safelyDetachRef(current, current.return); existingHiddenCallbacks = null !== finishedWork.memoizedState; - var wasHidden$95 = null !== current && null !== current.memoizedState; + var wasHidden$100 = null !== current && null !== current.memoizedState; if (finishedWork.mode & 1) { var prevOffscreenSubtreeIsHidden = offscreenSubtreeIsHidden, prevOffscreenSubtreeWasHidden = offscreenSubtreeWasHidden; offscreenSubtreeIsHidden = prevOffscreenSubtreeIsHidden || existingHiddenCallbacks; offscreenSubtreeWasHidden = - prevOffscreenSubtreeWasHidden || wasHidden$95; + prevOffscreenSubtreeWasHidden || wasHidden$100; recursivelyTraverseMutationEffects(root, finishedWork); offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden; offscreenSubtreeIsHidden = prevOffscreenSubtreeIsHidden; @@ -5353,22 +5477,22 @@ function commitMutationEffectsOnFiber(finishedWork, root) { existingHiddenCallbacks && ((root = offscreenSubtreeIsHidden || offscreenSubtreeWasHidden), null === current || - wasHidden$95 || + wasHidden$100 || root || (0 !== (finishedWork.mode & 1) && recursivelyTraverseDisappearLayoutEffects(finishedWork))), null === finishedWork.memoizedProps || "manual" !== finishedWork.memoizedProps.mode) ) - a: for (current = null, wasHidden$95 = finishedWork; ; ) { - if (5 === wasHidden$95.tag) { + a: for (current = null, wasHidden$100 = finishedWork; ; ) { + if (5 === wasHidden$100.tag) { if (null === current) { - current = wasHidden$95; + current = wasHidden$100; try { - (type = wasHidden$95.stateNode), + (type = wasHidden$100.stateNode), existingHiddenCallbacks ? (type.isHidden = !0) - : (wasHidden$95.stateNode.isHidden = !1); + : (wasHidden$100.stateNode.isHidden = !1); } catch (error) { captureCommitPhaseError( finishedWork, @@ -5377,49 +5501,49 @@ function commitMutationEffectsOnFiber(finishedWork, root) { ); } } - } else if (6 === wasHidden$95.tag) { + } else if (6 === wasHidden$100.tag) { if (null === current) try { - wasHidden$95.stateNode.isHidden = existingHiddenCallbacks + wasHidden$100.stateNode.isHidden = existingHiddenCallbacks ? !0 : !1; - } catch (error$81) { + } catch (error$86) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$81 + error$86 ); } } else if ( - ((22 !== wasHidden$95.tag && 23 !== wasHidden$95.tag) || - null === wasHidden$95.memoizedState || - wasHidden$95 === finishedWork) && - null !== wasHidden$95.child + ((22 !== wasHidden$100.tag && 23 !== wasHidden$100.tag) || + null === wasHidden$100.memoizedState || + wasHidden$100 === finishedWork) && + null !== wasHidden$100.child ) { - wasHidden$95.child.return = wasHidden$95; - wasHidden$95 = wasHidden$95.child; + wasHidden$100.child.return = wasHidden$100; + wasHidden$100 = wasHidden$100.child; continue; } - if (wasHidden$95 === finishedWork) break a; - for (; null === wasHidden$95.sibling; ) { + if (wasHidden$100 === finishedWork) break a; + for (; null === wasHidden$100.sibling; ) { if ( - null === wasHidden$95.return || - wasHidden$95.return === finishedWork + null === wasHidden$100.return || + wasHidden$100.return === finishedWork ) break a; - current === wasHidden$95 && (current = null); - wasHidden$95 = wasHidden$95.return; + current === wasHidden$100 && (current = null); + wasHidden$100 = wasHidden$100.return; } - current === wasHidden$95 && (current = null); - wasHidden$95.sibling.return = wasHidden$95.return; - wasHidden$95 = wasHidden$95.sibling; + current === wasHidden$100 && (current = null); + wasHidden$100.sibling.return = wasHidden$100.return; + wasHidden$100 = wasHidden$100.sibling; } flags & 4 && ((flags = finishedWork.updateQueue), null !== flags && - ((existingHiddenCallbacks = flags.wakeables), + ((existingHiddenCallbacks = flags.retryQueue), null !== existingHiddenCallbacks && - ((flags.wakeables = null), + ((flags.retryQueue = null), attachSuspenseRetryListeners( finishedWork, existingHiddenCallbacks @@ -5468,12 +5592,12 @@ function commitReconciliationEffects(finishedWork) { break; case 3: case 4: - var parent$82 = JSCompiler_inline_result.stateNode.containerInfo, - before$83 = getHostSibling(finishedWork); + var parent$87 = JSCompiler_inline_result.stateNode.containerInfo, + before$88 = getHostSibling(finishedWork); insertOrAppendPlacementNodeIntoContainer( finishedWork, - before$83, - parent$82 + before$88, + parent$87 ); break; default: @@ -6149,6 +6273,8 @@ function ensureRootIsScheduled(root, currentTime) { (root.callbackPriority = 0); else if (2 === workInProgressSuspendedReason && workInProgressRoot === root) (root.callbackPriority = 0), (root.callbackNode = null); + else if (null !== root.cancelPendingCommit && 0 === (suspendedLanes & 42)) + (root.callbackPriority = 0), (root.callbackNode = null); else if ( ((currentTime = suspendedLanes & -suspendedLanes), root.callbackPriority !== currentTime) @@ -6206,28 +6332,28 @@ function performConcurrentWorkOnRoot(root, didTimeout) { root === workInProgressRoot ? workInProgressRootRenderLanes : 0 ); if (0 === lanes) return null; - didTimeout = + var exitStatus = includesBlockingLane(root, lanes) || 0 !== (lanes & root.expiredLanes) || didTimeout ? renderRootSync(root, lanes) : renderRootConcurrent(root, lanes); - if (0 !== didTimeout) { - if (2 === didTimeout) { - var originallyAttemptedLanes = lanes, - errorRetryLanes = getLanesToRetrySynchronouslyOnError( - root, - originallyAttemptedLanes - ); + if (0 !== exitStatus) { + if (2 === exitStatus) { + didTimeout = lanes; + var errorRetryLanes = getLanesToRetrySynchronouslyOnError( + root, + didTimeout + ); 0 !== errorRetryLanes && ((lanes = errorRetryLanes), - (didTimeout = recoverFromConcurrentError( + (exitStatus = recoverFromConcurrentError( root, - originallyAttemptedLanes, + didTimeout, errorRetryLanes ))); } - if (1 === didTimeout) + if (1 === exitStatus) throw ( ((originalCallbackNode = workInProgressRootFatalError), prepareFreshStack(root, 0), @@ -6235,30 +6361,30 @@ function performConcurrentWorkOnRoot(root, didTimeout) { ensureRootIsScheduled(root, now()), originalCallbackNode) ); - if (6 === didTimeout) markRootSuspended(root, lanes); + if (6 === exitStatus) markRootSuspended(root, lanes); else { errorRetryLanes = !includesBlockingLane(root, lanes); - originallyAttemptedLanes = root.current.alternate; + didTimeout = root.current.alternate; if ( errorRetryLanes && - !isRenderConsistentWithExternalStores(originallyAttemptedLanes) + !isRenderConsistentWithExternalStores(didTimeout) ) { - didTimeout = renderRootSync(root, lanes); - if (2 === didTimeout) { + exitStatus = renderRootSync(root, lanes); + if (2 === exitStatus) { errorRetryLanes = lanes; - var errorRetryLanes$103 = getLanesToRetrySynchronouslyOnError( + var errorRetryLanes$108 = getLanesToRetrySynchronouslyOnError( root, errorRetryLanes ); - 0 !== errorRetryLanes$103 && - ((lanes = errorRetryLanes$103), - (didTimeout = recoverFromConcurrentError( + 0 !== errorRetryLanes$108 && + ((lanes = errorRetryLanes$108), + (exitStatus = recoverFromConcurrentError( root, errorRetryLanes, - errorRetryLanes$103 + errorRetryLanes$108 ))); } - if (1 === didTimeout) + if (1 === exitStatus) throw ( ((originalCallbackNode = workInProgressRootFatalError), prepareFreshStack(root, 0), @@ -6267,94 +6393,84 @@ function performConcurrentWorkOnRoot(root, didTimeout) { originalCallbackNode) ); } - root.finishedWork = originallyAttemptedLanes; + root.finishedWork = didTimeout; root.finishedLanes = lanes; - switch (didTimeout) { + switch (exitStatus) { case 0: case 1: throw Error("Root did not complete. This is a bug in React."); case 2: - commitRoot( - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ); + commitRootWhenReady(root); break; case 3: markRootSuspended(root, lanes); if ( (lanes & 125829120) === lanes && - ((lanes = globalMostRecentFallbackTime + 500 - now()), 10 < lanes) + ((exitStatus = globalMostRecentFallbackTime + 500 - now()), + 10 < exitStatus) ) { if (0 !== getNextLanes(root, 0)) break; root.timeoutHandle = scheduleTimeout( - commitRoot.bind( + commitRootWhenReady.bind( null, root, + didTimeout, workInProgressRootRecoverableErrors, - workInProgressTransitions + workInProgressTransitions, + lanes ), - lanes + exitStatus ); break; } - commitRoot( - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ); + commitRootWhenReady(root); break; case 4: markRootSuspended(root, lanes); if ((lanes & 8388480) === lanes) break; - didTimeout = root.eventTimes; - for (originallyAttemptedLanes = -1; 0 < lanes; ) - (errorRetryLanes$103 = 31 - clz32(lanes)), - (errorRetryLanes = 1 << errorRetryLanes$103), - (errorRetryLanes$103 = didTimeout[errorRetryLanes$103]), - errorRetryLanes$103 > originallyAttemptedLanes && - (originallyAttemptedLanes = errorRetryLanes$103), - (lanes &= ~errorRetryLanes); - lanes = originallyAttemptedLanes; - lanes = now() - lanes; - lanes = - (120 > lanes + exitStatus = lanes; + errorRetryLanes = root.eventTimes; + for (errorRetryLanes$108 = -1; 0 < exitStatus; ) { + var index$2 = 31 - clz32(exitStatus), + lane = 1 << index$2; + index$2 = errorRetryLanes[index$2]; + index$2 > errorRetryLanes$108 && (errorRetryLanes$108 = index$2); + exitStatus &= ~lane; + } + exitStatus = errorRetryLanes$108; + exitStatus = now() - exitStatus; + exitStatus = + (120 > exitStatus ? 120 - : 480 > lanes + : 480 > exitStatus ? 480 - : 1080 > lanes + : 1080 > exitStatus ? 1080 - : 1920 > lanes + : 1920 > exitStatus ? 1920 - : 3e3 > lanes + : 3e3 > exitStatus ? 3e3 - : 4320 > lanes + : 4320 > exitStatus ? 4320 - : 1960 * ceil(lanes / 1960)) - lanes; - if (10 < lanes) { + : 1960 * ceil(exitStatus / 1960)) - exitStatus; + if (10 < exitStatus) { root.timeoutHandle = scheduleTimeout( - commitRoot.bind( + commitRootWhenReady.bind( null, root, + didTimeout, workInProgressRootRecoverableErrors, - workInProgressTransitions + workInProgressTransitions, + lanes ), - lanes + exitStatus ); break; } - commitRoot( - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ); + commitRootWhenReady(root); break; case 5: - commitRoot( - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ); + commitRootWhenReady(root); break; default: throw Error("Unknown root exit status."); @@ -6397,6 +6513,13 @@ function queueRecoverableErrors(errors) { errors ); } +function commitRootWhenReady(root) { + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); +} function isRenderConsistentWithExternalStores(finishedWork) { for (var node = finishedWork; ; ) { if (node.flags & 16384) { @@ -6516,6 +6639,8 @@ function resetWorkInProgressStack() { else resetContextDependencies(), resetHooksOnUnwind(), + (thenableState$1 = null), + (thenableIndexCounter$1 = 0), (interruptedWork = workInProgress); for (; null !== interruptedWork; ) unwindInterruptedWork(interruptedWork.alternate, interruptedWork), @@ -6529,6 +6654,9 @@ function prepareFreshStack(root, lanes) { var timeoutHandle = root.timeoutHandle; -1 !== timeoutHandle && ((root.timeoutHandle = -1), cancelTimeout(timeoutHandle)); + timeoutHandle = root.cancelPendingCommit; + null !== timeoutHandle && + ((root.cancelPendingCommit = null), timeoutHandle()); resetWorkInProgressStack(); workInProgressRoot = root; workInProgress = root = createWorkInProgress(root.current, null); @@ -6555,12 +6683,23 @@ function handleThrow(root, thrownValue) { throw Error( "Expected a suspended thenable. This is a bug in React. Please file an issue." ); - root = suspendedThenable; + thrownValue = suspendedThenable; suspendedThenable = null; - thrownValue = root; - workInProgressSuspendedReason = shouldAttemptToSuspendUntilDataResolves() - ? 2 - : 3; + (workInProgressRootRenderLanes & 8388480) === workInProgressRootRenderLanes + ? (root = null === shellBoundary ? !0 : !1) + : ((root = suspenseHandlerStackCursor.current), + (root = + null !== root && + (workInProgressRootRenderLanes & 125829120) === + workInProgressRootRenderLanes + ? root === shellBoundary + : !1)); + workInProgressSuspendedReason = + root && + 0 === (workInProgressRootSkippedLanes & 268435455) && + 0 === (workInProgressRootInterleavedUpdatedLanes & 268435455) + ? 2 + : 3; } else workInProgressSuspendedReason = thrownValue === SelectiveHydrationException @@ -6575,24 +6714,6 @@ function handleThrow(root, thrownValue) { ((workInProgressRootExitStatus = 1), (workInProgressRootFatalError = thrownValue)); } -function shouldAttemptToSuspendUntilDataResolves() { - if ( - 0 !== (workInProgressRootSkippedLanes & 268435455) || - 0 !== (workInProgressRootInterleavedUpdatedLanes & 268435455) - ) - return !1; - if ( - (workInProgressRootRenderLanes & 8388480) === - workInProgressRootRenderLanes - ) - return null === shellBoundary; - var handler = suspenseHandlerStackCursor.current; - return null !== handler && - (workInProgressRootRenderLanes & 125829120) === - workInProgressRootRenderLanes - ? handler === shellBoundary - : !1; -} function pushDispatcher() { var prevDispatcher = ReactCurrentDispatcher.current; ReactCurrentDispatcher.current = ContextOnlyDispatcher; @@ -6635,8 +6756,8 @@ function renderRootSync(root, lanes) { } workLoopSync(); break; - } catch (thrownValue$106) { - handleThrow(root, thrownValue$106); + } catch (thrownValue$111) { + handleThrow(root, thrownValue$111); } while (1); resetContextDependencies(); @@ -6717,8 +6838,8 @@ function renderRootConcurrent(root, lanes) { } workLoopConcurrent(); break; - } catch (thrownValue$108) { - handleThrow(root, thrownValue$108); + } catch (thrownValue$113) { + handleThrow(root, thrownValue$113); } while (1); resetContextDependencies(); @@ -6772,9 +6893,7 @@ function replaySuspendedUnitOfWork(unitOfWork) { ); break; default: - resetContextDependencies(), - resetHooksOnUnwind(), - unwindInterruptedWork(current, unitOfWork), + unwindInterruptedWork(current, unitOfWork), (unitOfWork = workInProgress = resetWorkInProgress(unitOfWork, renderLanes)), (current = beginWork(current, unitOfWork, renderLanes)); @@ -6788,6 +6907,8 @@ function replaySuspendedUnitOfWork(unitOfWork) { function unwindSuspendedUnitOfWork(unitOfWork, thrownValue) { resetContextDependencies(); resetHooksOnUnwind(); + thenableState$1 = null; + thenableIndexCounter$1 = 0; var returnFiber = unitOfWork.return; if (null === returnFiber || null === workInProgressRoot) (workInProgressRootExitStatus = 1), @@ -6849,27 +6970,35 @@ function unwindSuspendedUnitOfWork(unitOfWork, thrownValue) { else (suspenseBoundary.flags |= 65536), (suspenseBoundary.lanes = thrownValue); - var wakeables = suspenseBoundary.updateQueue; - null === wakeables - ? (suspenseBoundary.updateQueue = new Set([wakeable])) - : wakeables.add(wakeable); + if (wakeable === noopSuspenseyCommitThenable) + suspenseBoundary.flags |= 16384; + else { + var retryQueue = suspenseBoundary.updateQueue; + null === retryQueue + ? (suspenseBoundary.updateQueue = new Set([wakeable])) + : retryQueue.add(wakeable); + } break; case 22: if (suspenseBoundary.mode & 1) { suspenseBoundary.flags |= 65536; - var offscreenQueue = suspenseBoundary.updateQueue; - if (null === offscreenQueue) { - var newOffscreenQueue = { - transitions: null, - markerInstances: null, - wakeables: new Set([wakeable]) - }; - suspenseBoundary.updateQueue = newOffscreenQueue; - } else { - var wakeables$28 = offscreenQueue.wakeables; - null === wakeables$28 - ? (offscreenQueue.wakeables = new Set([wakeable])) - : wakeables$28.add(wakeable); + if (wakeable === noopSuspenseyCommitThenable) + suspenseBoundary.flags |= 16384; + else { + var offscreenQueue = suspenseBoundary.updateQueue; + if (null === offscreenQueue) { + var newOffscreenQueue = { + transitions: null, + markerInstances: null, + retryQueue: new Set([wakeable]) + }; + suspenseBoundary.updateQueue = newOffscreenQueue; + } else { + var retryQueue$31 = offscreenQueue.retryQueue; + null === retryQueue$31 + ? (offscreenQueue.retryQueue = new Set([wakeable])) + : retryQueue$31.add(wakeable); + } } break; } @@ -6958,7 +7087,7 @@ function completeUnitOfWork(unitOfWork) { } else { current = unwindWork(current, completedWork); if (null !== current) { - current.flags &= 16383; + current.flags &= 32767; workInProgress = current; return; } @@ -7020,6 +7149,7 @@ function commitRootImpl( ); root.callbackNode = null; root.callbackPriority = 0; + root.cancelPendingCommit = null; var remainingLanes = finishedWork.lanes | finishedWork.childLanes; remainingLanes |= concurrentlyUpdatedLanes; markRootFinished(root, remainingLanes); @@ -7241,11 +7371,7 @@ function pingSuspendedRoot(root, wakeable, pingedLanes) { } function retryTimedOutBoundary(boundaryFiber, retryLane) { 0 === retryLane && - (0 === (boundaryFiber.mode & 1) - ? (retryLane = 2) - : ((retryLane = nextRetryLane), - (nextRetryLane <<= 1), - 0 === (nextRetryLane & 125829120) && (nextRetryLane = 8388608))); + (retryLane = 0 === (boundaryFiber.mode & 1) ? 2 : claimNextRetryLane()); var eventTime = requestEventTime(); boundaryFiber = enqueueConcurrentRenderForLane(boundaryFiber, retryLane); null !== boundaryFiber && @@ -7756,7 +7882,7 @@ function createWorkInProgress(current, pendingProps) { (workInProgress.flags = 0), (workInProgress.subtreeFlags = 0), (workInProgress.deletions = null)); - workInProgress.flags = current.flags & 14680064; + workInProgress.flags = current.flags & 31457280; workInProgress.childLanes = current.childLanes; workInProgress.lanes = current.lanes; workInProgress.child = current.child; @@ -7775,7 +7901,7 @@ function createWorkInProgress(current, pendingProps) { return workInProgress; } function resetWorkInProgress(workInProgress, renderLanes) { - workInProgress.flags &= 14680066; + workInProgress.flags &= 31457282; var current = workInProgress.alternate; null === current ? ((workInProgress.childLanes = 0), @@ -7971,7 +8097,11 @@ function FiberRootNode( this.pendingChildren = null; this.timeoutHandle = -1; - this.callbackNode = this.pendingContext = this.context = null; + this.callbackNode = + this.pendingContext = + this.context = + this.cancelPendingCommit = + null; this.callbackPriority = 0; this.eventTimes = createLaneMap(0); this.expirationTimes = createLaneMap(-1); @@ -8391,19 +8521,19 @@ function wrapFiber(fiber) { fiberToWrapper.set(fiber, wrapper)); return wrapper; } -var devToolsConfig$jscomp$inline_982 = { +var devToolsConfig$jscomp$inline_1010 = { findFiberByHostInstance: function () { throw Error("TestRenderer does not support findFiberByHostInstance()"); }, bundleType: 0, - version: "18.3.0-next-ef8bdbecb-20230310", + version: "18.3.0-next-c57b90f50-20230320", rendererPackageName: "react-test-renderer" }; -var internals$jscomp$inline_1168 = { - bundleType: devToolsConfig$jscomp$inline_982.bundleType, - version: devToolsConfig$jscomp$inline_982.version, - rendererPackageName: devToolsConfig$jscomp$inline_982.rendererPackageName, - rendererConfig: devToolsConfig$jscomp$inline_982.rendererConfig, +var internals$jscomp$inline_1202 = { + bundleType: devToolsConfig$jscomp$inline_1010.bundleType, + version: devToolsConfig$jscomp$inline_1010.version, + rendererPackageName: devToolsConfig$jscomp$inline_1010.rendererPackageName, + rendererConfig: devToolsConfig$jscomp$inline_1010.rendererConfig, overrideHookState: null, overrideHookStateDeletePath: null, overrideHookStateRenamePath: null, @@ -8420,26 +8550,26 @@ var internals$jscomp$inline_1168 = { return null === fiber ? null : fiber.stateNode; }, findFiberByHostInstance: - devToolsConfig$jscomp$inline_982.findFiberByHostInstance || + devToolsConfig$jscomp$inline_1010.findFiberByHostInstance || emptyFindFiberByHostInstance, findHostInstancesForRefresh: null, scheduleRefresh: null, scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "18.3.0-next-ef8bdbecb-20230310" + reconcilerVersion: "18.3.0-next-c57b90f50-20230320" }; if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { - var hook$jscomp$inline_1169 = __REACT_DEVTOOLS_GLOBAL_HOOK__; + var hook$jscomp$inline_1203 = __REACT_DEVTOOLS_GLOBAL_HOOK__; if ( - !hook$jscomp$inline_1169.isDisabled && - hook$jscomp$inline_1169.supportsFiber + !hook$jscomp$inline_1203.isDisabled && + hook$jscomp$inline_1203.supportsFiber ) try { - (rendererID = hook$jscomp$inline_1169.inject( - internals$jscomp$inline_1168 + (rendererID = hook$jscomp$inline_1203.inject( + internals$jscomp$inline_1202 )), - (injectedHook = hook$jscomp$inline_1169); + (injectedHook = hook$jscomp$inline_1203); } catch (err) {} } exports._Scheduler = Scheduler; diff --git a/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react-test-renderer/cjs/ReactTestRenderer-profiling.js b/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react-test-renderer/cjs/ReactTestRenderer-profiling.js index c04771824c7df..6854d07647044 100644 --- a/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react-test-renderer/cjs/ReactTestRenderer-profiling.js +++ b/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react-test-renderer/cjs/ReactTestRenderer-profiling.js @@ -474,6 +474,12 @@ function claimNextTransitionLane() { 0 === (nextTransitionLane & 8388480) && (nextTransitionLane = 128); return lane; } +function claimNextRetryLane() { + var lane = nextRetryLane; + nextRetryLane <<= 1; + 0 === (nextRetryLane & 125829120) && (nextRetryLane = 8388608); + return lane; +} function createLaneMap(initial) { for (var laneMap = [], i = 0; 31 > i; i++) laneMap.push(initial); return laneMap; @@ -690,30 +696,43 @@ var objectIs = "function" === typeof Object.is ? Object.is : is, function flushSyncCallbacks() { if (!isFlushingSyncQueue && null !== syncQueue) { isFlushingSyncQueue = !0; - var i = 0, - previousUpdatePriority = currentUpdatePriority; - try { - var queue = syncQueue; - for (currentUpdatePriority = 2; i < queue.length; i++) { - var callback = queue[i]; + var previousUpdatePriority = currentUpdatePriority; + currentUpdatePriority = 2; + for (var errors = null, queue = syncQueue, i = 0; i < queue.length; i++) { + var callback = queue[i]; + try { do callback = callback(!0); while (null !== callback); + } catch (error) { + null === errors ? (errors = [error]) : errors.push(error); } - syncQueue = null; - includesLegacySyncCallbacks = !1; - } catch (error) { - throw ( - (null !== syncQueue && (syncQueue = syncQueue.slice(i + 1)), - scheduleCallback$2(ImmediatePriority, flushSyncCallbacks), - error) - ); - } finally { - (currentUpdatePriority = previousUpdatePriority), - (isFlushingSyncQueue = !1); + } + syncQueue = null; + includesLegacySyncCallbacks = !1; + currentUpdatePriority = previousUpdatePriority; + isFlushingSyncQueue = !1; + if (null !== errors) { + if (1 < errors.length) { + if ("function" === typeof AggregateError) + throw new AggregateError(errors); + for ( + previousUpdatePriority = 1; + previousUpdatePriority < errors.length; + previousUpdatePriority++ + ) + scheduleCallback$2( + ImmediatePriority, + throwError.bind(null, errors[previousUpdatePriority]) + ); + } + throw errors[0]; } } return null; } +function throwError(error) { + throw error; +} var contextStackCursor = createCursor(null), contextFiberStackCursor = createCursor(null), rootInstanceStackCursor = createCursor(null); @@ -1101,6 +1120,65 @@ function describeFiber(fiber) { return ""; } } +var SuspenseException = Error( + "Suspense Exception: This is not a real error! It's an implementation detail of `use` to interrupt the current render. You must either rethrow it immediately, or move the `use` call outside of the `try/catch` block. Capturing without rethrowing will lead to unexpected behavior.\n\nTo handle async errors, wrap your component in an error boundary, or call the promise's `.catch` method and pass the result to `use`" + ), + noopSuspenseyCommitThenable = { then: function () {} }; +function isThenableResolved(thenable) { + thenable = thenable.status; + return "fulfilled" === thenable || "rejected" === thenable; +} +function noop() {} +function trackUsedThenable(thenableState, thenable, index) { + index = thenableState[index]; + void 0 === index + ? thenableState.push(thenable) + : index !== thenable && (thenable.then(noop, noop), (thenable = index)); + switch (thenable.status) { + case "fulfilled": + return thenable.value; + case "rejected": + throw thenable.reason; + default: + "string" === typeof thenable.status + ? thenable.then(noop, noop) + : ((thenableState = thenable), + (thenableState.status = "pending"), + thenableState.then( + function (fulfilledValue) { + if ("pending" === thenable.status) { + var fulfilledThenable = thenable; + fulfilledThenable.status = "fulfilled"; + fulfilledThenable.value = fulfilledValue; + } + }, + function (error) { + if ("pending" === thenable.status) { + var rejectedThenable = thenable; + rejectedThenable.status = "rejected"; + rejectedThenable.reason = error; + } + } + )); + switch (thenable.status) { + case "fulfilled": + return thenable.value; + case "rejected": + throw thenable.reason; + } + suspendedThenable = thenable; + throw SuspenseException; + } +} +var suspendedThenable = null, + thenableState$1 = null, + thenableIndexCounter$1 = 0; +function unwrapThenable(thenable) { + var index = thenableIndexCounter$1; + thenableIndexCounter$1 += 1; + null === thenableState$1 && (thenableState$1 = []); + return trackUsedThenable(thenableState$1, thenable, index); +} function coerceRef(returnFiber, current, element) { returnFiber = element.ref; if ( @@ -1205,16 +1283,16 @@ function createChildReconciler(shouldTrackSideEffects) { return ( (newIndex = newIndex.index), newIndex < lastPlacedIndex - ? ((newFiber.flags |= 16777218), lastPlacedIndex) + ? ((newFiber.flags |= 33554434), lastPlacedIndex) : newIndex ); - newFiber.flags |= 16777218; + newFiber.flags |= 33554434; return lastPlacedIndex; } function placeSingleChild(newFiber) { shouldTrackSideEffects && null === newFiber.alternate && - (newFiber.flags |= 16777218); + (newFiber.flags |= 33554434); return newFiber; } function updateTextNode(returnFiber, current, textContent, lanes) { @@ -1351,6 +1429,17 @@ function createChildReconciler(shouldTrackSideEffects) { (newChild.return = returnFiber), newChild ); + if ("function" === typeof newChild.then) + return createChild(returnFiber, unwrapThenable(newChild), lanes); + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) + return createChild( + returnFiber, + readContextDuringReconcilation(returnFiber, newChild, lanes), + lanes + ); throwOnInvalidObjectType(returnFiber, newChild); } return null; @@ -1384,6 +1473,23 @@ function createChildReconciler(shouldTrackSideEffects) { return null !== key ? null : updateFragment(returnFiber, oldFiber, newChild, lanes, null); + if ("function" === typeof newChild.then) + return updateSlot( + returnFiber, + oldFiber, + unwrapThenable(newChild), + lanes + ); + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) + return updateSlot( + returnFiber, + oldFiber, + readContextDuringReconcilation(returnFiber, newChild, lanes), + lanes + ); throwOnInvalidObjectType(returnFiber, newChild); } return null; @@ -1436,6 +1542,25 @@ function createChildReconciler(shouldTrackSideEffects) { (existingChildren = existingChildren.get(newIdx) || null), updateFragment(returnFiber, existingChildren, newChild, lanes, null) ); + if ("function" === typeof newChild.then) + return updateFromMap( + existingChildren, + returnFiber, + newIdx, + unwrapThenable(newChild), + lanes + ); + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) + return updateFromMap( + existingChildren, + returnFiber, + newIdx, + readContextDuringReconcilation(returnFiber, newChild, lanes), + lanes + ); throwOnInvalidObjectType(returnFiber, newChild); } return null; @@ -1607,7 +1732,7 @@ function createChildReconciler(shouldTrackSideEffects) { }); return iteratorFn; } - function reconcileChildFibers( + function reconcileChildFibersImpl( returnFiber, currentFirstChild, newChild, @@ -1752,6 +1877,23 @@ function createChildReconciler(shouldTrackSideEffects) { newChild, lanes ); + if ("function" === typeof newChild.then) + return reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + unwrapThenable(newChild), + lanes + ); + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) + return reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + readContextDuringReconcilation(returnFiber, newChild, lanes), + lanes + ); throwOnInvalidObjectType(returnFiber, newChild); } return ("string" === typeof newChild && "" !== newChild) || @@ -1773,6 +1915,22 @@ function createChildReconciler(shouldTrackSideEffects) { placeSingleChild(returnFiber)) : deleteRemainingChildren(returnFiber, currentFirstChild); } + function reconcileChildFibers( + returnFiber, + currentFirstChild, + newChild, + lanes + ) { + thenableIndexCounter$1 = 0; + returnFiber = reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + newChild, + lanes + ); + thenableState$1 = null; + return returnFiber; + } return reconcileChildFibers; } var reconcileChildFibers = createChildReconciler(!0), @@ -1851,57 +2009,7 @@ function resetWorkInProgressVersions() { workInProgressSources[i]._workInProgressVersionSecondary = null; workInProgressSources.length = 0; } -var SuspenseException = Error( - "Suspense Exception: This is not a real error! It's an implementation detail of `use` to interrupt the current render. You must either rethrow it immediately, or move the `use` call outside of the `try/catch` block. Capturing without rethrowing will lead to unexpected behavior.\n\nTo handle async errors, wrap your component in an error boundary, or call the promise's `.catch` method and pass the result to `use`" -); -function isThenableResolved(thenable) { - thenable = thenable.status; - return "fulfilled" === thenable || "rejected" === thenable; -} -function noop() {} -function trackUsedThenable(thenableState, thenable, index) { - index = thenableState[index]; - void 0 === index - ? thenableState.push(thenable) - : index !== thenable && (thenable.then(noop, noop), (thenable = index)); - switch (thenable.status) { - case "fulfilled": - return thenable.value; - case "rejected": - throw thenable.reason; - default: - "string" === typeof thenable.status - ? thenable.then(noop, noop) - : ((thenableState = thenable), - (thenableState.status = "pending"), - thenableState.then( - function (fulfilledValue) { - if ("pending" === thenable.status) { - var fulfilledThenable = thenable; - fulfilledThenable.status = "fulfilled"; - fulfilledThenable.value = fulfilledValue; - } - }, - function (error) { - if ("pending" === thenable.status) { - var rejectedThenable = thenable; - rejectedThenable.status = "rejected"; - rejectedThenable.reason = error; - } - } - )); - switch (thenable.status) { - case "fulfilled": - return thenable.value; - case "rejected": - throw thenable.reason; - } - suspendedThenable = thenable; - throw SuspenseException; - } -} -var suspendedThenable = null, - ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, +var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, ReactCurrentBatchConfig$2 = ReactSharedInternals.ReactCurrentBatchConfig, renderLanes$1 = 0, currentlyRenderingFiber$1 = null, @@ -2061,10 +2169,10 @@ createFunctionComponentUpdateQueue = function () { function use(usable) { if (null !== usable && "object" === typeof usable) { if ("function" === typeof usable.then) { - var index$23 = thenableIndexCounter; + var index$25 = thenableIndexCounter; thenableIndexCounter += 1; null === thenableState && (thenableState = []); - usable = trackUsedThenable(thenableState, usable, index$23); + usable = trackUsedThenable(thenableState, usable, index$25); null === currentlyRenderingFiber$1.alternate && (null === workInProgressHook ? null === currentlyRenderingFiber$1.memoizedState @@ -2391,8 +2499,9 @@ function startTransition(setPending, callback) { var previousPriority = currentUpdatePriority; currentUpdatePriority = 0 !== previousPriority && 8 > previousPriority ? previousPriority : 8; - setPending(!0); var prevTransition = ReactCurrentBatchConfig$2.transition; + ReactCurrentBatchConfig$2.transition = null; + setPending(!0); ReactCurrentBatchConfig$2.transition = {}; try { setPending(!1), callback(); @@ -3610,7 +3719,7 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { (nextProps.treeBaseDuration = JSCompiler_temp.treeBaseDuration)), (workInProgress.deletions = null)) : ((nextProps = createWorkInProgress(JSCompiler_temp, primaryChildProps)), - (nextProps.subtreeFlags = JSCompiler_temp.subtreeFlags & 14680064)); + (nextProps.subtreeFlags = JSCompiler_temp.subtreeFlags & 31457280)); null !== dehydrated ? (showFallback = createWorkInProgress(dehydrated, showFallback)) : ((showFallback = createFiberFromFragment( @@ -4200,21 +4309,26 @@ function prepareToReadContext(workInProgress, renderLanes) { (workInProgress.firstContext = null)); } function readContext(context) { + return readContextForConsumer(currentlyRenderingFiber, context); +} +function readContextDuringReconcilation(consumer, context, renderLanes) { + null === currentlyRenderingFiber && + prepareToReadContext(consumer, renderLanes); + return readContextForConsumer(consumer, context); +} +function readContextForConsumer(consumer, context) { var value = context._currentValue2; if (lastFullyObservedContext !== context) if ( ((context = { context: context, memoizedValue: value, next: null }), null === lastContextDependency) ) { - if (null === currentlyRenderingFiber) + if (null === consumer) throw 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()." ); lastContextDependency = context; - currentlyRenderingFiber.dependencies = { - lanes: 0, - firstContext: context - }; + consumer.dependencies = { lanes: 0, firstContext: context }; } else lastContextDependency = lastContextDependency.next = context; return value; } @@ -4281,6 +4395,14 @@ function getSuspendedCache() { ? null : { parent: CacheContext._currentValue2, pool: cacheFromPool }; } +function scheduleRetryEffect(workInProgress, retryQueue) { + null !== retryQueue + ? (workInProgress.flags |= 4) + : workInProgress.flags & 16384 && + ((retryQueue = + 22 !== workInProgress.tag ? claimNextRetryLane() : 1073741824), + (workInProgress.lanes |= retryQueue)); +} function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { switch (renderState.tailMode) { case "hidden": @@ -4295,14 +4417,14 @@ function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { break; case "collapsed": lastTailNode = renderState.tail; - for (var lastTailNode$59 = null; null !== lastTailNode; ) - null !== lastTailNode.alternate && (lastTailNode$59 = lastTailNode), + for (var lastTailNode$62 = null; null !== lastTailNode; ) + null !== lastTailNode.alternate && (lastTailNode$62 = lastTailNode), (lastTailNode = lastTailNode.sibling); - null === lastTailNode$59 + null === lastTailNode$62 ? hasRenderedATailFallback || null === renderState.tail ? (renderState.tail = null) : (renderState.tail.sibling = null) - : (lastTailNode$59.sibling = null); + : (lastTailNode$62.sibling = null); } } function bubbleProperties(completedWork) { @@ -4314,53 +4436,53 @@ function bubbleProperties(completedWork) { if (didBailout) if (0 !== (completedWork.mode & 2)) { for ( - var treeBaseDuration$61 = completedWork.selfBaseDuration, - child$62 = completedWork.child; - null !== child$62; + var treeBaseDuration$64 = completedWork.selfBaseDuration, + child$65 = completedWork.child; + null !== child$65; ) - (newChildLanes |= child$62.lanes | child$62.childLanes), - (subtreeFlags |= child$62.subtreeFlags & 14680064), - (subtreeFlags |= child$62.flags & 14680064), - (treeBaseDuration$61 += child$62.treeBaseDuration), - (child$62 = child$62.sibling); - completedWork.treeBaseDuration = treeBaseDuration$61; + (newChildLanes |= child$65.lanes | child$65.childLanes), + (subtreeFlags |= child$65.subtreeFlags & 31457280), + (subtreeFlags |= child$65.flags & 31457280), + (treeBaseDuration$64 += child$65.treeBaseDuration), + (child$65 = child$65.sibling); + completedWork.treeBaseDuration = treeBaseDuration$64; } else for ( - treeBaseDuration$61 = completedWork.child; - null !== treeBaseDuration$61; + treeBaseDuration$64 = completedWork.child; + null !== treeBaseDuration$64; ) (newChildLanes |= - treeBaseDuration$61.lanes | treeBaseDuration$61.childLanes), - (subtreeFlags |= treeBaseDuration$61.subtreeFlags & 14680064), - (subtreeFlags |= treeBaseDuration$61.flags & 14680064), - (treeBaseDuration$61.return = completedWork), - (treeBaseDuration$61 = treeBaseDuration$61.sibling); + treeBaseDuration$64.lanes | treeBaseDuration$64.childLanes), + (subtreeFlags |= treeBaseDuration$64.subtreeFlags & 31457280), + (subtreeFlags |= treeBaseDuration$64.flags & 31457280), + (treeBaseDuration$64.return = completedWork), + (treeBaseDuration$64 = treeBaseDuration$64.sibling); else if (0 !== (completedWork.mode & 2)) { - treeBaseDuration$61 = completedWork.actualDuration; - child$62 = completedWork.selfBaseDuration; + treeBaseDuration$64 = completedWork.actualDuration; + child$65 = completedWork.selfBaseDuration; for (var child = completedWork.child; null !== child; ) (newChildLanes |= child.lanes | child.childLanes), (subtreeFlags |= child.subtreeFlags), (subtreeFlags |= child.flags), - (treeBaseDuration$61 += child.actualDuration), - (child$62 += child.treeBaseDuration), + (treeBaseDuration$64 += child.actualDuration), + (child$65 += child.treeBaseDuration), (child = child.sibling); - completedWork.actualDuration = treeBaseDuration$61; - completedWork.treeBaseDuration = child$62; + completedWork.actualDuration = treeBaseDuration$64; + completedWork.treeBaseDuration = child$65; } else for ( - treeBaseDuration$61 = completedWork.child; - null !== treeBaseDuration$61; + treeBaseDuration$64 = completedWork.child; + null !== treeBaseDuration$64; ) (newChildLanes |= - treeBaseDuration$61.lanes | treeBaseDuration$61.childLanes), - (subtreeFlags |= treeBaseDuration$61.subtreeFlags), - (subtreeFlags |= treeBaseDuration$61.flags), - (treeBaseDuration$61.return = completedWork), - (treeBaseDuration$61 = treeBaseDuration$61.sibling); + treeBaseDuration$64.lanes | treeBaseDuration$64.childLanes), + (subtreeFlags |= treeBaseDuration$64.subtreeFlags), + (subtreeFlags |= treeBaseDuration$64.flags), + (treeBaseDuration$64.return = completedWork), + (treeBaseDuration$64 = treeBaseDuration$64.sibling); completedWork.subtreeFlags |= subtreeFlags; completedWork.childLanes = newChildLanes; return didBailout; @@ -4418,7 +4540,8 @@ function completeWork(current, workInProgress, renderLanes) { renderLanes = workInProgress.type; if (null !== current && null != workInProgress.stateNode) current.memoizedProps !== newProps && - (workInProgress.updateQueue = UPDATE_SIGNAL) && + ((workInProgress.flags &= -16777217), + (workInProgress.updateQueue = UPDATE_SIGNAL)) && (workInProgress.flags |= 4), current.ref !== workInProgress.ref && (workInProgress.flags |= 2097664); @@ -4464,6 +4587,7 @@ function completeWork(current, workInProgress, renderLanes) { renderLanes = renderLanes.sibling; } workInProgress.stateNode = current; + workInProgress.flags &= -16777217; null !== workInProgress.ref && (workInProgress.flags |= 2097664); } bubbleProperties(workInProgress); @@ -4533,16 +4657,16 @@ function completeWork(current, workInProgress, renderLanes) { null !== newProps.alternate.memoizedState && null !== newProps.alternate.memoizedState.cachePool && (index = newProps.alternate.memoizedState.cachePool.pool); - var cache$69 = null; + var cache$72 = null; null !== newProps.memoizedState && null !== newProps.memoizedState.cachePool && - (cache$69 = newProps.memoizedState.cachePool.pool); - cache$69 !== index && (newProps.flags |= 2048); + (cache$72 = newProps.memoizedState.cachePool.pool); + cache$72 !== index && (newProps.flags |= 2048); } renderLanes !== current && renderLanes && (workInProgress.child.flags |= 8192); - null !== workInProgress.updateQueue && (workInProgress.flags |= 4); + scheduleRetryEffect(workInProgress, workInProgress.updateQueue); bubbleProperties(workInProgress); 0 !== (workInProgress.mode & 2) && renderLanes && @@ -4569,8 +4693,8 @@ function completeWork(current, workInProgress, renderLanes) { index = workInProgress.memoizedState; if (null === index) return bubbleProperties(workInProgress), null; newProps = 0 !== (workInProgress.flags & 128); - cache$69 = index.rendering; - if (null === cache$69) + cache$72 = index.rendering; + if (null === cache$72) if (newProps) cutOffTailIfNeeded(index, !1); else { if ( @@ -4578,14 +4702,13 @@ function completeWork(current, workInProgress, renderLanes) { (null !== current && 0 !== (current.flags & 128)) ) for (current = workInProgress.child; null !== current; ) { - cache$69 = findFirstSuspended(current); - if (null !== cache$69) { + cache$72 = findFirstSuspended(current); + if (null !== cache$72) { workInProgress.flags |= 128; cutOffTailIfNeeded(index, !1); - current = cache$69.updateQueue; - null !== current && - ((workInProgress.updateQueue = current), - (workInProgress.flags |= 4)); + current = cache$72.updateQueue; + workInProgress.updateQueue = current; + scheduleRetryEffect(workInProgress, current); workInProgress.subtreeFlags = 0; current = renderLanes; for (renderLanes = workInProgress.child; null !== renderLanes; ) @@ -4608,18 +4731,17 @@ function completeWork(current, workInProgress, renderLanes) { } else { if (!newProps) - if (((current = findFirstSuspended(cache$69)), null !== current)) { + if (((current = findFirstSuspended(cache$72)), null !== current)) { if ( ((workInProgress.flags |= 128), (newProps = !0), (current = current.updateQueue), - null !== current && - ((workInProgress.updateQueue = current), - (workInProgress.flags |= 4)), + (workInProgress.updateQueue = current), + scheduleRetryEffect(workInProgress, current), cutOffTailIfNeeded(index, !0), null === index.tail && "hidden" === index.tailMode && - !cache$69.alternate) + !cache$72.alternate) ) return bubbleProperties(workInProgress), null; } else @@ -4631,13 +4753,13 @@ function completeWork(current, workInProgress, renderLanes) { cutOffTailIfNeeded(index, !1), (workInProgress.lanes = 8388608)); index.isBackwards - ? ((cache$69.sibling = workInProgress.child), - (workInProgress.child = cache$69)) + ? ((cache$72.sibling = workInProgress.child), + (workInProgress.child = cache$72)) : ((current = index.last), null !== current - ? (current.sibling = cache$69) - : (workInProgress.child = cache$69), - (index.last = cache$69)); + ? (current.sibling = cache$72) + : (workInProgress.child = cache$72), + (index.last = cache$72)); } if (null !== index.tail) return ( @@ -4668,7 +4790,9 @@ function completeWork(current, workInProgress, renderLanes) { (bubbleProperties(workInProgress), workInProgress.subtreeFlags & 6 && (workInProgress.flags |= 8192)) : bubbleProperties(workInProgress), - null !== workInProgress.updateQueue && (workInProgress.flags |= 4), + (renderLanes = workInProgress.updateQueue), + null !== renderLanes && + scheduleRetryEffect(workInProgress, renderLanes.retryQueue), (renderLanes = null), null !== current && null !== current.memoizedState && @@ -4891,8 +5015,8 @@ function safelyDetachRef(current, nearestMountedAncestor) { recordLayoutEffectDuration(current); } else ref(null); - } catch (error$83) { - captureCommitPhaseError(current, nearestMountedAncestor, error$83); + } catch (error$88) { + captureCommitPhaseError(current, nearestMountedAncestor, error$88); } else ref.current = null; } @@ -4997,8 +5121,8 @@ function commitHookEffectListMount(flags, finishedWork) { var effect = (finishedWork = finishedWork.next); do { if ((effect.tag & flags) === flags) { - var create$84 = effect.create; - effect.destroy = create$84(); + var create$89 = effect.create; + effect.destroy = create$89(); } effect = effect.next; } while (effect !== finishedWork); @@ -5016,8 +5140,8 @@ function commitHookLayoutEffects(finishedWork, hookFlags) { } else try { commitHookEffectListMount(hookFlags, finishedWork); - } catch (error$86) { - captureCommitPhaseError(finishedWork, finishedWork.return, error$86); + } catch (error$91) { + captureCommitPhaseError(finishedWork, finishedWork.return, error$91); } } function commitClassCallbacks(finishedWork) { @@ -5097,11 +5221,11 @@ function commitLayoutEffectOnFiber(finishedRoot, current, finishedWork) { } else try { finishedRoot.componentDidMount(); - } catch (error$87) { + } catch (error$92) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$87 + error$92 ); } else { @@ -5118,11 +5242,11 @@ function commitLayoutEffectOnFiber(finishedRoot, current, finishedWork) { current, finishedRoot.__reactInternalSnapshotBeforeUpdate ); - } catch (error$88) { + } catch (error$93) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$88 + error$93 ); } recordLayoutEffectDuration(finishedWork); @@ -5133,11 +5257,11 @@ function commitLayoutEffectOnFiber(finishedRoot, current, finishedWork) { current, finishedRoot.__reactInternalSnapshotBeforeUpdate ); - } catch (error$89) { + } catch (error$94) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$89 + error$94 ); } } @@ -5517,22 +5641,22 @@ function commitMutationEffectsOnFiber(finishedWork, root) { try { startLayoutEffectTimer(), commitHookEffectListUnmount(5, finishedWork, finishedWork.return); - } catch (error$98) { + } catch (error$103) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$98 + error$103 ); } recordLayoutEffectDuration(finishedWork); } else try { commitHookEffectListUnmount(5, finishedWork, finishedWork.return); - } catch (error$99) { + } catch (error$104) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$99 + error$104 ); } } @@ -5573,11 +5697,11 @@ function commitMutationEffectsOnFiber(finishedWork, root) { if (null !== current) try { (flags.type = type), (flags.props = existingHiddenCallbacks); - } catch (error$102) { + } catch (error$107) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$102 + error$107 ); } } @@ -5594,8 +5718,8 @@ function commitMutationEffectsOnFiber(finishedWork, root) { existingHiddenCallbacks = finishedWork.memoizedProps; try { flags.text = existingHiddenCallbacks; - } catch (error$103) { - captureCommitPhaseError(finishedWork, finishedWork.return, error$103); + } catch (error$108) { + captureCommitPhaseError(finishedWork, finishedWork.return, error$108); } } break; @@ -5627,14 +5751,14 @@ function commitMutationEffectsOnFiber(finishedWork, root) { null !== current && safelyDetachRef(current, current.return); existingHiddenCallbacks = null !== finishedWork.memoizedState; - var wasHidden$107 = null !== current && null !== current.memoizedState; + var wasHidden$112 = null !== current && null !== current.memoizedState; if (finishedWork.mode & 1) { var prevOffscreenSubtreeIsHidden = offscreenSubtreeIsHidden, prevOffscreenSubtreeWasHidden = offscreenSubtreeWasHidden; offscreenSubtreeIsHidden = prevOffscreenSubtreeIsHidden || existingHiddenCallbacks; offscreenSubtreeWasHidden = - prevOffscreenSubtreeWasHidden || wasHidden$107; + prevOffscreenSubtreeWasHidden || wasHidden$112; recursivelyTraverseMutationEffects(root, finishedWork); offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden; offscreenSubtreeIsHidden = prevOffscreenSubtreeIsHidden; @@ -5652,22 +5776,22 @@ function commitMutationEffectsOnFiber(finishedWork, root) { existingHiddenCallbacks && ((root = offscreenSubtreeIsHidden || offscreenSubtreeWasHidden), null === current || - wasHidden$107 || + wasHidden$112 || root || (0 !== (finishedWork.mode & 1) && recursivelyTraverseDisappearLayoutEffects(finishedWork))), null === finishedWork.memoizedProps || "manual" !== finishedWork.memoizedProps.mode) ) - a: for (current = null, wasHidden$107 = finishedWork; ; ) { - if (5 === wasHidden$107.tag) { + a: for (current = null, wasHidden$112 = finishedWork; ; ) { + if (5 === wasHidden$112.tag) { if (null === current) { - current = wasHidden$107; + current = wasHidden$112; try { - (type = wasHidden$107.stateNode), + (type = wasHidden$112.stateNode), existingHiddenCallbacks ? (type.isHidden = !0) - : (wasHidden$107.stateNode.isHidden = !1); + : (wasHidden$112.stateNode.isHidden = !1); } catch (error) { captureCommitPhaseError( finishedWork, @@ -5676,49 +5800,49 @@ function commitMutationEffectsOnFiber(finishedWork, root) { ); } } - } else if (6 === wasHidden$107.tag) { + } else if (6 === wasHidden$112.tag) { if (null === current) try { - wasHidden$107.stateNode.isHidden = existingHiddenCallbacks + wasHidden$112.stateNode.isHidden = existingHiddenCallbacks ? !0 : !1; - } catch (error$92) { + } catch (error$97) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$92 + error$97 ); } } else if ( - ((22 !== wasHidden$107.tag && 23 !== wasHidden$107.tag) || - null === wasHidden$107.memoizedState || - wasHidden$107 === finishedWork) && - null !== wasHidden$107.child + ((22 !== wasHidden$112.tag && 23 !== wasHidden$112.tag) || + null === wasHidden$112.memoizedState || + wasHidden$112 === finishedWork) && + null !== wasHidden$112.child ) { - wasHidden$107.child.return = wasHidden$107; - wasHidden$107 = wasHidden$107.child; + wasHidden$112.child.return = wasHidden$112; + wasHidden$112 = wasHidden$112.child; continue; } - if (wasHidden$107 === finishedWork) break a; - for (; null === wasHidden$107.sibling; ) { + if (wasHidden$112 === finishedWork) break a; + for (; null === wasHidden$112.sibling; ) { if ( - null === wasHidden$107.return || - wasHidden$107.return === finishedWork + null === wasHidden$112.return || + wasHidden$112.return === finishedWork ) break a; - current === wasHidden$107 && (current = null); - wasHidden$107 = wasHidden$107.return; + current === wasHidden$112 && (current = null); + wasHidden$112 = wasHidden$112.return; } - current === wasHidden$107 && (current = null); - wasHidden$107.sibling.return = wasHidden$107.return; - wasHidden$107 = wasHidden$107.sibling; + current === wasHidden$112 && (current = null); + wasHidden$112.sibling.return = wasHidden$112.return; + wasHidden$112 = wasHidden$112.sibling; } flags & 4 && ((flags = finishedWork.updateQueue), null !== flags && - ((existingHiddenCallbacks = flags.wakeables), + ((existingHiddenCallbacks = flags.retryQueue), null !== existingHiddenCallbacks && - ((flags.wakeables = null), + ((flags.retryQueue = null), attachSuspenseRetryListeners( finishedWork, existingHiddenCallbacks @@ -5767,12 +5891,12 @@ function commitReconciliationEffects(finishedWork) { break; case 3: case 4: - var parent$93 = JSCompiler_inline_result.stateNode.containerInfo, - before$94 = getHostSibling(finishedWork); + var parent$98 = JSCompiler_inline_result.stateNode.containerInfo, + before$99 = getHostSibling(finishedWork); insertOrAppendPlacementNodeIntoContainer( finishedWork, - before$94, - parent$93 + before$99, + parent$98 ); break; default: @@ -5952,8 +6076,8 @@ function commitHookPassiveMountEffects(finishedWork, hookFlags) { } else try { commitHookEffectListMount(hookFlags, finishedWork); - } catch (error$110) { - captureCommitPhaseError(finishedWork, finishedWork.return, error$110); + } catch (error$115) { + captureCommitPhaseError(finishedWork, finishedWork.return, error$115); } } function commitOffscreenPassiveMountEffects(current, finishedWork) { @@ -6485,6 +6609,8 @@ function ensureRootIsScheduled(root, currentTime) { (root.callbackPriority = 0); else if (2 === workInProgressSuspendedReason && workInProgressRoot === root) (root.callbackPriority = 0), (root.callbackNode = null); + else if (null !== root.cancelPendingCommit && 0 === (suspendedLanes & 42)) + (root.callbackPriority = 0), (root.callbackNode = null); else if ( ((currentTime = suspendedLanes & -suspendedLanes), root.callbackPriority !== currentTime) @@ -6543,28 +6669,28 @@ function performConcurrentWorkOnRoot(root, didTimeout) { root === workInProgressRoot ? workInProgressRootRenderLanes : 0 ); if (0 === lanes) return null; - didTimeout = + var exitStatus = includesBlockingLane(root, lanes) || 0 !== (lanes & root.expiredLanes) || didTimeout ? renderRootSync(root, lanes) : renderRootConcurrent(root, lanes); - if (0 !== didTimeout) { - if (2 === didTimeout) { - var originallyAttemptedLanes = lanes, - errorRetryLanes = getLanesToRetrySynchronouslyOnError( - root, - originallyAttemptedLanes - ); + if (0 !== exitStatus) { + if (2 === exitStatus) { + didTimeout = lanes; + var errorRetryLanes = getLanesToRetrySynchronouslyOnError( + root, + didTimeout + ); 0 !== errorRetryLanes && ((lanes = errorRetryLanes), - (didTimeout = recoverFromConcurrentError( + (exitStatus = recoverFromConcurrentError( root, - originallyAttemptedLanes, + didTimeout, errorRetryLanes ))); } - if (1 === didTimeout) + if (1 === exitStatus) throw ( ((originalCallbackNode = workInProgressRootFatalError), prepareFreshStack(root, 0), @@ -6572,30 +6698,30 @@ function performConcurrentWorkOnRoot(root, didTimeout) { ensureRootIsScheduled(root, now$1()), originalCallbackNode) ); - if (6 === didTimeout) markRootSuspended(root, lanes); + if (6 === exitStatus) markRootSuspended(root, lanes); else { errorRetryLanes = !includesBlockingLane(root, lanes); - originallyAttemptedLanes = root.current.alternate; + didTimeout = root.current.alternate; if ( errorRetryLanes && - !isRenderConsistentWithExternalStores(originallyAttemptedLanes) + !isRenderConsistentWithExternalStores(didTimeout) ) { - didTimeout = renderRootSync(root, lanes); - if (2 === didTimeout) { + exitStatus = renderRootSync(root, lanes); + if (2 === exitStatus) { errorRetryLanes = lanes; - var errorRetryLanes$116 = getLanesToRetrySynchronouslyOnError( + var errorRetryLanes$121 = getLanesToRetrySynchronouslyOnError( root, errorRetryLanes ); - 0 !== errorRetryLanes$116 && - ((lanes = errorRetryLanes$116), - (didTimeout = recoverFromConcurrentError( + 0 !== errorRetryLanes$121 && + ((lanes = errorRetryLanes$121), + (exitStatus = recoverFromConcurrentError( root, errorRetryLanes, - errorRetryLanes$116 + errorRetryLanes$121 ))); } - if (1 === didTimeout) + if (1 === exitStatus) throw ( ((originalCallbackNode = workInProgressRootFatalError), prepareFreshStack(root, 0), @@ -6604,94 +6730,84 @@ function performConcurrentWorkOnRoot(root, didTimeout) { originalCallbackNode) ); } - root.finishedWork = originallyAttemptedLanes; + root.finishedWork = didTimeout; root.finishedLanes = lanes; - switch (didTimeout) { + switch (exitStatus) { case 0: case 1: throw Error("Root did not complete. This is a bug in React."); case 2: - commitRoot( - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ); + commitRootWhenReady(root); break; case 3: markRootSuspended(root, lanes); if ( (lanes & 125829120) === lanes && - ((lanes = globalMostRecentFallbackTime + 500 - now$1()), 10 < lanes) + ((exitStatus = globalMostRecentFallbackTime + 500 - now$1()), + 10 < exitStatus) ) { if (0 !== getNextLanes(root, 0)) break; root.timeoutHandle = scheduleTimeout( - commitRoot.bind( + commitRootWhenReady.bind( null, root, + didTimeout, workInProgressRootRecoverableErrors, - workInProgressTransitions + workInProgressTransitions, + lanes ), - lanes + exitStatus ); break; } - commitRoot( - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ); + commitRootWhenReady(root); break; case 4: markRootSuspended(root, lanes); if ((lanes & 8388480) === lanes) break; - didTimeout = root.eventTimes; - for (originallyAttemptedLanes = -1; 0 < lanes; ) - (errorRetryLanes$116 = 31 - clz32(lanes)), - (errorRetryLanes = 1 << errorRetryLanes$116), - (errorRetryLanes$116 = didTimeout[errorRetryLanes$116]), - errorRetryLanes$116 > originallyAttemptedLanes && - (originallyAttemptedLanes = errorRetryLanes$116), - (lanes &= ~errorRetryLanes); - lanes = originallyAttemptedLanes; - lanes = now$1() - lanes; - lanes = - (120 > lanes + exitStatus = lanes; + errorRetryLanes = root.eventTimes; + for (errorRetryLanes$121 = -1; 0 < exitStatus; ) { + var index$2 = 31 - clz32(exitStatus), + lane = 1 << index$2; + index$2 = errorRetryLanes[index$2]; + index$2 > errorRetryLanes$121 && (errorRetryLanes$121 = index$2); + exitStatus &= ~lane; + } + exitStatus = errorRetryLanes$121; + exitStatus = now$1() - exitStatus; + exitStatus = + (120 > exitStatus ? 120 - : 480 > lanes + : 480 > exitStatus ? 480 - : 1080 > lanes + : 1080 > exitStatus ? 1080 - : 1920 > lanes + : 1920 > exitStatus ? 1920 - : 3e3 > lanes + : 3e3 > exitStatus ? 3e3 - : 4320 > lanes + : 4320 > exitStatus ? 4320 - : 1960 * ceil(lanes / 1960)) - lanes; - if (10 < lanes) { + : 1960 * ceil(exitStatus / 1960)) - exitStatus; + if (10 < exitStatus) { root.timeoutHandle = scheduleTimeout( - commitRoot.bind( + commitRootWhenReady.bind( null, root, + didTimeout, workInProgressRootRecoverableErrors, - workInProgressTransitions + workInProgressTransitions, + lanes ), - lanes + exitStatus ); break; } - commitRoot( - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ); + commitRootWhenReady(root); break; case 5: - commitRoot( - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ); + commitRootWhenReady(root); break; default: throw Error("Unknown root exit status."); @@ -6734,6 +6850,13 @@ function queueRecoverableErrors(errors) { errors ); } +function commitRootWhenReady(root) { + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); +} function isRenderConsistentWithExternalStores(finishedWork) { for (var node = finishedWork; ; ) { if (node.flags & 16384) { @@ -6855,6 +6978,8 @@ function resetWorkInProgressStack() { else resetContextDependencies(), resetHooksOnUnwind(), + (thenableState$1 = null), + (thenableIndexCounter$1 = 0), (interruptedWork = workInProgress); for (; null !== interruptedWork; ) unwindInterruptedWork(interruptedWork.alternate, interruptedWork), @@ -6868,6 +6993,9 @@ function prepareFreshStack(root, lanes) { var timeoutHandle = root.timeoutHandle; -1 !== timeoutHandle && ((root.timeoutHandle = -1), cancelTimeout(timeoutHandle)); + timeoutHandle = root.cancelPendingCommit; + null !== timeoutHandle && + ((root.cancelPendingCommit = null), timeoutHandle()); resetWorkInProgressStack(); workInProgressRoot = root; workInProgress = root = createWorkInProgress(root.current, null); @@ -6896,9 +7024,21 @@ function handleThrow(root, thrownValue) { ); thrownValue = suspendedThenable; suspendedThenable = null; - workInProgressSuspendedReason = shouldAttemptToSuspendUntilDataResolves() - ? 2 - : 3; + (workInProgressRootRenderLanes & 8388480) === workInProgressRootRenderLanes + ? (root = null === shellBoundary ? !0 : !1) + : ((root = suspenseHandlerStackCursor.current), + (root = + null !== root && + (workInProgressRootRenderLanes & 125829120) === + workInProgressRootRenderLanes + ? root === shellBoundary + : !1)); + workInProgressSuspendedReason = + root && + 0 === (workInProgressRootSkippedLanes & 268435455) && + 0 === (workInProgressRootInterleavedUpdatedLanes & 268435455) + ? 2 + : 3; } else workInProgressSuspendedReason = thrownValue === SelectiveHydrationException @@ -6915,24 +7055,6 @@ function handleThrow(root, thrownValue) { (workInProgressRootFatalError = thrownValue)) : root.mode & 2 && stopProfilerTimerIfRunningAndRecordDelta(root, !0); } -function shouldAttemptToSuspendUntilDataResolves() { - if ( - 0 !== (workInProgressRootSkippedLanes & 268435455) || - 0 !== (workInProgressRootInterleavedUpdatedLanes & 268435455) - ) - return !1; - if ( - (workInProgressRootRenderLanes & 8388480) === - workInProgressRootRenderLanes - ) - return null === shellBoundary; - var handler = suspenseHandlerStackCursor.current; - return null !== handler && - (workInProgressRootRenderLanes & 125829120) === - workInProgressRootRenderLanes - ? handler === shellBoundary - : !1; -} function pushDispatcher() { var prevDispatcher = ReactCurrentDispatcher.current; ReactCurrentDispatcher.current = ContextOnlyDispatcher; @@ -6975,8 +7097,8 @@ function renderRootSync(root, lanes) { } workLoopSync(); break; - } catch (thrownValue$119) { - handleThrow(root, thrownValue$119); + } catch (thrownValue$124) { + handleThrow(root, thrownValue$124); } while (1); resetContextDependencies(); @@ -7057,8 +7179,8 @@ function renderRootConcurrent(root, lanes) { } workLoopConcurrent(); break; - } catch (thrownValue$121) { - handleThrow(root, thrownValue$121); + } catch (thrownValue$126) { + handleThrow(root, thrownValue$126); } while (1); resetContextDependencies(); @@ -7121,9 +7243,7 @@ function replaySuspendedUnitOfWork(unitOfWork) { ); break; default: - resetContextDependencies(), - resetHooksOnUnwind(), - unwindInterruptedWork(current, unitOfWork), + unwindInterruptedWork(current, unitOfWork), (unitOfWork = workInProgress = resetWorkInProgress(unitOfWork, renderLanes)), (current = beginWork(current, unitOfWork, renderLanes)); @@ -7138,6 +7258,8 @@ function replaySuspendedUnitOfWork(unitOfWork) { function unwindSuspendedUnitOfWork(unitOfWork, thrownValue) { resetContextDependencies(); resetHooksOnUnwind(); + thenableState$1 = null; + thenableIndexCounter$1 = 0; var returnFiber = unitOfWork.return; if (null === returnFiber || null === workInProgressRoot) (workInProgressRootExitStatus = 1), @@ -7199,27 +7321,35 @@ function unwindSuspendedUnitOfWork(unitOfWork, thrownValue) { else (suspenseBoundary.flags |= 65536), (suspenseBoundary.lanes = thrownValue); - var wakeables = suspenseBoundary.updateQueue; - null === wakeables - ? (suspenseBoundary.updateQueue = new Set([wakeable])) - : wakeables.add(wakeable); + if (wakeable === noopSuspenseyCommitThenable) + suspenseBoundary.flags |= 16384; + else { + var retryQueue = suspenseBoundary.updateQueue; + null === retryQueue + ? (suspenseBoundary.updateQueue = new Set([wakeable])) + : retryQueue.add(wakeable); + } break; case 22: if (suspenseBoundary.mode & 1) { suspenseBoundary.flags |= 65536; - var offscreenQueue = suspenseBoundary.updateQueue; - if (null === offscreenQueue) { - var newOffscreenQueue = { - transitions: null, - markerInstances: null, - wakeables: new Set([wakeable]) - }; - suspenseBoundary.updateQueue = newOffscreenQueue; - } else { - var wakeables$28 = offscreenQueue.wakeables; - null === wakeables$28 - ? (offscreenQueue.wakeables = new Set([wakeable])) - : wakeables$28.add(wakeable); + if (wakeable === noopSuspenseyCommitThenable) + suspenseBoundary.flags |= 16384; + else { + var offscreenQueue = suspenseBoundary.updateQueue; + if (null === offscreenQueue) { + var newOffscreenQueue = { + transitions: null, + markerInstances: null, + retryQueue: new Set([wakeable]) + }; + suspenseBoundary.updateQueue = newOffscreenQueue; + } else { + var retryQueue$31 = offscreenQueue.retryQueue; + null === retryQueue$31 + ? (offscreenQueue.retryQueue = new Set([wakeable])) + : retryQueue$31.add(wakeable); + } } break; } @@ -7312,7 +7442,7 @@ function completeUnitOfWork(unitOfWork) { } else { current = unwindWork(current, completedWork); if (null !== current) { - current.flags &= 16383; + current.flags &= 32767; workInProgress = current; return; } @@ -7381,6 +7511,7 @@ function commitRootImpl( ); root.callbackNode = null; root.callbackPriority = 0; + root.cancelPendingCommit = null; var remainingLanes = finishedWork.lanes | finishedWork.childLanes; remainingLanes |= concurrentlyUpdatedLanes; markRootFinished(root, remainingLanes); @@ -7507,11 +7638,11 @@ function flushPassiveEffects() { _finishedWork$memoize = finishedWork.memoizedProps, id = _finishedWork$memoize.id, onPostCommit = _finishedWork$memoize.onPostCommit, - commitTime$85 = commitTime, + commitTime$90 = commitTime, phase = null === finishedWork.alternate ? "mount" : "update"; currentUpdateIsNested && (phase = "nested-update"); "function" === typeof onPostCommit && - onPostCommit(id, phase, passiveEffectDuration, commitTime$85); + onPostCommit(id, phase, passiveEffectDuration, commitTime$90); var parentFiber = finishedWork.return; b: for (; null !== parentFiber; ) { switch (parentFiber.tag) { @@ -7649,11 +7780,7 @@ function pingSuspendedRoot(root, wakeable, pingedLanes) { } function retryTimedOutBoundary(boundaryFiber, retryLane) { 0 === retryLane && - (0 === (boundaryFiber.mode & 1) - ? (retryLane = 2) - : ((retryLane = nextRetryLane), - (nextRetryLane <<= 1), - 0 === (nextRetryLane & 125829120) && (nextRetryLane = 8388608))); + (retryLane = 0 === (boundaryFiber.mode & 1) ? 2 : claimNextRetryLane()); var eventTime = requestEventTime(); boundaryFiber = enqueueConcurrentRenderForLane(boundaryFiber, retryLane); null !== boundaryFiber && @@ -8173,7 +8300,7 @@ function createWorkInProgress(current, pendingProps) { (workInProgress.deletions = null), (workInProgress.actualDuration = 0), (workInProgress.actualStartTime = -1)); - workInProgress.flags = current.flags & 14680064; + workInProgress.flags = current.flags & 31457280; workInProgress.childLanes = current.childLanes; workInProgress.lanes = current.lanes; workInProgress.child = current.child; @@ -8194,7 +8321,7 @@ function createWorkInProgress(current, pendingProps) { return workInProgress; } function resetWorkInProgress(workInProgress, renderLanes) { - workInProgress.flags &= 14680066; + workInProgress.flags &= 31457282; var current = workInProgress.alternate; null === current ? ((workInProgress.childLanes = 0), @@ -8395,7 +8522,11 @@ function FiberRootNode( this.pendingChildren = null; this.timeoutHandle = -1; - this.callbackNode = this.pendingContext = this.context = null; + this.callbackNode = + this.pendingContext = + this.context = + this.cancelPendingCommit = + null; this.callbackPriority = 0; this.eventTimes = createLaneMap(0); this.expirationTimes = createLaneMap(-1); @@ -8817,19 +8948,19 @@ function wrapFiber(fiber) { fiberToWrapper.set(fiber, wrapper)); return wrapper; } -var devToolsConfig$jscomp$inline_1023 = { +var devToolsConfig$jscomp$inline_1051 = { findFiberByHostInstance: function () { throw Error("TestRenderer does not support findFiberByHostInstance()"); }, bundleType: 0, - version: "18.3.0-next-ef8bdbecb-20230310", + version: "18.3.0-next-c57b90f50-20230320", rendererPackageName: "react-test-renderer" }; -var internals$jscomp$inline_1207 = { - bundleType: devToolsConfig$jscomp$inline_1023.bundleType, - version: devToolsConfig$jscomp$inline_1023.version, - rendererPackageName: devToolsConfig$jscomp$inline_1023.rendererPackageName, - rendererConfig: devToolsConfig$jscomp$inline_1023.rendererConfig, +var internals$jscomp$inline_1241 = { + bundleType: devToolsConfig$jscomp$inline_1051.bundleType, + version: devToolsConfig$jscomp$inline_1051.version, + rendererPackageName: devToolsConfig$jscomp$inline_1051.rendererPackageName, + rendererConfig: devToolsConfig$jscomp$inline_1051.rendererConfig, overrideHookState: null, overrideHookStateDeletePath: null, overrideHookStateRenamePath: null, @@ -8846,26 +8977,26 @@ var internals$jscomp$inline_1207 = { return null === fiber ? null : fiber.stateNode; }, findFiberByHostInstance: - devToolsConfig$jscomp$inline_1023.findFiberByHostInstance || + devToolsConfig$jscomp$inline_1051.findFiberByHostInstance || emptyFindFiberByHostInstance, findHostInstancesForRefresh: null, scheduleRefresh: null, scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "18.3.0-next-ef8bdbecb-20230310" + reconcilerVersion: "18.3.0-next-c57b90f50-20230320" }; if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { - var hook$jscomp$inline_1208 = __REACT_DEVTOOLS_GLOBAL_HOOK__; + var hook$jscomp$inline_1242 = __REACT_DEVTOOLS_GLOBAL_HOOK__; if ( - !hook$jscomp$inline_1208.isDisabled && - hook$jscomp$inline_1208.supportsFiber + !hook$jscomp$inline_1242.isDisabled && + hook$jscomp$inline_1242.supportsFiber ) try { - (rendererID = hook$jscomp$inline_1208.inject( - internals$jscomp$inline_1207 + (rendererID = hook$jscomp$inline_1242.inject( + internals$jscomp$inline_1241 )), - (injectedHook = hook$jscomp$inline_1208); + (injectedHook = hook$jscomp$inline_1242); } catch (err) {} } exports._Scheduler = Scheduler; diff --git a/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/cjs/JSXDEVRuntime-dev.js b/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/cjs/JSXDEVRuntime-dev.js index b1d38fb748a80..c3c7a0d5afc87 100644 --- a/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/cjs/JSXDEVRuntime-dev.js +++ b/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/cjs/JSXDEVRuntime-dev.js @@ -693,7 +693,7 @@ function defineRefPropWarningGetter(props, displayName) { * @internal */ -var ReactElement = function (type, key, ref, self, source, owner, props) { +function ReactElement(type, key, ref, self, source, owner, props) { var element = { // This tag allows us to uniquely identify this as a React Element $$typeof: REACT_ELEMENT_TYPE, @@ -745,7 +745,7 @@ var ReactElement = function (type, key, ref, self, source, owner, props) { } return element; -}; +} /** * https://github.com/reactjs/rfcs/pull/107 * @param {*} type diff --git a/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/cjs/JSXRuntime-dev.js b/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/cjs/JSXRuntime-dev.js index c83f5500316ff..79388846a806e 100644 --- a/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/cjs/JSXRuntime-dev.js +++ b/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/cjs/JSXRuntime-dev.js @@ -693,7 +693,7 @@ function defineRefPropWarningGetter(props, displayName) { * @internal */ -var ReactElement = function (type, key, ref, self, source, owner, props) { +function ReactElement(type, key, ref, self, source, owner, props) { var element = { // This tag allows us to uniquely identify this as a React Element $$typeof: REACT_ELEMENT_TYPE, @@ -745,7 +745,7 @@ var ReactElement = function (type, key, ref, self, source, owner, props) { } return element; -}; +} /** * https://github.com/reactjs/rfcs/pull/107 * @param {*} type diff --git a/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/cjs/React-dev.js b/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/cjs/React-dev.js index 20d5205ca69dd..6c8bf4df54366 100644 --- a/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/cjs/React-dev.js +++ b/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/cjs/React-dev.js @@ -27,7 +27,7 @@ if ( } "use strict"; -var ReactVersion = "18.3.0-next-ef8bdbecb-20230310"; +var ReactVersion = "18.3.0-next-c57b90f50-20230320"; // ATTENTION // When adding new symbols to this file, @@ -830,7 +830,7 @@ function warnIfStringRefCannotBeAutoConverted$1(config) { * @internal */ -var ReactElement$1 = function (type, key, ref, self, source, owner, props) { +function ReactElement$1(type, key, ref, self, source, owner, props) { var element = { // This tag allows us to uniquely identify this as a React Element $$typeof: REACT_ELEMENT_TYPE, @@ -882,7 +882,7 @@ var ReactElement$1 = function (type, key, ref, self, source, owner, props) { } return element; -}; +} /** * Create and return a new ReactElement of the given type. * See https://reactjs.org/docs/react-api.html#createelement @@ -3327,7 +3327,7 @@ function defineRefPropWarningGetter(props, displayName) { * @internal */ -var ReactElement = function (type, key, ref, self, source, owner, props) { +function ReactElement(type, key, ref, self, source, owner, props) { var element = { // This tag allows us to uniquely identify this as a React Element $$typeof: REACT_ELEMENT_TYPE, @@ -3379,7 +3379,7 @@ var ReactElement = function (type, key, ref, self, source, owner, props) { } return element; -}; +} /** * https://github.com/reactjs/rfcs/pull/107 * @param {*} type diff --git a/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/cjs/React-prod.js b/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/cjs/React-prod.js index 7a78494c61867..1fbc378400010 100644 --- a/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/cjs/React-prod.js +++ b/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/cjs/React-prod.js @@ -639,4 +639,4 @@ exports.useSyncExternalStore = function ( ); }; exports.useTransition = useTransition; -exports.version = "18.3.0-next-ef8bdbecb-20230310"; +exports.version = "18.3.0-next-c57b90f50-20230320"; diff --git a/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/cjs/React-profiling.js b/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/cjs/React-profiling.js index 466255a4ec084..34f021a70147b 100644 --- a/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/cjs/React-profiling.js +++ b/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/cjs/React-profiling.js @@ -642,7 +642,7 @@ exports.useSyncExternalStore = function ( ); }; exports.useTransition = useTransition; -exports.version = "18.3.0-next-ef8bdbecb-20230310"; +exports.version = "18.3.0-next-c57b90f50-20230320"; /* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */ if ( diff --git a/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactFabric-dev.fb.js b/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactFabric-dev.fb.js index 69cd4e5678d29..e672463d2347e 100644 --- a/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactFabric-dev.fb.js +++ b/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactFabric-dev.fb.js @@ -428,10 +428,9 @@ function setComponentTree( } } } -var validateEventDispatches; -{ - validateEventDispatches = function (event) { +function validateEventDispatches(event) { + { var dispatchListeners = event._dispatchListeners; var dispatchInstances = event._dispatchInstances; var listenersIsArr = isArray(dispatchListeners); @@ -450,7 +449,7 @@ var validateEventDispatches; if (instancesIsArr !== listenersIsArr || instancesLen !== listenersLen) { error("EventPluginUtils: Invalid `event`."); } - }; + } } /** * Dispatch the event to the listener. @@ -1307,7 +1306,7 @@ var responderInst = null; var trackedTouchCount = 0; -var changeResponder = function (nextResponderInst, blockHostResponder) { +function changeResponder(nextResponderInst, blockHostResponder) { var oldResponderInst = responderInst; responderInst = nextResponderInst; @@ -1318,7 +1317,7 @@ var changeResponder = function (nextResponderInst, blockHostResponder) { blockHostResponder ); } -}; +} var eventTypes = { /** @@ -2539,24 +2538,6 @@ injectEventPluginsByName({ ReactNativeBridgeEventPlugin: ReactNativeBridgeEventPlugin }); -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$1 = {}; /** @@ -3022,205 +3003,308 @@ function diff(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$1(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 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 + ); + } + } } } -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. + * `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. * - * @param {?object} event Synthetic event to be dispatched. - * @private + * 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 executeDispatchesAndRelease = function (event) { - if (event) { - executeDispatchesInOrder(event); - - if (!event.isPersistent()) { - event.constructor.release(event); - } - } -}; // $FlowFixMe[missing-local-annot] +// NOTE: There are no flags, currently. Uncomment the stuff below if we add one. +// the exports object every time a flag is read. -var executeDispatchesAndReleaseTopLevel = function (e) { - return executeDispatchesAndRelease(e); -}; +var enableUseRefAccessWarning = dynamicFlags.enableUseRefAccessWarning; // The rest of the flags are static for better dead code elimination. +var enableSchedulingProfiler = true; +var enableProfilerTimer = true; +var enableProfilerCommitHooks = true; +var enableProfilerNestedUpdatePhase = true; +var createRootStrictEffectsByDefault = false; +var enableLazyContextPropagation = false; -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. +// ATTENTION +// When adding new symbols to this file, +// Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols' +// The Symbol used to tag the ReactElement-like types. +var REACT_ELEMENT_TYPE = Symbol.for("react.element"); +var REACT_PORTAL_TYPE = Symbol.for("react.portal"); +var REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"); +var REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"); +var REACT_PROFILER_TYPE = Symbol.for("react.profiler"); +var REACT_PROVIDER_TYPE = Symbol.for("react.provider"); +var REACT_CONTEXT_TYPE = Symbol.for("react.context"); +var REACT_SERVER_CONTEXT_TYPE = Symbol.for("react.server_context"); +var REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"); +var REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"); +var REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"); +var REACT_MEMO_TYPE = Symbol.for("react.memo"); +var REACT_LAZY_TYPE = Symbol.for("react.lazy"); +var REACT_SCOPE_TYPE = Symbol.for("react.scope"); +var REACT_DEBUG_TRACING_MODE_TYPE = Symbol.for("react.debug_trace_mode"); +var REACT_OFFSCREEN_TYPE = Symbol.for("react.offscreen"); +var REACT_LEGACY_HIDDEN_TYPE = Symbol.for("react.legacy_hidden"); +var REACT_CACHE_TYPE = Symbol.for("react.cache"); +var REACT_TRACING_MARKER_TYPE = Symbol.for("react.tracing_marker"); +var REACT_SERVER_CONTEXT_DEFAULT_VALUE_NOT_LOADED = Symbol.for( + "react.default_value" +); +var REACT_MEMO_CACHE_SENTINEL = Symbol.for("react.memo_cache_sentinel"); +var MAYBE_ITERATOR_SYMBOL = Symbol.iterator; +var FAUX_ITERATOR_SYMBOL = "@@iterator"; +function getIteratorFn(maybeIterable) { + if (maybeIterable === null || typeof maybeIterable !== "object") { + return null; + } - var processingEventQueue = eventQueue; - eventQueue = null; + var maybeIterator = + (MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL]) || + maybeIterable[FAUX_ITERATOR_SYMBOL]; - if (!processingEventQueue) { - return; + if (typeof maybeIterator === "function") { + return maybeIterator; } - forEachAccumulated(processingEventQueue, executeDispatchesAndReleaseTopLevel); + 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$1(outerType, innerType, wrapperName) { + var displayName = outerType.displayName; - rethrowCaughtError(); -} + if (displayName) { + return displayName; + } -/** - * Allows registered plugins an opportunity to extract events from top-level - * native browser events. - * - * @return {*} An accumulation of synthetic events. - * @internal - */ + var functionName = innerType.displayName || innerType.name || ""; + return functionName !== "" + ? wrapperName + "(" + functionName + ")" + : wrapperName; +} // Keep in sync with react-reconciler/getComponentNameFromFiber -function extractPluginEvents( - topLevelType, - targetInst, - nativeEvent, - nativeEventTarget -) { - var events = null; - var legacyPlugins = plugins; +function getContextName$1(type) { + return type.displayName || "Context"; +} // Note that the reconciler package should generally prefer to use getComponentNameFromFiber() instead. - for (var i = 0; i < legacyPlugins.length; i++) { - // Not every plugin in the ordering may be loaded at runtime. - var possiblePlugin = legacyPlugins[i]; +function getComponentNameFromType(type) { + if (type == null) { + // Host root, text node or just invalid type. + return null; + } - if (possiblePlugin) { - var extractedEvents = possiblePlugin.extractEvents( - topLevelType, - targetInst, - nativeEvent, - nativeEventTarget + { + if (typeof type.tag === "number") { + error( + "Received an unexpected object in getComponentNameFromType(). " + + "This is likely a bug in React. Please file an issue." ); - - if (extractedEvents) { - events = accumulateInto(events, extractedEvents); - } } } - return events; -} + if (typeof type === "function") { + return type.displayName || type.name || null; + } -function runExtractedPluginEventsInBatch( - topLevelType, - targetInst, - nativeEvent, - nativeEventTarget -) { - var events = extractPluginEvents( - topLevelType, - targetInst, - nativeEvent, - nativeEventTarget - ); - runEventsInBatch(events); -} + if (typeof type === "string") { + return type; + } -function dispatchEvent(target, topLevelType, nativeEvent) { - var targetFiber = target; - var eventTarget = null; + switch (type) { + case REACT_FRAGMENT_TYPE: + return "Fragment"; - if (targetFiber != null) { - var stateNode = targetFiber.stateNode; // Guard against Fiber being unmounted + case REACT_PORTAL_TYPE: + return "Portal"; - if (stateNode != null) { - // $FlowExpectedError[incompatible-cast] public instances in Fabric do not implement `EventTarget` yet. - eventTarget = getPublicInstance(stateNode); - } - } + case REACT_PROFILER_TYPE: + return "Profiler"; - batchedUpdates$1(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 - }; // $FlowFixMe[class-object-subtyping] found when upgrading Flow + case REACT_STRICT_MODE_TYPE: + return "StrictMode"; - ReactNativePrivateInterface.RawEventEmitter.emit(topLevelType, event); // $FlowFixMe[class-object-subtyping] found when upgrading Flow + case REACT_SUSPENSE_TYPE: + return "Suspense"; - ReactNativePrivateInterface.RawEventEmitter.emit("*", event); // Heritage plugin event system + case REACT_SUSPENSE_LIST_TYPE: + return "SuspenseList"; + } - runExtractedPluginEventsInBatch( - topLevelType, - targetFiber, - nativeEvent, - eventTarget - ); - }); // React Native doesn't use ReactControlledComponent but if it did, here's - // where it would do it. + if (typeof type === "object") { + switch (type.$$typeof) { + case REACT_CONTEXT_TYPE: + var context = type; + return getContextName$1(context) + ".Consumer"; + + case REACT_PROVIDER_TYPE: + var provider = type; + return getContextName$1(provider._context) + ".Provider"; + + case REACT_FORWARD_REF_TYPE: + return getWrappedName$1(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; + } + } + + case REACT_SERVER_CONTEXT_TYPE: { + var context2 = type; + return (context2.displayName || context2._globalName) + ".Provider"; + } + + // eslint-disable-next-line no-fallthrough + } + } + + return null; } -// NOTE: There are no flags, currently. Uncomment the stuff below if we add one. -// the exports object every time a flag is read. +function getWrappedName(outerType, innerType, wrapperName) { + var functionName = innerType.displayName || innerType.name || ""; + return ( + outerType.displayName || + (functionName !== "" ? wrapperName + "(" + functionName + ")" : wrapperName) + ); +} // Keep in sync with shared/getComponentNameFromType -var enableUseRefAccessWarning = dynamicFlags.enableUseRefAccessWarning; // The rest of the flags are static for better dead code elimination. -var enableSchedulingProfiler = true; -var enableProfilerTimer = true; -var enableProfilerCommitHooks = true; -var enableProfilerNestedUpdatePhase = true; -var createRootStrictEffectsByDefault = false; -var enableLazyContextPropagation = false; +function getContextName(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(context) + ".Consumer"; + + case ContextProvider: + var provider = type; + return getContextName(provider._context) + ".Provider"; + + case DehydratedFragment: + return "DehydratedFragment"; + + case ForwardRef: + return getWrappedName(type, type.render, "ForwardRef"); + + case Fragment: + return "Fragment"; + + case HostHoistable: + case HostSingleton: + 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; + + case LegacyHiddenComponent: { + return "LegacyHidden"; + } + } + + return null; +} var NoFlags$1 = /* */ @@ -3241,7 +3325,7 @@ var Hydrating = var Update = /* */ 4; -/* Skipped value: 0b000000000000000000000001000; */ +/* Skipped value: 0b0000000000000000000000001000; */ var ChildDeletion = /* */ @@ -3252,7 +3336,7 @@ var ContentReset = var Callback = /* */ 64; -/* Used by DidCapture: 0b000000000000000000010000000; */ +/* Used by DidCapture: 0b0000000000000000000010000000; */ var ForceClientRender = /* */ @@ -3266,20 +3350,24 @@ var Snapshot = var Passive$1 = /* */ 2048; -/* Used by Hydrating: 0b000000000000001000000000000; */ +/* Used by Hydrating: 0b0000000000000001000000000000; */ var Visibility = /* */ 8192; var StoreConsistency = /* */ - 16384; + 16384; // It's OK to reuse this bit because these flags are mutually exclusive for +// different fiber types. We should really be doing this for as many flags as +// possible, because we're about to run out of bits. + +var ScheduleRetry = StoreConsistency; var LifecycleEffectMask = Passive$1 | Update | Callback | Ref | Snapshot | StoreConsistency; // Union of all commit flags (flags with the lifetime of a particular commit) var HostEffectMask = /* */ - 16383; // These are not really side effects, but we still reuse this field. + 32767; // These are not really side effects, but we still reuse this field. var Incomplete = /* */ @@ -3306,17 +3394,20 @@ var LayoutStatic = 4194304; var PassiveStatic = /* */ - 8388608; // Flag used to identify newly inserted fibers. It isn't reset after commit unlike `Placement`. + 8388608; +var SuspenseyCommit = + /* */ + 16777216; // Flag used to identify newly inserted fibers. It isn't reset after commit unlike `Placement`. var PlacementDEV = /* */ - 16777216; + 33554432; var MountLayoutDev = /* */ - 33554432; + 67108864; var MountPassiveDev = /* */ - 67108864; // Groups of flags that are used in the commit phase to skip over trees that + 134217728; // Groups of flags that are used in the commit phase to skip over trees that // don't contain effects, by checking subtreeFlags. var BeforeMutationMask = // TODO: Remove Update flag from before mutation phase by re-landing Visibility @@ -3336,595 +3427,984 @@ var PassiveMask = Passive$1 | Visibility | ChildDeletion; // Union of tags that // 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 StaticMask = LayoutStatic | PassiveStatic | RefStatic | SuspenseyCommit; -// This module only exists as an ESM wrapper around the external CommonJS -var scheduleCallback$1 = Scheduler.unstable_scheduleCallback; -var cancelCallback$1 = Scheduler.unstable_cancelCallback; -var shouldYield = Scheduler.unstable_shouldYield; -var requestPaint = Scheduler.unstable_requestPaint; -var now$1 = Scheduler.unstable_now; -var ImmediatePriority = Scheduler.unstable_ImmediatePriority; -var UserBlockingPriority = Scheduler.unstable_UserBlockingPriority; -var NormalPriority = Scheduler.unstable_NormalPriority; -var IdlePriority = Scheduler.unstable_IdlePriority; // this doesn't actually exist on the scheduler, but it *does* +var ReactCurrentOwner$3 = ReactSharedInternals.ReactCurrentOwner; +function getNearestMountedFiber(fiber) { + var node = fiber; + var nearestMounted = fiber; -// Helpers to patch console.logs to avoid logging during side-effect free -// replaying on render function. This currently only patches the object -// lazily which won't cover if the log function was extracted eagerly. -// We could also eagerly patch the method. -var disabledDepth = 0; -var prevLog; -var prevInfo; -var prevWarn; -var prevError; -var prevGroup; -var prevGroupCollapsed; -var prevGroupEnd; + if (!fiber.alternate) { + // If there is no alternate, this might be a new tree that isn't inserted + // yet. If it is, then it will have a pending insertion effect on it. + var nextNode = node; -function disabledLog() {} + do { + node = nextNode; -disabledLog.__reactDisabledLog = true; -function disableLogs() { - { - if (disabledDepth === 0) { - /* eslint-disable react-internal/no-production-logging */ - prevLog = console.log; - prevInfo = console.info; - prevWarn = console.warn; - prevError = console.error; - prevGroup = console.group; - prevGroupCollapsed = console.groupCollapsed; - prevGroupEnd = console.groupEnd; // https://github.com/facebook/react/issues/19099 + if ((node.flags & (Placement | Hydrating)) !== NoFlags$1) { + // This is an insertion or in-progress hydration. The nearest possible + // mounted fiber is the parent but we need to continue to figure out + // if that one is still mounted. + nearestMounted = node.return; + } // $FlowFixMe[incompatible-type] we bail out when we get a null - var props = { - configurable: true, - enumerable: true, - value: disabledLog, - writable: true - }; // $FlowFixMe Flow thinks console is immutable. - - Object.defineProperties(console, { - info: props, - log: props, - warn: props, - error: props, - group: props, - groupCollapsed: props, - groupEnd: props - }); - /* eslint-enable react-internal/no-production-logging */ + nextNode = node.return; + } while (nextNode); + } else { + while (node.return) { + node = node.return; } - - disabledDepth++; } + + 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 reenableLogs() { +function isFiberMounted(fiber) { + return getNearestMountedFiber(fiber) === fiber; +} +function isMounted(component) { { - disabledDepth--; + var owner = ReactCurrentOwner$3.current; - if (disabledDepth === 0) { - /* eslint-disable react-internal/no-production-logging */ - var props = { - configurable: true, - enumerable: true, - writable: true - }; // $FlowFixMe Flow thinks console is immutable. + if (owner !== null && owner.tag === ClassComponent) { + var ownerFiber = owner; + var instance = ownerFiber.stateNode; - Object.defineProperties(console, { - log: assign({}, props, { - value: prevLog - }), - info: assign({}, props, { - value: prevInfo - }), - warn: assign({}, props, { - value: prevWarn - }), - error: assign({}, props, { - value: prevError - }), - group: assign({}, props, { - value: prevGroup - }), - groupCollapsed: assign({}, props, { - value: prevGroupCollapsed - }), - groupEnd: assign({}, props, { - value: prevGroupEnd - }) - }); - /* eslint-enable react-internal/no-production-logging */ - } + if (!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 (disabledDepth < 0) { - error( - "disabledDepth fell below zero. " + - "This is a bug in React. Please file an issue." - ); + instance._warnedAboutRefsInRender = true; } } -} -var rendererID = null; -var injectedHook = null; -var injectedProfilingHooks = null; -var hasLoggedError = false; -var isDevToolsPresent = typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== "undefined"; -function injectInternals(internals) { - if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === "undefined") { - // No DevTools + var fiber = get(component); + + if (!fiber) { return false; } - var hook = __REACT_DEVTOOLS_GLOBAL_HOOK__; + return getNearestMountedFiber(fiber) === fiber; +} - 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; +function assertIsMounted(fiber) { + if (getNearestMountedFiber(fiber) !== fiber) { + throw new Error("Unable to find node on an unmounted component."); } +} - if (!hook.supportsFiber) { - { - error( - "The installed version of React DevTools is too old and will not work " + - "with the current version of React. Please update React DevTools. " + - "https://reactjs.org/link/react-devtools" - ); - } // DevTools exists, even though it doesn't support Fiber. +function findCurrentFiberUsingSlowPath(fiber) { + var alternate = fiber.alternate; - return true; - } + if (!alternate) { + // If there is no alternate, then we only need to check if it is mounted. + var nearestMounted = getNearestMountedFiber(fiber); - 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 - }); + if (nearestMounted === null) { + throw new Error("Unable to find node on an unmounted component."); } - 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 (nearestMounted !== fiber) { + return null; } - } - 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; + 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. - error("React instrumentation encountered an error: %s", err); - } - } + var a = fiber; + var b = alternate; + + while (true) { + var parentA = a.return; + + if (parentA === null) { + // We're at the root. + break; } - } -} -function onCommitRoot(root, eventPriority) { - if (injectedHook && typeof injectedHook.onCommitFiberRoot === "function") { - try { - var didError = (root.current.flags & DidCapture) === DidCapture; - if (enableProfilerTimer) { - var schedulerPriority; + var parentB = parentA.alternate; - switch (eventPriority) { - case DiscreteEventPriority: - schedulerPriority = ImmediatePriority; - break; + 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 ContinuousEventPriority: - schedulerPriority = UserBlockingPriority; - break; + if (nextParent !== null) { + a = b = nextParent; + continue; + } // If there's no parent, we're at the root. - case DefaultEventPriority: - schedulerPriority = NormalPriority; - break; + break; + } // If both copies of the parent fiber point to the same child, we can + // assume that the child is current. This happens when we bailout on low + // priority: the bailed out fiber's child reuses the current child. - case IdleEventPriority: - schedulerPriority = IdlePriority; - break; + if (parentA.child === parentB.child) { + var child = parentA.child; - default: - schedulerPriority = NormalPriority; - break; + while (child) { + if (child === a) { + // We've determined that A is the current branch. + assertIsMounted(parentA); + return fiber; } - injectedHook.onCommitFiberRoot( - rendererID, - root, - schedulerPriority, - didError - ); - } - } catch (err) { - { - if (!hasLoggedError) { - hasLoggedError = true; - - error("React instrumentation encountered an error: %s", err); + 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."); } - } -} -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 (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; } - } - } -} -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); + 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 setIsStrictModeForDevtools(newIsStrictMode) { - { - if (newIsStrictMode) { - disableLogs(); - } else { - reenableLogs(); +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. + var tag = node.tag; + + if ( + tag === HostComponent || + tag === HostHoistable || + tag === HostSingleton || + tag === HostText + ) { + return node; + } + + var child = node.child; + + while (child !== null) { + var match = findCurrentHostFiberImpl(child); + + if (match !== null) { + return match; } + + child = child.sibling; } -} // Profiler API hooks -function injectProfilingHooks(profilingHooks) { - injectedProfilingHooks = profilingHooks; + return null; } -function getLaneLabelMap() { +// Helpers to patch console.logs to avoid logging during side-effect free +// replaying on render function. This currently only patches the object +// lazily which won't cover if the log function was extracted eagerly. +// We could also eagerly patch the method. +var disabledDepth = 0; +var prevLog; +var prevInfo; +var prevWarn; +var prevError; +var prevGroup; +var prevGroupCollapsed; +var prevGroupEnd; + +function disabledLog() {} + +disabledLog.__reactDisabledLog = true; +function disableLogs() { { - var map = new Map(); - var lane = 1; + if (disabledDepth === 0) { + /* eslint-disable react-internal/no-production-logging */ + prevLog = console.log; + prevInfo = console.info; + prevWarn = console.warn; + prevError = console.error; + prevGroup = console.group; + prevGroupCollapsed = console.groupCollapsed; + prevGroupEnd = console.groupEnd; // https://github.com/facebook/react/issues/19099 - for (var index = 0; index < TotalLanes; index++) { - var label = getLabelForLane(lane); - map.set(lane, label); - lane *= 2; + var props = { + configurable: true, + enumerable: true, + value: disabledLog, + writable: true + }; // $FlowFixMe Flow thinks console is immutable. + + Object.defineProperties(console, { + info: props, + log: props, + warn: props, + error: props, + group: props, + groupCollapsed: props, + groupEnd: props + }); + /* eslint-enable react-internal/no-production-logging */ } - return map; + disabledDepth++; } } - -function markCommitStarted(lanes) { +function reenableLogs() { { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markCommitStarted === "function" - ) { - injectedProfilingHooks.markCommitStarted(lanes); + disabledDepth--; + + if (disabledDepth === 0) { + /* eslint-disable react-internal/no-production-logging */ + var props = { + configurable: true, + enumerable: true, + writable: true + }; // $FlowFixMe Flow thinks console is immutable. + + Object.defineProperties(console, { + log: assign({}, props, { + value: prevLog + }), + info: assign({}, props, { + value: prevInfo + }), + warn: assign({}, props, { + value: prevWarn + }), + error: assign({}, props, { + value: prevError + }), + group: assign({}, props, { + value: prevGroup + }), + groupCollapsed: assign({}, props, { + value: prevGroupCollapsed + }), + groupEnd: assign({}, props, { + value: prevGroupEnd + }) + }); + /* eslint-enable react-internal/no-production-logging */ + } + + if (disabledDepth < 0) { + error( + "disabledDepth fell below zero. " + + "This is a bug in React. Please file an issue." + ); } } } -function markCommitStopped() { + +function describeBuiltInComponentFrame(name, source, ownerFn) { { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markCommitStopped === "function" - ) { - injectedProfilingHooks.markCommitStopped(); + var ownerName = null; + + if (ownerFn) { + ownerName = ownerFn.displayName || ownerFn.name || null; } + + return describeComponentFrame(name, source, ownerName); } } -function markComponentRenderStarted(fiber) { - { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentRenderStarted === "function" - ) { - injectedProfilingHooks.markComponentRenderStarted(fiber); - } - } -} -function markComponentRenderStopped() { - { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentRenderStopped === "function" - ) { - injectedProfilingHooks.markComponentRenderStopped(); - } - } -} -function markComponentPassiveEffectMountStarted(fiber) { - { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentPassiveEffectMountStarted === - "function" - ) { - injectedProfilingHooks.markComponentPassiveEffectMountStarted(fiber); - } - } -} -function markComponentPassiveEffectMountStopped() { - { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentPassiveEffectMountStopped === - "function" - ) { - injectedProfilingHooks.markComponentPassiveEffectMountStopped(); - } - } -} -function markComponentPassiveEffectUnmountStarted(fiber) { - { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentPassiveEffectUnmountStarted === - "function" - ) { - injectedProfilingHooks.markComponentPassiveEffectUnmountStarted(fiber); - } - } -} -function markComponentPassiveEffectUnmountStopped() { - { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentPassiveEffectUnmountStopped === - "function" - ) { - injectedProfilingHooks.markComponentPassiveEffectUnmountStopped(); - } - } + +{ + var PossiblyWeakMap$1 = typeof WeakMap === "function" ? WeakMap : Map; + new PossiblyWeakMap$1(); } -function markComponentLayoutEffectMountStarted(fiber) { - { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentLayoutEffectMountStarted === - "function" - ) { - injectedProfilingHooks.markComponentLayoutEffectMountStarted(fiber); +var BEFORE_SLASH_RE = /^(.*)[\\\/]/; + +function describeComponentFrame(name, source, ownerName) { + var sourceInfo = ""; + + 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". + + if (/^index\./.test(fileName)) { + var match = path.match(BEFORE_SLASH_RE); + + if (match) { + var pathBeforeSlash = match[1]; + + if (pathBeforeSlash) { + var folderName = pathBeforeSlash.replace(BEFORE_SLASH_RE, ""); + fileName = folderName + "/" + fileName; + } + } } + + sourceInfo = " (at " + fileName + ":" + source.lineNumber + ")"; + } else if (ownerName) { + sourceInfo = " (created by " + ownerName + ")"; } + + return "\n in " + (name || "Unknown") + sourceInfo; } -function markComponentLayoutEffectMountStopped() { + +function describeClassComponentFrame(ctor, source, ownerFn) { { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentLayoutEffectMountStopped === - "function" - ) { - injectedProfilingHooks.markComponentLayoutEffectMountStopped(); - } + return describeFunctionComponentFrame(ctor, source, ownerFn); } } -function markComponentLayoutEffectUnmountStarted(fiber) { +function describeFunctionComponentFrame(fn, source, ownerFn) { { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentLayoutEffectUnmountStarted === - "function" - ) { - injectedProfilingHooks.markComponentLayoutEffectUnmountStarted(fiber); + if (!fn) { + return ""; } - } -} -function markComponentLayoutEffectUnmountStopped() { - { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentLayoutEffectUnmountStopped === - "function" - ) { - injectedProfilingHooks.markComponentLayoutEffectUnmountStopped(); + + var name = fn.displayName || fn.name || null; + var ownerName = null; + + if (ownerFn) { + ownerName = ownerFn.displayName || ownerFn.name || null; } + + return describeComponentFrame(name, source, ownerName); } } -function markComponentErrored(fiber, thrownValue, lanes) { - { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentErrored === "function" - ) { - injectedProfilingHooks.markComponentErrored(fiber, thrownValue, lanes); - } + +function describeUnknownElementTypeFrameInDEV(type, source, ownerFn) { + if (type == null) { + return ""; } -} -function markComponentSuspended(fiber, wakeable, lanes) { - { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentSuspended === "function" - ) { - injectedProfilingHooks.markComponentSuspended(fiber, wakeable, lanes); + + if (typeof type === "function") { + { + return describeFunctionComponentFrame(type, source, ownerFn); } } -} -function markLayoutEffectsStarted(lanes) { - { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markLayoutEffectsStarted === "function" - ) { - injectedProfilingHooks.markLayoutEffectsStarted(lanes); - } + + if (typeof type === "string") { + return describeBuiltInComponentFrame(type, source, ownerFn); } -} -function markLayoutEffectsStopped() { - { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markLayoutEffectsStopped === "function" - ) { - injectedProfilingHooks.markLayoutEffectsStopped(); - } + + switch (type) { + case REACT_SUSPENSE_TYPE: + return describeBuiltInComponentFrame("Suspense", source, ownerFn); + + case REACT_SUSPENSE_LIST_TYPE: + return describeBuiltInComponentFrame("SuspenseList", source, ownerFn); } -} -function markPassiveEffectsStarted(lanes) { - { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markPassiveEffectsStarted === "function" - ) { - injectedProfilingHooks.markPassiveEffectsStarted(lanes); + + 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; + + try { + // Lazy may contain any component type so we recursively resolve it. + return describeUnknownElementTypeFrameInDEV( + init(payload), + source, + ownerFn + ); + } catch (x) {} + } } } + + return ""; } -function markPassiveEffectsStopped() { + +// $FlowFixMe[method-unbinding] +var hasOwnProperty = Object.prototype.hasOwnProperty; + +var loggedTypeFailures = {}; +var ReactDebugCurrentFrame$1 = ReactSharedInternals.ReactDebugCurrentFrame; + +function setCurrentlyValidatingElement(element) { { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markPassiveEffectsStopped === "function" - ) { - injectedProfilingHooks.markPassiveEffectsStopped(); + if (element) { + var owner = element._owner; + var stack = describeUnknownElementTypeFrameInDEV( + element.type, + element._source, + owner ? owner.type : null + ); + ReactDebugCurrentFrame$1.setExtraStackFrame(stack); + } else { + ReactDebugCurrentFrame$1.setExtraStackFrame(null); } } } -function markRenderStarted(lanes) { + +function checkPropTypes(typeSpecs, values, location, componentName, element) { { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markRenderStarted === "function" - ) { - injectedProfilingHooks.markRenderStarted(lanes); + // $FlowFixMe This is okay but Flow doesn't know it. + var has = Function.call.bind(hasOwnProperty); + + for (var typeSpecName in typeSpecs) { + if (has(typeSpecs, typeSpecName)) { + var error$1 = void 0; // Prop type validation may throw. In case they do, we don't want to + // fail the render phase where it didn't fail before. So we log it. + // After these have been cleaned up, we'll let them throw. + + try { + // This is intentionally an invariant that gets caught. It's the same + // behavior as without this statement except with a better message. + if (typeof typeSpecs[typeSpecName] !== "function") { + // eslint-disable-next-line react-internal/prod-error-codes + var err = Error( + (componentName || "React class") + + ": " + + location + + " type `" + + typeSpecName + + "` is invalid; " + + "it must be a function, usually from the `prop-types` package, but received `" + + typeof typeSpecs[typeSpecName] + + "`." + + "This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`." + ); + err.name = "Invariant Violation"; + throw err; + } + + 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 (error$1 && !(error$1 instanceof Error)) { + setCurrentlyValidatingElement(element); + + error( + "%s: type specification of %s" + + " `%s` is invalid; the type checker " + + "function must return `null` or an `Error` but returned a %s. " + + "You may have forgotten to pass an argument to the type checker " + + "creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and " + + "shape all require an argument).", + componentName || "React class", + location, + typeSpecName, + typeof error$1 + ); + + setCurrentlyValidatingElement(null); + } + + if ( + error$1 instanceof Error && + !(error$1.message in loggedTypeFailures) + ) { + // Only monitor this failure once because there tends to be a lot of the + // same error. + loggedTypeFailures[error$1.message] = true; + setCurrentlyValidatingElement(element); + + error("Failed %s type: %s", location, error$1.message); + + setCurrentlyValidatingElement(null); + } + } } } } -function markRenderYielded() { + +var valueStack = []; +var fiberStack; + +{ + fiberStack = []; +} + +var index = -1; + +function createCursor(defaultValue) { + return { + current: defaultValue + }; +} + +function pop(cursor, fiber) { + if (index < 0) { + { + error("Unexpected pop."); + } + + return; + } + { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markRenderYielded === "function" - ) { - injectedProfilingHooks.markRenderYielded(); + if (fiber !== fiberStack[index]) { + error("Unexpected Fiber popped."); } } + + cursor.current = valueStack[index]; + valueStack[index] = null; + + { + fiberStack[index] = null; + } + + index--; } -function markRenderStopped() { + +function push(cursor, value, fiber) { + index++; + valueStack[index] = cursor.current; + { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markRenderStopped === "function" - ) { - injectedProfilingHooks.markRenderStopped(); - } + fiberStack[index] = fiber; } + + cursor.current = value; } -function markRenderScheduled(lane) { + +var warnedAboutMissingGetChildContext; + +{ + warnedAboutMissingGetChildContext = {}; +} + +var emptyContextObject = {}; + +{ + Object.freeze(emptyContextObject); +} // A cursor to the current merged context object on the stack. + +var contextStackCursor$1 = createCursor(emptyContextObject); // A cursor to a boolean indicating whether the context has changed. + +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 previousContext = emptyContextObject; + +function getUnmaskedContext( + workInProgress, + Component, + didPushOwnContextIfProvider +) { { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markRenderScheduled === "function" - ) { - injectedProfilingHooks.markRenderScheduled(lane); + 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 contextStackCursor$1.current; } } -function markForceUpdateScheduled(fiber, lane) { + +function cacheContext(workInProgress, unmaskedContext, maskedContext) { { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markForceUpdateScheduled === "function" - ) { - injectedProfilingHooks.markForceUpdateScheduled(fiber, lane); - } + var instance = workInProgress.stateNode; + instance.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext; + instance.__reactInternalMemoizedMaskedChildContext = maskedContext; } } -function markStateUpdateScheduled(fiber, lane) { + +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 ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markStateUpdateScheduled === "function" + instance && + instance.__reactInternalMemoizedUnmaskedChildContext === unmaskedContext ) { - injectedProfilingHooks.markStateUpdateScheduled(fiber, lane); + return instance.__reactInternalMemoizedMaskedChildContext; } - } -} - -var NoMode = - /* */ - 0; // TODO: Remove ConcurrentMode by reading from the root tag instead -var ConcurrentMode = - /* */ - 1; -var ProfileMode = - /* */ - 2; -var StrictLegacyMode = - /* */ - 8; -var StrictEffectsMode = - /* */ - 16; -var ConcurrentUpdatesByDefaultMode = - /* */ - 32; + var context = {}; -// 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 + for (var key in contextTypes) { + context[key] = unmaskedContext[key]; + } -var log = Math.log; -var LN2 = Math.LN2; + { + var name = getComponentNameFromFiber(workInProgress) || "Unknown"; + checkPropTypes(contextTypes, context, "context", name); + } // Cache unmasked context so we can avoid recreating masked context unless necessary. + // Context is created before the class component is instantiated so check for instance. -function clz32Fallback(x) { - var asUint = x >>> 0; + if (instance) { + cacheContext(workInProgress, unmaskedContext, context); + } - if (asUint === 0) { - return 32; + return context; } - - return (31 - ((log(asUint) / LN2) | 0)) | 0; } -// If those values are changed that package should be rebuilt and redeployed. - -var TotalLanes = 31; +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$1, fiber); + } +} + +function popTopLevelContextObject(fiber) { + { + pop(didPerformWorkStackCursor, fiber); + pop(contextStackCursor$1, fiber); + } +} + +function pushTopLevelContextObject(fiber, context, didChange) { + { + if (contextStackCursor$1.current !== emptyContextObject) { + throw new Error( + "Unexpected context found on stack. " + + "This error is likely caused by a bug in React. Please file an issue." + ); + } + + push(contextStackCursor$1, 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 + ); + } + } + + 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.' + ); + } + } + + { + var name = getComponentNameFromFiber(fiber) || "Unknown"; + checkPropTypes(childContextTypes, childContext, "child context", name); + } + + 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$1.current; + push(contextStackCursor$1, 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." + ); + } + + 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$1, workInProgress); // Now push the new context and mark that it has changed. + + push(contextStackCursor$1, mergedContext, workInProgress); + push(didPerformWorkStackCursor, didChange, workInProgress); + } else { + pop(didPerformWorkStackCursor, workInProgress); + push(didPerformWorkStackCursor, didChange, workInProgress); + } + } +} + +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 node = fiber; + + do { + switch (node.tag) { + case HostRoot: + return node.stateNode.context; + + case ClassComponent: { + var Component = node.type; + + if (isContextProvider(Component)) { + return node.stateNode.__reactInternalMemoizedMergedChildContext; + } + + break; + } + } // $FlowFixMe[incompatible-type] we bail out when we get a null + + node = node.return; + } while (node !== null); + + throw new Error( + "Found unexpected detached subtree parent. " + + "This error is likely caused by a bug in React. Please file an issue." + ); + } +} + +var LegacyRoot = 0; +var ConcurrentRoot = 1; + +// We use the existence of the state object as an indicator that the component +// is hidden. +var OffscreenVisible = + /* */ + 1; +var OffscreenDetached = + /* */ + 2; +var OffscreenPassiveEffectsConnected = + /* */ + 4; +function isOffscreenManual(offscreenFiber) { + return ( + offscreenFiber.memoizedProps !== null && + offscreenFiber.memoizedProps.mode === "manual" + ); +} + +var NoMode = + /* */ + 0; // TODO: Remove ConcurrentMode by reading from the root tag instead + +var ConcurrentMode = + /* */ + 1; +var ProfileMode = + /* */ + 2; +var StrictLegacyMode = + /* */ + 8; +var StrictEffectsMode = + /* */ + 16; +var ConcurrentUpdatesByDefaultMode = + /* */ + 32; + +// 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; @@ -4814,5705 +5294,5457 @@ function lanesToEventPriority(lanes) { return IdleEventPriority; } -// Renderers that don't support mutation -// can re-export everything from this module. -function shim$1() { - 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$1; - -// Renderers that don't support hydration -// can re-export everything from this module. -function shim() { - throw new Error( - "The current renderer does not support 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 errorHydratingContainer = shim; - -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, - fabricGetBoundingClientRect = _nativeFabricUIManage.getBoundingClientRect; -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); -} - -var noop$1 = function () {}; -/** - * This is used for refs on host components. - */ +// This module only exists as an ESM wrapper around the external CommonJS +var scheduleCallback$1 = Scheduler.unstable_scheduleCallback; +var cancelCallback$1 = Scheduler.unstable_cancelCallback; +var shouldYield = Scheduler.unstable_shouldYield; +var requestPaint = Scheduler.unstable_requestPaint; +var now$1 = Scheduler.unstable_now; +var ImmediatePriority = Scheduler.unstable_ImmediatePriority; +var UserBlockingPriority = Scheduler.unstable_UserBlockingPriority; +var NormalPriority = Scheduler.unstable_NormalPriority; +var IdlePriority = Scheduler.unstable_IdlePriority; // this doesn't actually exist on the scheduler, but it *does* -var ReactFabricHostComponent = /*#__PURE__*/ (function () { - function ReactFabricHostComponent( - tag, - viewConfig, - props, - internalInstanceHandle - ) { - this._nativeTag = void 0; - this.viewConfig = void 0; - this.currentProps = void 0; - this._internalInstanceHandle = void 0; - this._nativeTag = tag; - this.viewConfig = viewConfig; - this.currentProps = props; - this._internalInstanceHandle = internalInstanceHandle; +var rendererID = null; +var injectedHook = null; +var injectedProfilingHooks = null; +var hasLoggedError = false; +var isDevToolsPresent = typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== "undefined"; +function injectInternals(internals) { + if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === "undefined") { + // No DevTools + return false; } - var _proto = ReactFabricHostComponent.prototype; + var hook = __REACT_DEVTOOLS_GLOBAL_HOOK__; - _proto.blur = function blur() { - ReactNativePrivateInterface.TextInputState.blurTextInput(this); - }; + 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; + } - _proto.focus = function focus() { - ReactNativePrivateInterface.TextInputState.focusTextInput(this); - }; + if (!hook.supportsFiber) { + { + error( + "The installed version of React DevTools is too old and will not work " + + "with the current version of React. Please update React DevTools. " + + "https://reactjs.org/link/react-devtools" + ); + } // DevTools exists, even though it doesn't support Fiber. - _proto.measure = function measure(callback) { - var node = getShadowNodeFromInternalInstanceHandle( - this._internalInstanceHandle - ); + return true; + } - if (node != null) { - fabricMeasure(node, callback); + 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 + }); } - }; - _proto.measureInWindow = function measureInWindow(callback) { - var node = getShadowNodeFromInternalInstanceHandle( - this._internalInstanceHandle - ); + rendererID = hook.inject(internals); // We have successfully injected, so now it is safe to set up hooks. - if (node != null) { - fabricMeasureInWindow(node, callback); + injectedHook = hook; + } catch (err) { + // Catch all errors because it is unsafe to throw during initialization. + { + error("React instrumentation encountered an error: %s.", err); } - }; + } - _proto.measureLayout = function measureLayout( - relativeToNativeNode, - onSuccess, - onFail - /* currently unused */ - ) { + 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 ( - typeof relativeToNativeNode === "number" || - !(relativeToNativeNode instanceof ReactFabricHostComponent) + injectedHook && + typeof injectedHook.onScheduleFiberRoot === "function" ) { - { - error( - "Warning: ref.measureLayout must be called with a ref to a native component." - ); - } + try { + injectedHook.onScheduleFiberRoot(rendererID, root, children); + } catch (err) { + if (!hasLoggedError) { + hasLoggedError = true; - return; + 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; - var toStateNode = getShadowNodeFromInternalInstanceHandle( - this._internalInstanceHandle - ); - var fromStateNode = getShadowNodeFromInternalInstanceHandle( - relativeToNativeNode._internalInstanceHandle - ); + if (enableProfilerTimer) { + var schedulerPriority; - if (toStateNode != null && fromStateNode != null) { - fabricMeasureLayout( - toStateNode, - fromStateNode, - onFail != null ? onFail : noop$1, - onSuccess != null ? onSuccess : noop$1 - ); - } - }; + switch (eventPriority) { + case DiscreteEventPriority: + schedulerPriority = ImmediatePriority; + break; - _proto.unstable_getBoundingClientRect = - function unstable_getBoundingClientRect() { - var node = getShadowNodeFromInternalInstanceHandle( - this._internalInstanceHandle - ); + case ContinuousEventPriority: + schedulerPriority = UserBlockingPriority; + break; - if (node != null) { - var rect = fabricGetBoundingClientRect(node); + case DefaultEventPriority: + schedulerPriority = NormalPriority; + break; - if (rect) { - return new DOMRect(rect[0], rect[1], rect[2], rect[3]); + case IdleEventPriority: + schedulerPriority = IdlePriority; + break; + + default: + schedulerPriority = NormalPriority; + break; } - } // Empty rect if any of the above failed - return new DOMRect(0, 0, 0, 0); - }; + injectedHook.onCommitFiberRoot( + rendererID, + root, + schedulerPriority, + didError + ); + } + } catch (err) { + { + if (!hasLoggedError) { + hasLoggedError = true; - _proto.setNativeProps = function setNativeProps(nativeProps) { - { - warnForStyleProps(nativeProps, this.viewConfig.validAttributes); + 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; - var updatePayload = create(nativeProps, this.viewConfig.validAttributes); - var node = getShadowNodeFromInternalInstanceHandle( - this._internalInstanceHandle - ); - - if (node != null && updatePayload != null) { - _setNativeProps(node, updatePayload); + error("React instrumentation encountered an error: %s", err); + } + } } - }; - - return ReactFabricHostComponent; -})(); - -function getShadowNodeFromInternalInstanceHandle(internalInstanceHandle) { - return ( - // $FlowExpectedError[incompatible-return] internalInstanceHandle is opaque but we need to make an exception here. - internalInstanceHandle && // $FlowExpectedError[incompatible-return] - internalInstanceHandle.stateNode && // $FlowExpectedError[incompatible-use] - internalInstanceHandle.stateNode.node - ); -} -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); +function onCommitUnmount(fiber) { + if (injectedHook && typeof injectedHook.onCommitFiberUnmount === "function") { + try { + injectedHook.onCommitFiberUnmount(rendererID, fiber); + } catch (err) { + { + if (!hasLoggedError) { + hasLoggedError = true; - { - for (var key in viewConfig.validAttributes) { - if (props.hasOwnProperty(key)) { - ReactNativePrivateInterface.deepFreezeAndThrowOnMutationInDev( - props[key] - ); + error("React instrumentation encountered an error: %s", err); + } } } } - - 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 -) { +function setIsStrictModeForDevtools(newIsStrictMode) { { - if (!hostContext.isInAParentText) { - error("Text strings must be rendered within a component."); + if (newIsStrictMode) { + disableLogs(); + } else { + reenableLogs(); } } +} // Profiler API hooks - 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) { - 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 injectProfilingHooks(profilingHooks) { + injectedProfilingHooks = profilingHooks; } -function getPublicInstance(instance) { - if (instance.canonical) { - return instance.canonical; - } // For compatibility with Paper - if (instance._nativeTag != null) { - return instance; - } +function getLaneLabelMap() { + { + var map = new Map(); + var lane = 1; - return null; -} -function prepareUpdate(instance, type, oldProps, newProps, 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. + for (var index = 0; index < TotalLanes; index++) { + var label = getLabelForLane(lane); + map.set(lane, label); + lane *= 2; + } - instance.canonical.currentProps = newProps; - return updatePayload; -} -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; + return map; + } } -function getCurrentEventPriority() { - var currentEventPriority = fabricGetCurrentEventPriority - ? fabricGetCurrentEventPriority() - : null; - - if (currentEventPriority != null) { - switch (currentEventPriority) { - case FabricDiscretePriority: - return DiscreteEventPriority; - case FabricDefaultPriority: - default: - return DefaultEventPriority; +function markCommitStarted(lanes) { + { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markCommitStarted === "function" + ) { + injectedProfilingHooks.markCommitStarted(lanes); } } - - 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); +} +function markCommitStopped() { + { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markCommitStopped === "function" + ) { + injectedProfilingHooks.markCommitStopped(); } - } else { - if (updatePayload !== null) { - clone = cloneNodeWithNewChildrenAndProps(node, updatePayload); - } else { - clone = cloneNodeWithNewChildren(node); + } +} +function markComponentRenderStarted(fiber) { + { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentRenderStarted === "function" + ) { + injectedProfilingHooks.markComponentRenderStarted(fiber); } } - - 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 markComponentRenderStopped() { + { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentRenderStopped === "function" + ) { + injectedProfilingHooks.markComponentRenderStopped(); + } + } } -function cloneHiddenTextInstance(instance, text, internalInstanceHandle) { - throw new Error("Not yet implemented."); +function markComponentPassiveEffectMountStarted(fiber) { + { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentPassiveEffectMountStarted === + "function" + ) { + injectedProfilingHooks.markComponentPassiveEffectMountStarted(fiber); + } + } } -function createContainerChildSet(container) { - return createChildNodeSet(container); +function markComponentPassiveEffectMountStopped() { + { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentPassiveEffectMountStopped === + "function" + ) { + injectedProfilingHooks.markComponentPassiveEffectMountStopped(); + } + } } -function appendChildToContainerChildSet(childSet, child) { - appendChildNodeToSet(childSet, child.node); +function markComponentPassiveEffectUnmountStarted(fiber) { + { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentPassiveEffectUnmountStarted === + "function" + ) { + injectedProfilingHooks.markComponentPassiveEffectUnmountStarted(fiber); + } + } } -function finalizeContainerChildren(container, newChildren) { - completeRoot(container, newChildren); -} -function replaceContainerChildren(container, newChildren) {} - -// This is ok in DOM because they types are interchangeable, but in React Native -// they aren't. - -function getInstanceFromNode(node) { - // $FlowFixMe[incompatible-return] DevTools incorrectly passes a fiber in React Native. - return node; +function markComponentPassiveEffectUnmountStopped() { + { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentPassiveEffectUnmountStopped === + "function" + ) { + injectedProfilingHooks.markComponentPassiveEffectUnmountStopped(); + } + } } - -function getNodeFromInstance(fiber) { - var publicInstance = getPublicInstance(fiber.stateNode); - - if (publicInstance == null) { - throw new Error("Could not find host instance from fiber"); +function markComponentLayoutEffectMountStarted(fiber) { + { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentLayoutEffectMountStarted === + "function" + ) { + injectedProfilingHooks.markComponentLayoutEffectMountStarted(fiber); + } } - - return publicInstance; } - -function getFiberCurrentPropsFromNode(instance) { - return instance.canonical.currentProps; +function markComponentLayoutEffectMountStopped() { + { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentLayoutEffectMountStopped === + "function" + ) { + injectedProfilingHooks.markComponentLayoutEffectMountStopped(); + } + } } - -var ReactFabricGlobalResponderHandler = { - onChange: function (from, to, blockNativeResponder) { - if (from) { - // equivalent to clearJSResponder - nativeFabricUIManager.setIsJSResponder( - from.stateNode.node, - false, - blockNativeResponder || false - ); +function markComponentLayoutEffectUnmountStarted(fiber) { + { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentLayoutEffectUnmountStarted === + "function" + ) { + injectedProfilingHooks.markComponentLayoutEffectUnmountStarted(fiber); } - - if (to) { - // equivalent to setJSResponder - nativeFabricUIManager.setIsJSResponder( - to.stateNode.node, - true, - blockNativeResponder || false - ); + } +} +function markComponentLayoutEffectUnmountStopped() { + { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentLayoutEffectUnmountStopped === + "function" + ) { + injectedProfilingHooks.markComponentLayoutEffectUnmountStopped(); } } -}; - -setComponentTree( - getFiberCurrentPropsFromNode, - getInstanceFromNode, - getNodeFromInstance -); -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; +function markComponentErrored(fiber, thrownValue, lanes) { + { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentErrored === "function" + ) { + injectedProfilingHooks.markComponentErrored(fiber, thrownValue, lanes); + } + } } - -// ATTENTION -// When adding new symbols to this file, -// Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols' -// The Symbol used to tag the ReactElement-like types. -var REACT_ELEMENT_TYPE = Symbol.for("react.element"); -var REACT_PORTAL_TYPE = Symbol.for("react.portal"); -var REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"); -var REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"); -var REACT_PROFILER_TYPE = Symbol.for("react.profiler"); -var REACT_PROVIDER_TYPE = Symbol.for("react.provider"); -var REACT_CONTEXT_TYPE = Symbol.for("react.context"); -var REACT_SERVER_CONTEXT_TYPE = Symbol.for("react.server_context"); -var REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"); -var REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"); -var REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"); -var REACT_MEMO_TYPE = Symbol.for("react.memo"); -var REACT_LAZY_TYPE = Symbol.for("react.lazy"); -var REACT_SCOPE_TYPE = Symbol.for("react.scope"); -var REACT_DEBUG_TRACING_MODE_TYPE = Symbol.for("react.debug_trace_mode"); -var REACT_OFFSCREEN_TYPE = Symbol.for("react.offscreen"); -var REACT_LEGACY_HIDDEN_TYPE = Symbol.for("react.legacy_hidden"); -var REACT_CACHE_TYPE = Symbol.for("react.cache"); -var REACT_TRACING_MARKER_TYPE = Symbol.for("react.tracing_marker"); -var REACT_SERVER_CONTEXT_DEFAULT_VALUE_NOT_LOADED = Symbol.for( - "react.default_value" -); -var REACT_MEMO_CACHE_SENTINEL = Symbol.for("react.memo_cache_sentinel"); -var MAYBE_ITERATOR_SYMBOL = Symbol.iterator; -var FAUX_ITERATOR_SYMBOL = "@@iterator"; -function getIteratorFn(maybeIterable) { - if (maybeIterable === null || typeof maybeIterable !== "object") { - return null; +function markComponentSuspended(fiber, wakeable, lanes) { + { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentSuspended === "function" + ) { + injectedProfilingHooks.markComponentSuspended(fiber, wakeable, lanes); + } } - - var maybeIterator = - (MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL]) || - maybeIterable[FAUX_ITERATOR_SYMBOL]; - - if (typeof maybeIterator === "function") { - return maybeIterator; +} +function markLayoutEffectsStarted(lanes) { + { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markLayoutEffectsStarted === "function" + ) { + injectedProfilingHooks.markLayoutEffectsStarted(lanes); + } } - - return null; } - -function getWrappedName$1(outerType, innerType, wrapperName) { - var displayName = outerType.displayName; - - if (displayName) { - return displayName; +function markLayoutEffectsStopped() { + { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markLayoutEffectsStopped === "function" + ) { + injectedProfilingHooks.markLayoutEffectsStopped(); + } } - - var functionName = innerType.displayName || innerType.name || ""; - return functionName !== "" - ? wrapperName + "(" + functionName + ")" - : wrapperName; -} // Keep in sync with react-reconciler/getComponentNameFromFiber - -function getContextName$1(type) { - return type.displayName || "Context"; -} // Note that the reconciler package should generally prefer to use getComponentNameFromFiber() instead. - -function getComponentNameFromType(type) { - if (type == null) { - // Host root, text node or just invalid type. - return null; +} +function markPassiveEffectsStarted(lanes) { + { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markPassiveEffectsStarted === "function" + ) { + injectedProfilingHooks.markPassiveEffectsStarted(lanes); + } } - +} +function markPassiveEffectsStopped() { { - if (typeof type.tag === "number") { - error( - "Received an unexpected object in getComponentNameFromType(). " + - "This is likely a bug in React. Please file an issue." - ); + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markPassiveEffectsStopped === "function" + ) { + injectedProfilingHooks.markPassiveEffectsStopped(); } } - - if (typeof type === "function") { - return type.displayName || type.name || null; +} +function markRenderStarted(lanes) { + { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markRenderStarted === "function" + ) { + injectedProfilingHooks.markRenderStarted(lanes); + } } - - if (typeof type === "string") { - return type; +} +function markRenderYielded() { + { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markRenderYielded === "function" + ) { + injectedProfilingHooks.markRenderYielded(); + } } +} +function markRenderStopped() { + { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markRenderStopped === "function" + ) { + injectedProfilingHooks.markRenderStopped(); + } + } +} +function markRenderScheduled(lane) { + { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markRenderScheduled === "function" + ) { + injectedProfilingHooks.markRenderScheduled(lane); + } + } +} +function markForceUpdateScheduled(fiber, lane) { + { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markForceUpdateScheduled === "function" + ) { + injectedProfilingHooks.markForceUpdateScheduled(fiber, lane); + } + } +} +function markStateUpdateScheduled(fiber, lane) { + { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markStateUpdateScheduled === "function" + ) { + injectedProfilingHooks.markStateUpdateScheduled(fiber, lane); + } + } +} - 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"; +/** + * 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 REACT_SUSPENSE_TYPE: - return "Suspense"; +var objectIs = typeof Object.is === "function" ? Object.is : is; // $FlowFixMe[method-unbinding] - case REACT_SUSPENSE_LIST_TYPE: - return "SuspenseList"; +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; // Set the event priority to discrete + // TODO: Is this necessary anymore? The only user code that runs in this + // queue is in the render or commit phases, which already set the + // event priority. Should be able to remove. - if (typeof type === "object") { - switch (type.$$typeof) { - case REACT_CONTEXT_TYPE: - var context = type; - return getContextName$1(context) + ".Consumer"; - - case REACT_PROVIDER_TYPE: - var provider = type; - return getContextName$1(provider._context) + ".Provider"; + var previousUpdatePriority = getCurrentUpdatePriority(); + setCurrentUpdatePriority(DiscreteEventPriority); + var errors = null; + var queue = syncQueue; // $FlowFixMe[incompatible-use] found when upgrading Flow - case REACT_FORWARD_REF_TYPE: - return getWrappedName$1(type, type.render, "ForwardRef"); + for (var i = 0; i < queue.length; i++) { + // $FlowFixMe[incompatible-use] found when upgrading Flow + var callback = queue[i]; - case REACT_MEMO_TYPE: - var outerName = type.displayName || null; + try { + do { + var isSync = true; // $FlowFixMe[incompatible-type] we bail out when we get a null - if (outerName !== null) { - return outerName; + callback = callback(isSync); + } while (callback !== null); + } catch (error) { + // Collect errors so we can rethrow them at the end + if (errors === null) { + errors = [error]; + } else { + errors.push(error); } + } + } - return getComponentNameFromType(type.type) || "Memo"; + syncQueue = null; + includesLegacySyncCallbacks = false; + setCurrentUpdatePriority(previousUpdatePriority); + isFlushingSyncQueue = false; - case REACT_LAZY_TYPE: { - var lazyComponent = type; - var payload = lazyComponent._payload; - var init = lazyComponent._init; + if (errors !== null) { + if (errors.length > 1) { + if (typeof AggregateError === "function") { + // eslint-disable-next-line no-undef + throw new AggregateError(errors); + } else { + for (var _i = 1; _i < errors.length; _i++) { + scheduleCallback$1( + ImmediatePriority, + throwError.bind(null, errors[_i]) + ); + } - try { - return getComponentNameFromType(init(payload)); - } catch (x) { - return null; + var firstError = errors[0]; + throw firstError; } + } else { + var error = errors[0]; + throw error; } - - case REACT_SERVER_CONTEXT_TYPE: { - var context2 = type; - return (context2.displayName || context2._globalName) + ".Provider"; - } - - // eslint-disable-next-line no-fallthrough } } return null; } -function getWrappedName(outerType, innerType, wrapperName) { - var functionName = innerType.displayName || innerType.name || ""; - return ( - outerType.displayName || - (functionName !== "" ? wrapperName + "(" + functionName + ")" : wrapperName) - ); -} // Keep in sync with shared/getComponentNameFromType +function throwError(error) { + throw error; +} -function getContextName(type) { - return type.displayName || "Context"; +// 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; } -function getComponentNameFromFiber(fiber) { - var tag = fiber.tag, - type = fiber.type; +var contextStackCursor = createCursor(null); +var contextFiberStackCursor = createCursor(null); +var rootInstanceStackCursor = createCursor(null); - switch (tag) { - case CacheComponent: - return "Cache"; +function requiredContext(c) { + { + if (c === null) { + error( + "Expected host context to exist. This error is likely caused by a bug " + + "in React. Please file an issue." + ); + } + } - case ContextConsumer: - var context = type; - return getContextName(context) + ".Consumer"; + return c; +} - case ContextProvider: - var provider = type; - return getContextName(provider._context) + ".Provider"; +function getRootHostContainer() { + var rootInstance = requiredContext(rootInstanceStackCursor.current); + return rootInstance; +} - case DehydratedFragment: - return "DehydratedFragment"; +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. - case ForwardRef: - return getWrappedName(type, type.render, "ForwardRef"); + 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. - case Fragment: - return "Fragment"; + push(contextStackCursor, null, fiber); + var nextRootContext = getRootHostContext(); // Now that we know this function doesn't throw, replace it. - case HostHoistable: - case HostSingleton: - case HostComponent: - // Host component type is the display name (e.g. "div", "View") - return type; + pop(contextStackCursor, fiber); + push(contextStackCursor, nextRootContext, fiber); +} - case HostPortal: - return "Portal"; +function popHostContainer(fiber) { + pop(contextStackCursor, fiber); + pop(contextFiberStackCursor, fiber); + pop(rootInstanceStackCursor, fiber); +} - case HostRoot: - return "Root"; +function getHostContext() { + var context = requiredContext(contextStackCursor.current); + return context; +} - case HostText: - return "Text"; +function pushHostContext(fiber) { + var context = requiredContext(contextStackCursor.current); + var nextContext = getChildHostContext(context, fiber.type); // Don't push this Fiber's context unless it's unique. - case LazyComponent: - // Name comes from the type in this case; we don't have a tag. - return getComponentNameFromType(type); + if (context === nextContext) { + return; + } // Track the context and the Fiber that provided it. + // This enables us to pop only Fibers that provide unique contexts. - case Mode: - if (type === REACT_STRICT_MODE_TYPE) { - // Don't be less specific than shared/getComponentNameFromType - return "StrictMode"; - } + push(contextFiberStackCursor, fiber, fiber); + push(contextStackCursor, nextContext, fiber); +} - return "Mode"; +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; + } - case OffscreenComponent: - return "Offscreen"; + pop(contextStackCursor, fiber); + pop(contextFiberStackCursor, fiber); +} - 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; - } +var isHydrating = false; // This flag allows for warning supression when we expect there to be mismatches +// due to earlier mismatches or a suspended fiber. - if (typeof type === "string") { - return type; - } +var didSuspendOrErrorDEV = false; // Hydration errors that were thrown inside this boundary - break; +var hydrationErrors = null; +function didSuspendOrErrorWhileHydratingDEV() { + { + return didSuspendOrErrorDEV; + } +} - case LegacyHiddenComponent: { - return "LegacyHidden"; - } +function prepareToHydrateHostInstance(fiber, hostContext) { + { + throw new Error( + "Expected prepareToHydrateHostInstance() to never be called. " + + "This error is likely caused by a bug in React. Please file an issue." + ); } +} - return null; +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 ReactCurrentOwner$3 = ReactSharedInternals.ReactCurrentOwner; -function getNearestMountedFiber(fiber) { - var node = fiber; - var nearestMounted = fiber; +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 (!fiber.alternate) { - // If there is no alternate, this might be a new tree that isn't inserted - // yet. If it is, then it will have a pending insertion effect on it. - var nextNode = node; +function popHydrationState(fiber) { + { + return false; + } +} - do { - node = nextNode; +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 ((node.flags & (Placement | Hydrating)) !== NoFlags$1) { - // This is an insertion or in-progress hydration. The nearest possible - // mounted fiber is the parent but we need to continue to figure out - // if that one is still mounted. - nearestMounted = node.return; - } // $FlowFixMe[incompatible-type] we bail out when we get a null +function getIsHydrating() { + return isHydrating; +} - nextNode = node.return; - } while (nextNode); +function queueHydrationError(error) { + if (hydrationErrors === null) { + hydrationErrors = [error]; } else { - while (node.return) { - node = node.return; - } + hydrationErrors.push(error); } +} - 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. +// we wait until the current render is over (either finished or interrupted) +// before adding it to the fiber/hook queue. Push to this array so we can +// access the queue, fiber, update, et al later. - return null; -} -function isFiberMounted(fiber) { - return getNearestMountedFiber(fiber) === fiber; -} -function isMounted(component) { - { - var owner = ReactCurrentOwner$3.current; +var concurrentQueues = []; +var concurrentQueuesIndex = 0; +var concurrentlyUpdatedLanes = NoLanes; +function finishQueueingConcurrentUpdates() { + var endIndex = concurrentQueuesIndex; + concurrentQueuesIndex = 0; + concurrentlyUpdatedLanes = NoLanes; + var i = 0; - if (owner !== null && owner.tag === ClassComponent) { - var ownerFiber = owner; - var instance = ownerFiber.stateNode; + while (i < endIndex) { + var fiber = concurrentQueues[i]; + concurrentQueues[i++] = null; + var queue = concurrentQueues[i]; + concurrentQueues[i++] = null; + var update = concurrentQueues[i]; + concurrentQueues[i++] = null; + var lane = concurrentQueues[i]; + concurrentQueues[i++] = null; - if (!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 (queue !== null && update !== null) { + var pending = queue.pending; + + if (pending === null) { + // This is the first update. Create a circular list. + update.next = update; + } else { + update.next = pending.next; + pending.next = update; } - instance._warnedAboutRefsInRender = true; + queue.pending = update; + } + + if (lane !== NoLane) { + markUpdateLaneFromFiberToRoot(fiber, update, lane); } } +} +function getConcurrentlyUpdatedLanes() { + return concurrentlyUpdatedLanes; +} - var fiber = get(component); +function enqueueUpdate$1(fiber, queue, update, lane) { + // Don't update the `childLanes` on the return path yet. If we already in + // the middle of rendering, wait until after it has completed. + concurrentQueues[concurrentQueuesIndex++] = fiber; + concurrentQueues[concurrentQueuesIndex++] = queue; + concurrentQueues[concurrentQueuesIndex++] = update; + concurrentQueues[concurrentQueuesIndex++] = lane; + concurrentlyUpdatedLanes = mergeLanes(concurrentlyUpdatedLanes, lane); // The fiber's `lane` field is used in some places to check if any work is + // scheduled, to perform an eager bailout, so we need to update it immediately. + // TODO: We should probably move this to the "shared" queue instead. - if (!fiber) { - return false; + fiber.lanes = mergeLanes(fiber.lanes, lane); + var alternate = fiber.alternate; + + if (alternate !== null) { + alternate.lanes = mergeLanes(alternate.lanes, lane); } +} - return getNearestMountedFiber(fiber) === fiber; +function enqueueConcurrentHookUpdate(fiber, queue, update, lane) { + var concurrentQueue = queue; + var concurrentUpdate = update; + enqueueUpdate$1(fiber, concurrentQueue, concurrentUpdate, lane); + return getRootForUpdatedFiber(fiber); } +function enqueueConcurrentHookUpdateAndEagerlyBailout(fiber, queue, update) { + // This function is used to queue an update that doesn't need a rerender. The + // only reason we queue it is in case there's a subsequent higher priority + // update that causes it to be rebased. + var lane = NoLane; + var concurrentQueue = queue; + var concurrentUpdate = update; + enqueueUpdate$1(fiber, concurrentQueue, concurrentUpdate, lane); // Usually we can rely on the upcoming render phase to process the concurrent + // queue. However, since this is a bail out, we're not scheduling any work + // here. So the update we just queued will leak until something else happens + // to schedule work (if ever). + // + // Check if we're currently in the middle of rendering a tree, and if not, + // process the queue immediately to prevent a leak. -function assertIsMounted(fiber) { - if (getNearestMountedFiber(fiber) !== fiber) { - throw new Error("Unable to find node on an unmounted component."); + var isConcurrentlyRendering = getWorkInProgressRoot() !== null; + + if (!isConcurrentlyRendering) { + finishQueueingConcurrentUpdates(); } } +function enqueueConcurrentClassUpdate(fiber, queue, update, lane) { + var concurrentQueue = queue; + var concurrentUpdate = update; + enqueueUpdate$1(fiber, concurrentQueue, concurrentUpdate, lane); + return getRootForUpdatedFiber(fiber); +} +function enqueueConcurrentRenderForLane(fiber, lane) { + enqueueUpdate$1(fiber, null, null, lane); + return getRootForUpdatedFiber(fiber); +} // Calling this function outside this module should only be done for backwards +// compatibility and should always be accompanied by a warning. -function 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); +function unsafe_markUpdateLaneFromFiberToRoot(sourceFiber, lane) { + // NOTE: For Hyrum's Law reasons, if an infinite update loop is detected, it + // should throw before `markUpdateLaneFromFiberToRoot` is called. But this is + // undefined behavior and we can change it if we need to; it just so happens + // that, at the time of this writing, there's an internal product test that + // happens to rely on this. + var root = getRootForUpdatedFiber(sourceFiber); + markUpdateLaneFromFiberToRoot(sourceFiber, null, lane); + return root; +} - if (nearestMounted === null) { - throw new Error("Unable to find node on an unmounted component."); - } +function markUpdateLaneFromFiberToRoot(sourceFiber, update, lane) { + // Update the source fiber's lanes + sourceFiber.lanes = mergeLanes(sourceFiber.lanes, lane); + var alternate = sourceFiber.alternate; - if (nearestMounted !== fiber) { - return null; - } + if (alternate !== null) { + alternate.lanes = mergeLanes(alternate.lanes, lane); + } // Walk the parent path to the root and update the child lanes. - 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; - } + var isHidden = false; + var parent = sourceFiber.return; + var node = sourceFiber; - 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. + while (parent !== null) { + parent.childLanes = mergeLanes(parent.childLanes, lane); + alternate = parent.alternate; - throw new Error("Unable to find node on an unmounted component."); + if (alternate !== null) { + alternate.childLanes = mergeLanes(alternate.childLanes, lane); } - 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. + if (parent.tag === OffscreenComponent) { + // Check if this offscreen boundary is currently hidden. // - // 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; - } + // The instance may be null if the Offscreen parent was unmounted. Usually + // the parent wouldn't be reachable in that case because we disconnect + // fibers from the tree when they are deleted. However, there's a weird + // edge case where setState is called on a fiber that was interrupted + // before it ever mounted. Because it never mounts, it also never gets + // deleted. Because it never gets deleted, its return pointer never gets + // disconnected. Which means it may be attached to a deleted Offscreen + // parent node. (This discovery suggests it may be better for memory usage + // if we don't attach the `return` pointer until the commit phase, though + // in order to do that we'd need some other way to track the return + // pointer during the initial render, like on the stack.) + // + // This case is always accompanied by a warning, but we still need to + // account for it. (There may be other cases that we haven't discovered, + // too.) + var offscreenInstance = parent.stateNode; - if (!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 ( + offscreenInstance !== null && + !(offscreenInstance._visibility & OffscreenVisible) + ) { + isHidden = true; } } - 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."); + node = parent; + parent = parent.return; } - 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. - var tag = node.tag; - - if ( - tag === HostComponent || - tag === HostHoistable || - tag === HostSingleton || - tag === HostText - ) { - return node; + if (isHidden && update !== null && node.tag === HostRoot) { + var root = node.stateNode; + markHiddenUpdate(root, update, lane); } +} - var child = node.child; - - while (child !== null) { - var match = findCurrentHostFiberImpl(child); +function getRootForUpdatedFiber(sourceFiber) { + // TODO: We will detect and infinite update loop and throw even if this fiber + // has already unmounted. This isn't really necessary but it happens to be the + // current behavior we've used for several release cycles. Consider not + // performing this check if the updated fiber already unmounted, since it's + // not possible for that to cause an infinite update loop. + throwIfInfiniteUpdateLoopDetected(); // When a setState happens, we must ensure the root is scheduled. Because + // update queues do not have a backpointer to the root, the only way to do + // this currently is to walk up the return path. This used to not be a big + // deal because we would have to walk up the return path to set + // the `childLanes`, anyway, but now those two traversals happen at + // different times. + // TODO: Consider adding a `root` backpointer on the update queue. - if (match !== null) { - return match; - } + detectUpdateOnUnmountedFiber(sourceFiber, sourceFiber); + var node = sourceFiber; + var parent = node.return; - child = child.sibling; + while (parent !== null) { + detectUpdateOnUnmountedFiber(sourceFiber, node); + node = parent; + parent = node.return; } - return null; + return node.tag === HostRoot ? node.stateNode : null; } -function describeBuiltInComponentFrame(name, source, ownerFn) { +function detectUpdateOnUnmountedFiber(sourceFiber, parent) { { - var ownerName = null; + var alternate = parent.alternate; - if (ownerFn) { - ownerName = ownerFn.displayName || ownerFn.name || null; + if ( + alternate === null && + (parent.flags & (Placement | Hydrating)) !== NoFlags$1 + ) { + warnAboutUpdateOnNotYetMountedFiberInDEV(sourceFiber); } - - return describeComponentFrame(name, source, ownerName); } } -{ - var PossiblyWeakMap$1 = typeof WeakMap === "function" ? WeakMap : Map; - new PossiblyWeakMap$1(); -} -var BEFORE_SLASH_RE = /^(.*)[\\\/]/; +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 describeComponentFrame(name, source, ownerName) { - var sourceInfo = ""; +var hasForceUpdate = false; +var didWarnUpdateInsideUpdate; +var currentlyProcessingQueue; - 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". +{ + didWarnUpdateInsideUpdate = false; + currentlyProcessingQueue = null; +} - if (/^index\./.test(fileName)) { - var match = path.match(BEFORE_SLASH_RE); - - if (match) { - var pathBeforeSlash = match[1]; - - if (pathBeforeSlash) { - var folderName = pathBeforeSlash.replace(BEFORE_SLASH_RE, ""); - fileName = folderName + "/" + fileName; - } - } - } +function initializeUpdateQueue(fiber) { + var queue = { + baseState: fiber.memoizedState, + firstBaseUpdate: null, + lastBaseUpdate: null, + shared: { + pending: null, + lanes: NoLanes, + hiddenCallbacks: null + }, + callbacks: null + }; + fiber.updateQueue = queue; +} +function cloneUpdateQueue(current, workInProgress) { + // Clone the update queue from current. Unless it's already a clone. + var queue = workInProgress.updateQueue; + var currentQueue = current.updateQueue; - sourceInfo = " (at " + fileName + ":" + source.lineNumber + ")"; - } else if (ownerName) { - sourceInfo = " (created by " + ownerName + ")"; + if (queue === currentQueue) { + var clone = { + baseState: currentQueue.baseState, + firstBaseUpdate: currentQueue.firstBaseUpdate, + lastBaseUpdate: currentQueue.lastBaseUpdate, + shared: currentQueue.shared, + callbacks: null + }; + workInProgress.updateQueue = clone; } - - return "\n in " + (name || "Unknown") + sourceInfo; } +function createUpdate(lane) { + var update = { + lane: lane, + tag: UpdateState, + payload: null, + callback: null, + next: null + }; + return update; +} +function enqueueUpdate(fiber, update, lane) { + var updateQueue = fiber.updateQueue; -function describeClassComponentFrame(ctor, source, ownerFn) { - { - return describeFunctionComponentFrame(ctor, source, ownerFn); + if (updateQueue === null) { + // Only occurs if the fiber has been unmounted. + return null; } -} -function describeFunctionComponentFrame(fn, source, ownerFn) { + + var sharedQueue = updateQueue.shared; + { - if (!fn) { - return ""; + if ( + currentlyProcessingQueue === sharedQueue && + !didWarnUpdateInsideUpdate + ) { + var componentName = getComponentNameFromFiber(fiber); + + error( + "An update (setState, replaceState, or forceUpdate) was scheduled " + + "from inside an update function. Update functions should be pure, " + + "with zero side-effects. Consider using componentDidUpdate or a " + + "callback.\n\nPlease update the following component: %s", + componentName + ); + + didWarnUpdateInsideUpdate = true; } + } - var name = fn.displayName || fn.name || null; - var ownerName = null; + if (isUnsafeClassRenderPhaseUpdate()) { + // This is an unsafe render phase update. Add directly to the update + // queue so we can process it immediately during the current render. + var pending = sharedQueue.pending; - if (ownerFn) { - ownerName = ownerFn.displayName || ownerFn.name || null; + if (pending === null) { + // This is the first update. Create a circular list. + update.next = update; + } else { + update.next = pending.next; + pending.next = update; } - return describeComponentFrame(name, source, ownerName); + 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). + + return unsafe_markUpdateLaneFromFiberToRoot(fiber, lane); + } else { + return enqueueConcurrentClassUpdate(fiber, sharedQueue, update, lane); } } +function entangleTransitions(root, fiber, lane) { + var updateQueue = fiber.updateQueue; -function describeUnknownElementTypeFrameInDEV(type, source, ownerFn) { - if (type == null) { - return ""; + if (updateQueue === null) { + // Only occurs if the fiber has been unmounted. + return; } - if (typeof type === "function") { - { - return describeFunctionComponentFrame(type, source, ownerFn); - } - } + var sharedQueue = updateQueue.shared; - if (typeof type === "string") { - return describeBuiltInComponentFrame(type, source, ownerFn); - } + 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. - switch (type) { - case REACT_SUSPENSE_TYPE: - return describeBuiltInComponentFrame("Suspense", source, ownerFn); + queueLanes = intersectLanes(queueLanes, root.pendingLanes); // Entangle the new transition lane with the other transition lanes. - case REACT_SUSPENSE_LIST_TYPE: - return describeBuiltInComponentFrame("SuspenseList", source, ownerFn); + var newQueueLanes = mergeLanes(queueLanes, lane); + sharedQueue.lanes = newQueueLanes; // Even if queue.lanes already include lane, we don't know for certain if + // the lane finished since the last time we entangled it. So we need to + // entangle it again, just to be sure. + + markRootEntangled(root, newQueueLanes); } +} +function enqueueCapturedUpdate(workInProgress, capturedUpdate) { + // Captured updates are updates that are thrown by a child during the render + // phase. They should be discarded if the render is aborted. Therefore, + // we should only put them on the work-in-progress queue, not the current one. + var queue = workInProgress.updateQueue; // Check if the work-in-progress queue is a clone. - if (typeof type === "object") { - switch (type.$$typeof) { - case REACT_FORWARD_REF_TYPE: - return describeFunctionComponentFrame(type.render, source, ownerFn); + var current = workInProgress.alternate; - case REACT_MEMO_TYPE: - // Memo may contain any component type so we recursively resolve it. - return describeUnknownElementTypeFrameInDEV(type.type, source, ownerFn); + if (current !== null) { + var currentQueue = current.updateQueue; - case REACT_LAZY_TYPE: { - var lazyComponent = type; - var payload = lazyComponent._payload; - var init = lazyComponent._init; + 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; - try { - // Lazy may contain any component type so we recursively resolve it. - return describeUnknownElementTypeFrameInDEV( - init(payload), - source, - ownerFn - ); - } catch (x) {} - } - } - } + if (firstBaseUpdate !== null) { + // Loop through the updates and clone them. + var update = firstBaseUpdate; - return ""; -} + do { + var clone = { + lane: update.lane, + tag: update.tag, + payload: update.payload, + // When this update is rebased, we should not fire its + // callback again. + callback: null, + next: null + }; -// $FlowFixMe[method-unbinding] -var hasOwnProperty = Object.prototype.hasOwnProperty; + if (newLast === null) { + newFirst = newLast = clone; + } else { + newLast.next = clone; + newLast = clone; + } // $FlowFixMe[incompatible-type] we bail out when we get a null -var loggedTypeFailures = {}; -var ReactDebugCurrentFrame$1 = ReactSharedInternals.ReactDebugCurrentFrame; + update = update.next; + } while (update !== null); // Append the captured update the end of the cloned list. -function setCurrentlyValidatingElement(element) { - { - if (element) { - var owner = element._owner; - var stack = describeUnknownElementTypeFrameInDEV( - element.type, - element._source, - owner ? owner.type : null - ); - ReactDebugCurrentFrame$1.setExtraStackFrame(stack); - } else { - ReactDebugCurrentFrame$1.setExtraStackFrame(null); + if (newLast === null) { + newFirst = newLast = capturedUpdate; + } else { + newLast.next = capturedUpdate; + newLast = capturedUpdate; + } + } else { + // There are no base updates. + newFirst = newLast = capturedUpdate; + } + + queue = { + baseState: currentQueue.baseState, + firstBaseUpdate: newFirst, + lastBaseUpdate: newLast, + shared: currentQueue.shared, + callbacks: currentQueue.callbacks + }; + workInProgress.updateQueue = queue; + return; } + } // Append the update to the end of the list. + + var lastBaseUpdate = queue.lastBaseUpdate; + + if (lastBaseUpdate === null) { + queue.firstBaseUpdate = capturedUpdate; + } else { + lastBaseUpdate.next = capturedUpdate; } -} -function checkPropTypes(typeSpecs, values, location, componentName, element) { - { - // $FlowFixMe This is okay but Flow doesn't know it. - var has = Function.call.bind(hasOwnProperty); + queue.lastBaseUpdate = capturedUpdate; +} - for (var typeSpecName in typeSpecs) { - if (has(typeSpecs, typeSpecName)) { - var error$1 = void 0; // Prop type validation may throw. In case they do, we don't want to - // fail the render phase where it didn't fail before. So we log it. - // After these have been cleaned up, we'll let them throw. - - try { - // This is intentionally an invariant that gets caught. It's the same - // behavior as without this statement except with a better message. - if (typeof typeSpecs[typeSpecName] !== "function") { - // eslint-disable-next-line react-internal/prod-error-codes - var err = Error( - (componentName || "React class") + - ": " + - location + - " type `" + - typeSpecName + - "` is invalid; " + - "it must be a function, usually from the `prop-types` package, but received `" + - typeof typeSpecs[typeSpecName] + - "`." + - "This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`." - ); - err.name = "Invariant Violation"; - throw err; - } +function getStateFromUpdate( + workInProgress, + queue, + update, + prevState, + nextProps, + instance +) { + switch (update.tag) { + case ReplaceState: { + var payload = update.payload; - 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 (typeof payload === "function") { + // Updater function + { + enterDisallowedContextReadInDEV(); } - if (error$1 && !(error$1 instanceof Error)) { - setCurrentlyValidatingElement(element); + var nextState = payload.call(instance, prevState, nextProps); - 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 (workInProgress.mode & StrictLegacyMode) { + setIsStrictModeForDevtools(true); - setCurrentlyValidatingElement(null); + try { + payload.call(instance, prevState, nextProps); + } finally { + setIsStrictModeForDevtools(false); + } + } + + exitDisallowedContextReadInDEV(); } - if ( - error$1 instanceof Error && - !(error$1.message in loggedTypeFailures) - ) { - // Only monitor this failure once because there tends to be a lot of the - // same error. - loggedTypeFailures[error$1.message] = true; - setCurrentlyValidatingElement(element); + return nextState; + } // State object - error("Failed %s type: %s", location, error$1.message); + return payload; + } - setCurrentlyValidatingElement(null); - } - } + case CaptureUpdate: { + workInProgress.flags = + (workInProgress.flags & ~ShouldCapture) | DidCapture; } - } -} + // Intentional fallthrough -var valueStack = []; -var fiberStack; + case UpdateState: { + var _payload = update.payload; + var partialState; -{ - fiberStack = []; -} + if (typeof _payload === "function") { + // Updater function + { + enterDisallowedContextReadInDEV(); + } -var index = -1; + partialState = _payload.call(instance, prevState, nextProps); -function createCursor(defaultValue) { - return { - current: defaultValue - }; -} + { + if (workInProgress.mode & StrictLegacyMode) { + setIsStrictModeForDevtools(true); -function pop(cursor, fiber) { - if (index < 0) { - { - error("Unexpected pop."); - } + try { + _payload.call(instance, prevState, nextProps); + } finally { + setIsStrictModeForDevtools(false); + } + } - return; - } + exitDisallowedContextReadInDEV(); + } + } else { + // Partial state object + partialState = _payload; + } - { - if (fiber !== fiberStack[index]) { - error("Unexpected Fiber popped."); - } - } + if (partialState === null || partialState === undefined) { + // Null and undefined are treated as no-ops. + return prevState; + } // Merge the partial state and the previous state. - cursor.current = valueStack[index]; - valueStack[index] = null; + return assign({}, prevState, partialState); + } - { - fiberStack[index] = null; + case ForceUpdate: { + hasForceUpdate = true; + return prevState; + } } - index--; + return prevState; } -function push(cursor, value, fiber) { - index++; - valueStack[index] = cursor.current; +function processUpdateQueue(workInProgress, props, instance, renderLanes) { + // This is always non-null on a ClassComponent or HostRoot + var queue = workInProgress.updateQueue; + hasForceUpdate = false; { - fiberStack[index] = fiber; + currentlyProcessingQueue = queue.shared; } - cursor.current = value; -} + var firstBaseUpdate = queue.firstBaseUpdate; + var lastBaseUpdate = queue.lastBaseUpdate; // Check if there are pending updates. If so, transfer them to the base queue. -var warnedAboutMissingGetChildContext; + var pendingQueue = queue.shared.pending; -{ - warnedAboutMissingGetChildContext = {}; -} + if (pendingQueue !== null) { + queue.shared.pending = null; // The pending queue is circular. Disconnect the pointer between first + // and last so that it's non-circular. -var emptyContextObject = {}; + var lastPendingUpdate = pendingQueue; + var firstPendingUpdate = lastPendingUpdate.next; + lastPendingUpdate.next = null; // Append pending updates to base queue -{ - Object.freeze(emptyContextObject); -} // A cursor to the current merged context object on the stack. + if (lastBaseUpdate === null) { + firstBaseUpdate = firstPendingUpdate; + } else { + lastBaseUpdate.next = firstPendingUpdate; + } -var contextStackCursor$1 = createCursor(emptyContextObject); // A cursor to a boolean indicating whether the context has changed. + lastBaseUpdate = lastPendingUpdate; // If there's a current queue, and it's different from the base queue, then + // we need to transfer the updates to that queue, too. Because the base + // queue is a singly-linked list with no cycles, we can append to both + // lists and take advantage of structural sharing. + // TODO: Pass `current` as argument -var 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 current = workInProgress.alternate; -var previousContext = emptyContextObject; + if (current !== null) { + // This is always non-null on a ClassComponent or HostRoot + var currentQueue = current.updateQueue; + var currentLastBaseUpdate = currentQueue.lastBaseUpdate; -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 (currentLastBaseUpdate !== lastBaseUpdate) { + if (currentLastBaseUpdate === null) { + currentQueue.firstBaseUpdate = firstPendingUpdate; + } else { + currentLastBaseUpdate.next = firstPendingUpdate; + } + + currentQueue.lastBaseUpdate = lastPendingUpdate; + } } + } // These values may change as we process the queue. - return contextStackCursor$1.current; - } -} + 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 cacheContext(workInProgress, unmaskedContext, maskedContext) { - { - var instance = workInProgress.stateNode; - instance.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext; - instance.__reactInternalMemoizedMaskedChildContext = maskedContext; - } -} + var newLanes = NoLanes; + var newBaseState = null; + var newFirstBaseUpdate = null; + var newLastBaseUpdate = null; + var update = firstBaseUpdate; -function getMaskedContext(workInProgress, unmaskedContext) { - { - var type = workInProgress.type; - var contextTypes = type.contextTypes; + do { + // An extra OffscreenLane bit is added to updates that were made to + // a hidden tree, so that we can distinguish them from updates that were + // already there when the tree was hidden. + var updateLane = removeLanes(update.lane, OffscreenLane); + var isHiddenUpdate = updateLane !== update.lane; // Check if this update was made while the tree was hidden. If so, then + // it's not a "base" update and we should disregard the extra base lanes + // that were added to renderLanes when we entered the Offscreen tree. - 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 shouldSkipUpdate = isHiddenUpdate + ? !isSubsetOfLanes(getWorkInProgressRootRenderLanes(), updateLane) + : !isSubsetOfLanes(renderLanes, updateLane); - var instance = workInProgress.stateNode; + if (shouldSkipUpdate) { + // Priority is insufficient. Skip this update. If this is the first + // skipped update, the previous update/state is the new base + // update/state. + var clone = { + lane: updateLane, + tag: update.tag, + payload: update.payload, + callback: update.callback, + next: null + }; - if ( - instance && - instance.__reactInternalMemoizedUnmaskedChildContext === unmaskedContext - ) { - return instance.__reactInternalMemoizedMaskedChildContext; - } + if (newLastBaseUpdate === null) { + newFirstBaseUpdate = newLastBaseUpdate = clone; + newBaseState = newState; + } else { + newLastBaseUpdate = newLastBaseUpdate.next = clone; + } // Update the remaining priority in the queue. - var context = {}; + newLanes = mergeLanes(newLanes, updateLane); + } else { + // This update does have sufficient priority. + if (newLastBaseUpdate !== null) { + var _clone = { + // This update is going to be committed so we never want uncommit + // it. Using NoLane works because 0 is a subset of all bitmasks, so + // this will never be skipped by the check above. + lane: NoLane, + tag: update.tag, + payload: update.payload, + // When this update is rebased, we should not fire its + // callback again. + callback: null, + next: null + }; + newLastBaseUpdate = newLastBaseUpdate.next = _clone; + } // Process this update. - for (var key in contextTypes) { - context[key] = unmaskedContext[key]; - } + newState = getStateFromUpdate( + workInProgress, + queue, + update, + newState, + props, + instance + ); + var callback = update.callback; - { - 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 (callback !== null) { + workInProgress.flags |= Callback; - if (instance) { - cacheContext(workInProgress, unmaskedContext, context); + if (isHiddenUpdate) { + workInProgress.flags |= Visibility; + } + + var callbacks = queue.callbacks; + + if (callbacks === null) { + queue.callbacks = [callback]; + } else { + callbacks.push(callback); + } + } + } // $FlowFixMe[incompatible-type] we bail out when we get a null + + update = update.next; + + if (update === null) { + pendingQueue = queue.shared.pending; + + if (pendingQueue === null) { + break; + } else { + // An update was scheduled from inside a reducer. Add the new + // pending updates to the end of the list and keep processing. + var _lastPendingUpdate = pendingQueue; // Intentionally unsound. Pending updates form a circular list, but we + // unravel them when transferring them to the base queue. + + var _firstPendingUpdate = _lastPendingUpdate.next; + _lastPendingUpdate.next = null; + update = _firstPendingUpdate; + queue.lastBaseUpdate = _lastPendingUpdate; + queue.shared.pending = null; + } + } + } while (true); + + if (newLastBaseUpdate === null) { + newBaseState = newState; } - return context; - } -} + queue.baseState = newBaseState; + queue.firstBaseUpdate = newFirstBaseUpdate; + queue.lastBaseUpdate = newLastBaseUpdate; -function hasContextChanged() { - { - return didPerformWorkStackCursor.current; + 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; } -} -function isContextProvider(type) { { - var childContextTypes = type.childContextTypes; - return childContextTypes !== null && childContextTypes !== undefined; + currentlyProcessingQueue = null; } } -function popContext(fiber) { - { - pop(didPerformWorkStackCursor, fiber); - pop(contextStackCursor$1, fiber); +function callCallback(callback, context) { + if (typeof callback !== "function") { + throw new Error( + "Invalid argument passed as callback. Expected a function. Instead " + + ("received: " + callback) + ); } + + callback.call(context); } -function popTopLevelContextObject(fiber) { - { - pop(didPerformWorkStackCursor, fiber); - pop(contextStackCursor$1, fiber); - } +function resetHasForceUpdateBeforeProcessing() { + hasForceUpdate = false; +} +function checkHasForceUpdateAfterProcessing() { + return hasForceUpdate; } +function deferHiddenCallbacks(updateQueue) { + // When an update finishes on a hidden component, its callback should not + // be fired until/unless the component is made visible again. Stash the + // callback on the shared queue object so it can be fired later. + var newHiddenCallbacks = updateQueue.callbacks; -function pushTopLevelContextObject(fiber, context, didChange) { - { - if (contextStackCursor$1.current !== emptyContextObject) { - throw new Error( - "Unexpected context found on stack. " + - "This error is likely caused by a bug in React. Please file an issue." - ); - } + if (newHiddenCallbacks !== null) { + var existingHiddenCallbacks = updateQueue.shared.hiddenCallbacks; - push(contextStackCursor$1, context, fiber); - push(didPerformWorkStackCursor, didChange, fiber); + if (existingHiddenCallbacks === null) { + updateQueue.shared.hiddenCallbacks = newHiddenCallbacks; + } else { + updateQueue.shared.hiddenCallbacks = + existingHiddenCallbacks.concat(newHiddenCallbacks); + } } } +function commitHiddenCallbacks(updateQueue, context) { + // This component is switching from hidden -> visible. Commit any callbacks + // that were previously deferred. + var hiddenCallbacks = updateQueue.shared.hiddenCallbacks; -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 (hiddenCallbacks !== null) { + updateQueue.shared.hiddenCallbacks = null; - return parentContext; + for (var i = 0; i < hiddenCallbacks.length; i++) { + var callback = hiddenCallbacks[i]; + callCallback(callback, context); } + } +} +function commitCallbacks(updateQueue, context) { + var callbacks = updateQueue.callbacks; - 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 (callbacks !== null) { + updateQueue.callbacks = null; - { - var name = getComponentNameFromFiber(fiber) || "Unknown"; - checkPropTypes(childContextTypes, childContext, "child context", name); + for (var i = 0; i < callbacks.length; i++) { + var callback = callbacks[i]; + callCallback(callback, context); } - - 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. +/** + * 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. + */ - previousContext = contextStackCursor$1.current; - push(contextStackCursor$1, memoizedMergedChildContext, workInProgress); - push( - didPerformWorkStackCursor, - didPerformWorkStackCursor.current, - workInProgress - ); +function shallowEqual(objA, objB) { + if (objectIs(objA, objB)) { return true; } -} -function invalidateContextProvider(workInProgress, type, didChange) { - { - var instance = workInProgress.stateNode; + if ( + typeof objA !== "object" || + objA === null || + typeof objB !== "object" || + objB === null + ) { + return false; + } - 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." - ); - } + var keysA = Object.keys(objA); + var keysB = Object.keys(objB); - if (didChange) { - // Merge parent and own context. - // Skip this if we're not updating due to sCU. - // This avoids unnecessarily recomputing memoized values. - var mergedContext = processChildContext( - workInProgress, - type, - previousContext - ); - instance.__reactInternalMemoizedMergedChildContext = mergedContext; // Replace the old (or empty) context with the new one. - // It is important to unwind the context in the reverse order. + if (keysA.length !== keysB.length) { + return false; + } // Test for A's keys different from B. - pop(didPerformWorkStackCursor, workInProgress); - pop(contextStackCursor$1, workInProgress); // Now push the new context and mark that it has changed. + for (var i = 0; i < keysA.length; i++) { + var currentKey = keysA[i]; - push(contextStackCursor$1, mergedContext, workInProgress); - push(didPerformWorkStackCursor, didChange, workInProgress); - } else { - pop(didPerformWorkStackCursor, workInProgress); - push(didPerformWorkStackCursor, didChange, workInProgress); + if ( + !hasOwnProperty.call(objB, currentKey) || + !objectIs(objA[currentKey], objB[currentKey]) + ) { + return false; } } + + return true; } -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 describeFiber(fiber) { + var owner = fiber._debugOwner ? fiber._debugOwner.type : null; + var source = fiber._debugSource; - var node = fiber; + switch (fiber.tag) { + case HostHoistable: + case HostSingleton: + case HostComponent: + return describeBuiltInComponentFrame(fiber.type, source, owner); - do { - switch (node.tag) { - case HostRoot: - return node.stateNode.context; + case LazyComponent: + return describeBuiltInComponentFrame("Lazy", source, owner); - case ClassComponent: { - var Component = node.type; + case SuspenseComponent: + return describeBuiltInComponentFrame("Suspense", source, owner); - if (isContextProvider(Component)) { - return node.stateNode.__reactInternalMemoizedMergedChildContext; - } + case SuspenseListComponent: + return describeBuiltInComponentFrame("SuspenseList", source, owner); - break; - } - } // $FlowFixMe[incompatible-type] we bail out when we get a null + case FunctionComponent: + case IndeterminateComponent: + case SimpleMemoComponent: + return describeFunctionComponentFrame(fiber.type, source, owner); - node = node.return; - } while (node !== null); + case ForwardRef: + return describeFunctionComponentFrame(fiber.type.render, source, owner); - throw new Error( - "Found unexpected detached subtree parent. " + - "This error is likely caused by a bug in React. Please file an issue." - ); + case ClassComponent: + return describeClassComponentFrame(fiber.type, source, owner); + + default: + return ""; } } -var LegacyRoot = 0; -var ConcurrentRoot = 1; - -// We use the existence of the state object as an indicator that the component -// is hidden. -var OffscreenVisible = - /* */ - 1; -var OffscreenDetached = - /* */ - 2; -var OffscreenPassiveEffectsConnected = - /* */ - 4; -function isOffscreenManual(offscreenFiber) { - return ( - offscreenFiber.memoizedProps !== null && - offscreenFiber.memoizedProps.mode === "manual" - ); -} +function getStackByFiberInDevAndProd(workInProgress) { + try { + var info = ""; + var node = workInProgress; -/** - * 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 - ); -} + do { + info += describeFiber(node); // $FlowFixMe[incompatible-type] we bail out when we get a null -var objectIs = typeof Object.is === "function" ? Object.is : is; // $FlowFixMe[method-unbinding] + node = node.return; + } while (node); -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(); + return info; + } catch (x) { + return "\nError generating stack: " + x.message + "\n" + x.stack; } } -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); // $FlowFixMe[incompatible-use] found when upgrading Flow - for (; i < queue.length; i++) { - // $FlowFixMe[incompatible-use] found when upgrading Flow - var callback = queue[i]; - - do { - // $FlowFixMe[incompatible-type] we bail out when we get a null - callback = callback(isSync); - } while (callback !== null); - } +var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; +var current = null; +var isRendering = false; +function getCurrentFiberOwnerNameInDevOrNull() { + { + if (current === null) { + return 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 + var owner = current._debugOwner; - scheduleCallback$1(ImmediatePriority, flushSyncCallbacks); - throw error; - } finally { - setCurrentUpdatePriority(previousUpdatePriority); - isFlushingSyncQueue = false; + if (owner !== null && typeof owner !== "undefined") { + return getComponentNameFromFiber(owner); } } return null; } -// This is imported by the event replaying implementation in React DOM. It's -// in a separate file to break a circular dependency between the renderer and -// the reconciler. -function isRootDehydrated(root) { - var currentState = root.current.memoizedState; - return currentState.isDehydrated; -} - -var contextStackCursor = createCursor(null); -var contextFiberStackCursor = createCursor(null); -var rootInstanceStackCursor = createCursor(null); - -function requiredContext(c) { +function getCurrentFiberStackInDev() { { - if (c === null) { - error( - "Expected host context to exist. This error is likely caused by a bug " + - "in React. Please file an issue." - ); - } - } + 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 c; + return getStackByFiberInDevAndProd(current); + } } -function getRootHostContainer() { - var rootInstance = requiredContext(rootInstanceStackCursor.current); - return rootInstance; +function resetCurrentFiber() { + { + ReactDebugCurrentFrame.getCurrentStack = null; + current = null; + isRendering = false; + } } - -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. - - 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. - - push(contextStackCursor, null, fiber); - var nextRootContext = getRootHostContext(); // Now that we know this function doesn't throw, replace it. - - pop(contextStackCursor, fiber); - push(contextStackCursor, nextRootContext, fiber); -} - -function popHostContainer(fiber) { - pop(contextStackCursor, fiber); - pop(contextFiberStackCursor, fiber); - pop(rootInstanceStackCursor, fiber); -} - -function getHostContext() { - var context = requiredContext(contextStackCursor.current); - return context; -} - -function pushHostContext(fiber) { - var context = requiredContext(contextStackCursor.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. - - push(contextFiberStackCursor, fiber, fiber); - push(contextStackCursor, nextContext, fiber); -} - -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; - } - - pop(contextStackCursor, fiber); - pop(contextFiberStackCursor, fiber); -} - -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() { +function setCurrentFiber(fiber) { { - return didSuspendOrErrorDEV; + ReactDebugCurrentFrame.getCurrentStack = + fiber === null ? null : getCurrentFiberStackInDev; + current = fiber; + isRendering = false; } } - -function prepareToHydrateHostInstance(fiber, hostContext) { +function getCurrentFiber() { { - throw new Error( - "Expected prepareToHydrateHostInstance() to never be called. " + - "This error is likely caused by a bug in React. Please file an issue." - ); + return current; } } - -function prepareToHydrateHostTextInstance(fiber) { +function setIsRendering(rendering) { { - throw new Error( - "Expected prepareToHydrateHostTextInstance() to never be called. " + - "This error is likely caused by a bug in React. Please file an issue." - ); + isRendering = rendering; } } -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 ReactStrictModeWarnings = { + recordUnsafeLifecycleWarnings: function (fiber, instance) {}, + flushPendingUnsafeLifecycleWarnings: function () {}, + recordLegacyContextWarning: function (fiber, instance) {}, + flushLegacyContextWarning: function () {}, + discardPendingWarnings: function () {} +}; -function popHydrationState(fiber) { - { - return false; - } -} +{ + var findStrictRoot = function (fiber) { + var maybeStrictRoot = null; + var node = fiber; -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; - } -} + while (node !== null) { + if (node.mode & StrictLegacyMode) { + maybeStrictRoot = node; + } -function getIsHydrating() { - return isHydrating; -} + node = node.return; + } -function queueHydrationError(error) { - if (hydrationErrors === null) { - hydrationErrors = [error]; - } else { - hydrationErrors.push(error); - } -} + return maybeStrictRoot; + }; -// we wait until the current render is over (either finished or interrupted) -// before adding it to the fiber/hook queue. Push to this array so we can -// access the queue, fiber, update, et al later. + var setToSortedString = function (set) { + var array = []; + set.forEach(function (value) { + array.push(value); + }); + return array.sort().join(", "); + }; -var concurrentQueues = []; -var concurrentQueuesIndex = 0; -var concurrentlyUpdatedLanes = NoLanes; -function finishQueueingConcurrentUpdates() { - var endIndex = concurrentQueuesIndex; - concurrentQueuesIndex = 0; - concurrentlyUpdatedLanes = NoLanes; - var i = 0; + var pendingComponentWillMountWarnings = []; + var pendingUNSAFE_ComponentWillMountWarnings = []; + var pendingComponentWillReceivePropsWarnings = []; + var pendingUNSAFE_ComponentWillReceivePropsWarnings = []; + var pendingComponentWillUpdateWarnings = []; + var pendingUNSAFE_ComponentWillUpdateWarnings = []; // Tracks components we have already warned about. - while (i < endIndex) { - var fiber = concurrentQueues[i]; - concurrentQueues[i++] = null; - var queue = concurrentQueues[i]; - concurrentQueues[i++] = null; - var update = concurrentQueues[i]; - concurrentQueues[i++] = null; - var lane = concurrentQueues[i]; - concurrentQueues[i++] = null; + var didWarnAboutUnsafeLifecycles = new Set(); - if (queue !== null && update !== null) { - var pending = queue.pending; + ReactStrictModeWarnings.recordUnsafeLifecycleWarnings = function ( + fiber, + instance + ) { + // Dedupe strategy: Warn once per component. + if (didWarnAboutUnsafeLifecycles.has(fiber.type)) { + return; + } - 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.componentWillMount === "function" && // Don't warn about react-lifecycles-compat polyfilled components. + instance.componentWillMount.__suppressDeprecationWarning !== true + ) { + pendingComponentWillMountWarnings.push(fiber); + } - queue.pending = update; + if ( + fiber.mode & StrictLegacyMode && + typeof instance.UNSAFE_componentWillMount === "function" + ) { + pendingUNSAFE_ComponentWillMountWarnings.push(fiber); } - if (lane !== NoLane) { - markUpdateLaneFromFiberToRoot(fiber, update, lane); + if ( + typeof instance.componentWillReceiveProps === "function" && + instance.componentWillReceiveProps.__suppressDeprecationWarning !== true + ) { + pendingComponentWillReceivePropsWarnings.push(fiber); } - } -} -function getConcurrentlyUpdatedLanes() { - return concurrentlyUpdatedLanes; -} -function enqueueUpdate$1(fiber, queue, update, lane) { - // Don't update the `childLanes` on the return path yet. If we already in - // the middle of rendering, wait until after it has completed. - concurrentQueues[concurrentQueuesIndex++] = fiber; - concurrentQueues[concurrentQueuesIndex++] = queue; - concurrentQueues[concurrentQueuesIndex++] = update; - concurrentQueues[concurrentQueuesIndex++] = lane; - concurrentlyUpdatedLanes = mergeLanes(concurrentlyUpdatedLanes, lane); // The fiber's `lane` field is used in some places to check if any work is - // scheduled, to perform an eager bailout, so we need to update it immediately. - // TODO: We should probably move this to the "shared" queue instead. + if ( + fiber.mode & StrictLegacyMode && + typeof instance.UNSAFE_componentWillReceiveProps === "function" + ) { + pendingUNSAFE_ComponentWillReceivePropsWarnings.push(fiber); + } - fiber.lanes = mergeLanes(fiber.lanes, lane); - var alternate = fiber.alternate; + if ( + typeof instance.componentWillUpdate === "function" && + instance.componentWillUpdate.__suppressDeprecationWarning !== true + ) { + pendingComponentWillUpdateWarnings.push(fiber); + } - if (alternate !== null) { - alternate.lanes = mergeLanes(alternate.lanes, lane); - } -} + if ( + fiber.mode & StrictLegacyMode && + typeof instance.UNSAFE_componentWillUpdate === "function" + ) { + pendingUNSAFE_ComponentWillUpdateWarnings.push(fiber); + } + }; -function enqueueConcurrentHookUpdate(fiber, queue, update, lane) { - var concurrentQueue = queue; - var concurrentUpdate = update; - enqueueUpdate$1(fiber, concurrentQueue, concurrentUpdate, lane); - return getRootForUpdatedFiber(fiber); -} -function enqueueConcurrentHookUpdateAndEagerlyBailout(fiber, queue, update) { - // This function is used to queue an update that doesn't need a rerender. The - // only reason we queue it is in case there's a subsequent higher priority - // update that causes it to be rebased. - var lane = NoLane; - var concurrentQueue = queue; - var concurrentUpdate = update; - enqueueUpdate$1(fiber, concurrentQueue, concurrentUpdate, lane); // Usually we can rely on the upcoming render phase to process the concurrent - // queue. However, since this is a bail out, we're not scheduling any work - // here. So the update we just queued will leak until something else happens - // to schedule work (if ever). - // - // Check if we're currently in the middle of rendering a tree, and if not, - // process the queue immediately to prevent a leak. - - var isConcurrentlyRendering = getWorkInProgressRoot() !== null; + ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings = function () { + // We do an initial pass to gather component names + var componentWillMountUniqueNames = new Set(); - if (!isConcurrentlyRendering) { - finishQueueingConcurrentUpdates(); - } -} -function enqueueConcurrentClassUpdate(fiber, queue, update, lane) { - var concurrentQueue = queue; - var concurrentUpdate = update; - enqueueUpdate$1(fiber, concurrentQueue, concurrentUpdate, lane); - return getRootForUpdatedFiber(fiber); -} -function enqueueConcurrentRenderForLane(fiber, lane) { - enqueueUpdate$1(fiber, null, null, lane); - return getRootForUpdatedFiber(fiber); -} // Calling this function outside this module should only be done for backwards -// compatibility and should always be accompanied by a warning. + if (pendingComponentWillMountWarnings.length > 0) { + pendingComponentWillMountWarnings.forEach(function (fiber) { + componentWillMountUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingComponentWillMountWarnings = []; + } -function unsafe_markUpdateLaneFromFiberToRoot(sourceFiber, lane) { - // NOTE: For Hyrum's Law reasons, if an infinite update loop is detected, it - // should throw before `markUpdateLaneFromFiberToRoot` is called. But this is - // undefined behavior and we can change it if we need to; it just so happens - // that, at the time of this writing, there's an internal product test that - // happens to rely on this. - var root = getRootForUpdatedFiber(sourceFiber); - markUpdateLaneFromFiberToRoot(sourceFiber, null, lane); - return root; -} + var UNSAFE_componentWillMountUniqueNames = new Set(); -function markUpdateLaneFromFiberToRoot(sourceFiber, update, lane) { - // Update the source fiber's lanes - sourceFiber.lanes = mergeLanes(sourceFiber.lanes, lane); - var alternate = sourceFiber.alternate; + if (pendingUNSAFE_ComponentWillMountWarnings.length > 0) { + pendingUNSAFE_ComponentWillMountWarnings.forEach(function (fiber) { + UNSAFE_componentWillMountUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingUNSAFE_ComponentWillMountWarnings = []; + } - if (alternate !== null) { - alternate.lanes = mergeLanes(alternate.lanes, lane); - } // Walk the parent path to the root and update the child lanes. + var componentWillReceivePropsUniqueNames = new Set(); - var isHidden = false; - var parent = sourceFiber.return; - var node = sourceFiber; + if (pendingComponentWillReceivePropsWarnings.length > 0) { + pendingComponentWillReceivePropsWarnings.forEach(function (fiber) { + componentWillReceivePropsUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingComponentWillReceivePropsWarnings = []; + } - while (parent !== null) { - parent.childLanes = mergeLanes(parent.childLanes, lane); - alternate = parent.alternate; + var UNSAFE_componentWillReceivePropsUniqueNames = new Set(); - if (alternate !== null) { - alternate.childLanes = mergeLanes(alternate.childLanes, lane); + if (pendingUNSAFE_ComponentWillReceivePropsWarnings.length > 0) { + pendingUNSAFE_ComponentWillReceivePropsWarnings.forEach(function (fiber) { + UNSAFE_componentWillReceivePropsUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingUNSAFE_ComponentWillReceivePropsWarnings = []; } - if (parent.tag === OffscreenComponent) { - // Check if this offscreen boundary is currently hidden. - // - // The instance may be null if the Offscreen parent was unmounted. Usually - // the parent wouldn't be reachable in that case because we disconnect - // fibers from the tree when they are deleted. However, there's a weird - // edge case where setState is called on a fiber that was interrupted - // before it ever mounted. Because it never mounts, it also never gets - // deleted. Because it never gets deleted, its return pointer never gets - // disconnected. Which means it may be attached to a deleted Offscreen - // parent node. (This discovery suggests it may be better for memory usage - // if we don't attach the `return` pointer until the commit phase, though - // in order to do that we'd need some other way to track the return - // pointer during the initial render, like on the stack.) - // - // This case is always accompanied by a warning, but we still need to - // account for it. (There may be other cases that we haven't discovered, - // too.) - var offscreenInstance = parent.stateNode; + var componentWillUpdateUniqueNames = new Set(); - if ( - offscreenInstance !== null && - !(offscreenInstance._visibility & OffscreenVisible) - ) { - isHidden = true; - } + if (pendingComponentWillUpdateWarnings.length > 0) { + pendingComponentWillUpdateWarnings.forEach(function (fiber) { + componentWillUpdateUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingComponentWillUpdateWarnings = []; } - node = parent; - parent = parent.return; - } + var UNSAFE_componentWillUpdateUniqueNames = new Set(); - if (isHidden && update !== null && node.tag === HostRoot) { - var root = node.stateNode; - markHiddenUpdate(root, update, lane); - } -} + 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' -function getRootForUpdatedFiber(sourceFiber) { - // TODO: We will detect and infinite update loop and throw even if this fiber - // has already unmounted. This isn't really necessary but it happens to be the - // current behavior we've used for several release cycles. Consider not - // performing this check if the updated fiber already unmounted, since it's - // not possible for that to cause an infinite update loop. - throwIfInfiniteUpdateLoopDetected(); // When a setState happens, we must ensure the root is scheduled. Because - // update queues do not have a backpointer to the root, the only way to do - // this currently is to walk up the return path. This used to not be a big - // deal because we would have to walk up the return path to set - // the `childLanes`, anyway, but now those two traversals happen at - // different times. - // TODO: Consider adding a `root` backpointer on the update queue. + if (UNSAFE_componentWillMountUniqueNames.size > 0) { + var sortedNames = setToSortedString(UNSAFE_componentWillMountUniqueNames); - detectUpdateOnUnmountedFiber(sourceFiber, sourceFiber); - var node = sourceFiber; - var parent = node.return; + error( + "Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code. " + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + + "* Move code with side effects to componentDidMount, and set initial state in the constructor.\n" + + "\nPlease update the following components: %s", + sortedNames + ); + } - while (parent !== null) { - detectUpdateOnUnmountedFiber(sourceFiber, node); - node = parent; - parent = node.return; - } + if (UNSAFE_componentWillReceivePropsUniqueNames.size > 0) { + var _sortedNames = setToSortedString( + UNSAFE_componentWillReceivePropsUniqueNames + ); - return node.tag === HostRoot ? node.stateNode : null; -} + error( + "Using UNSAFE_componentWillReceiveProps in strict mode is not recommended " + + "and may indicate bugs in your code. " + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + + "* Move data fetching code or side effects to componentDidUpdate.\n" + + "* If you're updating state whenever props change, " + + "refactor your code to use memoization techniques or move it to " + + "static getDerivedStateFromProps. Learn more at: https://reactjs.org/link/derived-state\n" + + "\nPlease update the following components: %s", + _sortedNames + ); + } -function detectUpdateOnUnmountedFiber(sourceFiber, parent) { - { - var alternate = parent.alternate; + if (UNSAFE_componentWillUpdateUniqueNames.size > 0) { + var _sortedNames2 = setToSortedString( + UNSAFE_componentWillUpdateUniqueNames + ); - if ( - alternate === null && - (parent.flags & (Placement | Hydrating)) !== NoFlags$1 - ) { - warnAboutUpdateOnNotYetMountedFiberInDEV(sourceFiber); + error( + "Using UNSAFE_componentWillUpdate in strict mode is not recommended " + + "and may indicate bugs in your code. " + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + + "* Move data fetching code or side effects to componentDidUpdate.\n" + + "\nPlease update the following components: %s", + _sortedNames2 + ); } - } -} -var UpdateState = 0; -var ReplaceState = 1; -var ForceUpdate = 2; -var CaptureUpdate = 3; // Global state that is reset at the beginning of calling `processUpdateQueue`. -// It should only be read right after calling `processUpdateQueue`, via -// `checkHasForceUpdateAfterProcessing`. + if (componentWillMountUniqueNames.size > 0) { + var _sortedNames3 = setToSortedString(componentWillMountUniqueNames); -var hasForceUpdate = false; -var didWarnUpdateInsideUpdate; -var currentlyProcessingQueue; + warn( + "componentWillMount has been renamed, and is not recommended for use. " + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + + "* Move code with side effects to componentDidMount, and set initial state in the constructor.\n" + + "* Rename componentWillMount to UNSAFE_componentWillMount to suppress " + + "this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. " + + "To rename all deprecated lifecycles to their new names, you can run " + + "`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n" + + "\nPlease update the following components: %s", + _sortedNames3 + ); + } -{ - didWarnUpdateInsideUpdate = false; - currentlyProcessingQueue = null; -} + if (componentWillReceivePropsUniqueNames.size > 0) { + var _sortedNames4 = setToSortedString( + componentWillReceivePropsUniqueNames + ); -function initializeUpdateQueue(fiber) { - var queue = { - baseState: fiber.memoizedState, - firstBaseUpdate: null, - lastBaseUpdate: null, - shared: { - pending: null, - lanes: NoLanes, - hiddenCallbacks: null - }, - callbacks: null - }; - fiber.updateQueue = queue; -} -function cloneUpdateQueue(current, workInProgress) { - // Clone the update queue from current. Unless it's already a clone. - var queue = workInProgress.updateQueue; - var currentQueue = current.updateQueue; + warn( + "componentWillReceiveProps has been renamed, and is not recommended for use. " + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + + "* Move data fetching code or side effects to componentDidUpdate.\n" + + "* If you're updating state whenever props change, refactor your " + + "code to use memoization techniques or move it to " + + "static getDerivedStateFromProps. Learn more at: https://reactjs.org/link/derived-state\n" + + "* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress " + + "this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. " + + "To rename all deprecated lifecycles to their new names, you can run " + + "`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n" + + "\nPlease update the following components: %s", + _sortedNames4 + ); + } - if (queue === currentQueue) { - var clone = { - baseState: currentQueue.baseState, - firstBaseUpdate: currentQueue.firstBaseUpdate, - lastBaseUpdate: currentQueue.lastBaseUpdate, - shared: currentQueue.shared, - callbacks: null - }; - workInProgress.updateQueue = clone; - } -} -function createUpdate(lane) { - var update = { - lane: lane, - tag: UpdateState, - payload: null, - callback: null, - next: null + if (componentWillUpdateUniqueNames.size > 0) { + var _sortedNames5 = setToSortedString(componentWillUpdateUniqueNames); + + warn( + "componentWillUpdate has been renamed, and is not recommended for use. " + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + + "* Move data fetching code or side effects to componentDidUpdate.\n" + + "* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress " + + "this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. " + + "To rename all deprecated lifecycles to their new names, you can run " + + "`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n" + + "\nPlease update the following components: %s", + _sortedNames5 + ); + } }; - return update; -} -function enqueueUpdate(fiber, update, lane) { - var updateQueue = fiber.updateQueue; - if (updateQueue === null) { - // Only occurs if the fiber has been unmounted. - return null; - } + var pendingLegacyContextWarning = new Map(); // Tracks components we have already warned about. - var sharedQueue = updateQueue.shared; + var didWarnAboutLegacyContext = new Set(); - { - if ( - currentlyProcessingQueue === sharedQueue && - !didWarnUpdateInsideUpdate - ) { - var componentName = getComponentNameFromFiber(fiber); + ReactStrictModeWarnings.recordLegacyContextWarning = function ( + fiber, + instance + ) { + var strictRoot = findStrictRoot(fiber); + if (strictRoot === null) { error( - "An update (setState, replaceState, or forceUpdate) was scheduled " + - "from inside an update function. Update functions should be pure, " + - "with zero side-effects. Consider using componentDidUpdate or a " + - "callback.\n\nPlease update the following component: %s", - componentName + "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." ); - didWarnUpdateInsideUpdate = true; + return; + } // Dedup strategy: Warn once per component. + + if (didWarnAboutLegacyContext.has(fiber.type)) { + return; } - } - if (isUnsafeClassRenderPhaseUpdate()) { - // This is an unsafe render phase update. Add directly to the update - // queue so we can process it immediately during the current render. - var pending = sharedQueue.pending; + var warningsForRoot = pendingLegacyContextWarning.get(strictRoot); - if (pending === null) { - // This is the first update. Create a circular list. - update.next = update; - } else { - update.next = pending.next; - pending.next = update; + if ( + fiber.type.contextTypes != null || + fiber.type.childContextTypes != null || + (instance !== null && typeof instance.getChildContext === "function") + ) { + if (warningsForRoot === undefined) { + warningsForRoot = []; + pendingLegacyContextWarning.set(strictRoot, warningsForRoot); + } + + warningsForRoot.push(fiber); } + }; - 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). + ReactStrictModeWarnings.flushLegacyContextWarning = function () { + pendingLegacyContextWarning.forEach(function (fiberArray, strictRoot) { + if (fiberArray.length === 0) { + return; + } - return unsafe_markUpdateLaneFromFiberToRoot(fiber, lane); - } else { - return enqueueConcurrentClassUpdate(fiber, sharedQueue, update, lane); - } -} -function entangleTransitions(root, fiber, lane) { - var updateQueue = fiber.updateQueue; + 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 (updateQueue === null) { - // Only occurs if the fiber has been unmounted. - return; - } + try { + setCurrentFiber(firstFiber); - var sharedQueue = updateQueue.shared; + error( + "Legacy context API has been detected within a strict-mode tree." + + "\n\nThe old API will be supported in all 16.x releases, but applications " + + "using it should migrate to the new version." + + "\n\nPlease update the following components: %s" + + "\n\nLearn more about this warning here: https://reactjs.org/link/legacy-context", + sortedNames + ); + } finally { + resetCurrentFiber(); + } + }); + }; - 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. + ReactStrictModeWarnings.discardPendingWarnings = function () { + pendingComponentWillMountWarnings = []; + pendingUNSAFE_ComponentWillMountWarnings = []; + pendingComponentWillReceivePropsWarnings = []; + pendingUNSAFE_ComponentWillReceivePropsWarnings = []; + pendingComponentWillUpdateWarnings = []; + pendingUNSAFE_ComponentWillUpdateWarnings = []; + pendingLegacyContextWarning = new Map(); + }; +} - queueLanes = intersectLanes(queueLanes, root.pendingLanes); // Entangle the new transition lane with the other transition lanes. +/* + * The `'' + value` pattern (used in perf-sensitive code) throws for Symbol + * and Temporal.* types. See https://github.com/facebook/react/pull/22064. + * + * The functions in this module will throw an easier-to-understand, + * easier-to-debug exception with a clear errors message message explaining the + * problem. (Instead of a confusing exception thrown inside the implementation + * of the `value` object). + */ +// $FlowFixMe only called in DEV, so void return is not possible. +function typeName(value) { + { + // toStringTag is needed for namespaced types like Temporal.Instant + var hasToStringTag = typeof Symbol === "function" && Symbol.toStringTag; + var type = + (hasToStringTag && value[Symbol.toStringTag]) || + value.constructor.name || + "Object"; // $FlowFixMe - 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. + return type; + } +} // $FlowFixMe only called in DEV, so void return is not possible. - markRootEntangled(root, newQueueLanes); +function willCoercionThrow(value) { + { + try { + testStringCoercion(value); + return false; + } catch (e) { + return true; + } } } -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; +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 (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; - - do { - var clone = { - lane: update.lane, - tag: update.tag, - payload: update.payload, - // When this update is rebased, we should not fire its - // callback again. - callback: null, - next: null - }; - - if (newLast === null) { - newFirst = newLast = clone; - } else { - newLast.next = clone; - newLast = clone; - } // $FlowFixMe[incompatible-type] we bail out when we get a null - - update = update.next; - } while (update !== null); // Append the captured update the end of the cloned list. - - if (newLast === null) { - newFirst = newLast = capturedUpdate; - } else { - newLast.next = capturedUpdate; - newLast = capturedUpdate; - } - } else { - // There are no base updates. - newFirst = newLast = capturedUpdate; - } - - queue = { - baseState: currentQueue.baseState, - firstBaseUpdate: newFirst, - lastBaseUpdate: newLast, - shared: currentQueue.shared, - callbacks: currentQueue.callbacks - }; - workInProgress.updateQueue = queue; - return; + return testStringCoercion(value); // throw (to help callers find troubleshooting comments) } - } // Append the update to the end of the list. - - var lastBaseUpdate = queue.lastBaseUpdate; - - if (lastBaseUpdate === null) { - queue.firstBaseUpdate = capturedUpdate; - } else { - lastBaseUpdate.next = capturedUpdate; } +} +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) + ); - queue.lastBaseUpdate = capturedUpdate; + return testStringCoercion(value); // throw (to help callers find troubleshooting comments) + } + } } -function getStateFromUpdate( - workInProgress, - queue, - update, - prevState, - nextProps, - instance -) { - switch (update.tag) { - case ReplaceState: { - var payload = update.payload; +var ReactCurrentActQueue$2 = ReactSharedInternals.ReactCurrentActQueue; // An error that is thrown (e.g. by `use`) to trigger Suspense. If we +// detect this is caught by userspace, we'll log a warning in development. - if (typeof payload === "function") { - // Updater function - { - enterDisallowedContextReadInDEV(); - } +var SuspenseException = new Error( + "Suspense Exception: This is not a real error! It's an implementation " + + "detail of `use` to interrupt the current render. You must either " + + "rethrow it immediately, or move the `use` call outside of the " + + "`try/catch` block. Capturing without rethrowing will lead to " + + "unexpected behavior.\n\n" + + "To handle async errors, wrap your component in an error boundary, or " + + "call the promise's `.catch` method and pass the result to `use`" +); // This is a noop thenable that we use to trigger a fallback in throwException. +// TODO: It would be better to refactor throwException into multiple functions +// so we can trigger a fallback directly without having to check the type. But +// for now this will do. - var nextState = payload.call(instance, prevState, nextProps); +var noopSuspenseyCommitThenable = { + then: function () {} +}; +function createThenableState() { + // The ThenableState is created the first time a component suspends. If it + // suspends again, we'll reuse the same state. + return []; +} +function isThenableResolved(thenable) { + var status = thenable.status; + return status === "fulfilled" || status === "rejected"; +} - { - if (workInProgress.mode & StrictLegacyMode) { - setIsStrictModeForDevtools(true); +function noop$1() {} - try { - payload.call(instance, prevState, nextProps); - } finally { - setIsStrictModeForDevtools(false); - } - } +function trackUsedThenable(thenableState, thenable, index) { + if (ReactCurrentActQueue$2.current !== null) { + ReactCurrentActQueue$2.didUsePromise = true; + } - exitDisallowedContextReadInDEV(); - } + var previous = thenableState[index]; - return nextState; - } // State object + if (previous === undefined) { + thenableState.push(thenable); + } else { + if (previous !== thenable) { + // Reuse the previous thenable, and drop the new one. We can assume + // they represent the same value, because components are idempotent. + // Avoid an unhandled rejection errors for the Promises that we'll + // intentionally ignore. + thenable.then(noop$1, noop$1); + thenable = previous; + } + } // We use an expando to track the status and result of a thenable so that we + // can synchronously unwrap the value. Think of this as an extension of the + // Promise API, or a custom interface that is a superset of Thenable. + // + // If the thenable doesn't have a status, set it to "pending" and attach + // a listener that will update its status and result when it resolves. - return payload; + switch (thenable.status) { + case "fulfilled": { + var fulfilledValue = thenable.value; + return fulfilledValue; } - case CaptureUpdate: { - workInProgress.flags = - (workInProgress.flags & ~ShouldCapture) | DidCapture; + case "rejected": { + var rejectedError = thenable.reason; + throw rejectedError; } - // Intentional fallthrough - case UpdateState: { - var _payload = update.payload; - var partialState; + default: { + if (typeof thenable.status === "string") { + // Only instrument the thenable if the status if not defined. If + // it's defined, but an unknown value, assume it's been instrumented by + // some custom userspace implementation. We treat it as "pending". + // Attach a dummy listener, to ensure that any lazy initialization can + // happen. Flight lazily parses JSON when the value is actually awaited. + thenable.then(noop$1, noop$1); + } else { + var pendingThenable = thenable; + pendingThenable.status = "pending"; + pendingThenable.then( + function (fulfilledValue) { + if (thenable.status === "pending") { + var fulfilledThenable = thenable; + fulfilledThenable.status = "fulfilled"; + fulfilledThenable.value = fulfilledValue; + } + }, + function (error) { + if (thenable.status === "pending") { + var rejectedThenable = thenable; + rejectedThenable.status = "rejected"; + rejectedThenable.reason = error; + } + } + ); + } // Check one more time in case the thenable resolved synchronously. - if (typeof _payload === "function") { - // Updater function - { - enterDisallowedContextReadInDEV(); + switch (thenable.status) { + case "fulfilled": { + var fulfilledThenable = thenable; + return fulfilledThenable.value; } - partialState = _payload.call(instance, prevState, nextProps); - - { - if (workInProgress.mode & StrictLegacyMode) { - setIsStrictModeForDevtools(true); + case "rejected": { + var rejectedThenable = thenable; + throw rejectedThenable.reason; + } + } // Suspend. + // + // Throwing here is an implementation detail that allows us to unwind the + // call stack. But we shouldn't allow it to leak into userspace. Throw an + // opaque placeholder value instead of the actual thenable. If it doesn't + // get captured by the work loop, log a warning, because that means + // something in userspace must have caught it. - try { - _payload.call(instance, prevState, nextProps); - } finally { - setIsStrictModeForDevtools(false); - } - } + suspendedThenable = thenable; - exitDisallowedContextReadInDEV(); - } - } else { - // Partial state object - partialState = _payload; + { + needsToResetSuspendedThenableDEV = true; } - 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); + throw SuspenseException; } + } +} +// passed to the rest of the Suspense implementation — which, for historical +// reasons, expects to receive a thenable. - case ForceUpdate: { - hasForceUpdate = true; - return prevState; - } +var suspendedThenable = null; +var needsToResetSuspendedThenableDEV = false; +function getSuspendedThenable() { + // This is called right after `use` suspends by throwing an exception. `use` + // throws an opaque value instead of the thenable itself so that it can't be + // caught in userspace. Then the work loop accesses the actual thenable using + // this function. + if (suspendedThenable === null) { + throw new Error( + "Expected a suspended thenable. This is a bug in React. Please file " + + "an issue." + ); } - return prevState; -} + var thenable = suspendedThenable; + suspendedThenable = null; -function processUpdateQueue(workInProgress, props, instance, renderLanes) { - // This is always non-null on a ClassComponent or HostRoot - var queue = workInProgress.updateQueue; - hasForceUpdate = false; + { + needsToResetSuspendedThenableDEV = false; + } + return thenable; +} +function checkIfUseWrappedInTryCatch() { { - currentlyProcessingQueue = queue.shared; + // This was set right before SuspenseException was thrown, and it should + // have been cleared when the exception was handled. If it wasn't, + // it must have been caught by userspace. + if (needsToResetSuspendedThenableDEV) { + needsToResetSuspendedThenableDEV = false; + return true; + } } - var firstBaseUpdate = queue.firstBaseUpdate; - var lastBaseUpdate = queue.lastBaseUpdate; // Check if there are pending updates. If so, transfer them to the base queue. + return false; +} - var pendingQueue = queue.shared.pending; +var thenableState$1 = null; +var thenableIndexCounter$1 = 0; +var didWarnAboutMaps; +var didWarnAboutGenerators; +var didWarnAboutStringRefs; +var ownerHasKeyUseWarning; +var ownerHasFunctionTypeWarning; - if (pendingQueue !== null) { - queue.shared.pending = null; // The pending queue is circular. Disconnect the pointer between first - // and last so that it's non-circular. +var warnForMissingKey = function (child, returnFiber) {}; - var lastPendingUpdate = pendingQueue; - var firstPendingUpdate = lastPendingUpdate.next; - lastPendingUpdate.next = null; // Append pending updates to base queue +{ + 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 (lastBaseUpdate === null) { - firstBaseUpdate = firstPendingUpdate; - } else { - lastBaseUpdate.next = firstPendingUpdate; - } + ownerHasKeyUseWarning = {}; + ownerHasFunctionTypeWarning = {}; - 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 + warnForMissingKey = function (child, returnFiber) { + if (child === null || typeof child !== "object") { + return; + } - var current = workInProgress.alternate; + if (!child._store || child._store.validated || child.key != null) { + return; + } - if (current !== null) { - // This is always non-null on a ClassComponent or HostRoot - var currentQueue = current.updateQueue; - var currentLastBaseUpdate = currentQueue.lastBaseUpdate; + if (typeof child._store !== "object") { + throw new Error( + "React Component in warnForMissingKey should have a _store. " + + "This error is likely caused by a bug in React. Please file an issue." + ); + } // $FlowFixMe unable to narrow type from mixed to writable object - if (currentLastBaseUpdate !== lastBaseUpdate) { - if (currentLastBaseUpdate === null) { - currentQueue.firstBaseUpdate = firstPendingUpdate; - } else { - currentLastBaseUpdate.next = firstPendingUpdate; - } + child._store.validated = true; + var componentName = getComponentNameFromFiber(returnFiber) || "Component"; - currentQueue.lastBaseUpdate = lastPendingUpdate; - } + if (ownerHasKeyUseWarning[componentName]) { + return; } - } // 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. + ownerHasKeyUseWarning[componentName] = true; - var newLanes = NoLanes; - var newBaseState = null; - var newFirstBaseUpdate = null; - var newLastBaseUpdate = null; - var update = firstBaseUpdate; + error( + "Each child in a list should have a unique " + + '"key" prop. See https://reactjs.org/link/warning-keys for ' + + "more information." + ); + }; +} - do { - // An extra OffscreenLane bit is added to updates that were made to - // a hidden tree, so that we can distinguish them from updates that were - // already there when the tree was hidden. - var updateLane = removeLanes(update.lane, OffscreenLane); - var isHiddenUpdate = updateLane !== update.lane; // Check if this update was made while the tree was hidden. If so, then - // it's not a "base" update and we should disregard the extra base lanes - // that were added to renderLanes when we entered the Offscreen tree. +function isReactClass(type) { + return type.prototype && type.prototype.isReactComponent; +} - var shouldSkipUpdate = isHiddenUpdate - ? !isSubsetOfLanes(getWorkInProgressRootRenderLanes(), updateLane) - : !isSubsetOfLanes(renderLanes, updateLane); +function unwrapThenable(thenable) { + var index = thenableIndexCounter$1; + thenableIndexCounter$1 += 1; - if (shouldSkipUpdate) { - // Priority is insufficient. Skip this update. If this is the first - // skipped update, the previous update/state is the new base - // update/state. - var clone = { - lane: updateLane, - tag: update.tag, - payload: update.payload, - callback: update.callback, - next: null - }; + if (thenableState$1 === null) { + thenableState$1 = createThenableState(); + } - if (newLastBaseUpdate === null) { - newFirstBaseUpdate = newLastBaseUpdate = clone; - newBaseState = newState; - } else { - newLastBaseUpdate = newLastBaseUpdate.next = clone; - } // Update the remaining priority in the queue. + return trackUsedThenable(thenableState$1, thenable, index); +} - newLanes = mergeLanes(newLanes, updateLane); - } else { - // This update does have sufficient priority. - if (newLastBaseUpdate !== null) { - var _clone = { - // This update is going to be committed so we never want uncommit - // it. Using NoLane works because 0 is a subset of all bitmasks, so - // this will never be skipped by the check above. - lane: NoLane, - tag: update.tag, - payload: update.payload, - // When this update is rebased, we should not fire its - // callback again. - callback: null, - next: null - }; - newLastBaseUpdate = newLastBaseUpdate.next = _clone; - } // Process this update. +function coerceRef(returnFiber, current, element) { + var mixedRef = element.ref; - newState = getStateFromUpdate( - workInProgress, - queue, - update, - newState, - props, - instance - ); - var callback = update.callback; + if ( + mixedRef !== null && + typeof mixedRef !== "function" && + typeof mixedRef !== "object" + ) { + { + if ( + // We warn in ReactElement.js if owner and self are equal for string refs + // because these cannot be automatically converted to an arrow function + // using a codemod. Therefore, we don't have to warn about string refs again. + !( + element._owner && + element._self && + element._owner.stateNode !== element._self + ) && // Will already throw with "Function components cannot have string refs" + !(element._owner && element._owner.tag !== ClassComponent) && // Will already warn with "Function components cannot be given refs" + !(typeof element.type === "function" && !isReactClass(element.type)) && // Will already throw with "Element ref was specified as a string (someStringRef) but no owner was set" + element._owner + ) { + var componentName = + getComponentNameFromFiber(returnFiber) || "Component"; - if (callback !== null) { - workInProgress.flags |= Callback; + if (!didWarnAboutStringRefs[componentName]) { + error( + 'Component "%s" contains the string ref "%s". Support for string refs ' + + "will be removed in a future major release. We recommend using " + + "useRef() or createRef() instead. " + + "Learn more about using refs safely here: " + + "https://reactjs.org/link/strict-mode-string-ref", + componentName, + mixedRef + ); - if (isHiddenUpdate) { - workInProgress.flags |= Visibility; - } + didWarnAboutStringRefs[componentName] = true; + } + } + } - var callbacks = queue.callbacks; + if (element._owner) { + var owner = element._owner; + var inst; - if (callbacks === null) { - queue.callbacks = [callback]; - } else { - callbacks.push(callback); - } + if (owner) { + var ownerFiber = owner; + + if (ownerFiber.tag !== ClassComponent) { + throw new Error( + "Function components cannot have string refs. " + + "We recommend using useRef() instead. " + + "Learn more about using refs safely here: " + + "https://reactjs.org/link/strict-mode-string-ref" + ); } - } // $FlowFixMe[incompatible-type] we bail out when we get a null - update = update.next; + inst = ownerFiber.stateNode; + } - if (update === null) { - pendingQueue = queue.shared.pending; + if (!inst) { + throw new Error( + "Missing owner for string ref " + + mixedRef + + ". This error is likely caused by a " + + "bug in React. Please file an issue." + ); + } // Assigning this to a const so Flow knows it won't change in the closure - if (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 resolvedInst = inst; - var _firstPendingUpdate = _lastPendingUpdate.next; - _lastPendingUpdate.next = null; - update = _firstPendingUpdate; - queue.lastBaseUpdate = _lastPendingUpdate; - queue.shared.pending = null; - } + { + checkPropStringCoercion(mixedRef, "ref"); } - } while (true); - if (newLastBaseUpdate === null) { - newBaseState = newState; - } + var stringRef = "" + mixedRef; // Check if previous string ref matches new string ref - queue.baseState = newBaseState; - queue.firstBaseUpdate = newFirstBaseUpdate; - queue.lastBaseUpdate = newLastBaseUpdate; + if ( + current !== null && + current.ref !== null && + typeof current.ref === "function" && + current.ref._stringRef === stringRef + ) { + return current.ref; + } - 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. + var ref = function (value) { + var refs = resolvedInst.refs; - markSkippedUpdateLanes(newLanes); - workInProgress.lanes = newLanes; - workInProgress.memoizedState = newState; - } + if (value === null) { + delete refs[stringRef]; + } else { + refs[stringRef] = value; + } + }; - { - currentlyProcessingQueue = 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." + ); + } -function callCallback(callback, context) { - if (typeof callback !== "function") { - throw new Error( - "Invalid argument passed as callback. Expected a function. Instead " + - ("received: " + callback) - ); + if (!element._owner) { + throw new Error( + "Element ref was specified as a string (" + + mixedRef + + ") but no owner was set. This could happen for one of" + + " the following reasons:\n" + + "1. You may be adding a ref to a function component\n" + + "2. You may be adding a ref to a component that was not created inside a component's render method\n" + + "3. You have multiple copies of React loaded\n" + + "See https://reactjs.org/link/refs-must-have-owner for more information." + ); + } + } } - callback.call(context); + return mixedRef; } -function resetHasForceUpdateBeforeProcessing() { - hasForceUpdate = false; -} -function checkHasForceUpdateAfterProcessing() { - return hasForceUpdate; +function throwOnInvalidObjectType(returnFiber, newChild) { + // $FlowFixMe[method-unbinding] + var childString = Object.prototype.toString.call(newChild); + throw new Error( + "Objects are not valid as a React child (found: " + + (childString === "[object Object]" + ? "object with keys {" + Object.keys(newChild).join(", ") + "}" + : childString) + + "). " + + "If you meant to render a collection of children, use an array " + + "instead." + ); } -function deferHiddenCallbacks(updateQueue) { - // When an update finishes on a hidden component, its callback should not - // be fired until/unless the component is made visible again. Stash the - // callback on the shared queue object so it can be fired later. - var newHiddenCallbacks = updateQueue.callbacks; - if (newHiddenCallbacks !== null) { - var existingHiddenCallbacks = updateQueue.shared.hiddenCallbacks; +function warnOnFunctionType(returnFiber) { + { + var componentName = getComponentNameFromFiber(returnFiber) || "Component"; - if (existingHiddenCallbacks === null) { - updateQueue.shared.hiddenCallbacks = newHiddenCallbacks; - } else { - updateQueue.shared.hiddenCallbacks = - existingHiddenCallbacks.concat(newHiddenCallbacks); + if (ownerHasFunctionTypeWarning[componentName]) { + return; } - } -} -function commitHiddenCallbacks(updateQueue, context) { - // This component is switching from hidden -> visible. Commit any callbacks - // that were previously deferred. - var hiddenCallbacks = updateQueue.shared.hiddenCallbacks; - if (hiddenCallbacks !== null) { - updateQueue.shared.hiddenCallbacks = null; + ownerHasFunctionTypeWarning[componentName] = true; - for (var i = 0; i < hiddenCallbacks.length; i++) { - var callback = hiddenCallbacks[i]; - callCallback(callback, context); - } + 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." + ); } } -function commitCallbacks(updateQueue, context) { - var callbacks = updateQueue.callbacks; - if (callbacks !== null) { - updateQueue.callbacks = null; +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. - for (var i = 0; i < callbacks.length; i++) { - var callback = callbacks[i]; - callCallback(callback, context); +function createChildReconciler(shouldTrackSideEffects) { + function deleteChild(returnFiber, childToDelete) { + if (!shouldTrackSideEffects) { + // Noop. + return; } - } -} - -/** - * 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; - } + var deletions = returnFiber.deletions; - if ( - typeof objA !== "object" || - objA === null || - typeof objB !== "object" || - objB === null - ) { - return false; + if (deletions === null) { + returnFiber.deletions = [childToDelete]; + returnFiber.flags |= ChildDeletion; + } else { + deletions.push(childToDelete); + } } - var keysA = Object.keys(objA); - var keysB = Object.keys(objB); - - if (keysA.length !== keysB.length) { - return false; - } // Test for A's keys different from B. + 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. - for (var i = 0; i < keysA.length; i++) { - var currentKey = keysA[i]; + var childToDelete = currentFirstChild; - if ( - !hasOwnProperty.call(objB, currentKey) || - !objectIs(objA[currentKey], objB[currentKey]) - ) { - return false; + while (childToDelete !== null) { + deleteChild(returnFiber, childToDelete); + childToDelete = childToDelete.sibling; } + + return null; } - return true; -} + 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 describeFiber(fiber) { - var owner = fiber._debugOwner ? fiber._debugOwner.type : null; - var source = fiber._debugSource; + while (existingChild !== null) { + if (existingChild.key !== null) { + existingChildren.set(existingChild.key, existingChild); + } else { + existingChildren.set(existingChild.index, existingChild); + } - switch (fiber.tag) { - case HostHoistable: - case HostSingleton: - case HostComponent: - return describeBuiltInComponentFrame(fiber.type, source, owner); + existingChild = existingChild.sibling; + } - case LazyComponent: - return describeBuiltInComponentFrame("Lazy", source, owner); + return existingChildren; + } - case SuspenseComponent: - return describeBuiltInComponentFrame("Suspense", source, owner); + 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; + } - case SuspenseListComponent: - return describeBuiltInComponentFrame("SuspenseList", source, owner); + function placeChild(newFiber, lastPlacedIndex, newIndex) { + newFiber.index = newIndex; - case FunctionComponent: - case IndeterminateComponent: - case SimpleMemoComponent: - return describeFunctionComponentFrame(fiber.type, source, owner); + 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; + } - case ForwardRef: - return describeFunctionComponentFrame(fiber.type.render, source, owner); + var current = newFiber.alternate; - case ClassComponent: - return describeClassComponentFrame(fiber.type, source, owner); + if (current !== null) { + var oldIndex = current.index; - default: - return ""; - } -} - -function getStackByFiberInDevAndProd(workInProgress) { - try { - var info = ""; - var node = workInProgress; - - do { - info += describeFiber(node); // $FlowFixMe[incompatible-type] we bail out when we get a null - - node = node.return; - } while (node); - - return info; - } catch (x) { - return "\nError generating stack: " + x.message + "\n" + x.stack; - } -} - -var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; -var current = null; -var isRendering = false; -function getCurrentFiberOwnerNameInDevOrNull() { - { - if (current === null) { - return null; - } - - var owner = current._debugOwner; - - if (owner !== null && typeof owner !== "undefined") { - return getComponentNameFromFiber(owner); + if (oldIndex < lastPlacedIndex) { + // This is a move. + newFiber.flags |= Placement | PlacementDEV; + return lastPlacedIndex; + } else { + // This item can stay in place. + return oldIndex; + } + } else { + // This is an insertion. + newFiber.flags |= Placement | PlacementDEV; + return lastPlacedIndex; } } - return null; -} - -function getCurrentFiberStackInDev() { - { - if (current === null) { - return ""; - } // Safe because if current fiber exists, we are reconciling, - // and it is guaranteed to be the work-in-progress version. + function placeSingleChild(newFiber) { + // This is simpler for the single child case. We only need to do a + // placement for inserting new children. + if (shouldTrackSideEffects && newFiber.alternate === null) { + newFiber.flags |= Placement | PlacementDEV; + } - return getStackByFiberInDevAndProd(current); + return newFiber; } -} -function resetCurrentFiber() { - { - ReactDebugCurrentFrame.getCurrentStack = null; - current = null; - isRendering = false; - } -} -function setCurrentFiber(fiber) { - { - ReactDebugCurrentFrame.getCurrentStack = - fiber === null ? null : getCurrentFiberStackInDev; - current = fiber; - isRendering = false; - } -} -function getCurrentFiber() { - { - return current; - } -} -function setIsRendering(rendering) { - { - isRendering = rendering; + 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; + } } -} - -var ReactStrictModeWarnings = { - recordUnsafeLifecycleWarnings: function (fiber, instance) {}, - flushPendingUnsafeLifecycleWarnings: function () {}, - recordLegacyContextWarning: function (fiber, instance) {}, - flushLegacyContextWarning: function () {}, - discardPendingWarnings: function () {} -}; - -{ - var findStrictRoot = function (fiber) { - var maybeStrictRoot = null; - var node = fiber; - while (node !== null) { - if (node.mode & StrictLegacyMode) { - maybeStrictRoot = node; - } + function updateElement(returnFiber, current, element, lanes) { + var elementType = element.type; - node = node.return; + if (elementType === REACT_FRAGMENT_TYPE) { + return updateFragment( + returnFiber, + current, + element.props.children, + lanes, + element.key + ); } - return maybeStrictRoot; - }; - - var setToSortedString = function (set) { - var array = []; - set.forEach(function (value) { - array.push(value); - }); - return array.sort().join(", "); - }; + 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; - var pendingComponentWillMountWarnings = []; - var pendingUNSAFE_ComponentWillMountWarnings = []; - var pendingComponentWillReceivePropsWarnings = []; - var pendingUNSAFE_ComponentWillReceivePropsWarnings = []; - var pendingComponentWillUpdateWarnings = []; - var pendingUNSAFE_ComponentWillUpdateWarnings = []; // Tracks components we have already warned about. + { + existing._debugSource = element._source; + existing._debugOwner = element._owner; + } - var didWarnAboutUnsafeLifecycles = new Set(); + return existing; + } + } // Insert - ReactStrictModeWarnings.recordUnsafeLifecycleWarnings = function ( - fiber, - instance - ) { - // Dedupe strategy: Warn once per component. - if (didWarnAboutUnsafeLifecycles.has(fiber.type)) { - return; - } + var created = createFiberFromElement(element, returnFiber.mode, lanes); + created.ref = coerceRef(returnFiber, current, element); + created.return = returnFiber; + return created; + } + function updatePortal(returnFiber, current, portal, lanes) { if ( - typeof instance.componentWillMount === "function" && // Don't warn about react-lifecycles-compat polyfilled components. - instance.componentWillMount.__suppressDeprecationWarning !== true + current === null || + current.tag !== HostPortal || + current.stateNode.containerInfo !== portal.containerInfo || + current.stateNode.implementation !== portal.implementation ) { - pendingComponentWillMountWarnings.push(fiber); + // 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; } + } - if ( - fiber.mode & StrictLegacyMode && - typeof instance.UNSAFE_componentWillMount === "function" - ) { - pendingUNSAFE_ComponentWillMountWarnings.push(fiber); + 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; } + } + function createChild(returnFiber, newChild, lanes) { if ( - typeof instance.componentWillReceiveProps === "function" && - instance.componentWillReceiveProps.__suppressDeprecationWarning !== true + (typeof newChild === "string" && newChild !== "") || + typeof newChild === "number" ) { - pendingComponentWillReceivePropsWarnings.push(fiber); + // 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 ( - fiber.mode & StrictLegacyMode && - typeof instance.UNSAFE_componentWillReceiveProps === "function" - ) { - pendingUNSAFE_ComponentWillReceivePropsWarnings.push(fiber); - } + if (typeof newChild === "object" && newChild !== null) { + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE: { + var _created = createFiberFromElement( + newChild, + returnFiber.mode, + lanes + ); - if ( - typeof instance.componentWillUpdate === "function" && - instance.componentWillUpdate.__suppressDeprecationWarning !== true - ) { - pendingComponentWillUpdateWarnings.push(fiber); - } + _created.ref = coerceRef(returnFiber, null, newChild); + _created.return = returnFiber; + return _created; + } - if ( - fiber.mode & StrictLegacyMode && - typeof instance.UNSAFE_componentWillUpdate === "function" - ) { - pendingUNSAFE_ComponentWillUpdateWarnings.push(fiber); - } - }; - - ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings = function () { - // We do an initial pass to gather component names - var componentWillMountUniqueNames = new Set(); + case REACT_PORTAL_TYPE: { + var _created2 = createFiberFromPortal( + newChild, + returnFiber.mode, + lanes + ); - if (pendingComponentWillMountWarnings.length > 0) { - pendingComponentWillMountWarnings.forEach(function (fiber) { - componentWillMountUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingComponentWillMountWarnings = []; - } + _created2.return = returnFiber; + return _created2; + } - var UNSAFE_componentWillMountUniqueNames = new Set(); + case REACT_LAZY_TYPE: { + var payload = newChild._payload; + var init = newChild._init; + return createChild(returnFiber, init(payload), lanes); + } + } - if (pendingUNSAFE_ComponentWillMountWarnings.length > 0) { - pendingUNSAFE_ComponentWillMountWarnings.forEach(function (fiber) { - UNSAFE_componentWillMountUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" + if (isArray(newChild) || getIteratorFn(newChild)) { + var _created3 = createFiberFromFragment( + newChild, + returnFiber.mode, + lanes, + null ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingUNSAFE_ComponentWillMountWarnings = []; - } - - var componentWillReceivePropsUniqueNames = new Set(); - if (pendingComponentWillReceivePropsWarnings.length > 0) { - pendingComponentWillReceivePropsWarnings.forEach(function (fiber) { - componentWillReceivePropsUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingComponentWillReceivePropsWarnings = []; - } + _created3.return = returnFiber; + return _created3; + } // Usable node types + // + // Unwrap the inner value and recursively call this function again. - var UNSAFE_componentWillReceivePropsUniqueNames = new Set(); + if (typeof newChild.then === "function") { + var thenable = newChild; + return createChild(returnFiber, unwrapThenable(thenable), lanes); + } - if (pendingUNSAFE_ComponentWillReceivePropsWarnings.length > 0) { - pendingUNSAFE_ComponentWillReceivePropsWarnings.forEach(function (fiber) { - UNSAFE_componentWillReceivePropsUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) { + var context = newChild; + return createChild( + returnFiber, + readContextDuringReconcilation(returnFiber, context, lanes), + lanes ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingUNSAFE_ComponentWillReceivePropsWarnings = []; - } + } - var componentWillUpdateUniqueNames = new Set(); + throwOnInvalidObjectType(returnFiber, newChild); + } - if (pendingComponentWillUpdateWarnings.length > 0) { - pendingComponentWillUpdateWarnings.forEach(function (fiber) { - componentWillUpdateUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingComponentWillUpdateWarnings = []; + { + if (typeof newChild === "function") { + warnOnFunctionType(returnFiber); + } } - var UNSAFE_componentWillUpdateUniqueNames = new Set(); + return 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' + function updateSlot(returnFiber, oldFiber, newChild, lanes) { + // Update the fiber if the keys match, otherwise return null. + var key = oldFiber !== null ? oldFiber.key : null; - if (UNSAFE_componentWillMountUniqueNames.size > 0) { - var sortedNames = setToSortedString(UNSAFE_componentWillMountUniqueNames); + 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; + } - error( - "Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code. " + - "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + - "* Move code with side effects to componentDidMount, and set initial state in the constructor.\n" + - "\nPlease update the following components: %s", - sortedNames - ); + return updateTextNode(returnFiber, oldFiber, "" + newChild, lanes); } - if (UNSAFE_componentWillReceivePropsUniqueNames.size > 0) { - var _sortedNames = setToSortedString( - UNSAFE_componentWillReceivePropsUniqueNames - ); + 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; + } + } - error( - "Using UNSAFE_componentWillReceiveProps in strict mode is not recommended " + - "and may indicate bugs in your code. " + - "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + - "* Move data fetching code or side effects to componentDidUpdate.\n" + - "* If you're updating state whenever props change, " + - "refactor your code to use memoization techniques or move it to " + - "static getDerivedStateFromProps. Learn more at: https://reactjs.org/link/derived-state\n" + - "\nPlease update the following components: %s", - _sortedNames - ); - } + case REACT_PORTAL_TYPE: { + if (newChild.key === key) { + return updatePortal(returnFiber, oldFiber, newChild, lanes); + } else { + return null; + } + } - if (UNSAFE_componentWillUpdateUniqueNames.size > 0) { - var _sortedNames2 = setToSortedString( - UNSAFE_componentWillUpdateUniqueNames - ); + case REACT_LAZY_TYPE: { + var payload = newChild._payload; + var init = newChild._init; + return updateSlot(returnFiber, oldFiber, init(payload), lanes); + } + } - error( - "Using UNSAFE_componentWillUpdate in strict mode is not recommended " + - "and may indicate bugs in your code. " + - "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + - "* Move data fetching code or side effects to componentDidUpdate.\n" + - "\nPlease update the following components: %s", - _sortedNames2 - ); - } + if (isArray(newChild) || getIteratorFn(newChild)) { + if (key !== null) { + return null; + } - if (componentWillMountUniqueNames.size > 0) { - var _sortedNames3 = setToSortedString(componentWillMountUniqueNames); + return updateFragment(returnFiber, oldFiber, newChild, lanes, null); + } // Usable node types + // + // Unwrap the inner value and recursively call this function again. - warn( - "componentWillMount has been renamed, and is not recommended for use. " + - "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + - "* Move code with side effects to componentDidMount, and set initial state in the constructor.\n" + - "* Rename componentWillMount to UNSAFE_componentWillMount to suppress " + - "this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. " + - "To rename all deprecated lifecycles to their new names, you can run " + - "`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n" + - "\nPlease update the following components: %s", - _sortedNames3 - ); - } + if (typeof newChild.then === "function") { + var thenable = newChild; + return updateSlot( + returnFiber, + oldFiber, + unwrapThenable(thenable), + lanes + ); + } - if (componentWillReceivePropsUniqueNames.size > 0) { - var _sortedNames4 = setToSortedString( - componentWillReceivePropsUniqueNames - ); + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) { + var context = newChild; + return updateSlot( + returnFiber, + oldFiber, + readContextDuringReconcilation(returnFiber, context, lanes), + lanes + ); + } - warn( - "componentWillReceiveProps has been renamed, and is not recommended for use. " + - "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + - "* Move data fetching code or side effects to componentDidUpdate.\n" + - "* If you're updating state whenever props change, refactor your " + - "code to use memoization techniques or move it to " + - "static getDerivedStateFromProps. Learn more at: https://reactjs.org/link/derived-state\n" + - "* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress " + - "this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. " + - "To rename all deprecated lifecycles to their new names, you can run " + - "`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n" + - "\nPlease update the following components: %s", - _sortedNames4 - ); + throwOnInvalidObjectType(returnFiber, newChild); } - if (componentWillUpdateUniqueNames.size > 0) { - var _sortedNames5 = setToSortedString(componentWillUpdateUniqueNames); - - warn( - "componentWillUpdate has been renamed, and is not recommended for use. " + - "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + - "* Move data fetching code or side effects to componentDidUpdate.\n" + - "* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress " + - "this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. " + - "To rename all deprecated lifecycles to their new names, you can run " + - "`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n" + - "\nPlease update the following components: %s", - _sortedNames5 - ); + { + if (typeof newChild === "function") { + warnOnFunctionType(returnFiber); + } } - }; - var pendingLegacyContextWarning = new Map(); // Tracks components we have already warned about. - - var didWarnAboutLegacyContext = new Set(); + return null; + } - ReactStrictModeWarnings.recordLegacyContextWarning = function ( - fiber, - instance + function updateFromMap( + existingChildren, + returnFiber, + newIdx, + newChild, + lanes ) { - 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." - ); - - return; - } // Dedup strategy: Warn once per component. - - if (didWarnAboutLegacyContext.has(fiber.type)) { - return; + 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); } - var warningsForRoot = pendingLegacyContextWarning.get(strictRoot); + 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 ( - fiber.type.contextTypes != null || - fiber.type.childContextTypes != null || - (instance !== null && typeof instance.getChildContext === "function") - ) { - if (warningsForRoot === undefined) { - warningsForRoot = []; - pendingLegacyContextWarning.set(strictRoot, warningsForRoot); - } + return updateElement(returnFiber, _matchedFiber, newChild, lanes); + } - warningsForRoot.push(fiber); - } - }; + case REACT_PORTAL_TYPE: { + var _matchedFiber2 = + existingChildren.get( + newChild.key === null ? newIdx : newChild.key + ) || null; - ReactStrictModeWarnings.flushLegacyContextWarning = function () { - pendingLegacyContextWarning.forEach(function (fiberArray, strictRoot) { - if (fiberArray.length === 0) { - return; + 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 + ); } - 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 (isArray(newChild) || getIteratorFn(newChild)) { + var _matchedFiber3 = existingChildren.get(newIdx) || null; - try { - setCurrentFiber(firstFiber); + return updateFragment( + returnFiber, + _matchedFiber3, + newChild, + lanes, + null + ); + } // Usable node types + // + // Unwrap the inner value and recursively call this function again. - error( - "Legacy context API has been detected within a strict-mode tree." + - "\n\nThe old API will be supported in all 16.x releases, but applications " + - "using it should migrate to the new version." + - "\n\nPlease update the following components: %s" + - "\n\nLearn more about this warning here: https://reactjs.org/link/legacy-context", - sortedNames + if (typeof newChild.then === "function") { + var thenable = newChild; + return updateFromMap( + existingChildren, + returnFiber, + newIdx, + unwrapThenable(thenable), + lanes ); - } finally { - resetCurrentFiber(); } - }); - }; - - ReactStrictModeWarnings.discardPendingWarnings = function () { - pendingComponentWillMountWarnings = []; - pendingUNSAFE_ComponentWillMountWarnings = []; - pendingComponentWillReceivePropsWarnings = []; - pendingUNSAFE_ComponentWillReceivePropsWarnings = []; - pendingComponentWillUpdateWarnings = []; - pendingUNSAFE_ComponentWillUpdateWarnings = []; - pendingLegacyContextWarning = new Map(); - }; -} - -/* - * The `'' + value` pattern (used in perf-sensitive code) throws for Symbol - * and Temporal.* types. See https://github.com/facebook/react/pull/22064. - * - * The functions in this module will throw an easier-to-understand, - * easier-to-debug exception with a clear errors message message explaining the - * problem. (Instead of a confusing exception thrown inside the implementation - * of the `value` object). - */ -// $FlowFixMe only called in DEV, so void return is not possible. -function typeName(value) { - { - // toStringTag is needed for namespaced types like Temporal.Instant - var hasToStringTag = typeof Symbol === "function" && Symbol.toStringTag; - var type = - (hasToStringTag && value[Symbol.toStringTag]) || - value.constructor.name || - "Object"; // $FlowFixMe - return type; - } -} // $FlowFixMe only called in DEV, so void return is not possible. + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) { + var context = newChild; + return updateFromMap( + existingChildren, + returnFiber, + newIdx, + readContextDuringReconcilation(returnFiber, context, lanes), + lanes + ); + } -function willCoercionThrow(value) { - { - try { - testStringCoercion(value); - return false; - } catch (e) { - return true; + throwOnInvalidObjectType(returnFiber, newChild); } - } -} - -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) + { + if (typeof newChild === "function") { + warnOnFunctionType(returnFiber); + } } - } -} -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) - ); - return testStringCoercion(value); // throw (to help callers find troubleshooting comments) - } + return null; } -} - -var didWarnAboutMaps; -var didWarnAboutGenerators; -var didWarnAboutStringRefs; -var ownerHasKeyUseWarning; -var ownerHasFunctionTypeWarning; - -var warnForMissingKey = function (child, returnFiber) {}; - -{ - didWarnAboutMaps = false; - didWarnAboutGenerators = false; - didWarnAboutStringRefs = {}; /** - * Warn if there's no key explicitly set on dynamic arrays of children or - * object keys are not valid. This allows us to keep track of children between - * updates. + * Warns if there is a duplicate or missing key */ - ownerHasKeyUseWarning = {}; - ownerHasFunctionTypeWarning = {}; - - warnForMissingKey = function (child, returnFiber) { - if (child === null || typeof child !== "object") { - return; - } - - if (!child._store || child._store.validated || child.key != null) { - return; - } + function warnOnInvalidKey(child, knownKeys, returnFiber) { + { + if (typeof child !== "object" || child === null) { + return knownKeys; + } - if (typeof child._store !== "object") { - throw new Error( - "React Component in warnForMissingKey should have a _store. " + - "This error is likely caused by a bug in React. Please file an issue." - ); - } // $FlowFixMe unable to narrow type from mixed to writable object + switch (child.$$typeof) { + case REACT_ELEMENT_TYPE: + case REACT_PORTAL_TYPE: + warnForMissingKey(child, returnFiber); + var key = child.key; - child._store.validated = true; - var componentName = getComponentNameFromFiber(returnFiber) || "Component"; + if (typeof key !== "string") { + break; + } - if (ownerHasKeyUseWarning[componentName]) { - return; - } + if (knownKeys === null) { + knownKeys = new Set(); + knownKeys.add(key); + break; + } - ownerHasKeyUseWarning[componentName] = true; + if (!knownKeys.has(key)) { + knownKeys.add(key); + break; + } - error( - "Each child in a list should have a unique " + - '"key" prop. See https://reactjs.org/link/warning-keys for ' + - "more information." - ); - }; -} + 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 isReactClass(type) { - return type.prototype && type.prototype.isReactComponent; -} + break; -function coerceRef(returnFiber, current, element) { - var mixedRef = element.ref; + case REACT_LAZY_TYPE: + var payload = child._payload; + var init = child._init; + warnOnInvalidKey(init(payload), knownKeys, returnFiber); + break; + } + } - if ( - mixedRef !== null && - typeof mixedRef !== "function" && - typeof mixedRef !== "object" + 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. { - if ( - // We warn in ReactElement.js if owner and self are equal for string refs - // because these cannot be automatically converted to an arrow function - // using a codemod. Therefore, we don't have to warn about string refs again. - !( - element._owner && - element._self && - element._owner.stateNode !== element._self - ) && // Will already throw with "Function components cannot have string refs" - !(element._owner && element._owner.tag !== ClassComponent) && // Will already warn with "Function components cannot be given refs" - !(typeof element.type === "function" && !isReactClass(element.type)) && // Will already throw with "Element ref was specified as a string (someStringRef) but no owner was set" - element._owner - ) { - var componentName = - getComponentNameFromFiber(returnFiber) || "Component"; - - if (!didWarnAboutStringRefs[componentName]) { - error( - 'Component "%s" contains the string ref "%s". Support for string refs ' + - "will be removed in a future major release. We recommend using " + - "useRef() or createRef() instead. " + - "Learn more about using refs safely here: " + - "https://reactjs.org/link/strict-mode-string-ref", - componentName, - mixedRef - ); + // First, validate keys. + var knownKeys = null; - didWarnAboutStringRefs[componentName] = true; - } + for (var i = 0; i < newChildren.length; i++) { + var child = newChildren[i]; + knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); } } - if (element._owner) { - var owner = element._owner; - var inst; + var resultingFirstChild = null; + var previousNewFiber = null; + var oldFiber = currentFirstChild; + var lastPlacedIndex = 0; + var newIdx = 0; + var nextOldFiber = null; - if (owner) { - var ownerFiber = owner; + for (; oldFiber !== null && newIdx < newChildren.length; newIdx++) { + if (oldFiber.index > newIdx) { + nextOldFiber = oldFiber; + oldFiber = null; + } else { + nextOldFiber = oldFiber.sibling; + } - if (ownerFiber.tag !== ClassComponent) { - throw new Error( - "Function components cannot have string refs. " + - "We recommend using useRef() instead. " + - "Learn more about using refs safely here: " + - "https://reactjs.org/link/strict-mode-string-ref" - ); + var newFiber = updateSlot( + returnFiber, + oldFiber, + newChildren[newIdx], + lanes + ); + + if (newFiber === null) { + // TODO: This breaks on empty slots like null children. That's + // unfortunate because it triggers the slow path all the time. We need + // a better way to communicate whether this was a miss or null, + // boolean, undefined, etc. + if (oldFiber === null) { + oldFiber = nextOldFiber; } - inst = ownerFiber.stateNode; + break; } - if (!inst) { - throw new Error( - "Missing owner for string ref " + - mixedRef + - ". This error is likely caused by a " + - "bug in React. Please file an issue." - ); - } // Assigning this to a const so Flow knows it won't change in the closure - - var resolvedInst = inst; - - { - checkPropStringCoercion(mixedRef, "ref"); + if (shouldTrackSideEffects) { + if (oldFiber && newFiber.alternate === null) { + // We matched the slot, but we didn't reuse the existing fiber, so we + // need to delete the existing child. + deleteChild(returnFiber, oldFiber); + } } - var stringRef = "" + mixedRef; // Check if previous string ref matches new string ref + lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx); - if ( - current !== null && - current.ref !== null && - typeof current.ref === "function" && - current.ref._stringRef === stringRef - ) { - return current.ref; + if (previousNewFiber === null) { + // TODO: Move out of the loop. This only happens for the first run. + resultingFirstChild = newFiber; + } else { + // TODO: Defer siblings if we're not at the right index for this slot. + // I.e. if we had null values before, then we want to defer this + // for each null value. However, we also don't want to call updateSlot + // with the previous one. + previousNewFiber.sibling = newFiber; } - var ref = function (value) { - var refs = resolvedInst.refs; - - if (value === null) { - delete refs[stringRef]; - } else { - refs[stringRef] = value; - } - }; + previousNewFiber = newFiber; + oldFiber = nextOldFiber; + } - 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 (newIdx === newChildren.length) { + // We've reached the end of the new children. We can delete the rest. + deleteRemainingChildren(returnFiber, oldFiber); - if (!element._owner) { - throw new Error( - "Element ref was specified as a string (" + - mixedRef + - ") but no owner was set. This could happen for one of" + - " the following reasons:\n" + - "1. You may be adding a ref to a function component\n" + - "2. You may be adding a ref to a component that was not created inside a component's render method\n" + - "3. You have multiple copies of React loaded\n" + - "See https://reactjs.org/link/refs-must-have-owner for more information." - ); - } + return resultingFirstChild; } - } - return mixedRef; -} + 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 throwOnInvalidObjectType(returnFiber, newChild) { - // $FlowFixMe[method-unbinding] - var childString = Object.prototype.toString.call(newChild); - throw new Error( - "Objects are not valid as a React child (found: " + - (childString === "[object Object]" - ? "object with keys {" + Object.keys(newChild).join(", ") + "}" - : childString) + - "). " + - "If you meant to render a collection of children, use an array " + - "instead." - ); -} + if (_newFiber === null) { + continue; + } -function warnOnFunctionType(returnFiber) { - { - var componentName = getComponentNameFromFiber(returnFiber) || "Component"; + lastPlacedIndex = placeChild(_newFiber, lastPlacedIndex, newIdx); - if (ownerHasFunctionTypeWarning[componentName]) { - return; - } + if (previousNewFiber === null) { + // TODO: Move out of the loop. This only happens for the first run. + resultingFirstChild = _newFiber; + } else { + previousNewFiber.sibling = _newFiber; + } - ownerHasFunctionTypeWarning[componentName] = true; + previousNewFiber = _newFiber; + } - 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." - ); - } -} + return resultingFirstChild; + } // Add all children to a key map for quick lookups. -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 existingChildren = mapRemainingChildren(returnFiber, oldFiber); // Keep scanning and use the map to restore deleted items as moves. -function createChildReconciler(shouldTrackSideEffects) { - function deleteChild(returnFiber, childToDelete) { - if (!shouldTrackSideEffects) { - // Noop. - return; - } + for (; newIdx < newChildren.length; newIdx++) { + var _newFiber2 = updateFromMap( + existingChildren, + returnFiber, + newIdx, + newChildren[newIdx], + lanes + ); - var deletions = returnFiber.deletions; + 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 (deletions === null) { - returnFiber.deletions = [childToDelete]; - returnFiber.flags |= ChildDeletion; - } else { - deletions.push(childToDelete); - } - } + lastPlacedIndex = placeChild(_newFiber2, lastPlacedIndex, newIdx); - 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 (previousNewFiber === null) { + resultingFirstChild = _newFiber2; + } else { + previousNewFiber.sibling = _newFiber2; + } - var childToDelete = currentFirstChild; + previousNewFiber = _newFiber2; + } + } - while (childToDelete !== null) { - deleteChild(returnFiber, childToDelete); - childToDelete = childToDelete.sibling; + 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 null; + return resultingFirstChild; } - function mapRemainingChildren(returnFiber, currentFirstChild) { - // Add the remaining children to a temporary map so that we can find them by - // keys quickly. Implicit (null) keys get added to this set with their index - // instead. - var existingChildren = new Map(); - var existingChild = currentFirstChild; - - while (existingChild !== null) { - if (existingChild.key !== null) { - existingChildren.set(existingChild.key, existingChild); - } else { - existingChildren.set(existingChild.index, existingChild); - } + function reconcileChildrenIterator( + returnFiber, + currentFirstChild, + newChildrenIterable, + lanes + ) { + // This is the same implementation as reconcileChildrenArray(), + // but using the iterator instead. + var iteratorFn = getIteratorFn(newChildrenIterable); - existingChild = existingChild.sibling; + 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 existingChildren; - } + { + // 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." + ); + } - 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; - } + didWarnAboutGenerators = true; + } // Warn about using Maps as children - function placeChild(newFiber, lastPlacedIndex, newIndex) { - newFiber.index = newIndex; + if (newChildrenIterable.entries === iteratorFn) { + if (!didWarnAboutMaps) { + error( + "Using Maps as children is not supported. " + + "Use an array of keyed ReactElements instead." + ); + } - 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; - } + didWarnAboutMaps = true; + } // First, validate keys. + // We'll get a different iterator later for the main pass. - var current = newFiber.alternate; + var _newChildren = iteratorFn.call(newChildrenIterable); - if (current !== null) { - var oldIndex = current.index; + if (_newChildren) { + var knownKeys = null; - if (oldIndex < lastPlacedIndex) { - // This is a move. - newFiber.flags |= Placement | PlacementDEV; - return lastPlacedIndex; - } else { - // This item can stay in place. - return oldIndex; - } - } else { - // This is an insertion. - newFiber.flags |= Placement | PlacementDEV; - return lastPlacedIndex; - } - } + var _step = _newChildren.next(); - function placeSingleChild(newFiber) { - // This is simpler for the single child case. We only need to do a - // placement for inserting new children. - if (shouldTrackSideEffects && newFiber.alternate === null) { - newFiber.flags |= Placement | PlacementDEV; + for (; !_step.done; _step = _newChildren.next()) { + var child = _step.value; + knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); + } + } } - return newFiber; - } + var newChildren = iteratorFn.call(newChildrenIterable); - 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 (newChildren == null) { + throw new Error("An iterable object provided no iterator."); } - } - function updateElement(returnFiber, current, element, lanes) { - var elementType = element.type; + var resultingFirstChild = null; + var previousNewFiber = null; + var oldFiber = currentFirstChild; + var lastPlacedIndex = 0; + var newIdx = 0; + var nextOldFiber = null; + var step = newChildren.next(); - if (elementType === REACT_FRAGMENT_TYPE) { - return updateFragment( - returnFiber, - current, - element.props.children, - lanes, - element.key - ); - } + for ( + ; + oldFiber !== null && !step.done; + newIdx++, step = newChildren.next() + ) { + if (oldFiber.index > newIdx) { + nextOldFiber = oldFiber; + oldFiber = null; + } else { + nextOldFiber = oldFiber.sibling; + } - 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; + var newFiber = updateSlot(returnFiber, oldFiber, step.value, lanes); - { - existing._debugSource = element._source; - existing._debugOwner = element._owner; + 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; } - return existing; + break; } - } // Insert - var created = createFiberFromElement(element, returnFiber.mode, lanes); - created.ref = coerceRef(returnFiber, current, element); - created.return = returnFiber; - return created; - } + 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 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; - } - } + lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx); - 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 (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 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; + previousNewFiber = newFiber; + oldFiber = nextOldFiber; } - if (typeof newChild === "object" && newChild !== null) { - switch (newChild.$$typeof) { - case REACT_ELEMENT_TYPE: { - var _created = createFiberFromElement( - newChild, - returnFiber.mode, - lanes - ); - - _created.ref = coerceRef(returnFiber, null, newChild); - _created.return = returnFiber; - return _created; - } + if (step.done) { + // We've reached the end of the new children. We can delete the rest. + deleteRemainingChildren(returnFiber, oldFiber); - case REACT_PORTAL_TYPE: { - var _created2 = createFiberFromPortal( - newChild, - returnFiber.mode, - lanes - ); + return resultingFirstChild; + } - _created2.return = returnFiber; - return _created2; - } + 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); - case REACT_LAZY_TYPE: { - var payload = newChild._payload; - var init = newChild._init; - return createChild(returnFiber, init(payload), lanes); + if (_newFiber3 === null) { + continue; } - } - - if (isArray(newChild) || getIteratorFn(newChild)) { - var _created3 = createFiberFromFragment( - newChild, - returnFiber.mode, - lanes, - null - ); - _created3.return = returnFiber; - return _created3; - } + lastPlacedIndex = placeChild(_newFiber3, lastPlacedIndex, newIdx); - throwOnInvalidObjectType(returnFiber, newChild); - } + if (previousNewFiber === null) { + // TODO: Move out of the loop. This only happens for the first run. + resultingFirstChild = _newFiber3; + } else { + previousNewFiber.sibling = _newFiber3; + } - { - if (typeof newChild === "function") { - warnOnFunctionType(returnFiber); + previousNewFiber = _newFiber3; } - } - - return null; - } - - function updateSlot(returnFiber, oldFiber, newChild, lanes) { - // Update the fiber if the keys match, otherwise return null. - var key = oldFiber !== null ? oldFiber.key : null; - if ( - (typeof newChild === "string" && newChild !== "") || - typeof newChild === "number" - ) { - // Text nodes don't have keys. If the previous node is implicitly keyed - // we can continue to replace it without aborting even if it is not a text - // node. - if (key !== null) { - return null; - } + return resultingFirstChild; + } // Add all children to a key map for quick lookups. - return updateTextNode(returnFiber, oldFiber, "" + newChild, lanes); - } + var existingChildren = mapRemainingChildren(returnFiber, oldFiber); // Keep scanning and use the map to restore deleted items as moves. - 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; - } - } + for (; !step.done; newIdx++, step = newChildren.next()) { + var _newFiber4 = updateFromMap( + existingChildren, + returnFiber, + newIdx, + step.value, + lanes + ); - case REACT_PORTAL_TYPE: { - if (newChild.key === key) { - return updatePortal(returnFiber, oldFiber, newChild, lanes); - } else { - return null; + 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 + ); } } - case REACT_LAZY_TYPE: { - var payload = newChild._payload; - var init = newChild._init; - return updateSlot(returnFiber, oldFiber, init(payload), lanes); - } - } + lastPlacedIndex = placeChild(_newFiber4, lastPlacedIndex, newIdx); - if (isArray(newChild) || getIteratorFn(newChild)) { - if (key !== null) { - return null; + if (previousNewFiber === null) { + resultingFirstChild = _newFiber4; + } else { + previousNewFiber.sibling = _newFiber4; } - return updateFragment(returnFiber, oldFiber, newChild, lanes, null); + previousNewFiber = _newFiber4; } - - throwOnInvalidObjectType(returnFiber, newChild); } - { - if (typeof newChild === "function") { - warnOnFunctionType(returnFiber); - } + 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 null; + return resultingFirstChild; } - function updateFromMap( - existingChildren, + function reconcileSingleTextNode( returnFiber, - newIdx, - newChild, + currentFirstChild, + textContent, 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); - } + // 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. - if (typeof newChild === "object" && newChild !== null) { - switch (newChild.$$typeof) { - case REACT_ELEMENT_TYPE: { - var _matchedFiber = - existingChildren.get( - newChild.key === null ? newIdx : newChild.key - ) || null; + deleteRemainingChildren(returnFiber, currentFirstChild); + var created = createFiberFromText(textContent, returnFiber.mode, lanes); + created.return = returnFiber; + return created; + } - return updateElement(returnFiber, _matchedFiber, newChild, lanes); - } + function reconcileSingleElement( + returnFiber, + currentFirstChild, + element, + lanes + ) { + var key = element.key; + var child = currentFirstChild; - case REACT_PORTAL_TYPE: { - var _matchedFiber2 = - existingChildren.get( - newChild.key === null ? newIdx : newChild.key - ) || 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) { + var elementType = element.type; - return updatePortal(returnFiber, _matchedFiber2, newChild, lanes); + if (elementType === REACT_FRAGMENT_TYPE) { + if (child.tag === Fragment) { + deleteRemainingChildren(returnFiber, child.sibling); + var existing = useFiber(child, element.props.children); + existing.return = returnFiber; + + { + existing._debugSource = element._source; + existing._debugOwner = element._owner; + } + + return existing; + } + } else { + if ( + child.elementType === elementType || // Keep this check inline so it only runs on the false path: + isCompatibleFamilyForHotReloading(child, element) || // Lazy types should reconcile their resolved type. + // We need to do this after the Hot Reloading check above, + // because hot reloading has different semantics than prod because + // it doesn't resuspend. So we can't let the call below suspend. + (typeof elementType === "object" && + elementType !== null && + elementType.$$typeof === REACT_LAZY_TYPE && + resolveLazy(elementType) === child.type) + ) { + deleteRemainingChildren(returnFiber, child.sibling); + + var _existing = useFiber(child, element.props); + + _existing.ref = coerceRef(returnFiber, child, element); + _existing.return = returnFiber; + + { + _existing._debugSource = element._source; + _existing._debugOwner = element._owner; + } + + return _existing; + } + } // Didn't match. + + deleteRemainingChildren(returnFiber, child); + break; + } else { + deleteChild(returnFiber, child); + } + + child = child.sibling; + } + + if (element.type === REACT_FRAGMENT_TYPE) { + var created = createFiberFromFragment( + element.props.children, + returnFiber.mode, + lanes, + element.key + ); + created.return = returnFiber; + return created; + } else { + var _created4 = createFiberFromElement(element, returnFiber.mode, lanes); + + _created4.ref = coerceRef(returnFiber, currentFirstChild, element); + _created4.return = returnFiber; + return _created4; + } + } + + function reconcileSinglePortal( + returnFiber, + currentFirstChild, + portal, + lanes + ) { + var key = portal.key; + var child = currentFirstChild; + + while (child !== null) { + // TODO: If key === null and child.key === null, then this only applies to + // the first item in the list. + if (child.key === key) { + if ( + child.tag === HostPortal && + child.stateNode.containerInfo === portal.containerInfo && + child.stateNode.implementation === portal.implementation + ) { + deleteRemainingChildren(returnFiber, child.sibling); + var existing = useFiber(child, portal.children || []); + existing.return = returnFiber; + return existing; + } else { + deleteRemainingChildren(returnFiber, child); + break; } + } else { + deleteChild(returnFiber, child); + } + + child = child.sibling; + } + + var created = createFiberFromPortal(portal, returnFiber.mode, lanes); + created.return = returnFiber; + return created; + } // This API will tag the children with the side-effect of the reconciliation + // itself. They will be added to the side-effect list as we pass through the + // children and the parent. + + function reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + newChild, + lanes + ) { + // This function is not recursive. + // If the top level item is an array, we treat it as a set of children, + // not as a fragment. Nested arrays on the other hand will be treated as + // fragment nodes. Recursion happens at the normal flow. + // Handle top level unkeyed fragments as if they were arrays. + // This leads to an ambiguity between <>{[...]} and <>.... + // We treat the ambiguous cases above the same. + // TODO: Let's use recursion like we do for Usable nodes? + var isUnkeyedTopLevelFragment = + typeof newChild === "object" && + newChild !== null && + newChild.type === REACT_FRAGMENT_TYPE && + newChild.key === null; + + if (isUnkeyedTopLevelFragment) { + newChild = newChild.props.children; + } // Handle object types + + if (typeof newChild === "object" && newChild !== null) { + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE: + return placeSingleChild( + reconcileSingleElement( + returnFiber, + currentFirstChild, + newChild, + lanes + ) + ); + + case REACT_PORTAL_TYPE: + return placeSingleChild( + reconcileSinglePortal( + returnFiber, + currentFirstChild, + newChild, + lanes + ) + ); case REACT_LAZY_TYPE: var payload = newChild._payload; - var init = newChild._init; - return updateFromMap( - existingChildren, + var init = newChild._init; // TODO: This function is supposed to be non-recursive. + + return reconcileChildFibers( returnFiber, - newIdx, + currentFirstChild, init(payload), lanes ); } - if (isArray(newChild) || getIteratorFn(newChild)) { - var _matchedFiber3 = existingChildren.get(newIdx) || null; + if (isArray(newChild)) { + return reconcileChildrenArray( + returnFiber, + currentFirstChild, + newChild, + lanes + ); + } - return updateFragment( + if (getIteratorFn(newChild)) { + return reconcileChildrenIterator( returnFiber, - _matchedFiber3, + currentFirstChild, newChild, - lanes, - null + lanes + ); + } // Usables are a valid React node type. When React encounters a Usable in + // a child position, it unwraps it using the same algorithm as `use`. For + // example, for promises, React will throw an exception to unwind the + // stack, then replay the component once the promise resolves. + // + // A difference from `use` is that React will keep unwrapping the value + // until it reaches a non-Usable type. + // + // e.g. Usable>> should resolve to T + // + // The structure is a bit unfortunate. Ideally, we shouldn't need to + // replay the entire begin phase of the parent fiber in order to reconcile + // the children again. This would require a somewhat significant refactor, + // because reconcilation happens deep within the begin phase, and + // depending on the type of work, not always at the end. We should + // consider as an future improvement. + + if (typeof newChild.then === "function") { + var thenable = newChild; + return reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + unwrapThenable(thenable), + lanes + ); + } + + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) { + var context = newChild; + return reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + readContextDuringReconcilation(returnFiber, context, lanes), + lanes ); } throwOnInvalidObjectType(returnFiber, newChild); } + if ( + (typeof newChild === "string" && newChild !== "") || + typeof newChild === "number" + ) { + return placeSingleChild( + reconcileSingleTextNode( + returnFiber, + currentFirstChild, + "" + newChild, + lanes + ) + ); + } + { if (typeof newChild === "function") { warnOnFunctionType(returnFiber); } - } + } // Remaining cases are all treated as empty. - return null; + return deleteRemainingChildren(returnFiber, currentFirstChild); } - /** - * Warns if there is a duplicate or missing key - */ - function warnOnInvalidKey(child, knownKeys, returnFiber) { - { - if (typeof child !== "object" || child === null) { - return knownKeys; - } + function reconcileChildFibers( + returnFiber, + currentFirstChild, + newChild, + lanes + ) { + // This indirection only exists so we can reset `thenableState` at the end. + // It should get inlined by Closure. + thenableIndexCounter$1 = 0; + var firstChildFiber = reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + newChild, + lanes + ); + thenableState$1 = null; // Don't bother to reset `thenableIndexCounter` to 0 because it always gets + // set at the beginning. - switch (child.$$typeof) { - case REACT_ELEMENT_TYPE: - case REACT_PORTAL_TYPE: - warnForMissingKey(child, returnFiber); - var key = child.key; - - if (typeof key !== "string") { - break; - } - - if (knownKeys === null) { - knownKeys = new Set(); - knownKeys.add(key); - break; - } + return firstChildFiber; + } - if (!knownKeys.has(key)) { - knownKeys.add(key); - break; - } + return reconcileChildFibers; +} - 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 - ); +var reconcileChildFibers = createChildReconciler(true); +var mountChildFibers = createChildReconciler(false); +function resetChildReconcilerOnUnwind() { + // On unwind, clear any pending thenables that were used. + thenableState$1 = null; + thenableIndexCounter$1 = 0; +} +function cloneChildFibers(current, workInProgress) { + if (current !== null && workInProgress.child !== current.child) { + throw new Error("Resuming work not yet implemented."); + } - break; + if (workInProgress.child === null) { + return; + } - case REACT_LAZY_TYPE: - var payload = child._payload; - var init = child._init; - warnOnInvalidKey(init(payload), knownKeys, returnFiber); - break; - } - } + var currentChild = workInProgress.child; + var newChild = createWorkInProgress(currentChild, currentChild.pendingProps); + workInProgress.child = newChild; + newChild.return = workInProgress; - return knownKeys; + while (currentChild.sibling !== null) { + currentChild = currentChild.sibling; + newChild = newChild.sibling = createWorkInProgress( + currentChild, + currentChild.pendingProps + ); + newChild.return = workInProgress; } - function reconcileChildrenArray( - returnFiber, - currentFirstChild, - newChildren, - lanes - ) { - // This algorithm can't optimize by searching from both ends since we - // don't have backpointers on fibers. I'm trying to see how far we can get - // with that model. If it ends up not being worth the tradeoffs, we can - // add it later. - // Even with a two ended optimization, we'd want to optimize for the case - // where there are few changes and brute force the comparison instead of - // going for the Map. It'd like to explore hitting that path first in - // forward-only mode and only go for the Map once we notice that we need - // lots of look ahead. This doesn't handle reversal as well as two ended - // search but that's unusual. Besides, for the two ended optimization to - // work on Iterables, we'd need to copy the whole set. - // In this first iteration, we'll just live with hitting the bad case - // (adding everything to a Map) in for every insert/move. - // If you change this code, also update reconcileChildrenIterator() which - // uses the same algorithm. - { - // First, validate keys. - var knownKeys = null; - - for (var i = 0; i < newChildren.length; i++) { - var child = newChildren[i]; - knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); - } - } + newChild.sibling = null; +} // Reset a workInProgress child set to prepare it for a second pass. - var resultingFirstChild = null; - var previousNewFiber = null; - var oldFiber = currentFirstChild; - var lastPlacedIndex = 0; - var newIdx = 0; - var nextOldFiber = null; +function resetChildFibers(workInProgress, lanes) { + var child = workInProgress.child; - for (; oldFiber !== null && newIdx < newChildren.length; newIdx++) { - if (oldFiber.index > newIdx) { - nextOldFiber = oldFiber; - oldFiber = null; - } else { - nextOldFiber = oldFiber.sibling; - } + while (child !== null) { + resetWorkInProgress(child, lanes); + child = child.sibling; + } +} - var newFiber = updateSlot( - returnFiber, - oldFiber, - newChildren[newIdx], - lanes - ); +// TODO: This isn't being used yet, but it's intended to replace the +// InvisibleParentContext that is currently managed by SuspenseContext. - 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; - } +var currentTreeHiddenStackCursor = createCursor(null); +var prevRenderLanesStackCursor = createCursor(NoLanes); +function pushHiddenContext(fiber, context) { + var prevRenderLanes = getRenderLanes(); + push(prevRenderLanesStackCursor, prevRenderLanes, fiber); + push(currentTreeHiddenStackCursor, context, fiber); // When rendering a subtree that's currently hidden, we must include all + // lanes that would have rendered if the hidden subtree hadn't been deferred. + // That is, in order to reveal content from hidden -> visible, we must commit + // all the updates that we skipped when we originally hid the tree. - break; - } + setRenderLanes(mergeLanes(prevRenderLanes, context.baseLanes)); +} +function reuseHiddenContextOnStack(fiber) { + // This subtree is not currently hidden, so we don't need to add any lanes + // to the render lanes. But we still need to push something to avoid a + // context mismatch. Reuse the existing context on the stack. + push(prevRenderLanesStackCursor, getRenderLanes(), fiber); + push( + currentTreeHiddenStackCursor, + currentTreeHiddenStackCursor.current, + fiber + ); +} +function popHiddenContext(fiber) { + // Restore the previous render lanes from the stack + setRenderLanes(prevRenderLanesStackCursor.current); + pop(currentTreeHiddenStackCursor, fiber); + pop(prevRenderLanesStackCursor, fiber); +} +function isCurrentTreeHidden() { + return currentTreeHiddenStackCursor.current !== null; +} - 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); - } - } +// suspends, i.e. it's the nearest `catch` block on the stack. - lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx); +var suspenseHandlerStackCursor = createCursor(null); // Represents the outermost boundary that is not visible in the current tree. +// Everything above this is the "shell". When this is null, it means we're +// rendering in the shell of the app. If it's non-null, it means we're rendering +// deeper than the shell, inside a new tree that wasn't already visible. +// +// The main way we use this concept is to determine whether showing a fallback +// would result in a desirable or undesirable loading state. Activing a fallback +// in the shell is considered an undersirable loading state, because it would +// mean hiding visible (albeit stale) content in the current tree — we prefer to +// show the stale content, rather than switch to a fallback. But showing a +// fallback in a new tree is fine, because there's no stale content to +// prefer instead. - if (previousNewFiber === null) { - // TODO: Move out of the loop. This only happens for the first run. - resultingFirstChild = newFiber; - } else { - // TODO: Defer siblings if we're not at the right index for this slot. - // I.e. if we had null values before, then we want to defer this - // for each null value. However, we also don't want to call updateSlot - // with the previous one. - previousNewFiber.sibling = newFiber; - } +var shellBoundary = null; +function getShellBoundary() { + return shellBoundary; +} +function pushPrimaryTreeSuspenseHandler(handler) { + // TODO: Pass as argument + var current = handler.alternate; + // to push a nested Suspense handler, because it will get replaced by the + // outer fallback, anyway. Consider this as a future optimization. - previousNewFiber = newFiber; - oldFiber = nextOldFiber; - } + push(suspenseHandlerStackCursor, handler, handler); - if (newIdx === newChildren.length) { - // We've reached the end of the new children. We can delete the rest. - deleteRemainingChildren(returnFiber, oldFiber); + if (shellBoundary === null) { + if (current === null || isCurrentTreeHidden()) { + // This boundary is not visible in the current UI. + shellBoundary = handler; + } else { + var prevState = current.memoizedState; - return resultingFirstChild; + if (prevState !== null) { + // This boundary is showing a fallback in the current UI. + shellBoundary = handler; + } } + } +} +function pushFallbackTreeSuspenseHandler(fiber) { + // We're about to render the fallback. If something in the fallback suspends, + // it's akin to throwing inside of a `catch` block. This boundary should not + // capture. Reuse the existing handler on the stack. + reuseSuspenseHandlerOnStack(fiber); +} +function pushOffscreenSuspenseHandler(fiber) { + if (fiber.tag === OffscreenComponent) { + push(suspenseHandlerStackCursor, fiber, fiber); - if (oldFiber === null) { - // If we don't have any more existing children we can choose a fast path - // since the rest will all be insertions. - for (; newIdx < newChildren.length; newIdx++) { - var _newFiber = createChild(returnFiber, newChildren[newIdx], lanes); - - if (_newFiber === null) { - continue; - } + if (shellBoundary !== null); + else { + var current = fiber.alternate; - lastPlacedIndex = placeChild(_newFiber, lastPlacedIndex, newIdx); + if (current !== null) { + var prevState = current.memoizedState; - if (previousNewFiber === null) { - // TODO: Move out of the loop. This only happens for the first run. - resultingFirstChild = _newFiber; - } else { - previousNewFiber.sibling = _newFiber; + if (prevState !== null) { + // This is the first boundary in the stack that's already showing + // a fallback. So everything outside is considered the shell. + shellBoundary = fiber; } - - previousNewFiber = _newFiber; } + } + } else { + // This is a LegacyHidden component. + reuseSuspenseHandlerOnStack(fiber); + } +} +function reuseSuspenseHandlerOnStack(fiber) { + push(suspenseHandlerStackCursor, getSuspenseHandler(), fiber); +} +function getSuspenseHandler() { + return suspenseHandlerStackCursor.current; +} +function popSuspenseHandler(fiber) { + pop(suspenseHandlerStackCursor, fiber); - return resultingFirstChild; - } // Add all children to a key map for quick lookups. - - var existingChildren = mapRemainingChildren(returnFiber, oldFiber); // Keep scanning and use the map to restore deleted items as moves. - - for (; newIdx < newChildren.length; newIdx++) { - var _newFiber2 = updateFromMap( - existingChildren, - returnFiber, - newIdx, - newChildren[newIdx], - lanes - ); + if (shellBoundary === fiber) { + // Popping back into the shell. + shellBoundary = null; + } +} // SuspenseList context +// TODO: Move to a separate module? We may change the SuspenseList +// implementation to hide/show in the commit phase, anyway. - 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 - ); - } - } +var DefaultSuspenseContext = 0; +var SubtreeSuspenseContextMask = 1; // ForceSuspenseFallback can be used by SuspenseList to force newly added +// items into their fallback state during one of the render passes. - lastPlacedIndex = placeChild(_newFiber2, lastPlacedIndex, newIdx); +var ForceSuspenseFallback = 2; +var suspenseStackCursor = createCursor(DefaultSuspenseContext); +function hasSuspenseListContext(parentContext, flag) { + return (parentContext & flag) !== 0; +} +function setDefaultShallowSuspenseListContext(parentContext) { + return parentContext & SubtreeSuspenseContextMask; +} +function setShallowSuspenseListContext(parentContext, shallowContext) { + return (parentContext & SubtreeSuspenseContextMask) | shallowContext; +} +function pushSuspenseListContext(fiber, newContext) { + push(suspenseStackCursor, newContext, fiber); +} +function popSuspenseListContext(fiber) { + pop(suspenseStackCursor, fiber); +} - if (previousNewFiber === null) { - resultingFirstChild = _newFiber2; - } else { - previousNewFiber.sibling = _newFiber2; +// A non-null SuspenseState means that it is blocked for one reason or another. +// - A non-null dehydrated field means it's blocked pending hydration. +// - A non-null dehydrated field can use isSuspenseInstancePending or +// isSuspenseInstanceFallback to query the reason for being dehydrated. +// - A null dehydrated field means it's blocked by something suspending and +// we're currently showing a fallback instead. + +function findFirstSuspended(row) { + var node = row; + + while (node !== null) { + if (node.tag === SuspenseComponent) { + var state = node.memoizedState; + + if (state !== null) { + var dehydrated = state.dehydrated; + + if ( + dehydrated === null || + isSuspenseInstancePending() || + isSuspenseInstanceFallback() + ) { + return node; } + } + } else if ( + node.tag === SuspenseListComponent && // revealOrder undefined can't be trusted because it don't + // keep track of whether it suspended or not. + node.memoizedProps.revealOrder !== undefined + ) { + var didSuspend = (node.flags & DidCapture) !== NoFlags$1; - previousNewFiber = _newFiber2; + if (didSuspend) { + return node; } + } else if (node.child !== null) { + node.child.return = node; + node = node.child; + continue; } - 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 (node === row) { + return null; } - return resultingFirstChild; - } - - function reconcileChildrenIterator( - returnFiber, - currentFirstChild, - newChildrenIterable, - lanes - ) { - // This is the same implementation as reconcileChildrenArray(), - // but using the iterator instead. - var iteratorFn = getIteratorFn(newChildrenIterable); + while (node.sibling === null) { + if (node.return === null || node.return === row) { + 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." - ); + node = node.return; } - { - // 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." - ); - } + node.sibling.return = node.return; + node = node.sibling; + } - didWarnAboutGenerators = true; - } // Warn about using Maps as children + return null; +} - if (newChildrenIterable.entries === iteratorFn) { - if (!didWarnAboutMaps) { - error( - "Using Maps as children is not supported. " + - "Use an array of keyed ReactElements instead." - ); - } +var NoFlags = + /* */ + 0; // Represents whether effect should fire. - didWarnAboutMaps = true; - } // First, validate keys. - // We'll get a different iterator later for the main pass. +var HasEffect = + /* */ + 1; // Represents the phase in which the effect (not the clean-up) fires. - var _newChildren = iteratorFn.call(newChildrenIterable); +var Insertion = + /* */ + 2; +var Layout = + /* */ + 4; +var Passive = + /* */ + 8; - if (_newChildren) { - var knownKeys = null; +// and should be reset before starting a new render. +// This tracks which mutable sources need to be reset after a render. - var _step = _newChildren.next(); +var workInProgressSources = []; +var rendererSigil$1; - for (; !_step.done; _step = _newChildren.next()) { - var child = _step.value; - knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); - } - } - } +{ + // Used to detect multiple renderers using the same mutable source. + rendererSigil$1 = {}; +} - var newChildren = iteratorFn.call(newChildrenIterable); +function markSourceAsDirty(mutableSource) { + workInProgressSources.push(mutableSource); +} +function resetWorkInProgressVersions() { + for (var i = 0; i < workInProgressSources.length; i++) { + var mutableSource = workInProgressSources[i]; - if (newChildren == null) { - throw new Error("An iterable object provided no iterator."); + { + mutableSource._workInProgressVersionSecondary = null; } + } - var resultingFirstChild = null; - var previousNewFiber = null; - var oldFiber = currentFirstChild; - var lastPlacedIndex = 0; - var newIdx = 0; - var nextOldFiber = null; - var step = newChildren.next(); + workInProgressSources.length = 0; +} +function getWorkInProgressVersion(mutableSource) { + { + return mutableSource._workInProgressVersionSecondary; + } +} +function setWorkInProgressVersion(mutableSource, version) { + { + mutableSource._workInProgressVersionSecondary = version; + } - for ( - ; - oldFiber !== null && !step.done; - newIdx++, step = newChildren.next() - ) { - if (oldFiber.index > newIdx) { - nextOldFiber = oldFiber; - oldFiber = null; - } else { - nextOldFiber = oldFiber.sibling; + workInProgressSources.push(mutableSource); +} +function warnAboutMultipleRenderersDEV(mutableSource) { + { + { + if (mutableSource._currentSecondaryRenderer == null) { + mutableSource._currentSecondaryRenderer = rendererSigil$1; + } else if (mutableSource._currentSecondaryRenderer !== rendererSigil$1) { + error( + "Detected multiple renderers concurrently rendering the " + + "same mutable source. This is currently unsupported." + ); } + } + } +} // Eager reads the version of a mutable source and stores it on the root. - var newFiber = updateSlot(returnFiber, oldFiber, step.value, lanes); +var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, + ReactCurrentBatchConfig$2 = ReactSharedInternals.ReactCurrentBatchConfig; +var didWarnAboutMismatchedHooksForComponent; +var didWarnUncachedGetSnapshot; +var didWarnAboutUseWrappedInTryCatch; - 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; - } +{ + didWarnAboutMismatchedHooksForComponent = new Set(); + didWarnAboutUseWrappedInTryCatch = new Set(); +} // These are set right before calling the component. - break; - } +var renderLanes$1 = NoLanes; // The work-in-progress fiber. I've named it differently to distinguish it from +// the work-in-progress hook. - if (shouldTrackSideEffects) { - if (oldFiber && newFiber.alternate === null) { - // We matched the slot, but we didn't reuse the existing fiber, so we - // need to delete the existing child. - deleteChild(returnFiber, oldFiber); - } - } +var 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. - lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx); +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 (previousNewFiber === null) { - // TODO: Move out of the loop. This only happens for the first run. - resultingFirstChild = newFiber; - } else { - // TODO: Defer siblings if we're not at the right index for this slot. - // I.e. if we had null values before, then we want to defer this - // for each null value. However, we also don't want to call updateSlot - // with the previous one. - previousNewFiber.sibling = newFiber; - } +var 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`. - previousNewFiber = newFiber; - oldFiber = nextOldFiber; - } +var didScheduleRenderPhaseUpdateDuringThisPass = false; +var shouldDoubleInvokeUserFnsInHooksDEV = false; // Counts the number of useId hooks in this component. - if (step.done) { - // We've reached the end of the new children. We can delete the rest. - deleteRemainingChildren(returnFiber, oldFiber); +var thenableIndexCounter = 0; +var thenableState = null; // Used for ids that are generated completely client-side (i.e. not during +// hydration). This counter is global, so client ids are not stable across +// render attempts. - return resultingFirstChild; - } +var globalClientIdCounter = 0; +var RE_RENDER_LIMIT = 25; // In DEV, this is the name of the currently executing primitive hook - 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); +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. - if (_newFiber3 === null) { - continue; - } +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. - lastPlacedIndex = placeChild(_newFiber3, lastPlacedIndex, newIdx); +var ignorePreviousDependencies = false; - if (previousNewFiber === null) { - // TODO: Move out of the loop. This only happens for the first run. - resultingFirstChild = _newFiber3; - } else { - previousNewFiber.sibling = _newFiber3; - } +function mountHookTypesDev() { + { + var hookName = currentHookNameInDev; - previousNewFiber = _newFiber3; - } + if (hookTypesDev === null) { + hookTypesDev = [hookName]; + } else { + hookTypesDev.push(hookName); + } + } +} - return resultingFirstChild; - } // Add all children to a key map for quick lookups. +function updateHookTypesDev() { + { + var hookName = currentHookNameInDev; - var existingChildren = mapRemainingChildren(returnFiber, oldFiber); // Keep scanning and use the map to restore deleted items as moves. + if (hookTypesDev !== null) { + hookTypesUpdateIndexDev++; - for (; !step.done; newIdx++, step = newChildren.next()) { - var _newFiber4 = updateFromMap( - existingChildren, - returnFiber, - newIdx, - step.value, - lanes + if (hookTypesDev[hookTypesUpdateIndexDev] !== hookName) { + warnOnHookMismatchInDev(hookName); + } + } + } +} + +function checkDepsAreArrayDev(deps) { + { + if (deps !== undefined && deps !== null && !isArray(deps)) { + // Verify deps, but only on mount to avoid extra checks. + // It's unlikely their type would change as usually you define them inline. + error( + "%s received a final argument that is not an array (instead, received `%s`). When " + + "specified, the final argument must be an array.", + currentHookNameInDev, + typeof deps ); + } + } +} - 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 warnOnHookMismatchInDev(currentHookName) { + { + var componentName = getComponentNameFromFiber(currentlyRenderingFiber$1); - lastPlacedIndex = placeChild(_newFiber4, lastPlacedIndex, newIdx); + if (!didWarnAboutMismatchedHooksForComponent.has(componentName)) { + didWarnAboutMismatchedHooksForComponent.add(componentName); - if (previousNewFiber === null) { - resultingFirstChild = _newFiber4; - } else { - previousNewFiber.sibling = _newFiber4; + 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; } - previousNewFiber = _newFiber4; + error( + "React has detected a change in the order of Hooks called by %s. " + + "This will lead to bugs and errors if not fixed. " + + "For more information, read the Rules of Hooks: https://reactjs.org/link/rules-of-hooks\n\n" + + " Previous render Next render\n" + + " ------------------------------------------------------\n" + + "%s" + + " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + componentName, + table + ); } } + } +} - 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 throwInvalidHookError() { + throw new Error( + "Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for" + + " one of the following reasons:\n" + + "1. You might have mismatching versions of React and the renderer (such as React DOM)\n" + + "2. You might be breaking the Rules of Hooks\n" + + "3. You might have more than one copy of React in the same app\n" + + "See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem." + ); +} - return resultingFirstChild; +function areHookInputsEqual(nextDeps, prevDeps) { + { + if (ignorePreviousDependencies) { + // Only true when this component is being hot reloaded. + return false; + } } - 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. + 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 + ); + } - deleteRemainingChildren(returnFiber, currentFirstChild); - var created = createFiberFromText(textContent, returnFiber.mode, lanes); - created.return = returnFiber; - return created; + return false; } - function reconcileSingleElement( - returnFiber, - currentFirstChild, - element, - lanes - ) { - var key = element.key; - var child = currentFirstChild; - - while (child !== null) { - // TODO: If key === null and child.key === null, then this only applies to - // the first item in the list. - if (child.key === key) { - var elementType = element.type; - - if (elementType === REACT_FRAGMENT_TYPE) { - if (child.tag === Fragment) { - deleteRemainingChildren(returnFiber, child.sibling); - var existing = useFiber(child, element.props.children); - existing.return = returnFiber; + { + // Don't bother comparing lengths in prod because these arrays should be + // passed inline. + if (nextDeps.length !== prevDeps.length) { + error( + "The final argument passed to %s changed size between renders. The " + + "order and size of this array must remain constant.\n\n" + + "Previous: %s\n" + + "Incoming: %s", + currentHookNameInDev, + "[" + prevDeps.join(", ") + "]", + "[" + nextDeps.join(", ") + "]" + ); + } + } // $FlowFixMe[incompatible-use] found when upgrading Flow - { - existing._debugSource = element._source; - existing._debugOwner = element._owner; - } + for (var i = 0; i < prevDeps.length && i < nextDeps.length; i++) { + // $FlowFixMe[incompatible-use] found when upgrading Flow + if (objectIs(nextDeps[i], prevDeps[i])) { + continue; + } - return 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); + return false; + } - var _existing = useFiber(child, element.props); + return true; +} - _existing.ref = coerceRef(returnFiber, child, element); - _existing.return = returnFiber; +function renderWithHooks( + current, + workInProgress, + Component, + props, + secondArg, + nextRenderLanes +) { + renderLanes$1 = nextRenderLanes; + currentlyRenderingFiber$1 = workInProgress; - { - _existing._debugSource = element._source; - _existing._debugOwner = element._owner; - } + { + hookTypesDev = current !== null ? current._debugHookTypes : null; + hookTypesUpdateIndexDev = -1; // Used for hot reloading: - return _existing; - } - } // Didn't match. + ignorePreviousDependencies = + current !== null && current.type !== workInProgress.type; + } - deleteRemainingChildren(returnFiber, child); - break; - } else { - deleteChild(returnFiber, child); - } + workInProgress.memoizedState = null; + workInProgress.updateQueue = null; + workInProgress.lanes = NoLanes; // The following should have already been reset + // currentHook = null; + // workInProgressHook = null; + // didScheduleRenderPhaseUpdate = false; + // localIdCounter = 0; + // thenableIndexCounter = 0; + // thenableState = null; + // TODO Warn if no hooks are used at all during mount, then some are used during update. + // Currently we will identify the update render as a mount because memoizedState === null. + // This is tricky because it's valid for certain types of components (e.g. React.lazy) + // Using memoizedState to differentiate between mount/update only works if at least one stateful hook is used. + // Non-stateful hooks (e.g. context) don't get added to memoizedState, + // so memoizedState would be null during updates and mounts. - child = child.sibling; + { + if (current !== null && current.memoizedState !== null) { + ReactCurrentDispatcher$1.current = HooksDispatcherOnUpdateInDEV; + } else if (hookTypesDev !== null) { + // This dispatcher handles an edge case where a component is updating, + // but no stateful hooks have been used. + // We want to match the production code behavior (which will use HooksDispatcherOnMount), + // but with the extra DEV validation to ensure hooks ordering hasn't changed. + // This dispatcher does that. + ReactCurrentDispatcher$1.current = + HooksDispatcherOnMountWithHookTypesInDEV; + } else { + ReactCurrentDispatcher$1.current = HooksDispatcherOnMountInDEV; } + } // In Strict Mode, during development, user functions are double invoked to + // help detect side effects. The logic for how this is implemented for in + // hook components is a bit complex so let's break it down. + // + // We will invoke the entire component function twice. However, during the + // second invocation of the component, the hook state from the first + // invocation will be reused. That means things like `useMemo` functions won't + // run again, because the deps will match and the memoized result will + // be reused. + // + // We want memoized functions to run twice, too, so account for this, user + // functions are double invoked during the *first* invocation of the component + // function, and are *not* double invoked during the second incovation: + // + // - First execution of component function: user functions are double invoked + // - Second execution of component function (in Strict Mode, during + // development): user functions are not double invoked. + // + // This is intentional for a few reasons; most importantly, it's because of + // how `use` works when something suspends: it reuses the promise that was + // passed during the first attempt. This is itself a form of memoization. + // We need to be able to memoize the reactive inputs to the `use` call using + // a hook (i.e. `useMemo`), which means, the reactive inputs to `use` must + // come from the same component invocation as the output. + // + // There are plenty of tests to ensure this behavior is correct. - 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); + var shouldDoubleRenderDEV = + (workInProgress.mode & StrictLegacyMode) !== NoMode; + shouldDoubleInvokeUserFnsInHooksDEV = shouldDoubleRenderDEV; + var children = Component(props, secondArg); + shouldDoubleInvokeUserFnsInHooksDEV = false; // Check if there was a render phase update - _created4.ref = coerceRef(returnFiber, currentFirstChild, element); - _created4.return = returnFiber; - return _created4; - } + if (didScheduleRenderPhaseUpdateDuringThisPass) { + // Keep rendering until the component stabilizes (there are no more render + // phase updates). + children = renderWithHooksAgain( + workInProgress, + Component, + props, + secondArg + ); } - 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); - } + if (shouldDoubleRenderDEV) { + // In development, components are invoked twice to help detect side effects. + setIsStrictModeForDevtools(true); - child = child.sibling; + try { + children = renderWithHooksAgain( + workInProgress, + Component, + props, + secondArg + ); + } finally { + setIsStrictModeForDevtools(false); } + } - 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. + finishRenderingHooks(current, workInProgress); + return children; +} - 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; +function finishRenderingHooks(current, workInProgress) { + // 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 (isUnkeyedTopLevelFragment) { - newChild = newChild.props.children; - } // Handle object types + { + 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. - if (typeof newChild === "object" && newChild !== null) { - switch (newChild.$$typeof) { - case REACT_ELEMENT_TYPE: - return placeSingleChild( - reconcileSingleElement( - returnFiber, - currentFirstChild, - newChild, - lanes - ) - ); - - case REACT_PORTAL_TYPE: - return placeSingleChild( - reconcileSinglePortal( - returnFiber, - currentFirstChild, - newChild, - lanes - ) - ); - - case REACT_LAZY_TYPE: - var payload = newChild._payload; - var init = newChild._init; // TODO: This function is supposed to be non-recursive. - - return reconcileChildFibers( - returnFiber, - currentFirstChild, - init(payload), - lanes - ); - } - - if (isArray(newChild)) { - return reconcileChildrenArray( - returnFiber, - currentFirstChild, - newChild, - lanes - ); - } - - if (getIteratorFn(newChild)) { - return reconcileChildrenIterator( - returnFiber, - currentFirstChild, - newChild, - lanes - ); - } + var didRenderTooFewHooks = currentHook !== null && currentHook.next !== null; + renderLanes$1 = NoLanes; + currentlyRenderingFiber$1 = null; + currentHook = null; + workInProgressHook = null; - throwOnInvalidObjectType(returnFiber, newChild); - } + { + 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 ( - (typeof newChild === "string" && newChild !== "") || - typeof newChild === "number" + 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 ) { - return placeSingleChild( - reconcileSingleTextNode( - returnFiber, - currentFirstChild, - "" + newChild, - lanes - ) + error( + "Internal React error: Expected static flag was missing. Please " + + "notify the React team." ); } - - { - if (typeof newChild === "function") { - warnOnFunctionType(returnFiber); - } - } // Remaining cases are all treated as empty. - - return deleteRemainingChildren(returnFiber, currentFirstChild); - } - - return reconcileChildFibers; -} - -var reconcileChildFibers = createChildReconciler(true); -var mountChildFibers = createChildReconciler(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; - } + didScheduleRenderPhaseUpdate = false; // This is reset by checkDidRenderIdHook + // localIdCounter = 0; - var currentChild = workInProgress.child; - var newChild = createWorkInProgress(currentChild, currentChild.pendingProps); - workInProgress.child = newChild; - newChild.return = workInProgress; + thenableIndexCounter = 0; + thenableState = null; - while (currentChild.sibling !== null) { - currentChild = currentChild.sibling; - newChild = newChild.sibling = createWorkInProgress( - currentChild, - currentChild.pendingProps + if (didRenderTooFewHooks) { + throw new Error( + "Rendered fewer hooks than expected. This may be caused by an accidental " + + "early return statement." ); - newChild.return = workInProgress; } - newChild.sibling = null; -} // Reset a workInProgress child set to prepare it for a second pass. + { + if (checkIfUseWrappedInTryCatch()) { + var componentName = + getComponentNameFromFiber(workInProgress) || "Unknown"; -function resetChildFibers(workInProgress, lanes) { - var child = workInProgress.child; + if (!didWarnAboutUseWrappedInTryCatch.has(componentName)) { + didWarnAboutUseWrappedInTryCatch.add(componentName); - while (child !== null) { - resetWorkInProgress(child, lanes); - child = child.sibling; + error( + "`use` was called from inside a try/catch block. This is not allowed " + + "and can lead to unexpected behavior. To handle errors triggered " + + "by `use`, wrap your component in a error boundary." + ); + } + } } } -// TODO: This isn't being used yet, but it's intended to replace the -// InvisibleParentContext that is currently managed by SuspenseContext. +function replaySuspendedComponentWithHooks( + current, + workInProgress, + Component, + props, + secondArg +) { + // This function is used to replay a component that previously suspended, + // after its data resolves. + // + // It's a simplified version of renderWithHooks, but it doesn't need to do + // most of the set up work because they weren't reset when we suspended; they + // only get reset when the component either completes (finishRenderingHooks) + // or unwinds (resetHooksOnUnwind). + { + hookTypesUpdateIndexDev = -1; // Used for hot reloading: -var currentTreeHiddenStackCursor = createCursor(null); -var prevRenderLanesStackCursor = createCursor(NoLanes); -function pushHiddenContext(fiber, context) { - var prevRenderLanes = getRenderLanes(); - push(prevRenderLanesStackCursor, prevRenderLanes, fiber); - push(currentTreeHiddenStackCursor, context, fiber); // When rendering a subtree that's currently hidden, we must include all - // lanes that would have rendered if the hidden subtree hadn't been deferred. - // That is, in order to reveal content from hidden -> visible, we must commit - // all the updates that we skipped when we originally hid the tree. + ignorePreviousDependencies = + current !== null && current.type !== workInProgress.type; + } - setRenderLanes(mergeLanes(prevRenderLanes, context.baseLanes)); -} -function reuseHiddenContextOnStack(fiber) { - // This subtree is not currently hidden, so we don't need to add any lanes - // to the render lanes. But we still need to push something to avoid a - // context mismatch. Reuse the existing context on the stack. - push(prevRenderLanesStackCursor, getRenderLanes(), fiber); - push( - currentTreeHiddenStackCursor, - currentTreeHiddenStackCursor.current, - fiber + var children = renderWithHooksAgain( + workInProgress, + Component, + props, + secondArg ); -} -function popHiddenContext(fiber) { - // Restore the previous render lanes from the stack - setRenderLanes(prevRenderLanesStackCursor.current); - pop(currentTreeHiddenStackCursor, fiber); - pop(prevRenderLanesStackCursor, fiber); -} -function isCurrentTreeHidden() { - return currentTreeHiddenStackCursor.current !== null; + finishRenderingHooks(current, workInProgress); + return children; } -// suspends, i.e. it's the nearest `catch` block on the stack. +function renderWithHooksAgain(workInProgress, Component, props, secondArg) { + // This is used to perform another render pass. It's used when setState is + // called during render, and for double invoking components in Strict Mode + // during development. + // + // The state from the previous pass is reused whenever possible. So, state + // updates that were already processed are not processed again, and memoized + // functions (`useMemo`) are not invoked again. + // + // Keep rendering in a loop for as long as render phase updates continue to + // be scheduled. Use a counter to prevent infinite loops. + var numberOfReRenders = 0; + var children; -var suspenseHandlerStackCursor = createCursor(null); // Represents the outermost boundary that is not visible in the current tree. -// Everything above this is the "shell". When this is null, it means we're -// rendering in the shell of the app. If it's non-null, it means we're rendering -// deeper than the shell, inside a new tree that wasn't already visible. -// -// The main way we use this concept is to determine whether showing a fallback -// would result in a desirable or undesirable loading state. Activing a fallback -// in the shell is considered an undersirable loading state, because it would -// mean hiding visible (albeit stale) content in the current tree — we prefer to -// show the stale content, rather than switch to a fallback. But showing a -// fallback in a new tree is fine, because there's no stale content to -// prefer instead. + do { + if (didScheduleRenderPhaseUpdateDuringThisPass) { + // It's possible that a use() value depended on a state that was updated in + // this rerender, so we need to watch for different thenables this time. + thenableState = null; + } -var shellBoundary = null; -function getShellBoundary() { - return shellBoundary; -} -function pushPrimaryTreeSuspenseHandler(handler) { - // TODO: Pass as argument - var current = handler.alternate; - // to push a nested Suspense handler, because it will get replaced by the - // outer fallback, anyway. Consider this as a future optimization. + thenableIndexCounter = 0; + didScheduleRenderPhaseUpdateDuringThisPass = false; - push(suspenseHandlerStackCursor, handler, handler); + if (numberOfReRenders >= RE_RENDER_LIMIT) { + throw new Error( + "Too many re-renders. React limits the number of renders to prevent " + + "an infinite loop." + ); + } - if (shellBoundary === null) { - if (current === null || isCurrentTreeHidden()) { - // This boundary is not visible in the current UI. - shellBoundary = handler; - } else { - var prevState = current.memoizedState; + numberOfReRenders += 1; - if (prevState !== null) { - // This boundary is showing a fallback in the current UI. - shellBoundary = handler; - } - } - } -} -function pushFallbackTreeSuspenseHandler(fiber) { - // We're about to render the fallback. If something in the fallback suspends, - // it's akin to throwing inside of a `catch` block. This boundary should not - // capture. Reuse the existing handler on the stack. - reuseSuspenseHandlerOnStack(fiber); -} -function pushOffscreenSuspenseHandler(fiber) { - if (fiber.tag === OffscreenComponent) { - push(suspenseHandlerStackCursor, fiber, fiber); - - if (shellBoundary !== null); - else { - var current = fiber.alternate; + { + // 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 (current !== null) { - var prevState = current.memoizedState; + currentHook = null; + workInProgressHook = null; + workInProgress.updateQueue = null; - if (prevState !== null) { - // This is the first boundary in the stack that's already showing - // a fallback. So everything outside is considered the shell. - shellBoundary = fiber; - } - } + { + // Also validate hook order for cascading updates. + hookTypesUpdateIndexDev = -1; } - } else { - // This is a LegacyHidden component. - reuseSuspenseHandlerOnStack(fiber); - } -} -function reuseSuspenseHandlerOnStack(fiber) { - push(suspenseHandlerStackCursor, getSuspenseHandler(), fiber); -} -function getSuspenseHandler() { - return suspenseHandlerStackCursor.current; + + ReactCurrentDispatcher$1.current = HooksDispatcherOnRerenderInDEV; + children = Component(props, secondArg); + } while (didScheduleRenderPhaseUpdateDuringThisPass); + + return children; } -function popSuspenseHandler(fiber) { - pop(suspenseHandlerStackCursor, fiber); +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 (shellBoundary === fiber) { - // Popping back into the shell. - shellBoundary = null; + if ((workInProgress.mode & StrictEffectsMode) !== NoMode) { + workInProgress.flags &= ~( + MountPassiveDev | + MountLayoutDev | + Passive$1 | + Update + ); + } else { + workInProgress.flags &= ~(Passive$1 | Update); } -} // SuspenseList context -// TODO: Move to a separate module? We may change the SuspenseList -// implementation to hide/show in the commit phase, anyway. - -var DefaultSuspenseContext = 0; -var SubtreeSuspenseContextMask = 1; // ForceSuspenseFallback can be used by SuspenseList to force newly added -// items into their fallback state during one of the render passes. -var ForceSuspenseFallback = 2; -var suspenseStackCursor = createCursor(DefaultSuspenseContext); -function hasSuspenseListContext(parentContext, flag) { - return (parentContext & flag) !== 0; -} -function setDefaultShallowSuspenseListContext(parentContext) { - return parentContext & SubtreeSuspenseContextMask; -} -function setShallowSuspenseListContext(parentContext, shallowContext) { - return (parentContext & SubtreeSuspenseContextMask) | shallowContext; -} -function pushSuspenseListContext(fiber, newContext) { - push(suspenseStackCursor, newContext, fiber); + current.lanes = removeLanes(current.lanes, lanes); } -function popSuspenseListContext(fiber) { - pop(suspenseStackCursor, fiber); +function resetHooksAfterThrow() { + // This is called immediaetly after a throw. It shouldn't reset the entire + // module state, because the work loop might decide to replay the component + // again without rewinding. + // + // It should only reset things like the current dispatcher, to prevent hooks + // from being called outside of a component. + // We can assume the previous dispatcher is always this one, since we set it + // at the beginning of the render phase and there's no re-entrance. + ReactCurrentDispatcher$1.current = ContextOnlyDispatcher; } +function resetHooksOnUnwind() { + 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; -// A non-null SuspenseState means that it is blocked for one reason or another. -// - A non-null dehydrated field means it's blocked pending hydration. -// - A non-null dehydrated field can use isSuspenseInstancePending or -// isSuspenseInstanceFallback to query the reason for being dehydrated. -// - A null dehydrated field means it's blocked by something suspending and -// we're currently showing a fallback instead. - -function findFirstSuspended(row) { - var node = row; - - while (node !== null) { - if (node.tag === SuspenseComponent) { - var state = node.memoizedState; - - if (state !== null) { - var dehydrated = state.dehydrated; - - if ( - dehydrated === null || - isSuspenseInstancePending() || - isSuspenseInstanceFallback() - ) { - return node; - } - } - } else if ( - node.tag === SuspenseListComponent && // revealOrder undefined can't be trusted because it don't - // keep track of whether it suspended or not. - node.memoizedProps.revealOrder !== undefined - ) { - var didSuspend = (node.flags & DidCapture) !== NoFlags$1; + while (hook !== null) { + var queue = hook.queue; - if (didSuspend) { - return node; + if (queue !== null) { + queue.pending = null; } - } else if (node.child !== null) { - node.child.return = node; - node = node.child; - continue; - } - if (node === row) { - return null; + hook = hook.next; } - while (node.sibling === null) { - if (node.return === null || node.return === row) { - return null; - } + didScheduleRenderPhaseUpdate = false; + } - node = node.return; - } + renderLanes$1 = NoLanes; + currentlyRenderingFiber$1 = null; + currentHook = null; + workInProgressHook = null; - node.sibling.return = node.return; - node = node.sibling; + { + hookTypesDev = null; + hookTypesUpdateIndexDev = -1; + currentHookNameInDev = null; } - return null; + didScheduleRenderPhaseUpdateDuringThisPass = false; + thenableIndexCounter = 0; + thenableState = null; } -var NoFlags = - /* */ - 0; // Represents whether effect should fire. - -var HasEffect = - /* */ - 1; // Represents the phase in which the effect (not the clean-up) fires. - -var Insertion = - /* */ - 2; -var Layout = - /* */ - 4; -var Passive = - /* */ - 8; - -// and should be reset before starting a new render. -// This tracks which mutable sources need to be reset after a render. +function mountWorkInProgressHook() { + var hook = { + memoizedState: null, + baseState: null, + baseQueue: null, + queue: null, + next: null + }; -var workInProgressSources = []; -var rendererSigil$1; + 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; + } -{ - // Used to detect multiple renderers using the same mutable source. - rendererSigil$1 = {}; + return workInProgressHook; } -function markSourceAsDirty(mutableSource) { - workInProgressSources.push(mutableSource); -} -function resetWorkInProgressVersions() { - for (var i = 0; i < workInProgressSources.length; i++) { - var mutableSource = workInProgressSources[i]; +function updateWorkInProgressHook() { + // This function is used both for updates and for re-renders triggered by a + // render phase update. It assumes there is either a current hook we can + // clone, or a work-in-progress hook from a previous render pass that we can + // use as a base. + var nextCurrentHook; - { - mutableSource._workInProgressVersionSecondary = null; + if (currentHook === null) { + var current = currentlyRenderingFiber$1.alternate; + + if (current !== null) { + nextCurrentHook = current.memoizedState; + } else { + nextCurrentHook = null; } + } else { + nextCurrentHook = currentHook.next; } - workInProgressSources.length = 0; -} -function getWorkInProgressVersion(mutableSource) { - { - return mutableSource._workInProgressVersionSecondary; - } -} -function setWorkInProgressVersion(mutableSource, version) { - { - mutableSource._workInProgressVersionSecondary = version; - } + var nextWorkInProgressHook; - workInProgressSources.push(mutableSource); -} -function warnAboutMultipleRenderersDEV(mutableSource) { - { - { - if (mutableSource._currentSecondaryRenderer == null) { - mutableSource._currentSecondaryRenderer = rendererSigil$1; - } else if (mutableSource._currentSecondaryRenderer !== rendererSigil$1) { - error( - "Detected multiple renderers concurrently rendering the " + - "same mutable source. This is currently unsupported." + if (workInProgressHook === null) { + nextWorkInProgressHook = currentlyRenderingFiber$1.memoizedState; + } else { + nextWorkInProgressHook = workInProgressHook.next; + } + + if (nextWorkInProgressHook !== null) { + // There's already a work-in-progress. Reuse it. + workInProgressHook = nextWorkInProgressHook; + nextWorkInProgressHook = workInProgressHook.next; + currentHook = nextCurrentHook; + } else { + // Clone from the current hook. + if (nextCurrentHook === null) { + var currentFiber = currentlyRenderingFiber$1.alternate; + + if (currentFiber === null) { + // This is the initial render. This branch is reached when the component + // suspends, resumes, then renders an additional hook. + // Should never be reached because we should switch to the mount dispatcher first. + throw new Error( + "Update hook called on initial render. This is likely a bug in React. Please file an issue." ); + } else { + // This is an update. We should always have a current hook. + throw new Error("Rendered more hooks than during the previous render."); } } + + currentHook = nextCurrentHook; + var newHook = { + memoizedState: currentHook.memoizedState, + baseState: currentHook.baseState, + baseQueue: currentHook.baseQueue, + queue: currentHook.queue, + next: null + }; + + if (workInProgressHook === null) { + // This is the first hook in the list. + currentlyRenderingFiber$1.memoizedState = workInProgressHook = newHook; + } else { + // Append to the end of the list. + workInProgressHook = workInProgressHook.next = newHook; + } } -} // Eager reads the version of a mutable source and stores it on the root. -var ReactCurrentActQueue$2 = ReactSharedInternals.ReactCurrentActQueue; // An error that is thrown (e.g. by `use`) to trigger Suspense. If we -// detect this is caught by userspace, we'll log a warning in development. + return workInProgressHook; +} // NOTE: defining two versions of this function to avoid size impact when this feature is disabled. +// Previously this function was inlined, the additional `memoCache` property makes it not inlined. -var SuspenseException = new Error( - "Suspense Exception: This is not a real error! It's an implementation " + - "detail of `use` to interrupt the current render. You must either " + - "rethrow it immediately, or move the `use` call outside of the " + - "`try/catch` block. Capturing without rethrowing will lead to " + - "unexpected behavior.\n\n" + - "To handle async errors, wrap your component in an error boundary, or " + - "call the promise's `.catch` method and pass the result to `use`" -); -function createThenableState() { - // The ThenableState is created the first time a component suspends. If it - // suspends again, we'll reuse the same state. - return []; -} -function isThenableResolved(thenable) { - var status = thenable.status; - return status === "fulfilled" || status === "rejected"; +var createFunctionComponentUpdateQueue; + +{ + createFunctionComponentUpdateQueue = function () { + return { + lastEffect: null, + events: null, + stores: null, + memoCache: null + }; + }; } -function noop() {} +function use(usable) { + if (usable !== null && typeof usable === "object") { + // $FlowFixMe[method-unbinding] + if (typeof usable.then === "function") { + // This is a thenable. + var thenable = usable; // Track the position of the thenable within this fiber. -function trackUsedThenable(thenableState, thenable, index) { - if (ReactCurrentActQueue$2.current !== null) { - ReactCurrentActQueue$2.didUsePromise = true; - } + var index = thenableIndexCounter; + thenableIndexCounter += 1; - var previous = thenableState[index]; + if (thenableState === null) { + thenableState = createThenableState(); + } - if (previous === undefined) { - thenableState.push(thenable); - } else { - if (previous !== thenable) { - // Reuse the previous thenable, and drop the new one. We can assume - // they represent the same value, because components are idempotent. - // Avoid an unhandled rejection errors for the Promises that we'll - // intentionally ignore. - thenable.then(noop, noop); - thenable = previous; - } - } // We use an expando to track the status and result of a thenable so that we - // can synchronously unwrap the value. Think of this as an extension of the - // Promise API, or a custom interface that is a superset of Thenable. - // - // If the thenable doesn't have a status, set it to "pending" and attach - // a listener that will update its status and result when it resolves. + var result = trackUsedThenable(thenableState, thenable, index); - switch (thenable.status) { - case "fulfilled": { - var fulfilledValue = thenable.value; - return fulfilledValue; - } + if ( + currentlyRenderingFiber$1.alternate === null && + (workInProgressHook === null + ? currentlyRenderingFiber$1.memoizedState === null + : workInProgressHook.next === null) + ) { + // Initial render, and either this is the first time the component is + // called, or there were no Hooks called after this use() the previous + // time (perhaps because it threw). Subsequent Hook calls should use the + // mount dispatcher. + { + ReactCurrentDispatcher$1.current = HooksDispatcherOnMountInDEV; + } + } - case "rejected": { - var rejectedError = thenable.reason; - throw rejectedError; + return result; + } else if ( + usable.$$typeof === REACT_CONTEXT_TYPE || + usable.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) { + var context = usable; + return readContext(context); } + } // eslint-disable-next-line react-internal/safe-string-coercion - default: { - if (typeof thenable.status === "string") { - // Only instrument the thenable if the status if not defined. If - // it's defined, but an unknown value, assume it's been instrumented by - // some custom userspace implementation. We treat it as "pending". - // Attach a dummy listener, to ensure that any lazy initialization can - // happen. Flight lazily parses JSON when the value is actually awaited. - thenable.then(noop, noop); - } else { - var pendingThenable = thenable; - pendingThenable.status = "pending"; - pendingThenable.then( - function (fulfilledValue) { - if (thenable.status === "pending") { - var fulfilledThenable = thenable; - fulfilledThenable.status = "fulfilled"; - fulfilledThenable.value = fulfilledValue; - } - }, - function (error) { - if (thenable.status === "pending") { - var rejectedThenable = thenable; - rejectedThenable.status = "rejected"; - rejectedThenable.reason = error; - } - } - ); - } // Check one more time in case the thenable resolved synchronously. + throw new Error("An unsupported type was passed to use(): " + String(usable)); +} - switch (thenable.status) { - case "fulfilled": { - var fulfilledThenable = thenable; - return fulfilledThenable.value; - } +function useMemoCache(size) { + var memoCache = null; // Fast-path, load memo cache from wip fiber if already prepared - case "rejected": { - var rejectedThenable = thenable; - throw rejectedThenable.reason; - } - } // Suspend. - // - // Throwing here is an implementation detail that allows us to unwind the - // call stack. But we shouldn't allow it to leak into userspace. Throw an - // opaque placeholder value instead of the actual thenable. If it doesn't - // get captured by the work loop, log a warning, because that means - // something in userspace must have caught it. + var updateQueue = currentlyRenderingFiber$1.updateQueue; - suspendedThenable = thenable; + if (updateQueue !== null) { + memoCache = updateQueue.memoCache; + } // Otherwise clone from the current fiber - { - needsToResetSuspendedThenableDEV = true; - } + if (memoCache == null) { + var current = currentlyRenderingFiber$1.alternate; - throw SuspenseException; + if (current !== null) { + var currentUpdateQueue = current.updateQueue; + + if (currentUpdateQueue !== null) { + var currentMemoCache = currentUpdateQueue.memoCache; + + if (currentMemoCache != null) { + memoCache = { + data: currentMemoCache.data.map(function (array) { + return array.slice(); + }), + index: 0 + }; + } + } } + } // Finally fall back to allocating a fresh instance of the cache + + if (memoCache == null) { + memoCache = { + data: [], + index: 0 + }; } -} // This is used to track the actual thenable that suspended so it can be -// passed to the rest of the Suspense implementation — which, for historical -// reasons, expects to receive a thenable. -var suspendedThenable = null; -var needsToResetSuspendedThenableDEV = false; -function getSuspendedThenable() { - // This is called right after `use` suspends by throwing an exception. `use` - // throws an opaque value instead of the thenable itself so that it can't be - // caught in userspace. Then the work loop accesses the actual thenable using - // this function. - if (suspendedThenable === null) { - throw new Error( - "Expected a suspended thenable. This is a bug in React. Please file " + - "an issue." - ); + if (updateQueue === null) { + updateQueue = createFunctionComponentUpdateQueue(); + currentlyRenderingFiber$1.updateQueue = updateQueue; } - var thenable = suspendedThenable; - suspendedThenable = null; + updateQueue.memoCache = memoCache; + var data = memoCache.data[memoCache.index]; - { - needsToResetSuspendedThenableDEV = false; - } + if (data === undefined) { + data = memoCache.data[memoCache.index] = new Array(size); - return thenable; -} -function checkIfUseWrappedInTryCatch() { - { - // This was set right before SuspenseException was thrown, and it should - // have been cleared when the exception was handled. If it wasn't, - // it must have been caught by userspace. - if (needsToResetSuspendedThenableDEV) { - needsToResetSuspendedThenableDEV = false; - return true; + for (var i = 0; i < size; i++) { + data[i] = REACT_MEMO_CACHE_SENTINEL; + } + } else if (data.length !== size) { + // TODO: consider warning or throwing here + { + error( + "Expected a constant size argument for each invocation of useMemoCache. " + + "The previous cache was allocated with size %s but size %s was requested.", + data.length, + size + ); } } - return false; + memoCache.index++; + return data; } -var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, - ReactCurrentBatchConfig$2 = ReactSharedInternals.ReactCurrentBatchConfig; -var didWarnAboutMismatchedHooksForComponent; -var didWarnUncachedGetSnapshot; -var didWarnAboutUseWrappedInTryCatch; - -{ - didWarnAboutMismatchedHooksForComponent = new Set(); - didWarnAboutUseWrappedInTryCatch = new Set(); -} // These are set right before calling the component. - -var renderLanes$1 = NoLanes; // The work-in-progress fiber. I've named it differently to distinguish it from -// the work-in-progress hook. - -var currentlyRenderingFiber$1 = null; // Hooks are stored as a linked list on the fiber's memoizedState field. The -// current hook list is the list that belongs to the current fiber. The -// work-in-progress hook list is a new list that will be added to the -// work-in-progress fiber. - -var currentHook = null; -var workInProgressHook = null; // Whether an update was scheduled at any point during the render phase. This -// does not get reset if we do another render pass; only when we're completely -// finished evaluating this component. This is an optimization so we know -// whether we need to clear render phase updates after a throw. - -var didScheduleRenderPhaseUpdate = false; // Where an update was scheduled only during the current render pass. This -// gets reset after each attempt. -// TODO: Maybe there's some way to consolidate this with -// `didScheduleRenderPhaseUpdate`. Or with `numberOfReRenders`. - -var didScheduleRenderPhaseUpdateDuringThisPass = false; -var shouldDoubleInvokeUserFnsInHooksDEV = false; // Counts the number of useId hooks in this component. - -var thenableIndexCounter = 0; -var thenableState = null; // Used for ids that are generated completely client-side (i.e. not during -// hydration). This counter is global, so client ids are not stable across -// render attempts. - -var globalClientIdCounter = 0; -var RE_RENDER_LIMIT = 25; // In DEV, this is the name of the currently executing primitive hook - -var currentHookNameInDev = null; // In DEV, this list ensures that hooks are called in the same order between renders. -// The list stores the order of hooks used during the initial render (mount). -// Subsequent renders (updates) reference this list. - -var hookTypesDev = null; -var hookTypesUpdateIndexDev = -1; // In DEV, this tracks whether currently rendering component needs to ignore -// the dependencies for Hooks that need them (e.g. useEffect or useMemo). -// When true, such Hooks will always be "remounted". Only used during hot reload. - -var ignorePreviousDependencies = false; - -function mountHookTypesDev() { - { - var hookName = currentHookNameInDev; - - if (hookTypesDev === null) { - hookTypesDev = [hookName]; - } else { - hookTypesDev.push(hookName); - } - } +function basicStateReducer(state, action) { + // $FlowFixMe: Flow doesn't like mixed types + return typeof action === "function" ? action(state) : action; } -function updateHookTypesDev() { - { - var hookName = currentHookNameInDev; - - if (hookTypesDev !== null) { - hookTypesUpdateIndexDev++; +function mountReducer(reducer, initialArg, init) { + var hook = mountWorkInProgressHook(); + var initialState; - if (hookTypesDev[hookTypesUpdateIndexDev] !== hookName) { - warnOnHookMismatchInDev(hookName); - } - } + if (init !== undefined) { + initialState = init(initialArg); + } else { + initialState = initialArg; } -} -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 - ); - } - } + hook.memoizedState = hook.baseState = initialState; + var queue = { + pending: null, + lanes: NoLanes, + dispatch: null, + lastRenderedReducer: reducer, + lastRenderedState: initialState + }; + hook.queue = queue; + var dispatch = (queue.dispatch = dispatchReducerAction.bind( + null, + currentlyRenderingFiber$1, + queue + )); + return [hook.memoizedState, dispatch]; } -function warnOnHookMismatchInDev(currentHookName) { - { - var componentName = getComponentNameFromFiber(currentlyRenderingFiber$1); +function updateReducer(reducer, initialArg, init) { + var hook = updateWorkInProgressHook(); + var queue = hook.queue; - if (!didWarnAboutMismatchedHooksForComponent.has(componentName)) { - didWarnAboutMismatchedHooksForComponent.add(componentName); + if (queue === null) { + throw new Error( + "Should have a queue. This is likely a bug in React. Please file an issue." + ); + } - if (hookTypesDev !== null) { - var table = ""; - var secondColumnStart = 30; + queue.lastRenderedReducer = reducer; + var current = currentHook; // The last rebase update that is NOT part of the base state. - 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 baseQueue = current.baseQueue; // The last pending update that hasn't been processed yet. - while (row.length < secondColumnStart) { - row += " "; - } + var pendingQueue = queue.pending; - row += newHookName + "\n"; - table += row; - } + if (pendingQueue !== null) { + // We have new updates that haven't been processed yet. + // We'll add them to the base queue. + if (baseQueue !== null) { + // Merge the pending queue and the base queue. + var baseFirst = baseQueue.next; + var pendingFirst = pendingQueue.next; + baseQueue.next = pendingFirst; + pendingQueue.next = baseFirst; + } + { + if (current.baseQueue !== baseQueue) { + // Internal invariant that should never happen, but feasibly could in + // the future if we implement resuming, or some form of that. error( - "React has detected a change in the order of Hooks called by %s. " + - "This will lead to bugs and errors if not fixed. " + - "For more information, read the Rules of Hooks: https://reactjs.org/link/rules-of-hooks\n\n" + - " Previous render Next render\n" + - " ------------------------------------------------------\n" + - "%s" + - " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", - componentName, - table + "Internal error: Expected work-in-progress queue to be a clone. " + + "This is a bug in React." ); } } - } -} -function throwInvalidHookError() { - throw new Error( - "Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for" + - " one of the following reasons:\n" + - "1. You might have mismatching versions of React and the renderer (such as React DOM)\n" + - "2. You might be breaking the Rules of Hooks\n" + - "3. You might have more than one copy of React in the same app\n" + - "See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem." - ); -} - -function areHookInputsEqual(nextDeps, prevDeps) { - { - if (ignorePreviousDependencies) { - // Only true when this component is being hot reloaded. - return false; - } + current.baseQueue = baseQueue = pendingQueue; + queue.pending = null; } - 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 (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; - return false; - } + do { + // An extra OffscreenLane bit is added to updates that were made to + // a hidden tree, so that we can distinguish them from updates that were + // already there when the tree was hidden. + var updateLane = removeLanes(update.lane, OffscreenLane); + var isHiddenUpdate = updateLane !== update.lane; // Check if this update was made while the tree was hidden. If so, then + // it's not a "base" update and we should disregard the extra base lanes + // that were added to renderLanes when we entered the Offscreen tree. - { - // Don't bother comparing lengths in prod because these arrays should be - // passed inline. - if (nextDeps.length !== prevDeps.length) { - error( - "The final argument passed to %s changed size between renders. The " + - "order and size of this array must remain constant.\n\n" + - "Previous: %s\n" + - "Incoming: %s", - currentHookNameInDev, - "[" + prevDeps.join(", ") + "]", - "[" + nextDeps.join(", ") + "]" - ); - } - } // $FlowFixMe[incompatible-use] found when upgrading Flow + var shouldSkipUpdate = isHiddenUpdate + ? !isSubsetOfLanes(getWorkInProgressRootRenderLanes(), updateLane) + : !isSubsetOfLanes(renderLanes$1, updateLane); - for (var i = 0; i < prevDeps.length && i < nextDeps.length; i++) { - // $FlowFixMe[incompatible-use] found when upgrading Flow - if (objectIs(nextDeps[i], prevDeps[i])) { - continue; - } + if (shouldSkipUpdate) { + // Priority is insufficient. Skip this update. If this is the first + // skipped update, the previous update/state is the new base + // update/state. + var clone = { + lane: updateLane, + action: update.action, + hasEagerState: update.hasEagerState, + eagerState: update.eagerState, + next: null + }; - return false; - } + 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. - return true; -} + 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. -function renderWithHooks( - current, - workInProgress, - Component, - props, - secondArg, - nextRenderLanes -) { - renderLanes$1 = nextRenderLanes; - currentlyRenderingFiber$1 = workInProgress; + var action = update.action; - { - hookTypesDev = current !== null ? current._debugHookTypes : null; - hookTypesUpdateIndexDev = -1; // Used for hot reloading: + if (shouldDoubleInvokeUserFnsInHooksDEV) { + reducer(newState, action); + } - ignorePreviousDependencies = - current !== null && current.type !== workInProgress.type; - } + if (update.hasEagerState) { + // If this update is a state update (not a reducer) and was processed eagerly, + // we can use the eagerly computed state + newState = update.eagerState; + } else { + newState = reducer(newState, action); + } + } - workInProgress.memoizedState = null; - workInProgress.updateQueue = null; - workInProgress.lanes = NoLanes; // The following should have already been reset - // currentHook = null; - // workInProgressHook = null; - // didScheduleRenderPhaseUpdate = false; - // localIdCounter = 0; - // thenableIndexCounter = 0; - // thenableState = null; - // TODO Warn if no hooks are used at all during mount, then some are used during update. - // Currently we will identify the update render as a mount because memoizedState === null. - // This is tricky because it's valid for certain types of components (e.g. React.lazy) - // Using memoizedState to differentiate between mount/update only works if at least one stateful hook is used. - // Non-stateful hooks (e.g. context) don't get added to memoizedState, - // so memoizedState would be null during updates and mounts. + update = update.next; + } while (update !== null && update !== first); - { - 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; + if (newBaseQueueLast === null) { + newBaseState = newState; } else { - ReactCurrentDispatcher$1.current = HooksDispatcherOnMountInDEV; - } - } // In Strict Mode, during development, user functions are double invoked to - // help detect side effects. The logic for how this is implemented for in - // hook components is a bit complex so let's break it down. - // - // We will invoke the entire component function twice. However, during the - // second invocation of the component, the hook state from the first - // invocation will be reused. That means things like `useMemo` functions won't - // run again, because the deps will match and the memoized result will - // be reused. - // - // We want memoized functions to run twice, too, so account for this, user - // functions are double invoked during the *first* invocation of the component - // function, and are *not* double invoked during the second incovation: - // - // - First execution of component function: user functions are double invoked - // - Second execution of component function (in Strict Mode, during - // development): user functions are not double invoked. - // - // This is intentional for a few reasons; most importantly, it's because of - // how `use` works when something suspends: it reuses the promise that was - // passed during the first attempt. This is itself a form of memoization. - // We need to be able to memoize the reactive inputs to the `use` call using - // a hook (i.e. `useMemo`), which means, the reactive inputs to `use` must - // come from the same component invocation as the output. - // - // There are plenty of tests to ensure this behavior is correct. + newBaseQueueLast.next = newBaseQueueFirst; + } // Mark that the fiber performed work, but only if the new state is + // different from the current state. - var shouldDoubleRenderDEV = - (workInProgress.mode & StrictLegacyMode) !== NoMode; - shouldDoubleInvokeUserFnsInHooksDEV = shouldDoubleRenderDEV; - var children = Component(props, secondArg); - shouldDoubleInvokeUserFnsInHooksDEV = false; // Check if there was a render phase update + if (!objectIs(newState, hook.memoizedState)) { + markWorkInProgressReceivedUpdate(); + } - if (didScheduleRenderPhaseUpdateDuringThisPass) { - // Keep rendering until the component stabilizes (there are no more render - // phase updates). - children = renderWithHooksAgain( - workInProgress, - Component, - props, - secondArg - ); + hook.memoizedState = newState; + hook.baseState = newBaseState; + hook.baseQueue = newBaseQueueLast; + queue.lastRenderedState = newState; } - if (shouldDoubleRenderDEV) { - // In development, components are invoked twice to help detect side effects. - setIsStrictModeForDevtools(true); - - try { - children = renderWithHooksAgain( - workInProgress, - Component, - props, - secondArg - ); - } finally { - setIsStrictModeForDevtools(false); - } + 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; } - finishRenderingHooks(current, workInProgress); - return children; + var dispatch = queue.dispatch; + return [hook.memoizedState, dispatch]; } -function finishRenderingHooks(current, workInProgress) { - // We can assume the previous dispatcher is always this one, since we set it - // at the beginning of the render phase and there's no re-entrance. - ReactCurrentDispatcher$1.current = ContextOnlyDispatcher; +function rerenderReducer(reducer, initialArg, init) { + var hook = updateWorkInProgressHook(); + var queue = hook.queue; - { - 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. + if (queue === null) { + throw new Error( + "Should have a queue. This is likely a bug in React. Please file an issue." + ); + } - var didRenderTooFewHooks = currentHook !== null && currentHook.next !== null; - renderLanes$1 = NoLanes; - currentlyRenderingFiber$1 = null; - currentHook = null; - workInProgressHook = null; + queue.lastRenderedReducer = reducer; // This is a re-render. Apply the new render phase updates to the previous + // work-in-progress hook. - { - 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 dispatch = queue.dispatch; + var lastRenderPhaseUpdate = queue.pending; + var newState = hook.memoizedState; - 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 (lastRenderPhaseUpdate !== null) { + // The queue doesn't persist past this render pass. + queue.pending = null; + var firstRenderPhaseUpdate = lastRenderPhaseUpdate.next; + var update = firstRenderPhaseUpdate; + + do { + // Process this render phase update. We don't have to check the + // priority because it will always be the same as the current + // render's. + var action = update.action; + newState = reducer(newState, action); + update = update.next; + } while (update !== firstRenderPhaseUpdate); // Mark that the fiber performed work, but only if the new state is + // different from the current state. + + if (!objectIs(newState, hook.memoizedState)) { + markWorkInProgressReceivedUpdate(); } - } - didScheduleRenderPhaseUpdate = false; // This is reset by checkDidRenderIdHook - // localIdCounter = 0; + 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. - thenableIndexCounter = 0; - thenableState = null; + if (hook.baseQueue === null) { + hook.baseState = newState; + } - if (didRenderTooFewHooks) { - throw new Error( - "Rendered fewer hooks than expected. This may be caused by an accidental " + - "early return statement." - ); + queue.lastRenderedState = newState; } - { - if (checkIfUseWrappedInTryCatch()) { - var componentName = - getComponentNameFromFiber(workInProgress) || "Unknown"; - - if (!didWarnAboutUseWrappedInTryCatch.has(componentName)) { - didWarnAboutUseWrappedInTryCatch.add(componentName); - - error( - "`use` was called from inside a try/catch block. This is not allowed " + - "and can lead to unexpected behavior. To handle errors triggered " + - "by `use`, wrap your component in a error boundary." - ); - } - } - } + return [newState, dispatch]; } -function replaySuspendedComponentWithHooks( - current, - workInProgress, - Component, - props, - secondArg -) { - // This function is used to replay a component that previously suspended, - // after its data resolves. - // - // It's a simplified version of renderWithHooks, but it doesn't need to do - // most of the set up work because they weren't reset when we suspended; they - // only get reset when the component either completes (finishRenderingHooks) - // or unwinds (resetHooksOnUnwind). +function readFromUnsubscribedMutableSource(root, source, getSnapshot) { { - hookTypesUpdateIndexDev = -1; // Used for hot reloading: - - ignorePreviousDependencies = - current !== null && current.type !== workInProgress.type; + warnAboutMultipleRenderersDEV(source); } - var children = renderWithHooksAgain( - workInProgress, - Component, - props, - secondArg - ); - finishRenderingHooks(current, workInProgress); - return children; -} + var getVersion = source._getVersion; + var version = getVersion(source._source); // Is it safe for this component to read from this source during the current render? -function renderWithHooksAgain(workInProgress, Component, props, secondArg) { - // This is used to perform another render pass. It's used when setState is - // called during render, and for double invoking components in Strict Mode - // during development. - // - // The state from the previous pass is reused whenever possible. So, state - // updates that were already processed are not processed again, and memoized - // functions (`useMemo`) are not invoked again. - // - // Keep rendering in a loop for as long as render phase updates continue to - // be scheduled. Use a counter to prevent infinite loops. - var numberOfReRenders = 0; - var children; + var isSafeToReadFromSource = false; // Check the version first. + // If this render has already been started with a specific version, + // we can use it alone to determine if we can safely read from the source. - do { - if (didScheduleRenderPhaseUpdateDuringThisPass) { - // It's possible that a use() value depended on a state that was updated in - // this rerender, so we need to watch for different thenables this time. - thenableState = null; - } + var currentRenderVersion = getWorkInProgressVersion(source); - thenableIndexCounter = 0; - didScheduleRenderPhaseUpdateDuringThisPass = false; + if (currentRenderVersion !== null) { + // It's safe to read if the store hasn't been mutated since the last time + // we read something. + isSafeToReadFromSource = currentRenderVersion === version; + } else { + // If there's no version, then this is the first time we've read from the + // source during the current render pass, so we need to do a bit more work. + // What we need to determine is if there are any hooks that already + // subscribed to the source, and if so, whether there are any pending + // mutations that haven't been synchronized yet. + // + // If there are no pending mutations, then `root.mutableReadLanes` will be + // empty, and we know we can safely read. + // + // If there *are* pending mutations, we may still be able to safely read + // if the currently rendering lanes are inclusive of the pending mutation + // lanes, since that guarantees that the value we're about to read from + // the source is consistent with the values that we read during the most + // recent mutation. + isSafeToReadFromSource = isSubsetOfLanes( + renderLanes$1, + root.mutableReadLanes + ); - if (numberOfReRenders >= RE_RENDER_LIMIT) { - throw new Error( - "Too many re-renders. React limits the number of renders to prevent " + - "an infinite loop." - ); + if (isSafeToReadFromSource) { + // If it's safe to read from this source during the current render, + // store the version in case other components read from it. + // A changed version number will let those components know to throw and restart the render. + setWorkInProgressVersion(source, version); } + } - numberOfReRenders += 1; - - { - // Even when hot reloading, allow dependencies to stabilize - // after first render to prevent infinite render phase updates. - ignorePreviousDependencies = false; - } // Start over from the beginning of the list - - currentHook = null; - workInProgressHook = null; - workInProgress.updateQueue = null; + if (isSafeToReadFromSource) { + var snapshot = getSnapshot(source._source); { - // Also validate hook order for cascading updates. - hookTypesUpdateIndexDev = -1; + if (typeof snapshot === "function") { + error( + "Mutable source should not return a function as the snapshot value. " + + "Functions may close over mutable values and cause tearing." + ); + } } - ReactCurrentDispatcher$1.current = HooksDispatcherOnRerenderInDEV; - children = Component(props, secondArg); - } while (didScheduleRenderPhaseUpdateDuringThisPass); + return snapshot; + } else { + // This handles the special case of a mutable source being shared between renderers. + // In that case, if the source is mutated between the first and second renderer, + // The second renderer don't know that it needs to reset the WIP version during unwind, + // (because the hook only marks sources as dirty if it's written to their WIP version). + // That would cause this tear check to throw again and eventually be visible to the user. + // We can avoid this infinite loop by explicitly marking the source as dirty. + // + // This can lead to tearing in the first renderer when it resumes, + // but there's nothing we can do about that (short of throwing here and refusing to continue the render). + markSourceAsDirty(source); // Intentioally throw an error to force React to retry synchronously. During + // the synchronous retry, it will block interleaved mutations, so we should + // get a consistent read. Therefore, the following error should never be + // visible to the user. + // We expect this error not to be thrown during the synchronous retry, + // because we blocked interleaved mutations. - return children; + throw new Error( + "Cannot read from mutable source during the current render without tearing. This may be a bug in React. Please file an issue." + ); + } } -function bailoutHooks(current, workInProgress, lanes) { - workInProgress.updateQueue = current.updateQueue; // TODO: Don't need to reset the flags here, because they're reset in the - // complete phase (bubbleProperties). - if ((workInProgress.mode & StrictEffectsMode) !== NoMode) { - workInProgress.flags &= ~( - MountPassiveDev | - MountLayoutDev | - Passive$1 | - Update +function useMutableSource(hook, source, getSnapshot, subscribe) { + 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." ); - } else { - workInProgress.flags &= ~(Passive$1 | Update); } - current.lanes = removeLanes(current.lanes, lanes); -} -function resetHooksAfterThrow() { - // This is called immediaetly after a throw. It shouldn't reset the entire - // module state, because the work loop might decide to replay the component - // again without rewinding. - // - // It should only reset things like the current dispatcher, to prevent hooks - // from being called outside of a component. - // We can assume the previous dispatcher is always this one, since we set it - // at the beginning of the render phase and there's no re-entrance. - ReactCurrentDispatcher$1.current = ContextOnlyDispatcher; -} -function resetHooksOnUnwind() { - 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; + var getVersion = source._getVersion; + var version = getVersion(source._source); + var dispatcher = ReactCurrentDispatcher$1.current; // eslint-disable-next-line prefer-const - while (hook !== null) { - var queue = hook.queue; + var _dispatcher$useState = dispatcher.useState(function () { + return readFromUnsubscribedMutableSource(root, source, getSnapshot); + }), + currentSnapshot = _dispatcher$useState[0], + setSnapshot = _dispatcher$useState[1]; - if (queue !== null) { - queue.pending = null; - } + var snapshot = currentSnapshot; // Grab a handle to the state hook as well. + // We use it to clear the pending update queue if we have a new source. - hook = hook.next; - } + var stateHook = workInProgressHook; + var memoizedState = hook.memoizedState; + var refs = memoizedState.refs; + var prevGetSnapshot = refs.getSnapshot; + var prevSource = memoizedState.source; + var prevSubscribe = memoizedState.subscribe; + var fiber = currentlyRenderingFiber$1; + hook.memoizedState = { + refs: refs, + source: source, + subscribe: subscribe + }; // Sync the values needed by our subscription handler after each commit. - didScheduleRenderPhaseUpdate = false; - } + dispatcher.useEffect( + function () { + refs.getSnapshot = getSnapshot; // Normally the dispatch function for a state hook never changes, + // but this hook recreates the queue in certain cases to avoid updates from stale sources. + // handleChange() below needs to reference the dispatch function without re-subscribing, + // so we use a ref to ensure that it always has the latest version. - renderLanes$1 = NoLanes; - currentlyRenderingFiber$1 = null; - currentHook = null; - workInProgressHook = null; + refs.setSnapshot = setSnapshot; // Check for a possible change between when we last rendered now. - { - hookTypesDev = null; - hookTypesUpdateIndexDev = -1; - currentHookNameInDev = null; - } + var maybeNewVersion = getVersion(source._source); - didScheduleRenderPhaseUpdateDuringThisPass = false; - thenableIndexCounter = 0; - thenableState = null; -} + if (!objectIs(version, maybeNewVersion)) { + var maybeNewSnapshot = getSnapshot(source._source); -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 (typeof maybeNewSnapshot === "function") { + error( + "Mutable source should not return a function as the snapshot value. " + + "Functions may close over mutable values and cause tearing." + ); + } + } -function updateWorkInProgressHook() { - // This function is used both for updates and for re-renders triggered by a - // render phase update. It assumes there is either a current hook we can - // clone, or a work-in-progress hook from a previous render pass that we can - // use as a base. - var nextCurrentHook; + if (!objectIs(snapshot, maybeNewSnapshot)) { + setSnapshot(maybeNewSnapshot); + var lane = requestUpdateLane(fiber); + markRootMutableRead(root, lane); + } // If the source mutated between render and now, + // there may be state updates already scheduled from the old source. + // Entangle the updates so that they render in the same batch. - if (currentHook === null) { - var current = currentlyRenderingFiber$1.alternate; + markRootEntangled(root, root.mutableReadLanes); + } + }, + [getSnapshot, source, subscribe] + ); // If we got a new source or subscribe function, re-subscribe in a passive effect. - if (current !== null) { - nextCurrentHook = current.memoizedState; - } else { - nextCurrentHook = null; - } - } else { - nextCurrentHook = currentHook.next; - } + dispatcher.useEffect( + function () { + var handleChange = function () { + var latestGetSnapshot = refs.getSnapshot; + var latestSetSnapshot = refs.setSnapshot; - var nextWorkInProgressHook; + try { + latestSetSnapshot(latestGetSnapshot(source._source)); // Record a pending mutable source update with the same expiration time. - if (workInProgressHook === null) { - nextWorkInProgressHook = currentlyRenderingFiber$1.memoizedState; - } else { - nextWorkInProgressHook = workInProgressHook.next; - } + var lane = requestUpdateLane(fiber); + markRootMutableRead(root, lane); + } catch (error) { + // A selector might throw after a source mutation. + // e.g. it might try to read from a part of the store that no longer exists. + // In this case we should still schedule an update with React. + // Worst case the selector will throw again and then an error boundary will handle it. + latestSetSnapshot(function () { + throw error; + }); + } + }; - if (nextWorkInProgressHook !== null) { - // There's already a work-in-progress. Reuse it. - workInProgressHook = nextWorkInProgressHook; - nextWorkInProgressHook = workInProgressHook.next; - currentHook = nextCurrentHook; - } else { - // Clone from the current hook. - if (nextCurrentHook === null) { - var currentFiber = currentlyRenderingFiber$1.alternate; + var unsubscribe = subscribe(source._source, handleChange); - if (currentFiber === null) { - // This is the initial render. This branch is reached when the component - // suspends, resumes, then renders an additional hook. - // Should never be reached because we should switch to the mount dispatcher first. - throw new Error( - "Update hook called on initial render. This is likely a bug in React. Please file an issue." - ); - } else { - // This is an update. We should always have a current hook. - throw new Error("Rendered more hooks than during the previous render."); + { + if (typeof unsubscribe !== "function") { + error( + "Mutable source subscribe function must return an unsubscribe function." + ); + } } - } - currentHook = nextCurrentHook; - var newHook = { - memoizedState: currentHook.memoizedState, - baseState: currentHook.baseState, - baseQueue: currentHook.baseQueue, - queue: currentHook.queue, - next: null - }; + return unsubscribe; + }, + [source, subscribe] + ); // If any of the inputs to useMutableSource change, reading is potentially unsafe. + // + // If either the source or the subscription have changed we can't can't trust the update queue. + // Maybe the source changed in a way that the old subscription ignored but the new one depends on. + // + // If the getSnapshot function changed, we also shouldn't rely on the update queue. + // It's possible that the underlying source was mutated between the when the last "change" event fired, + // and when the current render (with the new getSnapshot function) is processed. + // + // In both cases, we need to throw away pending updates (since they are no longer relevant) + // and treat reading from the source as we do in the mount case. - 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 ( + !objectIs(prevGetSnapshot, getSnapshot) || + !objectIs(prevSource, source) || + !objectIs(prevSubscribe, subscribe) + ) { + // Create a new queue and setState method, + // So if there are interleaved updates, they get pushed to the older queue. + // When this becomes current, the previous queue and dispatch method will be discarded, + // including any interleaving updates that occur. + var newQueue = { + pending: null, + lanes: NoLanes, + dispatch: null, + lastRenderedReducer: basicStateReducer, + lastRenderedState: snapshot + }; + newQueue.dispatch = setSnapshot = dispatchSetState.bind( + null, + currentlyRenderingFiber$1, + newQueue + ); + stateHook.queue = newQueue; + stateHook.baseQueue = null; + snapshot = readFromUnsubscribedMutableSource(root, source, getSnapshot); + stateHook.memoizedState = stateHook.baseState = snapshot; } - return workInProgressHook; -} // NOTE: defining two versions of this function to avoid size impact when this feature is disabled. -// Previously this function was inlined, the additional `memoCache` property makes it not inlined. - -var createFunctionComponentUpdateQueue; + return snapshot; +} -{ - createFunctionComponentUpdateQueue = function () { - return { - lastEffect: null, - events: null, - stores: null, - memoCache: null - }; +function mountMutableSource(source, getSnapshot, subscribe) { + var hook = mountWorkInProgressHook(); + hook.memoizedState = { + refs: { + getSnapshot: getSnapshot, + setSnapshot: null + }, + source: source, + subscribe: subscribe }; + return useMutableSource(hook, source, getSnapshot, subscribe); } -function use(usable) { - if (usable !== null && typeof usable === "object") { - // $FlowFixMe[method-unbinding] - if (typeof usable.then === "function") { - // This is a thenable. - var thenable = usable; // Track the position of the thenable within this fiber. +function updateMutableSource(source, getSnapshot, subscribe) { + var hook = updateWorkInProgressHook(); + return useMutableSource(hook, source, getSnapshot, subscribe); +} - var index = thenableIndexCounter; - thenableIndexCounter += 1; +function mountSyncExternalStore(subscribe, getSnapshot, getServerSnapshot) { + var fiber = currentlyRenderingFiber$1; + var hook = mountWorkInProgressHook(); + var nextSnapshot; - if (thenableState === null) { - thenableState = createThenableState(); - } + { + nextSnapshot = getSnapshot(); - var result = trackUsedThenable(thenableState, thenable, index); + { + if (!didWarnUncachedGetSnapshot) { + var cachedSnapshot = getSnapshot(); - if ( - currentlyRenderingFiber$1.alternate === null && - (workInProgressHook === null - ? currentlyRenderingFiber$1.memoizedState === null - : workInProgressHook.next === null) - ) { - // Initial render, and either this is the first time the component is - // called, or there were no Hooks called after this use() the previous - // time (perhaps because it threw). Subsequent Hook calls should use the - // mount dispatcher. - { - ReactCurrentDispatcher$1.current = HooksDispatcherOnMountInDEV; + if (!objectIs(nextSnapshot, cachedSnapshot)) { + error( + "The result of getSnapshot should be cached to avoid an infinite loop" + ); + + didWarnUncachedGetSnapshot = true; } } + } // Unless we're rendering a blocking lane, schedule a consistency check. + // Right before committing, we will walk the tree and check if any of the + // stores were mutated. + // + // We won't do this if we're hydrating server-rendered content, because if + // the content is stale, it's already visible anyway. Instead we'll patch + // it up in a passive effect. - return result; - } else if ( - usable.$$typeof === REACT_CONTEXT_TYPE || - usable.$$typeof === REACT_SERVER_CONTEXT_TYPE - ) { - var context = usable; - return readContext(context); + 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." + ); } - } // eslint-disable-next-line react-internal/safe-string-coercion - throw new Error("An unsupported type was passed to use(): " + String(usable)); -} + if (!includesBlockingLane(root, renderLanes$1)) { + 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. -function useMemoCache(size) { - var memoCache = null; // Fast-path, load memo cache from wip fiber if already prepared + hook.memoizedState = nextSnapshot; + var inst = { + value: nextSnapshot, + getSnapshot: getSnapshot + }; + hook.queue = inst; // Schedule an effect to subscribe to the store. - var updateQueue = currentlyRenderingFiber$1.updateQueue; + 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. - if (updateQueue !== null) { - memoCache = updateQueue.memoCache; - } // Otherwise clone from the current fiber + fiber.flags |= Passive$1; + pushEffect( + HasEffect | Passive, + updateStoreInstance.bind(null, fiber, inst, nextSnapshot, getSnapshot), + undefined, + null + ); + return nextSnapshot; +} - if (memoCache == null) { - var current = currentlyRenderingFiber$1.alternate; +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 (current !== null) { - var currentUpdateQueue = current.updateQueue; + var nextSnapshot = getSnapshot(); - if (currentUpdateQueue !== null) { - var currentMemoCache = currentUpdateQueue.memoCache; + { + if (!didWarnUncachedGetSnapshot) { + var cachedSnapshot = getSnapshot(); - if (currentMemoCache != null) { - memoCache = { - data: currentMemoCache.data.map(function (array) { - return array.slice(); - }), - index: 0 - }; - } + if (!objectIs(nextSnapshot, cachedSnapshot)) { + error( + "The result of getSnapshot should be cached to avoid an infinite loop" + ); + + didWarnUncachedGetSnapshot = true; } } - } // Finally fall back to allocating a fresh instance of the cache - - if (memoCache == null) { - memoCache = { - data: [], - index: 0 - }; } - if (updateQueue === null) { - updateQueue = createFunctionComponentUpdateQueue(); - currentlyRenderingFiber$1.updateQueue = updateQueue; + var prevSnapshot = (currentHook || hook).memoizedState; + var snapshotChanged = !objectIs(prevSnapshot, nextSnapshot); + + if (snapshotChanged) { + hook.memoizedState = nextSnapshot; + markWorkInProgressReceivedUpdate(); } - updateQueue.memoCache = memoCache; - var data = memoCache.data[memoCache.index]; + 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 (data === undefined) { - data = memoCache.data[memoCache.index] = new Array(size); + 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$1; + pushEffect( + HasEffect | Passive, + 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. - for (var i = 0; i < size; i++) { - data[i] = REACT_MEMO_CACHE_SENTINEL; - } - } else if (data.length !== size) { - // TODO: consider warning or throwing here - { - error( - "Expected a constant size argument for each invocation of useMemoCache. " + - "The previous cache was allocated with size %s but size %s was requested.", - data.length, - size + var root = getWorkInProgressRoot(); + + if (root === null) { + throw new Error( + "Expected a work-in-progress root. This is a bug in React. Please file an issue." ); } + + if (!includesBlockingLane(root, renderLanes$1)) { + pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot); + } } - memoCache.index++; - return data; + return nextSnapshot; } -function basicStateReducer(state, action) { - // $FlowFixMe: Flow doesn't like mixed types - return typeof action === "function" ? action(state) : action; +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 mountReducer(reducer, initialArg, init) { +function updateStoreInstance(fiber, inst, nextSnapshot, getSnapshot) { + // These are updated in the passive phase + inst.value = nextSnapshot; + inst.getSnapshot = getSnapshot; // Something may have been mutated in between render and commit. This could + // have been in an event that fired before the passive effects, or it could + // have been in a layout effect. In that case, we would have used the old + // snapsho and getSnapshot values to bail out. We need to check one more time. + + if (checkIfSnapshotChanged(inst)) { + // Force a re-render. + forceStoreRerender(fiber); + } +} + +function subscribeToStore(fiber, inst, subscribe) { + var handleStoreChange = function () { + // The store changed. Check if the snapshot changed since the last time we + // read from the store. + if (checkIfSnapshotChanged(inst)) { + // Force a re-render. + forceStoreRerender(fiber); + } + }; // Subscribe to the store and return a clean-up function. + + return subscribe(handleStoreChange); +} + +function checkIfSnapshotChanged(inst) { + var latestGetSnapshot = inst.getSnapshot; + var prevValue = inst.value; + + try { + var nextValue = latestGetSnapshot(); + return !objectIs(prevValue, nextValue); + } catch (error) { + return true; + } +} + +function forceStoreRerender(fiber) { + var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + } +} + +function mountState(initialState) { var hook = mountWorkInProgressHook(); - var initialState; - if (init !== undefined) { - initialState = init(initialArg); - } else { - initialState = initialArg; + if (typeof initialState === "function") { + // $FlowFixMe: Flow doesn't like mixed types + initialState = initialState(); } hook.memoizedState = hook.baseState = initialState; @@ -10520,11 +10752,11 @@ function mountReducer(reducer, initialArg, init) { pending: null, lanes: NoLanes, dispatch: null, - lastRenderedReducer: reducer, + lastRenderedReducer: basicStateReducer, lastRenderedState: initialState }; hook.queue = queue; - var dispatch = (queue.dispatch = dispatchReducerAction.bind( + var dispatch = (queue.dispatch = dispatchSetState.bind( null, currentlyRenderingFiber$1, queue @@ -10532,1600 +10764,1275 @@ function mountReducer(reducer, initialArg, init) { return [hook.memoizedState, dispatch]; } -function updateReducer(reducer, initialArg, init) { - var hook = updateWorkInProgressHook(); - var queue = hook.queue; +function updateState(initialState) { + return updateReducer(basicStateReducer); +} - if (queue === null) { - throw new Error( - "Should have a queue. This is likely a bug in React. Please file an issue." - ); - } +function rerenderState(initialState) { + return rerenderReducer(basicStateReducer); +} - queue.lastRenderedReducer = reducer; - var current = currentHook; // The last rebase update that is NOT part of the base state. +function pushEffect(tag, create, destroy, deps) { + var effect = { + tag: tag, + create: create, + destroy: destroy, + deps: deps, + // Circular + next: null + }; + var componentUpdateQueue = currentlyRenderingFiber$1.updateQueue; - var baseQueue = current.baseQueue; // The last pending update that hasn't been processed yet. + if (componentUpdateQueue === null) { + componentUpdateQueue = createFunctionComponentUpdateQueue(); + currentlyRenderingFiber$1.updateQueue = componentUpdateQueue; + componentUpdateQueue.lastEffect = effect.next = effect; + } else { + var lastEffect = componentUpdateQueue.lastEffect; - var pendingQueue = queue.pending; + if (lastEffect === null) { + componentUpdateQueue.lastEffect = effect.next = effect; + } else { + var firstEffect = lastEffect.next; + lastEffect.next = effect; + effect.next = firstEffect; + componentUpdateQueue.lastEffect = effect; + } + } - if (pendingQueue !== null) { - // We have new updates that haven't been processed yet. - // We'll add them to the base queue. - if (baseQueue !== null) { - // Merge the pending queue and the base queue. - var baseFirst = baseQueue.next; - var pendingFirst = pendingQueue.next; - baseQueue.next = pendingFirst; - pendingQueue.next = baseFirst; - } + return effect; +} - { - 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." - ); - } - } +var stackContainsErrorMessage = null; - current.baseQueue = baseQueue = pendingQueue; - queue.pending = null; +function getCallerStackFrame() { + // eslint-disable-next-line react-internal/prod-error-codes + var stackFrames = new Error("Error message").stack.split("\n"); // Some browsers (e.g. Chrome) include the error message in the stack + // but others (e.g. Firefox) do not. + + if (stackContainsErrorMessage === null) { + stackContainsErrorMessage = stackFrames[0].includes("Error message"); } - 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; + return stackContainsErrorMessage + ? stackFrames.slice(3, 4).join("\n") + : stackFrames.slice(2, 3).join("\n"); +} - do { - // An extra OffscreenLane bit is added to updates that were made to - // a hidden tree, so that we can distinguish them from updates that were - // already there when the tree was hidden. - var updateLane = removeLanes(update.lane, OffscreenLane); - var isHiddenUpdate = updateLane !== update.lane; // Check if this update was made while the tree was hidden. If so, then - // it's not a "base" update and we should disregard the extra base lanes - // that were added to renderLanes when we entered the Offscreen tree. +function mountRef(initialValue) { + var hook = mountWorkInProgressHook(); - var shouldSkipUpdate = isHiddenUpdate - ? !isSubsetOfLanes(getWorkInProgressRootRenderLanes(), updateLane) - : !isSubsetOfLanes(renderLanes$1, updateLane); + if (enableUseRefAccessWarning) { + { + // Support lazy initialization pattern shown in docs. + // We need to store the caller stack frame so that we don't warn on subsequent renders. + var hasBeenInitialized = initialValue != null; + var lazyInitGetterStack = null; + var didCheckForLazyInit = false; // Only warn once per component+hook. - if (shouldSkipUpdate) { - // Priority is insufficient. Skip this update. If this is the first - // skipped update, the previous update/state is the new base - // update/state. - var clone = { - lane: updateLane, - action: update.action, - hasEagerState: update.hasEagerState, - eagerState: update.eagerState, - next: null - }; + var didWarnAboutRead = false; + var didWarnAboutWrite = false; + var current = initialValue; + var ref = { + get current() { + if (!hasBeenInitialized) { + didCheckForLazyInit = true; + lazyInitGetterStack = getCallerStackFrame(); + } else if (currentlyRenderingFiber$1 !== null && !didWarnAboutRead) { + if ( + lazyInitGetterStack === null || + lazyInitGetterStack !== getCallerStackFrame() + ) { + didWarnAboutRead = true; - if (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. + warn( + "%s: Unsafe read of a mutable value during render.\n\n" + + "Reading from a ref during render is only safe if:\n" + + "1. The ref value has not been updated, or\n" + + "2. The ref holds a lazily-initialized value that is only set once.\n", + getComponentNameFromFiber(currentlyRenderingFiber$1) || + "Unknown" + ); + } + } - 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. + return current; + }, - var action = update.action; + set current(value) { + if (currentlyRenderingFiber$1 !== null && !didWarnAboutWrite) { + if (hasBeenInitialized || !didCheckForLazyInit) { + didWarnAboutWrite = true; - if (shouldDoubleInvokeUserFnsInHooksDEV) { - reducer(newState, action); - } + warn( + "%s: Unsafe write of a mutable value during render.\n\n" + + "Writing to a ref during render is only safe if the ref holds " + + "a lazily-initialized value that is only set once.\n", + getComponentNameFromFiber(currentlyRenderingFiber$1) || + "Unknown" + ); + } + } - if (update.hasEagerState) { - // If this update is a state update (not a reducer) and was processed eagerly, - // we can use the eagerly computed state - newState = update.eagerState; - } else { - newState = reducer(newState, action); + hasBeenInitialized = true; + current = value; } - } + }; + Object.seal(ref); + hook.memoizedState = ref; + return ref; + } + } else { + var _ref2 = { + current: initialValue + }; + hook.memoizedState = _ref2; + return _ref2; + } +} - update = update.next; - } while (update !== null && update !== first); +function updateRef(initialValue) { + var hook = updateWorkInProgressHook(); + return hook.memoizedState; +} - 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. +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 (!objectIs(newState, hook.memoizedState)) { - markWorkInProgressReceivedUpdate(); - } +function updateEffectImpl(fiberFlags, hookFlags, create, deps) { + var hook = updateWorkInProgressHook(); + var nextDeps = deps === undefined ? null : deps; + var destroy = undefined; // currentHook is null when rerendering after a render phase state update. - hook.memoizedState = newState; - hook.baseState = newBaseState; - hook.baseQueue = newBaseQueueLast; - queue.lastRenderedState = newState; - } + if (currentHook !== null) { + var prevEffect = currentHook.memoizedState; + destroy = prevEffect.destroy; - 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 (nextDeps !== null) { + var prevDeps = prevEffect.deps; + + if (areHookInputsEqual(nextDeps, prevDeps)) { + hook.memoizedState = pushEffect(hookFlags, create, destroy, nextDeps); + return; + } + } } - var dispatch = queue.dispatch; - return [hook.memoizedState, dispatch]; + currentlyRenderingFiber$1.flags |= fiberFlags; + hook.memoizedState = pushEffect( + HasEffect | hookFlags, + create, + destroy, + nextDeps + ); } -function rerenderReducer(reducer, initialArg, init) { - var hook = updateWorkInProgressHook(); - var queue = hook.queue; - - if (queue === null) { - throw new Error( - "Should have a queue. This is likely a bug in React. Please file an issue." +function mountEffect(create, deps) { + if ((currentlyRenderingFiber$1.mode & StrictEffectsMode) !== NoMode) { + mountEffectImpl( + MountPassiveDev | Passive$1 | PassiveStatic, + Passive, + create, + deps ); + } else { + mountEffectImpl(Passive$1 | PassiveStatic, Passive, create, deps); } +} - queue.lastRenderedReducer = reducer; // This is a re-render. Apply the new render phase updates to the previous - // work-in-progress hook. - - var dispatch = queue.dispatch; - var lastRenderPhaseUpdate = queue.pending; - var newState = hook.memoizedState; +function updateEffect(create, deps) { + updateEffectImpl(Passive$1, Passive, create, deps); +} - if (lastRenderPhaseUpdate !== null) { - // The queue doesn't persist past this render pass. - queue.pending = null; - var firstRenderPhaseUpdate = lastRenderPhaseUpdate.next; - var update = firstRenderPhaseUpdate; +function mountInsertionEffect(create, deps) { + mountEffectImpl(Update, Insertion, create, deps); +} - do { - // Process this render phase update. We don't have to check the - // priority because it will always be the same as the current - // render's. - var action = update.action; - newState = reducer(newState, action); - update = update.next; - } while (update !== firstRenderPhaseUpdate); // Mark that the fiber performed work, but only if the new state is - // different from the current state. - - if (!objectIs(newState, hook.memoizedState)) { - markWorkInProgressReceivedUpdate(); - } - - hook.memoizedState = newState; // Don't persist the state accumulated from the render phase updates to - // the base state unless the queue is empty. - // TODO: Not sure if this is the desired semantics, but it's what we - // do for gDSFP. I can't remember why. +function updateInsertionEffect(create, deps) { + return updateEffectImpl(Update, Insertion, create, deps); +} - if (hook.baseQueue === null) { - hook.baseState = newState; - } +function mountLayoutEffect(create, deps) { + var fiberFlags = Update | LayoutStatic; - queue.lastRenderedState = newState; + if ((currentlyRenderingFiber$1.mode & StrictEffectsMode) !== NoMode) { + fiberFlags |= MountLayoutDev; } - return [newState, dispatch]; + return mountEffectImpl(fiberFlags, Layout, create, deps); } -function readFromUnsubscribedMutableSource(root, source, getSnapshot) { - { - warnAboutMultipleRenderersDEV(source); - } - - var getVersion = source._getVersion; - var version = getVersion(source._source); // Is it safe for this component to read from this source during the current render? - - var isSafeToReadFromSource = false; // Check the version first. - // If this render has already been started with a specific version, - // we can use it alone to determine if we can safely read from the source. - - var currentRenderVersion = getWorkInProgressVersion(source); - - if (currentRenderVersion !== null) { - // It's safe to read if the store hasn't been mutated since the last time - // we read something. - isSafeToReadFromSource = currentRenderVersion === version; - } else { - // If there's no version, then this is the first time we've read from the - // source during the current render pass, so we need to do a bit more work. - // What we need to determine is if there are any hooks that already - // subscribed to the source, and if so, whether there are any pending - // mutations that haven't been synchronized yet. - // - // If there are no pending mutations, then `root.mutableReadLanes` will be - // empty, and we know we can safely read. - // - // If there *are* pending mutations, we may still be able to safely read - // if the currently rendering lanes are inclusive of the pending mutation - // lanes, since that guarantees that the value we're about to read from - // the source is consistent with the values that we read during the most - // recent mutation. - isSafeToReadFromSource = isSubsetOfLanes( - renderLanes$1, - root.mutableReadLanes - ); - - if (isSafeToReadFromSource) { - // If it's safe to read from this source during the current render, - // store the version in case other components read from it. - // A changed version number will let those components know to throw and restart the render. - setWorkInProgressVersion(source, version); - } - } +function updateLayoutEffect(create, deps) { + return updateEffectImpl(Update, Layout, create, deps); +} - if (isSafeToReadFromSource) { - var snapshot = getSnapshot(source._source); +function imperativeHandleEffect(create, ref) { + if (typeof ref === "function") { + var refCallback = ref; + var inst = create(); + refCallback(inst); + return function () { + refCallback(null); + }; + } else if (ref !== null && ref !== undefined) { + var refObject = ref; { - if (typeof snapshot === "function") { + if (!refObject.hasOwnProperty("current")) { error( - "Mutable source should not return a function as the snapshot value. " + - "Functions may close over mutable values and cause tearing." + "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(", ") + "}" ); } } - return snapshot; - } else { - // This handles the special case of a mutable source being shared between renderers. - // In that case, if the source is mutated between the first and second renderer, - // The second renderer don't know that it needs to reset the WIP version during unwind, - // (because the hook only marks sources as dirty if it's written to their WIP version). - // That would cause this tear check to throw again and eventually be visible to the user. - // We can avoid this infinite loop by explicitly marking the source as dirty. - // - // This can lead to tearing in the first renderer when it resumes, - // but there's nothing we can do about that (short of throwing here and refusing to continue the render). - markSourceAsDirty(source); // Intentioally throw an error to force React to retry synchronously. During - // the synchronous retry, it will block interleaved mutations, so we should - // get a consistent read. Therefore, the following error should never be - // visible to the user. - // We expect this error not to be thrown during the synchronous retry, - // because we blocked interleaved mutations. + var _inst = create(); - throw new Error( - "Cannot read from mutable source during the current render without tearing. This may be a bug in React. Please file an issue." - ); + refObject.current = _inst; + return function () { + refObject.current = null; + }; } } -function useMutableSource(hook, source, getSnapshot, subscribe) { - var root = getWorkInProgressRoot(); +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 (root === null) { - throw new Error( - "Expected a work-in-progress root. This is a bug in React. Please file an issue." - ); + var effectDeps = + deps !== null && deps !== undefined ? deps.concat([ref]) : null; + var fiberFlags = Update | LayoutStatic; + + if ((currentlyRenderingFiber$1.mode & StrictEffectsMode) !== NoMode) { + fiberFlags |= MountLayoutDev; } - var getVersion = source._getVersion; - var version = getVersion(source._source); - var dispatcher = ReactCurrentDispatcher$1.current; // eslint-disable-next-line prefer-const + mountEffectImpl( + fiberFlags, + Layout, + imperativeHandleEffect.bind(null, create, ref), + effectDeps + ); +} - var _dispatcher$useState = dispatcher.useState(function () { - return readFromUnsubscribedMutableSource(root, source, getSnapshot); - }), - currentSnapshot = _dispatcher$useState[0], - setSnapshot = _dispatcher$useState[1]; +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 snapshot = currentSnapshot; // Grab a handle to the state hook as well. - // We use it to clear the pending update queue if we have a new source. + var effectDeps = + deps !== null && deps !== undefined ? deps.concat([ref]) : null; + updateEffectImpl( + Update, + Layout, + imperativeHandleEffect.bind(null, create, ref), + effectDeps + ); +} - var stateHook = workInProgressHook; - var memoizedState = hook.memoizedState; - var refs = memoizedState.refs; - var prevGetSnapshot = refs.getSnapshot; - var prevSource = memoizedState.source; - var prevSubscribe = memoizedState.subscribe; - var fiber = currentlyRenderingFiber$1; - hook.memoizedState = { - refs: refs, - source: source, - subscribe: subscribe - }; // Sync the values needed by our subscription handler after each commit. +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. +} - dispatcher.useEffect( - function () { - refs.getSnapshot = getSnapshot; // Normally the dispatch function for a state hook never changes, - // but this hook recreates the queue in certain cases to avoid updates from stale sources. - // handleChange() below needs to reference the dispatch function without re-subscribing, - // so we use a ref to ensure that it always has the latest version. +var updateDebugValue = mountDebugValue; - refs.setSnapshot = setSnapshot; // Check for a possible change between when we last rendered now. +function mountCallback(callback, deps) { + var hook = mountWorkInProgressHook(); + var nextDeps = deps === undefined ? null : deps; + hook.memoizedState = [callback, nextDeps]; + return callback; +} - var maybeNewVersion = getVersion(source._source); +function updateCallback(callback, deps) { + var hook = updateWorkInProgressHook(); + var nextDeps = deps === undefined ? null : deps; + var prevState = hook.memoizedState; - if (!objectIs(version, maybeNewVersion)) { - var maybeNewSnapshot = getSnapshot(source._source); + if (nextDeps !== null) { + var prevDeps = prevState[1]; - { - if (typeof maybeNewSnapshot === "function") { - error( - "Mutable source should not return a function as the snapshot value. " + - "Functions may close over mutable values and cause tearing." - ); - } - } + if (areHookInputsEqual(nextDeps, prevDeps)) { + return prevState[0]; + } + } - if (!objectIs(snapshot, maybeNewSnapshot)) { - setSnapshot(maybeNewSnapshot); - var lane = requestUpdateLane(fiber); - markRootMutableRead(root, lane); - } // If the source mutated between render and now, - // there may be state updates already scheduled from the old source. - // Entangle the updates so that they render in the same batch. + hook.memoizedState = [callback, nextDeps]; + return callback; +} - markRootEntangled(root, root.mutableReadLanes); - } - }, - [getSnapshot, source, subscribe] - ); // If we got a new source or subscribe function, re-subscribe in a passive effect. +function mountMemo(nextCreate, deps) { + var hook = mountWorkInProgressHook(); + var nextDeps = deps === undefined ? null : deps; - dispatcher.useEffect( - function () { - var handleChange = function () { - var latestGetSnapshot = refs.getSnapshot; - var latestSetSnapshot = refs.setSnapshot; - - try { - latestSetSnapshot(latestGetSnapshot(source._source)); // Record a pending mutable source update with the same expiration time. + if (shouldDoubleInvokeUserFnsInHooksDEV) { + nextCreate(); + } - var lane = requestUpdateLane(fiber); - markRootMutableRead(root, lane); - } catch (error) { - // A selector might throw after a source mutation. - // e.g. it might try to read from a part of the store that no longer exists. - // In this case we should still schedule an update with React. - // Worst case the selector will throw again and then an error boundary will handle it. - latestSetSnapshot(function () { - throw error; - }); - } - }; + var nextValue = nextCreate(); + hook.memoizedState = [nextValue, nextDeps]; + return nextValue; +} - var unsubscribe = subscribe(source._source, handleChange); +function updateMemo(nextCreate, deps) { + var hook = updateWorkInProgressHook(); + var nextDeps = deps === undefined ? null : deps; + var prevState = hook.memoizedState; // Assume these are defined. If they're not, areHookInputsEqual will warn. - { - if (typeof unsubscribe !== "function") { - error( - "Mutable source subscribe function must return an unsubscribe function." - ); - } - } + if (nextDeps !== null) { + var prevDeps = prevState[1]; - return unsubscribe; - }, - [source, subscribe] - ); // If any of the inputs to useMutableSource change, reading is potentially unsafe. - // - // If either the source or the subscription have changed we can't can't trust the update queue. - // Maybe the source changed in a way that the old subscription ignored but the new one depends on. - // - // If the getSnapshot function changed, we also shouldn't rely on the update queue. - // It's possible that the underlying source was mutated between the when the last "change" event fired, - // and when the current render (with the new getSnapshot function) is processed. - // - // In both cases, we need to throw away pending updates (since they are no longer relevant) - // and treat reading from the source as we do in the mount case. + if (areHookInputsEqual(nextDeps, prevDeps)) { + return prevState[0]; + } + } - if ( - !objectIs(prevGetSnapshot, getSnapshot) || - !objectIs(prevSource, source) || - !objectIs(prevSubscribe, subscribe) - ) { - // Create a new queue and setState method, - // So if there are interleaved updates, they get pushed to the older queue. - // When this becomes current, the previous queue and dispatch method will be discarded, - // including any interleaving updates that occur. - var newQueue = { - pending: null, - lanes: NoLanes, - dispatch: null, - lastRenderedReducer: basicStateReducer, - lastRenderedState: snapshot - }; - newQueue.dispatch = setSnapshot = dispatchSetState.bind( - null, - currentlyRenderingFiber$1, - newQueue - ); - stateHook.queue = newQueue; - stateHook.baseQueue = null; - snapshot = readFromUnsubscribedMutableSource(root, source, getSnapshot); - stateHook.memoizedState = stateHook.baseState = snapshot; + if (shouldDoubleInvokeUserFnsInHooksDEV) { + nextCreate(); } - return snapshot; + var nextValue = nextCreate(); + hook.memoizedState = [nextValue, nextDeps]; + return nextValue; } -function mountMutableSource(source, getSnapshot, subscribe) { +function mountDeferredValue(value) { var hook = mountWorkInProgressHook(); - hook.memoizedState = { - refs: { - getSnapshot: getSnapshot, - setSnapshot: null - }, - source: source, - subscribe: subscribe - }; - return useMutableSource(hook, source, getSnapshot, subscribe); + hook.memoizedState = value; + return value; } -function updateMutableSource(source, getSnapshot, subscribe) { +function updateDeferredValue(value) { var hook = updateWorkInProgressHook(); - return useMutableSource(hook, source, getSnapshot, subscribe); + var resolvedCurrentHook = currentHook; + var prevValue = resolvedCurrentHook.memoizedState; + return updateDeferredValueImpl(hook, prevValue, value); } -function mountSyncExternalStore(subscribe, getSnapshot, getServerSnapshot) { - var fiber = currentlyRenderingFiber$1; - var hook = mountWorkInProgressHook(); - var nextSnapshot; - - { - nextSnapshot = getSnapshot(); - - { - if (!didWarnUncachedGetSnapshot) { - var cachedSnapshot = getSnapshot(); - - if (!objectIs(nextSnapshot, cachedSnapshot)) { - error( - "The result of getSnapshot should be cached to avoid an infinite loop" - ); +function rerenderDeferredValue(value) { + var hook = updateWorkInProgressHook(); - 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. + 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); + } +} - var root = getWorkInProgressRoot(); +function updateDeferredValueImpl(hook, prevValue, value) { + var shouldDeferValue = !includesOnlyNonUrgentLanes(renderLanes$1); - if (root === null) { - throw new Error( - "Expected a work-in-progress root. This is a bug in React. Please file an issue." + 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. - if (!includesBlockingLane(root, renderLanes$1)) { - 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.baseState = true; + } // Reuse the previous value - hook.memoizedState = nextSnapshot; - var inst = { - value: nextSnapshot, - getSnapshot: getSnapshot - }; - hook.queue = inst; // Schedule an effect to subscribe to the store. + 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(); + } - 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. + hook.memoizedState = value; + return value; + } +} - fiber.flags |= Passive$1; - pushEffect( - HasEffect | Passive, - updateStoreInstance.bind(null, fiber, inst, nextSnapshot, getSnapshot), - undefined, - null +function startTransition(setPending, callback, options) { + var previousPriority = getCurrentUpdatePriority(); + setCurrentUpdatePriority( + higherEventPriority(previousPriority, ContinuousEventPriority) ); - return nextSnapshot; -} + var prevTransition = ReactCurrentBatchConfig$2.transition; + ReactCurrentBatchConfig$2.transition = null; + setPending(true); + var currentTransition = (ReactCurrentBatchConfig$2.transition = {}); -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. + { + ReactCurrentBatchConfig$2.transition._updatedFibers = new Set(); + } - var nextSnapshot = getSnapshot(); + try { + setPending(false); + callback(); + } finally { + setCurrentUpdatePriority(previousPriority); + ReactCurrentBatchConfig$2.transition = prevTransition; - { - if (!didWarnUncachedGetSnapshot) { - var cachedSnapshot = getSnapshot(); + { + if (prevTransition === null && currentTransition._updatedFibers) { + var updatedFibersCount = currentTransition._updatedFibers.size; - if (!objectIs(nextSnapshot, cachedSnapshot)) { - error( - "The result of getSnapshot should be cached to avoid an infinite loop" - ); + currentTransition._updatedFibers.clear(); - didWarnUncachedGetSnapshot = true; + 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." + ); + } } } } +} - var prevSnapshot = (currentHook || hook).memoizedState; - var snapshotChanged = !objectIs(prevSnapshot, nextSnapshot); - - if (snapshotChanged) { - hook.memoizedState = nextSnapshot; - markWorkInProgressReceivedUpdate(); - } - - var inst = hook.queue; - updateEffect(subscribeToStore.bind(null, fiber, inst, subscribe), [ - subscribe - ]); // Whenever getSnapshot or subscribe changes, we need to check in the - // commit phase if there was an interleaved mutation. In concurrent mode - // this can happen all the time, but even in synchronous mode, an earlier - // effect may have mutated the store. - - if ( - inst.getSnapshot !== getSnapshot || - snapshotChanged || // Check if the 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$1; - pushEffect( - HasEffect | Passive, - 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." - ); - } - - if (!includesBlockingLane(root, renderLanes$1)) { - pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot); - } - } - - return nextSnapshot; -} - -function pushStoreConsistencyCheck(fiber, getSnapshot, renderedSnapshot) { - fiber.flags |= StoreConsistency; - var check = { - getSnapshot: getSnapshot, - value: renderedSnapshot - }; - var componentUpdateQueue = currentlyRenderingFiber$1.updateQueue; - - if (componentUpdateQueue === null) { - componentUpdateQueue = createFunctionComponentUpdateQueue(); - currentlyRenderingFiber$1.updateQueue = componentUpdateQueue; - componentUpdateQueue.stores = [check]; - } else { - var stores = componentUpdateQueue.stores; - - if (stores === null) { - componentUpdateQueue.stores = [check]; - } else { - stores.push(check); - } - } -} - -function updateStoreInstance(fiber, inst, nextSnapshot, getSnapshot) { - // These are updated in the passive phase - inst.value = nextSnapshot; - inst.getSnapshot = getSnapshot; // Something may have been mutated in between render and commit. This could - // have been in an event that fired before the passive effects, or it could - // have been in a layout effect. In that case, we would have used the old - // snapsho and getSnapshot values to bail out. We need to check one more time. - - if (checkIfSnapshotChanged(inst)) { - // Force a re-render. - forceStoreRerender(fiber); - } -} - -function subscribeToStore(fiber, inst, subscribe) { - var handleStoreChange = function () { - // The store changed. Check if the snapshot changed since the last time we - // read from the store. - if (checkIfSnapshotChanged(inst)) { - // Force a re-render. - forceStoreRerender(fiber); - } - }; // Subscribe to the store and return a clean-up function. +function mountTransition() { + var _mountState = mountState(false), + isPending = _mountState[0], + setPending = _mountState[1]; // The `start` method never changes. - return subscribe(handleStoreChange); + var start = startTransition.bind(null, setPending); + var hook = mountWorkInProgressHook(); + hook.memoizedState = start; + return [isPending, start]; } -function checkIfSnapshotChanged(inst) { - var latestGetSnapshot = inst.getSnapshot; - var prevValue = inst.value; +function updateTransition() { + var _updateState = updateState(), + isPending = _updateState[0]; - try { - var nextValue = latestGetSnapshot(); - return !objectIs(prevValue, nextValue); - } catch (error) { - return true; - } + var hook = updateWorkInProgressHook(); + var start = hook.memoizedState; + return [isPending, start]; } -function forceStoreRerender(fiber) { - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); +function rerenderTransition() { + var _rerenderState = rerenderState(), + isPending = _rerenderState[0]; - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); - } + var hook = updateWorkInProgressHook(); + var start = hook.memoizedState; + return [isPending, start]; } -function mountState(initialState) { +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 (typeof initialState === "function") { - // $FlowFixMe: Flow doesn't like mixed types - initialState = initialState(); + 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 = hook.baseState = initialState; - var queue = { - pending: 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]; + hook.memoizedState = id; + return id; } -function updateState(initialState) { - return updateReducer(basicStateReducer); +function updateId() { + var hook = updateWorkInProgressHook(); + var id = hook.memoizedState; + return id; } -function rerenderState(initialState) { - return rerenderReducer(basicStateReducer); -} +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()." + ); + } + } -function pushEffect(tag, create, destroy, deps) { - var effect = { - tag: tag, - create: create, - destroy: destroy, - deps: deps, - // Circular + var lane = requestUpdateLane(fiber); + var update = { + lane: lane, + action: action, + hasEagerState: false, + eagerState: null, next: null }; - var componentUpdateQueue = currentlyRenderingFiber$1.updateQueue; - if (componentUpdateQueue === null) { - componentUpdateQueue = createFunctionComponentUpdateQueue(); - currentlyRenderingFiber$1.updateQueue = componentUpdateQueue; - componentUpdateQueue.lastEffect = effect.next = effect; + if (isRenderPhaseUpdate(fiber)) { + enqueueRenderPhaseUpdate(queue, update); } else { - var lastEffect = componentUpdateQueue.lastEffect; + var root = enqueueConcurrentHookUpdate(fiber, queue, update, lane); - if (lastEffect === null) { - componentUpdateQueue.lastEffect = effect.next = effect; - } else { - var firstEffect = lastEffect.next; - lastEffect.next = effect; - effect.next = firstEffect; - componentUpdateQueue.lastEffect = effect; + if (root !== null) { + var eventTime = requestEventTime(); + scheduleUpdateOnFiber(root, fiber, lane, eventTime); + entangleTransitionUpdate(root, queue, lane); } } - return effect; + markUpdateInDevTools(fiber, lane); } -var stackContainsErrorMessage = null; - -function getCallerStackFrame() { - // eslint-disable-next-line react-internal/prod-error-codes - var stackFrames = new Error("Error message").stack.split("\n"); // Some browsers (e.g. Chrome) include the error message in the stack - // but others (e.g. Firefox) do not. - - if (stackContainsErrorMessage === null) { - stackContainsErrorMessage = stackFrames[0].includes("Error message"); +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 stackContainsErrorMessage - ? stackFrames.slice(3, 4).join("\n") - : stackFrames.slice(2, 3).join("\n"); -} + var lane = requestUpdateLane(fiber); + var update = { + lane: lane, + action: action, + hasEagerState: false, + eagerState: null, + next: null + }; -function mountRef(initialValue) { - var hook = mountWorkInProgressHook(); + if (isRenderPhaseUpdate(fiber)) { + enqueueRenderPhaseUpdate(queue, update); + } else { + var alternate = fiber.alternate; - if (enableUseRefAccessWarning) { - { - // Support lazy initialization pattern shown in docs. - // We need to store the caller stack frame so that we don't warn on subsequent renders. - var hasBeenInitialized = initialValue != null; - var lazyInitGetterStack = null; - var didCheckForLazyInit = false; // Only warn once per component+hook. + 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; - var didWarnAboutRead = false; - var didWarnAboutWrite = false; - var current = initialValue; - var ref = { - get current() { - if (!hasBeenInitialized) { - didCheckForLazyInit = true; - lazyInitGetterStack = getCallerStackFrame(); - } else if (currentlyRenderingFiber$1 !== null && !didWarnAboutRead) { - if ( - lazyInitGetterStack === null || - lazyInitGetterStack !== getCallerStackFrame() - ) { - didWarnAboutRead = true; + if (lastRenderedReducer !== null) { + var prevDispatcher; - warn( - "%s: Unsafe read of a mutable value during render.\n\n" + - "Reading from a ref during render is only safe if:\n" + - "1. The ref value has not been updated, or\n" + - "2. The ref holds a lazily-initialized value that is only set once.\n", - getComponentNameFromFiber(currentlyRenderingFiber$1) || - "Unknown" - ); - } - } + { + prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnUpdateInDEV; + } - return current; - }, + 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. - set current(value) { - if (currentlyRenderingFiber$1 !== null && !didWarnAboutWrite) { - if (hasBeenInitialized || !didCheckForLazyInit) { - didWarnAboutWrite = true; + update.hasEagerState = true; + update.eagerState = eagerState; - warn( - "%s: Unsafe write of a mutable value during render.\n\n" + - "Writing to a ref during render is only safe if the ref holds " + - "a lazily-initialized value that is only set once.\n", - getComponentNameFromFiber(currentlyRenderingFiber$1) || - "Unknown" - ); - } + if (objectIs(eagerState, currentState)) { + // Fast path. We can bail out without scheduling React to re-render. + // It's still possible that we'll need to rebase this update later, + // if the component re-renders for a different reason and by that + // time the reducer has changed. + // TODO: Do we still need to entangle transitions in this case? + enqueueConcurrentHookUpdateAndEagerlyBailout(fiber, queue, update); + return; + } + } catch (error) { + // Suppress the error. It will throw again in the render phase. + } finally { + { + ReactCurrentDispatcher$1.current = prevDispatcher; } - - hasBeenInitialized = true; - current = value; } - }; - Object.seal(ref); - hook.memoizedState = ref; - return ref; + } } - } else { - var _ref2 = { - current: initialValue - }; - hook.memoizedState = _ref2; - return _ref2; - } -} - -function updateRef(initialValue) { - var hook = updateWorkInProgressHook(); - return hook.memoizedState; -} -function mountEffectImpl(fiberFlags, hookFlags, create, deps) { - var hook = mountWorkInProgressHook(); - var nextDeps = deps === undefined ? null : deps; - currentlyRenderingFiber$1.flags |= fiberFlags; - hook.memoizedState = pushEffect( - HasEffect | hookFlags, - create, - undefined, - nextDeps - ); -} - -function updateEffectImpl(fiberFlags, hookFlags, create, deps) { - var hook = updateWorkInProgressHook(); - var nextDeps = deps === undefined ? null : deps; - var destroy = undefined; // currentHook is null when rerendering after a render phase state update. - - if (currentHook !== null) { - var prevEffect = currentHook.memoizedState; - destroy = prevEffect.destroy; - - if (nextDeps !== null) { - var prevDeps = prevEffect.deps; + var root = enqueueConcurrentHookUpdate(fiber, queue, update, lane); - if (areHookInputsEqual(nextDeps, prevDeps)) { - hook.memoizedState = pushEffect(hookFlags, create, destroy, nextDeps); - return; - } + if (root !== null) { + var eventTime = requestEventTime(); + scheduleUpdateOnFiber(root, fiber, lane, eventTime); + entangleTransitionUpdate(root, queue, lane); } } - currentlyRenderingFiber$1.flags |= fiberFlags; - hook.memoizedState = pushEffect( - HasEffect | hookFlags, - create, - destroy, - nextDeps + markUpdateInDevTools(fiber, lane); +} + +function isRenderPhaseUpdate(fiber) { + var alternate = fiber.alternate; + return ( + fiber === currentlyRenderingFiber$1 || + (alternate !== null && alternate === currentlyRenderingFiber$1) ); } -function mountEffect(create, deps) { - if ((currentlyRenderingFiber$1.mode & StrictEffectsMode) !== NoMode) { - mountEffectImpl( - MountPassiveDev | Passive$1 | PassiveStatic, - Passive, - create, - deps - ); +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 { - mountEffectImpl(Passive$1 | PassiveStatic, Passive, create, deps); + update.next = pending.next; + pending.next = update; } -} -function updateEffect(create, deps) { - updateEffectImpl(Passive$1, Passive, create, deps); -} + queue.pending = update; +} // TODO: Move to ReactFiberConcurrentUpdates? -function mountInsertionEffect(create, deps) { - mountEffectImpl(Update, Insertion, create, deps); -} +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. -function updateInsertionEffect(create, deps) { - return updateEffectImpl(Update, Insertion, create, deps); -} + queueLanes = intersectLanes(queueLanes, root.pendingLanes); // Entangle the new transition lane with the other transition lanes. -function mountLayoutEffect(create, deps) { - var fiberFlags = Update | LayoutStatic; + 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. - if ((currentlyRenderingFiber$1.mode & StrictEffectsMode) !== NoMode) { - fiberFlags |= MountLayoutDev; + markRootEntangled(root, newQueueLanes); } - - return mountEffectImpl(fiberFlags, Layout, create, deps); } -function updateLayoutEffect(create, deps) { - return updateEffectImpl(Update, Layout, create, deps); +function markUpdateInDevTools(fiber, lane, action) { + { + markStateUpdateScheduled(fiber, lane); + } } -function imperativeHandleEffect(create, ref) { - if (typeof ref === "function") { - var refCallback = ref; - var inst = create(); - refCallback(inst); - return function () { - refCallback(null); - }; - } else if (ref !== null && ref !== undefined) { - var refObject = ref; - - { - if (!refObject.hasOwnProperty("current")) { - error( - "Expected useImperativeHandle() first argument to either be a " + - "ref callback or React.createRef() object. Instead received: %s.", - "an object with keys {" + Object.keys(refObject).join(", ") + "}" - ); - } - } +var 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 +}; - var _inst = create(); +{ + ContextOnlyDispatcher.use = throwInvalidHookError; +} - refObject.current = _inst; - return function () { - refObject.current = null; - }; - } +{ + ContextOnlyDispatcher.useMemoCache = throwInvalidHookError; } -function mountImperativeHandle(ref, create, deps) { - { - if (typeof create !== "function") { - error( - "Expected useImperativeHandle() second argument to be a function " + - "that creates a handle. Instead received: %s.", - create !== null ? typeof create : "null" - ); - } - } // TODO: If deps are provided, should we skip comparing the ref itself? - - var effectDeps = - deps !== null && deps !== undefined ? deps.concat([ref]) : null; - var fiberFlags = Update | LayoutStatic; - - if ((currentlyRenderingFiber$1.mode & StrictEffectsMode) !== NoMode) { - fiberFlags |= MountLayoutDev; - } - - mountEffectImpl( - fiberFlags, - Layout, - imperativeHandleEffect.bind(null, create, ref), - effectDeps - ); -} - -function updateImperativeHandle(ref, create, deps) { - { - if (typeof create !== "function") { - error( - "Expected useImperativeHandle() second argument to be a function " + - "that creates a handle. Instead received: %s.", - create !== null ? typeof create : "null" - ); - } - } // TODO: If deps are provided, should we skip comparing the ref itself? - - var effectDeps = - deps !== null && deps !== undefined ? deps.concat([ref]) : null; - updateEffectImpl( - Update, - Layout, - imperativeHandleEffect.bind(null, create, ref), - effectDeps - ); -} - -function mountDebugValue(value, formatterFn) { - // This hook is normally a no-op. - // The react-debug-hooks package injects its own implementation - // so that e.g. DevTools can display custom hook values. -} - -var updateDebugValue = mountDebugValue; - -function mountCallback(callback, deps) { - var hook = mountWorkInProgressHook(); - var nextDeps = deps === undefined ? null : deps; - hook.memoizedState = [callback, nextDeps]; - return callback; -} - -function updateCallback(callback, deps) { - var hook = updateWorkInProgressHook(); - var nextDeps = deps === undefined ? null : deps; - var prevState = hook.memoizedState; - - if (nextDeps !== null) { - var prevDeps = prevState[1]; - - if (areHookInputsEqual(nextDeps, prevDeps)) { - return prevState[0]; - } - } - - hook.memoizedState = [callback, nextDeps]; - return callback; -} - -function mountMemo(nextCreate, deps) { - var hook = mountWorkInProgressHook(); - var nextDeps = deps === undefined ? null : deps; - - if (shouldDoubleInvokeUserFnsInHooksDEV) { - nextCreate(); - } - - var nextValue = nextCreate(); - hook.memoizedState = [nextValue, nextDeps]; - return nextValue; -} - -function updateMemo(nextCreate, deps) { - var hook = updateWorkInProgressHook(); - var nextDeps = deps === undefined ? null : deps; - var prevState = hook.memoizedState; // Assume these are defined. If they're not, areHookInputsEqual will warn. - - if (nextDeps !== null) { - var prevDeps = prevState[1]; - - if (areHookInputsEqual(nextDeps, prevDeps)) { - return prevState[0]; - } - } - - if (shouldDoubleInvokeUserFnsInHooksDEV) { - nextCreate(); - } - - var nextValue = nextCreate(); - hook.memoizedState = [nextValue, nextDeps]; - return nextValue; -} - -function mountDeferredValue(value) { - var hook = mountWorkInProgressHook(); - hook.memoizedState = value; - return value; -} - -function updateDeferredValue(value) { - var hook = updateWorkInProgressHook(); - var resolvedCurrentHook = currentHook; - var prevValue = resolvedCurrentHook.memoizedState; - return updateDeferredValueImpl(hook, prevValue, value); -} - -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); - } -} - -function updateDeferredValueImpl(hook, prevValue, value) { - var shouldDeferValue = !includesOnlyNonUrgentLanes(renderLanes$1); - - 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; - } -} - -function startTransition(setPending, callback, options) { - var previousPriority = getCurrentUpdatePriority(); - setCurrentUpdatePriority( - higherEventPriority(previousPriority, ContinuousEventPriority) - ); - setPending(true); - var prevTransition = ReactCurrentBatchConfig$2.transition; - ReactCurrentBatchConfig$2.transition = {}; - var currentTransition = ReactCurrentBatchConfig$2.transition; - - { - ReactCurrentBatchConfig$2.transition._updatedFibers = new Set(); - } +var HooksDispatcherOnMountInDEV = null; +var HooksDispatcherOnMountWithHookTypesInDEV = null; +var HooksDispatcherOnUpdateInDEV = null; +var HooksDispatcherOnRerenderInDEV = null; +var InvalidNestedHooksDispatcherOnMountInDEV = null; +var InvalidNestedHooksDispatcherOnUpdateInDEV = null; +var InvalidNestedHooksDispatcherOnRerenderInDEV = null; - try { - setPending(false); - callback(); - } finally { - setCurrentUpdatePriority(previousPriority); - ReactCurrentBatchConfig$2.transition = prevTransition; +{ + 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 (prevTransition === null && currentTransition._updatedFibers) { - var updatedFibersCount = currentTransition._updatedFibers.size; + var warnInvalidHookAccess = function () { + error( + "Do not call Hooks inside useEffect(...), useMemo(...), or other built-in Hooks. " + + "You can only call Hooks at the top level of your React function. " + + "For more information, see " + + "https://reactjs.org/link/rules-of-hooks" + ); + }; - currentTransition._updatedFibers.clear(); + 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 (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." - ); - } + try { + return mountMemo(create, deps); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; } - } - } -} - -function mountTransition() { - var _mountState = mountState(false), - isPending = _mountState[0], - setPending = _mountState[1]; // The `start` method never changes. - - var start = startTransition.bind(null, setPending); - var hook = mountWorkInProgressHook(); - hook.memoizedState = start; - return [isPending, start]; -} - -function updateTransition() { - var _updateState = updateState(), - isPending = _updateState[0]; - - 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 mountId() { - var hook = mountWorkInProgressHook(); - var root = getWorkInProgressRoot(); // TODO: In Fizz, id generation is specific to each server config. Maybe we - // should do this in Fiber, too? Deferring this decision for now because - // there's no other place to store the prefix except for an internal field on - // the public createRoot object, which the fiber tree does not currently have - // a reference to. - - var identifierPrefix = root.identifierPrefix; - var id; - - { - // Use a lowercase r prefix for client-generated ids. - var globalClientId = globalClientIdCounter++; - id = ":" + identifierPrefix + "r" + globalClientId.toString(32) + ":"; - } - - hook.memoizedState = id; - return id; -} - -function updateId() { - var hook = updateWorkInProgressHook(); - var id = hook.memoizedState; - return id; -} - -function 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 - }; + }, + useReducer: function (reducer, initialArg, init) { + currentHookNameInDev = "useReducer"; + mountHookTypesDev(); + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnMountInDEV; - if (isRenderPhaseUpdate(fiber)) { - enqueueRenderPhaseUpdate(queue, update); - } else { - var root = enqueueConcurrentHookUpdate(fiber, queue, update, lane); + 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; - if (root !== null) { - var eventTime = requestEventTime(); - scheduleUpdateOnFiber(root, fiber, lane, eventTime); - entangleTransitionUpdate(root, queue, lane); + 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(source, getSnapshot, subscribe); + }, + useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { + currentHookNameInDev = "useSyncExternalStore"; + mountHookTypesDev(); + return mountSyncExternalStore(subscribe, getSnapshot); + }, + useId: function () { + currentHookNameInDev = "useId"; + mountHookTypesDev(); + return mountId(); } - } - - markUpdateInDevTools(fiber, 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()." - ); - } + HooksDispatcherOnMountInDEV.use = use; } - 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; + { + HooksDispatcherOnMountInDEV.useMemoCache = useMemoCache; + } - { - prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnUpdateInDEV; - } + 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 { - 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. + 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; - update.hasEagerState = true; - update.eagerState = eagerState; + 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 (objectIs(eagerState, currentState)) { - // Fast path. We can bail out without scheduling React to re-render. - // It's still possible that we'll need to rebase this update later, - // if the component re-renders for a different reason and by that - // time the reducer has changed. - // TODO: Do we still need to entangle transitions in this case? - enqueueConcurrentHookUpdateAndEagerlyBailout(fiber, queue, update); - return; - } - } catch (error) { - // Suppress the error. It will throw again in the render phase. - } finally { - { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - } + 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(source, getSnapshot, subscribe); + }, + useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { + currentHookNameInDev = "useSyncExternalStore"; + updateHookTypesDev(); + return mountSyncExternalStore(subscribe, getSnapshot); + }, + useId: function () { + currentHookNameInDev = "useId"; + updateHookTypesDev(); + return mountId(); } + }; - var root = enqueueConcurrentHookUpdate(fiber, queue, update, lane); - - if (root !== null) { - var eventTime = requestEventTime(); - scheduleUpdateOnFiber(root, fiber, lane, eventTime); - entangleTransitionUpdate(root, queue, lane); - } + { + HooksDispatcherOnMountWithHookTypesInDEV.use = use; } - markUpdateInDevTools(fiber, 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; + { + HooksDispatcherOnMountWithHookTypesInDEV.useMemoCache = useMemoCache; } - queue.pending = update; -} // TODO: Move to ReactFiberConcurrentUpdates? + 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; -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. + 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; - queueLanes = intersectLanes(queueLanes, root.pendingLanes); // Entangle the new transition lane with the other transition lanes. + 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; - 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. + 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(source, getSnapshot, subscribe); + }, + useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { + currentHookNameInDev = "useSyncExternalStore"; + updateHookTypesDev(); + return updateSyncExternalStore(subscribe, getSnapshot); + }, + useId: function () { + currentHookNameInDev = "useId"; + updateHookTypesDev(); + return updateId(); + } + }; - markRootEntangled(root, newQueueLanes); + { + HooksDispatcherOnUpdateInDEV.use = use; } -} -function markUpdateInDevTools(fiber, lane, action) { { - markStateUpdateScheduled(fiber, lane); + HooksDispatcherOnUpdateInDEV.useMemoCache = useMemoCache; } -} - -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 -}; - -{ - ContextOnlyDispatcher.use = throwInvalidHookError; -} - -{ - ContextOnlyDispatcher.useMemoCache = throwInvalidHookError; -} - -var HooksDispatcherOnMountInDEV = null; -var HooksDispatcherOnMountWithHookTypesInDEV = null; -var HooksDispatcherOnUpdateInDEV = null; -var HooksDispatcherOnRerenderInDEV = null; -var InvalidNestedHooksDispatcherOnMountInDEV = null; -var InvalidNestedHooksDispatcherOnUpdateInDEV = null; -var InvalidNestedHooksDispatcherOnRerenderInDEV = null; - -{ - var warnInvalidContextAccess = function () { - error( - "Context can only be read while React is rendering. " + - "In classes, you can read it in the render method or getDerivedStateFromProps. " + - "In function components, you can read it directly in the function body, but not " + - "inside Hooks like useReducer() or useMemo()." - ); - }; - - var warnInvalidHookAccess = function () { - error( - "Do not call Hooks inside useEffect(...), useMemo(...), or other built-in Hooks. " + - "You can only call Hooks at the top level of your React function. " + - "For more information, see " + - "https://reactjs.org/link/rules-of-hooks" - ); - }; - HooksDispatcherOnMountInDEV = { + HooksDispatcherOnRerenderInDEV = { readContext: function (context) { return readContext(context); }, useCallback: function (callback, deps) { currentHookNameInDev = "useCallback"; - mountHookTypesDev(); - checkDepsAreArrayDev(deps); - return mountCallback(callback, deps); + updateHookTypesDev(); + return updateCallback(callback, deps); }, useContext: function (context) { currentHookNameInDev = "useContext"; - mountHookTypesDev(); + updateHookTypesDev(); return readContext(context); }, useEffect: function (create, deps) { currentHookNameInDev = "useEffect"; - mountHookTypesDev(); - checkDepsAreArrayDev(deps); - return mountEffect(create, deps); + updateHookTypesDev(); + return updateEffect(create, deps); }, useImperativeHandle: function (ref, create, deps) { currentHookNameInDev = "useImperativeHandle"; - mountHookTypesDev(); - checkDepsAreArrayDev(deps); - return mountImperativeHandle(ref, create, deps); + updateHookTypesDev(); + return updateImperativeHandle(ref, create, deps); }, useInsertionEffect: function (create, deps) { currentHookNameInDev = "useInsertionEffect"; - mountHookTypesDev(); - checkDepsAreArrayDev(deps); - return mountInsertionEffect(create, deps); + updateHookTypesDev(); + return updateInsertionEffect(create, deps); }, useLayoutEffect: function (create, deps) { currentHookNameInDev = "useLayoutEffect"; - mountHookTypesDev(); - checkDepsAreArrayDev(deps); - return mountLayoutEffect(create, deps); + updateHookTypesDev(); + return updateLayoutEffect(create, deps); }, useMemo: function (create, deps) { currentHookNameInDev = "useMemo"; - mountHookTypesDev(); - checkDepsAreArrayDev(deps); + updateHookTypesDev(); var prevDispatcher = ReactCurrentDispatcher$1.current; ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnMountInDEV; + InvalidNestedHooksDispatcherOnRerenderInDEV; try { - return mountMemo(create, deps); + return updateMemo(create, deps); } finally { ReactCurrentDispatcher$1.current = prevDispatcher; } }, useReducer: function (reducer, initialArg, init) { currentHookNameInDev = "useReducer"; - mountHookTypesDev(); + updateHookTypesDev(); var prevDispatcher = ReactCurrentDispatcher$1.current; ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnMountInDEV; + InvalidNestedHooksDispatcherOnRerenderInDEV; try { - return mountReducer(reducer, initialArg, init); + return rerenderReducer(reducer, initialArg, init); } finally { ReactCurrentDispatcher$1.current = prevDispatcher; } }, useRef: function (initialValue) { currentHookNameInDev = "useRef"; - mountHookTypesDev(); - return mountRef(initialValue); + updateHookTypesDev(); + return updateRef(); }, useState: function (initialState) { currentHookNameInDev = "useState"; - mountHookTypesDev(); + updateHookTypesDev(); var prevDispatcher = ReactCurrentDispatcher$1.current; ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnMountInDEV; + InvalidNestedHooksDispatcherOnRerenderInDEV; try { - return mountState(initialState); + return rerenderState(initialState); } finally { ReactCurrentDispatcher$1.current = prevDispatcher; } }, useDebugValue: function (value, formatterFn) { currentHookNameInDev = "useDebugValue"; - mountHookTypesDev(); - return mountDebugValue(); + updateHookTypesDev(); + return updateDebugValue(); }, useDeferredValue: function (value) { currentHookNameInDev = "useDeferredValue"; - mountHookTypesDev(); - return mountDeferredValue(value); + updateHookTypesDev(); + return rerenderDeferredValue(value); }, useTransition: function () { currentHookNameInDev = "useTransition"; - mountHookTypesDev(); - return mountTransition(); + updateHookTypesDev(); + return rerenderTransition(); }, useMutableSource: function (source, getSnapshot, subscribe) { currentHookNameInDev = "useMutableSource"; - mountHookTypesDev(); - return mountMutableSource(source, getSnapshot, subscribe); + updateHookTypesDev(); + return updateMutableSource(source, getSnapshot, subscribe); }, useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { currentHookNameInDev = "useSyncExternalStore"; - mountHookTypesDev(); - return mountSyncExternalStore(subscribe, getSnapshot); + updateHookTypesDev(); + return updateSyncExternalStore(subscribe, getSnapshot); }, useId: function () { currentHookNameInDev = "useId"; - mountHookTypesDev(); - return mountId(); + updateHookTypesDev(); + return updateId(); } }; { - HooksDispatcherOnMountInDEV.use = use; + HooksDispatcherOnRerenderInDEV.use = use; } { - HooksDispatcherOnMountInDEV.useMemoCache = useMemoCache; + HooksDispatcherOnRerenderInDEV.useMemoCache = useMemoCache; } - HooksDispatcherOnMountWithHookTypesInDEV = { + InvalidNestedHooksDispatcherOnMountInDEV = { readContext: function (context) { + warnInvalidContextAccess(); return readContext(context); }, useCallback: function (callback, deps) { currentHookNameInDev = "useCallback"; - updateHookTypesDev(); + warnInvalidHookAccess(); + mountHookTypesDev(); return mountCallback(callback, deps); }, useContext: function (context) { currentHookNameInDev = "useContext"; - updateHookTypesDev(); + warnInvalidHookAccess(); + mountHookTypesDev(); return readContext(context); }, useEffect: function (create, deps) { currentHookNameInDev = "useEffect"; - updateHookTypesDev(); + warnInvalidHookAccess(); + mountHookTypesDev(); return mountEffect(create, deps); }, useImperativeHandle: function (ref, create, deps) { currentHookNameInDev = "useImperativeHandle"; - updateHookTypesDev(); + warnInvalidHookAccess(); + mountHookTypesDev(); return mountImperativeHandle(ref, create, deps); }, useInsertionEffect: function (create, deps) { currentHookNameInDev = "useInsertionEffect"; - updateHookTypesDev(); + warnInvalidHookAccess(); + mountHookTypesDev(); return mountInsertionEffect(create, deps); }, useLayoutEffect: function (create, deps) { currentHookNameInDev = "useLayoutEffect"; - updateHookTypesDev(); + warnInvalidHookAccess(); + mountHookTypesDev(); return mountLayoutEffect(create, deps); }, useMemo: function (create, deps) { currentHookNameInDev = "useMemo"; - updateHookTypesDev(); + warnInvalidHookAccess(); + mountHookTypesDev(); var prevDispatcher = ReactCurrentDispatcher$1.current; ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV; @@ -12138,7 +12045,8 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; }, useReducer: function (reducer, initialArg, init) { currentHookNameInDev = "useReducer"; - updateHookTypesDev(); + warnInvalidHookAccess(); + mountHookTypesDev(); var prevDispatcher = ReactCurrentDispatcher$1.current; ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV; @@ -12151,12 +12059,14 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; }, useRef: function (initialValue) { currentHookNameInDev = "useRef"; - updateHookTypesDev(); + warnInvalidHookAccess(); + mountHookTypesDev(); return mountRef(initialValue); }, useState: function (initialState) { currentHookNameInDev = "useState"; - updateHookTypesDev(); + warnInvalidHookAccess(); + mountHookTypesDev(); var prevDispatcher = ReactCurrentDispatcher$1.current; ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV; @@ -12169,80 +12079,100 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; }, useDebugValue: function (value, formatterFn) { currentHookNameInDev = "useDebugValue"; - updateHookTypesDev(); + warnInvalidHookAccess(); + mountHookTypesDev(); return mountDebugValue(); }, useDeferredValue: function (value) { currentHookNameInDev = "useDeferredValue"; - updateHookTypesDev(); + warnInvalidHookAccess(); + mountHookTypesDev(); return mountDeferredValue(value); }, useTransition: function () { currentHookNameInDev = "useTransition"; - updateHookTypesDev(); + warnInvalidHookAccess(); + mountHookTypesDev(); return mountTransition(); }, useMutableSource: function (source, getSnapshot, subscribe) { currentHookNameInDev = "useMutableSource"; - updateHookTypesDev(); + warnInvalidHookAccess(); + mountHookTypesDev(); return mountMutableSource(source, getSnapshot, subscribe); }, useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { currentHookNameInDev = "useSyncExternalStore"; - updateHookTypesDev(); + warnInvalidHookAccess(); + mountHookTypesDev(); return mountSyncExternalStore(subscribe, getSnapshot); }, useId: function () { currentHookNameInDev = "useId"; - updateHookTypesDev(); + warnInvalidHookAccess(); + mountHookTypesDev(); return mountId(); } }; { - HooksDispatcherOnMountWithHookTypesInDEV.use = use; + InvalidNestedHooksDispatcherOnMountInDEV.use = function (usable) { + warnInvalidHookAccess(); + return use(usable); + }; } { - HooksDispatcherOnMountWithHookTypesInDEV.useMemoCache = useMemoCache; + InvalidNestedHooksDispatcherOnMountInDEV.useMemoCache = function (size) { + warnInvalidHookAccess(); + return useMemoCache(size); + }; } - HooksDispatcherOnUpdateInDEV = { + 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 = @@ -12256,6 +12186,7 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; }, useReducer: function (reducer, initialArg, init) { currentHookNameInDev = "useReducer"; + warnInvalidHookAccess(); updateHookTypesDev(); var prevDispatcher = ReactCurrentDispatcher$1.current; ReactCurrentDispatcher$1.current = @@ -12269,11 +12200,13 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; }, useRef: function (initialValue) { currentHookNameInDev = "useRef"; + warnInvalidHookAccess(); updateHookTypesDev(); return updateRef(); }, useState: function (initialState) { currentHookNameInDev = "useState"; + warnInvalidHookAccess(); updateHookTypesDev(); var prevDispatcher = ReactCurrentDispatcher$1.current; ReactCurrentDispatcher$1.current = @@ -12287,84 +12220,104 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; }, 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(source, getSnapshot, subscribe); }, useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { currentHookNameInDev = "useSyncExternalStore"; + warnInvalidHookAccess(); updateHookTypesDev(); return updateSyncExternalStore(subscribe, getSnapshot); }, useId: function () { currentHookNameInDev = "useId"; + warnInvalidHookAccess(); updateHookTypesDev(); return updateId(); } }; { - HooksDispatcherOnUpdateInDEV.use = use; + InvalidNestedHooksDispatcherOnUpdateInDEV.use = function (usable) { + warnInvalidHookAccess(); + return use(usable); + }; } { - HooksDispatcherOnUpdateInDEV.useMemoCache = useMemoCache; + InvalidNestedHooksDispatcherOnUpdateInDEV.useMemoCache = function (size) { + warnInvalidHookAccess(); + return useMemoCache(size); + }; } - HooksDispatcherOnRerenderInDEV = { + 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 = - InvalidNestedHooksDispatcherOnRerenderInDEV; + InvalidNestedHooksDispatcherOnUpdateInDEV; try { return updateMemo(create, deps); @@ -12374,10 +12327,11 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; }, useReducer: function (reducer, initialArg, init) { currentHookNameInDev = "useReducer"; + warnInvalidHookAccess(); updateHookTypesDev(); var prevDispatcher = ReactCurrentDispatcher$1.current; ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnRerenderInDEV; + InvalidNestedHooksDispatcherOnUpdateInDEV; try { return rerenderReducer(reducer, initialArg, init); @@ -12387,15 +12341,17 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; }, useRef: function (initialValue) { currentHookNameInDev = "useRef"; + warnInvalidHookAccess(); updateHookTypesDev(); return updateRef(); }, useState: function (initialState) { currentHookNameInDev = "useState"; + warnInvalidHookAccess(); updateHookTypesDev(); var prevDispatcher = ReactCurrentDispatcher$1.current; ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnRerenderInDEV; + InvalidNestedHooksDispatcherOnUpdateInDEV; try { return rerenderState(initialState); @@ -12405,2446 +12361,2545 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; }, 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(source, getSnapshot, subscribe); }, useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { currentHookNameInDev = "useSyncExternalStore"; + warnInvalidHookAccess(); updateHookTypesDev(); return updateSyncExternalStore(subscribe, getSnapshot); }, useId: function () { currentHookNameInDev = "useId"; + warnInvalidHookAccess(); updateHookTypesDev(); return updateId(); } }; { - HooksDispatcherOnRerenderInDEV.use = use; + InvalidNestedHooksDispatcherOnRerenderInDEV.use = function (usable) { + warnInvalidHookAccess(); + return use(usable); + }; + } + + { + InvalidNestedHooksDispatcherOnRerenderInDEV.useMemoCache = function (size) { + warnInvalidHookAccess(); + return useMemoCache(size); + }; + } +} + +var now = Scheduler.unstable_now; +var commitTime = 0; +var layoutEffectStartTime = -1; +var profilerStartTime = -1; +var passiveEffectStartTime = -1; +/** + * Tracks whether the current update was a nested/cascading update (scheduled from a layout effect). + * + * The overall sequence is: + * 1. render + * 2. commit (and call `onRender`, `onCommit`) + * 3. check for nested updates + * 4. flush passive effects (and call `onPostCommit`) + * + * Nested updates are identified in step 3 above, + * but step 4 still applies to the work that was just committed. + * We use two flags to track nested updates then: + * one tracks whether the upcoming update is a nested update, + * and the other tracks whether the current update was a nested update. + * The first value gets synced to the second at the start of the render phase. + */ + +var currentUpdateIsNested = false; +var nestedUpdateScheduled = false; + +function isCurrentUpdateNested() { + return currentUpdateIsNested; +} + +function markNestedUpdateScheduled() { + { + nestedUpdateScheduled = true; + } +} + +function resetNestedUpdateFlag() { + { + currentUpdateIsNested = false; + nestedUpdateScheduled = false; + } +} + +function syncNestedUpdateFlag() { + { + currentUpdateIsNested = nestedUpdateScheduled; + nestedUpdateScheduled = false; + } +} + +function getCommitTime() { + return commitTime; +} + +function recordCommitTime() { + commitTime = now(); +} + +function startProfilerTimer(fiber) { + profilerStartTime = now(); + + if (fiber.actualStartTime < 0) { + fiber.actualStartTime = now(); + } +} + +function stopProfilerTimerIfRunning(fiber) { + profilerStartTime = -1; +} + +function stopProfilerTimerIfRunningAndRecordDelta(fiber, overrideBaseTime) { + if (profilerStartTime >= 0) { + var elapsedTime = now() - profilerStartTime; + fiber.actualDuration += elapsedTime; + + if (overrideBaseTime) { + fiber.selfBaseDuration = elapsedTime; + } + + profilerStartTime = -1; + } +} + +function recordLayoutEffectDuration(fiber) { + if (layoutEffectStartTime >= 0) { + var elapsedTime = now() - layoutEffectStartTime; + layoutEffectStartTime = -1; // Store duration on the next nearest Profiler ancestor + // Or the root (for the DevTools Profiler to read) + + var 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() - 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(); +} + +function startPassiveEffectTimer() { + passiveEffectStartTime = now(); +} + +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; - { - HooksDispatcherOnRerenderInDEV.useMemoCache = useMemoCache; + while (child) { + // $FlowFixMe[unsafe-addition] addition with possible null/undefined value + fiber.actualDuration += child.actualDuration; + child = child.sibling; } +} - 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 resolveDefaultProps(Component, baseProps) { + if (Component && Component.defaultProps) { + // Resolve default props. Taken from ReactElement + var props = assign({}, baseProps); + var defaultProps = Component.defaultProps; - try { - return mountMemo(create, deps); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; + for (var propName in defaultProps) { + if (props[propName] === undefined) { + props[propName] = defaultProps[propName]; } - }, - 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; + return props; + } - 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(source, getSnapshot, subscribe); - }, - useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { - currentHookNameInDev = "useSyncExternalStore"; - warnInvalidHookAccess(); - mountHookTypesDev(); - return mountSyncExternalStore(subscribe, getSnapshot); - }, - useId: function () { - currentHookNameInDev = "useId"; - warnInvalidHookAccess(); - mountHookTypesDev(); - return mountId(); + return baseProps; +} + +var fakeInternalInstance = {}; +var didWarnAboutStateAssignmentForComponent; +var didWarnAboutUninitializedState; +var didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate; +var didWarnAboutLegacyLifecyclesAndDerivedState; +var didWarnAboutUndefinedDerivedState; +var didWarnAboutDirectlyAssigningPropsToState; +var didWarnAboutContextTypeAndContextTypes; +var didWarnAboutInvalidateContextType; +var didWarnOnInvalidCallback; + +{ + didWarnAboutStateAssignmentForComponent = new Set(); + didWarnAboutUninitializedState = new Set(); + didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate = new Set(); + didWarnAboutLegacyLifecyclesAndDerivedState = new Set(); + didWarnAboutDirectlyAssigningPropsToState = new Set(); + didWarnAboutUndefinedDerivedState = new Set(); + didWarnAboutContextTypeAndContextTypes = new Set(); + didWarnAboutInvalidateContextType = new Set(); + didWarnOnInvalidCallback = new Set(); // This is so gross but it's at least non-critical and can be removed if + // it causes problems. This is meant to give a nicer error message for + // ReactDOM15.unstable_renderSubtreeIntoContainer(reactDOM16Component, + // ...)) which otherwise throws a "_processChildContext is not a function" + // exception. + + Object.defineProperty(fakeInternalInstance, "_processChildContext", { + enumerable: false, + value: function () { + throw new Error( + "_processChildContext is not available in React 16+. This likely " + + "means you have multiple copies of React and are attempting to nest " + + "a React 15 tree inside a React 16 tree using " + + "unstable_renderSubtreeIntoContainer, which isn't supported. Try " + + "to make sure you have only one copy of React (and ideally, switch " + + "to ReactDOM.createPortal)." + ); } - }; + }); + Object.freeze(fakeInternalInstance); +} +function warnOnInvalidCallback(callback, callerName) { { - InvalidNestedHooksDispatcherOnMountInDEV.use = function (usable) { - warnInvalidHookAccess(); - return use(usable); - }; - } + if (callback === null || typeof callback === "function") { + return; + } - { - InvalidNestedHooksDispatcherOnMountInDEV.useMemoCache = function (size) { - warnInvalidHookAccess(); - return useMemoCache(size); - }; + 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 + ); + } } +} - 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; +function warnOnUndefinedDerivedState(type, partialState) { + { + if (partialState === undefined) { + var componentName = getComponentNameFromType(type) || "Component"; - 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; + if (!didWarnAboutUndefinedDerivedState.has(componentName)) { + didWarnAboutUndefinedDerivedState.add(componentName); - try { - return updateReducer(reducer, initialArg, init); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; + error( + "%s.getDerivedStateFromProps(): A valid state object (or null) must be returned. " + + "You have returned undefined.", + componentName + ); } - }, - 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 applyDerivedStateFromProps( + workInProgress, + ctor, + getDerivedStateFromProps, + nextProps +) { + var prevState = workInProgress.memoizedState; + var partialState = getDerivedStateFromProps(nextProps, prevState); + + { + if (workInProgress.mode & StrictLegacyMode) { + setIsStrictModeForDevtools(true); try { - return updateState(initialState); + // Invoke the function an extra time to help detect side-effects. + partialState = getDerivedStateFromProps(nextProps, prevState); } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; + setIsStrictModeForDevtools(false); } - }, - 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(source, getSnapshot, subscribe); - }, - useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { - currentHookNameInDev = "useSyncExternalStore"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateSyncExternalStore(subscribe, getSnapshot); - }, - useId: function () { - currentHookNameInDev = "useId"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateId(); } - }; - { - InvalidNestedHooksDispatcherOnUpdateInDEV.use = function (usable) { - warnInvalidHookAccess(); - return use(usable); - }; - } + warnOnUndefinedDerivedState(ctor, partialState); + } // Merge the partial state and the previous state. - { - InvalidNestedHooksDispatcherOnUpdateInDEV.useMemoCache = function (size) { - warnInvalidHookAccess(); - return useMemoCache(size); - }; + 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; } +} - 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 classComponentUpdater = { + isMounted: isMounted, + // $FlowFixMe[missing-local-annot] + enqueueSetState: function (inst, payload, callback) { + var fiber = get(inst); + var lane = requestUpdateLane(fiber); + var update = createUpdate(lane); + update.payload = payload; - try { - return updateMemo(create, deps); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; + if (callback !== undefined && callback !== null) { + { + warnOnInvalidCallback(callback, "setState"); } - }, - 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; + update.callback = callback; + } - 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(source, getSnapshot, subscribe); - }, - useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { - currentHookNameInDev = "useSyncExternalStore"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateSyncExternalStore(subscribe, getSnapshot); - }, - useId: function () { - currentHookNameInDev = "useId"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateId(); + var root = enqueueUpdate(fiber, update, lane); + + if (root !== null) { + var eventTime = requestEventTime(); + scheduleUpdateOnFiber(root, fiber, lane, eventTime); + entangleTransitions(root, fiber, lane); } - }; - { - InvalidNestedHooksDispatcherOnRerenderInDEV.use = function (usable) { - warnInvalidHookAccess(); - return use(usable); - }; - } + { + markStateUpdateScheduled(fiber, lane); + } + }, + enqueueReplaceState: function (inst, payload, callback) { + var fiber = get(inst); + var lane = requestUpdateLane(fiber); + var update = createUpdate(lane); + update.tag = ReplaceState; + update.payload = payload; - { - InvalidNestedHooksDispatcherOnRerenderInDEV.useMemoCache = function (size) { - warnInvalidHookAccess(); - return useMemoCache(size); - }; - } -} + if (callback !== undefined && callback !== null) { + { + warnOnInvalidCallback(callback, "replaceState"); + } -var now = Scheduler.unstable_now; -var commitTime = 0; -var layoutEffectStartTime = -1; -var profilerStartTime = -1; -var passiveEffectStartTime = -1; -/** - * Tracks whether the current update was a nested/cascading update (scheduled from a layout effect). - * - * The overall sequence is: - * 1. render - * 2. commit (and call `onRender`, `onCommit`) - * 3. check for nested updates - * 4. flush passive effects (and call `onPostCommit`) - * - * Nested updates are identified in step 3 above, - * but step 4 still applies to the work that was just committed. - * We use two flags to track nested updates then: - * one tracks whether the upcoming update is a nested update, - * and the other tracks whether the current update was a nested update. - * The first value gets synced to the second at the start of the render phase. - */ + update.callback = callback; + } -var currentUpdateIsNested = false; -var nestedUpdateScheduled = false; + var root = enqueueUpdate(fiber, update, lane); -function isCurrentUpdateNested() { - return currentUpdateIsNested; -} + if (root !== null) { + var eventTime = requestEventTime(); + scheduleUpdateOnFiber(root, fiber, lane, eventTime); + entangleTransitions(root, fiber, lane); + } -function markNestedUpdateScheduled() { - { - nestedUpdateScheduled = true; - } -} + { + markStateUpdateScheduled(fiber, lane); + } + }, + // $FlowFixMe[missing-local-annot] + enqueueForceUpdate: function (inst, callback) { + var fiber = get(inst); + var lane = requestUpdateLane(fiber); + var update = createUpdate(lane); + update.tag = ForceUpdate; -function resetNestedUpdateFlag() { - { - currentUpdateIsNested = false; - nestedUpdateScheduled = false; - } -} + if (callback !== undefined && callback !== null) { + { + warnOnInvalidCallback(callback, "forceUpdate"); + } -function syncNestedUpdateFlag() { - { - currentUpdateIsNested = nestedUpdateScheduled; - nestedUpdateScheduled = false; + update.callback = callback; + } + + var root = enqueueUpdate(fiber, update, lane); + + if (root !== null) { + var eventTime = requestEventTime(); + scheduleUpdateOnFiber(root, fiber, lane, eventTime); + entangleTransitions(root, fiber, lane); + } + + { + markForceUpdateScheduled(fiber, lane); + } } -} +}; -function getCommitTime() { - return commitTime; -} +function checkShouldComponentUpdate( + workInProgress, + ctor, + oldProps, + newProps, + oldState, + newState, + nextContext +) { + var instance = workInProgress.stateNode; -function recordCommitTime() { - commitTime = now(); -} + if (typeof instance.shouldComponentUpdate === "function") { + var shouldUpdate = instance.shouldComponentUpdate( + newProps, + newState, + nextContext + ); -function startProfilerTimer(fiber) { - profilerStartTime = now(); + { + if (workInProgress.mode & StrictLegacyMode) { + setIsStrictModeForDevtools(true); - if (fiber.actualStartTime < 0) { - fiber.actualStartTime = now(); + try { + // Invoke the function an extra time to help detect side-effects. + shouldUpdate = instance.shouldComponentUpdate( + newProps, + newState, + nextContext + ); + } finally { + setIsStrictModeForDevtools(false); + } + } + + if (shouldUpdate === undefined) { + error( + "%s.shouldComponentUpdate(): Returned undefined instead of a " + + "boolean value. Make sure to return true or false.", + getComponentNameFromType(ctor) || "Component" + ); + } + } + + return shouldUpdate; } -} -function stopProfilerTimerIfRunning(fiber) { - profilerStartTime = -1; + if (ctor.prototype && ctor.prototype.isPureReactComponent) { + return ( + !shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState) + ); + } + + return true; } -function stopProfilerTimerIfRunningAndRecordDelta(fiber, overrideBaseTime) { - if (profilerStartTime >= 0) { - var elapsedTime = now() - profilerStartTime; - fiber.actualDuration += elapsedTime; +function checkClassInstance(workInProgress, ctor, newProps) { + var instance = workInProgress.stateNode; - if (overrideBaseTime) { - fiber.selfBaseDuration = elapsedTime; + { + var name = getComponentNameFromType(ctor) || "Component"; + var renderPresent = instance.render; + + 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 + ); + } } - profilerStartTime = -1; - } -} + 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 + ); + } -function recordLayoutEffectDuration(fiber) { - if (layoutEffectStartTime >= 0) { - var elapsedTime = now() - layoutEffectStartTime; - layoutEffectStartTime = -1; // Store duration on the next nearest Profiler ancestor - // Or the root (for the DevTools Profiler to read) + 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 parentFiber = fiber.return; + if (instance.propTypes) { + error( + "propTypes was defined as an instance property on %s. Use a static " + + "property to define propTypes instead.", + name + ); + } - while (parentFiber !== null) { - switch (parentFiber.tag) { - case HostRoot: - var root = parentFiber.stateNode; - root.effectDuration += elapsedTime; - return; + if (instance.contextType) { + error( + "contextType was defined as an instance property on %s. Use a static " + + "property to define contextType instead.", + name + ); + } - case Profiler: - var parentStateNode = parentFiber.stateNode; - parentStateNode.effectDuration += elapsedTime; - return; + { + if (instance.contextTypes) { + error( + "contextTypes was defined as an instance property on %s. Use a static " + + "property to define contextTypes instead.", + name + ); } - parentFiber = parentFiber.return; + if ( + ctor.contextType && + ctor.contextTypes && + !didWarnAboutContextTypeAndContextTypes.has(ctor) + ) { + didWarnAboutContextTypeAndContextTypes.add(ctor); + + error( + "%s declares both contextTypes and contextType static properties. " + + "The legacy contextTypes property will be ignored.", + name + ); + } } - } -} -function recordPassiveEffectDuration(fiber) { - if (passiveEffectStartTime >= 0) { - var elapsedTime = now() - passiveEffectStartTime; - passiveEffectStartTime = -1; // Store duration on the next nearest Profiler ancestor - // Or the root (for the DevTools Profiler to read) + if (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 parentFiber = fiber.return; + 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" + ); + } - while (parentFiber !== null) { - switch (parentFiber.tag) { - case HostRoot: - var root = parentFiber.stateNode; + 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 (root !== null) { - root.passiveEffectDuration += elapsedTime; - } + 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 + ); + } - case Profiler: - var parentStateNode = parentFiber.stateNode; + if (typeof instance.UNSAFE_componentWillRecieveProps === "function") { + error( + "%s has a method called " + + "UNSAFE_componentWillRecieveProps(). Did you mean UNSAFE_componentWillReceiveProps()?", + name + ); + } - 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 hasMutatedProps = instance.props !== newProps; - return; - } + 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 + ); + } - parentFiber = parentFiber.return; + 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 startLayoutEffectTimer() { - layoutEffectStartTime = now(); -} + if ( + typeof instance.getSnapshotBeforeUpdate === "function" && + typeof instance.componentDidUpdate !== "function" && + !didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate.has(ctor) + ) { + didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate.add(ctor); -function startPassiveEffectTimer() { - passiveEffectStartTime = now(); -} + error( + "%s: getSnapshotBeforeUpdate() should be used with componentDidUpdate(). " + + "This component defines getSnapshotBeforeUpdate() only.", + getComponentNameFromType(ctor) + ); + } -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 (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 + ); + } - while (child) { - // $FlowFixMe[unsafe-addition] addition with possible null/undefined value - fiber.actualDuration += child.actualDuration; - child = child.sibling; - } -} + 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 resolveDefaultProps(Component, baseProps) { - if (Component && Component.defaultProps) { - // Resolve default props. Taken from ReactElement - var props = assign({}, baseProps); - var defaultProps = Component.defaultProps; + 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 + ); + } - for (var propName in defaultProps) { - if (props[propName] === undefined) { - props[propName] = defaultProps[propName]; - } + var state = instance.state; + + if (state && (typeof state !== "object" || isArray(state))) { + error("%s.state: must be set to an object or null", name); } - return props; + if ( + typeof instance.getChildContext === "function" && + typeof ctor.childContextTypes !== "object" + ) { + error( + "%s.getChildContext(): childContextTypes must be defined in order to " + + "use getChildContext().", + name + ); + } } - - return baseProps; } -var fakeInternalInstance = {}; -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(); +function adoptClassInstance(workInProgress, instance) { + instance.updater = classComponentUpdater; + workInProgress.stateNode = instance; // The instance needs access to the fiber so that it can schedule updates - warnOnInvalidCallback = function (callback, callerName) { - if (callback === null || typeof callback === "function") { - return; - } + set(instance, workInProgress); - var key = callerName + "_" + callback; + { + instance._reactInternalInstance = fakeInternalInstance; + } +} - if (!didWarnOnInvalidCallback.has(key)) { - didWarnOnInvalidCallback.add(key); +function constructClassInstance(workInProgress, ctor, props) { + var isLegacyContextConsumer = false; + var unmaskedContext = emptyContextObject; + var context = emptyContextObject; + var contextType = ctor.contextType; - error( - "%s(...): Expected the last optional `callback` argument to be a " + - "function. Instead received: %s.", - callerName, - callback - ); - } - }; + { + 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 - warnOnUndefinedDerivedState = function (type, partialState) { - if (partialState === undefined) { - var componentName = getComponentNameFromType(type) || "Component"; + if (!isValid && !didWarnAboutInvalidateContextType.has(ctor)) { + didWarnAboutInvalidateContextType.add(ctor); + var addendum = ""; - if (!didWarnAboutUndefinedDerivedState.has(componentName)) { - didWarnAboutUndefinedDerivedState.add(componentName); + 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.getDerivedStateFromProps(): A valid state object (or null) must be returned. " + - "You have returned undefined.", - componentName + "%s defines an invalid contextType. " + + "contextType should point to the Context object returned by React.createContext().%s", + getComponentNameFromType(ctor) || "Component", + addendum ); } } - }; // 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); -} + 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; + } -function applyDerivedStateFromProps( - workInProgress, - ctor, - getDerivedStateFromProps, - nextProps -) { - var prevState = workInProgress.memoizedState; - var partialState = getDerivedStateFromProps(nextProps, prevState); + var instance = new ctor(props, context); // Instantiate twice to help detect side-effects. { if (workInProgress.mode & StrictLegacyMode) { setIsStrictModeForDevtools(true); try { - // Invoke the function an extra time to help detect side-effects. - partialState = getDerivedStateFromProps(nextProps, prevState); + instance = new ctor(props, context); // eslint-disable-line no-new } finally { setIsStrictModeForDevtools(false); } } + } - 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. + var state = (workInProgress.memoizedState = + instance.state !== null && instance.state !== undefined + ? instance.state + : null); + adoptClassInstance(workInProgress, instance); - if (workInProgress.lanes === NoLanes) { - // Queue is always non-null for classes - var updateQueue = workInProgress.updateQueue; - updateQueue.baseState = memoizedState; - } -} + { + if (typeof ctor.getDerivedStateFromProps === "function" && state === null) { + var componentName = getComponentNameFromType(ctor) || "Component"; -var classComponentUpdater = { - isMounted: isMounted, - // $FlowFixMe[missing-local-annot] - enqueueSetState: function (inst, payload, callback) { - var fiber = get(inst); - var lane = requestUpdateLane(fiber); - var update = createUpdate(lane); - update.payload = payload; + if (!didWarnAboutUninitializedState.has(componentName)) { + didWarnAboutUninitializedState.add(componentName); - if (callback !== undefined && callback !== null) { - { - warnOnInvalidCallback(callback, "setState"); + 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. - update.callback = callback; - } - - var root = enqueueUpdate(fiber, update, lane); + if ( + typeof ctor.getDerivedStateFromProps === "function" || + typeof instance.getSnapshotBeforeUpdate === "function" + ) { + var foundWillMountName = null; + var foundWillReceivePropsName = null; + var foundWillUpdateName = null; - if (root !== null) { - var eventTime = requestEventTime(); - scheduleUpdateOnFiber(root, fiber, lane, eventTime); - entangleTransitions(root, fiber, lane); - } + if ( + typeof instance.componentWillMount === "function" && + instance.componentWillMount.__suppressDeprecationWarning !== true + ) { + foundWillMountName = "componentWillMount"; + } else if (typeof instance.UNSAFE_componentWillMount === "function") { + foundWillMountName = "UNSAFE_componentWillMount"; + } - { - markStateUpdateScheduled(fiber, lane); - } - }, - enqueueReplaceState: function (inst, payload, callback) { - var fiber = get(inst); - var lane = requestUpdateLane(fiber); - var update = createUpdate(lane); - update.tag = ReplaceState; - update.payload = payload; + if ( + typeof instance.componentWillReceiveProps === "function" && + instance.componentWillReceiveProps.__suppressDeprecationWarning !== true + ) { + foundWillReceivePropsName = "componentWillReceiveProps"; + } else if ( + typeof instance.UNSAFE_componentWillReceiveProps === "function" + ) { + foundWillReceivePropsName = "UNSAFE_componentWillReceiveProps"; + } - if (callback !== undefined && callback !== null) { - { - warnOnInvalidCallback(callback, "replaceState"); + if ( + typeof instance.componentWillUpdate === "function" && + instance.componentWillUpdate.__suppressDeprecationWarning !== true + ) { + foundWillUpdateName = "componentWillUpdate"; + } else if (typeof instance.UNSAFE_componentWillUpdate === "function") { + foundWillUpdateName = "UNSAFE_componentWillUpdate"; } - update.callback = callback; - } + if ( + foundWillMountName !== null || + foundWillReceivePropsName !== null || + foundWillUpdateName !== null + ) { + var _componentName = getComponentNameFromType(ctor) || "Component"; - var root = enqueueUpdate(fiber, update, lane); + var newApiName = + typeof ctor.getDerivedStateFromProps === "function" + ? "getDerivedStateFromProps()" + : "getSnapshotBeforeUpdate()"; - if (root !== null) { - var eventTime = requestEventTime(); - scheduleUpdateOnFiber(root, fiber, lane, eventTime); - entangleTransitions(root, fiber, lane); - } + if (!didWarnAboutLegacyLifecyclesAndDerivedState.has(_componentName)) { + didWarnAboutLegacyLifecyclesAndDerivedState.add(_componentName); - { - markStateUpdateScheduled(fiber, lane); + error( + "Unsafe legacy lifecycles will not be called for components using new component APIs.\n\n" + + "%s uses %s but also contains the following legacy lifecycles:%s%s%s\n\n" + + "The above lifecycles should be removed. Learn more about this warning here:\n" + + "https://reactjs.org/link/unsafe-component-lifecycles", + _componentName, + newApiName, + foundWillMountName !== null ? "\n " + foundWillMountName : "", + foundWillReceivePropsName !== null + ? "\n " + foundWillReceivePropsName + : "", + foundWillUpdateName !== null ? "\n " + foundWillUpdateName : "" + ); + } + } } - }, - // $FlowFixMe[missing-local-annot] - enqueueForceUpdate: function (inst, callback) { - var fiber = get(inst); - var lane = requestUpdateLane(fiber); - var update = createUpdate(lane); - update.tag = ForceUpdate; + } // 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 (callback !== undefined && callback !== null) { - { - warnOnInvalidCallback(callback, "forceUpdate"); - } + if (isLegacyContextConsumer) { + cacheContext(workInProgress, unmaskedContext, context); + } - update.callback = callback; - } + return instance; +} - var root = enqueueUpdate(fiber, update, lane); +function callComponentWillMount(workInProgress, instance) { + var oldState = instance.state; - if (root !== null) { - var eventTime = requestEventTime(); - scheduleUpdateOnFiber(root, fiber, lane, eventTime); - entangleTransitions(root, fiber, lane); - } + if (typeof instance.componentWillMount === "function") { + instance.componentWillMount(); + } + + if (typeof instance.UNSAFE_componentWillMount === "function") { + instance.UNSAFE_componentWillMount(); + } + if (oldState !== instance.state) { { - markForceUpdateScheduled(fiber, lane); + error( + "%s.componentWillMount(): Assigning directly to this.state is " + + "deprecated (except inside a component's " + + "constructor). Use setState instead.", + getComponentNameFromFiber(workInProgress) || "Component" + ); } + + classComponentUpdater.enqueueReplaceState(instance, instance.state, null); } -}; +} -function checkShouldComponentUpdate( +function callComponentWillReceiveProps( workInProgress, - ctor, - oldProps, + instance, newProps, - oldState, - newState, nextContext ) { - var instance = workInProgress.stateNode; + var oldState = instance.state; - if (typeof instance.shouldComponentUpdate === "function") { - var shouldUpdate = instance.shouldComponentUpdate( - newProps, - newState, - nextContext - ); + if (typeof instance.componentWillReceiveProps === "function") { + instance.componentWillReceiveProps(newProps, nextContext); + } + if (typeof instance.UNSAFE_componentWillReceiveProps === "function") { + instance.UNSAFE_componentWillReceiveProps(newProps, nextContext); + } + + if (instance.state !== oldState) { { - if (workInProgress.mode & StrictLegacyMode) { - setIsStrictModeForDevtools(true); + var componentName = + getComponentNameFromFiber(workInProgress) || "Component"; - try { - // Invoke the function an extra time to help detect side-effects. - shouldUpdate = instance.shouldComponentUpdate( - newProps, - newState, - nextContext - ); - } finally { - setIsStrictModeForDevtools(false); - } - } + if (!didWarnAboutStateAssignmentForComponent.has(componentName)) { + didWarnAboutStateAssignmentForComponent.add(componentName); - if (shouldUpdate === undefined) { error( - "%s.shouldComponentUpdate(): Returned undefined instead of a " + - "boolean value. Make sure to return true or false.", - getComponentNameFromType(ctor) || "Component" + "%s.componentWillReceiveProps(): Assigning directly to " + + "this.state is deprecated (except inside a component's " + + "constructor). Use setState instead.", + componentName ); } } - return shouldUpdate; + classComponentUpdater.enqueueReplaceState(instance, instance.state, null); } +} // Invokes the mount life-cycles on a previously never rendered instance. - if (ctor.prototype && ctor.prototype.isPureReactComponent) { - return ( - !shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState) - ); +function mountClassInstance(workInProgress, ctor, newProps, renderLanes) { + { + checkClassInstance(workInProgress, ctor, newProps); } - return true; -} - -function checkClassInstance(workInProgress, ctor, newProps) { var instance = workInProgress.stateNode; + instance.props = newProps; + instance.state = workInProgress.memoizedState; + instance.refs = {}; + initializeUpdateQueue(workInProgress); + var contextType = ctor.contextType; + + if (typeof contextType === "object" && contextType !== null) { + instance.context = readContext(contextType); + } else { + var unmaskedContext = getUnmaskedContext(workInProgress, ctor, true); + instance.context = getMaskedContext(workInProgress, unmaskedContext); + } { - var name = getComponentNameFromType(ctor) || "Component"; - var renderPresent = instance.render; + if (instance.state === newProps) { + var componentName = getComponentNameFromType(ctor) || "Component"; + + if (!didWarnAboutDirectlyAssigningPropsToState.has(componentName)) { + didWarnAboutDirectlyAssigningPropsToState.add(componentName); - 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 + "%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 ( - instance.getInitialState && - !instance.getInitialState.isReactClassApproved && - !instance.state - ) { - error( - "getInitialState was defined on %s, a plain JavaScript class. " + - "This is only supported for classes created using React.createClass. " + - "Did you mean to define a state property instead?", - name + if (workInProgress.mode & StrictLegacyMode) { + ReactStrictModeWarnings.recordLegacyContextWarning( + workInProgress, + instance ); } - 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 - ); - } + ReactStrictModeWarnings.recordUnsafeLifecycleWarnings( + workInProgress, + instance + ); + } - if (instance.propTypes) { - error( - "propTypes was defined as an instance property on %s. Use a static " + - "property to define propTypes instead.", - name - ); - } + instance.state = workInProgress.memoizedState; + var getDerivedStateFromProps = ctor.getDerivedStateFromProps; - if (instance.contextType) { - error( - "contextType was defined as an instance property on %s. Use a static " + - "property to define contextType instead.", - name - ); - } + 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 (instance.contextTypes) { - error( - "contextTypes was defined as an instance property on %s. Use a static " + - "property to define contextTypes instead.", - name - ); - } + if ( + typeof ctor.getDerivedStateFromProps !== "function" && + typeof instance.getSnapshotBeforeUpdate !== "function" && + (typeof instance.UNSAFE_componentWillMount === "function" || + typeof instance.componentWillMount === "function") + ) { + callComponentWillMount(workInProgress, instance); // If we had additional state updates during this life-cycle, let's + // process them now. - if ( - ctor.contextType && - ctor.contextTypes && - !didWarnAboutContextTypeAndContextTypes.has(ctor) - ) { - didWarnAboutContextTypeAndContextTypes.add(ctor); + processUpdateQueue(workInProgress, newProps, instance, renderLanes); + instance.state = workInProgress.memoizedState; + } - error( - "%s declares both contextTypes and contextType static properties. " + - "The legacy contextTypes property will be ignored.", - name - ); - } - } + if (typeof instance.componentDidMount === "function") { + var fiberFlags = Update | LayoutStatic; - 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 ((workInProgress.mode & StrictEffectsMode) !== NoMode) { + fiberFlags |= MountLayoutDev; } - 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" - ); - } + workInProgress.flags |= fiberFlags; + } +} - 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 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 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 (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 ); } + } - if (typeof instance.componentWillRecieveProps === "function") { - error( - "%s has a method called " + - "componentWillRecieveProps(). Did you mean componentWillReceiveProps()?", - name - ); - } + resetHasForceUpdateBeforeProcessing(); + var oldState = workInProgress.memoizedState; + var newState = (instance.state = oldState); + processUpdateQueue(workInProgress, newProps, instance, renderLanes); + newState = workInProgress.memoizedState; - if (typeof instance.UNSAFE_componentWillRecieveProps === "function") { - error( - "%s has a method called " + - "UNSAFE_componentWillRecieveProps(). Did you mean UNSAFE_componentWillReceiveProps()?", - name - ); - } + 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 | LayoutStatic; - var hasMutatedProps = instance.props !== newProps; + if ((workInProgress.mode & StrictEffectsMode) !== NoMode) { + fiberFlags |= MountLayoutDev; + } - 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 - ); + workInProgress.flags |= fiberFlags; } - 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 - ); - } + return false; + } - if ( - typeof instance.getSnapshotBeforeUpdate === "function" && - typeof instance.componentDidUpdate !== "function" && - !didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate.has(ctor) - ) { - didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate.add(ctor); + if (typeof getDerivedStateFromProps === "function") { + applyDerivedStateFromProps( + workInProgress, + ctor, + getDerivedStateFromProps, + newProps + ); + newState = workInProgress.memoizedState; + } - error( - "%s: getSnapshotBeforeUpdate() should be used with componentDidUpdate(). " + - "This component defines getSnapshotBeforeUpdate() only.", - getComponentNameFromType(ctor) - ); - } + var shouldUpdate = + checkHasForceUpdateAfterProcessing() || + checkShouldComponentUpdate( + workInProgress, + ctor, + oldProps, + newProps, + oldState, + newState, + nextContext + ); - 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 (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 (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 instance.UNSAFE_componentWillMount === "function") { + instance.UNSAFE_componentWillMount(); + } } - 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 (typeof instance.componentDidMount === "function") { + var _fiberFlags = Update | LayoutStatic; - var state = instance.state; + if ((workInProgress.mode & StrictEffectsMode) !== NoMode) { + _fiberFlags |= MountLayoutDev; + } - if (state && (typeof state !== "object" || isArray(state))) { - error("%s.state: must be set to an object or null", name); + 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 | LayoutStatic; - if ( - typeof instance.getChildContext === "function" && - typeof ctor.childContextTypes !== "object" - ) { - error( - "%s.getChildContext(): childContextTypes must be defined in order to " + - "use getChildContext().", - name - ); - } - } -} + if ((workInProgress.mode & StrictEffectsMode) !== NoMode) { + _fiberFlags2 |= MountLayoutDev; + } -function adoptClassInstance(workInProgress, instance) { - instance.updater = classComponentUpdater; - workInProgress.stateNode = instance; // The instance needs access to the fiber so that it can schedule updates + workInProgress.flags |= _fiberFlags2; + } // If shouldComponentUpdate returned false, we should still update the + // memoized state to indicate that this work can be reused. - set(instance, workInProgress); + workInProgress.memoizedProps = newProps; + workInProgress.memoizedState = newState; + } // Update the existing instance's state, props, and context pointers even + // if shouldComponentUpdate returns false. - { - instance._reactInternalInstance = fakeInternalInstance; - } -} + 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 constructClassInstance(workInProgress, ctor, props) { - var isLegacyContextConsumer = false; - var unmaskedContext = emptyContextObject; - var context = emptyContextObject; +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 ("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 (typeof contextType === "object" && contextType !== null) { + nextContext = readContext(contextType); + } else { + var nextUnmaskedContext = getUnmaskedContext(workInProgress, ctor, true); + nextContext = getMaskedContext(workInProgress, nextUnmaskedContext); + } - if (contextType === undefined) { - addendum = - " However, it is set to undefined. " + - "This can be caused by a typo or by mixing up named and default imports. " + - "This can also happen due to a circular dependency, so " + - "try moving the createContext() call to a separate file."; - } else if (typeof contextType !== "object") { - addendum = " However, it is set to a " + typeof contextType + "."; - } else if (contextType.$$typeof === REACT_PROVIDER_TYPE) { - addendum = " Did you accidentally pass the Context.Provider instead?"; - } else if (contextType._context !== undefined) { - // - addendum = " Did you accidentally pass the Context.Consumer instead?"; - } else { - addendum = - " However, it is set to an object with keys {" + - Object.keys(contextType).join(", ") + - "}."; - } + var 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. - error( - "%s defines an invalid contextType. " + - "contextType should point to the Context object returned by React.createContext().%s", - getComponentNameFromType(ctor) || "Component", - addendum - ); - } + if ( + !hasNewLifecycles && + (typeof instance.UNSAFE_componentWillReceiveProps === "function" || + typeof instance.componentWillReceiveProps === "function") + ) { + if ( + unresolvedOldProps !== unresolvedNewProps || + oldContext !== nextContext + ) { + callComponentWillReceiveProps( + workInProgress, + instance, + newProps, + nextContext + ); } } - 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. - - { - if (workInProgress.mode & StrictLegacyMode) { - setIsStrictModeForDevtools(true); + resetHasForceUpdateBeforeProcessing(); + var oldState = workInProgress.memoizedState; + var newState = (instance.state = oldState); + processUpdateQueue(workInProgress, newProps, instance, renderLanes); + newState = workInProgress.memoizedState; - try { - instance = new ctor(props, context); // eslint-disable-line no-new - } finally { - setIsStrictModeForDevtools(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 state = (workInProgress.memoizedState = - instance.state !== null && instance.state !== undefined - ? instance.state - : null); - adoptClassInstance(workInProgress, instance); + if (typeof instance.getSnapshotBeforeUpdate === "function") { + if ( + unresolvedOldProps !== current.memoizedProps || + oldState !== current.memoizedState + ) { + workInProgress.flags |= Snapshot; + } + } - { - if (typeof ctor.getDerivedStateFromProps === "function" && state === null) { - var componentName = getComponentNameFromType(ctor) || "Component"; + return false; + } - if (!didWarnAboutUninitializedState.has(componentName)) { - didWarnAboutUninitializedState.add(componentName); + if (typeof getDerivedStateFromProps === "function") { + applyDerivedStateFromProps( + workInProgress, + ctor, + getDerivedStateFromProps, + newProps + ); + newState = workInProgress.memoizedState; + } - error( - "`%s` uses `getDerivedStateFromProps` but its initial state is " + - "%s. This is not recommended. Instead, define the initial state by " + - "assigning an object to `this.state` in the constructor of `%s`. " + - "This ensures that `getDerivedStateFromProps` arguments have a consistent shape.", - componentName, - instance.state === null ? "null" : "undefined", - componentName - ); - } - } // If new component APIs are defined, "unsafe" lifecycles won't be called. - // Warn about these lifecycles if they are present. - // Don't warn about react-lifecycles-compat polyfilled methods though. + var 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 ( - typeof ctor.getDerivedStateFromProps === "function" || - typeof instance.getSnapshotBeforeUpdate === "function" + !hasNewLifecycles && + (typeof instance.UNSAFE_componentWillUpdate === "function" || + typeof instance.componentWillUpdate === "function") ) { - var foundWillMountName = null; - var foundWillReceivePropsName = null; - var foundWillUpdateName = null; - - if ( - typeof instance.componentWillMount === "function" && - instance.componentWillMount.__suppressDeprecationWarning !== true - ) { - foundWillMountName = "componentWillMount"; - } else if (typeof instance.UNSAFE_componentWillMount === "function") { - foundWillMountName = "UNSAFE_componentWillMount"; + if (typeof instance.componentWillUpdate === "function") { + instance.componentWillUpdate(newProps, newState, nextContext); } - if ( - typeof instance.componentWillReceiveProps === "function" && - instance.componentWillReceiveProps.__suppressDeprecationWarning !== true - ) { - foundWillReceivePropsName = "componentWillReceiveProps"; - } else if ( - typeof instance.UNSAFE_componentWillReceiveProps === "function" - ) { - foundWillReceivePropsName = "UNSAFE_componentWillReceiveProps"; + if (typeof instance.UNSAFE_componentWillUpdate === "function") { + instance.UNSAFE_componentWillUpdate(newProps, newState, nextContext); } + } + + if (typeof instance.componentDidUpdate === "function") { + workInProgress.flags |= Update; + } + if (typeof instance.getSnapshotBeforeUpdate === "function") { + workInProgress.flags |= Snapshot; + } + } else { + // If an update was already in progress, we should schedule an Update + // effect even though we're bailing out, so that cWU/cDU are called. + if (typeof instance.componentDidUpdate === "function") { if ( - typeof instance.componentWillUpdate === "function" && - instance.componentWillUpdate.__suppressDeprecationWarning !== true + unresolvedOldProps !== current.memoizedProps || + oldState !== current.memoizedState ) { - foundWillUpdateName = "componentWillUpdate"; - } else if (typeof instance.UNSAFE_componentWillUpdate === "function") { - foundWillUpdateName = "UNSAFE_componentWillUpdate"; + workInProgress.flags |= Update; } + } + if (typeof instance.getSnapshotBeforeUpdate === "function") { if ( - foundWillMountName !== null || - foundWillReceivePropsName !== null || - foundWillUpdateName !== null + unresolvedOldProps !== current.memoizedProps || + oldState !== current.memoizedState ) { - var _componentName = getComponentNameFromType(ctor) || "Component"; - - var newApiName = - typeof ctor.getDerivedStateFromProps === "function" - ? "getDerivedStateFromProps()" - : "getSnapshotBeforeUpdate()"; - - if (!didWarnAboutLegacyLifecyclesAndDerivedState.has(_componentName)) { - didWarnAboutLegacyLifecyclesAndDerivedState.add(_componentName); - - error( - "Unsafe legacy lifecycles will not be called for components using new component APIs.\n\n" + - "%s uses %s but also contains the following legacy lifecycles:%s%s%s\n\n" + - "The above lifecycles should be removed. Learn more about this warning here:\n" + - "https://reactjs.org/link/unsafe-component-lifecycles", - _componentName, - newApiName, - foundWillMountName !== null ? "\n " + foundWillMountName : "", - foundWillReceivePropsName !== null - ? "\n " + foundWillReceivePropsName - : "", - foundWillUpdateName !== null ? "\n " + foundWillUpdateName : "" - ); - } + workInProgress.flags |= Snapshot; } - } - } // 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 shouldComponentUpdate returned false, we should still update the + // memoized props/state to indicate that this work can be reused. - if (isLegacyContextConsumer) { - cacheContext(workInProgress, unmaskedContext, context); - } + workInProgress.memoizedProps = newProps; + workInProgress.memoizedState = newState; + } // Update the existing instance's state, props, and context pointers even + // if shouldComponentUpdate returns false. - return instance; + instance.props = newProps; + instance.state = newState; + instance.context = nextContext; + return shouldUpdate; } -function callComponentWillMount(workInProgress, instance) { - var oldState = instance.state; - - if (typeof instance.componentWillMount === "function") { - instance.componentWillMount(); - } - - if (typeof instance.UNSAFE_componentWillMount === "function") { - instance.UNSAFE_componentWillMount(); - } +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 (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 ( + typeof ReactNativePrivateInterface.ReactFiberErrorDialog.showErrorDialog !== + "function" +) { + throw new Error( + "Expected ReactFiberErrorDialog.showErrorDialog to be a function." + ); +} - classComponentUpdater.enqueueReplaceState(instance, instance.state, 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 + ); } -function callComponentWillReceiveProps( - workInProgress, - instance, - newProps, - nextContext -) { - var oldState = instance.state; +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 instance.componentWillReceiveProps === "function") { - instance.componentWillReceiveProps(newProps, nextContext); - } + if (logError === false) { + return; + } - if (typeof instance.UNSAFE_componentWillReceiveProps === "function") { - instance.UNSAFE_componentWillReceiveProps(newProps, nextContext); - } + var error = errorInfo.value; - if (instance.state !== oldState) { - { - var componentName = - getComponentNameFromFiber(workInProgress) || "Component"; + 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 (!didWarnAboutStateAssignmentForComponent.has(componentName)) { - didWarnAboutStateAssignmentForComponent.add(componentName); + if (error != null && error._suppressLogging) { + if (boundary.tag === ClassComponent) { + // The error is recoverable and was silenced. + // Ignore it and don't print the stack addendum. + // This is handy for testing error boundaries without noise. + return; + } // The error is fatal. Since the silencing might have + // been accidental, we'll surface it anyway. + // However, the browser would have silenced the original error + // so we'll print it first, and then print the stack addendum. - error( - "%s.componentWillReceiveProps(): Assigning directly to " + - "this.state is deprecated (except inside a component's " + - "constructor). Use setState instead.", - componentName - ); + 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 } - } - classComponentUpdater.enqueueReplaceState(instance, instance.state, null); - } -} // Invokes the mount life-cycles on a previously never rendered instance. + 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; -function mountClassInstance(workInProgress, ctor, newProps, renderLanes) { - { - checkClassInstance(workInProgress, ctor, newProps); - } + if (boundary.tag === HostRoot) { + errorBoundaryMessage = + "Consider adding an error boundary to your tree to customize error handling behavior.\n" + + "Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries."; + } else { + var errorBoundaryName = + getComponentNameFromFiber(boundary) || "Anonymous"; + errorBoundaryMessage = + "React will try to recreate this component tree from scratch " + + ("using the error boundary you provided, " + errorBoundaryName + "."); + } - var instance = workInProgress.stateNode; - instance.props = newProps; - instance.state = workInProgress.memoizedState; - instance.refs = {}; - initializeUpdateQueue(workInProgress); - var contextType = ctor.contextType; + 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. - if (typeof contextType === "object" && contextType !== null) { - instance.context = readContext(contextType); - } else { - var unmaskedContext = getUnmaskedContext(workInProgress, ctor, true); - instance.context = getMaskedContext(workInProgress, unmaskedContext); + console["error"](combinedMessage); // Don't transform to our wrapper + } + } catch (e) { + // This method must not throw, or React internal state will get messed up. + // If console.error is overridden, or logCapturedError() shows a dialog that throws, + // we want to report this error outside of the normal stack as a last resort. + // https://github.com/facebook/react/issues/13188 + setTimeout(function () { + throw e; + }); } +} - { - if (instance.state === newProps) { - var componentName = getComponentNameFromType(ctor) || "Component"; +function createRootErrorUpdate(fiber, errorInfo, lane) { + var update = createUpdate(lane); // Unmount the root by rendering null. - if (!didWarnAboutDirectlyAssigningPropsToState.has(componentName)) { - didWarnAboutDirectlyAssigningPropsToState.add(componentName); + update.tag = CaptureUpdate; // Caution: React DevTools currently depends on this property + // being called "element". - 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 - ); - } - } + update.payload = { + element: null + }; + var error = errorInfo.value; - if (workInProgress.mode & StrictLegacyMode) { - ReactStrictModeWarnings.recordLegacyContextWarning( - workInProgress, - instance - ); - } + update.callback = function () { + onUncaughtError(error); + logCapturedError(fiber, errorInfo); + }; - ReactStrictModeWarnings.recordUnsafeLifecycleWarnings( - workInProgress, - instance - ); - } + return update; +} - instance.state = workInProgress.memoizedState; - var getDerivedStateFromProps = ctor.getDerivedStateFromProps; +function createClassErrorUpdate(fiber, errorInfo, lane) { + var update = createUpdate(lane); + update.tag = CaptureUpdate; + var getDerivedStateFromError = fiber.type.getDerivedStateFromError; - 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 getDerivedStateFromError === "function") { + var error$1 = errorInfo.value; - 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. + update.payload = function () { + return getDerivedStateFromError(error$1); + }; - processUpdateQueue(workInProgress, newProps, instance, renderLanes); - instance.state = workInProgress.memoizedState; + update.callback = function () { + { + markFailedErrorBoundaryForHotReloading(fiber); + } + + logCapturedError(fiber, errorInfo); + }; } - if (typeof instance.componentDidMount === "function") { - var fiberFlags = Update | LayoutStatic; + var inst = fiber.stateNode; - if ((workInProgress.mode & StrictEffectsMode) !== NoMode) { - fiberFlags |= MountLayoutDev; - } + if (inst !== null && typeof inst.componentDidCatch === "function") { + // $FlowFixMe[missing-this-annot] + update.callback = function callback() { + { + markFailedErrorBoundaryForHotReloading(fiber); + } - workInProgress.flags |= fiberFlags; - } -} + logCapturedError(fiber, errorInfo); -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 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 (typeof contextType === "object" && contextType !== null) { - nextContext = readContext(contextType); - } else { - var nextLegacyUnmaskedContext = getUnmaskedContext( - workInProgress, - ctor, - true - ); - nextContext = getMaskedContext(workInProgress, nextLegacyUnmaskedContext); + 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" + ); + } + } + } + }; } - var getDerivedStateFromProps = ctor.getDerivedStateFromProps; - var hasNewLifecycles = - typeof getDerivedStateFromProps === "function" || - typeof instance.getSnapshotBeforeUpdate === "function"; // Note: During these life-cycles, instance.props/instance.state are what - // ever the previously attempted to render - not the "current". However, - // during componentDidUpdate we pass the "current" props. - // In order to support react-lifecycles-compat polyfilled components, - // Unsafe lifecycles should not be invoked for components using the new APIs. + return update; +} + +function resetSuspendedComponent(sourceFiber, rootRenderLanes) { + // A legacy mode Suspense quirk, only relevant to hook components. + + var tag = sourceFiber.tag; if ( - !hasNewLifecycles && - (typeof instance.UNSAFE_componentWillReceiveProps === "function" || - typeof instance.componentWillReceiveProps === "function") + (sourceFiber.mode & ConcurrentMode) === NoMode && + (tag === FunctionComponent || + tag === ForwardRef || + tag === SimpleMemoComponent) ) { - if (oldProps !== newProps || oldContext !== nextContext) { - callComponentWillReceiveProps( - workInProgress, - instance, - newProps, - nextContext - ); + 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; } } +} - resetHasForceUpdateBeforeProcessing(); - var oldState = workInProgress.memoizedState; - var newState = (instance.state = oldState); - processUpdateQueue(workInProgress, newProps, instance, renderLanes); - newState = workInProgress.memoizedState; +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. - 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 | LayoutStatic; + sourceFiber.flags &= ~(LifecycleEffectMask | Incomplete); - if ((workInProgress.mode & StrictEffectsMode) !== NoMode) { - fiberFlags |= MountLayoutDev; - } + if (sourceFiber.tag === ClassComponent) { + var currentSourceFiber = sourceFiber.alternate; - workInProgress.flags |= fiberFlags; + if (currentSourceFiber === null) { + // This is a new mount. Change the tag so it's not mistaken for a + // completed class component. For example, we should not call + // componentWillUnmount if it is deleted. + sourceFiber.tag = IncompleteClassComponent; + } else { + // When we try rendering again, we should not reuse the current fiber, + // since it's known to be in an inconsistent state. Use a force update to + // prevent a bail out. + var update = createUpdate(SyncLane); + update.tag = ForceUpdate; + enqueueUpdate(sourceFiber, update, SyncLane); + } + } // The source fiber did not complete. Mark it with Sync priority to + // indicate that it still has pending work. + + sourceFiber.lanes = mergeLanes(sourceFiber.lanes, SyncLane); } - return false; - } + 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. - if (typeof getDerivedStateFromProps === "function") { - applyDerivedStateFromProps( - workInProgress, - ctor, - getDerivedStateFromProps, - newProps - ); - newState = workInProgress.memoizedState; - } + suspenseBoundary.flags |= ShouldCapture; // TODO: I think we can remove this, since we now use `DidCapture` in + // the begin phase to prevent an early bailout. - var shouldUpdate = - checkHasForceUpdateAfterProcessing() || - checkShouldComponentUpdate( - workInProgress, - ctor, - oldProps, - newProps, - oldState, - newState, - nextContext - ); + suspenseBoundary.lanes = rootRenderLanes; + return suspenseBoundary; +} - 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 throwException( + root, + returnFiber, + sourceFiber, + value, + rootRenderLanes +) { + // The source fiber did not complete. + sourceFiber.flags |= Incomplete; - if (typeof instance.UNSAFE_componentWillMount === "function") { - instance.UNSAFE_componentWillMount(); - } + { + if (isDevToolsPresent) { + // If we have pending work still, restore the original updaters + restorePendingUpdaters(root, rootRenderLanes); } + } - if (typeof instance.componentDidMount === "function") { - var _fiberFlags = Update | LayoutStatic; + if ( + value !== null && + typeof value === "object" && + typeof value.then === "function" + ) { + // This is a wakeable. The component suspended. + var wakeable = value; + resetSuspendedComponent(sourceFiber); - if ((workInProgress.mode & StrictEffectsMode) !== NoMode) { - _fiberFlags |= MountLayoutDev; - } + var suspenseBoundary = getSuspenseHandler(); + + if (suspenseBoundary !== null) { + switch (suspenseBoundary.tag) { + case SuspenseComponent: { + // If this suspense boundary is not already showing a fallback, mark + // the in-progress render as suspended. We try to perform this logic + // as soon as soon as possible during the render phase, so the work + // loop can know things like whether it's OK to switch to other tasks, + // or whether it can wait for data to resolve before continuing. + // TODO: Most of these checks are already performed when entering a + // Suspense boundary. We should track the information on the stack so + // we don't have to recompute it on demand. This would also allow us + // to unify with `use` which needs to perform this logic even sooner, + // before `throwException` is called. + if (sourceFiber.mode & ConcurrentMode) { + if (getShellBoundary() === null) { + // Suspended in the "shell" of the app. This is an undesirable + // loading state. We should avoid committing this tree. + renderDidSuspendDelayIfPossible(); + } else { + // If we suspended deeper than the shell, we don't need to delay + // the commmit. However, we still call renderDidSuspend if this is + // a new boundary, to tell the work loop that a new fallback has + // appeared during this render. + // TODO: Theoretically we should be able to delete this branch. + // It's currently used for two things: 1) to throttle the + // appearance of successive loading states, and 2) in + // SuspenseList, to determine whether the children include any + // pending fallbacks. For 1, we should apply throttling to all + // retries, not just ones that render an additional fallback. For + // 2, we should check subtreeFlags instead. Then we can delete + // this branch. + var current = suspenseBoundary.alternate; - 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 | LayoutStatic; + if (current === null) { + renderDidSuspend(); + } + } + } - if ((workInProgress.mode & StrictEffectsMode) !== NoMode) { - _fiberFlags2 |= MountLayoutDev; - } + suspenseBoundary.flags &= ~ForceClientRender; + markSuspenseBoundaryShouldCapture( + suspenseBoundary, + returnFiber, + sourceFiber, + root, + rootRenderLanes + ); // Retry listener + // + // If the fallback does commit, we need to attach a different type of + // listener. This one schedules an update on the Suspense boundary to + // turn the fallback state off. + // + // Stash the wakeable on the boundary fiber so we can access it in the + // commit phase. + // + // When the wakeable resolves, we'll attempt to render the boundary + // again ("retry"). + // Check if this is a Suspensey resource. We do not attach retry + // listeners to these, because we don't actually need them for + // rendering. Only for committing. Instead, if a fallback commits + // and the only thing that suspended was a Suspensey resource, we + // retry immediately. + // TODO: Refactor throwException so that we don't have to do this type + // check. The caller already knows what the cause was. + + var isSuspenseyResource = wakeable === noopSuspenseyCommitThenable; + + if (isSuspenseyResource) { + suspenseBoundary.flags |= ScheduleRetry; + } else { + var retryQueue = suspenseBoundary.updateQueue; - workInProgress.flags |= _fiberFlags2; - } // If shouldComponentUpdate returned false, we should still update the - // memoized state to indicate that this work can be reused. + if (retryQueue === null) { + suspenseBoundary.updateQueue = new Set([wakeable]); + } else { + retryQueue.add(wakeable); + } + } - workInProgress.memoizedProps = newProps; - workInProgress.memoizedState = newState; - } // Update the existing instance's state, props, and context pointers even - // if shouldComponentUpdate returns false. + break; + } - instance.props = newProps; - instance.state = newState; - instance.context = nextContext; - return shouldUpdate; -} // Invokes the update life-cycles and returns false if it shouldn't rerender. + case OffscreenComponent: { + if (suspenseBoundary.mode & ConcurrentMode) { + suspenseBoundary.flags |= ShouldCapture; -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; + var _isSuspenseyResource = wakeable === noopSuspenseyCommitThenable; - if (typeof contextType === "object" && contextType !== null) { - nextContext = readContext(contextType); - } else { - var nextUnmaskedContext = getUnmaskedContext(workInProgress, ctor, true); - nextContext = getMaskedContext(workInProgress, nextUnmaskedContext); - } + if (_isSuspenseyResource) { + suspenseBoundary.flags |= ScheduleRetry; + } else { + var offscreenQueue = suspenseBoundary.updateQueue; + + if (offscreenQueue === null) { + var newOffscreenQueue = { + transitions: null, + markerInstances: null, + retryQueue: new Set([wakeable]) + }; + suspenseBoundary.updateQueue = newOffscreenQueue; + } else { + var _retryQueue = offscreenQueue.retryQueue; - var 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 (_retryQueue === null) { + offscreenQueue.retryQueue = new Set([wakeable]); + } else { + _retryQueue.add(wakeable); + } + } + } - if ( - !hasNewLifecycles && - (typeof instance.UNSAFE_componentWillReceiveProps === "function" || - typeof instance.componentWillReceiveProps === "function") - ) { - if ( - unresolvedOldProps !== unresolvedNewProps || - oldContext !== nextContext - ) { - callComponentWillReceiveProps( - workInProgress, - instance, - newProps, - nextContext - ); - } - } + break; + } + } + // eslint-disable-next-line no-fallthrough - resetHasForceUpdateBeforeProcessing(); - var oldState = workInProgress.memoizedState; - var newState = (instance.state = oldState); - processUpdateQueue(workInProgress, newProps, instance, renderLanes); - newState = workInProgress.memoizedState; + default: { + throw new Error( + "Unexpected Suspense handler tag (" + + suspenseBoundary.tag + + "). This " + + "is a bug in React." + ); + } + } // We only attach ping listeners in concurrent mode. Legacy Suspense always + // commits fallbacks synchronously, so there are no pings. - 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; + if (suspenseBoundary.mode & ConcurrentMode) { + attachPingListener(root, wakeable, rootRenderLanes); } - } - if (typeof instance.getSnapshotBeforeUpdate === "function") { - if ( - unresolvedOldProps !== current.memoizedProps || - oldState !== current.memoizedState - ) { - workInProgress.flags |= Snapshot; + 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 (root.tag === ConcurrentRoot) { + // In a concurrent root, suspending without a Suspense boundary is + // allowed. It will suspend indefinitely without committing. + // + // TODO: Should we have different behavior for discrete updates? What + // about flushSync? Maybe it should put the tree into an inert state, + // and potentially log a warning. Revisit this for a future release. + attachPingListener(root, wakeable, rootRenderLanes); + renderDidSuspendDelayIfPossible(); + return; + } else { + // In a legacy root, suspending without a boundary is always an error. + var uncaughtSuspenseError = new Error( + "A component suspended while responding to synchronous input. This " + + "will cause the UI to be replaced with a loading indicator. To " + + "fix, updates that suspend should be wrapped " + + "with startTransition." + ); + value = uncaughtSuspenseError; } } - - return false; - } - - if (typeof getDerivedStateFromProps === "function") { - applyDerivedStateFromProps( - workInProgress, - ctor, - getDerivedStateFromProps, - newProps - ); - newState = workInProgress.memoizedState; } - 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 (typeof instance.UNSAFE_componentWillUpdate === "function") { - instance.UNSAFE_componentWillUpdate(newProps, newState, nextContext); - } - } - - if (typeof instance.componentDidUpdate === "function") { - workInProgress.flags |= Update; - } + 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. - 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 workInProgress = returnFiber; - if (typeof instance.getSnapshotBeforeUpdate === "function") { - if ( - unresolvedOldProps !== current.memoizedProps || - oldState !== current.memoizedState - ) { - workInProgress.flags |= Snapshot; + 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 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. + case ClassComponent: + // Capture and retry + var errorInfo = value; + var ctor = workInProgress.type; + var instance = workInProgress.stateNode; - instance.props = newProps; - instance.state = newState; - instance.context = nextContext; - return shouldUpdate; -} + if ( + (workInProgress.flags & DidCapture) === NoFlags$1 && + (typeof ctor.getDerivedStateFromError === "function" || + (instance !== null && + typeof instance.componentDidCatch === "function" && + !isAlreadyFailedLegacyErrorBoundary(instance))) + ) { + workInProgress.flags |= ShouldCapture; -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 _lane = pickArbitraryLane(rootRenderLanes); -if ( - typeof ReactNativePrivateInterface.ReactFiberErrorDialog.showErrorDialog !== - "function" -) { - throw new Error( - "Expected ReactFiberErrorDialog.showErrorDialog to be a function." - ); -} + workInProgress.lanes = mergeLanes(workInProgress.lanes, _lane); // Schedule the error boundary to re-render using updated state -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 - ); -} + var _update = createClassErrorUpdate( + workInProgress, + errorInfo, + _lane + ); -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. + enqueueCapturedUpdate(workInProgress, _update); + return; + } - if (logError === false) { - return; - } + break; + } // $FlowFixMe[incompatible-type] we bail out when we get a null - var error = errorInfo.value; + workInProgress = workInProgress.return; + } while (workInProgress !== null); +} - 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 ReactCurrentOwner$2 = ReactSharedInternals.ReactCurrentOwner; // A special exception that's used to unwind the stack when an update flows +// into a dehydrated boundary. - 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. +var SelectiveHydrationException = new Error( + "This is not a real error. It's an implementation detail of React's " + + "selective hydration feature. If this leaks into userspace, it's a bug in " + + "React. Please file an issue." +); +var didReceiveUpdate = false; +var didWarnAboutBadClass; +var didWarnAboutModulePatternComponent; +var didWarnAboutContextTypeOnFunctionComponent; +var didWarnAboutGetDerivedStateOnFunctionComponent; +var didWarnAboutFunctionRefs; +var didWarnAboutReassigningProps; +var didWarnAboutRevealOrder; +var didWarnAboutTailOptions; +var didWarnAboutDefaultPropsOnFunctionComponent; - 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 - } +{ + didWarnAboutBadClass = {}; + didWarnAboutModulePatternComponent = {}; + didWarnAboutContextTypeOnFunctionComponent = {}; + didWarnAboutGetDerivedStateOnFunctionComponent = {}; + didWarnAboutFunctionRefs = {}; + didWarnAboutReassigningProps = false; + didWarnAboutRevealOrder = {}; + didWarnAboutTailOptions = {}; + didWarnAboutDefaultPropsOnFunctionComponent = {}; +} - 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; +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 + ); + } +} - if (boundary.tag === HostRoot) { - errorBoundaryMessage = - "Consider adding an error boundary to your tree to customize error handling behavior.\n" + - "Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries."; - } else { - var errorBoundaryName = - getComponentNameFromFiber(boundary) || "Anonymous"; - errorBoundaryMessage = - "React will try to recreate this component tree from scratch " + - ("using the error boundary you provided, " + errorBoundaryName + "."); - } +function 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. - 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. + workInProgress.child = reconcileChildFibers( + workInProgress, + null, + nextChildren, + renderLanes + ); +} - console["error"](combinedMessage); // Don't transform to our wrapper +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) + ); + } } - } 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 createRootErrorUpdate(fiber, errorInfo, lane) { - var update = createUpdate(lane); // Unmount the root by rendering null. + var render = Component.render; + var ref = workInProgress.ref; // The rest is a fork of updateFunctionComponent + + var nextChildren; + prepareToReadContext(workInProgress, renderLanes); + + { + markComponentRenderStarted(workInProgress); + } - update.tag = CaptureUpdate; // Caution: React DevTools currently depends on this property - // being called "element". + { + ReactCurrentOwner$2.current = workInProgress; + setIsRendering(true); + nextChildren = renderWithHooks( + current, + workInProgress, + render, + nextProps, + ref, + renderLanes + ); + setIsRendering(false); + } - update.payload = { - element: null - }; - var error = errorInfo.value; + { + markComponentRenderStopped(); + } - update.callback = function () { - onUncaughtError(error); - logCapturedError(fiber, errorInfo); - }; + if (current !== null && !didReceiveUpdate) { + bailoutHooks(current, workInProgress, renderLanes); + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); + } - return update; + workInProgress.flags |= PerformedWork; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; } -function createClassErrorUpdate(fiber, errorInfo, lane) { - var update = createUpdate(lane); - update.tag = CaptureUpdate; - var getDerivedStateFromError = fiber.type.getDerivedStateFromError; - - if (typeof getDerivedStateFromError === "function") { - var error$1 = errorInfo.value; +function updateMemoComponent( + current, + workInProgress, + Component, + nextProps, + renderLanes +) { + if (current === null) { + var type = Component.type; - update.payload = function () { - return getDerivedStateFromError(error$1); - }; + if ( + isSimpleFunctionComponent(type) && + Component.compare === null && // SimpleMemoComponent codepath doesn't resolve outer props either. + Component.defaultProps === undefined + ) { + var resolvedType = type; - update.callback = function () { { - markFailedErrorBoundaryForHotReloading(fiber); - } - - logCapturedError(fiber, errorInfo); - }; - } + 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 inst = fiber.stateNode; + workInProgress.tag = SimpleMemoComponent; + workInProgress.type = resolvedType; - if (inst !== null && typeof inst.componentDidCatch === "function") { - // $FlowFixMe[missing-this-annot] - update.callback = function callback() { { - markFailedErrorBoundaryForHotReloading(fiber); + validateFunctionComponentInDev(workInProgress, type); } - logCapturedError(fiber, errorInfo); + return updateSimpleMemoComponent( + current, + workInProgress, + resolvedType, + nextProps, + renderLanes + ); + } - 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 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 error$1 = errorInfo.value; - var stack = errorInfo.stack; - this.componentDidCatch(error$1, { - componentStack: stack !== null ? stack : "" - }); + if (Component.defaultProps !== undefined) { + var componentName = getComponentNameFromType(type) || "Unknown"; - { - if (typeof getDerivedStateFromError !== "function") { - // If componentDidCatch is the only error boundary method defined, - // then it needs to call setState to recover from errors. - // If no state update is scheduled then the boundary will swallow the error. - if (!includesSomeLane(fiber.lanes, SyncLane)) { - error( - "%s: Error boundaries should implement getDerivedStateFromError(). " + - "In that method, return a state update to display an error message or fallback UI.", - getComponentNameFromFiber(fiber) || "Unknown" - ); - } + if (!didWarnAboutDefaultPropsOnFunctionComponent[componentName]) { + error( + "%s: Support for defaultProps will be removed from memo components " + + "in a future major release. Use JavaScript default parameters instead.", + componentName + ); + + didWarnAboutDefaultPropsOnFunctionComponent[componentName] = true; } } - }; - } - - return update; -} - -function resetSuspendedComponent(sourceFiber, rootRenderLanes) { - // A legacy mode Suspense quirk, only relevant to hook components. + } - var tag = sourceFiber.tag; + var child = createFiberFromTypeAndProps( + Component.type, + null, + nextProps, + workInProgress, + workInProgress.mode, + renderLanes + ); + child.ref = workInProgress.ref; + child.return = workInProgress; + workInProgress.child = child; + return child; + } - if ( - (sourceFiber.mode & ConcurrentMode) === NoMode && - (tag === FunctionComponent || - tag === ForwardRef || - tag === SimpleMemoComponent) - ) { - var currentSource = sourceFiber.alternate; + { + var _type = Component.type; + var _innerPropTypes = _type.propTypes; - if (currentSource) { - sourceFiber.updateQueue = currentSource.updateQueue; - sourceFiber.memoizedState = currentSource.memoizedState; - sourceFiber.lanes = currentSource.lanes; - } else { - sourceFiber.updateQueue = null; - sourceFiber.memoizedState = null; + 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 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; + var currentChild = current.child; // This is always exactly one child - if (currentSourceFiber === null) { - // This is a new mount. Change the tag so it's not mistaken for a - // completed class component. For example, we should not call - // componentWillUnmount if it is deleted. - sourceFiber.tag = IncompleteClassComponent; - } else { - // When we try rendering again, we should not reuse the current fiber, - // since it's known to be in an inconsistent state. Use a force update to - // prevent a bail out. - var update = createUpdate(SyncLane); - update.tag = ForceUpdate; - enqueueUpdate(sourceFiber, update, SyncLane); - } - } // The source fiber did not complete. Mark it with Sync priority to - // indicate that it still has pending work. + var hasScheduledUpdateOrContext = checkScheduledUpdateOrContext( + current, + renderLanes + ); - sourceFiber.lanes = mergeLanes(sourceFiber.lanes, SyncLane); - } + 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 - 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 compare = Component.compare; + compare = compare !== null ? compare : shallowEqual; - 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 (compare(prevProps, nextProps) && current.ref === workInProgress.ref) { + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); + } + } // React DevTools reads this flag. - suspenseBoundary.lanes = rootRenderLanes; - return suspenseBoundary; + workInProgress.flags |= PerformedWork; + var newChild = createWorkInProgress(currentChild, nextProps); + newChild.ref = workInProgress.ref; + newChild.return = workInProgress; + workInProgress.child = newChild; + return newChild; } -function throwException( - root, - returnFiber, - sourceFiber, - value, - rootRenderLanes +function updateSimpleMemoComponent( + current, + workInProgress, + Component, + nextProps, + renderLanes ) { - // The source fiber did not complete. - sourceFiber.flags |= Incomplete; - + // 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 (isDevToolsPresent) { - // If we have pending work still, restore the original updaters - restorePendingUpdaters(root, rootRenderLanes); + 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 ( - value !== null && - typeof value === "object" && - typeof value.then === "function" - ) { - // This is a wakeable. The component suspended. - var wakeable = value; - resetSuspendedComponent(sourceFiber); - - var suspenseBoundary = getSuspenseHandler(); + if (current !== null) { + var prevProps = current.memoizedProps; - if (suspenseBoundary !== null) { - switch (suspenseBoundary.tag) { - case SuspenseComponent: { - // If this suspense boundary is not already showing a fallback, mark - // the in-progress render as suspended. We try to perform this logic - // as soon as soon as possible during the render phase, so the work - // loop can know things like whether it's OK to switch to other tasks, - // or whether it can wait for data to resolve before continuing. - // TODO: Most of these checks are already performed when entering a - // Suspense boundary. We should track the information on the stack so - // we don't have to recompute it on demand. This would also allow us - // to unify with `use` which needs to perform this logic even sooner, - // before `throwException` is called. - if (sourceFiber.mode & ConcurrentMode) { - if (getShellBoundary() === null) { - // Suspended in the "shell" of the app. This is an undesirable - // loading state. We should avoid committing this tree. - renderDidSuspendDelayIfPossible(); - } else { - // If we suspended deeper than the shell, we don't need to delay - // the commmit. However, we still call renderDidSuspend if this is - // a new boundary, to tell the work loop that a new fallback has - // appeared during this render. - // TODO: Theoretically we should be able to delete this branch. - // It's currently used for two things: 1) to throttle the - // appearance of successive loading states, and 2) in - // SuspenseList, to determine whether the children include any - // pending fallbacks. For 1, we should apply throttling to all - // retries, not just ones that render an additional fallback. For - // 2, we should check subtreeFlags instead. Then we can delete - // this branch. - var current = suspenseBoundary.alternate; + if ( + 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. - if (current === null) { - renderDidSuspend(); - } - } - } + workInProgress.pendingProps = nextProps = prevProps; - suspenseBoundary.flags &= ~ForceClientRender; - markSuspenseBoundaryShouldCapture( - suspenseBoundary, - returnFiber, - sourceFiber, - root, - rootRenderLanes - ); // Retry listener - // - // If the fallback does commit, we need to attach a different type of - // listener. This one schedules an update on the Suspense boundary to - // turn the fallback state off. - // - // Stash the wakeable on the boundary fiber so we can access it in the - // commit phase. - // - // When the wakeable resolves, we'll attempt to render the boundary - // again ("retry"). + if (!checkScheduledUpdateOrContext(current, renderLanes)) { + // The pending lanes were cleared at the beginning of beginWork. We're + // about to bail out, but there might be other lanes that weren't + // included in the current render. Usually, the priority level of the + // remaining updates is accumulated during the evaluation of the + // component (i.e. when processing the update queue). But since since + // we're bailing out early *without* evaluating the component, we need + // to account for it here, too. Reset to the value of the current fiber. + // NOTE: This only applies to SimpleMemoComponent, not MemoComponent, + // because a MemoComponent fiber does not have hooks or an update queue; + // rather, it wraps around an inner component, which may or may not + // contains hooks. + // TODO: Move the reset at in beginWork out of the common path so that + // this is no longer necessary. + workInProgress.lanes = current.lanes; + return bailoutOnAlreadyFinishedWork( + current, + workInProgress, + renderLanes + ); + } else if ((current.flags & ForceUpdateForLegacySuspense) !== NoFlags$1) { + // This is a special case that only exists for legacy mode. + // See https://github.com/facebook/react/pull/19216. + didReceiveUpdate = true; + } + } + } - var wakeables = suspenseBoundary.updateQueue; + return updateFunctionComponent( + current, + workInProgress, + Component, + nextProps, + renderLanes + ); +} - if (wakeables === null) { - suspenseBoundary.updateQueue = new Set([wakeable]); - } else { - wakeables.add(wakeable); - } +function updateOffscreenComponent(current, workInProgress, renderLanes) { + var nextProps = workInProgress.pendingProps; + var nextChildren = nextProps.children; + var nextIsDetached = + (workInProgress.stateNode._pendingVisibility & OffscreenDetached) !== 0; + var prevState = current !== null ? current.memoizedState : null; + markRef$1(current, workInProgress); - break; - } + if ( + nextProps.mode === "hidden" || + nextProps.mode === "unstable-defer-without-hiding" || + nextIsDetached + ) { + // Rendering a hidden tree. + var didSuspend = (workInProgress.flags & DidCapture) !== NoFlags$1; - case OffscreenComponent: { - if (suspenseBoundary.mode & ConcurrentMode) { - suspenseBoundary.flags |= ShouldCapture; - var offscreenQueue = suspenseBoundary.updateQueue; - - if (offscreenQueue === null) { - var newOffscreenQueue = { - transitions: null, - markerInstances: null, - wakeables: new Set([wakeable]) - }; - suspenseBoundary.updateQueue = newOffscreenQueue; - } else { - var _wakeables = offscreenQueue.wakeables; + if (didSuspend) { + // Something suspended inside a hidden tree + // Include the base lanes from the last render + var nextBaseLanes = + prevState !== null + ? mergeLanes(prevState.baseLanes, renderLanes) + : renderLanes; - if (_wakeables === null) { - offscreenQueue.wakeables = new Set([wakeable]); - } else { - _wakeables.add(wakeable); - } - } + if (current !== null) { + // Reset to the current children + var currentChild = (workInProgress.child = current.child); // The current render suspended, but there may be other lanes with + // pending work. We can't read `childLanes` from the current Offscreen + // fiber because we reset it when it was deferred; however, we can read + // the pending lanes from the child fibers. - break; - } - } - // eslint-disable-next-line no-fallthrough + var currentChildLanes = NoLanes; - default: { - throw new Error( - "Unexpected Suspense handler tag (" + - suspenseBoundary.tag + - "). This " + - "is a bug in React." + while (currentChild !== null) { + currentChildLanes = mergeLanes( + mergeLanes(currentChildLanes, currentChild.lanes), + currentChild.childLanes ); + currentChild = currentChild.sibling; } - } // 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); - } - 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 (root.tag === ConcurrentRoot) { - // In a concurrent root, suspending without a Suspense boundary is - // allowed. It will suspend indefinitely without committing. - // - // TODO: Should we have different behavior for discrete updates? What - // about flushSync? Maybe it should put the tree into an inert state, - // and potentially log a warning. Revisit this for a future release. - attachPingListener(root, wakeable, rootRenderLanes); - renderDidSuspendDelayIfPossible(); - return; - } else { - // In a legacy root, suspending without a boundary is always an error. - var uncaughtSuspenseError = new Error( - "A component suspended while responding to synchronous input. This " + - "will cause the UI to be replaced with a loading indicator. To " + - "fix, updates that suspend should be wrapped " + - "with startTransition." + var lanesWeJustAttempted = nextBaseLanes; + var remainingChildLanes = removeLanes( + currentChildLanes, + lanesWeJustAttempted ); - value = uncaughtSuspenseError; + workInProgress.childLanes = remainingChildLanes; + } else { + workInProgress.childLanes = NoLanes; + workInProgress.child = null; } + + return deferHiddenOffscreenComponent( + current, + workInProgress, + nextBaseLanes + ); } - } - 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. + if ((workInProgress.mode & ConcurrentMode) === NoMode) { + // In legacy sync mode, don't defer the subtree. Render it now. + // TODO: Consider how Offscreen should work with transitions in the future + var nextState = { + baseLanes: NoLanes, + cachePool: null + }; + workInProgress.memoizedState = nextState; - var workInProgress = returnFiber; + reuseHiddenContextOnStack(workInProgress); + pushOffscreenSuspenseHandler(workInProgress); + } else if (!includesSomeLane(renderLanes, OffscreenLane)) { + // We're hidden, and we're not rendering at Offscreen. We will bail out + // and resume this tree later. + // Schedule this fiber to re-render at Offscreen priority + workInProgress.lanes = workInProgress.childLanes = + laneToLanes(OffscreenLane); // Include the base lanes from the last render - 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; - } + var _nextBaseLanes = + prevState !== null + ? mergeLanes(prevState.baseLanes, renderLanes) + : renderLanes; - case ClassComponent: - // Capture and retry - var errorInfo = value; - var ctor = workInProgress.type; - var instance = workInProgress.stateNode; + return deferHiddenOffscreenComponent( + current, + workInProgress, + _nextBaseLanes + ); + } else { + // This is the second render. The surrounding visible content has already + // committed. Now we resume rendering the hidden tree. + // Rendering at offscreen, so we can clear the base lanes. + var _nextState = { + baseLanes: NoLanes, + cachePool: null + }; + workInProgress.memoizedState = _nextState; - if ( - (workInProgress.flags & DidCapture) === NoFlags$1 && - (typeof ctor.getDerivedStateFromError === "function" || - (instance !== null && - typeof instance.componentDidCatch === "function" && - !isAlreadyFailedLegacyErrorBoundary(instance))) - ) { - workInProgress.flags |= ShouldCapture; + if (prevState !== null) { + pushHiddenContext(workInProgress, prevState); + } else { + reuseHiddenContextOnStack(workInProgress); + } - var _lane = pickArbitraryLane(rootRenderLanes); + pushOffscreenSuspenseHandler(workInProgress); + } + } else { + // Rendering a visible tree. + if (prevState !== null) { + pushHiddenContext(workInProgress, prevState); + reuseSuspenseHandlerOnStack(workInProgress); // Since we're not hidden anymore, reset the state - workInProgress.lanes = mergeLanes(workInProgress.lanes, _lane); // Schedule the error boundary to re-render using updated state + workInProgress.memoizedState = null; + } else { + // to avoid a push/pop misalignment. - var _update = createClassErrorUpdate( - workInProgress, - errorInfo, - _lane - ); + reuseHiddenContextOnStack(workInProgress); + reuseSuspenseHandlerOnStack(workInProgress); + } + } - enqueueCapturedUpdate(workInProgress, _update); - return; - } + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; +} - break; - } // $FlowFixMe[incompatible-type] we bail out when we get a null +function deferHiddenOffscreenComponent( + current, + workInProgress, + nextBaseLanes, + renderLanes +) { + var nextState = { + baseLanes: nextBaseLanes, + // Save the cache pool so we can resume later. + cachePool: null + }; + workInProgress.memoizedState = nextState; + // to avoid a push/pop misalignment. - workInProgress = workInProgress.return; - } while (workInProgress !== null); -} + reuseHiddenContextOnStack(workInProgress); + pushOffscreenSuspenseHandler(workInProgress); -var ReactCurrentOwner$2 = ReactSharedInternals.ReactCurrentOwner; // A special exception that's used to unwind the stack when an update flows -// into a dehydrated boundary. + return null; +} // Note: These happen to have identical begin phases, for now. We shouldn't hold +// ourselves to this constraint, though. If the behavior diverges, we should +// fork the function. -var SelectiveHydrationException = new Error( - "This is not a real error. It's an implementation detail of React's " + - "selective hydration feature. If this leaks into userspace, it's a bug in " + - "React. Please file an issue." -); -var didReceiveUpdate = false; -var didWarnAboutBadClass; -var didWarnAboutModulePatternComponent; -var didWarnAboutContextTypeOnFunctionComponent; -var didWarnAboutGetDerivedStateOnFunctionComponent; -var didWarnAboutFunctionRefs; -var didWarnAboutReassigningProps; -var didWarnAboutRevealOrder; -var didWarnAboutTailOptions; -var didWarnAboutDefaultPropsOnFunctionComponent; +var updateLegacyHiddenComponent = updateOffscreenComponent; -{ - didWarnAboutBadClass = {}; - didWarnAboutModulePatternComponent = {}; - didWarnAboutContextTypeOnFunctionComponent = {}; - didWarnAboutGetDerivedStateOnFunctionComponent = {}; - didWarnAboutFunctionRefs = {}; - didWarnAboutReassigningProps = false; - didWarnAboutRevealOrder = {}; - didWarnAboutTailOptions = {}; - didWarnAboutDefaultPropsOnFunctionComponent = {}; +function updateFragment(current, workInProgress, renderLanes) { + var nextChildren = workInProgress.pendingProps; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; } -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 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 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. +function markRef$1(current, workInProgress) { + var ref = workInProgress.ref; - workInProgress.child = reconcileChildFibers( - workInProgress, - null, - nextChildren, - renderLanes - ); + if ( + (current === null && ref !== null) || + (current !== null && current.ref !== ref) + ) { + // Schedule a Ref effect + workInProgress.flags |= Ref; + workInProgress.flags |= RefStatic; + } } -function updateForwardRef( +function updateFunctionComponent( 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 @@ -14862,8 +14917,12 @@ function updateForwardRef( } } - var render = Component.render; - var ref = workInProgress.ref; // The rest is a fork of updateFunctionComponent + var context; + + { + var unmaskedContext = getUnmaskedContext(workInProgress, Component, true); + context = getMaskedContext(workInProgress, unmaskedContext); + } var nextChildren; prepareToReadContext(workInProgress, renderLanes); @@ -14878,9 +14937,9 @@ function updateForwardRef( nextChildren = renderWithHooks( current, workInProgress, - render, + Component, nextProps, - ref, + context, renderLanes ); setIsRendering(false); @@ -14900,477 +14959,545 @@ function updateForwardRef( return workInProgress.child; } -function updateMemoComponent( +function replayFunctionComponent( current, workInProgress, - Component, nextProps, + Component, renderLanes ) { - if (current === null) { - var type = Component.type; + // This function is used to replay a component that previously suspended, + // after its data resolves. It's a simplified version of + // updateFunctionComponent that reuses the hooks from the previous attempt. + var context; - if ( - isSimpleFunctionComponent(type) && - Component.compare === null && // SimpleMemoComponent codepath doesn't resolve outer props either. - Component.defaultProps === undefined - ) { - var resolvedType = type; + { + var unmaskedContext = getUnmaskedContext(workInProgress, Component, true); + context = getMaskedContext(workInProgress, unmaskedContext); + } - { - 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. + prepareToReadContext(workInProgress, renderLanes); - workInProgress.tag = SimpleMemoComponent; - workInProgress.type = resolvedType; + { + markComponentRenderStarted(workInProgress); + } - { - validateFunctionComponentInDev(workInProgress, type); + var nextChildren = replaySuspendedComponentWithHooks( + current, + workInProgress, + Component, + nextProps, + context + ); + + { + markComponentRenderStopped(); + } + + if (current !== null && !didReceiveUpdate) { + bailoutHooks(current, workInProgress, renderLanes); + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); + } + + workInProgress.flags |= PerformedWork; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; +} + +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; } - return updateSimpleMemoComponent( - current, - workInProgress, - resolvedType, - nextProps, - renderLanes - ); + 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; + } } - { - var innerPropTypes = type.propTypes; + 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) { - // 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) + getComponentNameFromType(Component) ); } + } + } // Push context providers early to prevent context stack mismatches. + // During mounting we don't know the child context yet as the instance doesn't exist. + // We will invalidate the child context in finishClassComponent() right after rendering. - if (Component.defaultProps !== undefined) { - var componentName = getComponentNameFromType(type) || "Unknown"; + var hasContext; - if (!didWarnAboutDefaultPropsOnFunctionComponent[componentName]) { - error( - "%s: Support for defaultProps will be removed from memo components " + - "in a future major release. Use JavaScript default parameters instead.", - componentName - ); + if (isContextProvider(Component)) { + hasContext = true; + pushContextProvider(workInProgress); + } else { + hasContext = false; + } - didWarnAboutDefaultPropsOnFunctionComponent[componentName] = true; - } - } - } + prepareToReadContext(workInProgress, renderLanes); + var instance = workInProgress.stateNode; + var shouldUpdate; - var child = createFiberFromTypeAndProps( - Component.type, - null, + 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, - workInProgress.mode, + Component, + nextProps, 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( + var nextUnitOfWork = finishClassComponent( current, + workInProgress, + Component, + shouldUpdate, + hasContext, 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 inst = workInProgress.stateNode; - var compare = Component.compare; - compare = compare !== null ? compare : shallowEqual; + 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 (compare(prevProps, nextProps) && current.ref === workInProgress.ref) { - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); + didWarnAboutReassigningProps = true; } - } // 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; + return nextUnitOfWork; } -function updateSimpleMemoComponent( +function finishClassComponent( current, workInProgress, Component, - nextProps, + shouldUpdate, + hasContext, 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; + // Refs should update even if shouldComponentUpdate returns false + markRef$1(current, workInProgress); + var didCaptureError = (workInProgress.flags & DidCapture) !== NoFlags$1; - 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 (!shouldUpdate && !didCaptureError) { + // Context providers should defer to sCU for rendering + if (hasContext) { + invalidateContextProvider(workInProgress, Component, false); + } - try { - outerMemoType = init(payload); - } catch (x) { - outerMemoType = null; - } // Inner propTypes will be validated in the function component path. + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); + } - var outerPropTypes = outerMemoType && outerMemoType.propTypes; + var instance = workInProgress.stateNode; // Rerender - if (outerPropTypes) { - checkPropTypes( - outerPropTypes, - nextProps, // Resolved (SimpleMemoComponent has no defaultProps) - "prop", - getComponentNameFromType(outerMemoType) - ); + ReactCurrentOwner$2.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 { + { + markComponentRenderStarted(workInProgress); + } + + { + setIsRendering(true); + nextChildren = instance.render(); + + if (workInProgress.mode & StrictLegacyMode) { + setIsStrictModeForDevtools(true); + + try { + instance.render(); + } finally { + setIsStrictModeForDevtools(false); } } + + setIsRendering(false); + } + + { + markComponentRenderStopped(); } + } // React DevTools reads this flag. + + workInProgress.flags |= PerformedWork; + + if (current !== null && didCaptureError) { + // If we're recovering from an error, reconcile without reusing any of + // the existing children. Conceptually, the normal children and the children + // that are shown on error are two different sets, so we shouldn't reuse + // normal children even if their identities match. + forceUnmountCurrentAndReconcile( + 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); } - if (current !== null) { - var prevProps = current.memoizedProps; + return workInProgress.child; +} - 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. +function pushHostRootContext(workInProgress) { + var root = workInProgress.stateNode; - workInProgress.pendingProps = nextProps = prevProps; + 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 (!checkScheduledUpdateOrContext(current, renderLanes)) { - // The pending lanes were cleared at the beginning of beginWork. We're - // about to bail out, but there might be other lanes that weren't - // included in the current render. Usually, the priority level of the - // remaining updates is accumulated during the evaluation of the - // component (i.e. when processing the update queue). But since since - // we're bailing out early *without* evaluating the component, we need - // to account for it here, too. Reset to the value of the current fiber. - // NOTE: This only applies to SimpleMemoComponent, not MemoComponent, - // because a MemoComponent fiber does not have hooks or an update queue; - // rather, it wraps around an inner component, which may or may not - // contains hooks. - // TODO: Move the reset at in beginWork out of the common path so that - // this is no longer necessary. - workInProgress.lanes = current.lanes; - return bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderLanes - ); - } else if ((current.flags & ForceUpdateForLegacySuspense) !== NoFlags$1) { - // This is a special case that only exists for legacy mode. - // See https://github.com/facebook/react/pull/19216. - didReceiveUpdate = true; - } + 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; + // being called "element". + + var nextChildren = nextState.element; + + { + if (nextChildren === prevChildren) { + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); } + + reconcileChildren(current, workInProgress, nextChildren, renderLanes); } - return updateFunctionComponent( - current, - workInProgress, - Component, - nextProps, - renderLanes - ); + return workInProgress.child; } -function updateOffscreenComponent(current, workInProgress, renderLanes) { +function updateHostComponent$1(current, workInProgress, renderLanes) { + pushHostContext(workInProgress); var nextProps = workInProgress.pendingProps; + var prevProps = current !== null ? current.memoizedProps : null; var nextChildren = nextProps.children; - var nextIsDetached = - (workInProgress.stateNode._pendingVisibility & OffscreenDetached) !== 0; - var prevState = current !== null ? current.memoizedState : null; - markRef$1(current, workInProgress); - if ( - nextProps.mode === "hidden" || - nextProps.mode === "unstable-defer-without-hiding" || - nextIsDetached - ) { - // Rendering a hidden tree. - var didSuspend = (workInProgress.flags & DidCapture) !== NoFlags$1; + if (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$1(current, workInProgress); + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; +} - if (didSuspend) { - // Something suspended inside a hidden tree - // Include the base lanes from the last render - var nextBaseLanes = - prevState !== null - ? mergeLanes(prevState.baseLanes, renderLanes) - : renderLanes; +function updateHostText$1(current, workInProgress) { + // immediately after. - if (current !== null) { - // Reset to the current children - var currentChild = (workInProgress.child = current.child); // The current render suspended, but there may be other lanes with - // pending work. We can't read `childLanes` from the current Offscreen - // fiber because we reset it when it was deferred; however, we can read - // the pending lanes from the child fibers. + return null; +} - var currentChildLanes = NoLanes; +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. - while (currentChild !== null) { - currentChildLanes = mergeLanes( - mergeLanes(currentChildLanes, currentChild.lanes), - currentChild.childLanes - ); - currentChild = currentChild.sibling; - } + workInProgress.type = Component; + var resolvedTag = (workInProgress.tag = resolveLazyComponentTag(Component)); + var resolvedProps = resolveDefaultProps(Component, props); + var child; - var lanesWeJustAttempted = nextBaseLanes; - var remainingChildLanes = removeLanes( - currentChildLanes, - lanesWeJustAttempted - ); - workInProgress.childLanes = remainingChildLanes; - } else { - workInProgress.childLanes = NoLanes; - workInProgress.child = null; + switch (resolvedTag) { + case FunctionComponent: { + { + validateFunctionComponentInDev(workInProgress, Component); + workInProgress.type = Component = + resolveFunctionForHotReloading(Component); } - return deferHiddenOffscreenComponent( - current, + child = updateFunctionComponent( + null, workInProgress, - nextBaseLanes + Component, + resolvedProps, + renderLanes ); + return child; } - if ((workInProgress.mode & ConcurrentMode) === NoMode) { - // In legacy sync mode, don't defer the subtree. Render it now. - // TODO: Consider how Offscreen should work with transitions in the future - var nextState = { - baseLanes: NoLanes, - cachePool: null - }; - workInProgress.memoizedState = nextState; + case ClassComponent: { + { + workInProgress.type = Component = + resolveClassForHotReloading(Component); + } - reuseHiddenContextOnStack(workInProgress); - pushOffscreenSuspenseHandler(workInProgress); - } else if (!includesSomeLane(renderLanes, OffscreenLane)) { - // We're hidden, and we're not rendering at Offscreen. We will bail out - // and resume this tree later. - // Schedule this fiber to re-render at Offscreen priority - workInProgress.lanes = workInProgress.childLanes = - laneToLanes(OffscreenLane); // Include the base lanes from the last render + child = updateClassComponent( + null, + workInProgress, + Component, + resolvedProps, + renderLanes + ); + return child; + } - var _nextBaseLanes = - prevState !== null - ? mergeLanes(prevState.baseLanes, renderLanes) - : renderLanes; + case ForwardRef: { + { + workInProgress.type = Component = + resolveForwardRefForHotReloading(Component); + } - return deferHiddenOffscreenComponent( - current, + child = updateForwardRef( + null, workInProgress, - _nextBaseLanes + Component, + resolvedProps, + renderLanes ); - } else { - // This is the second render. The surrounding visible content has already - // committed. Now we resume rendering the hidden tree. - // Rendering at offscreen, so we can clear the base lanes. - var _nextState = { - baseLanes: NoLanes, - cachePool: null - }; - workInProgress.memoizedState = _nextState; + return child; + } - if (prevState !== null) { - pushHiddenContext(workInProgress, prevState); - } else { - reuseHiddenContextOnStack(workInProgress); + case MemoComponent: { + { + if (workInProgress.type !== workInProgress.elementType) { + var outerPropTypes = Component.propTypes; + + if (outerPropTypes) { + checkPropTypes( + outerPropTypes, + resolvedProps, // Resolved for outer only + "prop", + getComponentNameFromType(Component) + ); + } + } } - pushOffscreenSuspenseHandler(workInProgress); + child = updateMemoComponent( + null, + workInProgress, + Component, + resolveDefaultProps(Component.type, resolvedProps), // The inner type can have defaults too + renderLanes + ); + return child; } - } else { - // Rendering a visible tree. - if (prevState !== null) { - pushHiddenContext(workInProgress, prevState); - reuseSuspenseHandlerOnStack(workInProgress); // Since we're not hidden anymore, reset the state + } - workInProgress.memoizedState = null; - } else { - // to avoid a push/pop misalignment. + var hint = ""; - reuseHiddenContextOnStack(workInProgress); - reuseSuspenseHandlerOnStack(workInProgress); + { + 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. - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; + 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 deferHiddenOffscreenComponent( - current, +function mountIncompleteClassComponent( + _current, workInProgress, - nextBaseLanes, + Component, + nextProps, renderLanes ) { - var nextState = { - baseLanes: nextBaseLanes, - // Save the cache pool so we can resume later. - cachePool: null - }; - workInProgress.memoizedState = nextState; - // to avoid a push/pop misalignment. - - reuseHiddenContextOnStack(workInProgress); - pushOffscreenSuspenseHandler(workInProgress); - - return null; -} // Note: These happen to have identical begin phases, for now. We shouldn't hold -// ourselves to this constraint, though. If the behavior diverges, we should -// fork the function. - -var updateLegacyHiddenComponent = updateOffscreenComponent; - -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; - } - } + resetSuspendedCurrentOnMountInLegacyMode(_current, workInProgress); // Promote the fiber to a class and try rendering again. - var nextProps = workInProgress.pendingProps; - var nextChildren = nextProps.children; - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; -} + 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 markRef$1(current, workInProgress) { - var ref = workInProgress.ref; + var hasContext; - if ( - (current === null && ref !== null) || - (current !== null && current.ref !== ref) - ) { - // Schedule a Ref effect - workInProgress.flags |= Ref; - workInProgress.flags |= RefStatic; + 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 updateFunctionComponent( - current, +function mountIndeterminateComponent( + _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) - ); - } - } - } - + resetSuspendedCurrentOnMountInLegacyMode(_current, workInProgress); + var props = workInProgress.pendingProps; var context; { - var unmaskedContext = getUnmaskedContext(workInProgress, Component, true); + var unmaskedContext = getUnmaskedContext(workInProgress, Component, false); context = getMaskedContext(workInProgress, unmaskedContext); } - var nextChildren; prepareToReadContext(workInProgress, renderLanes); + var value; { markComponentRenderStarted(workInProgress); } { - ReactCurrentOwner$2.current = workInProgress; + 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); - nextChildren = renderWithHooks( - current, + ReactCurrentOwner$2.current = workInProgress; + value = renderWithHooks( + null, workInProgress, Component, - nextProps, + props, context, renderLanes ); @@ -15379,5666 +15506,5809 @@ function updateFunctionComponent( { markComponentRenderStopped(); + } // React DevTools reads this flag. + + 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 (current !== null && !didReceiveUpdate) { - bailoutHooks(current, workInProgress, renderLanes); - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); + 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 (Component.defaultProps !== undefined) { + var componentName = getComponentNameFromType(Component) || "Unknown"; + + if (!didWarnAboutDefaultPropsOnFunctionComponent[componentName]) { + error( + "%s: Support for defaultProps will be removed from function components " + + "in a future major release. Use JavaScript default parameters instead.", + componentName + ); + + didWarnAboutDefaultPropsOnFunctionComponent[componentName] = true; + } + } + + 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 +}; - workInProgress.flags |= PerformedWork; - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; +function mountSuspenseOffscreenState(renderLanes) { + return { + baseLanes: renderLanes, + cachePool: getSuspendedCache() + }; } -function replayFunctionComponent( - current, - workInProgress, - nextProps, - Component, - renderLanes -) { - // This function is used to replay a component that previously suspended, - // after its data resolves. It's a simplified version of - // updateFunctionComponent that reuses the hooks from the previous attempt. - var context; +function updateSuspenseOffscreenState(prevOffscreenState, renderLanes) { + var cachePool = null; - { - var unmaskedContext = getUnmaskedContext(workInProgress, Component, true); - context = getMaskedContext(workInProgress, unmaskedContext); - } + return { + baseLanes: mergeLanes(prevOffscreenState.baseLanes, renderLanes), + cachePool: cachePool + }; +} // TODO: Probably should inline this back - prepareToReadContext(workInProgress, renderLanes); +function shouldRemainOnFallback(current, workInProgress, renderLanes) { + // If we're already showing a fallback, there are cases where we need to + // remain on that fallback regardless of whether the content has resolved. + // For example, SuspenseList coordinates when nested content appears. + if (current !== null) { + var suspenseState = current.memoizedState; - { - markComponentRenderStarted(workInProgress); - } + 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. - var nextChildren = replaySuspendedComponentWithHooks( - current, - workInProgress, - Component, - nextProps, - context - ); + var suspenseContext = suspenseStackCursor.current; + return hasSuspenseListContext(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. { - markComponentRenderStopped(); + if (shouldSuspend(workInProgress)) { + workInProgress.flags |= DidCapture; + } } - if (current !== null && !didReceiveUpdate) { - bailoutHooks(current, workInProgress, renderLanes); - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); - } + var showFallback = false; + var didSuspend = (workInProgress.flags & DidCapture) !== NoFlags$1; - workInProgress.flags |= PerformedWork; - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; -} + if (didSuspend || shouldRemainOnFallback(current)) { + // Something in this boundary's subtree already suspended. Switch to + // rendering the fallback children. + showFallback = true; + workInProgress.flags &= ~DidCapture; + } // OK, the next part is confusing. We're about to reconcile the Suspense + // boundary's children. This involves some custom reconciliation logic. Two + // main reasons this is so complicated. + // + // First, Legacy Mode has different semantics for backwards compatibility. The + // primary tree will commit in an inconsistent state, so when we do the + // second pass to render the fallback, we do some exceedingly, uh, clever + // hacks to make that not totally break. Like transferring effects and + // deletions from hidden tree. In Concurrent Mode, it's much simpler, + // because we bailout on the primary tree completely and leave it in its old + // state, no effects. Same as what we do for Offscreen (except that + // Offscreen doesn't have the first render pass). + // + // Second is hydration. During hydration, the Suspense fiber has a slightly + // different layout, where the child points to a dehydrated fragment, which + // contains the DOM rendered by the server. + // + // Third, even if you set all that aside, Suspense is like error boundaries in + // that we first we try to render one tree, and if that fails, we render again + // and switch to a different tree. Like a try/catch block. So we have to track + // which branch we're currently rendering. Ideally we would model this using + // a stack. -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? + if (current === null) { + var nextPrimaryChildren = nextProps.children; + var nextFallbackChildren = nextProps.fallback; - var tempInstance = new ctor( - workInProgress.memoizedProps, - _instance.context - ); - var state = tempInstance.state; + if (showFallback) { + pushFallbackTreeSuspenseHandler(workInProgress); + var fallbackFragment = mountSuspenseFallbackChildren( + workInProgress, + nextPrimaryChildren, + nextFallbackChildren, + renderLanes + ); + var primaryChildFragment = workInProgress.child; + primaryChildFragment.memoizedState = + mountSuspenseOffscreenState(renderLanes); + workInProgress.memoizedState = SUSPENDED_MARKER; - _instance.updater.enqueueSetState(_instance, state, null); + return fallbackFragment; + } else if (typeof nextProps.unstable_expectedLoadTime === "number") { + // This is a CPU-bound tree. Skip this tree and show a placeholder to + // unblock the surrounding content. Then immediately retry after the + // initial commit. + pushFallbackTreeSuspenseHandler(workInProgress); - break; - } + var _fallbackFragment = mountSuspenseFallbackChildren( + workInProgress, + nextPrimaryChildren, + nextFallbackChildren, + renderLanes + ); - case true: { - workInProgress.flags |= DidCapture; - workInProgress.flags |= ShouldCapture; // eslint-disable-next-line react-internal/prod-error-codes + var _primaryChildFragment = workInProgress.child; + _primaryChildFragment.memoizedState = + mountSuspenseOffscreenState(renderLanes); + workInProgress.memoizedState = SUSPENDED_MARKER; // TODO: Transition Tracing is not yet implemented for CPU Suspense. + // Since nothing actually suspended, there will nothing to ping this to + // get it started back up to attempt the next item. While in terms of + // priority this work has the same priority as this current render, it's + // not part of the same transition once the transition has committed. If + // it's sync, we still want to yield so that it can be painted. + // Conceptually, this is really the same as pinging. We can use any + // RetryLane even if it's the one currently rendering since we're leaving + // it behind on this node. - 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 + workInProgress.lanes = SomeRetryLane; + return _fallbackFragment; + } else { + pushPrimaryTreeSuspenseHandler(workInProgress); + return mountSuspensePrimaryChildren(workInProgress, nextPrimaryChildren); + } + } else { + // This is an update. + // Special path for hydration + var prevState = current.memoizedState; - var update = createClassErrorUpdate( + if (prevState !== null) { + var _dehydrated = prevState.dehydrated; + + if (_dehydrated !== null) { + return updateDehydratedSuspenseComponent( + current, workInProgress, - createCapturedValueAtFiber(error$1, workInProgress), - lane + didSuspend, + nextProps, + _dehydrated, + prevState, + renderLanes ); - 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 (showFallback) { + pushFallbackTreeSuspenseHandler(workInProgress); + var _nextFallbackChildren = nextProps.fallback; + var _nextPrimaryChildren = nextProps.children; + var fallbackChildFragment = updateSuspenseFallbackChildren( + current, + workInProgress, + _nextPrimaryChildren, + _nextFallbackChildren, + renderLanes + ); + var _primaryChildFragment2 = workInProgress.child; + var prevOffscreenState = current.child.memoizedState; + _primaryChildFragment2.memoizedState = + prevOffscreenState === null + ? mountSuspenseOffscreenState(renderLanes) + : updateSuspenseOffscreenState(prevOffscreenState, renderLanes); - if (innerPropTypes) { - checkPropTypes( - innerPropTypes, - nextProps, // Resolved props - "prop", - getComponentNameFromType(Component) - ); - } + _primaryChildFragment2.childLanes = getRemainingWorkInPrimaryTree( + current, + renderLanes + ); + workInProgress.memoizedState = SUSPENDED_MARKER; + return fallbackChildFragment; + } else { + pushPrimaryTreeSuspenseHandler(workInProgress); + var _nextPrimaryChildren2 = nextProps.children; + + var _primaryChildFragment3 = updateSuspensePrimaryChildren( + current, + workInProgress, + _nextPrimaryChildren2, + renderLanes + ); + + workInProgress.memoizedState = null; + return _primaryChildFragment3; } - } // 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 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 (isContextProvider(Component)) { - hasContext = true; - pushContextProvider(workInProgress); - } else { - hasContext = false; - } +function mountSuspenseFallbackChildren( + workInProgress, + primaryChildren, + fallbackChildren, + renderLanes +) { + var mode = workInProgress.mode; + var progressedPrimaryFragment = workInProgress.child; + var primaryChildProps = { + mode: "hidden", + children: primaryChildren + }; + var primaryChildFragment; + var fallbackChildFragment; - prepareToReadContext(workInProgress, renderLanes); - var instance = workInProgress.stateNode; - var shouldUpdate; + 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 (instance === null) { - resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress); // In the initial pass we might need to construct the instance. + 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; + } - 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 + fallbackChildFragment = createFiberFromFragment( + fallbackChildren, + mode, + renderLanes, + null ); } else { - shouldUpdate = updateClassInstance( - current, - workInProgress, - Component, - nextProps, - renderLanes + primaryChildFragment = mountWorkInProgressOffscreenFiber( + primaryChildProps, + mode + ); + fallbackChildFragment = createFiberFromFragment( + fallbackChildren, + mode, + renderLanes, + null ); } - 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" - ); - } + primaryChildFragment.return = workInProgress; + fallbackChildFragment.return = workInProgress; + primaryChildFragment.sibling = fallbackChildFragment; + workInProgress.child = primaryChildFragment; + return fallbackChildFragment; +} - didWarnAboutReassigningProps = true; - } - } +function mountWorkInProgressOffscreenFiber(offscreenProps, mode, renderLanes) { + // The props argument to `createFiberFromOffscreen` is `any` typed, so we use + // this wrapper function to constrain it. + return createFiberFromOffscreen(offscreenProps, mode, NoLanes, null); +} - return nextUnitOfWork; +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 finishClassComponent( +function updateSuspensePrimaryChildren( current, workInProgress, - Component, - shouldUpdate, - hasContext, + primaryChildren, renderLanes ) { - // Refs should update even if shouldComponentUpdate returns false - markRef$1(current, workInProgress); - var didCaptureError = (workInProgress.flags & DidCapture) !== NoFlags$1; - - if (!shouldUpdate && !didCaptureError) { - // Context providers should defer to sCU for rendering - if (hasContext) { - invalidateContextProvider(workInProgress, Component, false); + var currentPrimaryChildFragment = current.child; + var currentFallbackChildFragment = currentPrimaryChildFragment.sibling; + var primaryChildFragment = updateWorkInProgressOffscreenFiber( + currentPrimaryChildFragment, + { + mode: "visible", + children: primaryChildren } + ); - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); + if ((workInProgress.mode & ConcurrentMode) === NoMode) { + primaryChildFragment.lanes = renderLanes; } - var instance = workInProgress.stateNode; // Rerender - - ReactCurrentOwner$2.current = workInProgress; - var nextChildren; + primaryChildFragment.return = workInProgress; + primaryChildFragment.sibling = null; - 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 (currentFallbackChildFragment !== null) { + // Delete the fallback child fragment + var deletions = workInProgress.deletions; - { - stopProfilerTimerIfRunning(); - } - } else { - { - markComponentRenderStarted(workInProgress); + if (deletions === null) { + workInProgress.deletions = [currentFallbackChildFragment]; + workInProgress.flags |= ChildDeletion; + } else { + deletions.push(currentFallbackChildFragment); } + } - { - setIsRendering(true); - nextChildren = instance.render(); - - if (workInProgress.mode & StrictLegacyMode) { - setIsStrictModeForDevtools(true); - - try { - instance.render(); - } finally { - setIsStrictModeForDevtools(false); - } - } + workInProgress.child = primaryChildFragment; + return primaryChildFragment; +} - setIsRendering(false); - } +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; - { - markComponentRenderStopped(); - } - } // React DevTools reads this flag. + 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; - workInProgress.flags |= PerformedWork; + 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. - 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 - ); + workInProgress.deletions = null; } 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. + primaryChildFragment = updateWorkInProgressOffscreenFiber( + currentPrimaryChildFragment, + primaryChildProps + ); // Since we're reusing a current tree, we need to reuse the flags, too. + // (We don't do this in legacy mode, because in legacy mode we don't re-use + // the current tree; see previous branch.) - if (hasContext) { - invalidateContextProvider(workInProgress, Component, true); + primaryChildFragment.subtreeFlags = + currentPrimaryChildFragment.subtreeFlags & StaticMask; } - return workInProgress.child; -} - -function pushHostRootContext(workInProgress) { - var root = workInProgress.stateNode; + var fallbackChildFragment; - if (root.pendingContext) { - pushTopLevelContextObject( - workInProgress, - root.pendingContext, - root.pendingContext !== root.context + if (currentFallbackChildFragment !== null) { + fallbackChildFragment = createWorkInProgress( + currentFallbackChildFragment, + fallbackChildren ); - } else if (root.context) { - // Should always be set - pushTopLevelContextObject(workInProgress, root.context, false); + } 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; } - pushHostContainer(workInProgress, root.containerInfo); + fallbackChildFragment.return = workInProgress; + primaryChildFragment.return = workInProgress; + primaryChildFragment.sibling = fallbackChildFragment; + workInProgress.child = primaryChildFragment; + return fallbackChildFragment; } -function updateHostRoot(current, workInProgress, renderLanes) { - pushHostRootContext(workInProgress); +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 - if (current === null) { - throw new Error("Should have a current fiber. This is a bug in React."); - } + reconcileChildFibers(workInProgress, current.child, null, renderLanes); // We're now not suspended nor dehydrated. var nextProps = workInProgress.pendingProps; - var prevState = workInProgress.memoizedState; - var prevChildren = prevState.element; - cloneUpdateQueue(current, workInProgress); - processUpdateQueue(workInProgress, nextProps, null, renderLanes); - var nextState = workInProgress.memoizedState; - // being called "element". - - var nextChildren = nextState.element; - - { - if (nextChildren === prevChildren) { - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); - } - - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - } + 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. - return workInProgress.child; + primaryChildFragment.flags |= Placement; + workInProgress.memoizedState = null; + return primaryChildFragment; } -function updateHostComponent$1(current, workInProgress, renderLanes) { - pushHostContext(workInProgress); - 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; - } +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. - markRef$1(current, workInProgress); - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; -} + fallbackChildFragment.flags |= Placement; + primaryChildFragment.return = workInProgress; + fallbackChildFragment.return = workInProgress; + primaryChildFragment.sibling = fallbackChildFragment; + workInProgress.child = primaryChildFragment; -function updateHostText$1(current, workInProgress) { - // immediately after. + 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 null; + return fallbackChildFragment; } -function mountLazyComponent( - _current, +function updateDehydratedSuspenseComponent( + current, workInProgress, - elementType, + didSuspend, + nextProps, + suspenseInstance, + suspenseState, 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 (!didSuspend) { + // This is the first render pass. Attempt to hydrate. + pushPrimaryTreeSuspenseHandler(workInProgress); // We should never be hydrating at this point because it is the first pass, - child = updateFunctionComponent( - null, + if ((workInProgress.mode & ConcurrentMode) === NoMode) { + return retrySuspenseComponentWithoutHydrating( + current, workInProgress, - Component, - resolvedProps, - renderLanes + renderLanes, + null ); - return child; } - case ClassComponent: { - { - workInProgress.type = Component = - resolveClassForHotReloading(Component); - } - - child = updateClassComponent( - null, - workInProgress, - Component, - resolvedProps, - renderLanes - ); - return child; - } + 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 ForwardRef: { { - workInProgress.type = Component = - resolveForwardRefForHotReloading(Component); - } - - child = updateForwardRef( - null, - workInProgress, - Component, - resolvedProps, - renderLanes - ); - return child; - } + var _getSuspenseInstanceF = getSuspenseInstanceFallbackErrorDetails(); - case MemoComponent: { - { - if (workInProgress.type !== workInProgress.elementType) { - var outerPropTypes = Component.propTypes; + digest = _getSuspenseInstanceF.digest; + message = _getSuspenseInstanceF.message; + stack = _getSuspenseInstanceF.stack; + } - if (outerPropTypes) { - checkPropTypes( - outerPropTypes, - resolvedProps, // Resolved for outer only - "prop", - getComponentNameFromType(Component) - ); - } - } + 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." + ); } - child = updateMemoComponent( - null, + error.digest = digest; + var capturedValue = createCapturedValue(error, digest, stack); + return retrySuspenseComponentWithoutHydrating( + current, workInProgress, - Component, - resolveDefaultProps(Component.type, resolvedProps), // The inner type can have defaults too - renderLanes + renderLanes, + capturedValue ); - return child; } - } - - var hint = ""; + // any context has changed, we need to treat is as if the input might have changed. - { - 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 hasContextChanged = includesSomeLane(renderLanes, current.childLanes); - 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) - ); -} + 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 mountIncompleteClassComponent( - _current, - workInProgress, - Component, - nextProps, - renderLanes -) { - resetSuspendedCurrentOnMountInLegacyMode(_current, workInProgress); // Promote the fiber to a class and try rendering again. + if (root !== null) { + var attemptHydrationAtLane = getBumpedLaneForHydration( + root, + renderLanes + ); - workInProgress.tag = ClassComponent; // The rest of this function is a fork of `updateClassComponent` - // Push context providers early to prevent context stack mismatches. - // During mounting we don't know the child context yet as the instance doesn't exist. - // We will invalidate the child context in finishClassComponent() right after rendering. + if ( + 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 hasContext; + var eventTime = NoTimestamp; + enqueueConcurrentRenderForLane(current, attemptHydrationAtLane); + scheduleUpdateOnFiber( + root, + current, + attemptHydrationAtLane, + eventTime + ); // Throw a special object that signals to the work loop that it should + // interrupt the current render. + // + // Because we're inside a React-only execution stack, we don't + // strictly need to throw here — we could instead modify some internal + // work loop state. But using an exception means we don't need to + // check for this case on every iteration of the work loop. So doing + // it this way moves the check out of the fast path. - if (isContextProvider(Component)) { - hasContext = true; - pushContextProvider(workInProgress); - } else { - hasContext = false; - } + throw SelectiveHydrationException; + } + } // If we did not selectively hydrate, we'll continue rendering without + // hydrating. Mark this tree as suspended to prevent it from committing + // outside a transition. + // + // This path should only happen if the hydration lane already suspended. + // Currently, it also happens during sync updates because there is no + // hydration lane for sync updates. + // TODO: We should ideally have a sync hydration lane that we can apply to do + // a pass where we hydrate this subtree in place using the previous Context and then + // reapply the update afterwards. - prepareToReadContext(workInProgress, renderLanes); - constructClassInstance(workInProgress, Component, nextProps); - mountClassInstance(workInProgress, Component, nextProps, renderLanes); - return finishClassComponent( - null, - workInProgress, - Component, - true, - hasContext, - renderLanes - ); -} + renderDidSuspendDelayIfPossible(); + return retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, + null + ); + } else if (isSuspenseInstancePending()) { + // This component is still pending more data from the server, so we can't hydrate its + // content. We treat it as if this component suspended itself. It might seem as if + // we could just try to render it client-side instead. However, this will perform a + // lot of unnecessary work and is unlikely to complete since it often will suspend + // on missing data anyway. Additionally, the server might be able to render more + // than we can on the client yet. In that case we'd end up with more fallback states + // on the client than if we just leave it alone. If the server times out or errors + // these should update this boundary to the permanent Fallback state instead. + // Mark it as having captured (i.e. suspended). + workInProgress.flags |= DidCapture; // Leave the child in place. I.e. the dehydrated fragment. -function mountIndeterminateComponent( - _current, - workInProgress, - Component, - renderLanes -) { - resetSuspendedCurrentOnMountInLegacyMode(_current, workInProgress); - var props = workInProgress.pendingProps; - var context; + workInProgress.child = current.child; // Register a callback to retry this boundary once the server has sent the result. - { - var unmaskedContext = getUnmaskedContext(workInProgress, Component, false); - context = getMaskedContext(workInProgress, unmaskedContext); - } + retryDehydratedSuspenseBoundary.bind(null, current); + registerSuspenseInstanceRetry(); + return null; + } else { + var primaryChildren = nextProps.children; + var primaryChildFragment = mountSuspensePrimaryChildren( + workInProgress, + primaryChildren + ); // Mark the children as hydrating. This is a fast path to know whether this + // tree is part of a hydrating tree. This is used to determine if a child + // node has fully mounted yet, and for scheduling event replaying. + // Conceptually this is similar to Placement in that a new subtree is + // inserted into the React tree here. It just happens to not need DOM + // mutations because it already exists. - prepareToReadContext(workInProgress, renderLanes); - var value; + primaryChildFragment.flags |= Hydrating; + return primaryChildFragment; + } + } else { + // This is the second render pass. We already attempted to hydrated, but + // something either suspended or errored. + if (workInProgress.flags & ForceClientRender) { + // Something errored during hydration. Try again without hydrating. + pushPrimaryTreeSuspenseHandler(workInProgress); + workInProgress.flags &= ~ForceClientRender; - { - markComponentRenderStarted(workInProgress); - } + var _capturedValue = createCapturedValue( + new Error( + "There was an error while hydrating this Suspense boundary. " + + "Switched to client rendering." + ) + ); - { - if ( - Component.prototype && - typeof Component.prototype.render === "function" - ) { - var componentName = getComponentNameFromType(Component) || "Unknown"; + return retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, + _capturedValue + ); + } else if (workInProgress.memoizedState !== null) { + // Something suspended and we should still be in dehydrated mode. + // Leave the existing child in place. + // Push to avoid a mismatch + pushFallbackTreeSuspenseHandler(workInProgress); + workInProgress.child = current.child; // The dehydrated completion pass expects this flag to be there + // but the normal suspense pass doesn't. - 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 + workInProgress.flags |= DidCapture; + return null; + } else { + // Suspended but we should no longer be in dehydrated mode. + // Therefore we now have to render the fallback. + pushFallbackTreeSuspenseHandler(workInProgress); + var nextPrimaryChildren = nextProps.children; + var nextFallbackChildren = nextProps.fallback; + var fallbackChildFragment = + mountSuspenseFallbackAfterRetryWithoutHydrating( + current, + workInProgress, + nextPrimaryChildren, + nextFallbackChildren, + renderLanes ); - - didWarnAboutBadClass[componentName] = true; - } + var _primaryChildFragment4 = workInProgress.child; + _primaryChildFragment4.memoizedState = + mountSuspenseOffscreenState(renderLanes); + workInProgress.memoizedState = SUSPENDED_MARKER; + return fallbackChildFragment; } + } +} - if (workInProgress.mode & StrictLegacyMode) { - ReactStrictModeWarnings.recordLegacyContextWarning(workInProgress, null); - } +function scheduleSuspenseWorkOnFiber(fiber, renderLanes, propagationRoot) { + fiber.lanes = mergeLanes(fiber.lanes, renderLanes); + var alternate = fiber.alternate; - setIsRendering(true); - ReactCurrentOwner$2.current = workInProgress; - value = renderWithHooks( - null, - workInProgress, - Component, - props, - context, - renderLanes - ); - setIsRendering(false); + if (alternate !== null) { + alternate.lanes = mergeLanes(alternate.lanes, renderLanes); } - { - markComponentRenderStopped(); - } // React DevTools reads this flag. - - workInProgress.flags |= PerformedWork; + scheduleContextWorkOnParentPath(fiber.return, renderLanes, propagationRoot); +} - { - // 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"; +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; - 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 - ); + while (node !== null) { + if (node.tag === SuspenseComponent) { + var state = node.memoizedState; - didWarnAboutModulePatternComponent[_componentName] = true; + 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 ( - // 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 - ); + if (node === workInProgress) { + return; + } // $FlowFixMe[incompatible-use] found when upgrading Flow - didWarnAboutModulePatternComponent[_componentName2] = true; + while (node.sibling === null) { + // $FlowFixMe[incompatible-use] found when upgrading Flow + if (node.return === null || node.return === workInProgress) { + return; } - } // 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; + node = node.return; + } // $FlowFixMe[incompatible-use] found when upgrading Flow - if (isContextProvider(Component)) { - hasContext = true; - pushContextProvider(workInProgress); - } else { - hasContext = false; - } + node.sibling.return = node.return; + node = node.sibling; + } +} - 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 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; - reconcileChildren(null, workInProgress, value, renderLanes); + while (row !== null) { + var currentRow = row.alternate; // New rows can't be content rows. - { - validateFunctionComponentInDev(workInProgress, Component); + if (currentRow !== null && findFirstSuspended(currentRow) === null) { + lastContentRow = row; } - return workInProgress.child; + row = row.sibling; } + + return lastContentRow; } -function validateFunctionComponentInDev(workInProgress, Component) { +function validateRevealOrder(revealOrder) { { - 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 + "`."; - } + if ( + revealOrder !== undefined && + revealOrder !== "forwards" && + revealOrder !== "backwards" && + revealOrder !== "together" && + !didWarnAboutRevealOrder[revealOrder] + ) { + didWarnAboutRevealOrder[revealOrder] = true; - var warningKey = ownerName || ""; - var debugSource = workInProgress._debugSource; + 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 (debugSource) { - warningKey = debugSource.fileName + ":" + debugSource.lineNumber; - } + break; + } - if (!didWarnAboutFunctionRefs[warningKey]) { - didWarnAboutFunctionRefs[warningKey] = true; + 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() + ); - error( - "Function components cannot be given refs. " + - "Attempts to access this ref will fail. " + - "Did you mean to use React.forwardRef()?%s", - info - ); - } - } + break; + } - if (Component.defaultProps !== undefined) { - var componentName = getComponentNameFromType(Component) || "Unknown"; + default: + error( + '"%s" is not a supported revealOrder on . ' + + 'Did you mean "together", "forwards" or "backwards"?', + revealOrder + ); - if (!didWarnAboutDefaultPropsOnFunctionComponent[componentName]) { + break; + } + } else { error( - "%s: Support for defaultProps will be removed from function components " + - "in a future major release. Use JavaScript default parameters instead.", - componentName + "%s is not a supported value for revealOrder on . " + + 'Did you mean "together", "forwards" or "backwards"?', + revealOrder ); - - didWarnAboutDefaultPropsOnFunctionComponent[componentName] = true; } } + } +} - if (typeof Component.getDerivedStateFromProps === "function") { - var _componentName3 = getComponentNameFromType(Component) || "Unknown"; +function validateTailOptions(tailMode, revealOrder) { + { + if (tailMode !== undefined && !didWarnAboutTailOptions[tailMode]) { + if (tailMode !== "collapsed" && tailMode !== "hidden") { + didWarnAboutTailOptions[tailMode] = true; - if (!didWarnAboutGetDerivedStateOnFunctionComponent[_componentName3]) { error( - "%s: Function components do not support getDerivedStateFromProps.", - _componentName3 + '"%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; - 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 + ' is only valid if revealOrder is ' + + '"forwards" or "backwards". ' + + 'Did you mean to specify revealOrder="forwards"?', + tailMode ); - - didWarnAboutContextTypeOnFunctionComponent[_componentName4] = true; } } } } -var SUSPENDED_MARKER = { - dehydrated: null, - treeContext: null, - retryLane: NoLane -}; - -function mountSuspenseOffscreenState(renderLanes) { - return { - baseLanes: renderLanes, - cachePool: getSuspendedCache() - }; -} - -function updateSuspenseOffscreenState(prevOffscreenState, renderLanes) { - var cachePool = null; +function validateSuspenseListNestedChild(childSlot, index) { + { + var isAnArray = isArray(childSlot); + var isIterable = + !isAnArray && typeof getIteratorFn(childSlot) === "function"; - return { - baseLanes: mergeLanes(prevOffscreenState.baseLanes, renderLanes), - cachePool: cachePool - }; -} // TODO: Probably should inline this back + if (isAnArray || isIterable) { + var type = isAnArray ? "array" : "iterable"; -function shouldRemainOnFallback(current, workInProgress, renderLanes) { - // If we're already showing a fallback, there are cases where we need to - // remain on that fallback regardless of whether the content has resolved. - // For example, SuspenseList coordinates when nested content appears. - if (current !== null) { - var suspenseState = current.memoizedState; + 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 (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. + } - var suspenseContext = suspenseStackCursor.current; - return hasSuspenseListContext(suspenseContext, ForceSuspenseFallback); + return true; } -function getRemainingWorkInPrimaryTree(current, renderLanes) { - // TODO: Should not remove render lanes that were pinged during this render - return removeLanes(current.childLanes, renderLanes); -} +function validateSuspenseListChildren(children, revealOrder) { + { + if ( + (revealOrder === "forwards" || revealOrder === "backwards") && + children !== undefined && + children !== null && + children !== false + ) { + if (isArray(children)) { + for (var i = 0; i < children.length; i++) { + if (!validateSuspenseListNestedChild(children[i], i)) { + return; + } + } + } else { + var iteratorFn = getIteratorFn(children); -function updateSuspenseComponent(current, workInProgress, renderLanes) { - var nextProps = workInProgress.pendingProps; // This is used by DevTools to force a boundary to suspend. + if (typeof iteratorFn === "function") { + var childrenIterator = iteratorFn.call(children); - { - if (shouldSuspend(workInProgress)) { - workInProgress.flags |= DidCapture; + 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 + ); + } + } } } +} - var showFallback = false; - var didSuspend = (workInProgress.flags & DidCapture) !== NoFlags$1; - - if (didSuspend || shouldRemainOnFallback(current)) { - // Something in this boundary's subtree already suspended. Switch to - // rendering the fallback children. - showFallback = true; - workInProgress.flags &= ~DidCapture; - } // OK, the next part is confusing. We're about to reconcile the Suspense - // boundary's children. This involves some custom reconciliation logic. Two - // main reasons this is so complicated. - // - // First, Legacy Mode has different semantics for backwards compatibility. The - // primary tree will commit in an inconsistent state, so when we do the - // second pass to render the fallback, we do some exceedingly, uh, clever - // hacks to make that not totally break. Like transferring effects and - // deletions from hidden tree. In Concurrent Mode, it's much simpler, - // because we bailout on the primary tree completely and leave it in its old - // state, no effects. Same as what we do for Offscreen (except that - // Offscreen doesn't have the first render pass). - // - // Second is hydration. During hydration, the Suspense fiber has a slightly - // different layout, where the child points to a dehydrated fragment, which - // contains the DOM rendered by the server. - // - // Third, even if you set all that aside, Suspense is like error boundaries in - // that we first we try to render one tree, and if that fails, we render again - // and switch to a different tree. Like a try/catch block. So we have to track - // which branch we're currently rendering. Ideally we would model this using - // a stack. +function initSuspenseListRenderState( + workInProgress, + isBackwards, + tail, + lastContentRow, + tailMode +) { + var renderState = workInProgress.memoizedState; - if (current === null) { - var nextPrimaryChildren = nextProps.children; - var nextFallbackChildren = nextProps.fallback; + 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. - if (showFallback) { - pushFallbackTreeSuspenseHandler(workInProgress); - var fallbackFragment = mountSuspenseFallbackChildren( - workInProgress, - nextPrimaryChildren, - nextFallbackChildren, - renderLanes - ); - var primaryChildFragment = workInProgress.child; - primaryChildFragment.memoizedState = - mountSuspenseOffscreenState(renderLanes); - workInProgress.memoizedState = SUSPENDED_MARKER; +function updateSuspenseListComponent(current, workInProgress, renderLanes) { + var nextProps = workInProgress.pendingProps; + var revealOrder = nextProps.revealOrder; + var tailMode = nextProps.tail; + var newChildren = nextProps.children; + validateRevealOrder(revealOrder); + validateTailOptions(tailMode, revealOrder); + validateSuspenseListChildren(newChildren, revealOrder); + reconcileChildren(current, workInProgress, newChildren, renderLanes); + var suspenseContext = suspenseStackCursor.current; + var shouldForceFallback = hasSuspenseListContext( + suspenseContext, + ForceSuspenseFallback + ); - return fallbackFragment; - } else if (typeof nextProps.unstable_expectedLoadTime === "number") { - // This is a CPU-bound tree. Skip this tree and show a placeholder to - // unblock the surrounding content. Then immediately retry after the - // initial commit. - pushFallbackTreeSuspenseHandler(workInProgress); + if (shouldForceFallback) { + suspenseContext = setShallowSuspenseListContext( + suspenseContext, + ForceSuspenseFallback + ); + workInProgress.flags |= DidCapture; + } else { + var didSuspendBefore = + current !== null && (current.flags & DidCapture) !== NoFlags$1; - var _fallbackFragment = mountSuspenseFallbackChildren( + 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, - nextPrimaryChildren, - nextFallbackChildren, + workInProgress.child, renderLanes ); + } - var _primaryChildFragment = workInProgress.child; - _primaryChildFragment.memoizedState = - mountSuspenseOffscreenState(renderLanes); - workInProgress.memoizedState = SUSPENDED_MARKER; // TODO: Transition Tracing is not yet implemented for CPU Suspense. - // Since nothing actually suspended, there will nothing to ping this to - // get it started back up to attempt the next item. While in terms of - // priority this work has the same priority as this current render, it's - // not part of the same transition once the transition has committed. If - // it's sync, we still want to yield so that it can be painted. - // Conceptually, this is really the same as pinging. We can use any - // RetryLane even if it's the one currently rendering since we're leaving - // it behind on this node. + suspenseContext = setDefaultShallowSuspenseListContext(suspenseContext); + } - workInProgress.lanes = SomeRetryLane; - return _fallbackFragment; - } else { - pushPrimaryTreeSuspenseHandler(workInProgress); - return mountSuspensePrimaryChildren(workInProgress, nextPrimaryChildren); - } + pushSuspenseListContext(workInProgress, suspenseContext); + + if ((workInProgress.mode & ConcurrentMode) === NoMode) { + // In legacy mode, SuspenseList doesn't work so we just + // use make it a noop by treating it as the default revealOrder. + workInProgress.memoizedState = null; } else { - // This is an update. - // Special path for hydration - var prevState = current.memoizedState; + switch (revealOrder) { + case "forwards": { + var lastContentRow = findLastContentRow(workInProgress.child); + var tail; - if (prevState !== null) { - var _dehydrated = prevState.dehydrated; + 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 (_dehydrated !== null) { - return updateDehydratedSuspenseComponent( - current, + initSuspenseListRenderState( workInProgress, - didSuspend, - nextProps, - _dehydrated, - prevState, - renderLanes + false, // isBackwards + tail, + lastContentRow, + tailMode ); + break; } - } - if (showFallback) { - pushFallbackTreeSuspenseHandler(workInProgress); - var _nextFallbackChildren = nextProps.fallback; - var _nextPrimaryChildren = nextProps.children; - var fallbackChildFragment = updateSuspenseFallbackChildren( - current, - workInProgress, - _nextPrimaryChildren, - _nextFallbackChildren, - renderLanes - ); - var _primaryChildFragment2 = workInProgress.child; - var prevOffscreenState = current.child.memoizedState; - _primaryChildFragment2.memoizedState = - prevOffscreenState === null - ? mountSuspenseOffscreenState(renderLanes) - : updateSuspenseOffscreenState(prevOffscreenState, renderLanes); + case "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; - _primaryChildFragment2.childLanes = getRemainingWorkInPrimaryTree( - current, - renderLanes - ); - workInProgress.memoizedState = SUSPENDED_MARKER; - return fallbackChildFragment; - } else { - pushPrimaryTreeSuspenseHandler(workInProgress); - var _nextPrimaryChildren2 = nextProps.children; + while (row !== null) { + var currentRow = row.alternate; // New rows can't be content rows. - var _primaryChildFragment3 = updateSuspensePrimaryChildren( - current, - workInProgress, - _nextPrimaryChildren2, - renderLanes - ); + if (currentRow !== null && findFirstSuspended(currentRow) === null) { + // This is the beginning of the main content. + workInProgress.child = row; + break; + } - workInProgress.memoizedState = null; - return _primaryChildFragment3; + 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; + } } } -} -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; + return workInProgress.child; } -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; - } +function updatePortalComponent(current, workInProgress, renderLanes) { + pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); + var nextChildren = workInProgress.pendingProps; - fallbackChildFragment = createFiberFromFragment( - fallbackChildren, - mode, - renderLanes, - null + 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 { - primaryChildFragment = mountWorkInProgressOffscreenFiber( - primaryChildProps, - mode - ); - fallbackChildFragment = createFiberFromFragment( - fallbackChildren, - mode, - renderLanes, - null - ); + reconcileChildren(current, workInProgress, nextChildren, renderLanes); } - primaryChildFragment.return = workInProgress; - fallbackChildFragment.return = workInProgress; - primaryChildFragment.sibling = fallbackChildFragment; - workInProgress.child = primaryChildFragment; - return fallbackChildFragment; + return workInProgress.child; } -function mountWorkInProgressOffscreenFiber(offscreenProps, mode, renderLanes) { - // The props argument to `createFiberFromOffscreen` is `any` typed, so we use - // this wrapper function to constrain it. - return createFiberFromOffscreen(offscreenProps, mode, NoLanes, null); -} +var hasWarnedAboutUsingNoValuePropOnContextProvider = false; -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 updateContextProvider(current, workInProgress, renderLanes) { + var providerType = workInProgress.type; + var context = providerType._context; + var newProps = workInProgress.pendingProps; + var oldProps = workInProgress.memoizedProps; + var newValue = newProps.value; -function updateSuspensePrimaryChildren( - current, - workInProgress, - primaryChildren, - renderLanes -) { - var currentPrimaryChildFragment = current.child; - var currentFallbackChildFragment = currentPrimaryChildFragment.sibling; - var primaryChildFragment = updateWorkInProgressOffscreenFiber( - currentPrimaryChildFragment, - { - mode: "visible", - children: primaryChildren + { + 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?" + ); + } } - ); - if ((workInProgress.mode & ConcurrentMode) === NoMode) { - primaryChildFragment.lanes = renderLanes; + var providerPropTypes = workInProgress.type.propTypes; + + if (providerPropTypes) { + checkPropTypes(providerPropTypes, newProps, "prop", "Context.Provider"); + } } - primaryChildFragment.return = workInProgress; - primaryChildFragment.sibling = null; + pushProvider(workInProgress, context, newValue); - if (currentFallbackChildFragment !== null) { - // Delete the fallback child fragment - var deletions = workInProgress.deletions; + { + if (oldProps !== null) { + var oldValue = oldProps.value; - if (deletions === null) { - workInProgress.deletions = [currentFallbackChildFragment]; - workInProgress.flags |= ChildDeletion; - } else { - deletions.push(currentFallbackChildFragment); + 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); + } } } - workInProgress.child = primaryChildFragment; - return primaryChildFragment; + var newChildren = newProps.children; + reconcileChildren(current, workInProgress, newChildren, renderLanes); + return workInProgress.child; } -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; +var hasWarnedAboutUsingContextAsConsumer = false; - 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. +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. - workInProgress.deletions = null; - } else { - primaryChildFragment = updateWorkInProgressOffscreenFiber( - currentPrimaryChildFragment, - primaryChildProps - ); // Since we're reusing a current tree, we need to reuse the flags, too. - // (We don't do this in legacy mode, because in legacy mode we don't re-use - // the current tree; see previous branch.) + { + if (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; - primaryChildFragment.subtreeFlags = - currentPrimaryChildFragment.subtreeFlags & StaticMask; + 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 fallbackChildFragment; + var newProps = workInProgress.pendingProps; + var render = newProps.children; - if (currentFallbackChildFragment !== null) { - fallbackChildFragment = createWorkInProgress( - currentFallbackChildFragment, - fallbackChildren - ); - } else { - fallbackChildFragment = createFiberFromFragment( - fallbackChildren, - mode, - renderLanes, - null - ); // Needs a placement effect because the parent (the Suspense boundary) already - // mounted but this is a new fiber. + { + if (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." + ); + } + } - fallbackChildFragment.flags |= Placement; + prepareToReadContext(workInProgress, renderLanes); + var newValue = readContext(context); + + { + markComponentRenderStarted(workInProgress); } - fallbackChildFragment.return = workInProgress; - primaryChildFragment.return = workInProgress; - primaryChildFragment.sibling = fallbackChildFragment; - workInProgress.child = primaryChildFragment; - return fallbackChildFragment; -} + var newChildren; -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 + { + ReactCurrentOwner$2.current = workInProgress; + setIsRendering(true); + newChildren = render(newValue); + setIsRendering(false); + } - reconcileChildFibers(workInProgress, current.child, null, renderLanes); // We're now not suspended nor dehydrated. + { + markComponentRenderStopped(); + } // React DevTools reads this flag. - 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. + workInProgress.flags |= PerformedWork; + reconcileChildren(current, workInProgress, newChildren, renderLanes); + return workInProgress.child; +} - primaryChildFragment.flags |= Placement; - workInProgress.memoizedState = null; - return primaryChildFragment; +function markWorkInProgressReceivedUpdate() { + didReceiveUpdate = true; } -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. +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 - fallbackChildFragment.flags |= Placement; - primaryChildFragment.return = workInProgress; - fallbackChildFragment.return = workInProgress; - primaryChildFragment.sibling = fallbackChildFragment; - workInProgress.child = primaryChildFragment; + workInProgress.flags |= Placement; + } + } +} - 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); +function bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) { + if (current !== null) { + // Reuse previous dependencies + workInProgress.dependencies = current.dependencies; } - return fallbackChildFragment; -} + { + // Don't update "base" render times for bailouts. + stopProfilerTimerIfRunning(); + } -function updateDehydratedSuspenseComponent( - current, - workInProgress, - didSuspend, - nextProps, - suspenseInstance, - suspenseState, - renderLanes -) { - if (!didSuspend) { - // This is the first render pass. Attempt to hydrate. - pushPrimaryTreeSuspenseHandler(workInProgress); // We should never be hydrating at this point because it is the first pass, + markSkippedUpdateLanes(workInProgress.lanes); // Check if the children have any pending work. - if ((workInProgress.mode & ConcurrentMode) === NoMode) { - return retrySuspenseComponentWithoutHydrating( - current, - workInProgress, - renderLanes, - null - ); + 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. - 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; + cloneChildFibers(current, workInProgress); + return workInProgress.child; +} - { - var _getSuspenseInstanceF = getSuspenseInstanceFallbackErrorDetails(); +function remountFiber(current, oldWorkInProgress, newWorkInProgress) { + { + var returnFiber = oldWorkInProgress.return; - digest = _getSuspenseInstanceF.digest; - message = _getSuspenseInstanceF.message; - stack = _getSuspenseInstanceF.stack; - } + if (returnFiber === null) { + // eslint-disable-next-line react-internal/prod-error-codes + throw new Error("Cannot swap the root fiber."); + } // Disconnect from the old current. + // It will get deleted. - var error; + current.alternate = null; + oldWorkInProgress.alternate = null; // Connect to the new tree. - if (message) { + 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 - 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." - ); - } + throw new Error("Expected parent to have a child."); + } // $FlowFixMe[incompatible-use] found when upgrading Flow - error.digest = digest; - 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. + while (prevSibling.sibling !== oldWorkInProgress) { + // $FlowFixMe[incompatible-use] found when upgrading Flow + prevSibling = prevSibling.sibling; - var hasContextChanged = includesSomeLane(renderLanes, current.childLanes); + if (prevSibling === null) { + // eslint-disable-next-line react-internal/prod-error-codes + throw new Error("Expected to find the previous sibling."); + } + } // $FlowFixMe[incompatible-use] found when upgrading Flow - if (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(); + prevSibling.sibling = newWorkInProgress; + } // Delete the old fiber and place the new one. + // Since the old fiber is disconnected, we have to schedule it manually. - if (root !== null) { - var attemptHydrationAtLane = getBumpedLaneForHydration( - root, - renderLanes - ); + var deletions = returnFiber.deletions; - 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 + if (deletions === null) { + returnFiber.deletions = [current]; + returnFiber.flags |= ChildDeletion; + } else { + deletions.push(current); + } - var eventTime = NoTimestamp; - enqueueConcurrentRenderForLane(current, attemptHydrationAtLane); - scheduleUpdateOnFiber( - root, - current, - attemptHydrationAtLane, - eventTime - ); // Throw a special object that signals to the work loop that it should - // interrupt the current render. - // - // Because we're inside a React-only execution stack, we don't - // strictly need to throw here — we could instead modify some internal - // work loop state. But using an exception means we don't need to - // check for this case on every iteration of the work loop. So doing - // it this way moves the check out of the fast path. + newWorkInProgress.flags |= Placement; // Restart work from the new fiber. - throw SelectiveHydrationException; - } - } // If we did not selectively hydrate, we'll continue rendering without - // hydrating. Mark this tree as suspended to prevent it from committing - // outside a transition. - // - // This path should only happen if the hydration lane already suspended. - // Currently, it also happens during sync updates because there is no - // hydration lane for sync updates. - // TODO: We should ideally have a sync hydration lane that we can apply to do - // a pass where we hydrate this subtree in place using the previous Context and then - // reapply the update afterwards. + return newWorkInProgress; + } +} - renderDidSuspendDelayIfPossible(); - return retrySuspenseComponentWithoutHydrating( - current, - workInProgress, - renderLanes, - null - ); - } else if (isSuspenseInstancePending()) { - // This component is still pending more data from the server, so we can't hydrate its - // content. We treat it as if this component suspended itself. It might seem as if - // we could just try to render it client-side instead. However, this will perform a - // lot of unnecessary work and is unlikely to complete since it often will suspend - // on missing data anyway. Additionally, the server might be able to render more - // than we can on the client yet. In that case we'd end up with more fallback states - // on the client than if we just leave it alone. If the server times out or errors - // these should update this boundary to the permanent Fallback state instead. - // Mark it as having captured (i.e. suspended). - workInProgress.flags |= DidCapture; // Leave the child in place. I.e. the dehydrated fragment. +function checkScheduledUpdateOrContext(current, renderLanes) { + // Before performing an early bailout, we must check if there are pending + // updates or context. + var updateLanes = current.lanes; - workInProgress.child = current.child; // Register a callback to retry this boundary once the server has sent the result. + if (includesSomeLane(updateLanes, renderLanes)) { + return true; + } // No pending update, but because context is propagated lazily, we need - retryDehydratedSuspenseBoundary.bind(null, current); - registerSuspenseInstanceRetry(); - return null; - } else { - var primaryChildren = nextProps.children; - var primaryChildFragment = mountSuspensePrimaryChildren( - workInProgress, - primaryChildren - ); // Mark the children as hydrating. This is a fast path to know whether this - // tree is part of a hydrating tree. This is used to determine if a child - // node has fully mounted yet, and for scheduling event replaying. - // Conceptually this is similar to Placement in that a new subtree is - // inserted into the React tree here. It just happens to not need DOM - // mutations because it already exists. + return false; +} - primaryChildFragment.flags |= Hydrating; - return primaryChildFragment; - } - } else { - // This is the second render pass. We already attempted to hydrated, but - // something either suspended or errored. - if (workInProgress.flags & ForceClientRender) { - // Something errored during hydration. Try again without hydrating. - pushPrimaryTreeSuspenseHandler(workInProgress); - workInProgress.flags &= ~ForceClientRender; +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); + break; - var _capturedValue = createCapturedValue( - new Error( - "There was an error while hydrating this Suspense boundary. " + - "Switched to client rendering." - ) - ); + case HostSingleton: + case HostComponent: + pushHostContext(workInProgress); + break; - return retrySuspenseComponentWithoutHydrating( - current, - workInProgress, - renderLanes, - _capturedValue - ); - } else if (workInProgress.memoizedState !== null) { - // Something suspended and we should still be in dehydrated mode. - // Leave the existing child in place. - // Push to avoid a mismatch - pushFallbackTreeSuspenseHandler(workInProgress); - workInProgress.child = current.child; // The dehydrated completion pass expects this flag to be there - // but the normal suspense pass doesn't. + case ClassComponent: { + var Component = workInProgress.type; - workInProgress.flags |= DidCapture; - return null; - } else { - // Suspended but we should no longer be in dehydrated mode. - // Therefore we now have to render the fallback. - pushFallbackTreeSuspenseHandler(workInProgress); - var nextPrimaryChildren = nextProps.children; - var nextFallbackChildren = nextProps.fallback; - var fallbackChildFragment = - mountSuspenseFallbackAfterRetryWithoutHydrating( - current, - workInProgress, - nextPrimaryChildren, - nextFallbackChildren, - renderLanes - ); - var _primaryChildFragment4 = workInProgress.child; - _primaryChildFragment4.memoizedState = - mountSuspenseOffscreenState(renderLanes); - workInProgress.memoizedState = SUSPENDED_MARKER; - return fallbackChildFragment; + if (isContextProvider(Component)) { + pushContextProvider(workInProgress); + } + + break; + } + + case HostPortal: + pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); + break; + + case ContextProvider: { + var newValue = workInProgress.memoizedProps.value; + var context = workInProgress.type._context; + pushProvider(workInProgress, context, newValue); + break; } - } -} -function scheduleSuspenseWorkOnFiber(fiber, renderLanes, propagationRoot) { - fiber.lanes = mergeLanes(fiber.lanes, renderLanes); - var alternate = fiber.alternate; + case Profiler: + { + // Profiler should only call onRender when one of its descendants actually rendered. + var hasChildWork = includesSomeLane( + renderLanes, + workInProgress.childLanes + ); - if (alternate !== null) { - alternate.lanes = mergeLanes(alternate.lanes, renderLanes); - } + if (hasChildWork) { + workInProgress.flags |= Update; + } - scheduleContextWorkOnParentPath(fiber.return, renderLanes, propagationRoot); -} + { + // 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 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; + break; - while (node !== null) { - if (node.tag === SuspenseComponent) { - var state = node.memoizedState; + case SuspenseComponent: { + var state = workInProgress.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 (state.dehydrated !== null) { + // We're not going to render the children, so this is just to maintain + // push/pop symmetry + pushPrimaryTreeSuspenseHandler(workInProgress); // We know that this component will suspend again because if it has + // been unsuspended it has committed as a resolved Suspense component. + // If it needs to be retried, it should have work scheduled on it. - if (node === workInProgress) { - return; - } // $FlowFixMe[incompatible-use] found when upgrading Flow + workInProgress.flags |= DidCapture; // We should never render the children of a dehydrated boundary until we + // upgrade it. We return null instead of bailoutOnAlreadyFinishedWork. - while (node.sibling === null) { - // $FlowFixMe[incompatible-use] found when upgrading Flow - if (node.return === null || node.return === workInProgress) { - return; - } + 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. - node = node.return; - } // $FlowFixMe[incompatible-use] found when upgrading Flow + var primaryChildFragment = workInProgress.child; + var primaryChildLanes = primaryChildFragment.childLanes; - node.sibling.return = node.return; - node = node.sibling; - } -} + if (includesSomeLane(renderLanes, primaryChildLanes)) { + // The primary children have pending work. Use the normal path + // to attempt to render the primary children again. + return updateSuspenseComponent(current, workInProgress, renderLanes); + } else { + // The primary child fragment does not have pending work marked + // on it + pushPrimaryTreeSuspenseHandler(workInProgress); // The primary children do not have pending work with sufficient + // priority. Bailout. -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 child = bailoutOnAlreadyFinishedWork( + current, + workInProgress, + renderLanes + ); - while (row !== null) { - var currentRow = row.alternate; // New rows can't be content rows. + if (child !== null) { + // The fallback children have pending work. Skip over the + // primary children and work on the fallback. + return child.sibling; + } else { + // Note: We can return `null` here because we already checked + // whether there were nested context consumers, via the call to + // `bailoutOnAlreadyFinishedWork` above. + return null; + } + } + } else { + pushPrimaryTreeSuspenseHandler(workInProgress); + } - if (currentRow !== null && findFirstSuspended(currentRow) === null) { - lastContentRow = row; + break; } - row = row.sibling; - } - - return lastContentRow; -} + case SuspenseListComponent: { + var didSuspendBefore = (current.flags & DidCapture) !== NoFlags$1; -function validateRevealOrder(revealOrder) { - { - if ( - revealOrder !== undefined && - revealOrder !== "forwards" && - revealOrder !== "backwards" && - revealOrder !== "together" && - !didWarnAboutRevealOrder[revealOrder] - ) { - didWarnAboutRevealOrder[revealOrder] = true; + var _hasChildWork = includesSomeLane( + renderLanes, + workInProgress.childLanes + ); - 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 (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. - break; - } + 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. - 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() - ); + var renderState = workInProgress.memoizedState; - break; - } + 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; + } - default: - error( - '"%s" is not a supported revealOrder on . ' + - 'Did you mean "together", "forwards" or "backwards"?', - revealOrder - ); + pushSuspenseListContext(workInProgress, suspenseStackCursor.current); - break; - } + if (_hasChildWork) { + break; } else { - error( - "%s is not a supported value for revealOrder on . " + - 'Did you mean "together", "forwards" or "backwards"?', - revealOrder - ); + // If none of the children had any work, that means that none of + // them got retried so they'll still be blocked in the same way + // as before. We can fast bail out. + return null; } } - } -} - -function 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 - ); - } + 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 validateSuspenseListNestedChild(childSlot, index) { +function beginWork$1(current, workInProgress, renderLanes) { { - 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 (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 + ) ); - - return false; } } - return true; -} + if (current !== null) { + var oldProps = current.memoizedProps; + var newProps = workInProgress.pendingProps; -function validateSuspenseListChildren(children, revealOrder) { - { if ( - (revealOrder === "forwards" || revealOrder === "backwards") && - children !== undefined && - children !== null && - children !== false + oldProps !== newProps || + hasContextChanged() || // Force a re-render if the implementation changed due to hot reload: + workInProgress.type !== current.type ) { - 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; + // 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 + ); - for (; !step.done; step = childrenIterator.next()) { - if (!validateSuspenseListNestedChild(step.value, _i)) { - return; - } + if ( + !hasScheduledUpdateOrContext && // If this is the second pass of an error or suspense boundary, there + // may not be work scheduled on `current`, so we check for this flag. + (workInProgress.flags & DidCapture) === NoFlags$1 + ) { + // No pending updates or context. Bail out now. + didReceiveUpdate = false; + return attemptEarlyBailoutIfNoScheduledUpdate( + current, + workInProgress, + renderLanes + ); + } - _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 - ); - } + if ((current.flags & ForceUpdateForLegacySuspense) !== NoFlags$1) { + // This is a special case that only exists for legacy mode. + // See https://github.com/facebook/react/pull/19216. + didReceiveUpdate = true; + } else { + // An update was scheduled on this fiber, but there are no new props + // nor legacy context. Set this to false. If an update queue or context + // consumer produces a changed value, it will set this to true. Otherwise, + // the component will assume the children have not changed and bail out. + didReceiveUpdate = false; } } - } -} - -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. + 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. -function updateSuspenseListComponent(current, workInProgress, renderLanes) { - var nextProps = workInProgress.pendingProps; - var revealOrder = nextProps.revealOrder; - var tailMode = nextProps.tail; - var newChildren = nextProps.children; - validateRevealOrder(revealOrder); - validateTailOptions(tailMode, revealOrder); - validateSuspenseListChildren(newChildren, revealOrder); - reconcileChildren(current, workInProgress, newChildren, renderLanes); - var suspenseContext = suspenseStackCursor.current; - var shouldForceFallback = hasSuspenseListContext( - suspenseContext, - ForceSuspenseFallback - ); + workInProgress.lanes = NoLanes; - if (shouldForceFallback) { - suspenseContext = setShallowSuspenseListContext( - suspenseContext, - ForceSuspenseFallback - ); - workInProgress.flags |= DidCapture; - } else { - var didSuspendBefore = - current !== null && (current.flags & DidCapture) !== NoFlags$1; + switch (workInProgress.tag) { + case IndeterminateComponent: { + return mountIndeterminateComponent( + current, + workInProgress, + workInProgress.type, + renderLanes + ); + } - 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( + case LazyComponent: { + var elementType = workInProgress.elementType; + return mountLazyComponent( + current, workInProgress, - workInProgress.child, + elementType, renderLanes ); } - suspenseContext = setDefaultShallowSuspenseListContext(suspenseContext); - } + 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 + ); + } - pushSuspenseListContext(workInProgress, suspenseContext); + case ClassComponent: { + var _Component = workInProgress.type; + var _unresolvedProps = workInProgress.pendingProps; - 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; + var _resolvedProps = + workInProgress.elementType === _Component + ? _unresolvedProps + : resolveDefaultProps(_Component, _unresolvedProps); - 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; - } + return updateClassComponent( + current, + workInProgress, + _Component, + _resolvedProps, + renderLanes + ); + } - initSuspenseListRenderState( - workInProgress, - false, // isBackwards - tail, - lastContentRow, - tailMode - ); - break; - } + case HostRoot: + return updateHostRoot(current, workInProgress, renderLanes); - 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; + case HostHoistable: - while (row !== null) { - var currentRow = row.alternate; // New rows can't be content rows. + // eslint-disable-next-line no-fallthrough - if (currentRow !== null && findFirstSuspended(currentRow) === null) { - // This is the beginning of the main content. - workInProgress.child = row; - break; - } + case HostSingleton: - var nextRow = row.sibling; - row.sibling = _tail; - _tail = row; - row = nextRow; - } // TODO: If workInProgress.child is null, we can continue on the tail immediately. + // eslint-disable-next-line no-fallthrough - initSuspenseListRenderState( - workInProgress, - true, // isBackwards - _tail, - null, // last - tailMode - ); - break; - } + case HostComponent: + return updateHostComponent$1(current, workInProgress, renderLanes); - case "together": { - initSuspenseListRenderState( - workInProgress, - false, // isBackwards - null, // tail - null, // last - undefined - ); - break; - } + case HostText: + return updateHostText$1(); - default: { - // The default reveal order is the same as not having - // a boundary. - workInProgress.memoizedState = null; - } - } - } + case SuspenseComponent: + return updateSuspenseComponent(current, workInProgress, renderLanes); - return workInProgress.child; -} + case HostPortal: + return updatePortalComponent(current, workInProgress, renderLanes); -function updatePortalComponent(current, workInProgress, renderLanes) { - pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); - var nextChildren = workInProgress.pendingProps; + case ForwardRef: { + var type = workInProgress.type; + var _unresolvedProps2 = workInProgress.pendingProps; - if (current === null) { - // Portals are special because we don't append the children during mount - // but at commit. Therefore we need to track insertions which the normal - // flow doesn't do during mount. This doesn't happen at the root because - // the root always starts with a "current" with a null child. - // TODO: Consider unifying this with how the root works. - workInProgress.child = reconcileChildFibers( - workInProgress, - null, - nextChildren, - renderLanes - ); - } else { - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - } + var _resolvedProps2 = + workInProgress.elementType === type + ? _unresolvedProps2 + : resolveDefaultProps(type, _unresolvedProps2); - return workInProgress.child; -} + return updateForwardRef( + current, + workInProgress, + type, + _resolvedProps2, + renderLanes + ); + } -var hasWarnedAboutUsingNoValuePropOnContextProvider = false; + case Fragment: + return updateFragment(current, workInProgress, renderLanes); -function updateContextProvider(current, workInProgress, renderLanes) { - var providerType = workInProgress.type; - var context = providerType._context; - var newProps = workInProgress.pendingProps; - var oldProps = workInProgress.memoizedProps; - var newValue = newProps.value; + case Mode: + return updateMode(current, workInProgress, renderLanes); - { - if (!("value" in newProps)) { - if (!hasWarnedAboutUsingNoValuePropOnContextProvider) { - hasWarnedAboutUsingNoValuePropOnContextProvider = true; + case Profiler: + return updateProfiler(current, workInProgress, renderLanes); - error( - "The `value` prop is required for the ``. Did you misspell it or forget to pass it?" - ); - } - } + case ContextProvider: + return updateContextProvider(current, workInProgress, renderLanes); - var providerPropTypes = workInProgress.type.propTypes; + case ContextConsumer: + return updateContextConsumer(current, workInProgress, renderLanes); - if (providerPropTypes) { - checkPropTypes(providerPropTypes, newProps, "prop", "Context.Provider"); - } - } + case MemoComponent: { + var _type2 = workInProgress.type; + var _unresolvedProps3 = workInProgress.pendingProps; // Resolve outer props first, then resolve inner props. - pushProvider(workInProgress, context, newValue); + var _resolvedProps3 = resolveDefaultProps(_type2, _unresolvedProps3); - { - if (oldProps !== null) { - var oldValue = oldProps.value; + { + if (workInProgress.type !== workInProgress.elementType) { + var outerPropTypes = _type2.propTypes; - 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 (outerPropTypes) { + checkPropTypes( + outerPropTypes, + _resolvedProps3, // Resolved for outer only + "prop", + getComponentNameFromType(_type2) + ); + } } - } 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; -} + _resolvedProps3 = resolveDefaultProps(_type2.type, _resolvedProps3); + return updateMemoComponent( + current, + workInProgress, + _type2, + _resolvedProps3, + renderLanes + ); + } -var hasWarnedAboutUsingContextAsConsumer = false; + case SimpleMemoComponent: { + return updateSimpleMemoComponent( + current, + workInProgress, + workInProgress.type, + workInProgress.pendingProps, + renderLanes + ); + } -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. + case IncompleteClassComponent: { + var _Component2 = workInProgress.type; + var _unresolvedProps4 = workInProgress.pendingProps; - { - 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 _resolvedProps4 = + workInProgress.elementType === _Component2 + ? _unresolvedProps4 + : resolveDefaultProps(_Component2, _unresolvedProps4); - 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; + return mountIncompleteClassComponent( + current, + workInProgress, + _Component2, + _resolvedProps4, + renderLanes + ); } - } - var newProps = workInProgress.pendingProps; - var render = newProps.children; + case SuspenseListComponent: { + return updateSuspenseListComponent(current, workInProgress, renderLanes); + } - { - if (typeof render !== "function") { - error( - "A context consumer was rendered with multiple children, or a child " + - "that isn't a function. A context consumer expects a single child " + - "that is a function. If you did pass a function, make sure there " + - "is no trailing or leading whitespace around it." - ); + case ScopeComponent: { + break; } - } - prepareToReadContext(workInProgress, renderLanes); - var newValue = readContext(context); + case OffscreenComponent: { + return updateOffscreenComponent(current, workInProgress, renderLanes); + } - { - markComponentRenderStarted(workInProgress); + case LegacyHiddenComponent: { + { + return updateLegacyHiddenComponent( + current, + workInProgress, + renderLanes + ); + } + } } - var newChildren; + throw new Error( + "Unknown unit of work tag (" + + workInProgress.tag + + "). This error is likely caused by a bug in " + + "React. Please file an issue." + ); +} - { - ReactCurrentOwner$2.current = workInProgress; - setIsRendering(true); - newChildren = render(newValue); - setIsRendering(false); - } +var valueCursor = createCursor(null); - { - markComponentRenderStopped(); - } // React DevTools reads this flag. +var renderer2CursorDEV; - workInProgress.flags |= PerformedWork; - reconcileChildren(current, workInProgress, newChildren, renderLanes); - return workInProgress.child; +{ + renderer2CursorDEV = createCursor(null); } -function markWorkInProgressReceivedUpdate() { - didReceiveUpdate = true; +var rendererSigil; + +{ + // Use this to detect multiple renderers using the same context + rendererSigil = {}; } -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 +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; - workInProgress.flags |= Placement; - } + { + isDisallowedContextReadInDEV = false; } } - -function bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) { - if (current !== null) { - // Reuse previous dependencies - workInProgress.dependencies = current.dependencies; +function enterDisallowedContextReadInDEV() { + { + isDisallowedContextReadInDEV = true; } - +} +function exitDisallowedContextReadInDEV() { { - // Don't update "base" render times for bailouts. - stopProfilerTimerIfRunning(); + isDisallowedContextReadInDEV = false; } - - 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) { +function pushProvider(providerFiber, context, nextValue) { { - 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."); - } // $FlowFixMe[incompatible-use] found when upgrading Flow - - while (prevSibling.sibling !== oldWorkInProgress) { - // $FlowFixMe[incompatible-use] found when upgrading Flow - prevSibling = prevSibling.sibling; - - if (prevSibling === null) { - // eslint-disable-next-line react-internal/prod-error-codes - throw new Error("Expected to find the previous sibling."); - } - } // $FlowFixMe[incompatible-use] found when upgrading Flow + push(valueCursor, context._currentValue2, providerFiber); + context._currentValue2 = nextValue; - prevSibling.sibling = newWorkInProgress; - } // Delete the old fiber and place the new one. - // Since the old fiber is disconnected, we have to schedule it manually. + { + push(renderer2CursorDEV, context._currentRenderer2, providerFiber); - var deletions = returnFiber.deletions; + 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 (deletions === null) { - returnFiber.deletions = [current]; - returnFiber.flags |= ChildDeletion; - } else { - deletions.push(current); + context._currentRenderer2 = rendererSigil; } - - newWorkInProgress.flags |= Placement; // Restart work from the new fiber. - - return newWorkInProgress; } } +function popProvider(context, providerFiber) { + var currentValue = valueCursor.current; -function checkScheduledUpdateOrContext(current, renderLanes) { - // Before performing an early bailout, we must check if there are pending - // updates or context. - var updateLanes = current.lanes; + { + if (currentValue === REACT_SERVER_CONTEXT_DEFAULT_VALUE_NOT_LOADED) { + context._currentValue2 = context._defaultValue; + } else { + context._currentValue2 = currentValue; + } - if (includesSomeLane(updateLanes, renderLanes)) { - return true; - } // No pending update, but because context is propagated lazily, we need + { + var currentRenderer2 = renderer2CursorDEV.current; + pop(renderer2CursorDEV, providerFiber); + context._currentRenderer2 = currentRenderer2; + } + } - return false; + pop(valueCursor, providerFiber); } +function scheduleContextWorkOnParentPath(parent, renderLanes, propagationRoot) { + // Update the child lanes of all the ancestors, including the alternates. + var node = parent; -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); - break; - - case HostSingleton: - case HostComponent: - pushHostContext(workInProgress); - break; + while (node !== null) { + var alternate = node.alternate; - case ClassComponent: { - var Component = workInProgress.type; + if (!isSubsetOfLanes(node.childLanes, renderLanes)) { + node.childLanes = mergeLanes(node.childLanes, renderLanes); - if (isContextProvider(Component)) { - pushContextProvider(workInProgress); + if (alternate !== null) { + alternate.childLanes = mergeLanes(alternate.childLanes, renderLanes); } + } else if ( + alternate !== null && + !isSubsetOfLanes(alternate.childLanes, renderLanes) + ) { + alternate.childLanes = mergeLanes(alternate.childLanes, renderLanes); + } else; + if (node === propagationRoot) { break; } - case HostPortal: - pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); - break; + node = node.return; + } - case ContextProvider: { - var newValue = workInProgress.memoizedProps.value; - var context = workInProgress.type._context; - pushProvider(workInProgress, context, newValue); - break; + { + 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); + } +} - case Profiler: - { - // Profiler should only call onRender when one of its descendants actually rendered. - var hasChildWork = includesSomeLane( - renderLanes, - workInProgress.childLanes - ); - - if (hasChildWork) { - workInProgress.flags |= Update; - } +function propagateContextChange_eager(workInProgress, context, renderLanes) { + var fiber = workInProgress.child; - { - // 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 (fiber !== null) { + // Set the return pointer of the child to the work-in-progress fiber. + fiber.return = workInProgress; + } - break; + while (fiber !== null) { + var nextFiber = void 0; // Visit this fiber. - case SuspenseComponent: { - var state = workInProgress.memoizedState; + var list = fiber.dependencies; - if (state !== null) { - if (state.dehydrated !== null) { - // We're not going to render the children, so this is just to maintain - // push/pop symmetry - pushPrimaryTreeSuspenseHandler(workInProgress); // We know that this component will suspend again because if it has - // been unsuspended it has committed as a resolved Suspense component. - // If it needs to be retried, it should have work scheduled on it. + if (list !== null) { + nextFiber = fiber.child; + var dependency = list.firstContext; - workInProgress.flags |= DidCapture; // We should never render the children of a dehydrated boundary until we - // upgrade it. We return null instead of bailoutOnAlreadyFinishedWork. + while (dependency !== null) { + // Check if the context matches. + if (dependency.context === context) { + // Match! Schedule an update on this fiber. + if (fiber.tag === ClassComponent) { + // Schedule a force update on the work-in-progress. + var lane = pickArbitraryLane(renderLanes); + var update = createUpdate(lane); + update.tag = ForceUpdate; // TODO: Because we don't have a work-in-progress, this will add the + // update to the current fiber, too, which means it will persist even if + // this render is thrown away. Since it's a race condition, not sure it's + // worth fixing. + // Inlined `enqueueUpdate` to remove interleaved update check - 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 updateQueue = fiber.updateQueue; - var primaryChildFragment = workInProgress.child; - var primaryChildLanes = primaryChildFragment.childLanes; + if (updateQueue === null); + else { + var sharedQueue = updateQueue.shared; + var pending = sharedQueue.pending; - if (includesSomeLane(renderLanes, primaryChildLanes)) { - // The primary children have pending work. Use the normal path - // to attempt to render the primary children again. - return updateSuspenseComponent(current, workInProgress, renderLanes); - } else { - // The primary child fragment does not have pending work marked - // on it - pushPrimaryTreeSuspenseHandler(workInProgress); // The primary children do not have pending work with sufficient - // priority. Bailout. + if (pending === null) { + // This is the first update. Create a circular list. + update.next = update; + } else { + update.next = pending.next; + pending.next = update; + } - var child = bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderLanes - ); + sharedQueue.pending = update; + } + } - 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; + fiber.lanes = mergeLanes(fiber.lanes, renderLanes); + var alternate = fiber.alternate; + + if (alternate !== null) { + alternate.lanes = mergeLanes(alternate.lanes, renderLanes); } + + 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. + + break; } - } else { - pushPrimaryTreeSuspenseHandler(workInProgress); + + 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; - 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." + ); + } - case SuspenseListComponent: { - var didSuspendBefore = (current.flags & DidCapture) !== NoFlags$1; + parentSuspense.lanes = mergeLanes(parentSuspense.lanes, renderLanes); + var _alternate = parentSuspense.alternate; - var _hasChildWork = includesSomeLane( + if (_alternate !== null) { + _alternate.lanes = mergeLanes(_alternate.lanes, renderLanes); + } // This is intentionally passing this fiber as the parent + // because we want to schedule this fiber as having work + // on its children. We'll use the childLanes on + // this fiber to indicate that a context has changed. + + scheduleContextWorkOnParentPath( + parentSuspense, renderLanes, - workInProgress.childLanes + workInProgress ); + nextFiber = fiber.sibling; + } else { + // Traverse down. + nextFiber = fiber.child; + } - 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. + if (nextFiber !== null) { + // Set the return pointer of the child to the work-in-progress fiber. + nextFiber.return = fiber; + } else { + // No child. Traverse to next sibling. + nextFiber = fiber; - var renderState = workInProgress.memoizedState; + while (nextFiber !== null) { + if (nextFiber === workInProgress) { + // We're back to the root of this subtree. Exit. + nextFiber = null; + break; + } - 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; - } + var sibling = nextFiber.sibling; - pushSuspenseListContext(workInProgress, suspenseStackCursor.current); + 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 (_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; + nextFiber = nextFiber.return; } } - 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); - } + fiber = nextFiber; } - - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); } +function prepareToReadContext(workInProgress, renderLanes) { + currentlyRenderingFiber = workInProgress; + lastContextDependency = null; + lastFullyObservedContext = null; + var dependencies = workInProgress.dependencies; -function beginWork$1(current, workInProgress, renderLanes) { + if (dependencies !== null) { + { + var firstContext = dependencies.firstContext; + + 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) { { - 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 - ) + // 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 (current !== null) { - var oldProps = current.memoizedProps; - var newProps = workInProgress.pendingProps; + return readContextForConsumer(currentlyRenderingFiber, context); +} +function readContextDuringReconcilation(consumer, context, renderLanes) { + if (currentlyRenderingFiber === null) { + prepareToReadContext(consumer, renderLanes); + } - 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 - ); + return readContextForConsumer(consumer, context); +} - if ( - !hasScheduledUpdateOrContext && // If this is the second pass of an error or suspense boundary, there - // may not be work scheduled on `current`, so we check for this flag. - (workInProgress.flags & DidCapture) === NoFlags$1 - ) { - // No pending updates or context. Bail out now. - didReceiveUpdate = false; - return attemptEarlyBailoutIfNoScheduledUpdate( - current, - workInProgress, - renderLanes +function readContextForConsumer(consumer, context) { + var value = isPrimaryRenderer + ? context._currentValue + : context._currentValue2; + + if (lastFullyObservedContext === context); + else { + var contextItem = { + context: context, + memoizedValue: value, + next: null + }; + + if (lastContextDependency === null) { + if (consumer === null) { + throw new Error( + "Context can only be read while React is rendering. " + + "In classes, you can read it in the render method or getDerivedStateFromProps. " + + "In function components, you can read it directly in the function body, but not " + + "inside Hooks like useReducer() or useMemo()." ); - } + } // This is the first dependency for this component. Create a new list. - if ((current.flags & ForceUpdateForLegacySuspense) !== NoFlags$1) { - // This is a special case that only exists for legacy mode. - // See https://github.com/facebook/react/pull/19216. - didReceiveUpdate = true; - } else { - // An update was scheduled on this fiber, but there are no new props - // nor legacy context. Set this to false. If an update queue or context - // consumer produces a changed value, it will set this to true. Otherwise, - // the component will assume the children have not changed and bail out. - didReceiveUpdate = false; - } + lastContextDependency = contextItem; + consumer.dependencies = { + lanes: NoLanes, + firstContext: contextItem + }; + } else { + // Append a new context item. + lastContextDependency = lastContextDependency.next = contextItem; } - } else { - didReceiveUpdate = false; - } // Before entering the begin phase, clear pending update priority. - // TODO: This assumes that we're about to evaluate the component and process - // the update queue. However, there's an exception: SimpleMemoComponent - // sometimes bails out later in the begin phase. This indicates that we should - // move this assignment out of the common path and into each branch. + } - workInProgress.lanes = NoLanes; + return value; +} - switch (workInProgress.tag) { - case IndeterminateComponent: { - return mountIndeterminateComponent( - current, - workInProgress, - workInProgress.type, - renderLanes - ); - } +var ReactCurrentBatchConfig$1 = ReactSharedInternals.ReactCurrentBatchConfig; +var NoTransition = null; +function requestCurrentTransition() { + return ReactCurrentBatchConfig$1.transition; +} // When retrying a Suspense/Offscreen boundary, we restore the cache that was +function getSuspendedCache() { + { + return null; + } // This function is called when a Suspense boundary suspends. It returns the +} - case LazyComponent: { - var elementType = workInProgress.elementType; - return mountLazyComponent( - current, - workInProgress, - elementType, - renderLanes - ); - } +function markUpdate(workInProgress) { + // Tag the fiber with an update effect. This turns a Placement into + // a PlacementAndUpdate. + workInProgress.flags |= Update; +} - 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 - ); - } +function markRef(workInProgress) { + workInProgress.flags |= Ref | RefStatic; +} - case ClassComponent: { - var _Component = workInProgress.type; - var _unresolvedProps = workInProgress.pendingProps; +function hadNoMutationsEffects(current, completedWork) { + var didBailout = current !== null && current.child === completedWork.child; - var _resolvedProps = - workInProgress.elementType === _Component - ? _unresolvedProps - : resolveDefaultProps(_Component, _unresolvedProps); + if (didBailout) { + return true; + } - return updateClassComponent( - current, - workInProgress, - _Component, - _resolvedProps, - renderLanes - ); + if ((completedWork.flags & ChildDeletion) !== NoFlags$1) { + 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 ( + (child.flags & MutationMask) !== NoFlags$1 || + (child.subtreeFlags & MutationMask) !== NoFlags$1 + ) { + return false; } - case HostRoot: - return updateHostRoot(current, workInProgress, renderLanes); + child = child.sibling; + } - case HostHoistable: + return true; +} - // eslint-disable-next-line no-fallthrough +function appendAllChildren( + parent, + workInProgress, + needsVisibilityToggle, + isHidden +) { + { + // We only have the top Fiber that was created but we need recurse down its + // children to find all the terminal nodes. + var _node = workInProgress.child; - case HostSingleton: + while (_node !== null) { + // eslint-disable-next-line no-labels + if (_node.tag === HostComponent) { + var instance = _node.stateNode; - // eslint-disable-next-line no-fallthrough + if (needsVisibilityToggle && isHidden) { + instance = cloneHiddenInstance(instance); + } - case HostComponent: - return updateHostComponent$1(current, workInProgress, renderLanes); + appendInitialChild(parent, instance); + } else if (_node.tag === HostText) { + var _instance = _node.stateNode; - case HostText: - return updateHostText$1(); + if (needsVisibilityToggle && isHidden) { + _instance = cloneHiddenTextInstance(); + } - case SuspenseComponent: - return updateSuspenseComponent(current, workInProgress, renderLanes); + 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; - case HostPortal: - return updatePortalComponent(current, workInProgress, renderLanes); + if (child !== null) { + child.return = _node; + } - case ForwardRef: { - var type = workInProgress.type; - var _unresolvedProps2 = workInProgress.pendingProps; + appendAllChildren(parent, _node, true, true); + } else if (_node.child !== null) { + _node.child.return = _node; + _node = _node.child; + continue; + } - var _resolvedProps2 = - workInProgress.elementType === type - ? _unresolvedProps2 - : resolveDefaultProps(type, _unresolvedProps2); + _node = _node; - return updateForwardRef( - current, - workInProgress, - type, - _resolvedProps2, - renderLanes - ); + if (_node === workInProgress) { + return; + } // $FlowFixMe[incompatible-use] found when upgrading Flow + + while (_node.sibling === null) { + // $FlowFixMe[incompatible-use] found when upgrading Flow + if (_node.return === null || _node.return === workInProgress) { + return; + } + + _node = _node.return; + } // $FlowFixMe[incompatible-use] found when upgrading Flow + + _node.sibling.return = _node.return; + _node = _node.sibling; } + } +} // An unfortunate fork of appendAllChildren because we have two different parent types. - case Fragment: - return updateFragment(current, workInProgress, renderLanes); +function appendAllChildrenToContainer( + 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; - case Mode: - return updateMode(current, workInProgress, renderLanes); + while (node !== null) { + // eslint-disable-next-line no-labels + if (node.tag === HostComponent) { + var instance = node.stateNode; - case Profiler: - return updateProfiler(current, workInProgress, renderLanes); + if (needsVisibilityToggle && isHidden) { + instance = cloneHiddenInstance(instance); + } - case ContextProvider: - return updateContextProvider(current, workInProgress, renderLanes); + appendChildToContainerChildSet(containerChildSet, instance); + } else if (node.tag === HostText) { + var _instance2 = node.stateNode; - case ContextConsumer: - return updateContextConsumer(current, workInProgress, renderLanes); + if (needsVisibilityToggle && isHidden) { + _instance2 = cloneHiddenTextInstance(); + } - case MemoComponent: { - var _type2 = workInProgress.type; - var _unresolvedProps3 = workInProgress.pendingProps; // Resolve outer props first, then resolve inner props. + 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; - var _resolvedProps3 = resolveDefaultProps(_type2, _unresolvedProps3); + if (child !== null) { + child.return = node; + } // If Offscreen is not in manual mode, detached tree is hidden from user space. - { - if (workInProgress.type !== workInProgress.elementType) { - var outerPropTypes = _type2.propTypes; + var _needsVisibilityToggle = !isOffscreenManual(node); - if (outerPropTypes) { - checkPropTypes( - outerPropTypes, - _resolvedProps3, // Resolved for outer only - "prop", - getComponentNameFromType(_type2) - ); - } - } + appendAllChildrenToContainer( + containerChildSet, + node, + _needsVisibilityToggle, + true + ); + } else if (node.child !== null) { + node.child.return = node; + node = node.child; + continue; } - _resolvedProps3 = resolveDefaultProps(_type2.type, _resolvedProps3); - return updateMemoComponent( - current, - workInProgress, - _type2, - _resolvedProps3, - renderLanes - ); - } + node = node; - case SimpleMemoComponent: { - return updateSimpleMemoComponent( - current, - workInProgress, - workInProgress.type, - workInProgress.pendingProps, - renderLanes - ); - } + if (node === workInProgress) { + return; + } // $FlowFixMe[incompatible-use] found when upgrading Flow - case IncompleteClassComponent: { - var _Component2 = workInProgress.type; - var _unresolvedProps4 = workInProgress.pendingProps; + while (node.sibling === null) { + // $FlowFixMe[incompatible-use] found when upgrading Flow + if (node.return === null || node.return === workInProgress) { + return; + } - var _resolvedProps4 = - workInProgress.elementType === _Component2 - ? _unresolvedProps4 - : resolveDefaultProps(_Component2, _unresolvedProps4); + node = node.return; + } // $FlowFixMe[incompatible-use] found when upgrading Flow - return mountIncompleteClassComponent( - current, - workInProgress, - _Component2, - _resolvedProps4, - renderLanes - ); + node.sibling.return = node.return; + node = node.sibling; } + } +} - case SuspenseListComponent: { - return updateSuspenseListComponent(current, workInProgress, renderLanes); - } +function updateHostContainer(current, workInProgress) { + { + var portalOrRoot = workInProgress.stateNode; + var childrenUnchanged = hadNoMutationsEffects(current, workInProgress); - case ScopeComponent: { - break; - } + 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. - case OffscreenComponent: { - return updateOffscreenComponent(current, workInProgress, renderLanes); - } + appendAllChildrenToContainer(newChildSet, workInProgress, false, false); + portalOrRoot.pendingChildren = newChildSet; // Schedule an update on the container to swap out the container. - case LegacyHiddenComponent: { - { - return updateLegacyHiddenComponent( - current, - workInProgress, - renderLanes - ); - } + markUpdate(workInProgress); + finalizeContainerChildren(container, newChildSet); } } - - throw new Error( - "Unknown unit of work tag (" + - workInProgress.tag + - "). This error is likely caused by a bug in " + - "React. Please file an issue." - ); } -var valueCursor = createCursor(null); +function updateHostComponent( + current, + workInProgress, + type, + newProps, + renderLanes +) { + { + 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. -var renderer2CursorDEV; + var childrenUnchanged = hadNoMutationsEffects(current, workInProgress); -{ - renderer2CursorDEV = createCursor(null); -} + if (childrenUnchanged && _oldProps === newProps) { + // No changes, just reuse the existing instance. + // Note that this might release a previous clone. + workInProgress.stateNode = currentInstance; + return; + } -var rendererSigil; + var recyclableInstance = workInProgress.stateNode; -{ - // Use this to detect multiple renderers using the same context - rendererSigil = {}; -} + getHostContext(); -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; + var _updatePayload = null; - { - isDisallowedContextReadInDEV = false; - } -} -function enterDisallowedContextReadInDEV() { - { - isDisallowedContextReadInDEV = true; - } -} -function exitDisallowedContextReadInDEV() { - { - isDisallowedContextReadInDEV = false; - } -} -function pushProvider(providerFiber, context, nextValue) { - { - push(valueCursor, context._currentValue2, providerFiber); - context._currentValue2 = nextValue; + if (_oldProps !== newProps) { + _updatePayload = prepareUpdate( + recyclableInstance, + type, + _oldProps, + newProps + ); + } - { - push(renderer2CursorDEV, context._currentRenderer2, providerFiber); + if (childrenUnchanged && _updatePayload === null) { + // No changes, just reuse the existing instance. + // Note that this might release a previous clone. + workInProgress.stateNode = currentInstance; + return; + } - if ( - context._currentRenderer2 !== undefined && - context._currentRenderer2 !== null && - context._currentRenderer2 !== rendererSigil - ) { - error( - "Detected multiple renderers concurrently rendering the " + - "same context provider. This is currently unsupported." - ); - } + var newInstance = cloneInstance( + currentInstance, + _updatePayload, + type, + _oldProps, + newProps, + workInProgress, + childrenUnchanged + ); + suspendHostCommitIfNeeded(workInProgress); + + 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); + } + } +} // TODO: This should ideally move to begin phase, but currently the instance is +// not created until the complete phase. For our existing use cases, host nodes +// that suspend don't have children, so it doesn't matter. But that might not +// always be true in the future. - context._currentRenderer2 = rendererSigil; +function suspendHostCommitIfNeeded(workInProgress, type, props, renderLanes) { + // Ask the renderer if this instance should suspend the commit. + { + // If this flag was set previously, we can remove it. The flag represents + // whether this particular set of props might ever need to suspend. The + // safest thing to do is for shouldSuspendCommit to always return true, but + // if the renderer is reasonably confident that the underlying resource + // won't be evicted, it can return false as a performance optimization. + workInProgress.flags &= ~SuspenseyCommit; + return; + } // Mark this fiber with a flag. We use this right before the commit phase to +} + +function scheduleRetryEffect(workInProgress, retryQueue) { + var wakeables = retryQueue; + + if (wakeables !== null) { + // Schedule an effect to attach a retry listener to the promise. + // TODO: Move to passive phase + workInProgress.flags |= Update; + } else { + // This boundary suspended, but no wakeables were added to the retry + // queue. Check if the renderer suspended commit. If so, this means + // that once the fallback is committed, we can immediately retry + // rendering again, because rendering wasn't actually blocked. Only + // the commit phase. + // TODO: Consider a model where we always schedule an immediate retry, even + // for normal Suspense. That way the retry can partially render up to the + // first thing that suspends. + if (workInProgress.flags & ScheduleRetry) { + var retryLane = // TODO: This check should probably be moved into claimNextRetryLane + // I also suspect that we need some further consolidation of offscreen + // and retry lanes. + workInProgress.tag !== OffscreenComponent + ? claimNextRetryLane() + : OffscreenLane; + workInProgress.lanes = mergeLanes(workInProgress.lanes, retryLane); } } } -function popProvider(context, providerFiber) { - var currentValue = valueCursor.current; +function updateHostText(current, workInProgress, oldText, newText) { { - if (currentValue === REACT_SERVER_CONTEXT_DEFAULT_VALUE_NOT_LOADED) { - context._currentValue2 = context._defaultValue; - } else { - context._currentValue2 = currentValue; - } + 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. - { - var currentRenderer2 = renderer2CursorDEV.current; - pop(renderer2CursorDEV, providerFiber); - context._currentRenderer2 = currentRenderer2; + markUpdate(workInProgress); + } else { + workInProgress.stateNode = current.stateNode; } } - - pop(valueCursor, providerFiber); } -function scheduleContextWorkOnParentPath(parent, renderLanes, propagationRoot) { - // Update the child lanes of all the ancestors, including the alternates. - var node = parent; - while (node !== null) { - var alternate = node.alternate; +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; - if (!isSubsetOfLanes(node.childLanes, renderLanes)) { - node.childLanes = mergeLanes(node.childLanes, renderLanes); + while (tailNode !== null) { + if (tailNode.alternate !== null) { + lastTailNode = tailNode; + } - if (alternate !== null) { - alternate.childLanes = mergeLanes(alternate.childLanes, renderLanes); + 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 if ( - alternate !== null && - !isSubsetOfLanes(alternate.childLanes, renderLanes) - ) { - alternate.childLanes = mergeLanes(alternate.childLanes, renderLanes); - } else; - if (node === propagationRoot) { break; } - node = node.return; - } + 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; - { - 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." - ); + 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; } } } -function propagateContextChange(workInProgress, context, renderLanes) { - { - propagateContextChange_eager(workInProgress, context, renderLanes); - } -} -function propagateContextChange_eager(workInProgress, context, renderLanes) { - var fiber = workInProgress.child; +function bubbleProperties(completedWork) { + var didBailout = + completedWork.alternate !== null && + completedWork.alternate.child === completedWork.child; + var newChildLanes = NoLanes; + var subtreeFlags = NoFlags$1; - if (fiber !== null) { - // Set the return pointer of the child to the work-in-progress fiber. - fiber.return = workInProgress; - } + 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 (fiber !== null) { - var nextFiber = void 0; // Visit this 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. + // $FlowFixMe[unsafe-addition] addition with possible null/undefined value - var list = fiber.dependencies; + actualDuration += child.actualDuration; // $FlowFixMe[unsafe-addition] addition with possible null/undefined value - if (list !== null) { - nextFiber = fiber.child; - var dependency = list.firstContext; + treeBaseDuration += child.treeBaseDuration; + child = child.sibling; + } - while (dependency !== null) { - // Check if the context matches. - if (dependency.context === context) { - // Match! Schedule an update on this fiber. - if (fiber.tag === ClassComponent) { - // Schedule a force update on the work-in-progress. - var lane = pickArbitraryLane(renderLanes); - var update = createUpdate(lane); - update.tag = ForceUpdate; // TODO: Because we don't have a work-in-progress, this will add the - // update to the current fiber, too, which means it will persist even if - // this render is thrown away. Since it's a race condition, not sure it's - // worth fixing. - // Inlined `enqueueUpdate` to remove interleaved update check + completedWork.actualDuration = actualDuration; + completedWork.treeBaseDuration = treeBaseDuration; + } else { + var _child = completedWork.child; - var updateQueue = fiber.updateQueue; + 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 (updateQueue === null); - else { - var sharedQueue = updateQueue.shared; - var pending = sharedQueue.pending; + _child.return = completedWork; + _child = _child.sibling; + } + } - if (pending === null) { - // This is the first update. Create a circular list. - update.next = update; - } else { - update.next = pending.next; - pending.next = update; - } + 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; - sharedQueue.pending = update; - } - } + 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. - fiber.lanes = mergeLanes(fiber.lanes, renderLanes); - var alternate = fiber.alternate; + subtreeFlags |= _child2.subtreeFlags & StaticMask; + subtreeFlags |= _child2.flags & StaticMask; // $FlowFixMe[unsafe-addition] addition with possible null/undefined value - if (alternate !== null) { - alternate.lanes = mergeLanes(alternate.lanes, renderLanes); - } + _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. - scheduleContextWorkOnParentPath( - fiber.return, - renderLanes, - workInProgress - ); // Mark the updated lanes on the list, too. + _child3.return = completedWork; + _child3 = _child3.sibling; + } + } - list.lanes = mergeLanes(list.lanes, renderLanes); // Since we already found a match, we can stop traversing the - // dependency list. + completedWork.subtreeFlags |= subtreeFlags; + } - break; - } + completedWork.childLanes = newChildLanes; + return didBailout; +} - 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; +function completeDehydratedSuspenseBoundary( + current, + workInProgress, + nextState +) { + var wasHydrated = popHydrationState(); - if (parentSuspense === null) { + 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( - "We just came from a parent so we must have had a parent. This is a bug in React." + "A dehydrated suspense component was completed without a hydrated node. " + + "This is probably a bug in React." ); } - parentSuspense.lanes = mergeLanes(parentSuspense.lanes, renderLanes); - var _alternate = parentSuspense.alternate; + prepareToHydrateHostSuspenseInstance(); + bubbleProperties(workInProgress); - 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 ((workInProgress.mode & ProfileMode) !== NoMode) { + var isTimedOutSuspense = nextState !== null; - scheduleContextWorkOnParentPath( - parentSuspense, - renderLanes, - workInProgress - ); - nextFiber = fiber.sibling; - } else { - // Traverse down. - nextFiber = fiber.child; - } + if (isTimedOutSuspense) { + // Don't count time spent in a timed out Suspense subtree as part of the base duration. + var primaryChildFragment = workInProgress.child; - if (nextFiber !== null) { - // Set the return pointer of the child to the work-in-progress fiber. - nextFiber.return = fiber; + if (primaryChildFragment !== null) { + // $FlowFixMe Flow doesn't support type casting in combination with the -= operator + workInProgress.treeBaseDuration -= + primaryChildFragment.treeBaseDuration; + } + } + } + } + + return false; } else { - // No child. Traverse to next sibling. - nextFiber = fiber; + if ((workInProgress.flags & DidCapture) === NoFlags$1) { + // This boundary did not suspend so it's now hydrated and unsuspended. + workInProgress.memoizedState = null; + } // If nothing suspended, we need to schedule an effect to mark this boundary + // as having hydrated so events know that they're free to be invoked. + // It's also a signal to replay events and the suspense callback. + // If something suspended, schedule an effect to attach retry listeners. + // So we might as well always mark this. - while (nextFiber !== null) { - if (nextFiber === workInProgress) { - // We're back to the root of this subtree. Exit. - nextFiber = null; - break; - } + workInProgress.flags |= Update; + bubbleProperties(workInProgress); - var sibling = nextFiber.sibling; + { + if ((workInProgress.mode & ProfileMode) !== NoMode) { + var _isTimedOutSuspense = nextState !== null; - if (sibling !== null) { - // Set the return pointer of the sibling to the work-in-progress fiber. - sibling.return = nextFiber.return; - nextFiber = sibling; - break; - } // No more siblings. Traverse up. + if (_isTimedOutSuspense) { + // Don't count time spent in a timed out Suspense subtree as part of the base duration. + var _primaryChildFragment = workInProgress.child; - nextFiber = nextFiber.return; + if (_primaryChildFragment !== null) { + // $FlowFixMe Flow doesn't support type casting in combination with the -= operator + workInProgress.treeBaseDuration -= + _primaryChildFragment.treeBaseDuration; + } + } + } } + + 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 - fiber = nextFiber; + return true; } } -function prepareToReadContext(workInProgress, renderLanes) { - currentlyRenderingFiber = workInProgress; - lastContextDependency = null; - lastFullyObservedContext = null; - var dependencies = workInProgress.dependencies; - if (dependencies !== null) { - { - var firstContext = dependencies.firstContext; +function completeWork(current, workInProgress, renderLanes) { + var newProps = workInProgress.pendingProps; // Note: This intentionally doesn't check if we're hydrating because comparing - 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 + 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; - dependencies.firstContext = null; + case ClassComponent: { + var Component = workInProgress.type; + + if (isContextProvider(Component)) { + popContext(workInProgress); } + + bubbleProperties(workInProgress); + return 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; + case HostRoot: { + var fiberRoot = workInProgress.stateNode; + popHostContainer(workInProgress); + popTopLevelContextObject(workInProgress); + resetWorkInProgressVersions(); - if (lastFullyObservedContext === context); - else { - var contextItem = { - context: context, - memoizedValue: value, - next: null - }; + if (fiberRoot.pendingContext) { + fiberRoot.context = fiberRoot.pendingContext; + fiberRoot.pendingContext = 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. + 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(); - lastContextDependency = contextItem; - currentlyRenderingFiber.dependencies = { - lanes: NoLanes, - firstContext: contextItem - }; - } else { - // Append a new context item. - lastContextDependency = lastContextDependency.next = contextItem; - } - } + 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; - return value; -} + if ( + // Check if this is a client root + !prevState.isDehydrated || // Check if we reverted to client rendering (e.g. due to an error) + (workInProgress.flags & ForceClientRender) !== NoFlags$1 + ) { + // Schedule an effect to clear this container at the start of the + // next commit. This handles the case of React rendering into a + // container with previous children. It's also safe to do for + // updates too, because current.child would only be null if the + // previous render was null (so the container would already + // be empty). + workInProgress.flags |= Snapshot; // If this was a forced client render, there may have been + // recoverable errors during first hydration attempt. If so, add + // them to a queue so we can log them in the commit phase. -var ReactCurrentBatchConfig$1 = ReactSharedInternals.ReactCurrentBatchConfig; -var NoTransition = null; -function requestCurrentTransition() { - return ReactCurrentBatchConfig$1.transition; -} // When retrying a Suspense/Offscreen boundary, we restore the cache that was -function getSuspendedCache() { - { - return null; - } // This function is called when a Suspense boundary suspends. It returns the -} + upgradeHydrationErrorsToRecoverable(); + } + } + } + } -function markUpdate(workInProgress) { - // Tag the fiber with an update effect. This turns a Placement into - // a PlacementAndUpdate. - workInProgress.flags |= Update; -} + updateHostContainer(current, workInProgress); + bubbleProperties(workInProgress); -function markRef(workInProgress) { - workInProgress.flags |= Ref | RefStatic; -} + return null; + } -function hadNoMutationsEffects(current, completedWork) { - var didBailout = current !== null && current.child === completedWork.child; + case HostHoistable: + // eslint-disable-next-line-no-fallthrough - if (didBailout) { - return true; - } + case HostSingleton: + // eslint-disable-next-line-no-fallthrough - if ((completedWork.flags & ChildDeletion) !== NoFlags$1) { - return false; - } // TODO: If we move the `hadNoMutationsEffects` call after `bubbleProperties` - // then we only have to check the `completedWork.subtreeFlags`. + case HostComponent: { + popHostContext(workInProgress); + var _type = workInProgress.type; - var child = completedWork.child; + if (current !== null && workInProgress.stateNode != null) { + updateHostComponent(current, workInProgress, _type, newProps); - while (child !== null) { - if ( - (child.flags & MutationMask) !== NoFlags$1 || - (child.subtreeFlags & MutationMask) !== NoFlags$1 - ) { - return false; - } + if (current.ref !== workInProgress.ref) { + markRef(workInProgress); + } + } else { + if (!newProps) { + if (workInProgress.stateNode === null) { + throw new Error( + "We must have new props for new mounts. This error is likely " + + "caused by a bug in React. Please file an issue." + ); + } // This can happen when we abort work. - child = child.sibling; - } + bubbleProperties(workInProgress); + return null; + } - return true; -} + var _currentHostContext2 = 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. -function appendAllChildren( - parent, - workInProgress, - needsVisibilityToggle, - isHidden -) { - { - // We only have the top Fiber that was created but we need recurse down its - // children to find all the terminal nodes. - var _node = workInProgress.child; + var _wasHydrated2 = popHydrationState(); - while (_node !== null) { - // eslint-disable-next-line no-labels - if (_node.tag === HostComponent) { - var instance = _node.stateNode; + if (_wasHydrated2) { + // 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 _rootContainerInstance = getRootHostContainer(); - if (needsVisibilityToggle && isHidden) { - instance = cloneHiddenInstance(instance); + var _instance3 = createInstance( + _type, + newProps, + _rootContainerInstance, + _currentHostContext2, + workInProgress + ); + + appendAllChildren(_instance3, workInProgress, false, false); + workInProgress.stateNode = _instance3; // Certain renderers require commit-time effects for initial mount. } - appendInitialChild(parent, instance); - } else if (_node.tag === HostText) { - var _instance = _node.stateNode; + suspendHostCommitIfNeeded(workInProgress); - if (needsVisibilityToggle && isHidden) { - _instance = cloneHiddenTextInstance(); + if (workInProgress.ref !== null) { + // If there is a ref on a host node we need to schedule a callback + markRef(workInProgress); } + } - 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; + bubbleProperties(workInProgress); + return null; + } - if (child !== null) { - child.return = _node; + case HostText: { + var newText = newProps; + + if (current && workInProgress.stateNode != null) { + var oldText = current.memoizedProps; // If we have an alternate, that means this is an update and we need + // to schedule a side-effect to do the updates. + + updateHostText(current, workInProgress, oldText, newText); + } else { + if (typeof newText !== "string") { + if (workInProgress.stateNode === null) { + throw new Error( + "We must have new props for new mounts. This error is likely " + + "caused by a bug in React. Please file an issue." + ); + } // This can happen when we abort work. } - appendAllChildren(parent, _node, true, true); - } else if (_node.child !== null) { - _node.child.return = _node; - _node = _node.child; - continue; - } + var _rootContainerInstance2 = getRootHostContainer(); - _node = _node; + var _currentHostContext3 = getHostContext(); - if (_node === workInProgress) { - return; - } // $FlowFixMe[incompatible-use] found when upgrading Flow + var _wasHydrated3 = popHydrationState(); - while (_node.sibling === null) { - // $FlowFixMe[incompatible-use] found when upgrading Flow - if (_node.return === null || _node.return === workInProgress) { - return; + if (_wasHydrated3) { + if (prepareToHydrateHostTextInstance()) { + markUpdate(workInProgress); + } + } else { + workInProgress.stateNode = createTextInstance( + newText, + _rootContainerInstance2, + _currentHostContext3, + workInProgress + ); } + } - _node = _node.return; - } // $FlowFixMe[incompatible-use] found when upgrading Flow - - _node.sibling.return = _node.return; - _node = _node.sibling; + bubbleProperties(workInProgress); + return null; } - } -} // An unfortunate fork of appendAllChildren because we have two different parent types. -function appendAllChildrenToContainer( - 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; + case SuspenseComponent: { + popSuspenseHandler(workInProgress); + var nextState = workInProgress.memoizedState; // Special path for dehydrated boundaries. We may eventually move this + // to its own fiber type so that we can add other kinds of hydration + // boundaries that aren't associated with a Suspense tree. In anticipation + // of such a refactor, all the hydration logic is contained in + // this branch. - while (node !== null) { - // eslint-disable-next-line no-labels - if (node.tag === HostComponent) { - var instance = node.stateNode; + if ( + current === null || + (current.memoizedState !== null && + current.memoizedState.dehydrated !== null) + ) { + var fallthroughToNormalSuspensePath = + completeDehydratedSuspenseBoundary( + current, + workInProgress, + nextState + ); - if (needsVisibilityToggle && isHidden) { - instance = cloneHiddenInstance(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; + } + } // Continue with the normal Suspense path. + } - appendChildToContainerChildSet(containerChildSet, instance); - } else if (node.tag === HostText) { - var _instance2 = node.stateNode; + if ((workInProgress.flags & DidCapture) !== NoFlags$1) { + // Something suspended. Re-render with the fallback children. + workInProgress.lanes = renderLanes; // Do not reset the effect list. - if (needsVisibilityToggle && isHidden) { - _instance2 = cloneHiddenTextInstance(); + if ((workInProgress.mode & ProfileMode) !== NoMode) { + transferActualDuration(workInProgress); + } // Don't bubble properties in this case. + + return workInProgress; + } + + 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; } + } - 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; + var retryQueue = workInProgress.updateQueue; + scheduleRetryEffect(workInProgress, retryQueue); - if (child !== null) { - child.return = node; - } // If Offscreen is not in manual mode, detached tree is hidden from user space. + bubbleProperties(workInProgress); - var _needsVisibilityToggle = !isOffscreenManual(node); + { + 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; - appendAllChildrenToContainer( - containerChildSet, - node, - _needsVisibilityToggle, - true - ); - } else if (node.child !== null) { - node.child.return = node; - node = node.child; - continue; + if (primaryChildFragment !== null) { + // $FlowFixMe Flow doesn't support type casting in combination with the -= operator + workInProgress.treeBaseDuration -= + primaryChildFragment.treeBaseDuration; + } + } + } } - node = node; + return null; + } - if (node === workInProgress) { - return; - } // $FlowFixMe[incompatible-use] found when upgrading Flow + case HostPortal: + popHostContainer(workInProgress); + updateHostContainer(current, workInProgress); - while (node.sibling === null) { - // $FlowFixMe[incompatible-use] found when upgrading Flow - if (node.return === null || node.return === workInProgress) { - return; - } + bubbleProperties(workInProgress); + return null; - node = node.return; - } // $FlowFixMe[incompatible-use] found when upgrading Flow + case ContextProvider: + // Pop provider fiber + var context = workInProgress.type._context; + popProvider(context, workInProgress); + bubbleProperties(workInProgress); + return null; - node.sibling.return = node.return; - node = node.sibling; + case IncompleteClassComponent: { + // Same as class component case. I put it down here so that the tags are + // sequential to ensure this switch is compiled to a jump table. + var _Component = workInProgress.type; + + if (isContextProvider(_Component)) { + popContext(workInProgress); + } + + bubbleProperties(workInProgress); + return null; } - } -} -function updateHostContainer(current, workInProgress) { - { - var portalOrRoot = workInProgress.stateNode; - var childrenUnchanged = hadNoMutationsEffects(current, workInProgress); + case SuspenseListComponent: { + popSuspenseListContext(workInProgress); + var renderState = workInProgress.memoizedState; - 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. + if (renderState === null) { + // We're running in the default, "independent" mode. + // We don't do anything in this mode. + bubbleProperties(workInProgress); + return null; + } - appendAllChildrenToContainer(newChildSet, workInProgress, false, false); - portalOrRoot.pendingChildren = newChildSet; // Schedule an update on the container to swap out the container. + var didSuspendAlready = (workInProgress.flags & DidCapture) !== NoFlags$1; + var renderedTail = renderState.rendering; - markUpdate(workInProgress); - finalizeContainerChildren(container, newChildSet); - } - } -} + if (renderedTail === null) { + // We just rendered the head. + if (!didSuspendAlready) { + // This is the first pass. We need to figure out if anything is still + // suspended in the rendered set. + // If new content unsuspended, but there's still some content that + // didn't. Then we need to do a second pass that forces everything + // to keep showing their fallbacks. + // We might be suspended if something in this render pass suspended, or + // something in the previous committed pass suspended. Otherwise, + // there's no chance so we can skip the expensive call to + // findFirstSuspended. + var cannotBeSuspended = + renderHasNotSuspendedYet() && + (current === null || (current.flags & DidCapture) === NoFlags$1); -function updateHostComponent(current, workInProgress, type, newProps) { - { - 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. + if (!cannotBeSuspended) { + var row = workInProgress.child; - var childrenUnchanged = hadNoMutationsEffects(current, workInProgress); + while (row !== null) { + var suspended = findFirstSuspended(row); - if (childrenUnchanged && _oldProps === newProps) { - // No changes, just reuse the existing instance. - // Note that this might release a previous clone. - workInProgress.stateNode = currentInstance; - return; - } + 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 recyclableInstance = workInProgress.stateNode; + var _retryQueue = suspended.updateQueue; + workInProgress.updateQueue = _retryQueue; + scheduleRetryEffect(workInProgress, _retryQueue); // Rerender the whole list, but this time, we'll force fallbacks + // to stay in place. + // Reset the effect flags before doing the second pass since that's now invalid. + // Reset the child fibers to their original state. - getHostContext(); + workInProgress.subtreeFlags = NoFlags$1; + resetChildFibers(workInProgress, renderLanes); // Set up the Suspense List Context to force suspense and + // immediately rerender the children. - var _updatePayload = null; + pushSuspenseListContext( + workInProgress, + setShallowSuspenseListContext( + suspenseStackCursor.current, + ForceSuspenseFallback + ) + ); // Don't bubble properties in this case. - if (_oldProps !== newProps) { - _updatePayload = prepareUpdate( - recyclableInstance, - type, - _oldProps, - newProps - ); - } + return workInProgress.child; + } - if (childrenUnchanged && _updatePayload === null) { - // No changes, just reuse the existing instance. - // Note that this might release a previous clone. - workInProgress.stateNode = currentInstance; - return; - } + row = row.sibling; + } + } - var newInstance = cloneInstance( - currentInstance, - _updatePayload, - type, - _oldProps, - newProps, - workInProgress, - childrenUnchanged - ); + if (renderState.tail !== null && now$1() > getRenderTargetTime()) { + // We have already passed our CPU deadline but we still have rows + // left in the tail. We'll just give up further attempts to render + // the main content and only render fallbacks. + workInProgress.flags |= DidCapture; + didSuspendAlready = true; + cutOffTailIfNeeded(renderState, false); // Since nothing actually suspended, there will nothing to ping this + // to get it started back up to attempt the next item. While in terms + // of priority this work has the same priority as this current render, + // it's not part of the same transition once the transition has + // committed. If it's sync, we still want to yield so that it can be + // painted. Conceptually, this is really the same as pinging. + // We can use any RetryLane even if it's the one currently rendering + // since we're leaving it behind on this node. - workInProgress.stateNode = newInstance; + 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 (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); - } - } -} + if (_suspended !== null) { + workInProgress.flags |= DidCapture; + didSuspendAlready = true; // Ensure we transfer the update queue to the parent so that it doesn't + // get lost if this row ends up dropped during a second pass. + + var _retryQueue2 = _suspended.updateQueue; + workInProgress.updateQueue = _retryQueue2; + scheduleRetryEffect(workInProgress, _retryQueue2); + cutOffTailIfNeeded(renderState, true); // This might have been modified. + + if ( + renderState.tail === null && + renderState.tailMode === "hidden" && + !renderedTail.alternate && + !getIsHydrating() // We don't cut it if we're hydrating. + ) { + // We're done. + bubbleProperties(workInProgress); + return null; + } + } else if ( + // The time it took to render last row is greater than the remaining + // time we have to render. So rendering one more row would likely + // exceed it. + now$1() * 2 - renderState.renderingStartTime > + getRenderTargetTime() && + renderLanes !== OffscreenLane + ) { + // We have now passed our CPU deadline and we'll just give up further + // attempts to render the main content and only render fallbacks. + // The assumption is that this is usually faster. + workInProgress.flags |= DidCapture; + didSuspendAlready = true; + cutOffTailIfNeeded(renderState, false); // Since nothing actually suspended, there will nothing to ping this + // to get it started back up to attempt the next item. While in terms + // of priority this work has the same priority as this current render, + // it's not part of the same transition once the transition has + // committed. If it's sync, we still want to yield so that it can be + // painted. Conceptually, this is really the same as pinging. + // We can use any RetryLane even if it's the one currently rendering + // since we're leaving it behind on this node. -function updateHostText(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. + workInProgress.lanes = SomeRetryLane; + } + } - markUpdate(workInProgress); - } else { - workInProgress.stateNode = current.stateNode; - } - } -} + 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; -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; + if (previousSibling !== null) { + previousSibling.sibling = renderedTail; + } else { + workInProgress.child = renderedTail; + } - while (tailNode !== null) { - if (tailNode.alternate !== null) { - lastTailNode = tailNode; + renderState.last = renderedTail; } - - 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; - } + if (renderState.tail !== null) { + // We still have tail rows to render. + // Pop a row. + var next = renderState.tail; + renderState.rendering = next; + renderState.tail = next.sibling; + renderState.renderingStartTime = now$1(); + next.sibling = null; // Restore the context. + // TODO: We can probably just avoid popping it instead and only + // setting it the first time we go from not suspended to suspended. - case "collapsed": { - // Any insertions at the end of the tail list after this point - // should be invisible. If there are already mounted boundaries - // anything before them are not considered for collapsing. - // Therefore we need to go through the whole tail to find if - // there are any. - var _tailNode = renderState.tail; - var _lastTailNode = null; + var suspenseContext = suspenseStackCursor.current; - while (_tailNode !== null) { - if (_tailNode.alternate !== null) { - _lastTailNode = _tailNode; + if (didSuspendAlready) { + suspenseContext = setShallowSuspenseListContext( + suspenseContext, + ForceSuspenseFallback + ); + } else { + suspenseContext = + setDefaultShallowSuspenseListContext(suspenseContext); } - _tailNode = _tailNode.sibling; - } // Next we're simply going to delete all insertions after the - // last rendered item. + pushSuspenseListContext(workInProgress, suspenseContext); // Do a pass over the next row. + // Don't bubble properties in this case. - 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; + return next; } + bubbleProperties(workInProgress); + return null; + } + + case ScopeComponent: { break; } - } -} -function bubbleProperties(completedWork) { - var didBailout = - completedWork.alternate !== null && - completedWork.alternate.child === completedWork.child; - var newChildLanes = NoLanes; - var subtreeFlags = NoFlags$1; + case OffscreenComponent: + case LegacyHiddenComponent: { + popSuspenseHandler(workInProgress); + popHiddenContext(workInProgress); + var _nextState = workInProgress.memoizedState; + var nextIsHidden = _nextState !== null; // Schedule a Visibility effect if the visibility has changed - if (!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 (workInProgress.tag === LegacyHiddenComponent); + else { + if (current !== null) { + var _prevState = current.memoizedState; + var prevIsHidden = _prevState !== null; - while (child !== null) { - newChildLanes = mergeLanes( - newChildLanes, - mergeLanes(child.lanes, child.childLanes) - ); - subtreeFlags |= child.subtreeFlags; - subtreeFlags |= child.flags; // When a fiber is cloned, its actualDuration is reset to 0. This value will - // only be updated if work is done on the fiber (i.e. it doesn't bailout). - // When work is done, it should bubble to the parent's actualDuration. If - // the fiber has not been cloned though, (meaning no work was done), then - // this value will reflect the amount of time spent working on a previous - // render. In that case it should not bubble. We determine whether it was - // cloned by comparing the child pointer. - // $FlowFixMe[unsafe-addition] addition with possible null/undefined value + if (prevIsHidden !== nextIsHidden) { + workInProgress.flags |= Visibility; + } + } else { + // On initial mount, we only need a Visibility effect if the tree + // is hidden. + if (nextIsHidden) { + workInProgress.flags |= Visibility; + } + } + } - actualDuration += child.actualDuration; // $FlowFixMe[unsafe-addition] addition with possible null/undefined value + if (!nextIsHidden || (workInProgress.mode & ConcurrentMode) === NoMode) { + bubbleProperties(workInProgress); + } else { + // Don't bubble properties for hidden children unless we're rendering + // at offscreen priority. + if ( + includesSomeLane(renderLanes, OffscreenLane) && // Also don't bubble if the tree suspended + (workInProgress.flags & DidCapture) === NoLanes + ) { + bubbleProperties(workInProgress); // Check if there was an insertion or update in the hidden subtree. + // If so, we need to hide those nodes in the commit phase, so + // schedule a visibility effect. - treeBaseDuration += child.treeBaseDuration; - child = child.sibling; + if ( + workInProgress.tag !== LegacyHiddenComponent && + workInProgress.subtreeFlags & (Placement | Update) + ) { + workInProgress.flags |= Visibility; + } + } } - 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. + var offscreenQueue = workInProgress.updateQueue; - _child.return = completedWork; - _child = _child.sibling; + if (offscreenQueue !== null) { + var _retryQueue3 = offscreenQueue.retryQueue; + scheduleRetryEffect(workInProgress, _retryQueue3); } + return null; } - 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; + case CacheComponent: { + return null; + } - while (_child2 !== null) { - newChildLanes = mergeLanes( - newChildLanes, - mergeLanes(_child2.lanes, _child2.childLanes) - ); // "Static" flags share the lifetime of the fiber/hook they belong to, - // so we should bubble those up even during a bailout. All the other - // flags have a lifetime only of a single render + commit, so we should - // ignore them. + case TracingMarkerComponent: { + return null; + } + } - subtreeFlags |= _child2.subtreeFlags & StaticMask; - subtreeFlags |= _child2.flags & StaticMask; // $FlowFixMe[unsafe-addition] addition with possible null/undefined value + throw new Error( + "Unknown unit of work tag (" + + workInProgress.tag + + "). This error is likely caused by a bug in " + + "React. Please file an issue." + ); +} - _treeBaseDuration += _child2.treeBaseDuration; - _child2 = _child2.sibling; +function unwindWork(current, workInProgress, renderLanes) { + switch (workInProgress.tag) { + case ClassComponent: { + var Component = workInProgress.type; + + if (isContextProvider(Component)) { + popContext(workInProgress); } - completedWork.treeBaseDuration = _treeBaseDuration; - } else { - var _child3 = completedWork.child; + var flags = workInProgress.flags; - 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 (flags & ShouldCapture) { + workInProgress.flags = (flags & ~ShouldCapture) | DidCapture; - 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 ((workInProgress.mode & ProfileMode) !== NoMode) { + transferActualDuration(workInProgress); + } - _child3.return = completedWork; - _child3 = _child3.sibling; + return workInProgress; } + + return null; } - completedWork.subtreeFlags |= subtreeFlags; - } + case HostRoot: { + popHostContainer(workInProgress); + popTopLevelContextObject(workInProgress); + resetWorkInProgressVersions(); + var _flags = workInProgress.flags; - completedWork.childLanes = newChildLanes; - return didBailout; -} + if ( + (_flags & ShouldCapture) !== NoFlags$1 && + (_flags & DidCapture) === NoFlags$1 + ) { + // There was an error during render that wasn't captured by a suspense + // boundary. Do a second pass on the root to unmount the children. + workInProgress.flags = (_flags & ~ShouldCapture) | DidCapture; + return workInProgress; + } // We unwound to the root without completing it. Exit. -function completeDehydratedSuspenseBoundary( - current, - workInProgress, - nextState -) { - var wasHydrated = popHydrationState(); + return null; + } - 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." - ); - } + case HostHoistable: + case HostSingleton: + case HostComponent: { + // TODO: popHydrationState + popHostContext(workInProgress); + return null; + } - prepareToHydrateHostSuspenseInstance(); - bubbleProperties(workInProgress); + case SuspenseComponent: { + popSuspenseHandler(workInProgress); + var suspenseState = workInProgress.memoizedState; - { - if ((workInProgress.mode & ProfileMode) !== NoMode) { - var isTimedOutSuspense = nextState !== null; + if (suspenseState !== null && suspenseState.dehydrated !== null) { + if (workInProgress.alternate === null) { + throw new Error( + "Threw in newly mounted dehydrated component. This is likely a bug in " + + "React. Please file an issue." + ); + } + } - if (isTimedOutSuspense) { - // Don't count time spent in a timed out Suspense subtree as part of the base duration. - var primaryChildFragment = workInProgress.child; + var _flags2 = workInProgress.flags; - if (primaryChildFragment !== null) { - // $FlowFixMe Flow doesn't support type casting in combination with the -= operator - workInProgress.treeBaseDuration -= - primaryChildFragment.treeBaseDuration; - } - } + if (_flags2 & ShouldCapture) { + workInProgress.flags = (_flags2 & ~ShouldCapture) | DidCapture; // Captured a suspense effect. Re-render the boundary. + + if ((workInProgress.mode & ProfileMode) !== NoMode) { + transferActualDuration(workInProgress); } + + return workInProgress; } - return false; - } else { - if ((workInProgress.flags & DidCapture) === NoFlags$1) { - // This boundary did not suspend so it's now hydrated and unsuspended. - workInProgress.memoizedState = null; - } // If nothing suspended, we need to schedule an effect to mark this boundary - // as having hydrated so events know that they're free to be invoked. - // It's also a signal to replay events and the suspense callback. - // If something suspended, schedule an effect to attach retry listeners. - // So we might as well always mark this. + return null; + } - workInProgress.flags |= Update; - bubbleProperties(workInProgress); + case SuspenseListComponent: { + popSuspenseListContext(workInProgress); // SuspenseList doesn't actually catch anything. It should've been + // caught by a nested boundary. If not, it should bubble through. - { - if ((workInProgress.mode & ProfileMode) !== NoMode) { - var _isTimedOutSuspense = nextState !== null; + return null; + } - if (_isTimedOutSuspense) { - // Don't count time spent in a timed out Suspense subtree as part of the base duration. - var _primaryChildFragment = workInProgress.child; + case HostPortal: + popHostContainer(workInProgress); + return null; - if (_primaryChildFragment !== null) { - // $FlowFixMe Flow doesn't support type casting in combination with the -= operator - workInProgress.treeBaseDuration -= - _primaryChildFragment.treeBaseDuration; - } - } + case ContextProvider: + var context = workInProgress.type._context; + popProvider(context, workInProgress); + return null; + + case OffscreenComponent: + case LegacyHiddenComponent: { + popSuspenseHandler(workInProgress); + popHiddenContext(workInProgress); + var _flags3 = workInProgress.flags; + + if (_flags3 & ShouldCapture) { + workInProgress.flags = (_flags3 & ~ShouldCapture) | DidCapture; // Captured a suspense effect. Re-render the boundary. + + if ((workInProgress.mode & ProfileMode) !== NoMode) { + transferActualDuration(workInProgress); } + + return workInProgress; } - return false; + return null; } - } 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; - } -} + case CacheComponent: + return null; -function completeWork(current, workInProgress, renderLanes) { - var newProps = workInProgress.pendingProps; // Note: This intentionally doesn't check if we're hydrating because comparing + case TracingMarkerComponent: + return null; - 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); + default: return null; + } +} +function unwindInterruptedWork(current, interruptedWork, renderLanes) { + switch (interruptedWork.tag) { case ClassComponent: { - var Component = workInProgress.type; + var childContextTypes = interruptedWork.type.childContextTypes; - if (isContextProvider(Component)) { - popContext(workInProgress); + if (childContextTypes !== null && childContextTypes !== undefined) { + popContext(interruptedWork); } - bubbleProperties(workInProgress); - return null; + break; } case HostRoot: { - var fiberRoot = workInProgress.stateNode; - popHostContainer(workInProgress); - popTopLevelContextObject(workInProgress); + popHostContainer(interruptedWork); + popTopLevelContextObject(interruptedWork); resetWorkInProgressVersions(); + break; + } - if (fiberRoot.pendingContext) { - fiberRoot.context = fiberRoot.pendingContext; - fiberRoot.pendingContext = null; - } + case HostHoistable: + case HostSingleton: + case HostComponent: { + popHostContext(interruptedWork); + break; + } - 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(); + case HostPortal: + popHostContainer(interruptedWork); + break; - 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; + case SuspenseComponent: + popSuspenseHandler(interruptedWork); + break; - if ( - // Check if this is a client root - !prevState.isDehydrated || // Check if we reverted to client rendering (e.g. due to an error) - (workInProgress.flags & ForceClientRender) !== NoFlags$1 - ) { - // Schedule an effect to clear this container at the start of the - // next commit. This handles the case of React rendering into a - // container with previous children. It's also safe to do for - // updates too, because current.child would only be null if the - // previous render was null (so the container would already - // be empty). - workInProgress.flags |= Snapshot; // If this was a forced client render, there may have been - // recoverable errors during first hydration attempt. If so, add - // them to a queue so we can log them in the commit phase. + case SuspenseListComponent: + popSuspenseListContext(interruptedWork); + break; + + case ContextProvider: + var context = interruptedWork.type._context; + popProvider(context, interruptedWork); + break; + + case OffscreenComponent: + case LegacyHiddenComponent: + popSuspenseHandler(interruptedWork); + popHiddenContext(interruptedWork); + break; + } +} - upgradeHydrationErrorsToRecoverable(); - } - } - } - } +var didWarnAboutUndefinedSnapshotBeforeUpdate = null; - updateHostContainer(current, workInProgress); - bubbleProperties(workInProgress); +{ + didWarnAboutUndefinedSnapshotBeforeUpdate = new Set(); +} // Used during the commit phase to track the state of the Offscreen component stack. +// Allows us to avoid traversing the return path to find the nearest Offscreen ancestor. - return null; - } +var offscreenSubtreeIsHidden = false; +var offscreenSubtreeWasHidden = false; +var PossiblyWeakSet = typeof WeakSet === "function" ? WeakSet : Set; +var nextEffect = null; // Used for Profiling builds to track updaters. - case HostHoistable: - // eslint-disable-next-line-no-fallthrough +var inProgressLanes = null; +var inProgressRoot = null; - case HostSingleton: - // eslint-disable-next-line-no-fallthrough +function shouldProfile(current) { + return ( + (current.mode & ProfileMode) !== NoMode && + (getExecutionContext() & CommitContext) !== NoContext + ); +} - case HostComponent: { - popHostContext(workInProgress); - var _type = workInProgress.type; +function reportUncaughtErrorInDEV(error) { + // Wrapping each small part of the commit phase into a guarded + // callback is a bit too slow (https://github.com/facebook/react/pull/21666). + // But we rely on it to surface errors to DEV tools like overlays + // (https://github.com/facebook/react/issues/21712). + // As a compromise, rethrow only caught errors in a guard. + { + invokeGuardedCallback(null, function () { + throw error; + }); + clearCaughtError(); + } +} - if (current !== null && workInProgress.stateNode != null) { - updateHostComponent(current, workInProgress, _type, newProps); +function callComponentWillUnmountWithTimer(current, instance) { + instance.props = current.memoizedProps; + instance.state = current.memoizedState; - if (current.ref !== workInProgress.ref) { - markRef(workInProgress); - } - } else { - if (!newProps) { - if (workInProgress.stateNode === null) { - throw new Error( - "We must have new props for new mounts. This error is likely " + - "caused by a bug in React. Please file an issue." - ); - } // This can happen when we abort work. + if (shouldProfile(current)) { + try { + startLayoutEffectTimer(); + instance.componentWillUnmount(); + } finally { + recordLayoutEffectDuration(current); + } + } else { + instance.componentWillUnmount(); + } +} // Capture errors so they don't interrupt unmounting. - bubbleProperties(workInProgress); - return null; - } +function safelyCallComponentWillUnmount( + current, + nearestMountedAncestor, + instance +) { + try { + callComponentWillUnmountWithTimer(current, instance); + } catch (error) { + captureCommitPhaseError(current, nearestMountedAncestor, error); + } +} // Capture errors so they don't interrupt mounting. - var _currentHostContext2 = 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. +function safelyAttachRef(current, nearestMountedAncestor) { + try { + commitAttachRef(current); + } catch (error) { + captureCommitPhaseError(current, nearestMountedAncestor, error); + } +} - var _wasHydrated2 = popHydrationState(); +function safelyDetachRef(current, nearestMountedAncestor) { + var ref = current.ref; + var refCleanup = current.refCleanup; - if (_wasHydrated2) { - // 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); + if (ref !== null) { + if (typeof refCleanup === "function") { + try { + if (shouldProfile(current)) { + try { + startLayoutEffectTimer(); + refCleanup(); + } finally { + recordLayoutEffectDuration(current); } } else { - var _rootContainerInstance = getRootHostContainer(); - - var instance = createInstance( - _type, - newProps, - _rootContainerInstance, - _currentHostContext2, - workInProgress - ); - appendAllChildren(instance, workInProgress, false, false); - workInProgress.stateNode = instance; // Certain renderers require commit-time effects for initial mount. + refCleanup(); } + } catch (error) { + captureCommitPhaseError(current, nearestMountedAncestor, error); + } finally { + // `refCleanup` has been called. Nullify all references to it to prevent double invocation. + current.refCleanup = null; + var finishedWork = current.alternate; - if (workInProgress.ref !== null) { - // If there is a ref on a host node we need to schedule a callback - markRef(workInProgress); + if (finishedWork != null) { + finishedWork.refCleanup = null; } } + } else if (typeof ref === "function") { + var retVal; - bubbleProperties(workInProgress); - return null; - } - - case HostText: { - var newText = newProps; - - if (current && workInProgress.stateNode != null) { - var oldText = current.memoizedProps; // If we have an alternate, that means this is an update and we need - // to schedule a side-effect to do the updates. - - updateHostText(current, workInProgress, oldText, newText); - } else { - if (typeof newText !== "string") { - if (workInProgress.stateNode === null) { - throw new Error( - "We must have new props for new mounts. This error is likely " + - "caused by a bug in React. Please file an issue." - ); - } // This can happen when we abort work. - } - - var _rootContainerInstance2 = getRootHostContainer(); - - var _currentHostContext3 = getHostContext(); - - var _wasHydrated3 = popHydrationState(); - - if (_wasHydrated3) { - if (prepareToHydrateHostTextInstance()) { - markUpdate(workInProgress); + try { + if (shouldProfile(current)) { + try { + startLayoutEffectTimer(); + retVal = ref(null); + } finally { + recordLayoutEffectDuration(current); } } else { - workInProgress.stateNode = createTextInstance( - newText, - _rootContainerInstance2, - _currentHostContext3, - workInProgress - ); + retVal = ref(null); } + } catch (error) { + captureCommitPhaseError(current, nearestMountedAncestor, error); } - bubbleProperties(workInProgress); - return null; + { + if (typeof retVal === "function") { + error( + "Unexpected return value from a callback ref in %s. " + + "A callback ref should not return a function.", + getComponentNameFromFiber(current) + ); + } + } + } else { + // $FlowFixMe unable to narrow type to RefObject + ref.current = null; } + } +} - case SuspenseComponent: { - popSuspenseHandler(workInProgress); - var nextState = workInProgress.memoizedState; // Special path for dehydrated boundaries. We may eventually move this - // to its own fiber type so that we can add other kinds of hydration - // boundaries that aren't associated with a Suspense tree. In anticipation - // of such a refactor, all the hydration logic is contained in - // this branch. - - if ( - current === null || - (current.memoizedState !== null && - current.memoizedState.dehydrated !== null) - ) { - var fallthroughToNormalSuspensePath = - completeDehydratedSuspenseBoundary( - current, - workInProgress, - nextState - ); +function safelyCallDestroy(current, nearestMountedAncestor, destroy) { + try { + destroy(); + } catch (error) { + captureCommitPhaseError(current, nearestMountedAncestor, error); + } +} +var shouldFireAfterActiveInstanceBlur = false; +function commitBeforeMutationEffects(root, firstChild) { + nextEffect = firstChild; + commitBeforeMutationEffects_begin(); // We no longer need to track the active instance fiber - 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. - } + var shouldFire = shouldFireAfterActiveInstanceBlur; + shouldFireAfterActiveInstanceBlur = false; + return shouldFire; +} - if ((workInProgress.flags & DidCapture) !== NoFlags$1) { - // Something suspended. Re-render with the fallback children. - workInProgress.lanes = renderLanes; // Do not reset the effect list. +function commitBeforeMutationEffects_begin() { + while (nextEffect !== null) { + var fiber = nextEffect; // This phase is only used for beforeActiveInstanceBlur. - if ((workInProgress.mode & ProfileMode) !== NoMode) { - transferActualDuration(workInProgress); - } // Don't bubble properties in this case. + var child = fiber.child; - return workInProgress; - } + if ( + (fiber.subtreeFlags & BeforeMutationMask) !== NoFlags$1 && + child !== null + ) { + child.return = fiber; + nextEffect = child; + } else { + commitBeforeMutationEffects_complete(); + } + } +} - var nextDidTimeout = nextState !== null; - var prevDidTimeout = current !== null && current.memoizedState !== null; - // a passive effect, which is when we process the transitions +function commitBeforeMutationEffects_complete() { + while (nextEffect !== null) { + var fiber = nextEffect; + setCurrentFiber(fiber); - 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. + try { + commitBeforeMutationEffectsOnFiber(fiber); + } catch (error) { + captureCommitPhaseError(fiber, fiber.return, error); + } - if (nextDidTimeout) { - var _offscreenFiber2 = workInProgress.child; - _offscreenFiber2.flags |= Visibility; - } - } + resetCurrentFiber(); + var sibling = fiber.sibling; - var wakeables = workInProgress.updateQueue; + if (sibling !== null) { + sibling.return = fiber.return; + nextEffect = sibling; + return; + } - if (wakeables !== null) { - // Schedule an effect to attach a retry listener to the promise. - // TODO: Move to passive phase - workInProgress.flags |= Update; - } + nextEffect = fiber.return; + } +} - bubbleProperties(workInProgress); +function commitBeforeMutationEffectsOnFiber(finishedWork) { + var current = finishedWork.alternate; + var flags = finishedWork.flags; - { - if ((workInProgress.mode & ProfileMode) !== NoMode) { - if (nextDidTimeout) { - // Don't count time spent in a timed out Suspense subtree as part of the base duration. - var primaryChildFragment = workInProgress.child; + if ((flags & Snapshot) !== NoFlags$1) { + setCurrentFiber(finishedWork); + } - if (primaryChildFragment !== null) { - // $FlowFixMe Flow doesn't support type casting in combination with the -= operator - workInProgress.treeBaseDuration -= - primaryChildFragment.treeBaseDuration; - } - } - } - } + switch (finishedWork.tag) { + case FunctionComponent: { + break; + } - return null; + case ForwardRef: + case SimpleMemoComponent: { + break; } - case HostPortal: - popHostContainer(workInProgress); - updateHostContainer(current, workInProgress); + case ClassComponent: { + if ((flags & Snapshot) !== NoFlags$1) { + if (current !== null) { + var prevProps = current.memoizedProps; + var prevState = current.memoizedState; + var instance = finishedWork.stateNode; // We could update instance props and state here, + // but instead we rely on them being set during last render. + // TODO: revisit this when we implement resuming. - bubbleProperties(workInProgress); - return null; + { + if ( + finishedWork.type === finishedWork.elementType && + !didWarnAboutReassigningProps + ) { + if (instance.props !== finishedWork.memoizedProps) { + error( + "Expected %s props to match memoized props before " + + "getSnapshotBeforeUpdate. " + + "This might either be because of a bug in React, or because " + + "a component reassigns its own `this.props`. " + + "Please file an issue.", + getComponentNameFromFiber(finishedWork) || "instance" + ); + } - case ContextProvider: - // Pop provider fiber - var context = workInProgress.type._context; - popProvider(context, workInProgress); - bubbleProperties(workInProgress); - return null; + 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" + ); + } + } + } - 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; + var snapshot = instance.getSnapshotBeforeUpdate( + finishedWork.elementType === finishedWork.type + ? prevProps + : resolveDefaultProps(finishedWork.type, prevProps), + prevState + ); - if (isContextProvider(_Component)) { - popContext(workInProgress); - } + { + var didWarnSet = didWarnAboutUndefinedSnapshotBeforeUpdate; - bubbleProperties(workInProgress); - return null; - } + if (snapshot === undefined && !didWarnSet.has(finishedWork.type)) { + didWarnSet.add(finishedWork.type); - case SuspenseListComponent: { - popSuspenseListContext(workInProgress); - var renderState = workInProgress.memoizedState; + error( + "%s.getSnapshotBeforeUpdate(): A snapshot value (or null) " + + "must be returned. You have returned undefined.", + getComponentNameFromFiber(finishedWork) + ); + } + } - if (renderState === null) { - // We're running in the default, "independent" mode. - // We don't do anything in this mode. - bubbleProperties(workInProgress); - return null; + instance.__reactInternalSnapshotBeforeUpdate = snapshot; + } } - var didSuspendAlready = (workInProgress.flags & DidCapture) !== NoFlags$1; - var renderedTail = renderState.rendering; - - if (renderedTail === null) { - // We just rendered the head. - if (!didSuspendAlready) { - // This is the first pass. We need to figure out if anything is still - // suspended in the rendered set. - // If new content unsuspended, but there's still some content that - // didn't. Then we need to do a second pass that forces everything - // to keep showing their fallbacks. - // We might be suspended if something in this render pass suspended, or - // something in the previous committed pass suspended. Otherwise, - // there's no chance so we can skip the expensive call to - // findFirstSuspended. - var cannotBeSuspended = - renderHasNotSuspendedYet() && - (current === null || (current.flags & DidCapture) === NoFlags$1); - - if (!cannotBeSuspended) { - var row = workInProgress.child; + break; + } - while (row !== null) { - var suspended = findFirstSuspended(row); + case HostRoot: { + break; + } - 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. + case HostComponent: + case HostHoistable: + case HostSingleton: + case HostText: + case HostPortal: + case IncompleteClassComponent: + // Nothing to do for these component types + break; - var newThenables = suspended.updateQueue; + default: { + if ((flags & Snapshot) !== NoFlags$1) { + throw new Error( + "This unit of work tag should not have side-effects. This error is " + + "likely caused by a bug in React. Please file an issue." + ); + } + } + } - 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. + if ((flags & Snapshot) !== NoFlags$1) { + resetCurrentFiber(); + } +} - workInProgress.subtreeFlags = NoFlags$1; - resetChildFibers(workInProgress, renderLanes); // Set up the Suspense List Context to force suspense and - // immediately rerender the children. +function commitHookEffectListUnmount( + flags, + finishedWork, + nearestMountedAncestor +) { + var updateQueue = finishedWork.updateQueue; + var lastEffect = updateQueue !== null ? updateQueue.lastEffect : null; - pushSuspenseListContext( - workInProgress, - setShallowSuspenseListContext( - suspenseStackCursor.current, - ForceSuspenseFallback - ) - ); // Don't bubble properties in this case. + if (lastEffect !== null) { + var firstEffect = lastEffect.next; + var effect = firstEffect; - return workInProgress.child; - } + do { + if ((effect.tag & flags) === flags) { + // Unmount + var destroy = effect.destroy; + effect.destroy = undefined; - row = row.sibling; + if (destroy !== undefined) { + { + if ((flags & Passive) !== NoFlags) { + markComponentPassiveEffectUnmountStarted(finishedWork); + } else if ((flags & Layout) !== NoFlags) { + markComponentLayoutEffectUnmountStarted(finishedWork); } } - if (renderState.tail !== null && now$1() > getRenderTargetTime()) { - // We have already passed our CPU deadline but we still have rows - // left in the tail. We'll just give up further attempts to render - // the main content and only render fallbacks. - workInProgress.flags |= DidCapture; - didSuspendAlready = true; - cutOffTailIfNeeded(renderState, false); // Since nothing actually suspended, there will nothing to ping this - // to get it started back up to attempt the next item. While in terms - // of priority this work has the same priority as this current render, - // it's not part of the same transition once the transition has - // committed. If it's sync, we still want to yield so that it can be - // painted. Conceptually, this is really the same as pinging. - // We can use any RetryLane even if it's the one currently rendering - // since we're leaving it behind on this node. - - workInProgress.lanes = SomeRetryLane; + { + if ((flags & Insertion) !== NoFlags) { + setIsRunningInsertionEffect(true); + } } - } 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; + safelyCallDestroy(finishedWork, nearestMountedAncestor, destroy); - if (_newThenables !== null) { - workInProgress.updateQueue = _newThenables; - workInProgress.flags |= Update; + { + if ((flags & Insertion) !== NoFlags) { + setIsRunningInsertionEffect(false); } + } - 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 ((flags & Passive) !== NoFlags) { + markComponentPassiveEffectUnmountStopped(); + } else if ((flags & Layout) !== NoFlags) { + markComponentLayoutEffectUnmountStopped(); } - } else if ( - // The time it took to render last row is greater than the remaining - // time we have to render. So rendering one more row would likely - // exceed it. - now$1() * 2 - renderState.renderingStartTime > - getRenderTargetTime() && - renderLanes !== OffscreenLane - ) { - // We have now passed our CPU deadline and we'll just give up further - // attempts to render the main content and only render fallbacks. - // The assumption is that this is usually faster. - workInProgress.flags |= DidCapture; - didSuspendAlready = true; - cutOffTailIfNeeded(renderState, false); // Since nothing actually suspended, there will nothing to ping this - // to get it started back up to attempt the next item. While in terms - // of priority this work has the same priority as this current render, - // it's not part of the same transition once the transition has - // committed. If it's sync, we still want to yield so that it can be - // painted. Conceptually, this is really the same as pinging. - // We can use any RetryLane even if it's the one currently rendering - // since we're leaving it behind on this node. - - workInProgress.lanes = SomeRetryLane; } } + } - if (renderState.isBackwards) { - // The effect list of the backwards tail will have been added - // to the end. This breaks the guarantee that life-cycles fire in - // sibling order but that isn't a strong guarantee promised by React. - // Especially since these might also just pop in during future commits. - // Append to the beginning of the list. - renderedTail.sibling = workInProgress.child; - workInProgress.child = renderedTail; - } else { - var previousSibling = renderState.last; + effect = effect.next; + } while (effect !== firstEffect); + } +} - if (previousSibling !== null) { - previousSibling.sibling = renderedTail; - } else { - workInProgress.child = renderedTail; - } +function commitHookEffectListMount(flags, finishedWork) { + var updateQueue = finishedWork.updateQueue; + var lastEffect = updateQueue !== null ? updateQueue.lastEffect : null; - renderState.last = renderedTail; - } - } + if (lastEffect !== null) { + var firstEffect = lastEffect.next; + var effect = firstEffect; - if (renderState.tail !== null) { - // We still have tail rows to render. - // Pop a row. - var next = renderState.tail; - renderState.rendering = next; - renderState.tail = next.sibling; - renderState.renderingStartTime = now$1(); - next.sibling = null; // Restore the context. - // TODO: We can probably just avoid popping it instead and only - // setting it the first time we go from not suspended to suspended. + do { + if ((effect.tag & flags) === flags) { + { + if ((flags & Passive) !== NoFlags) { + markComponentPassiveEffectMountStarted(finishedWork); + } else if ((flags & Layout) !== NoFlags) { + markComponentLayoutEffectMountStarted(finishedWork); + } + } // Mount - var suspenseContext = suspenseStackCursor.current; + var create = effect.create; - if (didSuspendAlready) { - suspenseContext = setShallowSuspenseListContext( - suspenseContext, - ForceSuspenseFallback - ); - } else { - suspenseContext = - setDefaultShallowSuspenseListContext(suspenseContext); + { + if ((flags & Insertion) !== NoFlags) { + setIsRunningInsertionEffect(true); + } } - pushSuspenseListContext(workInProgress, suspenseContext); // Do a pass over the next row. - // Don't bubble properties in this case. + effect.destroy = create(); - return next; - } + { + if ((flags & Insertion) !== NoFlags) { + setIsRunningInsertionEffect(false); + } + } - bubbleProperties(workInProgress); - return null; - } + { + if ((flags & Passive) !== NoFlags) { + markComponentPassiveEffectMountStopped(); + } else if ((flags & Layout) !== NoFlags) { + markComponentLayoutEffectMountStopped(); + } + } - case ScopeComponent: { - break; - } + { + var destroy = effect.destroy; - case OffscreenComponent: - case LegacyHiddenComponent: { - popSuspenseHandler(workInProgress); - popHiddenContext(workInProgress); - var _nextState = workInProgress.memoizedState; - var nextIsHidden = _nextState !== null; // Schedule a Visibility effect if the visibility has changed + if (destroy !== undefined && typeof destroy !== "function") { + var hookName = void 0; - if (workInProgress.tag === LegacyHiddenComponent); - else { - if (current !== null) { - var _prevState = current.memoizedState; - var prevIsHidden = _prevState !== null; + if ((effect.tag & Layout) !== NoFlags$1) { + hookName = "useLayoutEffect"; + } else if ((effect.tag & Insertion) !== NoFlags$1) { + hookName = "useInsertionEffect"; + } else { + hookName = "useEffect"; + } - if (prevIsHidden !== nextIsHidden) { - workInProgress.flags |= Visibility; - } - } else { - // On initial mount, we only need a Visibility effect if the tree - // is hidden. - if (nextIsHidden) { - workInProgress.flags |= Visibility; - } - } - } + var addendum = void 0; - if (!nextIsHidden || (workInProgress.mode & ConcurrentMode) === NoMode) { - bubbleProperties(workInProgress); - } else { - // Don't bubble properties for hidden children unless we're rendering - // at offscreen priority. - if ( - includesSomeLane(renderLanes, OffscreenLane) && // Also don't bubble if the tree suspended - (workInProgress.flags & DidCapture) === NoLanes - ) { - bubbleProperties(workInProgress); // Check if there was an insertion or update in the hidden subtree. - // If so, we need to hide those nodes in the commit phase, so - // schedule a visibility effect. + if (destroy === null) { + addendum = + " You returned null. If your effect does not require clean " + + "up, return undefined (or nothing)."; + } else if (typeof destroy.then === "function") { + addendum = + "\n\nIt looks like you wrote " + + hookName + + "(async () => ...) or returned a Promise. " + + "Instead, write the async function inside your effect " + + "and call it immediately:\n\n" + + hookName + + "(() => {\n" + + " async function fetchData() {\n" + + " // You can await here\n" + + " const response = await MyAPI.getData(someId);\n" + + " // ...\n" + + " }\n" + + " fetchData();\n" + + "}, [someId]); // Or [] if effect doesn't need props or state\n\n" + + "Learn more about data fetching with Hooks: https://reactjs.org/link/hooks-data-fetching"; + } else { + addendum = " You returned: " + destroy; + } - if ( - workInProgress.tag !== LegacyHiddenComponent && - workInProgress.subtreeFlags & (Placement | Update) - ) { - workInProgress.flags |= Visibility; + error( + "%s must not return anything besides a function, " + + "which is used for clean-up.%s", + hookName, + addendum + ); } } } - if (workInProgress.updateQueue !== null) { - // Schedule an effect to attach Suspense retry listeners - // TODO: Move to passive phase - workInProgress.flags |= Update; - } - return null; - } - - case CacheComponent: { - return null; - } - - case TracingMarkerComponent: { - return null; - } + effect = effect.next; + } while (effect !== firstEffect); } - - 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) { - switch (workInProgress.tag) { - case ClassComponent: { - var Component = workInProgress.type; +function commitPassiveEffectDurations(finishedRoot, finishedWork) { + if (getExecutionContext() & CommitContext) { + // Only Profilers with work in their subtree will have an Update effect scheduled. + if ((finishedWork.flags & Update) !== NoFlags$1) { + switch (finishedWork.tag) { + case Profiler: { + var passiveEffectDuration = + finishedWork.stateNode.passiveEffectDuration; + var _finishedWork$memoize = finishedWork.memoizedProps, + id = _finishedWork$memoize.id, + onPostCommit = _finishedWork$memoize.onPostCommit; // This value will still reflect the previous commit phase. + // It does not get reset until the start of the next commit phase. - if (isContextProvider(Component)) { - popContext(workInProgress); - } + var commitTime = getCommitTime(); + var phase = finishedWork.alternate === null ? "mount" : "update"; - var flags = workInProgress.flags; + { + if (isCurrentUpdateNested()) { + phase = "nested-update"; + } + } - if (flags & ShouldCapture) { - workInProgress.flags = (flags & ~ShouldCapture) | DidCapture; + 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 ((workInProgress.mode & ProfileMode) !== NoMode) { - transferActualDuration(workInProgress); - } + var parentFiber = finishedWork.return; - return workInProgress; - } + outer: while (parentFiber !== null) { + switch (parentFiber.tag) { + case HostRoot: + var root = parentFiber.stateNode; + root.passiveEffectDuration += passiveEffectDuration; + break outer; - return null; - } + case Profiler: + var parentStateNode = parentFiber.stateNode; + parentStateNode.passiveEffectDuration += passiveEffectDuration; + break outer; + } - case HostRoot: { - popHostContainer(workInProgress); - popTopLevelContextObject(workInProgress); - resetWorkInProgressVersions(); - var _flags = workInProgress.flags; + parentFiber = parentFiber.return; + } - if ( - (_flags & ShouldCapture) !== NoFlags$1 && - (_flags & DidCapture) === NoFlags$1 - ) { - // There was an error during render that wasn't captured by a suspense - // boundary. Do a second pass on the root to unmount the children. - workInProgress.flags = (_flags & ~ShouldCapture) | DidCapture; - return workInProgress; - } // We unwound to the root without completing it. Exit. + break; + } + } + } + } +} - return null; +function commitHookLayoutEffects(finishedWork, hookFlags) { + // At this point layout effects have already been destroyed (during mutation phase). + // This is done to prevent sibling component effects from interfering with each other, + // e.g. a destroy function in one component should never override a ref set + // by a create function in another component during the same commit. + if (shouldProfile(finishedWork)) { + try { + startLayoutEffectTimer(); + commitHookEffectListMount(hookFlags, finishedWork); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); } - case HostHoistable: - case HostSingleton: - case HostComponent: { - // TODO: popHydrationState - popHostContext(workInProgress); - return null; + recordLayoutEffectDuration(finishedWork); + } else { + try { + commitHookEffectListMount(hookFlags, finishedWork); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); } + } +} - case SuspenseComponent: { - popSuspenseHandler(workInProgress); - var suspenseState = workInProgress.memoizedState; +function commitClassLayoutLifecycles(finishedWork, current) { + var instance = finishedWork.stateNode; - if (suspenseState !== null && suspenseState.dehydrated !== null) { - if (workInProgress.alternate === null) { - throw new Error( - "Threw in newly mounted dehydrated component. This is likely a bug in " + - "React. Please file an issue." + if (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" ); } - } - - var _flags2 = workInProgress.flags; - - if (_flags2 & ShouldCapture) { - workInProgress.flags = (_flags2 & ~ShouldCapture) | DidCapture; // Captured a suspense effect. Re-render the boundary. - if ((workInProgress.mode & ProfileMode) !== NoMode) { - transferActualDuration(workInProgress); + if (instance.state !== finishedWork.memoizedState) { + error( + "Expected %s state to match memoized state before " + + "componentDidMount. " + + "This might either be because of a bug in React, or because " + + "a component reassigns its own `this.state`. " + + "Please file an issue.", + getComponentNameFromFiber(finishedWork) || "instance" + ); } - - return workInProgress; } - - return null; - } - - case SuspenseListComponent: { - popSuspenseListContext(workInProgress); // SuspenseList doesn't actually catch anything. It should've been - // caught by a nested boundary. If not, it should bubble through. - - return null; } - case HostPortal: - popHostContainer(workInProgress); - return null; - - case ContextProvider: - var context = workInProgress.type._context; - popProvider(context, workInProgress); - return null; - - case OffscreenComponent: - case LegacyHiddenComponent: { - popSuspenseHandler(workInProgress); - popHiddenContext(workInProgress); - var _flags3 = workInProgress.flags; - - if (_flags3 & ShouldCapture) { - workInProgress.flags = (_flags3 & ~ShouldCapture) | DidCapture; // Captured a suspense effect. Re-render the boundary. - - if ((workInProgress.mode & ProfileMode) !== NoMode) { - transferActualDuration(workInProgress); - } - - return workInProgress; + if (shouldProfile(finishedWork)) { + try { + startLayoutEffectTimer(); + instance.componentDidMount(); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); } - return null; + recordLayoutEffectDuration(finishedWork); + } else { + try { + instance.componentDidMount(); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } } + } else { + var prevProps = + finishedWork.elementType === finishedWork.type + ? current.memoizedProps + : resolveDefaultProps(finishedWork.type, current.memoizedProps); + var prevState = current.memoizedState; // We could update instance props and state here, + // but instead we rely on them being set during last render. + // TODO: revisit this when we implement resuming. - case CacheComponent: - return null; - - case TracingMarkerComponent: - return null; - - default: - return null; - } -} - -function unwindInterruptedWork(current, interruptedWork, renderLanes) { - switch (interruptedWork.tag) { - case ClassComponent: { - var childContextTypes = interruptedWork.type.childContextTypes; - - if (childContextTypes !== null && childContextTypes !== undefined) { - popContext(interruptedWork); - } + { + 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" + ); + } - break; + 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: { - popHostContainer(interruptedWork); - popTopLevelContextObject(interruptedWork); - resetWorkInProgressVersions(); - break; - } + if (shouldProfile(finishedWork)) { + try { + startLayoutEffectTimer(); + instance.componentDidUpdate( + prevProps, + prevState, + instance.__reactInternalSnapshotBeforeUpdate + ); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } - case HostHoistable: - case HostSingleton: - case HostComponent: { - popHostContext(interruptedWork); - break; + recordLayoutEffectDuration(finishedWork); + } else { + try { + instance.componentDidUpdate( + prevProps, + prevState, + instance.__reactInternalSnapshotBeforeUpdate + ); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } } - - case HostPortal: - popHostContainer(interruptedWork); - break; - - case SuspenseComponent: - popSuspenseHandler(interruptedWork); - break; - - case SuspenseListComponent: - popSuspenseListContext(interruptedWork); - break; - - case ContextProvider: - var context = interruptedWork.type._context; - popProvider(context, interruptedWork); - break; - - case OffscreenComponent: - case LegacyHiddenComponent: - popSuspenseHandler(interruptedWork); - popHiddenContext(interruptedWork); - break; } } -var didWarnAboutUndefinedSnapshotBeforeUpdate = null; - -{ - didWarnAboutUndefinedSnapshotBeforeUpdate = new Set(); -} // Used during the commit phase to track the state of the Offscreen component stack. -// Allows us to avoid traversing the return path to find the nearest Offscreen ancestor. - -var offscreenSubtreeIsHidden = false; -var offscreenSubtreeWasHidden = false; -var PossiblyWeakSet = typeof WeakSet === "function" ? WeakSet : Set; -var nextEffect = null; // Used for Profiling builds to track updaters. - -var inProgressLanes = null; -var inProgressRoot = null; +function commitClassCallbacks(finishedWork) { + // TODO: I think this is now always non-null by the time it reaches the + // commit phase. Consider removing the type check. + var updateQueue = finishedWork.updateQueue; -function shouldProfile(current) { - return ( - (current.mode & ProfileMode) !== NoMode && - (getExecutionContext() & CommitContext) !== NoContext - ); -} + if (updateQueue !== null) { + var instance = finishedWork.stateNode; -function reportUncaughtErrorInDEV(error) { - // Wrapping each small part of the commit phase into a guarded - // callback is a bit too slow (https://github.com/facebook/react/pull/21666). - // But we rely on it to surface errors to DEV tools like overlays - // (https://github.com/facebook/react/issues/21712). - // As a compromise, rethrow only caught errors in a guard. - { - invokeGuardedCallback(null, function () { - throw error; - }); - clearCaughtError(); - } -} + { + if ( + 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" + ); + } -var callComponentWillUnmountWithTimer = function (current, instance) { - instance.props = current.memoizedProps; - instance.state = 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 (shouldProfile(current)) { try { - startLayoutEffectTimer(); - instance.componentWillUnmount(); - } finally { - recordLayoutEffectDuration(current); + commitCallbacks(updateQueue, instance); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); } - } else { - instance.componentWillUnmount(); } -}; // Capture errors so they don't interrupt unmounting. +} -function safelyCallComponentWillUnmount( - current, - nearestMountedAncestor, - instance -) { - try { - callComponentWillUnmountWithTimer(current, instance); - } catch (error) { - captureCommitPhaseError(current, nearestMountedAncestor, error); - } -} // Capture errors so they don't interrupt mounting. +function commitHostComponentMount(finishedWork) { + var type = finishedWork.type; + var props = finishedWork.memoizedProps; + var instance = finishedWork.stateNode; -function safelyAttachRef(current, nearestMountedAncestor) { try { - commitAttachRef(current); + commitMount(instance, type, props, finishedWork); } catch (error) { - captureCommitPhaseError(current, nearestMountedAncestor, error); + captureCommitPhaseError(finishedWork, finishedWork.return, error); } } -function safelyDetachRef(current, nearestMountedAncestor) { - var ref = current.ref; - var refCleanup = current.refCleanup; - - if (ref !== null) { - if (typeof refCleanup === "function") { - try { - if (shouldProfile(current)) { - try { - startLayoutEffectTimer(); - refCleanup(); - } finally { - recordLayoutEffectDuration(current); - } - } else { - refCleanup(); - } - } catch (error) { - captureCommitPhaseError(current, nearestMountedAncestor, error); - } finally { - // `refCleanup` has been called. Nullify all references to it to prevent double invocation. - current.refCleanup = null; - var finishedWork = current.alternate; +function commitProfilerUpdate(finishedWork, current) { + if (getExecutionContext() & CommitContext) { + try { + var _finishedWork$memoize2 = finishedWork.memoizedProps, + onCommit = _finishedWork$memoize2.onCommit, + onRender = _finishedWork$memoize2.onRender; + var effectDuration = finishedWork.stateNode.effectDuration; + var commitTime = getCommitTime(); + var phase = current === null ? "mount" : "update"; - if (finishedWork != null) { - finishedWork.refCleanup = null; + if (enableProfilerNestedUpdatePhase) { + if (isCurrentUpdateNested()) { + phase = "nested-update"; } } - } else if (typeof ref === "function") { - var retVal; - try { - if (shouldProfile(current)) { - try { - startLayoutEffectTimer(); - retVal = ref(null); - } finally { - recordLayoutEffectDuration(current); - } - } else { - retVal = ref(null); - } - } catch (error) { - captureCommitPhaseError(current, nearestMountedAncestor, error); + if (typeof onRender === "function") { + onRender( + finishedWork.memoizedProps.id, + phase, + finishedWork.actualDuration, + finishedWork.treeBaseDuration, + finishedWork.actualStartTime, + commitTime + ); } - { - 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 (enableProfilerCommitHooks) { + if (typeof onCommit === "function") { + onCommit( + finishedWork.memoizedProps.id, + phase, + effectDuration, + commitTime + ); + } // Schedule a passive effect for this Profiler to call onPostCommit hooks. + // This effect should be scheduled even if there is no onPostCommit callback for this Profiler, + // because the effect is also where times bubble to parent Profilers. + + enqueuePendingPassiveProfilerEffect(finishedWork); // Propagate layout effect durations to the next nearest Profiler ancestor. + // Do not reset these values until the next render so DevTools has a chance to read them first. + + var parentFiber = finishedWork.return; + + outer: while (parentFiber !== null) { + switch (parentFiber.tag) { + case HostRoot: + var root = parentFiber.stateNode; + root.effectDuration += effectDuration; + break outer; + + case Profiler: + var parentStateNode = parentFiber.stateNode; + parentStateNode.effectDuration += effectDuration; + break outer; + } + + parentFiber = parentFiber.return; } } - } else { - // $FlowFixMe unable to narrow type to RefObject - ref.current = null; + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); } } } -function safelyCallDestroy(current, nearestMountedAncestor, destroy) { - try { - destroy(); - } catch (error) { - captureCommitPhaseError(current, nearestMountedAncestor, error); - } -} -var shouldFireAfterActiveInstanceBlur = false; -function commitBeforeMutationEffects(root, firstChild) { - nextEffect = firstChild; - commitBeforeMutationEffects_begin(); // We no longer need to track the active instance fiber - - var shouldFire = shouldFireAfterActiveInstanceBlur; - shouldFireAfterActiveInstanceBlur = false; - return shouldFire; -} +function commitLayoutEffectOnFiber( + finishedRoot, + current, + finishedWork, + committedLanes +) { + // When updating this function, also update reappearLayoutEffects, which does + // most of the same things when an offscreen tree goes from hidden -> visible. + var flags = finishedWork.flags; -function commitBeforeMutationEffects_begin() { - while (nextEffect !== null) { - var fiber = nextEffect; // This phase is only used for beforeActiveInstanceBlur. + switch (finishedWork.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { + recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); - var child = fiber.child; + if (flags & Update) { + commitHookLayoutEffects(finishedWork, Layout | HasEffect); + } - if ( - (fiber.subtreeFlags & BeforeMutationMask) !== NoFlags$1 && - child !== null - ) { - child.return = fiber; - nextEffect = child; - } else { - commitBeforeMutationEffects_complete(); + break; } - } -} -function commitBeforeMutationEffects_complete() { - while (nextEffect !== null) { - var fiber = nextEffect; - setCurrentFiber(fiber); + case ClassComponent: { + recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); - try { - commitBeforeMutationEffectsOnFiber(fiber); - } catch (error) { - captureCommitPhaseError(fiber, fiber.return, error); - } + if (flags & Update) { + commitClassLayoutLifecycles(finishedWork, current); + } - resetCurrentFiber(); - var sibling = fiber.sibling; + if (flags & Callback) { + commitClassCallbacks(finishedWork); + } - if (sibling !== null) { - sibling.return = fiber.return; - nextEffect = sibling; - return; + if (flags & Ref) { + safelyAttachRef(finishedWork, finishedWork.return); + } + + break; } - nextEffect = fiber.return; - } -} + case HostRoot: { + recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); -function commitBeforeMutationEffectsOnFiber(finishedWork) { - var current = finishedWork.alternate; - var flags = finishedWork.flags; + if (flags & Callback) { + // TODO: I think this is now always non-null by the time it reaches the + // commit phase. Consider removing the type check. + var updateQueue = finishedWork.updateQueue; - if ((flags & Snapshot) !== NoFlags$1) { - setCurrentFiber(finishedWork); - } + if (updateQueue !== null) { + var instance = null; + + if (finishedWork.child !== null) { + switch (finishedWork.child.tag) { + case HostSingleton: + case HostComponent: + instance = getPublicInstance(finishedWork.child.stateNode); + break; + + case ClassComponent: + instance = finishedWork.child.stateNode; + break; + } + } + + try { + commitCallbacks(updateQueue, instance); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } + } + } - switch (finishedWork.tag) { - case FunctionComponent: { break; } - case ForwardRef: - case SimpleMemoComponent: { + case HostHoistable: + // eslint-disable-next-line-no-fallthrough + + case HostSingleton: + case HostComponent: { + recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); // Renderers may schedule work to be done after host components are mounted + // (eg DOM renderer may schedule auto-focus for inputs and form controls). + // These effects should only be committed when components are first mounted, + // aka when there is no current/alternate. + + if (current === null && flags & Update) { + commitHostComponentMount(finishedWork); + } + + if (flags & Ref) { + safelyAttachRef(finishedWork, finishedWork.return); + } + break; } - case ClassComponent: { - if ((flags & Snapshot) !== NoFlags$1) { - if (current !== null) { - var prevProps = current.memoizedProps; - var prevState = current.memoizedState; - var instance = finishedWork.stateNode; // We could update instance props and state here, - // but instead we rely on them being set during last render. - // TODO: revisit this when we implement resuming. + case Profiler: { + recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); // TODO: Should this fire inside an offscreen tree? Or should it wait to + // fire when the tree becomes visible again. - { - if ( - 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 (flags & Update) { + commitProfilerUpdate(finishedWork, current); + } - 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" - ); - } - } - } + break; + } - var snapshot = instance.getSnapshotBeforeUpdate( - finishedWork.elementType === finishedWork.type - ? prevProps - : resolveDefaultProps(finishedWork.type, prevProps), - prevState - ); + case SuspenseComponent: { + recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); - { - var didWarnSet = didWarnAboutUndefinedSnapshotBeforeUpdate; + break; + } - if (snapshot === undefined && !didWarnSet.has(finishedWork.type)) { - didWarnSet.add(finishedWork.type); + case OffscreenComponent: { + var isModernRoot = (finishedWork.mode & ConcurrentMode) !== NoMode; - error( - "%s.getSnapshotBeforeUpdate(): A snapshot value (or null) " + - "must be returned. You have returned undefined.", - getComponentNameFromFiber(finishedWork) - ); - } + if (isModernRoot) { + var isHidden = finishedWork.memoizedState !== null; + var newOffscreenSubtreeIsHidden = isHidden || offscreenSubtreeIsHidden; + + if (newOffscreenSubtreeIsHidden); + else { + // The Offscreen tree is visible. + var wasHidden = current !== null && current.memoizedState !== null; + var newOffscreenSubtreeWasHidden = + wasHidden || offscreenSubtreeWasHidden; + var prevOffscreenSubtreeIsHidden = offscreenSubtreeIsHidden; + var prevOffscreenSubtreeWasHidden = offscreenSubtreeWasHidden; + offscreenSubtreeIsHidden = newOffscreenSubtreeIsHidden; + offscreenSubtreeWasHidden = newOffscreenSubtreeWasHidden; + + if (offscreenSubtreeWasHidden && !prevOffscreenSubtreeWasHidden) { + // This is the root of a reappearing boundary. As we continue + // traversing the layout effects, we must also re-mount layout + // effects that were unmounted when the Offscreen subtree was + // hidden. So this is a superset of the normal commitLayoutEffects. + var includeWorkInProgressEffects = + (finishedWork.subtreeFlags & LayoutMask) !== NoFlags$1; + recursivelyTraverseReappearLayoutEffects( + finishedRoot, + finishedWork, + includeWorkInProgressEffects + ); + } else { + recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); } - instance.__reactInternalSnapshotBeforeUpdate = snapshot; + offscreenSubtreeIsHidden = prevOffscreenSubtreeIsHidden; + offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden; + } + } else { + recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); + } + + if (flags & Ref) { + var props = finishedWork.memoizedProps; + + if (props.mode === "manual") { + safelyAttachRef(finishedWork, finishedWork.return); + } else { + safelyDetachRef(finishedWork, finishedWork.return); } } break; } - case HostRoot: { - break; - } - - case HostComponent: - case HostHoistable: - case HostSingleton: - case HostText: - case HostPortal: - case IncompleteClassComponent: - // Nothing to do for these component types - break; - default: { - if ((flags & Snapshot) !== NoFlags$1) { - throw new Error( - "This unit of work tag should not have side-effects. This error is " + - "likely caused by a bug in React. Please file an issue." - ); - } + recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); + break; } } - - if ((flags & Snapshot) !== NoFlags$1) { - 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 & Passive) !== NoFlags) { - markComponentPassiveEffectUnmountStarted(finishedWork); - } else if ((flags & Layout) !== NoFlags) { - markComponentLayoutEffectUnmountStarted(finishedWork); - } - } +function commitAttachRef(finishedWork) { + var ref = finishedWork.ref; - { - if ((flags & Insertion) !== NoFlags) { - setIsRunningInsertionEffect(true); - } - } + if (ref !== null) { + var instance = finishedWork.stateNode; + var instanceToUse; - safelyCallDestroy(finishedWork, nearestMountedAncestor, destroy); + switch (finishedWork.tag) { + case HostHoistable: + case HostSingleton: + case HostComponent: + instanceToUse = getPublicInstance(instance); + break; - { - if ((flags & Insertion) !== NoFlags) { - setIsRunningInsertionEffect(false); - } - } + default: + instanceToUse = instance; + } // Moved outside to ensure DCE works with this flag - { - if ((flags & Passive) !== NoFlags) { - markComponentPassiveEffectUnmountStopped(); - } else if ((flags & Layout) !== NoFlags) { - markComponentLayoutEffectUnmountStopped(); - } - } + if (typeof ref === "function") { + if (shouldProfile(finishedWork)) { + try { + startLayoutEffectTimer(); + finishedWork.refCleanup = ref(instanceToUse); + } finally { + recordLayoutEffectDuration(finishedWork); } + } else { + finishedWork.refCleanup = ref(instanceToUse); } + } else { + { + if (!ref.hasOwnProperty("current")) { + error( + "Unexpected ref object provided for %s. " + + "Use either a ref-setter function or React.createRef().", + getComponentNameFromFiber(finishedWork) + ); + } + } // $FlowFixMe unable to narrow type to the non-function case - effect = effect.next; - } while (effect !== firstEffect); + ref.current = instanceToUse; + } } } -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; - - do { - if ((effect.tag & flags) === flags) { - { - if ((flags & Passive) !== NoFlags) { - markComponentPassiveEffectMountStarted(finishedWork); - } else if ((flags & Layout) !== NoFlags) { - markComponentLayoutEffectMountStarted(finishedWork); - } - } // Mount - - var create = effect.create; +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 & Insertion) !== NoFlags) { - setIsRunningInsertionEffect(true); - } - } + if (alternate !== null) { + alternate.return = null; + } - effect.destroy = create(); + fiber.return = null; +} - { - if ((flags & Insertion) !== NoFlags) { - setIsRunningInsertionEffect(false); - } - } +function detachFiberAfterEffects(fiber) { + var alternate = fiber.alternate; - { - if ((flags & Passive) !== NoFlags) { - markComponentPassiveEffectMountStopped(); - } else if ((flags & Layout) !== NoFlags) { - markComponentLayoutEffectMountStopped(); - } - } + if (alternate !== null) { + fiber.alternate = null; + detachFiberAfterEffects(alternate); + } // Clear cyclical Fiber fields. This level alone is designed to roughly + // approximate the planned Fiber refactor. In that world, `setState` will be + // bound to a special "instance" object instead of a Fiber. The Instance + // object will not have any of these fields. It will only be connected to + // the fiber tree via a single link at the root. So if this level alone is + // sufficient to fix memory issues, that bodes well for our plans. - { - var destroy = effect.destroy; + fiber.child = null; + fiber.deletions = null; + fiber.sibling = null; // The `stateNode` is cyclical because on host nodes it points to the host - if (destroy !== undefined && typeof destroy !== "function") { - var hookName = void 0; + fiber.stateNode = null; - if ((effect.tag & Layout) !== NoFlags$1) { - hookName = "useLayoutEffect"; - } else if ((effect.tag & Insertion) !== NoFlags$1) { - hookName = "useInsertionEffect"; - } else { - hookName = "useEffect"; - } + { + fiber._debugOwner = null; + } // Theoretically, nothing in here should be necessary, because we already + // disconnected the fiber from the tree. So even if something leaks this + // particular fiber, it won't leak anything else. - var addendum = void 0; + fiber.return = null; + fiber.dependencies = null; + fiber.memoizedProps = null; + fiber.memoizedState = null; + fiber.pendingProps = null; + fiber.stateNode = null; // TODO: Move to `commitPassiveUnmountInsideDeletedTreeOnFiber` instead. - if (destroy === null) { - addendum = - " You returned null. If your effect does not require clean " + - "up, return undefined (or nothing)."; - } else if (typeof destroy.then === "function") { - addendum = - "\n\nIt looks like you wrote " + - hookName + - "(async () => ...) or returned a Promise. " + - "Instead, write the async function inside your effect " + - "and call it immediately:\n\n" + - hookName + - "(() => {\n" + - " async function fetchData() {\n" + - " // You can await here\n" + - " const response = await MyAPI.getData(someId);\n" + - " // ...\n" + - " }\n" + - " fetchData();\n" + - "}, [someId]); // Or [] if effect doesn't need props or state\n\n" + - "Learn more about data fetching with Hooks: https://reactjs.org/link/hooks-data-fetching"; - } else { - addendum = " You returned: " + destroy; - } + fiber.updateQueue = null; +} - error( - "%s must not return anything besides a function, " + - "which is used for clean-up.%s", - hookName, - addendum - ); - } - } - } +function emptyPortalContainer(current) { + var portal = current.stateNode; + var containerInfo = portal.containerInfo; + createContainerChildSet(containerInfo); +} - effect = effect.next; - } while (effect !== firstEffect); +function commitPlacement(finishedWork) { + { + return; } } -function commitPassiveEffectDurations(finishedRoot, finishedWork) { - if (getExecutionContext() & CommitContext) { - // Only Profilers with work in their subtree will have an Update effect scheduled. - if ((finishedWork.flags & Update) !== NoFlags$1) { - switch (finishedWork.tag) { - case Profiler: { - var passiveEffectDuration = - finishedWork.stateNode.passiveEffectDuration; - var _finishedWork$memoize = finishedWork.memoizedProps, - id = _finishedWork$memoize.id, - onPostCommit = _finishedWork$memoize.onPostCommit; // This value will still reflect the previous commit phase. - // It does not get reset until the start of the next commit phase. +function commitDeletionEffects(root, returnFiber, deletedFiber) { + { + // Detach refs and call componentWillUnmount() on the whole subtree. + commitDeletionEffectsOnFiber(root, returnFiber, deletedFiber); + } - var commitTime = getCommitTime(); - var phase = finishedWork.alternate === null ? "mount" : "update"; + detachFiberMutation(deletedFiber); +} - { - if (isCurrentUpdateNested()) { - phase = "nested-update"; - } - } +function recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + parent +) { + // TODO: Use a static flag to skip trees that don't have unmount effects + var child = parent.child; - 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. + while (child !== null) { + commitDeletionEffectsOnFiber(finishedRoot, nearestMountedAncestor, child); + child = child.sibling; + } +} - var parentFiber = finishedWork.return; +function commitDeletionEffectsOnFiber( + finishedRoot, + nearestMountedAncestor, + deletedFiber +) { + onCommitUnmount(deletedFiber); // The cases in this outer switch modify the stack before they traverse + // into their subtree. There are simpler cases in the inner switch + // that don't modify the stack. - outer: while (parentFiber !== null) { - switch (parentFiber.tag) { - case HostRoot: - var root = parentFiber.stateNode; - root.passiveEffectDuration += passiveEffectDuration; - break outer; + switch (deletedFiber.tag) { + case HostHoistable: + // eslint-disable-next-line no-fallthrough - case Profiler: - var parentStateNode = parentFiber.stateNode; - parentStateNode.passiveEffectDuration += passiveEffectDuration; - break outer; - } + case HostSingleton: + // eslint-disable-next-line no-fallthrough - parentFiber = parentFiber.return; - } + case HostComponent: { + if (!offscreenSubtreeWasHidden) { + safelyDetachRef(deletedFiber, nearestMountedAncestor); + } // Intentional fallthrough to next branch + } + // eslint-disable-next-line-no-fallthrough - break; - } + 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; } - } -} -function commitHookLayoutEffects(finishedWork, hookFlags) { - // At this point layout effects have already been destroyed (during mutation phase). - // This is done to prevent sibling component effects from interfering with each other, - // e.g. a destroy function in one component should never override a ref set - // by a create function in another component during the same commit. - if (shouldProfile(finishedWork)) { - try { - startLayoutEffectTimer(); - commitHookEffectListMount(hookFlags, finishedWork); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); + case DehydratedFragment: { + return; } - recordLayoutEffectDuration(finishedWork); - } else { - try { - commitHookEffectListMount(hookFlags, finishedWork); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); + case HostPortal: { + { + emptyPortalContainer(deletedFiber); + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + } + + return; } - } -} -function commitClassLayoutLifecycles(finishedWork, current) { - var instance = finishedWork.stateNode; + case FunctionComponent: + case ForwardRef: + case MemoComponent: + case SimpleMemoComponent: { + if (!offscreenSubtreeWasHidden) { + var updateQueue = deletedFiber.updateQueue; - 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 (updateQueue !== null) { + var lastEffect = updateQueue.lastEffect; - if (instance.state !== finishedWork.memoizedState) { - error( - "Expected %s state to match memoized state before " + - "componentDidMount. " + - "This might either be because of a bug in React, or because " + - "a component reassigns its own `this.state`. " + - "Please file an issue.", - getComponentNameFromFiber(finishedWork) || "instance" - ); - } - } - } + if (lastEffect !== null) { + var firstEffect = lastEffect.next; + var effect = firstEffect; - if (shouldProfile(finishedWork)) { - try { - startLayoutEffectTimer(); - instance.componentDidMount(); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } + do { + var _effect = effect, + destroy = _effect.destroy, + tag = _effect.tag; - recordLayoutEffectDuration(finishedWork); - } else { - try { - instance.componentDidMount(); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); + if (destroy !== undefined) { + if ((tag & Insertion) !== NoFlags) { + safelyCallDestroy( + deletedFiber, + nearestMountedAncestor, + destroy + ); + } else if ((tag & Layout) !== NoFlags) { + { + markComponentLayoutEffectUnmountStarted(deletedFiber); + } + + if (shouldProfile(deletedFiber)) { + startLayoutEffectTimer(); + safelyCallDestroy( + deletedFiber, + nearestMountedAncestor, + destroy + ); + recordLayoutEffectDuration(deletedFiber); + } else { + safelyCallDestroy( + deletedFiber, + nearestMountedAncestor, + destroy + ); + } + + { + markComponentLayoutEffectUnmountStopped(); + } + } + } + + effect = effect.next; + } while (effect !== firstEffect); + } + } } + + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + return; } - } 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" - ); - } + case ClassComponent: { + if (!offscreenSubtreeWasHidden) { + safelyDetachRef(deletedFiber, nearestMountedAncestor); + var instance = deletedFiber.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" + if (typeof instance.componentWillUnmount === "function") { + safelyCallComponentWillUnmount( + deletedFiber, + nearestMountedAncestor, + instance ); } } + + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + return; } - if (shouldProfile(finishedWork)) { - try { - startLayoutEffectTimer(); - instance.componentDidUpdate( - prevProps, - prevState, - instance.__reactInternalSnapshotBeforeUpdate - ); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } + case ScopeComponent: { + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + return; + } - recordLayoutEffectDuration(finishedWork); - } else { - try { - instance.componentDidUpdate( - prevProps, - prevState, - instance.__reactInternalSnapshotBeforeUpdate + case OffscreenComponent: { + safelyDetachRef(deletedFiber, nearestMountedAncestor); + + if (deletedFiber.mode & ConcurrentMode) { + // If this offscreen component is hidden, we already unmounted it. Before + // deleting the children, track that it's already unmounted so that we + // don't attempt to unmount the effects again. + // TODO: If the tree is hidden, in most cases we should be able to skip + // over the nested children entirely. An exception is we haven't yet found + // the topmost host node to delete, which we already track on the stack. + // But the other case is portals, which need to be detached no matter how + // deeply they are nested. We should use a subtree flag to track whether a + // subtree includes a nested portal. + var prevOffscreenSubtreeWasHidden = offscreenSubtreeWasHidden; + offscreenSubtreeWasHidden = + prevOffscreenSubtreeWasHidden || deletedFiber.memoizedState !== null; + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden; + } else { + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber ); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); } + + break; + } + + default: { + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + return; } } } -function commitClassCallbacks(finishedWork) { - // TODO: I think this is now always non-null by the time it reaches the - // commit phase. Consider removing the type check. - var updateQueue = finishedWork.updateQueue; +function commitSuspenseCallback(finishedWork) {} - if (updateQueue !== null) { - var instance = finishedWork.stateNode; +function getRetryCache(finishedWork) { + // TODO: Unify the interface for the retry cache so we don't have to switch + // on the tag like this. + switch (finishedWork.tag) { + case SuspenseComponent: + case SuspenseListComponent: { + var retryCache = finishedWork.stateNode; - { - if ( - finishedWork.type === finishedWork.elementType && - !didWarnAboutReassigningProps - ) { - if (instance.props !== finishedWork.memoizedProps) { - error( - "Expected %s props to match memoized props before " + - "processing the update queue. " + - "This might either be because of a bug in React, or because " + - "a component reassigns its own `this.props`. " + - "Please file an issue.", - getComponentNameFromFiber(finishedWork) || "instance" - ); - } + if (retryCache === null) { + retryCache = finishedWork.stateNode = new PossiblyWeakSet(); + } - 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" - ); - } + return retryCache; + } + + case OffscreenComponent: { + var instance = finishedWork.stateNode; + var _retryCache = instance._retryCache; + + if (_retryCache === null) { + _retryCache = instance._retryCache = new PossiblyWeakSet(); } - } // We could update instance props and state here, - // but instead we rely on them being set during last render. - // TODO: revisit this when we implement resuming. - try { - commitCallbacks(updateQueue, instance); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); + return _retryCache; + } + + default: { + throw new Error( + "Unexpected Suspense handler tag (" + + finishedWork.tag + + "). This is a " + + "bug in React." + ); } } } -function commitHostComponentMount(finishedWork) { - var type = finishedWork.type; - var props = finishedWork.memoizedProps; - var instance = finishedWork.stateNode; +function detachOffscreenInstance(instance) { + var fiber = instance._current; - try { - commitMount(instance, type, props, finishedWork); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); + if (fiber === null) { + throw new Error( + "Calling Offscreen.detach before instance handle has been set." + ); + } + + if ((instance._pendingVisibility & OffscreenDetached) !== NoFlags$1) { + // The instance is already detached, this is a noop. + return; + } // TODO: There is an opportunity to optimise this by not entering commit phase + // and unmounting effects directly. + + var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + + if (root !== null) { + instance._pendingVisibility |= OffscreenDetached; + scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); } } +function attachOffscreenInstance(instance) { + var fiber = instance._current; -function commitProfilerUpdate(finishedWork, current) { - if (getExecutionContext() & CommitContext) { - try { - var _finishedWork$memoize2 = finishedWork.memoizedProps, - onCommit = _finishedWork$memoize2.onCommit, - onRender = _finishedWork$memoize2.onRender; - var effectDuration = finishedWork.stateNode.effectDuration; - var commitTime = getCommitTime(); - var phase = current === null ? "mount" : "update"; + if (fiber === null) { + throw new Error( + "Calling Offscreen.detach before instance handle has been set." + ); + } - if (enableProfilerNestedUpdatePhase) { - if (isCurrentUpdateNested()) { - phase = "nested-update"; + if ((instance._pendingVisibility & OffscreenDetached) === NoFlags$1) { + // The instance is already attached, this is a noop. + return; + } + + var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + + if (root !== null) { + instance._pendingVisibility &= ~OffscreenDetached; + scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + } +} + +function attachSuspenseRetryListeners(finishedWork, wakeables) { + // If this boundary just timed out, then it will have a set of wakeables. + // For each wakeable, attach a listener so that when it resolves, React + // attempts to re-render the boundary in the primary (pre-timeout) state. + var retryCache = getRetryCache(finishedWork); + wakeables.forEach(function (wakeable) { + // Memoize using the boundary fiber to prevent redundant listeners. + var retry = resolveRetryWakeable.bind(null, finishedWork, wakeable); + + if (!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." + ); + } } } - if (typeof onRender === "function") { - onRender( - finishedWork.memoizedProps.id, - phase, - finishedWork.actualDuration, - finishedWork.treeBaseDuration, - finishedWork.actualStartTime, - commitTime - ); - } + 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 (enableProfilerCommitHooks) { - if (typeof onCommit === "function") { - onCommit( - finishedWork.memoizedProps.id, - phase, - effectDuration, - commitTime - ); - } // Schedule a passive effect for this Profiler to call onPostCommit hooks. - // This effect should be scheduled even if there is no onPostCommit callback for this Profiler, - // because the effect is also where times bubble to parent Profilers. +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; - enqueuePendingPassiveProfilerEffect(finishedWork); // Propagate layout effect durations to the next nearest Profiler ancestor. - // Do not reset these values until the next render so DevTools has a chance to read them first. + if (deletions !== null) { + for (var i = 0; i < deletions.length; i++) { + var childToDelete = deletions[i]; - var parentFiber = finishedWork.return; + try { + commitDeletionEffects(root, parentFiber, childToDelete); + } catch (error) { + captureCommitPhaseError(childToDelete, parentFiber, error); + } + } + } - outer: while (parentFiber !== null) { - switch (parentFiber.tag) { - case HostRoot: - var root = parentFiber.stateNode; - root.effectDuration += effectDuration; - break outer; + var prevDebugFiber = getCurrentFiber(); - case Profiler: - var parentStateNode = parentFiber.stateNode; - parentStateNode.effectDuration += effectDuration; - break outer; - } + if (parentFiber.subtreeFlags & MutationMask) { + var child = parentFiber.child; - parentFiber = parentFiber.return; - } - } - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); + while (child !== null) { + setCurrentFiber(child); + commitMutationEffectsOnFiber(child, root); + child = child.sibling; } } + + setCurrentFiber(prevDebugFiber); } -function commitLayoutEffectOnFiber( - finishedRoot, - current, - finishedWork, - committedLanes -) { - // When updating this function, also update reappearLayoutEffects, which does - // most of the same things when an offscreen tree goes from hidden -> visible. - var flags = finishedWork.flags; +function commitMutationEffectsOnFiber(finishedWork, root, lanes) { + var current = finishedWork.alternate; + var flags = finishedWork.flags; // The effect flag should be checked *after* we refine the type of fiber, + // because the fiber tag is more specific. An exception is any flag related + // to reconciliation, because those can be set on all fiber types. switch (finishedWork.tag) { case FunctionComponent: case ForwardRef: + case MemoComponent: case SimpleMemoComponent: { - recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); if (flags & Update) { - commitHookLayoutEffects(finishedWork, Layout | HasEffect); + try { + commitHookEffectListUnmount( + Insertion | HasEffect, + finishedWork, + finishedWork.return + ); + commitHookEffectListMount(Insertion | HasEffect, finishedWork); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } // Layout effects are destroyed during the mutation phase so that all + // destroy functions for all fibers are called before any create functions. + // This prevents sibling component effects from interfering with each other, + // e.g. a destroy function in one component should never override a ref set + // by a create function in another component during the same commit. + + if (shouldProfile(finishedWork)) { + try { + startLayoutEffectTimer(); + commitHookEffectListUnmount( + Layout | HasEffect, + finishedWork, + finishedWork.return + ); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } + + recordLayoutEffectDuration(finishedWork); + } else { + try { + commitHookEffectListUnmount( + Layout | HasEffect, + finishedWork, + finishedWork.return + ); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } + } } - break; + return; } case ClassComponent: { - recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); - - if (flags & Update) { - commitClassLayoutLifecycles(finishedWork, current); - } - - if (flags & Callback) { - commitClassCallbacks(finishedWork); - } + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); if (flags & Ref) { - safelyAttachRef(finishedWork, finishedWork.return); + if (current !== null) { + safelyDetachRef(current, current.return); + } } - break; - } - - case HostRoot: { - recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); - - if (flags & Callback) { - // TODO: I think this is now always non-null by the time it reaches the - // commit phase. Consider removing the type check. + if (flags & Callback && offscreenSubtreeIsHidden) { var updateQueue = finishedWork.updateQueue; if (updateQueue !== null) { - var instance = null; - - if (finishedWork.child !== null) { - switch (finishedWork.child.tag) { - case HostSingleton: - case HostComponent: - instance = getPublicInstance(finishedWork.child.stateNode); - break; - - case ClassComponent: - instance = finishedWork.child.stateNode; - break; - } - } - - try { - commitCallbacks(updateQueue, instance); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } + deferHiddenCallbacks(updateQueue); } } - break; + return; } case HostHoistable: // eslint-disable-next-line-no-fallthrough case HostSingleton: - case HostComponent: { - recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); // Renderers may schedule work to be done after host components are mounted - // (eg DOM renderer may schedule auto-focus for inputs and form controls). - // These effects should only be committed when components are first mounted, - // aka when there is no current/alternate. + // eslint-disable-next-line-no-fallthrough - if (current === null && flags & Update) { - commitHostComponentMount(finishedWork); - } + case HostComponent: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); if (flags & Ref) { - safelyAttachRef(finishedWork, finishedWork.return); + if (current !== null) { + safelyDetachRef(current, current.return); + } } - break; + return; } - case Profiler: { - recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); // TODO: Should this fire inside an offscreen tree? Or should it wait to - // fire when the tree becomes visible again. + case HostText: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); - if (flags & Update) { - commitProfilerUpdate(finishedWork, current); + return; + } + + case HostRoot: { + { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); } - break; - } + if (flags & Update) { + { + var containerInfo = root.containerInfo; + var pendingChildren = root.pendingChildren; - case SuspenseComponent: { - recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); + try { + replaceContainerChildren(containerInfo, pendingChildren); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } + } + } - break; + return; } - case OffscreenComponent: { - var isModernRoot = (finishedWork.mode & ConcurrentMode) !== NoMode; - - if (isModernRoot) { - var isHidden = finishedWork.memoizedState !== null; - var newOffscreenSubtreeIsHidden = isHidden || offscreenSubtreeIsHidden; + case HostPortal: { + { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + } - if (newOffscreenSubtreeIsHidden); - else { - // The Offscreen tree is visible. - var wasHidden = current !== null && current.memoizedState !== null; - var newOffscreenSubtreeWasHidden = - wasHidden || offscreenSubtreeWasHidden; - var prevOffscreenSubtreeIsHidden = offscreenSubtreeIsHidden; - var prevOffscreenSubtreeWasHidden = offscreenSubtreeWasHidden; - offscreenSubtreeIsHidden = newOffscreenSubtreeIsHidden; - offscreenSubtreeWasHidden = newOffscreenSubtreeWasHidden; + if (flags & Update) { + { + var portal = finishedWork.stateNode; + var _containerInfo = portal.containerInfo; + var _pendingChildren = portal.pendingChildren; - if (offscreenSubtreeWasHidden && !prevOffscreenSubtreeWasHidden) { - // This is the root of a reappearing boundary. As we continue - // traversing the layout effects, we must also re-mount layout - // effects that were unmounted when the Offscreen subtree was - // hidden. So this is a superset of the normal commitLayoutEffects. - var includeWorkInProgressEffects = - (finishedWork.subtreeFlags & LayoutMask) !== NoFlags$1; - recursivelyTraverseReappearLayoutEffects( - finishedRoot, - finishedWork, - includeWorkInProgressEffects - ); - } else { - recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); + try { + replaceContainerChildren(_containerInfo, _pendingChildren); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); } - - offscreenSubtreeIsHidden = prevOffscreenSubtreeIsHidden; - offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden; } - } else { - recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); } - if (flags & Ref) { - var props = finishedWork.memoizedProps; + return; + } - if (props.mode === "manual") { - safelyAttachRef(finishedWork, finishedWork.return); - } else { - safelyDetachRef(finishedWork, finishedWork.return); + case SuspenseComponent: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + var offscreenFiber = finishedWork.child; + + if (offscreenFiber.flags & Visibility) { + var newState = offscreenFiber.memoizedState; + var isHidden = newState !== null; + + if (isHidden) { + var wasHidden = + offscreenFiber.alternate !== null && + offscreenFiber.alternate.memoizedState !== null; + + if (!wasHidden) { + // TODO: Move to passive phase + markCommitTimeOfFallback(); + } } } - break; - } + if (flags & Update) { + try { + commitSuspenseCallback(finishedWork); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } - default: { - recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); - break; + var retryQueue = finishedWork.updateQueue; + + if (retryQueue !== null) { + finishedWork.updateQueue = null; + attachSuspenseRetryListeners(finishedWork, retryQueue); + } + } + + return; } - } -} -function commitAttachRef(finishedWork) { - var ref = finishedWork.ref; + case OffscreenComponent: { + if (flags & Ref) { + if (current !== null) { + safelyDetachRef(current, current.return); + } + } - if (ref !== null) { - var instance = finishedWork.stateNode; - var instanceToUse; + var _newState = finishedWork.memoizedState; - switch (finishedWork.tag) { - case HostHoistable: - case HostSingleton: - case HostComponent: - instanceToUse = getPublicInstance(instance); - break; + var _isHidden = _newState !== null; - default: - instanceToUse = instance; - } // Moved outside to ensure DCE works with this flag + var _wasHidden = current !== null && current.memoizedState !== null; - if (typeof ref === "function") { - if (shouldProfile(finishedWork)) { - try { - startLayoutEffectTimer(); - finishedWork.refCleanup = ref(instanceToUse); - } finally { - recordLayoutEffectDuration(finishedWork); - } + if (finishedWork.mode & ConcurrentMode) { + // Before committing the children, track on the stack whether this + // offscreen subtree was already hidden, so that we don't unmount the + // effects again. + var prevOffscreenSubtreeIsHidden = offscreenSubtreeIsHidden; + var prevOffscreenSubtreeWasHidden = offscreenSubtreeWasHidden; + offscreenSubtreeIsHidden = prevOffscreenSubtreeIsHidden || _isHidden; + offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden || _wasHidden; + recursivelyTraverseMutationEffects(root, finishedWork); + offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden; + offscreenSubtreeIsHidden = prevOffscreenSubtreeIsHidden; } else { - finishedWork.refCleanup = ref(instanceToUse); + recursivelyTraverseMutationEffects(root, finishedWork); } - } else { - { - if (!ref.hasOwnProperty("current")) { - error( - "Unexpected ref object provided for %s. " + - "Use either a ref-setter function or React.createRef().", - getComponentNameFromFiber(finishedWork) - ); - } - } // $FlowFixMe unable to narrow type to the non-function case - ref.current = instanceToUse; - } - } -} + commitReconciliationEffects(finishedWork); + var offscreenInstance = finishedWork.stateNode; // TODO: Add explicit effect flag to set _current. -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; + offscreenInstance._current = finishedWork; // Offscreen stores pending changes to visibility in `_pendingVisibility`. This is + // to support batching of `attach` and `detach` calls. - if (alternate !== null) { - alternate.return = null; - } + offscreenInstance._visibility &= ~OffscreenDetached; + offscreenInstance._visibility |= + offscreenInstance._pendingVisibility & OffscreenDetached; - fiber.return = null; -} + if (flags & Visibility) { + // Track the current state on the Offscreen instance so we can + // read it during an event + if (_isHidden) { + offscreenInstance._visibility &= ~OffscreenVisible; + } else { + offscreenInstance._visibility |= OffscreenVisible; + } -function detachFiberAfterEffects(fiber) { - var alternate = fiber.alternate; + if (_isHidden) { + var isUpdate = current !== null; + var wasHiddenByAncestorOffscreen = + offscreenSubtreeIsHidden || offscreenSubtreeWasHidden; // Only trigger disapper layout effects if: + // - This is an update, not first mount. + // - This Offscreen was not hidden before. + // - Ancestor Offscreen was not hidden in previous commit. - if (alternate !== null) { - fiber.alternate = null; - detachFiberAfterEffects(alternate); - } // Clear cyclical Fiber fields. This level alone is designed to roughly - // approximate the planned Fiber refactor. In that world, `setState` will be - // bound to a special "instance" object instead of a Fiber. The Instance - // object will not have any of these fields. It will only be connected to - // the fiber tree via a single link at the root. So if this level alone is - // sufficient to fix memory issues, that bodes well for our plans. + if (isUpdate && !_wasHidden && !wasHiddenByAncestorOffscreen) { + if ((finishedWork.mode & ConcurrentMode) !== NoMode) { + // Disappear the layout effects of all the children + recursivelyTraverseDisappearLayoutEffects(finishedWork); + } + } + } // Offscreen with manual mode manages visibility manually. + } // TODO: Move to passive phase - fiber.child = null; - fiber.deletions = null; - fiber.sibling = null; // The `stateNode` is cyclical because on host nodes it points to the host + if (flags & Update) { + var offscreenQueue = finishedWork.updateQueue; - fiber.stateNode = null; + if (offscreenQueue !== null) { + var _retryQueue = offscreenQueue.retryQueue; - { - fiber._debugOwner = null; - } // Theoretically, nothing in here should be necessary, because we already - // disconnected the fiber from the tree. So even if something leaks this - // particular fiber, it won't leak anything else. + if (_retryQueue !== null) { + offscreenQueue.retryQueue = null; + attachSuspenseRetryListeners(finishedWork, _retryQueue); + } + } + } - fiber.return = null; - fiber.dependencies = null; - fiber.memoizedProps = null; - fiber.memoizedState = null; - fiber.pendingProps = null; - fiber.stateNode = null; // TODO: Move to `commitPassiveUnmountInsideDeletedTreeOnFiber` instead. + return; + } - fiber.updateQueue = null; -} + case SuspenseListComponent: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); -function emptyPortalContainer(current) { - var portal = current.stateNode; - var containerInfo = portal.containerInfo; - createContainerChildSet(containerInfo); -} + if (flags & Update) { + var _retryQueue2 = finishedWork.updateQueue; -function commitPlacement(finishedWork) { - { - return; + if (_retryQueue2 !== null) { + finishedWork.updateQueue = null; + attachSuspenseRetryListeners(finishedWork, _retryQueue2); + } + } + + return; + } + + case ScopeComponent: { + return; + } + + default: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + return; + } } } -function commitDeletionEffects(root, returnFiber, deletedFiber) { - { - // Detach refs and call componentWillUnmount() on the whole subtree. - commitDeletionEffectsOnFiber(root, returnFiber, deletedFiber); - } +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; - detachFiberMutation(deletedFiber); -} + 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. -function recursivelyTraverseDeletionEffects( - finishedRoot, - nearestMountedAncestor, - parent -) { - // TODO: Use a static flag to skip trees that don't have unmount effects - var child = parent.child; + finishedWork.flags &= ~Placement; + } - while (child !== null) { - commitDeletionEffectsOnFiber(finishedRoot, nearestMountedAncestor, child); - child = child.sibling; + if (flags & Hydrating) { + finishedWork.flags &= ~Hydrating; } } -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 commitLayoutEffects(finishedWork, root, committedLanes) { + inProgressLanes = committedLanes; + inProgressRoot = root; + var current = finishedWork.alternate; + commitLayoutEffectOnFiber(root, current, finishedWork); + inProgressLanes = null; + inProgressRoot = null; +} - switch (deletedFiber.tag) { - case HostHoistable: - // eslint-disable-next-line no-fallthrough +function recursivelyTraverseLayoutEffects(root, parentFiber, lanes) { + var prevDebugFiber = getCurrentFiber(); - case HostSingleton: - // eslint-disable-next-line no-fallthrough + if (parentFiber.subtreeFlags & LayoutMask) { + var child = parentFiber.child; - case HostComponent: { - if (!offscreenSubtreeWasHidden) { - safelyDetachRef(deletedFiber, nearestMountedAncestor); - } // Intentional fallthrough to next branch + while (child !== null) { + setCurrentFiber(child); + var current = child.alternate; + commitLayoutEffectOnFiber(root, current, child); + child = child.sibling; } - // 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. - { - recursivelyTraverseDeletionEffects( - finishedRoot, - nearestMountedAncestor, - deletedFiber - ); + setCurrentFiber(prevDebugFiber); +} + +function disappearLayoutEffects(finishedWork) { + switch (finishedWork.tag) { + case FunctionComponent: + case ForwardRef: + case MemoComponent: + case SimpleMemoComponent: { + // TODO (Offscreen) Check: flags & LayoutStatic + if (shouldProfile(finishedWork)) { + try { + startLayoutEffectTimer(); + commitHookEffectListUnmount( + Layout, + finishedWork, + finishedWork.return + ); + } finally { + recordLayoutEffectDuration(finishedWork); + } + } else { + commitHookEffectListUnmount(Layout, finishedWork, finishedWork.return); } - return; + recursivelyTraverseDisappearLayoutEffects(finishedWork); + break; } - case DehydratedFragment: { - return; - } + case ClassComponent: { + // TODO (Offscreen) Check: flags & RefStatic + safelyDetachRef(finishedWork, finishedWork.return); + var instance = finishedWork.stateNode; - case HostPortal: { - { - emptyPortalContainer(deletedFiber); - recursivelyTraverseDeletionEffects( - finishedRoot, - nearestMountedAncestor, - deletedFiber + if (typeof instance.componentWillUnmount === "function") { + safelyCallComponentWillUnmount( + finishedWork, + finishedWork.return, + instance ); } - return; + recursivelyTraverseDisappearLayoutEffects(finishedWork); + break; } - case FunctionComponent: - case ForwardRef: - case MemoComponent: - case SimpleMemoComponent: { - if (!offscreenSubtreeWasHidden) { - var updateQueue = deletedFiber.updateQueue; + case HostHoistable: + case HostSingleton: + case HostComponent: { + // TODO (Offscreen) Check: flags & RefStatic + safelyDetachRef(finishedWork, finishedWork.return); + recursivelyTraverseDisappearLayoutEffects(finishedWork); + break; + } - if (updateQueue !== null) { - var lastEffect = updateQueue.lastEffect; + case OffscreenComponent: { + // TODO (Offscreen) Check: flags & RefStatic + safelyDetachRef(finishedWork, finishedWork.return); + var isHidden = finishedWork.memoizedState !== null; - if (lastEffect !== null) { - var firstEffect = lastEffect.next; - var effect = firstEffect; + if (isHidden); + else { + recursivelyTraverseDisappearLayoutEffects(finishedWork); + } - do { - var _effect = effect, - destroy = _effect.destroy, - tag = _effect.tag; + break; + } - if (destroy !== undefined) { - if ((tag & Insertion) !== NoFlags) { - safelyCallDestroy( - deletedFiber, - nearestMountedAncestor, - destroy - ); - } else if ((tag & Layout) !== NoFlags) { - { - markComponentLayoutEffectUnmountStarted(deletedFiber); - } + default: { + recursivelyTraverseDisappearLayoutEffects(finishedWork); + break; + } + } +} - if (shouldProfile(deletedFiber)) { - startLayoutEffectTimer(); - safelyCallDestroy( - deletedFiber, - nearestMountedAncestor, - destroy - ); - recordLayoutEffectDuration(deletedFiber); - } else { - safelyCallDestroy( - deletedFiber, - nearestMountedAncestor, - destroy - ); - } +function recursivelyTraverseDisappearLayoutEffects(parentFiber) { + // TODO (Offscreen) Check: flags & (RefStatic | LayoutStatic) + var child = parentFiber.child; - { - markComponentLayoutEffectUnmountStopped(); - } - } - } + while (child !== null) { + disappearLayoutEffects(child); + child = child.sibling; + } +} - effect = effect.next; - } while (effect !== firstEffect); - } - } - } +function reappearLayoutEffects( + finishedRoot, + current, + finishedWork, // This function visits both newly finished work and nodes that were re-used + // from a previously committed tree. We cannot check non-static flags if the + // node was reused. + includeWorkInProgressEffects +) { + // Turn on layout effects in a tree that previously disappeared. + var flags = finishedWork.flags; - recursivelyTraverseDeletionEffects( + switch (finishedWork.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { + recursivelyTraverseReappearLayoutEffects( finishedRoot, - nearestMountedAncestor, - deletedFiber - ); - return; + finishedWork, + includeWorkInProgressEffects + ); // TODO: Check flags & LayoutStatic + + commitHookLayoutEffects(finishedWork, Layout); + break; } case ClassComponent: { - if (!offscreenSubtreeWasHidden) { - safelyDetachRef(deletedFiber, nearestMountedAncestor); - var instance = deletedFiber.stateNode; + recursivelyTraverseReappearLayoutEffects( + finishedRoot, + finishedWork, + includeWorkInProgressEffects + ); // TODO: Check for LayoutStatic flag - if (typeof instance.componentWillUnmount === "function") { - safelyCallComponentWillUnmount( - deletedFiber, - nearestMountedAncestor, - instance - ); + var instance = finishedWork.stateNode; + + if (typeof instance.componentDidMount === "function") { + try { + instance.componentDidMount(); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); } - } + } // Commit any callbacks that would have fired while the component + // was hidden. - recursivelyTraverseDeletionEffects( - finishedRoot, - nearestMountedAncestor, - deletedFiber - ); - return; - } + var updateQueue = finishedWork.updateQueue; - case ScopeComponent: { - recursivelyTraverseDeletionEffects( - finishedRoot, - nearestMountedAncestor, - deletedFiber - ); - return; + if (updateQueue !== null) { + commitHiddenCallbacks(updateQueue, instance); + } // If this is newly finished work, check for setState callbacks + + if (includeWorkInProgressEffects && flags & Callback) { + commitClassCallbacks(finishedWork); + } // TODO: Check flags & RefStatic + + safelyAttachRef(finishedWork, finishedWork.return); + break; } + // Unlike commitLayoutEffectsOnFiber, we don't need to handle HostRoot + // because this function only visits nodes that are inside an + // Offscreen fiber. + // case HostRoot: { + // ... + // } - case OffscreenComponent: { - safelyDetachRef(deletedFiber, nearestMountedAncestor); + case HostHoistable: + case HostSingleton: + case HostComponent: { + recursivelyTraverseReappearLayoutEffects( + finishedRoot, + finishedWork, + includeWorkInProgressEffects + ); // Renderers may schedule work to be done after host components are mounted + // (eg DOM renderer may schedule auto-focus for inputs and form controls). + // These effects should only be committed when components are first mounted, + // aka when there is no current/alternate. - if (deletedFiber.mode & ConcurrentMode) { - // If this offscreen component is hidden, we already unmounted it. Before - // deleting the children, track that it's already unmounted so that we - // don't attempt to unmount the effects again. - // TODO: If the tree is hidden, in most cases we should be able to skip - // over the nested children entirely. An exception is we haven't yet found - // the topmost host node to delete, which we already track on the stack. - // But the other case is portals, which need to be detached no matter how - // deeply they are nested. We should use a subtree flag to track whether a - // subtree includes a nested portal. - var prevOffscreenSubtreeWasHidden = offscreenSubtreeWasHidden; - offscreenSubtreeWasHidden = - prevOffscreenSubtreeWasHidden || deletedFiber.memoizedState !== null; - recursivelyTraverseDeletionEffects( - finishedRoot, - nearestMountedAncestor, - deletedFiber - ); - offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden; - } else { - recursivelyTraverseDeletionEffects( - finishedRoot, - nearestMountedAncestor, - deletedFiber - ); - } + if (includeWorkInProgressEffects && current === null && flags & Update) { + commitHostComponentMount(finishedWork); + } // TODO: Check flags & Ref + safelyAttachRef(finishedWork, finishedWork.return); break; } - default: { - recursivelyTraverseDeletionEffects( + case Profiler: { + recursivelyTraverseReappearLayoutEffects( finishedRoot, - nearestMountedAncestor, - deletedFiber - ); - return; - } - } -} + finishedWork, + includeWorkInProgressEffects + ); // TODO: Figure out how Profiler updates should work with Offscreen -function commitSuspenseCallback(finishedWork) {} + if (includeWorkInProgressEffects && flags & Update) { + commitProfilerUpdate(finishedWork, current); + } -function getRetryCache(finishedWork) { - // TODO: Unify the interface for the retry cache so we don't have to switch - // on the tag like this. - switch (finishedWork.tag) { - case SuspenseComponent: - case SuspenseListComponent: { - var retryCache = finishedWork.stateNode; + break; + } - if (retryCache === null) { - retryCache = finishedWork.stateNode = new PossiblyWeakSet(); - } + case SuspenseComponent: { + recursivelyTraverseReappearLayoutEffects( + finishedRoot, + finishedWork, + includeWorkInProgressEffects + ); // TODO: Figure out how Suspense hydration callbacks should work - return retryCache; + break; } case OffscreenComponent: { - var instance = finishedWork.stateNode; - var _retryCache = instance._retryCache; + var offscreenState = finishedWork.memoizedState; + var isHidden = offscreenState !== null; - if (_retryCache === null) { - _retryCache = instance._retryCache = new PossiblyWeakSet(); - } + if (isHidden); + else { + recursivelyTraverseReappearLayoutEffects( + finishedRoot, + finishedWork, + includeWorkInProgressEffects + ); + } // TODO: Check flags & Ref - return _retryCache; + safelyAttachRef(finishedWork, finishedWork.return); + break; } default: { - throw new Error( - "Unexpected Suspense handler tag (" + - finishedWork.tag + - "). This is a " + - "bug in React." + recursivelyTraverseReappearLayoutEffects( + finishedRoot, + finishedWork, + includeWorkInProgressEffects ); + break; } } } -function detachOffscreenInstance(instance) { - var fiber = instance._current; +function recursivelyTraverseReappearLayoutEffects( + finishedRoot, + parentFiber, + includeWorkInProgressEffects +) { + // This function visits both newly finished work and nodes that were re-used + // from a previously committed tree. We cannot check non-static flags if the + // node was reused. + var childShouldIncludeWorkInProgressEffects = + includeWorkInProgressEffects && + (parentFiber.subtreeFlags & LayoutMask) !== NoFlags$1; // TODO (Offscreen) Check: flags & (RefStatic | LayoutStatic) - if (fiber === null) { - throw new Error( - "Calling Offscreen.detach before instance handle has been set." + var prevDebugFiber = getCurrentFiber(); + var child = parentFiber.child; + + while (child !== null) { + var current = child.alternate; + reappearLayoutEffects( + finishedRoot, + current, + child, + childShouldIncludeWorkInProgressEffects ); + child = child.sibling; } - if ((instance._pendingVisibility & OffscreenDetached) !== NoFlags$1) { - // The instance is already detached, this is a noop. - return; - } // TODO: There is an opportunity to optimise this by not entering commit phase - // and unmounting effects directly. - - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); - - if (root !== null) { - instance._pendingVisibility |= OffscreenDetached; - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); - } + setCurrentFiber(prevDebugFiber); } -function attachOffscreenInstance(instance) { - var fiber = instance._current; - - if (fiber === null) { - throw new Error( - "Calling Offscreen.detach before instance handle has been set." - ); - } - if ((instance._pendingVisibility & OffscreenDetached) === NoFlags$1) { - // The instance is already attached, this is a noop. - return; - } +function commitHookPassiveMountEffects(finishedWork, hookFlags) { + if (shouldProfile(finishedWork)) { + startPassiveEffectTimer(); - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + try { + commitHookEffectListMount(hookFlags, finishedWork); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } - if (root !== null) { - instance._pendingVisibility &= ~OffscreenDetached; - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + recordPassiveEffectDuration(finishedWork); + } else { + try { + commitHookEffectListMount(hookFlags, finishedWork); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } } } -function attachSuspenseRetryListeners(finishedWork, wakeables) { - // If this boundary just timed out, then it will have a set of wakeables. - // For each wakeable, attach a listener so that when it resolves, React - // attempts to re-render the boundary in the primary (pre-timeout) state. - var retryCache = getRetryCache(finishedWork); - wakeables.forEach(function (wakeable) { - // Memoize using the boundary fiber to prevent redundant listeners. - var retry = resolveRetryWakeable.bind(null, finishedWork, wakeable); - - if (!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); +function commitPassiveMountEffects( + root, + finishedWork, + committedLanes, + committedTransitions +) { setCurrentFiber(finishedWork); - inProgressLanes = null; - inProgressRoot = null; + commitPassiveMountOnFiber(root, finishedWork); + resetCurrentFiber(); } -function recursivelyTraverseMutationEffects(root, parentFiber, lanes) { - // Deletions effects can be scheduled on any fiber type. They need to happen - // before the children effects hae fired. - var deletions = parentFiber.deletions; - - if (deletions !== null) { - for (var i = 0; i < deletions.length; i++) { - var childToDelete = deletions[i]; - - try { - commitDeletionEffects(root, parentFiber, childToDelete); - } catch (error) { - captureCommitPhaseError(childToDelete, parentFiber, error); - } - } - } - +function recursivelyTraversePassiveMountEffects( + root, + parentFiber, + committedLanes, + committedTransitions +) { var prevDebugFiber = getCurrentFiber(); - if (parentFiber.subtreeFlags & MutationMask) { + if (parentFiber.subtreeFlags & PassiveMask) { var child = parentFiber.child; while (child !== null) { setCurrentFiber(child); - commitMutationEffectsOnFiber(child, root); + commitPassiveMountOnFiber(root, child); child = child.sibling; } } @@ -21046,347 +21316,289 @@ function recursivelyTraverseMutationEffects(root, parentFiber, lanes) { setCurrentFiber(prevDebugFiber); } -function commitMutationEffectsOnFiber(finishedWork, root, lanes) { - var current = finishedWork.alternate; - var flags = finishedWork.flags; // The effect flag should be checked *after* we refine the type of fiber, - // because the fiber tag is more specific. An exception is any flag related - // to reconciliation, because those can be set on all fiber types. +function commitPassiveMountOnFiber( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions +) { + // When updating this function, also update reconnectPassiveEffects, which does + // most of the same things when an offscreen tree goes from hidden -> visible, + // or when toggling effects inside a hidden tree. + var flags = finishedWork.flags; switch (finishedWork.tag) { case FunctionComponent: case ForwardRef: - case 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. - - if (shouldProfile(finishedWork)) { - 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); - } - } - } - - return; - } - - case ClassComponent: { - recursivelyTraverseMutationEffects(root, finishedWork); - commitReconciliationEffects(finishedWork); - - if (flags & Ref) { - if (current !== null) { - safelyDetachRef(current, current.return); - } - } - - if (flags & Callback && offscreenSubtreeIsHidden) { - var updateQueue = finishedWork.updateQueue; - - if (updateQueue !== null) { - deferHiddenCallbacks(updateQueue); - } - } - - return; - } - - case HostHoistable: - // eslint-disable-next-line-no-fallthrough - - case HostSingleton: - // eslint-disable-next-line-no-fallthrough - - case HostComponent: { - recursivelyTraverseMutationEffects(root, finishedWork); - commitReconciliationEffects(finishedWork); + recursivelyTraversePassiveMountEffects(finishedRoot, finishedWork); - if (flags & Ref) { - if (current !== null) { - safelyDetachRef(current, current.return); - } + if (flags & Passive$1) { + commitHookPassiveMountEffects(finishedWork, Passive | HasEffect); } - return; - } - - case HostText: { - recursivelyTraverseMutationEffects(root, finishedWork); - commitReconciliationEffects(finishedWork); - - return; + break; } case HostRoot: { - { - recursivelyTraverseMutationEffects(root, finishedWork); - commitReconciliationEffects(finishedWork); - } - - if (flags & Update) { - { - var containerInfo = root.containerInfo; - var pendingChildren = root.pendingChildren; - - try { - replaceContainerChildren(containerInfo, pendingChildren); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } - } - } + recursivelyTraversePassiveMountEffects(finishedRoot, finishedWork); - return; + break; } - case HostPortal: { + case LegacyHiddenComponent: { { - recursivelyTraverseMutationEffects(root, finishedWork); - commitReconciliationEffects(finishedWork); - } - - 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); - } - } + recursivelyTraversePassiveMountEffects(finishedRoot, finishedWork); } - return; + break; } - case SuspenseComponent: { - recursivelyTraverseMutationEffects(root, finishedWork); - commitReconciliationEffects(finishedWork); - var offscreenFiber = finishedWork.child; - - if (offscreenFiber.flags & Visibility) { - var newState = offscreenFiber.memoizedState; - var isHidden = newState !== null; - - if (isHidden) { - var wasHidden = - offscreenFiber.alternate !== null && - offscreenFiber.alternate.memoizedState !== null; + case OffscreenComponent: { + // TODO: Pass `current` as argument to this function + var _instance3 = finishedWork.stateNode; + var nextState = finishedWork.memoizedState; + var isHidden = nextState !== null; - if (!wasHidden) { - // TODO: Move to passive phase - markCommitTimeOfFallback(); + if (isHidden) { + if (_instance3._visibility & OffscreenPassiveEffectsConnected) { + // The effects are currently connected. Update them. + recursivelyTraversePassiveMountEffects(finishedRoot, finishedWork); + } else { + if (finishedWork.mode & ConcurrentMode); + else { + // Legacy Mode: Fire the effects even if the tree is hidden. + _instance3._visibility |= OffscreenPassiveEffectsConnected; + recursivelyTraversePassiveMountEffects(finishedRoot, finishedWork); } } - } - - if (flags & Update) { - try { - commitSuspenseCallback(finishedWork); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } - - var wakeables = finishedWork.updateQueue; - - if (wakeables !== null) { - finishedWork.updateQueue = null; - attachSuspenseRetryListeners(finishedWork, wakeables); + } else { + // Tree is visible + if (_instance3._visibility & OffscreenPassiveEffectsConnected) { + // The effects are currently connected. Update them. + recursivelyTraversePassiveMountEffects(finishedRoot, finishedWork); + } else { + // The effects are currently disconnected. Reconnect them, while also + // firing effects inside newly mounted trees. This also applies to + // the initial render. + _instance3._visibility |= OffscreenPassiveEffectsConnected; + recursivelyTraverseReconnectPassiveEffects( + finishedRoot, + finishedWork + ); } } - return; + break; } - case OffscreenComponent: { - if (flags & Ref) { - if (current !== null) { - safelyDetachRef(current, current.return); - } - } - - var _newState = finishedWork.memoizedState; + case CacheComponent: { + recursivelyTraversePassiveMountEffects(finishedRoot, finishedWork); - var _isHidden = _newState !== null; + break; + } - var _wasHidden = current !== null && current.memoizedState !== null; + case TracingMarkerComponent: + // eslint-disable-next-line-no-fallthrough - if (finishedWork.mode & ConcurrentMode) { - // Before committing the children, track on the stack whether this - // offscreen subtree was already hidden, so that we don't unmount the - // effects again. - var prevOffscreenSubtreeIsHidden = offscreenSubtreeIsHidden; - var prevOffscreenSubtreeWasHidden = offscreenSubtreeWasHidden; - offscreenSubtreeIsHidden = prevOffscreenSubtreeIsHidden || _isHidden; - offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden || _wasHidden; - recursivelyTraverseMutationEffects(root, finishedWork); - offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden; - offscreenSubtreeIsHidden = prevOffscreenSubtreeIsHidden; - } else { - recursivelyTraverseMutationEffects(root, finishedWork); - } + default: { + recursivelyTraversePassiveMountEffects(finishedRoot, finishedWork); + break; + } + } +} - commitReconciliationEffects(finishedWork); - var offscreenInstance = finishedWork.stateNode; // TODO: Add explicit effect flag to set _current. +function recursivelyTraverseReconnectPassiveEffects( + finishedRoot, + parentFiber, + committedLanes, + committedTransitions, + includeWorkInProgressEffects +) { + var prevDebugFiber = getCurrentFiber(); + var child = parentFiber.child; - offscreenInstance._current = finishedWork; // Offscreen stores pending changes to visibility in `_pendingVisibility`. This is - // to support batching of `attach` and `detach` calls. + while (child !== null) { + reconnectPassiveEffects(finishedRoot, child); + child = child.sibling; + } - offscreenInstance._visibility &= ~OffscreenDetached; - offscreenInstance._visibility |= - offscreenInstance._pendingVisibility & OffscreenDetached; + setCurrentFiber(prevDebugFiber); +} - if (flags & Visibility) { - // Track the current state on the Offscreen instance so we can - // read it during an event - if (_isHidden) { - offscreenInstance._visibility &= ~OffscreenVisible; - } else { - offscreenInstance._visibility |= OffscreenVisible; - } +function reconnectPassiveEffects( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions, // This function visits both newly finished work and nodes that were re-used + // from a previously committed tree. We cannot check non-static flags if the + // node was reused. + includeWorkInProgressEffects +) { + switch (finishedWork.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { + recursivelyTraverseReconnectPassiveEffects(finishedRoot, finishedWork); // TODO: Check for PassiveStatic flag - if (_isHidden) { - var isUpdate = current !== null; - var wasHiddenByAncestorOffscreen = - offscreenSubtreeIsHidden || offscreenSubtreeWasHidden; // Only trigger disapper layout effects if: - // - This is an update, not first mount. - // - This Offscreen was not hidden before. - // - Ancestor Offscreen was not hidden in previous commit. + commitHookPassiveMountEffects(finishedWork, Passive); + break; + } + // Unlike commitPassiveMountOnFiber, we don't need to handle HostRoot + // because this function only visits nodes that are inside an + // Offscreen fiber. + // case HostRoot: { + // ... + // } - if (isUpdate && !_wasHidden && !wasHiddenByAncestorOffscreen) { - if ((finishedWork.mode & ConcurrentMode) !== NoMode) { - // Disappear the layout effects of all the children - recursivelyTraverseDisappearLayoutEffects(finishedWork); - } - } - } // Offscreen with manual mode manages visibility manually. - } // TODO: Move to passive phase + case LegacyHiddenComponent: { + { + recursivelyTraverseReconnectPassiveEffects(finishedRoot, finishedWork); + } - if (flags & Update) { - var offscreenQueue = finishedWork.updateQueue; + break; + } - if (offscreenQueue !== null) { - var _wakeables = offscreenQueue.wakeables; + case OffscreenComponent: { + var _instance4 = finishedWork.stateNode; + var nextState = finishedWork.memoizedState; + var isHidden = nextState !== null; - if (_wakeables !== null) { - offscreenQueue.wakeables = null; - attachSuspenseRetryListeners(finishedWork, _wakeables); + if (isHidden) { + if (_instance4._visibility & OffscreenPassiveEffectsConnected) { + // The effects are currently connected. Update them. + recursivelyTraverseReconnectPassiveEffects( + finishedRoot, + finishedWork + ); + } else { + if (finishedWork.mode & ConcurrentMode); + else { + // Legacy Mode: Fire the effects even if the tree is hidden. + _instance4._visibility |= OffscreenPassiveEffectsConnected; + recursivelyTraverseReconnectPassiveEffects( + finishedRoot, + finishedWork + ); } } + } else { + // Tree is visible + // Since we're already inside a reconnecting tree, it doesn't matter + // whether the effects are currently connected. In either case, we'll + // continue traversing the tree and firing all the effects. + // + // We do need to set the "connected" flag on the instance, though. + _instance4._visibility |= OffscreenPassiveEffectsConnected; + recursivelyTraverseReconnectPassiveEffects(finishedRoot, finishedWork); } - return; + break; } - case SuspenseListComponent: { - recursivelyTraverseMutationEffects(root, finishedWork); - commitReconciliationEffects(finishedWork); - - if (flags & Update) { - var _wakeables2 = finishedWork.updateQueue; - - if (_wakeables2 !== null) { - finishedWork.updateQueue = null; - attachSuspenseRetryListeners(finishedWork, _wakeables2); - } - } + case CacheComponent: { + recursivelyTraverseReconnectPassiveEffects(finishedRoot, finishedWork); - return; + break; } - case ScopeComponent: { - return; - } + case TracingMarkerComponent: + // eslint-disable-next-line-no-fallthrough default: { - recursivelyTraverseMutationEffects(root, finishedWork); - commitReconciliationEffects(finishedWork); - return; + recursivelyTraverseReconnectPassiveEffects(finishedRoot, finishedWork); + break; } } } -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 commitPassiveUnmountEffects(finishedWork) { + setCurrentFiber(finishedWork); + commitPassiveUnmountOnFiber(finishedWork); + resetCurrentFiber(); +} - 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. +function detachAlternateSiblings(parentFiber) { + // A fiber was deleted from this parent fiber, but it's still part of the + // previous (alternate) parent fiber's list of children. Because children + // are a linked list, an earlier sibling that's still alive will be + // connected to the deleted fiber via its `alternate`: + // + // live fiber --alternate--> previous live fiber --sibling--> deleted + // fiber + // + // We can't disconnect `alternate` on nodes that haven't been deleted yet, + // but we can disconnect the `sibling` and `child` pointers. + var previousFiber = parentFiber.alternate; - finishedWork.flags &= ~Placement; - } + if (previousFiber !== null) { + var detachedChild = previousFiber.child; - if (flags & Hydrating) { - finishedWork.flags &= ~Hydrating; + if (detachedChild !== null) { + previousFiber.child = null; + + do { + // $FlowFixMe[incompatible-use] found when upgrading Flow + var detachedSibling = detachedChild.sibling; // $FlowFixMe[incompatible-use] found when upgrading Flow + + detachedChild.sibling = null; + detachedChild = detachedSibling; + } while (detachedChild !== null); + } } } -function commitLayoutEffects(finishedWork, root, committedLanes) { - inProgressLanes = committedLanes; - inProgressRoot = root; - var current = finishedWork.alternate; - commitLayoutEffectOnFiber(root, current, finishedWork); - inProgressLanes = null; - inProgressRoot = null; +function commitHookPassiveUnmountEffects( + finishedWork, + nearestMountedAncestor, + hookFlags +) { + if (shouldProfile(finishedWork)) { + startPassiveEffectTimer(); + commitHookEffectListUnmount( + hookFlags, + finishedWork, + nearestMountedAncestor + ); + recordPassiveEffectDuration(finishedWork); + } else { + commitHookEffectListUnmount( + hookFlags, + finishedWork, + nearestMountedAncestor + ); + } } -function recursivelyTraverseLayoutEffects(root, parentFiber, lanes) { - var prevDebugFiber = getCurrentFiber(); +function recursivelyTraversePassiveUnmountEffects(parentFiber) { + // Deletions effects can be scheduled on any fiber type. They need to happen + // before the children effects have fired. + var deletions = parentFiber.deletions; - if (parentFiber.subtreeFlags & LayoutMask) { + if ((parentFiber.flags & ChildDeletion) !== NoFlags$1) { + if (deletions !== null) { + for (var i = 0; i < deletions.length; i++) { + var childToDelete = deletions[i]; // TODO: Convert this to use recursion + + nextEffect = childToDelete; + commitPassiveUnmountEffectsInsideOfDeletedTree_begin( + childToDelete, + parentFiber + ); + } + } + + detachAlternateSiblings(parentFiber); + } + + var prevDebugFiber = getCurrentFiber(); // TODO: Split PassiveMask into separate masks for mount and unmount? + + if (parentFiber.subtreeFlags & PassiveMask) { var child = parentFiber.child; while (child !== null) { setCurrentFiber(child); - var current = child.alternate; - commitLayoutEffectOnFiber(root, current, child); + commitPassiveUnmountOnFiber(child); child = child.sibling; } } @@ -21394,5691 +21606,6034 @@ function recursivelyTraverseLayoutEffects(root, parentFiber, lanes) { setCurrentFiber(prevDebugFiber); } -function disappearLayoutEffects(finishedWork) { - switch (finishedWork.tag) { - case FunctionComponent: - case ForwardRef: - case MemoComponent: - case SimpleMemoComponent: { - // TODO (Offscreen) Check: flags & LayoutStatic - if (shouldProfile(finishedWork)) { - try { - startLayoutEffectTimer(); - commitHookEffectListUnmount( - Layout, - finishedWork, - finishedWork.return - ); - } finally { - recordLayoutEffectDuration(finishedWork); - } - } else { - commitHookEffectListUnmount(Layout, finishedWork, finishedWork.return); - } - - recursivelyTraverseDisappearLayoutEffects(finishedWork); - break; - } - - case ClassComponent: { - // TODO (Offscreen) Check: flags & RefStatic - safelyDetachRef(finishedWork, finishedWork.return); - var instance = finishedWork.stateNode; +function commitPassiveUnmountOnFiber(finishedWork) { + switch (finishedWork.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { + recursivelyTraversePassiveUnmountEffects(finishedWork); - if (typeof instance.componentWillUnmount === "function") { - safelyCallComponentWillUnmount( + if (finishedWork.flags & Passive$1) { + commitHookPassiveUnmountEffects( finishedWork, finishedWork.return, - instance + Passive | HasEffect ); } - recursivelyTraverseDisappearLayoutEffects(finishedWork); - break; - } - - case HostHoistable: - case HostSingleton: - case HostComponent: { - // TODO (Offscreen) Check: flags & RefStatic - safelyDetachRef(finishedWork, finishedWork.return); - recursivelyTraverseDisappearLayoutEffects(finishedWork); break; } case OffscreenComponent: { - // TODO (Offscreen) Check: flags & RefStatic - safelyDetachRef(finishedWork, finishedWork.return); - var isHidden = finishedWork.memoizedState !== null; + var instance = finishedWork.stateNode; + var nextState = finishedWork.memoizedState; + var isHidden = nextState !== null; - if (isHidden); - else { - recursivelyTraverseDisappearLayoutEffects(finishedWork); + if ( + isHidden && + instance._visibility & OffscreenPassiveEffectsConnected && // For backwards compatibility, don't unmount when a tree suspends. In + // the future we may change this to unmount after a delay. + (finishedWork.return === null || + finishedWork.return.tag !== SuspenseComponent) + ) { + // The effects are currently connected. Disconnect them. + // TODO: Add option or heuristic to delay before disconnecting the + // effects. Then if the tree reappears before the delay has elapsed, we + // can skip toggling the effects entirely. + instance._visibility &= ~OffscreenPassiveEffectsConnected; + recursivelyTraverseDisconnectPassiveEffects(finishedWork); + } else { + recursivelyTraversePassiveUnmountEffects(finishedWork); } break; } default: { - recursivelyTraverseDisappearLayoutEffects(finishedWork); + recursivelyTraversePassiveUnmountEffects(finishedWork); break; } } } -function recursivelyTraverseDisappearLayoutEffects(parentFiber) { - // TODO (Offscreen) Check: flags & (RefStatic | LayoutStatic) +function recursivelyTraverseDisconnectPassiveEffects(parentFiber) { + // Deletions effects can be scheduled on any fiber type. They need to happen + // before the children effects have fired. + var deletions = parentFiber.deletions; + + if ((parentFiber.flags & ChildDeletion) !== NoFlags$1) { + if (deletions !== null) { + for (var i = 0; i < deletions.length; i++) { + var childToDelete = deletions[i]; // TODO: Convert this to use recursion + + nextEffect = childToDelete; + commitPassiveUnmountEffectsInsideOfDeletedTree_begin( + childToDelete, + parentFiber + ); + } + } + + detachAlternateSiblings(parentFiber); + } + + var prevDebugFiber = getCurrentFiber(); // TODO: Check PassiveStatic flag + var child = parentFiber.child; while (child !== null) { - disappearLayoutEffects(child); + setCurrentFiber(child); + disconnectPassiveEffect(child); child = child.sibling; } -} -function reappearLayoutEffects( - finishedRoot, - current, - finishedWork, // This function visits both newly finished work and nodes that were re-used - // from a previously committed tree. We cannot check non-static flags if the - // node was reused. - includeWorkInProgressEffects -) { - // Turn on layout effects in a tree that previously disappeared. - var flags = finishedWork.flags; + setCurrentFiber(prevDebugFiber); +} +function disconnectPassiveEffect(finishedWork) { switch (finishedWork.tag) { case FunctionComponent: case ForwardRef: case SimpleMemoComponent: { - recursivelyTraverseReappearLayoutEffects( - finishedRoot, + // TODO: Check PassiveStatic flag + commitHookPassiveUnmountEffects( finishedWork, - includeWorkInProgressEffects - ); // TODO: Check flags & LayoutStatic + finishedWork.return, + Passive + ); // When disconnecting passive effects, we fire the effects in the same + // order as during a deletiong: parent before child - commitHookLayoutEffects(finishedWork, Layout); + recursivelyTraverseDisconnectPassiveEffects(finishedWork); break; } - case ClassComponent: { - recursivelyTraverseReappearLayoutEffects( - finishedRoot, - finishedWork, - includeWorkInProgressEffects - ); // TODO: Check for LayoutStatic flag - + case OffscreenComponent: { var instance = finishedWork.stateNode; - if (typeof instance.componentDidMount === "function") { - try { - instance.componentDidMount(); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } - } // Commit any callbacks that would have fired while the component - // was hidden. - - var updateQueue = finishedWork.updateQueue; - - if (updateQueue !== null) { - commitHiddenCallbacks(updateQueue, instance); - } // If this is newly finished work, check for setState callbacks - - if (includeWorkInProgressEffects && flags & Callback) { - commitClassCallbacks(finishedWork); - } // TODO: Check flags & RefStatic - - safelyAttachRef(finishedWork, finishedWork.return); - break; - } - // Unlike commitLayoutEffectsOnFiber, we don't need to handle HostRoot - // because this function only visits nodes that are inside an - // Offscreen fiber. - // case HostRoot: { - // ... - // } - - case HostHoistable: - case HostSingleton: - case HostComponent: { - recursivelyTraverseReappearLayoutEffects( - finishedRoot, - finishedWork, - includeWorkInProgressEffects - ); // Renderers may schedule work to be done after host components are mounted - // (eg DOM renderer may schedule auto-focus for inputs and form controls). - // These effects should only be committed when components are first mounted, - // aka when there is no current/alternate. - - if (includeWorkInProgressEffects && current === null && flags & Update) { - commitHostComponentMount(finishedWork); - } // TODO: Check flags & Ref - - safelyAttachRef(finishedWork, finishedWork.return); - break; - } - - case Profiler: { - recursivelyTraverseReappearLayoutEffects( - finishedRoot, - finishedWork, - includeWorkInProgressEffects - ); // TODO: Figure out how Profiler updates should work with Offscreen - - if (includeWorkInProgressEffects && flags & Update) { - commitProfilerUpdate(finishedWork, current); + if (instance._visibility & OffscreenPassiveEffectsConnected) { + instance._visibility &= ~OffscreenPassiveEffectsConnected; + recursivelyTraverseDisconnectPassiveEffects(finishedWork); } break; } - case SuspenseComponent: { - recursivelyTraverseReappearLayoutEffects( - finishedRoot, - finishedWork, - includeWorkInProgressEffects - ); // TODO: Figure out how Suspense hydration callbacks should work - - break; - } - - case OffscreenComponent: { - var offscreenState = finishedWork.memoizedState; - var isHidden = offscreenState !== null; - - if (isHidden); - else { - recursivelyTraverseReappearLayoutEffects( - finishedRoot, - finishedWork, - includeWorkInProgressEffects - ); - } // TODO: Check flags & Ref - - safelyAttachRef(finishedWork, finishedWork.return); - break; - } - default: { - recursivelyTraverseReappearLayoutEffects( - finishedRoot, - finishedWork, - includeWorkInProgressEffects - ); + recursivelyTraverseDisconnectPassiveEffects(finishedWork); break; } } } -function recursivelyTraverseReappearLayoutEffects( - finishedRoot, - parentFiber, - includeWorkInProgressEffects +function commitPassiveUnmountEffectsInsideOfDeletedTree_begin( + deletedSubtreeRoot, + nearestMountedAncestor ) { - // This function visits both newly finished work and nodes that were re-used - // from a previously committed tree. We cannot check non-static flags if the - // node was reused. - var childShouldIncludeWorkInProgressEffects = - includeWorkInProgressEffects && - (parentFiber.subtreeFlags & LayoutMask) !== NoFlags$1; // TODO (Offscreen) Check: flags & (RefStatic | LayoutStatic) - - var prevDebugFiber = getCurrentFiber(); - var child = parentFiber.child; - - while (child !== null) { - var current = child.alternate; - reappearLayoutEffects( - finishedRoot, - current, - child, - childShouldIncludeWorkInProgressEffects - ); - child = child.sibling; - } - - setCurrentFiber(prevDebugFiber); -} - -function commitHookPassiveMountEffects(finishedWork, hookFlags) { - if (shouldProfile(finishedWork)) { - startPassiveEffectTimer(); - - try { - commitHookEffectListMount(hookFlags, finishedWork); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } + while (nextEffect !== null) { + var fiber = nextEffect; // Deletion effects fire in parent -> child order + // TODO: Check if fiber has a PassiveStatic flag - recordPassiveEffectDuration(finishedWork); - } else { - try { - commitHookEffectListMount(hookFlags, finishedWork); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); + setCurrentFiber(fiber); + commitPassiveUnmountInsideDeletedTreeOnFiber(fiber, nearestMountedAncestor); + resetCurrentFiber(); + var child = fiber.child; // TODO: Only traverse subtree if it has a PassiveStatic flag. + + if (child !== null) { + child.return = fiber; + nextEffect = child; + } else { + commitPassiveUnmountEffectsInsideOfDeletedTree_complete( + deletedSubtreeRoot + ); } } } -function commitPassiveMountEffects( - root, - finishedWork, - committedLanes, - committedTransitions +function commitPassiveUnmountEffectsInsideOfDeletedTree_complete( + deletedSubtreeRoot ) { - setCurrentFiber(finishedWork); - commitPassiveMountOnFiber(root, finishedWork); - resetCurrentFiber(); -} + while (nextEffect !== null) { + var fiber = nextEffect; + var sibling = fiber.sibling; + var returnFiber = fiber.return; // Recursively traverse the entire deleted tree and clean up fiber fields. + // This is more aggressive than ideal, and the long term goal is to only + // have to detach the deleted tree at the root. -function recursivelyTraversePassiveMountEffects( - root, - parentFiber, - committedLanes, - committedTransitions -) { - var prevDebugFiber = getCurrentFiber(); + detachFiberAfterEffects(fiber); - if (parentFiber.subtreeFlags & PassiveMask) { - var child = parentFiber.child; + if (fiber === deletedSubtreeRoot) { + nextEffect = null; + return; + } - while (child !== null) { - setCurrentFiber(child); - commitPassiveMountOnFiber(root, child); - child = child.sibling; + if (sibling !== null) { + sibling.return = returnFiber; + nextEffect = sibling; + return; } - } - setCurrentFiber(prevDebugFiber); + nextEffect = returnFiber; + } } -function commitPassiveMountOnFiber( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions +function commitPassiveUnmountInsideDeletedTreeOnFiber( + current, + nearestMountedAncestor ) { - // When updating this function, also update reconnectPassiveEffects, which does - // most of the same things when an offscreen tree goes from hidden -> visible, - // or when toggling effects inside a hidden tree. - var flags = finishedWork.flags; - - switch (finishedWork.tag) { + switch (current.tag) { case FunctionComponent: case ForwardRef: case SimpleMemoComponent: { - recursivelyTraversePassiveMountEffects(finishedRoot, finishedWork); + commitHookPassiveUnmountEffects(current, nearestMountedAncestor, Passive); + break; + } + } +} - if (flags & Passive$1) { - commitHookPassiveMountEffects(finishedWork, Passive | HasEffect); +function invokeLayoutEffectMountInDEV(fiber) { + { + // We don't need to re-check StrictEffectsMode here. + // This function is only called if that check has already passed. + switch (fiber.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { + try { + commitHookEffectListMount(Layout | HasEffect, fiber); + } catch (error) { + captureCommitPhaseError(fiber, fiber.return, error); + } + + break; } - break; - } + case ClassComponent: { + var instance = fiber.stateNode; - case HostRoot: { - recursivelyTraversePassiveMountEffects(finishedRoot, finishedWork); + try { + instance.componentDidMount(); + } catch (error) { + captureCommitPhaseError(fiber, fiber.return, error); + } - break; + break; + } } + } +} - case LegacyHiddenComponent: { - { - recursivelyTraversePassiveMountEffects(finishedRoot, finishedWork); - } +function invokePassiveEffectMountInDEV(fiber) { + { + // We don't need to re-check StrictEffectsMode here. + // This function is only called if that check has already passed. + switch (fiber.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { + try { + commitHookEffectListMount(Passive | HasEffect, fiber); + } catch (error) { + captureCommitPhaseError(fiber, fiber.return, error); + } - break; + break; + } } + } +} - case OffscreenComponent: { - // TODO: Pass `current` as argument to this function - var _instance3 = finishedWork.stateNode; - var nextState = finishedWork.memoizedState; - var isHidden = nextState !== null; - - if (isHidden) { - if (_instance3._visibility & OffscreenPassiveEffectsConnected) { - // The effects are currently connected. Update them. - recursivelyTraversePassiveMountEffects(finishedRoot, finishedWork); - } else { - if (finishedWork.mode & ConcurrentMode); - else { - // Legacy Mode: Fire the effects even if the tree is hidden. - _instance3._visibility |= OffscreenPassiveEffectsConnected; - recursivelyTraversePassiveMountEffects(finishedRoot, finishedWork); - } - } - } else { - // Tree is visible - if (_instance3._visibility & OffscreenPassiveEffectsConnected) { - // The effects are currently connected. Update them. - recursivelyTraversePassiveMountEffects(finishedRoot, finishedWork); - } else { - // The effects are currently disconnected. Reconnect them, while also - // firing effects inside newly mounted trees. This also applies to - // the initial render. - _instance3._visibility |= OffscreenPassiveEffectsConnected; - recursivelyTraverseReconnectPassiveEffects( - finishedRoot, - finishedWork - ); +function invokeLayoutEffectUnmountInDEV(fiber) { + { + // We don't need to re-check StrictEffectsMode here. + // This function is only called if that check has already passed. + switch (fiber.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { + try { + commitHookEffectListUnmount(Layout | HasEffect, fiber, fiber.return); + } catch (error) { + captureCommitPhaseError(fiber, fiber.return, error); } + + break; } - break; - } + case ClassComponent: { + var instance = fiber.stateNode; - case CacheComponent: { - recursivelyTraversePassiveMountEffects(finishedRoot, finishedWork); + if (typeof instance.componentWillUnmount === "function") { + safelyCallComponentWillUnmount(fiber, fiber.return, instance); + } - break; + break; + } } + } +} - case TracingMarkerComponent: - // eslint-disable-next-line-no-fallthrough - - default: { - recursivelyTraversePassiveMountEffects(finishedRoot, finishedWork); - break; +function invokePassiveEffectUnmountInDEV(fiber) { + { + // We don't need to re-check StrictEffectsMode here. + // This function is only called if that check has already passed. + switch (fiber.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { + try { + commitHookEffectListUnmount(Passive | HasEffect, fiber, fiber.return); + } catch (error) { + captureCommitPhaseError(fiber, fiber.return, error); + } + } } } } -function recursivelyTraverseReconnectPassiveEffects( - finishedRoot, - parentFiber, - committedLanes, - committedTransitions, - includeWorkInProgressEffects -) { - var prevDebugFiber = getCurrentFiber(); - var child = parentFiber.child; +if (typeof Symbol === "function" && Symbol.for) { + var symbolFor = Symbol.for; + symbolFor("selector.component"); + symbolFor("selector.has_pseudo_class"); + symbolFor("selector.role"); + symbolFor("selector.test_id"); + symbolFor("selector.text"); +} + +var ReactCurrentActQueue$1 = ReactSharedInternals.ReactCurrentActQueue; +function isLegacyActEnvironment(fiber) { + { + // Legacy mode. We preserve the behavior of React 17's act. It assumes an + // act environment whenever `jest` is defined, but you can still turn off + // spurious warnings by setting IS_REACT_ACT_ENVIRONMENT explicitly + // to false. + // $FlowFixMe[cannot-resolve-name] Flow doesn't know about IS_REACT_ACT_ENVIRONMENT global + typeof IS_REACT_ACT_ENVIRONMENT !== "undefined" // $FlowFixMe[cannot-resolve-name] + ? IS_REACT_ACT_ENVIRONMENT + : undefined; // $FlowFixMe - Flow doesn't know about jest + return warnsIfNotActing; + } +} +function isConcurrentActEnvironment() { + { + var isReactActEnvironmentGlobal = // $FlowFixMe[cannot-resolve-name] Flow doesn't know about IS_REACT_ACT_ENVIRONMENT global + typeof IS_REACT_ACT_ENVIRONMENT !== "undefined" // $FlowFixMe[cannot-resolve-name] + ? IS_REACT_ACT_ENVIRONMENT + : undefined; + + if ( + !isReactActEnvironmentGlobal && + ReactCurrentActQueue$1.current !== null + ) { + // TODO: Include link to relevant documentation page. + error( + "The current testing environment is not configured to support " + + "act(...)" + ); + } - while (child !== null) { - reconnectPassiveEffects(finishedRoot, child); - child = child.sibling; + return isReactActEnvironmentGlobal; } - - setCurrentFiber(prevDebugFiber); } -function reconnectPassiveEffects( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions, // This function visits both newly finished work and nodes that were re-used - // from a previously committed tree. We cannot check non-static flags if the - // node was reused. - includeWorkInProgressEffects -) { - switch (finishedWork.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - recursivelyTraverseReconnectPassiveEffects(finishedRoot, finishedWork); // TODO: Check for PassiveStatic flag - - commitHookPassiveMountEffects(finishedWork, Passive); - break; - } - // Unlike commitPassiveMountOnFiber, we don't need to handle HostRoot - // because this function only visits nodes that are inside an - // Offscreen fiber. - // case HostRoot: { - // ... - // } - - case LegacyHiddenComponent: { - { - recursivelyTraverseReconnectPassiveEffects(finishedRoot, finishedWork); - } +var ceil = Math.ceil; +var PossiblyWeakMap = typeof WeakMap === "function" ? WeakMap : Map; +var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher, + ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner, + ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig, + ReactCurrentActQueue = ReactSharedInternals.ReactCurrentActQueue; +var NoContext = + /* */ + 0; +var BatchedContext = + /* */ + 1; +var RenderContext = + /* */ + 2; +var CommitContext = + /* */ + 4; +var RootInProgress = 0; +var RootFatalErrored = 1; +var RootErrored = 2; +var RootSuspended = 3; +var RootSuspendedWithDelay = 4; +var RootCompleted = 5; +var RootDidNotComplete = 6; // Describes where we are in the React execution stack - break; - } +var executionContext = NoContext; // The root we're working on - case OffscreenComponent: { - var _instance4 = finishedWork.stateNode; - var nextState = finishedWork.memoizedState; - var isHidden = nextState !== null; +var workInProgressRoot = null; // The fiber we're working on - if (isHidden) { - if (_instance4._visibility & OffscreenPassiveEffectsConnected) { - // The effects are currently connected. Update them. - recursivelyTraverseReconnectPassiveEffects( - finishedRoot, - finishedWork - ); - } else { - if (finishedWork.mode & ConcurrentMode); - else { - // Legacy Mode: Fire the effects even if the tree is hidden. - _instance4._visibility |= OffscreenPassiveEffectsConnected; - recursivelyTraverseReconnectPassiveEffects( - finishedRoot, - finishedWork - ); - } - } - } else { - // Tree is visible - // Since we're already inside a reconnecting tree, it doesn't matter - // whether the effects are currently connected. In either case, we'll - // continue traversing the tree and firing all the effects. - // - // We do need to set the "connected" flag on the instance, though. - _instance4._visibility |= OffscreenPassiveEffectsConnected; - recursivelyTraverseReconnectPassiveEffects(finishedRoot, finishedWork); - } +var workInProgress = null; // The lanes we're rendering - break; - } +var workInProgressRootRenderLanes = NoLanes; +var NotSuspended = 0; +var SuspendedOnError = 1; +var SuspendedOnData = 2; +var SuspendedOnImmediate = 3; +var SuspendedOnDeprecatedThrowPromise = 4; +var SuspendedAndReadyToContinue = 5; +var SuspendedOnHydration = 6; // When this is true, the work-in-progress fiber just suspended (or errored) and +// we've yet to unwind the stack. In some cases, we may yield to the main thread +// after this happens. If the fiber is pinged before we resume, we can retry +// immediately instead of unwinding the stack. - case CacheComponent: { - recursivelyTraverseReconnectPassiveEffects(finishedRoot, finishedWork); +var workInProgressSuspendedReason = NotSuspended; +var workInProgressThrownValue = null; // Whether a ping listener was attached during this render. This is slightly +// different that whether something suspended, because we don't add multiple +// listeners to a promise we've already seen (per root and lane). - break; - } +var workInProgressRootDidAttachPingListener = false; // A contextual version of workInProgressRootRenderLanes. It is a superset of +// the lanes that we started working on at the root. When we enter a subtree +// that is currently hidden, we add the lanes that would have committed if +// the hidden tree hadn't been deferred. This is modified by the +// HiddenContext module. +// +// Most things in the work loop should deal with workInProgressRootRenderLanes. +// Most things in begin/complete phases should deal with renderLanes. - case TracingMarkerComponent: - // eslint-disable-next-line-no-fallthrough +var renderLanes = NoLanes; // Whether to root completed, errored, suspended, etc. - default: { - recursivelyTraverseReconnectPassiveEffects(finishedRoot, finishedWork); - break; - } - } -} +var workInProgressRootExitStatus = RootInProgress; // A fatal error, if one is thrown -function commitPassiveUnmountEffects(finishedWork) { - setCurrentFiber(finishedWork); - commitPassiveUnmountOnFiber(finishedWork); - resetCurrentFiber(); -} +var workInProgressRootFatalError = null; // The work left over by components that were visited during this render. Only +// includes unprocessed updates, not work in bailed out children. -function detachAlternateSiblings(parentFiber) { - // A fiber was deleted from this parent fiber, but it's still part of the - // previous (alternate) parent fiber's list of children. Because children - // are a linked list, an earlier sibling that's still alive will be - // connected to the deleted fiber via its `alternate`: - // - // live fiber --alternate--> previous live fiber --sibling--> deleted - // fiber - // - // We can't disconnect `alternate` on nodes that haven't been deleted yet, - // but we can disconnect the `sibling` and `child` pointers. - var previousFiber = parentFiber.alternate; +var workInProgressRootSkippedLanes = NoLanes; // Lanes that were updated (in an interleaved event) during this render. - if (previousFiber !== null) { - var detachedChild = previousFiber.child; +var workInProgressRootInterleavedUpdatedLanes = NoLanes; // Lanes that were updated during the render phase (*not* an interleaved event). - if (detachedChild !== null) { - previousFiber.child = null; +var workInProgressRootPingedLanes = NoLanes; // Errors that are thrown during the render phase. - do { - // $FlowFixMe[incompatible-use] found when upgrading Flow - var detachedSibling = detachedChild.sibling; // $FlowFixMe[incompatible-use] found when upgrading Flow +var workInProgressRootConcurrentErrors = null; // These are errors that we recovered from without surfacing them to the UI. +// We will log them once the tree commits. - detachedChild.sibling = null; - detachedChild = detachedSibling; - } while (detachedChild !== null); - } - } -} +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. -function commitHookPassiveUnmountEffects( - finishedWork, - nearestMountedAncestor, - hookFlags -) { - if (shouldProfile(finishedWork)) { - startPassiveEffectTimer(); - commitHookEffectListUnmount( - hookFlags, - finishedWork, - nearestMountedAncestor - ); - recordPassiveEffectDuration(finishedWork); - } else { - commitHookEffectListUnmount( - hookFlags, - finishedWork, - nearestMountedAncestor - ); - } -} +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. -function recursivelyTraversePassiveUnmountEffects(parentFiber) { - // Deletions effects can be scheduled on any fiber type. They need to happen - // before the children effects have fired. - var deletions = parentFiber.deletions; +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. - if ((parentFiber.flags & ChildDeletion) !== NoFlags$1) { - if (deletions !== null) { - for (var i = 0; i < deletions.length; i++) { - var childToDelete = deletions[i]; // TODO: Convert this to use recursion +var RENDER_TIMEOUT_MS = 500; +var workInProgressTransitions = null; - nextEffect = childToDelete; - commitPassiveUnmountEffectsInsideOfDeletedTree_begin( - childToDelete, - parentFiber - ); - } - } +function resetRenderTimer() { + workInProgressRootRenderTargetTime = now$1() + RENDER_TIMEOUT_MS; +} - detachAlternateSiblings(parentFiber); - } +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 prevDebugFiber = getCurrentFiber(); // TODO: Split PassiveMask into separate masks for mount and unmount? +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 (parentFiber.subtreeFlags & PassiveMask) { - var child = parentFiber.child; +var currentEventTime = NoTimestamp; +var currentEventTransitionLane = NoLanes; +var isRunningInsertionEffect = false; +function getWorkInProgressRoot() { + return workInProgressRoot; +} +function getWorkInProgressRootRenderLanes() { + return workInProgressRootRenderLanes; +} +function requestEventTime() { + if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { + // We're inside React, so it's fine to read the actual time. + return now$1(); + } // We're not inside React, so we may be in the middle of a browser event. - while (child !== null) { - setCurrentFiber(child); - commitPassiveUnmountOnFiber(child); - child = child.sibling; - } - } + 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. - setCurrentFiber(prevDebugFiber); + currentEventTime = now$1(); + return currentEventTime; } +function requestUpdateLane(fiber) { + // Special cases + var mode = fiber.mode; -function commitPassiveUnmountOnFiber(finishedWork) { - switch (finishedWork.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - recursivelyTraversePassiveUnmountEffects(finishedWork); - - if (finishedWork.flags & Passive$1) { - commitHookPassiveUnmountEffects( - finishedWork, - finishedWork.return, - Passive | HasEffect - ); - } + if ((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); + } - break; - } + var isTransition = requestCurrentTransition() !== NoTransition; - case OffscreenComponent: { - var instance = finishedWork.stateNode; - var nextState = finishedWork.memoizedState; - var isHidden = nextState !== null; + if (isTransition) { + if (ReactCurrentBatchConfig.transition !== null) { + var transition = ReactCurrentBatchConfig.transition; - if ( - isHidden && - instance._visibility & OffscreenPassiveEffectsConnected && // For backwards compatibility, don't unmount when a tree suspends. In - // the future we may change this to unmount after a delay. - (finishedWork.return === null || - finishedWork.return.tag !== SuspenseComponent) - ) { - // The effects are currently connected. Disconnect them. - // TODO: Add option or heuristic to delay before disconnecting the - // effects. Then if the tree reappears before the delay has elapsed, we - // can skip toggling the effects entirely. - instance._visibility &= ~OffscreenPassiveEffectsConnected; - recursivelyTraverseDisconnectPassiveEffects(finishedWork); - } else { - recursivelyTraversePassiveUnmountEffects(finishedWork); + if (!transition._updatedFibers) { + transition._updatedFibers = new Set(); } - break; - } + 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. - default: { - recursivelyTraversePassiveUnmountEffects(finishedWork); - break; + if (currentEventTransitionLane === NoLane) { + // All transitions within the same event are assigned the same lane. + currentEventTransitionLane = claimNextTransitionLane(); } - } -} - -function recursivelyTraverseDisconnectPassiveEffects(parentFiber) { - // Deletions effects can be scheduled on any fiber type. They need to happen - // before the children effects have fired. - var deletions = parentFiber.deletions; - if ((parentFiber.flags & ChildDeletion) !== NoFlags$1) { - if (deletions !== null) { - for (var i = 0; i < deletions.length; i++) { - var childToDelete = deletions[i]; // TODO: Convert this to use recursion + 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. - nextEffect = childToDelete; - commitPassiveUnmountEffectsInsideOfDeletedTree_begin( - childToDelete, - parentFiber - ); - } - } + var updateLane = getCurrentUpdatePriority(); - detachAlternateSiblings(parentFiber); - } + 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 prevDebugFiber = getCurrentFiber(); // TODO: Check PassiveStatic flag + var eventLane = getCurrentEventPriority(); + return eventLane; +} - var child = parentFiber.child; +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; - while (child !== null) { - setCurrentFiber(child); - disconnectPassiveEffect(child); - child = child.sibling; + if ((mode & ConcurrentMode) === NoMode) { + return SyncLane; } - setCurrentFiber(prevDebugFiber); + return claimNextRetryLane(); } -function disconnectPassiveEffect(finishedWork) { - switch (finishedWork.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - // TODO: Check PassiveStatic flag - commitHookPassiveUnmountEffects( - finishedWork, - finishedWork.return, - Passive - ); // When disconnecting passive effects, we fire the effects in the same - // order as during a deletiong: parent before child - - recursivelyTraverseDisconnectPassiveEffects(finishedWork); - break; - } - - case OffscreenComponent: { - var instance = finishedWork.stateNode; - - if (instance._visibility & OffscreenPassiveEffectsConnected) { - instance._visibility &= ~OffscreenPassiveEffectsConnected; - recursivelyTraverseDisconnectPassiveEffects(finishedWork); - } - - break; +function scheduleUpdateOnFiber(root, fiber, lane, eventTime) { + { + if (isRunningInsertionEffect) { + error("useInsertionEffect must not schedule updates."); } + } - default: { - recursivelyTraverseDisconnectPassiveEffects(finishedWork); - break; + { + if (isFlushingPassiveEffects) { + didScheduleUpdateDuringPassiveEffects = true; } - } -} + } // Check if the work loop is currently suspended and waiting for data to + // finish loading. -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 ( + workInProgressSuspendedReason === SuspendedOnData && + root === workInProgressRoot + ) { + // The incoming update might unblock the current render. Interrupt the + // current attempt and restart from the top. + prepareFreshStack(root, NoLanes); + markRootSuspended(root, workInProgressRootRenderLanes); + } // Mark that the root has a pending update. - setCurrentFiber(fiber); - commitPassiveUnmountInsideDeletedTreeOnFiber(fiber, nearestMountedAncestor); - resetCurrentFiber(); - var child = fiber.child; // TODO: Only traverse subtree if it has a PassiveStatic flag. + markRootUpdated(root, lane, eventTime); - if (child !== null) { - child.return = fiber; - nextEffect = child; - } else { - commitPassiveUnmountEffectsInsideOfDeletedTree_complete( - deletedSubtreeRoot - ); + 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 commitPassiveUnmountEffectsInsideOfDeletedTree_complete( - deletedSubtreeRoot -) { - while (nextEffect !== null) { - var fiber = nextEffect; - var sibling = fiber.sibling; - var returnFiber = fiber.return; // Recursively traverse the entire deleted tree and clean up fiber fields. - // This is more aggressive than ideal, and the long term goal is to only - // have to detach the deleted tree at the root. - detachFiberAfterEffects(fiber); + warnIfUpdatesNotWrappedWithActDEV(fiber); - if (fiber === deletedSubtreeRoot) { - nextEffect = null; - return; - } + 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 (sibling !== null) { - sibling.return = returnFiber; - nextEffect = sibling; - return; + if (workInProgressRootExitStatus === RootSuspendedWithDelay) { + // The root already suspended with a delay, which means this render + // definitely won't finish. Since we have a new update, let's mark it as + // suspended now, right before marking the incoming update. This has the + // effect of interrupting the current render and switching to the update. + // TODO: Make sure this doesn't override pings that happen while we've + // already started rendering. + markRootSuspended(root, workInProgressRootRenderLanes); + } } - nextEffect = returnFiber; - } -} + ensureRootIsScheduled(root, eventTime); -function commitPassiveUnmountInsideDeletedTreeOnFiber( - current, - nearestMountedAncestor -) { - switch (current.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - commitHookPassiveUnmountEffects(current, nearestMountedAncestor, Passive); - break; + if ( + lane === SyncLane && + executionContext === NoContext && + (fiber.mode & ConcurrentMode) === NoMode && // Treat `act` as if it's inside `batchedUpdates`, even in legacy mode. + !ReactCurrentActQueue.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 invokeLayoutEffectMountInDEV(fiber) { - { - // We don't need to re-check StrictEffectsMode here. - // This function is only called if that check has already passed. - switch (fiber.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - try { - commitHookEffectListMount(Layout | HasEffect, fiber); - } catch (error) { - captureCommitPhaseError(fiber, fiber.return, error); - } - - break; - } +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. - case ClassComponent: { - var instance = fiber.stateNode; + markStarvedLanesAsExpired(root, currentTime); // Determine the next lanes to work on, and their priority. - try { - instance.componentDidMount(); - } catch (error) { - captureCommitPhaseError(fiber, fiber.return, error); - } + var nextLanes = getNextLanes( + root, + root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes + ); - break; - } + if (nextLanes === NoLanes) { + // Special case: There's nothing to work on. + if (existingCallbackNode !== null) { + cancelCallback(existingCallbackNode); } - } -} -function invokePassiveEffectMountInDEV(fiber) { - { - // We don't need to re-check StrictEffectsMode here. - // This function is only called if that check has already passed. - switch (fiber.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - try { - commitHookEffectListMount(Passive | HasEffect, fiber); - } catch (error) { - captureCommitPhaseError(fiber, fiber.return, error); - } + root.callbackNode = null; + root.callbackPriority = NoLane; + return; + } // If this root is currently suspended and waiting for data to resolve, don't + // schedule a task to render it. We'll either wait for a ping, or wait to + // receive an update. - break; - } - } + if ( + workInProgressSuspendedReason === SuspendedOnData && + workInProgressRoot === root + ) { + root.callbackPriority = NoLane; + root.callbackNode = null; + return; } -} -function invokeLayoutEffectUnmountInDEV(fiber) { - { - // We don't need to re-check StrictEffectsMode here. - // This function is only called if that check has already passed. - switch (fiber.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - try { - commitHookEffectListUnmount(Layout | HasEffect, fiber, fiber.return); - } catch (error) { - captureCommitPhaseError(fiber, fiber.return, error); - } + var cancelPendingCommit = root.cancelPendingCommit; - break; - } + if (cancelPendingCommit !== null) { + // We should only interrupt a pending commit if the new update + // is urgent. + if (includesOnlyNonUrgentLanes(nextLanes)) { + // The new update is not urgent. Don't interrupt the pending commit. + root.callbackPriority = NoLane; + root.callbackNode = null; + return; + } + } // We use the highest priority lane to represent the priority of the callback. - case ClassComponent: { - var instance = fiber.stateNode; + var newCallbackPriority = getHighestPriorityLane(nextLanes); // Check if there's an existing task. We may be able to reuse it. - if (typeof instance.componentWillUnmount === "function") { - safelyCallComponentWillUnmount(fiber, fiber.return, instance); - } + var existingCallbackPriority = root.callbackPriority; - break; + 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.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 && + !includesSyncLane(existingCallbackPriority) + ) { + 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. -function invokePassiveEffectUnmountInDEV(fiber) { - { - // We don't need to re-check StrictEffectsMode here. - // This function is only called if that check has already passed. - switch (fiber.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - try { - commitHookEffectListUnmount(Passive | HasEffect, fiber, fiber.return); - } catch (error) { - captureCommitPhaseError(fiber, fiber.return, error); - } - } - } + return; } -} -if (typeof Symbol === "function" && Symbol.for) { - var symbolFor = Symbol.for; - symbolFor("selector.component"); - symbolFor("selector.has_pseudo_class"); - symbolFor("selector.role"); - symbolFor("selector.test_id"); - symbolFor("selector.text"); -} + if (existingCallbackNode != null) { + // Cancel the existing callback. We'll schedule a new one below. + cancelCallback(existingCallbackNode); + } // Schedule a new callback. -var ReactCurrentActQueue$1 = ReactSharedInternals.ReactCurrentActQueue; -function isLegacyActEnvironment(fiber) { - { - // Legacy mode. We preserve the behavior of React 17's act. It assumes an - // act environment whenever `jest` is defined, but you can still turn off - // spurious warnings by setting IS_REACT_ACT_ENVIRONMENT explicitly - // to false. - // $FlowFixMe[cannot-resolve-name] Flow doesn't know about IS_REACT_ACT_ENVIRONMENT global - typeof IS_REACT_ACT_ENVIRONMENT !== "undefined" // $FlowFixMe[cannot-resolve-name] - ? IS_REACT_ACT_ENVIRONMENT - : undefined; // $FlowFixMe - Flow doesn't know about jest - return warnsIfNotActing; - } -} -function isConcurrentActEnvironment() { - { - var isReactActEnvironmentGlobal = // $FlowFixMe[cannot-resolve-name] Flow doesn't know about IS_REACT_ACT_ENVIRONMENT global - typeof IS_REACT_ACT_ENVIRONMENT !== "undefined" // $FlowFixMe[cannot-resolve-name] - ? IS_REACT_ACT_ENVIRONMENT - : undefined; + var newCallbackNode; - if ( - !isReactActEnvironmentGlobal && - ReactCurrentActQueue$1.current !== null - ) { - // TODO: Include link to relevant documentation page. - error( - "The current testing environment is not configured to support " + - "act(...)" - ); + if (includesSyncLane(newCallbackPriority)) { + // Special case: Sync React callbacks are scheduled on a special + // internal queue + if (root.tag === LegacyRoot) { + if (ReactCurrentActQueue.isBatchingLegacy !== null) { + ReactCurrentActQueue.didScheduleLegacyUpdate = true; + } + + scheduleLegacySyncCallback(performSyncWorkOnRoot.bind(null, root)); + } else { + scheduleSyncCallback(performSyncWorkOnRoot.bind(null, root)); + } + + { + // Flush the queue in an Immediate task. + scheduleCallback(ImmediatePriority, flushSyncCallbacks); } - return isReactActEnvironmentGlobal; - } -} + newCallbackNode = null; + } else { + var schedulerPriorityLevel; -var ceil = Math.ceil; -var PossiblyWeakMap = typeof WeakMap === "function" ? WeakMap : Map; -var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher, - ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner, - ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig, - ReactCurrentActQueue = ReactSharedInternals.ReactCurrentActQueue; -var NoContext = - /* */ - 0; -var BatchedContext = - /* */ - 1; -var RenderContext = - /* */ - 2; -var CommitContext = - /* */ - 4; -var RootInProgress = 0; -var RootFatalErrored = 1; -var RootErrored = 2; -var RootSuspended = 3; -var RootSuspendedWithDelay = 4; -var RootCompleted = 5; -var RootDidNotComplete = 6; // Describes where we are in the React execution stack + switch (lanesToEventPriority(nextLanes)) { + case DiscreteEventPriority: + schedulerPriorityLevel = ImmediatePriority; + break; -var executionContext = NoContext; // The root we're working on + case ContinuousEventPriority: + schedulerPriorityLevel = UserBlockingPriority; + break; -var workInProgressRoot = null; // The fiber we're working on + case DefaultEventPriority: + schedulerPriorityLevel = NormalPriority; + break; -var workInProgress = null; // The lanes we're rendering + case IdleEventPriority: + schedulerPriorityLevel = IdlePriority; + break; -var workInProgressRootRenderLanes = NoLanes; -var NotSuspended = 0; -var SuspendedOnError = 1; -var SuspendedOnData = 2; -var SuspendedOnImmediate = 3; -var SuspendedOnDeprecatedThrowPromise = 4; -var SuspendedAndReadyToContinue = 5; -var SuspendedOnHydration = 6; // When this is true, the work-in-progress fiber just suspended (or errored) and -// we've yet to unwind the stack. In some cases, we may yield to the main thread -// after this happens. If the fiber is pinged before we resume, we can retry -// immediately instead of unwinding the stack. + default: + schedulerPriorityLevel = NormalPriority; + break; + } -var workInProgressSuspendedReason = NotSuspended; -var workInProgressThrownValue = null; // Whether a ping listener was attached during this render. This is slightly -// different that whether something suspended, because we don't add multiple -// listeners to a promise we've already seen (per root and lane). + newCallbackNode = scheduleCallback( + schedulerPriorityLevel, + performConcurrentWorkOnRoot.bind(null, root) + ); + } -var workInProgressRootDidAttachPingListener = false; // A contextual version of workInProgressRootRenderLanes. It is a superset of -// the lanes that we started working on at the root. When we enter a subtree -// that is currently hidden, we add the lanes that would have committed if -// the hidden tree hadn't been deferred. This is modified by the -// HiddenContext module. -// -// Most things in the work loop should deal with workInProgressRootRenderLanes. -// Most things in begin/complete phases should deal with renderLanes. + root.callbackPriority = newCallbackPriority; + root.callbackNode = newCallbackNode; +} // This is the entry point for every concurrent task, i.e. anything that +// goes through Scheduler. -var renderLanes = NoLanes; // Whether to root completed, errored, suspended, etc. +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. -var workInProgressRootExitStatus = RootInProgress; // A fatal error, if one is thrown + currentEventTime = NoTimestamp; + currentEventTransitionLane = NoLanes; -var workInProgressRootFatalError = null; // The work left over by components that were visited during this render. Only -// includes unprocessed updates, not work in bailed out children. + 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 workInProgressRootSkippedLanes = NoLanes; // Lanes that were updated (in an interleaved event) during this render. + var originalCallbackNode = root.callbackNode; + var didFlushPassiveEffects = flushPassiveEffects(); -var workInProgressRootInterleavedUpdatedLanes = NoLanes; // Lanes that were updated during the render phase (*not* an interleaved event). + 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 workInProgressRootPingedLanes = NoLanes; // Errors that are thrown during the render phase. + var lanes = getNextLanes( + root, + root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes + ); -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 (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 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 shouldTimeSlice = + !includesBlockingLane(root, lanes) && + !includesExpiredLane(root, lanes) && + !didTimeout; + var exitStatus = shouldTimeSlice + ? renderRootConcurrent(root, lanes) + : renderRootSync(root, lanes); -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. + 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 originallyAttemptedLanes = lanes; + var errorRetryLanes = getLanesToRetrySynchronouslyOnError( + root, + originallyAttemptedLanes + ); -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. + if (errorRetryLanes !== NoLanes) { + lanes = errorRetryLanes; + exitStatus = recoverFromConcurrentError( + root, + originallyAttemptedLanes, + errorRetryLanes + ); + } + } -var RENDER_TIMEOUT_MS = 500; -var workInProgressTransitions = null; + if (exitStatus === RootFatalErrored) { + var fatalError = workInProgressRootFatalError; + prepareFreshStack(root, NoLanes); + markRootSuspended(root, lanes); + ensureRootIsScheduled(root, now$1()); + throw fatalError; + } -function resetRenderTimer() { - workInProgressRootRenderTargetTime = now$1() + RENDER_TIMEOUT_MS; -} + if (exitStatus === RootDidNotComplete) { + // The render unwound without completing the tree. This happens in special + // cases where need to exit the current render without producing a + // consistent tree or committing. + markRootSuspended(root, lanes); + } 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; -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 = []; + 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 -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 (exitStatus === RootErrored) { + var _originallyAttemptedLanes = lanes; -var currentEventTime = NoTimestamp; -var currentEventTransitionLane = NoLanes; -var isRunningInsertionEffect = false; -function getWorkInProgressRoot() { - return workInProgressRoot; -} -function getWorkInProgressRootRenderLanes() { - return workInProgressRootRenderLanes; -} -function requestEventTime() { - if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { - // We're inside React, so it's fine to read the actual time. - return now$1(); - } // We're not inside React, so we may be in the middle of a browser event. + var _errorRetryLanes = getLanesToRetrySynchronouslyOnError( + root, + _originallyAttemptedLanes + ); + + if (_errorRetryLanes !== NoLanes) { + lanes = _errorRetryLanes; + exitStatus = recoverFromConcurrentError( + root, + _originallyAttemptedLanes, + _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(root, lanes); + ensureRootIsScheduled(root, now$1()); + throw _fatalError; + } // FIXME: Need to check for RootDidNotComplete again. The factoring here + // isn't ideal. + } // We now have a consistent tree. The next step is either to commit it, + // or, if something suspended, wait to commit it after a timeout. - if (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. + root.finishedWork = finishedWork; + root.finishedLanes = lanes; + finishConcurrentRender(root, exitStatus, finishedWork, lanes); + } + } - currentEventTime = now$1(); - return currentEventTime; -} -function requestUpdateLane(fiber) { - // Special cases - var mode = fiber.mode; + ensureRootIsScheduled(root, now$1()); - 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); + 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); } - var isTransition = requestCurrentTransition() !== NoTransition; - - if (isTransition) { - if (ReactCurrentBatchConfig.transition !== null) { - var transition = ReactCurrentBatchConfig.transition; + return null; +} - if (!transition._updatedFibers) { - transition._updatedFibers = new Set(); - } +function recoverFromConcurrentError( + root, + originallyAttemptedLanes, + errorRetryLanes +) { + // If an error occurred during hydration, discard server response and fall + // back to client side render. + // Before rendering again, save the errors from the previous attempt. + var errorsFromFirstAttempt = workInProgressRootConcurrentErrors; + var wasRootDehydrated = isRootDehydrated(root); - 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. + if (wasRootDehydrated) { + // The shell failed to hydrate. Set a flag to force a client rendering + // during the next attempt. To do this, we call prepareFreshStack now + // to create the root work-in-progress fiber. This is a bit weird in terms + // of factoring, because it relies on renderRootSync not calling + // prepareFreshStack again in the call below, which happens because the + // root and lanes haven't changed. // - // 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. + // TODO: I think what we should do is set ForceClientRender inside + // throwException, like we do for nested Suspense boundaries. The reason + // it's here instead is so we can switch to the synchronous work loop, too. + // Something to consider for a future refactor. + var rootWorkInProgress = prepareFreshStack(root, errorRetryLanes); + rootWorkInProgress.flags |= ForceClientRender; - if (currentEventTransitionLane === NoLane) { - // All transitions within the same event are assigned the same lane. - currentEventTransitionLane = claimNextTransitionLane(); + { + errorHydratingContainer(); } + } - 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(); + var exitStatus = renderRootSync(root, errorRetryLanes); - 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 (exitStatus !== RootErrored) { + // Successfully finished rendering on retry + if (workInProgressRootDidAttachPingListener && !wasRootDehydrated) { + // During the synchronous render, we attached additional ping listeners. + // This is highly suggestive of an uncached promise (though it's not the + // only reason this would happen). If it was an uncached promise, then + // it may have masked a downstream error from ocurring without actually + // fixing it. Example: + // + // use(Promise.resolve('uncached')) + // throw new Error('Oops!') + // + // When this happens, there's a conflict between blocking potential + // concurrent data races and unwrapping uncached promise values. We + // have to choose one or the other. Because the data race recovery is + // a last ditch effort, we'll disable it. + root.errorRecoveryDisabledLanes = mergeLanes( + root.errorRecoveryDisabledLanes, + originallyAttemptedLanes + ); // Mark the current render as suspended and force it to restart. Once + // these lanes finish successfully, we'll re-enable the error recovery + // mechanism for subsequent updates. - var eventLane = getCurrentEventPriority(); - return eventLane; -} + workInProgressRootInterleavedUpdatedLanes |= originallyAttemptedLanes; + return RootSuspendedWithDelay; + } // The errors from the failed first attempt have been recovered. Add + // them to the collection of recoverable errors. We'll log them in the + // commit phase. -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; + 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 ((mode & ConcurrentMode) === NoMode) { - return SyncLane; + if (errorsFromSecondAttempt !== null) { + queueRecoverableErrors(errorsFromSecondAttempt); + } } - return claimNextRetryLane(); + return exitStatus; } -function scheduleUpdateOnFiber(root, fiber, lane, eventTime) { - { - if (isRunningInsertionEffect) { - error("useInsertionEffect must not schedule updates."); - } +function queueRecoverableErrors(errors) { + if (workInProgressRootRecoverableErrors === null) { + workInProgressRootRecoverableErrors = errors; + } else { + // $FlowFixMe[method-unbinding] + workInProgressRootRecoverableErrors.push.apply( + workInProgressRootRecoverableErrors, + errors + ); } +} - { - if (isFlushingPassiveEffects) { - didScheduleUpdateDuringPassiveEffects = true; +function finishConcurrentRender(root, exitStatus, finishedWork, lanes) { + switch (exitStatus) { + case RootInProgress: + case RootFatalErrored: { + throw new Error("Root did not complete. This is a bug in React."); } - } // Check if the work loop is currently suspended and waiting for data to - // finish loading. + // 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 ( - workInProgressSuspendedReason === SuspendedOnData && - root === workInProgressRoot - ) { - // The incoming update might unblock the current render. Interrupt the - // current attempt and restart from the top. - prepareFreshStack(root, NoLanes); - markRootSuspended(root, workInProgressRootRenderLanes); - } // Mark that the root has a pending update. + case RootErrored: { + // We should have already attempted to retry this tree. If we reached + // this point, it errored again. Commit it. + commitRootWhenReady( + root, + finishedWork, + workInProgressRootRecoverableErrors, + workInProgressTransitions, + lanes + ); + break; + } - markRootUpdated(root, lane, eventTime); + case RootSuspended: { + markRootSuspended(root, lanes); // We have an acceptable loading state. We need to figure out if we + // should immediately commit it or wait a bit. - 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 ( + 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$1(); // 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; + } // 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( + commitRootWhenReady.bind( + null, + root, + finishedWork, + workInProgressRootRecoverableErrors, + workInProgressTransitions, + lanes + ), + msUntilTimeout + ); + break; + } + } // The work expired. Commit immediately. + + commitRootWhenReady( + root, + finishedWork, + workInProgressRootRecoverableErrors, + workInProgressTransitions, + lanes + ); + break; + } + + case RootSuspendedWithDelay: { + markRootSuspended(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; } - } - warnIfUpdatesNotWrappedWithActDEV(fiber); + 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$1() - eventTimeMs; - 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 - ); - } + var _msUntilTimeout = jnd(timeElapsedMs) - timeElapsedMs; // Don't bother with a very short suspense time. - if (workInProgressRootExitStatus === RootSuspendedWithDelay) { - // The root already suspended with a delay, which means this render - // definitely won't finish. Since we have a new update, let's mark it as - // suspended now, right before marking the incoming update. This has the - // effect of interrupting the current render and switching to the update. - // TODO: Make sure this doesn't override pings that happen while we've - // already started rendering. - markRootSuspended(root, workInProgressRootRenderLanes); - } + if (_msUntilTimeout > 10) { + // Instead of committing the fallback immediately, wait for more data + // to arrive. + root.timeoutHandle = scheduleTimeout( + commitRootWhenReady.bind( + null, + root, + finishedWork, + workInProgressRootRecoverableErrors, + workInProgressTransitions, + lanes + ), + _msUntilTimeout + ); + break; + } + } // Commit the placeholder. + + commitRootWhenReady( + root, + finishedWork, + workInProgressRootRecoverableErrors, + workInProgressTransitions, + lanes + ); + break; } - ensureRootIsScheduled(root, eventTime); + case RootCompleted: { + // The work completed. + commitRootWhenReady( + root, + finishedWork, + workInProgressRootRecoverableErrors, + workInProgressTransitions, + lanes + ); + break; + } - if ( - lane === SyncLane && - executionContext === NoContext && - (fiber.mode & ConcurrentMode) === NoMode && // Treat `act` as if it's inside `batchedUpdates`, even in legacy mode. - !ReactCurrentActQueue.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(); + default: { + throw new Error("Unknown root exit status."); } } } -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. +function commitRootWhenReady( + root, + finishedWork, + recoverableErrors, + transitions, + lanes +) { + if (includesOnlyNonUrgentLanes(lanes)) { + // suspend. If it's not ready, it will return a callback to subscribe to + // a ready event. + + var schedulePendingCommit = waitForCommitToBeReady(); + + if (schedulePendingCommit !== null) { + // NOTE: waitForCommitToBeReady returns a subscribe function so that we + // only allocate a function if the commit isn't ready yet. The other + // pattern would be to always pass a callback to waitForCommitToBeReady. + // Not yet ready to commit. Delay the commit until the renderer notifies + // us that it's ready. This will be canceled if we start work on the + // root again. + root.cancelPendingCommit = schedulePendingCommit( + commitRoot.bind( + null, + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ) + ); + return; + } + } // Otherwise, commit immediately. - var nextLanes = getNextLanes( + commitRoot( root, - root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes + workInProgressRootRecoverableErrors, + workInProgressTransitions ); +} - if (nextLanes === NoLanes) { - // Special case: There's nothing to work on. - if (existingCallbackNode !== null) { - cancelCallback(existingCallbackNode); - } - - root.callbackNode = null; - root.callbackPriority = NoLane; - return; - } // If this root is currently suspended and waiting for data to resolve, don't - // schedule a task to render it. We'll either wait for a ping, or wait to - // receive an update. +function isRenderConsistentWithExternalStores(finishedWork) { + // Search the rendered tree for external store reads, and check whether the + // stores were mutated in a concurrent event. Intentionally using an iterative + // loop instead of recursion so we can exit early. + var node = finishedWork; - if ( - workInProgressSuspendedReason === SuspendedOnData && - workInProgressRoot === root - ) { - root.callbackPriority = NoLane; - root.callbackNode = null; - return; - } // We use the highest priority lane to represent the priority of the callback. + while (true) { + if (node.flags & StoreConsistency) { + var updateQueue = node.updateQueue; - var newCallbackPriority = getHighestPriorityLane(nextLanes); // Check if there's an existing task. We may be able to reuse it. + if (updateQueue !== null) { + var checks = updateQueue.stores; - var existingCallbackPriority = root.callbackPriority; + if (checks !== null) { + for (var i = 0; i < checks.length; i++) { + var check = checks[i]; + var getSnapshot = check.getSnapshot; + var renderedValue = check.value; - 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.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 && - !includesSyncLane(existingCallbackPriority) - ) { - error( - "Expected scheduled callback to exist. This error is likely caused by a bug in React. Please file an issue." - ); + 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; + } + } + } } - } // The priority hasn't changed. We can reuse the existing task. Exit. + } - return; - } + var child = node.child; - if (existingCallbackNode != null) { - // Cancel the existing callback. We'll schedule a new one below. - cancelCallback(existingCallbackNode); - } // Schedule a new callback. + if (node.subtreeFlags & StoreConsistency && child !== null) { + child.return = node; + node = child; + continue; + } - var newCallbackNode; + if (node === finishedWork) { + return true; + } - if (includesSyncLane(newCallbackPriority)) { - // Special case: Sync React callbacks are scheduled on a special - // internal queue - if (root.tag === LegacyRoot) { - if (ReactCurrentActQueue.isBatchingLegacy !== null) { - ReactCurrentActQueue.didScheduleLegacyUpdate = true; + while (node.sibling === null) { + if (node.return === null || node.return === finishedWork) { + return true; } - scheduleLegacySyncCallback(performSyncWorkOnRoot.bind(null, root)); - } else { - scheduleSyncCallback(performSyncWorkOnRoot.bind(null, root)); + node = node.return; } - { - // Flush the queue in an Immediate task. - scheduleCallback(ImmediatePriority, flushSyncCallbacks); - } + node.sibling.return = node.return; + node = node.sibling; + } // Flow doesn't know this is unreachable, but eslint does + // eslint-disable-next-line no-unreachable - newCallbackNode = null; - } else { - var schedulerPriorityLevel; + return true; +} - switch (lanesToEventPriority(nextLanes)) { - case DiscreteEventPriority: - schedulerPriorityLevel = ImmediatePriority; - break; +function markRootSuspended(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$1(root, suspendedLanes); +} // This is the entry point for synchronous tasks that don't go +// through Scheduler + +function performSyncWorkOnRoot(root) { + { + syncNestedUpdateFlag(); + } - case ContinuousEventPriority: - schedulerPriorityLevel = UserBlockingPriority; - break; + if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { + throw new Error("Should not already be working."); + } - case DefaultEventPriority: - schedulerPriorityLevel = NormalPriority; - break; + flushPassiveEffects(); + var lanes = getNextLanes(root, NoLanes); - case IdleEventPriority: - schedulerPriorityLevel = IdlePriority; - break; + if (!includesSyncLane(lanes)) { + // There's no remaining sync work left. + ensureRootIsScheduled(root, now$1()); + return null; + } - default: - schedulerPriorityLevel = NormalPriority; - break; - } + var exitStatus = renderRootSync(root, lanes); - newCallbackNode = scheduleCallback( - schedulerPriorityLevel, - performConcurrentWorkOnRoot.bind(null, root) + if (root.tag !== LegacyRoot && exitStatus === RootErrored) { + // If something threw an error, try rendering one more time. We'll render + // synchronously to block concurrent data mutations, and we'll includes + // all pending updates are included. If it still fails after the second + // attempt, we'll give up and commit the resulting tree. + var originallyAttemptedLanes = lanes; + var errorRetryLanes = getLanesToRetrySynchronouslyOnError( + root, + originallyAttemptedLanes ); + + if (errorRetryLanes !== NoLanes) { + lanes = errorRetryLanes; + exitStatus = recoverFromConcurrentError( + root, + originallyAttemptedLanes, + errorRetryLanes + ); + } } - root.callbackPriority = newCallbackPriority; - root.callbackNode = newCallbackNode; -} // This is the entry point for every concurrent task, i.e. anything that -// goes through Scheduler. + if (exitStatus === RootFatalErrored) { + var fatalError = workInProgressRootFatalError; + prepareFreshStack(root, NoLanes); + markRootSuspended(root, lanes); + ensureRootIsScheduled(root, now$1()); + throw fatalError; + } -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. + if (exitStatus === RootDidNotComplete) { + // The render unwound without completing the tree. This happens in special + // cases where need to exit the current render without producing a + // consistent tree or committing. + markRootSuspended(root, lanes); + ensureRootIsScheduled(root, now$1()); + return null; + } // We now have a consistent tree. Because this is a sync render, we + // will commit it even if something suspended. - currentEventTime = NoTimestamp; - currentEventTransitionLane = NoLanes; + 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. - 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. + ensureRootIsScheduled(root, now$1()); + return null; +} +function getExecutionContext() { + return executionContext; +} +function batchedUpdates$1(fn, a) { + var prevExecutionContext = executionContext; + executionContext |= BatchedContext; - var originalCallbackNode = root.callbackNode; - var didFlushPassiveEffects = flushPassiveEffects(); + 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 (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; + if ( + executionContext === NoContext && // Treat `act` as if it's inside `batchedUpdates`, even in legacy mode. + !ReactCurrentActQueue.isBatchingLegacy + ) { + resetRenderTimer(); + flushSyncCallbacksOnlyInLegacyMode(); } - } // Determine the next lanes to work on, using the fields stored - // on the root. - - var lanes = getNextLanes( - root, - root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes - ); + } +} +// Warning, this opts-out of checking the function body. +// eslint-disable-next-line no-unused-vars +// eslint-disable-next-line no-redeclare +// eslint-disable-next-line no-redeclare - 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. +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 shouldTimeSlice = - !includesBlockingLane(root, lanes) && - !includesExpiredLane(root, lanes) && - !didTimeout; - var exitStatus = shouldTimeSlice - ? renderRootConcurrent(root, lanes) - : renderRootSync(root, lanes); + var prevExecutionContext = executionContext; + executionContext |= BatchedContext; + var prevTransition = ReactCurrentBatchConfig.transition; + var previousPriority = getCurrentUpdatePriority(); - 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 originallyAttemptedLanes = lanes; - var errorRetryLanes = getLanesToRetrySynchronouslyOnError( - root, - originallyAttemptedLanes - ); + try { + ReactCurrentBatchConfig.transition = null; + setCurrentUpdatePriority(DiscreteEventPriority); - if (errorRetryLanes !== NoLanes) { - lanes = errorRetryLanes; - exitStatus = recoverFromConcurrentError( - root, - originallyAttemptedLanes, - errorRetryLanes - ); - } + if (fn) { + return fn(); + } else { + return undefined; } + } finally { + setCurrentUpdatePriority(previousPriority); + ReactCurrentBatchConfig.transition = prevTransition; + executionContext = prevExecutionContext; // Flush the immediate callbacks that were scheduled during this batch. + // Note that this will happen even if batchedUpdates is higher up + // the stack. - if (exitStatus === RootFatalErrored) { - var fatalError = workInProgressRootFatalError; - prepareFreshStack(root, NoLanes); - markRootSuspended(root, lanes); - ensureRootIsScheduled(root, now$1()); - throw fatalError; + if ((executionContext & (RenderContext | CommitContext)) === NoContext) { + flushSyncCallbacks(); } + } +} +// hidden subtree. The stack logic is managed there because that's the only +// place that ever modifies it. Which module it lives in doesn't matter for +// performance because this function will get inlined regardless - if (exitStatus === RootDidNotComplete) { - // The render unwound without completing the tree. This happens in special - // cases where need to exit the current render without producing a - // consistent tree or committing. - markRootSuspended(root, lanes); - } 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; +function setRenderLanes(subtreeRenderLanes) { + renderLanes = subtreeRenderLanes; +} +function getRenderLanes() { + return renderLanes; +} - 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 +function resetWorkInProgressStack() { + if (workInProgress === null) return; + var interruptedWork; - if (exitStatus === RootErrored) { - var _originallyAttemptedLanes = lanes; + if (workInProgressSuspendedReason === NotSuspended) { + // Normal case. Work-in-progress hasn't started yet. Unwind all + // its parents. + interruptedWork = workInProgress.return; + } else { + // Work-in-progress is in suspended state. Reset the work loop and unwind + // both the suspended fiber and all its parents. + resetSuspendedWorkLoopOnUnwind(); + interruptedWork = workInProgress; + } + + while (interruptedWork !== null) { + var current = interruptedWork.alternate; + unwindInterruptedWork(current, interruptedWork); + interruptedWork = interruptedWork.return; + } + + workInProgress = null; +} + +function prepareFreshStack(root, lanes) { + root.finishedWork = null; + root.finishedLanes = NoLanes; + var timeoutHandle = root.timeoutHandle; - var _errorRetryLanes = getLanesToRetrySynchronouslyOnError( - root, - _originallyAttemptedLanes - ); + 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 - if (_errorRetryLanes !== NoLanes) { - lanes = _errorRetryLanes; - exitStatus = recoverFromConcurrentError( - root, - _originallyAttemptedLanes, - _errorRetryLanes - ); // We assume the tree is now consistent because we didn't yield to any - // concurrent events. - } - } + cancelTimeout(timeoutHandle); + } - if (exitStatus === RootFatalErrored) { - var _fatalError = workInProgressRootFatalError; - prepareFreshStack(root, NoLanes); - markRootSuspended(root, lanes); - ensureRootIsScheduled(root, now$1()); - throw _fatalError; - } // FIXME: Need to check for RootDidNotComplete again. The factoring here - // isn't ideal. - } // 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. + var cancelPendingCommit = root.cancelPendingCommit; - root.finishedWork = finishedWork; - root.finishedLanes = lanes; - finishConcurrentRender(root, exitStatus, lanes); - } + if (cancelPendingCommit !== null) { + root.cancelPendingCommit = null; + cancelPendingCommit(); } - ensureRootIsScheduled(root, now$1()); + resetWorkInProgressStack(); + workInProgressRoot = root; + var rootWorkInProgress = createWorkInProgress(root.current, null); + workInProgress = rootWorkInProgress; + workInProgressRootRenderLanes = renderLanes = lanes; + workInProgressSuspendedReason = NotSuspended; + workInProgressThrownValue = null; + workInProgressRootDidAttachPingListener = false; + workInProgressRootExitStatus = RootInProgress; + workInProgressRootFatalError = null; + workInProgressRootSkippedLanes = NoLanes; + workInProgressRootInterleavedUpdatedLanes = NoLanes; + workInProgressRootPingedLanes = NoLanes; + workInProgressRootConcurrentErrors = null; + workInProgressRootRecoverableErrors = null; + finishQueueingConcurrentUpdates(); - 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); + { + ReactStrictModeWarnings.discardPendingWarnings(); } - return null; + return rootWorkInProgress; } -function recoverFromConcurrentError( - root, - originallyAttemptedLanes, - errorRetryLanes -) { - // If an error occurred during hydration, discard server response and fall - // back to client side render. - // Before rendering again, save the errors from the previous attempt. - var errorsFromFirstAttempt = workInProgressRootConcurrentErrors; - var wasRootDehydrated = isRootDehydrated(root); +function resetSuspendedWorkLoopOnUnwind() { + // Reset module-level state that was set during the render phase. + resetContextDependencies(); + resetHooksOnUnwind(); + resetChildReconcilerOnUnwind(); +} - if (wasRootDehydrated) { - // The shell failed to hydrate. Set a flag to force a client rendering - // during the next attempt. To do this, we call prepareFreshStack now - // to create the root work-in-progress fiber. This is a bit weird in terms - // of factoring, because it relies on renderRootSync not calling - // prepareFreshStack again in the call below, which happens because the - // root and lanes haven't changed. - // - // TODO: I think what we should do is set ForceClientRender inside - // throwException, like we do for nested Suspense boundaries. The reason - // it's here instead is so we can switch to the synchronous work loop, too. - // Something to consider for a future refactor. - var rootWorkInProgress = prepareFreshStack(root, errorRetryLanes); - rootWorkInProgress.flags |= ForceClientRender; +function handleThrow(root, thrownValue) { + // A component threw an exception. Usually this is because it suspended, but + // it also includes regular program errors. + // + // We're either going to unwind the stack to show a Suspense or error + // boundary, or we're going to replay the component again. Like after a + // promise resolves. + // + // Until we decide whether we're going to unwind or replay, we should preserve + // the current state of the work loop without resetting anything. + // + // If we do decide to unwind the stack, module-level variables will be reset + // in resetSuspendedWorkLoopOnUnwind. + // These should be reset immediately because they're only supposed to be set + // when React is executing user code. + resetHooksAfterThrow(); + resetCurrentFiber(); + ReactCurrentOwner$1.current = null; - { - errorHydratingContainer(); - } + if (thrownValue === SuspenseException) { + // This is a special type of exception used for Suspense. For historical + // reasons, the rest of the Suspense implementation expects the thrown value + // to be a thenable, because before `use` existed that was the (unstable) + // API for suspending. This implementation detail can change later, once we + // deprecate the old API in favor of `use`. + thrownValue = getSuspendedThenable(); + workInProgressSuspendedReason = + shouldRemainOnPreviousScreen() && // Check if there are other pending updates that might possibly unblock this + // component from suspending. This mirrors the check in + // renderDidSuspendDelayIfPossible. We should attempt to unify them somehow. + // TODO: Consider unwinding immediately, using the + // SuspendedOnHydration mechanism. + !includesNonIdleWork(workInProgressRootSkippedLanes) && + !includesNonIdleWork(workInProgressRootInterleavedUpdatedLanes) // Suspend work loop until data resolves + ? SuspendedOnData // Don't suspend work loop, except to check if the data has + : // immediately resolved (i.e. in a microtask). Otherwise, trigger the + // nearest Suspense fallback. + SuspendedOnImmediate; + } else if (thrownValue === SelectiveHydrationException) { + // An update flowed into a dehydrated boundary. Before we can apply the + // update, we need to finish hydrating. Interrupt the work-in-progress + // render so we can restart at the hydration lane. + // + // The ideal implementation would be able to switch contexts without + // unwinding the current stack. + // + // We could name this something more general but as of now it's the only + // case where we think this should happen. + workInProgressSuspendedReason = SuspendedOnHydration; + } else { + // This is a regular error. + var isWakeable = + thrownValue !== null && + typeof thrownValue === "object" && + typeof thrownValue.then === "function"; + workInProgressSuspendedReason = isWakeable // A wakeable object was thrown by a legacy Suspense implementation. + ? // This has slightly different behavior than suspending with `use`. + SuspendedOnDeprecatedThrowPromise // This is a regular error. If something earlier in the component already + : // suspended, we must clear the thenable state to unblock the work loop. + SuspendedOnError; } - var exitStatus = renderRootSync(root, errorRetryLanes); + workInProgressThrownValue = thrownValue; + var erroredWork = workInProgress; - if (exitStatus !== RootErrored) { - // Successfully finished rendering on retry - if (workInProgressRootDidAttachPingListener && !wasRootDehydrated) { - // During the synchronous render, we attached additional ping listeners. - // This is highly suggestive of an uncached promise (though it's not the - // only reason this would happen). If it was an uncached promise, then - // it may have masked a downstream error from ocurring without actually - // fixing it. Example: - // - // use(Promise.resolve('uncached')) - // throw new Error('Oops!') - // - // When this happens, there's a conflict between blocking potential - // concurrent data races and unwrapping uncached promise values. We - // have to choose one or the other. Because the data race recovery is - // a last ditch effort, we'll disable it. - root.errorRecoveryDisabledLanes = mergeLanes( - root.errorRecoveryDisabledLanes, - originallyAttemptedLanes - ); // Mark the current render as suspended and force it to restart. Once - // these lanes finish successfully, we'll re-enable the error recovery - // mechanism for subsequent updates. + if (erroredWork === null) { + // This is a fatal error + workInProgressRootExitStatus = RootFatalErrored; + workInProgressRootFatalError = thrownValue; + return; + } - workInProgressRootInterleavedUpdatedLanes |= originallyAttemptedLanes; - return RootSuspendedWithDelay; - } // The errors from the failed first attempt have been recovered. Add - // them to the collection of recoverable errors. We'll log them in the - // commit phase. + if (erroredWork.mode & ProfileMode) { + // Record the time spent rendering before an error was thrown. This + // avoids inaccurate Profiler durations in the case of a + // suspended render. + stopProfilerTimerIfRunningAndRecordDelta(erroredWork, true); + } - 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. + { + markComponentRenderStopped(); - if (errorsFromSecondAttempt !== null) { - queueRecoverableErrors(errorsFromSecondAttempt); + switch (workInProgressSuspendedReason) { + case SuspendedOnError: { + markComponentErrored( + erroredWork, + thrownValue, + workInProgressRootRenderLanes + ); + break; + } + + case SuspendedOnData: + case SuspendedOnImmediate: + case SuspendedOnDeprecatedThrowPromise: + case SuspendedAndReadyToContinue: { + var wakeable = thrownValue; + markComponentSuspended( + erroredWork, + wakeable, + workInProgressRootRenderLanes + ); + break; + } } } - - return exitStatus; } -function queueRecoverableErrors(errors) { - if (workInProgressRootRecoverableErrors === null) { - workInProgressRootRecoverableErrors = errors; - } else { - // $FlowFixMe[method-unbinding] - workInProgressRootRecoverableErrors.push.apply( - workInProgressRootRecoverableErrors, - errors - ); +function shouldRemainOnPreviousScreen() { + // This is asking whether it's better to suspend the transition and remain + // on the previous screen, versus showing a fallback as soon as possible. It + // takes into account both the priority of render and also whether showing a + // fallback would produce a desirable user experience. + // TODO: Once `use` has fully replaced the `throw promise` pattern, we should + // be able to remove the equivalent check in finishConcurrentRender, and rely + // just on this one. + if (includesOnlyTransitions(workInProgressRootRenderLanes)) { + if (getShellBoundary() === null) { + // We're rendering inside the "shell" of the app. Activating the nearest + // fallback would cause visible content to disappear. It's better to + // suspend the transition and remain on the previous screen. + return true; + } else { + // We're rendering content that wasn't part of the previous screen. + // Rather than block the transition, it's better to show a fallback as + // soon as possible. The appearance of any nested fallbacks will be + // throttled to avoid jank. + return false; + } } -} -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 + var handler = getSuspenseHandler(); - 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 (handler === null); + else { + if (includesOnlyRetries(workInProgressRootRenderLanes)) { + // During a retry, we can suspend rendering if the nearest Suspense boundary + // is the boundary of the "shell", because we're guaranteed not to block + // any new content from appearing. + return handler === getShellBoundary(); } + } // For all other Lanes besides Transitions and Retries, we should not wait + // for the data to load. + // TODO: We should wait during Offscreen prerendering, too. - case RootSuspended: { - markRootSuspended(root, lanes); // We have an acceptable loading state. We need to figure out if we - // should immediately commit it or wait a bit. - - 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$1(); // Don't bother with a very short suspense time. + return false; +} - if (msUntilTimeout > 10) { - var nextLanes = getNextLanes(root, NoLanes); +function pushDispatcher(container) { + var prevDispatcher = ReactCurrentDispatcher.current; + ReactCurrentDispatcher.current = ContextOnlyDispatcher; - if (nextLanes !== NoLanes) { - // There's additional work on this root. - 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. + 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; + } +} - root.timeoutHandle = scheduleTimeout( - commitRoot.bind( - null, - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ), - msUntilTimeout - ); - break; - } - } // The work expired. Commit immediately. +function popDispatcher(prevDispatcher) { + ReactCurrentDispatcher.current = prevDispatcher; +} - commitRoot( - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ); - break; - } +function markCommitTimeOfFallback() { + globalMostRecentFallbackTime = now$1(); +} +function markSkippedUpdateLanes(lane) { + workInProgressRootSkippedLanes = mergeLanes( + lane, + workInProgressRootSkippedLanes + ); +} +function renderDidSuspend() { + if (workInProgressRootExitStatus === RootInProgress) { + workInProgressRootExitStatus = RootSuspended; + } +} +function renderDidSuspendDelayIfPossible() { + workInProgressRootExitStatus = RootSuspendedWithDelay; // Check if there are updates that we skipped tree that might have unblocked + // this render. - case RootSuspendedWithDelay: { - markRootSuspended(root, lanes); + 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. + // TODO: Consider unwinding immediately, using the + // SuspendedOnHydration mechanism. + // $FlowFixMe[incompatible-call] need null check workInProgressRoot + markRootSuspended(workInProgressRoot, workInProgressRootRenderLanes); + } +} +function renderDidError(error) { + if (workInProgressRootExitStatus !== RootSuspendedWithDelay) { + workInProgressRootExitStatus = RootErrored; + } - 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 (workInProgressRootConcurrentErrors === null) { + workInProgressRootConcurrentErrors = [error]; + } else { + workInProgressRootConcurrentErrors.push(error); + } +} // Called during render to determine if anything has suspended. +// Returns false if we're not sure. - 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$1() - eventTimeMs; +function renderHasNotSuspendedYet() { + // If something errored or completed, we can't really be sure, + // so those are false. + return workInProgressRootExitStatus === RootInProgress; +} // TODO: Over time, this function and renderRootConcurrent have become more +// and more similar. Not sure it makes sense to maintain forked paths. Consider +// unifying them again. - var _msUntilTimeout = jnd(timeElapsedMs) - timeElapsedMs; // Don't bother with a very short suspense time. +function renderRootSync(root, lanes) { + var prevExecutionContext = executionContext; + executionContext |= RenderContext; + var prevDispatcher = pushDispatcher(); + // and prepare a fresh one. Otherwise we'll continue where we left off. - 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. + if (workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes) { + { + if (isDevToolsPresent) { + var memoizedUpdaters = root.memoizedUpdaters; - commitRoot( - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ); - break; - } + 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. - case RootCompleted: { - // The work completed. Ready to commit. - commitRoot( - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ); - break; + movePendingFibersToMemoized(root, lanes); + } } - default: { - throw new Error("Unknown root exit status."); - } + workInProgressTransitions = getTransitionsForLanes(); + prepareFreshStack(root, lanes); } -} -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; + { + markRenderStarted(lanes); + } - if (updateQueue !== null) { - var checks = updateQueue.stores; + outer: do { + try { + if ( + workInProgressSuspendedReason !== NotSuspended && + workInProgress !== null + ) { + // The work loop is suspended. During a synchronous render, we don't + // yield to the main thread. Immediately unwind the stack. This will + // trigger either a fallback or an error boundary. + // TODO: For discrete and "default" updates (anything that's not + // flushSync), we want to wait for the microtasks the flush before + // unwinding. Will probably implement this using renderRootConcurrent, + // or merge renderRootSync and renderRootConcurrent into the same + // function and fork the behavior some other way. + var unitOfWork = workInProgress; + var thrownValue = workInProgressThrownValue; - if (checks !== null) { - for (var i = 0; i < checks.length; i++) { - var check = checks[i]; - var getSnapshot = check.getSnapshot; - var renderedValue = check.value; + switch (workInProgressSuspendedReason) { + case SuspendedOnHydration: { + // Selective hydration. An update flowed into a dehydrated tree. + // Interrupt the current render so the work loop can switch to the + // hydration lane. + resetWorkInProgressStack(); + workInProgressRootExitStatus = RootDidNotComplete; + break outer; + } - 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; - } + default: { + // Continue with the normal work loop. + workInProgressSuspendedReason = NotSuspended; + workInProgressThrownValue = null; + unwindSuspendedUnitOfWork(unitOfWork, thrownValue); + break; } } } + + workLoopSync(); + break; + } catch (thrownValue) { + handleThrow(root, thrownValue); } + } while (true); - var child = node.child; + resetContextDependencies(); + executionContext = prevExecutionContext; + popDispatcher(prevDispatcher); - if (node.subtreeFlags & StoreConsistency && child !== null) { - child.return = node; - node = child; - continue; - } + 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 (node === finishedWork) { - return true; - } + { + markRenderStopped(); + } // Set this to null to indicate there's no in-progress render. - while (node.sibling === null) { - if (node.return === null || node.return === finishedWork) { - return true; - } + workInProgressRoot = null; + workInProgressRootRenderLanes = NoLanes; // It's safe to process the queue now that the render phase is complete. - node = node.return; - } + finishQueueingConcurrentUpdates(); + return workInProgressRootExitStatus; +} // The work loop is an extremely hot path. Tell Closure not to inline it. - node.sibling.return = node.return; - node = node.sibling; - } // Flow doesn't know this is unreachable, but eslint does - // eslint-disable-next-line no-unreachable +/** @noinline */ - return true; +function workLoopSync() { + // Perform work without checking if we need to yield between fiber. + while (workInProgress !== null) { + performUnitOfWork(workInProgress); + } } -function markRootSuspended(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$1(root, suspendedLanes); -} // This is the entry point for synchronous tasks that don't go -// through Scheduler +function renderRootConcurrent(root, lanes) { + var prevExecutionContext = executionContext; + executionContext |= RenderContext; + var prevDispatcher = pushDispatcher(); + // and prepare a fresh one. Otherwise we'll continue where we left off. -function performSyncWorkOnRoot(root) { - { - syncNestedUpdateFlag(); + if (workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes) { + { + if (isDevToolsPresent) { + var memoizedUpdaters = root.memoizedUpdaters; + + if (memoizedUpdaters.size > 0) { + restorePendingUpdaters(root, workInProgressRootRenderLanes); + memoizedUpdaters.clear(); + } // At this point, move Fibers that scheduled the upcoming work from the Map to the Set. + // If we bailout on this work, we'll move them back (like above). + // It's important to move them now in case the work spawns more work at the same priority with different updaters. + // That way we can keep the current update and future updates separate. + + movePendingFibersToMemoized(root, lanes); + } + } + + workInProgressTransitions = getTransitionsForLanes(); + resetRenderTimer(); + prepareFreshStack(root, lanes); } - if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { - throw new Error("Should not already be working."); + { + markRenderStarted(lanes); } - flushPassiveEffects(); - var lanes = getNextLanes(root, NoLanes); + outer: do { + try { + if ( + workInProgressSuspendedReason !== NotSuspended && + workInProgress !== null + ) { + // The work loop is suspended. We need to either unwind the stack or + // replay the suspended component. + var unitOfWork = workInProgress; + var thrownValue = workInProgressThrownValue; - if (!includesSyncLane(lanes)) { - // There's no remaining sync work left. - ensureRootIsScheduled(root, now$1()); - return null; - } + switch (workInProgressSuspendedReason) { + case SuspendedOnError: { + // Unwind then continue with the normal work loop. + workInProgressSuspendedReason = NotSuspended; + workInProgressThrownValue = null; + unwindSuspendedUnitOfWork(unitOfWork, thrownValue); + break; + } - var exitStatus = renderRootSync(root, lanes); + case SuspendedOnData: { + var thenable = thrownValue; - if (root.tag !== LegacyRoot && exitStatus === RootErrored) { - // If something threw an error, try rendering one more time. We'll render - // synchronously to block concurrent data mutations, and we'll includes - // all pending updates are included. If it still fails after the second - // attempt, we'll give up and commit the resulting tree. - var originallyAttemptedLanes = lanes; - var errorRetryLanes = getLanesToRetrySynchronouslyOnError( - root, - originallyAttemptedLanes - ); + if (isThenableResolved(thenable)) { + // The data resolved. Try rendering the component again. + workInProgressSuspendedReason = NotSuspended; + workInProgressThrownValue = null; + replaySuspendedUnitOfWork(unitOfWork); + break; + } // The work loop is suspended on data. We should wait for it to + // resolve before continuing to render. + // TODO: Handle the case where the promise resolves synchronously. + // Usually this is handled when we instrument the promise to add a + // `status` field, but if the promise already has a status, we won't + // have added a listener until right here. - if (errorRetryLanes !== NoLanes) { - lanes = errorRetryLanes; - exitStatus = recoverFromConcurrentError( - root, - originallyAttemptedLanes, - errorRetryLanes - ); - } - } + var onResolution = function () { + // Check if the root is still suspended on this promise. + if ( + workInProgressSuspendedReason === SuspendedOnData && + workInProgressRoot === root + ) { + // Mark the root as ready to continue rendering. + workInProgressSuspendedReason = SuspendedAndReadyToContinue; + } // Ensure the root is scheduled. We should do this even if we're + // currently working on a different root, so that we resume + // rendering later. - if (exitStatus === RootFatalErrored) { - var fatalError = workInProgressRootFatalError; - prepareFreshStack(root, NoLanes); - markRootSuspended(root, lanes); - ensureRootIsScheduled(root, now$1()); - throw fatalError; - } + ensureRootIsScheduled(root, now$1()); + }; - if (exitStatus === RootDidNotComplete) { - // The render unwound without completing the tree. This happens in special - // cases where need to exit the current render without producing a - // consistent tree or committing. - markRootSuspended(root, lanes); - ensureRootIsScheduled(root, now$1()); - return null; - } // We now have a consistent tree. Because this is a sync render, we - // will commit it even if something suspended. + thenable.then(onResolution, onResolution); + break outer; + } - 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. + case SuspendedOnImmediate: { + // If this fiber just suspended, it's possible the data is already + // cached. Yield to the main thread to give it a chance to ping. If + // it does, we can retry immediately without unwinding the stack. + workInProgressSuspendedReason = SuspendedAndReadyToContinue; + break outer; + } - ensureRootIsScheduled(root, now$1()); - return null; -} -function getExecutionContext() { - return executionContext; -} -function batchedUpdates(fn, a) { - var prevExecutionContext = executionContext; - executionContext |= BatchedContext; + case SuspendedAndReadyToContinue: { + var _thenable = thrownValue; - 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 (isThenableResolved(_thenable)) { + // The data resolved. Try rendering the component again. + workInProgressSuspendedReason = NotSuspended; + workInProgressThrownValue = null; + replaySuspendedUnitOfWork(unitOfWork); + } else { + // Otherwise, unwind then continue with the normal work loop. + workInProgressSuspendedReason = NotSuspended; + workInProgressThrownValue = null; + unwindSuspendedUnitOfWork(unitOfWork, thrownValue); + } - if ( - executionContext === NoContext && // Treat `act` as if it's inside `batchedUpdates`, even in legacy mode. - !ReactCurrentActQueue.isBatchingLegacy - ) { - resetRenderTimer(); - flushSyncCallbacksOnlyInLegacyMode(); - } - } -} -// Warning, this opts-out of checking the function body. -// eslint-disable-next-line no-unused-vars -// eslint-disable-next-line no-redeclare -// eslint-disable-next-line no-redeclare + break; + } -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(); - } + case SuspendedOnDeprecatedThrowPromise: { + // Suspended by an old implementation that uses the `throw promise` + // pattern. The newer replaying behavior can cause subtle issues + // like infinite ping loops. So we maintain the old behavior and + // always unwind. + workInProgressSuspendedReason = NotSuspended; + workInProgressThrownValue = null; + unwindSuspendedUnitOfWork(unitOfWork, thrownValue); + break; + } - var prevExecutionContext = executionContext; - executionContext |= BatchedContext; - var prevTransition = ReactCurrentBatchConfig.transition; - var previousPriority = getCurrentUpdatePriority(); + case SuspendedOnHydration: { + // Selective hydration. An update flowed into a dehydrated tree. + // Interrupt the current render so the work loop can switch to the + // hydration lane. + resetWorkInProgressStack(); + workInProgressRootExitStatus = RootDidNotComplete; + break outer; + } - try { - ReactCurrentBatchConfig.transition = null; - setCurrentUpdatePriority(DiscreteEventPriority); + default: { + throw new Error( + "Unexpected SuspendedReason. This is a bug in React." + ); + } + } + } - if (fn) { - return fn(); - } else { - return undefined; - } - } finally { - setCurrentUpdatePriority(previousPriority); - ReactCurrentBatchConfig.transition = prevTransition; - executionContext = prevExecutionContext; // Flush the immediate callbacks that were scheduled during this batch. - // Note that this will happen even if batchedUpdates is higher up - // the stack. + if (true && ReactCurrentActQueue.current !== null) { + // `act` special case: If we're inside an `act` scope, don't consult + // `shouldYield`. Always keep working until the render is complete. + // This is not just an optimization: in a unit test environment, we + // can't trust the result of `shouldYield`, because the host I/O is + // likely mocked. + workLoopSync(); + } else { + workLoopConcurrent(); + } - if ((executionContext & (RenderContext | CommitContext)) === NoContext) { - flushSyncCallbacks(); + break; + } catch (thrownValue) { + handleThrow(root, thrownValue); } - } -} -// hidden subtree. The stack logic is managed there because that's the only -// place that ever modifies it. Which module it lives in doesn't matter for -// performance because this function will get inlined regardless + } while (true); -function setRenderLanes(subtreeRenderLanes) { - renderLanes = subtreeRenderLanes; -} -function getRenderLanes() { - return renderLanes; -} + resetContextDependencies(); + popDispatcher(prevDispatcher); + executionContext = prevExecutionContext; -function resetWorkInProgressStack() { - if (workInProgress === null) return; - var interruptedWork; + if (workInProgress !== null) { + // Still work remaining. + { + markRenderYielded(); + } - if (workInProgressSuspendedReason === NotSuspended) { - // Normal case. Work-in-progress hasn't started yet. Unwind all - // its parents. - interruptedWork = workInProgress.return; + return RootInProgress; } else { - // Work-in-progress is in suspended state. Reset the work loop and unwind - // both the suspended fiber and all its parents. - resetSuspendedWorkLoopOnUnwind(); - interruptedWork = workInProgress; - } - - while (interruptedWork !== null) { - var current = interruptedWork.alternate; - unwindInterruptedWork(current, interruptedWork); - interruptedWork = interruptedWork.return; - } - - workInProgress = null; -} + // Completed the tree. + { + markRenderStopped(); + } // Set this to null to indicate there's no in-progress render. -function prepareFreshStack(root, lanes) { - root.finishedWork = null; - root.finishedLanes = NoLanes; - var timeoutHandle = root.timeoutHandle; + workInProgressRoot = null; + workInProgressRootRenderLanes = NoLanes; // It's safe to process the queue now that the render phase is complete. - 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 + finishQueueingConcurrentUpdates(); // Return the final exit status. - cancelTimeout(timeoutHandle); + return workInProgressRootExitStatus; } +} +/** @noinline */ - resetWorkInProgressStack(); - workInProgressRoot = root; - var rootWorkInProgress = createWorkInProgress(root.current, null); - workInProgress = rootWorkInProgress; - workInProgressRootRenderLanes = renderLanes = lanes; - workInProgressSuspendedReason = NotSuspended; - workInProgressThrownValue = null; - workInProgressRootDidAttachPingListener = false; - workInProgressRootExitStatus = RootInProgress; - workInProgressRootFatalError = null; - workInProgressRootSkippedLanes = NoLanes; - workInProgressRootInterleavedUpdatedLanes = NoLanes; - workInProgressRootPingedLanes = NoLanes; - workInProgressRootConcurrentErrors = null; - workInProgressRootRecoverableErrors = null; - finishQueueingConcurrentUpdates(); - - { - ReactStrictModeWarnings.discardPendingWarnings(); +function workLoopConcurrent() { + // Perform work until Scheduler asks us to yield + while (workInProgress !== null && !shouldYield()) { + // $FlowFixMe[incompatible-call] found when upgrading Flow + performUnitOfWork(workInProgress); } - - return rootWorkInProgress; } -function resetSuspendedWorkLoopOnUnwind() { - // Reset module-level state that was set during the render phase. - resetContextDependencies(); - resetHooksOnUnwind(); -} +function performUnitOfWork(unitOfWork) { + // The current, flushed, state of this fiber is the alternate. Ideally + // nothing should rely on this, but relying on it here means that we don't + // need an additional field on the work in progress. + var current = unitOfWork.alternate; + setCurrentFiber(unitOfWork); + var next; + + if ((unitOfWork.mode & ProfileMode) !== NoMode) { + startProfilerTimer(unitOfWork); + next = beginWork(current, unitOfWork, renderLanes); + stopProfilerTimerIfRunningAndRecordDelta(unitOfWork, true); + } else { + next = beginWork(current, unitOfWork, renderLanes); + } -function handleThrow(root, thrownValue) { - // A component threw an exception. Usually this is because it suspended, but - // it also includes regular program errors. - // - // We're either going to unwind the stack to show a Suspense or error - // boundary, or we're going to replay the component again. Like after a - // promise resolves. - // - // Until we decide whether we're going to unwind or replay, we should preserve - // the current state of the work loop without resetting anything. - // - // If we do decide to unwind the stack, module-level variables will be reset - // in resetSuspendedWorkLoopOnUnwind. - // These should be reset immediately because they're only supposed to be set - // when React is executing user code. - resetHooksAfterThrow(); resetCurrentFiber(); - ReactCurrentOwner$1.current = null; + unitOfWork.memoizedProps = unitOfWork.pendingProps; - if (thrownValue === SuspenseException) { - // This is a special type of exception used for Suspense. For historical - // reasons, the rest of the Suspense implementation expects the thrown value - // to be a thenable, because before `use` existed that was the (unstable) - // API for suspending. This implementation detail can change later, once we - // deprecate the old API in favor of `use`. - thrownValue = getSuspendedThenable(); - workInProgressSuspendedReason = shouldAttemptToSuspendUntilDataResolves() - ? SuspendedOnData - : SuspendedOnImmediate; - } else if (thrownValue === SelectiveHydrationException) { - // An update flowed into a dehydrated boundary. Before we can apply the - // update, we need to finish hydrating. Interrupt the work-in-progress - // render so we can restart at the hydration lane. - // - // The ideal implementation would be able to switch contexts without - // unwinding the current stack. - // - // We could name this something more general but as of now it's the only - // case where we think this should happen. - workInProgressSuspendedReason = SuspendedOnHydration; + if (next === null) { + // If this doesn't spawn new work, complete the current work. + completeUnitOfWork(unitOfWork); } else { - // This is a regular error. - var isWakeable = - thrownValue !== null && - typeof thrownValue === "object" && - typeof thrownValue.then === "function"; - workInProgressSuspendedReason = isWakeable // A wakeable object was thrown by a legacy Suspense implementation. - ? // This has slightly different behavior than suspending with `use`. - SuspendedOnDeprecatedThrowPromise // This is a regular error. If something earlier in the component already - : // suspended, we must clear the thenable state to unblock the work loop. - SuspendedOnError; + workInProgress = next; } - workInProgressThrownValue = thrownValue; - var erroredWork = workInProgress; + ReactCurrentOwner$1.current = null; +} - if (erroredWork === null) { - // This is a fatal error - workInProgressRootExitStatus = RootFatalErrored; - workInProgressRootFatalError = thrownValue; - return; - } +function replaySuspendedUnitOfWork(unitOfWork) { + // This is a fork of performUnitOfWork specifcally for replaying a fiber that + // just suspended. + // + var current = unitOfWork.alternate; + setCurrentFiber(unitOfWork); + var next; + setCurrentFiber(unitOfWork); + var isProfilingMode = (unitOfWork.mode & ProfileMode) !== NoMode; - if (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 (isProfilingMode) { + startProfilerTimer(unitOfWork); } - { - markComponentRenderStopped(); - - switch (workInProgressSuspendedReason) { - case SuspendedOnError: { - markComponentErrored( - erroredWork, - thrownValue, - workInProgressRootRenderLanes - ); - break; - } + switch (unitOfWork.tag) { + case IndeterminateComponent: { + // Because it suspended with `use`, we can assume it's a + // function component. + unitOfWork.tag = FunctionComponent; // Fallthrough to the next branch. + } + // eslint-disable-next-line no-fallthrough - case SuspendedOnData: - case SuspendedOnImmediate: - case SuspendedOnDeprecatedThrowPromise: - case SuspendedAndReadyToContinue: { - var wakeable = thrownValue; - markComponentSuspended( - erroredWork, - wakeable, - workInProgressRootRenderLanes - ); - break; - } + case FunctionComponent: + case ForwardRef: { + // Resolve `defaultProps`. This logic is copied from `beginWork`. + // TODO: Consider moving this switch statement into that module. Also, + // could maybe use this as an opportunity to say `use` doesn't work with + // `defaultProps` :) + var Component = unitOfWork.type; + var unresolvedProps = unitOfWork.pendingProps; + var resolvedProps = + unitOfWork.elementType === Component + ? unresolvedProps + : resolveDefaultProps(Component, unresolvedProps); + next = replayFunctionComponent( + current, + unitOfWork, + resolvedProps, + Component, + workInProgressRootRenderLanes + ); + break; } - } -} - -function shouldAttemptToSuspendUntilDataResolves() { - // Check if there are other pending updates that might possibly unblock this - // component from suspending. This mirrors the check in - // renderDidSuspendDelayIfPossible. We should attempt to unify them somehow. - // TODO: Consider unwinding immediately, using the - // SuspendedOnHydration mechanism. - if ( - includesNonIdleWork(workInProgressRootSkippedLanes) || - includesNonIdleWork(workInProgressRootInterleavedUpdatedLanes) - ) { - // Suspend normally. renderDidSuspendDelayIfPossible will handle - // interrupting the work loop. - return false; - } // TODO: We should be able to remove the equivalent check in - // finishConcurrentRender, and rely just on this one. - - if (includesOnlyTransitions(workInProgressRootRenderLanes)) { - // If we're rendering inside the "shell" of the app, it's better to suspend - // rendering and wait for the data to resolve. Otherwise, we should switch - // to a fallback and continue rendering. - return getShellBoundary() === null; - } - var handler = getSuspenseHandler(); + case SimpleMemoComponent: { + var _Component = unitOfWork.type; + var nextProps = unitOfWork.pendingProps; + next = replayFunctionComponent( + current, + unitOfWork, + nextProps, + _Component, + workInProgressRootRenderLanes + ); + break; + } - if (handler === null); - else { - if (includesOnlyRetries(workInProgressRootRenderLanes)) { - // During a retry, we can suspend rendering if the nearest Suspense boundary - // is the boundary of the "shell", because we're guaranteed not to block - // any new content from appearing. - return handler === getShellBoundary(); + default: { + // Other types besides function components are reset completely before + // being replayed. Currently this only happens when a Usable type is + // reconciled — the reconciler will suspend. + // + // We reset the fiber back to its original state; however, this isn't + // a full "unwind" because we're going to reuse the promises that were + // reconciled previously. So it's intentional that we don't call + // resetSuspendedWorkLoopOnUnwind here. + unwindInterruptedWork(current, unitOfWork); + unitOfWork = workInProgress = resetWorkInProgress( + unitOfWork, + renderLanes + ); + next = beginWork(current, unitOfWork, renderLanes); + break; } - } // For all other Lanes besides Transitions and Retries, we should not wait - // for the data to load. - // TODO: We should wait during Offscreen prerendering, too. + } - return false; -} + if (isProfilingMode) { + stopProfilerTimerIfRunningAndRecordDelta(unitOfWork, true); + } // The begin phase finished successfully without suspending. Return to the + // normal work loop. -function pushDispatcher(container) { - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = ContextOnlyDispatcher; + resetCurrentFiber(); + unitOfWork.memoizedProps = unitOfWork.pendingProps; - 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; + if (next === null) { + // If this doesn't spawn new work, complete the current work. + completeUnitOfWork(unitOfWork); } else { - return prevDispatcher; + workInProgress = next; } -} -function popDispatcher(prevDispatcher) { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentOwner$1.current = null; } -function markCommitTimeOfFallback() { - globalMostRecentFallbackTime = now$1(); -} -function markSkippedUpdateLanes(lane) { - workInProgressRootSkippedLanes = mergeLanes( - lane, - workInProgressRootSkippedLanes - ); -} -function renderDidSuspend() { - if (workInProgressRootExitStatus === RootInProgress) { - workInProgressRootExitStatus = RootSuspended; - } -} -function renderDidSuspendDelayIfPossible() { - workInProgressRootExitStatus = RootSuspendedWithDelay; // Check if there are updates that we skipped tree that might have unblocked - // this render. +function unwindSuspendedUnitOfWork(unitOfWork, thrownValue) { + // This is a fork of performUnitOfWork specifcally for unwinding a fiber + // that threw an exception. + // + // Return to the normal work loop. This will unwind the stack, and potentially + // result in showing a fallback. + resetSuspendedWorkLoopOnUnwind(); + var returnFiber = unitOfWork.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. - // TODO: Consider unwinding immediately, using the - // SuspendedOnHydration mechanism. - // $FlowFixMe[incompatible-call] need null check workInProgressRoot - markRootSuspended(workInProgressRoot, workInProgressRootRenderLanes); - } -} -function renderDidError(error) { - if (workInProgressRootExitStatus !== RootSuspendedWithDelay) { - workInProgressRootExitStatus = RootErrored; - } + if (returnFiber === null || workInProgressRoot === null) { + // Expected to be working on a non-root fiber. This is a fatal error + // because there's no ancestor that can handle it; the root is + // supposed to capture all errors that weren't caught by an error + // boundary. + workInProgressRootExitStatus = RootFatalErrored; + workInProgressRootFatalError = thrownValue; // Set `workInProgress` to null. This represents advancing to the next + // sibling, or the parent if there are no siblings. But since the root + // has no siblings nor a parent, we set it to null. Usually this is + // handled by `completeUnitOfWork` or `unwindWork`, but since we're + // intentionally not calling those, we need set it here. + // TODO: Consider calling `unwindWork` to pop the contexts. - if (workInProgressRootConcurrentErrors === null) { - workInProgressRootConcurrentErrors = [error]; - } else { - workInProgressRootConcurrentErrors.push(error); + workInProgress = null; + return; } -} // Called during render to determine if anything has suspended. -// Returns false if we're not sure. -function renderHasNotSuspendedYet() { - // If something errored or completed, we can't really be sure, - // so those are false. - return workInProgressRootExitStatus === RootInProgress; -} // TODO: Over time, this function and renderRootConcurrent have become more -// and more similar. Not sure it makes sense to maintain forked paths. Consider -// unifying them again. + try { + // Find and mark the nearest Suspense or error boundary that can handle + // this "exception". + throwException( + workInProgressRoot, + returnFiber, + unitOfWork, + thrownValue, + workInProgressRootRenderLanes + ); + } catch (error) { + // We had trouble processing the error. An example of this happening is + // when accessing the `componentDidCatch` property of an error boundary + // throws an error. A weird edge case. There's a regression test for this. + // To prevent an infinite loop, bubble the error up to the next parent. + workInProgress = returnFiber; + throw error; + } // Return to the normal work loop. -function renderRootSync(root, lanes) { - var prevExecutionContext = executionContext; - executionContext |= RenderContext; - var prevDispatcher = pushDispatcher(); - // and prepare a fresh one. Otherwise we'll continue where we left off. + completeUnitOfWork(unitOfWork); +} - if (workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes) { - { - if (isDevToolsPresent) { - var memoizedUpdaters = root.memoizedUpdaters; +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 (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. + 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. - movePendingFibersToMemoized(root, lanes); + if ((completedWork.flags & Incomplete) === NoFlags$1) { + setCurrentFiber(completedWork); + var next = void 0; + + if ((completedWork.mode & ProfileMode) === NoMode) { + next = completeWork(current, completedWork, renderLanes); + } else { + startProfilerTimer(completedWork); + next = completeWork(current, completedWork, renderLanes); // Update render duration assuming we didn't error. + + stopProfilerTimerIfRunningAndRecordDelta(completedWork, false); } - } - workInProgressTransitions = getTransitionsForLanes(); - prepareFreshStack(root, lanes); - } + resetCurrentFiber(); - { - markRenderStarted(lanes); - } + 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. - outer: do { - try { - if ( - workInProgressSuspendedReason !== NotSuspended && - workInProgress !== null - ) { - // The work loop is suspended. During a synchronous render, we don't - // yield to the main thread. Immediately unwind the stack. This will - // trigger either a fallback or an error boundary. - // TODO: For discrete and "default" updates (anything that's not - // flushSync), we want to wait for the microtasks the flush before - // unwinding. Will probably implement this using renderRootConcurrent, - // or merge renderRootSync and renderRootConcurrent into the same - // function and fork the behavior some other way. - var unitOfWork = workInProgress; - var thrownValue = workInProgressThrownValue; + if (_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; + } - switch (workInProgressSuspendedReason) { - case SuspendedOnHydration: { - // Selective hydration. An update flowed into a dehydrated tree. - // Interrupt the current render so the work loop can switch to the - // hydration lane. - resetWorkInProgressStack(); - workInProgressRootExitStatus = RootDidNotComplete; - break outer; - } + if ((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. - default: { - // Continue with the normal work loop. - workInProgressSuspendedReason = NotSuspended; - workInProgressThrownValue = null; - unwindSuspendedUnitOfWork(unitOfWork, thrownValue); - break; - } + var actualDuration = completedWork.actualDuration; + var child = completedWork.child; + + while (child !== null) { + // $FlowFixMe[unsafe-addition] addition with possible null/undefined value + actualDuration += child.actualDuration; + child = child.sibling; } + + completedWork.actualDuration = actualDuration; } - workLoopSync(); - break; - } catch (thrownValue) { - handleThrow(root, thrownValue); + if (returnFiber !== null) { + // Mark the parent fiber as incomplete and clear its subtree flags. + returnFiber.flags |= Incomplete; + returnFiber.subtreeFlags = NoFlags$1; + returnFiber.deletions = null; + } else { + // We've unwound all the way to the root. + workInProgressRootExitStatus = RootDidNotComplete; + workInProgress = null; + return; + } } - } while (true); - - resetContextDependencies(); - executionContext = prevExecutionContext; - popDispatcher(prevDispatcher); - - 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." - ); - } - { - markRenderStopped(); - } // Set this to null to indicate there's no in-progress render. + var siblingFiber = completedWork.sibling; - workInProgressRoot = null; - workInProgressRootRenderLanes = NoLanes; // It's safe to process the queue now that the render phase is complete. + if (siblingFiber !== null) { + // If there is more work to do in this returnFiber, do that next. + workInProgress = siblingFiber; + return; + } // Otherwise, return to the parent + // $FlowFixMe[incompatible-type] we bail out when we get a null - finishQueueingConcurrentUpdates(); - return workInProgressRootExitStatus; -} // The work loop is an extremely hot path. Tell Closure not to inline it. + completedWork = returnFiber; // Update the next thing we're working on in case something throws. -/** @noinline */ + workInProgress = completedWork; + } while (completedWork !== null); // We've reached the root. -function workLoopSync() { - // Perform work without checking if we need to yield between fiber. - while (workInProgress !== null) { - performUnitOfWork(workInProgress); + if (workInProgressRootExitStatus === RootInProgress) { + workInProgressRootExitStatus = RootCompleted; } } -function renderRootConcurrent(root, lanes) { - var prevExecutionContext = executionContext; - executionContext |= RenderContext; - var prevDispatcher = pushDispatcher(); - // and prepare a fresh one. Otherwise we'll continue where we left off. +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.transition; - if (workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes) { - { - if (isDevToolsPresent) { - var memoizedUpdaters = root.memoizedUpdaters; + try { + ReactCurrentBatchConfig.transition = null; + setCurrentUpdatePriority(DiscreteEventPriority); + commitRootImpl( + root, + recoverableErrors, + transitions, + previousUpdateLanePriority + ); + } finally { + ReactCurrentBatchConfig.transition = prevTransition; + setCurrentUpdatePriority(previousUpdateLanePriority); + } - if (memoizedUpdaters.size > 0) { - restorePendingUpdaters(root, workInProgressRootRenderLanes); - memoizedUpdaters.clear(); - } // At this point, move Fibers that scheduled the upcoming work from the Map to the Set. - // If we bailout on this work, we'll move them back (like above). - // It's important to move them now in case the work spawns more work at the same priority with different updaters. - // That way we can keep the current update and future updates separate. + return null; +} - movePendingFibersToMemoized(root, lanes); - } - } +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); - workInProgressTransitions = getTransitionsForLanes(); - resetRenderTimer(); - prepareFreshStack(root, lanes); + flushRenderPhaseStrictModeWarningsInDEV(); + + if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { + throw new Error("Should not already be working."); } + var finishedWork = root.finishedWork; + var lanes = root.finishedLanes; + { - markRenderStarted(lanes); + markCommitStarted(lanes); } - outer: do { - try { - if ( - workInProgressSuspendedReason !== NotSuspended && - workInProgress !== null - ) { - // The work loop is suspended. We need to either unwind the stack or - // replay the suspended component. - var unitOfWork = workInProgress; - var thrownValue = workInProgressThrownValue; - - switch (workInProgressSuspendedReason) { - case SuspendedOnError: { - // Unwind then continue with the normal work loop. - workInProgressSuspendedReason = NotSuspended; - workInProgressThrownValue = null; - unwindSuspendedUnitOfWork(unitOfWork, thrownValue); - break; - } + if (finishedWork === null) { + { + markCommitStopped(); + } - case SuspendedOnData: { - var thenable = thrownValue; + return null; + } else { + { + if (lanes === NoLanes) { + error( + "root.finishedLanes should not be empty during a commit. This is a " + + "bug in React." + ); + } + } + } - if (isThenableResolved(thenable)) { - // The data resolved. Try rendering the component again. - workInProgressSuspendedReason = NotSuspended; - workInProgressThrownValue = null; - replaySuspendedUnitOfWork(unitOfWork); - break; - } // The work loop is suspended on data. We should wait for it to - // resolve before continuing to render. - // TODO: Handle the case where the promise resolves synchronously. - // Usually this is handled when we instrument the promise to add a - // `status` field, but if the promise already has a status, we won't - // have added a listener until right here. + root.finishedWork = null; + root.finishedLanes = NoLanes; - var onResolution = function () { - // Check if the root is still suspended on this promise. - if ( - workInProgressSuspendedReason === SuspendedOnData && - workInProgressRoot === root - ) { - // Mark the root as ready to continue rendering. - workInProgressSuspendedReason = SuspendedAndReadyToContinue; - } // Ensure the root is scheduled. We should do this even if we're - // currently working on a different root, so that we resume - // rendering later. + if (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. - ensureRootIsScheduled(root, now$1()); - }; + root.callbackNode = null; + root.callbackPriority = NoLane; + root.cancelPendingCommit = null; // Check which lanes no longer have any work scheduled on them, and mark + // those as finished. - thenable.then(onResolution, onResolution); - break outer; - } + var remainingLanes = mergeLanes(finishedWork.lanes, finishedWork.childLanes); // Make sure to account for lanes that were updated by a concurrent event + // during the render phase; don't mark them as finished. - case SuspendedOnImmediate: { - // If this fiber just suspended, it's possible the data is already - // cached. Yield to the main thread to give it a chance to ping. If - // it does, we can retry immediately without unwinding the stack. - workInProgressSuspendedReason = SuspendedAndReadyToContinue; - break outer; - } + var concurrentlyUpdatedLanes = getConcurrentlyUpdatedLanes(); + remainingLanes = mergeLanes(remainingLanes, concurrentlyUpdatedLanes); + markRootFinished(root, remainingLanes); - case SuspendedAndReadyToContinue: { - var _thenable = thrownValue; + 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 (isThenableResolved(_thenable)) { - // The data resolved. Try rendering the component again. - workInProgressSuspendedReason = NotSuspended; - workInProgressThrownValue = null; - replaySuspendedUnitOfWork(unitOfWork); - } else { - // Otherwise, unwind then continue with the normal work loop. - workInProgressSuspendedReason = NotSuspended; - workInProgressThrownValue = null; - unwindSuspendedUnitOfWork(unitOfWork, thrownValue); - } + if ( + (finishedWork.subtreeFlags & PassiveMask) !== NoFlags$1 || + (finishedWork.flags & PassiveMask) !== NoFlags$1 + ) { + if (!rootDoesHavePassiveEffects) { + rootDoesHavePassiveEffects = true; + scheduleCallback(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) - break; - } + 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. - case SuspendedOnDeprecatedThrowPromise: { - // Suspended by an old implementation that uses the `throw promise` - // pattern. The newer replaying behavior can cause subtle issues - // like infinite ping loops. So we maintain the old behavior and - // always unwind. - workInProgressSuspendedReason = NotSuspended; - workInProgressThrownValue = null; - unwindSuspendedUnitOfWork(unitOfWork, thrownValue); - break; - } + var subtreeHasEffects = + (finishedWork.subtreeFlags & + (BeforeMutationMask | MutationMask | LayoutMask | PassiveMask)) !== + NoFlags$1; + var rootHasEffect = + (finishedWork.flags & + (BeforeMutationMask | MutationMask | LayoutMask | PassiveMask)) !== + NoFlags$1; - case SuspendedOnHydration: { - // Selective hydration. An update flowed into a dehydrated tree. - // Interrupt the current render so the work loop can switch to the - // hydration lane. - resetWorkInProgressStack(); - workInProgressRootExitStatus = RootDidNotComplete; - break outer; - } + if (subtreeHasEffects || rootHasEffect) { + var prevTransition = ReactCurrentBatchConfig.transition; + ReactCurrentBatchConfig.transition = null; + var previousPriority = getCurrentUpdatePriority(); + setCurrentUpdatePriority(DiscreteEventPriority); + var prevExecutionContext = executionContext; + executionContext |= CommitContext; // Reset this to null before calling lifecycles - default: { - throw new Error( - "Unexpected SuspendedReason. This is a bug in React." - ); - } - } - } + ReactCurrentOwner$1.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. - if (true && ReactCurrentActQueue.current !== null) { - // `act` special case: If we're inside an `act` scope, don't consult - // `shouldYield`. Always keep working until the render is complete. - // This is not just an optimization: in a unit test environment, we - // can't trust the result of `shouldYield`, because the host I/O is - // likely mocked. - workLoopSync(); - } else { - workLoopConcurrent(); - } + commitBeforeMutationEffects(root, finishedWork); - break; - } catch (thrownValue) { - handleThrow(root, thrownValue); + { + // Mark the current commit time to be shared by all Profilers in this + // batch. This enables them to be grouped later. + recordCommitTime(); } - } while (true); - resetContextDependencies(); - popDispatcher(prevDispatcher); - executionContext = prevExecutionContext; + commitMutationEffects(root, finishedWork, lanes); + // the mutation phase, so that the previous tree is still current during + // componentWillUnmount, but before the layout phase, so that the finished + // work is current during componentDidMount/Update. + + root.current = finishedWork; // The next phase is the layout phase, where we call effects that read - if (workInProgress !== null) { - // Still work remaining. { - markRenderYielded(); + markLayoutEffectsStarted(lanes); } - return RootInProgress; - } else { - // Completed the tree. - { - markRenderStopped(); - } // Set this to null to indicate there's no in-progress render. + commitLayoutEffects(finishedWork, root, lanes); - workInProgressRoot = null; - workInProgressRootRenderLanes = NoLanes; // It's safe to process the queue now that the render phase is complete. + { + markLayoutEffectsStopped(); + } + // opportunity to paint. - finishQueueingConcurrentUpdates(); // Return the final exit status. + requestPaint(); + executionContext = prevExecutionContext; // Reset the priority to the previous non-sync value. - return workInProgressRootExitStatus; - } -} -/** @noinline */ + setCurrentUpdatePriority(previousPriority); + ReactCurrentBatchConfig.transition = prevTransition; + } else { + // No effects. + root.current = finishedWork; // Measure these anyway so the flamegraph explicitly shows that there were + // no effects. + // TODO: Maybe there's a better way to report this. -function workLoopConcurrent() { - // Perform work until Scheduler asks us to yield - while (workInProgress !== null && !shouldYield()) { - // $FlowFixMe[incompatible-call] found when upgrading Flow - performUnitOfWork(workInProgress); + { + recordCommitTime(); + } } -} -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; + var rootDidHavePassiveEffects = rootDoesHavePassiveEffects; - if ((unitOfWork.mode & ProfileMode) !== NoMode) { - startProfilerTimer(unitOfWork); - next = beginWork(current, unitOfWork, renderLanes); - stopProfilerTimerIfRunningAndRecordDelta(unitOfWork, true); + 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 { - next = beginWork(current, unitOfWork, renderLanes); - } + { + nestedPassiveUpdateCount = 0; + rootWithPassiveNestedUpdates = null; + } + } // Read this again, since an effect might have updated it - resetCurrentFiber(); - unitOfWork.memoizedProps = unitOfWork.pendingProps; + 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 (next === null) { - // If this doesn't spawn new work, complete the current work. - completeUnitOfWork(unitOfWork); - } else { - workInProgress = next; + if (remainingLanes === NoLanes) { + // If there's no remaining work, we can clear the set of already failed + // error boundaries. + legacyErrorBoundariesThatAlreadyFailed = null; } - ReactCurrentOwner$1.current = null; -} - -function replaySuspendedUnitOfWork(unitOfWork) { - // This is a fork of performUnitOfWork specifcally for replaying a fiber that - // just suspended. - // - var current = unitOfWork.alternate; - setCurrentFiber(unitOfWork); - var next; - setCurrentFiber(unitOfWork); - var isProfilingMode = (unitOfWork.mode & ProfileMode) !== NoMode; - - if (isProfilingMode) { - startProfilerTimer(unitOfWork); + { + if (!rootDidHavePassiveEffects) { + commitDoubleInvokeEffectsInDEV(root, false); + } } - switch (unitOfWork.tag) { - case IndeterminateComponent: { - // Because it suspended with `use`, we can assume it's a - // function component. - unitOfWork.tag = FunctionComponent; // Fallthrough to the next branch. - } - // eslint-disable-next-line no-fallthrough + onCommitRoot(finishedWork.stateNode, renderPriorityLevel); - case FunctionComponent: - case ForwardRef: { - // Resolve `defaultProps`. This logic is copied from `beginWork`. - // TODO: Consider moving this switch statement into that module. Also, - // could maybe use this as an opportunity to say `use` doesn't work with - // `defaultProps` :) - var Component = unitOfWork.type; - var unresolvedProps = unitOfWork.pendingProps; - var resolvedProps = - unitOfWork.elementType === Component - ? unresolvedProps - : resolveDefaultProps(Component, unresolvedProps); - next = replayFunctionComponent( - current, - unitOfWork, - resolvedProps, - Component, - workInProgressRootRenderLanes - ); - break; + { + if (isDevToolsPresent) { + root.memoizedUpdaters.clear(); } + } + // additional work on this root is scheduled. - case SimpleMemoComponent: { - var _Component = unitOfWork.type; - var nextProps = unitOfWork.pendingProps; - next = replayFunctionComponent( - current, - unitOfWork, - nextProps, - _Component, - workInProgressRootRenderLanes - ); - break; - } + ensureRootIsScheduled(root, now$1()); - default: { - { - error( - "Unexpected type of work: %s, Currently only function " + - "components are replayed after suspending. This is a bug in React.", - unitOfWork.tag - ); - } + 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; - resetSuspendedWorkLoopOnUnwind(); - unwindInterruptedWork(current, unitOfWork); - unitOfWork = workInProgress = resetWorkInProgress( - unitOfWork, - renderLanes + for (var i = 0; i < recoverableErrors.length; i++) { + var recoverableError = recoverableErrors[i]; + var errorInfo = makeErrorInfo( + recoverableError.digest, + recoverableError.stack ); - next = beginWork(current, unitOfWork, renderLanes); - break; + onRecoverableError(recoverableError.value, errorInfo); } } - if (isProfilingMode) { - stopProfilerTimerIfRunningAndRecordDelta(unitOfWork, true); - } // The begin phase finished successfully without suspending. Return to the - // normal work loop. + 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. - resetCurrentFiber(); - unitOfWork.memoizedProps = unitOfWork.pendingProps; + if (includesSyncLane(pendingPassiveEffectsLanes) && root.tag !== LegacyRoot) { + flushPassiveEffects(); + } // Read this again, since a passive effect might have updated it - if (next === null) { - // If this doesn't spawn new work, complete the current work. - completeUnitOfWork(unitOfWork); + remainingLanes = root.pendingLanes; + + if (includesSyncLane(remainingLanes)) { + { + 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 { - workInProgress = next; + nestedUpdateCount = 0; + } // If layout work was scheduled, flush it now. + + flushSyncCallbacks(); + + { + markCommitStopped(); } - ReactCurrentOwner$1.current = null; + return null; } -function unwindSuspendedUnitOfWork(unitOfWork, thrownValue) { - // This is a fork of performUnitOfWork specifcally for unwinding a fiber - // that threw an exception. - // - // Return to the normal work loop. This will unwind the stack, and potentially - // result in showing a fallback. - resetSuspendedWorkLoopOnUnwind(); - var returnFiber = unitOfWork.return; - - if (returnFiber === null || workInProgressRoot === null) { - // Expected to be working on a non-root fiber. This is a fatal error - // because there's no ancestor that can handle it; the root is - // supposed to capture all errors that weren't caught by an error - // boundary. - workInProgressRootExitStatus = RootFatalErrored; - workInProgressRootFatalError = thrownValue; // Set `workInProgress` to null. This represents advancing to the next - // sibling, or the parent if there are no siblings. But since the root - // has no siblings nor a parent, we set it to null. Usually this is - // handled by `completeUnitOfWork` or `unwindWork`, but since we're - // intentionally not calling those, we need set it here. - // TODO: Consider calling `unwindWork` to pop the contexts. +function makeErrorInfo(digest, componentStack) { + { + var errorInfo = { + componentStack: componentStack, + digest: digest + }; + Object.defineProperty(errorInfo, "digest", { + configurable: false, + enumerable: true, + get: function () { + error( + 'You are accessing "digest" from the errorInfo object passed to onRecoverableError.' + + " This property is deprecated and will be removed in a future version of React." + + " To access the digest of an Error look for this property on the Error instance itself." + ); - workInProgress = null; - return; + return digest; + } + }); + return errorInfo; } +} - try { - // Find and mark the nearest Suspense or error boundary that can handle - // this "exception". - throwException( - workInProgressRoot, - returnFiber, - unitOfWork, - thrownValue, - workInProgressRootRenderLanes - ); - } catch (error) { - // We had trouble processing the error. An example of this happening is - // when accessing the `componentDidCatch` property of an error boundary - // throws an error. A weird edge case. There's a regression test for this. - // To prevent an infinite loop, bubble the error up to the next parent. - workInProgress = returnFiber; - throw error; - } // Return to the normal work loop. +function flushPassiveEffects() { + // Returns whether passive effects were flushed. + // TODO: Combine this check with the one in flushPassiveEFfectsImpl. We should + // probably just combine the two functions. I believe they were only separate + // in the first place because we used to wrap it with + // `Scheduler.runWithPriority`, which accepts a function. But now we track the + // priority within React itself, so we can mutate the variable directly. + if (rootWithPendingPassiveEffects !== null) { + var renderPriority = lanesToEventPriority(pendingPassiveEffectsLanes); + var priority = lowerEventPriority(DefaultEventPriority, renderPriority); + var prevTransition = ReactCurrentBatchConfig.transition; + var previousPriority = getCurrentUpdatePriority(); - completeUnitOfWork(unitOfWork); + try { + ReactCurrentBatchConfig.transition = null; + setCurrentUpdatePriority(priority); + return flushPassiveEffectsImpl(); + } finally { + setCurrentUpdatePriority(previousPriority); + ReactCurrentBatchConfig.transition = prevTransition; // Once passive effects have run for the tree - giving components a + } + } + + return false; } +function enqueuePendingPassiveProfilerEffect(fiber) { + { + pendingPassiveProfilerEffects.push(fiber); -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 (!rootDoesHavePassiveEffects) { + rootDoesHavePassiveEffects = true; + scheduleCallback(NormalPriority, function () { + flushPassiveEffects(); + return null; + }); + } + } +} - 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. +function flushPassiveEffectsImpl() { + if (rootWithPendingPassiveEffects === null) { + return false; + } // Cache and clear the transitions flag + 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 ((completedWork.flags & Incomplete) === NoFlags$1) { - setCurrentFiber(completedWork); - var next = void 0; + pendingPassiveEffectsLanes = NoLanes; - if ((completedWork.mode & ProfileMode) === NoMode) { - next = completeWork(current, completedWork, renderLanes); - } else { - startProfilerTimer(completedWork); - next = completeWork(current, completedWork, renderLanes); // Update render duration assuming we didn't error. + if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { + throw new Error("Cannot flush passive effects while already rendering."); + } - stopProfilerTimerIfRunningAndRecordDelta(completedWork, false); - } + { + isFlushingPassiveEffects = true; + didScheduleUpdateDuringPassiveEffects = false; + } - resetCurrentFiber(); + { + markPassiveEffectsStarted(lanes); + } - 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. + var prevExecutionContext = executionContext; + executionContext |= CommitContext; + commitPassiveUnmountEffects(root.current); + commitPassiveMountEffects(root, root.current); // TODO: Move to commitPassiveMountEffects - 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; - } + { + var profilerEffects = pendingPassiveProfilerEffects; + pendingPassiveProfilerEffects = []; - 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. + for (var i = 0; i < profilerEffects.length; i++) { + var fiber = profilerEffects[i]; + commitPassiveEffectDurations(root, fiber); + } + } - var actualDuration = completedWork.actualDuration; - var child = completedWork.child; + { + markPassiveEffectsStopped(); + } - while (child !== null) { - // $FlowFixMe[unsafe-addition] addition with possible null/undefined value - actualDuration += child.actualDuration; - child = child.sibling; - } + { + commitDoubleInvokeEffectsInDEV(root, true); + } - completedWork.actualDuration = actualDuration; - } + executionContext = prevExecutionContext; + flushSyncCallbacks(); - if (returnFiber !== null) { - // Mark the parent fiber as incomplete and clear its subtree flags. - returnFiber.flags |= Incomplete; - returnFiber.subtreeFlags = NoFlags$1; - returnFiber.deletions = null; - } else { - // We've unwound all the way to the root. - workInProgressRootExitStatus = RootDidNotComplete; - workInProgress = null; - return; + { + // 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; } - var siblingFiber = completedWork.sibling; + isFlushingPassiveEffects = false; + didScheduleUpdateDuringPassiveEffects = false; + } // TODO: Move to commitPassiveMountEffects - if (siblingFiber !== null) { - // If there is more work to do in this returnFiber, do that next. - workInProgress = siblingFiber; - return; - } // Otherwise, return to the parent - // $FlowFixMe[incompatible-type] we bail out when we get a null + onPostCommitRoot(root); - completedWork = returnFiber; // Update the next thing we're working on in case something throws. + { + var stateNode = root.current.stateNode; + stateNode.effectDuration = 0; + stateNode.passiveEffectDuration = 0; + } - workInProgress = completedWork; - } while (completedWork !== null); // We've reached the root. + return true; +} - if (workInProgressRootExitStatus === RootInProgress) { - workInProgressRootExitStatus = RootCompleted; +function isAlreadyFailedLegacyErrorBoundary(instance) { + return ( + legacyErrorBoundariesThatAlreadyFailed !== null && + legacyErrorBoundariesThatAlreadyFailed.has(instance) + ); +} +function markLegacyErrorBoundaryAsFailed(instance) { + if (legacyErrorBoundariesThatAlreadyFailed === null) { + legacyErrorBoundariesThatAlreadyFailed = new Set([instance]); + } else { + legacyErrorBoundariesThatAlreadyFailed.add(instance); } } -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.transition; - - try { - ReactCurrentBatchConfig.transition = null; - setCurrentUpdatePriority(DiscreteEventPriority); - commitRootImpl( - root, - recoverableErrors, - transitions, - previousUpdateLanePriority - ); - } finally { - ReactCurrentBatchConfig.transition = prevTransition; - setCurrentUpdatePriority(previousUpdateLanePriority); +function prepareToThrowUncaughtError(error) { + if (!hasUncaughtError) { + hasUncaughtError = true; + firstUncaughtError = error; } - - return null; } -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 onUncaughtError = prepareToThrowUncaughtError; - flushRenderPhaseStrictModeWarningsInDEV(); +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 ((executionContext & (RenderContext | CommitContext)) !== NoContext) { - throw new Error("Should not already be working."); + if (root !== null) { + markRootUpdated(root, SyncLane, eventTime); + ensureRootIsScheduled(root, eventTime); } +} - var finishedWork = root.finishedWork; - var lanes = root.finishedLanes; - +function captureCommitPhaseError(sourceFiber, nearestMountedAncestor, error$1) { { - markCommitStarted(lanes); + reportUncaughtErrorInDEV(error$1); + setIsRunningInsertionEffect(false); } - if (finishedWork === null) { - { - markCommitStopped(); - } - - return null; - } else { - { - if (lanes === NoLanes) { - error( - "root.finishedLanes should not be empty during a commit. This is a " + - "bug in React." - ); - } - } + 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; } - 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; // Check which lanes no longer have any work scheduled on them, and mark - // those as finished. + var fiber = null; - var remainingLanes = mergeLanes(finishedWork.lanes, finishedWork.childLanes); // Make sure to account for lanes that were updated by a concurrent event - // during the render phase; don't mark them as finished. + { + fiber = sourceFiber.return; + } - var concurrentlyUpdatedLanes = getConcurrentlyUpdatedLanes(); - remainingLanes = mergeLanes(remainingLanes, concurrentlyUpdatedLanes); - markRootFinished(root, remainingLanes); + while (fiber !== null) { + if (fiber.tag === HostRoot) { + captureCommitPhaseErrorOnRoot(fiber, sourceFiber, error$1); + return; + } else if (fiber.tag === ClassComponent) { + var ctor = fiber.type; + var instance = fiber.stateNode; - if (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 ( + 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 ( - (finishedWork.subtreeFlags & PassiveMask) !== NoFlags$1 || - (finishedWork.flags & PassiveMask) !== NoFlags$1 - ) { - if (!rootDoesHavePassiveEffects) { - rootDoesHavePassiveEffects = true; - scheduleCallback(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 (root !== null) { + markRootUpdated(root, SyncLane, eventTime); + ensureRootIsScheduled(root, eventTime); + } - return null; - }); + return; + } } - } // Check if there are any effects in the whole tree. - // TODO: This is left over from the effect list implementation, where we had - // to check for the existence of `firstEffect` to satisfy Flow. I think the - // only other reason this optimization exists is because it affects profiling. - // Reconsider whether this is necessary. - - var subtreeHasEffects = - (finishedWork.subtreeFlags & - (BeforeMutationMask | MutationMask | LayoutMask | PassiveMask)) !== - NoFlags$1; - var rootHasEffect = - (finishedWork.flags & - (BeforeMutationMask | MutationMask | LayoutMask | PassiveMask)) !== - NoFlags$1; - - if (subtreeHasEffects || rootHasEffect) { - var prevTransition = ReactCurrentBatchConfig.transition; - ReactCurrentBatchConfig.transition = null; - var previousPriority = getCurrentUpdatePriority(); - setCurrentUpdatePriority(DiscreteEventPriority); - var prevExecutionContext = executionContext; - executionContext |= CommitContext; // Reset this to null before calling lifecycles - ReactCurrentOwner$1.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. + fiber = fiber.return; + } - commitBeforeMutationEffects(root, finishedWork); + { + // 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 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; - { - // Mark the current commit time to be shared by all Profilers in this - // batch. This enables them to be grouped later. - recordCommitTime(); + if (pingCache === null) { + pingCache = root.pingCache = new PossiblyWeakMap(); + threadIDs = new Set(); + pingCache.set(wakeable, threadIDs); + } else { + threadIDs = pingCache.get(wakeable); + + if (threadIDs === undefined) { + threadIDs = new Set(); + pingCache.set(wakeable, threadIDs); } + } - commitMutationEffects(root, finishedWork, lanes); - // the mutation phase, so that the previous tree is still current during - // componentWillUnmount, but before the layout phase, so that the finished - // work is current during componentDidMount/Update. + if (!threadIDs.has(lanes)) { + workInProgressRootDidAttachPingListener = true; // Memoize using the thread ID to prevent redundant listeners. - root.current = finishedWork; // The next phase is the layout phase, where we call effects that read + threadIDs.add(lanes); + var ping = pingSuspendedRoot.bind(null, root, wakeable, lanes); { - markLayoutEffectsStarted(lanes); + if (isDevToolsPresent) { + // If we have pending work still, restore the original updaters + restorePendingUpdaters(root, lanes); + } } - commitLayoutEffects(finishedWork, root, lanes); + wakeable.then(ping, ping); + } +} - { - markLayoutEffectsStopped(); - } - // opportunity to paint. +function pingSuspendedRoot(root, wakeable, pingedLanes) { + var pingCache = root.pingCache; - requestPaint(); - executionContext = prevExecutionContext; // Reset the priority to the previous non-sync value. + if (pingCache !== null) { + // The wakeable resolved, so we no longer need to memoize, because it will + // never be thrown again. + pingCache.delete(wakeable); + } - setCurrentUpdatePriority(previousPriority); - ReactCurrentBatchConfig.transition = prevTransition; - } else { - // No effects. - root.current = finishedWork; // Measure these anyway so the flamegraph explicitly shows that there were - // no effects. - // TODO: Maybe there's a better way to report this. + var eventTime = requestEventTime(); + markRootPinged(root, pingedLanes); + warnIfSuspenseResolutionNotWrappedWithActDEV(root); - { - recordCommitTime(); + if ( + workInProgressRoot === root && + isSubsetOfLanes(workInProgressRootRenderLanes, pingedLanes) + ) { + // Received a ping at the same priority level at which we're currently + // rendering. We might want to restart this render. This should mirror + // the logic of whether or not a root suspends once it completes. + // TODO: If we're rendering sync either due to Sync, Batched or expired, + // we should probably never restart. + // If we're suspended with delay, or if it's a retry, we'll always suspend + // so we can always restart. + if ( + workInProgressRootExitStatus === RootSuspendedWithDelay || + (workInProgressRootExitStatus === RootSuspended && + includesOnlyRetries(workInProgressRootRenderLanes) && + now$1() - globalMostRecentFallbackTime < FALLBACK_THROTTLE_MS) + ) { + // Force a restart from the root by unwinding the stack. Unless this is + // being called from the render phase, because that would cause a crash. + if ((executionContext & RenderContext) === NoContext) { + prepareFreshStack(root, NoLanes); + } + } else { + // Even though we can't restart right now, we might get an + // opportunity later. So we mark this render as having a ping. + workInProgressRootPingedLanes = mergeLanes( + workInProgressRootPingedLanes, + pingedLanes + ); } } - var rootDidHavePassiveEffects = rootDoesHavePassiveEffects; + ensureRootIsScheduled(root, eventTime); +} - 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 +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? - 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. + var eventTime = requestEventTime(); + var root = enqueueConcurrentRenderForLane(boundaryFiber, retryLane); - if (remainingLanes === NoLanes) { - // If there's no remaining work, we can clear the set of already failed - // error boundaries. - legacyErrorBoundariesThatAlreadyFailed = null; + if (root !== null) { + markRootUpdated(root, retryLane, eventTime); + ensureRootIsScheduled(root, eventTime); } +} - { - if (!rootDidHavePassiveEffects) { - commitDoubleInvokeEffectsInDEV(root, false); - } +function retryDehydratedSuspenseBoundary(boundaryFiber) { + var suspenseState = boundaryFiber.memoizedState; + var retryLane = NoLane; + + if (suspenseState !== null) { + retryLane = suspenseState.retryLane; } - onCommitRoot(finishedWork.stateNode, renderPriorityLevel); + retryTimedOutBoundary(boundaryFiber, retryLane); +} +function resolveRetryWakeable(boundaryFiber, wakeable) { + var retryLane = NoLane; // Default - { - if (isDevToolsPresent) { - root.memoizedUpdaters.clear(); - } - } - // additional work on this root is scheduled. + var retryCache; - ensureRootIsScheduled(root, now$1()); + switch (boundaryFiber.tag) { + case SuspenseComponent: + retryCache = boundaryFiber.stateNode; + var suspenseState = boundaryFiber.memoizedState; - if (recoverableErrors !== null) { - // There were errors during this render, but recovered from them without - // needing to surface it to the UI. We log them here. - var onRecoverableError = root.onRecoverableError; + if (suspenseState !== null) { + retryLane = suspenseState.retryLane; + } - for (var i = 0; i < recoverableErrors.length; i++) { - var recoverableError = recoverableErrors[i]; - var errorInfo = makeErrorInfo( - recoverableError.digest, - recoverableError.stack - ); - onRecoverableError(recoverableError.value, errorInfo); - } - } + break; - 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. + case SuspenseListComponent: + retryCache = boundaryFiber.stateNode; + break; - if (includesSyncLane(pendingPassiveEffectsLanes) && root.tag !== LegacyRoot) { - flushPassiveEffects(); - } // Read this again, since a passive effect might have updated it + case OffscreenComponent: { + var instance = boundaryFiber.stateNode; + retryCache = instance._retryCache; + break; + } - remainingLanes = root.pendingLanes; + default: + throw new Error( + "Pinged unknown suspense boundary type. " + + "This is probably a bug in React." + ); + } - if (includesSyncLane(remainingLanes)) { - { - 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 (retryCache !== null) { + // The wakeable resolved, so we no longer need to memoize, because it will + // never be thrown again. + retryCache.delete(wakeable); + } - if (root === rootWithNestedUpdates) { - nestedUpdateCount++; - } else { - nestedUpdateCount = 0; - rootWithNestedUpdates = root; - } - } else { - nestedUpdateCount = 0; - } // If layout work was scheduled, flush it now. + 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. - flushSyncCallbacks(); +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; +} - { - markCommitStopped(); +function throwIfInfiniteUpdateLoopDetected() { + if (nestedUpdateCount > NESTED_UPDATE_LIMIT) { + nestedUpdateCount = 0; + nestedPassiveUpdateCount = 0; + rootWithNestedUpdates = null; + rootWithPassiveNestedUpdates = null; + throw new Error( + "Maximum update depth exceeded. This can happen when a component " + + "repeatedly calls setState inside componentWillUpdate or " + + "componentDidUpdate. React limits the number of nested updates to " + + "prevent infinite loops." + ); } - return null; -} - -function makeErrorInfo(digest, componentStack) { { - var errorInfo = { - componentStack: componentStack, - digest: digest - }; - Object.defineProperty(errorInfo, "digest", { - configurable: false, - enumerable: true, - get: function () { - error( - 'You are accessing "digest" from the errorInfo object passed to onRecoverableError.' + - " This property is deprecated and will be removed in a future version of React." + - " To access the digest of an Error look for this property on the Error instance itself." - ); + if (nestedPassiveUpdateCount > NESTED_PASSIVE_UPDATE_LIMIT) { + nestedPassiveUpdateCount = 0; + rootWithPassiveNestedUpdates = null; - return digest; - } - }); - return errorInfo; + 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." + ); + } } } -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.transition; - var previousPriority = getCurrentUpdatePriority(); - - try { - ReactCurrentBatchConfig.transition = null; - setCurrentUpdatePriority(priority); - return flushPassiveEffectsImpl(); - } finally { - setCurrentUpdatePriority(previousPriority); - ReactCurrentBatchConfig.transition = prevTransition; // Once passive effects have run for the tree - giving components a - } +function flushRenderPhaseStrictModeWarningsInDEV() { + { + ReactStrictModeWarnings.flushLegacyContextWarning(); + ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings(); } - - return false; } -function enqueuePendingPassiveProfilerEffect(fiber) { - { - pendingPassiveProfilerEffects.push(fiber); - if (!rootDoesHavePassiveEffects) { - rootDoesHavePassiveEffects = true; - scheduleCallback(NormalPriority, function () { - flushPassiveEffects(); - return null; - }); +function commitDoubleInvokeEffectsInDEV(root, hasPassiveEffects) { + { + { + legacyCommitDoubleInvokeEffectsInDEV(root.current, hasPassiveEffects); } } } -function flushPassiveEffectsImpl() { - if (rootWithPendingPassiveEffects === null) { - return false; - } // Cache and clear the transitions flag - 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; +function legacyCommitDoubleInvokeEffectsInDEV(fiber, hasPassiveEffects) { + // TODO (StrictEffects) Should we set a marker on the root if it contains strict effects + // so we don't traverse unnecessarily? similar to subtreeFlags but just at the root level. + // Maybe not a big deal since this is DEV only behavior. + setCurrentFiber(fiber); + invokeEffectsInDev(fiber, MountLayoutDev, invokeLayoutEffectUnmountInDEV); - if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { - throw new Error("Cannot flush passive effects while already rendering."); + if (hasPassiveEffects) { + invokeEffectsInDev(fiber, MountPassiveDev, invokePassiveEffectUnmountInDEV); } - { - isFlushingPassiveEffects = true; - didScheduleUpdateDuringPassiveEffects = false; - } + invokeEffectsInDev(fiber, MountLayoutDev, invokeLayoutEffectMountInDEV); - { - markPassiveEffectsStarted(lanes); + if (hasPassiveEffects) { + invokeEffectsInDev(fiber, MountPassiveDev, invokePassiveEffectMountInDEV); } - var prevExecutionContext = executionContext; - executionContext |= CommitContext; - commitPassiveUnmountEffects(root.current); - commitPassiveMountEffects(root, root.current); // TODO: Move to commitPassiveMountEffects - - { - var profilerEffects = pendingPassiveProfilerEffects; - pendingPassiveProfilerEffects = []; - - for (var i = 0; i < profilerEffects.length; i++) { - var fiber = profilerEffects[i]; - commitPassiveEffectDurations(root, fiber); - } - } + resetCurrentFiber(); +} - { - markPassiveEffectsStopped(); - } +function invokeEffectsInDev(firstChild, fiberFlags, invokeEffectFn) { + var current = firstChild; + var subtreeRoot = null; - { - commitDoubleInvokeEffectsInDEV(root, true); - } + while (current != null) { + var primarySubtreeFlag = current.subtreeFlags & fiberFlags; - executionContext = prevExecutionContext; - flushSyncCallbacks(); + if ( + current !== subtreeRoot && + current.child != null && + primarySubtreeFlag !== NoFlags$1 + ) { + current = current.child; + } else { + if ((current.flags & fiberFlags) !== NoFlags$1) { + invokeEffectFn(current); + } - { - // 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++; + if (current.sibling !== null) { + current = current.sibling; } else { - nestedPassiveUpdateCount = 0; - rootWithPassiveNestedUpdates = root; + current = subtreeRoot = current.return; } - } else { - nestedPassiveUpdateCount = 0; } + } +} - isFlushingPassiveEffects = false; - didScheduleUpdateDuringPassiveEffects = false; - } // TODO: Move to commitPassiveMountEffects - - onPostCommitRoot(root); - +var didWarnStateUpdateForNotYetMountedComponent = null; +function warnAboutUpdateOnNotYetMountedFiberInDEV(fiber) { { - var stateNode = root.current.stateNode; - stateNode.effectDuration = 0; - stateNode.passiveEffectDuration = 0; - } + if ((executionContext & RenderContext) !== NoContext) { + // We let the other warning about render phase updates deal with this one. + return; + } - return true; -} + if (!(fiber.mode & ConcurrentMode)) { + return; + } -function isAlreadyFailedLegacyErrorBoundary(instance) { - return ( - legacyErrorBoundariesThatAlreadyFailed !== null && - legacyErrorBoundariesThatAlreadyFailed.has(instance) - ); -} -function markLegacyErrorBoundaryAsFailed(instance) { - if (legacyErrorBoundariesThatAlreadyFailed === null) { - legacyErrorBoundariesThatAlreadyFailed = new Set([instance]); - } else { - legacyErrorBoundariesThatAlreadyFailed.add(instance); - } -} + var tag = fiber.tag; -function prepareToThrowUncaughtError(error) { - if (!hasUncaughtError) { - hasUncaughtError = true; - firstUncaughtError = error; - } -} + 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. -var onUncaughtError = prepareToThrowUncaughtError; + var componentName = getComponentNameFromFiber(fiber) || "ReactComponent"; -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 (didWarnStateUpdateForNotYetMountedComponent !== null) { + if (didWarnStateUpdateForNotYetMountedComponent.has(componentName)) { + return; + } // $FlowFixMe[incompatible-use] found when upgrading Flow - if (root !== null) { - markRootUpdated(root, SyncLane, eventTime); - ensureRootIsScheduled(root, eventTime); - } -} + didWarnStateUpdateForNotYetMountedComponent.add(componentName); + } else { + didWarnStateUpdateForNotYetMountedComponent = new Set([componentName]); + } -function captureCommitPhaseError(sourceFiber, nearestMountedAncestor, error$1) { - { - reportUncaughtErrorInDEV(error$1); - setIsRunningInsertionEffect(false); - } + var previousFiber = current; - 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; + try { + setCurrentFiber(fiber); + + error( + "Can't perform a React state update on a component that hasn't mounted yet. " + + "This indicates that you have a side-effect in your render function that " + + "asynchronously later calls tries to update the component. Move this work to " + + "useEffect instead." + ); + } finally { + if (previousFiber) { + setCurrentFiber(fiber); + } else { + resetCurrentFiber(); + } + } } +} +var beginWork; - var fiber = null; - - { - fiber = sourceFiber.return; - } +{ + var dummyFiber = null; - 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; + beginWork = function (current, unitOfWork, lanes) { + // If a component throws an error, we replay it again in a synchronously + // dispatched event, so that the debugger will treat it as an uncaught + // error See ReactErrorUtils for more information. + // Before entering the begin phase, copy the work-in-progress onto a dummy + // fiber. If beginWork throws, we'll use this to reset the state. + var originalWorkInProgressCopy = assignFiberPropertiesInDEV( + dummyFiber, + unitOfWork + ); + try { + return beginWork$1(current, unitOfWork, lanes); + } catch (originalError) { if ( - typeof ctor.getDerivedStateFromError === "function" || - (typeof instance.componentDidCatch === "function" && - !isAlreadyFailedLegacyErrorBoundary(instance)) + didSuspendOrErrorWhileHydratingDEV() || + originalError === SuspenseException || + originalError === SelectiveHydrationException || + (originalError !== null && + typeof originalError === "object" && + typeof originalError.then === "function") ) { - var errorInfo = createCapturedValueAtFiber(error$1, sourceFiber); - var update = createClassErrorUpdate(fiber, errorInfo, SyncLane); - var root = enqueueUpdate(fiber, update, SyncLane); - var eventTime = requestEventTime(); + // Don't replay promises. + // Don't replay errors if we are hydrating and have already suspended or handled an error + throw originalError; + } // Don't reset current debug fiber, since we're about to work on the + // same fiber again. + // Unwind the failed stack frame - if (root !== null) { - markRootUpdated(root, SyncLane, eventTime); - ensureRootIsScheduled(root, eventTime); - } + resetSuspendedWorkLoopOnUnwind(); + unwindInterruptedWork(current, unitOfWork); // Restore the original properties of the fiber. - return; - } - } + assignFiberPropertiesInDEV(unitOfWork, originalWorkInProgressCopy); - fiber = fiber.return; - } + if (unitOfWork.mode & ProfileMode) { + // Reset the profiler timer. + startProfilerTimer(unitOfWork); + } // Run beginWork again. - { - // 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 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; + invokeGuardedCallback( + null, + beginWork$1, + null, + current, + unitOfWork, + lanes + ); - if (pingCache === null) { - pingCache = root.pingCache = new PossiblyWeakMap(); - threadIDs = new Set(); - pingCache.set(wakeable, threadIDs); - } else { - threadIDs = pingCache.get(wakeable); + if (hasCaughtError()) { + var replayError = clearCaughtError(); - if (threadIDs === undefined) { - threadIDs = new Set(); - pingCache.set(wakeable, threadIDs); + 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. + + throw originalError; } - } + }; +} - if (!threadIDs.has(lanes)) { - workInProgressRootDidAttachPingListener = true; // Memoize using the thread ID to prevent redundant listeners. +var didWarnAboutUpdateInRender = false; +var didWarnAboutUpdateInRenderForAnotherComponent; - threadIDs.add(lanes); - var ping = pingSuspendedRoot.bind(null, root, wakeable, lanes); +{ + didWarnAboutUpdateInRenderForAnotherComponent = new Set(); +} - { - if (isDevToolsPresent) { - // If we have pending work still, restore the original updaters - restorePendingUpdaters(root, lanes); - } - } +function warnAboutRenderPhaseUpdatesInDEV(fiber) { + { + if (isRendering) { + switch (fiber.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { + var renderingComponentName = + (workInProgress && getComponentNameFromFiber(workInProgress)) || + "Unknown"; // Dedupe by the rendering component because it's the one that needs to be fixed. - wakeable.then(ping, ping); - } -} + var dedupeKey = renderingComponentName; -function pingSuspendedRoot(root, wakeable, pingedLanes) { - var pingCache = root.pingCache; + if (!didWarnAboutUpdateInRenderForAnotherComponent.has(dedupeKey)) { + didWarnAboutUpdateInRenderForAnotherComponent.add(dedupeKey); + var setStateComponentName = + getComponentNameFromFiber(fiber) || "Unknown"; - if (pingCache !== null) { - // The wakeable resolved, so we no longer need to memoize, because it will - // never be thrown again. - pingCache.delete(wakeable); - } + error( + "Cannot update a component (`%s`) while rendering a " + + "different component (`%s`). To locate the bad setState() call inside `%s`, " + + "follow the stack trace as described in https://reactjs.org/link/setstate-in-render", + setStateComponentName, + renderingComponentName, + renderingComponentName + ); + } - var eventTime = requestEventTime(); - markRootPinged(root, pingedLanes); - warnIfSuspenseResolutionNotWrappedWithActDEV(root); + break; + } - if ( - workInProgressRoot === root && - isSubsetOfLanes(workInProgressRootRenderLanes, pingedLanes) - ) { - // Received a ping at the same priority level at which we're currently - // rendering. We might want to restart this render. This should mirror - // the logic of whether or not a root suspends once it completes. - // TODO: If we're rendering sync either due to Sync, Batched or expired, - // we should probably never restart. - // If we're suspended with delay, or if it's a retry, we'll always suspend - // so we can always restart. - if ( - workInProgressRootExitStatus === RootSuspendedWithDelay || - (workInProgressRootExitStatus === RootSuspended && - includesOnlyRetries(workInProgressRootRenderLanes) && - now$1() - globalMostRecentFallbackTime < FALLBACK_THROTTLE_MS) - ) { - // Force a restart from the root by unwinding the stack. Unless this is - // being called from the render phase, because that would cause a crash. - if ((executionContext & RenderContext) === NoContext) { - prepareFreshStack(root, NoLanes); + 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." + ); + + didWarnAboutUpdateInRender = true; + } + + break; + } } - } else { - // Even though we can't restart right now, we might get an - // opportunity later. So we mark this render as having a ping. - workInProgressRootPingedLanes = mergeLanes( - workInProgressRootPingedLanes, - pingedLanes - ); } } - - ensureRootIsScheduled(root, 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? +function restorePendingUpdaters(root, lanes) { + { + if (isDevToolsPresent) { + var memoizedUpdaters = root.memoizedUpdaters; + memoizedUpdaters.forEach(function (schedulingFiber) { + addFiberToLanesMap(root, schedulingFiber, lanes); + }); // This function intentionally does not clear memoized updaters. + // Those may still be relevant to the current commit + // and a future one (e.g. Suspense). + } + } +} +var fakeActCallbackNode = {}; // $FlowFixMe[missing-local-annot] - var eventTime = requestEventTime(); - var root = enqueueConcurrentRenderForLane(boundaryFiber, retryLane); +function scheduleCallback(priorityLevel, callback) { + { + // If we're currently inside an `act` scope, bypass Scheduler and push to + // the `act` queue instead. + var actQueue = ReactCurrentActQueue.current; - if (root !== null) { - markRootUpdated(root, retryLane, eventTime); - ensureRootIsScheduled(root, eventTime); + if (actQueue !== null) { + actQueue.push(callback); + return fakeActCallbackNode; + } else { + return scheduleCallback$1(priorityLevel, callback); + } } } -function retryDehydratedSuspenseBoundary(boundaryFiber) { - var suspenseState = boundaryFiber.memoizedState; - var retryLane = NoLane; +function cancelCallback(callbackNode) { + if (callbackNode === fakeActCallbackNode) { + return; + } // In production, always call Scheduler. This function will be stripped out. - if (suspenseState !== null) { - retryLane = suspenseState.retryLane; - } + return cancelCallback$1(callbackNode); +} - retryTimedOutBoundary(boundaryFiber, retryLane); +function shouldForceFlushFallbacksInDEV() { + // Never force flush in production. This function should get stripped out. + return ReactCurrentActQueue.current !== null; } -function resolveRetryWakeable(boundaryFiber, wakeable) { - var retryLane = NoLane; // Default - var retryCache; +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; + } - switch (boundaryFiber.tag) { - case SuspenseComponent: - retryCache = boundaryFiber.stateNode; - var suspenseState = boundaryFiber.memoizedState; + if (executionContext !== NoContext) { + // Legacy mode doesn't warn if the update is batched, i.e. + // batchedUpdates or flushSync. + return; + } - if (suspenseState !== null) { - retryLane = suspenseState.retryLane; + 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; } + } - break; + if (ReactCurrentActQueue.current === null) { + var previousFiber = current; - case SuspenseListComponent: - retryCache = boundaryFiber.stateNode; - break; + try { + setCurrentFiber(fiber); - case OffscreenComponent: { - var instance = boundaryFiber.stateNode; - retryCache = instance._retryCache; - break; + error( + "An update to %s inside a test was not wrapped in act(...).\n\n" + + "When testing, code that causes React state updates should be " + + "wrapped into act(...):\n\n" + + "act(() => {\n" + + " /* fire events that update state */\n" + + "});\n" + + "/* assert on the output */\n\n" + + "This ensures that you're testing the behavior the user would see " + + "in the browser." + + " Learn more at https://reactjs.org/link/wrap-tests-with-act", + getComponentNameFromFiber(fiber) + ); + } finally { + if (previousFiber) { + setCurrentFiber(fiber); + } else { + resetCurrentFiber(); + } + } } - - 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; } -function throwIfInfiniteUpdateLoopDetected() { - if (nestedUpdateCount > NESTED_UPDATE_LIMIT) { - nestedUpdateCount = 0; - nestedPassiveUpdateCount = 0; - rootWithNestedUpdates = null; - rootWithPassiveNestedUpdates = null; - throw new Error( - "Maximum update depth exceeded. This can happen when a component " + - "repeatedly calls setState inside componentWillUpdate or " + - "componentDidUpdate. React limits the number of nested updates to " + - "prevent infinite loops." - ); - } - +function warnIfSuspenseResolutionNotWrappedWithActDEV(root) { { - if (nestedPassiveUpdateCount > NESTED_PASSIVE_UPDATE_LIMIT) { - nestedPassiveUpdateCount = 0; - rootWithPassiveNestedUpdates = null; - + if ( + root.tag !== LegacyRoot && + isConcurrentActEnvironment() && + ReactCurrentActQueue.current === 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." + "A suspended resource finished loading inside a test, but the event " + + "was not wrapped in act(...).\n\n" + + "When testing, code that resolves suspended data should be wrapped " + + "into act(...):\n\n" + + "act(() => {\n" + + " /* finish loading suspended data */\n" + + "});\n" + + "/* assert on the output */\n\n" + + "This ensures that you're testing the behavior the user would see " + + "in the browser." + + " Learn more at https://reactjs.org/link/wrap-tests-with-act" ); } } } -function flushRenderPhaseStrictModeWarningsInDEV() { +function setIsRunningInsertionEffect(isRunning) { { - ReactStrictModeWarnings.flushLegacyContextWarning(); - ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings(); + isRunningInsertionEffect = isRunning; } } -function commitDoubleInvokeEffectsInDEV(root, hasPassiveEffects) { +/* eslint-disable react-internal/prod-error-codes */ +// Used by React Refresh runtime through DevTools Global Hook. + +var resolveFamily = null; +var failedBoundaries = null; +var setRefreshHandler = function (handler) { { - { - legacyCommitDoubleInvokeEffectsInDEV(root.current, hasPassiveEffects); + resolveFamily = handler; + } +}; +function resolveFunctionForHotReloading(type) { + { + if (resolveFamily === null) { + // Hot reloading is disabled. + return type; + } + + var family = resolveFamily(type); + + if (family === undefined) { + return type; + } // Use the latest known implementation. + + return family.current; + } +} +function resolveClassForHotReloading(type) { + // No implementation differences. + return resolveFunctionForHotReloading(type); +} +function resolveForwardRefForHotReloading(type) { + { + if (resolveFamily === null) { + // Hot reloading is disabled. + return type; } + + 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 + }; + + if (type.displayName !== undefined) { + syntheticType.displayName = type.displayName; + } + + return syntheticType; + } + } + + return type; + } // Use the latest known implementation. + + return family.current; } } +function isCompatibleFamilyForHotReloading(fiber, element) { + { + if (resolveFamily === null) { + // Hot reloading is disabled. + return false; + } + + var prevType = fiber.elementType; + var nextType = element.type; // If we got here, we know types aren't === equal. -function legacyCommitDoubleInvokeEffectsInDEV(fiber, hasPassiveEffects) { - // TODO (StrictEffects) Should we set a marker on the root if it contains strict effects - // so we don't traverse unnecessarily? similar to subtreeFlags but just at the root level. - // Maybe not a big deal since this is DEV only behavior. - setCurrentFiber(fiber); - invokeEffectsInDev(fiber, MountLayoutDev, invokeLayoutEffectUnmountInDEV); + var needsCompareFamilies = false; + var $$typeofNextType = + typeof nextType === "object" && nextType !== null + ? nextType.$$typeof + : null; - if (hasPassiveEffects) { - invokeEffectsInDev(fiber, MountPassiveDev, invokePassiveEffectUnmountInDEV); - } + switch (fiber.tag) { + case ClassComponent: { + if (typeof nextType === "function") { + needsCompareFamilies = true; + } - invokeEffectsInDev(fiber, MountLayoutDev, invokeLayoutEffectMountInDEV); + break; + } - if (hasPassiveEffects) { - invokeEffectsInDev(fiber, MountPassiveDev, invokePassiveEffectMountInDEV); - } + 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; + } - resetCurrentFiber(); -} + break; + } -function invokeEffectsInDev(firstChild, fiberFlags, invokeEffectFn) { - var current = firstChild; - var subtreeRoot = null; + case ForwardRef: { + if ($$typeofNextType === REACT_FORWARD_REF_TYPE) { + needsCompareFamilies = true; + } else if ($$typeofNextType === REACT_LAZY_TYPE) { + needsCompareFamilies = true; + } - while (current != null) { - var primarySubtreeFlag = current.subtreeFlags & fiberFlags; + break; + } - if ( - current !== subtreeRoot && - current.child != null && - primarySubtreeFlag !== NoFlags$1 - ) { - current = current.child; - } else { - if ((current.flags & fiberFlags) !== NoFlags$1) { - invokeEffectFn(current); + 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; } - if (current.sibling !== null) { - current = current.sibling; - } else { - current = subtreeRoot = current.return; + 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); // $FlowFixMe[not-a-function] found when upgrading Flow + + if (prevFamily !== undefined && prevFamily === resolveFamily(nextType)) { + return true; } } + + return false; } } - -var didWarnStateUpdateForNotYetMountedComponent = null; -function warnAboutUpdateOnNotYetMountedFiberInDEV(fiber) { +function markFailedErrorBoundaryForHotReloading(fiber) { { - if ((executionContext & RenderContext) !== NoContext) { - // We let the other warning about render phase updates deal with this one. + if (resolveFamily === null) { + // Hot reloading is disabled. return; } - if (!(fiber.mode & ConcurrentMode)) { + if (typeof WeakSet !== "function") { return; } - var tag = fiber.tag; - - 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. - - var componentName = getComponentNameFromFiber(fiber) || "ReactComponent"; - - if (didWarnStateUpdateForNotYetMountedComponent !== null) { - if (didWarnStateUpdateForNotYetMountedComponent.has(componentName)) { - return; - } // $FlowFixMe[incompatible-use] found when upgrading Flow - - didWarnStateUpdateForNotYetMountedComponent.add(componentName); - } else { - didWarnStateUpdateForNotYetMountedComponent = new Set([componentName]); + if (failedBoundaries === null) { + failedBoundaries = new WeakSet(); } - var previousFiber = current; - - try { - setCurrentFiber(fiber); - - error( - "Can't perform a React state update on a component that hasn't mounted yet. " + - "This indicates that you have a side-effect in your render function that " + - "asynchronously later calls tries to update the component. Move this work to " + - "useEffect instead." - ); - } finally { - if (previousFiber) { - setCurrentFiber(fiber); - } else { - resetCurrentFiber(); - } - } + failedBoundaries.add(fiber); } } -var beginWork; - -{ - var dummyFiber = null; - - beginWork = function (current, unitOfWork, lanes) { - // If a component throws an error, we replay it again in a synchronously - // dispatched event, so that the debugger will treat it as an uncaught - // error See ReactErrorUtils for more information. - // Before entering the begin phase, copy the work-in-progress onto a dummy - // fiber. If beginWork throws, we'll use this to reset the state. - var originalWorkInProgressCopy = assignFiberPropertiesInDEV( - dummyFiber, - unitOfWork - ); - - try { - return beginWork$1(current, unitOfWork, lanes); - } catch (originalError) { - if ( - didSuspendOrErrorWhileHydratingDEV() || - originalError === SuspenseException || - originalError === SelectiveHydrationException || - (originalError !== null && - typeof originalError === "object" && - typeof originalError.then === "function") - ) { - // Don't replay promises. - // Don't replay errors if we are hydrating and have already suspended or handled an error - throw originalError; - } // Don't reset current debug fiber, since we're about to work on the - // same fiber again. - // Unwind the failed stack frame - - resetSuspendedWorkLoopOnUnwind(); - unwindInterruptedWork(current, unitOfWork); // Restore the original properties of the fiber. - - assignFiberPropertiesInDEV(unitOfWork, originalWorkInProgressCopy); - - if (unitOfWork.mode & ProfileMode) { - // Reset the profiler timer. - startProfilerTimer(unitOfWork); - } // Run beginWork again. +var scheduleRefresh = function (root, update) { + { + if (resolveFamily === null) { + // Hot reloading is disabled. + return; + } - invokeGuardedCallback( - null, - beginWork$1, - null, - current, - unitOfWork, - lanes + 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 (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. + flushPassiveEffects(); + flushSync(function () { + updateContainer(element, root, null, null); + }); + } +}; - throw originalError; - } - }; -} +function scheduleFibersWithFamiliesRecursively( + fiber, + updatedFamilies, + staleFamilies +) { + { + var alternate = fiber.alternate, + child = fiber.child, + sibling = fiber.sibling, + tag = fiber.tag, + type = fiber.type; + var candidateType = null; -var didWarnAboutUpdateInRender = false; -var didWarnAboutUpdateInRenderForAnotherComponent; + switch (tag) { + case FunctionComponent: + case SimpleMemoComponent: + case ClassComponent: + candidateType = type; + break; -{ - didWarnAboutUpdateInRenderForAnotherComponent = new Set(); -} + case ForwardRef: + candidateType = type.render; + break; + } -function warnAboutRenderPhaseUpdatesInDEV(fiber) { - { - if (isRendering) { - switch (fiber.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - var renderingComponentName = - (workInProgress && getComponentNameFromFiber(workInProgress)) || - "Unknown"; // Dedupe by the rendering component because it's the one that needs to be fixed. + if (resolveFamily === null) { + throw new Error("Expected resolveFamily to be set during hot reload."); + } - var dedupeKey = renderingComponentName; + var needsRender = false; + var needsRemount = false; - if (!didWarnAboutUpdateInRenderForAnotherComponent.has(dedupeKey)) { - didWarnAboutUpdateInRenderForAnotherComponent.add(dedupeKey); - var setStateComponentName = - getComponentNameFromFiber(fiber) || "Unknown"; + if (candidateType !== null) { + var family = resolveFamily(candidateType); - error( - "Cannot update a component (`%s`) while rendering a " + - "different component (`%s`). To locate the bad setState() call inside `%s`, " + - "follow the stack trace as described in https://reactjs.org/link/setstate-in-render", - setStateComponentName, - renderingComponentName, - renderingComponentName - ); + if (family !== undefined) { + if (staleFamilies.has(family)) { + needsRemount = true; + } else if (updatedFamilies.has(family)) { + if (tag === ClassComponent) { + needsRemount = true; + } else { + needsRender = 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 (failedBoundaries !== null) { + if ( + failedBoundaries.has(fiber) || // $FlowFixMe[incompatible-use] found when upgrading Flow + (alternate !== null && failedBoundaries.has(alternate)) + ) { + needsRemount = true; + } + } - didWarnAboutUpdateInRender = true; - } + if (needsRemount) { + fiber._debugNeedsRemount = true; + } - break; - } + if (needsRemount || needsRender) { + var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); } } + + if (child !== null && !needsRemount) { + scheduleFibersWithFamiliesRecursively( + child, + updatedFamilies, + staleFamilies + ); + } + + if (sibling !== null) { + scheduleFibersWithFamiliesRecursively( + sibling, + updatedFamilies, + staleFamilies + ); + } } } -function restorePendingUpdaters(root, lanes) { +var findHostInstancesForRefresh = function (root, families) { { - 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 hostInstances = new Set(); + var types = new Set( + families.map(function (family) { + return family.current; + }) + ); + findHostInstancesForMatchingFibersRecursively( + root.current, + types, + hostInstances + ); + return hostInstances; } -} -var fakeActCallbackNode = {}; // $FlowFixMe[missing-local-annot] +}; -function scheduleCallback(priorityLevel, callback) { +function findHostInstancesForMatchingFibersRecursively( + fiber, + types, + hostInstances +) { { - // If we're currently inside an `act` scope, bypass Scheduler and push to - // the `act` queue instead. - var actQueue = ReactCurrentActQueue.current; + var child = fiber.child, + sibling = fiber.sibling, + tag = fiber.tag, + type = fiber.type; + var candidateType = null; - if (actQueue !== null) { - actQueue.push(callback); - return fakeActCallbackNode; - } else { - return scheduleCallback$1(priorityLevel, callback); + switch (tag) { + case FunctionComponent: + case SimpleMemoComponent: + case ClassComponent: + candidateType = type; + break; + + case ForwardRef: + candidateType = type.render; + break; } - } -} -function cancelCallback(callbackNode) { - if (callbackNode === fakeActCallbackNode) { - return; - } // In production, always call Scheduler. This function will be stripped out. + var didMatch = false; - return cancelCallback$1(callbackNode); -} + if (candidateType !== null) { + if (types.has(candidateType)) { + didMatch = true; + } + } -function shouldForceFlushFallbacksInDEV() { - // Never force flush in production. This function should get stripped out. - return ReactCurrentActQueue.current !== null; + 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 (sibling !== null) { + findHostInstancesForMatchingFibersRecursively( + sibling, + types, + hostInstances + ); + } + } } -function warnIfUpdatesNotWrappedWithActDEV(fiber) { +function findHostInstancesForFiberShallowly(fiber, hostInstances) { { - 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 foundHostInstances = findChildHostInstancesForFiberShallowly( + fiber, + hostInstances + ); - if (executionContext !== NoContext) { - // Legacy mode doesn't warn if the update is batched, i.e. - // batchedUpdates or flushSync. - return; - } + if (foundHostInstances) { + return; + } // If we didn't find any host children, fallback to closest host parent. - if ( - fiber.tag !== FunctionComponent && - fiber.tag !== ForwardRef && - fiber.tag !== SimpleMemoComponent - ) { - // For backwards compatibility with pre-hooks code, legacy mode only - // warns for updates that originate from a hook. - return; - } - } + var node = fiber; - if (ReactCurrentActQueue.current === null) { - var previousFiber = current; + while (true) { + switch (node.tag) { + case HostSingleton: + case HostComponent: + hostInstances.add(node.stateNode); + return; - try { - setCurrentFiber(fiber); + case HostPortal: + hostInstances.add(node.stateNode.containerInfo); + return; + + case HostRoot: + hostInstances.add(node.stateNode.containerInfo); + return; + } - error( - "An update to %s inside a test was not wrapped in act(...).\n\n" + - "When testing, code that causes React state updates should be " + - "wrapped into act(...):\n\n" + - "act(() => {\n" + - " /* fire events that update state */\n" + - "});\n" + - "/* assert on the output */\n\n" + - "This ensures that you're testing the behavior the user would see " + - "in the browser." + - " Learn more at https://reactjs.org/link/wrap-tests-with-act", - getComponentNameFromFiber(fiber) - ); - } finally { - if (previousFiber) { - setCurrentFiber(fiber); - } else { - resetCurrentFiber(); - } + if (node.return === null) { + throw new Error("Expected to reach root first."); } + + node = node.return; } } } -function warnIfSuspenseResolutionNotWrappedWithActDEV(root) { +function findChildHostInstancesForFiberShallowly(fiber, hostInstances) { { - if ( - root.tag !== LegacyRoot && - isConcurrentActEnvironment() && - ReactCurrentActQueue.current === null - ) { - error( - "A suspended resource finished loading inside a test, but the event " + - "was not wrapped in act(...).\n\n" + - "When testing, code that resolves suspended data should be wrapped " + - "into act(...):\n\n" + - "act(() => {\n" + - " /* finish loading suspended data */\n" + - "});\n" + - "/* assert on the output */\n\n" + - "This ensures that you're testing the behavior the user would see " + - "in the browser." + - " Learn more at https://reactjs.org/link/wrap-tests-with-act" - ); + var node = fiber; + var foundHostInstances = false; + + while (true) { + if (node.tag === HostComponent || node.tag === HostHoistable || false) { + // We got a match. + foundHostInstances = true; + hostInstances.add(node.stateNode); // There may still be more, so keep searching. + } else if (node.child !== null) { + node.child.return = node; + node = node.child; + continue; + } + + if (node === fiber) { + return foundHostInstances; + } + + while (node.sibling === null) { + if (node.return === null || node.return === fiber) { + return foundHostInstances; + } + + node = node.return; + } + + node.sibling.return = node.return; + node = node.sibling; } } + + return false; } -function setIsRunningInsertionEffect(isRunning) { - { - isRunningInsertionEffect = isRunning; +var hasBadMapPolyfill; + +{ + hasBadMapPolyfill = false; + + 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; } } -/* eslint-disable react-internal/prod-error-codes */ -// Used by React Refresh runtime through DevTools Global Hook. +function FiberNode(tag, pendingProps, key, mode) { + // Instance + this.tag = tag; + this.key = key; + this.elementType = null; + this.type = null; + this.stateNode = null; // Fiber + + this.return = null; + this.child = null; + this.sibling = null; + this.index = 0; + this.ref = null; + this.refCleanup = null; + this.pendingProps = pendingProps; + this.memoizedProps = null; + this.updateQueue = null; + this.memoizedState = null; + this.dependencies = null; + this.mode = mode; // Effects + + this.flags = NoFlags$1; + this.subtreeFlags = NoFlags$1; + this.deletions = null; + this.lanes = NoLanes; + this.childLanes = NoLanes; + this.alternate = null; -var resolveFamily = null; -var failedBoundaries = null; -var setRefreshHandler = function (handler) { { - resolveFamily = handler; + // 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; } -}; -function resolveFunctionForHotReloading(type) { + { - if (resolveFamily === null) { - // Hot reloading is disabled. - return type; - } + // This isn't directly used but is handy for debugging internals: + this._debugSource = null; + this._debugOwner = null; + this._debugNeedsRemount = false; + this._debugHookTypes = null; - var family = resolveFamily(type); + 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. - if (family === undefined) { - return type; - } // Use the latest known implementation. +function createFiber(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 shouldConstruct(Component) { + var prototype = Component.prototype; + return !!(prototype && prototype.isReactComponent); } -function resolveClassForHotReloading(type) { - // No implementation differences. - return resolveFunctionForHotReloading(type); + +function isSimpleFunctionComponent(type) { + return ( + typeof type === "function" && + !shouldConstruct(type) && + type.defaultProps === undefined + ); } -function resolveForwardRefForHotReloading(type) { - { - if (resolveFamily === null) { - // Hot reloading is disabled. - return type; +function resolveLazyComponentTag(Component) { + if (typeof Component === "function") { + return shouldConstruct(Component) ? ClassComponent : FunctionComponent; + } else if (Component !== undefined && Component !== null) { + var $$typeof = Component.$$typeof; + + if ($$typeof === REACT_FORWARD_REF_TYPE) { + return ForwardRef; } - var family = resolveFamily(type); + if ($$typeof === REACT_MEMO_TYPE) { + return MemoComponent; + } + } - 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); + return IndeterminateComponent; +} // This is used to create an alternate fiber to do work on. + +function createWorkInProgress(current, pendingProps) { + var workInProgress = current.alternate; + + if (workInProgress === null) { + // We use a double buffering pooling technique because we know that we'll + // only ever need at most two versions of a tree. We pool the "other" unused + // node that we're free to reuse. This is lazily created to avoid allocating + // extra objects for things that are never updated. It also allow us to + // reclaim the extra memory if needed. + workInProgress = createFiber( + current.tag, + pendingProps, + current.key, + current.mode + ); + workInProgress.elementType = current.elementType; + workInProgress.type = current.type; + workInProgress.stateNode = current.stateNode; + + { + // DEV-only fields + workInProgress._debugSource = current._debugSource; + workInProgress._debugOwner = current._debugOwner; + workInProgress._debugHookTypes = current._debugHookTypes; + } - if (type.render !== currentRender) { - var syntheticType = { - $$typeof: REACT_FORWARD_REF_TYPE, - render: currentRender - }; + workInProgress.alternate = current; + current.alternate = workInProgress; + } else { + workInProgress.pendingProps = pendingProps; // Needed because Blocks store data on type. - if (type.displayName !== undefined) { - syntheticType.displayName = type.displayName; - } + workInProgress.type = current.type; // We already have an alternate. + // Reset the effect tag. - return syntheticType; - } - } + workInProgress.flags = NoFlags$1; // The effects are no longer valid. - return type; - } // Use the latest known implementation. + workInProgress.subtreeFlags = NoFlags$1; + workInProgress.deletions = null; - return family.current; - } -} -function isCompatibleFamilyForHotReloading(fiber, element) { - { - if (resolveFamily === null) { - // Hot reloading is disabled. - return false; + { + // 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. - var prevType = fiber.elementType; - var nextType = element.type; // If we got here, we know types aren't === equal. + 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 needsCompareFamilies = false; - var $$typeofNextType = - typeof nextType === "object" && nextType !== null - ? nextType.$$typeof - : null; + var currentDependencies = current.dependencies; + workInProgress.dependencies = + currentDependencies === null + ? null + : { + lanes: currentDependencies.lanes, + firstContext: currentDependencies.firstContext + }; // These will be overridden during the parent's reconciliation - switch (fiber.tag) { - case ClassComponent: { - if (typeof nextType === "function") { - needsCompareFamilies = true; - } + workInProgress.sibling = current.sibling; + workInProgress.index = current.index; + workInProgress.ref = current.ref; + workInProgress.refCleanup = current.refCleanup; - break; - } + { + workInProgress.selfBaseDuration = current.selfBaseDuration; + workInProgress.treeBaseDuration = current.treeBaseDuration; + } - 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._debugNeedsRemount = current._debugNeedsRemount; + switch (workInProgress.tag) { + case IndeterminateComponent: + case FunctionComponent: + case SimpleMemoComponent: + workInProgress.type = resolveFunctionForHotReloading(current.type); break; - } - case ForwardRef: { - if ($$typeofNextType === REACT_FORWARD_REF_TYPE) { - needsCompareFamilies = true; - } else if ($$typeofNextType === REACT_LAZY_TYPE) { - needsCompareFamilies = true; - } + case ClassComponent: + workInProgress.type = resolveClassForHotReloading(current.type); + break; + case ForwardRef: + workInProgress.type = resolveForwardRefForHotReloading(current.type); break; - } + } + } - case MemoComponent: - case SimpleMemoComponent: { - if ($$typeofNextType === REACT_MEMO_TYPE) { - // TODO: if it was but can no longer be simple, - // we shouldn't set this. - needsCompareFamilies = true; - } else if ($$typeofNextType === REACT_LAZY_TYPE) { - needsCompareFamilies = true; - } + return 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. - default: - return false; - } // Check if both types have a family and it's the same one. + var current = workInProgress.alternate; - if (needsCompareFamilies) { - // Note: memo() and forwardRef() we'll compare outer rather than inner type. - // This means both of them need to be registered to preserve state. - // If we unwrapped and compared the inner types for wrappers instead, - // then we would risk falsely saying two separate memo(Foo) - // calls are equivalent because they wrap the same Foo function. - var prevFamily = resolveFamily(prevType); // $FlowFixMe[not-a-function] found when upgrading Flow + if (current === null) { + // Reset to createFiber's initial values. + workInProgress.childLanes = NoLanes; + workInProgress.lanes = renderLanes; + workInProgress.child = null; + workInProgress.subtreeFlags = NoFlags$1; + workInProgress.memoizedProps = null; + workInProgress.memoizedState = null; + workInProgress.updateQueue = null; + workInProgress.dependencies = null; + workInProgress.stateNode = null; - if (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 = 0; + workInProgress.treeBaseDuration = 0; } + } else { + // Reset to the cloned values that createWorkInProgress would've. + workInProgress.childLanes = current.childLanes; + workInProgress.lanes = current.lanes; + workInProgress.child = current.child; + workInProgress.subtreeFlags = NoFlags$1; + workInProgress.deletions = null; + workInProgress.memoizedProps = current.memoizedProps; + workInProgress.memoizedState = current.memoizedState; + workInProgress.updateQueue = current.updateQueue; // Needed because Blocks store data on type. - return false; + 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 + }; + + { + // 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 workInProgress; } -function markFailedErrorBoundaryForHotReloading(fiber) { - { - if (resolveFamily === null) { - // Hot reloading is disabled. - return; - } +function createHostRootFiber( + tag, + isStrictMode, + concurrentUpdatesByDefaultOverride +) { + var mode; - if (typeof WeakSet !== "function") { - return; + if (tag === ConcurrentRoot) { + mode = ConcurrentMode; + + if (isStrictMode === true || createRootStrictEffectsByDefault) { + mode |= StrictLegacyMode | StrictEffectsMode; } - if (failedBoundaries === null) { - failedBoundaries = new WeakSet(); + if ( + // Only for internal experiments. + concurrentUpdatesByDefaultOverride + ) { + mode |= ConcurrentUpdatesByDefaultMode; } + } else { + mode = NoMode; + } - failedBoundaries.add(fiber); + 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); } -var scheduleRefresh = function (root, update) { - { - if (resolveFamily === null) { - // Hot reloading is disabled. - return; +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; + + { + resolvedType = resolveClassForHotReloading(resolvedType); + } + } else { + { + resolvedType = resolveFunctionForHotReloading(resolvedType); + } } - - 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; + } else if (typeof type === "string") { + { + fiberTag = HostComponent; } + } else { + getTag: switch (type) { + case REACT_FRAGMENT_TYPE: + return createFiberFromFragment(pendingProps.children, mode, lanes, key); - flushPassiveEffects(); - flushSync(function () { - updateContainer(element, root, null, null); - }); - } -}; + case REACT_STRICT_MODE_TYPE: + fiberTag = Mode; + mode |= StrictLegacyMode; -function scheduleFibersWithFamiliesRecursively( - fiber, - updatedFamilies, - staleFamilies -) { - { - var alternate = fiber.alternate, - child = fiber.child, - sibling = fiber.sibling, - tag = fiber.tag, - type = fiber.type; - var candidateType = null; + if ((mode & ConcurrentMode) !== NoMode) { + // Strict effects should never run on legacy roots + mode |= StrictEffectsMode; + } - switch (tag) { - case FunctionComponent: - case SimpleMemoComponent: - case ClassComponent: - candidateType = type; break; - case ForwardRef: - candidateType = type.render; - break; - } + case REACT_PROFILER_TYPE: + return createFiberFromProfiler(pendingProps, mode, lanes, key); - if (resolveFamily === null) { - throw new Error("Expected resolveFamily to be set during hot reload."); - } + case REACT_SUSPENSE_TYPE: + return createFiberFromSuspense(pendingProps, mode, lanes, key); - var needsRender = false; - var needsRemount = false; + case REACT_SUSPENSE_LIST_TYPE: + return createFiberFromSuspenseList(pendingProps, mode, lanes, key); - if (candidateType !== null) { - var family = resolveFamily(candidateType); + case REACT_OFFSCREEN_TYPE: + return createFiberFromOffscreen(pendingProps, mode, lanes, key); - if (family !== undefined) { - if (staleFamilies.has(family)) { - needsRemount = true; - } else if (updatedFamilies.has(family)) { - if (tag === ClassComponent) { - needsRemount = true; - } else { - needsRender = true; - } - } + case REACT_LEGACY_HIDDEN_TYPE: { + return createFiberFromLegacyHidden(pendingProps, mode, lanes, key); } - } - if (failedBoundaries !== null) { - if ( - failedBoundaries.has(fiber) || // $FlowFixMe[incompatible-use] found when upgrading Flow - (alternate !== null && failedBoundaries.has(alternate)) - ) { - needsRemount = true; - } - } + // eslint-disable-next-line no-fallthrough - if (needsRemount) { - fiber._debugNeedsRemount = true; - } + case REACT_SCOPE_TYPE: - if (needsRemount || needsRender) { - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + // eslint-disable-next-line no-fallthrough - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); - } - } + case REACT_CACHE_TYPE: - if (child !== null && !needsRemount) { - scheduleFibersWithFamiliesRecursively( - child, - updatedFamilies, - staleFamilies - ); - } + // eslint-disable-next-line no-fallthrough - if (sibling !== null) { - scheduleFibersWithFamiliesRecursively( - sibling, - updatedFamilies, - staleFamilies - ); - } - } -} + case REACT_TRACING_MARKER_TYPE: -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; - } -}; + // eslint-disable-next-line no-fallthrough -function findHostInstancesForMatchingFibersRecursively( - fiber, - types, - hostInstances -) { - { - var child = fiber.child, - sibling = fiber.sibling, - tag = fiber.tag, - type = fiber.type; - var candidateType = null; + case REACT_DEBUG_TRACING_MODE_TYPE: - switch (tag) { - case FunctionComponent: - case SimpleMemoComponent: - case ClassComponent: - candidateType = type; - break; + // eslint-disable-next-line no-fallthrough - case ForwardRef: - candidateType = type.render; - break; - } + default: { + if (typeof type === "object" && type !== null) { + switch (type.$$typeof) { + case REACT_PROVIDER_TYPE: + fiberTag = ContextProvider; + break getTag; - var didMatch = false; + case REACT_CONTEXT_TYPE: + // This is a consumer + fiberTag = ContextConsumer; + break getTag; - if (candidateType !== null) { - if (types.has(candidateType)) { - didMatch = true; - } - } + case REACT_FORWARD_REF_TYPE: + fiberTag = ForwardRef; - 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 = resolveForwardRefForHotReloading(resolvedType); + } - if (sibling !== null) { - findHostInstancesForMatchingFibersRecursively( - sibling, - types, - hostInstances - ); - } - } -} + break getTag; -function findHostInstancesForFiberShallowly(fiber, hostInstances) { - { - var foundHostInstances = findChildHostInstancesForFiberShallowly( - fiber, - hostInstances - ); + case REACT_MEMO_TYPE: + fiberTag = MemoComponent; + break getTag; - if (foundHostInstances) { - return; - } // If we didn't find any host children, fallback to closest host parent. + case REACT_LAZY_TYPE: + fiberTag = LazyComponent; + resolvedType = null; + break getTag; + } + } - var node = fiber; + var info = ""; - while (true) { - switch (node.tag) { - case HostSingleton: - case HostComponent: - hostInstances.add(node.stateNode); - return; + { + if ( + type === undefined || + (typeof type === "object" && + type !== null && + Object.keys(type).length === 0) + ) { + info += + " You likely forgot to export your component from the file " + + "it's defined in, or you might have mixed up default and " + + "named imports."; + } + + var ownerName = owner ? getComponentNameFromFiber(owner) : null; - case HostPortal: - hostInstances.add(node.stateNode.containerInfo); - return; + if (ownerName) { + info += "\n\nCheck the render method of `" + ownerName + "`."; + } + } - case HostRoot: - hostInstances.add(node.stateNode.containerInfo); - return; + throw new Error( + "Element type is invalid: expected a string (for built-in " + + "components) or a class/function (for composite components) " + + ("but got: " + (type == null ? type : typeof type) + "." + info) + ); } + } + } - if (node.return === null) { - throw new Error("Expected to reach root first."); - } + var fiber = createFiber(fiberTag, pendingProps, key, mode); + fiber.elementType = type; + fiber.type = resolvedType; + fiber.lanes = lanes; - node = node.return; - } + { + fiber._debugOwner = owner; } + + return fiber; } +function createFiberFromElement(element, mode, lanes) { + var owner = null; -function findChildHostInstancesForFiberShallowly(fiber, hostInstances) { { - var node = fiber; - var foundHostInstances = false; - - while (true) { - if (node.tag === HostComponent || node.tag === HostHoistable || false) { - // We got a match. - foundHostInstances = true; - hostInstances.add(node.stateNode); // There may still be more, so keep searching. - } else if (node.child !== null) { - node.child.return = node; - node = node.child; - continue; - } + owner = element._owner; + } - if (node === fiber) { - return foundHostInstances; - } + var type = element.type; + var key = element.key; + var pendingProps = element.props; + var fiber = createFiberFromTypeAndProps( + type, + key, + pendingProps, + owner, + mode, + lanes + ); - while (node.sibling === null) { - if (node.return === null || node.return === fiber) { - return foundHostInstances; - } + { + fiber._debugSource = element._source; + fiber._debugOwner = element._owner; + } - node = node.return; - } + return fiber; +} +function createFiberFromFragment(elements, mode, lanes, key) { + var fiber = createFiber(Fragment, elements, key, mode); + fiber.lanes = lanes; + return fiber; +} - node.sibling.return = node.return; - node = node.sibling; +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 false; + var fiber = createFiber(Profiler, pendingProps, key, mode | ProfileMode); + fiber.elementType = REACT_PROFILER_TYPE; + fiber.lanes = lanes; + + { + fiber.stateNode = { + effectDuration: 0, + passiveEffectDuration: 0 + }; + } + + return fiber; } -var hasBadMapPolyfill; +function createFiberFromSuspense(pendingProps, mode, lanes, key) { + var fiber = createFiber(SuspenseComponent, pendingProps, key, mode); + fiber.elementType = REACT_SUSPENSE_TYPE; + fiber.lanes = lanes; + return fiber; +} +function createFiberFromSuspenseList(pendingProps, mode, lanes, key) { + var fiber = createFiber(SuspenseListComponent, pendingProps, key, mode); + fiber.elementType = REACT_SUSPENSE_LIST_TYPE; + fiber.lanes = lanes; + return fiber; +} +function createFiberFromOffscreen(pendingProps, mode, lanes, key) { + var fiber = createFiber(OffscreenComponent, pendingProps, key, mode); + fiber.elementType = REACT_OFFSCREEN_TYPE; + fiber.lanes = lanes; + var primaryChildInstance = { + _visibility: OffscreenVisible, + _pendingVisibility: OffscreenVisible, + _pendingMarkers: null, + _retryCache: null, + _transitions: null, + _current: null, + detach: function () { + return detachOffscreenInstance(primaryChildInstance); + }, + attach: function () { + return attachOffscreenInstance(primaryChildInstance); + } + }; + fiber.stateNode = primaryChildInstance; + return fiber; +} +function createFiberFromLegacyHidden(pendingProps, mode, lanes, key) { + var fiber = createFiber(LegacyHiddenComponent, pendingProps, key, mode); + fiber.elementType = REACT_LEGACY_HIDDEN_TYPE; + fiber.lanes = lanes; // Adding a stateNode for legacy hidden because it's currently using + // the offscreen implementation, which depends on a state node -{ - hasBadMapPolyfill = false; + var instance = { + _visibility: OffscreenVisible, + _pendingVisibility: OffscreenVisible, + _pendingMarkers: null, + _transitions: null, + _retryCache: null, + _current: null, + detach: function () { + return detachOffscreenInstance(instance); + }, + attach: function () { + return attachOffscreenInstance(instance); + } + }; + fiber.stateNode = instance; + return fiber; +} +function 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. - try { - var nonExtensibleObject = Object.preventExtensions({}); - /* eslint-disable no-new */ +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. - new Map([[nonExtensibleObject, null]]); - new Set([nonExtensibleObject]); - /* eslint-enable no-new */ - } catch (e) { - // TODO: Consider warning about bad polyfills - hasBadMapPolyfill = true; + target.tag = source.tag; + target.key = source.key; + target.elementType = source.elementType; + target.type = source.type; + target.stateNode = source.stateNode; + target.return = source.return; + target.child = source.child; + target.sibling = source.sibling; + target.index = source.index; + target.ref = source.ref; + target.refCleanup = source.refCleanup; + target.pendingProps = source.pendingProps; + target.memoizedProps = source.memoizedProps; + target.updateQueue = source.updateQueue; + target.memoizedState = source.memoizedState; + target.dependencies = source.dependencies; + target.mode = source.mode; + target.flags = source.flags; + target.subtreeFlags = source.subtreeFlags; + target.deletions = source.deletions; + target.lanes = source.lanes; + target.childLanes = source.childLanes; + target.alternate = source.alternate; + + { + target.actualDuration = source.actualDuration; + target.actualStartTime = source.actualStartTime; + target.selfBaseDuration = source.selfBaseDuration; + target.treeBaseDuration = source.treeBaseDuration; } + + target._debugSource = source._debugSource; + target._debugOwner = source._debugOwner; + target._debugNeedsRemount = source._debugNeedsRemount; + target._debugHookTypes = source._debugHookTypes; + return target; } -function FiberNode(tag, pendingProps, key, mode) { - // Instance +function FiberRootNode( + containerInfo, // $FlowFixMe[missing-local-annot] + tag, + hydrate, + identifierPrefix, + onRecoverableError +) { this.tag = tag; - this.key = key; - this.elementType = null; - this.type = null; - this.stateNode = null; // Fiber - - this.return = null; - this.child = null; - this.sibling = null; - this.index = 0; - this.ref = null; - this.refCleanup = null; - this.pendingProps = pendingProps; - this.memoizedProps = null; - this.updateQueue = null; - this.memoizedState = null; - this.dependencies = null; - this.mode = mode; // Effects + this.containerInfo = containerInfo; + this.pendingChildren = null; + this.current = null; + this.pingCache = null; + this.finishedWork = null; + this.timeoutHandle = noTimeout; + this.cancelPendingCommit = null; + this.context = null; + this.pendingContext = null; + this.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.errorRecoveryDisabledLanes = NoLanes; + this.entangledLanes = NoLanes; + this.entanglements = createLaneMap(NoLanes); + this.hiddenUpdates = createLaneMap(null); + this.identifierPrefix = identifierPrefix; + this.onRecoverableError = onRecoverableError; - this.flags = NoFlags$1; - this.subtreeFlags = NoFlags$1; - this.deletions = null; - this.lanes = NoLanes; - this.childLanes = NoLanes; - this.alternate = null; + this.incompleteTransitions = new Map(); { - // 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.effectDuration = 0; + this.passiveEffectDuration = 0; } { - // This isn't directly used but is handy for debugging internals: - this._debugSource = null; - this._debugOwner = null; - this._debugNeedsRemount = false; - this._debugHookTypes = null; + this.memoizedUpdaters = new Set(); + var pendingUpdatersLaneMap = (this.pendingUpdatersLaneMap = []); - if (!hasBadMapPolyfill && typeof Object.preventExtensions === "function") { - Object.preventExtensions(this); + for (var _i = 0; _i < TotalLanes; _i++) { + pendingUpdatersLaneMap.push(new Set()); } } -} // 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); -}; + { + switch (tag) { + case ConcurrentRoot: + this._debugRootType = hydrate ? "hydrateRoot()" : "createRoot()"; + break; -function shouldConstruct(Component) { - var prototype = Component.prototype; - return !!(prototype && prototype.isReactComponent); + case LegacyRoot: + this._debugRootType = hydrate ? "hydrate()" : "render()"; + break; + } + } } -function isSimpleFunctionComponent(type) { - return ( - typeof type === "function" && - !shouldConstruct(type) && - type.defaultProps === undefined +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 +) { + // $FlowFixMe[invalid-constructor] Flow no longer supports calling new on functions + var root = new FiberRootNode( + containerInfo, + tag, + hydrate, + identifierPrefix, + onRecoverableError ); -} -function resolveLazyComponentTag(Component) { - if (typeof Component === "function") { - return shouldConstruct(Component) ? ClassComponent : FunctionComponent; - } else if (Component !== undefined && Component !== null) { - var $$typeof = Component.$$typeof; + // stateNode is any. - if ($$typeof === REACT_FORWARD_REF_TYPE) { - return ForwardRef; - } + var uninitializedFiber = createHostRootFiber( + tag, + isStrictMode, + concurrentUpdatesByDefaultOverride + ); + root.current = uninitializedFiber; + uninitializedFiber.stateNode = root; - if ($$typeof === REACT_MEMO_TYPE) { - return MemoComponent; - } + { + var _initialState = { + element: initialChildren, + isDehydrated: hydrate, + cache: null // not enabled yet + }; + uninitializedFiber.memoizedState = _initialState; } - return IndeterminateComponent; -} // This is used to create an alternate fiber to do work on. - -function createWorkInProgress(current, pendingProps) { - var workInProgress = current.alternate; - - if (workInProgress === null) { - // We use a double buffering pooling technique because we know that we'll - // only ever need at most two versions of a tree. We pool the "other" unused - // node that we're free to reuse. This is lazily created to avoid allocating - // extra objects for things that are never updated. It also allow us to - // reclaim the extra memory if needed. - workInProgress = createFiber( - current.tag, - pendingProps, - current.key, - current.mode - ); - workInProgress.elementType = current.elementType; - workInProgress.type = current.type; - workInProgress.stateNode = current.stateNode; - - { - // DEV-only fields - workInProgress._debugSource = current._debugSource; - workInProgress._debugOwner = current._debugOwner; - workInProgress._debugHookTypes = current._debugHookTypes; - } - - workInProgress.alternate = current; - current.alternate = workInProgress; - } else { - workInProgress.pendingProps = pendingProps; // Needed because Blocks store data on type. + initializeUpdateQueue(uninitializedFiber); + return root; +} - workInProgress.type = current.type; // We already have an alternate. - // Reset the effect tag. +var ReactVersion = "18.3.0-next-c57b90f50-20230320"; - workInProgress.flags = NoFlags$1; // The effects are no longer valid. +function createPortal$1( + children, + containerInfo, // TODO: figure out the API for cross-renderer implementation. + implementation +) { + var key = + arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; - workInProgress.subtreeFlags = NoFlags$1; - workInProgress.deletions = null; + { + checkKeyStringCoercion(key); + } - { - // 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. + 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 + }; +} - 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. +// Might add PROFILE later. - var currentDependencies = current.dependencies; - workInProgress.dependencies = - currentDependencies === null - ? null - : { - lanes: currentDependencies.lanes, - firstContext: currentDependencies.firstContext - }; // These will be overridden during the parent's reconciliation +var didWarnAboutNestedUpdates; +var didWarnAboutFindNodeInStrictMode; - workInProgress.sibling = current.sibling; - workInProgress.index = current.index; - workInProgress.ref = current.ref; - workInProgress.refCleanup = current.refCleanup; +{ + didWarnAboutNestedUpdates = false; + didWarnAboutFindNodeInStrictMode = {}; +} - { - workInProgress.selfBaseDuration = current.selfBaseDuration; - workInProgress.treeBaseDuration = current.treeBaseDuration; +function getContextForSubtree(parentComponent) { + if (!parentComponent) { + return emptyContextObject; } - { - workInProgress._debugNeedsRemount = current._debugNeedsRemount; - - switch (workInProgress.tag) { - case IndeterminateComponent: - case FunctionComponent: - case SimpleMemoComponent: - workInProgress.type = resolveFunctionForHotReloading(current.type); - break; + var fiber = get(parentComponent); + var parentContext = findCurrentUnmaskedContext(fiber); - case ClassComponent: - workInProgress.type = resolveClassForHotReloading(current.type); - break; + if (fiber.tag === ClassComponent) { + var Component = fiber.type; - case ForwardRef: - workInProgress.type = resolveForwardRefForHotReloading(current.type); - break; + if (isContextProvider(Component)) { + return processChildContext(fiber, Component, parentContext); } } - return workInProgress; -} // Used to reuse a Fiber for a second pass. + return parentContext; +} -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. +function findHostInstanceWithWarning(component, methodName) { + { + var fiber = get(component); - var current = workInProgress.alternate; + 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 + ); + } + } - if (current === null) { - // Reset to createFiber's initial values. - workInProgress.childLanes = NoLanes; - workInProgress.lanes = renderLanes; - workInProgress.child = null; - workInProgress.subtreeFlags = NoFlags$1; - workInProgress.memoizedProps = null; - workInProgress.memoizedState = null; - workInProgress.updateQueue = null; - workInProgress.dependencies = null; - workInProgress.stateNode = null; + var hostFiber = findCurrentHostFiber(fiber); - { - // 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; + if (hostFiber === null) { + return null; } - } else { - // Reset to the cloned values that createWorkInProgress would've. - workInProgress.childLanes = current.childLanes; - workInProgress.lanes = current.lanes; - workInProgress.child = current.child; - workInProgress.subtreeFlags = NoFlags$1; - workInProgress.deletions = null; - workInProgress.memoizedProps = current.memoizedProps; - workInProgress.memoizedState = current.memoizedState; - workInProgress.updateQueue = current.updateQueue; // Needed because Blocks store data on type. - workInProgress.type = current.type; // Clone the dependencies object. This is mutated during the render phase, so - // it cannot be shared with the current fiber. + if (hostFiber.mode & StrictLegacyMode) { + var componentName = getComponentNameFromFiber(fiber) || "Component"; - var currentDependencies = current.dependencies; - workInProgress.dependencies = - currentDependencies === null - ? null - : { - lanes: currentDependencies.lanes, - firstContext: currentDependencies.firstContext - }; + if (!didWarnAboutFindNodeInStrictMode[componentName]) { + didWarnAboutFindNodeInStrictMode[componentName] = true; + var previousFiber = current; - { - // 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; + 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://reactjs.org/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://reactjs.org/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(); + } + } + } } - } - return workInProgress; + return getPublicInstance(hostFiber.stateNode); + } } -function createHostRootFiber( + +function createContainer( + containerInfo, tag, + hydrationCallbacks, isStrictMode, - concurrentUpdatesByDefaultOverride + concurrentUpdatesByDefaultOverride, + identifierPrefix, + onRecoverableError, + transitionCallbacks ) { - var mode; - - if (tag === ConcurrentRoot) { - mode = ConcurrentMode; - - if (isStrictMode === true || createRootStrictEffectsByDefault) { - mode |= StrictLegacyMode | StrictEffectsMode; - } - - if ( - // Only for internal experiments. - concurrentUpdatesByDefaultOverride - ) { - mode |= ConcurrentUpdatesByDefaultMode; - } - } else { - mode = NoMode; + 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); } - if (isDevToolsPresent) { - // Always collect profile timings when DevTools are present. - // This enables DevTools to start capturing timing at any point– - // Without some nodes in the tree having empty base times. - mode |= ProfileMode; + var current$1 = container.current; + var lane = requestUpdateLane(current$1); + + { + markRenderScheduled(lane); } - 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 context = getContextForSubtree(parentComponent); - var resolvedType = type; + if (container.context === null) { + container.context = context; + } else { + container.pendingContext = context; + } - if (typeof type === "function") { - if (shouldConstruct(type)) { - fiberTag = ClassComponent; + { + if (isRendering && current !== null && !didWarnAboutNestedUpdates) { + didWarnAboutNestedUpdates = true; - { - resolvedType = resolveClassForHotReloading(resolvedType); - } - } else { - { - resolvedType = resolveFunctionForHotReloading(resolvedType); - } - } - } else if (typeof type === "string") { - { - fiberTag = HostComponent; + 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" + ); } - } else { - getTag: switch (type) { - case REACT_FRAGMENT_TYPE: - return createFiberFromFragment(pendingProps.children, mode, lanes, key); - - case REACT_STRICT_MODE_TYPE: - fiberTag = Mode; - mode |= StrictLegacyMode; + } - if ((mode & ConcurrentMode) !== NoMode) { - // Strict effects should never run on legacy roots - mode |= StrictEffectsMode; - } + var update = createUpdate(lane); // Caution: React DevTools currently depends on this property + // being called "element". - break; + update.payload = { + element: element + }; + callback = callback === undefined ? null : callback; - case REACT_PROFILER_TYPE: - return createFiberFromProfiler(pendingProps, mode, lanes, key); + if (callback !== null) { + { + if (typeof callback !== "function") { + error( + "render(...): Expected the last optional `callback` argument to be a " + + "function. Instead received: %s.", + callback + ); + } + } - case REACT_SUSPENSE_TYPE: - return createFiberFromSuspense(pendingProps, mode, lanes, key); + update.callback = callback; + } - case REACT_SUSPENSE_LIST_TYPE: - return createFiberFromSuspenseList(pendingProps, mode, lanes, key); + var root = enqueueUpdate(current$1, update, lane); - case REACT_OFFSCREEN_TYPE: - return createFiberFromOffscreen(pendingProps, mode, lanes, key); + if (root !== null) { + var eventTime = requestEventTime(); + scheduleUpdateOnFiber(root, current$1, lane, eventTime); + entangleTransitions(root, current$1, lane); + } - case REACT_LEGACY_HIDDEN_TYPE: { - return createFiberFromLegacyHidden(pendingProps, mode, lanes, key); - } + return lane; +} +function getPublicRootInstance(container) { + var containerFiber = container.current; - // eslint-disable-next-line no-fallthrough + if (!containerFiber.child) { + return null; + } - case REACT_SCOPE_TYPE: + switch (containerFiber.child.tag) { + case HostSingleton: + case HostComponent: + return getPublicInstance(containerFiber.child.stateNode); - // eslint-disable-next-line no-fallthrough + default: + return containerFiber.child.stateNode; + } +} - case REACT_CACHE_TYPE: +var shouldErrorImpl = function (fiber) { + return null; +}; - // eslint-disable-next-line no-fallthrough +function shouldError(fiber) { + return shouldErrorImpl(fiber); +} - case REACT_TRACING_MARKER_TYPE: +var shouldSuspendImpl = function (fiber) { + return false; +}; - // eslint-disable-next-line no-fallthrough +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; - case REACT_DEBUG_TRACING_MODE_TYPE: +{ + var copyWithDeleteImpl = function (obj, path, index) { + var key = path[index]; + var updated = isArray(obj) ? obj.slice() : assign({}, obj); - // eslint-disable-next-line no-fallthrough + if (index + 1 === path.length) { + if (isArray(updated)) { + updated.splice(key, 1); + } else { + delete updated[key]; + } - default: { - if (typeof type === "object" && type !== null) { - switch (type.$$typeof) { - case REACT_PROVIDER_TYPE: - fiberTag = ContextProvider; - break getTag; + return updated; + } // $FlowFixMe number or string is fine here - case REACT_CONTEXT_TYPE: - // This is a consumer - fiberTag = ContextConsumer; - break getTag; + updated[key] = copyWithDeleteImpl(obj[key], path, index + 1); + return updated; + }; - case REACT_FORWARD_REF_TYPE: - fiberTag = ForwardRef; + var copyWithDelete = function (obj, path) { + return copyWithDeleteImpl(obj, path, 0); + }; - { - resolvedType = resolveForwardRefForHotReloading(resolvedType); - } + var copyWithRenameImpl = function (obj, oldPath, newPath, index) { + var oldKey = oldPath[index]; + var updated = isArray(obj) ? obj.slice() : assign({}, obj); - break getTag; + if (index + 1 === oldPath.length) { + var newKey = newPath[index]; // $FlowFixMe number or string is fine here - case REACT_MEMO_TYPE: - fiberTag = MemoComponent; - break getTag; + updated[newKey] = updated[oldKey]; - case REACT_LAZY_TYPE: - fiberTag = LazyComponent; - resolvedType = null; - break getTag; - } - } + 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 info = ""; + return updated; + }; - { - if ( - type === undefined || - (typeof type === "object" && - type !== null && - Object.keys(type).length === 0) - ) { - info += - " You likely forgot to export your component from the file " + - "it's defined in, or you might have mixed up default and " + - "named imports."; - } + var copyWithRename = function (obj, oldPath, newPath) { + if (oldPath.length !== newPath.length) { + warn("copyWithRename() expects paths of the same length"); - var ownerName = owner ? getComponentNameFromFiber(owner) : null; + 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" + ); - if (ownerName) { - info += "\n\nCheck the render method of `" + ownerName + "`."; - } + return; } - - throw new Error( - "Element type is invalid: expected a string (for built-in " + - "components) or a class/function (for composite components) " + - ("but got: " + (type == null ? type : typeof type) + "." + info) - ); } } - } - - var fiber = createFiber(fiberTag, pendingProps, key, mode); - fiber.elementType = type; - fiber.type = resolvedType; - fiber.lanes = lanes; - { - fiber._debugOwner = owner; - } + return copyWithRenameImpl(obj, oldPath, newPath, 0); + }; - return fiber; -} -function createFiberFromElement(element, mode, lanes) { - var owner = null; + var copyWithSetImpl = function (obj, path, index, value) { + if (index >= path.length) { + return value; + } - { - owner = element._owner; - } + var key = path[index]; + var updated = isArray(obj) ? obj.slice() : assign({}, obj); // $FlowFixMe number or string is fine here - var type = element.type; - var key = element.key; - var pendingProps = element.props; - var fiber = createFiberFromTypeAndProps( - type, - key, - pendingProps, - owner, - mode, - lanes - ); + updated[key] = copyWithSetImpl(obj[key], path, index + 1, value); + return updated; + }; - { - fiber._debugSource = element._source; - fiber._debugOwner = element._owner; - } + var copyWithSet = function (obj, path, value) { + return copyWithSetImpl(obj, path, 0, value); + }; - return fiber; -} -function createFiberFromFragment(elements, mode, lanes, key) { - var fiber = createFiber(Fragment, elements, key, mode); - fiber.lanes = lanes; - return fiber; -} + 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; -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 - ); + while (currentHook !== null && id > 0) { + currentHook = currentHook.next; + id--; } - } - var fiber = createFiber(Profiler, pendingProps, key, mode | ProfileMode); - fiber.elementType = REACT_PROFILER_TYPE; - fiber.lanes = lanes; + return currentHook; + }; // Support DevTools editable values for useState and useReducer. - { - fiber.stateNode = { - effectDuration: 0, - passiveEffectDuration: 0 - }; - } + overrideHookState = function (fiber, id, path, value) { + var hook = findHook(fiber, id); + + 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 fiber; -} + fiber.memoizedProps = assign({}, fiber.memoizedProps); + var root = enqueueConcurrentRenderForLane(fiber, SyncLane); -function createFiberFromSuspense(pendingProps, mode, lanes, key) { - var fiber = createFiber(SuspenseComponent, pendingProps, key, mode); - fiber.elementType = REACT_SUSPENSE_TYPE; - fiber.lanes = lanes; - return fiber; -} -function createFiberFromSuspenseList(pendingProps, mode, lanes, key) { - var fiber = createFiber(SuspenseListComponent, pendingProps, key, mode); - fiber.elementType = REACT_SUSPENSE_LIST_TYPE; - fiber.lanes = lanes; - return fiber; -} -function createFiberFromOffscreen(pendingProps, mode, lanes, key) { - var fiber = createFiber(OffscreenComponent, pendingProps, key, mode); - fiber.elementType = REACT_OFFSCREEN_TYPE; - fiber.lanes = lanes; - var primaryChildInstance = { - _visibility: OffscreenVisible, - _pendingVisibility: OffscreenVisible, - _pendingMarkers: null, - _retryCache: null, - _transitions: null, - _current: null, - detach: function () { - return detachOffscreenInstance(primaryChildInstance); - }, - attach: function () { - return attachOffscreenInstance(primaryChildInstance); + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + } } }; - fiber.stateNode = primaryChildInstance; - return fiber; -} -function createFiberFromLegacyHidden(pendingProps, mode, lanes, key) { - var fiber = createFiber(LegacyHiddenComponent, pendingProps, key, mode); - fiber.elementType = REACT_LEGACY_HIDDEN_TYPE; - fiber.lanes = lanes; // Adding a stateNode for legacy hidden because it's currently using - // the offscreen implementation, which depends on a state node - var instance = { - _visibility: OffscreenVisible, - _pendingVisibility: OffscreenVisible, - _pendingMarkers: null, - _transitions: null, - _retryCache: null, - _current: null, - detach: function () { - return detachOffscreenInstance(instance); - }, - attach: function () { - return attachOffscreenInstance(instance); + overrideHookStateDeletePath = function (fiber, id, path) { + var hook = findHook(fiber, id); + + 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. + + fiber.memoizedProps = assign({}, fiber.memoizedProps); + var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + } } }; - fiber.stateNode = instance; - 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. + overrideHookStateRenamePath = function (fiber, id, oldPath, newPath) { + var hook = findHook(fiber, id); - target.tag = source.tag; - target.key = source.key; - target.elementType = source.elementType; - target.type = source.type; - target.stateNode = source.stateNode; - target.return = source.return; - target.child = source.child; - target.sibling = source.sibling; - target.index = source.index; - target.ref = source.ref; - target.refCleanup = source.refCleanup; - target.pendingProps = source.pendingProps; - target.memoizedProps = source.memoizedProps; - target.updateQueue = source.updateQueue; - target.memoizedState = source.memoizedState; - target.dependencies = source.dependencies; - target.mode = source.mode; - target.flags = source.flags; - target.subtreeFlags = source.subtreeFlags; - target.deletions = source.deletions; - target.lanes = source.lanes; - target.childLanes = source.childLanes; - target.alternate = source.alternate; + 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. - { - target.actualDuration = source.actualDuration; - target.actualStartTime = source.actualStartTime; - target.selfBaseDuration = source.selfBaseDuration; - target.treeBaseDuration = source.treeBaseDuration; - } + fiber.memoizedProps = assign({}, fiber.memoizedProps); + var root = enqueueConcurrentRenderForLane(fiber, SyncLane); - target._debugSource = source._debugSource; - target._debugOwner = source._debugOwner; - target._debugNeedsRemount = source._debugNeedsRemount; - target._debugHookTypes = source._debugHookTypes; - return target; -} + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + } + } + }; // Support DevTools props for function components, forwardRef, memo, host components, etc. -function FiberRootNode( - containerInfo, // $FlowFixMe[missing-local-annot] - 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.errorRecoveryDisabledLanes = NoLanes; - this.entangledLanes = NoLanes; - this.entanglements = createLaneMap(NoLanes); - this.hiddenUpdates = createLaneMap(null); - this.identifierPrefix = identifierPrefix; - this.onRecoverableError = onRecoverableError; + overrideProps = function (fiber, path, value) { + fiber.pendingProps = copyWithSet(fiber.memoizedProps, path, value); - this.incompleteTransitions = new Map(); + if (fiber.alternate) { + fiber.alternate.pendingProps = fiber.pendingProps; + } - { - this.effectDuration = 0; - this.passiveEffectDuration = 0; - } + var root = enqueueConcurrentRenderForLane(fiber, SyncLane); - { - this.memoizedUpdaters = new Set(); - var pendingUpdatersLaneMap = (this.pendingUpdatersLaneMap = []); + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + } + }; - for (var _i = 0; _i < TotalLanes; _i++) { - pendingUpdatersLaneMap.push(new Set()); + overridePropsDeletePath = function (fiber, path) { + fiber.pendingProps = copyWithDelete(fiber.memoizedProps, path); + + if (fiber.alternate) { + fiber.alternate.pendingProps = fiber.pendingProps; } - } - { - switch (tag) { - case ConcurrentRoot: - this._debugRootType = hydrate ? "hydrateRoot()" : "createRoot()"; - break; + var root = enqueueConcurrentRenderForLane(fiber, SyncLane); - case LegacyRoot: - this._debugRootType = hydrate ? "hydrate()" : "render()"; - break; + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); } - } -} + }; -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 -) { - // $FlowFixMe[invalid-constructor] Flow no longer supports calling new on functions - var root = new FiberRootNode( - containerInfo, - tag, - hydrate, - identifierPrefix, - onRecoverableError - ); - // stateNode is any. + overridePropsRenamePath = function (fiber, oldPath, newPath) { + fiber.pendingProps = copyWithRename(fiber.memoizedProps, oldPath, newPath); + + if (fiber.alternate) { + fiber.alternate.pendingProps = fiber.pendingProps; + } - var uninitializedFiber = createHostRootFiber( - tag, - isStrictMode, - concurrentUpdatesByDefaultOverride - ); - root.current = uninitializedFiber; - uninitializedFiber.stateNode = root; + var root = enqueueConcurrentRenderForLane(fiber, SyncLane); - { - var _initialState = { - element: initialChildren, - isDehydrated: hydrate, - cache: null // not enabled yet - }; - uninitializedFiber.memoizedState = _initialState; - } + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + } + }; - initializeUpdateQueue(uninitializedFiber); - return root; -} + scheduleUpdate = function (fiber) { + var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + } + }; -var ReactVersion = "18.3.0-next-ef8bdbecb-20230310"; + setErrorHandler = function (newShouldErrorImpl) { + shouldErrorImpl = newShouldErrorImpl; + }; -function createPortal$1( - children, - containerInfo, // TODO: figure out the API for cross-renderer implementation. - implementation -) { - var key = - arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; + setSuspenseHandler = function (newShouldSuspendImpl) { + shouldSuspendImpl = newShouldSuspendImpl; + }; +} - { - checkKeyStringCoercion(key); +function findHostInstanceByFiber(fiber) { + var hostFiber = findCurrentHostFiber(fiber); + + if (hostFiber === null) { + return null; } - 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 - }; + return hostFiber.stateNode; } -// Might add PROFILE later. +function emptyFindFiberByHostInstance(instance) { + return null; +} -var didWarnAboutNestedUpdates; -var didWarnAboutFindNodeInStrictMode; +function getCurrentFiberForDevTools() { + return current; +} -{ - didWarnAboutNestedUpdates = false; - didWarnAboutFindNodeInStrictMode = {}; +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 getContextForSubtree(parentComponent) { - if (!parentComponent) { - return emptyContextObject; - } +/** + * IMPORTANT: This module is used in Paper and Fabric. It needs to be defined + * outside of `ReactFabricPublicInstance` because that module requires + * `nativeFabricUIManager` to be defined in the global scope (which does not + * happen in Paper). + */ +function getNativeTagFromPublicInstance(publicInstance) { + return publicInstance.__nativeTag; +} +function getInternalInstanceHandleFromPublicInstance(publicInstance) { + return publicInstance.__internalInstanceHandle; +} - var fiber = get(parentComponent); - var parentContext = findCurrentUnmaskedContext(fiber); +var ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; +function findHostInstance_DEPRECATED(componentOrHandle) { + { + var owner = ReactCurrentOwner.current; - if (fiber.tag === ClassComponent) { - var Component = fiber.type; + 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 (isContextProvider(Component)) { - return processChildContext(fiber, Component, parentContext); + owner.stateNode._warnedAboutRefsInRender = true; } } - return parentContext; -} + if (componentOrHandle == null) { + return null; + } // For compatibility with Fabric instances + + if ( + componentOrHandle.canonical && + componentOrHandle.canonical.publicInstance + ) { + // $FlowExpectedError[incompatible-return] Can't refine componentOrHandle as a Fabric instance + return componentOrHandle.canonical.publicInstance; + } // For compatibility with legacy renderer instances + + if (componentOrHandle._nativeTag) { + // $FlowFixMe[incompatible-exact] Necessary when running Flow on Fabric + // $FlowFixMe[incompatible-return] + return componentOrHandle; + } + + var hostInstance; -function findHostInstanceWithWarning(component, methodName) { { - var fiber = get(component); + hostInstance = findHostInstanceWithWarning( + componentOrHandle, + "findHostInstance_DEPRECATED" + ); + } // findHostInstance handles legacy vs. Fabric differences correctly + // $FlowFixMe[incompatible-exact] we need to fix the definition of `HostComponent` to use NativeMethods as an interface, not as a type. - 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 + return hostInstance; +} +function findNodeHandle(componentOrHandle) { + { + var owner = ReactCurrentOwner.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" ); } + + owner.stateNode._warnedAboutRefsInRender = true; } + } - var hostFiber = findCurrentHostFiber(fiber); + if (componentOrHandle == null) { + return null; + } - if (hostFiber === null) { - return null; - } + if (typeof componentOrHandle === "number") { + // Already a node handle + return componentOrHandle; + } // For compatibility with legacy renderer instances - if (hostFiber.mode & StrictLegacyMode) { - var componentName = getComponentNameFromFiber(fiber) || "Component"; + if (componentOrHandle._nativeTag) { + return componentOrHandle._nativeTag; + } // For compatibility with Fabric instances - if (!didWarnAboutFindNodeInStrictMode[componentName]) { - didWarnAboutFindNodeInStrictMode[componentName] = true; - var previousFiber = current; + if ( + componentOrHandle.canonical != null && + componentOrHandle.canonical.nativeTag != null + ) { + return componentOrHandle.canonical.nativeTag; + } // For compatibility with Fabric public instances - try { - setCurrentFiber(hostFiber); + var nativeTag = getNativeTagFromPublicInstance(componentOrHandle); - 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://reactjs.org/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://reactjs.org/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 (nativeTag) { + return nativeTag; + } + + var hostInstance; + + { + hostInstance = findHostInstanceWithWarning( + componentOrHandle, + "findNodeHandle" + ); + } + + if (hostInstance == null) { + return hostInstance; + } // $FlowFixMe[prop-missing] For compatibility with legacy renderer instances + + if (hostInstance._nativeTag != null) { + // $FlowFixMe[incompatible-return] + return hostInstance._nativeTag; + } // $FlowFixMe[incompatible-call] Necessary when running Flow on the legacy renderer + + return getNativeTagFromPublicInstance(hostInstance); +} +function dispatchCommand(handle, command, args) { + var nativeTag = + handle._nativeTag != null + ? handle._nativeTag + : getNativeTagFromPublicInstance(handle); + + if (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 getPublicInstance(hostFiber.stateNode); + return; } -} -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 internalInstanceHandle = + getInternalInstanceHandleFromPublicInstance(handle); + + if (internalInstanceHandle != null) { + var node = getNodeFromInternalInstanceHandle(internalInstanceHandle); + + if (node != null) { + nativeFabricUIManager.dispatchCommand(node, command, args); + } + } else { + ReactNativePrivateInterface.UIManager.dispatchViewManagerCommand( + nativeTag, + command, + args + ); } +} +function sendAccessibilityEvent(handle, eventType) { + var nativeTag = + handle._nativeTag != null + ? handle._nativeTag + : getNativeTagFromPublicInstance(handle); - var current$1 = container.current; - var lane = requestUpdateLane(current$1); + if (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" + ); + } - { - markRenderScheduled(lane); + return; } - var context = getContextForSubtree(parentComponent); + var internalInstanceHandle = + getInternalInstanceHandleFromPublicInstance(handle); - if (container.context === null) { - container.context = context; + if (internalInstanceHandle != null) { + var node = getNodeFromInternalInstanceHandle(internalInstanceHandle); + + if (node != null) { + nativeFabricUIManager.sendAccessibilityEvent(node, eventType); + } } else { - container.pendingContext = context; + ReactNativePrivateInterface.legacySendAccessibilityEvent( + nativeTag, + eventType + ); } +} +function getNodeFromInternalInstanceHandle(internalInstanceHandle) { + return ( + // $FlowExpectedError[incompatible-return] internalInstanceHandle is opaque but we need to make an exception here. + internalInstanceHandle && // $FlowExpectedError[incompatible-return] + internalInstanceHandle.stateNode && // $FlowExpectedError[incompatible-use] + internalInstanceHandle.stateNode.node + ); +} - { - if (isRendering && current !== null && !didWarnAboutNestedUpdates) { - didWarnAboutNestedUpdates = true; +var _nativeFabricUIManage$1 = nativeFabricUIManager, + fabricMeasure = _nativeFabricUIManage$1.measure, + fabricMeasureInWindow = _nativeFabricUIManage$1.measureInWindow, + fabricMeasureLayout = _nativeFabricUIManage$1.measureLayout, + _setNativeProps = _nativeFabricUIManage$1.setNativeProps, + fabricGetBoundingClientRect = _nativeFabricUIManage$1.getBoundingClientRect; - 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 noop = function () {}; +/** + * This is used for refs on host components. + */ + +var ReactFabricHostComponent = /*#__PURE__*/ (function () { + // These need to be accessible from `ReactFabricPublicInstanceUtils`. + function ReactFabricHostComponent(tag, viewConfig, internalInstanceHandle) { + this.__nativeTag = void 0; + this.__internalInstanceHandle = void 0; + this._viewConfig = void 0; + this.__nativeTag = tag; + this._viewConfig = viewConfig; + this.__internalInstanceHandle = internalInstanceHandle; } - var update = createUpdate(lane); // Caution: React DevTools currently depends on this property - // being called "element". + var _proto = ReactFabricHostComponent.prototype; - update.payload = { - element: element + _proto.blur = function blur() { + ReactNativePrivateInterface.TextInputState.blurTextInput(this); }; - callback = callback === undefined ? null : callback; - if (callback !== null) { - { - if (typeof callback !== "function") { + _proto.focus = function focus() { + ReactNativePrivateInterface.TextInputState.focusTextInput(this); + }; + + _proto.measure = function measure(callback) { + var node = getNodeFromInternalInstanceHandle(this.__internalInstanceHandle); + + if (node != null) { + fabricMeasure(node, callback); + } + }; + + _proto.measureInWindow = function measureInWindow(callback) { + var node = getNodeFromInternalInstanceHandle(this.__internalInstanceHandle); + + if (node != null) { + fabricMeasureInWindow(node, callback); + } + }; + + _proto.measureLayout = function measureLayout( + relativeToNativeNode, + onSuccess, + onFail + /* currently unused */ + ) { + if ( + typeof relativeToNativeNode === "number" || + !(relativeToNativeNode instanceof ReactFabricHostComponent) + ) { + { error( - "render(...): Expected the last optional `callback` argument to be a " + - "function. Instead received: %s.", - callback + "Warning: ref.measureLayout must be called with a ref to a native component." ); } + + return; } - update.callback = callback; - } + var toStateNode = getNodeFromInternalInstanceHandle( + this.__internalInstanceHandle + ); + var fromStateNode = getNodeFromInternalInstanceHandle( + relativeToNativeNode.__internalInstanceHandle + ); - var root = enqueueUpdate(current$1, update, lane); + if (toStateNode != null && fromStateNode != null) { + fabricMeasureLayout( + toStateNode, + fromStateNode, + onFail != null ? onFail : noop, + onSuccess != null ? onSuccess : noop + ); + } + }; - if (root !== null) { - var eventTime = requestEventTime(); - scheduleUpdateOnFiber(root, current$1, lane, eventTime); - entangleTransitions(root, current$1, lane); - } + _proto.unstable_getBoundingClientRect = + function unstable_getBoundingClientRect() { + var node = getNodeFromInternalInstanceHandle( + this.__internalInstanceHandle + ); - return lane; + if (node != null) { + var rect = fabricGetBoundingClientRect(node); + + if (rect) { + return new DOMRect(rect[0], rect[1], rect[2], rect[3]); + } + } // Empty rect if any of the above failed + + return new DOMRect(0, 0, 0, 0); + }; + + _proto.setNativeProps = function setNativeProps(nativeProps) { + { + warnForStyleProps(nativeProps, this._viewConfig.validAttributes); + } + + var updatePayload = create(nativeProps, this._viewConfig.validAttributes); + var node = getNodeFromInternalInstanceHandle(this.__internalInstanceHandle); + + if (node != null && updatePayload != null) { + _setNativeProps(node, updatePayload); + } + }; + + return ReactFabricHostComponent; +})(); +function createPublicInstance(tag, viewConfig, internalInstanceHandle) { + return new ReactFabricHostComponent(tag, viewConfig, internalInstanceHandle); } -function getPublicRootInstance(container) { - var containerFiber = container.current; - if (!containerFiber.child) { - return null; +// 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); } - switch (containerFiber.child.tag) { - case HostSingleton: - case HostComponent: - return getPublicInstance(containerFiber.child.stateNode); + isInsideEventHandler = true; - default: - return containerFiber.child.stateNode; + try { + return batchedUpdatesImpl(fn, bookkeeping); + } finally { + isInsideEventHandler = false; } } +function setBatchingImplementation(_batchedUpdatesImpl, _discreteUpdatesImpl) { + batchedUpdatesImpl = _batchedUpdatesImpl; +} -var shouldErrorImpl = function (fiber) { - return null; -}; +/** + * Internal queue of events that have accumulated their dispatches and are + * waiting to have their dispatches executed. + */ -function shouldError(fiber) { - return shouldErrorImpl(fiber); -} +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 shouldSuspendImpl = function (fiber) { - return false; -}; +function executeDispatchesAndRelease(event) { + if (event) { + executeDispatchesInOrder(event); -function shouldSuspend(fiber) { - return shouldSuspendImpl(fiber); + if (!event.isPersistent()) { + event.constructor.release(event); + } + } +} // $FlowFixMe[missing-local-annot] + +function executeDispatchesAndReleaseTopLevel(e) { + return executeDispatchesAndRelease(e); } -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); +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 (index + 1 === path.length) { - if (isArray(updated)) { - updated.splice(key, 1); - } else { - delete updated[key]; - } + if (!processingEventQueue) { + return; + } - return updated; - } // $FlowFixMe number or string is fine here + forEachAccumulated(processingEventQueue, executeDispatchesAndReleaseTopLevel); - updated[key] = copyWithDeleteImpl(obj[key], path, index + 1); - return updated; - }; + 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. - var copyWithDelete = function (obj, path) { - return copyWithDeleteImpl(obj, path, 0); - }; + rethrowCaughtError(); +} - var copyWithRenameImpl = function (obj, oldPath, newPath, index) { - var oldKey = oldPath[index]; - var updated = isArray(obj) ? obj.slice() : assign({}, obj); +/** + * Allows registered plugins an opportunity to extract events from top-level + * native browser events. + * + * @return {*} An accumulation of synthetic events. + * @internal + */ - if (index + 1 === oldPath.length) { - var newKey = newPath[index]; // $FlowFixMe number or string is fine here +function extractPluginEvents( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget +) { + var events = null; + var legacyPlugins = plugins; - updated[newKey] = updated[oldKey]; + for (var i = 0; i < legacyPlugins.length; i++) { + // Not every plugin in the ordering may be loaded at runtime. + var possiblePlugin = legacyPlugins[i]; - 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 + if (possiblePlugin) { + var extractedEvents = possiblePlugin.extractEvents( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget ); - } - return updated; - }; + if (extractedEvents) { + events = accumulateInto(events, extractedEvents); + } + } + } - var copyWithRename = function (obj, oldPath, newPath) { - if (oldPath.length !== newPath.length) { - warn("copyWithRename() expects paths of the same length"); + return events; +} - 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" - ); +function runExtractedPluginEventsInBatch( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget +) { + var events = extractPluginEvents( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget + ); + runEventsInBatch(events); +} - return; - } - } - } +function dispatchEvent(target, topLevelType, nativeEvent) { + var targetFiber = target; + var eventTarget = null; - return copyWithRenameImpl(obj, oldPath, newPath, 0); - }; + if (targetFiber != null) { + var stateNode = targetFiber.stateNode; // Guard against Fiber being unmounted - var copyWithSetImpl = function (obj, path, index, value) { - if (index >= path.length) { - return value; + if (stateNode != null) { + // $FlowExpectedError[incompatible-cast] public instances in Fabric do not implement `EventTarget` yet. + eventTarget = getPublicInstance(stateNode); } + } - var key = path[index]; - var updated = isArray(obj) ? obj.slice() : assign({}, obj); // $FlowFixMe number or string is fine here + 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 + }; // $FlowFixMe[class-object-subtyping] found when upgrading Flow - updated[key] = copyWithSetImpl(obj[key], path, index + 1, value); - return updated; - }; + ReactNativePrivateInterface.RawEventEmitter.emit(topLevelType, event); // $FlowFixMe[class-object-subtyping] found when upgrading Flow - var copyWithSet = function (obj, path, value) { - return copyWithSetImpl(obj, path, 0, value); - }; + ReactNativePrivateInterface.RawEventEmitter.emit("*", event); // Heritage plugin event system - 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; + runExtractedPluginEventsInBatch( + topLevelType, + targetFiber, + nativeEvent, + eventTarget + ); + }); // React Native doesn't use ReactControlledComponent but if it did, here's + // where it would do it. +} - while (currentHook !== null && id > 0) { - currentHook = currentHook.next; - id--; - } +// Renderers that don't support mutation +// can re-export everything from this module. +function shim$1() { + 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$1; - return currentHook; - }; // Support DevTools editable values for useState and useReducer. +// 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 errorHydratingContainer = shim; - overrideHookState = function (fiber, id, path, value) { - var hook = findHook(fiber, id); +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, + FabricDefaultPriority = _nativeFabricUIManage.unstable_DefaultEventPriority, + FabricDiscretePriority = _nativeFabricUIManage.unstable_DiscreteEventPriority, + fabricGetCurrentEventPriority = + _nativeFabricUIManage.unstable_getCurrentEventPriority; +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. - 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. +var nextReactTag = 2; // TODO: Remove this conditional once all changes have propagated. - fiber.memoizedProps = assign({}, fiber.memoizedProps); - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); +if (registerEventHandler) { + /** + * Register the event emitter with the native bridge + */ + registerEventHandler(dispatchEvent); +} +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); - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + { + for (var key in viewConfig.validAttributes) { + if (props.hasOwnProperty(key)) { + ReactNativePrivateInterface.deepFreezeAndThrowOnMutationInDev( + props[key] + ); } } - }; - - overrideHookStateDeletePath = function (fiber, id, path) { - var hook = findHook(fiber, id); - - 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. - - fiber.memoizedProps = assign({}, fiber.memoizedProps); - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + } - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); - } + var updatePayload = create(props, viewConfig.validAttributes); + var node = createNode( + tag, // reactTag + viewConfig.uiViewClassName, // viewName + rootContainerInstance, // rootTag + updatePayload, // props + internalInstanceHandle // internalInstanceHandle + ); + var component = createPublicInstance(tag, viewConfig, internalInstanceHandle); + return { + node: node, + canonical: { + nativeTag: tag, + viewConfig: viewConfig, + currentProps: props, + internalInstanceHandle: internalInstanceHandle, + publicInstance: component } }; +} +function createTextInstance( + text, + rootContainerInstance, + hostContext, + internalInstanceHandle +) { + { + if (!hostContext.isInAParentText) { + error("Text strings must be rendered within a component."); + } + } - overrideHookStateRenamePath = function (fiber, id, oldPath, newPath) { - var hook = findHook(fiber, id); - - 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. + 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) { + 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. - fiber.memoizedProps = assign({}, fiber.memoizedProps); - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + if (prevIsInAParentText !== isInAParentText) { + return { + isInAParentText: isInAParentText + }; + } else { + return parentHostContext; + } +} +function getPublicInstance(instance) { + if (instance.canonical != null && instance.canonical.publicInstance != null) { + return instance.canonical.publicInstance; + } // For compatibility with the legacy renderer, in case it's used with Fabric + // in the same app. + // $FlowExpectedError[prop-missing] - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); - } - } - }; // Support DevTools props for function components, forwardRef, memo, host components, etc. + if (instance._nativeTag != null) { + // $FlowExpectedError[incompatible-return] + return instance; + } - overrideProps = function (fiber, path, value) { - fiber.pendingProps = copyWithSet(fiber.memoizedProps, path, value); + return null; +} +function prepareUpdate(instance, type, oldProps, newProps, 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. - if (fiber.alternate) { - fiber.alternate.pendingProps = fiber.pendingProps; - } + instance.canonical.currentProps = newProps; + return updatePayload; +} +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; - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + if (currentEventPriority != null) { + switch (currentEventPriority) { + case FabricDiscretePriority: + return DiscreteEventPriority; - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + case FabricDefaultPriority: + default: + return DefaultEventPriority; } - }; + } - overridePropsDeletePath = function (fiber, path) { - fiber.pendingProps = copyWithDelete(fiber.memoizedProps, path); + return DefaultEventPriority; +} // The Fabric renderer is secondary to the existing React Native renderer. - if (fiber.alternate) { - fiber.alternate.pendingProps = fiber.pendingProps; - } +var isPrimaryRenderer = false; // The Fabric renderer shouldn't trigger missing act() warnings - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); +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 (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + if (keepChildren) { + if (updatePayload !== null) { + clone = cloneNodeWithNewProps(node, updatePayload); + } else { + clone = cloneNode(node); } - }; - - overridePropsRenamePath = function (fiber, oldPath, newPath) { - fiber.pendingProps = copyWithRename(fiber.memoizedProps, oldPath, newPath); - - if (fiber.alternate) { - fiber.alternate.pendingProps = fiber.pendingProps; + } else { + if (updatePayload !== null) { + clone = cloneNodeWithNewChildrenAndProps(node, updatePayload); + } else { + clone = cloneNodeWithNewChildren(node); } + } - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); - - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); - } + 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 waitForCommitToBeReady() { + return null; +} - scheduleUpdate = function (fiber) { - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); +// This is ok in DOM because they types are interchangeable, but in React Native +// they aren't. - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); - } - }; +function getInstanceFromNode(node) { + var instance = node; // In React Native, node is never a text instance - setErrorHandler = function (newShouldErrorImpl) { - shouldErrorImpl = newShouldErrorImpl; - }; + if ( + instance.canonical != null && + instance.canonical.internalInstanceHandle != null + ) { + return instance.canonical.internalInstanceHandle; + } // $FlowFixMe[incompatible-return] DevTools incorrectly passes a fiber in React Native. - setSuspenseHandler = function (newShouldSuspendImpl) { - shouldSuspendImpl = newShouldSuspendImpl; - }; + return node; } -function findHostInstanceByFiber(fiber) { - var hostFiber = findCurrentHostFiber(fiber); +function getNodeFromInstance(fiber) { + var publicInstance = getPublicInstance(fiber.stateNode); - if (hostFiber === null) { - return null; + if (publicInstance == null) { + throw new Error("Could not find host instance from fiber"); } - return hostFiber.stateNode; + return publicInstance; } -function emptyFindFiberByHostInstance(instance) { - return null; +function getFiberCurrentPropsFromNode(instance) { + return instance.canonical.currentProps; } -function getCurrentFiberForDevTools() { - return current; -} +var ReactFabricGlobalResponderHandler = { + onChange: function (from, to, blockNativeResponder) { + if (from && from.stateNode) { + // equivalent to clearJSResponder + nativeFabricUIManager.setIsJSResponder( + from.stateNode.node, + false, + blockNativeResponder || false + ); + } -function injectIntoDevTools(devToolsConfig) { - var findFiberByHostInstance = devToolsConfig.findFiberByHostInstance; - var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher; - return injectInternals({ - bundleType: devToolsConfig.bundleType, - version: devToolsConfig.version, - rendererPackageName: devToolsConfig.rendererPackageName, - rendererConfig: devToolsConfig.rendererConfig, - overrideHookState: overrideHookState, - overrideHookStateDeletePath: overrideHookStateDeletePath, - overrideHookStateRenamePath: overrideHookStateRenamePath, - overrideProps: overrideProps, - overridePropsDeletePath: overridePropsDeletePath, - overridePropsRenamePath: overridePropsRenamePath, - setErrorHandler: setErrorHandler, - setSuspenseHandler: setSuspenseHandler, - scheduleUpdate: scheduleUpdate, - currentDispatcherRef: ReactCurrentDispatcher, - findHostInstanceByFiber: findHostInstanceByFiber, - findFiberByHostInstance: - findFiberByHostInstance || emptyFindFiberByHostInstance, - // React Refresh - findHostInstancesForRefresh: findHostInstancesForRefresh, - scheduleRefresh: scheduleRefresh, - scheduleRoot: scheduleRoot, - setRefreshHandler: setRefreshHandler, - // Enables DevTools to append owner stacks to error messages in DEV mode. - getCurrentFiber: getCurrentFiberForDevTools, - // Enables DevTools to detect reconciler version rather than renderer version - // which may not match for third party renderers. - reconcilerVersion: ReactVersion - }); -} + if (to && to.stateNode) { + // equivalent to setJSResponder + nativeFabricUIManager.setIsJSResponder( + to.stateNode.node, + true, + blockNativeResponder || false + ); + } + } +}; + +setComponentTree( + getFiberCurrentPropsFromNode, + getInstanceFromNode, + getNodeFromInstance +); +ResponderEventPlugin.injection.injectGlobalResponderHandler( + ReactFabricGlobalResponderHandler +); var instanceCache = new Map(); @@ -27090,50 +27645,41 @@ var emptyObject = {}; { Object.freeze(emptyObject); -} - -var createHierarchy; -var getHostNode; -var getHostProps; -var lastNonHostInstance; -exports.getInspectorDataForInstance = void 0; -var getOwnerHierarchy; -var traverseOwnerTreeUp; +} // $FlowFixMe[missing-local-annot] -{ - // $FlowFixMe[missing-local-annot] - 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 createHierarchy(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 shadow node and use that to measure. + var hostFiber = findCurrentHostFiber(fiber); + var node = + hostFiber != null && + hostFiber.stateNode !== null && + hostFiber.stateNode.node; + + if (node) { + nativeFabricUIManager.measure(node, callback); + } else { + return ReactNativePrivateInterface.UIManager.measure( + getHostNode(fiber, findNodeHandle), + callback + ); } - }; - } - }; - }); - }; // $FlowFixMe[missing-local-annot] + } + }; + } + }; + }); +} // $FlowFixMe[missing-local-annot] - getHostNode = function (fiber, findNodeHandle) { +function getHostNode(fiber, findNodeHandle) { + { var hostNode; // look for children first for the hostNode // as composite fibers do not have a hostNode @@ -27150,19 +27696,21 @@ var traverseOwnerTreeUp; } return null; - }; // $FlowFixMe[missing-local-annot] + } +} // $FlowFixMe[missing-local-annot] - getHostProps = function (fiber) { - var host = findCurrentHostFiber(fiber); +function getHostProps(fiber) { + var host = findCurrentHostFiber(fiber); - if (host) { - return host.memoizedProps || emptyObject; - } + if (host) { + return host.memoizedProps || emptyObject; + } - return emptyObject; - }; + return emptyObject; +} - exports.getInspectorDataForInstance = function (closestInstance) { +function getInspectorDataForInstance(closestInstance) { + { // Handle case where user clicks outside of ReactNative if (!closestInstance) { return { @@ -27187,39 +27735,38 @@ var traverseOwnerTreeUp; selectedIndex: selectedIndex, source: source }; - }; + } +} - getOwnerHierarchy = function (instance) { - var hierarchy = []; - traverseOwnerTreeUp(hierarchy, instance); - return hierarchy; - }; // $FlowFixMe[missing-local-annot] +function getOwnerHierarchy(instance) { + var hierarchy = []; + traverseOwnerTreeUp(hierarchy, instance); + return hierarchy; +} // $FlowFixMe[missing-local-annot] - lastNonHostInstance = function (hierarchy) { - for (var i = hierarchy.length - 1; i > 1; i--) { - var instance = hierarchy[i]; +function lastNonHostInstance(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]; - }; // $FlowFixMe[missing-local-annot] + return hierarchy[0]; +} // $FlowFixMe[missing-local-annot] - traverseOwnerTreeUp = function (hierarchy, instance) { +function traverseOwnerTreeUp(hierarchy, instance) { + { if (instance) { hierarchy.unshift(instance); traverseOwnerTreeUp(hierarchy, instance._debugOwner); } - }; + } } -var getInspectorDataForViewTag; -var getInspectorDataForViewAtPoint; - -{ - getInspectorDataForViewTag = function (viewTag) { +function getInspectorDataForViewTag(viewTag) { + { var closestInstance = getInstanceFromTag(viewTag); // Handle case where user clicks outside of ReactNative if (!closestInstance) { @@ -27244,25 +27791,38 @@ var getInspectorDataForViewAtPoint; selectedIndex: selectedIndex, source: source }; - }; + } +} - getInspectorDataForViewAtPoint = function ( - findNodeHandle, - inspectedView, - locationX, - locationY, - callback - ) { +function getInspectorDataForViewAtPoint( + findNodeHandle, + inspectedView, + locationX, + locationY, + callback +) { + { var closestInstance = null; + var fabricInstanceHandle = + getInternalInstanceHandleFromPublicInstance(inspectedView); + var fabricNode = + fabricInstanceHandle != null + ? getNodeFromInternalInstanceHandle(fabricInstanceHandle) + : null; - if (inspectedView._internalInstanceHandle != null) { + if (fabricNode) { // For Fabric we can look up the instance handle directly and measure it. nativeFabricUIManager.findNodeAtPoint( - inspectedView._internalInstanceHandle.stateNode.node, + fabricNode, locationX, locationY, function (internalInstanceHandle) { - if (internalInstanceHandle == null) { + var node = + internalInstanceHandle != null + ? getNodeFromInternalInstanceHandle(internalInstanceHandle) + : null; + + if (internalInstanceHandle == null || node == null) { callback( assign( { @@ -27274,21 +27834,21 @@ var getInspectorDataForViewAtPoint; height: 0 } }, - exports.getInspectorDataForInstance(closestInstance) + getInspectorDataForInstance(closestInstance) ) ); + return; } 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. + 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; + internalInstanceHandle.stateNode.canonical.nativeTag; nativeFabricUIManager.measure( - internalInstanceHandle.stateNode.node, + node, function (x, y, width, height, pageX, pageY) { - var inspectorData = - exports.getInspectorDataForInstance(closestInstance); + var inspectorData = getInspectorDataForInstance(closestInstance); callback( assign({}, inspectorData, { pointerY: locationY, @@ -27311,7 +27871,7 @@ var getInspectorDataForViewAtPoint; findNodeHandle(inspectedView), [locationX, locationY], function (nativeViewTag, left, top, width, height) { - var inspectorData = exports.getInspectorDataForInstance( + var inspectorData = getInspectorDataForInstance( getInstanceFromTag(nativeViewTag) ); callback( @@ -27335,156 +27895,6 @@ var getInspectorDataForViewAtPoint; return; } - }; -} - -var ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; -function findHostInstance_DEPRECATED(componentOrHandle) { - { - var owner = ReactCurrentOwner.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" - ); - } - - owner.stateNode._warnedAboutRefsInRender = true; - } - } - - if (componentOrHandle == null) { - return null; - } // $FlowFixMe Flow has hardcoded values for React DOM that don't work with RN - - if (componentOrHandle._nativeTag) { - // $FlowFixMe Flow has hardcoded values for React DOM that don't work with RN - return componentOrHandle; - } // $FlowFixMe Flow has hardcoded values for React DOM that don't work with RN - - if (componentOrHandle.canonical && componentOrHandle.canonical._nativeTag) { - // $FlowFixMe Flow has hardcoded values for React DOM that don't work with RN - return componentOrHandle.canonical; - } - - var hostInstance; - - { - hostInstance = findHostInstanceWithWarning( - componentOrHandle, - "findHostInstance_DEPRECATED" - ); - } // $FlowFixMe[incompatible-exact] we need to fix the definition of `HostComponent` to use NativeMethods as an interface, not as a type. - - return hostInstance; -} -function findNodeHandle(componentOrHandle) { - { - var owner = ReactCurrentOwner.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" - ); - } - - owner.stateNode._warnedAboutRefsInRender = true; - } - } - - if (componentOrHandle == null) { - return null; - } - - if (typeof componentOrHandle === "number") { - // Already a node handle - return componentOrHandle; - } - - if (componentOrHandle._nativeTag) { - return componentOrHandle._nativeTag; - } - - if (componentOrHandle.canonical && componentOrHandle.canonical._nativeTag) { - return componentOrHandle.canonical._nativeTag; - } - - var hostInstance; - - { - hostInstance = findHostInstanceWithWarning( - componentOrHandle, - "findNodeHandle" - ); - } - - if (hostInstance == null) { - return hostInstance; - } - - return hostInstance._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; - } - - 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 - ); - } -} -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 (stateNode != null) { - nativeFabricUIManager.sendAccessibilityEvent(stateNode.node, eventType); - } - } else { - ReactNativePrivateInterface.legacySendAccessibilityEvent( - handle._nativeTag, - eventType - ); } } @@ -27538,7 +27948,7 @@ function createPortal(children, containerTag) { return createPortal$1(children, containerTag, null, key); } -setBatchingImplementation(batchedUpdates); +setBatchingImplementation(batchedUpdates$1); var roots = new Map(); injectIntoDevTools({ // $FlowExpectedError[incompatible-call] The type of `Instance` in `getClosestInstanceFromNode` does not match in Fabric and the legacy renderer, so it fails to typecheck here. @@ -27559,6 +27969,8 @@ exports.createPortal = createPortal; exports.dispatchCommand = dispatchCommand; exports.findHostInstance_DEPRECATED = findHostInstance_DEPRECATED; exports.findNodeHandle = findNodeHandle; +exports.getInspectorDataForInstance = getInspectorDataForInstance; +exports.getNodeFromInternalInstanceHandle = getNodeFromInternalInstanceHandle; exports.render = render; exports.sendAccessibilityEvent = sendAccessibilityEvent; exports.stopSurface = stopSurface; diff --git a/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactFabric-prod.fb.js b/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactFabric-prod.fb.js index 052060bef870a..2990116972409 100644 --- a/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactFabric-prod.fb.js +++ b/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactFabric-prod.fb.js @@ -940,7 +940,7 @@ eventPluginOrder = Array.prototype.slice.call([ "ReactNativeBridgeEventPlugin" ]); recomputePluginOrdering(); -var injectedNamesToPlugins$jscomp$inline_232 = { +var injectedNamesToPlugins$jscomp$inline_241 = { ResponderEventPlugin: ResponderEventPlugin, ReactNativeBridgeEventPlugin: { eventTypes: {}, @@ -986,32 +986,32 @@ var injectedNamesToPlugins$jscomp$inline_232 = { } } }, - isOrderingDirty$jscomp$inline_233 = !1, - pluginName$jscomp$inline_234; -for (pluginName$jscomp$inline_234 in injectedNamesToPlugins$jscomp$inline_232) + isOrderingDirty$jscomp$inline_242 = !1, + pluginName$jscomp$inline_243; +for (pluginName$jscomp$inline_243 in injectedNamesToPlugins$jscomp$inline_241) if ( - injectedNamesToPlugins$jscomp$inline_232.hasOwnProperty( - pluginName$jscomp$inline_234 + injectedNamesToPlugins$jscomp$inline_241.hasOwnProperty( + pluginName$jscomp$inline_243 ) ) { - var pluginModule$jscomp$inline_235 = - injectedNamesToPlugins$jscomp$inline_232[pluginName$jscomp$inline_234]; + var pluginModule$jscomp$inline_244 = + injectedNamesToPlugins$jscomp$inline_241[pluginName$jscomp$inline_243]; if ( - !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_234) || - namesToPlugins[pluginName$jscomp$inline_234] !== - pluginModule$jscomp$inline_235 + !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_243) || + namesToPlugins[pluginName$jscomp$inline_243] !== + pluginModule$jscomp$inline_244 ) { - if (namesToPlugins[pluginName$jscomp$inline_234]) + if (namesToPlugins[pluginName$jscomp$inline_243]) throw Error( "EventPluginRegistry: Cannot inject two different event plugins using the same name, `" + - (pluginName$jscomp$inline_234 + "`.") + (pluginName$jscomp$inline_243 + "`.") ); - namesToPlugins[pluginName$jscomp$inline_234] = - pluginModule$jscomp$inline_235; - isOrderingDirty$jscomp$inline_233 = !0; + namesToPlugins[pluginName$jscomp$inline_243] = + pluginModule$jscomp$inline_244; + isOrderingDirty$jscomp$inline_242 = !0; } } -isOrderingDirty$jscomp$inline_233 && recomputePluginOrdering(); +isOrderingDirty$jscomp$inline_242 && recomputePluginOrdering(); var emptyObject$1 = {}, removedKeys = null, removedKeyCount = 0, @@ -1235,512 +1235,10 @@ function diffProperties(updatePayload, prevProps, nextProps, validAttributes) { ))))); return updatePayload; } -function batchedUpdatesImpl(fn, bookkeeping) { - return fn(bookkeeping); -} -var isInsideEventHandler = !1; -function batchedUpdates$1(fn, bookkeeping) { - if (isInsideEventHandler) return fn(bookkeeping); - isInsideEventHandler = !0; - try { - return batchedUpdatesImpl(fn, bookkeeping); - } finally { - isInsideEventHandler = !1; - } -} -var eventQueue = null; -function executeDispatchesAndReleaseTopLevel(e) { - if (e) { - var dispatchListeners = e._dispatchListeners, - dispatchInstances = e._dispatchInstances; - if (isArrayImpl(dispatchListeners)) - for ( - var i = 0; - i < dispatchListeners.length && !e.isPropagationStopped(); - i++ - ) - executeDispatch(e, dispatchListeners[i], dispatchInstances[i]); - else - dispatchListeners && - executeDispatch(e, dispatchListeners, dispatchInstances); - e._dispatchListeners = null; - e._dispatchInstances = null; - e.isPersistent() || e.constructor.release(e); - } -} -function dispatchEvent(target, topLevelType, nativeEvent) { - var eventTarget = null; - if (null != target) { - var stateNode = target.stateNode; - null != stateNode && (eventTarget = getPublicInstance(stateNode)); - } - batchedUpdates$1(function () { - var event = { eventName: topLevelType, nativeEvent: nativeEvent }; - ReactNativePrivateInterface.RawEventEmitter.emit(topLevelType, event); - ReactNativePrivateInterface.RawEventEmitter.emit("*", event); - event = eventTarget; - for ( - var events = null, legacyPlugins = plugins, i = 0; - i < legacyPlugins.length; - i++ - ) { - var possiblePlugin = legacyPlugins[i]; - possiblePlugin && - (possiblePlugin = possiblePlugin.extractEvents( - topLevelType, - target, - nativeEvent, - event - )) && - (events = accumulateInto(events, possiblePlugin)); - } - event = events; - null !== event && (eventQueue = accumulateInto(eventQueue, event)); - event = eventQueue; - eventQueue = null; - if (event) { - forEachAccumulated(event, executeDispatchesAndReleaseTopLevel); - if (eventQueue) - throw Error( - "processEventQueue(): Additional events were enqueued while processing an event queue. Support for this has not yet been implemented." - ); - if (hasRethrowError) - throw ( - ((event = rethrowError), - (hasRethrowError = !1), - (rethrowError = null), - event) - ); - } - }); -} -var enableUseRefAccessWarning = dynamicFlags.enableUseRefAccessWarning, - scheduleCallback$1 = Scheduler.unstable_scheduleCallback, - cancelCallback$1 = Scheduler.unstable_cancelCallback, - shouldYield = Scheduler.unstable_shouldYield, - requestPaint = Scheduler.unstable_requestPaint, - now = Scheduler.unstable_now, - ImmediatePriority = Scheduler.unstable_ImmediatePriority, - UserBlockingPriority = Scheduler.unstable_UserBlockingPriority, - NormalPriority = Scheduler.unstable_NormalPriority, - IdlePriority = Scheduler.unstable_IdlePriority, - ReactSharedInternals = - React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, - rendererID = null, - injectedHook = null; -function onCommitRoot(root) { - if (injectedHook && "function" === typeof injectedHook.onCommitFiberRoot) - try { - injectedHook.onCommitFiberRoot( - rendererID, - root, - void 0, - 128 === (root.current.flags & 128) - ); - } catch (err) {} -} -var clz32 = Math.clz32 ? Math.clz32 : clz32Fallback, - log = Math.log, - LN2 = Math.LN2; -function clz32Fallback(x) { - x >>>= 0; - return 0 === x ? 32 : (31 - ((log(x) / LN2) | 0)) | 0; -} -var nextTransitionLane = 128, - nextRetryLane = 8388608; -function getHighestPriorityLanes(lanes) { - switch (lanes & -lanes) { - case 1: - return 1; - case 2: - return 2; - case 4: - return 4; - case 8: - return 8; - case 16: - return 16; - case 32: - return 32; - case 64: - return 64; - case 128: - case 256: - case 512: - case 1024: - case 2048: - case 4096: - case 8192: - case 16384: - case 32768: - case 65536: - case 131072: - case 262144: - case 524288: - case 1048576: - case 2097152: - case 4194304: - return lanes & 8388480; - case 8388608: - case 16777216: - case 33554432: - case 67108864: - return lanes & 125829120; - case 134217728: - return 134217728; - case 268435456: - return 268435456; - case 536870912: - return 536870912; - case 1073741824: - return 1073741824; - default: - return lanes; - } -} -function getNextLanes(root, wipLanes) { - var pendingLanes = root.pendingLanes; - if (0 === pendingLanes) return 0; - var nextLanes = 0, - suspendedLanes = root.suspendedLanes, - pingedLanes = root.pingedLanes, - nonIdlePendingLanes = pendingLanes & 268435455; - if (0 !== nonIdlePendingLanes) { - var nonIdleUnblockedLanes = nonIdlePendingLanes & ~suspendedLanes; - 0 !== nonIdleUnblockedLanes - ? (nextLanes = getHighestPriorityLanes(nonIdleUnblockedLanes)) - : ((pingedLanes &= nonIdlePendingLanes), - 0 !== pingedLanes && - (nextLanes = getHighestPriorityLanes(pingedLanes))); - } else - (nonIdlePendingLanes = pendingLanes & ~suspendedLanes), - 0 !== nonIdlePendingLanes - ? (nextLanes = getHighestPriorityLanes(nonIdlePendingLanes)) - : 0 !== 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 || - (32 === suspendedLanes && 0 !== (pingedLanes & 8388480))) - ) - return wipLanes; - 0 === (root.current.mode & 32) && - 0 !== (nextLanes & 8) && - (nextLanes |= pendingLanes & 32); - wipLanes = root.entangledLanes; - if (0 !== wipLanes) - for (root = root.entanglements, wipLanes &= nextLanes; 0 < wipLanes; ) - (pendingLanes = 31 - clz32(wipLanes)), - (suspendedLanes = 1 << pendingLanes), - (nextLanes |= root[pendingLanes]), - (wipLanes &= ~suspendedLanes); - return nextLanes; -} -function computeExpirationTime(lane, currentTime) { - switch (lane) { - case 1: - case 2: - case 4: - case 8: - return currentTime + 250; - case 16: - case 32: - case 64: - case 128: - case 256: - case 512: - case 1024: - case 2048: - case 4096: - case 8192: - case 16384: - case 32768: - case 65536: - case 131072: - case 262144: - case 524288: - case 1048576: - case 2097152: - case 4194304: - return currentTime + 5e3; - case 8388608: - case 16777216: - case 33554432: - case 67108864: - return -1; - case 134217728: - case 268435456: - case 536870912: - case 1073741824: - return -1; - default: - return -1; - } -} -function getLanesToRetrySynchronouslyOnError(root, originallyAttemptedLanes) { - if (root.errorRecoveryDisabledLanes & originallyAttemptedLanes) return 0; - root = root.pendingLanes & -1073741825; - return 0 !== root ? root : root & 1073741824 ? 1073741824 : 0; -} -function includesBlockingLane(root, lanes) { - return 0 !== (root.current.mode & 32) ? !1 : 0 !== (lanes & 60); -} -function claimNextTransitionLane() { - var lane = nextTransitionLane; - nextTransitionLane <<= 1; - 0 === (nextTransitionLane & 8388480) && (nextTransitionLane = 128); - return lane; -} -function createLaneMap(initial) { - for (var laneMap = [], i = 0; 31 > i; i++) laneMap.push(initial); - return laneMap; -} -function markRootUpdated(root, updateLane, eventTime) { - root.pendingLanes |= updateLane; - 536870912 !== updateLane && - ((root.suspendedLanes = 0), (root.pingedLanes = 0)); - root = root.eventTimes; - updateLane = 31 - clz32(updateLane); - root[updateLane] = eventTime; -} -function markRootFinished(root, remainingLanes) { - var noLongerPendingLanes = root.pendingLanes & ~remainingLanes; - root.pendingLanes = remainingLanes; - root.suspendedLanes = 0; - root.pingedLanes = 0; - root.expiredLanes &= remainingLanes; - root.mutableReadLanes &= remainingLanes; - root.entangledLanes &= remainingLanes; - root.errorRecoveryDisabledLanes &= remainingLanes; - remainingLanes = root.entanglements; - var eventTimes = root.eventTimes, - expirationTimes = root.expirationTimes; - for (root = root.hiddenUpdates; 0 < noLongerPendingLanes; ) { - var index$6 = 31 - clz32(noLongerPendingLanes), - lane = 1 << index$6; - remainingLanes[index$6] = 0; - eventTimes[index$6] = -1; - expirationTimes[index$6] = -1; - var hiddenUpdatesForLane = root[index$6]; - if (null !== hiddenUpdatesForLane) - for ( - root[index$6] = null, index$6 = 0; - index$6 < hiddenUpdatesForLane.length; - index$6++ - ) { - var update = hiddenUpdatesForLane[index$6]; - null !== update && (update.lane &= -1073741825); - } - noLongerPendingLanes &= ~lane; - } -} -function markRootEntangled(root, entangledLanes) { - var rootEntangledLanes = (root.entangledLanes |= entangledLanes); - for (root = root.entanglements; rootEntangledLanes; ) { - var index$7 = 31 - clz32(rootEntangledLanes), - lane = 1 << index$7; - (lane & entangledLanes) | (root[index$7] & entangledLanes) && - (root[index$7] |= entangledLanes); - rootEntangledLanes &= ~lane; - } -} -var currentUpdatePriority = 0; -function lanesToEventPriority(lanes) { - lanes &= -lanes; - return 2 < lanes - ? 8 < lanes - ? 0 !== (lanes & 268435455) - ? 32 - : 536870912 - : 8 - : 2; -} -function shim() { - throw Error( - "The current renderer does not support hydration. This error is likely caused by a bug in React. Please file an issue." - ); -} -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, - FabricDiscretePriority = _nativeFabricUIManage.unstable_DiscreteEventPriority, - fabricGetCurrentEventPriority = - _nativeFabricUIManage.unstable_getCurrentEventPriority, - _setNativeProps = _nativeFabricUIManage.setNativeProps, - fabricGetBoundingClientRect = _nativeFabricUIManage.getBoundingClientRect, - getViewConfigForType = - ReactNativePrivateInterface.ReactNativeViewConfigRegistry.get, - nextReactTag = 2; -registerEventHandler && registerEventHandler(dispatchEvent); -function noop$1() {} -var ReactFabricHostComponent = (function () { - function ReactFabricHostComponent( - tag, - viewConfig, - props, - internalInstanceHandle - ) { - this.viewConfig = void 0; - this._nativeTag = tag; - this.viewConfig = viewConfig; - this.currentProps = props; - this._internalInstanceHandle = internalInstanceHandle; - } - var _proto = ReactFabricHostComponent.prototype; - _proto.blur = function () { - ReactNativePrivateInterface.TextInputState.blurTextInput(this); - }; - _proto.focus = function () { - ReactNativePrivateInterface.TextInputState.focusTextInput(this); - }; - _proto.measure = function (callback) { - var node = getShadowNodeFromInternalInstanceHandle( - this._internalInstanceHandle - ); - null != node && fabricMeasure(node, callback); - }; - _proto.measureInWindow = function (callback) { - var node = getShadowNodeFromInternalInstanceHandle( - this._internalInstanceHandle - ); - null != node && fabricMeasureInWindow(node, callback); - }; - _proto.measureLayout = function (relativeToNativeNode, onSuccess, onFail) { - if ( - "number" !== typeof relativeToNativeNode && - relativeToNativeNode instanceof ReactFabricHostComponent - ) { - var toStateNode = getShadowNodeFromInternalInstanceHandle( - this._internalInstanceHandle - ); - relativeToNativeNode = getShadowNodeFromInternalInstanceHandle( - relativeToNativeNode._internalInstanceHandle - ); - null != toStateNode && - null != relativeToNativeNode && - fabricMeasureLayout( - toStateNode, - relativeToNativeNode, - null != onFail ? onFail : noop$1, - null != onSuccess ? onSuccess : noop$1 - ); - } - }; - _proto.unstable_getBoundingClientRect = function () { - var node = getShadowNodeFromInternalInstanceHandle( - this._internalInstanceHandle - ); - return null != node && (node = fabricGetBoundingClientRect(node)) - ? new DOMRect(node[0], node[1], node[2], node[3]) - : new DOMRect(0, 0, 0, 0); - }; - _proto.setNativeProps = function (nativeProps) { - nativeProps = diffProperties( - null, - emptyObject$1, - nativeProps, - this.viewConfig.validAttributes - ); - var node = getShadowNodeFromInternalInstanceHandle( - this._internalInstanceHandle - ); - null != node && null != nativeProps && _setNativeProps(node, nativeProps); - }; - return ReactFabricHostComponent; -})(); -function getShadowNodeFromInternalInstanceHandle(internalInstanceHandle) { - return ( - internalInstanceHandle && - internalInstanceHandle.stateNode && - internalInstanceHandle.stateNode.node - ); -} -function createTextInstance( - text, - rootContainerInstance, - hostContext, - internalInstanceHandle -) { - hostContext = nextReactTag; - nextReactTag += 2; - return { - node: createNode( - hostContext, - "RCTRawText", - rootContainerInstance, - { text: text }, - internalInstanceHandle - ) - }; -} -function getPublicInstance(instance) { - return instance.canonical - ? instance.canonical - : null != instance._nativeTag - ? instance - : null; -} -var scheduleTimeout = setTimeout, - cancelTimeout = clearTimeout; -function cloneHiddenInstance(instance) { - var node = instance.node; - var JSCompiler_inline_result = diffProperties( - null, - emptyObject$1, - { style: { display: "none" } }, - instance.canonical.viewConfig.validAttributes - ); - return { - node: cloneNodeWithNewProps(node, JSCompiler_inline_result), - canonical: instance.canonical - }; -} -function getInstanceFromNode(node) { - return node; -} -getFiberCurrentPropsFromNode$1 = function (instance) { - return instance.canonical.currentProps; -}; -getInstanceFromNode$1 = getInstanceFromNode; -getNodeFromInstance$1 = function (fiber) { - fiber = getPublicInstance(fiber.stateNode); - if (null == fiber) throw Error("Could not find host instance from fiber"); - return fiber; -}; -ResponderEventPlugin.injection.injectGlobalResponderHandler({ - onChange: function (from, to, blockNativeResponder) { - from && - nativeFabricUIManager.setIsJSResponder( - from.stateNode.node, - !1, - blockNativeResponder || !1 - ); - to && - nativeFabricUIManager.setIsJSResponder( - to.stateNode.node, - !0, - blockNativeResponder || !1 - ); - } -}); -var REACT_ELEMENT_TYPE = Symbol.for("react.element"), +var ReactSharedInternals = + React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, + enableUseRefAccessWarning = dynamicFlags.enableUseRefAccessWarning, + REACT_ELEMENT_TYPE = Symbol.for("react.element"), REACT_PORTAL_TYPE = Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"), REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"), @@ -1931,36 +1429,36 @@ function findCurrentFiberUsingSlowPath(fiber) { } if (a.return !== b.return) (a = parentA), (b = parentB); else { - for (var didFindChild = !1, child$8 = parentA.child; child$8; ) { - if (child$8 === a) { + for (var didFindChild = !1, child$2 = parentA.child; child$2; ) { + if (child$2 === a) { didFindChild = !0; a = parentA; b = parentB; break; } - if (child$8 === b) { + if (child$2 === b) { didFindChild = !0; b = parentA; a = parentB; break; } - child$8 = child$8.sibling; + child$2 = child$2.sibling; } if (!didFindChild) { - for (child$8 = parentB.child; child$8; ) { - if (child$8 === a) { + for (child$2 = parentB.child; child$2; ) { + if (child$2 === a) { didFindChild = !0; a = parentB; b = parentA; break; } - if (child$8 === b) { + if (child$2 === b) { didFindChild = !0; b = parentB; a = parentA; break; } - child$8 = child$8.sibling; + child$2 = child$2.sibling; } if (!didFindChild) throw Error( @@ -1989,115 +1487,364 @@ function findCurrentHostFiberImpl(node) { if (null !== tag) return tag; node = node.sibling; } - return null; + return null; +} +function describeComponentFrame(name, source, ownerName) { + source = ""; + ownerName && (source = " (created by " + ownerName + ")"); + return "\n in " + (name || "Unknown") + source; +} +function describeFunctionComponentFrame(fn, source) { + return fn + ? describeComponentFrame(fn.displayName || fn.name || null, source, null) + : ""; +} +var hasOwnProperty = Object.prototype.hasOwnProperty, + valueStack = [], + index = -1; +function createCursor(defaultValue) { + return { current: defaultValue }; +} +function pop(cursor) { + 0 > index || + ((cursor.current = valueStack[index]), (valueStack[index] = null), index--); +} +function push(cursor, value) { + index++; + valueStack[index] = cursor.current; + cursor.current = value; +} +var emptyContextObject = {}, + contextStackCursor$1 = createCursor(emptyContextObject), + didPerformWorkStackCursor = createCursor(!1), + previousContext = emptyContextObject; +function getMaskedContext(workInProgress, unmaskedContext) { + var contextTypes = workInProgress.type.contextTypes; + if (!contextTypes) return emptyContextObject; + var instance = workInProgress.stateNode; + if ( + instance && + instance.__reactInternalMemoizedUnmaskedChildContext === unmaskedContext + ) + return instance.__reactInternalMemoizedMaskedChildContext; + var context = {}, + key; + for (key in contextTypes) context[key] = unmaskedContext[key]; + instance && + ((workInProgress = workInProgress.stateNode), + (workInProgress.__reactInternalMemoizedUnmaskedChildContext = + unmaskedContext), + (workInProgress.__reactInternalMemoizedMaskedChildContext = context)); + return context; +} +function isContextProvider(type) { + type = type.childContextTypes; + return null !== type && void 0 !== type; +} +function popContext() { + pop(didPerformWorkStackCursor); + pop(contextStackCursor$1); +} +function pushTopLevelContextObject(fiber, context, didChange) { + if (contextStackCursor$1.current !== emptyContextObject) + throw Error( + "Unexpected context found on stack. This error is likely caused by a bug in React. Please file an issue." + ); + push(contextStackCursor$1, context); + push(didPerformWorkStackCursor, didChange); +} +function processChildContext(fiber, type, parentContext) { + var instance = fiber.stateNode; + type = type.childContextTypes; + if ("function" !== typeof instance.getChildContext) return parentContext; + instance = instance.getChildContext(); + for (var contextKey in instance) + if (!(contextKey in type)) + throw Error( + (getComponentNameFromFiber(fiber) || "Unknown") + + '.getChildContext(): key "' + + contextKey + + '" is not defined in childContextTypes.' + ); + return assign({}, parentContext, instance); +} +function pushContextProvider(workInProgress) { + workInProgress = + ((workInProgress = workInProgress.stateNode) && + workInProgress.__reactInternalMemoizedMergedChildContext) || + emptyContextObject; + previousContext = contextStackCursor$1.current; + push(contextStackCursor$1, workInProgress); + push(didPerformWorkStackCursor, didPerformWorkStackCursor.current); + return !0; +} +function invalidateContextProvider(workInProgress, type, didChange) { + var instance = workInProgress.stateNode; + if (!instance) + throw Error( + "Expected to have an instance by this point. This error is likely caused by a bug in React. Please file an issue." + ); + didChange + ? ((workInProgress = processChildContext( + workInProgress, + type, + previousContext + )), + (instance.__reactInternalMemoizedMergedChildContext = workInProgress), + pop(didPerformWorkStackCursor), + pop(contextStackCursor$1), + push(contextStackCursor$1, workInProgress)) + : pop(didPerformWorkStackCursor); + push(didPerformWorkStackCursor, didChange); +} +var clz32 = Math.clz32 ? Math.clz32 : clz32Fallback, + log = Math.log, + LN2 = Math.LN2; +function clz32Fallback(x) { + x >>>= 0; + return 0 === x ? 32 : (31 - ((log(x) / LN2) | 0)) | 0; +} +var nextTransitionLane = 128, + nextRetryLane = 8388608; +function getHighestPriorityLanes(lanes) { + switch (lanes & -lanes) { + case 1: + return 1; + case 2: + return 2; + case 4: + return 4; + case 8: + return 8; + case 16: + return 16; + case 32: + return 32; + case 64: + return 64; + case 128: + case 256: + case 512: + case 1024: + case 2048: + case 4096: + case 8192: + case 16384: + case 32768: + case 65536: + case 131072: + case 262144: + case 524288: + case 1048576: + case 2097152: + case 4194304: + return lanes & 8388480; + case 8388608: + case 16777216: + case 33554432: + case 67108864: + return lanes & 125829120; + case 134217728: + return 134217728; + case 268435456: + return 268435456; + case 536870912: + return 536870912; + case 1073741824: + return 1073741824; + default: + return lanes; + } +} +function getNextLanes(root, wipLanes) { + var pendingLanes = root.pendingLanes; + if (0 === pendingLanes) return 0; + var nextLanes = 0, + suspendedLanes = root.suspendedLanes, + pingedLanes = root.pingedLanes, + nonIdlePendingLanes = pendingLanes & 268435455; + if (0 !== nonIdlePendingLanes) { + var nonIdleUnblockedLanes = nonIdlePendingLanes & ~suspendedLanes; + 0 !== nonIdleUnblockedLanes + ? (nextLanes = getHighestPriorityLanes(nonIdleUnblockedLanes)) + : ((pingedLanes &= nonIdlePendingLanes), + 0 !== pingedLanes && + (nextLanes = getHighestPriorityLanes(pingedLanes))); + } else + (nonIdlePendingLanes = pendingLanes & ~suspendedLanes), + 0 !== nonIdlePendingLanes + ? (nextLanes = getHighestPriorityLanes(nonIdlePendingLanes)) + : 0 !== 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 || + (32 === suspendedLanes && 0 !== (pingedLanes & 8388480))) + ) + return wipLanes; + 0 === (root.current.mode & 32) && + 0 !== (nextLanes & 8) && + (nextLanes |= pendingLanes & 32); + wipLanes = root.entangledLanes; + if (0 !== wipLanes) + for (root = root.entanglements, wipLanes &= nextLanes; 0 < wipLanes; ) + (pendingLanes = 31 - clz32(wipLanes)), + (suspendedLanes = 1 << pendingLanes), + (nextLanes |= root[pendingLanes]), + (wipLanes &= ~suspendedLanes); + return nextLanes; +} +function computeExpirationTime(lane, currentTime) { + switch (lane) { + case 1: + case 2: + case 4: + case 8: + return currentTime + 250; + case 16: + case 32: + case 64: + case 128: + case 256: + case 512: + case 1024: + case 2048: + case 4096: + case 8192: + case 16384: + case 32768: + case 65536: + case 131072: + case 262144: + case 524288: + case 1048576: + case 2097152: + case 4194304: + return currentTime + 5e3; + case 8388608: + case 16777216: + case 33554432: + case 67108864: + return -1; + case 134217728: + case 268435456: + case 536870912: + case 1073741824: + return -1; + default: + return -1; + } } -function describeComponentFrame(name, source, ownerName) { - source = ""; - ownerName && (source = " (created by " + ownerName + ")"); - return "\n in " + (name || "Unknown") + source; +function getLanesToRetrySynchronouslyOnError(root, originallyAttemptedLanes) { + if (root.errorRecoveryDisabledLanes & originallyAttemptedLanes) return 0; + root = root.pendingLanes & -1073741825; + return 0 !== root ? root : root & 1073741824 ? 1073741824 : 0; } -function describeFunctionComponentFrame(fn, source) { - return fn - ? describeComponentFrame(fn.displayName || fn.name || null, source, null) - : ""; +function includesBlockingLane(root, lanes) { + return 0 !== (root.current.mode & 32) ? !1 : 0 !== (lanes & 60); } -var hasOwnProperty = Object.prototype.hasOwnProperty, - valueStack = [], - index = -1; -function createCursor(defaultValue) { - return { current: defaultValue }; +function claimNextTransitionLane() { + var lane = nextTransitionLane; + nextTransitionLane <<= 1; + 0 === (nextTransitionLane & 8388480) && (nextTransitionLane = 128); + return lane; } -function pop(cursor) { - 0 > index || - ((cursor.current = valueStack[index]), (valueStack[index] = null), index--); +function claimNextRetryLane() { + var lane = nextRetryLane; + nextRetryLane <<= 1; + 0 === (nextRetryLane & 125829120) && (nextRetryLane = 8388608); + return lane; } -function push(cursor, value) { - index++; - valueStack[index] = cursor.current; - cursor.current = value; +function createLaneMap(initial) { + for (var laneMap = [], i = 0; 31 > i; i++) laneMap.push(initial); + return laneMap; } -var emptyContextObject = {}, - contextStackCursor$1 = createCursor(emptyContextObject), - didPerformWorkStackCursor = createCursor(!1), - previousContext = emptyContextObject; -function getMaskedContext(workInProgress, unmaskedContext) { - var contextTypes = workInProgress.type.contextTypes; - if (!contextTypes) return emptyContextObject; - var instance = workInProgress.stateNode; - if ( - instance && - instance.__reactInternalMemoizedUnmaskedChildContext === unmaskedContext - ) - return instance.__reactInternalMemoizedMaskedChildContext; - var context = {}, - key; - for (key in contextTypes) context[key] = unmaskedContext[key]; - instance && - ((workInProgress = workInProgress.stateNode), - (workInProgress.__reactInternalMemoizedUnmaskedChildContext = - unmaskedContext), - (workInProgress.__reactInternalMemoizedMaskedChildContext = context)); - return context; +function markRootUpdated(root, updateLane, eventTime) { + root.pendingLanes |= updateLane; + 536870912 !== updateLane && + ((root.suspendedLanes = 0), (root.pingedLanes = 0)); + root = root.eventTimes; + updateLane = 31 - clz32(updateLane); + root[updateLane] = eventTime; } -function isContextProvider(type) { - type = type.childContextTypes; - return null !== type && void 0 !== type; +function markRootFinished(root, remainingLanes) { + var noLongerPendingLanes = root.pendingLanes & ~remainingLanes; + root.pendingLanes = remainingLanes; + root.suspendedLanes = 0; + root.pingedLanes = 0; + root.expiredLanes &= remainingLanes; + root.mutableReadLanes &= remainingLanes; + root.entangledLanes &= remainingLanes; + root.errorRecoveryDisabledLanes &= remainingLanes; + remainingLanes = root.entanglements; + var eventTimes = root.eventTimes, + expirationTimes = root.expirationTimes; + for (root = root.hiddenUpdates; 0 < noLongerPendingLanes; ) { + var index$7 = 31 - clz32(noLongerPendingLanes), + lane = 1 << index$7; + remainingLanes[index$7] = 0; + eventTimes[index$7] = -1; + expirationTimes[index$7] = -1; + var hiddenUpdatesForLane = root[index$7]; + if (null !== hiddenUpdatesForLane) + for ( + root[index$7] = null, index$7 = 0; + index$7 < hiddenUpdatesForLane.length; + index$7++ + ) { + var update = hiddenUpdatesForLane[index$7]; + null !== update && (update.lane &= -1073741825); + } + noLongerPendingLanes &= ~lane; + } } -function popContext() { - pop(didPerformWorkStackCursor); - pop(contextStackCursor$1); +function markRootEntangled(root, entangledLanes) { + var rootEntangledLanes = (root.entangledLanes |= entangledLanes); + for (root = root.entanglements; rootEntangledLanes; ) { + var index$8 = 31 - clz32(rootEntangledLanes), + lane = 1 << index$8; + (lane & entangledLanes) | (root[index$8] & entangledLanes) && + (root[index$8] |= entangledLanes); + rootEntangledLanes &= ~lane; + } } -function pushTopLevelContextObject(fiber, context, didChange) { - if (contextStackCursor$1.current !== emptyContextObject) - throw Error( - "Unexpected context found on stack. This error is likely caused by a bug in React. Please file an issue." - ); - push(contextStackCursor$1, context); - push(didPerformWorkStackCursor, didChange); +var currentUpdatePriority = 0; +function lanesToEventPriority(lanes) { + lanes &= -lanes; + return 2 < lanes + ? 8 < lanes + ? 0 !== (lanes & 268435455) + ? 32 + : 536870912 + : 8 + : 2; } -function processChildContext(fiber, type, parentContext) { - var instance = fiber.stateNode; - type = type.childContextTypes; - if ("function" !== typeof instance.getChildContext) return parentContext; - instance = instance.getChildContext(); - for (var contextKey in instance) - if (!(contextKey in type)) - throw Error( - (getComponentNameFromFiber(fiber) || "Unknown") + - '.getChildContext(): key "' + - contextKey + - '" is not defined in childContextTypes.' +var scheduleCallback$1 = Scheduler.unstable_scheduleCallback, + cancelCallback$1 = Scheduler.unstable_cancelCallback, + shouldYield = Scheduler.unstable_shouldYield, + requestPaint = Scheduler.unstable_requestPaint, + now = Scheduler.unstable_now, + ImmediatePriority = Scheduler.unstable_ImmediatePriority, + UserBlockingPriority = Scheduler.unstable_UserBlockingPriority, + NormalPriority = Scheduler.unstable_NormalPriority, + IdlePriority = Scheduler.unstable_IdlePriority, + rendererID = null, + injectedHook = null; +function onCommitRoot(root) { + if (injectedHook && "function" === typeof injectedHook.onCommitFiberRoot) + try { + injectedHook.onCommitFiberRoot( + rendererID, + root, + void 0, + 128 === (root.current.flags & 128) ); - return assign({}, parentContext, instance); -} -function pushContextProvider(workInProgress) { - workInProgress = - ((workInProgress = workInProgress.stateNode) && - workInProgress.__reactInternalMemoizedMergedChildContext) || - emptyContextObject; - previousContext = contextStackCursor$1.current; - push(contextStackCursor$1, workInProgress); - push(didPerformWorkStackCursor, didPerformWorkStackCursor.current); - return !0; -} -function invalidateContextProvider(workInProgress, type, didChange) { - var instance = workInProgress.stateNode; - if (!instance) - throw Error( - "Expected to have an instance by this point. This error is likely caused by a bug in React. Please file an issue." - ); - didChange - ? ((workInProgress = processChildContext( - workInProgress, - type, - previousContext - )), - (instance.__reactInternalMemoizedMergedChildContext = workInProgress), - pop(didPerformWorkStackCursor), - pop(contextStackCursor$1), - push(contextStackCursor$1, workInProgress)) - : pop(didPerformWorkStackCursor); - push(didPerformWorkStackCursor, didChange); + } catch (err) {} } function is(x, y) { return (x === y && (0 !== x || 1 / x === 1 / y)) || (x !== x && y !== y); @@ -2109,30 +1856,43 @@ var objectIs = "function" === typeof Object.is ? Object.is : is, function flushSyncCallbacks() { if (!isFlushingSyncQueue && null !== syncQueue) { isFlushingSyncQueue = !0; - var i = 0, - previousUpdatePriority = currentUpdatePriority; - try { - var queue = syncQueue; - for (currentUpdatePriority = 2; i < queue.length; i++) { - var callback = queue[i]; + var previousUpdatePriority = currentUpdatePriority; + currentUpdatePriority = 2; + for (var errors = null, queue = syncQueue, i = 0; i < queue.length; i++) { + var callback = queue[i]; + try { do callback = callback(!0); while (null !== callback); + } catch (error) { + null === errors ? (errors = [error]) : errors.push(error); } - syncQueue = null; - includesLegacySyncCallbacks = !1; - } catch (error) { - throw ( - (null !== syncQueue && (syncQueue = syncQueue.slice(i + 1)), - scheduleCallback$1(ImmediatePriority, flushSyncCallbacks), - error) - ); - } finally { - (currentUpdatePriority = previousUpdatePriority), - (isFlushingSyncQueue = !1); + } + syncQueue = null; + includesLegacySyncCallbacks = !1; + currentUpdatePriority = previousUpdatePriority; + isFlushingSyncQueue = !1; + if (null !== errors) { + if (1 < errors.length) { + if ("function" === typeof AggregateError) + throw new AggregateError(errors); + for ( + previousUpdatePriority = 1; + previousUpdatePriority < errors.length; + previousUpdatePriority++ + ) + scheduleCallback$1( + ImmediatePriority, + throwError.bind(null, errors[previousUpdatePriority]) + ); + } + throw errors[0]; } } return null; } +function throwError(error) { + throw error; +} var contextStackCursor = createCursor(null), contextFiberStackCursor = createCursor(null), rootInstanceStackCursor = createCursor(null); @@ -2532,6 +2292,65 @@ function describeFiber(fiber) { return ""; } } +var SuspenseException = Error( + "Suspense Exception: This is not a real error! It's an implementation detail of `use` to interrupt the current render. You must either rethrow it immediately, or move the `use` call outside of the `try/catch` block. Capturing without rethrowing will lead to unexpected behavior.\n\nTo handle async errors, wrap your component in an error boundary, or call the promise's `.catch` method and pass the result to `use`" + ), + noopSuspenseyCommitThenable = { then: function () {} }; +function isThenableResolved(thenable) { + thenable = thenable.status; + return "fulfilled" === thenable || "rejected" === thenable; +} +function noop$1() {} +function trackUsedThenable(thenableState, thenable, index) { + index = thenableState[index]; + void 0 === index + ? thenableState.push(thenable) + : index !== thenable && (thenable.then(noop$1, noop$1), (thenable = index)); + switch (thenable.status) { + case "fulfilled": + return thenable.value; + case "rejected": + throw thenable.reason; + default: + "string" === typeof thenable.status + ? thenable.then(noop$1, noop$1) + : ((thenableState = thenable), + (thenableState.status = "pending"), + thenableState.then( + function (fulfilledValue) { + if ("pending" === thenable.status) { + var fulfilledThenable = thenable; + fulfilledThenable.status = "fulfilled"; + fulfilledThenable.value = fulfilledValue; + } + }, + function (error) { + if ("pending" === thenable.status) { + var rejectedThenable = thenable; + rejectedThenable.status = "rejected"; + rejectedThenable.reason = error; + } + } + )); + switch (thenable.status) { + case "fulfilled": + return thenable.value; + case "rejected": + throw thenable.reason; + } + suspendedThenable = thenable; + throw SuspenseException; + } +} +var suspendedThenable = null, + thenableState$1 = null, + thenableIndexCounter$1 = 0; +function unwrapThenable(thenable) { + var index = thenableIndexCounter$1; + thenableIndexCounter$1 += 1; + null === thenableState$1 && (thenableState$1 = []); + return trackUsedThenable(thenableState$1, thenable, index); +} function coerceRef(returnFiber, current, element) { returnFiber = element.ref; if ( @@ -2636,16 +2455,16 @@ function createChildReconciler(shouldTrackSideEffects) { return ( (newIndex = newIndex.index), newIndex < lastPlacedIndex - ? ((newFiber.flags |= 16777218), lastPlacedIndex) + ? ((newFiber.flags |= 33554434), lastPlacedIndex) : newIndex ); - newFiber.flags |= 16777218; + newFiber.flags |= 33554434; return lastPlacedIndex; } function placeSingleChild(newFiber) { shouldTrackSideEffects && null === newFiber.alternate && - (newFiber.flags |= 16777218); + (newFiber.flags |= 33554434); return newFiber; } function updateTextNode(returnFiber, current, textContent, lanes) { @@ -2782,6 +2601,17 @@ function createChildReconciler(shouldTrackSideEffects) { (newChild.return = returnFiber), newChild ); + if ("function" === typeof newChild.then) + return createChild(returnFiber, unwrapThenable(newChild), lanes); + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) + return createChild( + returnFiber, + readContextDuringReconcilation(returnFiber, newChild, lanes), + lanes + ); throwOnInvalidObjectType(returnFiber, newChild); } return null; @@ -2815,6 +2645,23 @@ function createChildReconciler(shouldTrackSideEffects) { return null !== key ? null : updateFragment(returnFiber, oldFiber, newChild, lanes, null); + if ("function" === typeof newChild.then) + return updateSlot( + returnFiber, + oldFiber, + unwrapThenable(newChild), + lanes + ); + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) + return updateSlot( + returnFiber, + oldFiber, + readContextDuringReconcilation(returnFiber, newChild, lanes), + lanes + ); throwOnInvalidObjectType(returnFiber, newChild); } return null; @@ -2867,6 +2714,25 @@ function createChildReconciler(shouldTrackSideEffects) { (existingChildren = existingChildren.get(newIdx) || null), updateFragment(returnFiber, existingChildren, newChild, lanes, null) ); + if ("function" === typeof newChild.then) + return updateFromMap( + existingChildren, + returnFiber, + newIdx, + unwrapThenable(newChild), + lanes + ); + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) + return updateFromMap( + existingChildren, + returnFiber, + newIdx, + readContextDuringReconcilation(returnFiber, newChild, lanes), + lanes + ); throwOnInvalidObjectType(returnFiber, newChild); } return null; @@ -3038,7 +2904,7 @@ function createChildReconciler(shouldTrackSideEffects) { }); return iteratorFn; } - function reconcileChildFibers( + function reconcileChildFibersImpl( returnFiber, currentFirstChild, newChild, @@ -3183,6 +3049,23 @@ function createChildReconciler(shouldTrackSideEffects) { newChild, lanes ); + if ("function" === typeof newChild.then) + return reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + unwrapThenable(newChild), + lanes + ); + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) + return reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + readContextDuringReconcilation(returnFiber, newChild, lanes), + lanes + ); throwOnInvalidObjectType(returnFiber, newChild); } return ("string" === typeof newChild && "" !== newChild) || @@ -3204,6 +3087,22 @@ function createChildReconciler(shouldTrackSideEffects) { placeSingleChild(returnFiber)) : deleteRemainingChildren(returnFiber, currentFirstChild); } + function reconcileChildFibers( + returnFiber, + currentFirstChild, + newChild, + lanes + ) { + thenableIndexCounter$1 = 0; + returnFiber = reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + newChild, + lanes + ); + thenableState$1 = null; + return returnFiber; + } return reconcileChildFibers; } var reconcileChildFibers = createChildReconciler(!0), @@ -3282,57 +3181,7 @@ function resetWorkInProgressVersions() { workInProgressSources[i]._workInProgressVersionSecondary = null; workInProgressSources.length = 0; } -var SuspenseException = Error( - "Suspense Exception: This is not a real error! It's an implementation detail of `use` to interrupt the current render. You must either rethrow it immediately, or move the `use` call outside of the `try/catch` block. Capturing without rethrowing will lead to unexpected behavior.\n\nTo handle async errors, wrap your component in an error boundary, or call the promise's `.catch` method and pass the result to `use`" -); -function isThenableResolved(thenable) { - thenable = thenable.status; - return "fulfilled" === thenable || "rejected" === thenable; -} -function noop() {} -function trackUsedThenable(thenableState, thenable, index) { - index = thenableState[index]; - void 0 === index - ? thenableState.push(thenable) - : index !== thenable && (thenable.then(noop, noop), (thenable = index)); - switch (thenable.status) { - case "fulfilled": - return thenable.value; - case "rejected": - throw thenable.reason; - default: - "string" === typeof thenable.status - ? thenable.then(noop, noop) - : ((thenableState = thenable), - (thenableState.status = "pending"), - thenableState.then( - function (fulfilledValue) { - if ("pending" === thenable.status) { - var fulfilledThenable = thenable; - fulfilledThenable.status = "fulfilled"; - fulfilledThenable.value = fulfilledValue; - } - }, - function (error) { - if ("pending" === thenable.status) { - var rejectedThenable = thenable; - rejectedThenable.status = "rejected"; - rejectedThenable.reason = error; - } - } - )); - switch (thenable.status) { - case "fulfilled": - return thenable.value; - case "rejected": - throw thenable.reason; - } - suspendedThenable = thenable; - throw SuspenseException; - } -} -var suspendedThenable = null, - ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, +var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, ReactCurrentBatchConfig$2 = ReactSharedInternals.ReactCurrentBatchConfig, renderLanes$1 = 0, currentlyRenderingFiber$1 = null, @@ -3492,10 +3341,10 @@ createFunctionComponentUpdateQueue = function () { function use(usable) { if (null !== usable && "object" === typeof usable) { if ("function" === typeof usable.then) { - var index$25 = thenableIndexCounter; + var index$27 = thenableIndexCounter; thenableIndexCounter += 1; null === thenableState && (thenableState = []); - usable = trackUsedThenable(thenableState, usable, index$25); + usable = trackUsedThenable(thenableState, usable, index$27); null === currentlyRenderingFiber$1.alternate && (null === workInProgressHook ? null === currentlyRenderingFiber$1.memoizedState @@ -3950,8 +3799,9 @@ function startTransition(setPending, callback) { var previousPriority = currentUpdatePriority; currentUpdatePriority = 0 !== previousPriority && 8 > previousPriority ? previousPriority : 8; - setPending(!0); var prevTransition = ReactCurrentBatchConfig$2.transition; + ReactCurrentBatchConfig$2.transition = null; + setPending(!0); ReactCurrentBatchConfig$2.transition = {}; try { setPending(!1), callback(); @@ -5076,7 +4926,7 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { (nextProps.pendingProps = primaryChildProps), (workInProgress.deletions = null)) : ((nextProps = createWorkInProgress(JSCompiler_temp, primaryChildProps)), - (nextProps.subtreeFlags = JSCompiler_temp.subtreeFlags & 14680064)); + (nextProps.subtreeFlags = JSCompiler_temp.subtreeFlags & 31457280)); null !== dehydrated ? (showFallback = createWorkInProgress(dehydrated, showFallback)) : ((showFallback = createFiberFromFragment( @@ -5602,21 +5452,26 @@ function prepareToReadContext(workInProgress, renderLanes) { (workInProgress.firstContext = null)); } function readContext(context) { + return readContextForConsumer(currentlyRenderingFiber, context); +} +function readContextDuringReconcilation(consumer, context, renderLanes) { + null === currentlyRenderingFiber && + prepareToReadContext(consumer, renderLanes); + return readContextForConsumer(consumer, context); +} +function readContextForConsumer(consumer, context) { var value = context._currentValue2; if (lastFullyObservedContext !== context) if ( ((context = { context: context, memoizedValue: value, next: null }), null === lastContextDependency) ) { - if (null === currentlyRenderingFiber) + if (null === consumer) throw 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()." ); lastContextDependency = context; - currentlyRenderingFiber.dependencies = { - lanes: 0, - firstContext: context - }; + consumer.dependencies = { lanes: 0, firstContext: context }; } else lastContextDependency = lastContextDependency.next = context; return value; } @@ -5724,6 +5579,14 @@ function updateHostContainer(current, workInProgress) { completeRoot(current, newChildSet); } } +function scheduleRetryEffect(workInProgress, retryQueue) { + null !== retryQueue + ? (workInProgress.flags |= 4) + : workInProgress.flags & 16384 && + ((retryQueue = + 22 !== workInProgress.tag ? claimNextRetryLane() : 1073741824), + (workInProgress.lanes |= retryQueue)); +} function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { switch (renderState.tailMode) { case "hidden": @@ -5738,14 +5601,14 @@ function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { break; case "collapsed": lastTailNode = renderState.tail; - for (var lastTailNode$63 = null; null !== lastTailNode; ) - null !== lastTailNode.alternate && (lastTailNode$63 = lastTailNode), + for (var lastTailNode$66 = null; null !== lastTailNode; ) + null !== lastTailNode.alternate && (lastTailNode$66 = lastTailNode), (lastTailNode = lastTailNode.sibling); - null === lastTailNode$63 + null === lastTailNode$66 ? hasRenderedATailFallback || null === renderState.tail ? (renderState.tail = null) : (renderState.tail.sibling = null) - : (lastTailNode$63.sibling = null); + : (lastTailNode$66.sibling = null); } } function bubbleProperties(completedWork) { @@ -5755,19 +5618,19 @@ function bubbleProperties(completedWork) { newChildLanes = 0, subtreeFlags = 0; if (didBailout) - for (var child$64 = completedWork.child; null !== child$64; ) - (newChildLanes |= child$64.lanes | child$64.childLanes), - (subtreeFlags |= child$64.subtreeFlags & 14680064), - (subtreeFlags |= child$64.flags & 14680064), - (child$64.return = completedWork), - (child$64 = child$64.sibling); + for (var child$67 = completedWork.child; null !== child$67; ) + (newChildLanes |= child$67.lanes | child$67.childLanes), + (subtreeFlags |= child$67.subtreeFlags & 31457280), + (subtreeFlags |= child$67.flags & 31457280), + (child$67.return = completedWork), + (child$67 = child$67.sibling); else - for (child$64 = completedWork.child; null !== child$64; ) - (newChildLanes |= child$64.lanes | child$64.childLanes), - (subtreeFlags |= child$64.subtreeFlags), - (subtreeFlags |= child$64.flags), - (child$64.return = completedWork), - (child$64 = child$64.sibling); + for (child$67 = completedWork.child; null !== child$67; ) + (newChildLanes |= child$67.lanes | child$67.childLanes), + (subtreeFlags |= child$67.subtreeFlags), + (subtreeFlags |= child$67.flags), + (child$67.return = completedWork), + (child$67 = child$67.sibling); completedWork.subtreeFlags |= subtreeFlags; completedWork.childLanes = newChildLanes; return didBailout; @@ -5818,15 +5681,15 @@ function completeWork(current, workInProgress, renderLanes) { case 27: case 5: popHostContext(workInProgress); - var type = workInProgress.type; + renderLanes = workInProgress.type; if (null !== current && null != workInProgress.stateNode) { - type = current.stateNode; - var oldProps = current.memoizedProps; + var currentInstance = current.stateNode, + oldProps = current.memoizedProps; if ( (renderLanes = hadNoMutationsEffects(current, workInProgress)) && oldProps === newProps ) - workInProgress.stateNode = type; + workInProgress.stateNode = currentInstance; else { var recyclableInstance = workInProgress.stateNode, updatePayload = null; @@ -5840,9 +5703,9 @@ function completeWork(current, workInProgress, renderLanes) { (recyclableInstance.canonical.currentProps = newProps), (updatePayload = oldProps)); renderLanes && null === updatePayload - ? (workInProgress.stateNode = type) + ? (workInProgress.stateNode = currentInstance) : ((newProps = updatePayload), - (recyclableInstance = type.node), + (recyclableInstance = currentInstance.node), (newProps = { node: renderLanes ? null !== newProps @@ -5854,8 +5717,9 @@ function completeWork(current, workInProgress, renderLanes) { newProps ) : cloneNodeWithNewChildren(recyclableInstance), - canonical: type.canonical + canonical: currentInstance.canonical }), + (workInProgress.flags &= -16777217), (workInProgress.stateNode = newProps), renderLanes ? (workInProgress.flags |= 4) @@ -5871,32 +5735,41 @@ function completeWork(current, workInProgress, renderLanes) { bubbleProperties(workInProgress); return null; } - renderLanes = rootInstanceStackCursor.current; + currentInstance = rootInstanceStackCursor.current; current = nextReactTag; nextReactTag += 2; - type = getViewConfigForType(type); + renderLanes = getViewConfigForType(renderLanes); recyclableInstance = diffProperties( null, emptyObject$1, newProps, - type.validAttributes + renderLanes.validAttributes ); - renderLanes = createNode( + currentInstance = createNode( current, - type.uiViewClassName, - renderLanes, + renderLanes.uiViewClassName, + currentInstance, recyclableInstance, workInProgress ); - current = new ReactFabricHostComponent( + recyclableInstance = new ReactFabricHostComponent( current, - type, - newProps, + renderLanes, workInProgress ); - current = { node: renderLanes, canonical: current }; + current = { + node: currentInstance, + canonical: { + nativeTag: current, + viewConfig: renderLanes, + currentProps: newProps, + internalInstanceHandle: workInProgress, + publicInstance: recyclableInstance + } + }; appendAllChildren(current, workInProgress, !1, !1); workInProgress.stateNode = current; + workInProgress.flags &= -16777217; null !== workInProgress.ref && (workInProgress.flags |= 2097664); } bubbleProperties(workInProgress); @@ -5947,12 +5820,13 @@ function completeWork(current, workInProgress, renderLanes) { (workInProgress.memoizedState = null); workInProgress.flags |= 4; bubbleProperties(workInProgress); - type = !1; + currentInstance = !1; } else null !== hydrationErrors && (queueRecoverableErrors(hydrationErrors), (hydrationErrors = null)), - (type = !0); - if (!type) return workInProgress.flags & 65536 ? workInProgress : null; + (currentInstance = !0); + if (!currentInstance) + return workInProgress.flags & 65536 ? workInProgress : null; } if (0 !== (workInProgress.flags & 128)) return (workInProgress.lanes = renderLanes), workInProgress; @@ -5960,7 +5834,7 @@ function completeWork(current, workInProgress, renderLanes) { newProps !== (null !== current && null !== current.memoizedState) && newProps && (workInProgress.child.flags |= 8192); - null !== workInProgress.updateQueue && (workInProgress.flags |= 4); + scheduleRetryEffect(workInProgress, workInProgress.updateQueue); bubbleProperties(workInProgress); return null; case 4: @@ -5984,12 +5858,13 @@ function completeWork(current, workInProgress, renderLanes) { ); case 19: pop(suspenseStackCursor); - type = workInProgress.memoizedState; - if (null === type) return bubbleProperties(workInProgress), null; + currentInstance = workInProgress.memoizedState; + if (null === currentInstance) + return bubbleProperties(workInProgress), null; newProps = 0 !== (workInProgress.flags & 128); - recyclableInstance = type.rendering; + recyclableInstance = currentInstance.rendering; if (null === recyclableInstance) - if (newProps) cutOffTailIfNeeded(type, !1); + if (newProps) cutOffTailIfNeeded(currentInstance, !1); else { if ( 0 !== workInProgressRootExitStatus || @@ -5999,11 +5874,10 @@ function completeWork(current, workInProgress, renderLanes) { recyclableInstance = findFirstSuspended(current); if (null !== recyclableInstance) { workInProgress.flags |= 128; - cutOffTailIfNeeded(type, !1); + cutOffTailIfNeeded(currentInstance, !1); current = recyclableInstance.updateQueue; - null !== current && - ((workInProgress.updateQueue = current), - (workInProgress.flags |= 4)); + workInProgress.updateQueue = current; + scheduleRetryEffect(workInProgress, current); workInProgress.subtreeFlags = 0; current = renderLanes; for (newProps = workInProgress.child; null !== newProps; ) @@ -6017,11 +5891,11 @@ function completeWork(current, workInProgress, renderLanes) { } current = current.sibling; } - null !== type.tail && + null !== currentInstance.tail && now() > workInProgressRootRenderTargetTime && ((workInProgress.flags |= 128), (newProps = !0), - cutOffTailIfNeeded(type, !1), + cutOffTailIfNeeded(currentInstance, !1), (workInProgress.lanes = 8388608)); } else { @@ -6034,38 +5908,37 @@ function completeWork(current, workInProgress, renderLanes) { ((workInProgress.flags |= 128), (newProps = !0), (current = current.updateQueue), - null !== current && - ((workInProgress.updateQueue = current), - (workInProgress.flags |= 4)), - cutOffTailIfNeeded(type, !0), - null === type.tail && - "hidden" === type.tailMode && + (workInProgress.updateQueue = current), + scheduleRetryEffect(workInProgress, current), + cutOffTailIfNeeded(currentInstance, !0), + null === currentInstance.tail && + "hidden" === currentInstance.tailMode && !recyclableInstance.alternate) ) return bubbleProperties(workInProgress), null; } else - 2 * now() - type.renderingStartTime > + 2 * now() - currentInstance.renderingStartTime > workInProgressRootRenderTargetTime && 1073741824 !== renderLanes && ((workInProgress.flags |= 128), (newProps = !0), - cutOffTailIfNeeded(type, !1), + cutOffTailIfNeeded(currentInstance, !1), (workInProgress.lanes = 8388608)); - type.isBackwards + currentInstance.isBackwards ? ((recyclableInstance.sibling = workInProgress.child), (workInProgress.child = recyclableInstance)) - : ((current = type.last), + : ((current = currentInstance.last), null !== current ? (current.sibling = recyclableInstance) : (workInProgress.child = recyclableInstance), - (type.last = recyclableInstance)); + (currentInstance.last = recyclableInstance)); } - if (null !== type.tail) + if (null !== currentInstance.tail) return ( - (workInProgress = type.tail), - (type.rendering = workInProgress), - (type.tail = workInProgress.sibling), - (type.renderingStartTime = now()), + (workInProgress = currentInstance.tail), + (currentInstance.rendering = workInProgress), + (currentInstance.tail = workInProgress.sibling), + (currentInstance.renderingStartTime = now()), (workInProgress.sibling = null), (current = suspenseStackCursor.current), push(suspenseStackCursor, newProps ? (current & 1) | 2 : current & 1), @@ -6092,7 +5965,9 @@ function completeWork(current, workInProgress, renderLanes) { workInProgress.subtreeFlags & 6 && (workInProgress.flags |= 8192)) : bubbleProperties(workInProgress), - null !== workInProgress.updateQueue && (workInProgress.flags |= 4), + (current = workInProgress.updateQueue), + null !== current && + scheduleRetryEffect(workInProgress, current.retryQueue), null ); case 24: @@ -6247,8 +6122,8 @@ function safelyDetachRef(current, nearestMountedAncestor) { else if ("function" === typeof ref) try { ref(null); - } catch (error$77) { - captureCommitPhaseError(current, nearestMountedAncestor, error$77); + } catch (error$82) { + captureCommitPhaseError(current, nearestMountedAncestor, error$82); } else ref.current = null; } @@ -6351,8 +6226,8 @@ function commitHookEffectListMount(flags, finishedWork) { var effect = (finishedWork = finishedWork.next); do { if ((effect.tag & flags) === flags) { - var create$78 = effect.create; - effect.destroy = create$78(); + var create$83 = effect.create; + effect.destroy = create$83(); } effect = effect.next; } while (effect !== finishedWork); @@ -6415,11 +6290,11 @@ function commitLayoutEffectOnFiber(finishedRoot, current, finishedWork) { current, finishedRoot.__reactInternalSnapshotBeforeUpdate ); - } catch (error$79) { + } catch (error$84) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$79 + error$84 ); } } @@ -6737,8 +6612,8 @@ function commitMutationEffectsOnFiber(finishedWork, root) { } try { commitHookEffectListUnmount(5, finishedWork, finishedWork.return); - } catch (error$81) { - captureCommitPhaseError(finishedWork, finishedWork.return, error$81); + } catch (error$86) { + captureCommitPhaseError(finishedWork, finishedWork.return, error$86); } } break; @@ -6798,14 +6673,14 @@ function commitMutationEffectsOnFiber(finishedWork, root) { flags & 512 && null !== current && safelyDetachRef(current, current.return); - var isHidden$88 = null !== finishedWork.memoizedState, - wasHidden$89 = null !== current && null !== current.memoizedState; + var isHidden$93 = null !== finishedWork.memoizedState, + wasHidden$94 = null !== current && null !== current.memoizedState; if (finishedWork.mode & 1) { var prevOffscreenSubtreeIsHidden = offscreenSubtreeIsHidden, prevOffscreenSubtreeWasHidden = offscreenSubtreeWasHidden; - offscreenSubtreeIsHidden = prevOffscreenSubtreeIsHidden || isHidden$88; + offscreenSubtreeIsHidden = prevOffscreenSubtreeIsHidden || isHidden$93; offscreenSubtreeWasHidden = - prevOffscreenSubtreeWasHidden || wasHidden$89; + prevOffscreenSubtreeWasHidden || wasHidden$94; recursivelyTraverseMutationEffects(root, finishedWork); offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden; offscreenSubtreeIsHidden = prevOffscreenSubtreeIsHidden; @@ -6816,23 +6691,23 @@ function commitMutationEffectsOnFiber(finishedWork, root) { root._visibility &= -3; root._visibility |= root._pendingVisibility & 2; flags & 8192 && - ((root._visibility = isHidden$88 + ((root._visibility = isHidden$93 ? root._visibility & -2 : root._visibility | 1), - isHidden$88 && - ((isHidden$88 = + isHidden$93 && + ((isHidden$93 = offscreenSubtreeIsHidden || offscreenSubtreeWasHidden), null === current || - wasHidden$89 || - isHidden$88 || + wasHidden$94 || + isHidden$93 || (0 !== (finishedWork.mode & 1) && recursivelyTraverseDisappearLayoutEffects(finishedWork)))); flags & 4 && ((flags = finishedWork.updateQueue), null !== flags && - ((current = flags.wakeables), + ((current = flags.retryQueue), null !== current && - ((flags.wakeables = null), + ((flags.retryQueue = null), attachSuspenseRetryListeners(finishedWork, current)))); break; case 19: @@ -7321,12 +7196,12 @@ function ensureRootIsScheduled(root, currentTime) { 0 < lanes; ) { - var index$4 = 31 - clz32(lanes), - lane = 1 << index$4, - expirationTime = expirationTimes[index$4]; + var index$5 = 31 - clz32(lanes), + lane = 1 << index$5, + expirationTime = expirationTimes[index$5]; if (-1 === expirationTime) { if (0 === (lane & suspendedLanes) || 0 !== (lane & pingedLanes)) - expirationTimes[index$4] = computeExpirationTime(lane, currentTime); + expirationTimes[index$5] = computeExpirationTime(lane, currentTime); } else expirationTime <= currentTime && (root.expiredLanes |= lane); lanes &= ~lane; } @@ -7340,6 +7215,8 @@ function ensureRootIsScheduled(root, currentTime) { (root.callbackPriority = 0); else if (2 === workInProgressSuspendedReason && workInProgressRoot === root) (root.callbackPriority = 0), (root.callbackNode = null); + else if (null !== root.cancelPendingCommit && 0 === (suspendedLanes & 42)) + (root.callbackPriority = 0), (root.callbackNode = null); else if ( ((currentTime = suspendedLanes & -suspendedLanes), root.callbackPriority !== currentTime) @@ -7397,28 +7274,28 @@ function performConcurrentWorkOnRoot(root, didTimeout) { root === workInProgressRoot ? workInProgressRootRenderLanes : 0 ); if (0 === lanes) return null; - didTimeout = + var exitStatus = includesBlockingLane(root, lanes) || 0 !== (lanes & root.expiredLanes) || didTimeout ? renderRootSync(root, lanes) : renderRootConcurrent(root, lanes); - if (0 !== didTimeout) { - if (2 === didTimeout) { - var originallyAttemptedLanes = lanes, - errorRetryLanes = getLanesToRetrySynchronouslyOnError( - root, - originallyAttemptedLanes - ); + if (0 !== exitStatus) { + if (2 === exitStatus) { + didTimeout = lanes; + var errorRetryLanes = getLanesToRetrySynchronouslyOnError( + root, + didTimeout + ); 0 !== errorRetryLanes && ((lanes = errorRetryLanes), - (didTimeout = recoverFromConcurrentError( + (exitStatus = recoverFromConcurrentError( root, - originallyAttemptedLanes, + didTimeout, errorRetryLanes ))); } - if (1 === didTimeout) + if (1 === exitStatus) throw ( ((originalCallbackNode = workInProgressRootFatalError), prepareFreshStack(root, 0), @@ -7426,30 +7303,30 @@ function performConcurrentWorkOnRoot(root, didTimeout) { ensureRootIsScheduled(root, now()), originalCallbackNode) ); - if (6 === didTimeout) markRootSuspended(root, lanes); + if (6 === exitStatus) markRootSuspended(root, lanes); else { errorRetryLanes = !includesBlockingLane(root, lanes); - originallyAttemptedLanes = root.current.alternate; + didTimeout = root.current.alternate; if ( errorRetryLanes && - !isRenderConsistentWithExternalStores(originallyAttemptedLanes) + !isRenderConsistentWithExternalStores(didTimeout) ) { - didTimeout = renderRootSync(root, lanes); - if (2 === didTimeout) { + exitStatus = renderRootSync(root, lanes); + if (2 === exitStatus) { errorRetryLanes = lanes; - var errorRetryLanes$93 = getLanesToRetrySynchronouslyOnError( + var errorRetryLanes$98 = getLanesToRetrySynchronouslyOnError( root, errorRetryLanes ); - 0 !== errorRetryLanes$93 && - ((lanes = errorRetryLanes$93), - (didTimeout = recoverFromConcurrentError( + 0 !== errorRetryLanes$98 && + ((lanes = errorRetryLanes$98), + (exitStatus = recoverFromConcurrentError( root, errorRetryLanes, - errorRetryLanes$93 + errorRetryLanes$98 ))); } - if (1 === didTimeout) + if (1 === exitStatus) throw ( ((originalCallbackNode = workInProgressRootFatalError), prepareFreshStack(root, 0), @@ -7458,94 +7335,84 @@ function performConcurrentWorkOnRoot(root, didTimeout) { originalCallbackNode) ); } - root.finishedWork = originallyAttemptedLanes; + root.finishedWork = didTimeout; root.finishedLanes = lanes; - switch (didTimeout) { + switch (exitStatus) { case 0: case 1: throw Error("Root did not complete. This is a bug in React."); case 2: - commitRoot( - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ); + commitRootWhenReady(root); break; case 3: markRootSuspended(root, lanes); if ( (lanes & 125829120) === lanes && - ((lanes = globalMostRecentFallbackTime + 500 - now()), 10 < lanes) + ((exitStatus = globalMostRecentFallbackTime + 500 - now()), + 10 < exitStatus) ) { if (0 !== getNextLanes(root, 0)) break; root.timeoutHandle = scheduleTimeout( - commitRoot.bind( + commitRootWhenReady.bind( null, root, + didTimeout, workInProgressRootRecoverableErrors, - workInProgressTransitions + workInProgressTransitions, + lanes ), - lanes + exitStatus ); break; } - commitRoot( - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ); + commitRootWhenReady(root); break; case 4: markRootSuspended(root, lanes); if ((lanes & 8388480) === lanes) break; - didTimeout = root.eventTimes; - for (originallyAttemptedLanes = -1; 0 < lanes; ) - (errorRetryLanes$93 = 31 - clz32(lanes)), - (errorRetryLanes = 1 << errorRetryLanes$93), - (errorRetryLanes$93 = didTimeout[errorRetryLanes$93]), - errorRetryLanes$93 > originallyAttemptedLanes && - (originallyAttemptedLanes = errorRetryLanes$93), - (lanes &= ~errorRetryLanes); - lanes = originallyAttemptedLanes; - lanes = now() - lanes; - lanes = - (120 > lanes + exitStatus = lanes; + errorRetryLanes = root.eventTimes; + for (errorRetryLanes$98 = -1; 0 < exitStatus; ) { + var index$4 = 31 - clz32(exitStatus), + lane = 1 << index$4; + index$4 = errorRetryLanes[index$4]; + index$4 > errorRetryLanes$98 && (errorRetryLanes$98 = index$4); + exitStatus &= ~lane; + } + exitStatus = errorRetryLanes$98; + exitStatus = now() - exitStatus; + exitStatus = + (120 > exitStatus ? 120 - : 480 > lanes + : 480 > exitStatus ? 480 - : 1080 > lanes + : 1080 > exitStatus ? 1080 - : 1920 > lanes + : 1920 > exitStatus ? 1920 - : 3e3 > lanes + : 3e3 > exitStatus ? 3e3 - : 4320 > lanes + : 4320 > exitStatus ? 4320 - : 1960 * ceil(lanes / 1960)) - lanes; - if (10 < lanes) { + : 1960 * ceil(exitStatus / 1960)) - exitStatus; + if (10 < exitStatus) { root.timeoutHandle = scheduleTimeout( - commitRoot.bind( + commitRootWhenReady.bind( null, root, + didTimeout, workInProgressRootRecoverableErrors, - workInProgressTransitions + workInProgressTransitions, + lanes ), - lanes + exitStatus ); break; } - commitRoot( - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ); + commitRootWhenReady(root); break; case 5: - commitRoot( - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ); + commitRootWhenReady(root); break; default: throw Error("Unknown root exit status."); @@ -7588,6 +7455,13 @@ function queueRecoverableErrors(errors) { errors ); } +function commitRootWhenReady(root) { + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); +} function isRenderConsistentWithExternalStores(finishedWork) { for (var node = finishedWork; ; ) { if (node.flags & 16384) { @@ -7628,9 +7502,9 @@ function markRootSuspended(root, suspendedLanes) { root.suspendedLanes |= suspendedLanes; root.pingedLanes &= ~suspendedLanes; for (root = root.expirationTimes; 0 < suspendedLanes; ) { - var index$5 = 31 - clz32(suspendedLanes), - lane = 1 << index$5; - root[index$5] = -1; + var index$6 = 31 - clz32(suspendedLanes), + lane = 1 << index$6; + root[index$6] = -1; suspendedLanes &= ~lane; } } @@ -7684,6 +7558,8 @@ function resetWorkInProgressStack() { else resetContextDependencies(), resetHooksOnUnwind(), + (thenableState$1 = null), + (thenableIndexCounter$1 = 0), (interruptedWork = workInProgress); for (; null !== interruptedWork; ) unwindInterruptedWork(interruptedWork.alternate, interruptedWork), @@ -7697,6 +7573,9 @@ function prepareFreshStack(root, lanes) { var timeoutHandle = root.timeoutHandle; -1 !== timeoutHandle && ((root.timeoutHandle = -1), cancelTimeout(timeoutHandle)); + timeoutHandle = root.cancelPendingCommit; + null !== timeoutHandle && + ((root.cancelPendingCommit = null), timeoutHandle()); resetWorkInProgressStack(); workInProgressRoot = root; workInProgress = root = createWorkInProgress(root.current, null); @@ -7723,12 +7602,23 @@ function handleThrow(root, thrownValue) { throw Error( "Expected a suspended thenable. This is a bug in React. Please file an issue." ); - root = suspendedThenable; + thrownValue = suspendedThenable; suspendedThenable = null; - thrownValue = root; - workInProgressSuspendedReason = shouldAttemptToSuspendUntilDataResolves() - ? 2 - : 3; + (workInProgressRootRenderLanes & 8388480) === workInProgressRootRenderLanes + ? (root = null === shellBoundary ? !0 : !1) + : ((root = suspenseHandlerStackCursor.current), + (root = + null !== root && + (workInProgressRootRenderLanes & 125829120) === + workInProgressRootRenderLanes + ? root === shellBoundary + : !1)); + workInProgressSuspendedReason = + root && + 0 === (workInProgressRootSkippedLanes & 268435455) && + 0 === (workInProgressRootInterleavedUpdatedLanes & 268435455) + ? 2 + : 3; } else workInProgressSuspendedReason = thrownValue === SelectiveHydrationException @@ -7743,24 +7633,6 @@ function handleThrow(root, thrownValue) { ((workInProgressRootExitStatus = 1), (workInProgressRootFatalError = thrownValue)); } -function shouldAttemptToSuspendUntilDataResolves() { - if ( - 0 !== (workInProgressRootSkippedLanes & 268435455) || - 0 !== (workInProgressRootInterleavedUpdatedLanes & 268435455) - ) - return !1; - if ( - (workInProgressRootRenderLanes & 8388480) === - workInProgressRootRenderLanes - ) - return null === shellBoundary; - var handler = suspenseHandlerStackCursor.current; - return null !== handler && - (workInProgressRootRenderLanes & 125829120) === - workInProgressRootRenderLanes - ? handler === shellBoundary - : !1; -} function pushDispatcher() { var prevDispatcher = ReactCurrentDispatcher.current; ReactCurrentDispatcher.current = ContextOnlyDispatcher; @@ -7797,8 +7669,8 @@ function renderRootSync(root, lanes) { } workLoopSync(); break; - } catch (thrownValue$96) { - handleThrow(root, thrownValue$96); + } catch (thrownValue$101) { + handleThrow(root, thrownValue$101); } while (1); resetContextDependencies(); @@ -7877,8 +7749,8 @@ function renderRootConcurrent(root, lanes) { } workLoopConcurrent(); break; - } catch (thrownValue$98) { - handleThrow(root, thrownValue$98); + } catch (thrownValue$103) { + handleThrow(root, thrownValue$103); } while (1); resetContextDependencies(); @@ -7931,9 +7803,7 @@ function replaySuspendedUnitOfWork(unitOfWork) { ); break; default: - resetContextDependencies(), - resetHooksOnUnwind(), - unwindInterruptedWork(current, unitOfWork), + unwindInterruptedWork(current, unitOfWork), (unitOfWork = workInProgress = resetWorkInProgress(unitOfWork, renderLanes)), (current = beginWork(current, unitOfWork, renderLanes)); @@ -7947,6 +7817,8 @@ function replaySuspendedUnitOfWork(unitOfWork) { function unwindSuspendedUnitOfWork(unitOfWork, thrownValue) { resetContextDependencies(); resetHooksOnUnwind(); + thenableState$1 = null; + thenableIndexCounter$1 = 0; var returnFiber = unitOfWork.return; if (null === returnFiber || null === workInProgressRoot) (workInProgressRootExitStatus = 1), @@ -8008,27 +7880,35 @@ function unwindSuspendedUnitOfWork(unitOfWork, thrownValue) { else (suspenseBoundary.flags |= 65536), (suspenseBoundary.lanes = thrownValue); - var wakeables = suspenseBoundary.updateQueue; - null === wakeables - ? (suspenseBoundary.updateQueue = new Set([wakeable])) - : wakeables.add(wakeable); + if (wakeable === noopSuspenseyCommitThenable) + suspenseBoundary.flags |= 16384; + else { + var retryQueue = suspenseBoundary.updateQueue; + null === retryQueue + ? (suspenseBoundary.updateQueue = new Set([wakeable])) + : retryQueue.add(wakeable); + } break; case 22: if (suspenseBoundary.mode & 1) { suspenseBoundary.flags |= 65536; - var offscreenQueue = suspenseBoundary.updateQueue; - if (null === offscreenQueue) { - var newOffscreenQueue = { - transitions: null, - markerInstances: null, - wakeables: new Set([wakeable]) - }; - suspenseBoundary.updateQueue = newOffscreenQueue; - } else { - var wakeables$31 = offscreenQueue.wakeables; - null === wakeables$31 - ? (offscreenQueue.wakeables = new Set([wakeable])) - : wakeables$31.add(wakeable); + if (wakeable === noopSuspenseyCommitThenable) + suspenseBoundary.flags |= 16384; + else { + var offscreenQueue = suspenseBoundary.updateQueue; + if (null === offscreenQueue) { + var newOffscreenQueue = { + transitions: null, + markerInstances: null, + retryQueue: new Set([wakeable]) + }; + suspenseBoundary.updateQueue = newOffscreenQueue; + } else { + var retryQueue$34 = offscreenQueue.retryQueue; + null === retryQueue$34 + ? (offscreenQueue.retryQueue = new Set([wakeable])) + : retryQueue$34.add(wakeable); + } } break; } @@ -8117,7 +7997,7 @@ function completeUnitOfWork(unitOfWork) { } else { current = unwindWork(current, completedWork); if (null !== current) { - current.flags &= 16383; + current.flags &= 32767; workInProgress = current; return; } @@ -8179,6 +8059,7 @@ function commitRootImpl( ); root.callbackNode = null; root.callbackPriority = 0; + root.cancelPendingCommit = null; var remainingLanes = transitions.lanes | transitions.childLanes; remainingLanes |= concurrentlyUpdatedLanes; markRootFinished(root, remainingLanes); @@ -8378,11 +8259,7 @@ function pingSuspendedRoot(root, wakeable, pingedLanes) { } function retryTimedOutBoundary(boundaryFiber, retryLane) { 0 === retryLane && - (0 === (boundaryFiber.mode & 1) - ? (retryLane = 2) - : ((retryLane = nextRetryLane), - (nextRetryLane <<= 1), - 0 === (nextRetryLane & 125829120) && (nextRetryLane = 8388608))); + (retryLane = 0 === (boundaryFiber.mode & 1) ? 2 : claimNextRetryLane()); var eventTime = requestEventTime(); boundaryFiber = enqueueConcurrentRenderForLane(boundaryFiber, retryLane); null !== boundaryFiber && @@ -8922,7 +8799,7 @@ function createWorkInProgress(current, pendingProps) { (workInProgress.flags = 0), (workInProgress.subtreeFlags = 0), (workInProgress.deletions = null)); - workInProgress.flags = current.flags & 14680064; + workInProgress.flags = current.flags & 31457280; workInProgress.childLanes = current.childLanes; workInProgress.lanes = current.lanes; workInProgress.child = current.child; @@ -8941,7 +8818,7 @@ function createWorkInProgress(current, pendingProps) { return workInProgress; } function resetWorkInProgress(workInProgress, renderLanes) { - workInProgress.flags &= 14680066; + workInProgress.flags &= 31457282; var current = workInProgress.alternate; null === current ? ((workInProgress.childLanes = 0), @@ -9039,222 +8916,487 @@ function createFiberFromTypeAndProps( break a; } 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) + ".") + "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) + ".") + ); + } + key = createFiber(fiberTag, pendingProps, key, mode); + key.elementType = type; + key.type = owner; + key.lanes = lanes; + return key; +} +function createFiberFromFragment(elements, mode, lanes, key) { + elements = createFiber(7, elements, key, mode); + elements.lanes = lanes; + return elements; +} +function createFiberFromOffscreen(pendingProps, mode, lanes, key) { + pendingProps = createFiber(22, pendingProps, key, mode); + pendingProps.elementType = REACT_OFFSCREEN_TYPE; + pendingProps.lanes = lanes; + var primaryChildInstance = { + _visibility: 1, + _pendingVisibility: 1, + _pendingMarkers: null, + _retryCache: null, + _transitions: null, + _current: null, + detach: function () { + return detachOffscreenInstance(primaryChildInstance); + }, + attach: function () { + return attachOffscreenInstance(primaryChildInstance); + } + }; + pendingProps.stateNode = primaryChildInstance; + return pendingProps; +} +function createFiberFromLegacyHidden(pendingProps, mode, lanes, key) { + pendingProps = createFiber(23, pendingProps, key, mode); + pendingProps.elementType = REACT_LEGACY_HIDDEN_TYPE; + pendingProps.lanes = lanes; + var instance = { + _visibility: 1, + _pendingVisibility: 1, + _pendingMarkers: null, + _transitions: null, + _retryCache: null, + _current: null, + detach: function () { + return detachOffscreenInstance(instance); + }, + attach: function () { + return attachOffscreenInstance(instance); + } + }; + pendingProps.stateNode = instance; + return pendingProps; +} +function createFiberFromText(content, mode, lanes) { + content = createFiber(6, content, null, mode); + content.lanes = lanes; + return content; +} +function createFiberFromPortal(portal, mode, lanes) { + mode = createFiber( + 4, + null !== portal.children ? portal.children : [], + portal.key, + mode + ); + mode.lanes = lanes; + mode.stateNode = { + containerInfo: portal.containerInfo, + pendingChildren: null, + implementation: portal.implementation + }; + return mode; +} +function FiberRootNode( + containerInfo, + tag, + hydrate, + identifierPrefix, + onRecoverableError +) { + this.tag = tag; + this.containerInfo = containerInfo; + this.finishedWork = + this.pingCache = + this.current = + this.pendingChildren = + null; + this.timeoutHandle = -1; + this.callbackNode = + this.pendingContext = + this.context = + this.cancelPendingCommit = + null; + this.callbackPriority = 0; + this.eventTimes = createLaneMap(0); + this.expirationTimes = createLaneMap(-1); + this.entangledLanes = + this.errorRecoveryDisabledLanes = + this.finishedLanes = + this.mutableReadLanes = + this.expiredLanes = + this.pingedLanes = + this.suspendedLanes = + this.pendingLanes = + 0; + this.entanglements = createLaneMap(0); + this.hiddenUpdates = createLaneMap(null); + this.identifierPrefix = identifierPrefix; + this.onRecoverableError = onRecoverableError; + this.incompleteTransitions = new Map(); +} +function createPortal$1(children, containerInfo, implementation) { + var key = + 3 < arguments.length && void 0 !== arguments[3] ? arguments[3] : null; + return { + $$typeof: REACT_PORTAL_TYPE, + key: null == key ? null : "" + key, + children: children, + containerInfo: containerInfo, + implementation: implementation + }; +} +function findHostInstance(component) { + var fiber = component._reactInternals; + if (void 0 === fiber) { + if ("function" === typeof component.render) + throw Error("Unable to find node on an unmounted component."); + component = Object.keys(component).join(","); + throw Error( + "Argument appears to not be a ReactComponent. Keys: " + component + ); + } + component = findCurrentHostFiber(fiber); + return null === component ? null : getPublicInstance(component.stateNode); +} +function updateContainer(element, container, parentComponent, callback) { + var current = container.current, + lane = requestUpdateLane(current); + a: if (parentComponent) { + parentComponent = parentComponent._reactInternals; + b: { + if ( + getNearestMountedFiber(parentComponent) !== parentComponent || + 1 !== parentComponent.tag + ) + throw 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 JSCompiler_inline_result = parentComponent; + do { + switch (JSCompiler_inline_result.tag) { + case 3: + JSCompiler_inline_result = + JSCompiler_inline_result.stateNode.context; + break b; + case 1: + if (isContextProvider(JSCompiler_inline_result.type)) { + JSCompiler_inline_result = + JSCompiler_inline_result.stateNode + .__reactInternalMemoizedMergedChildContext; + break b; + } + } + JSCompiler_inline_result = JSCompiler_inline_result.return; + } while (null !== JSCompiler_inline_result); + throw Error( + "Found unexpected detached subtree parent. This error is likely caused by a bug in React. Please file an issue." + ); + } + if (1 === parentComponent.tag) { + var Component = parentComponent.type; + if (isContextProvider(Component)) { + parentComponent = processChildContext( + parentComponent, + Component, + JSCompiler_inline_result ); + break a; + } } - key = createFiber(fiberTag, pendingProps, key, mode); - key.elementType = type; - key.type = owner; - key.lanes = lanes; - return key; + parentComponent = JSCompiler_inline_result; + } else parentComponent = emptyContextObject; + null === container.context + ? (container.context = parentComponent) + : (container.pendingContext = parentComponent); + container = createUpdate(lane); + container.payload = { element: element }; + callback = void 0 === callback ? null : callback; + null !== callback && (container.callback = callback); + element = enqueueUpdate(current, container, lane); + null !== element && + ((callback = requestEventTime()), + scheduleUpdateOnFiber(element, current, lane, callback), + entangleTransitions(element, current, lane)); + return lane; } -function createFiberFromFragment(elements, mode, lanes, key) { - elements = createFiber(7, elements, key, mode); - elements.lanes = lanes; - return elements; +function emptyFindFiberByHostInstance() { + return null; } -function createFiberFromOffscreen(pendingProps, mode, lanes, key) { - pendingProps = createFiber(22, pendingProps, key, mode); - pendingProps.elementType = REACT_OFFSCREEN_TYPE; - pendingProps.lanes = lanes; - var primaryChildInstance = { - _visibility: 1, - _pendingVisibility: 1, - _pendingMarkers: null, - _retryCache: null, - _transitions: null, - _current: null, - detach: function () { - return detachOffscreenInstance(primaryChildInstance); - }, - attach: function () { - return attachOffscreenInstance(primaryChildInstance); - } - }; - pendingProps.stateNode = primaryChildInstance; - return pendingProps; +function findNodeHandle(componentOrHandle) { + if (null == componentOrHandle) return null; + if ("number" === typeof componentOrHandle) return componentOrHandle; + if (componentOrHandle._nativeTag) return componentOrHandle._nativeTag; + if ( + null != componentOrHandle.canonical && + null != componentOrHandle.canonical.nativeTag + ) + return componentOrHandle.canonical.nativeTag; + var nativeTag = componentOrHandle.__nativeTag; + if (nativeTag) return nativeTag; + componentOrHandle = findHostInstance(componentOrHandle); + return null == componentOrHandle + ? componentOrHandle + : null != componentOrHandle._nativeTag + ? componentOrHandle._nativeTag + : componentOrHandle.__nativeTag; } -function createFiberFromLegacyHidden(pendingProps, mode, lanes, key) { - pendingProps = createFiber(23, pendingProps, key, mode); - pendingProps.elementType = REACT_LEGACY_HIDDEN_TYPE; - pendingProps.lanes = lanes; - var instance = { - _visibility: 1, - _pendingVisibility: 1, - _pendingMarkers: null, - _transitions: null, - _retryCache: null, - _current: null, - detach: function () { - return detachOffscreenInstance(instance); - }, - attach: function () { - return attachOffscreenInstance(instance); +function getNodeFromInternalInstanceHandle(internalInstanceHandle) { + return ( + internalInstanceHandle && + internalInstanceHandle.stateNode && + internalInstanceHandle.stateNode.node + ); +} +var _nativeFabricUIManage$1 = nativeFabricUIManager, + fabricMeasure = _nativeFabricUIManage$1.measure, + fabricMeasureInWindow = _nativeFabricUIManage$1.measureInWindow, + fabricMeasureLayout = _nativeFabricUIManage$1.measureLayout, + _setNativeProps = _nativeFabricUIManage$1.setNativeProps, + fabricGetBoundingClientRect = _nativeFabricUIManage$1.getBoundingClientRect; +function noop() {} +var ReactFabricHostComponent = (function () { + function ReactFabricHostComponent(tag, viewConfig, internalInstanceHandle) { + this.__nativeTag = tag; + this._viewConfig = viewConfig; + this.__internalInstanceHandle = internalInstanceHandle; + } + var _proto = ReactFabricHostComponent.prototype; + _proto.blur = function () { + ReactNativePrivateInterface.TextInputState.blurTextInput(this); + }; + _proto.focus = function () { + ReactNativePrivateInterface.TextInputState.focusTextInput(this); + }; + _proto.measure = function (callback) { + var node = getNodeFromInternalInstanceHandle(this.__internalInstanceHandle); + null != node && fabricMeasure(node, callback); + }; + _proto.measureInWindow = function (callback) { + var node = getNodeFromInternalInstanceHandle(this.__internalInstanceHandle); + null != node && fabricMeasureInWindow(node, callback); + }; + _proto.measureLayout = function (relativeToNativeNode, onSuccess, onFail) { + if ( + "number" !== typeof relativeToNativeNode && + relativeToNativeNode instanceof ReactFabricHostComponent + ) { + var toStateNode = getNodeFromInternalInstanceHandle( + this.__internalInstanceHandle + ); + relativeToNativeNode = getNodeFromInternalInstanceHandle( + relativeToNativeNode.__internalInstanceHandle + ); + null != toStateNode && + null != relativeToNativeNode && + fabricMeasureLayout( + toStateNode, + relativeToNativeNode, + null != onFail ? onFail : noop, + null != onSuccess ? onSuccess : noop + ); } }; - pendingProps.stateNode = instance; - return pendingProps; + _proto.unstable_getBoundingClientRect = function () { + var node = getNodeFromInternalInstanceHandle(this.__internalInstanceHandle); + return null != node && (node = fabricGetBoundingClientRect(node)) + ? new DOMRect(node[0], node[1], node[2], node[3]) + : new DOMRect(0, 0, 0, 0); + }; + _proto.setNativeProps = function (nativeProps) { + nativeProps = diffProperties( + null, + emptyObject$1, + nativeProps, + this._viewConfig.validAttributes + ); + var node = getNodeFromInternalInstanceHandle(this.__internalInstanceHandle); + null != node && null != nativeProps && _setNativeProps(node, nativeProps); + }; + return ReactFabricHostComponent; +})(); +function batchedUpdatesImpl(fn, bookkeeping) { + return fn(bookkeeping); } -function createFiberFromText(content, mode, lanes) { - content = createFiber(6, content, null, mode); - content.lanes = lanes; - return content; +var isInsideEventHandler = !1; +function batchedUpdates(fn, bookkeeping) { + if (isInsideEventHandler) return fn(bookkeeping); + isInsideEventHandler = !0; + try { + return batchedUpdatesImpl(fn, bookkeeping); + } finally { + isInsideEventHandler = !1; + } } -function createFiberFromPortal(portal, mode, lanes) { - mode = createFiber( - 4, - null !== portal.children ? portal.children : [], - portal.key, - mode +var eventQueue = null; +function executeDispatchesAndReleaseTopLevel(e) { + if (e) { + var dispatchListeners = e._dispatchListeners, + dispatchInstances = e._dispatchInstances; + if (isArrayImpl(dispatchListeners)) + for ( + var i = 0; + i < dispatchListeners.length && !e.isPropagationStopped(); + i++ + ) + executeDispatch(e, dispatchListeners[i], dispatchInstances[i]); + else + dispatchListeners && + executeDispatch(e, dispatchListeners, dispatchInstances); + e._dispatchListeners = null; + e._dispatchInstances = null; + e.isPersistent() || e.constructor.release(e); + } +} +function dispatchEvent(target, topLevelType, nativeEvent) { + var eventTarget = null; + if (null != target) { + var stateNode = target.stateNode; + null != stateNode && (eventTarget = getPublicInstance(stateNode)); + } + batchedUpdates(function () { + var event = { eventName: topLevelType, nativeEvent: nativeEvent }; + ReactNativePrivateInterface.RawEventEmitter.emit(topLevelType, event); + ReactNativePrivateInterface.RawEventEmitter.emit("*", event); + event = eventTarget; + for ( + var events = null, legacyPlugins = plugins, i = 0; + i < legacyPlugins.length; + i++ + ) { + var possiblePlugin = legacyPlugins[i]; + possiblePlugin && + (possiblePlugin = possiblePlugin.extractEvents( + topLevelType, + target, + nativeEvent, + event + )) && + (events = accumulateInto(events, possiblePlugin)); + } + event = events; + null !== event && (eventQueue = accumulateInto(eventQueue, event)); + event = eventQueue; + eventQueue = null; + if (event) { + forEachAccumulated(event, executeDispatchesAndReleaseTopLevel); + if (eventQueue) + throw Error( + "processEventQueue(): Additional events were enqueued while processing an event queue. Support for this has not yet been implemented." + ); + if (hasRethrowError) + throw ( + ((event = rethrowError), + (hasRethrowError = !1), + (rethrowError = null), + event) + ); + } + }); +} +function shim() { + throw Error( + "The current renderer does not support hydration. This error is likely caused by a bug in React. Please file an issue." ); - mode.lanes = lanes; - mode.stateNode = { - containerInfo: portal.containerInfo, - pendingChildren: null, - implementation: portal.implementation - }; - return mode; } -function FiberRootNode( - containerInfo, - tag, - hydrate, - identifierPrefix, - onRecoverableError +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, + FabricDiscretePriority = _nativeFabricUIManage.unstable_DiscreteEventPriority, + fabricGetCurrentEventPriority = + _nativeFabricUIManage.unstable_getCurrentEventPriority, + getViewConfigForType = + ReactNativePrivateInterface.ReactNativeViewConfigRegistry.get, + nextReactTag = 2; +registerEventHandler && registerEventHandler(dispatchEvent); +function createTextInstance( + text, + rootContainerInstance, + hostContext, + internalInstanceHandle ) { - this.tag = tag; - this.containerInfo = containerInfo; - this.finishedWork = - this.pingCache = - this.current = - this.pendingChildren = - null; - this.timeoutHandle = -1; - this.callbackNode = this.pendingContext = this.context = null; - this.callbackPriority = 0; - this.eventTimes = createLaneMap(0); - this.expirationTimes = createLaneMap(-1); - this.entangledLanes = - this.errorRecoveryDisabledLanes = - this.finishedLanes = - this.mutableReadLanes = - this.expiredLanes = - this.pingedLanes = - this.suspendedLanes = - this.pendingLanes = - 0; - this.entanglements = createLaneMap(0); - this.hiddenUpdates = createLaneMap(null); - this.identifierPrefix = identifierPrefix; - this.onRecoverableError = onRecoverableError; - this.incompleteTransitions = new Map(); -} -function createPortal$1(children, containerInfo, implementation) { - var key = - 3 < arguments.length && void 0 !== arguments[3] ? arguments[3] : null; + hostContext = nextReactTag; + nextReactTag += 2; return { - $$typeof: REACT_PORTAL_TYPE, - key: null == key ? null : "" + key, - children: children, - containerInfo: containerInfo, - implementation: implementation + node: createNode( + hostContext, + "RCTRawText", + rootContainerInstance, + { text: text }, + internalInstanceHandle + ) }; } -function findHostInstance(component) { - var fiber = component._reactInternals; - if (void 0 === fiber) { - if ("function" === typeof component.render) - throw Error("Unable to find node on an unmounted component."); - component = Object.keys(component).join(","); - throw Error( - "Argument appears to not be a ReactComponent. Keys: " + component - ); - } - component = findCurrentHostFiber(fiber); - return null === component ? null : getPublicInstance(component.stateNode); +function getPublicInstance(instance) { + return null != instance.canonical && null != instance.canonical.publicInstance + ? instance.canonical.publicInstance + : null != instance._nativeTag + ? instance + : null; } -function updateContainer(element, container, parentComponent, callback) { - var current = container.current, - lane = requestUpdateLane(current); - a: if (parentComponent) { - parentComponent = parentComponent._reactInternals; - b: { - if ( - getNearestMountedFiber(parentComponent) !== parentComponent || - 1 !== parentComponent.tag - ) - throw 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 JSCompiler_inline_result = parentComponent; - do { - switch (JSCompiler_inline_result.tag) { - case 3: - JSCompiler_inline_result = - JSCompiler_inline_result.stateNode.context; - break b; - case 1: - if (isContextProvider(JSCompiler_inline_result.type)) { - JSCompiler_inline_result = - JSCompiler_inline_result.stateNode - .__reactInternalMemoizedMergedChildContext; - break b; - } - } - JSCompiler_inline_result = JSCompiler_inline_result.return; - } while (null !== JSCompiler_inline_result); - throw Error( - "Found unexpected detached subtree parent. This error is likely caused by a bug in React. Please file an issue." - ); - } - if (1 === parentComponent.tag) { - var Component = parentComponent.type; - if (isContextProvider(Component)) { - parentComponent = processChildContext( - parentComponent, - Component, - JSCompiler_inline_result - ); - break a; - } - } - parentComponent = JSCompiler_inline_result; - } else parentComponent = emptyContextObject; - null === container.context - ? (container.context = parentComponent) - : (container.pendingContext = parentComponent); - container = createUpdate(lane); - container.payload = { element: element }; - callback = void 0 === callback ? null : callback; - null !== callback && (container.callback = callback); - element = enqueueUpdate(current, container, lane); - null !== element && - ((callback = requestEventTime()), - scheduleUpdateOnFiber(element, current, lane, callback), - entangleTransitions(element, current, lane)); - return lane; +var scheduleTimeout = setTimeout, + cancelTimeout = clearTimeout; +function cloneHiddenInstance(instance) { + var node = instance.node; + var JSCompiler_inline_result = diffProperties( + null, + emptyObject$1, + { style: { display: "none" } }, + instance.canonical.viewConfig.validAttributes + ); + return { + node: cloneNodeWithNewProps(node, JSCompiler_inline_result), + canonical: instance.canonical + }; } -function emptyFindFiberByHostInstance() { - return null; +function getInstanceFromNode(node) { + return null != node.canonical && null != node.canonical.internalInstanceHandle + ? node.canonical.internalInstanceHandle + : node; } -var emptyObject = {}, - createHierarchy, - getHostNode, - getHostProps, - lastNonHostInstance; -exports.getInspectorDataForInstance = void 0; -var getOwnerHierarchy, traverseOwnerTreeUp; -createHierarchy = function (fiberHierarchy) { - return fiberHierarchy.map(function (fiber) { +getFiberCurrentPropsFromNode$1 = function (instance) { + return instance.canonical.currentProps; +}; +getInstanceFromNode$1 = getInstanceFromNode; +getNodeFromInstance$1 = function (fiber) { + fiber = getPublicInstance(fiber.stateNode); + if (null == fiber) throw Error("Could not find host instance from fiber"); + return fiber; +}; +ResponderEventPlugin.injection.injectGlobalResponderHandler({ + onChange: function (from, to, blockNativeResponder) { + from && + from.stateNode && + nativeFabricUIManager.setIsJSResponder( + from.stateNode.node, + !1, + blockNativeResponder || !1 + ); + to && + to.stateNode && + nativeFabricUIManager.setIsJSResponder( + to.stateNode.node, + !0, + blockNativeResponder || !1 + ); + } +}); +var emptyObject = {}; +function createHierarchy(fiberHierarchy) { + return fiberHierarchy.map(function (fiber$jscomp$0) { return { - name: getComponentNameFromType(fiber.type), + name: getComponentNameFromType(fiber$jscomp$0.type), getInspectorData: function (findNodeHandle) { return { - props: getHostProps(fiber), - source: fiber._debugSource, + props: getHostProps(fiber$jscomp$0), + source: fiber$jscomp$0._debugSource, measure: function (callback) { - var hostFiber = findCurrentHostFiber(fiber); + var hostFiber = findCurrentHostFiber(fiber$jscomp$0); if ( (hostFiber = null != hostFiber && @@ -9262,82 +9404,43 @@ createHierarchy = function (fiberHierarchy) { hostFiber.stateNode.node) ) nativeFabricUIManager.measure(hostFiber, callback); - else - return ReactNativePrivateInterface.UIManager.measure( - getHostNode(fiber, findNodeHandle), + else { + hostFiber = ReactNativePrivateInterface.UIManager; + var JSCompiler_temp_const = hostFiber.measure, + JSCompiler_inline_result; + a: { + for (var fiber = fiber$jscomp$0; fiber; ) { + null !== fiber.stateNode && + 5 === fiber.tag && + (JSCompiler_inline_result = findNodeHandle( + fiber.stateNode + )); + if (JSCompiler_inline_result) break a; + fiber = fiber.child; + } + JSCompiler_inline_result = null; + } + return JSCompiler_temp_const.call( + hostFiber, + JSCompiler_inline_result, callback ); + } } }; } }; }); -}; -getHostNode = function (fiber, findNodeHandle) { - for (var hostNode; fiber; ) { - null !== fiber.stateNode && - 5 === fiber.tag && - (hostNode = findNodeHandle(fiber.stateNode)); - if (hostNode) return hostNode; - fiber = fiber.child; - } - return null; -}; -getHostProps = function (fiber) { +} +function getHostProps(fiber) { return (fiber = findCurrentHostFiber(fiber)) ? fiber.memoizedProps || emptyObject : emptyObject; -}; -exports.getInspectorDataForInstance = function (closestInstance) { - if (!closestInstance) - return { - hierarchy: [], - props: emptyObject, - selectedIndex: null, - source: null - }; - closestInstance = findCurrentFiberUsingSlowPath(closestInstance); - var fiberHierarchy = getOwnerHierarchy(closestInstance); - closestInstance = lastNonHostInstance(fiberHierarchy); - var hierarchy = createHierarchy(fiberHierarchy), - props = getHostProps(closestInstance), - source = closestInstance._debugSource; - fiberHierarchy = fiberHierarchy.indexOf(closestInstance); - return { - closestInstance: closestInstance, - hierarchy: hierarchy, - props: props, - selectedIndex: fiberHierarchy, - source: source - }; -}; -getOwnerHierarchy = function (instance) { - var hierarchy = []; - traverseOwnerTreeUp(hierarchy, instance); - return hierarchy; -}; -lastNonHostInstance = function (hierarchy) { - for (var i = hierarchy.length - 1; 1 < i; i--) { - var instance = hierarchy[i]; - if (5 !== instance.tag) return instance; - } - return hierarchy[0]; -}; -traverseOwnerTreeUp = function (hierarchy, instance) { +} +function traverseOwnerTreeUp(hierarchy, instance) { instance && (hierarchy.unshift(instance), traverseOwnerTreeUp(hierarchy, instance._debugOwner)); -}; -function findNodeHandle(componentOrHandle) { - if (null == componentOrHandle) return null; - if ("number" === typeof componentOrHandle) return componentOrHandle; - if (componentOrHandle._nativeTag) return componentOrHandle._nativeTag; - if (componentOrHandle.canonical && componentOrHandle.canonical._nativeTag) - return componentOrHandle.canonical._nativeTag; - componentOrHandle = findHostInstance(componentOrHandle); - return null == componentOrHandle - ? componentOrHandle - : componentOrHandle._nativeTag; } function onRecoverableError(error) { console.error(error); @@ -9355,10 +9458,10 @@ batchedUpdatesImpl = function (fn, a) { } }; var roots = new Map(), - devToolsConfig$jscomp$inline_986 = { + devToolsConfig$jscomp$inline_1030 = { findFiberByHostInstance: getInstanceFromNode, bundleType: 0, - version: "18.3.0-next-ef8bdbecb-20230310", + version: "18.3.0-next-c57b90f50-20230320", rendererPackageName: "react-native-renderer", rendererConfig: { getInspectorDataForViewTag: function () { @@ -9373,11 +9476,11 @@ var roots = new Map(), }.bind(null, findNodeHandle) } }; -var internals$jscomp$inline_1227 = { - bundleType: devToolsConfig$jscomp$inline_986.bundleType, - version: devToolsConfig$jscomp$inline_986.version, - rendererPackageName: devToolsConfig$jscomp$inline_986.rendererPackageName, - rendererConfig: devToolsConfig$jscomp$inline_986.rendererConfig, +var internals$jscomp$inline_1277 = { + bundleType: devToolsConfig$jscomp$inline_1030.bundleType, + version: devToolsConfig$jscomp$inline_1030.version, + rendererPackageName: devToolsConfig$jscomp$inline_1030.rendererPackageName, + rendererConfig: devToolsConfig$jscomp$inline_1030.rendererConfig, overrideHookState: null, overrideHookStateDeletePath: null, overrideHookStateRenamePath: null, @@ -9393,26 +9496,26 @@ var internals$jscomp$inline_1227 = { return null === fiber ? null : fiber.stateNode; }, findFiberByHostInstance: - devToolsConfig$jscomp$inline_986.findFiberByHostInstance || + devToolsConfig$jscomp$inline_1030.findFiberByHostInstance || emptyFindFiberByHostInstance, findHostInstancesForRefresh: null, scheduleRefresh: null, scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "18.3.0-next-ef8bdbecb-20230310" + reconcilerVersion: "18.3.0-next-c57b90f50-20230320" }; if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { - var hook$jscomp$inline_1228 = __REACT_DEVTOOLS_GLOBAL_HOOK__; + var hook$jscomp$inline_1278 = __REACT_DEVTOOLS_GLOBAL_HOOK__; if ( - !hook$jscomp$inline_1228.isDisabled && - hook$jscomp$inline_1228.supportsFiber + !hook$jscomp$inline_1278.isDisabled && + hook$jscomp$inline_1278.supportsFiber ) try { - (rendererID = hook$jscomp$inline_1228.inject( - internals$jscomp$inline_1227 + (rendererID = hook$jscomp$inline_1278.inject( + internals$jscomp$inline_1277 )), - (injectedHook = hook$jscomp$inline_1228); + (injectedHook = hook$jscomp$inline_1278); } catch (err) {} } exports.createPortal = function (children, containerTag) { @@ -9424,13 +9527,16 @@ exports.createPortal = function (children, containerTag) { ); }; exports.dispatchCommand = function (handle, command, args) { - null != handle._nativeTag && - (null != handle._internalInstanceHandle - ? ((handle = handle._internalInstanceHandle.stateNode), - null != handle && - nativeFabricUIManager.dispatchCommand(handle.node, command, args)) + var nativeTag = + null != handle._nativeTag ? handle._nativeTag : handle.__nativeTag; + null != nativeTag && + ((handle = handle.__internalInstanceHandle), + null != handle + ? ((nativeTag = getNodeFromInternalInstanceHandle(handle)), + null != nativeTag && + nativeFabricUIManager.dispatchCommand(nativeTag, command, args)) : ReactNativePrivateInterface.UIManager.dispatchViewManagerCommand( - handle._nativeTag, + nativeTag, command, args )); @@ -9438,13 +9544,47 @@ exports.dispatchCommand = function (handle, command, args) { exports.findHostInstance_DEPRECATED = function (componentOrHandle) { return null == componentOrHandle ? null + : componentOrHandle.canonical && componentOrHandle.canonical.publicInstance + ? componentOrHandle.canonical.publicInstance : componentOrHandle._nativeTag ? componentOrHandle - : componentOrHandle.canonical && componentOrHandle.canonical._nativeTag - ? componentOrHandle.canonical : findHostInstance(componentOrHandle); }; exports.findNodeHandle = findNodeHandle; +exports.getInspectorDataForInstance = function (closestInstance) { + if (!closestInstance) + return { + hierarchy: [], + props: emptyObject, + selectedIndex: null, + source: null + }; + var fiber = findCurrentFiberUsingSlowPath(closestInstance); + closestInstance = []; + traverseOwnerTreeUp(closestInstance, fiber); + a: { + for (fiber = closestInstance.length - 1; 1 < fiber; fiber--) { + var instance = closestInstance[fiber]; + if (5 !== instance.tag) { + fiber = instance; + break a; + } + } + fiber = closestInstance[0]; + } + instance = createHierarchy(closestInstance); + var props = getHostProps(fiber), + source = fiber._debugSource; + closestInstance = closestInstance.indexOf(fiber); + return { + closestInstance: fiber, + hierarchy: instance, + props: props, + selectedIndex: closestInstance, + source: source + }; +}; +exports.getNodeFromInternalInstanceHandle = getNodeFromInternalInstanceHandle; exports.render = function (element, containerTag, callback, concurrentRoot) { var root = roots.get(containerTag); root || @@ -9477,13 +9617,16 @@ exports.render = function (element, containerTag, callback, concurrentRoot) { return element; }; exports.sendAccessibilityEvent = function (handle, eventType) { - null != handle._nativeTag && - (null != handle._internalInstanceHandle - ? ((handle = handle._internalInstanceHandle.stateNode), - null != handle && - nativeFabricUIManager.sendAccessibilityEvent(handle.node, eventType)) + var nativeTag = + null != handle._nativeTag ? handle._nativeTag : handle.__nativeTag; + null != nativeTag && + ((handle = handle.__internalInstanceHandle), + null != handle + ? ((nativeTag = getNodeFromInternalInstanceHandle(handle)), + null != nativeTag && + nativeFabricUIManager.sendAccessibilityEvent(nativeTag, eventType)) : ReactNativePrivateInterface.legacySendAccessibilityEvent( - handle._nativeTag, + nativeTag, eventType )); }; diff --git a/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactFabric-profiling.fb.js b/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactFabric-profiling.fb.js index 9067865d620d8..7dd91873fdb18 100644 --- a/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactFabric-profiling.fb.js +++ b/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactFabric-profiling.fb.js @@ -24,9 +24,9 @@ if ( "use strict"; require("react-native/Libraries/ReactPrivate/ReactNativePrivateInitializeCore"); var ReactNativePrivateInterface = require("react-native/Libraries/ReactPrivate/ReactNativePrivateInterface"), + React = require("react"), dynamicFlags = require("ReactNativeInternalFeatureFlags"), - Scheduler = require("scheduler"), - React = require("react"); + Scheduler = require("scheduler"); function invokeGuardedCallbackImpl(name, func, context) { var funcArgs = Array.prototype.slice.call(arguments, 3); try { @@ -951,7 +951,7 @@ eventPluginOrder = Array.prototype.slice.call([ "ReactNativeBridgeEventPlugin" ]); recomputePluginOrdering(); -var injectedNamesToPlugins$jscomp$inline_248 = { +var injectedNamesToPlugins$jscomp$inline_257 = { ResponderEventPlugin: ResponderEventPlugin, ReactNativeBridgeEventPlugin: { eventTypes: {}, @@ -997,32 +997,32 @@ var injectedNamesToPlugins$jscomp$inline_248 = { } } }, - isOrderingDirty$jscomp$inline_249 = !1, - pluginName$jscomp$inline_250; -for (pluginName$jscomp$inline_250 in injectedNamesToPlugins$jscomp$inline_248) + isOrderingDirty$jscomp$inline_258 = !1, + pluginName$jscomp$inline_259; +for (pluginName$jscomp$inline_259 in injectedNamesToPlugins$jscomp$inline_257) if ( - injectedNamesToPlugins$jscomp$inline_248.hasOwnProperty( - pluginName$jscomp$inline_250 + injectedNamesToPlugins$jscomp$inline_257.hasOwnProperty( + pluginName$jscomp$inline_259 ) ) { - var pluginModule$jscomp$inline_251 = - injectedNamesToPlugins$jscomp$inline_248[pluginName$jscomp$inline_250]; + var pluginModule$jscomp$inline_260 = + injectedNamesToPlugins$jscomp$inline_257[pluginName$jscomp$inline_259]; if ( - !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_250) || - namesToPlugins[pluginName$jscomp$inline_250] !== - pluginModule$jscomp$inline_251 + !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_259) || + namesToPlugins[pluginName$jscomp$inline_259] !== + pluginModule$jscomp$inline_260 ) { - if (namesToPlugins[pluginName$jscomp$inline_250]) + if (namesToPlugins[pluginName$jscomp$inline_259]) throw Error( "EventPluginRegistry: Cannot inject two different event plugins using the same name, `" + - (pluginName$jscomp$inline_250 + "`.") + (pluginName$jscomp$inline_259 + "`.") ); - namesToPlugins[pluginName$jscomp$inline_250] = - pluginModule$jscomp$inline_251; - isOrderingDirty$jscomp$inline_249 = !0; + namesToPlugins[pluginName$jscomp$inline_259] = + pluginModule$jscomp$inline_260; + isOrderingDirty$jscomp$inline_258 = !0; } } -isOrderingDirty$jscomp$inline_249 && recomputePluginOrdering(); +isOrderingDirty$jscomp$inline_258 && recomputePluginOrdering(); var emptyObject$1 = {}, removedKeys = null, removedKeyCount = 0, @@ -1246,181 +1246,367 @@ function diffProperties(updatePayload, prevProps, nextProps, validAttributes) { ))))); return updatePayload; } -function batchedUpdatesImpl(fn, bookkeeping) { - return fn(bookkeeping); -} -var isInsideEventHandler = !1; -function batchedUpdates$1(fn, bookkeeping) { - if (isInsideEventHandler) return fn(bookkeeping); - isInsideEventHandler = !0; - try { - return batchedUpdatesImpl(fn, bookkeeping); - } finally { - isInsideEventHandler = !1; - } -} -var eventQueue = null; -function executeDispatchesAndReleaseTopLevel(e) { - if (e) { - var dispatchListeners = e._dispatchListeners, - dispatchInstances = e._dispatchInstances; - if (isArrayImpl(dispatchListeners)) - for ( - var i = 0; - i < dispatchListeners.length && !e.isPropagationStopped(); - i++ - ) - executeDispatch(e, dispatchListeners[i], dispatchInstances[i]); - else - dispatchListeners && - executeDispatch(e, dispatchListeners, dispatchInstances); - e._dispatchListeners = null; - e._dispatchInstances = null; - e.isPersistent() || e.constructor.release(e); - } +var ReactSharedInternals = + React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, + enableUseRefAccessWarning = dynamicFlags.enableUseRefAccessWarning, + REACT_ELEMENT_TYPE = Symbol.for("react.element"), + REACT_PORTAL_TYPE = Symbol.for("react.portal"), + REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"), + REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"), + REACT_PROFILER_TYPE = Symbol.for("react.profiler"), + REACT_PROVIDER_TYPE = Symbol.for("react.provider"), + REACT_CONTEXT_TYPE = Symbol.for("react.context"), + REACT_SERVER_CONTEXT_TYPE = Symbol.for("react.server_context"), + REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"), + REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"), + REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"), + REACT_MEMO_TYPE = Symbol.for("react.memo"), + REACT_LAZY_TYPE = Symbol.for("react.lazy"); +Symbol.for("react.scope"); +Symbol.for("react.debug_trace_mode"); +var REACT_OFFSCREEN_TYPE = Symbol.for("react.offscreen"), + REACT_LEGACY_HIDDEN_TYPE = Symbol.for("react.legacy_hidden"); +Symbol.for("react.cache"); +Symbol.for("react.tracing_marker"); +var REACT_SERVER_CONTEXT_DEFAULT_VALUE_NOT_LOADED = Symbol.for( + "react.default_value" + ), + REACT_MEMO_CACHE_SENTINEL = Symbol.for("react.memo_cache_sentinel"), + MAYBE_ITERATOR_SYMBOL = Symbol.iterator; +function getIteratorFn(maybeIterable) { + if (null === maybeIterable || "object" !== typeof maybeIterable) return null; + maybeIterable = + (MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL]) || + maybeIterable["@@iterator"]; + return "function" === typeof maybeIterable ? maybeIterable : null; } -function dispatchEvent(target, topLevelType, nativeEvent) { - var eventTarget = null; - if (null != target) { - var stateNode = target.stateNode; - null != stateNode && (eventTarget = getPublicInstance(stateNode)); +function getComponentNameFromType(type) { + if (null == type) return null; + if ("function" === typeof type) return type.displayName || type.name || null; + if ("string" === typeof type) 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"; } - batchedUpdates$1(function () { - var event = { eventName: topLevelType, nativeEvent: nativeEvent }; - ReactNativePrivateInterface.RawEventEmitter.emit(topLevelType, event); - ReactNativePrivateInterface.RawEventEmitter.emit("*", event); - event = eventTarget; - for ( - var events = null, legacyPlugins = plugins, i = 0; - i < legacyPlugins.length; - i++ - ) { - var possiblePlugin = legacyPlugins[i]; - possiblePlugin && - (possiblePlugin = possiblePlugin.extractEvents( - topLevelType, - target, - nativeEvent, - event - )) && - (events = accumulateInto(events, possiblePlugin)); - } - event = events; - null !== event && (eventQueue = accumulateInto(eventQueue, event)); - event = eventQueue; - eventQueue = null; - if (event) { - forEachAccumulated(event, executeDispatchesAndReleaseTopLevel); - if (eventQueue) - throw Error( - "processEventQueue(): Additional events were enqueued while processing an event queue. Support for this has not yet been implemented." - ); - if (hasRethrowError) - throw ( - ((event = rethrowError), - (hasRethrowError = !1), - (rethrowError = null), - event) + if ("object" === typeof type) + switch (type.$$typeof) { + case REACT_CONTEXT_TYPE: + return (type.displayName || "Context") + ".Consumer"; + case REACT_PROVIDER_TYPE: + return (type._context.displayName || "Context") + ".Provider"; + case REACT_FORWARD_REF_TYPE: + var innerType = type.render; + type = type.displayName; + type || + ((type = innerType.displayName || innerType.name || ""), + (type = "" !== type ? "ForwardRef(" + type + ")" : "ForwardRef")); + return type; + case REACT_MEMO_TYPE: + return ( + (innerType = type.displayName || null), + null !== innerType + ? innerType + : getComponentNameFromType(type.type) || "Memo" ); + case REACT_LAZY_TYPE: + innerType = type._payload; + type = type._init; + try { + return getComponentNameFromType(type(innerType)); + } catch (x) { + break; + } + case REACT_SERVER_CONTEXT_TYPE: + return (type.displayName || type._globalName) + ".Provider"; } - }); + return null; } -var enableUseRefAccessWarning = dynamicFlags.enableUseRefAccessWarning, - scheduleCallback$1 = Scheduler.unstable_scheduleCallback, - cancelCallback$1 = Scheduler.unstable_cancelCallback, - shouldYield = Scheduler.unstable_shouldYield, - requestPaint = Scheduler.unstable_requestPaint, - now$1 = Scheduler.unstable_now, - ImmediatePriority = Scheduler.unstable_ImmediatePriority, - UserBlockingPriority = Scheduler.unstable_UserBlockingPriority, - NormalPriority = Scheduler.unstable_NormalPriority, - IdlePriority = Scheduler.unstable_IdlePriority, - ReactSharedInternals = - React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, - rendererID = null, - injectedHook = null, - injectedProfilingHooks = null, - isDevToolsPresent = "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__; -function onCommitRoot(root, eventPriority) { - if (injectedHook && "function" === typeof injectedHook.onCommitFiberRoot) - try { - var didError = 128 === (root.current.flags & 128); - switch (eventPriority) { - case 2: - var schedulerPriority = ImmediatePriority; - break; - case 8: - schedulerPriority = UserBlockingPriority; - break; - case 32: - schedulerPriority = NormalPriority; - break; - case 536870912: - schedulerPriority = IdlePriority; - break; - default: - schedulerPriority = NormalPriority; - } - injectedHook.onCommitFiberRoot( - rendererID, - root, - schedulerPriority, - didError +function getComponentNameFromFiber(fiber) { + var type = fiber.type; + switch (fiber.tag) { + case 24: + return "Cache"; + case 9: + return (type.displayName || "Context") + ".Consumer"; + case 10: + return (type._context.displayName || "Context") + ".Provider"; + case 18: + return "DehydratedFragment"; + case 11: + return ( + (fiber = type.render), + (fiber = fiber.displayName || fiber.name || ""), + type.displayName || + ("" !== fiber ? "ForwardRef(" + fiber + ")" : "ForwardRef") ); - } catch (err) {} -} -function injectProfilingHooks(profilingHooks) { - injectedProfilingHooks = profilingHooks; -} -function getLaneLabelMap() { - for (var map = new Map(), lane = 1, index$2 = 0; 31 > index$2; index$2++) { - var label = getLabelForLane(lane); - map.set(lane, label); - lane *= 2; + case 7: + return "Fragment"; + case 26: + case 27: + case 5: + return type; + case 4: + return "Portal"; + case 3: + return "Root"; + case 6: + return "Text"; + case 16: + return getComponentNameFromType(type); + case 8: + return type === REACT_STRICT_MODE_TYPE ? "StrictMode" : "Mode"; + case 22: + return "Offscreen"; + case 12: + return "Profiler"; + case 21: + return "Scope"; + case 13: + return "Suspense"; + case 19: + return "SuspenseList"; + case 25: + return "TracingMarker"; + case 1: + case 0: + case 17: + case 2: + case 14: + case 15: + if ("function" === typeof type) + return type.displayName || type.name || null; + if ("string" === typeof type) return type; + break; + case 23: + return "LegacyHidden"; } - return map; + return null; } -function markCommitStopped() { - null !== injectedProfilingHooks && - "function" === typeof injectedProfilingHooks.markCommitStopped && - injectedProfilingHooks.markCommitStopped(); +function getNearestMountedFiber(fiber) { + var node = fiber, + nearestMounted = fiber; + if (fiber.alternate) for (; node.return; ) node = node.return; + else { + fiber = node; + do + (node = fiber), + 0 !== (node.flags & 4098) && (nearestMounted = node.return), + (fiber = node.return); + while (fiber); + } + return 3 === node.tag ? nearestMounted : null; } -function markComponentRenderStarted(fiber) { - null !== injectedProfilingHooks && - "function" === typeof injectedProfilingHooks.markComponentRenderStarted && - injectedProfilingHooks.markComponentRenderStarted(fiber); +function assertIsMounted(fiber) { + if (getNearestMountedFiber(fiber) !== fiber) + throw Error("Unable to find node on an unmounted component."); } -function markComponentRenderStopped() { - null !== injectedProfilingHooks && - "function" === typeof injectedProfilingHooks.markComponentRenderStopped && - injectedProfilingHooks.markComponentRenderStopped(); +function findCurrentFiberUsingSlowPath(fiber) { + var alternate = fiber.alternate; + if (!alternate) { + alternate = getNearestMountedFiber(fiber); + if (null === alternate) + throw Error("Unable to find node on an unmounted component."); + return alternate !== fiber ? null : fiber; + } + for (var a = fiber, b = alternate; ; ) { + var parentA = a.return; + if (null === parentA) break; + var parentB = parentA.alternate; + if (null === parentB) { + b = parentA.return; + if (null !== b) { + a = b; + continue; + } + break; + } + if (parentA.child === parentB.child) { + for (parentB = parentA.child; parentB; ) { + if (parentB === a) return assertIsMounted(parentA), fiber; + if (parentB === b) return assertIsMounted(parentA), alternate; + parentB = parentB.sibling; + } + throw Error("Unable to find node on an unmounted component."); + } + if (a.return !== b.return) (a = parentA), (b = parentB); + else { + for (var didFindChild = !1, child$2 = parentA.child; child$2; ) { + if (child$2 === a) { + didFindChild = !0; + a = parentA; + b = parentB; + break; + } + if (child$2 === b) { + didFindChild = !0; + b = parentA; + a = parentB; + break; + } + child$2 = child$2.sibling; + } + if (!didFindChild) { + for (child$2 = parentB.child; child$2; ) { + if (child$2 === a) { + didFindChild = !0; + a = parentB; + b = parentA; + break; + } + if (child$2 === b) { + didFindChild = !0; + b = parentB; + a = parentA; + break; + } + child$2 = child$2.sibling; + } + if (!didFindChild) + throw Error( + "Child was not found in either parent set. This indicates a bug in React related to the return pointer. Please file an issue." + ); + } + } + if (a.alternate !== b) + throw Error( + "Return fibers should always be each others' alternates. This error is likely caused by a bug in React. Please file an issue." + ); + } + if (3 !== a.tag) + throw Error("Unable to find node on an unmounted component."); + return a.stateNode.current === a ? fiber : alternate; } -function markComponentLayoutEffectUnmountStarted(fiber) { - null !== injectedProfilingHooks && - "function" === - typeof injectedProfilingHooks.markComponentLayoutEffectUnmountStarted && - injectedProfilingHooks.markComponentLayoutEffectUnmountStarted(fiber); +function findCurrentHostFiber(parent) { + parent = findCurrentFiberUsingSlowPath(parent); + return null !== parent ? findCurrentHostFiberImpl(parent) : null; } -function markComponentLayoutEffectUnmountStopped() { - null !== injectedProfilingHooks && - "function" === - typeof injectedProfilingHooks.markComponentLayoutEffectUnmountStopped && - injectedProfilingHooks.markComponentLayoutEffectUnmountStopped(); +function findCurrentHostFiberImpl(node) { + var tag = node.tag; + if (5 === tag || 26 === tag || 27 === tag || 6 === tag) return node; + for (node = node.child; null !== node; ) { + tag = findCurrentHostFiberImpl(node); + if (null !== tag) return tag; + node = node.sibling; + } + return null; } -function markRenderStarted(lanes) { - null !== injectedProfilingHooks && - "function" === typeof injectedProfilingHooks.markRenderStarted && - injectedProfilingHooks.markRenderStarted(lanes); +function describeComponentFrame(name, source, ownerName) { + source = ""; + ownerName && (source = " (created by " + ownerName + ")"); + return "\n in " + (name || "Unknown") + source; } -function markRenderStopped() { - null !== injectedProfilingHooks && - "function" === typeof injectedProfilingHooks.markRenderStopped && - injectedProfilingHooks.markRenderStopped(); +function describeFunctionComponentFrame(fn, source) { + return fn + ? describeComponentFrame(fn.displayName || fn.name || null, source, null) + : ""; } -function markStateUpdateScheduled(fiber, lane) { - null !== injectedProfilingHooks && - "function" === typeof injectedProfilingHooks.markStateUpdateScheduled && - injectedProfilingHooks.markStateUpdateScheduled(fiber, lane); +var hasOwnProperty = Object.prototype.hasOwnProperty, + valueStack = [], + index = -1; +function createCursor(defaultValue) { + return { current: defaultValue }; +} +function pop(cursor) { + 0 > index || + ((cursor.current = valueStack[index]), (valueStack[index] = null), index--); +} +function push(cursor, value) { + index++; + valueStack[index] = cursor.current; + cursor.current = value; +} +var emptyContextObject = {}, + contextStackCursor$1 = createCursor(emptyContextObject), + didPerformWorkStackCursor = createCursor(!1), + previousContext = emptyContextObject; +function getMaskedContext(workInProgress, unmaskedContext) { + var contextTypes = workInProgress.type.contextTypes; + if (!contextTypes) return emptyContextObject; + var instance = workInProgress.stateNode; + if ( + instance && + instance.__reactInternalMemoizedUnmaskedChildContext === unmaskedContext + ) + return instance.__reactInternalMemoizedMaskedChildContext; + var context = {}, + key; + for (key in contextTypes) context[key] = unmaskedContext[key]; + instance && + ((workInProgress = workInProgress.stateNode), + (workInProgress.__reactInternalMemoizedUnmaskedChildContext = + unmaskedContext), + (workInProgress.__reactInternalMemoizedMaskedChildContext = context)); + return context; +} +function isContextProvider(type) { + type = type.childContextTypes; + return null !== type && void 0 !== type; +} +function popContext() { + pop(didPerformWorkStackCursor); + pop(contextStackCursor$1); +} +function pushTopLevelContextObject(fiber, context, didChange) { + if (contextStackCursor$1.current !== emptyContextObject) + throw Error( + "Unexpected context found on stack. This error is likely caused by a bug in React. Please file an issue." + ); + push(contextStackCursor$1, context); + push(didPerformWorkStackCursor, didChange); +} +function processChildContext(fiber, type, parentContext) { + var instance = fiber.stateNode; + type = type.childContextTypes; + if ("function" !== typeof instance.getChildContext) return parentContext; + instance = instance.getChildContext(); + for (var contextKey in instance) + if (!(contextKey in type)) + throw Error( + (getComponentNameFromFiber(fiber) || "Unknown") + + '.getChildContext(): key "' + + contextKey + + '" is not defined in childContextTypes.' + ); + return assign({}, parentContext, instance); +} +function pushContextProvider(workInProgress) { + workInProgress = + ((workInProgress = workInProgress.stateNode) && + workInProgress.__reactInternalMemoizedMergedChildContext) || + emptyContextObject; + previousContext = contextStackCursor$1.current; + push(contextStackCursor$1, workInProgress); + push(didPerformWorkStackCursor, didPerformWorkStackCursor.current); + return !0; +} +function invalidateContextProvider(workInProgress, type, didChange) { + var instance = workInProgress.stateNode; + if (!instance) + throw Error( + "Expected to have an instance by this point. This error is likely caused by a bug in React. Please file an issue." + ); + didChange + ? ((workInProgress = processChildContext( + workInProgress, + type, + previousContext + )), + (instance.__reactInternalMemoizedMergedChildContext = workInProgress), + pop(didPerformWorkStackCursor), + pop(contextStackCursor$1), + push(contextStackCursor$1, workInProgress)) + : pop(didPerformWorkStackCursor); + push(didPerformWorkStackCursor, didChange); } var clz32 = Math.clz32 ? Math.clz32 : clz32Fallback, log = Math.log, @@ -1527,705 +1713,266 @@ function getNextLanes(root, wipLanes) { (32 === suspendedLanes && 0 !== (pingedLanes & 8388480))) ) return wipLanes; - 0 === (root.current.mode & 32) && - 0 !== (nextLanes & 8) && - (nextLanes |= pendingLanes & 32); - wipLanes = root.entangledLanes; - if (0 !== wipLanes) - for (root = root.entanglements, wipLanes &= nextLanes; 0 < wipLanes; ) - (pendingLanes = 31 - clz32(wipLanes)), - (suspendedLanes = 1 << pendingLanes), - (nextLanes |= root[pendingLanes]), - (wipLanes &= ~suspendedLanes); - return nextLanes; -} -function computeExpirationTime(lane, currentTime) { - switch (lane) { - case 1: - case 2: - case 4: - case 8: - return currentTime + 250; - case 16: - case 32: - case 64: - case 128: - case 256: - case 512: - case 1024: - case 2048: - case 4096: - case 8192: - case 16384: - case 32768: - case 65536: - case 131072: - case 262144: - case 524288: - case 1048576: - case 2097152: - case 4194304: - return currentTime + 5e3; - case 8388608: - case 16777216: - case 33554432: - case 67108864: - return -1; - case 134217728: - case 268435456: - case 536870912: - case 1073741824: - return -1; - default: - return -1; - } -} -function getLanesToRetrySynchronouslyOnError(root, originallyAttemptedLanes) { - if (root.errorRecoveryDisabledLanes & originallyAttemptedLanes) return 0; - root = root.pendingLanes & -1073741825; - return 0 !== root ? root : root & 1073741824 ? 1073741824 : 0; -} -function includesBlockingLane(root, lanes) { - return 0 !== (root.current.mode & 32) ? !1 : 0 !== (lanes & 60); -} -function claimNextTransitionLane() { - var lane = nextTransitionLane; - nextTransitionLane <<= 1; - 0 === (nextTransitionLane & 8388480) && (nextTransitionLane = 128); - return lane; -} -function createLaneMap(initial) { - for (var laneMap = [], i = 0; 31 > i; i++) laneMap.push(initial); - return laneMap; -} -function markRootUpdated(root, updateLane, eventTime) { - root.pendingLanes |= updateLane; - 536870912 !== updateLane && - ((root.suspendedLanes = 0), (root.pingedLanes = 0)); - root = root.eventTimes; - updateLane = 31 - clz32(updateLane); - root[updateLane] = eventTime; -} -function markRootFinished(root, remainingLanes) { - var noLongerPendingLanes = root.pendingLanes & ~remainingLanes; - root.pendingLanes = remainingLanes; - root.suspendedLanes = 0; - root.pingedLanes = 0; - root.expiredLanes &= remainingLanes; - root.mutableReadLanes &= remainingLanes; - root.entangledLanes &= remainingLanes; - root.errorRecoveryDisabledLanes &= remainingLanes; - remainingLanes = root.entanglements; - var eventTimes = root.eventTimes, - expirationTimes = root.expirationTimes; - for (root = root.hiddenUpdates; 0 < noLongerPendingLanes; ) { - var index$7 = 31 - clz32(noLongerPendingLanes), - lane = 1 << index$7; - remainingLanes[index$7] = 0; - eventTimes[index$7] = -1; - expirationTimes[index$7] = -1; - var hiddenUpdatesForLane = root[index$7]; - if (null !== hiddenUpdatesForLane) - for ( - root[index$7] = null, index$7 = 0; - index$7 < hiddenUpdatesForLane.length; - index$7++ - ) { - var update = hiddenUpdatesForLane[index$7]; - null !== update && (update.lane &= -1073741825); - } - noLongerPendingLanes &= ~lane; - } -} -function markRootEntangled(root, entangledLanes) { - var rootEntangledLanes = (root.entangledLanes |= entangledLanes); - for (root = root.entanglements; rootEntangledLanes; ) { - var index$8 = 31 - clz32(rootEntangledLanes), - lane = 1 << index$8; - (lane & entangledLanes) | (root[index$8] & entangledLanes) && - (root[index$8] |= entangledLanes); - rootEntangledLanes &= ~lane; - } -} -function addFiberToLanesMap(root, fiber, lanes) { - if (isDevToolsPresent) - for (root = root.pendingUpdatersLaneMap; 0 < lanes; ) { - var index$9 = 31 - clz32(lanes), - lane = 1 << index$9; - root[index$9].add(fiber); - lanes &= ~lane; - } -} -function movePendingFibersToMemoized(root, lanes) { - if (isDevToolsPresent) - for ( - var pendingUpdatersLaneMap = root.pendingUpdatersLaneMap, - memoizedUpdaters = root.memoizedUpdaters; - 0 < lanes; - - ) { - var index$10 = 31 - clz32(lanes); - root = 1 << index$10; - index$10 = pendingUpdatersLaneMap[index$10]; - 0 < index$10.size && - (index$10.forEach(function (fiber) { - var alternate = fiber.alternate; - (null !== alternate && memoizedUpdaters.has(alternate)) || - memoizedUpdaters.add(fiber); - }), - index$10.clear()); - lanes &= ~root; - } -} -var currentUpdatePriority = 0; -function lanesToEventPriority(lanes) { - lanes &= -lanes; - return 2 < lanes - ? 8 < lanes - ? 0 !== (lanes & 268435455) - ? 32 - : 536870912 - : 8 - : 2; -} -function shim() { - throw Error( - "The current renderer does not support hydration. This error is likely caused by a bug in React. Please file an issue." - ); -} -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, - FabricDiscretePriority = _nativeFabricUIManage.unstable_DiscreteEventPriority, - fabricGetCurrentEventPriority = - _nativeFabricUIManage.unstable_getCurrentEventPriority, - _setNativeProps = _nativeFabricUIManage.setNativeProps, - fabricGetBoundingClientRect = _nativeFabricUIManage.getBoundingClientRect, - getViewConfigForType = - ReactNativePrivateInterface.ReactNativeViewConfigRegistry.get, - nextReactTag = 2; -registerEventHandler && registerEventHandler(dispatchEvent); -function noop$1() {} -var ReactFabricHostComponent = (function () { - function ReactFabricHostComponent( - tag, - viewConfig, - props, - internalInstanceHandle - ) { - this.viewConfig = void 0; - this._nativeTag = tag; - this.viewConfig = viewConfig; - this.currentProps = props; - this._internalInstanceHandle = internalInstanceHandle; - } - var _proto = ReactFabricHostComponent.prototype; - _proto.blur = function () { - ReactNativePrivateInterface.TextInputState.blurTextInput(this); - }; - _proto.focus = function () { - ReactNativePrivateInterface.TextInputState.focusTextInput(this); - }; - _proto.measure = function (callback) { - var node = getShadowNodeFromInternalInstanceHandle( - this._internalInstanceHandle - ); - null != node && fabricMeasure(node, callback); - }; - _proto.measureInWindow = function (callback) { - var node = getShadowNodeFromInternalInstanceHandle( - this._internalInstanceHandle - ); - null != node && fabricMeasureInWindow(node, callback); - }; - _proto.measureLayout = function (relativeToNativeNode, onSuccess, onFail) { - if ( - "number" !== typeof relativeToNativeNode && - relativeToNativeNode instanceof ReactFabricHostComponent - ) { - var toStateNode = getShadowNodeFromInternalInstanceHandle( - this._internalInstanceHandle - ); - relativeToNativeNode = getShadowNodeFromInternalInstanceHandle( - relativeToNativeNode._internalInstanceHandle - ); - null != toStateNode && - null != relativeToNativeNode && - fabricMeasureLayout( - toStateNode, - relativeToNativeNode, - null != onFail ? onFail : noop$1, - null != onSuccess ? onSuccess : noop$1 - ); - } - }; - _proto.unstable_getBoundingClientRect = function () { - var node = getShadowNodeFromInternalInstanceHandle( - this._internalInstanceHandle - ); - return null != node && (node = fabricGetBoundingClientRect(node)) - ? new DOMRect(node[0], node[1], node[2], node[3]) - : new DOMRect(0, 0, 0, 0); - }; - _proto.setNativeProps = function (nativeProps) { - nativeProps = diffProperties( - null, - emptyObject$1, - nativeProps, - this.viewConfig.validAttributes - ); - var node = getShadowNodeFromInternalInstanceHandle( - this._internalInstanceHandle - ); - null != node && null != nativeProps && _setNativeProps(node, nativeProps); - }; - return ReactFabricHostComponent; -})(); -function getShadowNodeFromInternalInstanceHandle(internalInstanceHandle) { - return ( - internalInstanceHandle && - internalInstanceHandle.stateNode && - internalInstanceHandle.stateNode.node - ); -} -function createTextInstance( - text, - rootContainerInstance, - hostContext, - internalInstanceHandle -) { - hostContext = nextReactTag; - nextReactTag += 2; - return { - node: createNode( - hostContext, - "RCTRawText", - rootContainerInstance, - { text: text }, - internalInstanceHandle - ) - }; -} -function getPublicInstance(instance) { - return instance.canonical - ? instance.canonical - : null != instance._nativeTag - ? instance - : null; -} -var scheduleTimeout = setTimeout, - cancelTimeout = clearTimeout; -function cloneHiddenInstance(instance) { - var node = instance.node; - var JSCompiler_inline_result = diffProperties( - null, - emptyObject$1, - { style: { display: "none" } }, - instance.canonical.viewConfig.validAttributes - ); - return { - node: cloneNodeWithNewProps(node, JSCompiler_inline_result), - canonical: instance.canonical - }; -} -function getInstanceFromNode(node) { - return node; -} -getFiberCurrentPropsFromNode$1 = function (instance) { - return instance.canonical.currentProps; -}; -getInstanceFromNode$1 = getInstanceFromNode; -getNodeFromInstance$1 = function (fiber) { - fiber = getPublicInstance(fiber.stateNode); - if (null == fiber) throw Error("Could not find host instance from fiber"); - return fiber; -}; -ResponderEventPlugin.injection.injectGlobalResponderHandler({ - onChange: function (from, to, blockNativeResponder) { - from && - nativeFabricUIManager.setIsJSResponder( - from.stateNode.node, - !1, - blockNativeResponder || !1 - ); - to && - nativeFabricUIManager.setIsJSResponder( - to.stateNode.node, - !0, - blockNativeResponder || !1 - ); - } -}); -var REACT_ELEMENT_TYPE = Symbol.for("react.element"), - REACT_PORTAL_TYPE = Symbol.for("react.portal"), - REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"), - REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"), - REACT_PROFILER_TYPE = Symbol.for("react.profiler"), - REACT_PROVIDER_TYPE = Symbol.for("react.provider"), - REACT_CONTEXT_TYPE = Symbol.for("react.context"), - REACT_SERVER_CONTEXT_TYPE = Symbol.for("react.server_context"), - REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"), - REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"), - REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"), - REACT_MEMO_TYPE = Symbol.for("react.memo"), - REACT_LAZY_TYPE = Symbol.for("react.lazy"); -Symbol.for("react.scope"); -Symbol.for("react.debug_trace_mode"); -var REACT_OFFSCREEN_TYPE = Symbol.for("react.offscreen"), - REACT_LEGACY_HIDDEN_TYPE = Symbol.for("react.legacy_hidden"); -Symbol.for("react.cache"); -Symbol.for("react.tracing_marker"); -var REACT_SERVER_CONTEXT_DEFAULT_VALUE_NOT_LOADED = Symbol.for( - "react.default_value" - ), - REACT_MEMO_CACHE_SENTINEL = Symbol.for("react.memo_cache_sentinel"), - MAYBE_ITERATOR_SYMBOL = Symbol.iterator; -function getIteratorFn(maybeIterable) { - if (null === maybeIterable || "object" !== typeof maybeIterable) return null; - maybeIterable = - (MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL]) || - maybeIterable["@@iterator"]; - return "function" === typeof maybeIterable ? maybeIterable : null; -} -function getComponentNameFromType(type) { - if (null == type) return null; - if ("function" === typeof type) return type.displayName || type.name || null; - if ("string" === typeof type) 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 ("object" === typeof type) - switch (type.$$typeof) { - case REACT_CONTEXT_TYPE: - return (type.displayName || "Context") + ".Consumer"; - case REACT_PROVIDER_TYPE: - return (type._context.displayName || "Context") + ".Provider"; - case REACT_FORWARD_REF_TYPE: - var innerType = type.render; - type = type.displayName; - type || - ((type = innerType.displayName || innerType.name || ""), - (type = "" !== type ? "ForwardRef(" + type + ")" : "ForwardRef")); - return type; - case REACT_MEMO_TYPE: - return ( - (innerType = type.displayName || null), - null !== innerType - ? innerType - : getComponentNameFromType(type.type) || "Memo" - ); - case REACT_LAZY_TYPE: - innerType = type._payload; - type = type._init; - try { - return getComponentNameFromType(type(innerType)); - } catch (x) { - break; - } - case REACT_SERVER_CONTEXT_TYPE: - return (type.displayName || type._globalName) + ".Provider"; - } - return null; -} -function getComponentNameFromFiber(fiber) { - var type = fiber.type; - switch (fiber.tag) { - case 24: - return "Cache"; - case 9: - return (type.displayName || "Context") + ".Consumer"; - case 10: - return (type._context.displayName || "Context") + ".Provider"; - case 18: - return "DehydratedFragment"; - case 11: - return ( - (fiber = type.render), - (fiber = fiber.displayName || fiber.name || ""), - type.displayName || - ("" !== fiber ? "ForwardRef(" + fiber + ")" : "ForwardRef") - ); - case 7: - return "Fragment"; - case 26: - case 27: - case 5: - return type; - case 4: - return "Portal"; - case 3: - return "Root"; - case 6: - return "Text"; - case 16: - return getComponentNameFromType(type); - case 8: - return type === REACT_STRICT_MODE_TYPE ? "StrictMode" : "Mode"; - case 22: - return "Offscreen"; - case 12: - return "Profiler"; - case 21: - return "Scope"; - case 13: - return "Suspense"; - case 19: - return "SuspenseList"; - case 25: - return "TracingMarker"; + 0 === (root.current.mode & 32) && + 0 !== (nextLanes & 8) && + (nextLanes |= pendingLanes & 32); + wipLanes = root.entangledLanes; + if (0 !== wipLanes) + for (root = root.entanglements, wipLanes &= nextLanes; 0 < wipLanes; ) + (pendingLanes = 31 - clz32(wipLanes)), + (suspendedLanes = 1 << pendingLanes), + (nextLanes |= root[pendingLanes]), + (wipLanes &= ~suspendedLanes); + return nextLanes; +} +function computeExpirationTime(lane, currentTime) { + switch (lane) { case 1: - case 0: - case 17: case 2: - case 14: - case 15: - if ("function" === typeof type) - return type.displayName || type.name || null; - if ("string" === typeof type) return type; - break; - case 23: - return "LegacyHidden"; + case 4: + case 8: + return currentTime + 250; + case 16: + case 32: + case 64: + case 128: + case 256: + case 512: + case 1024: + case 2048: + case 4096: + case 8192: + case 16384: + case 32768: + case 65536: + case 131072: + case 262144: + case 524288: + case 1048576: + case 2097152: + case 4194304: + return currentTime + 5e3; + case 8388608: + case 16777216: + case 33554432: + case 67108864: + return -1; + case 134217728: + case 268435456: + case 536870912: + case 1073741824: + return -1; + default: + return -1; } - return null; } -function getNearestMountedFiber(fiber) { - var node = fiber, - nearestMounted = fiber; - if (fiber.alternate) for (; node.return; ) node = node.return; - else { - fiber = node; - do - (node = fiber), - 0 !== (node.flags & 4098) && (nearestMounted = node.return), - (fiber = node.return); - while (fiber); - } - return 3 === node.tag ? nearestMounted : null; +function getLanesToRetrySynchronouslyOnError(root, originallyAttemptedLanes) { + if (root.errorRecoveryDisabledLanes & originallyAttemptedLanes) return 0; + root = root.pendingLanes & -1073741825; + return 0 !== root ? root : root & 1073741824 ? 1073741824 : 0; } -function assertIsMounted(fiber) { - if (getNearestMountedFiber(fiber) !== fiber) - throw Error("Unable to find node on an unmounted component."); +function includesBlockingLane(root, lanes) { + return 0 !== (root.current.mode & 32) ? !1 : 0 !== (lanes & 60); } -function findCurrentFiberUsingSlowPath(fiber) { - var alternate = fiber.alternate; - if (!alternate) { - alternate = getNearestMountedFiber(fiber); - if (null === alternate) - throw Error("Unable to find node on an unmounted component."); - return alternate !== fiber ? null : fiber; - } - for (var a = fiber, b = alternate; ; ) { - var parentA = a.return; - if (null === parentA) break; - var parentB = parentA.alternate; - if (null === parentB) { - b = parentA.return; - if (null !== b) { - a = b; - continue; +function claimNextTransitionLane() { + var lane = nextTransitionLane; + nextTransitionLane <<= 1; + 0 === (nextTransitionLane & 8388480) && (nextTransitionLane = 128); + return lane; +} +function claimNextRetryLane() { + var lane = nextRetryLane; + nextRetryLane <<= 1; + 0 === (nextRetryLane & 125829120) && (nextRetryLane = 8388608); + return lane; +} +function createLaneMap(initial) { + for (var laneMap = [], i = 0; 31 > i; i++) laneMap.push(initial); + return laneMap; +} +function markRootUpdated(root, updateLane, eventTime) { + root.pendingLanes |= updateLane; + 536870912 !== updateLane && + ((root.suspendedLanes = 0), (root.pingedLanes = 0)); + root = root.eventTimes; + updateLane = 31 - clz32(updateLane); + root[updateLane] = eventTime; +} +function markRootFinished(root, remainingLanes) { + var noLongerPendingLanes = root.pendingLanes & ~remainingLanes; + root.pendingLanes = remainingLanes; + root.suspendedLanes = 0; + root.pingedLanes = 0; + root.expiredLanes &= remainingLanes; + root.mutableReadLanes &= remainingLanes; + root.entangledLanes &= remainingLanes; + root.errorRecoveryDisabledLanes &= remainingLanes; + remainingLanes = root.entanglements; + var eventTimes = root.eventTimes, + expirationTimes = root.expirationTimes; + for (root = root.hiddenUpdates; 0 < noLongerPendingLanes; ) { + var index$7 = 31 - clz32(noLongerPendingLanes), + lane = 1 << index$7; + remainingLanes[index$7] = 0; + eventTimes[index$7] = -1; + expirationTimes[index$7] = -1; + var hiddenUpdatesForLane = root[index$7]; + if (null !== hiddenUpdatesForLane) + for ( + root[index$7] = null, index$7 = 0; + index$7 < hiddenUpdatesForLane.length; + index$7++ + ) { + var update = hiddenUpdatesForLane[index$7]; + null !== update && (update.lane &= -1073741825); } - break; + noLongerPendingLanes &= ~lane; + } +} +function markRootEntangled(root, entangledLanes) { + var rootEntangledLanes = (root.entangledLanes |= entangledLanes); + for (root = root.entanglements; rootEntangledLanes; ) { + var index$8 = 31 - clz32(rootEntangledLanes), + lane = 1 << index$8; + (lane & entangledLanes) | (root[index$8] & entangledLanes) && + (root[index$8] |= entangledLanes); + rootEntangledLanes &= ~lane; + } +} +function addFiberToLanesMap(root, fiber, lanes) { + if (isDevToolsPresent) + for (root = root.pendingUpdatersLaneMap; 0 < lanes; ) { + var index$9 = 31 - clz32(lanes), + lane = 1 << index$9; + root[index$9].add(fiber); + lanes &= ~lane; } - if (parentA.child === parentB.child) { - for (parentB = parentA.child; parentB; ) { - if (parentB === a) return assertIsMounted(parentA), fiber; - if (parentB === b) return assertIsMounted(parentA), alternate; - parentB = parentB.sibling; - } - throw Error("Unable to find node on an unmounted component."); +} +function movePendingFibersToMemoized(root, lanes) { + if (isDevToolsPresent) + for ( + var pendingUpdatersLaneMap = root.pendingUpdatersLaneMap, + memoizedUpdaters = root.memoizedUpdaters; + 0 < lanes; + + ) { + var index$10 = 31 - clz32(lanes); + root = 1 << index$10; + index$10 = pendingUpdatersLaneMap[index$10]; + 0 < index$10.size && + (index$10.forEach(function (fiber) { + var alternate = fiber.alternate; + (null !== alternate && memoizedUpdaters.has(alternate)) || + memoizedUpdaters.add(fiber); + }), + index$10.clear()); + lanes &= ~root; } - if (a.return !== b.return) (a = parentA), (b = parentB); - else { - for (var didFindChild = !1, child$11 = parentA.child; child$11; ) { - if (child$11 === a) { - didFindChild = !0; - a = parentA; - b = parentB; +} +var currentUpdatePriority = 0; +function lanesToEventPriority(lanes) { + lanes &= -lanes; + return 2 < lanes + ? 8 < lanes + ? 0 !== (lanes & 268435455) + ? 32 + : 536870912 + : 8 + : 2; +} +var scheduleCallback$1 = Scheduler.unstable_scheduleCallback, + cancelCallback$1 = Scheduler.unstable_cancelCallback, + shouldYield = Scheduler.unstable_shouldYield, + requestPaint = Scheduler.unstable_requestPaint, + now$1 = Scheduler.unstable_now, + ImmediatePriority = Scheduler.unstable_ImmediatePriority, + UserBlockingPriority = Scheduler.unstable_UserBlockingPriority, + NormalPriority = Scheduler.unstable_NormalPriority, + IdlePriority = Scheduler.unstable_IdlePriority, + rendererID = null, + injectedHook = null, + injectedProfilingHooks = null, + isDevToolsPresent = "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__; +function onCommitRoot(root, eventPriority) { + if (injectedHook && "function" === typeof injectedHook.onCommitFiberRoot) + try { + var didError = 128 === (root.current.flags & 128); + switch (eventPriority) { + case 2: + var schedulerPriority = ImmediatePriority; break; - } - if (child$11 === b) { - didFindChild = !0; - b = parentA; - a = parentB; + case 8: + schedulerPriority = UserBlockingPriority; break; - } - child$11 = child$11.sibling; - } - if (!didFindChild) { - for (child$11 = parentB.child; child$11; ) { - if (child$11 === a) { - didFindChild = !0; - a = parentB; - b = parentA; - break; - } - if (child$11 === b) { - didFindChild = !0; - b = parentB; - a = parentA; - break; - } - child$11 = child$11.sibling; - } - if (!didFindChild) - throw Error( - "Child was not found in either parent set. This indicates a bug in React related to the return pointer. Please file an issue." - ); + case 32: + schedulerPriority = NormalPriority; + break; + case 536870912: + schedulerPriority = IdlePriority; + break; + default: + schedulerPriority = NormalPriority; } - } - if (a.alternate !== b) - throw Error( - "Return fibers should always be each others' alternates. This error is likely caused by a bug in React. Please file an issue." + injectedHook.onCommitFiberRoot( + rendererID, + root, + schedulerPriority, + didError ); - } - if (3 !== a.tag) - throw Error("Unable to find node on an unmounted component."); - return a.stateNode.current === a ? fiber : alternate; + } catch (err) {} } -function findCurrentHostFiber(parent) { - parent = findCurrentFiberUsingSlowPath(parent); - return null !== parent ? findCurrentHostFiberImpl(parent) : null; +function injectProfilingHooks(profilingHooks) { + injectedProfilingHooks = profilingHooks; } -function findCurrentHostFiberImpl(node) { - var tag = node.tag; - if (5 === tag || 26 === tag || 27 === tag || 6 === tag) return node; - for (node = node.child; null !== node; ) { - tag = findCurrentHostFiberImpl(node); - if (null !== tag) return tag; - node = node.sibling; +function getLaneLabelMap() { + for (var map = new Map(), lane = 1, index$11 = 0; 31 > index$11; index$11++) { + var label = getLabelForLane(lane); + map.set(lane, label); + lane *= 2; } - return null; -} -function describeComponentFrame(name, source, ownerName) { - source = ""; - ownerName && (source = " (created by " + ownerName + ")"); - return "\n in " + (name || "Unknown") + source; -} -function describeFunctionComponentFrame(fn, source) { - return fn - ? describeComponentFrame(fn.displayName || fn.name || null, source, null) - : ""; -} -var hasOwnProperty = Object.prototype.hasOwnProperty, - valueStack = [], - index = -1; -function createCursor(defaultValue) { - return { current: defaultValue }; -} -function pop(cursor) { - 0 > index || - ((cursor.current = valueStack[index]), (valueStack[index] = null), index--); + return map; } -function push(cursor, value) { - index++; - valueStack[index] = cursor.current; - cursor.current = value; +function markCommitStopped() { + null !== injectedProfilingHooks && + "function" === typeof injectedProfilingHooks.markCommitStopped && + injectedProfilingHooks.markCommitStopped(); } -var emptyContextObject = {}, - contextStackCursor$1 = createCursor(emptyContextObject), - didPerformWorkStackCursor = createCursor(!1), - previousContext = emptyContextObject; -function getMaskedContext(workInProgress, unmaskedContext) { - var contextTypes = workInProgress.type.contextTypes; - if (!contextTypes) return emptyContextObject; - var instance = workInProgress.stateNode; - if ( - instance && - instance.__reactInternalMemoizedUnmaskedChildContext === unmaskedContext - ) - return instance.__reactInternalMemoizedMaskedChildContext; - var context = {}, - key; - for (key in contextTypes) context[key] = unmaskedContext[key]; - instance && - ((workInProgress = workInProgress.stateNode), - (workInProgress.__reactInternalMemoizedUnmaskedChildContext = - unmaskedContext), - (workInProgress.__reactInternalMemoizedMaskedChildContext = context)); - return context; +function markComponentRenderStarted(fiber) { + null !== injectedProfilingHooks && + "function" === typeof injectedProfilingHooks.markComponentRenderStarted && + injectedProfilingHooks.markComponentRenderStarted(fiber); } -function isContextProvider(type) { - type = type.childContextTypes; - return null !== type && void 0 !== type; +function markComponentRenderStopped() { + null !== injectedProfilingHooks && + "function" === typeof injectedProfilingHooks.markComponentRenderStopped && + injectedProfilingHooks.markComponentRenderStopped(); } -function popContext() { - pop(didPerformWorkStackCursor); - pop(contextStackCursor$1); +function markComponentLayoutEffectUnmountStarted(fiber) { + null !== injectedProfilingHooks && + "function" === + typeof injectedProfilingHooks.markComponentLayoutEffectUnmountStarted && + injectedProfilingHooks.markComponentLayoutEffectUnmountStarted(fiber); } -function pushTopLevelContextObject(fiber, context, didChange) { - if (contextStackCursor$1.current !== emptyContextObject) - throw Error( - "Unexpected context found on stack. This error is likely caused by a bug in React. Please file an issue." - ); - push(contextStackCursor$1, context); - push(didPerformWorkStackCursor, didChange); +function markComponentLayoutEffectUnmountStopped() { + null !== injectedProfilingHooks && + "function" === + typeof injectedProfilingHooks.markComponentLayoutEffectUnmountStopped && + injectedProfilingHooks.markComponentLayoutEffectUnmountStopped(); } -function processChildContext(fiber, type, parentContext) { - var instance = fiber.stateNode; - type = type.childContextTypes; - if ("function" !== typeof instance.getChildContext) return parentContext; - instance = instance.getChildContext(); - for (var contextKey in instance) - if (!(contextKey in type)) - throw Error( - (getComponentNameFromFiber(fiber) || "Unknown") + - '.getChildContext(): key "' + - contextKey + - '" is not defined in childContextTypes.' - ); - return assign({}, parentContext, instance); +function markRenderStarted(lanes) { + null !== injectedProfilingHooks && + "function" === typeof injectedProfilingHooks.markRenderStarted && + injectedProfilingHooks.markRenderStarted(lanes); } -function pushContextProvider(workInProgress) { - workInProgress = - ((workInProgress = workInProgress.stateNode) && - workInProgress.__reactInternalMemoizedMergedChildContext) || - emptyContextObject; - previousContext = contextStackCursor$1.current; - push(contextStackCursor$1, workInProgress); - push(didPerformWorkStackCursor, didPerformWorkStackCursor.current); - return !0; +function markRenderStopped() { + null !== injectedProfilingHooks && + "function" === typeof injectedProfilingHooks.markRenderStopped && + injectedProfilingHooks.markRenderStopped(); } -function invalidateContextProvider(workInProgress, type, didChange) { - var instance = workInProgress.stateNode; - if (!instance) - throw Error( - "Expected to have an instance by this point. This error is likely caused by a bug in React. Please file an issue." - ); - didChange - ? ((workInProgress = processChildContext( - workInProgress, - type, - previousContext - )), - (instance.__reactInternalMemoizedMergedChildContext = workInProgress), - pop(didPerformWorkStackCursor), - pop(contextStackCursor$1), - push(contextStackCursor$1, workInProgress)) - : pop(didPerformWorkStackCursor); - push(didPerformWorkStackCursor, didChange); +function markStateUpdateScheduled(fiber, lane) { + null !== injectedProfilingHooks && + "function" === typeof injectedProfilingHooks.markStateUpdateScheduled && + injectedProfilingHooks.markStateUpdateScheduled(fiber, lane); } function is(x, y) { return (x === y && (0 !== x || 1 / x === 1 / y)) || (x !== x && y !== y); @@ -2237,30 +1984,43 @@ var objectIs = "function" === typeof Object.is ? Object.is : is, function flushSyncCallbacks() { if (!isFlushingSyncQueue && null !== syncQueue) { isFlushingSyncQueue = !0; - var i = 0, - previousUpdatePriority = currentUpdatePriority; - try { - var queue = syncQueue; - for (currentUpdatePriority = 2; i < queue.length; i++) { - var callback = queue[i]; + var previousUpdatePriority = currentUpdatePriority; + currentUpdatePriority = 2; + for (var errors = null, queue = syncQueue, i = 0; i < queue.length; i++) { + var callback = queue[i]; + try { do callback = callback(!0); while (null !== callback); + } catch (error) { + null === errors ? (errors = [error]) : errors.push(error); } - syncQueue = null; - includesLegacySyncCallbacks = !1; - } catch (error) { - throw ( - (null !== syncQueue && (syncQueue = syncQueue.slice(i + 1)), - scheduleCallback$1(ImmediatePriority, flushSyncCallbacks), - error) - ); - } finally { - (currentUpdatePriority = previousUpdatePriority), - (isFlushingSyncQueue = !1); + } + syncQueue = null; + includesLegacySyncCallbacks = !1; + currentUpdatePriority = previousUpdatePriority; + isFlushingSyncQueue = !1; + if (null !== errors) { + if (1 < errors.length) { + if ("function" === typeof AggregateError) + throw new AggregateError(errors); + for ( + previousUpdatePriority = 1; + previousUpdatePriority < errors.length; + previousUpdatePriority++ + ) + scheduleCallback$1( + ImmediatePriority, + throwError.bind(null, errors[previousUpdatePriority]) + ); + } + throw errors[0]; } } return null; } +function throwError(error) { + throw error; +} var contextStackCursor = createCursor(null), contextFiberStackCursor = createCursor(null), rootInstanceStackCursor = createCursor(null); @@ -2660,6 +2420,65 @@ function describeFiber(fiber) { return ""; } } +var SuspenseException = Error( + "Suspense Exception: This is not a real error! It's an implementation detail of `use` to interrupt the current render. You must either rethrow it immediately, or move the `use` call outside of the `try/catch` block. Capturing without rethrowing will lead to unexpected behavior.\n\nTo handle async errors, wrap your component in an error boundary, or call the promise's `.catch` method and pass the result to `use`" + ), + noopSuspenseyCommitThenable = { then: function () {} }; +function isThenableResolved(thenable) { + thenable = thenable.status; + return "fulfilled" === thenable || "rejected" === thenable; +} +function noop$1() {} +function trackUsedThenable(thenableState, thenable, index) { + index = thenableState[index]; + void 0 === index + ? thenableState.push(thenable) + : index !== thenable && (thenable.then(noop$1, noop$1), (thenable = index)); + switch (thenable.status) { + case "fulfilled": + return thenable.value; + case "rejected": + throw thenable.reason; + default: + "string" === typeof thenable.status + ? thenable.then(noop$1, noop$1) + : ((thenableState = thenable), + (thenableState.status = "pending"), + thenableState.then( + function (fulfilledValue) { + if ("pending" === thenable.status) { + var fulfilledThenable = thenable; + fulfilledThenable.status = "fulfilled"; + fulfilledThenable.value = fulfilledValue; + } + }, + function (error) { + if ("pending" === thenable.status) { + var rejectedThenable = thenable; + rejectedThenable.status = "rejected"; + rejectedThenable.reason = error; + } + } + )); + switch (thenable.status) { + case "fulfilled": + return thenable.value; + case "rejected": + throw thenable.reason; + } + suspendedThenable = thenable; + throw SuspenseException; + } +} +var suspendedThenable = null, + thenableState$1 = null, + thenableIndexCounter$1 = 0; +function unwrapThenable(thenable) { + var index = thenableIndexCounter$1; + thenableIndexCounter$1 += 1; + null === thenableState$1 && (thenableState$1 = []); + return trackUsedThenable(thenableState$1, thenable, index); +} function coerceRef(returnFiber, current, element) { returnFiber = element.ref; if ( @@ -2764,16 +2583,16 @@ function createChildReconciler(shouldTrackSideEffects) { return ( (newIndex = newIndex.index), newIndex < lastPlacedIndex - ? ((newFiber.flags |= 16777218), lastPlacedIndex) + ? ((newFiber.flags |= 33554434), lastPlacedIndex) : newIndex ); - newFiber.flags |= 16777218; + newFiber.flags |= 33554434; return lastPlacedIndex; } function placeSingleChild(newFiber) { shouldTrackSideEffects && null === newFiber.alternate && - (newFiber.flags |= 16777218); + (newFiber.flags |= 33554434); return newFiber; } function updateTextNode(returnFiber, current, textContent, lanes) { @@ -2910,6 +2729,17 @@ function createChildReconciler(shouldTrackSideEffects) { (newChild.return = returnFiber), newChild ); + if ("function" === typeof newChild.then) + return createChild(returnFiber, unwrapThenable(newChild), lanes); + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) + return createChild( + returnFiber, + readContextDuringReconcilation(returnFiber, newChild, lanes), + lanes + ); throwOnInvalidObjectType(returnFiber, newChild); } return null; @@ -2943,6 +2773,23 @@ function createChildReconciler(shouldTrackSideEffects) { return null !== key ? null : updateFragment(returnFiber, oldFiber, newChild, lanes, null); + if ("function" === typeof newChild.then) + return updateSlot( + returnFiber, + oldFiber, + unwrapThenable(newChild), + lanes + ); + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) + return updateSlot( + returnFiber, + oldFiber, + readContextDuringReconcilation(returnFiber, newChild, lanes), + lanes + ); throwOnInvalidObjectType(returnFiber, newChild); } return null; @@ -2995,6 +2842,25 @@ function createChildReconciler(shouldTrackSideEffects) { (existingChildren = existingChildren.get(newIdx) || null), updateFragment(returnFiber, existingChildren, newChild, lanes, null) ); + if ("function" === typeof newChild.then) + return updateFromMap( + existingChildren, + returnFiber, + newIdx, + unwrapThenable(newChild), + lanes + ); + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) + return updateFromMap( + existingChildren, + returnFiber, + newIdx, + readContextDuringReconcilation(returnFiber, newChild, lanes), + lanes + ); throwOnInvalidObjectType(returnFiber, newChild); } return null; @@ -3166,7 +3032,7 @@ function createChildReconciler(shouldTrackSideEffects) { }); return iteratorFn; } - function reconcileChildFibers( + function reconcileChildFibersImpl( returnFiber, currentFirstChild, newChild, @@ -3311,6 +3177,23 @@ function createChildReconciler(shouldTrackSideEffects) { newChild, lanes ); + if ("function" === typeof newChild.then) + return reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + unwrapThenable(newChild), + lanes + ); + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) + return reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + readContextDuringReconcilation(returnFiber, newChild, lanes), + lanes + ); throwOnInvalidObjectType(returnFiber, newChild); } return ("string" === typeof newChild && "" !== newChild) || @@ -3332,6 +3215,22 @@ function createChildReconciler(shouldTrackSideEffects) { placeSingleChild(returnFiber)) : deleteRemainingChildren(returnFiber, currentFirstChild); } + function reconcileChildFibers( + returnFiber, + currentFirstChild, + newChild, + lanes + ) { + thenableIndexCounter$1 = 0; + returnFiber = reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + newChild, + lanes + ); + thenableState$1 = null; + return returnFiber; + } return reconcileChildFibers; } var reconcileChildFibers = createChildReconciler(!0), @@ -3410,57 +3309,7 @@ function resetWorkInProgressVersions() { workInProgressSources[i]._workInProgressVersionSecondary = null; workInProgressSources.length = 0; } -var SuspenseException = Error( - "Suspense Exception: This is not a real error! It's an implementation detail of `use` to interrupt the current render. You must either rethrow it immediately, or move the `use` call outside of the `try/catch` block. Capturing without rethrowing will lead to unexpected behavior.\n\nTo handle async errors, wrap your component in an error boundary, or call the promise's `.catch` method and pass the result to `use`" -); -function isThenableResolved(thenable) { - thenable = thenable.status; - return "fulfilled" === thenable || "rejected" === thenable; -} -function noop() {} -function trackUsedThenable(thenableState, thenable, index) { - index = thenableState[index]; - void 0 === index - ? thenableState.push(thenable) - : index !== thenable && (thenable.then(noop, noop), (thenable = index)); - switch (thenable.status) { - case "fulfilled": - return thenable.value; - case "rejected": - throw thenable.reason; - default: - "string" === typeof thenable.status - ? thenable.then(noop, noop) - : ((thenableState = thenable), - (thenableState.status = "pending"), - thenableState.then( - function (fulfilledValue) { - if ("pending" === thenable.status) { - var fulfilledThenable = thenable; - fulfilledThenable.status = "fulfilled"; - fulfilledThenable.value = fulfilledValue; - } - }, - function (error) { - if ("pending" === thenable.status) { - var rejectedThenable = thenable; - rejectedThenable.status = "rejected"; - rejectedThenable.reason = error; - } - } - )); - switch (thenable.status) { - case "fulfilled": - return thenable.value; - case "rejected": - throw thenable.reason; - } - suspendedThenable = thenable; - throw SuspenseException; - } -} -var suspendedThenable = null, - ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, +var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, ReactCurrentBatchConfig$2 = ReactSharedInternals.ReactCurrentBatchConfig, renderLanes$1 = 0, currentlyRenderingFiber$1 = null, @@ -3620,10 +3469,10 @@ createFunctionComponentUpdateQueue = function () { function use(usable) { if (null !== usable && "object" === typeof usable) { if ("function" === typeof usable.then) { - var index$28 = thenableIndexCounter; + var index$30 = thenableIndexCounter; thenableIndexCounter += 1; null === thenableState && (thenableState = []); - usable = trackUsedThenable(thenableState, usable, index$28); + usable = trackUsedThenable(thenableState, usable, index$30); null === currentlyRenderingFiber$1.alternate && (null === workInProgressHook ? null === currentlyRenderingFiber$1.memoizedState @@ -4078,8 +3927,9 @@ function startTransition(setPending, callback) { var previousPriority = currentUpdatePriority; currentUpdatePriority = 0 !== previousPriority && 8 > previousPriority ? previousPriority : 8; - setPending(!0); var prevTransition = ReactCurrentBatchConfig$2.transition; + ReactCurrentBatchConfig$2.transition = null; + setPending(!0); ReactCurrentBatchConfig$2.transition = {}; try { setPending(!1), callback(); @@ -5291,7 +5141,7 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { (nextProps.treeBaseDuration = JSCompiler_temp.treeBaseDuration)), (workInProgress.deletions = null)) : ((nextProps = createWorkInProgress(JSCompiler_temp, primaryChildProps)), - (nextProps.subtreeFlags = JSCompiler_temp.subtreeFlags & 14680064)); + (nextProps.subtreeFlags = JSCompiler_temp.subtreeFlags & 31457280)); null !== dehydrated ? (showFallback = createWorkInProgress(dehydrated, showFallback)) : ((showFallback = createFiberFromFragment( @@ -5830,21 +5680,26 @@ function prepareToReadContext(workInProgress, renderLanes) { (workInProgress.firstContext = null)); } function readContext(context) { + return readContextForConsumer(currentlyRenderingFiber, context); +} +function readContextDuringReconcilation(consumer, context, renderLanes) { + null === currentlyRenderingFiber && + prepareToReadContext(consumer, renderLanes); + return readContextForConsumer(consumer, context); +} +function readContextForConsumer(consumer, context) { var value = context._currentValue2; if (lastFullyObservedContext !== context) if ( ((context = { context: context, memoizedValue: value, next: null }), null === lastContextDependency) ) { - if (null === currentlyRenderingFiber) + if (null === consumer) throw 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()." ); lastContextDependency = context; - currentlyRenderingFiber.dependencies = { - lanes: 0, - firstContext: context - }; + consumer.dependencies = { lanes: 0, firstContext: context }; } else lastContextDependency = lastContextDependency.next = context; return value; } @@ -5952,6 +5807,14 @@ function updateHostContainer(current, workInProgress) { completeRoot(current, newChildSet); } } +function scheduleRetryEffect(workInProgress, retryQueue) { + null !== retryQueue + ? (workInProgress.flags |= 4) + : workInProgress.flags & 16384 && + ((retryQueue = + 22 !== workInProgress.tag ? claimNextRetryLane() : 1073741824), + (workInProgress.lanes |= retryQueue)); +} function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { switch (renderState.tailMode) { case "hidden": @@ -5966,14 +5829,14 @@ function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { break; case "collapsed": lastTailNode = renderState.tail; - for (var lastTailNode$67 = null; null !== lastTailNode; ) - null !== lastTailNode.alternate && (lastTailNode$67 = lastTailNode), + for (var lastTailNode$70 = null; null !== lastTailNode; ) + null !== lastTailNode.alternate && (lastTailNode$70 = lastTailNode), (lastTailNode = lastTailNode.sibling); - null === lastTailNode$67 + null === lastTailNode$70 ? hasRenderedATailFallback || null === renderState.tail ? (renderState.tail = null) : (renderState.tail.sibling = null) - : (lastTailNode$67.sibling = null); + : (lastTailNode$70.sibling = null); } } function bubbleProperties(completedWork) { @@ -5985,53 +5848,53 @@ function bubbleProperties(completedWork) { if (didBailout) if (0 !== (completedWork.mode & 2)) { for ( - var treeBaseDuration$69 = completedWork.selfBaseDuration, - child$70 = completedWork.child; - null !== child$70; + var treeBaseDuration$72 = completedWork.selfBaseDuration, + child$73 = completedWork.child; + null !== child$73; ) - (newChildLanes |= child$70.lanes | child$70.childLanes), - (subtreeFlags |= child$70.subtreeFlags & 14680064), - (subtreeFlags |= child$70.flags & 14680064), - (treeBaseDuration$69 += child$70.treeBaseDuration), - (child$70 = child$70.sibling); - completedWork.treeBaseDuration = treeBaseDuration$69; + (newChildLanes |= child$73.lanes | child$73.childLanes), + (subtreeFlags |= child$73.subtreeFlags & 31457280), + (subtreeFlags |= child$73.flags & 31457280), + (treeBaseDuration$72 += child$73.treeBaseDuration), + (child$73 = child$73.sibling); + completedWork.treeBaseDuration = treeBaseDuration$72; } else for ( - treeBaseDuration$69 = completedWork.child; - null !== treeBaseDuration$69; + treeBaseDuration$72 = completedWork.child; + null !== treeBaseDuration$72; ) (newChildLanes |= - treeBaseDuration$69.lanes | treeBaseDuration$69.childLanes), - (subtreeFlags |= treeBaseDuration$69.subtreeFlags & 14680064), - (subtreeFlags |= treeBaseDuration$69.flags & 14680064), - (treeBaseDuration$69.return = completedWork), - (treeBaseDuration$69 = treeBaseDuration$69.sibling); + treeBaseDuration$72.lanes | treeBaseDuration$72.childLanes), + (subtreeFlags |= treeBaseDuration$72.subtreeFlags & 31457280), + (subtreeFlags |= treeBaseDuration$72.flags & 31457280), + (treeBaseDuration$72.return = completedWork), + (treeBaseDuration$72 = treeBaseDuration$72.sibling); else if (0 !== (completedWork.mode & 2)) { - treeBaseDuration$69 = completedWork.actualDuration; - child$70 = completedWork.selfBaseDuration; + treeBaseDuration$72 = completedWork.actualDuration; + child$73 = completedWork.selfBaseDuration; for (var child = completedWork.child; null !== child; ) (newChildLanes |= child.lanes | child.childLanes), (subtreeFlags |= child.subtreeFlags), (subtreeFlags |= child.flags), - (treeBaseDuration$69 += child.actualDuration), - (child$70 += child.treeBaseDuration), + (treeBaseDuration$72 += child.actualDuration), + (child$73 += child.treeBaseDuration), (child = child.sibling); - completedWork.actualDuration = treeBaseDuration$69; - completedWork.treeBaseDuration = child$70; + completedWork.actualDuration = treeBaseDuration$72; + completedWork.treeBaseDuration = child$73; } else for ( - treeBaseDuration$69 = completedWork.child; - null !== treeBaseDuration$69; + treeBaseDuration$72 = completedWork.child; + null !== treeBaseDuration$72; ) (newChildLanes |= - treeBaseDuration$69.lanes | treeBaseDuration$69.childLanes), - (subtreeFlags |= treeBaseDuration$69.subtreeFlags), - (subtreeFlags |= treeBaseDuration$69.flags), - (treeBaseDuration$69.return = completedWork), - (treeBaseDuration$69 = treeBaseDuration$69.sibling); + treeBaseDuration$72.lanes | treeBaseDuration$72.childLanes), + (subtreeFlags |= treeBaseDuration$72.subtreeFlags), + (subtreeFlags |= treeBaseDuration$72.flags), + (treeBaseDuration$72.return = completedWork), + (treeBaseDuration$72 = treeBaseDuration$72.sibling); completedWork.subtreeFlags |= subtreeFlags; completedWork.childLanes = newChildLanes; return didBailout; @@ -6082,15 +5945,15 @@ function completeWork(current, workInProgress, renderLanes) { case 27: case 5: popHostContext(workInProgress); - var type = workInProgress.type; + renderLanes = workInProgress.type; if (null !== current && null != workInProgress.stateNode) { - type = current.stateNode; - var oldProps = current.memoizedProps; + var currentInstance = current.stateNode, + oldProps = current.memoizedProps; if ( (renderLanes = hadNoMutationsEffects(current, workInProgress)) && oldProps === newProps ) - workInProgress.stateNode = type; + workInProgress.stateNode = currentInstance; else { var recyclableInstance = workInProgress.stateNode, updatePayload = null; @@ -6104,9 +5967,9 @@ function completeWork(current, workInProgress, renderLanes) { (recyclableInstance.canonical.currentProps = newProps), (updatePayload = oldProps)); renderLanes && null === updatePayload - ? (workInProgress.stateNode = type) + ? (workInProgress.stateNode = currentInstance) : ((newProps = updatePayload), - (recyclableInstance = type.node), + (recyclableInstance = currentInstance.node), (newProps = { node: renderLanes ? null !== newProps @@ -6118,8 +5981,9 @@ function completeWork(current, workInProgress, renderLanes) { newProps ) : cloneNodeWithNewChildren(recyclableInstance), - canonical: type.canonical + canonical: currentInstance.canonical }), + (workInProgress.flags &= -16777217), (workInProgress.stateNode = newProps), renderLanes ? (workInProgress.flags |= 4) @@ -6135,32 +5999,41 @@ function completeWork(current, workInProgress, renderLanes) { bubbleProperties(workInProgress); return null; } - renderLanes = rootInstanceStackCursor.current; + currentInstance = rootInstanceStackCursor.current; current = nextReactTag; nextReactTag += 2; - type = getViewConfigForType(type); + renderLanes = getViewConfigForType(renderLanes); recyclableInstance = diffProperties( null, emptyObject$1, newProps, - type.validAttributes + renderLanes.validAttributes ); - renderLanes = createNode( + currentInstance = createNode( current, - type.uiViewClassName, - renderLanes, + renderLanes.uiViewClassName, + currentInstance, recyclableInstance, workInProgress ); - current = new ReactFabricHostComponent( + recyclableInstance = new ReactFabricHostComponent( current, - type, - newProps, + renderLanes, workInProgress ); - current = { node: renderLanes, canonical: current }; + current = { + node: currentInstance, + canonical: { + nativeTag: current, + viewConfig: renderLanes, + currentProps: newProps, + internalInstanceHandle: workInProgress, + publicInstance: recyclableInstance + } + }; appendAllChildren(current, workInProgress, !1, !1); workInProgress.stateNode = current; + workInProgress.flags &= -16777217; null !== workInProgress.ref && (workInProgress.flags |= 2097664); } bubbleProperties(workInProgress); @@ -6213,15 +6086,17 @@ function completeWork(current, workInProgress, renderLanes) { bubbleProperties(workInProgress); 0 !== (workInProgress.mode & 2) && null !== newProps && - ((type = workInProgress.child), - null !== type && - (workInProgress.treeBaseDuration -= type.treeBaseDuration)); - type = !1; + ((currentInstance = workInProgress.child), + null !== currentInstance && + (workInProgress.treeBaseDuration -= + currentInstance.treeBaseDuration)); + currentInstance = !1; } else null !== hydrationErrors && (queueRecoverableErrors(hydrationErrors), (hydrationErrors = null)), - (type = !0); - if (!type) return workInProgress.flags & 65536 ? workInProgress : null; + (currentInstance = !0); + if (!currentInstance) + return workInProgress.flags & 65536 ? workInProgress : null; } if (0 !== (workInProgress.flags & 128)) return ( @@ -6234,7 +6109,7 @@ function completeWork(current, workInProgress, renderLanes) { newProps !== (null !== current && null !== current.memoizedState) && newProps && (workInProgress.child.flags |= 8192); - null !== workInProgress.updateQueue && (workInProgress.flags |= 4); + scheduleRetryEffect(workInProgress, workInProgress.updateQueue); bubbleProperties(workInProgress); 0 !== (workInProgress.mode & 2) && newProps && @@ -6263,12 +6138,13 @@ function completeWork(current, workInProgress, renderLanes) { ); case 19: pop(suspenseStackCursor); - type = workInProgress.memoizedState; - if (null === type) return bubbleProperties(workInProgress), null; + currentInstance = workInProgress.memoizedState; + if (null === currentInstance) + return bubbleProperties(workInProgress), null; newProps = 0 !== (workInProgress.flags & 128); - recyclableInstance = type.rendering; + recyclableInstance = currentInstance.rendering; if (null === recyclableInstance) - if (newProps) cutOffTailIfNeeded(type, !1); + if (newProps) cutOffTailIfNeeded(currentInstance, !1); else { if ( 0 !== workInProgressRootExitStatus || @@ -6278,11 +6154,10 @@ function completeWork(current, workInProgress, renderLanes) { recyclableInstance = findFirstSuspended(current); if (null !== recyclableInstance) { workInProgress.flags |= 128; - cutOffTailIfNeeded(type, !1); + cutOffTailIfNeeded(currentInstance, !1); current = recyclableInstance.updateQueue; - null !== current && - ((workInProgress.updateQueue = current), - (workInProgress.flags |= 4)); + workInProgress.updateQueue = current; + scheduleRetryEffect(workInProgress, current); workInProgress.subtreeFlags = 0; current = renderLanes; for (newProps = workInProgress.child; null !== newProps; ) @@ -6296,11 +6171,11 @@ function completeWork(current, workInProgress, renderLanes) { } current = current.sibling; } - null !== type.tail && + null !== currentInstance.tail && now$1() > workInProgressRootRenderTargetTime && ((workInProgress.flags |= 128), (newProps = !0), - cutOffTailIfNeeded(type, !1), + cutOffTailIfNeeded(currentInstance, !1), (workInProgress.lanes = 8388608)); } else { @@ -6313,38 +6188,37 @@ function completeWork(current, workInProgress, renderLanes) { ((workInProgress.flags |= 128), (newProps = !0), (current = current.updateQueue), - null !== current && - ((workInProgress.updateQueue = current), - (workInProgress.flags |= 4)), - cutOffTailIfNeeded(type, !0), - null === type.tail && - "hidden" === type.tailMode && + (workInProgress.updateQueue = current), + scheduleRetryEffect(workInProgress, current), + cutOffTailIfNeeded(currentInstance, !0), + null === currentInstance.tail && + "hidden" === currentInstance.tailMode && !recyclableInstance.alternate) ) return bubbleProperties(workInProgress), null; } else - 2 * now$1() - type.renderingStartTime > + 2 * now$1() - currentInstance.renderingStartTime > workInProgressRootRenderTargetTime && 1073741824 !== renderLanes && ((workInProgress.flags |= 128), (newProps = !0), - cutOffTailIfNeeded(type, !1), + cutOffTailIfNeeded(currentInstance, !1), (workInProgress.lanes = 8388608)); - type.isBackwards + currentInstance.isBackwards ? ((recyclableInstance.sibling = workInProgress.child), (workInProgress.child = recyclableInstance)) - : ((current = type.last), + : ((current = currentInstance.last), null !== current ? (current.sibling = recyclableInstance) : (workInProgress.child = recyclableInstance), - (type.last = recyclableInstance)); + (currentInstance.last = recyclableInstance)); } - if (null !== type.tail) + if (null !== currentInstance.tail) return ( - (workInProgress = type.tail), - (type.rendering = workInProgress), - (type.tail = workInProgress.sibling), - (type.renderingStartTime = now$1()), + (workInProgress = currentInstance.tail), + (currentInstance.rendering = workInProgress), + (currentInstance.tail = workInProgress.sibling), + (currentInstance.renderingStartTime = now$1()), (workInProgress.sibling = null), (current = suspenseStackCursor.current), push(suspenseStackCursor, newProps ? (current & 1) | 2 : current & 1), @@ -6371,7 +6245,9 @@ function completeWork(current, workInProgress, renderLanes) { workInProgress.subtreeFlags & 6 && (workInProgress.flags |= 8192)) : bubbleProperties(workInProgress), - null !== workInProgress.updateQueue && (workInProgress.flags |= 4), + (current = workInProgress.updateQueue), + null !== current && + scheduleRetryEffect(workInProgress, current.retryQueue), null ); case 24: @@ -6569,8 +6445,8 @@ function safelyDetachRef(current, nearestMountedAncestor) { recordLayoutEffectDuration(current); } else ref(null); - } catch (error$86) { - captureCommitPhaseError(current, nearestMountedAncestor, error$86); + } catch (error$91) { + captureCommitPhaseError(current, nearestMountedAncestor, error$91); } else ref.current = null; } @@ -6702,8 +6578,8 @@ function commitHookEffectListMount(flags, finishedWork) { injectedProfilingHooks.markComponentLayoutEffectMountStarted( finishedWork ); - var create$87 = effect.create; - effect.destroy = create$87(); + var create$92 = effect.create; + effect.destroy = create$92(); 0 !== (flags & 8) ? null !== injectedProfilingHooks && "function" === @@ -6731,8 +6607,8 @@ function commitHookLayoutEffects(finishedWork, hookFlags) { } else try { commitHookEffectListMount(hookFlags, finishedWork); - } catch (error$89) { - captureCommitPhaseError(finishedWork, finishedWork.return, error$89); + } catch (error$94) { + captureCommitPhaseError(finishedWork, finishedWork.return, error$94); } } function commitClassCallbacks(finishedWork) { @@ -6821,11 +6697,11 @@ function commitLayoutEffectOnFiber(finishedRoot, current, finishedWork) { } else try { finishedRoot.componentDidMount(); - } catch (error$90) { + } catch (error$95) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$90 + error$95 ); } else { @@ -6842,11 +6718,11 @@ function commitLayoutEffectOnFiber(finishedRoot, current, finishedWork) { current, finishedRoot.__reactInternalSnapshotBeforeUpdate ); - } catch (error$91) { + } catch (error$96) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$91 + error$96 ); } recordLayoutEffectDuration(finishedWork); @@ -6857,11 +6733,11 @@ function commitLayoutEffectOnFiber(finishedRoot, current, finishedWork) { current, finishedRoot.__reactInternalSnapshotBeforeUpdate ); - } catch (error$92) { + } catch (error$97) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$92 + error$97 ); } } @@ -7205,22 +7081,22 @@ function commitMutationEffectsOnFiber(finishedWork, root) { try { startLayoutEffectTimer(), commitHookEffectListUnmount(5, finishedWork, finishedWork.return); - } catch (error$95) { + } catch (error$100) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$95 + error$100 ); } recordLayoutEffectDuration(finishedWork); } else try { commitHookEffectListUnmount(5, finishedWork, finishedWork.return); - } catch (error$96) { + } catch (error$101) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$96 + error$101 ); } } @@ -7281,14 +7157,14 @@ function commitMutationEffectsOnFiber(finishedWork, root) { flags & 512 && null !== current && safelyDetachRef(current, current.return); - var isHidden$103 = null !== finishedWork.memoizedState, - wasHidden$104 = null !== current && null !== current.memoizedState; + var isHidden$108 = null !== finishedWork.memoizedState, + wasHidden$109 = null !== current && null !== current.memoizedState; if (finishedWork.mode & 1) { var prevOffscreenSubtreeIsHidden = offscreenSubtreeIsHidden, prevOffscreenSubtreeWasHidden = offscreenSubtreeWasHidden; - offscreenSubtreeIsHidden = prevOffscreenSubtreeIsHidden || isHidden$103; + offscreenSubtreeIsHidden = prevOffscreenSubtreeIsHidden || isHidden$108; offscreenSubtreeWasHidden = - prevOffscreenSubtreeWasHidden || wasHidden$104; + prevOffscreenSubtreeWasHidden || wasHidden$109; recursivelyTraverseMutationEffects(root, finishedWork); offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden; offscreenSubtreeIsHidden = prevOffscreenSubtreeIsHidden; @@ -7299,23 +7175,23 @@ function commitMutationEffectsOnFiber(finishedWork, root) { root._visibility &= -3; root._visibility |= root._pendingVisibility & 2; flags & 8192 && - ((root._visibility = isHidden$103 + ((root._visibility = isHidden$108 ? root._visibility & -2 : root._visibility | 1), - isHidden$103 && - ((isHidden$103 = + isHidden$108 && + ((isHidden$108 = offscreenSubtreeIsHidden || offscreenSubtreeWasHidden), null === current || - wasHidden$104 || - isHidden$103 || + wasHidden$109 || + isHidden$108 || (0 !== (finishedWork.mode & 1) && recursivelyTraverseDisappearLayoutEffects(finishedWork)))); flags & 4 && ((flags = finishedWork.updateQueue), null !== flags && - ((current = flags.wakeables), + ((current = flags.retryQueue), null !== current && - ((flags.wakeables = null), + ((flags.retryQueue = null), attachSuspenseRetryListeners(finishedWork, current)))); break; case 19: @@ -7514,8 +7390,8 @@ function commitHookPassiveMountEffects(finishedWork, hookFlags) { } else try { commitHookEffectListMount(hookFlags, finishedWork); - } catch (error$107) { - captureCommitPhaseError(finishedWork, finishedWork.return, error$107); + } catch (error$112) { + captureCommitPhaseError(finishedWork, finishedWork.return, error$112); } } function recursivelyTraversePassiveMountEffects(root, parentFiber) { @@ -7866,6 +7742,8 @@ function ensureRootIsScheduled(root, currentTime) { (root.callbackPriority = 0); else if (2 === workInProgressSuspendedReason && workInProgressRoot === root) (root.callbackPriority = 0), (root.callbackNode = null); + else if (null !== root.cancelPendingCommit && 0 === (suspendedLanes & 42)) + (root.callbackPriority = 0), (root.callbackNode = null); else if ( ((currentTime = suspendedLanes & -suspendedLanes), root.callbackPriority !== currentTime) @@ -7924,28 +7802,28 @@ function performConcurrentWorkOnRoot(root, didTimeout) { root === workInProgressRoot ? workInProgressRootRenderLanes : 0 ); if (0 === lanes) return null; - didTimeout = + var exitStatus = includesBlockingLane(root, lanes) || 0 !== (lanes & root.expiredLanes) || didTimeout ? renderRootSync(root, lanes) : renderRootConcurrent(root, lanes); - if (0 !== didTimeout) { - if (2 === didTimeout) { - var originallyAttemptedLanes = lanes, - errorRetryLanes = getLanesToRetrySynchronouslyOnError( - root, - originallyAttemptedLanes - ); + if (0 !== exitStatus) { + if (2 === exitStatus) { + didTimeout = lanes; + var errorRetryLanes = getLanesToRetrySynchronouslyOnError( + root, + didTimeout + ); 0 !== errorRetryLanes && ((lanes = errorRetryLanes), - (didTimeout = recoverFromConcurrentError( + (exitStatus = recoverFromConcurrentError( root, - originallyAttemptedLanes, + didTimeout, errorRetryLanes ))); } - if (1 === didTimeout) + if (1 === exitStatus) throw ( ((originalCallbackNode = workInProgressRootFatalError), prepareFreshStack(root, 0), @@ -7953,30 +7831,30 @@ function performConcurrentWorkOnRoot(root, didTimeout) { ensureRootIsScheduled(root, now$1()), originalCallbackNode) ); - if (6 === didTimeout) markRootSuspended(root, lanes); + if (6 === exitStatus) markRootSuspended(root, lanes); else { errorRetryLanes = !includesBlockingLane(root, lanes); - originallyAttemptedLanes = root.current.alternate; + didTimeout = root.current.alternate; if ( errorRetryLanes && - !isRenderConsistentWithExternalStores(originallyAttemptedLanes) + !isRenderConsistentWithExternalStores(didTimeout) ) { - didTimeout = renderRootSync(root, lanes); - if (2 === didTimeout) { + exitStatus = renderRootSync(root, lanes); + if (2 === exitStatus) { errorRetryLanes = lanes; - var errorRetryLanes$109 = getLanesToRetrySynchronouslyOnError( + var errorRetryLanes$114 = getLanesToRetrySynchronouslyOnError( root, errorRetryLanes ); - 0 !== errorRetryLanes$109 && - ((lanes = errorRetryLanes$109), - (didTimeout = recoverFromConcurrentError( + 0 !== errorRetryLanes$114 && + ((lanes = errorRetryLanes$114), + (exitStatus = recoverFromConcurrentError( root, errorRetryLanes, - errorRetryLanes$109 + errorRetryLanes$114 ))); } - if (1 === didTimeout) + if (1 === exitStatus) throw ( ((originalCallbackNode = workInProgressRootFatalError), prepareFreshStack(root, 0), @@ -7985,94 +7863,84 @@ function performConcurrentWorkOnRoot(root, didTimeout) { originalCallbackNode) ); } - root.finishedWork = originallyAttemptedLanes; + root.finishedWork = didTimeout; root.finishedLanes = lanes; - switch (didTimeout) { + switch (exitStatus) { case 0: case 1: throw Error("Root did not complete. This is a bug in React."); case 2: - commitRoot( - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ); + commitRootWhenReady(root); break; case 3: markRootSuspended(root, lanes); if ( (lanes & 125829120) === lanes && - ((lanes = globalMostRecentFallbackTime + 500 - now$1()), 10 < lanes) + ((exitStatus = globalMostRecentFallbackTime + 500 - now$1()), + 10 < exitStatus) ) { if (0 !== getNextLanes(root, 0)) break; root.timeoutHandle = scheduleTimeout( - commitRoot.bind( + commitRootWhenReady.bind( null, root, + didTimeout, workInProgressRootRecoverableErrors, - workInProgressTransitions + workInProgressTransitions, + lanes ), - lanes + exitStatus ); break; } - commitRoot( - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ); + commitRootWhenReady(root); break; case 4: markRootSuspended(root, lanes); if ((lanes & 8388480) === lanes) break; - didTimeout = root.eventTimes; - for (originallyAttemptedLanes = -1; 0 < lanes; ) - (errorRetryLanes$109 = 31 - clz32(lanes)), - (errorRetryLanes = 1 << errorRetryLanes$109), - (errorRetryLanes$109 = didTimeout[errorRetryLanes$109]), - errorRetryLanes$109 > originallyAttemptedLanes && - (originallyAttemptedLanes = errorRetryLanes$109), - (lanes &= ~errorRetryLanes); - lanes = originallyAttemptedLanes; - lanes = now$1() - lanes; - lanes = - (120 > lanes + exitStatus = lanes; + errorRetryLanes = root.eventTimes; + for (errorRetryLanes$114 = -1; 0 < exitStatus; ) { + var index$4 = 31 - clz32(exitStatus), + lane = 1 << index$4; + index$4 = errorRetryLanes[index$4]; + index$4 > errorRetryLanes$114 && (errorRetryLanes$114 = index$4); + exitStatus &= ~lane; + } + exitStatus = errorRetryLanes$114; + exitStatus = now$1() - exitStatus; + exitStatus = + (120 > exitStatus ? 120 - : 480 > lanes + : 480 > exitStatus ? 480 - : 1080 > lanes + : 1080 > exitStatus ? 1080 - : 1920 > lanes + : 1920 > exitStatus ? 1920 - : 3e3 > lanes + : 3e3 > exitStatus ? 3e3 - : 4320 > lanes + : 4320 > exitStatus ? 4320 - : 1960 * ceil(lanes / 1960)) - lanes; - if (10 < lanes) { + : 1960 * ceil(exitStatus / 1960)) - exitStatus; + if (10 < exitStatus) { root.timeoutHandle = scheduleTimeout( - commitRoot.bind( + commitRootWhenReady.bind( null, root, + didTimeout, workInProgressRootRecoverableErrors, - workInProgressTransitions + workInProgressTransitions, + lanes ), - lanes + exitStatus ); break; } - commitRoot( - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ); + commitRootWhenReady(root); break; case 5: - commitRoot( - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ); + commitRootWhenReady(root); break; default: throw Error("Unknown root exit status."); @@ -8115,6 +7983,13 @@ function queueRecoverableErrors(errors) { errors ); } +function commitRootWhenReady(root) { + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); +} function isRenderConsistentWithExternalStores(finishedWork) { for (var node = finishedWork; ; ) { if (node.flags & 16384) { @@ -8213,6 +8088,8 @@ function resetWorkInProgressStack() { else resetContextDependencies(), resetHooksOnUnwind(), + (thenableState$1 = null), + (thenableIndexCounter$1 = 0), (interruptedWork = workInProgress); for (; null !== interruptedWork; ) unwindInterruptedWork(interruptedWork.alternate, interruptedWork), @@ -8226,6 +8103,9 @@ function prepareFreshStack(root, lanes) { var timeoutHandle = root.timeoutHandle; -1 !== timeoutHandle && ((root.timeoutHandle = -1), cancelTimeout(timeoutHandle)); + timeoutHandle = root.cancelPendingCommit; + null !== timeoutHandle && + ((root.cancelPendingCommit = null), timeoutHandle()); resetWorkInProgressStack(); workInProgressRoot = root; workInProgress = root = createWorkInProgress(root.current, null); @@ -8254,9 +8134,21 @@ function handleThrow(root, thrownValue) { ); thrownValue = suspendedThenable; suspendedThenable = null; - workInProgressSuspendedReason = shouldAttemptToSuspendUntilDataResolves() - ? 2 - : 3; + (workInProgressRootRenderLanes & 8388480) === workInProgressRootRenderLanes + ? (root = null === shellBoundary ? !0 : !1) + : ((root = suspenseHandlerStackCursor.current), + (root = + null !== root && + (workInProgressRootRenderLanes & 125829120) === + workInProgressRootRenderLanes + ? root === shellBoundary + : !1)); + workInProgressSuspendedReason = + root && + 0 === (workInProgressRootSkippedLanes & 268435455) && + 0 === (workInProgressRootInterleavedUpdatedLanes & 268435455) + ? 2 + : 3; } else workInProgressSuspendedReason = thrownValue === SelectiveHydrationException @@ -8299,24 +8191,6 @@ function handleThrow(root, thrownValue) { ); } } -function shouldAttemptToSuspendUntilDataResolves() { - if ( - 0 !== (workInProgressRootSkippedLanes & 268435455) || - 0 !== (workInProgressRootInterleavedUpdatedLanes & 268435455) - ) - return !1; - if ( - (workInProgressRootRenderLanes & 8388480) === - workInProgressRootRenderLanes - ) - return null === shellBoundary; - var handler = suspenseHandlerStackCursor.current; - return null !== handler && - (workInProgressRootRenderLanes & 125829120) === - workInProgressRootRenderLanes - ? handler === shellBoundary - : !1; -} function pushDispatcher() { var prevDispatcher = ReactCurrentDispatcher.current; ReactCurrentDispatcher.current = ContextOnlyDispatcher; @@ -8364,8 +8238,8 @@ function renderRootSync(root, lanes) { } workLoopSync(); break; - } catch (thrownValue$112) { - handleThrow(root, thrownValue$112); + } catch (thrownValue$117) { + handleThrow(root, thrownValue$117); } while (1); resetContextDependencies(); @@ -8455,8 +8329,8 @@ function renderRootConcurrent(root, lanes) { } workLoopConcurrent(); break; - } catch (thrownValue$114) { - handleThrow(root, thrownValue$114); + } catch (thrownValue$119) { + handleThrow(root, thrownValue$119); } while (1); resetContextDependencies(); @@ -8525,9 +8399,7 @@ function replaySuspendedUnitOfWork(unitOfWork) { ); break; default: - resetContextDependencies(), - resetHooksOnUnwind(), - unwindInterruptedWork(current, unitOfWork), + unwindInterruptedWork(current, unitOfWork), (unitOfWork = workInProgress = resetWorkInProgress(unitOfWork, renderLanes)), (current = beginWork(current, unitOfWork, renderLanes)); @@ -8542,6 +8414,8 @@ function replaySuspendedUnitOfWork(unitOfWork) { function unwindSuspendedUnitOfWork(unitOfWork, thrownValue) { resetContextDependencies(); resetHooksOnUnwind(); + thenableState$1 = null; + thenableIndexCounter$1 = 0; var returnFiber = unitOfWork.return; if (null === returnFiber || null === workInProgressRoot) (workInProgressRootExitStatus = 1), @@ -8604,27 +8478,35 @@ function unwindSuspendedUnitOfWork(unitOfWork, thrownValue) { else (suspenseBoundary.flags |= 65536), (suspenseBoundary.lanes = thrownValue); - var wakeables = suspenseBoundary.updateQueue; - null === wakeables - ? (suspenseBoundary.updateQueue = new Set([wakeable])) - : wakeables.add(wakeable); + if (wakeable === noopSuspenseyCommitThenable) + suspenseBoundary.flags |= 16384; + else { + var retryQueue = suspenseBoundary.updateQueue; + null === retryQueue + ? (suspenseBoundary.updateQueue = new Set([wakeable])) + : retryQueue.add(wakeable); + } break; case 22: if (suspenseBoundary.mode & 1) { suspenseBoundary.flags |= 65536; - var offscreenQueue = suspenseBoundary.updateQueue; - if (null === offscreenQueue) { - var newOffscreenQueue = { - transitions: null, - markerInstances: null, - wakeables: new Set([wakeable]) - }; - suspenseBoundary.updateQueue = newOffscreenQueue; - } else { - var wakeables$34 = offscreenQueue.wakeables; - null === wakeables$34 - ? (offscreenQueue.wakeables = new Set([wakeable])) - : wakeables$34.add(wakeable); + if (wakeable === noopSuspenseyCommitThenable) + suspenseBoundary.flags |= 16384; + else { + var offscreenQueue = suspenseBoundary.updateQueue; + if (null === offscreenQueue) { + var newOffscreenQueue = { + transitions: null, + markerInstances: null, + retryQueue: new Set([wakeable]) + }; + suspenseBoundary.updateQueue = newOffscreenQueue; + } else { + var retryQueue$37 = offscreenQueue.retryQueue; + null === retryQueue$37 + ? (offscreenQueue.retryQueue = new Set([wakeable])) + : retryQueue$37.add(wakeable); + } } break; } @@ -8717,7 +8599,7 @@ function completeUnitOfWork(unitOfWork) { } else { current = unwindWork(current, completedWork); if (null !== current) { - current.flags &= 16383; + current.flags &= 32767; workInProgress = current; return; } @@ -8789,6 +8671,7 @@ function commitRootImpl( ); root.callbackNode = null; root.callbackPriority = 0; + root.cancelPendingCommit = null; var remainingLanes = transitions.lanes | transitions.childLanes; remainingLanes |= concurrentlyUpdatedLanes; markRootFinished(root, remainingLanes); @@ -8907,11 +8790,11 @@ function flushPassiveEffects() { _finishedWork$memoize = finishedWork.memoizedProps, id = _finishedWork$memoize.id, onPostCommit = _finishedWork$memoize.onPostCommit, - commitTime$88 = commitTime, + commitTime$93 = commitTime, phase = null === finishedWork.alternate ? "mount" : "update"; currentUpdateIsNested && (phase = "nested-update"); "function" === typeof onPostCommit && - onPostCommit(id, phase, passiveEffectDuration, commitTime$88); + onPostCommit(id, phase, passiveEffectDuration, commitTime$93); var parentFiber = finishedWork.return; b: for (; null !== parentFiber; ) { switch (parentFiber.tag) { @@ -9053,11 +8936,7 @@ function pingSuspendedRoot(root, wakeable, pingedLanes) { } function retryTimedOutBoundary(boundaryFiber, retryLane) { 0 === retryLane && - (0 === (boundaryFiber.mode & 1) - ? (retryLane = 2) - : ((retryLane = nextRetryLane), - (nextRetryLane <<= 1), - 0 === (nextRetryLane & 125829120) && (nextRetryLane = 8388608))); + (retryLane = 0 === (boundaryFiber.mode & 1) ? 2 : claimNextRetryLane()); var eventTime = requestEventTime(); boundaryFiber = enqueueConcurrentRenderForLane(boundaryFiber, retryLane); null !== boundaryFiber && @@ -9616,7 +9495,7 @@ function createWorkInProgress(current, pendingProps) { (workInProgress.deletions = null), (workInProgress.actualDuration = 0), (workInProgress.actualStartTime = -1)); - workInProgress.flags = current.flags & 14680064; + workInProgress.flags = current.flags & 31457280; workInProgress.childLanes = current.childLanes; workInProgress.lanes = current.lanes; workInProgress.child = current.child; @@ -9637,7 +9516,7 @@ function createWorkInProgress(current, pendingProps) { return workInProgress; } function resetWorkInProgress(workInProgress, renderLanes) { - workInProgress.flags &= 14680066; + workInProgress.flags &= 31457282; var current = workInProgress.alternate; null === current ? ((workInProgress.childLanes = 0), @@ -9740,229 +9619,494 @@ function createFiberFromTypeAndProps( break a; } 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) + ".") + "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) + ".") + ); + } + key = createFiber(fiberTag, pendingProps, key, mode); + key.elementType = type; + key.type = owner; + key.lanes = lanes; + return key; +} +function createFiberFromFragment(elements, mode, lanes, key) { + elements = createFiber(7, elements, key, mode); + elements.lanes = lanes; + return elements; +} +function createFiberFromOffscreen(pendingProps, mode, lanes, key) { + pendingProps = createFiber(22, pendingProps, key, mode); + pendingProps.elementType = REACT_OFFSCREEN_TYPE; + pendingProps.lanes = lanes; + var primaryChildInstance = { + _visibility: 1, + _pendingVisibility: 1, + _pendingMarkers: null, + _retryCache: null, + _transitions: null, + _current: null, + detach: function () { + return detachOffscreenInstance(primaryChildInstance); + }, + attach: function () { + return attachOffscreenInstance(primaryChildInstance); + } + }; + pendingProps.stateNode = primaryChildInstance; + return pendingProps; +} +function createFiberFromLegacyHidden(pendingProps, mode, lanes, key) { + pendingProps = createFiber(23, pendingProps, key, mode); + pendingProps.elementType = REACT_LEGACY_HIDDEN_TYPE; + pendingProps.lanes = lanes; + var instance = { + _visibility: 1, + _pendingVisibility: 1, + _pendingMarkers: null, + _transitions: null, + _retryCache: null, + _current: null, + detach: function () { + return detachOffscreenInstance(instance); + }, + attach: function () { + return attachOffscreenInstance(instance); + } + }; + pendingProps.stateNode = instance; + return pendingProps; +} +function createFiberFromText(content, mode, lanes) { + content = createFiber(6, content, null, mode); + content.lanes = lanes; + return content; +} +function createFiberFromPortal(portal, mode, lanes) { + mode = createFiber( + 4, + null !== portal.children ? portal.children : [], + portal.key, + mode + ); + mode.lanes = lanes; + mode.stateNode = { + containerInfo: portal.containerInfo, + pendingChildren: null, + implementation: portal.implementation + }; + return mode; +} +function FiberRootNode( + containerInfo, + tag, + hydrate, + identifierPrefix, + onRecoverableError +) { + this.tag = tag; + this.containerInfo = containerInfo; + this.finishedWork = + this.pingCache = + this.current = + this.pendingChildren = + null; + this.timeoutHandle = -1; + this.callbackNode = + this.pendingContext = + this.context = + this.cancelPendingCommit = + null; + this.callbackPriority = 0; + this.eventTimes = createLaneMap(0); + this.expirationTimes = createLaneMap(-1); + this.entangledLanes = + this.errorRecoveryDisabledLanes = + this.finishedLanes = + this.mutableReadLanes = + this.expiredLanes = + this.pingedLanes = + this.suspendedLanes = + this.pendingLanes = + 0; + this.entanglements = createLaneMap(0); + this.hiddenUpdates = createLaneMap(null); + this.identifierPrefix = identifierPrefix; + this.onRecoverableError = onRecoverableError; + this.incompleteTransitions = new Map(); + this.passiveEffectDuration = this.effectDuration = 0; + this.memoizedUpdaters = new Set(); + containerInfo = this.pendingUpdatersLaneMap = []; + for (tag = 0; 31 > tag; tag++) containerInfo.push(new Set()); +} +function createPortal$1(children, containerInfo, implementation) { + var key = + 3 < arguments.length && void 0 !== arguments[3] ? arguments[3] : null; + return { + $$typeof: REACT_PORTAL_TYPE, + key: null == key ? null : "" + key, + children: children, + containerInfo: containerInfo, + implementation: implementation + }; +} +function findHostInstance(component) { + var fiber = component._reactInternals; + if (void 0 === fiber) { + if ("function" === typeof component.render) + throw Error("Unable to find node on an unmounted component."); + component = Object.keys(component).join(","); + throw Error( + "Argument appears to not be a ReactComponent. Keys: " + component + ); + } + component = findCurrentHostFiber(fiber); + return null === component ? null : getPublicInstance(component.stateNode); +} +function updateContainer(element, container, parentComponent, callback) { + var current = container.current, + lane = requestUpdateLane(current); + null !== injectedProfilingHooks && + "function" === typeof injectedProfilingHooks.markRenderScheduled && + injectedProfilingHooks.markRenderScheduled(lane); + a: if (parentComponent) { + parentComponent = parentComponent._reactInternals; + b: { + if ( + getNearestMountedFiber(parentComponent) !== parentComponent || + 1 !== parentComponent.tag + ) + throw 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 JSCompiler_inline_result = parentComponent; + do { + switch (JSCompiler_inline_result.tag) { + case 3: + JSCompiler_inline_result = + JSCompiler_inline_result.stateNode.context; + break b; + case 1: + if (isContextProvider(JSCompiler_inline_result.type)) { + JSCompiler_inline_result = + JSCompiler_inline_result.stateNode + .__reactInternalMemoizedMergedChildContext; + break b; + } + } + JSCompiler_inline_result = JSCompiler_inline_result.return; + } while (null !== JSCompiler_inline_result); + throw Error( + "Found unexpected detached subtree parent. This error is likely caused by a bug in React. Please file an issue." + ); + } + if (1 === parentComponent.tag) { + var Component = parentComponent.type; + if (isContextProvider(Component)) { + parentComponent = processChildContext( + parentComponent, + Component, + JSCompiler_inline_result ); + break a; + } } - key = createFiber(fiberTag, pendingProps, key, mode); - key.elementType = type; - key.type = owner; - key.lanes = lanes; - return key; + parentComponent = JSCompiler_inline_result; + } else parentComponent = emptyContextObject; + null === container.context + ? (container.context = parentComponent) + : (container.pendingContext = parentComponent); + container = createUpdate(lane); + container.payload = { element: element }; + callback = void 0 === callback ? null : callback; + null !== callback && (container.callback = callback); + element = enqueueUpdate(current, container, lane); + null !== element && + ((callback = requestEventTime()), + scheduleUpdateOnFiber(element, current, lane, callback), + entangleTransitions(element, current, lane)); + return lane; } -function createFiberFromFragment(elements, mode, lanes, key) { - elements = createFiber(7, elements, key, mode); - elements.lanes = lanes; - return elements; +function emptyFindFiberByHostInstance() { + return null; } -function createFiberFromOffscreen(pendingProps, mode, lanes, key) { - pendingProps = createFiber(22, pendingProps, key, mode); - pendingProps.elementType = REACT_OFFSCREEN_TYPE; - pendingProps.lanes = lanes; - var primaryChildInstance = { - _visibility: 1, - _pendingVisibility: 1, - _pendingMarkers: null, - _retryCache: null, - _transitions: null, - _current: null, - detach: function () { - return detachOffscreenInstance(primaryChildInstance); - }, - attach: function () { - return attachOffscreenInstance(primaryChildInstance); - } - }; - pendingProps.stateNode = primaryChildInstance; - return pendingProps; +function findNodeHandle(componentOrHandle) { + if (null == componentOrHandle) return null; + if ("number" === typeof componentOrHandle) return componentOrHandle; + if (componentOrHandle._nativeTag) return componentOrHandle._nativeTag; + if ( + null != componentOrHandle.canonical && + null != componentOrHandle.canonical.nativeTag + ) + return componentOrHandle.canonical.nativeTag; + var nativeTag = componentOrHandle.__nativeTag; + if (nativeTag) return nativeTag; + componentOrHandle = findHostInstance(componentOrHandle); + return null == componentOrHandle + ? componentOrHandle + : null != componentOrHandle._nativeTag + ? componentOrHandle._nativeTag + : componentOrHandle.__nativeTag; } -function createFiberFromLegacyHidden(pendingProps, mode, lanes, key) { - pendingProps = createFiber(23, pendingProps, key, mode); - pendingProps.elementType = REACT_LEGACY_HIDDEN_TYPE; - pendingProps.lanes = lanes; - var instance = { - _visibility: 1, - _pendingVisibility: 1, - _pendingMarkers: null, - _transitions: null, - _retryCache: null, - _current: null, - detach: function () { - return detachOffscreenInstance(instance); - }, - attach: function () { - return attachOffscreenInstance(instance); +function getNodeFromInternalInstanceHandle(internalInstanceHandle) { + return ( + internalInstanceHandle && + internalInstanceHandle.stateNode && + internalInstanceHandle.stateNode.node + ); +} +var _nativeFabricUIManage$1 = nativeFabricUIManager, + fabricMeasure = _nativeFabricUIManage$1.measure, + fabricMeasureInWindow = _nativeFabricUIManage$1.measureInWindow, + fabricMeasureLayout = _nativeFabricUIManage$1.measureLayout, + _setNativeProps = _nativeFabricUIManage$1.setNativeProps, + fabricGetBoundingClientRect = _nativeFabricUIManage$1.getBoundingClientRect; +function noop() {} +var ReactFabricHostComponent = (function () { + function ReactFabricHostComponent(tag, viewConfig, internalInstanceHandle) { + this.__nativeTag = tag; + this._viewConfig = viewConfig; + this.__internalInstanceHandle = internalInstanceHandle; + } + var _proto = ReactFabricHostComponent.prototype; + _proto.blur = function () { + ReactNativePrivateInterface.TextInputState.blurTextInput(this); + }; + _proto.focus = function () { + ReactNativePrivateInterface.TextInputState.focusTextInput(this); + }; + _proto.measure = function (callback) { + var node = getNodeFromInternalInstanceHandle(this.__internalInstanceHandle); + null != node && fabricMeasure(node, callback); + }; + _proto.measureInWindow = function (callback) { + var node = getNodeFromInternalInstanceHandle(this.__internalInstanceHandle); + null != node && fabricMeasureInWindow(node, callback); + }; + _proto.measureLayout = function (relativeToNativeNode, onSuccess, onFail) { + if ( + "number" !== typeof relativeToNativeNode && + relativeToNativeNode instanceof ReactFabricHostComponent + ) { + var toStateNode = getNodeFromInternalInstanceHandle( + this.__internalInstanceHandle + ); + relativeToNativeNode = getNodeFromInternalInstanceHandle( + relativeToNativeNode.__internalInstanceHandle + ); + null != toStateNode && + null != relativeToNativeNode && + fabricMeasureLayout( + toStateNode, + relativeToNativeNode, + null != onFail ? onFail : noop, + null != onSuccess ? onSuccess : noop + ); } }; - pendingProps.stateNode = instance; - return pendingProps; + _proto.unstable_getBoundingClientRect = function () { + var node = getNodeFromInternalInstanceHandle(this.__internalInstanceHandle); + return null != node && (node = fabricGetBoundingClientRect(node)) + ? new DOMRect(node[0], node[1], node[2], node[3]) + : new DOMRect(0, 0, 0, 0); + }; + _proto.setNativeProps = function (nativeProps) { + nativeProps = diffProperties( + null, + emptyObject$1, + nativeProps, + this._viewConfig.validAttributes + ); + var node = getNodeFromInternalInstanceHandle(this.__internalInstanceHandle); + null != node && null != nativeProps && _setNativeProps(node, nativeProps); + }; + return ReactFabricHostComponent; +})(); +function batchedUpdatesImpl(fn, bookkeeping) { + return fn(bookkeeping); } -function createFiberFromText(content, mode, lanes) { - content = createFiber(6, content, null, mode); - content.lanes = lanes; - return content; +var isInsideEventHandler = !1; +function batchedUpdates(fn, bookkeeping) { + if (isInsideEventHandler) return fn(bookkeeping); + isInsideEventHandler = !0; + try { + return batchedUpdatesImpl(fn, bookkeeping); + } finally { + isInsideEventHandler = !1; + } } -function createFiberFromPortal(portal, mode, lanes) { - mode = createFiber( - 4, - null !== portal.children ? portal.children : [], - portal.key, - mode +var eventQueue = null; +function executeDispatchesAndReleaseTopLevel(e) { + if (e) { + var dispatchListeners = e._dispatchListeners, + dispatchInstances = e._dispatchInstances; + if (isArrayImpl(dispatchListeners)) + for ( + var i = 0; + i < dispatchListeners.length && !e.isPropagationStopped(); + i++ + ) + executeDispatch(e, dispatchListeners[i], dispatchInstances[i]); + else + dispatchListeners && + executeDispatch(e, dispatchListeners, dispatchInstances); + e._dispatchListeners = null; + e._dispatchInstances = null; + e.isPersistent() || e.constructor.release(e); + } +} +function dispatchEvent(target, topLevelType, nativeEvent) { + var eventTarget = null; + if (null != target) { + var stateNode = target.stateNode; + null != stateNode && (eventTarget = getPublicInstance(stateNode)); + } + batchedUpdates(function () { + var event = { eventName: topLevelType, nativeEvent: nativeEvent }; + ReactNativePrivateInterface.RawEventEmitter.emit(topLevelType, event); + ReactNativePrivateInterface.RawEventEmitter.emit("*", event); + event = eventTarget; + for ( + var events = null, legacyPlugins = plugins, i = 0; + i < legacyPlugins.length; + i++ + ) { + var possiblePlugin = legacyPlugins[i]; + possiblePlugin && + (possiblePlugin = possiblePlugin.extractEvents( + topLevelType, + target, + nativeEvent, + event + )) && + (events = accumulateInto(events, possiblePlugin)); + } + event = events; + null !== event && (eventQueue = accumulateInto(eventQueue, event)); + event = eventQueue; + eventQueue = null; + if (event) { + forEachAccumulated(event, executeDispatchesAndReleaseTopLevel); + if (eventQueue) + throw Error( + "processEventQueue(): Additional events were enqueued while processing an event queue. Support for this has not yet been implemented." + ); + if (hasRethrowError) + throw ( + ((event = rethrowError), + (hasRethrowError = !1), + (rethrowError = null), + event) + ); + } + }); +} +function shim() { + throw Error( + "The current renderer does not support hydration. This error is likely caused by a bug in React. Please file an issue." ); - mode.lanes = lanes; - mode.stateNode = { - containerInfo: portal.containerInfo, - pendingChildren: null, - implementation: portal.implementation - }; - return mode; } -function FiberRootNode( - containerInfo, - tag, - hydrate, - identifierPrefix, - onRecoverableError +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, + FabricDiscretePriority = _nativeFabricUIManage.unstable_DiscreteEventPriority, + fabricGetCurrentEventPriority = + _nativeFabricUIManage.unstable_getCurrentEventPriority, + getViewConfigForType = + ReactNativePrivateInterface.ReactNativeViewConfigRegistry.get, + nextReactTag = 2; +registerEventHandler && registerEventHandler(dispatchEvent); +function createTextInstance( + text, + rootContainerInstance, + hostContext, + internalInstanceHandle ) { - this.tag = tag; - this.containerInfo = containerInfo; - this.finishedWork = - this.pingCache = - this.current = - this.pendingChildren = - null; - this.timeoutHandle = -1; - this.callbackNode = this.pendingContext = this.context = null; - this.callbackPriority = 0; - this.eventTimes = createLaneMap(0); - this.expirationTimes = createLaneMap(-1); - this.entangledLanes = - this.errorRecoveryDisabledLanes = - this.finishedLanes = - this.mutableReadLanes = - this.expiredLanes = - this.pingedLanes = - this.suspendedLanes = - this.pendingLanes = - 0; - this.entanglements = createLaneMap(0); - this.hiddenUpdates = createLaneMap(null); - this.identifierPrefix = identifierPrefix; - this.onRecoverableError = onRecoverableError; - this.incompleteTransitions = new Map(); - this.passiveEffectDuration = this.effectDuration = 0; - this.memoizedUpdaters = new Set(); - containerInfo = this.pendingUpdatersLaneMap = []; - for (tag = 0; 31 > tag; tag++) containerInfo.push(new Set()); -} -function createPortal$1(children, containerInfo, implementation) { - var key = - 3 < arguments.length && void 0 !== arguments[3] ? arguments[3] : null; + hostContext = nextReactTag; + nextReactTag += 2; return { - $$typeof: REACT_PORTAL_TYPE, - key: null == key ? null : "" + key, - children: children, - containerInfo: containerInfo, - implementation: implementation + node: createNode( + hostContext, + "RCTRawText", + rootContainerInstance, + { text: text }, + internalInstanceHandle + ) }; } -function findHostInstance(component) { - var fiber = component._reactInternals; - if (void 0 === fiber) { - if ("function" === typeof component.render) - throw Error("Unable to find node on an unmounted component."); - component = Object.keys(component).join(","); - throw Error( - "Argument appears to not be a ReactComponent. Keys: " + component - ); - } - component = findCurrentHostFiber(fiber); - return null === component ? null : getPublicInstance(component.stateNode); +function getPublicInstance(instance) { + return null != instance.canonical && null != instance.canonical.publicInstance + ? instance.canonical.publicInstance + : null != instance._nativeTag + ? instance + : null; } -function updateContainer(element, container, parentComponent, callback) { - var current = container.current, - lane = requestUpdateLane(current); - null !== injectedProfilingHooks && - "function" === typeof injectedProfilingHooks.markRenderScheduled && - injectedProfilingHooks.markRenderScheduled(lane); - a: if (parentComponent) { - parentComponent = parentComponent._reactInternals; - b: { - if ( - getNearestMountedFiber(parentComponent) !== parentComponent || - 1 !== parentComponent.tag - ) - throw 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 JSCompiler_inline_result = parentComponent; - do { - switch (JSCompiler_inline_result.tag) { - case 3: - JSCompiler_inline_result = - JSCompiler_inline_result.stateNode.context; - break b; - case 1: - if (isContextProvider(JSCompiler_inline_result.type)) { - JSCompiler_inline_result = - JSCompiler_inline_result.stateNode - .__reactInternalMemoizedMergedChildContext; - break b; - } - } - JSCompiler_inline_result = JSCompiler_inline_result.return; - } while (null !== JSCompiler_inline_result); - throw Error( - "Found unexpected detached subtree parent. This error is likely caused by a bug in React. Please file an issue." - ); - } - if (1 === parentComponent.tag) { - var Component = parentComponent.type; - if (isContextProvider(Component)) { - parentComponent = processChildContext( - parentComponent, - Component, - JSCompiler_inline_result - ); - break a; - } - } - parentComponent = JSCompiler_inline_result; - } else parentComponent = emptyContextObject; - null === container.context - ? (container.context = parentComponent) - : (container.pendingContext = parentComponent); - container = createUpdate(lane); - container.payload = { element: element }; - callback = void 0 === callback ? null : callback; - null !== callback && (container.callback = callback); - element = enqueueUpdate(current, container, lane); - null !== element && - ((callback = requestEventTime()), - scheduleUpdateOnFiber(element, current, lane, callback), - entangleTransitions(element, current, lane)); - return lane; +var scheduleTimeout = setTimeout, + cancelTimeout = clearTimeout; +function cloneHiddenInstance(instance) { + var node = instance.node; + var JSCompiler_inline_result = diffProperties( + null, + emptyObject$1, + { style: { display: "none" } }, + instance.canonical.viewConfig.validAttributes + ); + return { + node: cloneNodeWithNewProps(node, JSCompiler_inline_result), + canonical: instance.canonical + }; } -function emptyFindFiberByHostInstance() { - return null; +function getInstanceFromNode(node) { + return null != node.canonical && null != node.canonical.internalInstanceHandle + ? node.canonical.internalInstanceHandle + : node; } -var emptyObject = {}, - createHierarchy, - getHostNode, - getHostProps, - lastNonHostInstance; -exports.getInspectorDataForInstance = void 0; -var getOwnerHierarchy, traverseOwnerTreeUp; -createHierarchy = function (fiberHierarchy) { - return fiberHierarchy.map(function (fiber) { +getFiberCurrentPropsFromNode$1 = function (instance) { + return instance.canonical.currentProps; +}; +getInstanceFromNode$1 = getInstanceFromNode; +getNodeFromInstance$1 = function (fiber) { + fiber = getPublicInstance(fiber.stateNode); + if (null == fiber) throw Error("Could not find host instance from fiber"); + return fiber; +}; +ResponderEventPlugin.injection.injectGlobalResponderHandler({ + onChange: function (from, to, blockNativeResponder) { + from && + from.stateNode && + nativeFabricUIManager.setIsJSResponder( + from.stateNode.node, + !1, + blockNativeResponder || !1 + ); + to && + to.stateNode && + nativeFabricUIManager.setIsJSResponder( + to.stateNode.node, + !0, + blockNativeResponder || !1 + ); + } +}); +var emptyObject = {}; +function createHierarchy(fiberHierarchy) { + return fiberHierarchy.map(function (fiber$jscomp$0) { return { - name: getComponentNameFromType(fiber.type), + name: getComponentNameFromType(fiber$jscomp$0.type), getInspectorData: function (findNodeHandle) { return { - props: getHostProps(fiber), - source: fiber._debugSource, + props: getHostProps(fiber$jscomp$0), + source: fiber$jscomp$0._debugSource, measure: function (callback) { - var hostFiber = findCurrentHostFiber(fiber); + var hostFiber = findCurrentHostFiber(fiber$jscomp$0); if ( (hostFiber = null != hostFiber && @@ -9970,82 +10114,43 @@ createHierarchy = function (fiberHierarchy) { hostFiber.stateNode.node) ) nativeFabricUIManager.measure(hostFiber, callback); - else - return ReactNativePrivateInterface.UIManager.measure( - getHostNode(fiber, findNodeHandle), + else { + hostFiber = ReactNativePrivateInterface.UIManager; + var JSCompiler_temp_const = hostFiber.measure, + JSCompiler_inline_result; + a: { + for (var fiber = fiber$jscomp$0; fiber; ) { + null !== fiber.stateNode && + 5 === fiber.tag && + (JSCompiler_inline_result = findNodeHandle( + fiber.stateNode + )); + if (JSCompiler_inline_result) break a; + fiber = fiber.child; + } + JSCompiler_inline_result = null; + } + return JSCompiler_temp_const.call( + hostFiber, + JSCompiler_inline_result, callback ); + } } }; } }; }); -}; -getHostNode = function (fiber, findNodeHandle) { - for (var hostNode; fiber; ) { - null !== fiber.stateNode && - 5 === fiber.tag && - (hostNode = findNodeHandle(fiber.stateNode)); - if (hostNode) return hostNode; - fiber = fiber.child; - } - return null; -}; -getHostProps = function (fiber) { +} +function getHostProps(fiber) { return (fiber = findCurrentHostFiber(fiber)) ? fiber.memoizedProps || emptyObject : emptyObject; -}; -exports.getInspectorDataForInstance = function (closestInstance) { - if (!closestInstance) - return { - hierarchy: [], - props: emptyObject, - selectedIndex: null, - source: null - }; - closestInstance = findCurrentFiberUsingSlowPath(closestInstance); - var fiberHierarchy = getOwnerHierarchy(closestInstance); - closestInstance = lastNonHostInstance(fiberHierarchy); - var hierarchy = createHierarchy(fiberHierarchy), - props = getHostProps(closestInstance), - source = closestInstance._debugSource; - fiberHierarchy = fiberHierarchy.indexOf(closestInstance); - return { - closestInstance: closestInstance, - hierarchy: hierarchy, - props: props, - selectedIndex: fiberHierarchy, - source: source - }; -}; -getOwnerHierarchy = function (instance) { - var hierarchy = []; - traverseOwnerTreeUp(hierarchy, instance); - return hierarchy; -}; -lastNonHostInstance = function (hierarchy) { - for (var i = hierarchy.length - 1; 1 < i; i--) { - var instance = hierarchy[i]; - if (5 !== instance.tag) return instance; - } - return hierarchy[0]; -}; -traverseOwnerTreeUp = function (hierarchy, instance) { +} +function traverseOwnerTreeUp(hierarchy, instance) { instance && (hierarchy.unshift(instance), traverseOwnerTreeUp(hierarchy, instance._debugOwner)); -}; -function findNodeHandle(componentOrHandle) { - if (null == componentOrHandle) return null; - if ("number" === typeof componentOrHandle) return componentOrHandle; - if (componentOrHandle._nativeTag) return componentOrHandle._nativeTag; - if (componentOrHandle.canonical && componentOrHandle.canonical._nativeTag) - return componentOrHandle.canonical._nativeTag; - componentOrHandle = findHostInstance(componentOrHandle); - return null == componentOrHandle - ? componentOrHandle - : componentOrHandle._nativeTag; } function onRecoverableError(error) { console.error(error); @@ -10063,10 +10168,10 @@ batchedUpdatesImpl = function (fn, a) { } }; var roots = new Map(), - devToolsConfig$jscomp$inline_1063 = { + devToolsConfig$jscomp$inline_1107 = { findFiberByHostInstance: getInstanceFromNode, bundleType: 0, - version: "18.3.0-next-ef8bdbecb-20230310", + version: "18.3.0-next-c57b90f50-20230320", rendererPackageName: "react-native-renderer", rendererConfig: { getInspectorDataForViewTag: function () { @@ -10095,10 +10200,10 @@ var roots = new Map(), } catch (err) {} return hook.checkDCE ? !0 : !1; })({ - bundleType: devToolsConfig$jscomp$inline_1063.bundleType, - version: devToolsConfig$jscomp$inline_1063.version, - rendererPackageName: devToolsConfig$jscomp$inline_1063.rendererPackageName, - rendererConfig: devToolsConfig$jscomp$inline_1063.rendererConfig, + bundleType: devToolsConfig$jscomp$inline_1107.bundleType, + version: devToolsConfig$jscomp$inline_1107.version, + rendererPackageName: devToolsConfig$jscomp$inline_1107.rendererPackageName, + rendererConfig: devToolsConfig$jscomp$inline_1107.rendererConfig, overrideHookState: null, overrideHookStateDeletePath: null, overrideHookStateRenamePath: null, @@ -10114,14 +10219,14 @@ var roots = new Map(), return null === fiber ? null : fiber.stateNode; }, findFiberByHostInstance: - devToolsConfig$jscomp$inline_1063.findFiberByHostInstance || + devToolsConfig$jscomp$inline_1107.findFiberByHostInstance || emptyFindFiberByHostInstance, findHostInstancesForRefresh: null, scheduleRefresh: null, scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "18.3.0-next-ef8bdbecb-20230310" + reconcilerVersion: "18.3.0-next-c57b90f50-20230320" }); exports.createPortal = function (children, containerTag) { return createPortal$1( @@ -10132,13 +10237,16 @@ exports.createPortal = function (children, containerTag) { ); }; exports.dispatchCommand = function (handle, command, args) { - null != handle._nativeTag && - (null != handle._internalInstanceHandle - ? ((handle = handle._internalInstanceHandle.stateNode), - null != handle && - nativeFabricUIManager.dispatchCommand(handle.node, command, args)) + var nativeTag = + null != handle._nativeTag ? handle._nativeTag : handle.__nativeTag; + null != nativeTag && + ((handle = handle.__internalInstanceHandle), + null != handle + ? ((nativeTag = getNodeFromInternalInstanceHandle(handle)), + null != nativeTag && + nativeFabricUIManager.dispatchCommand(nativeTag, command, args)) : ReactNativePrivateInterface.UIManager.dispatchViewManagerCommand( - handle._nativeTag, + nativeTag, command, args )); @@ -10146,13 +10254,47 @@ exports.dispatchCommand = function (handle, command, args) { exports.findHostInstance_DEPRECATED = function (componentOrHandle) { return null == componentOrHandle ? null + : componentOrHandle.canonical && componentOrHandle.canonical.publicInstance + ? componentOrHandle.canonical.publicInstance : componentOrHandle._nativeTag ? componentOrHandle - : componentOrHandle.canonical && componentOrHandle.canonical._nativeTag - ? componentOrHandle.canonical : findHostInstance(componentOrHandle); }; exports.findNodeHandle = findNodeHandle; +exports.getInspectorDataForInstance = function (closestInstance) { + if (!closestInstance) + return { + hierarchy: [], + props: emptyObject, + selectedIndex: null, + source: null + }; + var fiber = findCurrentFiberUsingSlowPath(closestInstance); + closestInstance = []; + traverseOwnerTreeUp(closestInstance, fiber); + a: { + for (fiber = closestInstance.length - 1; 1 < fiber; fiber--) { + var instance = closestInstance[fiber]; + if (5 !== instance.tag) { + fiber = instance; + break a; + } + } + fiber = closestInstance[0]; + } + instance = createHierarchy(closestInstance); + var props = getHostProps(fiber), + source = fiber._debugSource; + closestInstance = closestInstance.indexOf(fiber); + return { + closestInstance: fiber, + hierarchy: instance, + props: props, + selectedIndex: closestInstance, + source: source + }; +}; +exports.getNodeFromInternalInstanceHandle = getNodeFromInternalInstanceHandle; exports.render = function (element, containerTag, callback, concurrentRoot) { var root = roots.get(containerTag); root || @@ -10187,13 +10329,16 @@ exports.render = function (element, containerTag, callback, concurrentRoot) { return element; }; exports.sendAccessibilityEvent = function (handle, eventType) { - null != handle._nativeTag && - (null != handle._internalInstanceHandle - ? ((handle = handle._internalInstanceHandle.stateNode), - null != handle && - nativeFabricUIManager.sendAccessibilityEvent(handle.node, eventType)) + var nativeTag = + null != handle._nativeTag ? handle._nativeTag : handle.__nativeTag; + null != nativeTag && + ((handle = handle.__internalInstanceHandle), + null != handle + ? ((nativeTag = getNodeFromInternalInstanceHandle(handle)), + null != nativeTag && + nativeFabricUIManager.sendAccessibilityEvent(nativeTag, eventType)) : ReactNativePrivateInterface.legacySendAccessibilityEvent( - handle._nativeTag, + nativeTag, eventType )); }; diff --git a/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactNativeRenderer-dev.fb.js b/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactNativeRenderer-dev.fb.js index 524c53a89ca9d..6d2f812f644e8 100644 --- a/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactNativeRenderer-dev.fb.js +++ b/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactNativeRenderer-dev.fb.js @@ -428,10 +428,9 @@ function setComponentTree( } } } -var validateEventDispatches; -{ - validateEventDispatches = function (event) { +function validateEventDispatches(event) { + { var dispatchListeners = event._dispatchListeners; var dispatchInstances = event._dispatchInstances; var listenersIsArr = isArray(dispatchListeners); @@ -450,7 +449,7 @@ var validateEventDispatches; if (instancesIsArr !== listenersIsArr || instancesLen !== listenersLen) { error("EventPluginUtils: Invalid `event`."); } - }; + } } /** * Dispatch the event to the listener. @@ -1307,7 +1306,7 @@ var responderInst = null; var trackedTouchCount = 0; -var changeResponder = function (nextResponderInst, blockHostResponder) { +function changeResponder(nextResponderInst, blockHostResponder) { var oldResponderInst = responderInst; responderInst = nextResponderInst; @@ -1318,7 +1317,7 @@ var changeResponder = function (nextResponderInst, blockHostResponder) { blockHostResponder ); } -}; +} var eventTypes = { /** @@ -2557,9 +2556,10 @@ function getTagFromInstance(inst) { var nativeInstance = inst.stateNode; var tag = nativeInstance._nativeTag; - if (tag === undefined) { - nativeInstance = nativeInstance.canonical; - tag = nativeInstance._nativeTag; + if (tag === undefined && nativeInstance.canonical != null) { + // For compatibility with Fabric + tag = nativeInstance.canonical.nativeTag; + nativeInstance = nativeInstance.canonical.publicInstance; } if (!tag) { @@ -2618,7 +2618,7 @@ var eventQueue = null; * @private */ -var executeDispatchesAndRelease = function (event) { +function executeDispatchesAndRelease(event) { if (event) { executeDispatchesInOrder(event); @@ -2626,11 +2626,11 @@ var executeDispatchesAndRelease = function (event) { event.constructor.release(event); } } -}; // $FlowFixMe[missing-local-annot] +} // $FlowFixMe[missing-local-annot] -var executeDispatchesAndReleaseTopLevel = function (e) { +function executeDispatchesAndReleaseTopLevel(e) { return executeDispatchesAndRelease(e); -}; +} function runEventsInBatch(events) { if (events !== null) { @@ -2673,7 +2673,7 @@ var EMPTY_NATIVE_EVENT = {}; */ // $FlowFixMe[missing-local-annot] -var touchSubsequence = function (touches, indices) { +function touchSubsequence(touches, indices) { var ret = []; for (var i = 0; i < indices.length; i++) { @@ -2681,7 +2681,7 @@ var touchSubsequence = function (touches, indices) { } return ret; -}; +} /** * TODO: Pool all of this. * @@ -2694,7 +2694,7 @@ var touchSubsequence = function (touches, indices) { * @return {Array} Subsequence of removed touch objects. */ -var removeTouchesAtIndices = function (touches, indices) { +function removeTouchesAtIndices(touches, indices) { var rippedOut = []; // use an unsafe downcast to alias to nullable elements, // so we can delete and then compact. @@ -2718,7 +2718,7 @@ var removeTouchesAtIndices = function (touches, indices) { temp.length = fillAt; return rippedOut; -}; +} /** * Internal version of `receiveEvent` in terms of normalized (non-tag) * `rootNodeID`. @@ -3199,7 +3199,7 @@ var Hydrating = var Update = /* */ 4; -/* Skipped value: 0b000000000000000000000001000; */ +/* Skipped value: 0b0000000000000000000000001000; */ var ChildDeletion = /* */ @@ -3210,7 +3210,7 @@ var ContentReset = var Callback = /* */ 64; -/* Used by DidCapture: 0b000000000000000000010000000; */ +/* Used by DidCapture: 0b0000000000000000000010000000; */ var ForceClientRender = /* */ @@ -3224,20 +3224,24 @@ var Snapshot = var Passive$1 = /* */ 2048; -/* Used by Hydrating: 0b000000000000001000000000000; */ +/* Used by Hydrating: 0b0000000000000001000000000000; */ var Visibility = /* */ 8192; var StoreConsistency = /* */ - 16384; + 16384; // It's OK to reuse this bit because these flags are mutually exclusive for +// different fiber types. We should really be doing this for as many flags as +// possible, because we're about to run out of bits. + +var ScheduleRetry = StoreConsistency; var LifecycleEffectMask = Passive$1 | Update | Callback | Ref | Snapshot | StoreConsistency; // Union of all commit flags (flags with the lifetime of a particular commit) var HostEffectMask = /* */ - 16383; // These are not really side effects, but we still reuse this field. + 32767; // These are not really side effects, but we still reuse this field. var Incomplete = /* */ @@ -3264,17 +3268,20 @@ var LayoutStatic = 4194304; var PassiveStatic = /* */ - 8388608; // Flag used to identify newly inserted fibers. It isn't reset after commit unlike `Placement`. + 8388608; +var SuspenseyCommit = + /* */ + 16777216; // Flag used to identify newly inserted fibers. It isn't reset after commit unlike `Placement`. var PlacementDEV = /* */ - 16777216; + 33554432; var MountLayoutDev = /* */ - 33554432; + 67108864; var MountPassiveDev = /* */ - 67108864; // Groups of flags that are used in the commit phase to skip over trees that + 134217728; // Groups of flags that are used in the commit phase to skip over trees that // don't contain effects, by checking subtreeFlags. var BeforeMutationMask = // TODO: Remove Update flag from before mutation phase by re-landing Visibility @@ -3294,7 +3301,7 @@ var PassiveMask = Passive$1 | Visibility | ChildDeletion; // Union of tags that // 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 StaticMask = LayoutStatic | PassiveStatic | RefStatic | SuspenseyCommit; var ReactCurrentOwner$3 = ReactSharedInternals.ReactCurrentOwner; function getNearestMountedFiber(fiber) { @@ -5815,8 +5822,8 @@ function getChildHostContext(parentHostContext, type) { } function getPublicInstance(instance) { // $FlowExpectedError[prop-missing] For compatibility with Fabric - if (instance.canonical) { - return instance.canonical; + if (instance.canonical != null && instance.canonical.publicInstance != null) { + return instance.canonical.publicInstance; } return instance; @@ -6018,6 +6025,9 @@ function unhideInstance(instance, props) { function unhideTextInstance(textInstance, text) { throw new Error("Not yet implemented."); } +function waitForCommitToBeReady() { + return null; +} function describeBuiltInComponentFrame(name, source, ownerFn) { { @@ -6629,46 +6639,71 @@ function flushSyncCallbacksOnlyInLegacyMode() { function flushSyncCallbacks() { if (!isFlushingSyncQueue && syncQueue !== null) { // Prevent re-entrance. - isFlushingSyncQueue = true; - var i = 0; - var previousUpdatePriority = getCurrentUpdatePriority(); + isFlushingSyncQueue = true; // Set the event priority to discrete + // TODO: Is this necessary anymore? The only user code that runs in this + // queue is in the render or commit phases, which already set the + // event priority. Should be able to remove. - 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); // $FlowFixMe[incompatible-use] found when upgrading Flow + var previousUpdatePriority = getCurrentUpdatePriority(); + setCurrentUpdatePriority(DiscreteEventPriority); + var errors = null; + var queue = syncQueue; // $FlowFixMe[incompatible-use] found when upgrading Flow - for (; i < queue.length; i++) { - // $FlowFixMe[incompatible-use] found when upgrading Flow - var callback = queue[i]; + for (var i = 0; i < queue.length; i++) { + // $FlowFixMe[incompatible-use] found when upgrading Flow + var callback = queue[i]; + try { do { - // $FlowFixMe[incompatible-type] we bail out when we get a null + var isSync = true; // $FlowFixMe[incompatible-type] we bail out when we get a null + callback = callback(isSync); } while (callback !== null); + } catch (error) { + // Collect errors so we can rethrow them at the end + if (errors === null) { + errors = [error]; + } else { + errors.push(error); + } } + } - 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 + syncQueue = null; + includesLegacySyncCallbacks = false; + setCurrentUpdatePriority(previousUpdatePriority); + isFlushingSyncQueue = false; - scheduleCallback$1(ImmediatePriority, flushSyncCallbacks); - throw error; - } finally { - setCurrentUpdatePriority(previousUpdatePriority); - isFlushingSyncQueue = false; + if (errors !== null) { + if (errors.length > 1) { + if (typeof AggregateError === "function") { + // eslint-disable-next-line no-undef + throw new AggregateError(errors); + } else { + for (var _i = 1; _i < errors.length; _i++) { + scheduleCallback$1( + ImmediatePriority, + throwError.bind(null, errors[_i]) + ); + } + + var firstError = errors[0]; + throw firstError; + } + } else { + var error = errors[0]; + throw error; + } } } return null; } +function throwError(error) { + throw error; +} + // 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. @@ -8183,6 +8218,172 @@ function checkPropStringCoercion(value, propName) { } } +var ReactCurrentActQueue$2 = ReactSharedInternals.ReactCurrentActQueue; // An error that is thrown (e.g. by `use`) to trigger Suspense. If we +// detect this is caught by userspace, we'll log a warning in development. + +var SuspenseException = new Error( + "Suspense Exception: This is not a real error! It's an implementation " + + "detail of `use` to interrupt the current render. You must either " + + "rethrow it immediately, or move the `use` call outside of the " + + "`try/catch` block. Capturing without rethrowing will lead to " + + "unexpected behavior.\n\n" + + "To handle async errors, wrap your component in an error boundary, or " + + "call the promise's `.catch` method and pass the result to `use`" +); // This is a noop thenable that we use to trigger a fallback in throwException. +// TODO: It would be better to refactor throwException into multiple functions +// so we can trigger a fallback directly without having to check the type. But +// for now this will do. + +var noopSuspenseyCommitThenable = { + then: function () {} +}; +function createThenableState() { + // The ThenableState is created the first time a component suspends. If it + // suspends again, we'll reuse the same state. + return []; +} +function isThenableResolved(thenable) { + var status = thenable.status; + return status === "fulfilled" || status === "rejected"; +} + +function noop() {} + +function trackUsedThenable(thenableState, thenable, index) { + if (ReactCurrentActQueue$2.current !== null) { + ReactCurrentActQueue$2.didUsePromise = true; + } + + var previous = thenableState[index]; + + if (previous === undefined) { + thenableState.push(thenable); + } else { + if (previous !== thenable) { + // Reuse the previous thenable, and drop the new one. We can assume + // they represent the same value, because components are idempotent. + // Avoid an unhandled rejection errors for the Promises that we'll + // intentionally ignore. + thenable.then(noop, noop); + thenable = previous; + } + } // We use an expando to track the status and result of a thenable so that we + // can synchronously unwrap the value. Think of this as an extension of the + // Promise API, or a custom interface that is a superset of Thenable. + // + // If the thenable doesn't have a status, set it to "pending" and attach + // a listener that will update its status and result when it resolves. + + switch (thenable.status) { + case "fulfilled": { + var fulfilledValue = thenable.value; + return fulfilledValue; + } + + case "rejected": { + var rejectedError = thenable.reason; + throw rejectedError; + } + + default: { + if (typeof thenable.status === "string") { + // Only instrument the thenable if the status if not defined. If + // it's defined, but an unknown value, assume it's been instrumented by + // some custom userspace implementation. We treat it as "pending". + // Attach a dummy listener, to ensure that any lazy initialization can + // happen. Flight lazily parses JSON when the value is actually awaited. + thenable.then(noop, noop); + } else { + var pendingThenable = thenable; + pendingThenable.status = "pending"; + pendingThenable.then( + function (fulfilledValue) { + if (thenable.status === "pending") { + var fulfilledThenable = thenable; + fulfilledThenable.status = "fulfilled"; + fulfilledThenable.value = fulfilledValue; + } + }, + function (error) { + if (thenable.status === "pending") { + var rejectedThenable = thenable; + rejectedThenable.status = "rejected"; + rejectedThenable.reason = error; + } + } + ); + } // Check one more time in case the thenable resolved synchronously. + + switch (thenable.status) { + case "fulfilled": { + var fulfilledThenable = thenable; + return fulfilledThenable.value; + } + + case "rejected": { + var rejectedThenable = thenable; + throw rejectedThenable.reason; + } + } // Suspend. + // + // Throwing here is an implementation detail that allows us to unwind the + // call stack. But we shouldn't allow it to leak into userspace. Throw an + // opaque placeholder value instead of the actual thenable. If it doesn't + // get captured by the work loop, log a warning, because that means + // something in userspace must have caught it. + + suspendedThenable = thenable; + + { + needsToResetSuspendedThenableDEV = true; + } + + throw SuspenseException; + } + } +} +// passed to the rest of the Suspense implementation — which, for historical +// reasons, expects to receive a thenable. + +var suspendedThenable = null; +var needsToResetSuspendedThenableDEV = false; +function getSuspendedThenable() { + // This is called right after `use` suspends by throwing an exception. `use` + // throws an opaque value instead of the thenable itself so that it can't be + // caught in userspace. Then the work loop accesses the actual thenable using + // this function. + if (suspendedThenable === null) { + throw new Error( + "Expected a suspended thenable. This is a bug in React. Please file " + + "an issue." + ); + } + + var thenable = suspendedThenable; + suspendedThenable = null; + + { + needsToResetSuspendedThenableDEV = false; + } + + return thenable; +} +function checkIfUseWrappedInTryCatch() { + { + // This was set right before SuspenseException was thrown, and it should + // have been cleared when the exception was handled. If it wasn't, + // it must have been caught by userspace. + if (needsToResetSuspendedThenableDEV) { + needsToResetSuspendedThenableDEV = false; + return true; + } + } + + return false; +} + +var thenableState$1 = null; +var thenableIndexCounter$1 = 0; var didWarnAboutMaps; var didWarnAboutGenerators; var didWarnAboutStringRefs; @@ -8241,6 +8442,17 @@ function isReactClass(type) { return type.prototype && type.prototype.isReactComponent; } +function unwrapThenable(thenable) { + var index = thenableIndexCounter$1; + thenableIndexCounter$1 += 1; + + if (thenableState$1 === null) { + thenableState$1 = createThenableState(); + } + + return trackUsedThenable(thenableState$1, thenable, index); +} + function coerceRef(returnFiber, current, element) { var mixedRef = element.ref; @@ -8660,6 +8872,25 @@ function createChildReconciler(shouldTrackSideEffects) { _created3.return = returnFiber; return _created3; + } // Usable node types + // + // Unwrap the inner value and recursively call this function again. + + if (typeof newChild.then === "function") { + var thenable = newChild; + return createChild(returnFiber, unwrapThenable(thenable), lanes); + } + + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) { + var context = newChild; + return createChild( + returnFiber, + readContextDuringReconcilation(returnFiber, context, lanes), + lanes + ); } throwOnInvalidObjectType(returnFiber, newChild); @@ -8723,6 +8954,31 @@ function createChildReconciler(shouldTrackSideEffects) { } return updateFragment(returnFiber, oldFiber, newChild, lanes, null); + } // Usable node types + // + // Unwrap the inner value and recursively call this function again. + + if (typeof newChild.then === "function") { + var thenable = newChild; + return updateSlot( + returnFiber, + oldFiber, + unwrapThenable(thenable), + lanes + ); + } + + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) { + var context = newChild; + return updateSlot( + returnFiber, + oldFiber, + readContextDuringReconcilation(returnFiber, context, lanes), + lanes + ); } throwOnInvalidObjectType(returnFiber, newChild); @@ -8796,6 +9052,33 @@ function createChildReconciler(shouldTrackSideEffects) { lanes, null ); + } // Usable node types + // + // Unwrap the inner value and recursively call this function again. + + if (typeof newChild.then === "function") { + var thenable = newChild; + return updateFromMap( + existingChildren, + returnFiber, + newIdx, + unwrapThenable(thenable), + lanes + ); + } + + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) { + var context = newChild; + return updateFromMap( + existingChildren, + returnFiber, + newIdx, + readContextDuringReconcilation(returnFiber, context, lanes), + lanes + ); } throwOnInvalidObjectType(returnFiber, newChild); @@ -9385,7 +9668,7 @@ function createChildReconciler(shouldTrackSideEffects) { // itself. They will be added to the side-effect list as we pass through the // children and the parent. - function reconcileChildFibers( + function reconcileChildFibersImpl( returnFiber, currentFirstChild, newChild, @@ -9398,6 +9681,7 @@ function createChildReconciler(shouldTrackSideEffects) { // Handle top level unkeyed fragments as if they were arrays. // This leads to an ambiguity between <>{[...]} and <>.... // We treat the ambiguous cases above the same. + // TODO: Let's use recursion like we do for Usable nodes? var isUnkeyedTopLevelFragment = typeof newChild === "object" && newChild !== null && @@ -9458,12 +9742,50 @@ function createChildReconciler(shouldTrackSideEffects) { newChild, lanes ); + } // Usables are a valid React node type. When React encounters a Usable in + // a child position, it unwraps it using the same algorithm as `use`. For + // example, for promises, React will throw an exception to unwind the + // stack, then replay the component once the promise resolves. + // + // A difference from `use` is that React will keep unwrapping the value + // until it reaches a non-Usable type. + // + // e.g. Usable>> should resolve to T + // + // The structure is a bit unfortunate. Ideally, we shouldn't need to + // replay the entire begin phase of the parent fiber in order to reconcile + // the children again. This would require a somewhat significant refactor, + // because reconcilation happens deep within the begin phase, and + // depending on the type of work, not always at the end. We should + // consider as an future improvement. + + if (typeof newChild.then === "function") { + var thenable = newChild; + return reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + unwrapThenable(thenable), + lanes + ); } - throwOnInvalidObjectType(returnFiber, newChild); - } - - if ( + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) { + var context = newChild; + return reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + readContextDuringReconcilation(returnFiber, context, lanes), + lanes + ); + } + + throwOnInvalidObjectType(returnFiber, newChild); + } + + if ( (typeof newChild === "string" && newChild !== "") || typeof newChild === "number" ) { @@ -9486,11 +9808,37 @@ function createChildReconciler(shouldTrackSideEffects) { return deleteRemainingChildren(returnFiber, currentFirstChild); } + function reconcileChildFibers( + returnFiber, + currentFirstChild, + newChild, + lanes + ) { + // This indirection only exists so we can reset `thenableState` at the end. + // It should get inlined by Closure. + thenableIndexCounter$1 = 0; + var firstChildFiber = reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + newChild, + lanes + ); + thenableState$1 = null; // Don't bother to reset `thenableIndexCounter` to 0 because it always gets + // set at the beginning. + + return firstChildFiber; + } + return reconcileChildFibers; } var reconcileChildFibers = createChildReconciler(true); var mountChildFibers = createChildReconciler(false); +function resetChildReconcilerOnUnwind() { + // On unwind, clear any pending thenables that were used. + thenableState$1 = null; + thenableIndexCounter$1 = 0; +} function cloneChildFibers(current, workInProgress) { if (current !== null && workInProgress.child !== current.child) { throw new Error("Resuming work not yet implemented."); @@ -9801,163 +10149,6 @@ function warnAboutMultipleRenderersDEV(mutableSource) { } } // Eager reads the version of a mutable source and stores it on the root. -var ReactCurrentActQueue$2 = ReactSharedInternals.ReactCurrentActQueue; // An error that is thrown (e.g. by `use`) to trigger Suspense. If we -// detect this is caught by userspace, we'll log a warning in development. - -var SuspenseException = new Error( - "Suspense Exception: This is not a real error! It's an implementation " + - "detail of `use` to interrupt the current render. You must either " + - "rethrow it immediately, or move the `use` call outside of the " + - "`try/catch` block. Capturing without rethrowing will lead to " + - "unexpected behavior.\n\n" + - "To handle async errors, wrap your component in an error boundary, or " + - "call the promise's `.catch` method and pass the result to `use`" -); -function createThenableState() { - // The ThenableState is created the first time a component suspends. If it - // suspends again, we'll reuse the same state. - return []; -} -function isThenableResolved(thenable) { - var status = thenable.status; - return status === "fulfilled" || status === "rejected"; -} - -function noop() {} - -function trackUsedThenable(thenableState, thenable, index) { - if (ReactCurrentActQueue$2.current !== null) { - ReactCurrentActQueue$2.didUsePromise = true; - } - - var previous = thenableState[index]; - - if (previous === undefined) { - thenableState.push(thenable); - } else { - if (previous !== thenable) { - // Reuse the previous thenable, and drop the new one. We can assume - // they represent the same value, because components are idempotent. - // Avoid an unhandled rejection errors for the Promises that we'll - // intentionally ignore. - thenable.then(noop, noop); - thenable = previous; - } - } // We use an expando to track the status and result of a thenable so that we - // can synchronously unwrap the value. Think of this as an extension of the - // Promise API, or a custom interface that is a superset of Thenable. - // - // If the thenable doesn't have a status, set it to "pending" and attach - // a listener that will update its status and result when it resolves. - - switch (thenable.status) { - case "fulfilled": { - var fulfilledValue = thenable.value; - return fulfilledValue; - } - - case "rejected": { - var rejectedError = thenable.reason; - throw rejectedError; - } - - default: { - if (typeof thenable.status === "string") { - // Only instrument the thenable if the status if not defined. If - // it's defined, but an unknown value, assume it's been instrumented by - // some custom userspace implementation. We treat it as "pending". - // Attach a dummy listener, to ensure that any lazy initialization can - // happen. Flight lazily parses JSON when the value is actually awaited. - thenable.then(noop, noop); - } else { - var pendingThenable = thenable; - pendingThenable.status = "pending"; - pendingThenable.then( - function (fulfilledValue) { - if (thenable.status === "pending") { - var fulfilledThenable = thenable; - fulfilledThenable.status = "fulfilled"; - fulfilledThenable.value = fulfilledValue; - } - }, - function (error) { - if (thenable.status === "pending") { - var rejectedThenable = thenable; - rejectedThenable.status = "rejected"; - rejectedThenable.reason = error; - } - } - ); - } // Check one more time in case the thenable resolved synchronously. - - switch (thenable.status) { - case "fulfilled": { - var fulfilledThenable = thenable; - return fulfilledThenable.value; - } - - case "rejected": { - var rejectedThenable = thenable; - throw rejectedThenable.reason; - } - } // Suspend. - // - // Throwing here is an implementation detail that allows us to unwind the - // call stack. But we shouldn't allow it to leak into userspace. Throw an - // opaque placeholder value instead of the actual thenable. If it doesn't - // get captured by the work loop, log a warning, because that means - // something in userspace must have caught it. - - suspendedThenable = thenable; - - { - needsToResetSuspendedThenableDEV = true; - } - - throw SuspenseException; - } - } -} // This is used to track the actual thenable that suspended so it can be -// passed to the rest of the Suspense implementation — which, for historical -// reasons, expects to receive a thenable. - -var suspendedThenable = null; -var needsToResetSuspendedThenableDEV = false; -function getSuspendedThenable() { - // This is called right after `use` suspends by throwing an exception. `use` - // throws an opaque value instead of the thenable itself so that it can't be - // caught in userspace. Then the work loop accesses the actual thenable using - // this function. - if (suspendedThenable === null) { - throw new Error( - "Expected a suspended thenable. This is a bug in React. Please file " + - "an issue." - ); - } - - var thenable = suspendedThenable; - suspendedThenable = null; - - { - needsToResetSuspendedThenableDEV = false; - } - - return thenable; -} -function checkIfUseWrappedInTryCatch() { - { - // This was set right before SuspenseException was thrown, and it should - // have been cleared when the exception was handled. If it wasn't, - // it must have been caught by userspace. - if (needsToResetSuspendedThenableDEV) { - needsToResetSuspendedThenableDEV = false; - return true; - } - } - - return false; -} - var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, ReactCurrentBatchConfig$2 = ReactSharedInternals.ReactCurrentBatchConfig; var didWarnAboutMismatchedHooksForComponent; @@ -11856,10 +12047,10 @@ function startTransition(setPending, callback, options) { setCurrentUpdatePriority( higherEventPriority(previousPriority, ContinuousEventPriority) ); - setPending(true); var prevTransition = ReactCurrentBatchConfig$2.transition; - ReactCurrentBatchConfig$2.transition = {}; - var currentTransition = ReactCurrentBatchConfig$2.transition; + ReactCurrentBatchConfig$2.transition = null; + setPending(true); + var currentTransition = (ReactCurrentBatchConfig$2.transition = {}); { ReactCurrentBatchConfig$2.transition._updatedFibers = new Set(); @@ -13264,11 +13455,10 @@ var didWarnAboutUninitializedState; var didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate; var didWarnAboutLegacyLifecyclesAndDerivedState; var didWarnAboutUndefinedDerivedState; -var warnOnUndefinedDerivedState; -var warnOnInvalidCallback; var didWarnAboutDirectlyAssigningPropsToState; var didWarnAboutContextTypeAndContextTypes; var didWarnAboutInvalidateContextType; +var didWarnOnInvalidCallback; { didWarnAboutStateAssignmentForComponent = new Set(); @@ -13279,9 +13469,30 @@ var didWarnAboutInvalidateContextType; didWarnAboutUndefinedDerivedState = new Set(); didWarnAboutContextTypeAndContextTypes = new Set(); didWarnAboutInvalidateContextType = new Set(); - var didWarnOnInvalidCallback = new Set(); + didWarnOnInvalidCallback = new Set(); // This is so gross but it's at least non-critical and can be removed if + // it causes problems. This is meant to give a nicer error message for + // ReactDOM15.unstable_renderSubtreeIntoContainer(reactDOM16Component, + // ...)) which otherwise throws a "_processChildContext is not a function" + // exception. + + Object.defineProperty(fakeInternalInstance, "_processChildContext", { + enumerable: false, + value: function () { + throw new Error( + "_processChildContext is not available in React 16+. This likely " + + "means you have multiple copies of React and are attempting to nest " + + "a React 15 tree inside a React 16 tree using " + + "unstable_renderSubtreeIntoContainer, which isn't supported. Try " + + "to make sure you have only one copy of React (and ideally, switch " + + "to ReactDOM.createPortal)." + ); + } + }); + Object.freeze(fakeInternalInstance); +} - warnOnInvalidCallback = function (callback, callerName) { +function warnOnInvalidCallback(callback, callerName) { + { if (callback === null || typeof callback === "function") { return; } @@ -13298,9 +13509,11 @@ var didWarnAboutInvalidateContextType; callback ); } - }; + } +} - warnOnUndefinedDerivedState = function (type, partialState) { +function warnOnUndefinedDerivedState(type, partialState) { + { if (partialState === undefined) { var componentName = getComponentNameFromType(type) || "Component"; @@ -13314,26 +13527,7 @@ var didWarnAboutInvalidateContextType; ); } } - }; // 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( @@ -14816,13 +15010,26 @@ function throwException( // // When the wakeable resolves, we'll attempt to render the boundary // again ("retry"). - - var wakeables = suspenseBoundary.updateQueue; - - if (wakeables === null) { - suspenseBoundary.updateQueue = new Set([wakeable]); + // Check if this is a Suspensey resource. We do not attach retry + // listeners to these, because we don't actually need them for + // rendering. Only for committing. Instead, if a fallback commits + // and the only thing that suspended was a Suspensey resource, we + // retry immediately. + // TODO: Refactor throwException so that we don't have to do this type + // check. The caller already knows what the cause was. + + var isSuspenseyResource = wakeable === noopSuspenseyCommitThenable; + + if (isSuspenseyResource) { + suspenseBoundary.flags |= ScheduleRetry; } else { - wakeables.add(wakeable); + var retryQueue = suspenseBoundary.updateQueue; + + if (retryQueue === null) { + suspenseBoundary.updateQueue = new Set([wakeable]); + } else { + retryQueue.add(wakeable); + } } break; @@ -14831,22 +15038,29 @@ function throwException( case OffscreenComponent: { if (suspenseBoundary.mode & ConcurrentMode) { suspenseBoundary.flags |= ShouldCapture; - var offscreenQueue = suspenseBoundary.updateQueue; - - if (offscreenQueue === null) { - var newOffscreenQueue = { - transitions: null, - markerInstances: null, - wakeables: new Set([wakeable]) - }; - suspenseBoundary.updateQueue = newOffscreenQueue; - } else { - var _wakeables = offscreenQueue.wakeables; - if (_wakeables === null) { - offscreenQueue.wakeables = new Set([wakeable]); + var _isSuspenseyResource = wakeable === noopSuspenseyCommitThenable; + + if (_isSuspenseyResource) { + suspenseBoundary.flags |= ScheduleRetry; + } else { + var offscreenQueue = suspenseBoundary.updateQueue; + + if (offscreenQueue === null) { + var newOffscreenQueue = { + transitions: null, + markerInstances: null, + retryQueue: new Set([wakeable]) + }; + suspenseBoundary.updateQueue = newOffscreenQueue; } else { - _wakeables.add(wakeable); + var _retryQueue = offscreenQueue.retryQueue; + + if (_retryQueue === null) { + offscreenQueue.retryQueue = new Set([wakeable]); + } else { + _retryQueue.add(wakeable); + } } } @@ -18445,6 +18659,17 @@ function readContext(context) { } } + return readContextForConsumer(currentlyRenderingFiber, context); +} +function readContextDuringReconcilation(consumer, context, renderLanes) { + if (currentlyRenderingFiber === null) { + prepareToReadContext(consumer, renderLanes); + } + + return readContextForConsumer(consumer, context); +} + +function readContextForConsumer(consumer, context) { var value = context._currentValue; if (lastFullyObservedContext === context); @@ -18456,7 +18681,7 @@ function readContext(context) { }; if (lastContextDependency === null) { - if (currentlyRenderingFiber === null) { + if (consumer === null) { throw new Error( "Context can only be read while React is rendering. " + "In classes, you can read it in the render method or getDerivedStateFromProps. " + @@ -18466,7 +18691,7 @@ function readContext(context) { } // This is the first dependency for this component. Create a new list. lastContextDependency = contextItem; - currentlyRenderingFiber.dependencies = { + consumer.dependencies = { lanes: NoLanes, firstContext: contextItem }; @@ -18540,7 +18765,13 @@ function appendAllChildren( } } // An unfortunate fork of appendAllChildren because we have two different parent types. -function updateHostComponent(current, workInProgress, type, newProps) { +function updateHostComponent( + current, + workInProgress, + type, + newProps, + renderLanes +) { { // If we have an alternate, that means this is an update and we need to // schedule a side-effect to do the updates. @@ -18551,6 +18782,7 @@ function updateHostComponent(current, workInProgress, type, newProps) { // we won't touch this node even if children changed. return; } // If we get updated because one of our children updated, we don't + suspendHostCommitIfNeeded(workInProgress); 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`. @@ -18564,15 +18796,59 @@ function updateHostComponent(current, workInProgress, type, newProps) { markUpdate(workInProgress); } } -} +} // TODO: This should ideally move to begin phase, but currently the instance is +// not created until the complete phase. For our existing use cases, host nodes +// that suspend don't have children, so it doesn't matter. But that might not +// always be true in the future. -function updateHostText(current, workInProgress, oldText, newText) { +function suspendHostCommitIfNeeded(workInProgress, type, props, renderLanes) { + // Ask the renderer if this instance should suspend the commit. { - // If the text differs, mark it as an update. All the work in done in commitWork. - if (oldText !== newText) { - markUpdate(workInProgress); - } - } + // If this flag was set previously, we can remove it. The flag represents + // whether this particular set of props might ever need to suspend. The + // safest thing to do is for shouldSuspendCommit to always return true, but + // if the renderer is reasonably confident that the underlying resource + // won't be evicted, it can return false as a performance optimization. + workInProgress.flags &= ~SuspenseyCommit; + return; + } // Mark this fiber with a flag. We use this right before the commit phase to +} + +function scheduleRetryEffect(workInProgress, retryQueue) { + var wakeables = retryQueue; + + if (wakeables !== null) { + // Schedule an effect to attach a retry listener to the promise. + // TODO: Move to passive phase + workInProgress.flags |= Update; + } else { + // This boundary suspended, but no wakeables were added to the retry + // queue. Check if the renderer suspended commit. If so, this means + // that once the fallback is committed, we can immediately retry + // rendering again, because rendering wasn't actually blocked. Only + // the commit phase. + // TODO: Consider a model where we always schedule an immediate retry, even + // for normal Suspense. That way the retry can partially render up to the + // first thing that suspends. + if (workInProgress.flags & ScheduleRetry) { + var retryLane = // TODO: This check should probably be moved into claimNextRetryLane + // I also suspect that we need some further consolidation of offscreen + // and retry lanes. + workInProgress.tag !== OffscreenComponent + ? claimNextRetryLane() + : OffscreenLane; + workInProgress.lanes = mergeLanes(workInProgress.lanes, retryLane); + } + } +} + +function updateHostText(current, workInProgress, oldText, newText) { + { + // If the text differs, mark it as an update. All the work in done in commitWork. + if (oldText !== newText) { + markUpdate(workInProgress); + } + } } function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { @@ -18963,23 +19239,26 @@ function completeWork(current, workInProgress, renderLanes) { } else { var _rootContainerInstance = getRootHostContainer(); - var instance = createInstance( + var _instance3 = createInstance( _type, newProps, _rootContainerInstance, _currentHostContext2, workInProgress ); - appendAllChildren(instance, workInProgress); - workInProgress.stateNode = instance; // Certain renderers require commit-time effects for initial mount. + + appendAllChildren(_instance3, workInProgress); + workInProgress.stateNode = _instance3; // 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. - if (finalizeInitialChildren(instance)) { + if (finalizeInitialChildren(_instance3)) { markUpdate(workInProgress); } } + suspendHostCommitIfNeeded(workInProgress); + if (workInProgress.ref !== null) { // If there is a ref on a host node we need to schedule a callback markRef(workInProgress); @@ -19098,13 +19377,8 @@ function completeWork(current, workInProgress, renderLanes) { } } - var wakeables = workInProgress.updateQueue; - - if (wakeables !== null) { - // Schedule an effect to attach a retry listener to the promise. - // TODO: Move to passive phase - workInProgress.flags |= Update; - } + var retryQueue = workInProgress.updateQueue; + scheduleRetryEffect(workInProgress, retryQueue); bubbleProperties(workInProgress); @@ -19204,12 +19478,9 @@ function completeWork(current, workInProgress, renderLanes) { // 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 + var _retryQueue = suspended.updateQueue; + workInProgress.updateQueue = _retryQueue; + scheduleRetryEffect(workInProgress, _retryQueue); // Rerender the whole list, but this time, we'll force fallbacks // to stay in place. // Reset the effect flags before doing the second pass since that's now invalid. // Reset the child fibers to their original state. @@ -19263,13 +19534,9 @@ function completeWork(current, workInProgress, renderLanes) { 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; - } - + var _retryQueue2 = _suspended.updateQueue; + workInProgress.updateQueue = _retryQueue2; + scheduleRetryEffect(workInProgress, _retryQueue2); cutOffTailIfNeeded(renderState, true); // This might have been modified. if ( @@ -19413,10 +19680,11 @@ function completeWork(current, workInProgress, renderLanes) { } } - if (workInProgress.updateQueue !== null) { - // Schedule an effect to attach Suspense retry listeners - // TODO: Move to passive phase - workInProgress.flags |= Update; + var offscreenQueue = workInProgress.updateQueue; + + if (offscreenQueue !== null) { + var _retryQueue3 = offscreenQueue.retryQueue; + scheduleRetryEffect(workInProgress, _retryQueue3); } return null; } @@ -19650,7 +19918,7 @@ function reportUncaughtErrorInDEV(error) { } } -var callComponentWillUnmountWithTimer = function (current, instance) { +function callComponentWillUnmountWithTimer(current, instance) { instance.props = current.memoizedProps; instance.state = current.memoizedState; @@ -19664,7 +19932,7 @@ var callComponentWillUnmountWithTimer = function (current, instance) { } else { instance.componentWillUnmount(); } -}; // Capture errors so they don't interrupt unmounting. +} // Capture errors so they don't interrupt unmounting. function safelyCallComponentWillUnmount( current, @@ -21620,11 +21888,11 @@ function commitMutationEffectsOnFiber(finishedWork, root, lanes) { captureCommitPhaseError(finishedWork, finishedWork.return, error); } - var wakeables = finishedWork.updateQueue; + var retryQueue = finishedWork.updateQueue; - if (wakeables !== null) { + if (retryQueue !== null) { finishedWork.updateQueue = null; - attachSuspenseRetryListeners(finishedWork, wakeables); + attachSuspenseRetryListeners(finishedWork, retryQueue); } } @@ -21705,11 +21973,11 @@ function commitMutationEffectsOnFiber(finishedWork, root, lanes) { var offscreenQueue = finishedWork.updateQueue; if (offscreenQueue !== null) { - var _wakeables = offscreenQueue.wakeables; + var _retryQueue = offscreenQueue.retryQueue; - if (_wakeables !== null) { - offscreenQueue.wakeables = null; - attachSuspenseRetryListeners(finishedWork, _wakeables); + if (_retryQueue !== null) { + offscreenQueue.retryQueue = null; + attachSuspenseRetryListeners(finishedWork, _retryQueue); } } } @@ -21722,11 +21990,11 @@ function commitMutationEffectsOnFiber(finishedWork, root, lanes) { commitReconciliationEffects(finishedWork); if (flags & Update) { - var _wakeables2 = finishedWork.updateQueue; + var _retryQueue2 = finishedWork.updateQueue; - if (_wakeables2 !== null) { + if (_retryQueue2 !== null) { finishedWork.updateQueue = null; - attachSuspenseRetryListeners(finishedWork, _wakeables2); + attachSuspenseRetryListeners(finishedWork, _retryQueue2); } } @@ -23067,6 +23335,19 @@ function ensureRootIsScheduled(root, currentTime) { root.callbackPriority = NoLane; root.callbackNode = null; return; + } + + var cancelPendingCommit = root.cancelPendingCommit; + + if (cancelPendingCommit !== null) { + // We should only interrupt a pending commit if the new update + // is urgent. + if (includesOnlyNonUrgentLanes(nextLanes)) { + // The new update is not urgent. Don't interrupt the pending commit. + root.callbackPriority = NoLane; + root.callbackNode = null; + 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. @@ -23298,7 +23579,7 @@ function performConcurrentWorkOnRoot(root, didTimeout) { root.finishedWork = finishedWork; root.finishedLanes = lanes; - finishConcurrentRender(root, exitStatus, lanes); + finishConcurrentRender(root, exitStatus, finishedWork, lanes); } } @@ -23399,7 +23680,7 @@ function queueRecoverableErrors(errors) { } } -function finishConcurrentRender(root, exitStatus, lanes) { +function finishConcurrentRender(root, exitStatus, finishedWork, lanes) { switch (exitStatus) { case RootInProgress: case RootFatalErrored: { @@ -23412,10 +23693,12 @@ function finishConcurrentRender(root, exitStatus, lanes) { case RootErrored: { // We should have already attempted to retry this tree. If we reached // this point, it errored again. Commit it. - commitRoot( + commitRootWhenReady( root, + finishedWork, workInProgressRootRecoverableErrors, - workInProgressTransitions + workInProgressTransitions, + lanes ); break; } @@ -23444,11 +23727,13 @@ function finishConcurrentRender(root, exitStatus, lanes) { // immediately, wait for more data to arrive. root.timeoutHandle = scheduleTimeout( - commitRoot.bind( + commitRootWhenReady.bind( null, root, + finishedWork, workInProgressRootRecoverableErrors, - workInProgressTransitions + workInProgressTransitions, + lanes ), msUntilTimeout ); @@ -23456,10 +23741,12 @@ function finishConcurrentRender(root, exitStatus, lanes) { } } // The work expired. Commit immediately. - commitRoot( + commitRootWhenReady( root, + finishedWork, workInProgressRootRecoverableErrors, - workInProgressTransitions + workInProgressTransitions, + lanes ); break; } @@ -23491,11 +23778,13 @@ function finishConcurrentRender(root, exitStatus, lanes) { // Instead of committing the fallback immediately, wait for more data // to arrive. root.timeoutHandle = scheduleTimeout( - commitRoot.bind( + commitRootWhenReady.bind( null, root, + finishedWork, workInProgressRootRecoverableErrors, - workInProgressTransitions + workInProgressTransitions, + lanes ), _msUntilTimeout ); @@ -23503,20 +23792,24 @@ function finishConcurrentRender(root, exitStatus, lanes) { } } // Commit the placeholder. - commitRoot( + commitRootWhenReady( root, + finishedWork, workInProgressRootRecoverableErrors, - workInProgressTransitions + workInProgressTransitions, + lanes ); break; } case RootCompleted: { - // The work completed. Ready to commit. - commitRoot( + // The work completed. + commitRootWhenReady( root, + finishedWork, workInProgressRootRecoverableErrors, - workInProgressTransitions + workInProgressTransitions, + lanes ); break; } @@ -23527,6 +23820,45 @@ function finishConcurrentRender(root, exitStatus, lanes) { } } +function commitRootWhenReady( + root, + finishedWork, + recoverableErrors, + transitions, + lanes +) { + if (includesOnlyNonUrgentLanes(lanes)) { + // suspend. If it's not ready, it will return a callback to subscribe to + // a ready event. + + var schedulePendingCommit = waitForCommitToBeReady(); + + if (schedulePendingCommit !== null) { + // NOTE: waitForCommitToBeReady returns a subscribe function so that we + // only allocate a function if the commit isn't ready yet. The other + // pattern would be to always pass a callback to waitForCommitToBeReady. + // Not yet ready to commit. Delay the commit until the renderer notifies + // us that it's ready. This will be canceled if we start work on the + // root again. + root.cancelPendingCommit = schedulePendingCommit( + commitRoot.bind( + null, + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ) + ); + return; + } + } // Otherwise, commit immediately. + + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); +} + 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 @@ -23787,6 +24119,13 @@ function prepareFreshStack(root, lanes) { cancelTimeout(timeoutHandle); } + var cancelPendingCommit = root.cancelPendingCommit; + + if (cancelPendingCommit !== null) { + root.cancelPendingCommit = null; + cancelPendingCommit(); + } + resetWorkInProgressStack(); workInProgressRoot = root; var rootWorkInProgress = createWorkInProgress(root.current, null); @@ -23815,6 +24154,7 @@ function resetSuspendedWorkLoopOnUnwind() { // Reset module-level state that was set during the render phase. resetContextDependencies(); resetHooksOnUnwind(); + resetChildReconcilerOnUnwind(); } function handleThrow(root, thrownValue) { @@ -23843,9 +24183,18 @@ function handleThrow(root, thrownValue) { // API for suspending. This implementation detail can change later, once we // deprecate the old API in favor of `use`. thrownValue = getSuspendedThenable(); - workInProgressSuspendedReason = shouldAttemptToSuspendUntilDataResolves() - ? SuspendedOnData - : SuspendedOnImmediate; + workInProgressSuspendedReason = + shouldRemainOnPreviousScreen() && // Check if there are other pending updates that might possibly unblock this + // component from suspending. This mirrors the check in + // renderDidSuspendDelayIfPossible. We should attempt to unify them somehow. + // TODO: Consider unwinding immediately, using the + // SuspendedOnHydration mechanism. + !includesNonIdleWork(workInProgressRootSkippedLanes) && + !includesNonIdleWork(workInProgressRootInterleavedUpdatedLanes) // Suspend work loop until data resolves + ? SuspendedOnData // Don't suspend work loop, except to check if the data has + : // immediately resolved (i.e. in a microtask). Otherwise, trigger the + // nearest Suspense fallback. + SuspendedOnImmediate; } else if (thrownValue === SelectiveHydrationException) { // An update flowed into a dehydrated boundary. Before we can apply the // update, we need to finish hydrating. Interrupt the work-in-progress @@ -23916,27 +24265,27 @@ function handleThrow(root, thrownValue) { } } -function shouldAttemptToSuspendUntilDataResolves() { - // Check if there are other pending updates that might possibly unblock this - // component from suspending. This mirrors the check in - // renderDidSuspendDelayIfPossible. We should attempt to unify them somehow. - // TODO: Consider unwinding immediately, using the - // SuspendedOnHydration mechanism. - if ( - includesNonIdleWork(workInProgressRootSkippedLanes) || - includesNonIdleWork(workInProgressRootInterleavedUpdatedLanes) - ) { - // Suspend normally. renderDidSuspendDelayIfPossible will handle - // interrupting the work loop. - return false; - } // TODO: We should be able to remove the equivalent check in - // finishConcurrentRender, and rely just on this one. - +function shouldRemainOnPreviousScreen() { + // This is asking whether it's better to suspend the transition and remain + // on the previous screen, versus showing a fallback as soon as possible. It + // takes into account both the priority of render and also whether showing a + // fallback would produce a desirable user experience. + // TODO: Once `use` has fully replaced the `throw promise` pattern, we should + // be able to remove the equivalent check in finishConcurrentRender, and rely + // just on this one. if (includesOnlyTransitions(workInProgressRootRenderLanes)) { - // If we're rendering inside the "shell" of the app, it's better to suspend - // rendering and wait for the data to resolve. Otherwise, we should switch - // to a fallback and continue rendering. - return getShellBoundary() === null; + if (getShellBoundary() === null) { + // We're rendering inside the "shell" of the app. Activating the nearest + // fallback would cause visible content to disappear. It's better to + // suspend the transition and remain on the previous screen. + return true; + } else { + // We're rendering content that wasn't part of the previous screen. + // Rather than block the transition, it's better to show a fallback as + // soon as possible. The appearance of any nested fallbacks will be + // throttled to avoid jank. + return false; + } } var handler = getSuspenseHandler(); @@ -24418,15 +24767,14 @@ function replaySuspendedUnitOfWork(unitOfWork) { } default: { - { - error( - "Unexpected type of work: %s, Currently only function " + - "components are replayed after suspending. This is a bug in React.", - unitOfWork.tag - ); - } - - resetSuspendedWorkLoopOnUnwind(); + // Other types besides function components are reset completely before + // being replayed. Currently this only happens when a Usable type is + // reconciled — the reconciler will suspend. + // + // We reset the fiber back to its original state; however, this isn't + // a full "unwind" because we're going to reuse the promises that were + // reconciled previously. So it's intentional that we don't call + // resetSuspendedWorkLoopOnUnwind here. unwindInterruptedWork(current, unitOfWork); unitOfWork = workInProgress = resetWorkInProgress( unitOfWork, @@ -24680,7 +25028,8 @@ function commitRootImpl( // So we can clear these now to allow a new callback to be scheduled. root.callbackNode = null; - root.callbackPriority = NoLane; // Check which lanes no longer have any work scheduled on them, and mark + root.callbackPriority = NoLane; + root.cancelPendingCommit = null; // Check which lanes no longer have any work scheduled on them, and mark // those as finished. var remainingLanes = mergeLanes(finishedWork.lanes, finishedWork.childLanes); // Make sure to account for lanes that were updated by a concurrent event @@ -26282,10 +26631,10 @@ function FiberNode(tag, pendingProps, key, mode) { // 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) { +function createFiber(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; @@ -26860,6 +27209,7 @@ function FiberRootNode( this.pingCache = null; this.finishedWork = null; this.timeoutHandle = noTimeout; + this.cancelPendingCommit = null; this.context = null; this.pendingContext = null; this.callbackNode = null; @@ -26954,7 +27304,7 @@ function createFiberRoot( return root; } -var ReactVersion = "18.3.0-next-ef8bdbecb-20230310"; +var ReactVersion = "18.3.0-next-c57b90f50-20230320"; function createPortal$1( children, @@ -27483,54 +27833,251 @@ function injectIntoDevTools(devToolsConfig) { }); } -var emptyObject = {}; +/** + * IMPORTANT: This module is used in Paper and Fabric. It needs to be defined + * outside of `ReactFabricPublicInstance` because that module requires + * `nativeFabricUIManager` to be defined in the global scope (which does not + * happen in Paper). + */ +function getNativeTagFromPublicInstance(publicInstance) { + return publicInstance.__nativeTag; +} +function getInternalInstanceHandleFromPublicInstance(publicInstance) { + return publicInstance.__internalInstanceHandle; +} -{ - Object.freeze(emptyObject); +var ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; +function findHostInstance_DEPRECATED(componentOrHandle) { + { + var owner = ReactCurrentOwner.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" + ); + } + + owner.stateNode._warnedAboutRefsInRender = true; + } + } + + if (componentOrHandle == null) { + return null; + } // For compatibility with Fabric instances + + if ( + componentOrHandle.canonical && + componentOrHandle.canonical.publicInstance + ) { + // $FlowExpectedError[incompatible-return] Can't refine componentOrHandle as a Fabric instance + return componentOrHandle.canonical.publicInstance; + } // For compatibility with legacy renderer instances + + if (componentOrHandle._nativeTag) { + // $FlowFixMe[incompatible-exact] Necessary when running Flow on Fabric + // $FlowFixMe[incompatible-return] + return componentOrHandle; + } + + var hostInstance; + + { + hostInstance = findHostInstanceWithWarning( + componentOrHandle, + "findHostInstance_DEPRECATED" + ); + } // findHostInstance handles legacy vs. Fabric differences correctly + // $FlowFixMe[incompatible-exact] we need to fix the definition of `HostComponent` to use NativeMethods as an interface, not as a type. + + return hostInstance; +} +function findNodeHandle(componentOrHandle) { + { + var owner = ReactCurrentOwner.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" + ); + } + + owner.stateNode._warnedAboutRefsInRender = true; + } + } + + if (componentOrHandle == null) { + return null; + } + + if (typeof componentOrHandle === "number") { + // Already a node handle + return componentOrHandle; + } // For compatibility with legacy renderer instances + + if (componentOrHandle._nativeTag) { + return componentOrHandle._nativeTag; + } // For compatibility with Fabric instances + + if ( + componentOrHandle.canonical != null && + componentOrHandle.canonical.nativeTag != null + ) { + return componentOrHandle.canonical.nativeTag; + } // For compatibility with Fabric public instances + + var nativeTag = getNativeTagFromPublicInstance(componentOrHandle); + + if (nativeTag) { + return nativeTag; + } + + var hostInstance; + + { + hostInstance = findHostInstanceWithWarning( + componentOrHandle, + "findNodeHandle" + ); + } + + if (hostInstance == null) { + return hostInstance; + } // $FlowFixMe[prop-missing] For compatibility with legacy renderer instances + + if (hostInstance._nativeTag != null) { + // $FlowFixMe[incompatible-return] + return hostInstance._nativeTag; + } // $FlowFixMe[incompatible-call] Necessary when running Flow on the legacy renderer + + return getNativeTagFromPublicInstance(hostInstance); } +function dispatchCommand(handle, command, args) { + var nativeTag = + handle._nativeTag != null + ? handle._nativeTag + : getNativeTagFromPublicInstance(handle); + + if (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; + } -var createHierarchy; -var getHostNode; -var getHostProps; -var lastNonHostInstance; -exports.getInspectorDataForInstance = void 0; -var getOwnerHierarchy; -var traverseOwnerTreeUp; + var internalInstanceHandle = + getInternalInstanceHandleFromPublicInstance(handle); + + if (internalInstanceHandle != null) { + var node = getNodeFromInternalInstanceHandle(internalInstanceHandle); + + if (node != null) { + nativeFabricUIManager.dispatchCommand(node, command, args); + } + } else { + ReactNativePrivateInterface.UIManager.dispatchViewManagerCommand( + nativeTag, + command, + args + ); + } +} +function sendAccessibilityEvent(handle, eventType) { + var nativeTag = + handle._nativeTag != null + ? handle._nativeTag + : getNativeTagFromPublicInstance(handle); + + if (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; + } + + var internalInstanceHandle = + getInternalInstanceHandleFromPublicInstance(handle); + + if (internalInstanceHandle != null) { + var node = getNodeFromInternalInstanceHandle(internalInstanceHandle); + + if (node != null) { + nativeFabricUIManager.sendAccessibilityEvent(node, eventType); + } + } else { + ReactNativePrivateInterface.legacySendAccessibilityEvent( + nativeTag, + eventType + ); + } +} +function getNodeFromInternalInstanceHandle(internalInstanceHandle) { + return ( + // $FlowExpectedError[incompatible-return] internalInstanceHandle is opaque but we need to make an exception here. + internalInstanceHandle && // $FlowExpectedError[incompatible-return] + internalInstanceHandle.stateNode && // $FlowExpectedError[incompatible-use] + internalInstanceHandle.stateNode.node + ); +} + +var emptyObject = {}; { - // $FlowFixMe[missing-local-annot] - 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 - ); - } + Object.freeze(emptyObject); +} // $FlowFixMe[missing-local-annot] + +function createHierarchy(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 shadow node and use that to measure. + var hostFiber = findCurrentHostFiber(fiber); + var node = + hostFiber != null && + hostFiber.stateNode !== null && + hostFiber.stateNode.node; + + if (node) { + nativeFabricUIManager.measure(node, callback); + } else { + return ReactNativePrivateInterface.UIManager.measure( + getHostNode(fiber, findNodeHandle), + callback + ); } - }; - } - }; - }); - }; // $FlowFixMe[missing-local-annot] + } + }; + } + }; + }); +} // $FlowFixMe[missing-local-annot] - getHostNode = function (fiber, findNodeHandle) { +function getHostNode(fiber, findNodeHandle) { + { var hostNode; // look for children first for the hostNode // as composite fibers do not have a hostNode @@ -27547,19 +28094,21 @@ var traverseOwnerTreeUp; } return null; - }; // $FlowFixMe[missing-local-annot] + } +} // $FlowFixMe[missing-local-annot] - getHostProps = function (fiber) { - var host = findCurrentHostFiber(fiber); +function getHostProps(fiber) { + var host = findCurrentHostFiber(fiber); - if (host) { - return host.memoizedProps || emptyObject; - } + if (host) { + return host.memoizedProps || emptyObject; + } - return emptyObject; - }; + return emptyObject; +} - exports.getInspectorDataForInstance = function (closestInstance) { +function getInspectorDataForInstance(closestInstance) { + { // Handle case where user clicks outside of ReactNative if (!closestInstance) { return { @@ -27584,39 +28133,38 @@ var traverseOwnerTreeUp; selectedIndex: selectedIndex, source: source }; - }; + } +} - getOwnerHierarchy = function (instance) { - var hierarchy = []; - traverseOwnerTreeUp(hierarchy, instance); - return hierarchy; - }; // $FlowFixMe[missing-local-annot] +function getOwnerHierarchy(instance) { + var hierarchy = []; + traverseOwnerTreeUp(hierarchy, instance); + return hierarchy; +} // $FlowFixMe[missing-local-annot] - lastNonHostInstance = function (hierarchy) { - for (var i = hierarchy.length - 1; i > 1; i--) { - var instance = hierarchy[i]; +function lastNonHostInstance(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]; - }; // $FlowFixMe[missing-local-annot] + return hierarchy[0]; +} // $FlowFixMe[missing-local-annot] - traverseOwnerTreeUp = function (hierarchy, instance) { +function traverseOwnerTreeUp(hierarchy, instance) { + { if (instance) { hierarchy.unshift(instance); traverseOwnerTreeUp(hierarchy, instance._debugOwner); } - }; + } } -var getInspectorDataForViewTag; -var getInspectorDataForViewAtPoint; - -{ - getInspectorDataForViewTag = function (viewTag) { +function getInspectorDataForViewTag(viewTag) { + { var closestInstance = getInstanceFromTag(viewTag); // Handle case where user clicks outside of ReactNative if (!closestInstance) { @@ -27641,25 +28189,38 @@ var getInspectorDataForViewAtPoint; selectedIndex: selectedIndex, source: source }; - }; + } +} - getInspectorDataForViewAtPoint = function ( - findNodeHandle, - inspectedView, - locationX, - locationY, - callback - ) { +function getInspectorDataForViewAtPoint( + findNodeHandle, + inspectedView, + locationX, + locationY, + callback +) { + { var closestInstance = null; + var fabricInstanceHandle = + getInternalInstanceHandleFromPublicInstance(inspectedView); + var fabricNode = + fabricInstanceHandle != null + ? getNodeFromInternalInstanceHandle(fabricInstanceHandle) + : null; - if (inspectedView._internalInstanceHandle != null) { + if (fabricNode) { // For Fabric we can look up the instance handle directly and measure it. nativeFabricUIManager.findNodeAtPoint( - inspectedView._internalInstanceHandle.stateNode.node, + fabricNode, locationX, locationY, function (internalInstanceHandle) { - if (internalInstanceHandle == null) { + var node = + internalInstanceHandle != null + ? getNodeFromInternalInstanceHandle(internalInstanceHandle) + : null; + + if (internalInstanceHandle == null || node == null) { callback( assign( { @@ -27671,21 +28232,21 @@ var getInspectorDataForViewAtPoint; height: 0 } }, - exports.getInspectorDataForInstance(closestInstance) + getInspectorDataForInstance(closestInstance) ) ); + return; } 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. + 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; + internalInstanceHandle.stateNode.canonical.nativeTag; nativeFabricUIManager.measure( - internalInstanceHandle.stateNode.node, + node, function (x, y, width, height, pageX, pageY) { - var inspectorData = - exports.getInspectorDataForInstance(closestInstance); + var inspectorData = getInspectorDataForInstance(closestInstance); callback( assign({}, inspectorData, { pointerY: locationY, @@ -27708,7 +28269,7 @@ var getInspectorDataForViewAtPoint; findNodeHandle(inspectedView), [locationX, locationY], function (nativeViewTag, left, top, width, height) { - var inspectorData = exports.getInspectorDataForInstance( + var inspectorData = getInspectorDataForInstance( getInstanceFromTag(nativeViewTag) ); callback( @@ -27732,156 +28293,6 @@ var getInspectorDataForViewAtPoint; return; } - }; -} - -var ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; -function findHostInstance_DEPRECATED(componentOrHandle) { - { - var owner = ReactCurrentOwner.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" - ); - } - - owner.stateNode._warnedAboutRefsInRender = true; - } - } - - if (componentOrHandle == null) { - return null; - } // $FlowFixMe Flow has hardcoded values for React DOM that don't work with RN - - if (componentOrHandle._nativeTag) { - // $FlowFixMe Flow has hardcoded values for React DOM that don't work with RN - return componentOrHandle; - } // $FlowFixMe Flow has hardcoded values for React DOM that don't work with RN - - if (componentOrHandle.canonical && componentOrHandle.canonical._nativeTag) { - // $FlowFixMe Flow has hardcoded values for React DOM that don't work with RN - return componentOrHandle.canonical; - } - - var hostInstance; - - { - hostInstance = findHostInstanceWithWarning( - componentOrHandle, - "findHostInstance_DEPRECATED" - ); - } // $FlowFixMe[incompatible-exact] we need to fix the definition of `HostComponent` to use NativeMethods as an interface, not as a type. - - return hostInstance; -} -function findNodeHandle(componentOrHandle) { - { - var owner = ReactCurrentOwner.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" - ); - } - - owner.stateNode._warnedAboutRefsInRender = true; - } - } - - if (componentOrHandle == null) { - return null; - } - - if (typeof componentOrHandle === "number") { - // Already a node handle - return componentOrHandle; - } - - if (componentOrHandle._nativeTag) { - return componentOrHandle._nativeTag; - } - - if (componentOrHandle.canonical && componentOrHandle.canonical._nativeTag) { - return componentOrHandle.canonical._nativeTag; - } - - var hostInstance; - - { - hostInstance = findHostInstanceWithWarning( - componentOrHandle, - "findNodeHandle" - ); - } - - if (hostInstance == null) { - return hostInstance; - } - - return hostInstance._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; - } - - 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 - ); - } -} -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 (stateNode != null) { - nativeFabricUIManager.sendAccessibilityEvent(stateNode.node, eventType); - } - } else { - ReactNativePrivateInterface.legacySendAccessibilityEvent( - handle._nativeTag, - eventType - ); } } @@ -27972,6 +28383,7 @@ exports.createPortal = createPortal; exports.dispatchCommand = dispatchCommand; exports.findHostInstance_DEPRECATED = findHostInstance_DEPRECATED; exports.findNodeHandle = findNodeHandle; +exports.getInspectorDataForInstance = getInspectorDataForInstance; exports.render = render; exports.sendAccessibilityEvent = sendAccessibilityEvent; exports.unmountComponentAtNode = unmountComponentAtNode; diff --git a/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactNativeRenderer-prod.fb.js b/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactNativeRenderer-prod.fb.js index 36a264f766298..5e56905936467 100644 --- a/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactNativeRenderer-prod.fb.js +++ b/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactNativeRenderer-prod.fb.js @@ -940,7 +940,7 @@ eventPluginOrder = Array.prototype.slice.call([ "ReactNativeBridgeEventPlugin" ]); recomputePluginOrdering(); -var injectedNamesToPlugins$jscomp$inline_239 = { +var injectedNamesToPlugins$jscomp$inline_248 = { ResponderEventPlugin: ResponderEventPlugin, ReactNativeBridgeEventPlugin: { eventTypes: {}, @@ -986,32 +986,32 @@ var injectedNamesToPlugins$jscomp$inline_239 = { } } }, - isOrderingDirty$jscomp$inline_240 = !1, - pluginName$jscomp$inline_241; -for (pluginName$jscomp$inline_241 in injectedNamesToPlugins$jscomp$inline_239) + isOrderingDirty$jscomp$inline_249 = !1, + pluginName$jscomp$inline_250; +for (pluginName$jscomp$inline_250 in injectedNamesToPlugins$jscomp$inline_248) if ( - injectedNamesToPlugins$jscomp$inline_239.hasOwnProperty( - pluginName$jscomp$inline_241 + injectedNamesToPlugins$jscomp$inline_248.hasOwnProperty( + pluginName$jscomp$inline_250 ) ) { - var pluginModule$jscomp$inline_242 = - injectedNamesToPlugins$jscomp$inline_239[pluginName$jscomp$inline_241]; + var pluginModule$jscomp$inline_251 = + injectedNamesToPlugins$jscomp$inline_248[pluginName$jscomp$inline_250]; if ( - !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_241) || - namesToPlugins[pluginName$jscomp$inline_241] !== - pluginModule$jscomp$inline_242 + !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_250) || + namesToPlugins[pluginName$jscomp$inline_250] !== + pluginModule$jscomp$inline_251 ) { - if (namesToPlugins[pluginName$jscomp$inline_241]) + if (namesToPlugins[pluginName$jscomp$inline_250]) throw Error( "EventPluginRegistry: Cannot inject two different event plugins using the same name, `" + - (pluginName$jscomp$inline_241 + "`.") + (pluginName$jscomp$inline_250 + "`.") ); - namesToPlugins[pluginName$jscomp$inline_241] = - pluginModule$jscomp$inline_242; - isOrderingDirty$jscomp$inline_240 = !0; + namesToPlugins[pluginName$jscomp$inline_250] = + pluginModule$jscomp$inline_251; + isOrderingDirty$jscomp$inline_249 = !0; } } -isOrderingDirty$jscomp$inline_240 && recomputePluginOrdering(); +isOrderingDirty$jscomp$inline_249 && recomputePluginOrdering(); var instanceCache = new Map(), instanceProps = new Map(); function getInstanceFromTag(tag) { @@ -1141,7 +1141,9 @@ getInstanceFromNode = getInstanceFromTag; getNodeFromInstance = function (inst) { inst = inst.stateNode; var tag = inst._nativeTag; - void 0 === tag && ((inst = inst.canonical), (tag = inst._nativeTag)); + void 0 === tag && + null != inst.canonical && + ((tag = inst.canonical.nativeTag), (inst = inst.canonical.publicInstance)); if (!tag) throw Error("All native instances should have a tag."); return inst; }; @@ -1876,6 +1878,12 @@ function claimNextTransitionLane() { 0 === (nextTransitionLane & 8388480) && (nextTransitionLane = 128); return lane; } +function claimNextRetryLane() { + var lane = nextRetryLane; + nextRetryLane <<= 1; + 0 === (nextRetryLane & 125829120) && (nextRetryLane = 8388608); + return lane; +} function createLaneMap(initial) { for (var laneMap = [], i = 0; 31 > i; i++) laneMap.push(initial); return laneMap; @@ -1977,7 +1985,9 @@ function finalizeInitialChildren(parentInstance) { return !1; } function getPublicInstance(instance) { - return instance.canonical ? instance.canonical : instance; + return null != instance.canonical && null != instance.canonical.publicInstance + ? instance.canonical.publicInstance + : instance; } var scheduleTimeout = setTimeout, cancelTimeout = clearTimeout; @@ -2099,30 +2109,43 @@ var objectIs = "function" === typeof Object.is ? Object.is : is, function flushSyncCallbacks() { if (!isFlushingSyncQueue && null !== syncQueue) { isFlushingSyncQueue = !0; - var i = 0, - previousUpdatePriority = currentUpdatePriority; - try { - var queue = syncQueue; - for (currentUpdatePriority = 2; i < queue.length; i++) { - var callback = queue[i]; + var previousUpdatePriority = currentUpdatePriority; + currentUpdatePriority = 2; + for (var errors = null, queue = syncQueue, i = 0; i < queue.length; i++) { + var callback = queue[i]; + try { do callback = callback(!0); while (null !== callback); + } catch (error) { + null === errors ? (errors = [error]) : errors.push(error); } - syncQueue = null; - includesLegacySyncCallbacks = !1; - } catch (error) { - throw ( - (null !== syncQueue && (syncQueue = syncQueue.slice(i + 1)), - scheduleCallback$1(ImmediatePriority, flushSyncCallbacks), - error) - ); - } finally { - (currentUpdatePriority = previousUpdatePriority), - (isFlushingSyncQueue = !1); + } + syncQueue = null; + includesLegacySyncCallbacks = !1; + currentUpdatePriority = previousUpdatePriority; + isFlushingSyncQueue = !1; + if (null !== errors) { + if (1 < errors.length) { + if ("function" === typeof AggregateError) + throw new AggregateError(errors); + for ( + previousUpdatePriority = 1; + previousUpdatePriority < errors.length; + previousUpdatePriority++ + ) + scheduleCallback$1( + ImmediatePriority, + throwError.bind(null, errors[previousUpdatePriority]) + ); + } + throw errors[0]; } } return null; } +function throwError(error) { + throw error; +} var contextStackCursor = createCursor(null), contextFiberStackCursor = createCursor(null), rootInstanceStackCursor = createCursor(null); @@ -2534,6 +2557,65 @@ function getStackByFiberInDevAndProd(workInProgress) { return "\nError generating stack: " + x.message + "\n" + x.stack; } } +var SuspenseException = Error( + "Suspense Exception: This is not a real error! It's an implementation detail of `use` to interrupt the current render. You must either rethrow it immediately, or move the `use` call outside of the `try/catch` block. Capturing without rethrowing will lead to unexpected behavior.\n\nTo handle async errors, wrap your component in an error boundary, or call the promise's `.catch` method and pass the result to `use`" + ), + noopSuspenseyCommitThenable = { then: function () {} }; +function isThenableResolved(thenable) { + thenable = thenable.status; + return "fulfilled" === thenable || "rejected" === thenable; +} +function noop() {} +function trackUsedThenable(thenableState, thenable, index) { + index = thenableState[index]; + void 0 === index + ? thenableState.push(thenable) + : index !== thenable && (thenable.then(noop, noop), (thenable = index)); + switch (thenable.status) { + case "fulfilled": + return thenable.value; + case "rejected": + throw thenable.reason; + default: + "string" === typeof thenable.status + ? thenable.then(noop, noop) + : ((thenableState = thenable), + (thenableState.status = "pending"), + thenableState.then( + function (fulfilledValue) { + if ("pending" === thenable.status) { + var fulfilledThenable = thenable; + fulfilledThenable.status = "fulfilled"; + fulfilledThenable.value = fulfilledValue; + } + }, + function (error) { + if ("pending" === thenable.status) { + var rejectedThenable = thenable; + rejectedThenable.status = "rejected"; + rejectedThenable.reason = error; + } + } + )); + switch (thenable.status) { + case "fulfilled": + return thenable.value; + case "rejected": + throw thenable.reason; + } + suspendedThenable = thenable; + throw SuspenseException; + } +} +var suspendedThenable = null, + thenableState$1 = null, + thenableIndexCounter$1 = 0; +function unwrapThenable(thenable) { + var index = thenableIndexCounter$1; + thenableIndexCounter$1 += 1; + null === thenableState$1 && (thenableState$1 = []); + return trackUsedThenable(thenableState$1, thenable, index); +} function coerceRef(returnFiber, current, element) { returnFiber = element.ref; if ( @@ -2638,16 +2720,16 @@ function createChildReconciler(shouldTrackSideEffects) { return ( (newIndex = newIndex.index), newIndex < lastPlacedIndex - ? ((newFiber.flags |= 16777218), lastPlacedIndex) + ? ((newFiber.flags |= 33554434), lastPlacedIndex) : newIndex ); - newFiber.flags |= 16777218; + newFiber.flags |= 33554434; return lastPlacedIndex; } function placeSingleChild(newFiber) { shouldTrackSideEffects && null === newFiber.alternate && - (newFiber.flags |= 16777218); + (newFiber.flags |= 33554434); return newFiber; } function updateTextNode(returnFiber, current, textContent, lanes) { @@ -2784,6 +2866,17 @@ function createChildReconciler(shouldTrackSideEffects) { (newChild.return = returnFiber), newChild ); + if ("function" === typeof newChild.then) + return createChild(returnFiber, unwrapThenable(newChild), lanes); + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) + return createChild( + returnFiber, + readContextDuringReconcilation(returnFiber, newChild, lanes), + lanes + ); throwOnInvalidObjectType(returnFiber, newChild); } return null; @@ -2817,6 +2910,23 @@ function createChildReconciler(shouldTrackSideEffects) { return null !== key ? null : updateFragment(returnFiber, oldFiber, newChild, lanes, null); + if ("function" === typeof newChild.then) + return updateSlot( + returnFiber, + oldFiber, + unwrapThenable(newChild), + lanes + ); + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) + return updateSlot( + returnFiber, + oldFiber, + readContextDuringReconcilation(returnFiber, newChild, lanes), + lanes + ); throwOnInvalidObjectType(returnFiber, newChild); } return null; @@ -2869,6 +2979,25 @@ function createChildReconciler(shouldTrackSideEffects) { (existingChildren = existingChildren.get(newIdx) || null), updateFragment(returnFiber, existingChildren, newChild, lanes, null) ); + if ("function" === typeof newChild.then) + return updateFromMap( + existingChildren, + returnFiber, + newIdx, + unwrapThenable(newChild), + lanes + ); + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) + return updateFromMap( + existingChildren, + returnFiber, + newIdx, + readContextDuringReconcilation(returnFiber, newChild, lanes), + lanes + ); throwOnInvalidObjectType(returnFiber, newChild); } return null; @@ -3040,7 +3169,7 @@ function createChildReconciler(shouldTrackSideEffects) { }); return iteratorFn; } - function reconcileChildFibers( + function reconcileChildFibersImpl( returnFiber, currentFirstChild, newChild, @@ -3185,6 +3314,23 @@ function createChildReconciler(shouldTrackSideEffects) { newChild, lanes ); + if ("function" === typeof newChild.then) + return reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + unwrapThenable(newChild), + lanes + ); + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) + return reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + readContextDuringReconcilation(returnFiber, newChild, lanes), + lanes + ); throwOnInvalidObjectType(returnFiber, newChild); } return ("string" === typeof newChild && "" !== newChild) || @@ -3206,6 +3352,22 @@ function createChildReconciler(shouldTrackSideEffects) { placeSingleChild(returnFiber)) : deleteRemainingChildren(returnFiber, currentFirstChild); } + function reconcileChildFibers( + returnFiber, + currentFirstChild, + newChild, + lanes + ) { + thenableIndexCounter$1 = 0; + returnFiber = reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + newChild, + lanes + ); + thenableState$1 = null; + return returnFiber; + } return reconcileChildFibers; } var reconcileChildFibers = createChildReconciler(!0), @@ -3284,57 +3446,7 @@ function resetWorkInProgressVersions() { workInProgressSources[i]._workInProgressVersionPrimary = null; workInProgressSources.length = 0; } -var SuspenseException = Error( - "Suspense Exception: This is not a real error! It's an implementation detail of `use` to interrupt the current render. You must either rethrow it immediately, or move the `use` call outside of the `try/catch` block. Capturing without rethrowing will lead to unexpected behavior.\n\nTo handle async errors, wrap your component in an error boundary, or call the promise's `.catch` method and pass the result to `use`" -); -function isThenableResolved(thenable) { - thenable = thenable.status; - return "fulfilled" === thenable || "rejected" === thenable; -} -function noop() {} -function trackUsedThenable(thenableState, thenable, index) { - index = thenableState[index]; - void 0 === index - ? thenableState.push(thenable) - : index !== thenable && (thenable.then(noop, noop), (thenable = index)); - switch (thenable.status) { - case "fulfilled": - return thenable.value; - case "rejected": - throw thenable.reason; - default: - "string" === typeof thenable.status - ? thenable.then(noop, noop) - : ((thenableState = thenable), - (thenableState.status = "pending"), - thenableState.then( - function (fulfilledValue) { - if ("pending" === thenable.status) { - var fulfilledThenable = thenable; - fulfilledThenable.status = "fulfilled"; - fulfilledThenable.value = fulfilledValue; - } - }, - function (error) { - if ("pending" === thenable.status) { - var rejectedThenable = thenable; - rejectedThenable.status = "rejected"; - rejectedThenable.reason = error; - } - } - )); - switch (thenable.status) { - case "fulfilled": - return thenable.value; - case "rejected": - throw thenable.reason; - } - suspendedThenable = thenable; - throw SuspenseException; - } -} -var suspendedThenable = null, - ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, +var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, ReactCurrentBatchConfig$2 = ReactSharedInternals.ReactCurrentBatchConfig, renderLanes$1 = 0, currentlyRenderingFiber$1 = null, @@ -3494,10 +3606,10 @@ createFunctionComponentUpdateQueue = function () { function use(usable) { if (null !== usable && "object" === typeof usable) { if ("function" === typeof usable.then) { - var index$27 = thenableIndexCounter; + var index$29 = thenableIndexCounter; thenableIndexCounter += 1; null === thenableState && (thenableState = []); - usable = trackUsedThenable(thenableState, usable, index$27); + usable = trackUsedThenable(thenableState, usable, index$29); null === currentlyRenderingFiber$1.alternate && (null === workInProgressHook ? null === currentlyRenderingFiber$1.memoizedState @@ -3952,8 +4064,9 @@ function startTransition(setPending, callback) { var previousPriority = currentUpdatePriority; currentUpdatePriority = 0 !== previousPriority && 8 > previousPriority ? previousPriority : 8; - setPending(!0); var prevTransition = ReactCurrentBatchConfig$2.transition; + ReactCurrentBatchConfig$2.transition = null; + setPending(!0); ReactCurrentBatchConfig$2.transition = {}; try { setPending(!1), callback(); @@ -5068,7 +5181,7 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { (nextProps.pendingProps = primaryChildProps), (workInProgress.deletions = null)) : ((nextProps = createWorkInProgress(JSCompiler_temp, primaryChildProps)), - (nextProps.subtreeFlags = JSCompiler_temp.subtreeFlags & 14680064)); + (nextProps.subtreeFlags = JSCompiler_temp.subtreeFlags & 31457280)); null !== dehydrated ? (showFallback = createWorkInProgress(dehydrated, showFallback)) : ((showFallback = createFiberFromFragment( @@ -5594,25 +5707,38 @@ function prepareToReadContext(workInProgress, renderLanes) { (workInProgress.firstContext = null)); } function readContext(context) { + return readContextForConsumer(currentlyRenderingFiber, context); +} +function readContextDuringReconcilation(consumer, context, renderLanes) { + null === currentlyRenderingFiber && + prepareToReadContext(consumer, renderLanes); + return readContextForConsumer(consumer, context); +} +function readContextForConsumer(consumer, context) { var value = context._currentValue; if (lastFullyObservedContext !== context) if ( ((context = { context: context, memoizedValue: value, next: null }), null === lastContextDependency) ) { - if (null === currentlyRenderingFiber) + if (null === consumer) throw 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()." ); lastContextDependency = context; - currentlyRenderingFiber.dependencies = { - lanes: 0, - firstContext: context - }; + consumer.dependencies = { lanes: 0, firstContext: context }; } else lastContextDependency = lastContextDependency.next = context; return value; } var ReactCurrentBatchConfig$1 = ReactSharedInternals.ReactCurrentBatchConfig; +function scheduleRetryEffect(workInProgress, retryQueue) { + null !== retryQueue + ? (workInProgress.flags |= 4) + : workInProgress.flags & 16384 && + ((retryQueue = + 22 !== workInProgress.tag ? claimNextRetryLane() : 1073741824), + (workInProgress.lanes |= retryQueue)); +} function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { switch (renderState.tailMode) { case "hidden": @@ -5627,14 +5753,14 @@ function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { break; case "collapsed": lastTailNode = renderState.tail; - for (var lastTailNode$63 = null; null !== lastTailNode; ) - null !== lastTailNode.alternate && (lastTailNode$63 = lastTailNode), + for (var lastTailNode$66 = null; null !== lastTailNode; ) + null !== lastTailNode.alternate && (lastTailNode$66 = lastTailNode), (lastTailNode = lastTailNode.sibling); - null === lastTailNode$63 + null === lastTailNode$66 ? hasRenderedATailFallback || null === renderState.tail ? (renderState.tail = null) : (renderState.tail.sibling = null) - : (lastTailNode$63.sibling = null); + : (lastTailNode$66.sibling = null); } } function bubbleProperties(completedWork) { @@ -5644,19 +5770,19 @@ function bubbleProperties(completedWork) { newChildLanes = 0, subtreeFlags = 0; if (didBailout) - for (var child$64 = completedWork.child; null !== child$64; ) - (newChildLanes |= child$64.lanes | child$64.childLanes), - (subtreeFlags |= child$64.subtreeFlags & 14680064), - (subtreeFlags |= child$64.flags & 14680064), - (child$64.return = completedWork), - (child$64 = child$64.sibling); + for (var child$67 = completedWork.child; null !== child$67; ) + (newChildLanes |= child$67.lanes | child$67.childLanes), + (subtreeFlags |= child$67.subtreeFlags & 31457280), + (subtreeFlags |= child$67.flags & 31457280), + (child$67.return = completedWork), + (child$67 = child$67.sibling); else - for (child$64 = completedWork.child; null !== child$64; ) - (newChildLanes |= child$64.lanes | child$64.childLanes), - (subtreeFlags |= child$64.subtreeFlags), - (subtreeFlags |= child$64.flags), - (child$64.return = completedWork), - (child$64 = child$64.sibling); + for (child$67 = completedWork.child; null !== child$67; ) + (newChildLanes |= child$67.lanes | child$67.childLanes), + (subtreeFlags |= child$67.subtreeFlags), + (subtreeFlags |= child$67.flags), + (child$67.return = completedWork), + (child$67 = child$67.sibling); completedWork.subtreeFlags |= subtreeFlags; completedWork.childLanes = newChildLanes; return didBailout; @@ -5709,7 +5835,8 @@ function completeWork(current, workInProgress, renderLanes) { var type = workInProgress.type; if (null !== current && null != workInProgress.stateNode) current.memoizedProps !== newProps && - (workInProgress.updateQueue = UPDATE_SIGNAL) && + ((workInProgress.flags &= -16777217), + (workInProgress.updateQueue = UPDATE_SIGNAL)) && (workInProgress.flags |= 4), current.ref !== workInProgress.ref && (workInProgress.flags |= 2097664); @@ -5766,6 +5893,7 @@ function completeWork(current, workInProgress, renderLanes) { } workInProgress.stateNode = current; finalizeInitialChildren(current) && (workInProgress.flags |= 4); + workInProgress.flags &= -16777217; null !== workInProgress.ref && (workInProgress.flags |= 2097664); } bubbleProperties(workInProgress); @@ -5829,7 +5957,7 @@ function completeWork(current, workInProgress, renderLanes) { renderLanes !== (null !== current && null !== current.memoizedState) && renderLanes && (workInProgress.child.flags |= 8192); - null !== workInProgress.updateQueue && (workInProgress.flags |= 4); + scheduleRetryEffect(workInProgress, workInProgress.updateQueue); bubbleProperties(workInProgress); return null; case 4: @@ -5865,9 +5993,8 @@ function completeWork(current, workInProgress, renderLanes) { workInProgress.flags |= 128; cutOffTailIfNeeded(type, !1); current = updatePayload.updateQueue; - null !== current && - ((workInProgress.updateQueue = current), - (workInProgress.flags |= 4)); + workInProgress.updateQueue = current; + scheduleRetryEffect(workInProgress, current); workInProgress.subtreeFlags = 0; for (current = workInProgress.child; null !== current; ) resetWorkInProgress(current, renderLanes), @@ -5896,9 +6023,8 @@ function completeWork(current, workInProgress, renderLanes) { ((workInProgress.flags |= 128), (newProps = !0), (renderLanes = current.updateQueue), - null !== renderLanes && - ((workInProgress.updateQueue = renderLanes), - (workInProgress.flags |= 4)), + (workInProgress.updateQueue = renderLanes), + scheduleRetryEffect(workInProgress, renderLanes), cutOffTailIfNeeded(type, !0), null === type.tail && "hidden" === type.tailMode && @@ -5957,7 +6083,9 @@ function completeWork(current, workInProgress, renderLanes) { workInProgress.subtreeFlags & 6 && (workInProgress.flags |= 8192)) : bubbleProperties(workInProgress), - null !== workInProgress.updateQueue && (workInProgress.flags |= 4), + (renderLanes = workInProgress.updateQueue), + null !== renderLanes && + scheduleRetryEffect(workInProgress, renderLanes.retryQueue), null ); case 24: @@ -6112,8 +6240,8 @@ function safelyDetachRef(current, nearestMountedAncestor) { else if ("function" === typeof ref) try { ref(null); - } catch (error$77) { - captureCommitPhaseError(current, nearestMountedAncestor, error$77); + } catch (error$82) { + captureCommitPhaseError(current, nearestMountedAncestor, error$82); } else ref.current = null; } @@ -6216,8 +6344,8 @@ function commitHookEffectListMount(flags, finishedWork) { var effect = (finishedWork = finishedWork.next); do { if ((effect.tag & flags) === flags) { - var create$78 = effect.create; - effect.destroy = create$78(); + var create$83 = effect.create; + effect.destroy = create$83(); } effect = effect.next; } while (effect !== finishedWork); @@ -6271,11 +6399,11 @@ function commitLayoutEffectOnFiber(finishedRoot, current, finishedWork) { current, finishedRoot.__reactInternalSnapshotBeforeUpdate ); - } catch (error$79) { + } catch (error$84) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$79 + error$84 ); } } @@ -6758,8 +6886,8 @@ function commitMutationEffectsOnFiber(finishedWork, root) { } try { commitHookEffectListUnmount(5, finishedWork, finishedWork.return); - } catch (error$87) { - captureCommitPhaseError(finishedWork, finishedWork.return, error$87); + } catch (error$92) { + captureCommitPhaseError(finishedWork, finishedWork.return, error$92); } } break; @@ -6808,11 +6936,11 @@ function commitMutationEffectsOnFiber(finishedWork, root) { viewConfig.uiViewClassName, updatePayload$jscomp$0 ); - } catch (error$90) { + } catch (error$95) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$90 + error$95 ); } } @@ -6833,8 +6961,8 @@ function commitMutationEffectsOnFiber(finishedWork, root) { "RCTRawText", { text: current } ); - } catch (error$91) { - captureCommitPhaseError(finishedWork, finishedWork.return, error$91); + } catch (error$96) { + captureCommitPhaseError(finishedWork, finishedWork.return, error$96); } } break; @@ -6947,11 +7075,11 @@ function commitMutationEffectsOnFiber(finishedWork, root) { if (null === current) try { throw Error("Not yet implemented."); - } catch (error$81) { + } catch (error$86) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$81 + error$86 ); } } else if ( @@ -6977,9 +7105,9 @@ function commitMutationEffectsOnFiber(finishedWork, root) { flags & 4 && ((flags = finishedWork.updateQueue), null !== flags && - ((current = flags.wakeables), + ((current = flags.retryQueue), null !== current && - ((flags.wakeables = null), + ((flags.retryQueue = null), attachSuspenseRetryListeners(finishedWork, current)))); break; case 19: @@ -7025,12 +7153,12 @@ function commitReconciliationEffects(finishedWork) { break; case 3: case 4: - var parent$82 = JSCompiler_inline_result.stateNode.containerInfo, - before$83 = getHostSibling(finishedWork); + var parent$87 = JSCompiler_inline_result.stateNode.containerInfo, + before$88 = getHostSibling(finishedWork); insertOrAppendPlacementNodeIntoContainer( finishedWork, - before$83, - parent$82 + before$88, + parent$87 ); break; default: @@ -7511,6 +7639,8 @@ function ensureRootIsScheduled(root, currentTime) { (root.callbackPriority = 0); else if (2 === workInProgressSuspendedReason && workInProgressRoot === root) (root.callbackPriority = 0), (root.callbackNode = null); + else if (null !== root.cancelPendingCommit && 0 === (suspendedLanes & 42)) + (root.callbackPriority = 0), (root.callbackNode = null); else if ( ((currentTime = suspendedLanes & -suspendedLanes), root.callbackPriority !== currentTime) @@ -7568,28 +7698,28 @@ function performConcurrentWorkOnRoot(root, didTimeout) { root === workInProgressRoot ? workInProgressRootRenderLanes : 0 ); if (0 === lanes) return null; - didTimeout = + var exitStatus = includesBlockingLane(root, lanes) || 0 !== (lanes & root.expiredLanes) || didTimeout ? renderRootSync(root, lanes) : renderRootConcurrent(root, lanes); - if (0 !== didTimeout) { - if (2 === didTimeout) { - var originallyAttemptedLanes = lanes, - errorRetryLanes = getLanesToRetrySynchronouslyOnError( - root, - originallyAttemptedLanes - ); + if (0 !== exitStatus) { + if (2 === exitStatus) { + didTimeout = lanes; + var errorRetryLanes = getLanesToRetrySynchronouslyOnError( + root, + didTimeout + ); 0 !== errorRetryLanes && ((lanes = errorRetryLanes), - (didTimeout = recoverFromConcurrentError( + (exitStatus = recoverFromConcurrentError( root, - originallyAttemptedLanes, + didTimeout, errorRetryLanes ))); } - if (1 === didTimeout) + if (1 === exitStatus) throw ( ((originalCallbackNode = workInProgressRootFatalError), prepareFreshStack(root, 0), @@ -7597,30 +7727,30 @@ function performConcurrentWorkOnRoot(root, didTimeout) { ensureRootIsScheduled(root, now()), originalCallbackNode) ); - if (6 === didTimeout) markRootSuspended(root, lanes); + if (6 === exitStatus) markRootSuspended(root, lanes); else { errorRetryLanes = !includesBlockingLane(root, lanes); - originallyAttemptedLanes = root.current.alternate; + didTimeout = root.current.alternate; if ( errorRetryLanes && - !isRenderConsistentWithExternalStores(originallyAttemptedLanes) + !isRenderConsistentWithExternalStores(didTimeout) ) { - didTimeout = renderRootSync(root, lanes); - if (2 === didTimeout) { + exitStatus = renderRootSync(root, lanes); + if (2 === exitStatus) { errorRetryLanes = lanes; - var errorRetryLanes$99 = getLanesToRetrySynchronouslyOnError( + var errorRetryLanes$104 = getLanesToRetrySynchronouslyOnError( root, errorRetryLanes ); - 0 !== errorRetryLanes$99 && - ((lanes = errorRetryLanes$99), - (didTimeout = recoverFromConcurrentError( + 0 !== errorRetryLanes$104 && + ((lanes = errorRetryLanes$104), + (exitStatus = recoverFromConcurrentError( root, errorRetryLanes, - errorRetryLanes$99 + errorRetryLanes$104 ))); } - if (1 === didTimeout) + if (1 === exitStatus) throw ( ((originalCallbackNode = workInProgressRootFatalError), prepareFreshStack(root, 0), @@ -7629,94 +7759,84 @@ function performConcurrentWorkOnRoot(root, didTimeout) { originalCallbackNode) ); } - root.finishedWork = originallyAttemptedLanes; + root.finishedWork = didTimeout; root.finishedLanes = lanes; - switch (didTimeout) { + switch (exitStatus) { case 0: case 1: throw Error("Root did not complete. This is a bug in React."); case 2: - commitRoot( - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ); + commitRootWhenReady(root); break; case 3: markRootSuspended(root, lanes); if ( (lanes & 125829120) === lanes && - ((lanes = globalMostRecentFallbackTime + 500 - now()), 10 < lanes) + ((exitStatus = globalMostRecentFallbackTime + 500 - now()), + 10 < exitStatus) ) { if (0 !== getNextLanes(root, 0)) break; root.timeoutHandle = scheduleTimeout( - commitRoot.bind( + commitRootWhenReady.bind( null, root, + didTimeout, workInProgressRootRecoverableErrors, - workInProgressTransitions + workInProgressTransitions, + lanes ), - lanes + exitStatus ); break; } - commitRoot( - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ); + commitRootWhenReady(root); break; case 4: markRootSuspended(root, lanes); if ((lanes & 8388480) === lanes) break; - didTimeout = root.eventTimes; - for (originallyAttemptedLanes = -1; 0 < lanes; ) - (errorRetryLanes$99 = 31 - clz32(lanes)), - (errorRetryLanes = 1 << errorRetryLanes$99), - (errorRetryLanes$99 = didTimeout[errorRetryLanes$99]), - errorRetryLanes$99 > originallyAttemptedLanes && - (originallyAttemptedLanes = errorRetryLanes$99), - (lanes &= ~errorRetryLanes); - lanes = originallyAttemptedLanes; - lanes = now() - lanes; - lanes = - (120 > lanes + exitStatus = lanes; + errorRetryLanes = root.eventTimes; + for (errorRetryLanes$104 = -1; 0 < exitStatus; ) { + var index$5 = 31 - clz32(exitStatus), + lane = 1 << index$5; + index$5 = errorRetryLanes[index$5]; + index$5 > errorRetryLanes$104 && (errorRetryLanes$104 = index$5); + exitStatus &= ~lane; + } + exitStatus = errorRetryLanes$104; + exitStatus = now() - exitStatus; + exitStatus = + (120 > exitStatus ? 120 - : 480 > lanes + : 480 > exitStatus ? 480 - : 1080 > lanes + : 1080 > exitStatus ? 1080 - : 1920 > lanes + : 1920 > exitStatus ? 1920 - : 3e3 > lanes + : 3e3 > exitStatus ? 3e3 - : 4320 > lanes + : 4320 > exitStatus ? 4320 - : 1960 * ceil(lanes / 1960)) - lanes; - if (10 < lanes) { + : 1960 * ceil(exitStatus / 1960)) - exitStatus; + if (10 < exitStatus) { root.timeoutHandle = scheduleTimeout( - commitRoot.bind( + commitRootWhenReady.bind( null, root, + didTimeout, workInProgressRootRecoverableErrors, - workInProgressTransitions + workInProgressTransitions, + lanes ), - lanes + exitStatus ); break; } - commitRoot( - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ); + commitRootWhenReady(root); break; case 5: - commitRoot( - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ); + commitRootWhenReady(root); break; default: throw Error("Unknown root exit status."); @@ -7759,6 +7879,13 @@ function queueRecoverableErrors(errors) { errors ); } +function commitRootWhenReady(root) { + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); +} function isRenderConsistentWithExternalStores(finishedWork) { for (var node = finishedWork; ; ) { if (node.flags & 16384) { @@ -7855,6 +7982,8 @@ function resetWorkInProgressStack() { else resetContextDependencies(), resetHooksOnUnwind(), + (thenableState$1 = null), + (thenableIndexCounter$1 = 0), (interruptedWork = workInProgress); for (; null !== interruptedWork; ) unwindInterruptedWork(interruptedWork.alternate, interruptedWork), @@ -7868,6 +7997,9 @@ function prepareFreshStack(root, lanes) { var timeoutHandle = root.timeoutHandle; -1 !== timeoutHandle && ((root.timeoutHandle = -1), cancelTimeout(timeoutHandle)); + timeoutHandle = root.cancelPendingCommit; + null !== timeoutHandle && + ((root.cancelPendingCommit = null), timeoutHandle()); resetWorkInProgressStack(); workInProgressRoot = root; workInProgress = root = createWorkInProgress(root.current, null); @@ -7894,12 +8026,23 @@ function handleThrow(root, thrownValue) { throw Error( "Expected a suspended thenable. This is a bug in React. Please file an issue." ); - root = suspendedThenable; + thrownValue = suspendedThenable; suspendedThenable = null; - thrownValue = root; - workInProgressSuspendedReason = shouldAttemptToSuspendUntilDataResolves() - ? 2 - : 3; + (workInProgressRootRenderLanes & 8388480) === workInProgressRootRenderLanes + ? (root = null === shellBoundary ? !0 : !1) + : ((root = suspenseHandlerStackCursor.current), + (root = + null !== root && + (workInProgressRootRenderLanes & 125829120) === + workInProgressRootRenderLanes + ? root === shellBoundary + : !1)); + workInProgressSuspendedReason = + root && + 0 === (workInProgressRootSkippedLanes & 268435455) && + 0 === (workInProgressRootInterleavedUpdatedLanes & 268435455) + ? 2 + : 3; } else workInProgressSuspendedReason = thrownValue === SelectiveHydrationException @@ -7914,24 +8057,6 @@ function handleThrow(root, thrownValue) { ((workInProgressRootExitStatus = 1), (workInProgressRootFatalError = thrownValue)); } -function shouldAttemptToSuspendUntilDataResolves() { - if ( - 0 !== (workInProgressRootSkippedLanes & 268435455) || - 0 !== (workInProgressRootInterleavedUpdatedLanes & 268435455) - ) - return !1; - if ( - (workInProgressRootRenderLanes & 8388480) === - workInProgressRootRenderLanes - ) - return null === shellBoundary; - var handler = suspenseHandlerStackCursor.current; - return null !== handler && - (workInProgressRootRenderLanes & 125829120) === - workInProgressRootRenderLanes - ? handler === shellBoundary - : !1; -} function pushDispatcher() { var prevDispatcher = ReactCurrentDispatcher.current; ReactCurrentDispatcher.current = ContextOnlyDispatcher; @@ -7968,8 +8093,8 @@ function renderRootSync(root, lanes) { } workLoopSync(); break; - } catch (thrownValue$102) { - handleThrow(root, thrownValue$102); + } catch (thrownValue$107) { + handleThrow(root, thrownValue$107); } while (1); resetContextDependencies(); @@ -8048,8 +8173,8 @@ function renderRootConcurrent(root, lanes) { } workLoopConcurrent(); break; - } catch (thrownValue$104) { - handleThrow(root, thrownValue$104); + } catch (thrownValue$109) { + handleThrow(root, thrownValue$109); } while (1); resetContextDependencies(); @@ -8102,9 +8227,7 @@ function replaySuspendedUnitOfWork(unitOfWork) { ); break; default: - resetContextDependencies(), - resetHooksOnUnwind(), - unwindInterruptedWork(current, unitOfWork), + unwindInterruptedWork(current, unitOfWork), (unitOfWork = workInProgress = resetWorkInProgress(unitOfWork, renderLanes)), (current = beginWork(current, unitOfWork, renderLanes)); @@ -8118,6 +8241,8 @@ function replaySuspendedUnitOfWork(unitOfWork) { function unwindSuspendedUnitOfWork(unitOfWork, thrownValue) { resetContextDependencies(); resetHooksOnUnwind(); + thenableState$1 = null; + thenableIndexCounter$1 = 0; var returnFiber = unitOfWork.return; if (null === returnFiber || null === workInProgressRoot) (workInProgressRootExitStatus = 1), @@ -8179,27 +8304,35 @@ function unwindSuspendedUnitOfWork(unitOfWork, thrownValue) { else (suspenseBoundary.flags |= 65536), (suspenseBoundary.lanes = thrownValue); - var wakeables = suspenseBoundary.updateQueue; - null === wakeables - ? (suspenseBoundary.updateQueue = new Set([wakeable])) - : wakeables.add(wakeable); + if (wakeable === noopSuspenseyCommitThenable) + suspenseBoundary.flags |= 16384; + else { + var retryQueue = suspenseBoundary.updateQueue; + null === retryQueue + ? (suspenseBoundary.updateQueue = new Set([wakeable])) + : retryQueue.add(wakeable); + } break; case 22: if (suspenseBoundary.mode & 1) { suspenseBoundary.flags |= 65536; - var offscreenQueue = suspenseBoundary.updateQueue; - if (null === offscreenQueue) { - var newOffscreenQueue = { - transitions: null, - markerInstances: null, - wakeables: new Set([wakeable]) - }; - suspenseBoundary.updateQueue = newOffscreenQueue; - } else { - var wakeables$33 = offscreenQueue.wakeables; - null === wakeables$33 - ? (offscreenQueue.wakeables = new Set([wakeable])) - : wakeables$33.add(wakeable); + if (wakeable === noopSuspenseyCommitThenable) + suspenseBoundary.flags |= 16384; + else { + var offscreenQueue = suspenseBoundary.updateQueue; + if (null === offscreenQueue) { + var newOffscreenQueue = { + transitions: null, + markerInstances: null, + retryQueue: new Set([wakeable]) + }; + suspenseBoundary.updateQueue = newOffscreenQueue; + } else { + var retryQueue$36 = offscreenQueue.retryQueue; + null === retryQueue$36 + ? (offscreenQueue.retryQueue = new Set([wakeable])) + : retryQueue$36.add(wakeable); + } } break; } @@ -8288,7 +8421,7 @@ function completeUnitOfWork(unitOfWork) { } else { current = unwindWork(current, completedWork); if (null !== current) { - current.flags &= 16383; + current.flags &= 32767; workInProgress = current; return; } @@ -8350,6 +8483,7 @@ function commitRootImpl( ); root.callbackNode = null; root.callbackPriority = 0; + root.cancelPendingCommit = null; var remainingLanes = transitions.lanes | transitions.childLanes; remainingLanes |= concurrentlyUpdatedLanes; markRootFinished(root, remainingLanes); @@ -8549,11 +8683,7 @@ function pingSuspendedRoot(root, wakeable, pingedLanes) { } function retryTimedOutBoundary(boundaryFiber, retryLane) { 0 === retryLane && - (0 === (boundaryFiber.mode & 1) - ? (retryLane = 2) - : ((retryLane = nextRetryLane), - (nextRetryLane <<= 1), - 0 === (nextRetryLane & 125829120) && (nextRetryLane = 8388608))); + (retryLane = 0 === (boundaryFiber.mode & 1) ? 2 : claimNextRetryLane()); var eventTime = requestEventTime(); boundaryFiber = enqueueConcurrentRenderForLane(boundaryFiber, retryLane); null !== boundaryFiber && @@ -9093,7 +9223,7 @@ function createWorkInProgress(current, pendingProps) { (workInProgress.flags = 0), (workInProgress.subtreeFlags = 0), (workInProgress.deletions = null)); - workInProgress.flags = current.flags & 14680064; + workInProgress.flags = current.flags & 31457280; workInProgress.childLanes = current.childLanes; workInProgress.lanes = current.lanes; workInProgress.child = current.child; @@ -9112,7 +9242,7 @@ function createWorkInProgress(current, pendingProps) { return workInProgress; } function resetWorkInProgress(workInProgress, renderLanes) { - workInProgress.flags &= 14680066; + workInProgress.flags &= 31457282; var current = workInProgress.alternate; null === current ? ((workInProgress.childLanes = 0), @@ -9302,7 +9432,11 @@ function FiberRootNode( this.pendingChildren = null; this.timeoutHandle = -1; - this.callbackNode = this.pendingContext = this.context = null; + this.callbackNode = + this.pendingContext = + this.context = + this.cancelPendingCommit = + null; this.callbackPriority = 0; this.eventTimes = createLaneMap(0); this.expirationTimes = createLaneMap(-1); @@ -9409,23 +9543,35 @@ function updateContainer(element, container, parentComponent, callback) { function emptyFindFiberByHostInstance() { return null; } -var emptyObject = {}, - createHierarchy, - getHostNode, - getHostProps, - lastNonHostInstance; -exports.getInspectorDataForInstance = void 0; -var getOwnerHierarchy, traverseOwnerTreeUp; -createHierarchy = function (fiberHierarchy) { - return fiberHierarchy.map(function (fiber) { +function findNodeHandle(componentOrHandle) { + if (null == componentOrHandle) return null; + if ("number" === typeof componentOrHandle) return componentOrHandle; + if (componentOrHandle._nativeTag) return componentOrHandle._nativeTag; + if ( + null != componentOrHandle.canonical && + null != componentOrHandle.canonical.nativeTag + ) + return componentOrHandle.canonical.nativeTag; + var nativeTag = componentOrHandle.__nativeTag; + if (nativeTag) return nativeTag; + componentOrHandle = findHostInstance(componentOrHandle); + return null == componentOrHandle + ? componentOrHandle + : null != componentOrHandle._nativeTag + ? componentOrHandle._nativeTag + : componentOrHandle.__nativeTag; +} +var emptyObject = {}; +function createHierarchy(fiberHierarchy) { + return fiberHierarchy.map(function (fiber$jscomp$0) { return { - name: getComponentNameFromType(fiber.type), + name: getComponentNameFromType(fiber$jscomp$0.type), getInspectorData: function (findNodeHandle) { return { - props: getHostProps(fiber), - source: fiber._debugSource, + props: getHostProps(fiber$jscomp$0), + source: fiber$jscomp$0._debugSource, measure: function (callback) { - var hostFiber = findCurrentHostFiber(fiber); + var hostFiber = findCurrentHostFiber(fiber$jscomp$0); if ( (hostFiber = null != hostFiber && @@ -9433,82 +9579,43 @@ createHierarchy = function (fiberHierarchy) { hostFiber.stateNode.node) ) nativeFabricUIManager.measure(hostFiber, callback); - else - return ReactNativePrivateInterface.UIManager.measure( - getHostNode(fiber, findNodeHandle), + else { + hostFiber = ReactNativePrivateInterface.UIManager; + var JSCompiler_temp_const = hostFiber.measure, + JSCompiler_inline_result; + a: { + for (var fiber = fiber$jscomp$0; fiber; ) { + null !== fiber.stateNode && + 5 === fiber.tag && + (JSCompiler_inline_result = findNodeHandle( + fiber.stateNode + )); + if (JSCompiler_inline_result) break a; + fiber = fiber.child; + } + JSCompiler_inline_result = null; + } + return JSCompiler_temp_const.call( + hostFiber, + JSCompiler_inline_result, callback ); + } } }; } }; }); -}; -getHostNode = function (fiber, findNodeHandle) { - for (var hostNode; fiber; ) { - null !== fiber.stateNode && - 5 === fiber.tag && - (hostNode = findNodeHandle(fiber.stateNode)); - if (hostNode) return hostNode; - fiber = fiber.child; - } - return null; -}; -getHostProps = function (fiber) { +} +function getHostProps(fiber) { return (fiber = findCurrentHostFiber(fiber)) ? fiber.memoizedProps || emptyObject : emptyObject; -}; -exports.getInspectorDataForInstance = function (closestInstance) { - if (!closestInstance) - return { - hierarchy: [], - props: emptyObject, - selectedIndex: null, - source: null - }; - closestInstance = findCurrentFiberUsingSlowPath(closestInstance); - var fiberHierarchy = getOwnerHierarchy(closestInstance); - closestInstance = lastNonHostInstance(fiberHierarchy); - var hierarchy = createHierarchy(fiberHierarchy), - props = getHostProps(closestInstance), - source = closestInstance._debugSource; - fiberHierarchy = fiberHierarchy.indexOf(closestInstance); - return { - closestInstance: closestInstance, - hierarchy: hierarchy, - props: props, - selectedIndex: fiberHierarchy, - source: source - }; -}; -getOwnerHierarchy = function (instance) { - var hierarchy = []; - traverseOwnerTreeUp(hierarchy, instance); - return hierarchy; -}; -lastNonHostInstance = function (hierarchy) { - for (var i = hierarchy.length - 1; 1 < i; i--) { - var instance = hierarchy[i]; - if (5 !== instance.tag) return instance; - } - return hierarchy[0]; -}; -traverseOwnerTreeUp = function (hierarchy, instance) { +} +function traverseOwnerTreeUp(hierarchy, instance) { instance && (hierarchy.unshift(instance), traverseOwnerTreeUp(hierarchy, instance._debugOwner)); -}; -function findNodeHandle(componentOrHandle) { - if (null == componentOrHandle) return null; - if ("number" === typeof componentOrHandle) return componentOrHandle; - if (componentOrHandle._nativeTag) return componentOrHandle._nativeTag; - if (componentOrHandle.canonical && componentOrHandle.canonical._nativeTag) - return componentOrHandle.canonical._nativeTag; - componentOrHandle = findHostInstance(componentOrHandle); - return null == componentOrHandle - ? componentOrHandle - : componentOrHandle._nativeTag; } function onRecoverableError(error) { console.error(error); @@ -9533,10 +9640,10 @@ batchedUpdatesImpl = function (fn, a) { } }; var roots = new Map(), - devToolsConfig$jscomp$inline_1045 = { + devToolsConfig$jscomp$inline_1089 = { findFiberByHostInstance: getInstanceFromTag, bundleType: 0, - version: "18.3.0-next-ef8bdbecb-20230310", + version: "18.3.0-next-c57b90f50-20230320", rendererPackageName: "react-native-renderer", rendererConfig: { getInspectorDataForViewTag: function () { @@ -9551,11 +9658,11 @@ var roots = new Map(), }.bind(null, findNodeHandle) } }; -var internals$jscomp$inline_1293 = { - bundleType: devToolsConfig$jscomp$inline_1045.bundleType, - version: devToolsConfig$jscomp$inline_1045.version, - rendererPackageName: devToolsConfig$jscomp$inline_1045.rendererPackageName, - rendererConfig: devToolsConfig$jscomp$inline_1045.rendererConfig, +var internals$jscomp$inline_1343 = { + bundleType: devToolsConfig$jscomp$inline_1089.bundleType, + version: devToolsConfig$jscomp$inline_1089.version, + rendererPackageName: devToolsConfig$jscomp$inline_1089.rendererPackageName, + rendererConfig: devToolsConfig$jscomp$inline_1089.rendererConfig, overrideHookState: null, overrideHookStateDeletePath: null, overrideHookStateRenamePath: null, @@ -9571,26 +9678,26 @@ var internals$jscomp$inline_1293 = { return null === fiber ? null : fiber.stateNode; }, findFiberByHostInstance: - devToolsConfig$jscomp$inline_1045.findFiberByHostInstance || + devToolsConfig$jscomp$inline_1089.findFiberByHostInstance || emptyFindFiberByHostInstance, findHostInstancesForRefresh: null, scheduleRefresh: null, scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "18.3.0-next-ef8bdbecb-20230310" + reconcilerVersion: "18.3.0-next-c57b90f50-20230320" }; if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { - var hook$jscomp$inline_1294 = __REACT_DEVTOOLS_GLOBAL_HOOK__; + var hook$jscomp$inline_1344 = __REACT_DEVTOOLS_GLOBAL_HOOK__; if ( - !hook$jscomp$inline_1294.isDisabled && - hook$jscomp$inline_1294.supportsFiber + !hook$jscomp$inline_1344.isDisabled && + hook$jscomp$inline_1344.supportsFiber ) try { - (rendererID = hook$jscomp$inline_1294.inject( - internals$jscomp$inline_1293 + (rendererID = hook$jscomp$inline_1344.inject( + internals$jscomp$inline_1343 )), - (injectedHook = hook$jscomp$inline_1294); + (injectedHook = hook$jscomp$inline_1344); } catch (err) {} } exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = { @@ -9609,13 +9716,16 @@ exports.createPortal = function (children, containerTag) { ); }; exports.dispatchCommand = function (handle, command, args) { - null != handle._nativeTag && - (null != handle._internalInstanceHandle - ? ((handle = handle._internalInstanceHandle.stateNode), - null != handle && - nativeFabricUIManager.dispatchCommand(handle.node, command, args)) + var nativeTag = + null != handle._nativeTag ? handle._nativeTag : handle.__nativeTag; + null != nativeTag && + ((handle = handle.__internalInstanceHandle), + null != handle + ? ((nativeTag = handle && handle.stateNode && handle.stateNode.node), + null != nativeTag && + nativeFabricUIManager.dispatchCommand(nativeTag, command, args)) : ReactNativePrivateInterface.UIManager.dispatchViewManagerCommand( - handle._nativeTag, + nativeTag, command, args )); @@ -9623,13 +9733,46 @@ exports.dispatchCommand = function (handle, command, args) { exports.findHostInstance_DEPRECATED = function (componentOrHandle) { return null == componentOrHandle ? null + : componentOrHandle.canonical && componentOrHandle.canonical.publicInstance + ? componentOrHandle.canonical.publicInstance : componentOrHandle._nativeTag ? componentOrHandle - : componentOrHandle.canonical && componentOrHandle.canonical._nativeTag - ? componentOrHandle.canonical : findHostInstance(componentOrHandle); }; exports.findNodeHandle = findNodeHandle; +exports.getInspectorDataForInstance = function (closestInstance) { + if (!closestInstance) + return { + hierarchy: [], + props: emptyObject, + selectedIndex: null, + source: null + }; + var fiber = findCurrentFiberUsingSlowPath(closestInstance); + closestInstance = []; + traverseOwnerTreeUp(closestInstance, fiber); + a: { + for (fiber = closestInstance.length - 1; 1 < fiber; fiber--) { + var instance = closestInstance[fiber]; + if (5 !== instance.tag) { + fiber = instance; + break a; + } + } + fiber = closestInstance[0]; + } + instance = createHierarchy(closestInstance); + var props = getHostProps(fiber), + source = fiber._debugSource; + closestInstance = closestInstance.indexOf(fiber); + return { + closestInstance: fiber, + hierarchy: instance, + props: props, + selectedIndex: closestInstance, + source: source + }; +}; exports.render = function (element, containerTag, callback) { var root = roots.get(containerTag); if (!root) { @@ -9659,13 +9802,16 @@ exports.render = function (element, containerTag, callback) { return element; }; exports.sendAccessibilityEvent = function (handle, eventType) { - null != handle._nativeTag && - (null != handle._internalInstanceHandle - ? ((handle = handle._internalInstanceHandle.stateNode), - null != handle && - nativeFabricUIManager.sendAccessibilityEvent(handle.node, eventType)) + var nativeTag = + null != handle._nativeTag ? handle._nativeTag : handle.__nativeTag; + null != nativeTag && + ((handle = handle.__internalInstanceHandle), + null != handle + ? ((nativeTag = handle && handle.stateNode && handle.stateNode.node), + null != nativeTag && + nativeFabricUIManager.sendAccessibilityEvent(nativeTag, eventType)) : ReactNativePrivateInterface.legacySendAccessibilityEvent( - handle._nativeTag, + nativeTag, eventType )); }; diff --git a/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.fb.js b/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.fb.js index 9b63001be6bbc..fd7c3e6628655 100644 --- a/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.fb.js +++ b/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.fb.js @@ -951,7 +951,7 @@ eventPluginOrder = Array.prototype.slice.call([ "ReactNativeBridgeEventPlugin" ]); recomputePluginOrdering(); -var injectedNamesToPlugins$jscomp$inline_255 = { +var injectedNamesToPlugins$jscomp$inline_264 = { ResponderEventPlugin: ResponderEventPlugin, ReactNativeBridgeEventPlugin: { eventTypes: {}, @@ -997,32 +997,32 @@ var injectedNamesToPlugins$jscomp$inline_255 = { } } }, - isOrderingDirty$jscomp$inline_256 = !1, - pluginName$jscomp$inline_257; -for (pluginName$jscomp$inline_257 in injectedNamesToPlugins$jscomp$inline_255) + isOrderingDirty$jscomp$inline_265 = !1, + pluginName$jscomp$inline_266; +for (pluginName$jscomp$inline_266 in injectedNamesToPlugins$jscomp$inline_264) if ( - injectedNamesToPlugins$jscomp$inline_255.hasOwnProperty( - pluginName$jscomp$inline_257 + injectedNamesToPlugins$jscomp$inline_264.hasOwnProperty( + pluginName$jscomp$inline_266 ) ) { - var pluginModule$jscomp$inline_258 = - injectedNamesToPlugins$jscomp$inline_255[pluginName$jscomp$inline_257]; + var pluginModule$jscomp$inline_267 = + injectedNamesToPlugins$jscomp$inline_264[pluginName$jscomp$inline_266]; if ( - !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_257) || - namesToPlugins[pluginName$jscomp$inline_257] !== - pluginModule$jscomp$inline_258 + !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_266) || + namesToPlugins[pluginName$jscomp$inline_266] !== + pluginModule$jscomp$inline_267 ) { - if (namesToPlugins[pluginName$jscomp$inline_257]) + if (namesToPlugins[pluginName$jscomp$inline_266]) throw Error( "EventPluginRegistry: Cannot inject two different event plugins using the same name, `" + - (pluginName$jscomp$inline_257 + "`.") + (pluginName$jscomp$inline_266 + "`.") ); - namesToPlugins[pluginName$jscomp$inline_257] = - pluginModule$jscomp$inline_258; - isOrderingDirty$jscomp$inline_256 = !0; + namesToPlugins[pluginName$jscomp$inline_266] = + pluginModule$jscomp$inline_267; + isOrderingDirty$jscomp$inline_265 = !0; } } -isOrderingDirty$jscomp$inline_256 && recomputePluginOrdering(); +isOrderingDirty$jscomp$inline_265 && recomputePluginOrdering(); var instanceCache = new Map(), instanceProps = new Map(); function getInstanceFromTag(tag) { @@ -1152,7 +1152,9 @@ getInstanceFromNode = getInstanceFromTag; getNodeFromInstance = function (inst) { inst = inst.stateNode; var tag = inst._nativeTag; - void 0 === tag && ((inst = inst.canonical), (tag = inst._nativeTag)); + void 0 === tag && + null != inst.canonical && + ((tag = inst.canonical.nativeTag), (inst = inst.canonical.publicInstance)); if (!tag) throw Error("All native instances should have a tag."); return inst; }; @@ -1974,6 +1976,12 @@ function claimNextTransitionLane() { 0 === (nextTransitionLane & 8388480) && (nextTransitionLane = 128); return lane; } +function claimNextRetryLane() { + var lane = nextRetryLane; + nextRetryLane <<= 1; + 0 === (nextRetryLane & 125829120) && (nextRetryLane = 8388608); + return lane; +} function createLaneMap(initial) { for (var laneMap = [], i = 0; 31 > i; i++) laneMap.push(initial); return laneMap; @@ -2105,7 +2113,9 @@ function finalizeInitialChildren(parentInstance) { return !1; } function getPublicInstance(instance) { - return instance.canonical ? instance.canonical : instance; + return null != instance.canonical && null != instance.canonical.publicInstance + ? instance.canonical.publicInstance + : instance; } var scheduleTimeout = setTimeout, cancelTimeout = clearTimeout; @@ -2227,30 +2237,43 @@ var objectIs = "function" === typeof Object.is ? Object.is : is, function flushSyncCallbacks() { if (!isFlushingSyncQueue && null !== syncQueue) { isFlushingSyncQueue = !0; - var i = 0, - previousUpdatePriority = currentUpdatePriority; - try { - var queue = syncQueue; - for (currentUpdatePriority = 2; i < queue.length; i++) { - var callback = queue[i]; + var previousUpdatePriority = currentUpdatePriority; + currentUpdatePriority = 2; + for (var errors = null, queue = syncQueue, i = 0; i < queue.length; i++) { + var callback = queue[i]; + try { do callback = callback(!0); while (null !== callback); + } catch (error) { + null === errors ? (errors = [error]) : errors.push(error); } - syncQueue = null; - includesLegacySyncCallbacks = !1; - } catch (error) { - throw ( - (null !== syncQueue && (syncQueue = syncQueue.slice(i + 1)), - scheduleCallback$1(ImmediatePriority, flushSyncCallbacks), - error) - ); - } finally { - (currentUpdatePriority = previousUpdatePriority), - (isFlushingSyncQueue = !1); + } + syncQueue = null; + includesLegacySyncCallbacks = !1; + currentUpdatePriority = previousUpdatePriority; + isFlushingSyncQueue = !1; + if (null !== errors) { + if (1 < errors.length) { + if ("function" === typeof AggregateError) + throw new AggregateError(errors); + for ( + previousUpdatePriority = 1; + previousUpdatePriority < errors.length; + previousUpdatePriority++ + ) + scheduleCallback$1( + ImmediatePriority, + throwError.bind(null, errors[previousUpdatePriority]) + ); + } + throw errors[0]; } } return null; } +function throwError(error) { + throw error; +} var contextStackCursor = createCursor(null), contextFiberStackCursor = createCursor(null), rootInstanceStackCursor = createCursor(null); @@ -2662,6 +2685,65 @@ function getStackByFiberInDevAndProd(workInProgress) { return "\nError generating stack: " + x.message + "\n" + x.stack; } } +var SuspenseException = Error( + "Suspense Exception: This is not a real error! It's an implementation detail of `use` to interrupt the current render. You must either rethrow it immediately, or move the `use` call outside of the `try/catch` block. Capturing without rethrowing will lead to unexpected behavior.\n\nTo handle async errors, wrap your component in an error boundary, or call the promise's `.catch` method and pass the result to `use`" + ), + noopSuspenseyCommitThenable = { then: function () {} }; +function isThenableResolved(thenable) { + thenable = thenable.status; + return "fulfilled" === thenable || "rejected" === thenable; +} +function noop() {} +function trackUsedThenable(thenableState, thenable, index) { + index = thenableState[index]; + void 0 === index + ? thenableState.push(thenable) + : index !== thenable && (thenable.then(noop, noop), (thenable = index)); + switch (thenable.status) { + case "fulfilled": + return thenable.value; + case "rejected": + throw thenable.reason; + default: + "string" === typeof thenable.status + ? thenable.then(noop, noop) + : ((thenableState = thenable), + (thenableState.status = "pending"), + thenableState.then( + function (fulfilledValue) { + if ("pending" === thenable.status) { + var fulfilledThenable = thenable; + fulfilledThenable.status = "fulfilled"; + fulfilledThenable.value = fulfilledValue; + } + }, + function (error) { + if ("pending" === thenable.status) { + var rejectedThenable = thenable; + rejectedThenable.status = "rejected"; + rejectedThenable.reason = error; + } + } + )); + switch (thenable.status) { + case "fulfilled": + return thenable.value; + case "rejected": + throw thenable.reason; + } + suspendedThenable = thenable; + throw SuspenseException; + } +} +var suspendedThenable = null, + thenableState$1 = null, + thenableIndexCounter$1 = 0; +function unwrapThenable(thenable) { + var index = thenableIndexCounter$1; + thenableIndexCounter$1 += 1; + null === thenableState$1 && (thenableState$1 = []); + return trackUsedThenable(thenableState$1, thenable, index); +} function coerceRef(returnFiber, current, element) { returnFiber = element.ref; if ( @@ -2766,16 +2848,16 @@ function createChildReconciler(shouldTrackSideEffects) { return ( (newIndex = newIndex.index), newIndex < lastPlacedIndex - ? ((newFiber.flags |= 16777218), lastPlacedIndex) + ? ((newFiber.flags |= 33554434), lastPlacedIndex) : newIndex ); - newFiber.flags |= 16777218; + newFiber.flags |= 33554434; return lastPlacedIndex; } function placeSingleChild(newFiber) { shouldTrackSideEffects && null === newFiber.alternate && - (newFiber.flags |= 16777218); + (newFiber.flags |= 33554434); return newFiber; } function updateTextNode(returnFiber, current, textContent, lanes) { @@ -2912,6 +2994,17 @@ function createChildReconciler(shouldTrackSideEffects) { (newChild.return = returnFiber), newChild ); + if ("function" === typeof newChild.then) + return createChild(returnFiber, unwrapThenable(newChild), lanes); + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) + return createChild( + returnFiber, + readContextDuringReconcilation(returnFiber, newChild, lanes), + lanes + ); throwOnInvalidObjectType(returnFiber, newChild); } return null; @@ -2945,6 +3038,23 @@ function createChildReconciler(shouldTrackSideEffects) { return null !== key ? null : updateFragment(returnFiber, oldFiber, newChild, lanes, null); + if ("function" === typeof newChild.then) + return updateSlot( + returnFiber, + oldFiber, + unwrapThenable(newChild), + lanes + ); + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) + return updateSlot( + returnFiber, + oldFiber, + readContextDuringReconcilation(returnFiber, newChild, lanes), + lanes + ); throwOnInvalidObjectType(returnFiber, newChild); } return null; @@ -2997,6 +3107,25 @@ function createChildReconciler(shouldTrackSideEffects) { (existingChildren = existingChildren.get(newIdx) || null), updateFragment(returnFiber, existingChildren, newChild, lanes, null) ); + if ("function" === typeof newChild.then) + return updateFromMap( + existingChildren, + returnFiber, + newIdx, + unwrapThenable(newChild), + lanes + ); + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) + return updateFromMap( + existingChildren, + returnFiber, + newIdx, + readContextDuringReconcilation(returnFiber, newChild, lanes), + lanes + ); throwOnInvalidObjectType(returnFiber, newChild); } return null; @@ -3168,7 +3297,7 @@ function createChildReconciler(shouldTrackSideEffects) { }); return iteratorFn; } - function reconcileChildFibers( + function reconcileChildFibersImpl( returnFiber, currentFirstChild, newChild, @@ -3313,6 +3442,23 @@ function createChildReconciler(shouldTrackSideEffects) { newChild, lanes ); + if ("function" === typeof newChild.then) + return reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + unwrapThenable(newChild), + lanes + ); + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) + return reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + readContextDuringReconcilation(returnFiber, newChild, lanes), + lanes + ); throwOnInvalidObjectType(returnFiber, newChild); } return ("string" === typeof newChild && "" !== newChild) || @@ -3334,6 +3480,22 @@ function createChildReconciler(shouldTrackSideEffects) { placeSingleChild(returnFiber)) : deleteRemainingChildren(returnFiber, currentFirstChild); } + function reconcileChildFibers( + returnFiber, + currentFirstChild, + newChild, + lanes + ) { + thenableIndexCounter$1 = 0; + returnFiber = reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + newChild, + lanes + ); + thenableState$1 = null; + return returnFiber; + } return reconcileChildFibers; } var reconcileChildFibers = createChildReconciler(!0), @@ -3412,57 +3574,7 @@ function resetWorkInProgressVersions() { workInProgressSources[i]._workInProgressVersionPrimary = null; workInProgressSources.length = 0; } -var SuspenseException = Error( - "Suspense Exception: This is not a real error! It's an implementation detail of `use` to interrupt the current render. You must either rethrow it immediately, or move the `use` call outside of the `try/catch` block. Capturing without rethrowing will lead to unexpected behavior.\n\nTo handle async errors, wrap your component in an error boundary, or call the promise's `.catch` method and pass the result to `use`" -); -function isThenableResolved(thenable) { - thenable = thenable.status; - return "fulfilled" === thenable || "rejected" === thenable; -} -function noop() {} -function trackUsedThenable(thenableState, thenable, index) { - index = thenableState[index]; - void 0 === index - ? thenableState.push(thenable) - : index !== thenable && (thenable.then(noop, noop), (thenable = index)); - switch (thenable.status) { - case "fulfilled": - return thenable.value; - case "rejected": - throw thenable.reason; - default: - "string" === typeof thenable.status - ? thenable.then(noop, noop) - : ((thenableState = thenable), - (thenableState.status = "pending"), - thenableState.then( - function (fulfilledValue) { - if ("pending" === thenable.status) { - var fulfilledThenable = thenable; - fulfilledThenable.status = "fulfilled"; - fulfilledThenable.value = fulfilledValue; - } - }, - function (error) { - if ("pending" === thenable.status) { - var rejectedThenable = thenable; - rejectedThenable.status = "rejected"; - rejectedThenable.reason = error; - } - } - )); - switch (thenable.status) { - case "fulfilled": - return thenable.value; - case "rejected": - throw thenable.reason; - } - suspendedThenable = thenable; - throw SuspenseException; - } -} -var suspendedThenable = null, - ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, +var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, ReactCurrentBatchConfig$2 = ReactSharedInternals.ReactCurrentBatchConfig, renderLanes$1 = 0, currentlyRenderingFiber$1 = null, @@ -3622,10 +3734,10 @@ createFunctionComponentUpdateQueue = function () { function use(usable) { if (null !== usable && "object" === typeof usable) { if ("function" === typeof usable.then) { - var index$30 = thenableIndexCounter; + var index$32 = thenableIndexCounter; thenableIndexCounter += 1; null === thenableState && (thenableState = []); - usable = trackUsedThenable(thenableState, usable, index$30); + usable = trackUsedThenable(thenableState, usable, index$32); null === currentlyRenderingFiber$1.alternate && (null === workInProgressHook ? null === currentlyRenderingFiber$1.memoizedState @@ -4080,8 +4192,9 @@ function startTransition(setPending, callback) { var previousPriority = currentUpdatePriority; currentUpdatePriority = 0 !== previousPriority && 8 > previousPriority ? previousPriority : 8; - setPending(!0); var prevTransition = ReactCurrentBatchConfig$2.transition; + ReactCurrentBatchConfig$2.transition = null; + setPending(!0); ReactCurrentBatchConfig$2.transition = {}; try { setPending(!1), callback(); @@ -5283,7 +5396,7 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { (nextProps.treeBaseDuration = JSCompiler_temp.treeBaseDuration)), (workInProgress.deletions = null)) : ((nextProps = createWorkInProgress(JSCompiler_temp, primaryChildProps)), - (nextProps.subtreeFlags = JSCompiler_temp.subtreeFlags & 14680064)); + (nextProps.subtreeFlags = JSCompiler_temp.subtreeFlags & 31457280)); null !== dehydrated ? (showFallback = createWorkInProgress(dehydrated, showFallback)) : ((showFallback = createFiberFromFragment( @@ -5822,25 +5935,38 @@ function prepareToReadContext(workInProgress, renderLanes) { (workInProgress.firstContext = null)); } function readContext(context) { + return readContextForConsumer(currentlyRenderingFiber, context); +} +function readContextDuringReconcilation(consumer, context, renderLanes) { + null === currentlyRenderingFiber && + prepareToReadContext(consumer, renderLanes); + return readContextForConsumer(consumer, context); +} +function readContextForConsumer(consumer, context) { var value = context._currentValue; if (lastFullyObservedContext !== context) if ( ((context = { context: context, memoizedValue: value, next: null }), null === lastContextDependency) ) { - if (null === currentlyRenderingFiber) + if (null === consumer) throw 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()." ); lastContextDependency = context; - currentlyRenderingFiber.dependencies = { - lanes: 0, - firstContext: context - }; + consumer.dependencies = { lanes: 0, firstContext: context }; } else lastContextDependency = lastContextDependency.next = context; return value; } var ReactCurrentBatchConfig$1 = ReactSharedInternals.ReactCurrentBatchConfig; +function scheduleRetryEffect(workInProgress, retryQueue) { + null !== retryQueue + ? (workInProgress.flags |= 4) + : workInProgress.flags & 16384 && + ((retryQueue = + 22 !== workInProgress.tag ? claimNextRetryLane() : 1073741824), + (workInProgress.lanes |= retryQueue)); +} function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { switch (renderState.tailMode) { case "hidden": @@ -5855,14 +5981,14 @@ function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { break; case "collapsed": lastTailNode = renderState.tail; - for (var lastTailNode$67 = null; null !== lastTailNode; ) - null !== lastTailNode.alternate && (lastTailNode$67 = lastTailNode), + for (var lastTailNode$70 = null; null !== lastTailNode; ) + null !== lastTailNode.alternate && (lastTailNode$70 = lastTailNode), (lastTailNode = lastTailNode.sibling); - null === lastTailNode$67 + null === lastTailNode$70 ? hasRenderedATailFallback || null === renderState.tail ? (renderState.tail = null) : (renderState.tail.sibling = null) - : (lastTailNode$67.sibling = null); + : (lastTailNode$70.sibling = null); } } function bubbleProperties(completedWork) { @@ -5874,53 +6000,53 @@ function bubbleProperties(completedWork) { if (didBailout) if (0 !== (completedWork.mode & 2)) { for ( - var treeBaseDuration$69 = completedWork.selfBaseDuration, - child$70 = completedWork.child; - null !== child$70; + var treeBaseDuration$72 = completedWork.selfBaseDuration, + child$73 = completedWork.child; + null !== child$73; ) - (newChildLanes |= child$70.lanes | child$70.childLanes), - (subtreeFlags |= child$70.subtreeFlags & 14680064), - (subtreeFlags |= child$70.flags & 14680064), - (treeBaseDuration$69 += child$70.treeBaseDuration), - (child$70 = child$70.sibling); - completedWork.treeBaseDuration = treeBaseDuration$69; + (newChildLanes |= child$73.lanes | child$73.childLanes), + (subtreeFlags |= child$73.subtreeFlags & 31457280), + (subtreeFlags |= child$73.flags & 31457280), + (treeBaseDuration$72 += child$73.treeBaseDuration), + (child$73 = child$73.sibling); + completedWork.treeBaseDuration = treeBaseDuration$72; } else for ( - treeBaseDuration$69 = completedWork.child; - null !== treeBaseDuration$69; + treeBaseDuration$72 = completedWork.child; + null !== treeBaseDuration$72; ) (newChildLanes |= - treeBaseDuration$69.lanes | treeBaseDuration$69.childLanes), - (subtreeFlags |= treeBaseDuration$69.subtreeFlags & 14680064), - (subtreeFlags |= treeBaseDuration$69.flags & 14680064), - (treeBaseDuration$69.return = completedWork), - (treeBaseDuration$69 = treeBaseDuration$69.sibling); + treeBaseDuration$72.lanes | treeBaseDuration$72.childLanes), + (subtreeFlags |= treeBaseDuration$72.subtreeFlags & 31457280), + (subtreeFlags |= treeBaseDuration$72.flags & 31457280), + (treeBaseDuration$72.return = completedWork), + (treeBaseDuration$72 = treeBaseDuration$72.sibling); else if (0 !== (completedWork.mode & 2)) { - treeBaseDuration$69 = completedWork.actualDuration; - child$70 = completedWork.selfBaseDuration; + treeBaseDuration$72 = completedWork.actualDuration; + child$73 = completedWork.selfBaseDuration; for (var child = completedWork.child; null !== child; ) (newChildLanes |= child.lanes | child.childLanes), (subtreeFlags |= child.subtreeFlags), (subtreeFlags |= child.flags), - (treeBaseDuration$69 += child.actualDuration), - (child$70 += child.treeBaseDuration), + (treeBaseDuration$72 += child.actualDuration), + (child$73 += child.treeBaseDuration), (child = child.sibling); - completedWork.actualDuration = treeBaseDuration$69; - completedWork.treeBaseDuration = child$70; + completedWork.actualDuration = treeBaseDuration$72; + completedWork.treeBaseDuration = child$73; } else for ( - treeBaseDuration$69 = completedWork.child; - null !== treeBaseDuration$69; + treeBaseDuration$72 = completedWork.child; + null !== treeBaseDuration$72; ) (newChildLanes |= - treeBaseDuration$69.lanes | treeBaseDuration$69.childLanes), - (subtreeFlags |= treeBaseDuration$69.subtreeFlags), - (subtreeFlags |= treeBaseDuration$69.flags), - (treeBaseDuration$69.return = completedWork), - (treeBaseDuration$69 = treeBaseDuration$69.sibling); + treeBaseDuration$72.lanes | treeBaseDuration$72.childLanes), + (subtreeFlags |= treeBaseDuration$72.subtreeFlags), + (subtreeFlags |= treeBaseDuration$72.flags), + (treeBaseDuration$72.return = completedWork), + (treeBaseDuration$72 = treeBaseDuration$72.sibling); completedWork.subtreeFlags |= subtreeFlags; completedWork.childLanes = newChildLanes; return didBailout; @@ -5973,7 +6099,8 @@ function completeWork(current, workInProgress, renderLanes) { var type = workInProgress.type; if (null !== current && null != workInProgress.stateNode) current.memoizedProps !== newProps && - (workInProgress.updateQueue = UPDATE_SIGNAL) && + ((workInProgress.flags &= -16777217), + (workInProgress.updateQueue = UPDATE_SIGNAL)) && (workInProgress.flags |= 4), current.ref !== workInProgress.ref && (workInProgress.flags |= 2097664); @@ -6030,6 +6157,7 @@ function completeWork(current, workInProgress, renderLanes) { } workInProgress.stateNode = current; finalizeInitialChildren(current) && (workInProgress.flags |= 4); + workInProgress.flags &= -16777217; null !== workInProgress.ref && (workInProgress.flags |= 2097664); } bubbleProperties(workInProgress); @@ -6103,7 +6231,7 @@ function completeWork(current, workInProgress, renderLanes) { renderLanes !== (null !== current && null !== current.memoizedState) && renderLanes && (workInProgress.child.flags |= 8192); - null !== workInProgress.updateQueue && (workInProgress.flags |= 4); + scheduleRetryEffect(workInProgress, workInProgress.updateQueue); bubbleProperties(workInProgress); 0 !== (workInProgress.mode & 2) && renderLanes && @@ -6144,9 +6272,8 @@ function completeWork(current, workInProgress, renderLanes) { workInProgress.flags |= 128; cutOffTailIfNeeded(type, !1); current = updatePayload.updateQueue; - null !== current && - ((workInProgress.updateQueue = current), - (workInProgress.flags |= 4)); + workInProgress.updateQueue = current; + scheduleRetryEffect(workInProgress, current); workInProgress.subtreeFlags = 0; for (current = workInProgress.child; null !== current; ) resetWorkInProgress(current, renderLanes), @@ -6175,9 +6302,8 @@ function completeWork(current, workInProgress, renderLanes) { ((workInProgress.flags |= 128), (newProps = !0), (renderLanes = current.updateQueue), - null !== renderLanes && - ((workInProgress.updateQueue = renderLanes), - (workInProgress.flags |= 4)), + (workInProgress.updateQueue = renderLanes), + scheduleRetryEffect(workInProgress, renderLanes), cutOffTailIfNeeded(type, !0), null === type.tail && "hidden" === type.tailMode && @@ -6236,7 +6362,9 @@ function completeWork(current, workInProgress, renderLanes) { workInProgress.subtreeFlags & 6 && (workInProgress.flags |= 8192)) : bubbleProperties(workInProgress), - null !== workInProgress.updateQueue && (workInProgress.flags |= 4), + (renderLanes = workInProgress.updateQueue), + null !== renderLanes && + scheduleRetryEffect(workInProgress, renderLanes.retryQueue), null ); case 24: @@ -6434,8 +6562,8 @@ function safelyDetachRef(current, nearestMountedAncestor) { recordLayoutEffectDuration(current); } else ref(null); - } catch (error$86) { - captureCommitPhaseError(current, nearestMountedAncestor, error$86); + } catch (error$91) { + captureCommitPhaseError(current, nearestMountedAncestor, error$91); } else ref.current = null; } @@ -6567,8 +6695,8 @@ function commitHookEffectListMount(flags, finishedWork) { injectedProfilingHooks.markComponentLayoutEffectMountStarted( finishedWork ); - var create$87 = effect.create; - effect.destroy = create$87(); + var create$92 = effect.create; + effect.destroy = create$92(); 0 !== (flags & 8) ? null !== injectedProfilingHooks && "function" === @@ -6596,8 +6724,8 @@ function commitHookLayoutEffects(finishedWork, hookFlags) { } else try { commitHookEffectListMount(hookFlags, finishedWork); - } catch (error$89) { - captureCommitPhaseError(finishedWork, finishedWork.return, error$89); + } catch (error$94) { + captureCommitPhaseError(finishedWork, finishedWork.return, error$94); } } function commitClassCallbacks(finishedWork) { @@ -6677,11 +6805,11 @@ function commitLayoutEffectOnFiber(finishedRoot, current, finishedWork) { } else try { finishedRoot.componentDidMount(); - } catch (error$90) { + } catch (error$95) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$90 + error$95 ); } else { @@ -6698,11 +6826,11 @@ function commitLayoutEffectOnFiber(finishedRoot, current, finishedWork) { current, finishedRoot.__reactInternalSnapshotBeforeUpdate ); - } catch (error$91) { + } catch (error$96) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$91 + error$96 ); } recordLayoutEffectDuration(finishedWork); @@ -6713,11 +6841,11 @@ function commitLayoutEffectOnFiber(finishedRoot, current, finishedWork) { current, finishedRoot.__reactInternalSnapshotBeforeUpdate ); - } catch (error$92) { + } catch (error$97) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$92 + error$97 ); } } @@ -7226,22 +7354,22 @@ function commitMutationEffectsOnFiber(finishedWork, root) { try { startLayoutEffectTimer(), commitHookEffectListUnmount(5, finishedWork, finishedWork.return); - } catch (error$101) { + } catch (error$106) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$101 + error$106 ); } recordLayoutEffectDuration(finishedWork); } else try { commitHookEffectListUnmount(5, finishedWork, finishedWork.return); - } catch (error$102) { + } catch (error$107) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$102 + error$107 ); } } @@ -7291,11 +7419,11 @@ function commitMutationEffectsOnFiber(finishedWork, root) { viewConfig.uiViewClassName, updatePayload$jscomp$0 ); - } catch (error$105) { + } catch (error$110) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$105 + error$110 ); } } @@ -7316,8 +7444,8 @@ function commitMutationEffectsOnFiber(finishedWork, root) { "RCTRawText", { text: current } ); - } catch (error$106) { - captureCommitPhaseError(finishedWork, finishedWork.return, error$106); + } catch (error$111) { + captureCommitPhaseError(finishedWork, finishedWork.return, error$111); } } break; @@ -7430,11 +7558,11 @@ function commitMutationEffectsOnFiber(finishedWork, root) { if (null === current) try { throw Error("Not yet implemented."); - } catch (error$95) { + } catch (error$100) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$95 + error$100 ); } } else if ( @@ -7460,9 +7588,9 @@ function commitMutationEffectsOnFiber(finishedWork, root) { flags & 4 && ((flags = finishedWork.updateQueue), null !== flags && - ((current = flags.wakeables), + ((current = flags.retryQueue), null !== current && - ((flags.wakeables = null), + ((flags.retryQueue = null), attachSuspenseRetryListeners(finishedWork, current)))); break; case 19: @@ -7508,12 +7636,12 @@ function commitReconciliationEffects(finishedWork) { break; case 3: case 4: - var parent$96 = JSCompiler_inline_result.stateNode.containerInfo, - before$97 = getHostSibling(finishedWork); + var parent$101 = JSCompiler_inline_result.stateNode.containerInfo, + before$102 = getHostSibling(finishedWork); insertOrAppendPlacementNodeIntoContainer( finishedWork, - before$97, - parent$96 + before$102, + parent$101 ); break; default: @@ -7699,8 +7827,8 @@ function commitHookPassiveMountEffects(finishedWork, hookFlags) { } else try { commitHookEffectListMount(hookFlags, finishedWork); - } catch (error$113) { - captureCommitPhaseError(finishedWork, finishedWork.return, error$113); + } catch (error$118) { + captureCommitPhaseError(finishedWork, finishedWork.return, error$118); } } function recursivelyTraversePassiveMountEffects(root, parentFiber) { @@ -8038,6 +8166,8 @@ function ensureRootIsScheduled(root, currentTime) { (root.callbackPriority = 0); else if (2 === workInProgressSuspendedReason && workInProgressRoot === root) (root.callbackPriority = 0), (root.callbackNode = null); + else if (null !== root.cancelPendingCommit && 0 === (suspendedLanes & 42)) + (root.callbackPriority = 0), (root.callbackNode = null); else if ( ((currentTime = suspendedLanes & -suspendedLanes), root.callbackPriority !== currentTime) @@ -8096,28 +8226,28 @@ function performConcurrentWorkOnRoot(root, didTimeout) { root === workInProgressRoot ? workInProgressRootRenderLanes : 0 ); if (0 === lanes) return null; - didTimeout = + var exitStatus = includesBlockingLane(root, lanes) || 0 !== (lanes & root.expiredLanes) || didTimeout ? renderRootSync(root, lanes) : renderRootConcurrent(root, lanes); - if (0 !== didTimeout) { - if (2 === didTimeout) { - var originallyAttemptedLanes = lanes, - errorRetryLanes = getLanesToRetrySynchronouslyOnError( - root, - originallyAttemptedLanes - ); + if (0 !== exitStatus) { + if (2 === exitStatus) { + didTimeout = lanes; + var errorRetryLanes = getLanesToRetrySynchronouslyOnError( + root, + didTimeout + ); 0 !== errorRetryLanes && ((lanes = errorRetryLanes), - (didTimeout = recoverFromConcurrentError( + (exitStatus = recoverFromConcurrentError( root, - originallyAttemptedLanes, + didTimeout, errorRetryLanes ))); } - if (1 === didTimeout) + if (1 === exitStatus) throw ( ((originalCallbackNode = workInProgressRootFatalError), prepareFreshStack(root, 0), @@ -8125,30 +8255,30 @@ function performConcurrentWorkOnRoot(root, didTimeout) { ensureRootIsScheduled(root, now$1()), originalCallbackNode) ); - if (6 === didTimeout) markRootSuspended(root, lanes); + if (6 === exitStatus) markRootSuspended(root, lanes); else { errorRetryLanes = !includesBlockingLane(root, lanes); - originallyAttemptedLanes = root.current.alternate; + didTimeout = root.current.alternate; if ( errorRetryLanes && - !isRenderConsistentWithExternalStores(originallyAttemptedLanes) + !isRenderConsistentWithExternalStores(didTimeout) ) { - didTimeout = renderRootSync(root, lanes); - if (2 === didTimeout) { + exitStatus = renderRootSync(root, lanes); + if (2 === exitStatus) { errorRetryLanes = lanes; - var errorRetryLanes$115 = getLanesToRetrySynchronouslyOnError( + var errorRetryLanes$120 = getLanesToRetrySynchronouslyOnError( root, errorRetryLanes ); - 0 !== errorRetryLanes$115 && - ((lanes = errorRetryLanes$115), - (didTimeout = recoverFromConcurrentError( + 0 !== errorRetryLanes$120 && + ((lanes = errorRetryLanes$120), + (exitStatus = recoverFromConcurrentError( root, errorRetryLanes, - errorRetryLanes$115 + errorRetryLanes$120 ))); } - if (1 === didTimeout) + if (1 === exitStatus) throw ( ((originalCallbackNode = workInProgressRootFatalError), prepareFreshStack(root, 0), @@ -8157,94 +8287,84 @@ function performConcurrentWorkOnRoot(root, didTimeout) { originalCallbackNode) ); } - root.finishedWork = originallyAttemptedLanes; + root.finishedWork = didTimeout; root.finishedLanes = lanes; - switch (didTimeout) { + switch (exitStatus) { case 0: case 1: throw Error("Root did not complete. This is a bug in React."); case 2: - commitRoot( - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ); + commitRootWhenReady(root); break; case 3: markRootSuspended(root, lanes); if ( (lanes & 125829120) === lanes && - ((lanes = globalMostRecentFallbackTime + 500 - now$1()), 10 < lanes) + ((exitStatus = globalMostRecentFallbackTime + 500 - now$1()), + 10 < exitStatus) ) { if (0 !== getNextLanes(root, 0)) break; root.timeoutHandle = scheduleTimeout( - commitRoot.bind( + commitRootWhenReady.bind( null, root, + didTimeout, workInProgressRootRecoverableErrors, - workInProgressTransitions + workInProgressTransitions, + lanes ), - lanes + exitStatus ); break; } - commitRoot( - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ); + commitRootWhenReady(root); break; case 4: markRootSuspended(root, lanes); if ((lanes & 8388480) === lanes) break; - didTimeout = root.eventTimes; - for (originallyAttemptedLanes = -1; 0 < lanes; ) - (errorRetryLanes$115 = 31 - clz32(lanes)), - (errorRetryLanes = 1 << errorRetryLanes$115), - (errorRetryLanes$115 = didTimeout[errorRetryLanes$115]), - errorRetryLanes$115 > originallyAttemptedLanes && - (originallyAttemptedLanes = errorRetryLanes$115), - (lanes &= ~errorRetryLanes); - lanes = originallyAttemptedLanes; - lanes = now$1() - lanes; - lanes = - (120 > lanes + exitStatus = lanes; + errorRetryLanes = root.eventTimes; + for (errorRetryLanes$120 = -1; 0 < exitStatus; ) { + var index$6 = 31 - clz32(exitStatus), + lane = 1 << index$6; + index$6 = errorRetryLanes[index$6]; + index$6 > errorRetryLanes$120 && (errorRetryLanes$120 = index$6); + exitStatus &= ~lane; + } + exitStatus = errorRetryLanes$120; + exitStatus = now$1() - exitStatus; + exitStatus = + (120 > exitStatus ? 120 - : 480 > lanes + : 480 > exitStatus ? 480 - : 1080 > lanes + : 1080 > exitStatus ? 1080 - : 1920 > lanes + : 1920 > exitStatus ? 1920 - : 3e3 > lanes + : 3e3 > exitStatus ? 3e3 - : 4320 > lanes + : 4320 > exitStatus ? 4320 - : 1960 * ceil(lanes / 1960)) - lanes; - if (10 < lanes) { + : 1960 * ceil(exitStatus / 1960)) - exitStatus; + if (10 < exitStatus) { root.timeoutHandle = scheduleTimeout( - commitRoot.bind( + commitRootWhenReady.bind( null, root, + didTimeout, workInProgressRootRecoverableErrors, - workInProgressTransitions + workInProgressTransitions, + lanes ), - lanes + exitStatus ); break; } - commitRoot( - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ); + commitRootWhenReady(root); break; case 5: - commitRoot( - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ); + commitRootWhenReady(root); break; default: throw Error("Unknown root exit status."); @@ -8287,6 +8407,13 @@ function queueRecoverableErrors(errors) { errors ); } +function commitRootWhenReady(root) { + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); +} function isRenderConsistentWithExternalStores(finishedWork) { for (var node = finishedWork; ; ) { if (node.flags & 16384) { @@ -8385,6 +8512,8 @@ function resetWorkInProgressStack() { else resetContextDependencies(), resetHooksOnUnwind(), + (thenableState$1 = null), + (thenableIndexCounter$1 = 0), (interruptedWork = workInProgress); for (; null !== interruptedWork; ) unwindInterruptedWork(interruptedWork.alternate, interruptedWork), @@ -8398,6 +8527,9 @@ function prepareFreshStack(root, lanes) { var timeoutHandle = root.timeoutHandle; -1 !== timeoutHandle && ((root.timeoutHandle = -1), cancelTimeout(timeoutHandle)); + timeoutHandle = root.cancelPendingCommit; + null !== timeoutHandle && + ((root.cancelPendingCommit = null), timeoutHandle()); resetWorkInProgressStack(); workInProgressRoot = root; workInProgress = root = createWorkInProgress(root.current, null); @@ -8426,9 +8558,21 @@ function handleThrow(root, thrownValue) { ); thrownValue = suspendedThenable; suspendedThenable = null; - workInProgressSuspendedReason = shouldAttemptToSuspendUntilDataResolves() - ? 2 - : 3; + (workInProgressRootRenderLanes & 8388480) === workInProgressRootRenderLanes + ? (root = null === shellBoundary ? !0 : !1) + : ((root = suspenseHandlerStackCursor.current), + (root = + null !== root && + (workInProgressRootRenderLanes & 125829120) === + workInProgressRootRenderLanes + ? root === shellBoundary + : !1)); + workInProgressSuspendedReason = + root && + 0 === (workInProgressRootSkippedLanes & 268435455) && + 0 === (workInProgressRootInterleavedUpdatedLanes & 268435455) + ? 2 + : 3; } else workInProgressSuspendedReason = thrownValue === SelectiveHydrationException @@ -8471,24 +8615,6 @@ function handleThrow(root, thrownValue) { ); } } -function shouldAttemptToSuspendUntilDataResolves() { - if ( - 0 !== (workInProgressRootSkippedLanes & 268435455) || - 0 !== (workInProgressRootInterleavedUpdatedLanes & 268435455) - ) - return !1; - if ( - (workInProgressRootRenderLanes & 8388480) === - workInProgressRootRenderLanes - ) - return null === shellBoundary; - var handler = suspenseHandlerStackCursor.current; - return null !== handler && - (workInProgressRootRenderLanes & 125829120) === - workInProgressRootRenderLanes - ? handler === shellBoundary - : !1; -} function pushDispatcher() { var prevDispatcher = ReactCurrentDispatcher.current; ReactCurrentDispatcher.current = ContextOnlyDispatcher; @@ -8536,8 +8662,8 @@ function renderRootSync(root, lanes) { } workLoopSync(); break; - } catch (thrownValue$118) { - handleThrow(root, thrownValue$118); + } catch (thrownValue$123) { + handleThrow(root, thrownValue$123); } while (1); resetContextDependencies(); @@ -8627,8 +8753,8 @@ function renderRootConcurrent(root, lanes) { } workLoopConcurrent(); break; - } catch (thrownValue$120) { - handleThrow(root, thrownValue$120); + } catch (thrownValue$125) { + handleThrow(root, thrownValue$125); } while (1); resetContextDependencies(); @@ -8697,9 +8823,7 @@ function replaySuspendedUnitOfWork(unitOfWork) { ); break; default: - resetContextDependencies(), - resetHooksOnUnwind(), - unwindInterruptedWork(current, unitOfWork), + unwindInterruptedWork(current, unitOfWork), (unitOfWork = workInProgress = resetWorkInProgress(unitOfWork, renderLanes)), (current = beginWork(current, unitOfWork, renderLanes)); @@ -8714,6 +8838,8 @@ function replaySuspendedUnitOfWork(unitOfWork) { function unwindSuspendedUnitOfWork(unitOfWork, thrownValue) { resetContextDependencies(); resetHooksOnUnwind(); + thenableState$1 = null; + thenableIndexCounter$1 = 0; var returnFiber = unitOfWork.return; if (null === returnFiber || null === workInProgressRoot) (workInProgressRootExitStatus = 1), @@ -8776,27 +8902,35 @@ function unwindSuspendedUnitOfWork(unitOfWork, thrownValue) { else (suspenseBoundary.flags |= 65536), (suspenseBoundary.lanes = thrownValue); - var wakeables = suspenseBoundary.updateQueue; - null === wakeables - ? (suspenseBoundary.updateQueue = new Set([wakeable])) - : wakeables.add(wakeable); + if (wakeable === noopSuspenseyCommitThenable) + suspenseBoundary.flags |= 16384; + else { + var retryQueue = suspenseBoundary.updateQueue; + null === retryQueue + ? (suspenseBoundary.updateQueue = new Set([wakeable])) + : retryQueue.add(wakeable); + } break; case 22: if (suspenseBoundary.mode & 1) { suspenseBoundary.flags |= 65536; - var offscreenQueue = suspenseBoundary.updateQueue; - if (null === offscreenQueue) { - var newOffscreenQueue = { - transitions: null, - markerInstances: null, - wakeables: new Set([wakeable]) - }; - suspenseBoundary.updateQueue = newOffscreenQueue; - } else { - var wakeables$36 = offscreenQueue.wakeables; - null === wakeables$36 - ? (offscreenQueue.wakeables = new Set([wakeable])) - : wakeables$36.add(wakeable); + if (wakeable === noopSuspenseyCommitThenable) + suspenseBoundary.flags |= 16384; + else { + var offscreenQueue = suspenseBoundary.updateQueue; + if (null === offscreenQueue) { + var newOffscreenQueue = { + transitions: null, + markerInstances: null, + retryQueue: new Set([wakeable]) + }; + suspenseBoundary.updateQueue = newOffscreenQueue; + } else { + var retryQueue$39 = offscreenQueue.retryQueue; + null === retryQueue$39 + ? (offscreenQueue.retryQueue = new Set([wakeable])) + : retryQueue$39.add(wakeable); + } } break; } @@ -8889,7 +9023,7 @@ function completeUnitOfWork(unitOfWork) { } else { current = unwindWork(current, completedWork); if (null !== current) { - current.flags &= 16383; + current.flags &= 32767; workInProgress = current; return; } @@ -8961,6 +9095,7 @@ function commitRootImpl( ); root.callbackNode = null; root.callbackPriority = 0; + root.cancelPendingCommit = null; var remainingLanes = transitions.lanes | transitions.childLanes; remainingLanes |= concurrentlyUpdatedLanes; markRootFinished(root, remainingLanes); @@ -9079,11 +9214,11 @@ function flushPassiveEffects() { _finishedWork$memoize = finishedWork.memoizedProps, id = _finishedWork$memoize.id, onPostCommit = _finishedWork$memoize.onPostCommit, - commitTime$88 = commitTime, + commitTime$93 = commitTime, phase = null === finishedWork.alternate ? "mount" : "update"; currentUpdateIsNested && (phase = "nested-update"); "function" === typeof onPostCommit && - onPostCommit(id, phase, passiveEffectDuration, commitTime$88); + onPostCommit(id, phase, passiveEffectDuration, commitTime$93); var parentFiber = finishedWork.return; b: for (; null !== parentFiber; ) { switch (parentFiber.tag) { @@ -9225,11 +9360,7 @@ function pingSuspendedRoot(root, wakeable, pingedLanes) { } function retryTimedOutBoundary(boundaryFiber, retryLane) { 0 === retryLane && - (0 === (boundaryFiber.mode & 1) - ? (retryLane = 2) - : ((retryLane = nextRetryLane), - (nextRetryLane <<= 1), - 0 === (nextRetryLane & 125829120) && (nextRetryLane = 8388608))); + (retryLane = 0 === (boundaryFiber.mode & 1) ? 2 : claimNextRetryLane()); var eventTime = requestEventTime(); boundaryFiber = enqueueConcurrentRenderForLane(boundaryFiber, retryLane); null !== boundaryFiber && @@ -9788,7 +9919,7 @@ function createWorkInProgress(current, pendingProps) { (workInProgress.deletions = null), (workInProgress.actualDuration = 0), (workInProgress.actualStartTime = -1)); - workInProgress.flags = current.flags & 14680064; + workInProgress.flags = current.flags & 31457280; workInProgress.childLanes = current.childLanes; workInProgress.lanes = current.lanes; workInProgress.child = current.child; @@ -9809,7 +9940,7 @@ function createWorkInProgress(current, pendingProps) { return workInProgress; } function resetWorkInProgress(workInProgress, renderLanes) { - workInProgress.flags &= 14680066; + workInProgress.flags &= 31457282; var current = workInProgress.alternate; null === current ? ((workInProgress.childLanes = 0), @@ -10004,7 +10135,11 @@ function FiberRootNode( this.pendingChildren = null; this.timeoutHandle = -1; - this.callbackNode = this.pendingContext = this.context = null; + this.callbackNode = + this.pendingContext = + this.context = + this.cancelPendingCommit = + null; this.callbackPriority = 0; this.eventTimes = createLaneMap(0); this.expirationTimes = createLaneMap(-1); @@ -10118,23 +10253,35 @@ function updateContainer(element, container, parentComponent, callback) { function emptyFindFiberByHostInstance() { return null; } -var emptyObject = {}, - createHierarchy, - getHostNode, - getHostProps, - lastNonHostInstance; -exports.getInspectorDataForInstance = void 0; -var getOwnerHierarchy, traverseOwnerTreeUp; -createHierarchy = function (fiberHierarchy) { - return fiberHierarchy.map(function (fiber) { +function findNodeHandle(componentOrHandle) { + if (null == componentOrHandle) return null; + if ("number" === typeof componentOrHandle) return componentOrHandle; + if (componentOrHandle._nativeTag) return componentOrHandle._nativeTag; + if ( + null != componentOrHandle.canonical && + null != componentOrHandle.canonical.nativeTag + ) + return componentOrHandle.canonical.nativeTag; + var nativeTag = componentOrHandle.__nativeTag; + if (nativeTag) return nativeTag; + componentOrHandle = findHostInstance(componentOrHandle); + return null == componentOrHandle + ? componentOrHandle + : null != componentOrHandle._nativeTag + ? componentOrHandle._nativeTag + : componentOrHandle.__nativeTag; +} +var emptyObject = {}; +function createHierarchy(fiberHierarchy) { + return fiberHierarchy.map(function (fiber$jscomp$0) { return { - name: getComponentNameFromType(fiber.type), + name: getComponentNameFromType(fiber$jscomp$0.type), getInspectorData: function (findNodeHandle) { return { - props: getHostProps(fiber), - source: fiber._debugSource, + props: getHostProps(fiber$jscomp$0), + source: fiber$jscomp$0._debugSource, measure: function (callback) { - var hostFiber = findCurrentHostFiber(fiber); + var hostFiber = findCurrentHostFiber(fiber$jscomp$0); if ( (hostFiber = null != hostFiber && @@ -10142,82 +10289,43 @@ createHierarchy = function (fiberHierarchy) { hostFiber.stateNode.node) ) nativeFabricUIManager.measure(hostFiber, callback); - else - return ReactNativePrivateInterface.UIManager.measure( - getHostNode(fiber, findNodeHandle), + else { + hostFiber = ReactNativePrivateInterface.UIManager; + var JSCompiler_temp_const = hostFiber.measure, + JSCompiler_inline_result; + a: { + for (var fiber = fiber$jscomp$0; fiber; ) { + null !== fiber.stateNode && + 5 === fiber.tag && + (JSCompiler_inline_result = findNodeHandle( + fiber.stateNode + )); + if (JSCompiler_inline_result) break a; + fiber = fiber.child; + } + JSCompiler_inline_result = null; + } + return JSCompiler_temp_const.call( + hostFiber, + JSCompiler_inline_result, callback ); + } } }; } }; }); -}; -getHostNode = function (fiber, findNodeHandle) { - for (var hostNode; fiber; ) { - null !== fiber.stateNode && - 5 === fiber.tag && - (hostNode = findNodeHandle(fiber.stateNode)); - if (hostNode) return hostNode; - fiber = fiber.child; - } - return null; -}; -getHostProps = function (fiber) { +} +function getHostProps(fiber) { return (fiber = findCurrentHostFiber(fiber)) ? fiber.memoizedProps || emptyObject : emptyObject; -}; -exports.getInspectorDataForInstance = function (closestInstance) { - if (!closestInstance) - return { - hierarchy: [], - props: emptyObject, - selectedIndex: null, - source: null - }; - closestInstance = findCurrentFiberUsingSlowPath(closestInstance); - var fiberHierarchy = getOwnerHierarchy(closestInstance); - closestInstance = lastNonHostInstance(fiberHierarchy); - var hierarchy = createHierarchy(fiberHierarchy), - props = getHostProps(closestInstance), - source = closestInstance._debugSource; - fiberHierarchy = fiberHierarchy.indexOf(closestInstance); - return { - closestInstance: closestInstance, - hierarchy: hierarchy, - props: props, - selectedIndex: fiberHierarchy, - source: source - }; -}; -getOwnerHierarchy = function (instance) { - var hierarchy = []; - traverseOwnerTreeUp(hierarchy, instance); - return hierarchy; -}; -lastNonHostInstance = function (hierarchy) { - for (var i = hierarchy.length - 1; 1 < i; i--) { - var instance = hierarchy[i]; - if (5 !== instance.tag) return instance; - } - return hierarchy[0]; -}; -traverseOwnerTreeUp = function (hierarchy, instance) { +} +function traverseOwnerTreeUp(hierarchy, instance) { instance && (hierarchy.unshift(instance), traverseOwnerTreeUp(hierarchy, instance._debugOwner)); -}; -function findNodeHandle(componentOrHandle) { - if (null == componentOrHandle) return null; - if ("number" === typeof componentOrHandle) return componentOrHandle; - if (componentOrHandle._nativeTag) return componentOrHandle._nativeTag; - if (componentOrHandle.canonical && componentOrHandle.canonical._nativeTag) - return componentOrHandle.canonical._nativeTag; - componentOrHandle = findHostInstance(componentOrHandle); - return null == componentOrHandle - ? componentOrHandle - : componentOrHandle._nativeTag; } function onRecoverableError(error) { console.error(error); @@ -10242,10 +10350,10 @@ batchedUpdatesImpl = function (fn, a) { } }; var roots = new Map(), - devToolsConfig$jscomp$inline_1122 = { + devToolsConfig$jscomp$inline_1166 = { findFiberByHostInstance: getInstanceFromTag, bundleType: 0, - version: "18.3.0-next-ef8bdbecb-20230310", + version: "18.3.0-next-c57b90f50-20230320", rendererPackageName: "react-native-renderer", rendererConfig: { getInspectorDataForViewTag: function () { @@ -10274,10 +10382,10 @@ var roots = new Map(), } catch (err) {} return hook.checkDCE ? !0 : !1; })({ - bundleType: devToolsConfig$jscomp$inline_1122.bundleType, - version: devToolsConfig$jscomp$inline_1122.version, - rendererPackageName: devToolsConfig$jscomp$inline_1122.rendererPackageName, - rendererConfig: devToolsConfig$jscomp$inline_1122.rendererConfig, + bundleType: devToolsConfig$jscomp$inline_1166.bundleType, + version: devToolsConfig$jscomp$inline_1166.version, + rendererPackageName: devToolsConfig$jscomp$inline_1166.rendererPackageName, + rendererConfig: devToolsConfig$jscomp$inline_1166.rendererConfig, overrideHookState: null, overrideHookStateDeletePath: null, overrideHookStateRenamePath: null, @@ -10293,14 +10401,14 @@ var roots = new Map(), return null === fiber ? null : fiber.stateNode; }, findFiberByHostInstance: - devToolsConfig$jscomp$inline_1122.findFiberByHostInstance || + devToolsConfig$jscomp$inline_1166.findFiberByHostInstance || emptyFindFiberByHostInstance, findHostInstancesForRefresh: null, scheduleRefresh: null, scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "18.3.0-next-ef8bdbecb-20230310" + reconcilerVersion: "18.3.0-next-c57b90f50-20230320" }); exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = { computeComponentStackForErrorReporting: function (reactTag) { @@ -10318,13 +10426,16 @@ exports.createPortal = function (children, containerTag) { ); }; exports.dispatchCommand = function (handle, command, args) { - null != handle._nativeTag && - (null != handle._internalInstanceHandle - ? ((handle = handle._internalInstanceHandle.stateNode), - null != handle && - nativeFabricUIManager.dispatchCommand(handle.node, command, args)) + var nativeTag = + null != handle._nativeTag ? handle._nativeTag : handle.__nativeTag; + null != nativeTag && + ((handle = handle.__internalInstanceHandle), + null != handle + ? ((nativeTag = handle && handle.stateNode && handle.stateNode.node), + null != nativeTag && + nativeFabricUIManager.dispatchCommand(nativeTag, command, args)) : ReactNativePrivateInterface.UIManager.dispatchViewManagerCommand( - handle._nativeTag, + nativeTag, command, args )); @@ -10332,13 +10443,46 @@ exports.dispatchCommand = function (handle, command, args) { exports.findHostInstance_DEPRECATED = function (componentOrHandle) { return null == componentOrHandle ? null + : componentOrHandle.canonical && componentOrHandle.canonical.publicInstance + ? componentOrHandle.canonical.publicInstance : componentOrHandle._nativeTag ? componentOrHandle - : componentOrHandle.canonical && componentOrHandle.canonical._nativeTag - ? componentOrHandle.canonical : findHostInstance(componentOrHandle); }; exports.findNodeHandle = findNodeHandle; +exports.getInspectorDataForInstance = function (closestInstance) { + if (!closestInstance) + return { + hierarchy: [], + props: emptyObject, + selectedIndex: null, + source: null + }; + var fiber = findCurrentFiberUsingSlowPath(closestInstance); + closestInstance = []; + traverseOwnerTreeUp(closestInstance, fiber); + a: { + for (fiber = closestInstance.length - 1; 1 < fiber; fiber--) { + var instance = closestInstance[fiber]; + if (5 !== instance.tag) { + fiber = instance; + break a; + } + } + fiber = closestInstance[0]; + } + instance = createHierarchy(closestInstance); + var props = getHostProps(fiber), + source = fiber._debugSource; + closestInstance = closestInstance.indexOf(fiber); + return { + closestInstance: fiber, + hierarchy: instance, + props: props, + selectedIndex: closestInstance, + source: source + }; +}; exports.render = function (element, containerTag, callback) { var root = roots.get(containerTag); if (!root) { @@ -10375,13 +10519,16 @@ exports.render = function (element, containerTag, callback) { return element; }; exports.sendAccessibilityEvent = function (handle, eventType) { - null != handle._nativeTag && - (null != handle._internalInstanceHandle - ? ((handle = handle._internalInstanceHandle.stateNode), - null != handle && - nativeFabricUIManager.sendAccessibilityEvent(handle.node, eventType)) + var nativeTag = + null != handle._nativeTag ? handle._nativeTag : handle.__nativeTag; + null != nativeTag && + ((handle = handle.__internalInstanceHandle), + null != handle + ? ((nativeTag = handle && handle.stateNode && handle.stateNode.node), + null != nativeTag && + nativeFabricUIManager.sendAccessibilityEvent(nativeTag, eventType)) : ReactNativePrivateInterface.legacySendAccessibilityEvent( - handle._nativeTag, + nativeTag, eventType )); }; diff --git a/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/shims/ReactNativeTypes.js b/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/shims/ReactNativeTypes.js index a524d4313866c..ca9a9dfc04d03 100644 --- a/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/shims/ReactNativeTypes.js +++ b/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/shims/ReactNativeTypes.js @@ -212,6 +212,8 @@ export type ReactNativeType = { ... }; +export opaque type Node = mixed; + export type ReactFabricType = { findHostInstance_DEPRECATED( componentOrHandle: ?(ElementRef | number), @@ -235,6 +237,7 @@ export type ReactFabricType = { concurrentRoot: ?boolean, ): ?ElementRef, unmountComponentAtNode(containerTag: number): void, + getNodeFromInternalInstanceHandle(internalInstanceHandle: mixed): ?Node, ... };