From 118cf689142d6754a300d714caf33b4fd64b575d Mon Sep 17 00:00:00 2001 From: Rick Hanlon Date: Mon, 6 Jun 2022 10:58:29 -0700 Subject: [PATCH] React Native sync for revisions bd4784c...d300ceb MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: This sync includes the following changes: - **[dd4950c90](https://github.com/facebook/react/commit/dd4950c90 )**: [Flight] Implement useId hook ([#24172](https://github.com/facebook/react/pull/24172)) //// - **[26a5b3c7f](https://github.com/facebook/react/commit/26a5b3c7f )**: Explicitly set `highWaterMark` to 0 for `ReadableStream` ([#24641](https://github.com/facebook/react/pull/24641)) //// - **[aec575914](https://github.com/facebook/react/commit/aec575914 )**: [Fizz] Send errors down to client ([#24551](https://github.com/facebook/react/pull/24551)) //// - **[a2766387e](https://github.com/facebook/react/commit/a2766387e )**: [Fizz] Improve text separator byte efficiency ([#24630](https://github.com/facebook/react/pull/24630)) //// - **[f7860538a](https://github.com/facebook/react/commit/f7860538a )**: Fix typo in useSyncExternalStore main entry point error ([#24631](https://github.com/facebook/react/pull/24631)) //// - **[1bed20731](https://github.com/facebook/react/commit/1bed20731 )**: Add a module map option to the Webpack Flight Client ([#24629](https://github.com/facebook/react/pull/24629)) //// - **[b2763d3ea](https://github.com/facebook/react/commit/b2763d3ea )**: Move hydration code out of normal Suspense path ([#24532](https://github.com/facebook/react/pull/24532)) //// - **[357a61324](https://github.com/facebook/react/commit/357a61324 )**: [DevTools][Transition Tracing] Added support for Suspense Boundaries ([#23365](https://github.com/facebook/react/pull/23365)) //// - **[2c8a1452b](https://github.com/facebook/react/commit/2c8a1452b )**: Fix ignored setState in Safari when iframe is touched ([#24459](https://github.com/facebook/react/pull/24459)) //// - **[62662633d](https://github.com/facebook/react/commit/62662633d )**: Remove enableFlipOffscreenUnhideOrder ([#24545](https://github.com/facebook/react/pull/24545)) //// - **[34da5aa69](https://github.com/facebook/react/commit/34da5aa69 )**: Only treat updates to lazy as a new mount in legacy mode ([#24530](https://github.com/facebook/react/pull/24530)) //// - **[46a6d77e3](https://github.com/facebook/react/commit/46a6d77e3 )**: Unify JSResourceReference Interfaces ([#24507](https://github.com/facebook/react/pull/24507)) //// - **[6cbf0f7fa](https://github.com/facebook/react/commit/6cbf0f7fa )**: Fork ReactSymbols ([#24484](https://github.com/facebook/react/pull/24484)) //// - **[a10a9a6b5](https://github.com/facebook/react/commit/a10a9a6b5 )**: Add test for hiding children after layout destroy ([#24483](https://github.com/facebook/react/pull/24483)) //// - **[b4eb0ad71](https://github.com/facebook/react/commit/b4eb0ad71 )**: Do not replay erroring beginWork with invokeGuardedCallback when suspended or previously errored ([#24480](https://github.com/facebook/react/pull/24480)) //// - **[99eef9e2d](https://github.com/facebook/react/commit/99eef9e2d )**: Hide children of Offscreen after destroy effects ([#24446](https://github.com/facebook/react/pull/24446)) //// - **[ce1386028](https://github.com/facebook/react/commit/ce1386028 )**: Remove enablePersistentOffscreenHostContainer flag ([#24460](https://github.com/facebook/react/pull/24460)) //// - **[72b7462fe](https://github.com/facebook/react/commit/72b7462fe )**: Bump local package.json versions for 18.1 release ([#24447](https://github.com/facebook/react/pull/24447)) //// - **[22edb9f77](https://github.com/facebook/react/commit/22edb9f77 )**: React `version` field should match package.json ([#24445](https://github.com/facebook/react/pull/24445)) //// - **[6bf3deef5](https://github.com/facebook/react/commit/6bf3deef5 )**: Upgrade react-shallow-renderer to support react 18 ([#24442](https://github.com/facebook/react/pull/24442)) //// Changelog: [General][Changed] - React Native sync for revisions bd4784c...d300ceb jest_e2e[run_all_tests] Reviewed By: cortinico, kacieb Differential Revision: D36874368 fbshipit-source-id: c0ee015f4ef2fa56e57f7a1f6bc37dd05c949877 --- BUCK | 1 - Libraries/Renderer/REVISION | 2 +- .../implementations/ReactFabric-dev.js | 8058 +++++++++-------- .../implementations/ReactFabric-prod.js | 2666 +++--- .../implementations/ReactFabric-profiling.js | 3050 ++++--- .../ReactNativeRenderer-dev.js | 8027 ++++++++-------- .../ReactNativeRenderer-prod.js | 2832 +++--- .../ReactNativeRenderer-profiling.js | 3091 ++++--- package.json | 10 +- packages/rn-tester/package.json | 2 +- repo-config/package.json | 4 +- template/package.json | 4 +- yarn.lock | 56 +- 13 files changed, 15413 insertions(+), 12390 deletions(-) diff --git a/BUCK b/BUCK index a42859addf9f14..e43a573088bb6a 100644 --- a/BUCK +++ b/BUCK @@ -763,7 +763,6 @@ rn_library( "//xplat/js:node_modules__use_19sync_19external_19store", "//xplat/js:node_modules__whatwg_19fetch", "//xplat/js/RKJSModules/Libraries/Polyfills:Polyfills", - "//xplat/js/RKJSModules/Libraries/React:React", "//xplat/js/RKJSModules/vendor/react:react", "//xplat/js/RKJSModules/vendor/react-test-renderer:react-test-renderer", "//xplat/js/RKJSModules/vendor/scheduler:scheduler", diff --git a/Libraries/Renderer/REVISION b/Libraries/Renderer/REVISION index a9f8463f05680c..c9a2a7c8e0a927 100644 --- a/Libraries/Renderer/REVISION +++ b/Libraries/Renderer/REVISION @@ -1 +1 @@ -bd4784c8f8c6b17cf45c712db8ed8ed19a622b26 \ No newline at end of file +d300cebde2a63e742ccb8b6aa7b0f61db1ae29b4 \ No newline at end of file diff --git a/Libraries/Renderer/implementations/ReactFabric-dev.js b/Libraries/Renderer/implementations/ReactFabric-dev.js index af858df2513b9e..89b2d1153112db 100644 --- a/Libraries/Renderer/implementations/ReactFabric-dev.js +++ b/Libraries/Renderer/implementations/ReactFabric-dev.js @@ -8,7 +8,7 @@ * @nolint * @providesModule ReactFabric-dev * @preventMunge - * @generated SignedSource<<1905bf58c5e02827f73cc582ec7db91b>> + * @generated SignedSource<> */ 'use strict'; @@ -2776,7 +2776,6 @@ function set(key, value) { var enableSchedulingProfiler = false; var enableProfilerTimer = true; var enableProfilerCommitHooks = true; -var enableLazyElements = false; var warnAboutStringRefs = false; var enableSuspenseAvoidThisFallback = false; var enableNewReconciler = false; @@ -3039,9 +3038,6 @@ var Placement = var Update = /* */ 4; -var PlacementAndUpdate = - /* */ - Placement | Update; var ChildDeletion = /* */ 16; @@ -3069,9 +3065,6 @@ var Passive = var Hydrating = /* */ 4096; -var HydratingAndUpdate = - /* */ - Hydrating | Update; var Visibility = /* */ 8192; @@ -4302,13 +4295,13 @@ var InputContinuousHydrationLane = /* */ 2; var InputContinuousLane = - /* */ + /* */ 4; var DefaultHydrationLane = /* */ 8; var DefaultLane = - /* */ + /* */ 16; var TransitionHydrationLane = /* */ @@ -4387,13 +4380,13 @@ var SelectiveHydrationLane = /* */ 134217728; var NonIdleLanes = - /* */ + /* */ 268435455; var IdleHydrationLane = /* */ 268435456; var IdleLane = - /* */ + /* */ 536870912; var OffscreenLane = /* */ @@ -4726,6 +4719,10 @@ function includesNonIdleWork(lanes) { function includesOnlyRetries(lanes) { return (lanes & RetryLanes) === lanes; } +function includesOnlyNonUrgentLanes(lanes) { + var UrgentLanes = SyncLane | InputContinuousLane | DefaultLane; + return (lanes & UrgentLanes) === NoLanes; +} function includesOnlyTransitions(lanes) { return (lanes & TransitionLanes) === lanes; } @@ -4743,7 +4740,7 @@ function includesExpiredLane(root, lanes) { return (lanes & root.expiredLanes) !== NoLanes; } function isTransitionLane(lane) { - return (lane & TransitionLanes) !== 0; + return (lane & TransitionLanes) !== NoLanes; } function claimNextTransitionLane() { // Cycle through the lanes, assigning each new transition to the next lane. @@ -4752,7 +4749,7 @@ function claimNextTransitionLane() { var lane = nextTransitionLane; nextTransitionLane <<= 1; - if ((nextTransitionLane & TransitionLanes) === 0) { + if ((nextTransitionLane & TransitionLanes) === NoLanes) { nextTransitionLane = TransitionLane1; } @@ -4762,7 +4759,7 @@ function claimNextRetryLane() { var lane = nextRetryLane; nextRetryLane <<= 1; - if ((nextRetryLane & RetryLanes) === 0) { + if ((nextRetryLane & RetryLanes) === NoLanes) { nextRetryLane = RetryLane1; } @@ -4864,8 +4861,8 @@ function markRootFinished(root, remainingLanes) { var noLongerPendingLanes = root.pendingLanes & ~remainingLanes; root.pendingLanes = remainingLanes; // Let's try everything again - root.suspendedLanes = 0; - root.pingedLanes = 0; + root.suspendedLanes = NoLanes; + root.pingedLanes = NoLanes; root.expiredLanes &= remainingLanes; root.mutableReadLanes &= remainingLanes; root.entangledLanes &= remainingLanes; @@ -4915,6 +4912,63 @@ function markRootEntangled(root, entangledLanes) { lanes &= ~lane; } } +function getBumpedLaneForHydration(root, renderLanes) { + var renderLane = getHighestPriorityLane(renderLanes); + var lane; + + switch (renderLane) { + case InputContinuousLane: + lane = InputContinuousHydrationLane; + break; + + case DefaultLane: + lane = DefaultHydrationLane; + break; + + case TransitionLane1: + case TransitionLane2: + case TransitionLane3: + case TransitionLane4: + case TransitionLane5: + case TransitionLane6: + case TransitionLane7: + case TransitionLane8: + case TransitionLane9: + case TransitionLane10: + case TransitionLane11: + case TransitionLane12: + case TransitionLane13: + case TransitionLane14: + case TransitionLane15: + case TransitionLane16: + case RetryLane1: + case RetryLane2: + case RetryLane3: + case RetryLane4: + case RetryLane5: + lane = TransitionHydrationLane; + break; + + case IdleLane: + lane = IdleHydrationLane; + break; + + default: + // Everything else is already either a hydration lane, or shouldn't + // be retried at a hydration lane. + lane = NoLane; + break; + } // Check if the lane we chose is suspended. If so, that indicates that we + // already attempted and failed to hydrate at that level. Also check if we're + // already rendering that lane, which is rare but could happen. + + if ((lane & (root.suspendedLanes | renderLanes)) !== NoLane) { + // Give up trying to hydrate and fall back to client render. + return NoLane; + } + + return lane; +} function addFiberToLanesMap(root, fiber, lanes) { if (!isDevToolsPresent) { return; @@ -4957,6 +5011,11 @@ function movePendingFibersToMemoized(root, lanes) { lanes &= ~lane; } } +function getTransitionsForLanes(root, lanes) { + { + return null; + } +} var DiscreteEventPriority = SyncLane; var ContinuousEventPriority = InputContinuousLane; @@ -5005,8 +5064,6 @@ function shim() { "Please file an issue." ); } // Mutation (when unsupported) - -var supportsMutation = false; var commitMount = shim; // Renderers that don't support hydration @@ -5020,6 +5077,8 @@ function shim$1() { } // Hydration (when unsupported) var isSuspenseInstancePending = shim$1; var isSuspenseInstanceFallback = shim$1; +var getSuspenseInstanceFallbackErrorDetails = shim$1; +var registerSuspenseInstanceRetry = shim$1; var hydrateTextInstance = shim$1; var errorHydratingContainer = shim$1; @@ -5429,7 +5488,7 @@ function cloneInstance( node: clone, canonical: instance.canonical }; -} // TODO: These two methods should be replaced with `createOffscreenInstance` and +} function cloneHiddenInstance(instance, type, props, internalInstanceHandle) { var viewConfig = instance.canonical.viewConfig; var node = instance.node; @@ -5458,6 +5517,7 @@ function appendChildToContainerChildSet(childSet, child) { function finalizeContainerChildren(container, newChildren) { completeRoot(container, newChildren); } +function replaceContainerChildren(container, newChildren) {} function preparePortalMount(portalInstance) { // noop } @@ -6101,6 +6161,125 @@ function isRootDehydrated(root) { return currentState.isDehydrated; } +// TODO: Use the unified fiber stack module instead of this local one? +// Intentionally not using it yet to derisk the initial implementation, because +// the way we push/pop these values is a bit unusual. If there's a mistake, I'd +// rather the ids be wrong than crash the whole reconciler. +var forkStack = []; +var forkStackIndex = 0; +var treeForkProvider = null; +var treeForkCount = 0; +var idStack = []; +var idStackIndex = 0; +var treeContextProvider = null; +var treeContextId = 1; +var treeContextOverflow = ""; + +function popTreeContext(workInProgress) { + // Restore the previous values. + // This is a bit more complicated than other context-like modules in Fiber + // because the same Fiber may appear on the stack multiple times and for + // different reasons. We have to keep popping until the work-in-progress is + // no longer at the top of the stack. + while (workInProgress === treeForkProvider) { + treeForkProvider = forkStack[--forkStackIndex]; + forkStack[forkStackIndex] = null; + treeForkCount = forkStack[--forkStackIndex]; + forkStack[forkStackIndex] = null; + } + + while (workInProgress === treeContextProvider) { + treeContextProvider = idStack[--idStackIndex]; + idStack[idStackIndex] = null; + treeContextOverflow = idStack[--idStackIndex]; + idStack[idStackIndex] = null; + treeContextId = idStack[--idStackIndex]; + idStack[idStackIndex] = null; + } +} + +var isHydrating = false; // This flag allows for warning supression when we expect there to be mismatches +// due to earlier mismatches or a suspended fiber. + +var didSuspendOrErrorDEV = false; // Hydration errors that were thrown inside this boundary + +var hydrationErrors = null; +function didSuspendOrErrorWhileHydratingDEV() { + { + return didSuspendOrErrorDEV; + } +} + +function reenterHydrationStateFromDehydratedSuspenseInstance( + fiber, + suspenseInstance, + treeContext +) { + { + return false; + } +} + +function prepareToHydrateHostInstance( + fiber, + rootContainerInstance, + hostContext +) { + { + throw new Error( + "Expected prepareToHydrateHostInstance() to never be called. " + + "This error is likely caused by a bug in React. Please file an issue." + ); + } +} + +function prepareToHydrateHostTextInstance(fiber) { + { + throw new Error( + "Expected prepareToHydrateHostTextInstance() to never be called. " + + "This error is likely caused by a bug in React. Please file an issue." + ); + } + var shouldUpdate = hydrateTextInstance(); +} + +function prepareToHydrateHostSuspenseInstance(fiber) { + { + throw new Error( + "Expected prepareToHydrateHostSuspenseInstance() to never be called. " + + "This error is likely caused by a bug in React. Please file an issue." + ); + } +} + +function popHydrationState(fiber) { + { + return false; + } +} + +function upgradeHydrationErrorsToRecoverable() { + if (hydrationErrors !== null) { + // Successfully completed a forced client render. The errors that occurred + // during the hydration attempt are now recovered. We will log them in + // commit phase, once the entire tree has finished. + queueRecoverableErrors(hydrationErrors); + hydrationErrors = null; + } +} + +function getIsHydrating() { + return isHydrating; +} + +function queueHydrationError(error) { + if (hydrationErrors === null) { + hydrationErrors = [error]; + } else { + hydrationErrors.push(error); + } +} + var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig; var NoTransition = null; function requestCurrentTransition() { @@ -6236,11 +6415,17 @@ function resetCurrentFiber() { } function setCurrentFiber(fiber) { { - ReactDebugCurrentFrame$1.getCurrentStack = getCurrentFiberStackInDev; + ReactDebugCurrentFrame$1.getCurrentStack = + fiber === null ? null : getCurrentFiberStackInDev; current = fiber; isRendering = false; } } +function getCurrentFiber() { + { + return current; + } +} function setIsRendering(rendering) { { isRendering = rendering; @@ -6880,6 +7065,34 @@ function propagateContextChange_eager(workInProgress, context, renderLanes) { } else if (fiber.tag === ContextProvider) { // Don't scan deeper if this is a matching provider nextFiber = fiber.type === workInProgress.type ? null : fiber.child; + } else if (fiber.tag === DehydratedFragment) { + // If a dehydrated suspense boundary is in this subtree, we don't know + // if it will have any context consumers in it. The best we can do is + // mark it as having updates. + var parentSuspense = fiber.return; + + if (parentSuspense === null) { + throw new Error( + "We just came from a parent so we must have had a parent. This is a bug in React." + ); + } + + parentSuspense.lanes = mergeLanes(parentSuspense.lanes, renderLanes); + var _alternate = parentSuspense.alternate; + + if (_alternate !== null) { + _alternate.lanes = mergeLanes(_alternate.lanes, renderLanes); + } // This is intentionally passing this fiber as the parent + // because we want to schedule this fiber as having work + // on its children. We'll use the childLanes on + // this fiber to indicate that a context has changed. + + scheduleContextWorkOnParentPath( + parentSuspense, + renderLanes, + workInProgress + ); + nextFiber = fiber.sibling; } else { // Traverse down. nextFiber = fiber.child; @@ -6996,6 +7209,9 @@ function pushInterleavedQueue(queue) { interleavedQueues.push(queue); } } +function hasInterleavedUpdates() { + return interleavedQueues !== null; +} function enqueueInterleavedUpdates() { // Transfer the interleaved updates onto the main queue. Each queue has a // `pending` field and an `interleaved` field. When they are not null, they @@ -8619,78 +8835,6 @@ function updateClassInstance( return shouldUpdate; } -// TODO: Use the unified fiber stack module instead of this local one? -// Intentionally not using it yet to derisk the initial implementation, because -// the way we push/pop these values is a bit unusual. If there's a mistake, I'd -// rather the ids be wrong than crash the whole reconciler. -var forkStack = []; -var forkStackIndex = 0; -var treeForkProvider = null; -var treeForkCount = 0; -var idStack = []; -var idStackIndex = 0; -var treeContextProvider = null; -var treeContextId = 1; -var treeContextOverflow = ""; - -function popTreeContext(workInProgress) { - // Restore the previous values. - // This is a bit more complicated than other context-like modules in Fiber - // because the same Fiber may appear on the stack multiple times and for - // different reasons. We have to keep popping until the work-in-progress is - // no longer at the top of the stack. - while (workInProgress === treeForkProvider) { - treeForkProvider = forkStack[--forkStackIndex]; - forkStack[forkStackIndex] = null; - treeForkCount = forkStack[--forkStackIndex]; - forkStack[forkStackIndex] = null; - } - - while (workInProgress === treeContextProvider) { - treeContextProvider = idStack[--idStackIndex]; - idStack[idStackIndex] = null; - treeContextOverflow = idStack[--idStackIndex]; - idStack[idStackIndex] = null; - treeContextId = idStack[--idStackIndex]; - idStack[idStackIndex] = null; - } -} - -var isHydrating = false; - -function prepareToHydrateHostInstance( - fiber, - rootContainerInstance, - hostContext -) { - { - throw new Error( - "Expected prepareToHydrateHostInstance() to never be called. " + - "This error is likely caused by a bug in React. Please file an issue." - ); - } -} - -function prepareToHydrateHostTextInstance(fiber) { - { - throw new Error( - "Expected prepareToHydrateHostTextInstance() to never be called. " + - "This error is likely caused by a bug in React. Please file an issue." - ); - } - var shouldUpdate = hydrateTextInstance(); -} - -function popHydrationState(fiber) { - { - return false; - } -} - -function getIsHydrating() { - return isHydrating; -} - var didWarnAboutMaps; var didWarnAboutGenerators; var didWarnAboutStringRefs; @@ -8903,6 +9047,12 @@ function warnOnFunctionType(returnFiber) { ); } } + +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. @@ -9044,7 +9194,10 @@ function ChildReconciler(shouldTrackSideEffects) { // 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. - enableLazyElements + (typeof elementType === "object" && + elementType !== null && + elementType.$$typeof === REACT_LAZY_TYPE && + resolveLazy(elementType) === current.type) ) { // Move based on index var existing = useFiber(current, element.props); @@ -9141,6 +9294,12 @@ function ChildReconciler(shouldTrackSideEffects) { _created2.return = returnFiber; return _created2; } + + case REACT_LAZY_TYPE: { + var payload = newChild._payload; + var init = newChild._init; + return createChild(returnFiber, init(payload), lanes); + } } if (isArray(newChild) || getIteratorFn(newChild)) { @@ -9202,6 +9361,12 @@ function ChildReconciler(shouldTrackSideEffects) { return null; } } + + case REACT_LAZY_TYPE: { + var payload = newChild._payload; + var init = newChild._init; + return updateSlot(returnFiber, oldFiber, init(payload), lanes); + } } if (isArray(newChild) || getIteratorFn(newChild)) { @@ -9260,6 +9425,17 @@ function ChildReconciler(shouldTrackSideEffects) { return updatePortal(returnFiber, _matchedFiber2, newChild, lanes); } + + case REACT_LAZY_TYPE: + var payload = newChild._payload; + var init = newChild._init; + return updateFromMap( + existingChildren, + returnFiber, + newIdx, + init(payload), + lanes + ); } if (isArray(newChild) || getIteratorFn(newChild)) { @@ -9326,6 +9502,12 @@ function ChildReconciler(shouldTrackSideEffects) { ); break; + + case REACT_LAZY_TYPE: + var payload = child._payload; + var init = child._init; + warnOnInvalidKey(init(payload), knownKeys, returnFiber); + break; } } @@ -9767,7 +9949,10 @@ function ChildReconciler(shouldTrackSideEffects) { // 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. - enableLazyElements + (typeof elementType === "object" && + elementType !== null && + elementType.$$typeof === REACT_LAZY_TYPE && + resolveLazy(elementType) === child.type) ) { deleteRemainingChildren(returnFiber, child.sibling); @@ -9896,6 +10081,17 @@ function ChildReconciler(shouldTrackSideEffects) { 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)) { @@ -11415,66 +11611,72 @@ function updateMemo(nextCreate, deps) { } function mountDeferredValue(value) { - var _mountState = mountState(value), - prevValue = _mountState[0], - setValue = _mountState[1]; - - mountEffect( - function() { - var prevTransition = ReactCurrentBatchConfig$1.transition; - ReactCurrentBatchConfig$1.transition = {}; - - try { - setValue(value); - } finally { - ReactCurrentBatchConfig$1.transition = prevTransition; - } - }, - [value] - ); - return prevValue; -} + var hook = mountWorkInProgressHook(); + hook.memoizedState = value; + return value; +} function updateDeferredValue(value) { - var _updateState = updateState(), - prevValue = _updateState[0], - setValue = _updateState[1]; + var hook = updateWorkInProgressHook(); + var resolvedCurrentHook = currentHook; + var prevValue = resolvedCurrentHook.memoizedState; + return updateDeferredValueImpl(hook, prevValue, value); +} - updateEffect( - function() { - var prevTransition = ReactCurrentBatchConfig$1.transition; - ReactCurrentBatchConfig$1.transition = {}; +function rerenderDeferredValue(value) { + var hook = updateWorkInProgressHook(); - try { - setValue(value); - } finally { - ReactCurrentBatchConfig$1.transition = prevTransition; - } - }, - [value] - ); - return prevValue; + 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 rerenderDeferredValue(value) { - var _rerenderState = rerenderState(), - prevValue = _rerenderState[0], - setValue = _rerenderState[1]; +function updateDeferredValueImpl(hook, prevValue, value) { + var shouldDeferValue = !includesOnlyNonUrgentLanes(renderLanes); + + if (shouldDeferValue) { + // This is an urgent update. If the value has changed, keep using the + // previous value and spawn a deferred render to update it later. + if (!objectIs(value, prevValue)) { + // Schedule a deferred render + var deferredLane = claimNextTransitionLane(); + currentlyRenderingFiber$1.lanes = mergeLanes( + currentlyRenderingFiber$1.lanes, + deferredLane + ); + markSkippedUpdateLanes(deferredLane); // Set this to true to indicate that the rendered value is inconsistent + // from the latest value. The name "baseState" doesn't really match how we + // use it because we're reusing a state hook field instead of creating a + // new one. - updateEffect( - function() { - var prevTransition = ReactCurrentBatchConfig$1.transition; - ReactCurrentBatchConfig$1.transition = {}; + hook.baseState = true; + } // Reuse the previous value - try { - setValue(value); - } finally { - ReactCurrentBatchConfig$1.transition = prevTransition; - } - }, - [value] - ); - return prevValue; + 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) { @@ -11517,9 +11719,9 @@ function startTransition(setPending, callback, options) { } function mountTransition() { - var _mountState2 = mountState(false), - isPending = _mountState2[0], - setPending = _mountState2[1]; // The `start` method never changes. + var _mountState = mountState(false), + isPending = _mountState[0], + setPending = _mountState[1]; // The `start` method never changes. var start = startTransition.bind(null, setPending); var hook = mountWorkInProgressHook(); @@ -11528,8 +11730,8 @@ function mountTransition() { } function updateTransition() { - var _updateState2 = updateState(), - isPending = _updateState2[0]; + var _updateState = updateState(), + isPending = _updateState[0]; var hook = updateWorkInProgressHook(); var start = hook.memoizedState; @@ -11537,8 +11739,8 @@ function updateTransition() { } function rerenderTransition() { - var _rerenderState2 = rerenderState(), - isPending = _rerenderState2[0]; + var _rerenderState = rerenderState(), + isPending = _rerenderState[0]; var hook = updateWorkInProgressHook(); var start = hook.memoizedState; @@ -13348,3777 +13550,4156 @@ function getSuspendedCache() { } // This function is called when a Suspense boundary suspends. It returns the } -function markUpdate(workInProgress) { - // Tag the fiber with an update effect. This turns a Placement into - // a PlacementAndUpdate. - workInProgress.flags |= Update; +var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner; +var didReceiveUpdate = false; +var didWarnAboutBadClass; +var didWarnAboutModulePatternComponent; +var didWarnAboutContextTypeOnFunctionComponent; +var didWarnAboutGetDerivedStateOnFunctionComponent; +var didWarnAboutFunctionRefs; +var didWarnAboutReassigningProps; +var didWarnAboutRevealOrder; +var didWarnAboutTailOptions; + +{ + didWarnAboutBadClass = {}; + didWarnAboutModulePatternComponent = {}; + didWarnAboutContextTypeOnFunctionComponent = {}; + didWarnAboutGetDerivedStateOnFunctionComponent = {}; + didWarnAboutFunctionRefs = {}; + didWarnAboutReassigningProps = false; + didWarnAboutRevealOrder = {}; + didWarnAboutTailOptions = {}; } -function markRef(workInProgress) { - workInProgress.flags |= Ref; +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 hadNoMutationsEffects(current, completedWork) { - var didBailout = current !== null && current.child === completedWork.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. - if (didBailout) { - return true; + workInProgress.child = reconcileChildFibers( + workInProgress, + null, + nextChildren, + renderLanes + ); +} + +function updateForwardRef( + current, + workInProgress, + Component, + nextProps, + renderLanes +) { + // TODO: current can be non-null here even if the component + // hasn't yet mounted. This happens after the first render suspends. + // We'll need to figure out if this is fine or can cause issues. + { + if (workInProgress.type !== workInProgress.elementType) { + // Lazy component props can't be validated in createElement + // because they're only guaranteed to be resolved here. + var innerPropTypes = Component.propTypes; + + if (innerPropTypes) { + checkPropTypes( + innerPropTypes, + nextProps, // Resolved props + "prop", + getComponentNameFromType(Component) + ); + } + } } - if ((completedWork.flags & ChildDeletion) !== NoFlags) { - return false; - } // TODO: If we move the `hadNoMutationsEffects` call after `bubbleProperties` - // then we only have to check the `completedWork.subtreeFlags`. + var render = Component.render; + var ref = workInProgress.ref; // The rest is a fork of updateFunctionComponent - var child = completedWork.child; + var nextChildren; + prepareToReadContext(workInProgress, renderLanes); - while (child !== null) { - if ( - (child.flags & MutationMask) !== NoFlags || - (child.subtreeFlags & MutationMask) !== NoFlags - ) { - return false; - } + { + ReactCurrentOwner$1.current = workInProgress; + setIsRendering(true); + nextChildren = renderWithHooks( + current, + workInProgress, + render, + nextProps, + ref, + renderLanes + ); - child = child.sibling; + setIsRendering(false); } - return true; + if (current !== null && !didReceiveUpdate) { + bailoutHooks(current, workInProgress, renderLanes); + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); + } + + workInProgress.flags |= PerformedWork; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; } -var appendAllChildren; -var updateHostContainer; -var updateHostComponent; -var updateHostText; +function updateMemoComponent( + current, + workInProgress, + Component, + nextProps, + renderLanes +) { + if (current === null) { + var type = Component.type; -{ - // Persistent host tree mode - appendAllChildren = function( - parent, - workInProgress, - needsVisibilityToggle, - isHidden - ) { - // We only have the top Fiber that was created but we need recurse down its - // children to find all the terminal nodes. - var node = workInProgress.child; + if ( + isSimpleFunctionComponent(type) && + Component.compare === null && // SimpleMemoComponent codepath doesn't resolve outer props either. + Component.defaultProps === undefined + ) { + var resolvedType = type; - while (node !== null) { - // eslint-disable-next-line no-labels - if (node.tag === HostComponent) { - var instance = node.stateNode; + { + 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. - if (needsVisibilityToggle && isHidden) { - // This child is inside a timed out tree. Hide it. - var props = node.memoizedProps; - var type = node.type; - instance = cloneHiddenInstance(instance); - } + workInProgress.tag = SimpleMemoComponent; + workInProgress.type = resolvedType; - appendInitialChild(parent, instance); - } else if (node.tag === HostText) { - var _instance = node.stateNode; + { + validateFunctionComponentInDev(workInProgress, type); + } - if (needsVisibilityToggle && isHidden) { - // This child is inside a timed out tree. Hide it. - var text = node.memoizedProps; - _instance = cloneHiddenTextInstance(); - } + return updateSimpleMemoComponent( + current, + workInProgress, + resolvedType, + nextProps, + 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; - - if (child !== null) { - child.return = node; - } - - { - appendAllChildren(parent, node, true, true); - } - } else if (node.child !== null) { - node.child.return = node; - node = node.child; - continue; - } // $FlowFixMe This is correct but Flow is confused by the labeled break. - - node = node; + { + var innerPropTypes = type.propTypes; - if (node === workInProgress) { - return; + 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) + ); } + } - while (node.sibling === null) { - if (node.return === null || node.return === workInProgress) { - return; - } + var child = createFiberFromTypeAndProps( + Component.type, + null, + nextProps, + workInProgress, + workInProgress.mode, + renderLanes + ); + child.ref = workInProgress.ref; + child.return = workInProgress; + workInProgress.child = child; + return child; + } - node = node.return; - } + { + var _type = Component.type; + var _innerPropTypes = _type.propTypes; - node.sibling.return = node.return; - node = node.sibling; + 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) + ); } - }; // An unfortunate fork of appendAllChildren because we have two different parent types. + } - var appendAllChildrenToContainer = function( - containerChildSet, - workInProgress, - needsVisibilityToggle, - isHidden - ) { - // We only have the top Fiber that was created but we need recurse down its - // children to find all the terminal nodes. - var node = workInProgress.child; + var currentChild = current.child; // This is always exactly one child - while (node !== null) { - // eslint-disable-next-line no-labels - if (node.tag === HostComponent) { - var instance = node.stateNode; + var hasScheduledUpdateOrContext = checkScheduledUpdateOrContext( + current, + renderLanes + ); - if (needsVisibilityToggle && isHidden) { - // This child is inside a timed out tree. Hide it. - var props = node.memoizedProps; - var type = node.type; - instance = cloneHiddenInstance(instance); - } + 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 - appendChildToContainerChildSet(containerChildSet, instance); - } else if (node.tag === HostText) { - var _instance2 = node.stateNode; + var compare = Component.compare; + compare = compare !== null ? compare : shallowEqual; - if (needsVisibilityToggle && isHidden) { - // This child is inside a timed out tree. Hide it. - var text = node.memoizedProps; - _instance2 = cloneHiddenTextInstance(); - } + if (compare(prevProps, nextProps) && current.ref === workInProgress.ref) { + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); + } + } // React DevTools reads this flag. - 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; + workInProgress.flags |= PerformedWork; + var newChild = createWorkInProgress(currentChild, nextProps); + newChild.ref = workInProgress.ref; + newChild.return = workInProgress; + workInProgress.child = newChild; + return newChild; +} - if (child !== null) { - child.return = node; - } +function updateSimpleMemoComponent( + current, + workInProgress, + Component, + nextProps, + renderLanes +) { + // TODO: current can be non-null here even if the component + // hasn't yet mounted. This happens when the inner render suspends. + // We'll need to figure out if this is fine or can cause issues. + { + if (workInProgress.type !== workInProgress.elementType) { + // Lazy component props can't be validated in createElement + // because they're only guaranteed to be resolved here. + var outerMemoType = workInProgress.elementType; - { - appendAllChildrenToContainer(containerChildSet, node, true, true); - } - } else if (node.child !== null) { - node.child.return = node; - node = node.child; - continue; - } // $FlowFixMe This is correct but Flow is confused by the labeled break. + if (outerMemoType.$$typeof === REACT_LAZY_TYPE) { + // We warn when you define propTypes on lazy() + // so let's just skip over it to find memo() outer wrapper. + // Inner props for memo are validated later. + var lazyComponent = outerMemoType; + var payload = lazyComponent._payload; + var init = lazyComponent._init; - node = node; + try { + outerMemoType = init(payload); + } catch (x) { + outerMemoType = null; + } // Inner propTypes will be validated in the function component path. - if (node === workInProgress) { - return; - } + var outerPropTypes = outerMemoType && outerMemoType.propTypes; - while (node.sibling === null) { - if (node.return === null || node.return === workInProgress) { - return; + if (outerPropTypes) { + checkPropTypes( + outerPropTypes, + nextProps, // Resolved (SimpleMemoComponent has no defaultProps) + "prop", + getComponentNameFromType(outerMemoType) + ); } - - node = node.return; } - - node.sibling.return = node.return; - node = node.sibling; } - }; + } - updateHostContainer = function(current, workInProgress) { - var portalOrRoot = workInProgress.stateNode; - var childrenUnchanged = hadNoMutationsEffects(current, workInProgress); + if (current !== null) { + var prevProps = current.memoizedProps; - 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 ( + 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. - appendAllChildrenToContainer(newChildSet, workInProgress, false, false); - portalOrRoot.pendingChildren = newChildSet; // Schedule an update on the container to swap out the container. + workInProgress.pendingProps = nextProps = prevProps; - markUpdate(workInProgress); - finalizeContainerChildren(container, newChildSet); + if (!checkScheduledUpdateOrContext(current, renderLanes)) { + // The pending lanes were cleared at the beginning of beginWork. We're + // about to bail out, but there might be other lanes that weren't + // included in the current render. Usually, the priority level of the + // remaining updates is accumulated during the evaluation of the + // component (i.e. when processing the update queue). But since since + // we're bailing out early *without* evaluating the component, we need + // to account for it here, too. Reset to the value of the current fiber. + // NOTE: This only applies to SimpleMemoComponent, not MemoComponent, + // because a MemoComponent fiber does not have hooks or an update queue; + // rather, it wraps around an inner component, which may or may not + // contains hooks. + // TODO: Move the reset at in beginWork out of the common path so that + // this is no longer necessary. + workInProgress.lanes = current.lanes; + return bailoutOnAlreadyFinishedWork( + current, + workInProgress, + renderLanes + ); + } else if ((current.flags & ForceUpdateForLegacySuspense) !== NoFlags) { + // This is a special case that only exists for legacy mode. + // See https://github.com/facebook/react/pull/19216. + didReceiveUpdate = true; + } } - }; + } - updateHostComponent = function( + return updateFunctionComponent( current, workInProgress, - type, - newProps, - rootContainerInstance - ) { - var currentInstance = current.stateNode; - var oldProps = current.memoizedProps; // If there are no effects associated with this node, then none of our children had any updates. - // This guarantees that we can reuse all of them. - - var childrenUnchanged = hadNoMutationsEffects(current, workInProgress); - - if (childrenUnchanged && oldProps === newProps) { - // No changes, just reuse the existing instance. - // Note that this might release a previous clone. - workInProgress.stateNode = currentInstance; - return; - } + Component, + nextProps, + renderLanes + ); +} - var recyclableInstance = workInProgress.stateNode; - var currentHostContext = getHostContext(); - var updatePayload = null; +function updateOffscreenComponent(current, workInProgress, renderLanes) { + var nextProps = workInProgress.pendingProps; + var nextChildren = nextProps.children; + var prevState = current !== null ? current.memoizedState : null; - if (oldProps !== newProps) { - updatePayload = prepareUpdate( - recyclableInstance, - type, - oldProps, - newProps - ); - } + if (nextProps.mode === "hidden" || enableLegacyHidden) { + // Rendering a hidden tree. + if ((workInProgress.mode & ConcurrentMode) === NoMode) { + // In legacy sync mode, don't defer the subtree. Render it now. + // TODO: Consider how Offscreen should work with transitions in the future + var nextState = { + baseLanes: NoLanes, + cachePool: null, + transitions: null + }; + workInProgress.memoizedState = nextState; - if (childrenUnchanged && updatePayload === null) { - // No changes, just reuse the existing instance. - // Note that this might release a previous clone. - workInProgress.stateNode = currentInstance; - return; - } + pushRenderLanes(workInProgress, renderLanes); + } else if (!includesSomeLane(renderLanes, OffscreenLane)) { + var spawnedCachePool = null; // We're hidden, and we're not rendering at Offscreen. We will bail out + // and resume this tree later. - var newInstance = cloneInstance( - currentInstance, - updatePayload, - type, - oldProps, - newProps, - workInProgress, - childrenUnchanged - ); + var nextBaseLanes; - workInProgress.stateNode = newInstance; + if (prevState !== null) { + var prevBaseLanes = prevState.baseLanes; + nextBaseLanes = mergeLanes(prevBaseLanes, renderLanes); + } else { + nextBaseLanes = renderLanes; + } // Schedule this fiber to re-render at offscreen priority. Then bailout. - 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); - } - }; + workInProgress.lanes = workInProgress.childLanes = laneToLanes( + OffscreenLane + ); + var _nextState = { + baseLanes: nextBaseLanes, + cachePool: spawnedCachePool, + transitions: null + }; + workInProgress.memoizedState = _nextState; + workInProgress.updateQueue = null; + // to avoid a push/pop misalignment. - updateHostText = function(current, workInProgress, oldText, newText) { - if (oldText !== newText) { - // If the text content differs, we'll create a new text instance for it. - var rootContainerInstance = getRootHostContainer(); - var currentHostContext = getHostContext(); - workInProgress.stateNode = createTextInstance( - newText, - rootContainerInstance, - currentHostContext, - workInProgress - ); // We'll have to mark it as having an effect, even though we won't use the effect for anything. - // This lets the parents know that at least one of their children has changed. + pushRenderLanes(workInProgress, nextBaseLanes); - markUpdate(workInProgress); + return null; } else { - workInProgress.stateNode = current.stateNode; - } - }; -} - -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; + // This is the second render. The surrounding visible content has already + // committed. Now we resume rendering the hidden tree. + // Rendering at offscreen, so we can clear the base lanes. + var _nextState2 = { + baseLanes: NoLanes, + cachePool: null, + transitions: null + }; + workInProgress.memoizedState = _nextState2; // Push the lanes that were skipped when we bailed out. - while (tailNode !== null) { - if (tailNode.alternate !== null) { - lastTailNode = tailNode; - } + var subtreeRenderLanes = + prevState !== null ? prevState.baseLanes : renderLanes; - tailNode = tailNode.sibling; - } // Next we're simply going to delete all insertions after the - // last rendered item. + pushRenderLanes(workInProgress, subtreeRenderLanes); + } + } else { + // Rendering a visible tree. + var _subtreeRenderLanes; - if (lastTailNode === null) { - // All remaining items in the tail are insertions. - renderState.tail = null; - } else { - // Detach the insertion after the last node that was already - // inserted. - lastTailNode.sibling = null; - } + if (prevState !== null) { + // We're going from hidden -> visible. + _subtreeRenderLanes = mergeLanes(prevState.baseLanes, renderLanes); - break; + workInProgress.memoizedState = null; + } else { + // We weren't previously hidden, and we still aren't, so there's nothing + // special to do. Need to push to the stack regardless, though, to avoid + // a push/pop misalignment. + _subtreeRenderLanes = renderLanes; } - 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; + pushRenderLanes(workInProgress, _subtreeRenderLanes); + } - while (_tailNode !== null) { - if (_tailNode.alternate !== null) { - _lastTailNode = _tailNode; - } + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; +} // Note: These happen to have identical begin phases, for now. We shouldn't hold - _tailNode = _tailNode.sibling; - } // Next we're simply going to delete all insertions after the - // last rendered item. +function updateFragment(current, workInProgress, renderLanes) { + var nextChildren = workInProgress.pendingProps; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; +} - if (_lastTailNode === null) { - // All remaining items in the tail are insertions. - if (!hasRenderedATailFallback && renderState.tail !== null) { - // We suspended during the head. We want to show at least one - // row at the tail. So we'll keep on and cut off the rest. - renderState.tail.sibling = null; - } else { - renderState.tail = null; - } - } else { - // Detach the insertion after the last node that was already - // inserted. - _lastTailNode.sibling = null; - } +function updateMode(current, workInProgress, renderLanes) { + var nextChildren = workInProgress.pendingProps.children; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; +} - break; +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 bubbleProperties(completedWork) { - var didBailout = - completedWork.alternate !== null && - completedWork.alternate.child === completedWork.child; - var newChildLanes = NoLanes; - var subtreeFlags = NoFlags; +function markRef(current, workInProgress) { + var ref = workInProgress.ref; - 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 ( + (current === null && ref !== null) || + (current !== null && current.ref !== ref) + ) { + // Schedule a Ref effect + workInProgress.flags |= Ref; + } +} - 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. +function updateFunctionComponent( + current, + workInProgress, + Component, + nextProps, + renderLanes +) { + { + if (workInProgress.type !== workInProgress.elementType) { + // Lazy component props can't be validated in createElement + // because they're only guaranteed to be resolved here. + var innerPropTypes = Component.propTypes; - actualDuration += child.actualDuration; - treeBaseDuration += child.treeBaseDuration; - child = child.sibling; + if (innerPropTypes) { + checkPropTypes( + innerPropTypes, + nextProps, // Resolved props + "prop", + getComponentNameFromType(Component) + ); } + } + } - completedWork.actualDuration = actualDuration; - completedWork.treeBaseDuration = treeBaseDuration; - } else { - var _child = completedWork.child; + var context; - 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 unmaskedContext = getUnmaskedContext(workInProgress, Component, true); + context = getMaskedContext(workInProgress, unmaskedContext); + } - _child.return = completedWork; - _child = _child.sibling; - } - } + var nextChildren; + prepareToReadContext(workInProgress, renderLanes); - completedWork.subtreeFlags |= subtreeFlags; - } else { - // Bubble up the earliest expiration time. - if ((completedWork.mode & ProfileMode) !== NoMode) { - // In profiling mode, resetChildExpirationTime is also used to reset - // profiler durations. - var _treeBaseDuration = completedWork.selfBaseDuration; - var _child2 = completedWork.child; + { + ReactCurrentOwner$1.current = workInProgress; + setIsRendering(true); + nextChildren = renderWithHooks( + current, + workInProgress, + Component, + nextProps, + context, + renderLanes + ); - 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. + setIsRendering(false); + } - subtreeFlags |= _child2.subtreeFlags & StaticMask; - subtreeFlags |= _child2.flags & StaticMask; - _treeBaseDuration += _child2.treeBaseDuration; - _child2 = _child2.sibling; + 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; } - completedWork.treeBaseDuration = _treeBaseDuration; - } else { - var _child3 = completedWork.child; + case true: { + workInProgress.flags |= DidCapture; + workInProgress.flags |= ShouldCapture; // eslint-disable-next-line react-internal/prod-error-codes - 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. + 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 - subtreeFlags |= _child3.subtreeFlags & StaticMask; - subtreeFlags |= _child3.flags & StaticMask; // Update the return pointer so the tree is consistent. This is a code - // smell because it assumes the commit phase is never concurrent with - // the render phase. Will address during refactor to alternate model. + var update = createClassErrorUpdate( + workInProgress, + createCapturedValue(error$1, workInProgress), + lane + ); + enqueueCapturedUpdate(workInProgress, update); + break; + } + } - _child3.return = completedWork; - _child3 = _child3.sibling; + if (workInProgress.type !== workInProgress.elementType) { + // Lazy component props can't be validated in createElement + // because they're only guaranteed to be resolved here. + var innerPropTypes = Component.propTypes; + + if (innerPropTypes) { + checkPropTypes( + innerPropTypes, + nextProps, // Resolved props + "prop", + getComponentNameFromType(Component) + ); } } + } // Push context providers early to prevent context stack mismatches. + // During mounting we don't know the child context yet as the instance doesn't exist. + // We will invalidate the child context in finishClassComponent() right after rendering. - completedWork.subtreeFlags |= subtreeFlags; + var hasContext; + + if (isContextProvider(Component)) { + hasContext = true; + pushContextProvider(workInProgress); + } else { + hasContext = false; } - completedWork.childLanes = newChildLanes; - return didBailout; -} + prepareToReadContext(workInProgress, renderLanes); + var instance = workInProgress.stateNode; + var shouldUpdate; -function completeWork(current, workInProgress, renderLanes) { - var newProps = workInProgress.pendingProps; // Note: This intentionally doesn't check if we're hydrating because comparing - // to the current tree provider fiber is just as fast and less error-prone. - // Ideally we would have a special version of the work loop only - // for hydration. + if (instance === null) { + resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress); // In the initial pass we might need to construct the instance. - popTreeContext(workInProgress); + constructClassInstance(workInProgress, Component, nextProps); + mountClassInstance(workInProgress, Component, nextProps, renderLanes); + shouldUpdate = true; + } else if (current === null) { + // In a resume, we'll already have an instance we can reuse. + shouldUpdate = resumeMountClassInstance( + workInProgress, + Component, + nextProps, + renderLanes + ); + } else { + shouldUpdate = updateClassInstance( + current, + workInProgress, + Component, + nextProps, + renderLanes + ); + } - switch (workInProgress.tag) { - case IndeterminateComponent: - case LazyComponent: - case SimpleMemoComponent: - case FunctionComponent: - case ForwardRef: - case Fragment: - case Mode: - case Profiler: - case ContextConsumer: - case MemoComponent: - bubbleProperties(workInProgress); - return null; + var nextUnitOfWork = finishClassComponent( + current, + workInProgress, + Component, + shouldUpdate, + hasContext, + renderLanes + ); - case ClassComponent: { - var Component = workInProgress.type; + { + var inst = workInProgress.stateNode; - if (isContextProvider(Component)) { - popContext(workInProgress); + 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" + ); } - bubbleProperties(workInProgress); - return null; + didWarnAboutReassigningProps = true; } + } - case HostRoot: { - var fiberRoot = workInProgress.stateNode; + return nextUnitOfWork; +} - popHostContainer(workInProgress); - popTopLevelContextObject(workInProgress); - resetWorkInProgressVersions(); +function finishClassComponent( + current, + workInProgress, + Component, + shouldUpdate, + hasContext, + renderLanes +) { + // Refs should update even if shouldComponentUpdate returns false + markRef(current, workInProgress); + var didCaptureError = (workInProgress.flags & DidCapture) !== NoFlags; - if (fiberRoot.pendingContext) { - fiberRoot.context = fiberRoot.pendingContext; - fiberRoot.pendingContext = null; - } + if (!shouldUpdate && !didCaptureError) { + // Context providers should defer to sCU for rendering + if (hasContext) { + invalidateContextProvider(workInProgress, Component, false); + } - 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(); + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); + } - 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; + var instance = workInProgress.stateNode; // Rerender - if ( - // Check if this is a client root - !prevState.isDehydrated || // Check if we reverted to client rendering (e.g. due to an error) - (workInProgress.flags & ForceClientRender) !== NoFlags - ) { - // Schedule an effect to clear this container at the start of the - // next commit. This handles the case of React rendering into a - // container with previous children. It's also safe to do for - // updates too, because current.child would only be null if the - // previous render was null (so the container would already - // be empty). - workInProgress.flags |= Snapshot; // If this was a forced client render, there may have been - } - } - } - } - - updateHostContainer(current, workInProgress); - bubbleProperties(workInProgress); - return null; - } - - case HostComponent: { - popHostContext(workInProgress); - var rootContainerInstance = getRootHostContainer(); - var type = workInProgress.type; + ReactCurrentOwner$1.current = workInProgress; + var nextChildren; - if (current !== null && workInProgress.stateNode != null) { - updateHostComponent( - current, - workInProgress, - type, - newProps, - rootContainerInstance - ); + 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 (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. + { + stopProfilerTimerIfRunning(); + } + } else { + { + setIsRendering(true); + nextChildren = instance.render(); - bubbleProperties(workInProgress); - return null; - } + setIsRendering(false); + } + } // React DevTools reads this flag. - var currentHostContext = getHostContext(); // TODO: Move createInstance to beginWork and keep it on a context - // "stack" as the parent. Then append children as we go in beginWork - // or completeWork depending on whether we want to add them top->down or - // bottom->up. Top->down is faster in IE11. + workInProgress.flags |= PerformedWork; - var _wasHydrated = popHydrationState(); + if (current !== null && didCaptureError) { + // If we're recovering from an error, reconcile without reusing any of + // the existing children. Conceptually, the normal children and the children + // that are shown on error are two different sets, so we shouldn't reuse + // normal children even if their identities match. + forceUnmountCurrentAndReconcile( + current, + workInProgress, + nextChildren, + renderLanes + ); + } else { + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + } // Memoize state using the values we just used to render. + // TODO: Restructure so we never read values from the instance. - if (_wasHydrated) { - // TODO: Move this and createInstance step into the beginPhase - // to consolidate. - if (prepareToHydrateHostInstance()) { - // If changes to the hydrated node need to be applied at the - // commit-phase we mark this as such. - markUpdate(workInProgress); - } - } else { - var instance = createInstance( - type, - newProps, - rootContainerInstance, - currentHostContext, - workInProgress - ); - appendAllChildren(instance, workInProgress, false, false); - workInProgress.stateNode = instance; // Certain renderers require commit-time effects for initial mount. - } + workInProgress.memoizedState = instance.state; // The context might have changed so we need to recalculate it. - if (workInProgress.ref !== null) { - // If there is a ref on a host node we need to schedule a callback - markRef(workInProgress); - } - } + if (hasContext) { + invalidateContextProvider(workInProgress, Component, true); + } - bubbleProperties(workInProgress); - return null; - } + return workInProgress.child; +} - case HostText: { - var newText = newProps; +function pushHostRootContext(workInProgress) { + var root = workInProgress.stateNode; - if (current && workInProgress.stateNode != null) { - var oldText = current.memoizedProps; // If we have an alternate, that means this is an update and we need - // to schedule a side-effect to do the updates. + if (root.pendingContext) { + pushTopLevelContextObject( + workInProgress, + root.pendingContext, + root.pendingContext !== root.context + ); + } else if (root.context) { + // Should always be set + pushTopLevelContextObject(workInProgress, root.context, false); + } - 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. - } + pushHostContainer(workInProgress, root.containerInfo); +} - var _rootContainerInstance = getRootHostContainer(); +function updateHostRoot(current, workInProgress, renderLanes) { + pushHostRootContext(workInProgress); - var _currentHostContext = getHostContext(); + if (current === null) { + throw new Error("Should have a current fiber. This is a bug in React."); + } - var _wasHydrated2 = popHydrationState(); + var nextProps = workInProgress.pendingProps; + var prevState = workInProgress.memoizedState; + var prevChildren = prevState.element; + cloneUpdateQueue(current, workInProgress); + processUpdateQueue(workInProgress, nextProps, null, renderLanes); + var nextState = workInProgress.memoizedState; + var root = workInProgress.stateNode; + // being called "element". - if (_wasHydrated2) { - if (prepareToHydrateHostTextInstance()) { - markUpdate(workInProgress); - } - } else { - workInProgress.stateNode = createTextInstance( - newText, - _rootContainerInstance, - _currentHostContext, - workInProgress - ); - } - } + var nextChildren = nextState.element; - bubbleProperties(workInProgress); - return null; + { + if (nextChildren === prevChildren) { + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); } - case SuspenseComponent: { - popSuspenseContext(workInProgress); - var nextState = workInProgress.memoizedState; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + } - if ((workInProgress.flags & DidCapture) !== NoFlags) { - // Something suspended. Re-render with the fallback children. - workInProgress.lanes = renderLanes; // Do not reset the effect list. + return workInProgress.child; +} - if ((workInProgress.mode & ProfileMode) !== NoMode) { - transferActualDuration(workInProgress); - } // Don't bubble properties in this case. +function updateHostComponent(current, workInProgress, renderLanes) { + pushHostContext(workInProgress); - return workInProgress; - } + var type = workInProgress.type; + var nextProps = workInProgress.pendingProps; + var prevProps = current !== null ? current.memoizedProps : null; + var nextChildren = nextProps.children; - var nextDidTimeout = nextState !== null; - var prevDidTimeout = false; + 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; + } - if (current === null); - else { - var _prevState = current.memoizedState; - prevDidTimeout = _prevState !== null; - } - // 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 && !prevDidTimeout) { - var _offscreenFiber = workInProgress.child; - _offscreenFiber.flags |= Visibility; // TODO: This will still suspend a synchronous tree if anything - // in the concurrent tree already suspended during this render. - // This is a known bug. - - if ((workInProgress.mode & ConcurrentMode) !== NoMode) { - // TODO: Move this back to throwException because this is too late - // if this is a large tree which is common for initial loads. We - // don't know if we should restart a render or not until we get - // this marker, and this is too late. - // If this render already had a ping or lower pri updates, - // and this is the first time we know we're going to suspend we - // should be able to immediately restart from within throwException. - var hasInvisibleChildContext = - current === null && - (workInProgress.memoizedProps.unstable_avoidThisFallback !== true || - !enableSuspenseAvoidThisFallback); + markRef(current, workInProgress); + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; +} - if ( - hasInvisibleChildContext || - hasSuspenseContext( - suspenseStackCursor.current, - InvisibleParentSuspenseContext - ) - ) { - // If this was in an invisible tree or a new render, then showing - // this boundary is ok. - renderDidSuspend(); - } else { - // Otherwise, we're going to have to hide content so we should - // suspend for longer if possible. - renderDidSuspendDelayIfPossible(); - } - } - } +function updateHostText(current, workInProgress) { + // immediately after. - var wakeables = workInProgress.updateQueue; + return null; +} - if (wakeables !== null) { - // Schedule an effect to attach a retry listener to the promise. - // TODO: Move to passive phase - workInProgress.flags |= Update; - } +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. - bubbleProperties(workInProgress); + workInProgress.type = Component; + var resolvedTag = (workInProgress.tag = resolveLazyComponentTag(Component)); + var resolvedProps = resolveDefaultProps(Component, props); + var child; + switch (resolvedTag) { + case FunctionComponent: { { - 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 _primaryChildFragment2 = workInProgress.child; - - if (_primaryChildFragment2 !== null) { - // $FlowFixMe Flow doesn't support type casting in combination with the -= operator - workInProgress.treeBaseDuration -= - _primaryChildFragment2.treeBaseDuration; - } - } - } + validateFunctionComponentInDev(workInProgress, Component); + workInProgress.type = Component = resolveFunctionForHotReloading( + Component + ); } - return null; + child = updateFunctionComponent( + null, + workInProgress, + Component, + resolvedProps, + renderLanes + ); + return child; } - case HostPortal: - popHostContainer(workInProgress); - updateHostContainer(current, workInProgress); - - if (current === null) { - preparePortalMount(workInProgress.stateNode.containerInfo); + case ClassComponent: { + { + workInProgress.type = Component = resolveClassForHotReloading( + Component + ); } - bubbleProperties(workInProgress); - return null; - - case ContextProvider: - // Pop provider fiber - var context = workInProgress.type._context; - popProvider(context, workInProgress); - bubbleProperties(workInProgress); - return null; - - case IncompleteClassComponent: { - // Same as class component case. I put it down here so that the tags are - // sequential to ensure this switch is compiled to a jump table. - var _Component = workInProgress.type; + child = updateClassComponent( + null, + workInProgress, + Component, + resolvedProps, + renderLanes + ); + return child; + } - if (isContextProvider(_Component)) { - popContext(workInProgress); + case ForwardRef: { + { + workInProgress.type = Component = resolveForwardRefForHotReloading( + Component + ); } - bubbleProperties(workInProgress); - return null; + child = updateForwardRef( + null, + workInProgress, + Component, + resolvedProps, + renderLanes + ); + return child; } - case SuspenseListComponent: { - popSuspenseContext(workInProgress); - var renderState = workInProgress.memoizedState; + case MemoComponent: { + { + if (workInProgress.type !== workInProgress.elementType) { + var outerPropTypes = Component.propTypes; - if (renderState === null) { - // We're running in the default, "independent" mode. - // We don't do anything in this mode. - bubbleProperties(workInProgress); - return null; + if (outerPropTypes) { + checkPropTypes( + outerPropTypes, + resolvedProps, // Resolved for outer only + "prop", + getComponentNameFromType(Component) + ); + } + } } - var didSuspendAlready = (workInProgress.flags & DidCapture) !== NoFlags; - var renderedTail = renderState.rendering; + child = updateMemoComponent( + null, + workInProgress, + Component, + resolveDefaultProps(Component.type, resolvedProps), // The inner type can have defaults too + renderLanes + ); + return child; + } + } - 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); + var hint = ""; - if (!cannotBeSuspended) { - var row = workInProgress.child; + { + 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. - while (row !== null) { - var suspended = findFirstSuspended(row); + 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 (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. +function mountIncompleteClassComponent( + _current, + workInProgress, + Component, + nextProps, + renderLanes +) { + resetSuspendedCurrentOnMountInLegacyMode(_current, workInProgress); // Promote the fiber to a class and try rendering again. - var newThenables = suspended.updateQueue; + 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 (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. + var hasContext; - workInProgress.subtreeFlags = NoFlags; - resetChildFibers(workInProgress, renderLanes); // Set up the Suspense Context to force suspense and immediately - // rerender the children. + if (isContextProvider(Component)) { + hasContext = true; + pushContextProvider(workInProgress); + } else { + hasContext = false; + } - pushSuspenseContext( - workInProgress, - setShallowSuspenseContext( - suspenseStackCursor.current, - ForceSuspenseFallback - ) - ); // Don't bubble properties in this case. + prepareToReadContext(workInProgress, renderLanes); + constructClassInstance(workInProgress, Component, nextProps); + mountClassInstance(workInProgress, Component, nextProps, renderLanes); + return finishClassComponent( + null, + workInProgress, + Component, + true, + hasContext, + renderLanes + ); +} - return workInProgress.child; - } +function mountIndeterminateComponent( + _current, + workInProgress, + Component, + renderLanes +) { + resetSuspendedCurrentOnMountInLegacyMode(_current, workInProgress); + var props = workInProgress.pendingProps; + var context; - row = row.sibling; - } - } + { + var unmaskedContext = getUnmaskedContext(workInProgress, Component, false); + context = getMaskedContext(workInProgress, unmaskedContext); + } - if (renderState.tail !== null && now() > getRenderTargetTime()) { - // We have already passed our CPU deadline but we still have rows - // left in the tail. We'll just give up further attempts to render - // the main content and only render fallbacks. - workInProgress.flags |= DidCapture; - didSuspendAlready = true; - cutOffTailIfNeeded(renderState, false); // Since nothing actually suspended, there will nothing to ping this - // to get it started back up to attempt the next item. While in terms - // of priority this work has the same priority as this current render, - // it's not part of the same transition once the transition has - // committed. If it's sync, we still want to yield so that it can be - // painted. Conceptually, this is really the same as pinging. - // We can use any RetryLane even if it's the one currently rendering - // since we're leaving it behind on this node. + prepareToReadContext(workInProgress, renderLanes); + var value; - 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 ( + Component.prototype && + typeof Component.prototype.render === "function" + ) { + var componentName = getComponentNameFromType(Component) || "Unknown"; - if (_suspended !== null) { - workInProgress.flags |= DidCapture; - didSuspendAlready = true; // Ensure we transfer the update queue to the parent so that it doesn't - // get lost if this row ends up dropped during a second pass. + if (!didWarnAboutBadClass[componentName]) { + error( + "The <%s /> component appears to have a render method, but doesn't extend React.Component. " + + "This is likely to cause errors. Change %s to extend React.Component instead.", + componentName, + componentName + ); - var _newThenables = _suspended.updateQueue; + didWarnAboutBadClass[componentName] = true; + } + } - if (_newThenables !== null) { - workInProgress.updateQueue = _newThenables; - workInProgress.flags |= Update; - } - - cutOffTailIfNeeded(renderState, true); // This might have been modified. + if (workInProgress.mode & StrictLegacyMode) { + ReactStrictModeWarnings.recordLegacyContextWarning(workInProgress, null); + } - if ( - renderState.tail === null && - renderState.tailMode === "hidden" && - !renderedTail.alternate && - !getIsHydrating() // We don't cut it if we're hydrating. - ) { - // We're done. - bubbleProperties(workInProgress); - return null; - } - } else if ( - // The time it took to render last row is greater than the remaining - // time we have to render. So rendering one more row would likely - // exceed it. - now() * 2 - renderState.renderingStartTime > - getRenderTargetTime() && - renderLanes !== OffscreenLane - ) { - // We have now passed our CPU deadline and we'll just give up further - // attempts to render the main content and only render fallbacks. - // The assumption is that this is usually faster. - workInProgress.flags |= DidCapture; - didSuspendAlready = true; - cutOffTailIfNeeded(renderState, false); // Since nothing actually suspended, there will nothing to ping this - // to get it started back up to attempt the next item. While in terms - // of priority this work has the same priority as this current render, - // it's not part of the same transition once the transition has - // committed. If it's sync, we still want to yield so that it can be - // painted. Conceptually, this is really the same as pinging. - // We can use any RetryLane even if it's the one currently rendering - // since we're leaving it behind on this node. + setIsRendering(true); + ReactCurrentOwner$1.current = workInProgress; + value = renderWithHooks( + null, + workInProgress, + Component, + props, + context, + renderLanes + ); + setIsRendering(false); + } - workInProgress.lanes = SomeRetryLane; - } - } + workInProgress.flags |= PerformedWork; - 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; + { + // 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 (previousSibling !== null) { - previousSibling.sibling = renderedTail; - } else { - workInProgress.child = renderedTail; - } + 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 + ); - renderState.last = renderedTail; - } + didWarnAboutModulePatternComponent[_componentName] = true; } + } + } - if (renderState.tail !== null) { - // We still have tail rows to render. - // Pop a row. - var next = renderState.tail; - renderState.rendering = next; - renderState.tail = next.sibling; - renderState.renderingStartTime = now(); - next.sibling = null; // Restore the context. - // TODO: We can probably just avoid popping it instead and only - // setting it the first time we go from not suspended to suspended. + 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"; - var suspenseContext = suspenseStackCursor.current; + 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 (didSuspendAlready) { - suspenseContext = setShallowSuspenseContext( - suspenseContext, - ForceSuspenseFallback - ); - } else { - suspenseContext = setDefaultShallowSuspenseContext(suspenseContext); - } + didWarnAboutModulePatternComponent[_componentName2] = true; + } + } // Proceed under the assumption that this is a class instance - pushSuspenseContext(workInProgress, suspenseContext); // Do a pass over the next row. - // Don't bubble properties in this case. + workInProgress.tag = ClassComponent; // Throw out any hooks that were used. - return next; - } + 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. - bubbleProperties(workInProgress); - return null; + var hasContext = false; + + if (isContextProvider(Component)) { + hasContext = true; + pushContextProvider(workInProgress); + } else { + hasContext = false; } - case ScopeComponent: { - break; + 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); } - case OffscreenComponent: - case LegacyHiddenComponent: { - popRenderLanes(workInProgress); - var _nextState = workInProgress.memoizedState; - var nextIsHidden = _nextState !== null; + return workInProgress.child; + } +} - if (current !== null) { - var _prevState2 = current.memoizedState; - var prevIsHidden = _prevState2 !== null; +function validateFunctionComponentInDev(workInProgress, Component) { + { + if (Component) { + if (Component.childContextTypes) { + error( + "%s(...): childContextTypes cannot be defined on a function component.", + Component.displayName || Component.name || "Component" + ); + } + } - if ( - prevIsHidden !== nextIsHidden && // LegacyHidden doesn't do any hiding — it only pre-renders. - !enableLegacyHidden - ) { - workInProgress.flags |= Visibility; - } + if (workInProgress.ref !== null) { + var info = ""; + var ownerName = getCurrentFiberOwnerNameInDevOrNull(); + + if (ownerName) { + info += "\n\nCheck the render method of `" + ownerName + "`."; } - if (!nextIsHidden || (workInProgress.mode & ConcurrentMode) === NoMode) { - bubbleProperties(workInProgress); - } else { - // Don't bubble properties for hidden children unless we're rendering - // at offscreen priority. - if (includesSomeLane(subtreeRenderLanes, OffscreenLane)) { - bubbleProperties(workInProgress); - } + var warningKey = ownerName || ""; + var debugSource = workInProgress._debugSource; + + if (debugSource) { + warningKey = debugSource.fileName + ":" + debugSource.lineNumber; } - return null; - } + if (!didWarnAboutFunctionRefs[warningKey]) { + didWarnAboutFunctionRefs[warningKey] = true; - case CacheComponent: { - return null; + error( + "Function components cannot be given refs. " + + "Attempts to access this ref will fail. " + + "Did you mean to use React.forwardRef()?%s", + info + ); + } } - case TracingMarkerComponent: { - return null; - } - } + if (typeof Component.getDerivedStateFromProps === "function") { + var _componentName3 = getComponentNameFromType(Component) || "Unknown"; - throw new Error( - "Unknown unit of work tag (" + - workInProgress.tag + - "). This error is likely caused by a bug in " + - "React. Please file an issue." - ); -} + if (!didWarnAboutGetDerivedStateOnFunctionComponent[_componentName3]) { + error( + "%s: Function components do not support getDerivedStateFromProps.", + _componentName3 + ); -var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner; -var didReceiveUpdate = false; -var didWarnAboutBadClass; -var didWarnAboutModulePatternComponent; -var didWarnAboutContextTypeOnFunctionComponent; -var didWarnAboutGetDerivedStateOnFunctionComponent; -var didWarnAboutFunctionRefs; -var didWarnAboutReassigningProps; -var didWarnAboutRevealOrder; -var didWarnAboutTailOptions; + didWarnAboutGetDerivedStateOnFunctionComponent[_componentName3] = true; + } + } -{ - didWarnAboutBadClass = {}; - didWarnAboutModulePatternComponent = {}; - didWarnAboutContextTypeOnFunctionComponent = {}; - didWarnAboutGetDerivedStateOnFunctionComponent = {}; - didWarnAboutFunctionRefs = {}; - didWarnAboutReassigningProps = false; - didWarnAboutRevealOrder = {}; - didWarnAboutTailOptions = {}; -} + if ( + typeof Component.contextType === "object" && + Component.contextType !== null + ) { + var _componentName4 = getComponentNameFromType(Component) || "Unknown"; -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 (!didWarnAboutContextTypeOnFunctionComponent[_componentName4]) { + error( + "%s: Function components do not support contextType.", + _componentName4 + ); + + didWarnAboutContextTypeOnFunctionComponent[_componentName4] = true; + } + } } } -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 SUSPENDED_MARKER = { + dehydrated: null, + treeContext: null, + retryLane: NoLane +}; - workInProgress.child = reconcileChildFibers( - workInProgress, - null, - nextChildren, - renderLanes - ); +function mountSuspenseOffscreenState(renderLanes) { + return { + baseLanes: renderLanes, + cachePool: getSuspendedCache(), + transitions: null + }; } -function updateForwardRef( +function updateSuspenseOffscreenState(prevOffscreenState, renderLanes) { + var cachePool = null; + + return { + baseLanes: mergeLanes(prevOffscreenState.baseLanes, renderLanes), + cachePool: cachePool, + transitions: prevOffscreenState.transitions + }; +} // TODO: Probably should inline this back + +function shouldRemainOnFallback( + suspenseContext, current, workInProgress, - 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 we're already showing a fallback, there are cases where we need to + // remain on that fallback regardless of whether the content has resolved. + // For example, SuspenseList coordinates when nested content appears. + if (current !== null) { + var suspenseState = current.memoizedState; - if (innerPropTypes) { - checkPropTypes( - innerPropTypes, - nextProps, // Resolved props - "prop", - getComponentNameFromType(Component) - ); - } + 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 render = Component.render; - var ref = workInProgress.ref; // The rest is a fork of updateFunctionComponent + return hasSuspenseContext(suspenseContext, ForceSuspenseFallback); +} - var nextChildren; - prepareToReadContext(workInProgress, renderLanes); +function getRemainingWorkInPrimaryTree(current, renderLanes) { + // TODO: Should not remove render lanes that were pinged during this render + return removeLanes(current.childLanes, renderLanes); +} - { - ReactCurrentOwner$1.current = workInProgress; - setIsRendering(true); - nextChildren = renderWithHooks( - current, - workInProgress, - render, - nextProps, - ref, - renderLanes - ); +function updateSuspenseComponent(current, workInProgress, renderLanes) { + var nextProps = workInProgress.pendingProps; // This is used by DevTools to force a boundary to suspend. - setIsRendering(false); + { + if (shouldSuspend(workInProgress)) { + workInProgress.flags |= DidCapture; + } } - if (current !== null && !didReceiveUpdate) { - bailoutHooks(current, workInProgress, renderLanes); - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); + var suspenseContext = suspenseStackCursor.current; + var showFallback = false; + var didSuspend = (workInProgress.flags & DidCapture) !== NoFlags; + + if (didSuspend || shouldRemainOnFallback(suspenseContext, current)) { + // Something in this boundary's subtree already suspended. Switch to + // rendering the fallback children. + showFallback = true; + workInProgress.flags &= ~DidCapture; + } else { + // Attempting the main content + if (current === null || current.memoizedState !== null) { + // This is a new mount or this boundary is already showing a fallback state. + // Mark this subtree context as having at least one invisible parent that could + // handle the fallback state. + // Avoided boundaries are not considered since they cannot handle preferred fallback states. + { + suspenseContext = addSubtreeSuspenseContext( + suspenseContext, + InvisibleParentSuspenseContext + ); + } + } } - workInProgress.flags |= PerformedWork; - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; -} + suspenseContext = setDefaultShallowSuspenseContext(suspenseContext); + pushSuspenseContext(workInProgress, suspenseContext); // OK, the next part is confusing. We're about to reconcile the Suspense + // boundary's children. This involves some custom reconciliation logic. Two + // main reasons this is so complicated. + // + // First, Legacy Mode has different semantics for backwards compatibility. The + // primary tree will commit in an inconsistent state, so when we do the + // second pass to render the fallback, we do some exceedingly, uh, clever + // hacks to make that not totally break. Like transferring effects and + // deletions from hidden tree. In Concurrent Mode, it's much simpler, + // because we bailout on the primary tree completely and leave it in its old + // state, no effects. Same as what we do for Offscreen (except that + // Offscreen doesn't have the first render pass). + // + // Second is hydration. During hydration, the Suspense fiber has a slightly + // different layout, where the child points to a dehydrated fragment, which + // contains the DOM rendered by the server. + // + // Third, even if you set all that aside, Suspense is like error boundaries in + // that we first we try to render one tree, and if that fails, we render again + // and switch to a different tree. Like a try/catch block. So we have to track + // which branch we're currently rendering. Ideally we would model this using + // a stack. -function updateMemoComponent( - current, - workInProgress, - Component, - nextProps, - renderLanes -) { if (current === null) { - var type = Component.type; - - if ( - isSimpleFunctionComponent(type) && - Component.compare === null && // SimpleMemoComponent codepath doesn't resolve outer props either. - Component.defaultProps === undefined - ) { - var resolvedType = type; - - { - resolvedType = resolveFunctionForHotReloading(type); - } // If this is a plain function component without default props, - // and with only the default shallow comparison, we upgrade it - // to a SimpleMemoComponent to allow fast path updates. + var suspenseState = workInProgress.memoizedState; - workInProgress.tag = SimpleMemoComponent; - workInProgress.type = resolvedType; + if (suspenseState !== null) { + var dehydrated = suspenseState.dehydrated; - { - validateFunctionComponentInDev(workInProgress, type); + if (dehydrated !== null) { + return mountDehydratedSuspenseComponent(workInProgress); } - - return updateSimpleMemoComponent( - current, - workInProgress, - resolvedType, - nextProps, - renderLanes - ); } - { - var innerPropTypes = type.propTypes; + var nextPrimaryChildren = nextProps.children; + var nextFallbackChildren = nextProps.fallback; - if (innerPropTypes) { - // Inner memo component props aren't currently validated in createElement. - // We could move it there, but we'd still need this for lazy code path. - checkPropTypes( - innerPropTypes, - nextProps, // Resolved props - "prop", - getComponentNameFromType(type) + if (showFallback) { + var fallbackFragment = mountSuspenseFallbackChildren( + workInProgress, + nextPrimaryChildren, + nextFallbackChildren, + renderLanes + ); + var primaryChildFragment = workInProgress.child; + primaryChildFragment.memoizedState = mountSuspenseOffscreenState( + renderLanes + ); + workInProgress.memoizedState = SUSPENDED_MARKER; + + return fallbackFragment; + } else { + return mountSuspensePrimaryChildren(workInProgress, nextPrimaryChildren); + } + } else { + // This is an update. + // Special path for hydration + var prevState = current.memoizedState; + + if (prevState !== null) { + var _dehydrated = prevState.dehydrated; + + if (_dehydrated !== null) { + return updateDehydratedSuspenseComponent( + current, + workInProgress, + didSuspend, + nextProps, + _dehydrated, + prevState, + renderLanes ); } } - var child = createFiberFromTypeAndProps( - Component.type, - null, - nextProps, - workInProgress, - workInProgress.mode, - renderLanes - ); - child.ref = workInProgress.ref; - child.return = workInProgress; - workInProgress.child = child; - return child; - } - - { - var _type = Component.type; - var _innerPropTypes = _type.propTypes; + if (showFallback) { + var _nextFallbackChildren = nextProps.fallback; + var _nextPrimaryChildren = nextProps.children; + var fallbackChildFragment = updateSuspenseFallbackChildren( + current, + workInProgress, + _nextPrimaryChildren, + _nextFallbackChildren, + renderLanes + ); + var _primaryChildFragment2 = workInProgress.child; + var prevOffscreenState = current.child.memoizedState; + _primaryChildFragment2.memoizedState = + prevOffscreenState === null + ? mountSuspenseOffscreenState(renderLanes) + : updateSuspenseOffscreenState(prevOffscreenState, renderLanes); + + _primaryChildFragment2.childLanes = getRemainingWorkInPrimaryTree( + current, + renderLanes + ); + workInProgress.memoizedState = SUSPENDED_MARKER; + return fallbackChildFragment; + } else { + var _nextPrimaryChildren2 = nextProps.children; - 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 _primaryChildFragment3 = updateSuspensePrimaryChildren( + current, + workInProgress, + _nextPrimaryChildren2, + renderLanes ); + + workInProgress.memoizedState = null; + return _primaryChildFragment3; } } +} - var currentChild = current.child; // This is always exactly one child - - var hasScheduledUpdateOrContext = checkScheduledUpdateOrContext( - current, - renderLanes +function mountSuspensePrimaryChildren( + workInProgress, + primaryChildren, + renderLanes +) { + var mode = workInProgress.mode; + var primaryChildProps = { + mode: "visible", + children: primaryChildren + }; + var primaryChildFragment = mountWorkInProgressOffscreenFiber( + primaryChildProps, + mode ); + primaryChildFragment.return = workInProgress; + workInProgress.child = primaryChildFragment; + return primaryChildFragment; +} - if (!hasScheduledUpdateOrContext) { - // This will be the props with resolved defaultProps, - // unlike current.memoizedProps which will be the unresolved ones. - var prevProps = currentChild.memoizedProps; // Default to shallow comparison +function mountSuspenseFallbackChildren( + workInProgress, + primaryChildren, + fallbackChildren, + renderLanes +) { + var mode = workInProgress.mode; + var progressedPrimaryFragment = workInProgress.child; + var primaryChildProps = { + mode: "hidden", + children: primaryChildren + }; + var primaryChildFragment; + var fallbackChildFragment; - var compare = Component.compare; - compare = compare !== null ? compare : shallowEqual; + 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 (compare(prevProps, nextProps) && current.ref === workInProgress.ref) { - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); + 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; } - } // 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; + fallbackChildFragment = createFiberFromFragment( + fallbackChildren, + mode, + renderLanes, + null + ); + } else { + primaryChildFragment = mountWorkInProgressOffscreenFiber( + primaryChildProps, + mode + ); + fallbackChildFragment = createFiberFromFragment( + fallbackChildren, + mode, + renderLanes, + null + ); + } + + primaryChildFragment.return = workInProgress; + fallbackChildFragment.return = workInProgress; + primaryChildFragment.sibling = fallbackChildFragment; + workInProgress.child = primaryChildFragment; + return fallbackChildFragment; } -function updateSimpleMemoComponent( +function mountWorkInProgressOffscreenFiber(offscreenProps, mode, renderLanes) { + // The props argument to `createFiberFromOffscreen` is `any` typed, so we use + // this wrapper function to constrain it. + return createFiberFromOffscreen(offscreenProps, mode, NoLanes, null); +} + +function updateWorkInProgressOffscreenFiber(current, offscreenProps) { + // The props argument to `createWorkInProgress` is `any` typed, so we use this + // wrapper function to constrain it. + return createWorkInProgress(current, offscreenProps); +} + +function updateSuspensePrimaryChildren( current, workInProgress, - Component, - nextProps, + primaryChildren, 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; + var currentPrimaryChildFragment = current.child; + var currentFallbackChildFragment = currentPrimaryChildFragment.sibling; + var primaryChildFragment = updateWorkInProgressOffscreenFiber( + currentPrimaryChildFragment, + { + mode: "visible", + children: primaryChildren + } + ); - 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 ((workInProgress.mode & ConcurrentMode) === NoMode) { + primaryChildFragment.lanes = renderLanes; + } - try { - outerMemoType = init(payload); - } catch (x) { - outerMemoType = null; - } // Inner propTypes will be validated in the function component path. + primaryChildFragment.return = workInProgress; + primaryChildFragment.sibling = null; - var outerPropTypes = outerMemoType && outerMemoType.propTypes; + if (currentFallbackChildFragment !== null) { + // Delete the fallback child fragment + var deletions = workInProgress.deletions; - if (outerPropTypes) { - checkPropTypes( - outerPropTypes, - nextProps, // Resolved (SimpleMemoComponent has no defaultProps) - "prop", - getComponentNameFromType(outerMemoType) - ); - } - } + if (deletions === null) { + workInProgress.deletions = [currentFallbackChildFragment]; + workInProgress.flags |= ChildDeletion; + } else { + deletions.push(currentFallbackChildFragment); } } - if (current !== null) { - var prevProps = current.memoizedProps; - - if ( - shallowEqual(prevProps, nextProps) && - current.ref === workInProgress.ref && // Prevent bailout if the implementation changed due to hot reload. - workInProgress.type === current.type - ) { - didReceiveUpdate = false; + workInProgress.child = primaryChildFragment; + return primaryChildFragment; +} - if (!checkScheduledUpdateOrContext(current, renderLanes)) { - // The pending lanes were cleared at the beginning of beginWork. We're - // about to bail out, but there might be other lanes that weren't - // included in the current render. Usually, the priority level of the - // remaining updates is accumulated during the evaluation of the - // component (i.e. when processing the update queue). But since since - // we're bailing out early *without* evaluating the component, we need - // to account for it here, too. Reset to the value of the current fiber. - // NOTE: This only applies to SimpleMemoComponent, not MemoComponent, - // because a MemoComponent fiber does not have hooks or an update queue; - // rather, it wraps around an inner component, which may or may not - // contains hooks. - // TODO: Move the reset at in beginWork out of the common path so that - // this is no longer necessary. - workInProgress.lanes = current.lanes; - return bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderLanes - ); - } else if ((current.flags & ForceUpdateForLegacySuspense) !== NoFlags) { - // This is a special case that only exists for legacy mode. - // See https://github.com/facebook/react/pull/19216. - didReceiveUpdate = true; - } - } - } +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; - return updateFunctionComponent( - current, - workInProgress, - Component, - nextProps, - renderLanes - ); -} + 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; -function updateOffscreenComponent(current, workInProgress, renderLanes) { - var nextProps = workInProgress.pendingProps; - var nextChildren = nextProps.children; - var prevState = current !== null ? current.memoizedState : null; + 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 (nextProps.mode === "hidden" || enableLegacyHidden) { - // Rendering a hidden tree. - if ((workInProgress.mode & ConcurrentMode) === NoMode) { - // In legacy sync mode, don't defer the subtree. Render it now. - var nextState = { - baseLanes: NoLanes, - cachePool: null - }; - workInProgress.memoizedState = nextState; + 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.) - pushRenderLanes(workInProgress, renderLanes); - } else if (!includesSomeLane(renderLanes, OffscreenLane)) { - var spawnedCachePool = null; // We're hidden, and we're not rendering at Offscreen. We will bail out - // and resume this tree later. + primaryChildFragment.subtreeFlags = + currentPrimaryChildFragment.subtreeFlags & StaticMask; + } - var nextBaseLanes; + var fallbackChildFragment; - if (prevState !== null) { - var prevBaseLanes = prevState.baseLanes; - nextBaseLanes = mergeLanes(prevBaseLanes, renderLanes); - } else { - nextBaseLanes = renderLanes; - } // Schedule this fiber to re-render at offscreen priority. Then bailout. + 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. - workInProgress.lanes = workInProgress.childLanes = laneToLanes( - OffscreenLane - ); - var _nextState = { - baseLanes: nextBaseLanes, - cachePool: spawnedCachePool - }; - workInProgress.memoizedState = _nextState; - workInProgress.updateQueue = null; - // to avoid a push/pop misalignment. + fallbackChildFragment.flags |= Placement; + } - pushRenderLanes(workInProgress, nextBaseLanes); + fallbackChildFragment.return = workInProgress; + primaryChildFragment.return = workInProgress; + primaryChildFragment.sibling = fallbackChildFragment; + workInProgress.child = primaryChildFragment; + return fallbackChildFragment; +} - return null; - } else { - // This is the second render. The surrounding visible content has already - // committed. Now we resume rendering the hidden tree. - // Rendering at offscreen, so we can clear the base lanes. - var _nextState2 = { - baseLanes: NoLanes, - cachePool: null - }; - workInProgress.memoizedState = _nextState2; // Push the lanes that were skipped when we bailed out. +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 - var subtreeRenderLanes = - prevState !== null ? prevState.baseLanes : renderLanes; + reconcileChildFibers(workInProgress, current.child, null, renderLanes); // We're now not suspended nor dehydrated. - pushRenderLanes(workInProgress, subtreeRenderLanes); - } - } else { - // Rendering a visible tree. - var _subtreeRenderLanes; + 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. - if (prevState !== null) { - // We're going from hidden -> visible. - _subtreeRenderLanes = mergeLanes(prevState.baseLanes, renderLanes); + primaryChildFragment.flags |= Placement; + workInProgress.memoizedState = null; + return primaryChildFragment; +} - workInProgress.memoizedState = null; - } else { - // We weren't previously hidden, and we still aren't, so there's nothing - // special to do. Need to push to the stack regardless, though, to avoid - // a push/pop misalignment. - _subtreeRenderLanes = renderLanes; - } +function 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. - pushRenderLanes(workInProgress, _subtreeRenderLanes); - } + fallbackChildFragment.flags |= Placement; + primaryChildFragment.return = workInProgress; + fallbackChildFragment.return = workInProgress; + primaryChildFragment.sibling = fallbackChildFragment; + workInProgress.child = primaryChildFragment; - { - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; + 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 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; + return fallbackChildFragment; } -function updateProfiler(current, workInProgress, renderLanes) { - { - workInProgress.flags |= Update; - +function mountDehydratedSuspenseComponent( + workInProgress, + suspenseInstance, + renderLanes +) { + // During the first pass, we'll bail out and not drill into the children. + // Instead, we'll leave the content in place and try to hydrate it later. + if ((workInProgress.mode & ConcurrentMode) === NoMode) { { - // 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; + error( + "Cannot hydrate Suspense in legacy mode. Switch from " + + "ReactDOM.hydrate(element, container) to " + + "ReactDOMClient.hydrateRoot(container, )" + + ".render(element) or remove the Suspense components from " + + "the server rendered components." + ); } - } - var nextProps = workInProgress.pendingProps; - var nextChildren = nextProps.children; - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; -} - -function markRef$1(current, workInProgress) { - var ref = workInProgress.ref; - - if ( - (current === null && ref !== null) || - (current !== null && current.ref !== ref) - ) { - // Schedule a Ref effect - workInProgress.flags |= Ref; + workInProgress.lanes = laneToLanes(SyncLane); + } else if (isSuspenseInstanceFallback()) { + // This is a client-only boundary. Since we won't get any content from the server + // for this, we need to schedule that at a higher priority based on when it would + // have timed out. In theory we could render it in this pass but it would have the + // wrong priority associated with it and will prevent hydration of parent path. + // Instead, we'll leave work left on it to render it in a separate commit. + // TODO This time should be the time at which the server rendered response that is + // a parent to this boundary was displayed. However, since we currently don't have + // a protocol to transfer that time, we'll just estimate it by using the current + // time. This will mean that Suspense timeouts are slightly shifted to later than + // they should be. + // Schedule a normal pri update to render this content. + workInProgress.lanes = laneToLanes(DefaultHydrationLane); + } else { + // We'll continue hydrating the rest at offscreen priority since we'll already + // be showing the right content coming from the server, it is no rush. + workInProgress.lanes = laneToLanes(OffscreenLane); } + + return null; } -function updateFunctionComponent( +function updateDehydratedSuspenseComponent( current, workInProgress, - Component, + didSuspend, nextProps, + suspenseInstance, + suspenseState, 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 (!didSuspend) { + if ((workInProgress.mode & ConcurrentMode) === NoMode) { + return retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, // TODO: When we delete legacy mode, we should make this error argument + // required — every concurrent mode path that causes hydration to + // de-opt to client rendering should have an error message. + null + ); + } - if (innerPropTypes) { - checkPropTypes( - innerPropTypes, - nextProps, // Resolved props - "prop", - getComponentNameFromType(Component) - ); - } + 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 _getSuspenseInstanceF = getSuspenseInstanceFallbackErrorDetails(), + errorMessage = _getSuspenseInstanceF.errorMessage; + + var error = errorMessage // eslint-disable-next-line react-internal/prod-error-codes + ? new Error(errorMessage) + : new Error( + "The server could not finish this Suspense boundary, likely " + + "due to an error during server rendering. Switched to " + + "client rendering." + ); + return retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, + error + ); } - } + // any context has changed, we need to treat is as if the input might have changed. - var context; + var hasContextChanged = includesSomeLane(renderLanes, current.childLanes); - { - var unmaskedContext = getUnmaskedContext(workInProgress, Component, true); - context = getMaskedContext(workInProgress, unmaskedContext); - } + 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(); - var nextChildren; - prepareToReadContext(workInProgress, renderLanes); + if (root !== null) { + var attemptHydrationAtLane = getBumpedLaneForHydration( + root, + renderLanes + ); - { - ReactCurrentOwner$1.current = workInProgress; - setIsRendering(true); - nextChildren = renderWithHooks( - current, - workInProgress, - Component, - nextProps, - context, - renderLanes - ); + if ( + attemptHydrationAtLane !== NoLane && + attemptHydrationAtLane !== suspenseState.retryLane + ) { + // Intentionally mutating since this render will get interrupted. This + // is one of the very rare times where we mutate the current tree + // during the render phase. + suspenseState.retryLane = attemptHydrationAtLane; // TODO: Ideally this would inherit the event time of the current render - setIsRendering(false); + var eventTime = NoTimestamp; + scheduleUpdateOnFiber(current, attemptHydrationAtLane, eventTime); + } + } // If we have scheduled higher pri work above, this will probably just abort the render + // since we now have higher priority work, but in case it doesn't, we need to prepare to + // render something, if we time out. Even if that requires us to delete everything and + // skip hydration. + // Delay having to do this as long as the suspense timeout allows us. + + renderDidSuspendDelayIfPossible(); + return retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, + new Error( + "This Suspense boundary received an update before it finished " + + "hydrating. This caused the boundary to switch to client rendering. " + + "The usual way to fix this is to wrap the original update " + + "in startTransition." + ) + ); + } else if (isSuspenseInstancePending()) { + // This component is still pending more data from the server, so we can't hydrate its + // content. We treat it as if this component suspended itself. It might seem as if + // we could just try to render it client-side instead. However, this will perform a + // lot of unnecessary work and is unlikely to complete since it often will suspend + // on missing data anyway. Additionally, the server might be able to render more + // than we can on the client yet. In that case we'd end up with more fallback states + // on the client than if we just leave it alone. If the server times out or errors + // these should update this boundary to the permanent Fallback state instead. + // Mark it as having captured (i.e. suspended). + workInProgress.flags |= DidCapture; // Leave the child in place. I.e. the dehydrated fragment. + + workInProgress.child = current.child; // Register a callback to retry this boundary once the server has sent the result. + + var retry = retryDehydratedSuspenseBoundary.bind(null, current); + registerSuspenseInstanceRetry(); + return null; + } else { + // This is the first attempt. + reenterHydrationStateFromDehydratedSuspenseInstance( + workInProgress, + suspenseInstance, + suspenseState.treeContext + ); + var primaryChildren = nextProps.children; + var primaryChildFragment = mountSuspensePrimaryChildren( + workInProgress, + primaryChildren + ); // Mark the children as hydrating. This is a fast path to know whether this + // tree is part of a hydrating tree. This is used to determine if a child + // node has fully mounted yet, and for scheduling event replaying. + // Conceptually this is similar to Placement in that a new subtree is + // inserted into the React tree here. It just happens to not need DOM + // mutations because it already exists. + + primaryChildFragment.flags |= Hydrating; + return primaryChildFragment; + } + } else { + // This is the second render pass. We already attempted to hydrated, but + // something either suspended or errored. + if (workInProgress.flags & ForceClientRender) { + // Something errored during hydration. Try again without hydrating. + workInProgress.flags &= ~ForceClientRender; + return retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, + new Error( + "There was an error while hydrating this Suspense boundary. " + + "Switched to client rendering." + ) + ); + } else if (workInProgress.memoizedState !== null) { + // Something suspended and we should still be in dehydrated mode. + // Leave the existing child in place. + workInProgress.child = current.child; // The dehydrated completion pass expects this flag to be there + // but the normal suspense pass doesn't. + + workInProgress.flags |= DidCapture; + return null; + } else { + // Suspended but we should no longer be in dehydrated mode. + // Therefore we now have to render the fallback. + var nextPrimaryChildren = nextProps.children; + var nextFallbackChildren = nextProps.fallback; + var fallbackChildFragment = mountSuspenseFallbackAfterRetryWithoutHydrating( + current, + workInProgress, + nextPrimaryChildren, + nextFallbackChildren, + renderLanes + ); + var _primaryChildFragment4 = workInProgress.child; + _primaryChildFragment4.memoizedState = mountSuspenseOffscreenState( + renderLanes + ); + workInProgress.memoizedState = SUSPENDED_MARKER; + return fallbackChildFragment; + } } +} - if (current !== null && !didReceiveUpdate) { - bailoutHooks(current, workInProgress, renderLanes); - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); +function scheduleSuspenseWorkOnFiber(fiber, renderLanes, propagationRoot) { + fiber.lanes = mergeLanes(fiber.lanes, renderLanes); + var alternate = fiber.alternate; + + if (alternate !== null) { + alternate.lanes = mergeLanes(alternate.lanes, renderLanes); } - workInProgress.flags |= PerformedWork; - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; + scheduleContextWorkOnParentPath(fiber.return, renderLanes, propagationRoot); } -function updateClassComponent( - current, +function propagateSuspenseContextChange( workInProgress, - Component, - nextProps, + firstChild, renderLanes ) { - { - // This is used by DevTools to force a boundary to error. - switch (shouldError(workInProgress)) { - case false: { - var _instance = workInProgress.stateNode; - var ctor = workInProgress.type; // TODO This way of resetting the error boundary state is a hack. - // Is there a better way to do this? - - var tempInstance = new ctor( - workInProgress.memoizedProps, - _instance.context - ); - var state = tempInstance.state; - - _instance.updater.enqueueSetState(_instance, state, null); - - break; - } - - case true: { - workInProgress.flags |= DidCapture; - workInProgress.flags |= ShouldCapture; // eslint-disable-next-line react-internal/prod-error-codes + // Mark any Suspense boundaries with fallbacks as having work to do. + // If they were previously forced into fallbacks, they may now be able + // to unblock. + var node = firstChild; - var 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 + while (node !== null) { + if (node.tag === SuspenseComponent) { + var state = node.memoizedState; - var update = createClassErrorUpdate( - workInProgress, - createCapturedValue(error$1, workInProgress), - lane - ); - enqueueCapturedUpdate(workInProgress, update); - break; + 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 (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 (node === workInProgress) { + return; + } - if (innerPropTypes) { - checkPropTypes( - innerPropTypes, - nextProps, // Resolved props - "prop", - getComponentNameFromType(Component) - ); + while (node.sibling === null) { + if (node.return === null || node.return === workInProgress) { + return; } - } - } // 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; + node = node.return; + } - if (isContextProvider(Component)) { - hasContext = true; - pushContextProvider(workInProgress); - } else { - hasContext = false; + node.sibling.return = node.return; + node = node.sibling; } +} - prepareToReadContext(workInProgress, renderLanes); - var instance = workInProgress.stateNode; - var shouldUpdate; +function findLastContentRow(firstChild) { + // This is going to find the last row among these children that is already + // showing content on the screen, as opposed to being in fallback state or + // new. If a row has multiple Suspense boundaries, any of them being in the + // fallback state, counts as the whole row being in a fallback state. + // Note that the "rows" will be workInProgress, but any nested children + // will still be current since we haven't rendered them yet. The mounted + // order may not be the same as the new order. We use the new order. + var row = firstChild; + var lastContentRow = null; - if (instance === null) { - if (current !== null) { - // A class component without an instance 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 + while (row !== null) { + var currentRow = row.alternate; // New rows can't be content rows. - workInProgress.flags |= Placement; - } // In the initial pass we might need to construct the instance. + if (currentRow !== null && findFirstSuspended(currentRow) === null) { + lastContentRow = row; + } - constructClassInstance(workInProgress, Component, nextProps); - mountClassInstance(workInProgress, Component, nextProps, renderLanes); - shouldUpdate = true; - } else if (current === null) { - // In a resume, we'll already have an instance we can reuse. - shouldUpdate = resumeMountClassInstance( - workInProgress, - Component, - nextProps, - renderLanes - ); - } else { - shouldUpdate = updateClassInstance( - current, - workInProgress, - Component, - nextProps, - renderLanes - ); + row = row.sibling; } - var nextUnitOfWork = finishClassComponent( - current, - workInProgress, - Component, - shouldUpdate, - hasContext, - renderLanes - ); + return lastContentRow; +} +function validateRevealOrder(revealOrder) { { - var inst = workInProgress.stateNode; + if ( + revealOrder !== undefined && + revealOrder !== "forwards" && + revealOrder !== "backwards" && + revealOrder !== "together" && + !didWarnAboutRevealOrder[revealOrder] + ) { + didWarnAboutRevealOrder[revealOrder] = true; - 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 (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() + ); - didWarnAboutReassigningProps = true; - } - } - - return nextUnitOfWork; -} - -function finishClassComponent( - current, - workInProgress, - Component, - shouldUpdate, - hasContext, - renderLanes -) { - // Refs should update even if shouldComponentUpdate returns false - markRef$1(current, workInProgress); - var didCaptureError = (workInProgress.flags & DidCapture) !== NoFlags; - - if (!shouldUpdate && !didCaptureError) { - // Context providers should defer to sCU for rendering - if (hasContext) { - invalidateContextProvider(workInProgress, Component, false); - } - - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); - } - - var instance = workInProgress.stateNode; // Rerender + break; + } - ReactCurrentOwner$1.current = workInProgress; - var nextChildren; + case "forward": + case "backward": { + error( + '"%s" is not a valid value for revealOrder on . ' + + 'React uses the -s suffix in the spelling. Use "%ss" instead.', + revealOrder, + revealOrder.toLowerCase() + ); - if ( - 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; + break; + } - { - stopProfilerTimerIfRunning(); - } - } else { - { - setIsRendering(true); - nextChildren = instance.render(); + default: + error( + '"%s" is not a supported revealOrder on . ' + + 'Did you mean "together", "forwards" or "backwards"?', + revealOrder + ); - setIsRendering(false); + break; + } + } else { + error( + "%s is not a supported value for revealOrder on . " + + 'Did you mean "together", "forwards" or "backwards"?', + revealOrder + ); + } } - } // React DevTools reads this flag. - - workInProgress.flags |= PerformedWork; - - if (current !== null && didCaptureError) { - // If we're recovering from an error, reconcile without reusing any of - // the existing children. Conceptually, the normal children and the children - // that are shown on error are two different sets, so we shouldn't reuse - // normal children even if their identities match. - forceUnmountCurrentAndReconcile( - current, - workInProgress, - nextChildren, - renderLanes - ); - } else { - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - } // Memoize state using the values we just used to render. - // TODO: Restructure so we never read values from the instance. - - workInProgress.memoizedState = instance.state; // The context might have changed so we need to recalculate it. - - if (hasContext) { - invalidateContextProvider(workInProgress, Component, true); } - - return workInProgress.child; } -function pushHostRootContext(workInProgress) { - var root = workInProgress.stateNode; +function validateTailOptions(tailMode, revealOrder) { + { + if (tailMode !== undefined && !didWarnAboutTailOptions[tailMode]) { + if (tailMode !== "collapsed" && tailMode !== "hidden") { + didWarnAboutTailOptions[tailMode] = true; - if (root.pendingContext) { - pushTopLevelContextObject( - workInProgress, - root.pendingContext, - root.pendingContext !== root.context - ); - } else if (root.context) { - // Should always be set - pushTopLevelContextObject(workInProgress, root.context, false); - } + 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; - pushHostContainer(workInProgress, root.containerInfo); + error( + ' is only valid if revealOrder is ' + + '"forwards" or "backwards". ' + + 'Did you mean to specify revealOrder="forwards"?', + tailMode + ); + } + } + } } -function updateHostRoot(current, workInProgress, renderLanes) { - pushHostRootContext(workInProgress); - - if (current === null) { - throw new Error("Should have a current fiber. This is a bug in React."); - } +function validateSuspenseListNestedChild(childSlot, index) { + { + var isAnArray = isArray(childSlot); + var isIterable = + !isAnArray && typeof getIteratorFn(childSlot) === "function"; - var nextProps = workInProgress.pendingProps; - var prevState = workInProgress.memoizedState; - var prevChildren = prevState.element; - cloneUpdateQueue(current, workInProgress); - processUpdateQueue(workInProgress, nextProps, null, renderLanes); - var nextState = workInProgress.memoizedState; - var root = workInProgress.stateNode; - // being called "element". + if (isAnArray || isIterable) { + var type = isAnArray ? "array" : "iterable"; - var nextChildren = nextState.element; + 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 (nextChildren === prevChildren) { - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); + return false; } - - reconcileChildren(current, workInProgress, nextChildren, renderLanes); } - return workInProgress.child; + return true; } -function updateHostComponent$1(current, workInProgress, renderLanes) { - pushHostContext(workInProgress); - - var type = workInProgress.type; - var nextProps = workInProgress.pendingProps; - var prevProps = current !== null ? current.memoizedProps : null; - var nextChildren = nextProps.children; +function validateSuspenseListChildren(children, revealOrder) { + { + if ( + (revealOrder === "forwards" || revealOrder === "backwards") && + children !== undefined && + children !== null && + children !== false + ) { + if (isArray(children)) { + for (var i = 0; i < children.length; i++) { + if (!validateSuspenseListNestedChild(children[i], i)) { + return; + } + } + } else { + var iteratorFn = getIteratorFn(children); - if (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; - } + if (typeof iteratorFn === "function") { + var childrenIterator = iteratorFn.call(children); - markRef$1(current, workInProgress); - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; -} + if (childrenIterator) { + var step = childrenIterator.next(); + var _i = 0; -function updateHostText$1(current, workInProgress) { - // immediately after. + for (; !step.done; step = childrenIterator.next()) { + if (!validateSuspenseListNestedChild(step.value, _i)) { + return; + } - return null; + _i++; + } + } + } else { + error( + 'A single row was passed to a . ' + + "This is not useful since it needs multiple rows. " + + "Did you mean to pass multiple children or an array?", + revealOrder + ); + } + } + } + } } -function mountLazyComponent( - _current, +function initSuspenseListRenderState( workInProgress, - elementType, - renderLanes + isBackwards, + tail, + lastContentRow, + tailMode ) { - 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 renderState = workInProgress.memoizedState; - workInProgress.flags |= Placement; + 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. - 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; +function updateSuspenseListComponent(current, workInProgress, renderLanes) { + var nextProps = workInProgress.pendingProps; + var revealOrder = nextProps.revealOrder; + var tailMode = nextProps.tail; + var newChildren = nextProps.children; + validateRevealOrder(revealOrder); + validateTailOptions(tailMode, revealOrder); + validateSuspenseListChildren(newChildren, revealOrder); + reconcileChildren(current, workInProgress, newChildren, renderLanes); + var suspenseContext = suspenseStackCursor.current; + var shouldForceFallback = hasSuspenseContext( + suspenseContext, + ForceSuspenseFallback + ); - switch (resolvedTag) { - case FunctionComponent: { - { - validateFunctionComponentInDev(workInProgress, Component); - workInProgress.type = Component = resolveFunctionForHotReloading( - Component - ); - } + if (shouldForceFallback) { + suspenseContext = setShallowSuspenseContext( + suspenseContext, + ForceSuspenseFallback + ); + workInProgress.flags |= DidCapture; + } else { + var didSuspendBefore = + current !== null && (current.flags & DidCapture) !== NoFlags; - child = updateFunctionComponent( - null, + 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, - Component, - resolvedProps, + workInProgress.child, renderLanes ); - return child; } - case ClassComponent: { - { - workInProgress.type = Component = resolveClassForHotReloading( - Component - ); - } + suspenseContext = setDefaultShallowSuspenseContext(suspenseContext); + } - child = updateClassComponent( - null, - workInProgress, - Component, - resolvedProps, - renderLanes - ); - return child; - } + pushSuspenseContext(workInProgress, suspenseContext); - case ForwardRef: { - { - workInProgress.type = Component = resolveForwardRefForHotReloading( - Component + if ((workInProgress.mode & ConcurrentMode) === NoMode) { + // In legacy mode, SuspenseList doesn't work so we just + // use make it a noop by treating it as the default revealOrder. + workInProgress.memoizedState = null; + } else { + switch (revealOrder) { + case "forwards": { + var lastContentRow = findLastContentRow(workInProgress.child); + var tail; + + if (lastContentRow === null) { + // The whole list is part of the tail. + // TODO: We could fast path by just rendering the tail now. + tail = workInProgress.child; + workInProgress.child = null; + } else { + // Disconnect the tail rows after the content row. + // We're going to render them separately later. + tail = lastContentRow.sibling; + lastContentRow.sibling = null; + } + + initSuspenseListRenderState( + workInProgress, + false, // isBackwards + tail, + lastContentRow, + tailMode ); + break; } - child = updateForwardRef( - null, - workInProgress, - Component, - resolvedProps, - renderLanes - ); - return child; - } + 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 MemoComponent: { - { - if (workInProgress.type !== workInProgress.elementType) { - var outerPropTypes = Component.propTypes; + while (row !== null) { + var currentRow = row.alternate; // New rows can't be content rows. - if (outerPropTypes) { - checkPropTypes( - outerPropTypes, - resolvedProps, // Resolved for outer only - "prop", - getComponentNameFromType(Component) - ); + if (currentRow !== null && findFirstSuspended(currentRow) === null) { + // This is the beginning of the main content. + workInProgress.child = row; + break; } - } - } - child = updateMemoComponent( - null, - workInProgress, - Component, - resolveDefaultProps(Component.type, resolvedProps), // The inner type can have defaults too - renderLanes - ); - return child; - } - } + var nextRow = row.sibling; + row.sibling = _tail; + _tail = row; + row = nextRow; + } // TODO: If workInProgress.child is null, we can continue on the tail immediately. - var hint = ""; + initSuspenseListRenderState( + workInProgress, + true, // isBackwards + _tail, + null, // last + tailMode + ); + break; + } - { - if ( - Component !== null && - typeof Component === "object" && - Component.$$typeof === REACT_LAZY_TYPE - ) { - hint = " Did you wrap a component in React.lazy() more than once?"; + 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; + } } - } // This message intentionally doesn't mention ForwardRef or MemoComponent - // because the fact that it's a separate type of work is an - // implementation detail. + } - throw new Error( - "Element type is invalid. Received a promise that resolves to: " + - Component + - ". " + - ("Lazy element type must resolve to a class or function." + hint) - ); + return workInProgress.child; } -function mountIncompleteClassComponent( - _current, - workInProgress, - Component, - nextProps, - renderLanes -) { - if (_current !== null) { - // An incomplete component only mounts if it suspended inside a non- - // concurrent tree, in an inconsistent state. We want to treat it like - // a new mount, even though an empty version of it already committed. - // Disconnect the alternate pointers. - _current.alternate = null; - workInProgress.alternate = null; // Since this is conceptually a new fiber, schedule a Placement effect - - workInProgress.flags |= Placement; - } // Promote the fiber to a class and try rendering again. - - workInProgress.tag = ClassComponent; // The rest of this function is a fork of `updateClassComponent` - // Push context providers early to prevent context stack mismatches. - // During mounting we don't know the child context yet as the instance doesn't exist. - // We will invalidate the child context in finishClassComponent() right after rendering. - - var hasContext; +function updatePortalComponent(current, workInProgress, renderLanes) { + pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); + var nextChildren = workInProgress.pendingProps; - if (isContextProvider(Component)) { - hasContext = true; - pushContextProvider(workInProgress); + 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 { - hasContext = false; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); } - prepareToReadContext(workInProgress, renderLanes); - constructClassInstance(workInProgress, Component, nextProps); - mountClassInstance(workInProgress, Component, nextProps, renderLanes); - return finishClassComponent( - null, - workInProgress, - Component, - true, - hasContext, - renderLanes - ); + return workInProgress.child; } -function mountIndeterminateComponent( - _current, - workInProgress, - Component, - renderLanes -) { - if (_current !== null) { - // An indeterminate component only mounts if it suspended inside a non- - // concurrent tree, in an inconsistent state. We want to treat it like - // a new mount, even though an empty version of it already committed. - // Disconnect the alternate pointers. - _current.alternate = null; - workInProgress.alternate = null; // Since this is conceptually a new fiber, schedule a Placement effect - - workInProgress.flags |= Placement; - } - - var props = workInProgress.pendingProps; - var context; - - { - var unmaskedContext = getUnmaskedContext(workInProgress, Component, false); - context = getMaskedContext(workInProgress, unmaskedContext); - } +var hasWarnedAboutUsingNoValuePropOnContextProvider = false; - prepareToReadContext(workInProgress, renderLanes); - var value; +function updateContextProvider(current, workInProgress, renderLanes) { + var providerType = workInProgress.type; + var context = providerType._context; + var newProps = workInProgress.pendingProps; + var oldProps = workInProgress.memoizedProps; + var newValue = newProps.value; { - if ( - Component.prototype && - typeof Component.prototype.render === "function" - ) { - var componentName = getComponentNameFromType(Component) || "Unknown"; + if (!("value" in newProps)) { + if (!hasWarnedAboutUsingNoValuePropOnContextProvider) { + hasWarnedAboutUsingNoValuePropOnContextProvider = true; - 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 + "The `value` prop is required for the ``. Did you misspell it or forget to pass it?" ); - - didWarnAboutBadClass[componentName] = true; } } - if (workInProgress.mode & StrictLegacyMode) { - ReactStrictModeWarnings.recordLegacyContextWarning(workInProgress, null); - } + var providerPropTypes = workInProgress.type.propTypes; - setIsRendering(true); - ReactCurrentOwner$1.current = workInProgress; - value = renderWithHooks( - null, - workInProgress, - Component, - props, - context, - renderLanes - ); - setIsRendering(false); + if (providerPropTypes) { + checkPropTypes(providerPropTypes, newProps, "prop", "Context.Provider"); + } } - workInProgress.flags |= PerformedWork; + pushProvider(workInProgress, context, newValue); { - // 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 - ); + if (oldProps !== null) { + var oldValue = oldProps.value; - didWarnAboutModulePatternComponent[_componentName] = true; + if (objectIs(oldValue, newValue)) { + // No change. Bailout early if children are the same. + if (oldProps.children === newProps.children && !hasContextChanged()) { + return bailoutOnAlreadyFinishedWork( + current, + workInProgress, + renderLanes + ); + } + } else { + // The context value changed. Search for matching consumers and schedule + // them to update. + propagateContextChange(workInProgress, context, renderLanes); } } } - if ( - // 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 + var newChildren = newProps.children; + reconcileChildren(current, workInProgress, newChildren, renderLanes); + return workInProgress.child; +} - workInProgress.tag = ClassComponent; // Throw out any hooks that were used. +var hasWarnedAboutUsingContextAsConsumer = false; - workInProgress.memoizedState = null; - workInProgress.updateQueue = null; // Push context providers early to prevent context stack mismatches. - // During mounting we don't know the child context yet as the instance doesn't exist. - // We will invalidate the child context in finishClassComponent() right after rendering. +function updateContextConsumer(current, workInProgress, renderLanes) { + var context = workInProgress.type; // The logic below for Context differs depending on PROD or DEV mode. In + // DEV mode, we create a separate object for Context.Consumer that acts + // like a proxy to Context. This proxy object adds unnecessary code in PROD + // so we use the old behaviour (Context.Consumer references Context) to + // reduce size and overhead. The separate object references context via + // a property called "_context", which also gives us the ability to check + // in DEV mode if this property exists or not and warn if it does not. - var hasContext = false; + { + if (context._context === undefined) { + // This may be because it's a Context (rather than a Consumer). + // Or it may be because it's older React where they're the same thing. + // We only want to warn if we're sure it's a new React. + if (context !== context.Consumer) { + if (!hasWarnedAboutUsingContextAsConsumer) { + hasWarnedAboutUsingContextAsConsumer = true; - if (isContextProvider(Component)) { - hasContext = true; - pushContextProvider(workInProgress); + error( + "Rendering directly is not supported and will be removed in " + + "a future major release. Did you mean to render instead?" + ); + } + } } else { - hasContext = false; + context = context._context; } + } - 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); + var newProps = workInProgress.pendingProps; + var render = newProps.children; - { - validateFunctionComponentInDev(workInProgress, Component); + { + if (typeof render !== "function") { + error( + "A context consumer was rendered with multiple children, or a child " + + "that isn't a function. A context consumer expects a single child " + + "that is a function. If you did pass a function, make sure there " + + "is no trailing or leading whitespace around it." + ); } - - 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" - ); - } - } + prepareToReadContext(workInProgress, renderLanes); + var newValue = readContext(context); - if (workInProgress.ref !== null) { - var info = ""; - var ownerName = getCurrentFiberOwnerNameInDevOrNull(); + var newChildren; - if (ownerName) { - info += "\n\nCheck the render method of `" + ownerName + "`."; - } + { + ReactCurrentOwner$1.current = workInProgress; + setIsRendering(true); + newChildren = render(newValue); + setIsRendering(false); + } - var warningKey = ownerName || ""; - var debugSource = workInProgress._debugSource; + workInProgress.flags |= PerformedWork; + reconcileChildren(current, workInProgress, newChildren, renderLanes); + return workInProgress.child; +} - if (debugSource) { - warningKey = debugSource.fileName + ":" + debugSource.lineNumber; - } +function markWorkInProgressReceivedUpdate() { + didReceiveUpdate = true; +} - if (!didWarnAboutFunctionRefs[warningKey]) { - didWarnAboutFunctionRefs[warningKey] = true; +function resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress) { + if ((workInProgress.mode & ConcurrentMode) === NoMode) { + if (current !== null) { + // A lazy component only mounts if it suspended inside a non- + // concurrent tree, in an inconsistent state. We want to treat it like + // a new mount, even though an empty version of it already committed. + // Disconnect the alternate pointers. + current.alternate = null; + workInProgress.alternate = null; // Since this is conceptually a new fiber, schedule a Placement effect - error( - "Function components cannot be given refs. " + - "Attempts to access this ref will fail. " + - "Did you mean to use React.forwardRef()?%s", - info - ); - } + workInProgress.flags |= Placement; } + } +} - if (typeof Component.getDerivedStateFromProps === "function") { - var _componentName3 = getComponentNameFromType(Component) || "Unknown"; +function bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) { + if (current !== null) { + // Reuse previous dependencies + workInProgress.dependencies = current.dependencies; + } - if (!didWarnAboutGetDerivedStateOnFunctionComponent[_componentName3]) { - error( - "%s: Function components do not support getDerivedStateFromProps.", - _componentName3 - ); + { + // Don't update "base" render times for bailouts. + stopProfilerTimerIfRunning(); + } - didWarnAboutGetDerivedStateOnFunctionComponent[_componentName3] = true; - } + 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. - if ( - typeof Component.contextType === "object" && - Component.contextType !== null - ) { - var _componentName4 = getComponentNameFromType(Component) || "Unknown"; + cloneChildFibers(current, workInProgress); + return workInProgress.child; +} - if (!didWarnAboutContextTypeOnFunctionComponent[_componentName4]) { - error( - "%s: Function components do not support contextType.", - _componentName4 - ); +function remountFiber(current, oldWorkInProgress, newWorkInProgress) { + { + var returnFiber = oldWorkInProgress.return; - didWarnAboutContextTypeOnFunctionComponent[_componentName4] = true; + if (returnFiber === null) { + // eslint-disable-next-line react-internal/prod-error-codes + throw new Error("Cannot swap the root fiber."); + } // Disconnect from the old current. + // It will get deleted. + + current.alternate = null; + oldWorkInProgress.alternate = null; // Connect to the new tree. + + newWorkInProgress.index = oldWorkInProgress.index; + newWorkInProgress.sibling = oldWorkInProgress.sibling; + newWorkInProgress.return = oldWorkInProgress.return; + newWorkInProgress.ref = oldWorkInProgress.ref; // Replace the child/sibling pointers above it. + + if (oldWorkInProgress === returnFiber.child) { + returnFiber.child = newWorkInProgress; + } else { + var prevSibling = returnFiber.child; + + if (prevSibling === null) { + // eslint-disable-next-line react-internal/prod-error-codes + throw new Error("Expected parent to have a child."); + } + + while (prevSibling.sibling !== oldWorkInProgress) { + prevSibling = prevSibling.sibling; + + if (prevSibling === null) { + // eslint-disable-next-line react-internal/prod-error-codes + throw new Error("Expected to find the previous sibling."); + } } + + prevSibling.sibling = newWorkInProgress; + } // Delete the old fiber and place the new one. + // Since the old fiber is disconnected, we have to schedule it manually. + + var deletions = returnFiber.deletions; + + if (deletions === null) { + returnFiber.deletions = [current]; + returnFiber.flags |= ChildDeletion; + } else { + deletions.push(current); } - } -} -var SUSPENDED_MARKER = { - dehydrated: null, - treeContext: null, - retryLane: NoLane -}; + newWorkInProgress.flags |= Placement; // Restart work from the new fiber. -function mountSuspenseOffscreenState(renderLanes) { - return { - baseLanes: renderLanes, - cachePool: getSuspendedCache() - }; + return newWorkInProgress; + } } -function updateSuspenseOffscreenState(prevOffscreenState, renderLanes) { - var cachePool = null; +function checkScheduledUpdateOrContext(current, renderLanes) { + // Before performing an early bailout, we must check if there are pending + // updates or context. + var updateLanes = current.lanes; - return { - baseLanes: mergeLanes(prevOffscreenState.baseLanes, renderLanes), - cachePool: cachePool - }; -} // TODO: Probably should inline this back + if (includesSomeLane(updateLanes, renderLanes)) { + return true; + } // No pending update, but because context is propagated lazily, we need -function shouldRemainOnFallback( - suspenseContext, + return false; +} + +function attemptEarlyBailoutIfNoScheduledUpdate( current, workInProgress, renderLanes ) { - // If we're already showing a fallback, there are cases where we need to - // remain on that fallback regardless of whether the content has resolved. - // For example, SuspenseList coordinates when nested content appears. - if (current !== null) { - var suspenseState = current.memoizedState; - - if (suspenseState === null) { - // Currently showing content. Don't hide it, even if ForceSuspenseFallback - // is true. More precise name might be "ForceRemainSuspenseFallback". - // Note: This is a factoring smell. Can't remain on a fallback if there's - // no fallback to remain on. - return false; - } - } // Not currently showing content. Consult the Suspense context. + // This fiber does not have any pending work. Bailout without entering + // the begin phase. There's still some bookkeeping we that needs to be done + // in this optimized path, mostly pushing stuff onto the stack. + switch (workInProgress.tag) { + case HostRoot: + pushHostRootContext(workInProgress); + var root = workInProgress.stateNode; + break; - return hasSuspenseContext(suspenseContext, ForceSuspenseFallback); -} + case HostComponent: + pushHostContext(workInProgress); + break; -function getRemainingWorkInPrimaryTree(current, renderLanes) { - // TODO: Should not remove render lanes that were pinged during this render - return removeLanes(current.childLanes, renderLanes); -} + case ClassComponent: { + var Component = workInProgress.type; -function updateSuspenseComponent(current, workInProgress, renderLanes) { - var nextProps = workInProgress.pendingProps; // This is used by DevTools to force a boundary to suspend. + if (isContextProvider(Component)) { + pushContextProvider(workInProgress); + } - { - if (shouldSuspend(workInProgress)) { - workInProgress.flags |= DidCapture; + break; } - } - var suspenseContext = suspenseStackCursor.current; - var showFallback = false; - var didSuspend = (workInProgress.flags & DidCapture) !== NoFlags; + case HostPortal: + pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); + break; - if (didSuspend || shouldRemainOnFallback(suspenseContext, current)) { - // Something in this boundary's subtree already suspended. Switch to - // rendering the fallback children. - showFallback = true; - workInProgress.flags &= ~DidCapture; - } else { - // Attempting the main content - if (current === null || current.memoizedState !== null) { - // This is a new mount or this boundary is already showing a fallback state. - // Mark this subtree context as having at least one invisible parent that could - // handle the fallback state. - // Avoided boundaries are not considered since they cannot handle preferred fallback states. + case ContextProvider: { + var newValue = workInProgress.memoizedProps.value; + var context = workInProgress.type._context; + pushProvider(workInProgress, context, newValue); + break; + } + + case Profiler: { - suspenseContext = addSubtreeSuspenseContext( - suspenseContext, - InvisibleParentSuspenseContext + // Profiler should only call onRender when one of its descendants actually rendered. + var hasChildWork = includesSomeLane( + renderLanes, + workInProgress.childLanes ); + + if (hasChildWork) { + workInProgress.flags |= Update; + } + + { + // Reset effect durations for the next eventual effect phase. + // These are reset during render to allow the DevTools commit hook a chance to read them, + var stateNode = workInProgress.stateNode; + stateNode.effectDuration = 0; + stateNode.passiveEffectDuration = 0; + } } - } - } - suspenseContext = setDefaultShallowSuspenseContext(suspenseContext); - pushSuspenseContext(workInProgress, suspenseContext); // OK, the next part is confusing. We're about to reconcile the Suspense - // boundary's children. This involves some custom reconciliation logic. Two - // main reasons this is so complicated. - // - // First, Legacy Mode has different semantics for backwards compatibility. The - // primary tree will commit in an inconsistent state, so when we do the - // second pass to render the fallback, we do some exceedingly, uh, clever - // hacks to make that not totally break. Like transferring effects and - // deletions from hidden tree. In Concurrent Mode, it's much simpler, - // because we bailout on the primary tree completely and leave it in its old - // state, no effects. Same as what we do for Offscreen (except that - // Offscreen doesn't have the first render pass). - // - // Second is hydration. During hydration, the Suspense fiber has a slightly - // different layout, where the child points to a dehydrated fragment, which - // contains the DOM rendered by the server. - // - // Third, even if you set all that aside, Suspense is like error boundaries in - // that we first we try to render one tree, and if that fails, we render again - // and switch to a different tree. Like a try/catch block. So we have to track - // which branch we're currently rendering. Ideally we would model this using - // a stack. + break; - if (current === null) { - var nextPrimaryChildren = nextProps.children; - var nextFallbackChildren = nextProps.fallback; + case SuspenseComponent: { + var state = workInProgress.memoizedState; - if (showFallback) { - var fallbackFragment = mountSuspenseFallbackChildren( - workInProgress, - nextPrimaryChildren, - nextFallbackChildren, - renderLanes - ); - var primaryChildFragment = workInProgress.child; - primaryChildFragment.memoizedState = mountSuspenseOffscreenState( - renderLanes - ); - workInProgress.memoizedState = SUSPENDED_MARKER; - return fallbackFragment; - } else { - return mountSuspensePrimaryChildren(workInProgress, nextPrimaryChildren); - } - } else { - // This is an update. - // If the current fiber has a SuspenseState, that means it's already showing - // a fallback. - var prevState = current.memoizedState; + if (state !== null) { + if (state.dehydrated !== null) { + pushSuspenseContext( + workInProgress, + setDefaultShallowSuspenseContext(suspenseStackCursor.current) + ); // We know that this component will suspend again because if it has + // been unsuspended it has committed as a resolved Suspense component. + // If it needs to be retried, it should have work scheduled on it. - if (prevState !== null) { - if (showFallback) { - var _nextFallbackChildren2 = nextProps.fallback; - var _nextPrimaryChildren2 = nextProps.children; + workInProgress.flags |= DidCapture; // We should never render the children of a dehydrated boundary until we + // upgrade it. We return null instead of bailoutOnAlreadyFinishedWork. - var _fallbackChildFragment = updateSuspenseFallbackChildren( - current, - workInProgress, - _nextPrimaryChildren2, - _nextFallbackChildren2, - renderLanes - ); - - var _primaryChildFragment3 = workInProgress.child; - var prevOffscreenState = current.child.memoizedState; - _primaryChildFragment3.memoizedState = - prevOffscreenState === null - ? mountSuspenseOffscreenState(renderLanes) - : updateSuspenseOffscreenState(prevOffscreenState, renderLanes); - _primaryChildFragment3.childLanes = getRemainingWorkInPrimaryTree( - current, - renderLanes - ); - workInProgress.memoizedState = SUSPENDED_MARKER; - return _fallbackChildFragment; - } else { - var _nextPrimaryChildren3 = nextProps.children; - - var _primaryChildFragment4 = updateSuspensePrimaryChildren( - current, - workInProgress, - _nextPrimaryChildren3, - renderLanes - ); + return null; + } // If this boundary is currently timed out, we need to decide + // whether to retry the primary children, or to skip over it and + // go straight to the fallback. Check the priority of the primary + // child fragment. - workInProgress.memoizedState = null; - return _primaryChildFragment4; - } - } else { - // The current tree is not already showing a fallback. - if (showFallback) { - // Timed out. - var _nextFallbackChildren3 = nextProps.fallback; - var _nextPrimaryChildren4 = nextProps.children; + var primaryChildFragment = workInProgress.child; + var primaryChildLanes = primaryChildFragment.childLanes; - var _fallbackChildFragment2 = updateSuspenseFallbackChildren( - current, - workInProgress, - _nextPrimaryChildren4, - _nextFallbackChildren3, - renderLanes - ); + if (includesSomeLane(renderLanes, primaryChildLanes)) { + // The primary children have pending work. Use the normal path + // to attempt to render the primary children again. + return updateSuspenseComponent(current, workInProgress, renderLanes); + } else { + // The primary child fragment does not have pending work marked + // on it + pushSuspenseContext( + workInProgress, + setDefaultShallowSuspenseContext(suspenseStackCursor.current) + ); // The primary children do not have pending work with sufficient + // priority. Bailout. - var _primaryChildFragment5 = workInProgress.child; - var _prevOffscreenState = current.child.memoizedState; - _primaryChildFragment5.memoizedState = - _prevOffscreenState === null - ? mountSuspenseOffscreenState(renderLanes) - : updateSuspenseOffscreenState(_prevOffscreenState, renderLanes); - _primaryChildFragment5.childLanes = getRemainingWorkInPrimaryTree( - current, - renderLanes - ); // Skip the primary children, and continue working on the - // fallback children. + var child = bailoutOnAlreadyFinishedWork( + current, + workInProgress, + renderLanes + ); - workInProgress.memoizedState = SUSPENDED_MARKER; - return _fallbackChildFragment2; + 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 { - // Still haven't timed out. Continue rendering the children, like we - // normally do. - var _nextPrimaryChildren5 = nextProps.children; - - var _primaryChildFragment6 = updateSuspensePrimaryChildren( - current, + pushSuspenseContext( workInProgress, - _nextPrimaryChildren5, - renderLanes + setDefaultShallowSuspenseContext(suspenseStackCursor.current) ); - - workInProgress.memoizedState = null; - return _primaryChildFragment6; } - } - } -} -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; -} + break; + } -function mountSuspenseFallbackChildren( - workInProgress, - primaryChildren, - fallbackChildren, - renderLanes -) { - var mode = workInProgress.mode; - var progressedPrimaryFragment = workInProgress.child; - var primaryChildProps = { - mode: "hidden", - children: primaryChildren - }; - var primaryChildFragment; - var fallbackChildFragment; + case SuspenseListComponent: { + var didSuspendBefore = (current.flags & DidCapture) !== NoFlags; - 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; + var _hasChildWork = includesSomeLane( + renderLanes, + workInProgress.childLanes + ); - if (workInProgress.mode & ProfileMode) { - // Reset the durations from the first pass so they aren't included in the - // final amounts. This seems counterintuitive, since we're intentionally - // not measuring part of the render phase, but this makes it match what we - // do in Concurrent Mode. - primaryChildFragment.actualDuration = 0; - primaryChildFragment.actualStartTime = -1; - primaryChildFragment.selfBaseDuration = 0; - primaryChildFragment.treeBaseDuration = 0; - } + if (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. - fallbackChildFragment = createFiberFromFragment( - fallbackChildren, - mode, - renderLanes, - null - ); - } else { - primaryChildFragment = mountWorkInProgressOffscreenFiber( - primaryChildProps, - mode - ); - fallbackChildFragment = createFiberFromFragment( - fallbackChildren, - mode, - renderLanes, - null - ); - } + workInProgress.flags |= DidCapture; + } // If nothing suspended before and we're rendering the same children, + // then the tail doesn't matter. Anything new that suspends will work + // in the "together" mode, so we can continue from the state we had. - primaryChildFragment.return = workInProgress; - fallbackChildFragment.return = workInProgress; - primaryChildFragment.sibling = fallbackChildFragment; - workInProgress.child = primaryChildFragment; - return fallbackChildFragment; -} + var renderState = workInProgress.memoizedState; -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); -} + 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; + } -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); -} + pushSuspenseContext(workInProgress, suspenseStackCursor.current); -function updateSuspensePrimaryChildren( - current, - workInProgress, - primaryChildren, - renderLanes -) { - var currentPrimaryChildFragment = current.child; - var currentFallbackChildFragment = currentPrimaryChildFragment.sibling; - var primaryChildFragment = updateWorkInProgressOffscreenFiber( - currentPrimaryChildFragment, - { - mode: "visible", - children: primaryChildren + if (_hasChildWork) { + break; + } else { + // If none of the children had any work, that means that none of + // them got retried so they'll still be blocked in the same way + // as before. We can fast bail out. + return null; + } } - ); - if ((workInProgress.mode & ConcurrentMode) === NoMode) { - primaryChildFragment.lanes = renderLanes; + 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); + } } - primaryChildFragment.return = workInProgress; - primaryChildFragment.sibling = null; - - if (currentFallbackChildFragment !== null) { - // Delete the fallback child fragment - var deletions = workInProgress.deletions; + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); +} - if (deletions === null) { - workInProgress.deletions = [currentFallbackChildFragment]; - workInProgress.flags |= ChildDeletion; - } else { - deletions.push(currentFallbackChildFragment); +function beginWork(current, workInProgress, renderLanes) { + { + if (workInProgress._debugNeedsRemount && current !== null) { + // This will restart the begin phase with a new fiber. + return remountFiber( + current, + workInProgress, + createFiberFromTypeAndProps( + workInProgress.type, + workInProgress.key, + workInProgress.pendingProps, + workInProgress._debugOwner || null, + workInProgress.mode, + workInProgress.lanes + ) + ); } } - workInProgress.child = primaryChildFragment; - return primaryChildFragment; -} + if (current !== null) { + var oldProps = current.memoizedProps; + var newProps = workInProgress.pendingProps; -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 ( + oldProps !== newProps || + hasContextChanged() || // Force a re-render if the implementation changed due to hot reload: + workInProgress.type !== current.type + ) { + // If props or context changed, mark the fiber as having performed work. + // This may be unset if the props are determined to be equal later (memo). + didReceiveUpdate = true; + } else { + // Neither props nor legacy context changes. Check if there's a pending + // update or context change. + var hasScheduledUpdateOrContext = checkScheduledUpdateOrContext( + current, + renderLanes + ); - if ( - // In legacy mode, we commit the primary tree as if it successfully - // completed, even though it's in an inconsistent state. - (mode & ConcurrentMode) === NoMode && // Make sure we're on the second pass, i.e. the primary child fragment was - // already cloned. In legacy mode, the only case where this isn't true is - // when DevTools forces us to display a fallback; we skip the first render - // pass entirely and go straight to rendering the fallback. (In Concurrent - // Mode, SuspenseList can also trigger this scenario, but this is a legacy- - // only codepath.) - workInProgress.child !== currentPrimaryChildFragment - ) { - var progressedPrimaryFragment = workInProgress.child; - primaryChildFragment = progressedPrimaryFragment; - primaryChildFragment.childLanes = NoLanes; - primaryChildFragment.pendingProps = primaryChildProps; + if ( + !hasScheduledUpdateOrContext && // If this is the second pass of an error or suspense boundary, there + // may not be work scheduled on `current`, so we check for this flag. + (workInProgress.flags & DidCapture) === NoFlags + ) { + // No pending updates or context. Bail out now. + didReceiveUpdate = false; + return attemptEarlyBailoutIfNoScheduledUpdate( + current, + workInProgress, + renderLanes + ); + } - if (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; + if ((current.flags & ForceUpdateForLegacySuspense) !== NoFlags) { + // This is a special case that only exists for legacy mode. + // See https://github.com/facebook/react/pull/19216. + didReceiveUpdate = true; + } else { + // An update was scheduled on this fiber, but there are no new props + // nor legacy context. Set this to false. If an update queue or context + // consumer produces a changed value, it will set this to true. Otherwise, + // the component will assume the children have not changed and bail out. + didReceiveUpdate = false; + } } - // However, since we're going to remain on the fallback, we no longer want - // to delete it. - - workInProgress.deletions = null; } else { - primaryChildFragment = updateWorkInProgressOffscreenFiber( - currentPrimaryChildFragment, - primaryChildProps - ); - // (We don't do this in legacy mode, because in legacy mode we don't re-use - // the current tree; see previous branch.) + 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. - primaryChildFragment.subtreeFlags = - currentPrimaryChildFragment.subtreeFlags & StaticMask; - } + workInProgress.lanes = NoLanes; - var fallbackChildFragment; + switch (workInProgress.tag) { + case IndeterminateComponent: { + return mountIndeterminateComponent( + current, + workInProgress, + workInProgress.type, + renderLanes + ); + } - 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. + case LazyComponent: { + var elementType = workInProgress.elementType; + return mountLazyComponent( + current, + workInProgress, + elementType, + renderLanes + ); + } + + 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 + ); + } - fallbackChildFragment.flags |= Placement; - } + case ClassComponent: { + var _Component = workInProgress.type; + var _unresolvedProps = workInProgress.pendingProps; - fallbackChildFragment.return = workInProgress; - primaryChildFragment.return = workInProgress; - primaryChildFragment.sibling = fallbackChildFragment; - workInProgress.child = primaryChildFragment; - return fallbackChildFragment; -} + var _resolvedProps = + workInProgress.elementType === _Component + ? _unresolvedProps + : resolveDefaultProps(_Component, _unresolvedProps); -function scheduleSuspenseWorkOnFiber(fiber, renderLanes, propagationRoot) { - fiber.lanes = mergeLanes(fiber.lanes, renderLanes); - var alternate = fiber.alternate; + return updateClassComponent( + current, + workInProgress, + _Component, + _resolvedProps, + renderLanes + ); + } - if (alternate !== null) { - alternate.lanes = mergeLanes(alternate.lanes, renderLanes); - } + case HostRoot: + return updateHostRoot(current, workInProgress, renderLanes); - scheduleContextWorkOnParentPath(fiber.return, renderLanes, propagationRoot); -} + case HostComponent: + return updateHostComponent(current, workInProgress, renderLanes); -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; + case HostText: + return updateHostText(); - while (node !== null) { - if (node.tag === SuspenseComponent) { - var state = node.memoizedState; + case SuspenseComponent: + return updateSuspenseComponent(current, workInProgress, renderLanes); - 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; - } + case HostPortal: + return updatePortalComponent(current, workInProgress, renderLanes); - if (node === workInProgress) { - return; - } + case ForwardRef: { + var type = workInProgress.type; + var _unresolvedProps2 = workInProgress.pendingProps; - while (node.sibling === null) { - if (node.return === null || node.return === workInProgress) { - return; - } + var _resolvedProps2 = + workInProgress.elementType === type + ? _unresolvedProps2 + : resolveDefaultProps(type, _unresolvedProps2); - node = node.return; + return updateForwardRef( + current, + workInProgress, + type, + _resolvedProps2, + renderLanes + ); } - node.sibling.return = node.return; - node = node.sibling; - } -} + case Fragment: + return updateFragment(current, workInProgress, renderLanes); -function findLastContentRow(firstChild) { - // This is going to find the last row among these children that is already - // showing content on the screen, as opposed to being in fallback state or - // new. If a row has multiple Suspense boundaries, any of them being in the - // fallback state, counts as the whole row being in a fallback state. - // Note that the "rows" will be workInProgress, but any nested children - // will still be current since we haven't rendered them yet. The mounted - // order may not be the same as the new order. We use the new order. - var row = firstChild; - var lastContentRow = null; + case Mode: + return updateMode(current, workInProgress, renderLanes); - while (row !== null) { - var currentRow = row.alternate; // New rows can't be content rows. + case Profiler: + return updateProfiler(current, workInProgress, renderLanes); - if (currentRow !== null && findFirstSuspended(currentRow) === null) { - lastContentRow = row; - } + case ContextProvider: + return updateContextProvider(current, workInProgress, renderLanes); - row = row.sibling; - } + case ContextConsumer: + return updateContextConsumer(current, workInProgress, renderLanes); - return lastContentRow; -} + case MemoComponent: { + var _type2 = workInProgress.type; + var _unresolvedProps3 = workInProgress.pendingProps; // Resolve outer props first, then resolve inner props. -function validateRevealOrder(revealOrder) { - { - if ( - revealOrder !== undefined && - revealOrder !== "forwards" && - revealOrder !== "backwards" && - revealOrder !== "together" && - !didWarnAboutRevealOrder[revealOrder] - ) { - didWarnAboutRevealOrder[revealOrder] = true; + var _resolvedProps3 = resolveDefaultProps(_type2, _unresolvedProps3); - 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 (workInProgress.type !== workInProgress.elementType) { + var outerPropTypes = _type2.propTypes; - break; + if (outerPropTypes) { + checkPropTypes( + outerPropTypes, + _resolvedProps3, // Resolved for outer only + "prop", + getComponentNameFromType(_type2) + ); } + } + } - 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() - ); + _resolvedProps3 = resolveDefaultProps(_type2.type, _resolvedProps3); + return updateMemoComponent( + current, + workInProgress, + _type2, + _resolvedProps3, + renderLanes + ); + } - break; - } + case SimpleMemoComponent: { + return updateSimpleMemoComponent( + current, + workInProgress, + workInProgress.type, + workInProgress.pendingProps, + renderLanes + ); + } - default: - error( - '"%s" is not a supported revealOrder on . ' + - 'Did you mean "together", "forwards" or "backwards"?', - revealOrder - ); + case IncompleteClassComponent: { + var _Component2 = workInProgress.type; + var _unresolvedProps4 = workInProgress.pendingProps; - break; - } - } else { - error( - "%s is not a supported value for revealOrder on . " + - 'Did you mean "together", "forwards" or "backwards"?', - revealOrder - ); - } + var _resolvedProps4 = + workInProgress.elementType === _Component2 + ? _unresolvedProps4 + : resolveDefaultProps(_Component2, _unresolvedProps4); + + return mountIncompleteClassComponent( + current, + workInProgress, + _Component2, + _resolvedProps4, + renderLanes + ); } - } -} -function validateTailOptions(tailMode, revealOrder) { - { - if (tailMode !== undefined && !didWarnAboutTailOptions[tailMode]) { - if (tailMode !== "collapsed" && tailMode !== "hidden") { - didWarnAboutTailOptions[tailMode] = true; + case SuspenseListComponent: { + return updateSuspenseListComponent(current, workInProgress, renderLanes); + } - error( - '"%s" is not a supported value for tail on . ' + - 'Did you mean "collapsed" or "hidden"?', - tailMode - ); - } else if (revealOrder !== "forwards" && revealOrder !== "backwards") { - didWarnAboutTailOptions[tailMode] = true; + case ScopeComponent: { + break; + } - error( - ' is only valid if revealOrder is ' + - '"forwards" or "backwards". ' + - 'Did you mean to specify revealOrder="forwards"?', - tailMode - ); - } + case OffscreenComponent: { + return updateOffscreenComponent(current, workInProgress, renderLanes); } } + + throw new Error( + "Unknown unit of work tag (" + + workInProgress.tag + + "). This error is likely caused by a bug in " + + "React. Please file an issue." + ); +} + +function markUpdate(workInProgress) { + // Tag the fiber with an update effect. This turns a Placement into + // a PlacementAndUpdate. + workInProgress.flags |= Update; } -function validateSuspenseListNestedChild(childSlot, index) { - { - var isAnArray = isArray(childSlot); - var isIterable = - !isAnArray && typeof getIteratorFn(childSlot) === "function"; +function markRef$1(workInProgress) { + workInProgress.flags |= Ref; +} - if (isAnArray || isIterable) { - var type = isAnArray ? "array" : "iterable"; +function hadNoMutationsEffects(current, completedWork) { + var didBailout = current !== null && current.child === completedWork.child; - 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 (didBailout) { + return true; + } + + if ((completedWork.flags & ChildDeletion) !== NoFlags) { + return false; + } // TODO: If we move the `hadNoMutationsEffects` call after `bubbleProperties` + // then we only have to check the `completedWork.subtreeFlags`. + + var child = completedWork.child; + while (child !== null) { + if ( + (child.flags & MutationMask) !== NoFlags || + (child.subtreeFlags & MutationMask) !== NoFlags + ) { return false; } + + child = child.sibling; } return true; } -function validateSuspenseListChildren(children, revealOrder) { - { - if ( - (revealOrder === "forwards" || revealOrder === "backwards") && - children !== undefined && - children !== null && - children !== false - ) { - if (isArray(children)) { - for (var i = 0; i < children.length; i++) { - if (!validateSuspenseListNestedChild(children[i], i)) { - return; - } +var appendAllChildren; +var updateHostContainer; +var updateHostComponent$1; +var updateHostText$1; + +{ + // Persistent host tree mode + appendAllChildren = function( + parent, + workInProgress, + needsVisibilityToggle, + isHidden + ) { + // We only have the top Fiber that was created but we need recurse down its + // children to find all the terminal nodes. + var node = workInProgress.child; + + while (node !== null) { + // eslint-disable-next-line no-labels + if (node.tag === HostComponent) { + var instance = node.stateNode; + + if (needsVisibilityToggle && isHidden) { + // This child is inside a timed out tree. Hide it. + var props = node.memoizedProps; + var type = node.type; + instance = cloneHiddenInstance(instance); } - } else { - var iteratorFn = getIteratorFn(children); - if (typeof iteratorFn === "function") { - var childrenIterator = iteratorFn.call(children); + appendInitialChild(parent, instance); + } else if (node.tag === HostText) { + var _instance = node.stateNode; - if (childrenIterator) { - var step = childrenIterator.next(); - var _i = 0; + if (needsVisibilityToggle && isHidden) { + // This child is inside a timed out tree. Hide it. + var text = node.memoizedProps; + _instance = cloneHiddenTextInstance(); + } - for (; !step.done; step = childrenIterator.next()) { - if (!validateSuspenseListNestedChild(step.value, _i)) { - return; - } + 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; - _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 (child !== null) { + child.return = node; + } + + appendAllChildren(parent, node, true, true); + } else if (node.child !== null) { + node.child.return = node; + node = node.child; + continue; + } // $FlowFixMe This is correct but Flow is confused by the labeled break. + + node = node; + + if (node === workInProgress) { + return; + } + + while (node.sibling === null) { + if (node.return === null || node.return === workInProgress) { + return; } + + node = node.return; } + + node.sibling.return = node.return; + node = node.sibling; } - } -} + }; // An unfortunate fork of appendAllChildren because we have two different parent types. -function initSuspenseListRenderState( - workInProgress, - isBackwards, - tail, - lastContentRow, - tailMode -) { - var renderState = workInProgress.memoizedState; + var appendAllChildrenToContainer = function( + containerChildSet, + workInProgress, + needsVisibilityToggle, + isHidden + ) { + // We only have the top Fiber that was created but we need recurse down its + // children to find all the terminal nodes. + var node = workInProgress.child; - 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. + while (node !== null) { + // eslint-disable-next-line no-labels + if (node.tag === HostComponent) { + var instance = node.stateNode; -function updateSuspenseListComponent(current, workInProgress, renderLanes) { - var nextProps = workInProgress.pendingProps; - var revealOrder = nextProps.revealOrder; - var tailMode = nextProps.tail; - var newChildren = nextProps.children; - validateRevealOrder(revealOrder); - validateTailOptions(tailMode, revealOrder); - validateSuspenseListChildren(newChildren, revealOrder); - reconcileChildren(current, workInProgress, newChildren, renderLanes); - var suspenseContext = suspenseStackCursor.current; - var shouldForceFallback = hasSuspenseContext( - suspenseContext, - ForceSuspenseFallback - ); + if (needsVisibilityToggle && isHidden) { + // This child is inside a timed out tree. Hide it. + var props = node.memoizedProps; + var type = node.type; + instance = cloneHiddenInstance(instance); + } - if (shouldForceFallback) { - suspenseContext = setShallowSuspenseContext( - suspenseContext, - ForceSuspenseFallback - ); - workInProgress.flags |= DidCapture; - } else { - var didSuspendBefore = - current !== null && (current.flags & DidCapture) !== NoFlags; + appendChildToContainerChildSet(containerChildSet, instance); + } else if (node.tag === HostText) { + var _instance2 = node.stateNode; - if (didSuspendBefore) { - // If we previously forced a fallback, we need to schedule work - // on any nested boundaries to let them know to try to render - // again. This is the same as context updating. - propagateSuspenseContextChange( - workInProgress, - workInProgress.child, - renderLanes - ); - } + if (needsVisibilityToggle && isHidden) { + // This child is inside a timed out tree. Hide it. + var text = node.memoizedProps; + _instance2 = cloneHiddenTextInstance(); + } - suspenseContext = setDefaultShallowSuspenseContext(suspenseContext); - } + 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; - pushSuspenseContext(workInProgress, suspenseContext); + if (child !== null) { + child.return = node; + } - 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; + appendAllChildrenToContainer(containerChildSet, node, true, true); + } else if (node.child !== null) { + node.child.return = node; + node = node.child; + continue; + } // $FlowFixMe This is correct but Flow is confused by the labeled break. - 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; + node = node; + + if (node === workInProgress) { + return; + } + + while (node.sibling === null) { + if (node.return === null || node.return === workInProgress) { + return; } - initSuspenseListRenderState( - workInProgress, - false, // isBackwards - tail, - lastContentRow, - tailMode - ); - break; + node = node.return; } - 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; + node.sibling.return = node.return; + node = node.sibling; + } + }; - while (row !== null) { - var currentRow = row.alternate; // New rows can't be content rows. + updateHostContainer = function(current, workInProgress) { + var portalOrRoot = workInProgress.stateNode; + var childrenUnchanged = hadNoMutationsEffects(current, workInProgress); - if (currentRow !== null && findFirstSuspended(currentRow) === null) { - // This is the beginning of the main content. - workInProgress.child = row; - 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. - var nextRow = row.sibling; - row.sibling = _tail; - _tail = row; - row = nextRow; - } // TODO: If workInProgress.child is null, we can continue on the tail immediately. + appendAllChildrenToContainer(newChildSet, workInProgress, false, false); + portalOrRoot.pendingChildren = newChildSet; // Schedule an update on the container to swap out the container. - initSuspenseListRenderState( - workInProgress, - true, // isBackwards - _tail, - null, // last - tailMode - ); - break; - } + markUpdate(workInProgress); + finalizeContainerChildren(container, newChildSet); + } + }; - case "together": { - initSuspenseListRenderState( - workInProgress, - false, // isBackwards - null, // tail - null, // last - undefined - ); - break; - } + updateHostComponent$1 = function( + current, + workInProgress, + type, + newProps, + rootContainerInstance + ) { + var currentInstance = current.stateNode; + var oldProps = current.memoizedProps; // If there are no effects associated with this node, then none of our children had any updates. + // This guarantees that we can reuse all of them. - default: { - // The default reveal order is the same as not having - // a boundary. - workInProgress.memoizedState = null; - } + var childrenUnchanged = hadNoMutationsEffects(current, workInProgress); + + if (childrenUnchanged && oldProps === newProps) { + // No changes, just reuse the existing instance. + // Note that this might release a previous clone. + workInProgress.stateNode = currentInstance; + return; } - } - return workInProgress.child; -} + var recyclableInstance = workInProgress.stateNode; + var currentHostContext = getHostContext(); + var updatePayload = null; -function updatePortalComponent(current, workInProgress, renderLanes) { - pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); - var nextChildren = workInProgress.pendingProps; + if (oldProps !== newProps) { + updatePayload = prepareUpdate( + recyclableInstance, + type, + oldProps, + newProps + ); + } - 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( + if (childrenUnchanged && updatePayload === null) { + // No changes, just reuse the existing instance. + // Note that this might release a previous clone. + workInProgress.stateNode = currentInstance; + return; + } + + var newInstance = cloneInstance( + currentInstance, + updatePayload, + type, + oldProps, + newProps, workInProgress, - null, - nextChildren, - renderLanes + childrenUnchanged ); - } else { - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - } - return workInProgress.child; + workInProgress.stateNode = newInstance; + + if (childrenUnchanged) { + // If there are no other effects in this tree, we need to flag this node as having one. + // Even though we're not going to use it for anything. + // Otherwise parents won't know that there are new children to propagate upwards. + markUpdate(workInProgress); + } else { + // If children might have changed, we have to add them all to the set. + appendAllChildren(newInstance, workInProgress, false, false); + } + }; + + updateHostText$1 = function(current, workInProgress, oldText, newText) { + if (oldText !== newText) { + // If the text content differs, we'll create a new text instance for it. + var rootContainerInstance = getRootHostContainer(); + var currentHostContext = getHostContext(); + workInProgress.stateNode = createTextInstance( + newText, + rootContainerInstance, + currentHostContext, + workInProgress + ); // We'll have to mark it as having an effect, even though we won't use the effect for anything. + // This lets the parents know that at least one of their children has changed. + + markUpdate(workInProgress); + } else { + workInProgress.stateNode = current.stateNode; + } + }; } -var hasWarnedAboutUsingNoValuePropOnContextProvider = false; +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; -function updateContextProvider(current, workInProgress, renderLanes) { - var providerType = workInProgress.type; - var context = providerType._context; - var newProps = workInProgress.pendingProps; - var oldProps = workInProgress.memoizedProps; - var newValue = newProps.value; + while (tailNode !== null) { + if (tailNode.alternate !== null) { + lastTailNode = tailNode; + } - { - if (!("value" in newProps)) { - if (!hasWarnedAboutUsingNoValuePropOnContextProvider) { - hasWarnedAboutUsingNoValuePropOnContextProvider = true; + tailNode = tailNode.sibling; + } // Next we're simply going to delete all insertions after the + // last rendered item. - error( - "The `value` prop is required for the ``. Did you misspell it or forget to pass it?" - ); + if (lastTailNode === null) { + // All remaining items in the tail are insertions. + renderState.tail = null; + } else { + // Detach the insertion after the last node that was already + // inserted. + lastTailNode.sibling = null; } - } - var providerPropTypes = workInProgress.type.propTypes; - - if (providerPropTypes) { - checkPropTypes(providerPropTypes, newProps, "prop", "Context.Provider"); + break; } - } - pushProvider(workInProgress, context, newValue); + 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 (oldProps !== null) { - var oldValue = oldProps.value; + while (_tailNode !== null) { + if (_tailNode.alternate !== null) { + _lastTailNode = _tailNode; + } - if (objectIs(oldValue, newValue)) { - // No change. Bailout early if children are the same. - if (oldProps.children === newProps.children && !hasContextChanged()) { - return bailoutOnAlreadyFinishedWork( - current, - workInProgress, - 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. + 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 { - // The context value changed. Search for matching consumers and schedule - // them to update. - propagateContextChange(workInProgress, context, renderLanes); + // Detach the insertion after the last node that was already + // inserted. + _lastTailNode.sibling = null; } + + break; } } - - var newChildren = newProps.children; - reconcileChildren(current, workInProgress, newChildren, renderLanes); - return workInProgress.child; } -var hasWarnedAboutUsingContextAsConsumer = false; +function bubbleProperties(completedWork) { + var didBailout = + completedWork.alternate !== null && + completedWork.alternate.child === completedWork.child; + var newChildLanes = NoLanes; + var subtreeFlags = NoFlags; -function updateContextConsumer(current, workInProgress, renderLanes) { - var context = workInProgress.type; // The logic below for Context differs depending on PROD or DEV mode. In - // DEV mode, we create a separate object for Context.Consumer that acts - // like a proxy to Context. This proxy object adds unnecessary code in PROD - // so we use the old behaviour (Context.Consumer references Context) to - // reduce size and overhead. The separate object references context via - // a property called "_context", which also gives us the ability to check - // in DEV mode if this property exists or not and warn if it does not. + if (!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 (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; + 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. - error( - "Rendering directly is not supported and will be removed in " + - "a future major release. Did you mean to render instead?" - ); - } + actualDuration += child.actualDuration; + treeBaseDuration += child.treeBaseDuration; + child = child.sibling; } + + completedWork.actualDuration = actualDuration; + completedWork.treeBaseDuration = treeBaseDuration; } else { - context = context._context; - } - } + var _child = completedWork.child; - var newProps = workInProgress.pendingProps; - var render = newProps.children; + 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 (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." - ); + _child.return = completedWork; + _child = _child.sibling; + } } - } - prepareToReadContext(workInProgress, renderLanes); - var newValue = readContext(context); + 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; - var newChildren; + 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. - { - ReactCurrentOwner$1.current = workInProgress; - setIsRendering(true); - newChildren = render(newValue); - setIsRendering(false); - } + subtreeFlags |= _child2.subtreeFlags & StaticMask; + subtreeFlags |= _child2.flags & StaticMask; + _treeBaseDuration += _child2.treeBaseDuration; + _child2 = _child2.sibling; + } - workInProgress.flags |= PerformedWork; - reconcileChildren(current, workInProgress, newChildren, renderLanes); - return workInProgress.child; -} + completedWork.treeBaseDuration = _treeBaseDuration; + } else { + var _child3 = completedWork.child; -function markWorkInProgressReceivedUpdate() { - didReceiveUpdate = true; -} + while (_child3 !== null) { + newChildLanes = mergeLanes( + newChildLanes, + mergeLanes(_child3.lanes, _child3.childLanes) + ); // "Static" flags share the lifetime of the fiber/hook they belong to, + // so we should bubble those up even during a bailout. All the other + // flags have a lifetime only of a single render + commit, so we should + // ignore them. -function bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) { - if (current !== null) { - // Reuse previous dependencies - workInProgress.dependencies = current.dependencies; - } + 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. - { - // Don't update "base" render times for bailouts. - stopProfilerTimerIfRunning(); + _child3.return = completedWork; + _child3 = _child3.sibling; + } + } + + completedWork.subtreeFlags |= subtreeFlags; } - markSkippedUpdateLanes(workInProgress.lanes); // Check if the children have any pending work. + completedWork.childLanes = newChildLanes; + return didBailout; +} - 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. +function completeDehydratedSuspenseBoundary( + current, + workInProgress, + nextState +) { + var wasHydrated = popHydrationState(); - cloneChildFibers(current, workInProgress); - return workInProgress.child; -} + if (nextState !== null && nextState.dehydrated !== null) { + // We might be inside a hydration state the first time we're picking up this + // Suspense boundary, and also after we've reentered it for further hydration. + if (current === null) { + if (!wasHydrated) { + throw new Error( + "A dehydrated suspense component was completed without a hydrated node. " + + "This is probably a bug in React." + ); + } -function remountFiber(current, oldWorkInProgress, newWorkInProgress) { - { - var returnFiber = oldWorkInProgress.return; + prepareToHydrateHostSuspenseInstance(); + bubbleProperties(workInProgress); - if (returnFiber === null) { - // eslint-disable-next-line react-internal/prod-error-codes - throw new Error("Cannot swap the root fiber."); - } // Disconnect from the old current. - // It will get deleted. + { + if ((workInProgress.mode & ProfileMode) !== NoMode) { + var isTimedOutSuspense = nextState !== null; - current.alternate = null; - oldWorkInProgress.alternate = null; // Connect to the new tree. + if (isTimedOutSuspense) { + // Don't count time spent in a timed out Suspense subtree as part of the base duration. + var primaryChildFragment = workInProgress.child; - newWorkInProgress.index = oldWorkInProgress.index; - newWorkInProgress.sibling = oldWorkInProgress.sibling; - newWorkInProgress.return = oldWorkInProgress.return; - newWorkInProgress.ref = oldWorkInProgress.ref; // Replace the child/sibling pointers above it. + if (primaryChildFragment !== null) { + // $FlowFixMe Flow doesn't support type casting in combination with the -= operator + workInProgress.treeBaseDuration -= + primaryChildFragment.treeBaseDuration; + } + } + } + } - if (oldWorkInProgress === returnFiber.child) { - returnFiber.child = newWorkInProgress; + return false; } else { - var prevSibling = returnFiber.child; + if ((workInProgress.flags & DidCapture) === NoFlags) { + // This boundary did not suspend so it's now hydrated and unsuspended. + workInProgress.memoizedState = null; + } // If nothing suspended, we need to schedule an effect to mark this boundary + // as having hydrated so events know that they're free to be invoked. + // It's also a signal to replay events and the suspense callback. + // If something suspended, schedule an effect to attach retry listeners. + // So we might as well always mark this. - if (prevSibling === null) { - // eslint-disable-next-line react-internal/prod-error-codes - throw new Error("Expected parent to have a child."); - } + workInProgress.flags |= Update; + bubbleProperties(workInProgress); - while (prevSibling.sibling !== oldWorkInProgress) { - prevSibling = prevSibling.sibling; + { + if ((workInProgress.mode & ProfileMode) !== NoMode) { + var _isTimedOutSuspense = nextState !== null; - if (prevSibling === null) { - // eslint-disable-next-line react-internal/prod-error-codes - throw new Error("Expected to find the previous sibling."); + if (_isTimedOutSuspense) { + // Don't count time spent in a timed out Suspense subtree as part of the base duration. + var _primaryChildFragment = workInProgress.child; + + if (_primaryChildFragment !== null) { + // $FlowFixMe Flow doesn't support type casting in combination with the -= operator + workInProgress.treeBaseDuration -= + _primaryChildFragment.treeBaseDuration; + } + } } } - prevSibling.sibling = newWorkInProgress; - } // Delete the old fiber and place the new one. - // Since the old fiber is disconnected, we have to schedule it manually. - - var deletions = returnFiber.deletions; - - if (deletions === null) { - returnFiber.deletions = [current]; - returnFiber.flags |= ChildDeletion; - } else { - deletions.push(current); + 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 - newWorkInProgress.flags |= Placement; // Restart work from the new fiber. - - return newWorkInProgress; + return true; } } -function checkScheduledUpdateOrContext(current, renderLanes) { - // Before performing an early bailout, we must check if there are pending - // updates or context. - var updateLanes = current.lanes; - - if (includesSomeLane(updateLanes, renderLanes)) { - return true; - } // No pending update, but because context is propagated lazily, we need +function completeWork(current, workInProgress, renderLanes) { + var newProps = workInProgress.pendingProps; // Note: This intentionally doesn't check if we're hydrating because comparing + // to the current tree provider fiber is just as fast and less error-prone. + // Ideally we would have a special version of the work loop only + // for hydration. - return false; -} + popTreeContext(workInProgress); -function attemptEarlyBailoutIfNoScheduledUpdate( - current, - workInProgress, - renderLanes -) { - // This fiber does not have any pending work. Bailout without entering - // the begin phase. There's still some bookkeeping we that needs to be done - // in this optimized path, mostly pushing stuff onto the stack. switch (workInProgress.tag) { - case HostRoot: - pushHostRootContext(workInProgress); - var root = workInProgress.stateNode; - break; - - case HostComponent: - pushHostContext(workInProgress); - break; + case IndeterminateComponent: + case LazyComponent: + case SimpleMemoComponent: + case FunctionComponent: + case ForwardRef: + case Fragment: + case Mode: + case Profiler: + case ContextConsumer: + case MemoComponent: + bubbleProperties(workInProgress); + return null; case ClassComponent: { var Component = workInProgress.type; if (isContextProvider(Component)) { - pushContextProvider(workInProgress); + popContext(workInProgress); } - break; + bubbleProperties(workInProgress); + return null; } - case HostPortal: - pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); - break; + case HostRoot: { + var fiberRoot = workInProgress.stateNode; + popHostContainer(workInProgress); + popTopLevelContextObject(workInProgress); + resetWorkInProgressVersions(); - case ContextProvider: { - var newValue = workInProgress.memoizedProps.value; - var context = workInProgress.type._context; - pushProvider(workInProgress, context, newValue); - break; + if (fiberRoot.pendingContext) { + fiberRoot.context = fiberRoot.pendingContext; + fiberRoot.pendingContext = null; + } + + if (current === null || current.child === null) { + // If we hydrated, pop so that we can delete any remaining children + // that weren't hydrated. + var wasHydrated = popHydrationState(); + + if (wasHydrated) { + // If we hydrated, then we'll need to schedule an update for + // the commit side-effects on the root. + markUpdate(workInProgress); + } else { + if (current !== null) { + var prevState = current.memoizedState; + + if ( + // Check if this is a client root + !prevState.isDehydrated || // Check if we reverted to client rendering (e.g. due to an error) + (workInProgress.flags & ForceClientRender) !== NoFlags + ) { + // Schedule an effect to clear this container at the start of the + // next commit. This handles the case of React rendering into a + // container with previous children. It's also safe to do for + // updates too, because current.child would only be null if the + // previous render was null (so the container would already + // be empty). + workInProgress.flags |= Snapshot; // If this was a forced client render, there may have been + // recoverable errors during first hydration attempt. If so, add + // them to a queue so we can log them in the commit phase. + + upgradeHydrationErrorsToRecoverable(); + } + } + } + } + + updateHostContainer(current, workInProgress); + bubbleProperties(workInProgress); + + return null; } - case Profiler: - { - // Profiler should only call onRender when one of its descendants actually rendered. - var hasChildWork = includesSomeLane( - renderLanes, - workInProgress.childLanes + case HostComponent: { + popHostContext(workInProgress); + var rootContainerInstance = getRootHostContainer(); + var type = workInProgress.type; + + if (current !== null && workInProgress.stateNode != null) { + updateHostComponent$1( + current, + workInProgress, + type, + newProps, + rootContainerInstance ); - if (hasChildWork) { - workInProgress.flags |= Update; + if (current.ref !== workInProgress.ref) { + markRef$1(workInProgress); + } + } else { + if (!newProps) { + if (workInProgress.stateNode === null) { + throw new Error( + "We must have new props for new mounts. This error is likely " + + "caused by a bug in React. Please file an issue." + ); + } // This can happen when we abort work. + + bubbleProperties(workInProgress); + return null; } - { - // Reset effect durations for the next eventual effect phase. - // These are reset during render to allow the DevTools commit hook a chance to read them, - var stateNode = workInProgress.stateNode; - stateNode.effectDuration = 0; - stateNode.passiveEffectDuration = 0; + var currentHostContext = getHostContext(); // TODO: Move createInstance to beginWork and keep it on a context + // "stack" as the parent. Then append children as we go in beginWork + // or completeWork depending on whether we want to add them top->down or + // bottom->up. Top->down is faster in IE11. + + var _wasHydrated = popHydrationState(); + + if (_wasHydrated) { + // TODO: Move this and createInstance step into the beginPhase + // to consolidate. + if (prepareToHydrateHostInstance()) { + // If changes to the hydrated node need to be applied at the + // commit-phase we mark this as such. + markUpdate(workInProgress); + } + } else { + var instance = createInstance( + type, + newProps, + rootContainerInstance, + currentHostContext, + workInProgress + ); + appendAllChildren(instance, workInProgress, false, false); + workInProgress.stateNode = instance; // Certain renderers require commit-time effects for initial mount. + } + + if (workInProgress.ref !== null) { + // If there is a ref on a host node we need to schedule a callback + markRef$1(workInProgress); } } - break; + bubbleProperties(workInProgress); + return null; + } - case SuspenseComponent: { - var state = workInProgress.memoizedState; + case HostText: { + var newText = newProps; - if (state !== null) { - // whether to retry the primary children, or to skip over it and - // go straight to the fallback. Check the priority of the primary - // child fragment. + if (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. - var primaryChildFragment = workInProgress.child; - var primaryChildLanes = primaryChildFragment.childLanes; + updateHostText$1(current, workInProgress, oldText, newText); + } else { + if (typeof newText !== "string") { + if (workInProgress.stateNode === null) { + throw new Error( + "We must have new props for new mounts. This error is likely " + + "caused by a bug in React. Please file an issue." + ); + } // This can happen when we abort work. + } - if (includesSomeLane(renderLanes, primaryChildLanes)) { - // The primary children have pending work. Use the normal path - // to attempt to render the primary children again. - return updateSuspenseComponent(current, workInProgress, renderLanes); - } else { - // The primary child fragment does not have pending work marked - // on it - pushSuspenseContext( - workInProgress, - setDefaultShallowSuspenseContext(suspenseStackCursor.current) - ); // The primary children do not have pending work with sufficient - // priority. Bailout. + var _rootContainerInstance = getRootHostContainer(); - var child = bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderLanes - ); + var _currentHostContext = getHostContext(); - 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; + var _wasHydrated2 = popHydrationState(); + + if (_wasHydrated2) { + if (prepareToHydrateHostTextInstance()) { + markUpdate(workInProgress); } + } else { + workInProgress.stateNode = createTextInstance( + newText, + _rootContainerInstance, + _currentHostContext, + workInProgress + ); } - } else { - pushSuspenseContext( + } + + bubbleProperties(workInProgress); + return null; + } + + case SuspenseComponent: { + popSuspenseContext(workInProgress); + var nextState = workInProgress.memoizedState; // Special path for dehydrated boundaries. We may eventually move this + // to its own fiber type so that we can add other kinds of hydration + // boundaries that aren't associated with a Suspense tree. In anticipation + // of such a refactor, all the hydration logic is contained in + // this branch. + + if ( + current === null || + (current.memoizedState !== null && + current.memoizedState.dehydrated !== null) + ) { + var fallthroughToNormalSuspensePath = completeDehydratedSuspenseBoundary( + current, workInProgress, - setDefaultShallowSuspenseContext(suspenseStackCursor.current) + nextState ); + + 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. } - break; - } + if ((workInProgress.flags & DidCapture) !== NoFlags) { + // Something suspended. Re-render with the fallback children. + workInProgress.lanes = renderLanes; // Do not reset the effect list. - case SuspenseListComponent: { - var didSuspendBefore = (current.flags & DidCapture) !== NoFlags; + if ((workInProgress.mode & ProfileMode) !== NoMode) { + transferActualDuration(workInProgress); + } // Don't bubble properties in this case. - var _hasChildWork = includesSomeLane( - renderLanes, - workInProgress.childLanes - ); + return workInProgress; + } - if (didSuspendBefore) { - if (_hasChildWork) { - // If something was in fallback state last time, and we have all the - // same children then we're still in progressive loading state. - // Something might get unblocked by state updates or retries in the - // tree which will affect the tail. So we need to use the normal - // path to compute the correct tail. - return updateSuspenseListComponent( - current, - workInProgress, - renderLanes - ); - } // If none of the children had any work, that means that none of - // them got retried so they'll still be blocked in the same way - // as before. We can fast bail out. + var nextDidTimeout = nextState !== null; + var prevDidTimeout = current !== null && current.memoizedState !== null; + // a passive effect, which is when we process the transitions + + if (nextDidTimeout !== prevDidTimeout) { + // an effect to toggle the subtree's visibility. When we switch from + // fallback -> primary, the inner Offscreen fiber schedules this effect + // as part of its normal complete phase. But when we switch from + // primary -> fallback, the inner Offscreen fiber does not have a complete + // phase. So we need to schedule its effect here. + // + // We also use this flag to connect/disconnect the effects, but the same + // logic applies: when re-connecting, the Offscreen fiber's complete + // phase will handle scheduling the effect. It's only when the fallback + // is active that we have to do anything special. + + if (nextDidTimeout) { + var _offscreenFiber2 = workInProgress.child; + _offscreenFiber2.flags |= Visibility; // TODO: This will still suspend a synchronous tree if anything + // in the concurrent tree already suspended during this render. + // This is a known bug. + + if ((workInProgress.mode & ConcurrentMode) !== NoMode) { + // TODO: Move this back to throwException because this is too late + // if this is a large tree which is common for initial loads. We + // don't know if we should restart a render or not until we get + // this marker, and this is too late. + // If this render already had a ping or lower pri updates, + // and this is the first time we know we're going to suspend we + // should be able to immediately restart from within throwException. + var hasInvisibleChildContext = + current === null && + (workInProgress.memoizedProps.unstable_avoidThisFallback !== + true || + !enableSuspenseAvoidThisFallback); - 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 ( + hasInvisibleChildContext || + hasSuspenseContext( + suspenseStackCursor.current, + InvisibleParentSuspenseContext + ) + ) { + // If this was in an invisible tree or a new render, then showing + // this boundary is ok. + renderDidSuspend(); + } else { + // Otherwise, we're going to have to hide content so we should + // suspend for longer if possible. + renderDidSuspendDelayIfPossible(); + } + } + } + } - var renderState = workInProgress.memoizedState; + var wakeables = workInProgress.updateQueue; - if (renderState !== null) { - // Reset to the "together" mode in case we've started a different - // update in the past but didn't complete it. - renderState.rendering = null; - renderState.tail = null; - renderState.lastEffect = null; + if (wakeables !== null) { + // Schedule an effect to attach a retry listener to the promise. + // TODO: Move to passive phase + workInProgress.flags |= Update; } - pushSuspenseContext(workInProgress, suspenseStackCursor.current); + bubbleProperties(workInProgress); - if (_hasChildWork) { - break; - } else { - // If none of the children had any work, that means that none of - // them got retried so they'll still be blocked in the same way - // as before. We can fast bail out. - return null; + { + if ((workInProgress.mode & ProfileMode) !== NoMode) { + if (nextDidTimeout) { + // Don't count time spent in a timed out Suspense subtree as part of the base duration. + var primaryChildFragment = workInProgress.child; + + if (primaryChildFragment !== null) { + // $FlowFixMe Flow doesn't support type casting in combination with the -= operator + workInProgress.treeBaseDuration -= + primaryChildFragment.treeBaseDuration; + } + } + } } - } - case 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 null; } - } - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); -} + case HostPortal: + popHostContainer(workInProgress); + updateHostContainer(current, workInProgress); -function beginWork(current, workInProgress, renderLanes) { - { - if (workInProgress._debugNeedsRemount && current !== null) { - // This will restart the begin phase with a new fiber. - return remountFiber( - current, - workInProgress, - createFiberFromTypeAndProps( - workInProgress.type, - workInProgress.key, - workInProgress.pendingProps, - workInProgress._debugOwner || null, - workInProgress.mode, - workInProgress.lanes - ) - ); - } - } + if (current === null) { + preparePortalMount(workInProgress.stateNode.containerInfo); + } - if (current !== null) { - var oldProps = current.memoizedProps; - var newProps = workInProgress.pendingProps; + bubbleProperties(workInProgress); + return null; - 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 - ); + case ContextProvider: + // Pop provider fiber + var context = workInProgress.type._context; + popProvider(context, workInProgress); + bubbleProperties(workInProgress); + return null; - if ( - !hasScheduledUpdateOrContext && // If this is the second pass of an error or suspense boundary, there - // may not be work scheduled on `current`, so we check for this flag. - (workInProgress.flags & DidCapture) === NoFlags - ) { - // No pending updates or context. Bail out now. - didReceiveUpdate = false; - return attemptEarlyBailoutIfNoScheduledUpdate( - current, - workInProgress, - renderLanes - ); - } + 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 ((current.flags & ForceUpdateForLegacySuspense) !== NoFlags) { - // This is a special case that only exists for legacy mode. - // See https://github.com/facebook/react/pull/19216. - didReceiveUpdate = true; - } else { - // An update was scheduled on this fiber, but there are no new props - // nor legacy context. Set this to false. If an update queue or context - // consumer produces a changed value, it will set this to true. Otherwise, - // the component will assume the children have not changed and bail out. - didReceiveUpdate = false; + if (isContextProvider(_Component)) { + popContext(workInProgress); } + + bubbleProperties(workInProgress); + return null; } - } 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; + case SuspenseListComponent: { + popSuspenseContext(workInProgress); + var renderState = workInProgress.memoizedState; - switch (workInProgress.tag) { - case IndeterminateComponent: { - return mountIndeterminateComponent( - current, - workInProgress, - workInProgress.type, - renderLanes - ); - } + if (renderState === null) { + // We're running in the default, "independent" mode. + // We don't do anything in this mode. + bubbleProperties(workInProgress); + return null; + } - case LazyComponent: { - var elementType = workInProgress.elementType; - return mountLazyComponent( - current, - workInProgress, - elementType, - renderLanes - ); - } + var didSuspendAlready = (workInProgress.flags & DidCapture) !== NoFlags; + var renderedTail = renderState.rendering; - case FunctionComponent: { - var Component = workInProgress.type; - var unresolvedProps = workInProgress.pendingProps; - var resolvedProps = - workInProgress.elementType === Component - ? unresolvedProps - : resolveDefaultProps(Component, unresolvedProps); - return updateFunctionComponent( - current, - workInProgress, - Component, - resolvedProps, - renderLanes - ); - } + if (renderedTail === null) { + // We just rendered the head. + if (!didSuspendAlready) { + // This is the first pass. We need to figure out if anything is still + // suspended in the rendered set. + // If new content unsuspended, but there's still some content that + // didn't. Then we need to do a second pass that forces everything + // to keep showing their fallbacks. + // We might be suspended if something in this render pass suspended, or + // something in the previous committed pass suspended. Otherwise, + // there's no chance so we can skip the expensive call to + // findFirstSuspended. + var cannotBeSuspended = + renderHasNotSuspendedYet() && + (current === null || (current.flags & DidCapture) === NoFlags); + + if (!cannotBeSuspended) { + var row = workInProgress.child; + + while (row !== null) { + var suspended = findFirstSuspended(row); + + if (suspended !== null) { + didSuspendAlready = true; + workInProgress.flags |= DidCapture; + cutOffTailIfNeeded(renderState, false); // If this is a newly suspended tree, it might not get committed as + // part of the second pass. In that case nothing will subscribe to + // its thenables. Instead, we'll transfer its thenables to the + // SuspenseList so that it can retry if they resolve. + // There might be multiple of these in the list but since we're + // going to wait for all of them anyway, it doesn't really matter + // which ones gets to ping. In theory we could get clever and keep + // track of how many dependencies remain but it gets tricky because + // in the meantime, we can add/remove/change items and dependencies. + // We might bail out of the loop before finding any but that + // doesn't matter since that means that the other boundaries that + // we did find already has their listeners attached. - case ClassComponent: { - var _Component = workInProgress.type; - var _unresolvedProps = workInProgress.pendingProps; + var newThenables = suspended.updateQueue; - var _resolvedProps = - workInProgress.elementType === _Component - ? _unresolvedProps - : resolveDefaultProps(_Component, _unresolvedProps); + 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. - return updateClassComponent( - current, - workInProgress, - _Component, - _resolvedProps, - renderLanes - ); - } + workInProgress.subtreeFlags = NoFlags; + resetChildFibers(workInProgress, renderLanes); // Set up the Suspense Context to force suspense and immediately + // rerender the children. - case HostRoot: - return updateHostRoot(current, workInProgress, renderLanes); + pushSuspenseContext( + workInProgress, + setShallowSuspenseContext( + suspenseStackCursor.current, + ForceSuspenseFallback + ) + ); // Don't bubble properties in this case. - case HostComponent: - return updateHostComponent$1(current, workInProgress, renderLanes); + return workInProgress.child; + } - case HostText: - return updateHostText$1(); + row = row.sibling; + } + } - case SuspenseComponent: - return updateSuspenseComponent(current, workInProgress, renderLanes); + if (renderState.tail !== null && now() > getRenderTargetTime()) { + // We have already passed our CPU deadline but we still have rows + // left in the tail. We'll just give up further attempts to render + // the main content and only render fallbacks. + workInProgress.flags |= DidCapture; + didSuspendAlready = true; + cutOffTailIfNeeded(renderState, false); // Since nothing actually suspended, there will nothing to ping this + // to get it started back up to attempt the next item. While in terms + // of priority this work has the same priority as this current render, + // it's not part of the same transition once the transition has + // committed. If it's sync, we still want to yield so that it can be + // painted. Conceptually, this is really the same as pinging. + // We can use any RetryLane even if it's the one currently rendering + // since we're leaving it behind on this node. - case HostPortal: - return updatePortalComponent(current, workInProgress, renderLanes); + 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); - case ForwardRef: { - var type = workInProgress.type; - var _unresolvedProps2 = workInProgress.pendingProps; + 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 _resolvedProps2 = - workInProgress.elementType === type - ? _unresolvedProps2 - : resolveDefaultProps(type, _unresolvedProps2); + var _newThenables = _suspended.updateQueue; - return updateForwardRef( - current, - workInProgress, - type, - _resolvedProps2, - renderLanes - ); - } + if (_newThenables !== null) { + workInProgress.updateQueue = _newThenables; + workInProgress.flags |= Update; + } - case Fragment: - return updateFragment(current, workInProgress, renderLanes); + cutOffTailIfNeeded(renderState, true); // This might have been modified. - case Mode: - return updateMode(current, workInProgress, renderLanes); + if ( + renderState.tail === null && + renderState.tailMode === "hidden" && + !renderedTail.alternate && + !getIsHydrating() // We don't cut it if we're hydrating. + ) { + // We're done. + bubbleProperties(workInProgress); + return null; + } + } else if ( + // The time it took to render last row is greater than the remaining + // time we have to render. So rendering one more row would likely + // exceed it. + now() * 2 - renderState.renderingStartTime > + getRenderTargetTime() && + renderLanes !== OffscreenLane + ) { + // We have now passed our CPU deadline and we'll just give up further + // attempts to render the main content and only render fallbacks. + // The assumption is that this is usually faster. + workInProgress.flags |= DidCapture; + didSuspendAlready = true; + cutOffTailIfNeeded(renderState, false); // Since nothing actually suspended, there will nothing to ping this + // to get it started back up to attempt the next item. While in terms + // of priority this work has the same priority as this current render, + // it's not part of the same transition once the transition has + // committed. If it's sync, we still want to yield so that it can be + // painted. Conceptually, this is really the same as pinging. + // We can use any RetryLane even if it's the one currently rendering + // since we're leaving it behind on this node. - case Profiler: - return updateProfiler(current, workInProgress, renderLanes); + workInProgress.lanes = SomeRetryLane; + } + } - case ContextProvider: - return updateContextProvider(current, workInProgress, renderLanes); + 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; - case ContextConsumer: - return updateContextConsumer(current, workInProgress, renderLanes); + if (previousSibling !== null) { + previousSibling.sibling = renderedTail; + } else { + workInProgress.child = renderedTail; + } - case MemoComponent: { - var _type2 = workInProgress.type; - var _unresolvedProps3 = workInProgress.pendingProps; // Resolve outer props first, then resolve inner props. + renderState.last = renderedTail; + } + } - var _resolvedProps3 = resolveDefaultProps(_type2, _unresolvedProps3); + if (renderState.tail !== null) { + // We still have tail rows to render. + // Pop a row. + var next = renderState.tail; + renderState.rendering = next; + renderState.tail = next.sibling; + renderState.renderingStartTime = now(); + next.sibling = null; // Restore the context. + // TODO: We can probably just avoid popping it instead and only + // setting it the first time we go from not suspended to suspended. - { - if (workInProgress.type !== workInProgress.elementType) { - var outerPropTypes = _type2.propTypes; + var suspenseContext = suspenseStackCursor.current; - if (outerPropTypes) { - checkPropTypes( - outerPropTypes, - _resolvedProps3, // Resolved for outer only - "prop", - getComponentNameFromType(_type2) - ); - } + if (didSuspendAlready) { + suspenseContext = setShallowSuspenseContext( + suspenseContext, + ForceSuspenseFallback + ); + } else { + suspenseContext = setDefaultShallowSuspenseContext(suspenseContext); } + + pushSuspenseContext(workInProgress, suspenseContext); // Do a pass over the next row. + // Don't bubble properties in this case. + + return next; } - _resolvedProps3 = resolveDefaultProps(_type2.type, _resolvedProps3); - return updateMemoComponent( - current, - workInProgress, - _type2, - _resolvedProps3, - renderLanes - ); + bubbleProperties(workInProgress); + return null; } - case SimpleMemoComponent: { - return updateSimpleMemoComponent( - current, - workInProgress, - workInProgress.type, - workInProgress.pendingProps, - renderLanes - ); + case ScopeComponent: { + break; } - case IncompleteClassComponent: { - var _Component2 = workInProgress.type; - var _unresolvedProps4 = workInProgress.pendingProps; + case OffscreenComponent: + case LegacyHiddenComponent: { + popRenderLanes(workInProgress); + var _nextState = workInProgress.memoizedState; + var nextIsHidden = _nextState !== null; - var _resolvedProps4 = - workInProgress.elementType === _Component2 - ? _unresolvedProps4 - : resolveDefaultProps(_Component2, _unresolvedProps4); + if (current !== null) { + var _prevState = current.memoizedState; + var prevIsHidden = _prevState !== null; - return mountIncompleteClassComponent( - current, - workInProgress, - _Component2, - _resolvedProps4, - renderLanes - ); - } + if ( + prevIsHidden !== nextIsHidden && // LegacyHidden doesn't do any hiding — it only pre-renders. + !enableLegacyHidden + ) { + workInProgress.flags |= Visibility; + } + } - case SuspenseListComponent: { - return updateSuspenseListComponent(current, workInProgress, renderLanes); + if (!nextIsHidden || (workInProgress.mode & ConcurrentMode) === NoMode) { + bubbleProperties(workInProgress); + } else { + // Don't bubble properties for hidden children unless we're rendering + // at offscreen priority. + if (includesSomeLane(subtreeRenderLanes, OffscreenLane)) { + bubbleProperties(workInProgress); + } + } + return null; } - case ScopeComponent: { - break; + case CacheComponent: { + return null; } - case OffscreenComponent: { - return updateOffscreenComponent(current, workInProgress, renderLanes); + case TracingMarkerComponent: { + return null; } } @@ -17161,6 +17742,7 @@ function unwindWork(current, workInProgress, renderLanes) { } case HostRoot: { + var root = workInProgress.stateNode; popHostContainer(workInProgress); popTopLevelContextObject(workInProgress); resetWorkInProgressVersions(); @@ -17187,6 +17769,16 @@ function unwindWork(current, workInProgress, renderLanes) { case SuspenseComponent: { popSuspenseContext(workInProgress); + var suspenseState = workInProgress.memoizedState; + + if (suspenseState !== null && suspenseState.dehydrated !== null) { + if (workInProgress.alternate === null) { + throw new Error( + "Threw in newly mounted dehydrated component. This is likely a bug in " + + "React. Please file an issue." + ); + } + } var _flags2 = workInProgress.flags; @@ -17222,7 +17814,6 @@ function unwindWork(current, workInProgress, renderLanes) { case OffscreenComponent: case LegacyHiddenComponent: popRenderLanes(workInProgress); - return null; case CacheComponent: @@ -17252,6 +17843,7 @@ function unwindInterruptedWork(current, interruptedWork, renderLanes) { } case HostRoot: { + var root = interruptedWork.stateNode; popHostContainer(interruptedWork); popTopLevelContextObject(interruptedWork); resetWorkInProgressVersions(); @@ -17283,7 +17875,6 @@ function unwindInterruptedWork(current, interruptedWork, renderLanes) { case OffscreenComponent: case LegacyHiddenComponent: popRenderLanes(interruptedWork); - break; } } @@ -17298,7 +17889,6 @@ var nextEffect = null; // Used for Profiling builds to track updaters. var inProgressLanes = null; var inProgressRoot = null; - function reportUncaughtErrorInDEV(error) { // Wrapping each small part of the commit phase into a guarded // callback is a bit too slow (https://github.com/facebook/react/pull/21666). @@ -17337,7 +17927,6 @@ function safelyCallComponentWillUnmount( try { callComponentWillUnmountWithTimer(current, instance); } catch (error) { - reportUncaughtErrorInDEV(error); captureCommitPhaseError(current, nearestMountedAncestor, error); } } // Capture errors so they don't interrupt mounting. @@ -17365,7 +17954,6 @@ function safelyDetachRef(current, nearestMountedAncestor) { retVal = ref(null); } } catch (error) { - reportUncaughtErrorInDEV(error); captureCommitPhaseError(current, nearestMountedAncestor, error); } @@ -17388,7 +17976,6 @@ function safelyCallDestroy(current, nearestMountedAncestor, destroy) { try { destroy(); } catch (error) { - reportUncaughtErrorInDEV(error); captureCommitPhaseError(current, nearestMountedAncestor, error); } } @@ -17416,7 +18003,7 @@ function commitBeforeMutationEffects_begin() { (fiber.subtreeFlags & BeforeMutationMask) !== NoFlags && child !== null ) { - ensureCorrectReturnPointer(child, fiber); + child.return = fiber; nextEffect = child; } else { commitBeforeMutationEffects_complete(); @@ -17432,7 +18019,6 @@ function commitBeforeMutationEffects_complete() { try { commitBeforeMutationEffectsOnFiber(fiber); } catch (error) { - reportUncaughtErrorInDEV(error); captureCommitPhaseError(fiber, fiber.return, error); } @@ -17440,7 +18026,7 @@ function commitBeforeMutationEffects_complete() { var sibling = fiber.sibling; if (sibling !== null) { - ensureCorrectReturnPointer(sibling, fiber.return); + sibling.return = fiber.return; nextEffect = sibling; return; } @@ -17569,7 +18155,19 @@ function commitHookEffectListUnmount( effect.destroy = undefined; if (destroy !== undefined) { + { + if ((flags & Insertion) !== NoFlags$1) { + setIsRunningInsertionEffect(true); + } + } + safelyCallDestroy(finishedWork, nearestMountedAncestor, destroy); + + { + if ((flags & Insertion) !== NoFlags$1) { + setIsRunningInsertionEffect(false); + } + } } } @@ -17589,8 +18187,21 @@ function commitHookEffectListMount(flags, finishedWork) { do { if ((effect.tag & flags) === flags) { var create = effect.create; + + { + if ((flags & Insertion) !== NoFlags$1) { + setIsRunningInsertionEffect(true); + } + } + effect.destroy = create(); + { + if ((flags & Insertion) !== NoFlags$1) { + setIsRunningInsertionEffect(false); + } + } + { var destroy = effect.destroy; @@ -18005,7 +18616,8 @@ function commitLayoutEffectOnFiber( case IncompleteClassComponent: case ScopeComponent: case OffscreenComponent: - case LegacyHiddenComponent: { + case LegacyHiddenComponent: + case TracingMarkerComponent: { break; } @@ -18081,153 +18693,6 @@ function commitAttachRef(finishedWork) { } } -function commitDetachRef(current) { - var currentRef = current.ref; - - if (currentRef !== null) { - if (typeof currentRef === "function") { - if (current.mode & ProfileMode) { - try { - startLayoutEffectTimer(); - currentRef(null); - } finally { - recordLayoutEffectDuration(current); - } - } else { - currentRef(null); - } - } else { - currentRef.current = null; - } - } -} // User-originating errors (lifecycles and refs) should not interrupt -// deletion, so don't let them throw. Host-originating errors should -// interrupt deletion, so it's okay - -function commitUnmount(finishedRoot, current, nearestMountedAncestor) { - onCommitUnmount(current); - - switch (current.tag) { - case FunctionComponent: - case ForwardRef: - case MemoComponent: - case SimpleMemoComponent: { - var updateQueue = current.updateQueue; - - if (updateQueue !== null) { - var lastEffect = updateQueue.lastEffect; - - if (lastEffect !== null) { - var firstEffect = lastEffect.next; - var effect = firstEffect; - - do { - var _effect = effect, - destroy = _effect.destroy, - tag = _effect.tag; - - if (destroy !== undefined) { - if ((tag & Insertion) !== NoFlags$1) { - safelyCallDestroy(current, nearestMountedAncestor, destroy); - } else if ((tag & Layout) !== NoFlags$1) { - if (current.mode & ProfileMode) { - startLayoutEffectTimer(); - safelyCallDestroy(current, nearestMountedAncestor, destroy); - recordLayoutEffectDuration(current); - } else { - safelyCallDestroy(current, nearestMountedAncestor, destroy); - } - } - } - - effect = effect.next; - } while (effect !== firstEffect); - } - } - - return; - } - - case ClassComponent: { - safelyDetachRef(current, nearestMountedAncestor); - var instance = current.stateNode; - - if (typeof instance.componentWillUnmount === "function") { - safelyCallComponentWillUnmount( - current, - nearestMountedAncestor, - instance - ); - } - - return; - } - - case HostComponent: { - safelyDetachRef(current, nearestMountedAncestor); - return; - } - - case HostPortal: { - // TODO: this is recursive. - // We are also not using this parent because - // the portal will get pushed immediately. - { - emptyPortalContainer(current); - } - - return; - } - - case DehydratedFragment: { - return; - } - - case ScopeComponent: { - return; - } - } -} - -function commitNestedUnmounts(finishedRoot, root, nearestMountedAncestor) { - // While we're inside a removed host node we don't want to call - // removeChild on the inner nodes because they're removed by the top - // call anyway. We also want to call componentWillUnmount on all - // composites before this host node is removed from the tree. Therefore - // we do an inner loop while we're still inside the host node. - var node = root; - - while (true) { - commitUnmount(finishedRoot, node, nearestMountedAncestor); // Visit children because they may contain more composite or host nodes. - // Skip portals because commitUnmount() currently visits them recursively. - - if ( - node.child !== null && // If we use mutation we drill down into portals using commitUnmount above. - // If we don't use mutation we drill down into portals here instead. - !supportsMutation - ) { - node.child.return = node; - node = node.child; - continue; - } - - if (node === root) { - return; - } - - while (node.sibling === null) { - if (node.return === null || node.return === root) { - return; - } - - node = node.return; - } - - node.sibling.return = node.return; - node = node.sibling; - } -} - 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. @@ -18317,110 +18782,194 @@ function emptyPortalContainer(current) { var emptyChildSet = createContainerChildSet(containerInfo); } -function commitContainer(finishedWork) { - switch (finishedWork.tag) { - case ClassComponent: - case HostComponent: +function commitPlacement(finishedWork) { + { + return; + } // Recursively insert all host nodes into the parent. +} + +function commitDeletionEffects(root, returnFiber, deletedFiber) { + { + // Detach refs and call componentWillUnmount() on the whole subtree. + commitDeletionEffectsOnFiber(root, returnFiber, deletedFiber); + } + + detachFiberMutation(deletedFiber); +} + +function recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + parent +) { + // TODO: Use a static flag to skip trees that don't have unmount effects + var child = parent.child; + + while (child !== null) { + commitDeletionEffectsOnFiber(finishedRoot, nearestMountedAncestor, child); + child = child.sibling; + } +} + +function commitDeletionEffectsOnFiber( + finishedRoot, + nearestMountedAncestor, + deletedFiber +) { + onCommitUnmount(deletedFiber); // The cases in this outer switch modify the stack before they traverse + // into their subtree. There are simpler cases in the inner switch + // that don't modify the stack. + + switch (deletedFiber.tag) { + case HostComponent: { + { + safelyDetachRef(deletedFiber, nearestMountedAncestor); + } // Intentional fallthrough to next branch + } + // eslint-disable-next-line-no-fallthrough + 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; } - case HostRoot: - case HostPortal: { - var portalOrRoot = finishedWork.stateNode; - var containerInfo = portalOrRoot.containerInfo, - pendingChildren = portalOrRoot.pendingChildren; + case DehydratedFragment: { return; } - } - 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." - ); -} + case HostPortal: { + { + emptyPortalContainer(deletedFiber); + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + } -function commitDeletion(finishedRoot, current, nearestMountedAncestor) { - { - // Detach refs and call componentWillUnmount() on the whole subtree. - commitNestedUnmounts(finishedRoot, current, nearestMountedAncestor); - } + return; + } - detachFiberMutation(current); -} + case FunctionComponent: + case ForwardRef: + case MemoComponent: + case SimpleMemoComponent: { + { + var updateQueue = deletedFiber.updateQueue; -function commitWork(current, finishedWork) { - { - switch (finishedWork.tag) { - case FunctionComponent: - case ForwardRef: - case MemoComponent: - case SimpleMemoComponent: { - commitHookEffectListUnmount( - Insertion | HasEffect, - finishedWork, - finishedWork.return - ); - commitHookEffectListMount(Insertion | HasEffect, finishedWork); // 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. - // TODO: Check if we're inside an Offscreen subtree that disappeared - // during this commit. If so, we would have already unmounted its - // layout hooks. (However, since we null out the `destroy` function - // right before calling it, the behavior is already correct, so this - // would mostly be for modeling purposes.) + if (updateQueue !== null) { + var lastEffect = updateQueue.lastEffect; + + if (lastEffect !== null) { + var firstEffect = lastEffect.next; + var effect = firstEffect; + + do { + var _effect = effect, + destroy = _effect.destroy, + tag = _effect.tag; + + if (destroy !== undefined) { + if ((tag & Insertion) !== NoFlags$1) { + safelyCallDestroy( + deletedFiber, + nearestMountedAncestor, + destroy + ); + } else if ((tag & Layout) !== NoFlags$1) { + if (deletedFiber.mode & ProfileMode) { + startLayoutEffectTimer(); + safelyCallDestroy( + deletedFiber, + nearestMountedAncestor, + destroy + ); + recordLayoutEffectDuration(deletedFiber); + } else { + safelyCallDestroy( + deletedFiber, + nearestMountedAncestor, + destroy + ); + } + } + } - if (finishedWork.mode & ProfileMode) { - try { - startLayoutEffectTimer(); - commitHookEffectListUnmount( - Layout | HasEffect, - finishedWork, - finishedWork.return - ); - } finally { - recordLayoutEffectDuration(finishedWork); + effect = effect.next; + } while (effect !== firstEffect); } - } else { - commitHookEffectListUnmount( - Layout | HasEffect, - finishedWork, - finishedWork.return - ); } - - return; } - case Profiler: { - return; - } + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + return; + } - case SuspenseComponent: { - commitSuspenseCallback(finishedWork); - attachSuspenseRetryListeners(finishedWork); - return; + case ClassComponent: { + { + safelyDetachRef(deletedFiber, nearestMountedAncestor); + var instance = deletedFiber.stateNode; + + if (typeof instance.componentWillUnmount === "function") { + safelyCallComponentWillUnmount( + deletedFiber, + nearestMountedAncestor, + instance + ); + } } - case SuspenseListComponent: { - attachSuspenseRetryListeners(finishedWork); - return; - } + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + return; + } - case HostRoot: { - break; - } + case ScopeComponent: { + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + return; + } - case OffscreenComponent: - case LegacyHiddenComponent: { - return; + case OffscreenComponent: { + { + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); } + + break; } - commitContainer(finishedWork); - return; + default: { + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + return; + } } } @@ -18468,158 +19017,275 @@ function attachSuspenseRetryListeners(finishedWork) { }); } } // This function detects when a Suspense boundary goes from visible to hidden. - -function commitMutationEffects(root, firstChild, committedLanes) { +function commitMutationEffects(root, finishedWork, committedLanes) { inProgressLanes = committedLanes; inProgressRoot = root; - nextEffect = firstChild; - commitMutationEffects_begin(root, committedLanes); + setCurrentFiber(finishedWork); + commitMutationEffectsOnFiber(finishedWork, root); + setCurrentFiber(finishedWork); inProgressLanes = null; inProgressRoot = null; } -function commitMutationEffects_begin(root, lanes) { - while (nextEffect !== null) { - var fiber = nextEffect; // TODO: Should wrap this in flags check, too, as optimization +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); + } + } + } + + var prevDebugFiber = getCurrentFiber(); + + if (parentFiber.subtreeFlags & MutationMask) { + var child = parentFiber.child; + + while (child !== null) { + setCurrentFiber(child); + commitMutationEffectsOnFiber(child, root); + child = child.sibling; + } + } + + setCurrentFiber(prevDebugFiber); +} - var deletions = fiber.deletions; +function commitMutationEffectsOnFiber(finishedWork, root, lanes) { + var current = finishedWork.alternate; + var flags = finishedWork.flags; // The effect flag should be checked *after* we refine the type of fiber, + // because the fiber tag is more specific. An exception is any flag related + // to reconcilation, because those can be set on all fiber types. - if (deletions !== null) { - for (var i = 0; i < deletions.length; i++) { - var childToDelete = deletions[i]; + switch (finishedWork.tag) { + case FunctionComponent: + case ForwardRef: + case MemoComponent: + case SimpleMemoComponent: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + if (flags & Update) { try { - commitDeletion(root, childToDelete, fiber); + commitHookEffectListUnmount( + Insertion | HasEffect, + finishedWork, + finishedWork.return + ); + commitHookEffectListMount(Insertion | HasEffect, finishedWork); } catch (error) { - reportUncaughtErrorInDEV(error); - captureCommitPhaseError(childToDelete, fiber, error); + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } // Layout effects are destroyed during the mutation phase so that all + // destroy functions for all fibers are called before any create functions. + // This prevents sibling component effects from interfering with each other, + // e.g. a destroy function in one component should never override a ref set + // by a create function in another component during the same commit. + + if (finishedWork.mode & ProfileMode) { + try { + startLayoutEffectTimer(); + commitHookEffectListUnmount( + Layout | HasEffect, + finishedWork, + finishedWork.return + ); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } + + recordLayoutEffectDuration(finishedWork); + } else { + try { + commitHookEffectListUnmount( + Layout | HasEffect, + finishedWork, + finishedWork.return + ); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } + } + } + + return; + } + + case ClassComponent: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + + if (flags & Ref) { + if (current !== null) { + safelyDetachRef(current, current.return); } } + + return; } - var child = fiber.child; + case HostComponent: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); - if ((fiber.subtreeFlags & MutationMask) !== NoFlags && child !== null) { - ensureCorrectReturnPointer(child, fiber); - nextEffect = child; - } else { - commitMutationEffects_complete(root, lanes); + if (flags & Ref) { + if (current !== null) { + safelyDetachRef(current, current.return); + } + } + + return; } - } -} -function commitMutationEffects_complete(root, lanes) { - while (nextEffect !== null) { - var fiber = nextEffect; - setCurrentFiber(fiber); + case HostText: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); - try { - commitMutationEffectsOnFiber(fiber, root, lanes); - } catch (error) { - reportUncaughtErrorInDEV(error); - captureCommitPhaseError(fiber, fiber.return, error); + return; } - resetCurrentFiber(); - var sibling = fiber.sibling; + 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); + } + } + } - if (sibling !== null) { - ensureCorrectReturnPointer(sibling, fiber.return); - nextEffect = sibling; return; } - nextEffect = fiber.return; - } -} + case HostPortal: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); -function commitMutationEffectsOnFiber(finishedWork, root, lanes) { - // TODO: The factoring of this phase could probably be improved. Consider - // switching on the type of work before checking the flags. That's what - // we do in all the other phases. I think this one is only different - // because of the shared reconciliation logic below. - var flags = finishedWork.flags; + if (flags & Update) { + { + var portal = finishedWork.stateNode; + var _containerInfo = portal.containerInfo; + var _pendingChildren = portal.pendingChildren; - if (flags & Ref) { - var current = finishedWork.alternate; + try { + replaceContainerChildren(_containerInfo, _pendingChildren); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } + } + } - if (current !== null) { - commitDetachRef(current); + return; } - } - if (flags & Visibility) { - switch (finishedWork.tag) { - case SuspenseComponent: { - var newState = finishedWork.memoizedState; + 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 _current = finishedWork.alternate; - var wasHidden = _current !== null && _current.memoizedState !== null; + 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); + } + + attachSuspenseRetryListeners(finishedWork); } - case OffscreenComponent: { - var _newState = finishedWork.memoizedState; + return; + } - var _current2 = finishedWork.alternate; + case OffscreenComponent: { + var _wasHidden = current !== null && current.memoizedState !== null; - var _wasHidden = _current2 !== null && _current2.memoizedState !== null; + { + recursivelyTraverseMutationEffects(root, finishedWork); } - } - } // The following switch statement is only concerned about placement, - // updates, and deletions. To avoid needing to add a case for every possible - // bitmap value, we remove the secondary effects from the effect tag and - // switch on that value. - var primaryFlags = flags & (Placement | Update | Hydrating); + commitReconciliationEffects(finishedWork); - switch (primaryFlags) { - case Placement: { - // inserted, before any life-cycles like componentDidMount gets called. - // TODO: findDOMNode doesn't rely on this any more but isMounted does - // and isMounted is deprecated anyway so we should be able to kill this. + if (flags & Visibility) { + var _newState = finishedWork.memoizedState; + } - finishedWork.flags &= ~Placement; - break; + return; } - case PlacementAndUpdate: { - // inserted, before any life-cycles like componentDidMount gets called. + case SuspenseListComponent: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); - finishedWork.flags &= ~Placement; // Update + if (flags & Update) { + attachSuspenseRetryListeners(finishedWork); + } - var _current3 = finishedWork.alternate; - commitWork(_current3, finishedWork); - break; + return; } - case Hydrating: { - finishedWork.flags &= ~Hydrating; - break; + case ScopeComponent: { + return; } - case HydratingAndUpdate: { - finishedWork.flags &= ~Hydrating; // Update - - var _current4 = finishedWork.alternate; - commitWork(_current4, finishedWork); - break; + default: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + return; } + } +} - case Update: { - var _current5 = finishedWork.alternate; - commitWork(_current5, 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; + + if (flags & Placement) { + try { + commitPlacement(finishedWork); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } // Clear the "placement" from effect tag so that we know that this is + // inserted, before any life-cycles like componentDidMount gets called. + // TODO: findDOMNode doesn't rely on this any more but isMounted does + // and isMounted is deprecated anyway so we should be able to kill this. + + finishedWork.flags &= ~Placement; + } + + if (flags & Hydrating) { + finishedWork.flags &= ~Hydrating; } } @@ -18641,7 +19307,7 @@ function commitLayoutEffects_begin(subtreeRoot, root, committedLanes) { var firstChild = fiber.child; if ((fiber.subtreeFlags & LayoutMask) !== NoFlags && firstChild !== null) { - ensureCorrectReturnPointer(firstChild, fiber); + firstChild.return = fiber; nextEffect = firstChild; } else { commitLayoutMountEffects_complete(subtreeRoot, root, committedLanes); @@ -18660,7 +19326,6 @@ function commitLayoutMountEffects_complete(subtreeRoot, root, committedLanes) { try { commitLayoutEffectOnFiber(root, current, fiber, committedLanes); } catch (error) { - reportUncaughtErrorInDEV(error); captureCommitPhaseError(fiber, fiber.return, error); } @@ -18675,7 +19340,7 @@ function commitLayoutMountEffects_complete(subtreeRoot, root, committedLanes) { var sibling = fiber.sibling; if (sibling !== null) { - ensureCorrectReturnPointer(sibling, fiber.return); + sibling.return = fiber.return; nextEffect = sibling; return; } @@ -18684,26 +19349,51 @@ function commitLayoutMountEffects_complete(subtreeRoot, root, committedLanes) { } } -function commitPassiveMountEffects(root, finishedWork) { +function commitPassiveMountEffects( + root, + finishedWork, + committedLanes, + committedTransitions +) { nextEffect = finishedWork; - commitPassiveMountEffects_begin(finishedWork, root); + commitPassiveMountEffects_begin( + finishedWork, + root, + committedLanes, + committedTransitions + ); } -function commitPassiveMountEffects_begin(subtreeRoot, root) { +function commitPassiveMountEffects_begin( + subtreeRoot, + root, + committedLanes, + committedTransitions +) { while (nextEffect !== null) { var fiber = nextEffect; var firstChild = fiber.child; if ((fiber.subtreeFlags & PassiveMask) !== NoFlags && firstChild !== null) { - ensureCorrectReturnPointer(firstChild, fiber); + firstChild.return = fiber; nextEffect = firstChild; } else { - commitPassiveMountEffects_complete(subtreeRoot, root); + commitPassiveMountEffects_complete( + subtreeRoot, + root, + committedLanes, + committedTransitions + ); } } } -function commitPassiveMountEffects_complete(subtreeRoot, root) { +function commitPassiveMountEffects_complete( + subtreeRoot, + root, + committedLanes, + committedTransitions +) { while (nextEffect !== null) { var fiber = nextEffect; @@ -18711,9 +19401,13 @@ function commitPassiveMountEffects_complete(subtreeRoot, root) { setCurrentFiber(fiber); try { - commitPassiveMountOnFiber(root, fiber); + commitPassiveMountOnFiber( + root, + fiber, + committedLanes, + committedTransitions + ); } catch (error) { - reportUncaughtErrorInDEV(error); captureCommitPhaseError(fiber, fiber.return, error); } @@ -18728,7 +19422,7 @@ function commitPassiveMountEffects_complete(subtreeRoot, root) { var sibling = fiber.sibling; if (sibling !== null) { - ensureCorrectReturnPointer(sibling, fiber.return); + sibling.return = fiber.return; nextEffect = sibling; return; } @@ -18737,7 +19431,12 @@ function commitPassiveMountEffects_complete(subtreeRoot, root) { } } -function commitPassiveMountOnFiber(finishedRoot, finishedWork) { +function commitPassiveMountOnFiber( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions +) { switch (finishedWork.tag) { case FunctionComponent: case ForwardRef: @@ -18816,7 +19515,7 @@ function commitPassiveUnmountEffects_begin() { } if ((fiber.subtreeFlags & PassiveMask) !== NoFlags && child !== null) { - ensureCorrectReturnPointer(child, fiber); + child.return = fiber; nextEffect = child; } else { commitPassiveUnmountEffects_complete(); @@ -18837,7 +19536,7 @@ function commitPassiveUnmountEffects_complete() { var sibling = fiber.sibling; if (sibling !== null) { - ensureCorrectReturnPointer(sibling, fiber.return); + sibling.return = fiber.return; nextEffect = sibling; return; } @@ -18887,7 +19586,7 @@ function commitPassiveUnmountEffectsInsideOfDeletedTree_begin( // do this, still need to handle `deletedTreeCleanUpLevel` correctly.) if (child !== null) { - ensureCorrectReturnPointer(child, fiber); + child.return = fiber; nextEffect = child; } else { commitPassiveUnmountEffectsInsideOfDeletedTree_complete( @@ -18918,7 +19617,7 @@ function commitPassiveUnmountEffectsInsideOfDeletedTree_complete( } if (sibling !== null) { - ensureCorrectReturnPointer(sibling, returnFiber); + sibling.return = returnFiber; nextEffect = sibling; return; } @@ -18946,23 +19645,6 @@ function commitPassiveUnmountInsideDeletedTreeOnFiber( break; } } -} - -var didWarnWrongReturnPointer = false; - -function ensureCorrectReturnPointer(fiber, expectedReturnFiber) { - { - if (!didWarnWrongReturnPointer && fiber.return !== expectedReturnFiber) { - didWarnWrongReturnPointer = true; - - error( - "Internal React error: Return pointer is inconsistent " + "with parent." - ); - } - } // TODO: Remove this assignment once we're confident that it won't break - // anything, by checking the warning logs for the above invariant - - fiber.return = expectedReturnFiber; } // TODO: Reuse reappearLayoutEffects traversal here? var COMPONENT_TYPE = 0; @@ -19086,6 +19768,7 @@ var workInProgressRootRenderTargetTime = Infinity; // How long a render is suppo // suspense heuristics and opt out of rendering more content. var RENDER_TIMEOUT_MS = 500; +var workInProgressTransitions = null; function resetRenderTimer() { workInProgressRootRenderTargetTime = now() + RENDER_TIMEOUT_MS; @@ -19101,17 +19784,22 @@ var rootDoesHavePassiveEffects = false; var rootWithPendingPassiveEffects = null; var pendingPassiveEffectsLanes = NoLanes; var pendingPassiveProfilerEffects = []; +var pendingPassiveTransitions = null; // Use these to prevent an infinite loop of nested updates var NESTED_UPDATE_LIMIT = 50; var nestedUpdateCount = 0; var rootWithNestedUpdates = null; +var isFlushingPassiveEffects = false; +var didScheduleUpdateDuringPassiveEffects = false; var NESTED_PASSIVE_UPDATE_LIMIT = 50; -var nestedPassiveUpdateCount = 0; // If two updates are scheduled within the same event, we should treat their +var nestedPassiveUpdateCount = 0; +var rootWithPassiveNestedUpdates = null; // If two updates are scheduled within the same event, we should treat their // event times as simultaneous, even if the actual clock time has advanced // between the first and second call. var currentEventTime = NoTimestamp; var currentEventTransitionLane = NoLanes; +var isRunningInsertionEffect = false; function getWorkInProgressRoot() { return workInProgressRoot; } @@ -19214,10 +19902,23 @@ function requestRetryLane(fiber) { function scheduleUpdateOnFiber(fiber, lane, eventTime) { checkForNestedUpdates(); + + { + if (isRunningInsertionEffect) { + error("useInsertionEffect must not schedule updates."); + } + } + var root = markUpdateLaneFromFiberToRoot(fiber, lane); if (root === null) { return null; + } + + { + if (isFlushingPassiveEffects) { + didScheduleUpdateDuringPassiveEffects = true; + } } // Mark that the root has a pending update. markRootUpdated(root, lane, eventTime); @@ -19344,7 +20045,12 @@ function isInterleavedUpdate(fiber, lane) { // TODO: Optimize slightly by comparing to root that fiber belongs to. // Requires some refactoring. Not a big deal though since it's rare for // concurrent apps to have more than a single root. - workInProgressRoot !== null && + (workInProgressRoot !== null || // If the interleaved updates queue hasn't been cleared yet, then + // we should treat this as an interleaved update, too. This is also a + // defensive coding measure in case a new update comes in between when + // rendering has finished and when the interleaved updates are transferred + // to the main queue. + hasInterleavedUpdates()) && (fiber.mode & ConcurrentMode) !== NoMode && // If this is a render phase update (i.e. UNSAFE_componentWillReceiveProps), // then don't treat this as an interleaved update. This pattern is // accompanied by a warning but we haven't fully deprecated it yet. We can @@ -19678,7 +20384,11 @@ 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(root, workInProgressRootRecoverableErrors); + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); break; } @@ -19718,14 +20428,23 @@ function finishConcurrentRender(root, exitStatus, lanes) { // immediately, wait for more data to arrive. root.timeoutHandle = scheduleTimeout( - commitRoot.bind(null, root, workInProgressRootRecoverableErrors), + commitRoot.bind( + null, + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ), msUntilTimeout ); break; } } // The work expired. Commit immediately. - commitRoot(root, workInProgressRootRecoverableErrors); + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); break; } @@ -19756,20 +20475,33 @@ function finishConcurrentRender(root, exitStatus, lanes) { // Instead of committing the fallback immediately, wait for more data // to arrive. root.timeoutHandle = scheduleTimeout( - commitRoot.bind(null, root, workInProgressRootRecoverableErrors), + commitRoot.bind( + null, + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ), _msUntilTimeout ); break; } } // Commit the placeholder. - commitRoot(root, workInProgressRootRecoverableErrors); + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); break; } case RootCompleted: { // The work completed. Ready to commit. - commitRoot(root, workInProgressRootRecoverableErrors); + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); break; } @@ -19904,7 +20636,11 @@ function performSyncWorkOnRoot(root) { var finishedWork = root.current.alternate; root.finishedWork = finishedWork; root.finishedLanes = lanes; - commitRoot(root, workInProgressRootRecoverableErrors); // Before exiting, make sure there's a callback scheduled for the next + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); // Before exiting, make sure there's a callback scheduled for the next // pending level. ensureRootIsScheduled(root, now()); @@ -20211,6 +20947,8 @@ function renderRootSync(root, lanes) { movePendingFibersToMemoized(root, lanes); } } + + workInProgressTransitions = getTransitionsForLanes(); prepareFreshStack(root, lanes); } @@ -20271,6 +21009,8 @@ function renderRootConcurrent(root, lanes) { movePendingFibersToMemoized(root, lanes); } } + + workInProgressTransitions = getTransitionsForLanes(); resetRenderTimer(); prepareFreshStack(root, lanes); } @@ -20429,7 +21169,7 @@ function completeUnitOfWork(unitOfWork) { } } -function commitRoot(root, recoverableErrors) { +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(); @@ -20438,7 +21178,12 @@ function commitRoot(root, recoverableErrors) { try { ReactCurrentBatchConfig$2.transition = null; setCurrentUpdatePriority(DiscreteEventPriority); - commitRootImpl(root, recoverableErrors, previousUpdateLanePriority); + commitRootImpl( + root, + recoverableErrors, + transitions, + previousUpdateLanePriority + ); } finally { ReactCurrentBatchConfig$2.transition = prevTransition; setCurrentUpdatePriority(previousUpdateLanePriority); @@ -20447,7 +21192,12 @@ function commitRoot(root, recoverableErrors) { return null; } -function commitRootImpl(root, recoverableErrors, renderPriorityLevel) { +function commitRootImpl( + root, + recoverableErrors, + transitions, + renderPriorityLevel +) { do { // `flushPassiveEffects` will call `flushSyncUpdateQueue` at the end, which // means `flushPassiveEffects` will sometimes result in additional @@ -20515,6 +21265,13 @@ function commitRootImpl(root, recoverableErrors, renderPriorityLevel) { ) { if (!rootDoesHavePassiveEffects) { rootDoesHavePassiveEffects = true; + // to store it in pendingPassiveTransitions until they get processed + // We need to pass this through as an argument to commitRoot + // because workInProgressTransitions might have changed between + // the previous render and commit if we throttle the commit + // with setTimeout + + pendingPassiveTransitions = transitions; scheduleCallback$1(NormalPriority, function() { flushPassiveEffects(); // This render triggered passive effects: release the root cache pool // *after* passive effects fire to avoid freeing a cache pool that may @@ -20598,6 +21355,11 @@ function commitRootImpl(root, recoverableErrors, renderPriorityLevel) { rootDoesHavePassiveEffects = false; rootWithPendingPassiveEffects = root; pendingPassiveEffectsLanes = lanes; + } else { + { + nestedPassiveUpdateCount = 0; + rootWithPassiveNestedUpdates = null; + } } // Read this again, since an effect might have updated it remainingLanes = root.pendingLanes; // Check if there's remaining work on this root @@ -20725,9 +21487,12 @@ function enqueuePendingPassiveProfilerEffect(fiber) { function flushPassiveEffectsImpl() { if (rootWithPendingPassiveEffects === null) { return false; - } + } // Cache and clear the transitions flag + var transitions = pendingPassiveTransitions; + pendingPassiveTransitions = null; var root = rootWithPendingPassiveEffects; + var lanes = pendingPassiveEffectsLanes; rootWithPendingPassiveEffects = null; // TODO: This is sometimes out of sync with rootWithPendingPassiveEffects. // Figure out why and fix it. It's not causing any known issues (probably // because it's only used for profiling), but it's a refactor hazard. @@ -20738,10 +21503,15 @@ function flushPassiveEffectsImpl() { throw new Error("Cannot flush passive effects while already rendering."); } + { + isFlushingPassiveEffects = true; + didScheduleUpdateDuringPassiveEffects = false; + } + var prevExecutionContext = executionContext; executionContext |= CommitContext; commitPassiveUnmountEffects(root.current); - commitPassiveMountEffects(root, root.current); // TODO: Move to commitPassiveMountEffects + commitPassiveMountEffects(root, root.current, lanes, transitions); // TODO: Move to commitPassiveMountEffects { var profilerEffects = pendingPassiveProfilerEffects; @@ -20754,11 +21524,25 @@ function flushPassiveEffectsImpl() { } executionContext = prevExecutionContext; - flushSyncCallbacks(); // If additional passive effects were scheduled, increment a counter. If this - // exceeds the limit, we'll fire a warning. + flushSyncCallbacks(); + + { + // If additional passive effects were scheduled, increment a counter. If this + // exceeds the limit, we'll fire a warning. + if (didScheduleUpdateDuringPassiveEffects) { + if (root === rootWithPassiveNestedUpdates) { + nestedPassiveUpdateCount++; + } else { + nestedPassiveUpdateCount = 0; + rootWithPassiveNestedUpdates = root; + } + } else { + nestedPassiveUpdateCount = 0; + } - nestedPassiveUpdateCount = - rootWithPendingPassiveEffects === null ? 0 : nestedPassiveUpdateCount + 1; // TODO: Move to commitPassiveMountEffects + isFlushingPassiveEffects = false; + didScheduleUpdateDuringPassiveEffects = false; + } // TODO: Move to commitPassiveMountEffects onPostCommitRoot(root); @@ -20808,6 +21592,11 @@ function captureCommitPhaseErrorOnRoot(rootFiber, sourceFiber, error) { } function captureCommitPhaseError(sourceFiber, nearestMountedAncestor, error$1) { + { + reportUncaughtErrorInDEV(error$1); + setIsRunningInsertionEffect(false); + } + if (sourceFiber.tag === HostRoot) { // Error was thrown at the root. There is no parent, so the root // itself should capture it. @@ -20932,13 +21721,42 @@ function retryTimedOutBoundary(boundaryFiber, retryLane) { ensureRootIsScheduled(root, eventTime); } } + +function retryDehydratedSuspenseBoundary(boundaryFiber) { + var suspenseState = boundaryFiber.memoizedState; + var retryLane = NoLane; + + if (suspenseState !== null) { + retryLane = suspenseState.retryLane; + } + + retryTimedOutBoundary(boundaryFiber, retryLane); +} function resolveRetryWakeable(boundaryFiber, wakeable) { var retryLane = NoLane; // Default var retryCache; - { - retryCache = boundaryFiber.stateNode; + switch (boundaryFiber.tag) { + case SuspenseComponent: + retryCache = boundaryFiber.stateNode; + var suspenseState = boundaryFiber.memoizedState; + + if (suspenseState !== null) { + retryLane = suspenseState.retryLane; + } + + break; + + case SuspenseListComponent: + retryCache = boundaryFiber.stateNode; + break; + + default: + throw new Error( + "Pinged unknown suspense boundary type. " + + "This is probably a bug in React." + ); } if (retryCache !== null) { @@ -20989,6 +21807,7 @@ function checkForNestedUpdates() { { if (nestedPassiveUpdateCount > NESTED_PASSIVE_UPDATE_LIMIT) { nestedPassiveUpdateCount = 0; + rootWithPassiveNestedUpdates = null; error( "Maximum update depth exceeded. This can happen when a component " + @@ -21092,11 +21911,13 @@ var beginWork$1; return beginWork(current, unitOfWork, lanes); } catch (originalError) { if ( - originalError !== null && - typeof originalError === "object" && - typeof originalError.then === "function" + didSuspendOrErrorWhileHydratingDEV() || + (originalError !== null && + typeof originalError === "object" && + typeof originalError.then === "function") ) { - // Don't replay promises. Treat everything else like an error. + // Don't replay promises. + // Don't replay errors if we are hydrating and have already suspended or handled an error throw originalError; } // Keep this code in sync with handleError; any changes here must have // corresponding changes there. @@ -21322,6 +22143,12 @@ function warnIfSuspenseResolutionNotWrappedWithActDEV(root) { } } +function setIsRunningInsertionEffect(isRunning) { + { + isRunningInsertionEffect = isRunning; + } +} + /* eslint-disable react-internal/prod-error-codes */ var resolveFamily = null; // $FlowFixMe Flow gets confused by a WeakSet feature check below. @@ -22456,7 +23283,8 @@ function createFiberRoot( isDehydrated: hydrate, cache: null, // not enabled yet - transitions: null + transitions: null, + pendingSuspenseBoundaries: null }; uninitializedFiber.memoizedState = _initialState; } @@ -22465,7 +23293,7 @@ function createFiberRoot( return root; } -var ReactVersion = "18.0.0-34aa5cfe0-20220329"; +var ReactVersion = "18.2.0-next-d300cebde-20220601"; function createPortal( children, diff --git a/Libraries/Renderer/implementations/ReactFabric-prod.js b/Libraries/Renderer/implementations/ReactFabric-prod.js index 679ac7c7a33f14..9f83af5c81ecf0 100644 --- a/Libraries/Renderer/implementations/ReactFabric-prod.js +++ b/Libraries/Renderer/implementations/ReactFabric-prod.js @@ -8,7 +8,7 @@ * @nolint * @providesModule ReactFabric-prod * @preventMunge - * @generated SignedSource<<3337b7b8b4a72069e657cf2646bcff44>> + * @generated SignedSource<> */ "use strict"; @@ -1017,7 +1017,7 @@ eventPluginOrder = Array.prototype.slice.call([ "ReactNativeBridgeEventPlugin" ]); recomputePluginOrdering(); -var injectedNamesToPlugins$jscomp$inline_215 = { +var injectedNamesToPlugins$jscomp$inline_218 = { ResponderEventPlugin: ResponderEventPlugin, ReactNativeBridgeEventPlugin: { eventTypes: {}, @@ -1063,33 +1063,33 @@ var injectedNamesToPlugins$jscomp$inline_215 = { } } }, - isOrderingDirty$jscomp$inline_216 = !1, - pluginName$jscomp$inline_217; -for (pluginName$jscomp$inline_217 in injectedNamesToPlugins$jscomp$inline_215) + isOrderingDirty$jscomp$inline_219 = !1, + pluginName$jscomp$inline_220; +for (pluginName$jscomp$inline_220 in injectedNamesToPlugins$jscomp$inline_218) if ( - injectedNamesToPlugins$jscomp$inline_215.hasOwnProperty( - pluginName$jscomp$inline_217 + injectedNamesToPlugins$jscomp$inline_218.hasOwnProperty( + pluginName$jscomp$inline_220 ) ) { - var pluginModule$jscomp$inline_218 = - injectedNamesToPlugins$jscomp$inline_215[pluginName$jscomp$inline_217]; + var pluginModule$jscomp$inline_221 = + injectedNamesToPlugins$jscomp$inline_218[pluginName$jscomp$inline_220]; if ( - !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_217) || - namesToPlugins[pluginName$jscomp$inline_217] !== - pluginModule$jscomp$inline_218 + !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_220) || + namesToPlugins[pluginName$jscomp$inline_220] !== + pluginModule$jscomp$inline_221 ) { - if (namesToPlugins[pluginName$jscomp$inline_217]) + if (namesToPlugins[pluginName$jscomp$inline_220]) throw Error( "EventPluginRegistry: Cannot inject two different event plugins using the same name, `" + - (pluginName$jscomp$inline_217 + "`.") + (pluginName$jscomp$inline_220 + "`.") ); namesToPlugins[ - pluginName$jscomp$inline_217 - ] = pluginModule$jscomp$inline_218; - isOrderingDirty$jscomp$inline_216 = !0; + pluginName$jscomp$inline_220 + ] = pluginModule$jscomp$inline_221; + isOrderingDirty$jscomp$inline_219 = !0; } } -isOrderingDirty$jscomp$inline_216 && recomputePluginOrdering(); +isOrderingDirty$jscomp$inline_219 && recomputePluginOrdering(); function getInstanceFromInstance(instanceHandle) { return instanceHandle; } @@ -1841,6 +1841,12 @@ function getLanesToRetrySynchronouslyOnError(root) { root = root.pendingLanes & -1073741825; return 0 !== root ? root : root & 1073741824 ? 1073741824 : 0; } +function claimNextTransitionLane() { + var lane = nextTransitionLane; + nextTransitionLane <<= 1; + 0 === (nextTransitionLane & 4194240) && (nextTransitionLane = 64); + return lane; +} function createLaneMap(initial) { for (var laneMap = [], i = 0; 31 > i; i++) laneMap.push(initial); return laneMap; @@ -2189,7 +2195,28 @@ function flushSyncCallbacks() { } return null; } -var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig; +var forkStack = [], + forkStackIndex = 0, + treeForkProvider = null, + idStack = [], + idStackIndex = 0, + treeContextProvider = null; +function popTreeContext(workInProgress) { + for (; workInProgress === treeForkProvider; ) + (treeForkProvider = forkStack[--forkStackIndex]), + (forkStack[forkStackIndex] = null), + --forkStackIndex, + (forkStack[forkStackIndex] = null); + for (; workInProgress === treeContextProvider; ) + (treeContextProvider = idStack[--idStackIndex]), + (idStack[idStackIndex] = null), + --idStackIndex, + (idStack[idStackIndex] = null), + --idStackIndex, + (idStack[idStackIndex] = null); +} +var hydrationErrors = null, + ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig; function shallowEqual(objA, objB) { if (objectIs(objA, objB)) return !0; if ( @@ -2334,9 +2361,7 @@ function enqueueUpdate(fiber, update) { var updateQueue = fiber.updateQueue; null !== updateQueue && ((updateQueue = updateQueue.shared), - null !== workInProgressRoot && - 0 !== (fiber.mode & 1) && - 0 === (executionContext & 2) + isInterleavedUpdate(fiber) ? ((fiber = updateQueue.interleaved), null === fiber ? ((update.next = update), @@ -2704,26 +2729,6 @@ function mountClassInstance(workInProgress, ctor, newProps, renderLanes) { "function" === typeof instance.componentDidMount && (workInProgress.flags |= 4); } -var forkStack = [], - forkStackIndex = 0, - treeForkProvider = null, - idStack = [], - idStackIndex = 0, - treeContextProvider = null; -function popTreeContext(workInProgress) { - for (; workInProgress === treeForkProvider; ) - (treeForkProvider = forkStack[--forkStackIndex]), - (forkStack[forkStackIndex] = null), - --forkStackIndex, - (forkStack[forkStackIndex] = null); - for (; workInProgress === treeContextProvider; ) - (treeContextProvider = idStack[--idStackIndex]), - (idStack[idStackIndex] = null), - --idStackIndex, - (idStack[idStackIndex] = null), - --idStackIndex, - (idStack[idStackIndex] = null); -} function coerceRef(returnFiber, current, element) { returnFiber = element.ref; if ( @@ -2786,6 +2791,10 @@ function throwOnInvalidObjectType(returnFiber, newChild) { "). If you meant to render a collection of children, use an array instead." ); } +function resolveLazy(lazyType) { + var init = lazyType._init; + return init(lazyType._payload); +} function ChildReconciler(shouldTrackSideEffects) { function deleteChild(returnFiber, childToDelete) { if (shouldTrackSideEffects) { @@ -2858,7 +2867,14 @@ function ChildReconciler(shouldTrackSideEffects) { lanes, element.key ); - if (null !== current && current.elementType === elementType) + if ( + null !== current && + (current.elementType === elementType || + ("object" === typeof elementType && + null !== elementType && + elementType.$$typeof === REACT_LAZY_TYPE && + resolveLazy(elementType) === current.type)) + ) return ( (lanes = useFiber(current, element.props)), (lanes.ref = coerceRef(returnFiber, current, element)), @@ -2949,6 +2965,9 @@ function ChildReconciler(shouldTrackSideEffects) { (newChild.return = returnFiber), newChild ); + case REACT_LAZY_TYPE: + var init = newChild._init; + return createChild(returnFiber, init(newChild._payload), lanes); } if (isArrayImpl(newChild) || getIteratorFn(newChild)) return ( @@ -2984,6 +3003,11 @@ function ChildReconciler(shouldTrackSideEffects) { return newChild.key === key ? updatePortal(returnFiber, oldFiber, newChild, lanes) : null; + case REACT_LAZY_TYPE: + return ( + (key = newChild._init), + updateSlot(returnFiber, oldFiber, key(newChild._payload), lanes) + ); } if (isArrayImpl(newChild) || getIteratorFn(newChild)) return null !== key @@ -3026,6 +3050,15 @@ function ChildReconciler(shouldTrackSideEffects) { ) || null), updatePortal(returnFiber, existingChildren, newChild, lanes) ); + case REACT_LAZY_TYPE: + var init = newChild._init; + return updateFromMap( + existingChildren, + returnFiber, + newIdx, + init(newChild._payload), + lanes + ); } if (isArrayImpl(newChild) || getIteratorFn(newChild)) return ( @@ -3203,7 +3236,12 @@ function ChildReconciler(shouldTrackSideEffects) { }); return iteratorFn; } - return function(returnFiber, currentFirstChild, newChild, lanes) { + function reconcileChildFibers( + returnFiber, + currentFirstChild, + newChild, + lanes + ) { "object" === typeof newChild && null !== newChild && newChild.type === REACT_FRAGMENT_TYPE && @@ -3231,7 +3269,13 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber = currentFirstChild; break a; } - } else if (child.elementType === key) { + } else if ( + child.elementType === key || + ("object" === typeof key && + null !== key && + key.$$typeof === REACT_LAZY_TYPE && + resolveLazy(key) === child.type) + ) { deleteRemainingChildren(returnFiber, child.sibling); currentFirstChild = useFiber(child, newChild.props); currentFirstChild.ref = coerceRef( @@ -3312,6 +3356,16 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber = currentFirstChild; } return placeSingleChild(returnFiber); + case REACT_LAZY_TYPE: + return ( + (child = newChild._init), + reconcileChildFibers( + returnFiber, + currentFirstChild, + child(newChild._payload), + lanes + ) + ); } if (isArrayImpl(newChild)) return reconcileChildrenArray( @@ -3347,7 +3401,8 @@ function ChildReconciler(shouldTrackSideEffects) { (returnFiber = currentFirstChild)), placeSingleChild(returnFiber)) : deleteRemainingChildren(returnFiber, currentFirstChild); - }; + } + return reconcileChildFibers; } var reconcileChildFibers = ChildReconciler(!0), mountChildFibers = ChildReconciler(!1), @@ -3834,6 +3889,19 @@ function updateMemo(nextCreate, deps) { hook.memoizedState = [nextCreate, deps]; return nextCreate; } +function updateDeferredValueImpl(hook, prevValue, value) { + if (0 === (renderLanes & 21)) + return ( + hook.baseState && ((hook.baseState = !1), (didReceiveUpdate = !0)), + (hook.memoizedState = value) + ); + objectIs(value, prevValue) || + ((value = claimNextTransitionLane()), + (currentlyRenderingFiber$1.lanes |= value), + (workInProgressRootSkippedLanes |= value), + (hook.baseState = !0)); + return prevValue; +} function startTransition(setPending, callback) { var previousPriority = currentUpdatePriority; currentUpdatePriority = @@ -3915,9 +3983,7 @@ function enqueueRenderPhaseUpdate(queue, update) { queue.pending = update; } function enqueueUpdate$1(fiber, queue, update) { - null !== workInProgressRoot && - 0 !== (fiber.mode & 1) && - 0 === (executionContext & 2) + isInterleavedUpdate(fiber) ? ((fiber = queue.interleaved), null === fiber ? ((update.next = update), @@ -4022,29 +4088,14 @@ var ContextOnlyDispatcher = { useState: mountState, useDebugValue: mountDebugValue, useDeferredValue: function(value) { - var _mountState = mountState(value), - prevValue = _mountState[0], - setValue = _mountState[1]; - mountEffect( - function() { - var prevTransition = ReactCurrentBatchConfig$1.transition; - ReactCurrentBatchConfig$1.transition = {}; - try { - setValue(value); - } finally { - ReactCurrentBatchConfig$1.transition = prevTransition; - } - }, - [value] - ); - return prevValue; + return (mountWorkInProgressHook().memoizedState = value); }, useTransition: function() { - var _mountState2 = mountState(!1), - isPending = _mountState2[0]; - _mountState2 = startTransition.bind(null, _mountState2[1]); - mountWorkInProgressHook().memoizedState = _mountState2; - return [isPending, _mountState2]; + var _mountState = mountState(!1), + isPending = _mountState[0]; + _mountState = startTransition.bind(null, _mountState[1]); + mountWorkInProgressHook().memoizedState = _mountState; + return [isPending, _mountState]; }, useMutableSource: function() {}, useSyncExternalStore: function(subscribe, getSnapshot) { @@ -4098,22 +4149,8 @@ var ContextOnlyDispatcher = { }, useDebugValue: mountDebugValue, useDeferredValue: function(value) { - var _updateState = updateReducer(basicStateReducer), - prevValue = _updateState[0], - setValue = _updateState[1]; - updateEffect( - function() { - var prevTransition = ReactCurrentBatchConfig$1.transition; - ReactCurrentBatchConfig$1.transition = {}; - try { - setValue(value); - } finally { - ReactCurrentBatchConfig$1.transition = prevTransition; - } - }, - [value] - ); - return prevValue; + var hook = updateWorkInProgressHook(); + return updateDeferredValueImpl(hook, currentHook.memoizedState, value); }, useTransition: function() { var isPending = updateReducer(basicStateReducer)[0], @@ -4141,22 +4178,10 @@ var ContextOnlyDispatcher = { }, useDebugValue: mountDebugValue, useDeferredValue: function(value) { - var _rerenderState = rerenderReducer(basicStateReducer), - prevValue = _rerenderState[0], - setValue = _rerenderState[1]; - updateEffect( - function() { - var prevTransition = ReactCurrentBatchConfig$1.transition; - ReactCurrentBatchConfig$1.transition = {}; - try { - setValue(value); - } finally { - ReactCurrentBatchConfig$1.transition = prevTransition; - } - }, - [value] - ); - return prevValue; + var hook = updateWorkInProgressHook(); + return null === currentHook + ? (hook.memoizedState = value) + : updateDeferredValueImpl(hook, currentHook.memoizedState, value); }, useTransition: function() { var isPending = rerenderReducer(basicStateReducer)[0], @@ -4259,592 +4284,94 @@ function attachPingListener(root, wakeable, lanes) { (root = pingSuspendedRoot.bind(null, root, wakeable, lanes)), wakeable.then(root, root)); } -function hadNoMutationsEffects(current, completedWork) { - if (null !== current && current.child === completedWork.child) return !0; - if (0 !== (completedWork.flags & 16)) return !1; - for (current = completedWork.child; null !== current; ) { - if (0 !== (current.flags & 12854) || 0 !== (current.subtreeFlags & 12854)) - return !1; - current = current.sibling; - } - return !0; +var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner, + didReceiveUpdate = !1; +function reconcileChildren(current, workInProgress, nextChildren, renderLanes) { + workInProgress.child = + null === current + ? mountChildFibers(workInProgress, null, nextChildren, renderLanes) + : reconcileChildFibers( + workInProgress, + current.child, + nextChildren, + renderLanes + ); } -var appendAllChildren, updateHostContainer, updateHostComponent, updateHostText; -appendAllChildren = function( - parent, +function updateForwardRef( + current, workInProgress, - needsVisibilityToggle, - isHidden + Component, + nextProps, + renderLanes ) { - for (var node = workInProgress.child; null !== node; ) { - if (5 === node.tag) { - var instance = node.stateNode; - needsVisibilityToggle && - isHidden && - (instance = cloneHiddenInstance(instance)); - appendChildNode(parent.node, instance.node); - } else if (6 === node.tag) { - instance = node.stateNode; - if (needsVisibilityToggle && isHidden) - throw Error("Not yet implemented."); - appendChildNode(parent.node, instance.node); - } else if (4 !== node.tag) - if (22 === node.tag && null !== node.memoizedState) - (instance = node.child), - null !== instance && (instance.return = node), - appendAllChildren(parent, node, !0, !0); - else if (null !== node.child) { - node.child.return = node; - node = node.child; - continue; - } - if (node === workInProgress) break; - for (; null === node.sibling; ) { - if (null === node.return || node.return === workInProgress) return; - node = node.return; - } - node.sibling.return = node.return; - node = node.sibling; - } -}; -function appendAllChildrenToContainer( - containerChildSet, + Component = Component.render; + var ref = workInProgress.ref; + prepareToReadContext(workInProgress, renderLanes); + nextProps = renderWithHooks( + current, + workInProgress, + Component, + nextProps, + ref, + renderLanes + ); + if (null !== current && !didReceiveUpdate) + return ( + (workInProgress.updateQueue = current.updateQueue), + (workInProgress.flags &= -2053), + (current.lanes &= ~renderLanes), + bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) + ); + workInProgress.flags |= 1; + reconcileChildren(current, workInProgress, nextProps, renderLanes); + return workInProgress.child; +} +function updateMemoComponent( + current, workInProgress, - needsVisibilityToggle, - isHidden + Component, + nextProps, + renderLanes ) { - for (var node = workInProgress.child; null !== node; ) { - if (5 === node.tag) { - var instance = node.stateNode; - needsVisibilityToggle && - isHidden && - (instance = cloneHiddenInstance(instance)); - appendChildNodeToSet(containerChildSet, instance.node); - } else if (6 === node.tag) { - instance = node.stateNode; - if (needsVisibilityToggle && isHidden) - throw Error("Not yet implemented."); - appendChildNodeToSet(containerChildSet, instance.node); - } else if (4 !== node.tag) - if (22 === node.tag && null !== node.memoizedState) - (instance = node.child), - null !== instance && (instance.return = node), - appendAllChildrenToContainer(containerChildSet, node, !0, !0); - else if (null !== node.child) { - node.child.return = node; - node = node.child; - continue; - } - if (node === workInProgress) break; - for (; null === node.sibling; ) { - if (null === node.return || node.return === workInProgress) return; - node = node.return; - } - node.sibling.return = node.return; - node = node.sibling; + if (null === current) { + var type = Component.type; + if ( + "function" === typeof type && + !shouldConstruct(type) && + void 0 === type.defaultProps && + null === Component.compare && + void 0 === Component.defaultProps + ) + return ( + (workInProgress.tag = 15), + (workInProgress.type = type), + updateSimpleMemoComponent( + current, + workInProgress, + type, + nextProps, + renderLanes + ) + ); + current = createFiberFromTypeAndProps( + Component.type, + null, + nextProps, + workInProgress, + workInProgress.mode, + renderLanes + ); + current.ref = workInProgress.ref; + current.return = workInProgress; + return (workInProgress.child = current); } -} -updateHostContainer = function(current, workInProgress) { - var portalOrRoot = workInProgress.stateNode; - if (!hadNoMutationsEffects(current, workInProgress)) { - current = portalOrRoot.containerInfo; - var newChildSet = createChildNodeSet(current); - appendAllChildrenToContainer(newChildSet, workInProgress, !1, !1); - portalOrRoot.pendingChildren = newChildSet; - workInProgress.flags |= 4; - completeRoot(current, newChildSet); - } -}; -updateHostComponent = function(current, workInProgress, type, newProps) { - type = current.stateNode; - var oldProps = current.memoizedProps; - if ( - (current = hadNoMutationsEffects(current, workInProgress)) && - oldProps === newProps - ) - workInProgress.stateNode = type; - else { - var recyclableInstance = workInProgress.stateNode; - requiredContext(contextStackCursor$1.current); - var updatePayload = null; - oldProps !== newProps && - ((oldProps = diffProperties( - null, - oldProps, - newProps, - recyclableInstance.canonical.viewConfig.validAttributes - )), - (recyclableInstance.canonical.currentProps = newProps), - (updatePayload = oldProps)); - current && null === updatePayload - ? (workInProgress.stateNode = type) - : ((newProps = updatePayload), - (oldProps = type.node), - (type = { - node: current - ? null !== newProps - ? cloneNodeWithNewProps(oldProps, newProps) - : cloneNode(oldProps) - : null !== newProps - ? cloneNodeWithNewChildrenAndProps(oldProps, newProps) - : cloneNodeWithNewChildren(oldProps), - canonical: type.canonical - }), - (workInProgress.stateNode = type), - current - ? (workInProgress.flags |= 4) - : appendAllChildren(type, workInProgress, !1, !1)); - } -}; -updateHostText = function(current, workInProgress, oldText, newText) { - oldText !== newText - ? ((current = requiredContext(rootInstanceStackCursor.current)), - (oldText = requiredContext(contextStackCursor$1.current)), - (workInProgress.stateNode = createTextInstance( - newText, - current, - oldText, - workInProgress - )), - (workInProgress.flags |= 4)) - : (workInProgress.stateNode = current.stateNode); -}; -function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { - switch (renderState.tailMode) { - case "hidden": - hasRenderedATailFallback = renderState.tail; - for (var lastTailNode = null; null !== hasRenderedATailFallback; ) - null !== hasRenderedATailFallback.alternate && - (lastTailNode = hasRenderedATailFallback), - (hasRenderedATailFallback = hasRenderedATailFallback.sibling); - null === lastTailNode - ? (renderState.tail = null) - : (lastTailNode.sibling = null); - break; - case "collapsed": - lastTailNode = renderState.tail; - for (var lastTailNode$35 = null; null !== lastTailNode; ) - null !== lastTailNode.alternate && (lastTailNode$35 = lastTailNode), - (lastTailNode = lastTailNode.sibling); - null === lastTailNode$35 - ? hasRenderedATailFallback || null === renderState.tail - ? (renderState.tail = null) - : (renderState.tail.sibling = null) - : (lastTailNode$35.sibling = null); - } -} -function bubbleProperties(completedWork) { - var didBailout = - null !== completedWork.alternate && - completedWork.alternate.child === completedWork.child, - newChildLanes = 0, - subtreeFlags = 0; - if (didBailout) - for (var child$36 = completedWork.child; null !== child$36; ) - (newChildLanes |= child$36.lanes | child$36.childLanes), - (subtreeFlags |= child$36.subtreeFlags & 14680064), - (subtreeFlags |= child$36.flags & 14680064), - (child$36.return = completedWork), - (child$36 = child$36.sibling); - else - for (child$36 = completedWork.child; null !== child$36; ) - (newChildLanes |= child$36.lanes | child$36.childLanes), - (subtreeFlags |= child$36.subtreeFlags), - (subtreeFlags |= child$36.flags), - (child$36.return = completedWork), - (child$36 = child$36.sibling); - completedWork.subtreeFlags |= subtreeFlags; - completedWork.childLanes = newChildLanes; - return didBailout; -} -function completeWork(current, workInProgress, renderLanes) { - var newProps = workInProgress.pendingProps; - popTreeContext(workInProgress); - switch (workInProgress.tag) { - case 2: - case 16: - case 15: - case 0: - case 11: - case 7: - case 8: - case 12: - case 9: - case 14: - return bubbleProperties(workInProgress), null; - case 1: - return ( - isContextProvider(workInProgress.type) && popContext(), - bubbleProperties(workInProgress), - null - ); - case 3: - return ( - (newProps = workInProgress.stateNode), - popHostContainer(), - pop(didPerformWorkStackCursor), - pop(contextStackCursor), - resetWorkInProgressVersions(), - newProps.pendingContext && - ((newProps.context = newProps.pendingContext), - (newProps.pendingContext = null)), - (null !== current && null !== current.child) || - null === current || - (current.memoizedState.isDehydrated && - 0 === (workInProgress.flags & 256)) || - (workInProgress.flags |= 1024), - updateHostContainer(current, workInProgress), - bubbleProperties(workInProgress), - null - ); - case 5: - popHostContext(workInProgress); - renderLanes = requiredContext(rootInstanceStackCursor.current); - var type = workInProgress.type; - if (null !== current && null != workInProgress.stateNode) - updateHostComponent( - current, - workInProgress, - type, - newProps, - renderLanes - ), - current.ref !== workInProgress.ref && (workInProgress.flags |= 512); - else { - if (!newProps) { - if (null === workInProgress.stateNode) - throw Error( - "We must have new props for new mounts. This error is likely caused by a bug in React. Please file an issue." - ); - bubbleProperties(workInProgress); - return null; - } - requiredContext(contextStackCursor$1.current); - current = nextReactTag; - nextReactTag += 2; - type = getViewConfigForType(type); - var updatePayload = diffProperties( - null, - emptyObject, - newProps, - type.validAttributes - ); - renderLanes = createNode( - current, - type.uiViewClassName, - renderLanes, - updatePayload, - workInProgress - ); - current = new ReactFabricHostComponent( - current, - type, - newProps, - workInProgress - ); - current = { node: renderLanes, canonical: current }; - appendAllChildren(current, workInProgress, !1, !1); - workInProgress.stateNode = current; - null !== workInProgress.ref && (workInProgress.flags |= 512); - } - bubbleProperties(workInProgress); - return null; - case 6: - if (current && null != workInProgress.stateNode) - updateHostText( - current, - workInProgress, - current.memoizedProps, - newProps - ); - else { - if ("string" !== typeof newProps && null === workInProgress.stateNode) - throw Error( - "We must have new props for new mounts. This error is likely caused by a bug in React. Please file an issue." - ); - current = requiredContext(rootInstanceStackCursor.current); - renderLanes = requiredContext(contextStackCursor$1.current); - workInProgress.stateNode = createTextInstance( - newProps, - current, - renderLanes, - workInProgress - ); - } - bubbleProperties(workInProgress); - return null; - case 13: - pop(suspenseStackCursor); - newProps = workInProgress.memoizedState; - if (0 !== (workInProgress.flags & 128)) - return (workInProgress.lanes = renderLanes), workInProgress; - renderLanes = !1; - null !== current && (renderLanes = null !== current.memoizedState); - null === newProps || - renderLanes || - ((workInProgress.child.flags |= 8192), - 0 !== (workInProgress.mode & 1) && - (null === current || 0 !== (suspenseStackCursor.current & 1) - ? 0 === workInProgressRootExitStatus && - (workInProgressRootExitStatus = 3) - : renderDidSuspendDelayIfPossible())); - null !== workInProgress.updateQueue && (workInProgress.flags |= 4); - bubbleProperties(workInProgress); - return null; - case 4: - return ( - popHostContainer(), - updateHostContainer(current, workInProgress), - bubbleProperties(workInProgress), - null - ); - case 10: - return ( - popProvider(workInProgress.type._context), - bubbleProperties(workInProgress), - null - ); - case 17: - return ( - isContextProvider(workInProgress.type) && popContext(), - bubbleProperties(workInProgress), - null - ); - case 19: - pop(suspenseStackCursor); - type = workInProgress.memoizedState; - if (null === type) return bubbleProperties(workInProgress), null; - newProps = 0 !== (workInProgress.flags & 128); - updatePayload = type.rendering; - if (null === updatePayload) - if (newProps) cutOffTailIfNeeded(type, !1); - else { - if ( - 0 !== workInProgressRootExitStatus || - (null !== current && 0 !== (current.flags & 128)) - ) - for (current = workInProgress.child; null !== current; ) { - updatePayload = findFirstSuspended(current); - if (null !== updatePayload) { - workInProgress.flags |= 128; - cutOffTailIfNeeded(type, !1); - current = updatePayload.updateQueue; - null !== current && - ((workInProgress.updateQueue = current), - (workInProgress.flags |= 4)); - workInProgress.subtreeFlags = 0; - current = renderLanes; - for (newProps = workInProgress.child; null !== newProps; ) - (renderLanes = newProps), - (type = current), - (renderLanes.flags &= 14680066), - (updatePayload = renderLanes.alternate), - null === updatePayload - ? ((renderLanes.childLanes = 0), - (renderLanes.lanes = type), - (renderLanes.child = null), - (renderLanes.subtreeFlags = 0), - (renderLanes.memoizedProps = null), - (renderLanes.memoizedState = null), - (renderLanes.updateQueue = null), - (renderLanes.dependencies = null), - (renderLanes.stateNode = null)) - : ((renderLanes.childLanes = updatePayload.childLanes), - (renderLanes.lanes = updatePayload.lanes), - (renderLanes.child = updatePayload.child), - (renderLanes.subtreeFlags = 0), - (renderLanes.deletions = null), - (renderLanes.memoizedProps = - updatePayload.memoizedProps), - (renderLanes.memoizedState = - updatePayload.memoizedState), - (renderLanes.updateQueue = updatePayload.updateQueue), - (renderLanes.type = updatePayload.type), - (type = updatePayload.dependencies), - (renderLanes.dependencies = - null === type - ? null - : { - lanes: type.lanes, - firstContext: type.firstContext - })), - (newProps = newProps.sibling); - push( - suspenseStackCursor, - (suspenseStackCursor.current & 1) | 2 - ); - return workInProgress.child; - } - current = current.sibling; - } - null !== type.tail && - now() > workInProgressRootRenderTargetTime && - ((workInProgress.flags |= 128), - (newProps = !0), - cutOffTailIfNeeded(type, !1), - (workInProgress.lanes = 4194304)); - } - else { - if (!newProps) - if ( - ((current = findFirstSuspended(updatePayload)), null !== current) - ) { - if ( - ((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 && - !updatePayload.alternate) - ) - return bubbleProperties(workInProgress), null; - } else - 2 * now() - type.renderingStartTime > - workInProgressRootRenderTargetTime && - 1073741824 !== renderLanes && - ((workInProgress.flags |= 128), - (newProps = !0), - cutOffTailIfNeeded(type, !1), - (workInProgress.lanes = 4194304)); - type.isBackwards - ? ((updatePayload.sibling = workInProgress.child), - (workInProgress.child = updatePayload)) - : ((current = type.last), - null !== current - ? (current.sibling = updatePayload) - : (workInProgress.child = updatePayload), - (type.last = updatePayload)); - } - if (null !== type.tail) - return ( - (workInProgress = type.tail), - (type.rendering = workInProgress), - (type.tail = workInProgress.sibling), - (type.renderingStartTime = now()), - (workInProgress.sibling = null), - (current = suspenseStackCursor.current), - push(suspenseStackCursor, newProps ? (current & 1) | 2 : current & 1), - workInProgress - ); - bubbleProperties(workInProgress); - return null; - case 22: - case 23: - return ( - popRenderLanes(), - (newProps = null !== workInProgress.memoizedState), - null !== current && - (null !== current.memoizedState) !== newProps && - (workInProgress.flags |= 8192), - newProps && 0 !== (workInProgress.mode & 1) - ? 0 !== (subtreeRenderLanes & 1073741824) && - bubbleProperties(workInProgress) - : bubbleProperties(workInProgress), - null - ); - case 24: - return null; - case 25: - return null; - } - throw Error( - "Unknown unit of work tag (" + - workInProgress.tag + - "). This error is likely caused by a bug in React. Please file an issue." - ); -} -var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner, - didReceiveUpdate = !1; -function reconcileChildren(current, workInProgress, nextChildren, renderLanes) { - workInProgress.child = - null === current - ? mountChildFibers(workInProgress, null, nextChildren, renderLanes) - : reconcileChildFibers( - workInProgress, - current.child, - nextChildren, - renderLanes - ); -} -function updateForwardRef( - current, - workInProgress, - Component, - nextProps, - renderLanes -) { - Component = Component.render; - var ref = workInProgress.ref; - prepareToReadContext(workInProgress, renderLanes); - nextProps = renderWithHooks( - current, - workInProgress, - Component, - nextProps, - ref, - renderLanes - ); - if (null !== current && !didReceiveUpdate) - return ( - (workInProgress.updateQueue = current.updateQueue), - (workInProgress.flags &= -2053), - (current.lanes &= ~renderLanes), - bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) - ); - workInProgress.flags |= 1; - reconcileChildren(current, workInProgress, nextProps, renderLanes); - return workInProgress.child; -} -function updateMemoComponent( - current, - workInProgress, - Component, - nextProps, - renderLanes -) { - if (null === current) { - var type = Component.type; - if ( - "function" === typeof type && - !shouldConstruct(type) && - void 0 === type.defaultProps && - null === Component.compare && - void 0 === Component.defaultProps - ) - return ( - (workInProgress.tag = 15), - (workInProgress.type = type), - updateSimpleMemoComponent( - current, - workInProgress, - type, - nextProps, - renderLanes - ) - ); - current = createFiberFromTypeAndProps( - Component.type, - null, - nextProps, - workInProgress, - workInProgress.mode, - renderLanes - ); - current.ref = workInProgress.ref; - current.return = workInProgress; - return (workInProgress.child = current); - } - type = current.child; - if (0 === (current.lanes & renderLanes)) { - var prevProps = type.memoizedProps; - Component = Component.compare; - Component = null !== Component ? Component : shallowEqual; - if (Component(prevProps, nextProps) && current.ref === workInProgress.ref) - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); + type = current.child; + if (0 === (current.lanes & renderLanes)) { + var prevProps = type.memoizedProps; + Component = Component.compare; + Component = null !== Component ? Component : shallowEqual; + if (Component(prevProps, nextProps) && current.ref === workInProgress.ref) + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); } workInProgress.flags |= 1; current = createWorkInProgress(type, nextProps); @@ -4859,18 +4386,24 @@ function updateSimpleMemoComponent( nextProps, renderLanes ) { - if ( - null !== current && - shallowEqual(current.memoizedProps, nextProps) && - current.ref === workInProgress.ref - ) - if (((didReceiveUpdate = !1), 0 !== (current.lanes & renderLanes))) - 0 !== (current.flags & 131072) && (didReceiveUpdate = !0); - else - return ( - (workInProgress.lanes = current.lanes), - bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) - ); + if (null !== current) { + var prevProps = current.memoizedProps; + if ( + shallowEqual(prevProps, nextProps) && + current.ref === workInProgress.ref + ) + if ( + ((didReceiveUpdate = !1), + (workInProgress.pendingProps = nextProps = prevProps), + 0 !== (current.lanes & renderLanes)) + ) + 0 !== (current.flags & 131072) && (didReceiveUpdate = !0); + else + return ( + (workInProgress.lanes = current.lanes), + bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) + ); + } return updateFunctionComponent( current, workInProgress, @@ -4885,7 +4418,11 @@ function updateOffscreenComponent(current, workInProgress, renderLanes) { prevState = null !== current ? current.memoizedState : null; if ("hidden" === nextProps.mode) if (0 === (workInProgress.mode & 1)) - (workInProgress.memoizedState = { baseLanes: 0, cachePool: null }), + (workInProgress.memoizedState = { + baseLanes: 0, + cachePool: null, + transitions: null + }), push(subtreeRenderLanesCursor, subtreeRenderLanes), (subtreeRenderLanes |= renderLanes); else { @@ -4898,14 +4435,19 @@ function updateOffscreenComponent(current, workInProgress, renderLanes) { (workInProgress.lanes = workInProgress.childLanes = 1073741824), (workInProgress.memoizedState = { baseLanes: current, - cachePool: null + cachePool: null, + transitions: null }), (workInProgress.updateQueue = null), push(subtreeRenderLanesCursor, subtreeRenderLanes), (subtreeRenderLanes |= current), null ); - workInProgress.memoizedState = { baseLanes: 0, cachePool: null }; + workInProgress.memoizedState = { + baseLanes: 0, + cachePool: null, + transitions: null + }; nextProps = null !== prevState ? prevState.baseLanes : renderLanes; push(subtreeRenderLanesCursor, subtreeRenderLanes); subtreeRenderLanes |= nextProps; @@ -4920,7 +4462,7 @@ function updateOffscreenComponent(current, workInProgress, renderLanes) { reconcileChildren(current, workInProgress, nextChildren, renderLanes); return workInProgress.child; } -function markRef$1(current, workInProgress) { +function markRef(current, workInProgress) { var ref = workInProgress.ref; if ( (null === current && null !== ref) || @@ -4972,10 +4514,7 @@ function updateClassComponent( } else hasContext = !1; prepareToReadContext(workInProgress, renderLanes); if (null === workInProgress.stateNode) - null !== current && - ((current.alternate = null), - (workInProgress.alternate = null), - (workInProgress.flags |= 2)), + resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress), constructClassInstance(workInProgress, Component, nextProps), mountClassInstance(workInProgress, Component, nextProps, renderLanes), (nextProps = !0); @@ -5169,7 +4708,7 @@ function finishClassComponent( hasContext, renderLanes ) { - markRef$1(current, workInProgress); + markRef(current, workInProgress); var didCaptureError = 0 !== (workInProgress.flags & 128); if (!shouldUpdate && !didCaptureError) return ( @@ -5215,14 +4754,15 @@ function pushHostRootContext(workInProgress) { } var SUSPENDED_MARKER = { dehydrated: null, treeContext: null, retryLane: 0 }; function mountSuspenseOffscreenState(renderLanes) { - return { baseLanes: renderLanes, cachePool: null }; + return { baseLanes: renderLanes, cachePool: null, transitions: null }; } function updateSuspenseComponent(current, workInProgress, renderLanes) { var nextProps = workInProgress.pendingProps, suspenseContext = suspenseStackCursor.current, showFallback = !1, + didSuspend = 0 !== (workInProgress.flags & 128), JSCompiler_temp; - (JSCompiler_temp = 0 !== (workInProgress.flags & 128)) || + (JSCompiler_temp = didSuspend) || (JSCompiler_temp = null !== current && null === current.memoizedState ? !1 @@ -5232,167 +4772,297 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { suspenseContext |= 1; push(suspenseStackCursor, suspenseContext & 1); if (null === current) { - suspenseContext = nextProps.children; - current = nextProps.fallback; - if (showFallback) + current = workInProgress.memoizedState; + if (null !== current && null !== current.dehydrated) return ( - (showFallback = workInProgress.mode), - (nextProps = workInProgress.child), - (suspenseContext = { mode: "hidden", children: suspenseContext }), - 0 === (showFallback & 1) && null !== nextProps - ? ((nextProps.childLanes = 0), - (nextProps.pendingProps = suspenseContext)) - : (nextProps = createFiberFromOffscreen( - suspenseContext, - showFallback, + 0 === (workInProgress.mode & 1) + ? (workInProgress.lanes = 1) + : shim$1() + ? (workInProgress.lanes = 8) + : (workInProgress.lanes = 1073741824), + null + ); + didSuspend = nextProps.children; + current = nextProps.fallback; + return showFallback + ? ((nextProps = workInProgress.mode), + (showFallback = workInProgress.child), + (didSuspend = { mode: "hidden", children: didSuspend }), + 0 === (nextProps & 1) && null !== showFallback + ? ((showFallback.childLanes = 0), + (showFallback.pendingProps = didSuspend)) + : (showFallback = createFiberFromOffscreen( + didSuspend, + nextProps, 0, null )), (current = createFiberFromFragment( current, - showFallback, + nextProps, renderLanes, null )), - (nextProps.return = workInProgress), + (showFallback.return = workInProgress), (current.return = workInProgress), - (nextProps.sibling = current), - (workInProgress.child = nextProps), + (showFallback.sibling = current), + (workInProgress.child = showFallback), (workInProgress.child.memoizedState = mountSuspenseOffscreenState( renderLanes )), (workInProgress.memoizedState = SUSPENDED_MARKER), - current - ); - renderLanes = createFiberFromOffscreen( - { mode: "visible", children: suspenseContext }, - workInProgress.mode, - 0, - null - ); - renderLanes.return = workInProgress; - return (workInProgress.child = renderLanes); + current) + : mountSuspensePrimaryChildren(workInProgress, didSuspend); } - if (null !== current.memoizedState) { - if (showFallback) - return ( - (showFallback = updateSuspenseFallbackChildren( - current, - workInProgress, - nextProps.children, - nextProps.fallback, - renderLanes - )), - (nextProps = workInProgress.child), - (suspenseContext = current.child.memoizedState), - (nextProps.memoizedState = - null === suspenseContext - ? mountSuspenseOffscreenState(renderLanes) - : { - baseLanes: suspenseContext.baseLanes | renderLanes, - cachePool: null - }), - (nextProps.childLanes = current.childLanes & ~renderLanes), - (workInProgress.memoizedState = SUSPENDED_MARKER), - showFallback - ); - renderLanes = updateSuspensePrimaryChildren( + suspenseContext = current.memoizedState; + if ( + null !== suspenseContext && + ((JSCompiler_temp = suspenseContext.dehydrated), null !== JSCompiler_temp) + ) + return updateDehydratedSuspenseComponent( current, workInProgress, - nextProps.children, + didSuspend, + nextProps, + JSCompiler_temp, + suspenseContext, renderLanes ); - workInProgress.memoizedState = null; - return renderLanes; + if (showFallback) { + showFallback = nextProps.fallback; + didSuspend = workInProgress.mode; + suspenseContext = current.child; + JSCompiler_temp = suspenseContext.sibling; + var primaryChildProps = { mode: "hidden", children: nextProps.children }; + 0 === (didSuspend & 1) && workInProgress.child !== suspenseContext + ? ((nextProps = workInProgress.child), + (nextProps.childLanes = 0), + (nextProps.pendingProps = primaryChildProps), + (workInProgress.deletions = null)) + : ((nextProps = createWorkInProgress(suspenseContext, primaryChildProps)), + (nextProps.subtreeFlags = suspenseContext.subtreeFlags & 14680064)); + null !== JSCompiler_temp + ? (showFallback = createWorkInProgress(JSCompiler_temp, showFallback)) + : ((showFallback = createFiberFromFragment( + showFallback, + didSuspend, + renderLanes, + null + )), + (showFallback.flags |= 2)); + showFallback.return = workInProgress; + nextProps.return = workInProgress; + nextProps.sibling = showFallback; + workInProgress.child = nextProps; + nextProps = showFallback; + showFallback = workInProgress.child; + didSuspend = current.child.memoizedState; + didSuspend = + null === didSuspend + ? mountSuspenseOffscreenState(renderLanes) + : { + baseLanes: didSuspend.baseLanes | renderLanes, + cachePool: null, + transitions: didSuspend.transitions + }; + showFallback.memoizedState = didSuspend; + showFallback.childLanes = current.childLanes & ~renderLanes; + workInProgress.memoizedState = SUSPENDED_MARKER; + return nextProps; } - if (showFallback) - return ( - (showFallback = updateSuspenseFallbackChildren( - current, - workInProgress, - nextProps.children, - nextProps.fallback, - renderLanes - )), - (nextProps = workInProgress.child), - (suspenseContext = current.child.memoizedState), - (nextProps.memoizedState = - null === suspenseContext - ? mountSuspenseOffscreenState(renderLanes) - : { - baseLanes: suspenseContext.baseLanes | renderLanes, - cachePool: null - }), - (nextProps.childLanes = current.childLanes & ~renderLanes), - (workInProgress.memoizedState = SUSPENDED_MARKER), - showFallback - ); - renderLanes = updateSuspensePrimaryChildren( - current, - workInProgress, - nextProps.children, - renderLanes - ); - workInProgress.memoizedState = null; - return renderLanes; -} -function updateSuspensePrimaryChildren( - current, - workInProgress, - primaryChildren, - renderLanes -) { - var currentPrimaryChildFragment = current.child; - current = currentPrimaryChildFragment.sibling; - primaryChildren = createWorkInProgress(currentPrimaryChildFragment, { + showFallback = current.child; + current = showFallback.sibling; + nextProps = createWorkInProgress(showFallback, { mode: "visible", - children: primaryChildren + children: nextProps.children }); - 0 === (workInProgress.mode & 1) && (primaryChildren.lanes = renderLanes); - primaryChildren.return = workInProgress; - primaryChildren.sibling = null; + 0 === (workInProgress.mode & 1) && (nextProps.lanes = renderLanes); + nextProps.return = workInProgress; + nextProps.sibling = null; null !== current && ((renderLanes = workInProgress.deletions), null === renderLanes ? ((workInProgress.deletions = [current]), (workInProgress.flags |= 16)) : renderLanes.push(current)); + workInProgress.child = nextProps; + workInProgress.memoizedState = null; + return nextProps; +} +function mountSuspensePrimaryChildren(workInProgress, primaryChildren) { + primaryChildren = createFiberFromOffscreen( + { mode: "visible", children: primaryChildren }, + workInProgress.mode, + 0, + null + ); + primaryChildren.return = workInProgress; return (workInProgress.child = primaryChildren); } -function updateSuspenseFallbackChildren( +function retrySuspenseComponentWithoutHydrating( current, workInProgress, - primaryChildren, - fallbackChildren, + renderLanes, + recoverableError +) { + null !== recoverableError && + (null === hydrationErrors + ? (hydrationErrors = [recoverableError]) + : hydrationErrors.push(recoverableError)); + reconcileChildFibers(workInProgress, current.child, null, renderLanes); + current = mountSuspensePrimaryChildren( + workInProgress, + workInProgress.pendingProps.children + ); + current.flags |= 2; + workInProgress.memoizedState = null; + return current; +} +function updateDehydratedSuspenseComponent( + current, + workInProgress, + didSuspend, + nextProps, + suspenseInstance, + suspenseState, renderLanes ) { - var mode = workInProgress.mode; - current = current.child; - var currentFallbackChildFragment = current.sibling, - primaryChildProps = { mode: "hidden", children: primaryChildren }; - 0 === (mode & 1) && workInProgress.child !== current - ? ((primaryChildren = workInProgress.child), - (primaryChildren.childLanes = 0), - (primaryChildren.pendingProps = primaryChildProps), - (workInProgress.deletions = null)) - : ((primaryChildren = createWorkInProgress(current, primaryChildProps)), - (primaryChildren.subtreeFlags = current.subtreeFlags & 14680064)); - null !== currentFallbackChildFragment - ? (fallbackChildren = createWorkInProgress( - currentFallbackChildFragment, - fallbackChildren - )) - : ((fallbackChildren = createFiberFromFragment( - fallbackChildren, - mode, + if (didSuspend) { + if (workInProgress.flags & 256) + return ( + (workInProgress.flags &= -257), + retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, + Error( + "There was an error while hydrating this Suspense boundary. Switched to client rendering." + ) + ) + ); + if (null !== workInProgress.memoizedState) + return ( + (workInProgress.child = current.child), + (workInProgress.flags |= 128), + null + ); + suspenseState = nextProps.fallback; + didSuspend = workInProgress.mode; + nextProps = createFiberFromOffscreen( + { mode: "visible", children: nextProps.children }, + didSuspend, + 0, + null + ); + suspenseState = createFiberFromFragment( + suspenseState, + didSuspend, + renderLanes, + null + ); + suspenseState.flags |= 2; + nextProps.return = workInProgress; + suspenseState.return = workInProgress; + nextProps.sibling = suspenseState; + workInProgress.child = nextProps; + 0 !== (workInProgress.mode & 1) && + reconcileChildFibers(workInProgress, current.child, null, renderLanes); + workInProgress.child.memoizedState = mountSuspenseOffscreenState( + renderLanes + ); + workInProgress.memoizedState = SUSPENDED_MARKER; + return suspenseState; + } + if (0 === (workInProgress.mode & 1)) + return retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, + null + ); + if (shim$1()) + return ( + (suspenseState = shim$1().errorMessage), + retrySuspenseComponentWithoutHydrating( + current, + workInProgress, renderLanes, - null - )), - (fallbackChildren.flags |= 2)); - fallbackChildren.return = workInProgress; - primaryChildren.return = workInProgress; - primaryChildren.sibling = fallbackChildren; - workInProgress.child = primaryChildren; - return fallbackChildren; + suspenseState + ? Error(suspenseState) + : Error( + "The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering." + ) + ) + ); + didSuspend = 0 !== (renderLanes & current.childLanes); + if (didReceiveUpdate || didSuspend) { + nextProps = workInProgressRoot; + if (null !== nextProps) { + switch (renderLanes & -renderLanes) { + case 4: + didSuspend = 2; + break; + case 16: + didSuspend = 8; + break; + 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: + case 8388608: + case 16777216: + case 33554432: + case 67108864: + didSuspend = 32; + break; + case 536870912: + didSuspend = 268435456; + break; + default: + didSuspend = 0; + } + nextProps = + 0 !== (didSuspend & (nextProps.suspendedLanes | renderLanes)) + ? 0 + : didSuspend; + 0 !== nextProps && + nextProps !== suspenseState.retryLane && + ((suspenseState.retryLane = nextProps), + scheduleUpdateOnFiber(current, nextProps, -1)); + } + renderDidSuspendDelayIfPossible(); + return retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, + Error( + "This Suspense boundary received an update before it finished hydrating. This caused the boundary to switch to client rendering. The usual way to fix this is to wrap the original update in startTransition." + ) + ); + } + if (shim$1()) + return ( + (workInProgress.flags |= 128), + (workInProgress.child = current.child), + retryDehydratedSuspenseBoundary.bind(null, current), + shim$1(), + null + ); + current = mountSuspensePrimaryChildren(workInProgress, nextProps.children); + current.flags |= 4096; + return current; } function scheduleSuspenseWorkOnFiber(fiber, renderLanes, propagationRoot) { fiber.lanes |= renderLanes; @@ -5511,6 +5181,13 @@ function updateSuspenseListComponent(current, workInProgress, renderLanes) { } return workInProgress.child; } +function resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress) { + 0 === (workInProgress.mode & 1) && + null !== current && + ((current.alternate = null), + (workInProgress.alternate = null), + (workInProgress.flags |= 2)); +} function bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) { null !== current && (workInProgress.dependencies = current.dependencies); workInProgressRootSkippedLanes |= workInProgress.lanes; @@ -5530,74 +5207,607 @@ function bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) { (renderLanes.return = workInProgress); renderLanes.sibling = null; } - return workInProgress.child; + return workInProgress.child; +} +function attemptEarlyBailoutIfNoScheduledUpdate( + current, + workInProgress, + renderLanes +) { + switch (workInProgress.tag) { + case 3: + pushHostRootContext(workInProgress); + break; + case 5: + pushHostContext(workInProgress); + break; + case 1: + isContextProvider(workInProgress.type) && + pushContextProvider(workInProgress); + break; + case 4: + pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); + break; + case 10: + var context = workInProgress.type._context, + nextValue = workInProgress.memoizedProps.value; + push(valueCursor, context._currentValue2); + context._currentValue2 = nextValue; + break; + case 13: + context = workInProgress.memoizedState; + if (null !== context) { + if (null !== context.dehydrated) + return ( + push(suspenseStackCursor, suspenseStackCursor.current & 1), + (workInProgress.flags |= 128), + null + ); + if (0 !== (renderLanes & workInProgress.child.childLanes)) + return updateSuspenseComponent(current, workInProgress, renderLanes); + push(suspenseStackCursor, suspenseStackCursor.current & 1); + current = bailoutOnAlreadyFinishedWork( + current, + workInProgress, + renderLanes + ); + return null !== current ? current.sibling : null; + } + push(suspenseStackCursor, suspenseStackCursor.current & 1); + break; + case 19: + context = 0 !== (renderLanes & workInProgress.childLanes); + if (0 !== (current.flags & 128)) { + if (context) + return updateSuspenseListComponent( + current, + workInProgress, + renderLanes + ); + workInProgress.flags |= 128; + } + nextValue = workInProgress.memoizedState; + null !== nextValue && + ((nextValue.rendering = null), + (nextValue.tail = null), + (nextValue.lastEffect = null)); + push(suspenseStackCursor, suspenseStackCursor.current); + if (context) break; + else return null; + case 22: + case 23: + return ( + (workInProgress.lanes = 0), + updateOffscreenComponent(current, workInProgress, renderLanes) + ); + } + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); +} +function hadNoMutationsEffects(current, completedWork) { + if (null !== current && current.child === completedWork.child) return !0; + if (0 !== (completedWork.flags & 16)) return !1; + for (current = completedWork.child; null !== current; ) { + if (0 !== (current.flags & 12854) || 0 !== (current.subtreeFlags & 12854)) + return !1; + current = current.sibling; + } + return !0; +} +var appendAllChildren, + updateHostContainer, + updateHostComponent$1, + updateHostText$1; +appendAllChildren = function( + parent, + workInProgress, + needsVisibilityToggle, + isHidden +) { + for (var node = workInProgress.child; null !== node; ) { + if (5 === node.tag) { + var instance = node.stateNode; + needsVisibilityToggle && + isHidden && + (instance = cloneHiddenInstance(instance)); + appendChildNode(parent.node, instance.node); + } else if (6 === node.tag) { + instance = node.stateNode; + if (needsVisibilityToggle && isHidden) + throw Error("Not yet implemented."); + appendChildNode(parent.node, instance.node); + } else if (4 !== node.tag) + if (22 === node.tag && null !== node.memoizedState) + (instance = node.child), + null !== instance && (instance.return = node), + appendAllChildren(parent, node, !0, !0); + else if (null !== node.child) { + node.child.return = node; + node = node.child; + continue; + } + if (node === workInProgress) break; + for (; null === node.sibling; ) { + if (null === node.return || node.return === workInProgress) return; + node = node.return; + } + node.sibling.return = node.return; + node = node.sibling; + } +}; +function appendAllChildrenToContainer( + containerChildSet, + workInProgress, + needsVisibilityToggle, + isHidden +) { + for (var node = workInProgress.child; null !== node; ) { + if (5 === node.tag) { + var instance = node.stateNode; + needsVisibilityToggle && + isHidden && + (instance = cloneHiddenInstance(instance)); + appendChildNodeToSet(containerChildSet, instance.node); + } else if (6 === node.tag) { + instance = node.stateNode; + if (needsVisibilityToggle && isHidden) + throw Error("Not yet implemented."); + appendChildNodeToSet(containerChildSet, instance.node); + } else if (4 !== node.tag) + if (22 === node.tag && null !== node.memoizedState) + (instance = node.child), + null !== instance && (instance.return = node), + appendAllChildrenToContainer(containerChildSet, node, !0, !0); + else if (null !== node.child) { + node.child.return = node; + node = node.child; + continue; + } + if (node === workInProgress) break; + for (; null === node.sibling; ) { + if (null === node.return || node.return === workInProgress) return; + node = node.return; + } + node.sibling.return = node.return; + node = node.sibling; + } +} +updateHostContainer = function(current, workInProgress) { + var portalOrRoot = workInProgress.stateNode; + if (!hadNoMutationsEffects(current, workInProgress)) { + current = portalOrRoot.containerInfo; + var newChildSet = createChildNodeSet(current); + appendAllChildrenToContainer(newChildSet, workInProgress, !1, !1); + portalOrRoot.pendingChildren = newChildSet; + workInProgress.flags |= 4; + completeRoot(current, newChildSet); + } +}; +updateHostComponent$1 = function(current, workInProgress, type, newProps) { + type = current.stateNode; + var oldProps = current.memoizedProps; + if ( + (current = hadNoMutationsEffects(current, workInProgress)) && + oldProps === newProps + ) + workInProgress.stateNode = type; + else { + var recyclableInstance = workInProgress.stateNode; + requiredContext(contextStackCursor$1.current); + var updatePayload = null; + oldProps !== newProps && + ((oldProps = diffProperties( + null, + oldProps, + newProps, + recyclableInstance.canonical.viewConfig.validAttributes + )), + (recyclableInstance.canonical.currentProps = newProps), + (updatePayload = oldProps)); + current && null === updatePayload + ? (workInProgress.stateNode = type) + : ((newProps = updatePayload), + (oldProps = type.node), + (type = { + node: current + ? null !== newProps + ? cloneNodeWithNewProps(oldProps, newProps) + : cloneNode(oldProps) + : null !== newProps + ? cloneNodeWithNewChildrenAndProps(oldProps, newProps) + : cloneNodeWithNewChildren(oldProps), + canonical: type.canonical + }), + (workInProgress.stateNode = type), + current + ? (workInProgress.flags |= 4) + : appendAllChildren(type, workInProgress, !1, !1)); + } +}; +updateHostText$1 = function(current, workInProgress, oldText, newText) { + oldText !== newText + ? ((current = requiredContext(rootInstanceStackCursor.current)), + (oldText = requiredContext(contextStackCursor$1.current)), + (workInProgress.stateNode = createTextInstance( + newText, + current, + oldText, + workInProgress + )), + (workInProgress.flags |= 4)) + : (workInProgress.stateNode = current.stateNode); +}; +function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { + switch (renderState.tailMode) { + case "hidden": + hasRenderedATailFallback = renderState.tail; + for (var lastTailNode = null; null !== hasRenderedATailFallback; ) + null !== hasRenderedATailFallback.alternate && + (lastTailNode = hasRenderedATailFallback), + (hasRenderedATailFallback = hasRenderedATailFallback.sibling); + null === lastTailNode + ? (renderState.tail = null) + : (lastTailNode.sibling = null); + break; + case "collapsed": + lastTailNode = renderState.tail; + for (var lastTailNode$60 = null; null !== lastTailNode; ) + null !== lastTailNode.alternate && (lastTailNode$60 = lastTailNode), + (lastTailNode = lastTailNode.sibling); + null === lastTailNode$60 + ? hasRenderedATailFallback || null === renderState.tail + ? (renderState.tail = null) + : (renderState.tail.sibling = null) + : (lastTailNode$60.sibling = null); + } } -function attemptEarlyBailoutIfNoScheduledUpdate( - current, - workInProgress, - renderLanes -) { +function bubbleProperties(completedWork) { + var didBailout = + null !== completedWork.alternate && + completedWork.alternate.child === completedWork.child, + newChildLanes = 0, + subtreeFlags = 0; + if (didBailout) + for (var child$61 = completedWork.child; null !== child$61; ) + (newChildLanes |= child$61.lanes | child$61.childLanes), + (subtreeFlags |= child$61.subtreeFlags & 14680064), + (subtreeFlags |= child$61.flags & 14680064), + (child$61.return = completedWork), + (child$61 = child$61.sibling); + else + for (child$61 = completedWork.child; null !== child$61; ) + (newChildLanes |= child$61.lanes | child$61.childLanes), + (subtreeFlags |= child$61.subtreeFlags), + (subtreeFlags |= child$61.flags), + (child$61.return = completedWork), + (child$61 = child$61.sibling); + completedWork.subtreeFlags |= subtreeFlags; + completedWork.childLanes = newChildLanes; + return didBailout; +} +function completeWork(current, workInProgress, renderLanes) { + var newProps = workInProgress.pendingProps; + popTreeContext(workInProgress); switch (workInProgress.tag) { + case 2: + case 16: + case 15: + case 0: + case 11: + case 7: + case 8: + case 12: + case 9: + case 14: + return bubbleProperties(workInProgress), null; + case 1: + return ( + isContextProvider(workInProgress.type) && popContext(), + bubbleProperties(workInProgress), + null + ); case 3: - pushHostRootContext(workInProgress); - break; + return ( + (renderLanes = workInProgress.stateNode), + popHostContainer(), + pop(didPerformWorkStackCursor), + pop(contextStackCursor), + resetWorkInProgressVersions(), + renderLanes.pendingContext && + ((renderLanes.context = renderLanes.pendingContext), + (renderLanes.pendingContext = null)), + (null !== current && null !== current.child) || + null === current || + (current.memoizedState.isDehydrated && + 0 === (workInProgress.flags & 256)) || + ((workInProgress.flags |= 1024), + null !== hydrationErrors && + (queueRecoverableErrors(hydrationErrors), + (hydrationErrors = null))), + updateHostContainer(current, workInProgress), + bubbleProperties(workInProgress), + null + ); case 5: - pushHostContext(workInProgress); - break; - case 1: - isContextProvider(workInProgress.type) && - pushContextProvider(workInProgress); - break; - case 4: - pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); - break; - case 10: - var context = workInProgress.type._context, - nextValue = workInProgress.memoizedProps.value; - push(valueCursor, context._currentValue2); - context._currentValue2 = nextValue; - break; - case 13: - if (null !== workInProgress.memoizedState) { - if (0 !== (renderLanes & workInProgress.child.childLanes)) - return updateSuspenseComponent(current, workInProgress, renderLanes); - push(suspenseStackCursor, suspenseStackCursor.current & 1); - current = bailoutOnAlreadyFinishedWork( + popHostContext(workInProgress); + renderLanes = requiredContext(rootInstanceStackCursor.current); + var type = workInProgress.type; + if (null !== current && null != workInProgress.stateNode) + updateHostComponent$1( current, workInProgress, + type, + newProps, renderLanes + ), + current.ref !== workInProgress.ref && (workInProgress.flags |= 512); + else { + if (!newProps) { + if (null === workInProgress.stateNode) + throw Error( + "We must have new props for new mounts. This error is likely caused by a bug in React. Please file an issue." + ); + bubbleProperties(workInProgress); + return null; + } + requiredContext(contextStackCursor$1.current); + current = nextReactTag; + nextReactTag += 2; + type = getViewConfigForType(type); + var updatePayload = diffProperties( + null, + emptyObject, + newProps, + type.validAttributes ); - return null !== current ? current.sibling : null; + renderLanes = createNode( + current, + type.uiViewClassName, + renderLanes, + updatePayload, + workInProgress + ); + current = new ReactFabricHostComponent( + current, + type, + newProps, + workInProgress + ); + current = { node: renderLanes, canonical: current }; + appendAllChildren(current, workInProgress, !1, !1); + workInProgress.stateNode = current; + null !== workInProgress.ref && (workInProgress.flags |= 512); } - push(suspenseStackCursor, suspenseStackCursor.current & 1); - break; - case 19: - context = 0 !== (renderLanes & workInProgress.childLanes); - if (0 !== (current.flags & 128)) { - if (context) - return updateSuspenseListComponent( - current, - workInProgress, - renderLanes + bubbleProperties(workInProgress); + return null; + case 6: + if (current && null != workInProgress.stateNode) + updateHostText$1( + current, + workInProgress, + current.memoizedProps, + newProps + ); + else { + if ("string" !== typeof newProps && null === workInProgress.stateNode) + throw Error( + "We must have new props for new mounts. This error is likely caused by a bug in React. Please file an issue." ); - workInProgress.flags |= 128; + current = requiredContext(rootInstanceStackCursor.current); + renderLanes = requiredContext(contextStackCursor$1.current); + workInProgress.stateNode = createTextInstance( + newProps, + current, + renderLanes, + workInProgress + ); + } + bubbleProperties(workInProgress); + return null; + case 13: + pop(suspenseStackCursor); + newProps = workInProgress.memoizedState; + if ( + null === current || + (null !== current.memoizedState && + null !== current.memoizedState.dehydrated) + ) { + if (null !== newProps && null !== newProps.dehydrated) { + if (null === current) { + throw Error( + "A dehydrated suspense component was completed without a hydrated node. This is probably a bug in React." + ); + throw Error( + "Expected prepareToHydrateHostSuspenseInstance() to never be called. This error is likely caused by a bug in React. Please file an issue." + ); + } + 0 === (workInProgress.flags & 128) && + (workInProgress.memoizedState = null); + workInProgress.flags |= 4; + bubbleProperties(workInProgress); + type = !1; + } else + null !== hydrationErrors && + (queueRecoverableErrors(hydrationErrors), (hydrationErrors = null)), + (type = !0); + if (!type) return workInProgress.flags & 65536 ? workInProgress : null; + } + if (0 !== (workInProgress.flags & 128)) + return (workInProgress.lanes = renderLanes), workInProgress; + renderLanes = null !== newProps; + renderLanes !== (null !== current && null !== current.memoizedState) && + renderLanes && + ((workInProgress.child.flags |= 8192), + 0 !== (workInProgress.mode & 1) && + (null === current || 0 !== (suspenseStackCursor.current & 1) + ? 0 === workInProgressRootExitStatus && + (workInProgressRootExitStatus = 3) + : renderDidSuspendDelayIfPossible())); + null !== workInProgress.updateQueue && (workInProgress.flags |= 4); + bubbleProperties(workInProgress); + return null; + case 4: + return ( + popHostContainer(), + updateHostContainer(current, workInProgress), + bubbleProperties(workInProgress), + null + ); + case 10: + return ( + popProvider(workInProgress.type._context), + bubbleProperties(workInProgress), + null + ); + case 17: + return ( + isContextProvider(workInProgress.type) && popContext(), + bubbleProperties(workInProgress), + null + ); + case 19: + pop(suspenseStackCursor); + type = workInProgress.memoizedState; + if (null === type) return bubbleProperties(workInProgress), null; + newProps = 0 !== (workInProgress.flags & 128); + updatePayload = type.rendering; + if (null === updatePayload) + if (newProps) cutOffTailIfNeeded(type, !1); + else { + if ( + 0 !== workInProgressRootExitStatus || + (null !== current && 0 !== (current.flags & 128)) + ) + for (current = workInProgress.child; null !== current; ) { + updatePayload = findFirstSuspended(current); + if (null !== updatePayload) { + workInProgress.flags |= 128; + cutOffTailIfNeeded(type, !1); + current = updatePayload.updateQueue; + null !== current && + ((workInProgress.updateQueue = current), + (workInProgress.flags |= 4)); + workInProgress.subtreeFlags = 0; + current = renderLanes; + for (renderLanes = workInProgress.child; null !== renderLanes; ) + (newProps = renderLanes), + (type = current), + (newProps.flags &= 14680066), + (updatePayload = newProps.alternate), + null === updatePayload + ? ((newProps.childLanes = 0), + (newProps.lanes = type), + (newProps.child = null), + (newProps.subtreeFlags = 0), + (newProps.memoizedProps = null), + (newProps.memoizedState = null), + (newProps.updateQueue = null), + (newProps.dependencies = null), + (newProps.stateNode = null)) + : ((newProps.childLanes = updatePayload.childLanes), + (newProps.lanes = updatePayload.lanes), + (newProps.child = updatePayload.child), + (newProps.subtreeFlags = 0), + (newProps.deletions = null), + (newProps.memoizedProps = updatePayload.memoizedProps), + (newProps.memoizedState = updatePayload.memoizedState), + (newProps.updateQueue = updatePayload.updateQueue), + (newProps.type = updatePayload.type), + (type = updatePayload.dependencies), + (newProps.dependencies = + null === type + ? null + : { + lanes: type.lanes, + firstContext: type.firstContext + })), + (renderLanes = renderLanes.sibling); + push( + suspenseStackCursor, + (suspenseStackCursor.current & 1) | 2 + ); + return workInProgress.child; + } + current = current.sibling; + } + null !== type.tail && + now() > workInProgressRootRenderTargetTime && + ((workInProgress.flags |= 128), + (newProps = !0), + cutOffTailIfNeeded(type, !1), + (workInProgress.lanes = 4194304)); + } + else { + if (!newProps) + if ( + ((current = findFirstSuspended(updatePayload)), null !== current) + ) { + if ( + ((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 && + !updatePayload.alternate) + ) + return bubbleProperties(workInProgress), null; + } else + 2 * now() - type.renderingStartTime > + workInProgressRootRenderTargetTime && + 1073741824 !== renderLanes && + ((workInProgress.flags |= 128), + (newProps = !0), + cutOffTailIfNeeded(type, !1), + (workInProgress.lanes = 4194304)); + type.isBackwards + ? ((updatePayload.sibling = workInProgress.child), + (workInProgress.child = updatePayload)) + : ((current = type.last), + null !== current + ? (current.sibling = updatePayload) + : (workInProgress.child = updatePayload), + (type.last = updatePayload)); } - nextValue = workInProgress.memoizedState; - null !== nextValue && - ((nextValue.rendering = null), - (nextValue.tail = null), - (nextValue.lastEffect = null)); - push(suspenseStackCursor, suspenseStackCursor.current); - if (context) break; - else return null; + if (null !== type.tail) + return ( + (workInProgress = type.tail), + (type.rendering = workInProgress), + (type.tail = workInProgress.sibling), + (type.renderingStartTime = now()), + (workInProgress.sibling = null), + (current = suspenseStackCursor.current), + push(suspenseStackCursor, newProps ? (current & 1) | 2 : current & 1), + workInProgress + ); + bubbleProperties(workInProgress); + return null; case 22: case 23: return ( - (workInProgress.lanes = 0), - updateOffscreenComponent(current, workInProgress, renderLanes) + popRenderLanes(), + (renderLanes = null !== workInProgress.memoizedState), + null !== current && + (null !== current.memoizedState) !== renderLanes && + (workInProgress.flags |= 8192), + renderLanes && 0 !== (workInProgress.mode & 1) + ? 0 !== (subtreeRenderLanes & 1073741824) && + bubbleProperties(workInProgress) + : bubbleProperties(workInProgress), + null ); + case 24: + return null; + case 25: + return null; } - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); + throw Error( + "Unknown unit of work tag (" + + workInProgress.tag + + "). This error is likely caused by a bug in React. Please file an issue." + ); } function unwindWork(current, workInProgress) { popTreeContext(workInProgress); @@ -5624,13 +5834,20 @@ function unwindWork(current, workInProgress) { case 5: return popHostContext(workInProgress), null; case 13: - return ( - pop(suspenseStackCursor), - (current = workInProgress.flags), - current & 65536 - ? ((workInProgress.flags = (current & -65537) | 128), workInProgress) - : null - ); + pop(suspenseStackCursor); + current = workInProgress.memoizedState; + if ( + null !== current && + null !== current.dehydrated && + null === workInProgress.alternate + ) + throw Error( + "Threw in newly mounted dehydrated component. This is likely a bug in React. Please file an issue." + ); + current = workInProgress.flags; + return current & 65536 + ? ((workInProgress.flags = (current & -65537) | 128), workInProgress) + : null; case 19: return pop(suspenseStackCursor), null; case 4: @@ -5754,8 +5971,8 @@ function commitHookEffectListMount(flags, finishedWork) { var effect = (finishedWork = finishedWork.next); do { if ((effect.tag & flags) === flags) { - var create$77 = effect.create; - effect.destroy = create$77(); + var create$73 = effect.create; + effect.destroy = create$73(); } effect = effect.next; } while (effect !== finishedWork); @@ -5777,41 +5994,113 @@ function detachFiberAfterEffects(fiber) { fiber.stateNode = null; fiber.updateQueue = null; } -function commitWork(current, finishedWork) { - switch (finishedWork.tag) { +function recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + parent +) { + for (parent = parent.child; null !== parent; ) + commitDeletionEffectsOnFiber(finishedRoot, nearestMountedAncestor, parent), + (parent = parent.sibling); +} +function commitDeletionEffectsOnFiber( + finishedRoot, + nearestMountedAncestor, + deletedFiber +) { + if (injectedHook && "function" === typeof injectedHook.onCommitFiberUnmount) + try { + injectedHook.onCommitFiberUnmount(rendererID, deletedFiber); + } catch (err) {} + switch (deletedFiber.tag) { + case 5: + safelyDetachRef(deletedFiber, nearestMountedAncestor); + case 6: + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + break; + case 18: + break; + case 4: + createChildNodeSet(deletedFiber.stateNode.containerInfo); + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + break; case 0: case 11: case 14: case 15: - commitHookEffectListUnmount(3, finishedWork, finishedWork.return); - commitHookEffectListMount(3, finishedWork); - commitHookEffectListUnmount(5, finishedWork, finishedWork.return); - return; - case 12: - return; - case 13: - attachSuspenseRetryListeners(finishedWork); - return; - case 19: - attachSuspenseRetryListeners(finishedWork); - return; + var updateQueue = deletedFiber.updateQueue; + if ( + null !== updateQueue && + ((updateQueue = updateQueue.lastEffect), null !== updateQueue) + ) { + var effect = (updateQueue = updateQueue.next); + do { + var _effect = effect, + destroy = _effect.destroy; + _effect = _effect.tag; + void 0 !== destroy && + (0 !== (_effect & 2) + ? safelyCallDestroy(deletedFiber, nearestMountedAncestor, destroy) + : 0 !== (_effect & 4) && + safelyCallDestroy( + deletedFiber, + nearestMountedAncestor, + destroy + )); + effect = effect.next; + } while (effect !== updateQueue); + } + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + break; + case 1: + safelyDetachRef(deletedFiber, nearestMountedAncestor); + updateQueue = deletedFiber.stateNode; + if ("function" === typeof updateQueue.componentWillUnmount) + try { + (updateQueue.props = deletedFiber.memoizedProps), + (updateQueue.state = deletedFiber.memoizedState), + updateQueue.componentWillUnmount(); + } catch (error) { + captureCommitPhaseError(deletedFiber, nearestMountedAncestor, error); + } + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + break; + case 21: + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + break; case 22: - case 23: - return; - } - a: { - switch (finishedWork.tag) { - case 1: - case 5: - case 6: - break a; - case 3: - case 4: - break a; - } - throw 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." - ); + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + break; + default: + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); } } function attachSuspenseRetryListeners(finishedWork) { @@ -5828,146 +6117,106 @@ function attachSuspenseRetryListeners(finishedWork) { }); } } -function commitMutationEffects(root, firstChild) { - for (nextEffect = firstChild; null !== nextEffect; ) { - root = nextEffect; - firstChild = root.deletions; - if (null !== firstChild) - for (var i = 0; i < firstChild.length; i++) { - var childToDelete = firstChild[i]; - try { - a: for (var node = childToDelete; ; ) { - var current = node; - if ( - injectedHook && - "function" === typeof injectedHook.onCommitFiberUnmount - ) - try { - injectedHook.onCommitFiberUnmount(rendererID, current); - } catch (err) {} - switch (current.tag) { - case 0: - case 11: - case 14: - case 15: - var updateQueue = current.updateQueue; - if (null !== updateQueue) { - var lastEffect = updateQueue.lastEffect; - if (null !== lastEffect) { - var firstEffect = lastEffect.next, - effect = firstEffect; - do { - var _effect = effect, - destroy = _effect.destroy, - tag = _effect.tag; - void 0 !== destroy && - (0 !== (tag & 2) - ? safelyCallDestroy(current, root, destroy) - : 0 !== (tag & 4) && - safelyCallDestroy(current, root, destroy)); - effect = effect.next; - } while (effect !== firstEffect); - } - } - break; - case 1: - safelyDetachRef(current, root); - var instance = current.stateNode; - if ("function" === typeof instance.componentWillUnmount) - try { - (effect = current), - (_effect = instance), - (_effect.props = effect.memoizedProps), - (_effect.state = effect.memoizedState), - _effect.componentWillUnmount(); - } catch (error) { - captureCommitPhaseError(current, root, error); - } - break; - case 5: - safelyDetachRef(current, root); - break; - case 4: - createChildNodeSet(current.stateNode.containerInfo); - } - if (null !== node.child) - (node.child.return = node), (node = node.child); - else { - if (node === childToDelete) break; - for (; null === node.sibling; ) { - if (null === node.return || node.return === childToDelete) - break a; - node = node.return; - } - node.sibling.return = node.return; - node = node.sibling; - } - } - var alternate = childToDelete.alternate; - null !== alternate && (alternate.return = null); - childToDelete.return = null; - } catch (error) { - captureCommitPhaseError(childToDelete, root, error); - } +function recursivelyTraverseMutationEffects(root, parentFiber) { + var deletions = parentFiber.deletions; + if (null !== deletions) + for (var i = 0; i < deletions.length; i++) { + var childToDelete = deletions[i]; + try { + commitDeletionEffectsOnFiber(root, parentFiber, childToDelete); + var alternate = childToDelete.alternate; + null !== alternate && (alternate.return = null); + childToDelete.return = null; + } catch (error) { + captureCommitPhaseError(childToDelete, parentFiber, error); } - firstChild = root.child; - if (0 !== (root.subtreeFlags & 12854) && null !== firstChild) - (firstChild.return = root), (nextEffect = firstChild); - else - for (; null !== nextEffect; ) { - root = nextEffect; + } + if (parentFiber.subtreeFlags & 12854) + for (parentFiber = parentFiber.child; null !== parentFiber; ) + commitMutationEffectsOnFiber(parentFiber, root), + (parentFiber = parentFiber.sibling); +} +function commitMutationEffectsOnFiber(finishedWork, root) { + var current = finishedWork.alternate, + flags = finishedWork.flags; + switch (finishedWork.tag) { + case 0: + case 11: + case 14: + case 15: + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + if (flags & 4) { try { - var flags = root.flags; - if (flags & 512) { - var current$jscomp$0 = root.alternate; - if (null !== current$jscomp$0) { - var currentRef = current$jscomp$0.ref; - null !== currentRef && - ("function" === typeof currentRef - ? currentRef(null) - : (currentRef.current = null)); - } - } - if (flags & 8192) - switch (root.tag) { - case 13: - if (null !== root.memoizedState) { - var current$81 = root.alternate; - if (null === current$81 || null === current$81.memoizedState) - globalMostRecentFallbackTime = now(); - } - } - switch (flags & 4102) { - case 2: - root.flags &= -3; - break; - case 6: - root.flags &= -3; - commitWork(root.alternate, root); - break; - case 4096: - root.flags &= -4097; - break; - case 4100: - root.flags &= -4097; - commitWork(root.alternate, root); - break; - case 4: - commitWork(root.alternate, root); - } + commitHookEffectListUnmount(3, finishedWork, finishedWork.return), + commitHookEffectListMount(3, finishedWork); } catch (error) { - captureCommitPhaseError(root, root.return, error); + captureCommitPhaseError(finishedWork, finishedWork.return, error); } - firstChild = root.sibling; - if (null !== firstChild) { - firstChild.return = root.return; - nextEffect = firstChild; - break; + try { + commitHookEffectListUnmount(5, finishedWork, finishedWork.return); + } catch (error$77) { + captureCommitPhaseError(finishedWork, finishedWork.return, error$77); } - nextEffect = root.return; } + break; + case 1: + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + flags & 512 && + null !== current && + safelyDetachRef(current, current.return); + break; + case 5: + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + flags & 512 && + null !== current && + safelyDetachRef(current, current.return); + break; + case 6: + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + break; + case 3: + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + break; + case 4: + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + break; + case 13: + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + root = finishedWork.child; + root.flags & 8192 && + null !== root.memoizedState && + (null === root.alternate || null === root.alternate.memoizedState) && + (globalMostRecentFallbackTime = now()); + flags & 4 && attachSuspenseRetryListeners(finishedWork); + break; + case 22: + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + break; + case 19: + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + flags & 4 && attachSuspenseRetryListeners(finishedWork); + break; + case 21: + break; + default: + recursivelyTraverseMutationEffects(root, finishedWork), + commitReconciliationEffects(finishedWork); } } +function commitReconciliationEffects(finishedWork) { + var flags = finishedWork.flags; + flags & 2 && (finishedWork.flags &= -3); + flags & 4096 && (finishedWork.flags &= -4097); +} function commitLayoutEffects(finishedWork) { for (nextEffect = finishedWork; null !== nextEffect; ) { var fiber = nextEffect, @@ -6010,8 +6259,8 @@ function commitLayoutEffects(finishedWork) { commitUpdateQueue(firstChild, updateQueue, instance); break; case 3: - var updateQueue$78 = firstChild.updateQueue; - if (null !== updateQueue$78) { + var updateQueue$74 = firstChild.updateQueue; + if (null !== updateQueue$74) { current = null; if (null !== firstChild.child) switch (firstChild.child.tag) { @@ -6021,7 +6270,7 @@ function commitLayoutEffects(finishedWork) { case 1: current = firstChild.child.stateNode; } - commitUpdateQueue(firstChild, updateQueue$78, current); + commitUpdateQueue(firstChild, updateQueue$74, current); } break; case 5: @@ -6043,6 +6292,7 @@ function commitLayoutEffects(finishedWork) { case 21: case 22: case 23: + case 25: break; default: throw Error( @@ -6103,6 +6353,7 @@ var ceil = Math.ceil, workInProgressRootRecoverableErrors = null, globalMostRecentFallbackTime = 0, workInProgressRootRenderTargetTime = Infinity, + workInProgressTransitions = null, hasUncaughtError = !1, firstUncaughtError = null, legacyErrorBoundariesThatAlreadyFailed = null, @@ -6127,10 +6378,7 @@ function requestUpdateLane(fiber) { if (null !== ReactCurrentBatchConfig.transition) return ( 0 === currentEventTransitionLane && - ((fiber = nextTransitionLane), - (nextTransitionLane <<= 1), - 0 === (nextTransitionLane & 4194240) && (nextTransitionLane = 64), - (currentEventTransitionLane = fiber)), + (currentEventTransitionLane = claimNextTransitionLane()), currentEventTransitionLane ); fiber = currentUpdatePriority; @@ -6186,6 +6434,13 @@ function markUpdateLaneFromFiberToRoot(sourceFiber, lane) { (sourceFiber = sourceFiber.return); return 3 === alternate.tag ? alternate.stateNode : null; } +function isInterleavedUpdate(fiber) { + return ( + (null !== workInProgressRoot || null !== interleavedQueues) && + 0 !== (fiber.mode & 1) && + 0 === (executionContext & 2) + ); +} function ensureRootIsScheduled(root, currentTime) { for ( var existingCallbackNode = root.callbackNode, @@ -6281,7 +6536,8 @@ function performConcurrentWorkOnRoot(root, didTimeout) { workInProgressRoot !== root || workInProgressRootRenderLanes !== didTimeout ) - (workInProgressRootRenderTargetTime = now() + 500), + (workInProgressTransitions = null), + (workInProgressRootRenderTargetTime = now() + 500), prepareFreshStack(root, didTimeout); do try { @@ -6338,7 +6594,11 @@ function performConcurrentWorkOnRoot(root, didTimeout) { case 1: throw Error("Root did not complete. This is a bug in React."); case 2: - commitRoot(root, workInProgressRootRecoverableErrors); + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); break; case 3: markRootSuspended$1(root, lanes); @@ -6355,12 +6615,21 @@ function performConcurrentWorkOnRoot(root, didTimeout) { break; } root.timeoutHandle = scheduleTimeout( - commitRoot.bind(null, root, workInProgressRootRecoverableErrors), + commitRoot.bind( + null, + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ), didTimeout ); break; } - commitRoot(root, workInProgressRootRecoverableErrors); + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); break; case 4: markRootSuspended$1(root, lanes); @@ -6391,15 +6660,28 @@ function performConcurrentWorkOnRoot(root, didTimeout) { : 1960 * ceil(lanes / 1960)) - lanes; if (10 < lanes) { root.timeoutHandle = scheduleTimeout( - commitRoot.bind(null, root, workInProgressRootRecoverableErrors), + commitRoot.bind( + null, + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ), lanes ); break; } - commitRoot(root, workInProgressRootRecoverableErrors); + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); break; case 5: - commitRoot(root, workInProgressRootRecoverableErrors); + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); break; default: throw Error("Unknown root exit status."); @@ -6419,15 +6701,17 @@ function recoverFromConcurrentError(root, errorRetryLanes) { 2 !== root && ((errorRetryLanes = workInProgressRootRecoverableErrors), (workInProgressRootRecoverableErrors = errorsFromFirstAttempt), - null !== errorRetryLanes && - (null === workInProgressRootRecoverableErrors - ? (workInProgressRootRecoverableErrors = errorRetryLanes) - : workInProgressRootRecoverableErrors.push.apply( - workInProgressRootRecoverableErrors, - errorRetryLanes - ))); + null !== errorRetryLanes && queueRecoverableErrors(errorRetryLanes)); return root; } +function queueRecoverableErrors(errors) { + null === workInProgressRootRecoverableErrors + ? (workInProgressRootRecoverableErrors = errors) + : workInProgressRootRecoverableErrors.push.apply( + workInProgressRootRecoverableErrors, + errors + ); +} function isRenderConsistentWithExternalStores(finishedWork) { for (var node = finishedWork; ; ) { if (node.flags & 16384) { @@ -6497,7 +6781,11 @@ function performSyncWorkOnRoot(root) { throw Error("Root did not complete. This is a bug in React."); root.finishedWork = root.current.alternate; root.finishedLanes = lanes; - commitRoot(root, workInProgressRootRecoverableErrors); + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); ensureRootIsScheduled(root, now()); return null; } @@ -6733,12 +7021,12 @@ function handleError(root$jscomp$0, thrownValue) { root.flags |= 65536; thrownValue &= -thrownValue; root.lanes |= thrownValue; - var update$31 = createClassErrorUpdate( + var update$32 = createClassErrorUpdate( root, wakeable, thrownValue ); - enqueueCapturedUpdate(root, update$31); + enqueueCapturedUpdate(root, update$32); break a; } } @@ -6777,8 +7065,8 @@ function renderRootSync(root, lanes) { var prevExecutionContext = executionContext; executionContext |= 2; var prevDispatcher = pushDispatcher(); - (workInProgressRoot === root && workInProgressRootRenderLanes === lanes) || - prepareFreshStack(root, lanes); + if (workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes) + (workInProgressTransitions = null), prepareFreshStack(root, lanes); do try { workLoopSync(); @@ -6850,50 +7138,60 @@ function completeUnitOfWork(unitOfWork) { } while (null !== completedWork); 0 === workInProgressRootExitStatus && (workInProgressRootExitStatus = 5); } -function commitRoot(root, recoverableErrors) { +function commitRoot(root, recoverableErrors, transitions) { var previousUpdateLanePriority = currentUpdatePriority, prevTransition = ReactCurrentBatchConfig$2.transition; try { (ReactCurrentBatchConfig$2.transition = null), (currentUpdatePriority = 1), - commitRootImpl(root, recoverableErrors, previousUpdateLanePriority); + commitRootImpl( + root, + recoverableErrors, + transitions, + previousUpdateLanePriority + ); } finally { (ReactCurrentBatchConfig$2.transition = prevTransition), (currentUpdatePriority = previousUpdateLanePriority); } return null; } -function commitRootImpl(root, recoverableErrors, renderPriorityLevel) { +function commitRootImpl( + root, + recoverableErrors, + transitions, + renderPriorityLevel +) { do flushPassiveEffects(); while (null !== rootWithPendingPassiveEffects); if (0 !== (executionContext & 6)) throw Error("Should not already be working."); - var finishedWork = root.finishedWork, - lanes = root.finishedLanes; - if (null === finishedWork) return null; + transitions = root.finishedWork; + var lanes = root.finishedLanes; + if (null === transitions) return null; root.finishedWork = null; root.finishedLanes = 0; - if (finishedWork === root.current) + if (transitions === root.current) throw Error( "Cannot commit the same tree as before. This error is likely caused by a bug in React. Please file an issue." ); root.callbackNode = null; root.callbackPriority = 0; - var remainingLanes = finishedWork.lanes | finishedWork.childLanes; + var remainingLanes = transitions.lanes | transitions.childLanes; markRootFinished(root, remainingLanes); root === workInProgressRoot && ((workInProgress = workInProgressRoot = null), (workInProgressRootRenderLanes = 0)); - (0 === (finishedWork.subtreeFlags & 2064) && - 0 === (finishedWork.flags & 2064)) || + (0 === (transitions.subtreeFlags & 2064) && + 0 === (transitions.flags & 2064)) || rootDoesHavePassiveEffects || ((rootDoesHavePassiveEffects = !0), scheduleCallback$1(NormalPriority, function() { flushPassiveEffects(); return null; })); - remainingLanes = 0 !== (finishedWork.flags & 15990); - if (0 !== (finishedWork.subtreeFlags & 15990) || remainingLanes) { + remainingLanes = 0 !== (transitions.flags & 15990); + if (0 !== (transitions.subtreeFlags & 15990) || remainingLanes) { remainingLanes = ReactCurrentBatchConfig$2.transition; ReactCurrentBatchConfig$2.transition = null; var previousPriority = currentUpdatePriority; @@ -6901,30 +7199,30 @@ function commitRootImpl(root, recoverableErrors, renderPriorityLevel) { var prevExecutionContext = executionContext; executionContext |= 4; ReactCurrentOwner$2.current = null; - commitBeforeMutationEffects(root, finishedWork); - commitMutationEffects(root, finishedWork, lanes); - root.current = finishedWork; - commitLayoutEffects(finishedWork, root, lanes); + commitBeforeMutationEffects(root, transitions); + commitMutationEffectsOnFiber(transitions, root); + root.current = transitions; + commitLayoutEffects(transitions, root, lanes); requestPaint(); executionContext = prevExecutionContext; currentUpdatePriority = previousPriority; ReactCurrentBatchConfig$2.transition = remainingLanes; - } else root.current = finishedWork; + } else root.current = transitions; rootDoesHavePassiveEffects && ((rootDoesHavePassiveEffects = !1), (rootWithPendingPassiveEffects = root), (pendingPassiveEffectsLanes = lanes)); remainingLanes = root.pendingLanes; 0 === remainingLanes && (legacyErrorBoundariesThatAlreadyFailed = null); - onCommitRoot(finishedWork.stateNode, renderPriorityLevel); + onCommitRoot(transitions.stateNode, renderPriorityLevel); ensureRootIsScheduled(root, now()); if (null !== recoverableErrors) for ( - renderPriorityLevel = root.onRecoverableError, finishedWork = 0; - finishedWork < recoverableErrors.length; - finishedWork++ + renderPriorityLevel = root.onRecoverableError, transitions = 0; + transitions < recoverableErrors.length; + transitions++ ) - renderPriorityLevel(recoverableErrors[finishedWork]); + renderPriorityLevel(recoverableErrors[transitions]); if (hasUncaughtError) throw ((hasUncaughtError = !1), (root = firstUncaughtError), @@ -7159,21 +7457,43 @@ function pingSuspendedRoot(root, wakeable, pingedLanes) { : (workInProgressRootPingedLanes |= pingedLanes)); ensureRootIsScheduled(root, wakeable); } -function resolveRetryWakeable(boundaryFiber, wakeable) { - var retryCache = boundaryFiber.stateNode; - null !== retryCache && retryCache.delete(wakeable); - wakeable = 0; - 0 === wakeable && +function retryTimedOutBoundary(boundaryFiber, retryLane) { + 0 === retryLane && (0 === (boundaryFiber.mode & 1) - ? (wakeable = 1) - : ((wakeable = nextRetryLane), + ? (retryLane = 1) + : ((retryLane = nextRetryLane), (nextRetryLane <<= 1), 0 === (nextRetryLane & 130023424) && (nextRetryLane = 4194304))); - retryCache = requestEventTime(); - boundaryFiber = markUpdateLaneFromFiberToRoot(boundaryFiber, wakeable); + var eventTime = requestEventTime(); + boundaryFiber = markUpdateLaneFromFiberToRoot(boundaryFiber, retryLane); null !== boundaryFiber && - (markRootUpdated(boundaryFiber, wakeable, retryCache), - ensureRootIsScheduled(boundaryFiber, retryCache)); + (markRootUpdated(boundaryFiber, retryLane, eventTime), + ensureRootIsScheduled(boundaryFiber, eventTime)); +} +function retryDehydratedSuspenseBoundary(boundaryFiber) { + var suspenseState = boundaryFiber.memoizedState, + retryLane = 0; + null !== suspenseState && (retryLane = suspenseState.retryLane); + retryTimedOutBoundary(boundaryFiber, retryLane); +} +function resolveRetryWakeable(boundaryFiber, wakeable) { + var retryLane = 0; + switch (boundaryFiber.tag) { + case 13: + var retryCache = boundaryFiber.stateNode; + var suspenseState = boundaryFiber.memoizedState; + null !== suspenseState && (retryLane = suspenseState.retryLane); + break; + case 19: + retryCache = boundaryFiber.stateNode; + break; + default: + throw Error( + "Pinged unknown suspense boundary type. This is probably a bug in React." + ); + } + null !== retryCache && retryCache.delete(wakeable); + retryTimedOutBoundary(boundaryFiber, retryLane); } var beginWork$1; beginWork$1 = function(current, workInProgress, renderLanes) { @@ -7203,10 +7523,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { switch (workInProgress.tag) { case 2: var Component = workInProgress.type; - null !== current && - ((current.alternate = null), - (workInProgress.alternate = null), - (workInProgress.flags |= 2)); + resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress); current = workInProgress.pendingProps; var context = getMaskedContext( workInProgress, @@ -7260,10 +7577,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { case 16: Component = workInProgress.elementType; a: { - null !== current && - ((current.alternate = null), - (workInProgress.alternate = null), - (workInProgress.flags |= 2)); + resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress); current = workInProgress.pendingProps; context = Component._init; Component = context(Component._payload); @@ -7369,7 +7683,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { return ( pushHostContext(workInProgress), (Component = workInProgress.pendingProps.children), - markRef$1(current, workInProgress), + markRef(current, workInProgress), reconcileChildren(current, workInProgress, Component, renderLanes), workInProgress.child ); @@ -7463,24 +7777,24 @@ beginWork$1 = function(current, workInProgress, renderLanes) { } } else for ( - newValue = workInProgress.child, - null !== newValue && (newValue.return = workInProgress); - null !== newValue; + hasContext = workInProgress.child, + null !== hasContext && (hasContext.return = workInProgress); + null !== hasContext; ) { - var list = newValue.dependencies; + var list = hasContext.dependencies; if (null !== list) { - hasContext = newValue.child; + newValue = hasContext.child; for ( var dependency = list.firstContext; null !== dependency; ) { if (dependency.context === Component) { - if (1 === newValue.tag) { + if (1 === hasContext.tag) { dependency = createUpdate(-1, renderLanes & -renderLanes); dependency.tag = 2; - var updateQueue = newValue.updateQueue; + var updateQueue = hasContext.updateQueue; if (null !== updateQueue) { updateQueue = updateQueue.shared; var pending = updateQueue.pending; @@ -7491,11 +7805,11 @@ beginWork$1 = function(current, workInProgress, renderLanes) { updateQueue.pending = dependency; } } - newValue.lanes |= renderLanes; - dependency = newValue.alternate; + hasContext.lanes |= renderLanes; + dependency = hasContext.alternate; null !== dependency && (dependency.lanes |= renderLanes); scheduleContextWorkOnParentPath( - newValue.return, + hasContext.return, renderLanes, workInProgress ); @@ -7504,29 +7818,43 @@ beginWork$1 = function(current, workInProgress, renderLanes) { } dependency = dependency.next; } - } else - hasContext = - 10 === newValue.tag - ? newValue.type === workInProgress.type - ? null - : newValue.child - : newValue.child; - if (null !== hasContext) hasContext.return = newValue; + } else if (10 === hasContext.tag) + newValue = + hasContext.type === workInProgress.type + ? null + : hasContext.child; + else if (18 === hasContext.tag) { + newValue = hasContext.return; + if (null === newValue) + throw Error( + "We just came from a parent so we must have had a parent. This is a bug in React." + ); + newValue.lanes |= renderLanes; + list = newValue.alternate; + null !== list && (list.lanes |= renderLanes); + scheduleContextWorkOnParentPath( + newValue, + renderLanes, + workInProgress + ); + newValue = hasContext.sibling; + } else newValue = hasContext.child; + if (null !== newValue) newValue.return = hasContext; else - for (hasContext = newValue; null !== hasContext; ) { - if (hasContext === workInProgress) { - hasContext = null; + for (newValue = hasContext; null !== newValue; ) { + if (newValue === workInProgress) { + newValue = null; break; } - newValue = hasContext.sibling; - if (null !== newValue) { - newValue.return = hasContext.return; - hasContext = newValue; + hasContext = newValue.sibling; + if (null !== hasContext) { + hasContext.return = newValue.return; + newValue = hasContext; break; } - hasContext = hasContext.return; + newValue = newValue.return; } - newValue = hasContext; + hasContext = newValue; } reconcileChildren( current, @@ -7577,10 +7905,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { workInProgress.elementType === Component ? context : resolveDefaultProps(Component, context)), - null !== current && - ((current.alternate = null), - (workInProgress.alternate = null), - (workInProgress.flags |= 2)), + resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress), (workInProgress.tag = 1), isContextProvider(Component) ? ((current = !0), pushContextProvider(workInProgress)) @@ -7920,10 +8245,10 @@ batchedUpdatesImpl = function(fn, a) { } }; var roots = new Map(), - devToolsConfig$jscomp$inline_934 = { + devToolsConfig$jscomp$inline_925 = { findFiberByHostInstance: getInstanceFromInstance, bundleType: 0, - version: "18.0.0-experimental-34aa5cfe0-20220329", + version: "18.2.0-next-d300cebde-20220601", rendererPackageName: "react-native-renderer", rendererConfig: { getInspectorDataForViewTag: function() { @@ -7938,11 +8263,11 @@ var roots = new Map(), }.bind(null, findNodeHandle) } }; -var internals$jscomp$inline_1178 = { - bundleType: devToolsConfig$jscomp$inline_934.bundleType, - version: devToolsConfig$jscomp$inline_934.version, - rendererPackageName: devToolsConfig$jscomp$inline_934.rendererPackageName, - rendererConfig: devToolsConfig$jscomp$inline_934.rendererConfig, +var internals$jscomp$inline_1171 = { + bundleType: devToolsConfig$jscomp$inline_925.bundleType, + version: devToolsConfig$jscomp$inline_925.version, + rendererPackageName: devToolsConfig$jscomp$inline_925.rendererPackageName, + rendererConfig: devToolsConfig$jscomp$inline_925.rendererConfig, overrideHookState: null, overrideHookStateDeletePath: null, overrideHookStateRenamePath: null, @@ -7958,26 +8283,26 @@ var internals$jscomp$inline_1178 = { return null === fiber ? null : fiber.stateNode; }, findFiberByHostInstance: - devToolsConfig$jscomp$inline_934.findFiberByHostInstance || + devToolsConfig$jscomp$inline_925.findFiberByHostInstance || emptyFindFiberByHostInstance, findHostInstancesForRefresh: null, scheduleRefresh: null, scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "18.0.0-experimental-34aa5cfe0-20220329" + reconcilerVersion: "18.2.0-next-d300cebde-20220601" }; if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { - var hook$jscomp$inline_1179 = __REACT_DEVTOOLS_GLOBAL_HOOK__; + var hook$jscomp$inline_1172 = __REACT_DEVTOOLS_GLOBAL_HOOK__; if ( - !hook$jscomp$inline_1179.isDisabled && - hook$jscomp$inline_1179.supportsFiber + !hook$jscomp$inline_1172.isDisabled && + hook$jscomp$inline_1172.supportsFiber ) try { - (rendererID = hook$jscomp$inline_1179.inject( - internals$jscomp$inline_1178 + (rendererID = hook$jscomp$inline_1172.inject( + internals$jscomp$inline_1171 )), - (injectedHook = hook$jscomp$inline_1179); + (injectedHook = hook$jscomp$inline_1172); } catch (err) {} } exports.createPortal = function(children, containerTag) { @@ -8032,7 +8357,8 @@ exports.render = function(element, containerTag, callback, concurrentRoot) { element: null, isDehydrated: !1, cache: null, - transitions: null + transitions: null, + pendingSuspenseBoundaries: null }), initializeUpdateQueue(root), (root = concurrentRoot), diff --git a/Libraries/Renderer/implementations/ReactFabric-profiling.js b/Libraries/Renderer/implementations/ReactFabric-profiling.js index dee0ec43622f93..d8823b6d8e767d 100644 --- a/Libraries/Renderer/implementations/ReactFabric-profiling.js +++ b/Libraries/Renderer/implementations/ReactFabric-profiling.js @@ -8,7 +8,7 @@ * @nolint * @providesModule ReactFabric-profiling * @preventMunge - * @generated SignedSource<> + * @generated SignedSource<> */ @@ -1028,7 +1028,7 @@ eventPluginOrder = Array.prototype.slice.call([ "ReactNativeBridgeEventPlugin" ]); recomputePluginOrdering(); -var injectedNamesToPlugins$jscomp$inline_223 = { +var injectedNamesToPlugins$jscomp$inline_229 = { ResponderEventPlugin: ResponderEventPlugin, ReactNativeBridgeEventPlugin: { eventTypes: {}, @@ -1074,33 +1074,33 @@ var injectedNamesToPlugins$jscomp$inline_223 = { } } }, - isOrderingDirty$jscomp$inline_224 = !1, - pluginName$jscomp$inline_225; -for (pluginName$jscomp$inline_225 in injectedNamesToPlugins$jscomp$inline_223) + isOrderingDirty$jscomp$inline_230 = !1, + pluginName$jscomp$inline_231; +for (pluginName$jscomp$inline_231 in injectedNamesToPlugins$jscomp$inline_229) if ( - injectedNamesToPlugins$jscomp$inline_223.hasOwnProperty( - pluginName$jscomp$inline_225 + injectedNamesToPlugins$jscomp$inline_229.hasOwnProperty( + pluginName$jscomp$inline_231 ) ) { - var pluginModule$jscomp$inline_226 = - injectedNamesToPlugins$jscomp$inline_223[pluginName$jscomp$inline_225]; + var pluginModule$jscomp$inline_232 = + injectedNamesToPlugins$jscomp$inline_229[pluginName$jscomp$inline_231]; if ( - !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_225) || - namesToPlugins[pluginName$jscomp$inline_225] !== - pluginModule$jscomp$inline_226 + !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_231) || + namesToPlugins[pluginName$jscomp$inline_231] !== + pluginModule$jscomp$inline_232 ) { - if (namesToPlugins[pluginName$jscomp$inline_225]) + if (namesToPlugins[pluginName$jscomp$inline_231]) throw Error( "EventPluginRegistry: Cannot inject two different event plugins using the same name, `" + - (pluginName$jscomp$inline_225 + "`.") + (pluginName$jscomp$inline_231 + "`.") ); namesToPlugins[ - pluginName$jscomp$inline_225 - ] = pluginModule$jscomp$inline_226; - isOrderingDirty$jscomp$inline_224 = !0; + pluginName$jscomp$inline_231 + ] = pluginModule$jscomp$inline_232; + isOrderingDirty$jscomp$inline_230 = !0; } } -isOrderingDirty$jscomp$inline_224 && recomputePluginOrdering(); +isOrderingDirty$jscomp$inline_230 && recomputePluginOrdering(); function getInstanceFromInstance(instanceHandle) { return instanceHandle; } @@ -1870,6 +1870,12 @@ function getLanesToRetrySynchronouslyOnError(root) { root = root.pendingLanes & -1073741825; return 0 !== root ? root : root & 1073741824 ? 1073741824 : 0; } +function claimNextTransitionLane() { + var lane = nextTransitionLane; + nextTransitionLane <<= 1; + 0 === (nextTransitionLane & 4194240) && (nextTransitionLane = 64); + return lane; +} function createLaneMap(initial) { for (var laneMap = [], i = 0; 31 > i; i++) laneMap.push(initial); return laneMap; @@ -2248,7 +2254,28 @@ function flushSyncCallbacks() { } return null; } -var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig; +var forkStack = [], + forkStackIndex = 0, + treeForkProvider = null, + idStack = [], + idStackIndex = 0, + treeContextProvider = null; +function popTreeContext(workInProgress) { + for (; workInProgress === treeForkProvider; ) + (treeForkProvider = forkStack[--forkStackIndex]), + (forkStack[forkStackIndex] = null), + --forkStackIndex, + (forkStack[forkStackIndex] = null); + for (; workInProgress === treeContextProvider; ) + (treeContextProvider = idStack[--idStackIndex]), + (idStack[idStackIndex] = null), + --idStackIndex, + (idStack[idStackIndex] = null), + --idStackIndex, + (idStack[idStackIndex] = null); +} +var hydrationErrors = null, + ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig; function shallowEqual(objA, objB) { if (objectIs(objA, objB)) return !0; if ( @@ -2393,9 +2420,7 @@ function enqueueUpdate(fiber, update) { var updateQueue = fiber.updateQueue; null !== updateQueue && ((updateQueue = updateQueue.shared), - null !== workInProgressRoot && - 0 !== (fiber.mode & 1) && - 0 === (executionContext & 2) + isInterleavedUpdate(fiber) ? ((fiber = updateQueue.interleaved), null === fiber ? ((update.next = update), @@ -2763,26 +2788,6 @@ function mountClassInstance(workInProgress, ctor, newProps, renderLanes) { "function" === typeof instance.componentDidMount && (workInProgress.flags |= 4); } -var forkStack = [], - forkStackIndex = 0, - treeForkProvider = null, - idStack = [], - idStackIndex = 0, - treeContextProvider = null; -function popTreeContext(workInProgress) { - for (; workInProgress === treeForkProvider; ) - (treeForkProvider = forkStack[--forkStackIndex]), - (forkStack[forkStackIndex] = null), - --forkStackIndex, - (forkStack[forkStackIndex] = null); - for (; workInProgress === treeContextProvider; ) - (treeContextProvider = idStack[--idStackIndex]), - (idStack[idStackIndex] = null), - --idStackIndex, - (idStack[idStackIndex] = null), - --idStackIndex, - (idStack[idStackIndex] = null); -} function coerceRef(returnFiber, current, element) { returnFiber = element.ref; if ( @@ -2845,6 +2850,10 @@ function throwOnInvalidObjectType(returnFiber, newChild) { "). If you meant to render a collection of children, use an array instead." ); } +function resolveLazy(lazyType) { + var init = lazyType._init; + return init(lazyType._payload); +} function ChildReconciler(shouldTrackSideEffects) { function deleteChild(returnFiber, childToDelete) { if (shouldTrackSideEffects) { @@ -2917,7 +2926,14 @@ function ChildReconciler(shouldTrackSideEffects) { lanes, element.key ); - if (null !== current && current.elementType === elementType) + if ( + null !== current && + (current.elementType === elementType || + ("object" === typeof elementType && + null !== elementType && + elementType.$$typeof === REACT_LAZY_TYPE && + resolveLazy(elementType) === current.type)) + ) return ( (lanes = useFiber(current, element.props)), (lanes.ref = coerceRef(returnFiber, current, element)), @@ -3008,6 +3024,9 @@ function ChildReconciler(shouldTrackSideEffects) { (newChild.return = returnFiber), newChild ); + case REACT_LAZY_TYPE: + var init = newChild._init; + return createChild(returnFiber, init(newChild._payload), lanes); } if (isArrayImpl(newChild) || getIteratorFn(newChild)) return ( @@ -3043,6 +3062,11 @@ function ChildReconciler(shouldTrackSideEffects) { return newChild.key === key ? updatePortal(returnFiber, oldFiber, newChild, lanes) : null; + case REACT_LAZY_TYPE: + return ( + (key = newChild._init), + updateSlot(returnFiber, oldFiber, key(newChild._payload), lanes) + ); } if (isArrayImpl(newChild) || getIteratorFn(newChild)) return null !== key @@ -3085,6 +3109,15 @@ function ChildReconciler(shouldTrackSideEffects) { ) || null), updatePortal(returnFiber, existingChildren, newChild, lanes) ); + case REACT_LAZY_TYPE: + var init = newChild._init; + return updateFromMap( + existingChildren, + returnFiber, + newIdx, + init(newChild._payload), + lanes + ); } if (isArrayImpl(newChild) || getIteratorFn(newChild)) return ( @@ -3262,7 +3295,12 @@ function ChildReconciler(shouldTrackSideEffects) { }); return iteratorFn; } - return function(returnFiber, currentFirstChild, newChild, lanes) { + function reconcileChildFibers( + returnFiber, + currentFirstChild, + newChild, + lanes + ) { "object" === typeof newChild && null !== newChild && newChild.type === REACT_FRAGMENT_TYPE && @@ -3290,7 +3328,13 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber = currentFirstChild; break a; } - } else if (child.elementType === key) { + } else if ( + child.elementType === key || + ("object" === typeof key && + null !== key && + key.$$typeof === REACT_LAZY_TYPE && + resolveLazy(key) === child.type) + ) { deleteRemainingChildren(returnFiber, child.sibling); currentFirstChild = useFiber(child, newChild.props); currentFirstChild.ref = coerceRef( @@ -3371,6 +3415,16 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber = currentFirstChild; } return placeSingleChild(returnFiber); + case REACT_LAZY_TYPE: + return ( + (child = newChild._init), + reconcileChildFibers( + returnFiber, + currentFirstChild, + child(newChild._payload), + lanes + ) + ); } if (isArrayImpl(newChild)) return reconcileChildrenArray( @@ -3406,7 +3460,8 @@ function ChildReconciler(shouldTrackSideEffects) { (returnFiber = currentFirstChild)), placeSingleChild(returnFiber)) : deleteRemainingChildren(returnFiber, currentFirstChild); - }; + } + return reconcileChildFibers; } var reconcileChildFibers = ChildReconciler(!0), mountChildFibers = ChildReconciler(!1), @@ -3893,6 +3948,19 @@ function updateMemo(nextCreate, deps) { hook.memoizedState = [nextCreate, deps]; return nextCreate; } +function updateDeferredValueImpl(hook, prevValue, value) { + if (0 === (renderLanes & 21)) + return ( + hook.baseState && ((hook.baseState = !1), (didReceiveUpdate = !0)), + (hook.memoizedState = value) + ); + objectIs(value, prevValue) || + ((value = claimNextTransitionLane()), + (currentlyRenderingFiber$1.lanes |= value), + (workInProgressRootSkippedLanes |= value), + (hook.baseState = !0)); + return prevValue; +} function startTransition(setPending, callback) { var previousPriority = currentUpdatePriority; currentUpdatePriority = @@ -3974,9 +4042,7 @@ function enqueueRenderPhaseUpdate(queue, update) { queue.pending = update; } function enqueueUpdate$1(fiber, queue, update) { - null !== workInProgressRoot && - 0 !== (fiber.mode & 1) && - 0 === (executionContext & 2) + isInterleavedUpdate(fiber) ? ((fiber = queue.interleaved), null === fiber ? ((update.next = update), @@ -4081,29 +4147,14 @@ var ContextOnlyDispatcher = { useState: mountState, useDebugValue: mountDebugValue, useDeferredValue: function(value) { - var _mountState = mountState(value), - prevValue = _mountState[0], - setValue = _mountState[1]; - mountEffect( - function() { - var prevTransition = ReactCurrentBatchConfig$1.transition; - ReactCurrentBatchConfig$1.transition = {}; - try { - setValue(value); - } finally { - ReactCurrentBatchConfig$1.transition = prevTransition; - } - }, - [value] - ); - return prevValue; + return (mountWorkInProgressHook().memoizedState = value); }, useTransition: function() { - var _mountState2 = mountState(!1), - isPending = _mountState2[0]; - _mountState2 = startTransition.bind(null, _mountState2[1]); - mountWorkInProgressHook().memoizedState = _mountState2; - return [isPending, _mountState2]; + var _mountState = mountState(!1), + isPending = _mountState[0]; + _mountState = startTransition.bind(null, _mountState[1]); + mountWorkInProgressHook().memoizedState = _mountState; + return [isPending, _mountState]; }, useMutableSource: function() {}, useSyncExternalStore: function(subscribe, getSnapshot) { @@ -4157,22 +4208,8 @@ var ContextOnlyDispatcher = { }, useDebugValue: mountDebugValue, useDeferredValue: function(value) { - var _updateState = updateReducer(basicStateReducer), - prevValue = _updateState[0], - setValue = _updateState[1]; - updateEffect( - function() { - var prevTransition = ReactCurrentBatchConfig$1.transition; - ReactCurrentBatchConfig$1.transition = {}; - try { - setValue(value); - } finally { - ReactCurrentBatchConfig$1.transition = prevTransition; - } - }, - [value] - ); - return prevValue; + var hook = updateWorkInProgressHook(); + return updateDeferredValueImpl(hook, currentHook.memoizedState, value); }, useTransition: function() { var isPending = updateReducer(basicStateReducer)[0], @@ -4200,22 +4237,10 @@ var ContextOnlyDispatcher = { }, useDebugValue: mountDebugValue, useDeferredValue: function(value) { - var _rerenderState = rerenderReducer(basicStateReducer), - prevValue = _rerenderState[0], - setValue = _rerenderState[1]; - updateEffect( - function() { - var prevTransition = ReactCurrentBatchConfig$1.transition; - ReactCurrentBatchConfig$1.transition = {}; - try { - setValue(value); - } finally { - ReactCurrentBatchConfig$1.transition = prevTransition; - } - }, - [value] - ); - return prevValue; + var hook = updateWorkInProgressHook(); + return null === currentHook + ? (hook.memoizedState = value) + : updateDeferredValueImpl(hook, currentHook.memoizedState, value); }, useTransition: function() { var isPending = rerenderReducer(basicStateReducer)[0], @@ -4377,641 +4402,94 @@ function attachPingListener(root, wakeable, lanes) { isDevToolsPresent && restorePendingUpdaters(root, lanes), wakeable.then(pingCache, pingCache)); } -function hadNoMutationsEffects(current, completedWork) { - if (null !== current && current.child === completedWork.child) return !0; - if (0 !== (completedWork.flags & 16)) return !1; - for (current = completedWork.child; null !== current; ) { - if (0 !== (current.flags & 12854) || 0 !== (current.subtreeFlags & 12854)) - return !1; - current = current.sibling; - } - return !0; +var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner, + didReceiveUpdate = !1; +function reconcileChildren(current, workInProgress, nextChildren, renderLanes) { + workInProgress.child = + null === current + ? mountChildFibers(workInProgress, null, nextChildren, renderLanes) + : reconcileChildFibers( + workInProgress, + current.child, + nextChildren, + renderLanes + ); } -var appendAllChildren, updateHostContainer, updateHostComponent, updateHostText; -appendAllChildren = function( - parent, +function updateForwardRef( + current, workInProgress, - needsVisibilityToggle, - isHidden + Component, + nextProps, + renderLanes ) { - for (var node = workInProgress.child; null !== node; ) { - if (5 === node.tag) { - var instance = node.stateNode; - needsVisibilityToggle && - isHidden && - (instance = cloneHiddenInstance(instance)); - appendChildNode(parent.node, instance.node); - } else if (6 === node.tag) { - instance = node.stateNode; - if (needsVisibilityToggle && isHidden) - throw Error("Not yet implemented."); - appendChildNode(parent.node, instance.node); - } else if (4 !== node.tag) - if (22 === node.tag && null !== node.memoizedState) - (instance = node.child), - null !== instance && (instance.return = node), - appendAllChildren(parent, node, !0, !0); - else if (null !== node.child) { - node.child.return = node; - node = node.child; - continue; - } - if (node === workInProgress) break; - for (; null === node.sibling; ) { - if (null === node.return || node.return === workInProgress) return; - node = node.return; - } - node.sibling.return = node.return; - node = node.sibling; - } -}; -function appendAllChildrenToContainer( - containerChildSet, + Component = Component.render; + var ref = workInProgress.ref; + prepareToReadContext(workInProgress, renderLanes); + nextProps = renderWithHooks( + current, + workInProgress, + Component, + nextProps, + ref, + renderLanes + ); + if (null !== current && !didReceiveUpdate) + return ( + (workInProgress.updateQueue = current.updateQueue), + (workInProgress.flags &= -2053), + (current.lanes &= ~renderLanes), + bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) + ); + workInProgress.flags |= 1; + reconcileChildren(current, workInProgress, nextProps, renderLanes); + return workInProgress.child; +} +function updateMemoComponent( + current, workInProgress, - needsVisibilityToggle, - isHidden + Component, + nextProps, + renderLanes ) { - for (var node = workInProgress.child; null !== node; ) { - if (5 === node.tag) { - var instance = node.stateNode; - needsVisibilityToggle && - isHidden && - (instance = cloneHiddenInstance(instance)); - appendChildNodeToSet(containerChildSet, instance.node); - } else if (6 === node.tag) { - instance = node.stateNode; - if (needsVisibilityToggle && isHidden) - throw Error("Not yet implemented."); - appendChildNodeToSet(containerChildSet, instance.node); - } else if (4 !== node.tag) - if (22 === node.tag && null !== node.memoizedState) - (instance = node.child), - null !== instance && (instance.return = node), - appendAllChildrenToContainer(containerChildSet, node, !0, !0); - else if (null !== node.child) { - node.child.return = node; - node = node.child; - continue; - } - if (node === workInProgress) break; - for (; null === node.sibling; ) { - if (null === node.return || node.return === workInProgress) return; - node = node.return; - } - node.sibling.return = node.return; - node = node.sibling; + if (null === current) { + var type = Component.type; + if ( + "function" === typeof type && + !shouldConstruct(type) && + void 0 === type.defaultProps && + null === Component.compare && + void 0 === Component.defaultProps + ) + return ( + (workInProgress.tag = 15), + (workInProgress.type = type), + updateSimpleMemoComponent( + current, + workInProgress, + type, + nextProps, + renderLanes + ) + ); + current = createFiberFromTypeAndProps( + Component.type, + null, + nextProps, + workInProgress, + workInProgress.mode, + renderLanes + ); + current.ref = workInProgress.ref; + current.return = workInProgress; + return (workInProgress.child = current); } -} -updateHostContainer = function(current, workInProgress) { - var portalOrRoot = workInProgress.stateNode; - if (!hadNoMutationsEffects(current, workInProgress)) { - current = portalOrRoot.containerInfo; - var newChildSet = createChildNodeSet(current); - appendAllChildrenToContainer(newChildSet, workInProgress, !1, !1); - portalOrRoot.pendingChildren = newChildSet; - workInProgress.flags |= 4; - completeRoot(current, newChildSet); - } -}; -updateHostComponent = function(current, workInProgress, type, newProps) { - type = current.stateNode; - var oldProps = current.memoizedProps; - if ( - (current = hadNoMutationsEffects(current, workInProgress)) && - oldProps === newProps - ) - workInProgress.stateNode = type; - else { - var recyclableInstance = workInProgress.stateNode; - requiredContext(contextStackCursor$1.current); - var updatePayload = null; - oldProps !== newProps && - ((oldProps = diffProperties( - null, - oldProps, - newProps, - recyclableInstance.canonical.viewConfig.validAttributes - )), - (recyclableInstance.canonical.currentProps = newProps), - (updatePayload = oldProps)); - current && null === updatePayload - ? (workInProgress.stateNode = type) - : ((newProps = updatePayload), - (oldProps = type.node), - (type = { - node: current - ? null !== newProps - ? cloneNodeWithNewProps(oldProps, newProps) - : cloneNode(oldProps) - : null !== newProps - ? cloneNodeWithNewChildrenAndProps(oldProps, newProps) - : cloneNodeWithNewChildren(oldProps), - canonical: type.canonical - }), - (workInProgress.stateNode = type), - current - ? (workInProgress.flags |= 4) - : appendAllChildren(type, workInProgress, !1, !1)); - } -}; -updateHostText = function(current, workInProgress, oldText, newText) { - oldText !== newText - ? ((current = requiredContext(rootInstanceStackCursor.current)), - (oldText = requiredContext(contextStackCursor$1.current)), - (workInProgress.stateNode = createTextInstance( - newText, - current, - oldText, - workInProgress - )), - (workInProgress.flags |= 4)) - : (workInProgress.stateNode = current.stateNode); -}; -function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { - switch (renderState.tailMode) { - case "hidden": - hasRenderedATailFallback = renderState.tail; - for (var lastTailNode = null; null !== hasRenderedATailFallback; ) - null !== hasRenderedATailFallback.alternate && - (lastTailNode = hasRenderedATailFallback), - (hasRenderedATailFallback = hasRenderedATailFallback.sibling); - null === lastTailNode - ? (renderState.tail = null) - : (lastTailNode.sibling = null); - break; - case "collapsed": - lastTailNode = renderState.tail; - for (var lastTailNode$37 = null; null !== lastTailNode; ) - null !== lastTailNode.alternate && (lastTailNode$37 = lastTailNode), - (lastTailNode = lastTailNode.sibling); - null === lastTailNode$37 - ? hasRenderedATailFallback || null === renderState.tail - ? (renderState.tail = null) - : (renderState.tail.sibling = null) - : (lastTailNode$37.sibling = null); - } -} -function bubbleProperties(completedWork) { - var didBailout = - null !== completedWork.alternate && - completedWork.alternate.child === completedWork.child, - newChildLanes = 0, - subtreeFlags = 0; - if (didBailout) - if (0 !== (completedWork.mode & 2)) { - for ( - var treeBaseDuration$39 = completedWork.selfBaseDuration, - child$40 = completedWork.child; - null !== child$40; - - ) - (newChildLanes |= child$40.lanes | child$40.childLanes), - (subtreeFlags |= child$40.subtreeFlags & 14680064), - (subtreeFlags |= child$40.flags & 14680064), - (treeBaseDuration$39 += child$40.treeBaseDuration), - (child$40 = child$40.sibling); - completedWork.treeBaseDuration = treeBaseDuration$39; - } else - for ( - treeBaseDuration$39 = completedWork.child; - null !== treeBaseDuration$39; - - ) - (newChildLanes |= - treeBaseDuration$39.lanes | treeBaseDuration$39.childLanes), - (subtreeFlags |= treeBaseDuration$39.subtreeFlags & 14680064), - (subtreeFlags |= treeBaseDuration$39.flags & 14680064), - (treeBaseDuration$39.return = completedWork), - (treeBaseDuration$39 = treeBaseDuration$39.sibling); - else if (0 !== (completedWork.mode & 2)) { - treeBaseDuration$39 = completedWork.actualDuration; - child$40 = completedWork.selfBaseDuration; - for (var child = completedWork.child; null !== child; ) - (newChildLanes |= child.lanes | child.childLanes), - (subtreeFlags |= child.subtreeFlags), - (subtreeFlags |= child.flags), - (treeBaseDuration$39 += child.actualDuration), - (child$40 += child.treeBaseDuration), - (child = child.sibling); - completedWork.actualDuration = treeBaseDuration$39; - completedWork.treeBaseDuration = child$40; - } else - for ( - treeBaseDuration$39 = completedWork.child; - null !== treeBaseDuration$39; - - ) - (newChildLanes |= - treeBaseDuration$39.lanes | treeBaseDuration$39.childLanes), - (subtreeFlags |= treeBaseDuration$39.subtreeFlags), - (subtreeFlags |= treeBaseDuration$39.flags), - (treeBaseDuration$39.return = completedWork), - (treeBaseDuration$39 = treeBaseDuration$39.sibling); - completedWork.subtreeFlags |= subtreeFlags; - completedWork.childLanes = newChildLanes; - return didBailout; -} -function completeWork(current, workInProgress, renderLanes) { - var newProps = workInProgress.pendingProps; - popTreeContext(workInProgress); - switch (workInProgress.tag) { - case 2: - case 16: - case 15: - case 0: - case 11: - case 7: - case 8: - case 12: - case 9: - case 14: - return bubbleProperties(workInProgress), null; - case 1: - return ( - isContextProvider(workInProgress.type) && popContext(), - bubbleProperties(workInProgress), - null - ); - case 3: - return ( - (newProps = workInProgress.stateNode), - popHostContainer(), - pop(didPerformWorkStackCursor), - pop(contextStackCursor), - resetWorkInProgressVersions(), - newProps.pendingContext && - ((newProps.context = newProps.pendingContext), - (newProps.pendingContext = null)), - (null !== current && null !== current.child) || - null === current || - (current.memoizedState.isDehydrated && - 0 === (workInProgress.flags & 256)) || - (workInProgress.flags |= 1024), - updateHostContainer(current, workInProgress), - bubbleProperties(workInProgress), - null - ); - case 5: - popHostContext(workInProgress); - renderLanes = requiredContext(rootInstanceStackCursor.current); - var type = workInProgress.type; - if (null !== current && null != workInProgress.stateNode) - updateHostComponent( - current, - workInProgress, - type, - newProps, - renderLanes - ), - current.ref !== workInProgress.ref && (workInProgress.flags |= 512); - else { - if (!newProps) { - if (null === workInProgress.stateNode) - throw Error( - "We must have new props for new mounts. This error is likely caused by a bug in React. Please file an issue." - ); - bubbleProperties(workInProgress); - return null; - } - requiredContext(contextStackCursor$1.current); - current = nextReactTag; - nextReactTag += 2; - type = getViewConfigForType(type); - var updatePayload = diffProperties( - null, - emptyObject, - newProps, - type.validAttributes - ); - renderLanes = createNode( - current, - type.uiViewClassName, - renderLanes, - updatePayload, - workInProgress - ); - current = new ReactFabricHostComponent( - current, - type, - newProps, - workInProgress - ); - current = { node: renderLanes, canonical: current }; - appendAllChildren(current, workInProgress, !1, !1); - workInProgress.stateNode = current; - null !== workInProgress.ref && (workInProgress.flags |= 512); - } - bubbleProperties(workInProgress); - return null; - case 6: - if (current && null != workInProgress.stateNode) - updateHostText( - current, - workInProgress, - current.memoizedProps, - newProps - ); - else { - if ("string" !== typeof newProps && null === workInProgress.stateNode) - throw Error( - "We must have new props for new mounts. This error is likely caused by a bug in React. Please file an issue." - ); - current = requiredContext(rootInstanceStackCursor.current); - renderLanes = requiredContext(contextStackCursor$1.current); - workInProgress.stateNode = createTextInstance( - newProps, - current, - renderLanes, - workInProgress - ); - } - bubbleProperties(workInProgress); - return null; - case 13: - pop(suspenseStackCursor); - newProps = workInProgress.memoizedState; - if (0 !== (workInProgress.flags & 128)) - return ( - (workInProgress.lanes = renderLanes), - 0 !== (workInProgress.mode & 2) && - transferActualDuration(workInProgress), - workInProgress - ); - newProps = null !== newProps; - renderLanes = !1; - null !== current && (renderLanes = null !== current.memoizedState); - newProps && - !renderLanes && - ((workInProgress.child.flags |= 8192), - 0 !== (workInProgress.mode & 1) && - (null === current || 0 !== (suspenseStackCursor.current & 1) - ? 0 === workInProgressRootExitStatus && - (workInProgressRootExitStatus = 3) - : renderDidSuspendDelayIfPossible())); - null !== workInProgress.updateQueue && (workInProgress.flags |= 4); - bubbleProperties(workInProgress); - 0 !== (workInProgress.mode & 2) && - newProps && - ((current = workInProgress.child), - null !== current && - (workInProgress.treeBaseDuration -= current.treeBaseDuration)); - return null; - case 4: - return ( - popHostContainer(), - updateHostContainer(current, workInProgress), - bubbleProperties(workInProgress), - null - ); - case 10: - return ( - popProvider(workInProgress.type._context), - bubbleProperties(workInProgress), - null - ); - case 17: - return ( - isContextProvider(workInProgress.type) && popContext(), - bubbleProperties(workInProgress), - null - ); - case 19: - pop(suspenseStackCursor); - type = workInProgress.memoizedState; - if (null === type) return bubbleProperties(workInProgress), null; - newProps = 0 !== (workInProgress.flags & 128); - updatePayload = type.rendering; - if (null === updatePayload) - if (newProps) cutOffTailIfNeeded(type, !1); - else { - if ( - 0 !== workInProgressRootExitStatus || - (null !== current && 0 !== (current.flags & 128)) - ) - for (current = workInProgress.child; null !== current; ) { - updatePayload = findFirstSuspended(current); - if (null !== updatePayload) { - workInProgress.flags |= 128; - cutOffTailIfNeeded(type, !1); - current = updatePayload.updateQueue; - null !== current && - ((workInProgress.updateQueue = current), - (workInProgress.flags |= 4)); - workInProgress.subtreeFlags = 0; - current = renderLanes; - for (newProps = workInProgress.child; null !== newProps; ) - (renderLanes = newProps), - (updatePayload = current), - (renderLanes.flags &= 14680066), - (type = renderLanes.alternate), - null === type - ? ((renderLanes.childLanes = 0), - (renderLanes.lanes = updatePayload), - (renderLanes.child = null), - (renderLanes.subtreeFlags = 0), - (renderLanes.memoizedProps = null), - (renderLanes.memoizedState = null), - (renderLanes.updateQueue = null), - (renderLanes.dependencies = null), - (renderLanes.stateNode = null), - (renderLanes.selfBaseDuration = 0), - (renderLanes.treeBaseDuration = 0)) - : ((renderLanes.childLanes = type.childLanes), - (renderLanes.lanes = type.lanes), - (renderLanes.child = type.child), - (renderLanes.subtreeFlags = 0), - (renderLanes.deletions = null), - (renderLanes.memoizedProps = type.memoizedProps), - (renderLanes.memoizedState = type.memoizedState), - (renderLanes.updateQueue = type.updateQueue), - (renderLanes.type = type.type), - (updatePayload = type.dependencies), - (renderLanes.dependencies = - null === updatePayload - ? null - : { - lanes: updatePayload.lanes, - firstContext: updatePayload.firstContext - }), - (renderLanes.selfBaseDuration = type.selfBaseDuration), - (renderLanes.treeBaseDuration = type.treeBaseDuration)), - (newProps = newProps.sibling); - push( - suspenseStackCursor, - (suspenseStackCursor.current & 1) | 2 - ); - return workInProgress.child; - } - current = current.sibling; - } - null !== type.tail && - now() > workInProgressRootRenderTargetTime && - ((workInProgress.flags |= 128), - (newProps = !0), - cutOffTailIfNeeded(type, !1), - (workInProgress.lanes = 4194304)); - } - else { - if (!newProps) - if ( - ((current = findFirstSuspended(updatePayload)), null !== current) - ) { - if ( - ((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 && - !updatePayload.alternate) - ) - return bubbleProperties(workInProgress), null; - } else - 2 * now() - type.renderingStartTime > - workInProgressRootRenderTargetTime && - 1073741824 !== renderLanes && - ((workInProgress.flags |= 128), - (newProps = !0), - cutOffTailIfNeeded(type, !1), - (workInProgress.lanes = 4194304)); - type.isBackwards - ? ((updatePayload.sibling = workInProgress.child), - (workInProgress.child = updatePayload)) - : ((current = type.last), - null !== current - ? (current.sibling = updatePayload) - : (workInProgress.child = updatePayload), - (type.last = updatePayload)); - } - if (null !== type.tail) - return ( - (workInProgress = type.tail), - (type.rendering = workInProgress), - (type.tail = workInProgress.sibling), - (type.renderingStartTime = now()), - (workInProgress.sibling = null), - (current = suspenseStackCursor.current), - push(suspenseStackCursor, newProps ? (current & 1) | 2 : current & 1), - workInProgress - ); - bubbleProperties(workInProgress); - return null; - case 22: - case 23: - return ( - popRenderLanes(), - (newProps = null !== workInProgress.memoizedState), - null !== current && - (null !== current.memoizedState) !== newProps && - (workInProgress.flags |= 8192), - newProps && 0 !== (workInProgress.mode & 1) - ? 0 !== (subtreeRenderLanes & 1073741824) && - bubbleProperties(workInProgress) - : bubbleProperties(workInProgress), - null - ); - case 24: - return null; - case 25: - return null; - } - throw Error( - "Unknown unit of work tag (" + - workInProgress.tag + - "). This error is likely caused by a bug in React. Please file an issue." - ); -} -var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner, - didReceiveUpdate = !1; -function reconcileChildren(current, workInProgress, nextChildren, renderLanes) { - workInProgress.child = - null === current - ? mountChildFibers(workInProgress, null, nextChildren, renderLanes) - : reconcileChildFibers( - workInProgress, - current.child, - nextChildren, - renderLanes - ); -} -function updateForwardRef( - current, - workInProgress, - Component, - nextProps, - renderLanes -) { - Component = Component.render; - var ref = workInProgress.ref; - prepareToReadContext(workInProgress, renderLanes); - nextProps = renderWithHooks( - current, - workInProgress, - Component, - nextProps, - ref, - renderLanes - ); - if (null !== current && !didReceiveUpdate) - return ( - (workInProgress.updateQueue = current.updateQueue), - (workInProgress.flags &= -2053), - (current.lanes &= ~renderLanes), - bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) - ); - workInProgress.flags |= 1; - reconcileChildren(current, workInProgress, nextProps, renderLanes); - return workInProgress.child; -} -function updateMemoComponent( - current, - workInProgress, - Component, - nextProps, - renderLanes -) { - if (null === current) { - var type = Component.type; - if ( - "function" === typeof type && - !shouldConstruct(type) && - void 0 === type.defaultProps && - null === Component.compare && - void 0 === Component.defaultProps - ) - return ( - (workInProgress.tag = 15), - (workInProgress.type = type), - updateSimpleMemoComponent( - current, - workInProgress, - type, - nextProps, - renderLanes - ) - ); - current = createFiberFromTypeAndProps( - Component.type, - null, - nextProps, - workInProgress, - workInProgress.mode, - renderLanes - ); - current.ref = workInProgress.ref; - current.return = workInProgress; - return (workInProgress.child = current); - } - type = current.child; - if (0 === (current.lanes & renderLanes)) { - var prevProps = type.memoizedProps; - Component = Component.compare; - Component = null !== Component ? Component : shallowEqual; - if (Component(prevProps, nextProps) && current.ref === workInProgress.ref) - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); + type = current.child; + if (0 === (current.lanes & renderLanes)) { + var prevProps = type.memoizedProps; + Component = Component.compare; + Component = null !== Component ? Component : shallowEqual; + if (Component(prevProps, nextProps) && current.ref === workInProgress.ref) + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); } workInProgress.flags |= 1; current = createWorkInProgress(type, nextProps); @@ -5026,18 +4504,24 @@ function updateSimpleMemoComponent( nextProps, renderLanes ) { - if ( - null !== current && - shallowEqual(current.memoizedProps, nextProps) && - current.ref === workInProgress.ref - ) - if (((didReceiveUpdate = !1), 0 !== (current.lanes & renderLanes))) - 0 !== (current.flags & 131072) && (didReceiveUpdate = !0); - else - return ( - (workInProgress.lanes = current.lanes), - bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) - ); + if (null !== current) { + var prevProps = current.memoizedProps; + if ( + shallowEqual(prevProps, nextProps) && + current.ref === workInProgress.ref + ) + if ( + ((didReceiveUpdate = !1), + (workInProgress.pendingProps = nextProps = prevProps), + 0 !== (current.lanes & renderLanes)) + ) + 0 !== (current.flags & 131072) && (didReceiveUpdate = !0); + else + return ( + (workInProgress.lanes = current.lanes), + bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) + ); + } return updateFunctionComponent( current, workInProgress, @@ -5052,7 +4536,11 @@ function updateOffscreenComponent(current, workInProgress, renderLanes) { prevState = null !== current ? current.memoizedState : null; if ("hidden" === nextProps.mode) if (0 === (workInProgress.mode & 1)) - (workInProgress.memoizedState = { baseLanes: 0, cachePool: null }), + (workInProgress.memoizedState = { + baseLanes: 0, + cachePool: null, + transitions: null + }), push(subtreeRenderLanesCursor, subtreeRenderLanes), (subtreeRenderLanes |= renderLanes); else { @@ -5065,14 +4553,19 @@ function updateOffscreenComponent(current, workInProgress, renderLanes) { (workInProgress.lanes = workInProgress.childLanes = 1073741824), (workInProgress.memoizedState = { baseLanes: current, - cachePool: null + cachePool: null, + transitions: null }), (workInProgress.updateQueue = null), push(subtreeRenderLanesCursor, subtreeRenderLanes), (subtreeRenderLanes |= current), null ); - workInProgress.memoizedState = { baseLanes: 0, cachePool: null }; + workInProgress.memoizedState = { + baseLanes: 0, + cachePool: null, + transitions: null + }; nextProps = null !== prevState ? prevState.baseLanes : renderLanes; push(subtreeRenderLanesCursor, subtreeRenderLanes); subtreeRenderLanes |= nextProps; @@ -5087,7 +4580,7 @@ function updateOffscreenComponent(current, workInProgress, renderLanes) { reconcileChildren(current, workInProgress, nextChildren, renderLanes); return workInProgress.child; } -function markRef$1(current, workInProgress) { +function markRef(current, workInProgress) { var ref = workInProgress.ref; if ( (null === current && null !== ref) || @@ -5139,10 +4632,7 @@ function updateClassComponent( } else hasContext = !1; prepareToReadContext(workInProgress, renderLanes); if (null === workInProgress.stateNode) - null !== current && - ((current.alternate = null), - (workInProgress.alternate = null), - (workInProgress.flags |= 2)), + resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress), constructClassInstance(workInProgress, Component, nextProps), mountClassInstance(workInProgress, Component, nextProps, renderLanes), (nextProps = !0); @@ -5336,7 +4826,7 @@ function finishClassComponent( hasContext, renderLanes ) { - markRef$1(current, workInProgress); + markRef(current, workInProgress); var didCaptureError = 0 !== (workInProgress.flags & 128); if (!shouldUpdate && !didCaptureError) return ( @@ -5386,14 +4876,15 @@ function pushHostRootContext(workInProgress) { } var SUSPENDED_MARKER = { dehydrated: null, treeContext: null, retryLane: 0 }; function mountSuspenseOffscreenState(renderLanes) { - return { baseLanes: renderLanes, cachePool: null }; + return { baseLanes: renderLanes, cachePool: null, transitions: null }; } function updateSuspenseComponent(current, workInProgress, renderLanes) { var nextProps = workInProgress.pendingProps, suspenseContext = suspenseStackCursor.current, showFallback = !1, + didSuspend = 0 !== (workInProgress.flags & 128), JSCompiler_temp; - (JSCompiler_temp = 0 !== (workInProgress.flags & 128)) || + (JSCompiler_temp = didSuspend) || (JSCompiler_temp = null !== current && null === current.memoizedState ? !1 @@ -5403,177 +4894,307 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { suspenseContext |= 1; push(suspenseStackCursor, suspenseContext & 1); if (null === current) { - suspenseContext = nextProps.children; - current = nextProps.fallback; - if (showFallback) + current = workInProgress.memoizedState; + if (null !== current && null !== current.dehydrated) return ( - (showFallback = workInProgress.mode), - (nextProps = workInProgress.child), - (suspenseContext = { mode: "hidden", children: suspenseContext }), - 0 === (showFallback & 1) && null !== nextProps - ? ((nextProps.childLanes = 0), - (nextProps.pendingProps = suspenseContext), + 0 === (workInProgress.mode & 1) + ? (workInProgress.lanes = 1) + : shim$1() + ? (workInProgress.lanes = 8) + : (workInProgress.lanes = 1073741824), + null + ); + didSuspend = nextProps.children; + current = nextProps.fallback; + return showFallback + ? ((nextProps = workInProgress.mode), + (showFallback = workInProgress.child), + (didSuspend = { mode: "hidden", children: didSuspend }), + 0 === (nextProps & 1) && null !== showFallback + ? ((showFallback.childLanes = 0), + (showFallback.pendingProps = didSuspend), workInProgress.mode & 2 && - ((nextProps.actualDuration = 0), - (nextProps.actualStartTime = -1), - (nextProps.selfBaseDuration = 0), - (nextProps.treeBaseDuration = 0))) - : (nextProps = createFiberFromOffscreen( - suspenseContext, - showFallback, + ((showFallback.actualDuration = 0), + (showFallback.actualStartTime = -1), + (showFallback.selfBaseDuration = 0), + (showFallback.treeBaseDuration = 0))) + : (showFallback = createFiberFromOffscreen( + didSuspend, + nextProps, 0, null )), (current = createFiberFromFragment( current, - showFallback, + nextProps, renderLanes, null )), - (nextProps.return = workInProgress), + (showFallback.return = workInProgress), (current.return = workInProgress), - (nextProps.sibling = current), - (workInProgress.child = nextProps), + (showFallback.sibling = current), + (workInProgress.child = showFallback), (workInProgress.child.memoizedState = mountSuspenseOffscreenState( renderLanes )), (workInProgress.memoizedState = SUSPENDED_MARKER), - current - ); - renderLanes = createFiberFromOffscreen( - { mode: "visible", children: suspenseContext }, - workInProgress.mode, - 0, - null - ); - renderLanes.return = workInProgress; - return (workInProgress.child = renderLanes); + current) + : mountSuspensePrimaryChildren(workInProgress, didSuspend); } - if (null !== current.memoizedState) { - if (showFallback) - return ( - (showFallback = updateSuspenseFallbackChildren( - current, - workInProgress, - nextProps.children, - nextProps.fallback, - renderLanes - )), - (nextProps = workInProgress.child), - (suspenseContext = current.child.memoizedState), - (nextProps.memoizedState = - null === suspenseContext - ? mountSuspenseOffscreenState(renderLanes) - : { - baseLanes: suspenseContext.baseLanes | renderLanes, - cachePool: null - }), - (nextProps.childLanes = current.childLanes & ~renderLanes), - (workInProgress.memoizedState = SUSPENDED_MARKER), - showFallback - ); - renderLanes = updateSuspensePrimaryChildren( + suspenseContext = current.memoizedState; + if ( + null !== suspenseContext && + ((JSCompiler_temp = suspenseContext.dehydrated), null !== JSCompiler_temp) + ) + return updateDehydratedSuspenseComponent( current, workInProgress, - nextProps.children, + didSuspend, + nextProps, + JSCompiler_temp, + suspenseContext, renderLanes ); - workInProgress.memoizedState = null; - return renderLanes; - } - if (showFallback) - return ( - (showFallback = updateSuspenseFallbackChildren( - current, - workInProgress, - nextProps.children, - nextProps.fallback, - renderLanes - )), - (nextProps = workInProgress.child), - (suspenseContext = current.child.memoizedState), - (nextProps.memoizedState = - null === suspenseContext - ? mountSuspenseOffscreenState(renderLanes) - : { - baseLanes: suspenseContext.baseLanes | renderLanes, - cachePool: null - }), - (nextProps.childLanes = current.childLanes & ~renderLanes), - (workInProgress.memoizedState = SUSPENDED_MARKER), - showFallback - ); - renderLanes = updateSuspensePrimaryChildren( - current, - workInProgress, - nextProps.children, - renderLanes - ); - workInProgress.memoizedState = null; - return renderLanes; -} -function updateSuspensePrimaryChildren( - current, - workInProgress, - primaryChildren, - renderLanes -) { - var currentPrimaryChildFragment = current.child; - current = currentPrimaryChildFragment.sibling; - primaryChildren = createWorkInProgress(currentPrimaryChildFragment, { + if (showFallback) { + showFallback = nextProps.fallback; + didSuspend = workInProgress.mode; + suspenseContext = current.child; + JSCompiler_temp = suspenseContext.sibling; + var primaryChildProps = { mode: "hidden", children: nextProps.children }; + 0 === (didSuspend & 1) && workInProgress.child !== suspenseContext + ? ((nextProps = workInProgress.child), + (nextProps.childLanes = 0), + (nextProps.pendingProps = primaryChildProps), + workInProgress.mode & 2 && + ((nextProps.actualDuration = 0), + (nextProps.actualStartTime = -1), + (nextProps.selfBaseDuration = suspenseContext.selfBaseDuration), + (nextProps.treeBaseDuration = suspenseContext.treeBaseDuration)), + (workInProgress.deletions = null)) + : ((nextProps = createWorkInProgress(suspenseContext, primaryChildProps)), + (nextProps.subtreeFlags = suspenseContext.subtreeFlags & 14680064)); + null !== JSCompiler_temp + ? (showFallback = createWorkInProgress(JSCompiler_temp, showFallback)) + : ((showFallback = createFiberFromFragment( + showFallback, + didSuspend, + renderLanes, + null + )), + (showFallback.flags |= 2)); + showFallback.return = workInProgress; + nextProps.return = workInProgress; + nextProps.sibling = showFallback; + workInProgress.child = nextProps; + nextProps = showFallback; + showFallback = workInProgress.child; + didSuspend = current.child.memoizedState; + didSuspend = + null === didSuspend + ? mountSuspenseOffscreenState(renderLanes) + : { + baseLanes: didSuspend.baseLanes | renderLanes, + cachePool: null, + transitions: didSuspend.transitions + }; + showFallback.memoizedState = didSuspend; + showFallback.childLanes = current.childLanes & ~renderLanes; + workInProgress.memoizedState = SUSPENDED_MARKER; + return nextProps; + } + showFallback = current.child; + current = showFallback.sibling; + nextProps = createWorkInProgress(showFallback, { mode: "visible", - children: primaryChildren + children: nextProps.children }); - 0 === (workInProgress.mode & 1) && (primaryChildren.lanes = renderLanes); - primaryChildren.return = workInProgress; - primaryChildren.sibling = null; + 0 === (workInProgress.mode & 1) && (nextProps.lanes = renderLanes); + nextProps.return = workInProgress; + nextProps.sibling = null; null !== current && ((renderLanes = workInProgress.deletions), null === renderLanes ? ((workInProgress.deletions = [current]), (workInProgress.flags |= 16)) : renderLanes.push(current)); + workInProgress.child = nextProps; + workInProgress.memoizedState = null; + return nextProps; +} +function mountSuspensePrimaryChildren(workInProgress, primaryChildren) { + primaryChildren = createFiberFromOffscreen( + { mode: "visible", children: primaryChildren }, + workInProgress.mode, + 0, + null + ); + primaryChildren.return = workInProgress; return (workInProgress.child = primaryChildren); } -function updateSuspenseFallbackChildren( +function retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, + recoverableError +) { + null !== recoverableError && + (null === hydrationErrors + ? (hydrationErrors = [recoverableError]) + : hydrationErrors.push(recoverableError)); + reconcileChildFibers(workInProgress, current.child, null, renderLanes); + current = mountSuspensePrimaryChildren( + workInProgress, + workInProgress.pendingProps.children + ); + current.flags |= 2; + workInProgress.memoizedState = null; + return current; +} +function updateDehydratedSuspenseComponent( current, workInProgress, - primaryChildren, - fallbackChildren, + didSuspend, + nextProps, + suspenseInstance, + suspenseState, renderLanes ) { - var mode = workInProgress.mode; - current = current.child; - var currentFallbackChildFragment = current.sibling, - primaryChildProps = { mode: "hidden", children: primaryChildren }; - 0 === (mode & 1) && workInProgress.child !== current - ? ((primaryChildren = workInProgress.child), - (primaryChildren.childLanes = 0), - (primaryChildren.pendingProps = primaryChildProps), - workInProgress.mode & 2 && - ((primaryChildren.actualDuration = 0), - (primaryChildren.actualStartTime = -1), - (primaryChildren.selfBaseDuration = current.selfBaseDuration), - (primaryChildren.treeBaseDuration = current.treeBaseDuration)), - (workInProgress.deletions = null)) - : ((primaryChildren = createWorkInProgress(current, primaryChildProps)), - (primaryChildren.subtreeFlags = current.subtreeFlags & 14680064)); - null !== currentFallbackChildFragment - ? (fallbackChildren = createWorkInProgress( - currentFallbackChildFragment, - fallbackChildren - )) - : ((fallbackChildren = createFiberFromFragment( - fallbackChildren, - mode, - renderLanes, + if (didSuspend) { + if (workInProgress.flags & 256) + return ( + (workInProgress.flags &= -257), + retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, + Error( + "There was an error while hydrating this Suspense boundary. Switched to client rendering." + ) + ) + ); + if (null !== workInProgress.memoizedState) + return ( + (workInProgress.child = current.child), + (workInProgress.flags |= 128), null - )), - (fallbackChildren.flags |= 2)); - fallbackChildren.return = workInProgress; - primaryChildren.return = workInProgress; - primaryChildren.sibling = fallbackChildren; - workInProgress.child = primaryChildren; - return fallbackChildren; + ); + suspenseState = nextProps.fallback; + didSuspend = workInProgress.mode; + nextProps = createFiberFromOffscreen( + { mode: "visible", children: nextProps.children }, + didSuspend, + 0, + null + ); + suspenseState = createFiberFromFragment( + suspenseState, + didSuspend, + renderLanes, + null + ); + suspenseState.flags |= 2; + nextProps.return = workInProgress; + suspenseState.return = workInProgress; + nextProps.sibling = suspenseState; + workInProgress.child = nextProps; + 0 !== (workInProgress.mode & 1) && + reconcileChildFibers(workInProgress, current.child, null, renderLanes); + workInProgress.child.memoizedState = mountSuspenseOffscreenState( + renderLanes + ); + workInProgress.memoizedState = SUSPENDED_MARKER; + return suspenseState; + } + if (0 === (workInProgress.mode & 1)) + return retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, + null + ); + if (shim$1()) + return ( + (suspenseState = shim$1().errorMessage), + retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, + suspenseState + ? Error(suspenseState) + : Error( + "The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering." + ) + ) + ); + didSuspend = 0 !== (renderLanes & current.childLanes); + if (didReceiveUpdate || didSuspend) { + nextProps = workInProgressRoot; + if (null !== nextProps) { + switch (renderLanes & -renderLanes) { + case 4: + didSuspend = 2; + break; + case 16: + didSuspend = 8; + break; + 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: + case 8388608: + case 16777216: + case 33554432: + case 67108864: + didSuspend = 32; + break; + case 536870912: + didSuspend = 268435456; + break; + default: + didSuspend = 0; + } + nextProps = + 0 !== (didSuspend & (nextProps.suspendedLanes | renderLanes)) + ? 0 + : didSuspend; + 0 !== nextProps && + nextProps !== suspenseState.retryLane && + ((suspenseState.retryLane = nextProps), + scheduleUpdateOnFiber(current, nextProps, -1)); + } + renderDidSuspendDelayIfPossible(); + return retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, + Error( + "This Suspense boundary received an update before it finished hydrating. This caused the boundary to switch to client rendering. The usual way to fix this is to wrap the original update in startTransition." + ) + ); + } + if (shim$1()) + return ( + (workInProgress.flags |= 128), + (workInProgress.child = current.child), + retryDehydratedSuspenseBoundary.bind(null, current), + shim$1(), + null + ); + current = mountSuspensePrimaryChildren(workInProgress, nextProps.children); + current.flags |= 4096; + return current; } function scheduleSuspenseWorkOnFiber(fiber, renderLanes, propagationRoot) { fiber.lanes |= renderLanes; @@ -5635,158 +5256,753 @@ function updateSuspenseListComponent(current, workInProgress, renderLanes) { current.sibling.return = current.return; current = current.sibling; } - nextProps &= 1; + nextProps &= 1; + } + push(suspenseStackCursor, nextProps); + if (0 === (workInProgress.mode & 1)) workInProgress.memoizedState = null; + else + switch (revealOrder) { + case "forwards": + renderLanes = workInProgress.child; + for (revealOrder = null; null !== renderLanes; ) + (current = renderLanes.alternate), + null !== current && + null === findFirstSuspended(current) && + (revealOrder = renderLanes), + (renderLanes = renderLanes.sibling); + renderLanes = revealOrder; + null === renderLanes + ? ((revealOrder = workInProgress.child), + (workInProgress.child = null)) + : ((revealOrder = renderLanes.sibling), (renderLanes.sibling = null)); + initSuspenseListRenderState( + workInProgress, + !1, + revealOrder, + renderLanes, + tailMode + ); + break; + case "backwards": + renderLanes = null; + revealOrder = workInProgress.child; + for (workInProgress.child = null; null !== revealOrder; ) { + current = revealOrder.alternate; + if (null !== current && null === findFirstSuspended(current)) { + workInProgress.child = revealOrder; + break; + } + current = revealOrder.sibling; + revealOrder.sibling = renderLanes; + renderLanes = revealOrder; + revealOrder = current; + } + initSuspenseListRenderState( + workInProgress, + !0, + renderLanes, + null, + tailMode + ); + break; + case "together": + initSuspenseListRenderState(workInProgress, !1, null, null, void 0); + break; + default: + workInProgress.memoizedState = null; + } + return workInProgress.child; +} +function resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress) { + 0 === (workInProgress.mode & 1) && + null !== current && + ((current.alternate = null), + (workInProgress.alternate = null), + (workInProgress.flags |= 2)); +} +function bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) { + null !== current && (workInProgress.dependencies = current.dependencies); + profilerStartTime = -1; + workInProgressRootSkippedLanes |= workInProgress.lanes; + if (0 === (renderLanes & workInProgress.childLanes)) return null; + if (null !== current && workInProgress.child !== current.child) + throw Error("Resuming work not yet implemented."); + if (null !== workInProgress.child) { + current = workInProgress.child; + renderLanes = createWorkInProgress(current, current.pendingProps); + workInProgress.child = renderLanes; + for (renderLanes.return = workInProgress; null !== current.sibling; ) + (current = current.sibling), + (renderLanes = renderLanes.sibling = createWorkInProgress( + current, + current.pendingProps + )), + (renderLanes.return = workInProgress); + renderLanes.sibling = null; + } + return workInProgress.child; +} +function attemptEarlyBailoutIfNoScheduledUpdate( + current, + workInProgress, + renderLanes +) { + switch (workInProgress.tag) { + case 3: + pushHostRootContext(workInProgress); + break; + case 5: + pushHostContext(workInProgress); + break; + case 1: + isContextProvider(workInProgress.type) && + pushContextProvider(workInProgress); + break; + case 4: + pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); + break; + case 10: + var context = workInProgress.type._context, + nextValue = workInProgress.memoizedProps.value; + push(valueCursor, context._currentValue2); + context._currentValue2 = nextValue; + break; + case 12: + 0 !== (renderLanes & workInProgress.childLanes) && + (workInProgress.flags |= 4); + context = workInProgress.stateNode; + context.effectDuration = 0; + context.passiveEffectDuration = 0; + break; + case 13: + context = workInProgress.memoizedState; + if (null !== context) { + if (null !== context.dehydrated) + return ( + push(suspenseStackCursor, suspenseStackCursor.current & 1), + (workInProgress.flags |= 128), + null + ); + if (0 !== (renderLanes & workInProgress.child.childLanes)) + return updateSuspenseComponent(current, workInProgress, renderLanes); + push(suspenseStackCursor, suspenseStackCursor.current & 1); + current = bailoutOnAlreadyFinishedWork( + current, + workInProgress, + renderLanes + ); + return null !== current ? current.sibling : null; + } + push(suspenseStackCursor, suspenseStackCursor.current & 1); + break; + case 19: + context = 0 !== (renderLanes & workInProgress.childLanes); + if (0 !== (current.flags & 128)) { + if (context) + return updateSuspenseListComponent( + current, + workInProgress, + renderLanes + ); + workInProgress.flags |= 128; + } + nextValue = workInProgress.memoizedState; + null !== nextValue && + ((nextValue.rendering = null), + (nextValue.tail = null), + (nextValue.lastEffect = null)); + push(suspenseStackCursor, suspenseStackCursor.current); + if (context) break; + else return null; + case 22: + case 23: + return ( + (workInProgress.lanes = 0), + updateOffscreenComponent(current, workInProgress, renderLanes) + ); + } + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); +} +function hadNoMutationsEffects(current, completedWork) { + if (null !== current && current.child === completedWork.child) return !0; + if (0 !== (completedWork.flags & 16)) return !1; + for (current = completedWork.child; null !== current; ) { + if (0 !== (current.flags & 12854) || 0 !== (current.subtreeFlags & 12854)) + return !1; + current = current.sibling; + } + return !0; +} +var appendAllChildren, + updateHostContainer, + updateHostComponent$1, + updateHostText$1; +appendAllChildren = function( + parent, + workInProgress, + needsVisibilityToggle, + isHidden +) { + for (var node = workInProgress.child; null !== node; ) { + if (5 === node.tag) { + var instance = node.stateNode; + needsVisibilityToggle && + isHidden && + (instance = cloneHiddenInstance(instance)); + appendChildNode(parent.node, instance.node); + } else if (6 === node.tag) { + instance = node.stateNode; + if (needsVisibilityToggle && isHidden) + throw Error("Not yet implemented."); + appendChildNode(parent.node, instance.node); + } else if (4 !== node.tag) + if (22 === node.tag && null !== node.memoizedState) + (instance = node.child), + null !== instance && (instance.return = node), + appendAllChildren(parent, node, !0, !0); + else if (null !== node.child) { + node.child.return = node; + node = node.child; + continue; + } + if (node === workInProgress) break; + for (; null === node.sibling; ) { + if (null === node.return || node.return === workInProgress) return; + node = node.return; + } + node.sibling.return = node.return; + node = node.sibling; } - push(suspenseStackCursor, nextProps); - if (0 === (workInProgress.mode & 1)) workInProgress.memoizedState = null; - else - switch (revealOrder) { - case "forwards": - renderLanes = workInProgress.child; - for (revealOrder = null; null !== renderLanes; ) - (current = renderLanes.alternate), - null !== current && - null === findFirstSuspended(current) && - (revealOrder = renderLanes), - (renderLanes = renderLanes.sibling); - renderLanes = revealOrder; - null === renderLanes - ? ((revealOrder = workInProgress.child), - (workInProgress.child = null)) - : ((revealOrder = renderLanes.sibling), (renderLanes.sibling = null)); - initSuspenseListRenderState( - workInProgress, - !1, - revealOrder, - renderLanes, - tailMode - ); - break; - case "backwards": - renderLanes = null; - revealOrder = workInProgress.child; - for (workInProgress.child = null; null !== revealOrder; ) { - current = revealOrder.alternate; - if (null !== current && null === findFirstSuspended(current)) { - workInProgress.child = revealOrder; - break; - } - current = revealOrder.sibling; - revealOrder.sibling = renderLanes; - renderLanes = revealOrder; - revealOrder = current; - } - initSuspenseListRenderState( - workInProgress, - !0, - renderLanes, - null, - tailMode - ); - break; - case "together": - initSuspenseListRenderState(workInProgress, !1, null, null, void 0); - break; - default: - workInProgress.memoizedState = null; +}; +function appendAllChildrenToContainer( + containerChildSet, + workInProgress, + needsVisibilityToggle, + isHidden +) { + for (var node = workInProgress.child; null !== node; ) { + if (5 === node.tag) { + var instance = node.stateNode; + needsVisibilityToggle && + isHidden && + (instance = cloneHiddenInstance(instance)); + appendChildNodeToSet(containerChildSet, instance.node); + } else if (6 === node.tag) { + instance = node.stateNode; + if (needsVisibilityToggle && isHidden) + throw Error("Not yet implemented."); + appendChildNodeToSet(containerChildSet, instance.node); + } else if (4 !== node.tag) + if (22 === node.tag && null !== node.memoizedState) + (instance = node.child), + null !== instance && (instance.return = node), + appendAllChildrenToContainer(containerChildSet, node, !0, !0); + else if (null !== node.child) { + node.child.return = node; + node = node.child; + continue; + } + if (node === workInProgress) break; + for (; null === node.sibling; ) { + if (null === node.return || node.return === workInProgress) return; + node = node.return; } - return workInProgress.child; + node.sibling.return = node.return; + node = node.sibling; + } } -function bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) { - null !== current && (workInProgress.dependencies = current.dependencies); - profilerStartTime = -1; - workInProgressRootSkippedLanes |= workInProgress.lanes; - if (0 === (renderLanes & workInProgress.childLanes)) return null; - if (null !== current && workInProgress.child !== current.child) - throw Error("Resuming work not yet implemented."); - if (null !== workInProgress.child) { - current = workInProgress.child; - renderLanes = createWorkInProgress(current, current.pendingProps); - workInProgress.child = renderLanes; - for (renderLanes.return = workInProgress; null !== current.sibling; ) - (current = current.sibling), - (renderLanes = renderLanes.sibling = createWorkInProgress( - current, - current.pendingProps - )), - (renderLanes.return = workInProgress); - renderLanes.sibling = null; +updateHostContainer = function(current, workInProgress) { + var portalOrRoot = workInProgress.stateNode; + if (!hadNoMutationsEffects(current, workInProgress)) { + current = portalOrRoot.containerInfo; + var newChildSet = createChildNodeSet(current); + appendAllChildrenToContainer(newChildSet, workInProgress, !1, !1); + portalOrRoot.pendingChildren = newChildSet; + workInProgress.flags |= 4; + completeRoot(current, newChildSet); + } +}; +updateHostComponent$1 = function(current, workInProgress, type, newProps) { + type = current.stateNode; + var oldProps = current.memoizedProps; + if ( + (current = hadNoMutationsEffects(current, workInProgress)) && + oldProps === newProps + ) + workInProgress.stateNode = type; + else { + var recyclableInstance = workInProgress.stateNode; + requiredContext(contextStackCursor$1.current); + var updatePayload = null; + oldProps !== newProps && + ((oldProps = diffProperties( + null, + oldProps, + newProps, + recyclableInstance.canonical.viewConfig.validAttributes + )), + (recyclableInstance.canonical.currentProps = newProps), + (updatePayload = oldProps)); + current && null === updatePayload + ? (workInProgress.stateNode = type) + : ((newProps = updatePayload), + (oldProps = type.node), + (type = { + node: current + ? null !== newProps + ? cloneNodeWithNewProps(oldProps, newProps) + : cloneNode(oldProps) + : null !== newProps + ? cloneNodeWithNewChildrenAndProps(oldProps, newProps) + : cloneNodeWithNewChildren(oldProps), + canonical: type.canonical + }), + (workInProgress.stateNode = type), + current + ? (workInProgress.flags |= 4) + : appendAllChildren(type, workInProgress, !1, !1)); + } +}; +updateHostText$1 = function(current, workInProgress, oldText, newText) { + oldText !== newText + ? ((current = requiredContext(rootInstanceStackCursor.current)), + (oldText = requiredContext(contextStackCursor$1.current)), + (workInProgress.stateNode = createTextInstance( + newText, + current, + oldText, + workInProgress + )), + (workInProgress.flags |= 4)) + : (workInProgress.stateNode = current.stateNode); +}; +function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { + switch (renderState.tailMode) { + case "hidden": + hasRenderedATailFallback = renderState.tail; + for (var lastTailNode = null; null !== hasRenderedATailFallback; ) + null !== hasRenderedATailFallback.alternate && + (lastTailNode = hasRenderedATailFallback), + (hasRenderedATailFallback = hasRenderedATailFallback.sibling); + null === lastTailNode + ? (renderState.tail = null) + : (lastTailNode.sibling = null); + break; + case "collapsed": + lastTailNode = renderState.tail; + for (var lastTailNode$63 = null; null !== lastTailNode; ) + null !== lastTailNode.alternate && (lastTailNode$63 = lastTailNode), + (lastTailNode = lastTailNode.sibling); + null === lastTailNode$63 + ? hasRenderedATailFallback || null === renderState.tail + ? (renderState.tail = null) + : (renderState.tail.sibling = null) + : (lastTailNode$63.sibling = null); } - return workInProgress.child; } -function attemptEarlyBailoutIfNoScheduledUpdate( - current, - workInProgress, - renderLanes -) { +function bubbleProperties(completedWork) { + var didBailout = + null !== completedWork.alternate && + completedWork.alternate.child === completedWork.child, + newChildLanes = 0, + subtreeFlags = 0; + if (didBailout) + if (0 !== (completedWork.mode & 2)) { + for ( + var treeBaseDuration$65 = completedWork.selfBaseDuration, + child$66 = completedWork.child; + null !== child$66; + + ) + (newChildLanes |= child$66.lanes | child$66.childLanes), + (subtreeFlags |= child$66.subtreeFlags & 14680064), + (subtreeFlags |= child$66.flags & 14680064), + (treeBaseDuration$65 += child$66.treeBaseDuration), + (child$66 = child$66.sibling); + completedWork.treeBaseDuration = treeBaseDuration$65; + } else + for ( + treeBaseDuration$65 = completedWork.child; + null !== treeBaseDuration$65; + + ) + (newChildLanes |= + treeBaseDuration$65.lanes | treeBaseDuration$65.childLanes), + (subtreeFlags |= treeBaseDuration$65.subtreeFlags & 14680064), + (subtreeFlags |= treeBaseDuration$65.flags & 14680064), + (treeBaseDuration$65.return = completedWork), + (treeBaseDuration$65 = treeBaseDuration$65.sibling); + else if (0 !== (completedWork.mode & 2)) { + treeBaseDuration$65 = completedWork.actualDuration; + child$66 = completedWork.selfBaseDuration; + for (var child = completedWork.child; null !== child; ) + (newChildLanes |= child.lanes | child.childLanes), + (subtreeFlags |= child.subtreeFlags), + (subtreeFlags |= child.flags), + (treeBaseDuration$65 += child.actualDuration), + (child$66 += child.treeBaseDuration), + (child = child.sibling); + completedWork.actualDuration = treeBaseDuration$65; + completedWork.treeBaseDuration = child$66; + } else + for ( + treeBaseDuration$65 = completedWork.child; + null !== treeBaseDuration$65; + + ) + (newChildLanes |= + treeBaseDuration$65.lanes | treeBaseDuration$65.childLanes), + (subtreeFlags |= treeBaseDuration$65.subtreeFlags), + (subtreeFlags |= treeBaseDuration$65.flags), + (treeBaseDuration$65.return = completedWork), + (treeBaseDuration$65 = treeBaseDuration$65.sibling); + completedWork.subtreeFlags |= subtreeFlags; + completedWork.childLanes = newChildLanes; + return didBailout; +} +function completeWork(current, workInProgress, renderLanes) { + var newProps = workInProgress.pendingProps; + popTreeContext(workInProgress); switch (workInProgress.tag) { + case 2: + case 16: + case 15: + case 0: + case 11: + case 7: + case 8: + case 12: + case 9: + case 14: + return bubbleProperties(workInProgress), null; + case 1: + return ( + isContextProvider(workInProgress.type) && popContext(), + bubbleProperties(workInProgress), + null + ); case 3: - pushHostRootContext(workInProgress); - break; + return ( + (renderLanes = workInProgress.stateNode), + popHostContainer(), + pop(didPerformWorkStackCursor), + pop(contextStackCursor), + resetWorkInProgressVersions(), + renderLanes.pendingContext && + ((renderLanes.context = renderLanes.pendingContext), + (renderLanes.pendingContext = null)), + (null !== current && null !== current.child) || + null === current || + (current.memoizedState.isDehydrated && + 0 === (workInProgress.flags & 256)) || + ((workInProgress.flags |= 1024), + null !== hydrationErrors && + (queueRecoverableErrors(hydrationErrors), + (hydrationErrors = null))), + updateHostContainer(current, workInProgress), + bubbleProperties(workInProgress), + null + ); case 5: - pushHostContext(workInProgress); - break; - case 1: - isContextProvider(workInProgress.type) && - pushContextProvider(workInProgress); - break; - case 4: - pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); - break; - case 10: - var context = workInProgress.type._context, - nextValue = workInProgress.memoizedProps.value; - push(valueCursor, context._currentValue2); - context._currentValue2 = nextValue; - break; - case 12: - 0 !== (renderLanes & workInProgress.childLanes) && - (workInProgress.flags |= 4); - context = workInProgress.stateNode; - context.effectDuration = 0; - context.passiveEffectDuration = 0; - break; - case 13: - if (null !== workInProgress.memoizedState) { - if (0 !== (renderLanes & workInProgress.child.childLanes)) - return updateSuspenseComponent(current, workInProgress, renderLanes); - push(suspenseStackCursor, suspenseStackCursor.current & 1); - current = bailoutOnAlreadyFinishedWork( + popHostContext(workInProgress); + renderLanes = requiredContext(rootInstanceStackCursor.current); + var type = workInProgress.type; + if (null !== current && null != workInProgress.stateNode) + updateHostComponent$1( current, workInProgress, + type, + newProps, renderLanes + ), + current.ref !== workInProgress.ref && (workInProgress.flags |= 512); + else { + if (!newProps) { + if (null === workInProgress.stateNode) + throw Error( + "We must have new props for new mounts. This error is likely caused by a bug in React. Please file an issue." + ); + bubbleProperties(workInProgress); + return null; + } + requiredContext(contextStackCursor$1.current); + current = nextReactTag; + nextReactTag += 2; + type = getViewConfigForType(type); + var updatePayload = diffProperties( + null, + emptyObject, + newProps, + type.validAttributes ); - return null !== current ? current.sibling : null; + renderLanes = createNode( + current, + type.uiViewClassName, + renderLanes, + updatePayload, + workInProgress + ); + current = new ReactFabricHostComponent( + current, + type, + newProps, + workInProgress + ); + current = { node: renderLanes, canonical: current }; + appendAllChildren(current, workInProgress, !1, !1); + workInProgress.stateNode = current; + null !== workInProgress.ref && (workInProgress.flags |= 512); } - push(suspenseStackCursor, suspenseStackCursor.current & 1); - break; - case 19: - context = 0 !== (renderLanes & workInProgress.childLanes); - if (0 !== (current.flags & 128)) { - if (context) - return updateSuspenseListComponent( - current, - workInProgress, - renderLanes + bubbleProperties(workInProgress); + return null; + case 6: + if (current && null != workInProgress.stateNode) + updateHostText$1( + current, + workInProgress, + current.memoizedProps, + newProps + ); + else { + if ("string" !== typeof newProps && null === workInProgress.stateNode) + throw Error( + "We must have new props for new mounts. This error is likely caused by a bug in React. Please file an issue." ); - workInProgress.flags |= 128; + current = requiredContext(rootInstanceStackCursor.current); + renderLanes = requiredContext(contextStackCursor$1.current); + workInProgress.stateNode = createTextInstance( + newProps, + current, + renderLanes, + workInProgress + ); + } + bubbleProperties(workInProgress); + return null; + case 13: + pop(suspenseStackCursor); + newProps = workInProgress.memoizedState; + if ( + null === current || + (null !== current.memoizedState && + null !== current.memoizedState.dehydrated) + ) { + if (null !== newProps && null !== newProps.dehydrated) { + if (null === current) { + throw Error( + "A dehydrated suspense component was completed without a hydrated node. This is probably a bug in React." + ); + throw Error( + "Expected prepareToHydrateHostSuspenseInstance() to never be called. This error is likely caused by a bug in React. Please file an issue." + ); + } + 0 === (workInProgress.flags & 128) && + (workInProgress.memoizedState = null); + workInProgress.flags |= 4; + bubbleProperties(workInProgress); + 0 !== (workInProgress.mode & 2) && + null !== newProps && + ((type = workInProgress.child), + null !== type && + (workInProgress.treeBaseDuration -= type.treeBaseDuration)); + type = !1; + } else + null !== hydrationErrors && + (queueRecoverableErrors(hydrationErrors), (hydrationErrors = null)), + (type = !0); + if (!type) return workInProgress.flags & 65536 ? workInProgress : null; + } + if (0 !== (workInProgress.flags & 128)) + return ( + (workInProgress.lanes = renderLanes), + 0 !== (workInProgress.mode & 2) && + transferActualDuration(workInProgress), + workInProgress + ); + renderLanes = null !== newProps; + renderLanes !== (null !== current && null !== current.memoizedState) && + renderLanes && + ((workInProgress.child.flags |= 8192), + 0 !== (workInProgress.mode & 1) && + (null === current || 0 !== (suspenseStackCursor.current & 1) + ? 0 === workInProgressRootExitStatus && + (workInProgressRootExitStatus = 3) + : renderDidSuspendDelayIfPossible())); + null !== workInProgress.updateQueue && (workInProgress.flags |= 4); + bubbleProperties(workInProgress); + 0 !== (workInProgress.mode & 2) && + renderLanes && + ((current = workInProgress.child), + null !== current && + (workInProgress.treeBaseDuration -= current.treeBaseDuration)); + return null; + case 4: + return ( + popHostContainer(), + updateHostContainer(current, workInProgress), + bubbleProperties(workInProgress), + null + ); + case 10: + return ( + popProvider(workInProgress.type._context), + bubbleProperties(workInProgress), + null + ); + case 17: + return ( + isContextProvider(workInProgress.type) && popContext(), + bubbleProperties(workInProgress), + null + ); + case 19: + pop(suspenseStackCursor); + type = workInProgress.memoizedState; + if (null === type) return bubbleProperties(workInProgress), null; + newProps = 0 !== (workInProgress.flags & 128); + updatePayload = type.rendering; + if (null === updatePayload) + if (newProps) cutOffTailIfNeeded(type, !1); + else { + if ( + 0 !== workInProgressRootExitStatus || + (null !== current && 0 !== (current.flags & 128)) + ) + for (current = workInProgress.child; null !== current; ) { + updatePayload = findFirstSuspended(current); + if (null !== updatePayload) { + workInProgress.flags |= 128; + cutOffTailIfNeeded(type, !1); + current = updatePayload.updateQueue; + null !== current && + ((workInProgress.updateQueue = current), + (workInProgress.flags |= 4)); + workInProgress.subtreeFlags = 0; + current = renderLanes; + for (renderLanes = workInProgress.child; null !== renderLanes; ) + (newProps = renderLanes), + (updatePayload = current), + (newProps.flags &= 14680066), + (type = newProps.alternate), + null === type + ? ((newProps.childLanes = 0), + (newProps.lanes = updatePayload), + (newProps.child = null), + (newProps.subtreeFlags = 0), + (newProps.memoizedProps = null), + (newProps.memoizedState = null), + (newProps.updateQueue = null), + (newProps.dependencies = null), + (newProps.stateNode = null), + (newProps.selfBaseDuration = 0), + (newProps.treeBaseDuration = 0)) + : ((newProps.childLanes = type.childLanes), + (newProps.lanes = type.lanes), + (newProps.child = type.child), + (newProps.subtreeFlags = 0), + (newProps.deletions = null), + (newProps.memoizedProps = type.memoizedProps), + (newProps.memoizedState = type.memoizedState), + (newProps.updateQueue = type.updateQueue), + (newProps.type = type.type), + (updatePayload = type.dependencies), + (newProps.dependencies = + null === updatePayload + ? null + : { + lanes: updatePayload.lanes, + firstContext: updatePayload.firstContext + }), + (newProps.selfBaseDuration = type.selfBaseDuration), + (newProps.treeBaseDuration = type.treeBaseDuration)), + (renderLanes = renderLanes.sibling); + push( + suspenseStackCursor, + (suspenseStackCursor.current & 1) | 2 + ); + return workInProgress.child; + } + current = current.sibling; + } + null !== type.tail && + now() > workInProgressRootRenderTargetTime && + ((workInProgress.flags |= 128), + (newProps = !0), + cutOffTailIfNeeded(type, !1), + (workInProgress.lanes = 4194304)); + } + else { + if (!newProps) + if ( + ((current = findFirstSuspended(updatePayload)), null !== current) + ) { + if ( + ((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 && + !updatePayload.alternate) + ) + return bubbleProperties(workInProgress), null; + } else + 2 * now() - type.renderingStartTime > + workInProgressRootRenderTargetTime && + 1073741824 !== renderLanes && + ((workInProgress.flags |= 128), + (newProps = !0), + cutOffTailIfNeeded(type, !1), + (workInProgress.lanes = 4194304)); + type.isBackwards + ? ((updatePayload.sibling = workInProgress.child), + (workInProgress.child = updatePayload)) + : ((current = type.last), + null !== current + ? (current.sibling = updatePayload) + : (workInProgress.child = updatePayload), + (type.last = updatePayload)); } - nextValue = workInProgress.memoizedState; - null !== nextValue && - ((nextValue.rendering = null), - (nextValue.tail = null), - (nextValue.lastEffect = null)); - push(suspenseStackCursor, suspenseStackCursor.current); - if (context) break; - else return null; + if (null !== type.tail) + return ( + (workInProgress = type.tail), + (type.rendering = workInProgress), + (type.tail = workInProgress.sibling), + (type.renderingStartTime = now()), + (workInProgress.sibling = null), + (current = suspenseStackCursor.current), + push(suspenseStackCursor, newProps ? (current & 1) | 2 : current & 1), + workInProgress + ); + bubbleProperties(workInProgress); + return null; case 22: case 23: return ( - (workInProgress.lanes = 0), - updateOffscreenComponent(current, workInProgress, renderLanes) + popRenderLanes(), + (renderLanes = null !== workInProgress.memoizedState), + null !== current && + (null !== current.memoizedState) !== renderLanes && + (workInProgress.flags |= 8192), + renderLanes && 0 !== (workInProgress.mode & 1) + ? 0 !== (subtreeRenderLanes & 1073741824) && + bubbleProperties(workInProgress) + : bubbleProperties(workInProgress), + null ); + case 24: + return null; + case 25: + return null; } - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); + throw Error( + "Unknown unit of work tag (" + + workInProgress.tag + + "). This error is likely caused by a bug in React. Please file an issue." + ); } function unwindWork(current, workInProgress) { popTreeContext(workInProgress); @@ -5816,16 +6032,23 @@ function unwindWork(current, workInProgress) { case 5: return popHostContext(workInProgress), null; case 13: - return ( - pop(suspenseStackCursor), - (current = workInProgress.flags), - current & 65536 - ? ((workInProgress.flags = (current & -65537) | 128), - 0 !== (workInProgress.mode & 2) && - transferActualDuration(workInProgress), - workInProgress) - : null - ); + pop(suspenseStackCursor); + current = workInProgress.memoizedState; + if ( + null !== current && + null !== current.dehydrated && + null === workInProgress.alternate + ) + throw Error( + "Threw in newly mounted dehydrated component. This is likely a bug in React. Please file an issue." + ); + current = workInProgress.flags; + return current & 65536 + ? ((workInProgress.flags = (current & -65537) | 128), + 0 !== (workInProgress.mode & 2) && + transferActualDuration(workInProgress), + workInProgress) + : null; case 19: return pop(suspenseStackCursor), null; case 4: @@ -5957,8 +6180,8 @@ function commitHookEffectListMount(flags, finishedWork) { var effect = (finishedWork = finishedWork.next); do { if ((effect.tag & flags) === flags) { - var create$83 = effect.create; - effect.destroy = create$83(); + var create$81 = effect.create; + effect.destroy = create$81(); } effect = effect.next; } while (effect !== finishedWork); @@ -5980,48 +6203,129 @@ function detachFiberAfterEffects(fiber) { fiber.stateNode = null; fiber.updateQueue = null; } -function commitWork(current, finishedWork) { - switch (finishedWork.tag) { +function recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + parent +) { + for (parent = parent.child; null !== parent; ) + commitDeletionEffectsOnFiber(finishedRoot, nearestMountedAncestor, parent), + (parent = parent.sibling); +} +function commitDeletionEffectsOnFiber( + finishedRoot, + nearestMountedAncestor, + deletedFiber +) { + if (injectedHook && "function" === typeof injectedHook.onCommitFiberUnmount) + try { + injectedHook.onCommitFiberUnmount(rendererID, deletedFiber); + } catch (err) {} + switch (deletedFiber.tag) { + case 5: + safelyDetachRef(deletedFiber, nearestMountedAncestor); + case 6: + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + break; + case 18: + break; + case 4: + createChildNodeSet(deletedFiber.stateNode.containerInfo); + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + break; case 0: case 11: case 14: case 15: - commitHookEffectListUnmount(3, finishedWork, finishedWork.return); - commitHookEffectListMount(3, finishedWork); - if (finishedWork.mode & 2) + var updateQueue = deletedFiber.updateQueue; + if ( + null !== updateQueue && + ((updateQueue = updateQueue.lastEffect), null !== updateQueue) + ) { + var effect = (updateQueue = updateQueue.next); + do { + var _effect = effect, + destroy = _effect.destroy; + _effect = _effect.tag; + void 0 !== destroy && + (0 !== (_effect & 2) + ? safelyCallDestroy(deletedFiber, nearestMountedAncestor, destroy) + : 0 !== (_effect & 4) && + (deletedFiber.mode & 2 + ? (startLayoutEffectTimer(), + safelyCallDestroy( + deletedFiber, + nearestMountedAncestor, + destroy + ), + recordLayoutEffectDuration(deletedFiber)) + : safelyCallDestroy( + deletedFiber, + nearestMountedAncestor, + destroy + ))); + effect = effect.next; + } while (effect !== updateQueue); + } + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + break; + case 1: + safelyDetachRef(deletedFiber, nearestMountedAncestor); + updateQueue = deletedFiber.stateNode; + if ("function" === typeof updateQueue.componentWillUnmount) try { - startLayoutEffectTimer(), - commitHookEffectListUnmount(5, finishedWork, finishedWork.return); - } finally { - recordLayoutEffectDuration(finishedWork); + if ( + ((updateQueue.props = deletedFiber.memoizedProps), + (updateQueue.state = deletedFiber.memoizedState), + deletedFiber.mode & 2) + ) + try { + startLayoutEffectTimer(), updateQueue.componentWillUnmount(); + } finally { + recordLayoutEffectDuration(deletedFiber); + } + else updateQueue.componentWillUnmount(); + } catch (error) { + captureCommitPhaseError(deletedFiber, nearestMountedAncestor, error); } - else commitHookEffectListUnmount(5, finishedWork, finishedWork.return); - return; - case 12: - return; - case 13: - attachSuspenseRetryListeners(finishedWork); - return; - case 19: - attachSuspenseRetryListeners(finishedWork); - return; + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + break; + case 21: + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + break; case 22: - case 23: - return; - } - a: { - switch (finishedWork.tag) { - case 1: - case 5: - case 6: - break a; - case 3: - case 4: - break a; - } - throw 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." - ); + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + break; + default: + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); } } function attachSuspenseRetryListeners(finishedWork) { @@ -6047,172 +6351,128 @@ function attachSuspenseRetryListeners(finishedWork) { }); } } -function commitMutationEffects(root, firstChild, committedLanes) { +function commitMutationEffects(root, finishedWork, committedLanes) { inProgressLanes = committedLanes; inProgressRoot = root; - for (nextEffect = firstChild; null !== nextEffect; ) { - root = nextEffect; - firstChild = root.deletions; - if (null !== firstChild) - for ( - committedLanes = 0; - committedLanes < firstChild.length; - committedLanes++ - ) { - var childToDelete = firstChild[committedLanes]; + commitMutationEffectsOnFiber(finishedWork, root); + inProgressRoot = inProgressLanes = null; +} +function recursivelyTraverseMutationEffects(root, parentFiber) { + var deletions = parentFiber.deletions; + if (null !== deletions) + for (var i = 0; i < deletions.length; i++) { + var childToDelete = deletions[i]; + try { + commitDeletionEffectsOnFiber(root, parentFiber, childToDelete); + var alternate = childToDelete.alternate; + null !== alternate && (alternate.return = null); + childToDelete.return = null; + } catch (error) { + captureCommitPhaseError(childToDelete, parentFiber, error); + } + } + if (parentFiber.subtreeFlags & 12854) + for (parentFiber = parentFiber.child; null !== parentFiber; ) + commitMutationEffectsOnFiber(parentFiber, root), + (parentFiber = parentFiber.sibling); +} +function commitMutationEffectsOnFiber(finishedWork, root) { + var current = finishedWork.alternate, + flags = finishedWork.flags; + switch (finishedWork.tag) { + case 0: + case 11: + case 14: + case 15: + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + if (flags & 4) { try { - a: for (var node = childToDelete; ; ) { - var current = node; - if ( - injectedHook && - "function" === typeof injectedHook.onCommitFiberUnmount - ) - try { - injectedHook.onCommitFiberUnmount(rendererID, current); - } catch (err) {} - switch (current.tag) { - case 0: - case 11: - case 14: - case 15: - var updateQueue = current.updateQueue; - if (null !== updateQueue) { - var lastEffect = updateQueue.lastEffect; - if (null !== lastEffect) { - var firstEffect = lastEffect.next, - effect = firstEffect; - do { - var _effect = effect, - destroy = _effect.destroy, - tag = _effect.tag; - void 0 !== destroy && - (0 !== (tag & 2) - ? safelyCallDestroy(current, root, destroy) - : 0 !== (tag & 4) && - (current.mode & 2 - ? (startLayoutEffectTimer(), - safelyCallDestroy(current, root, destroy), - recordLayoutEffectDuration(current)) - : safelyCallDestroy(current, root, destroy))); - effect = effect.next; - } while (effect !== firstEffect); - } - } - break; - case 1: - safelyDetachRef(current, root); - var instance = current.stateNode; - if ("function" === typeof instance.componentWillUnmount) - try { - if ( - ((effect = current), - (_effect = instance), - (_effect.props = effect.memoizedProps), - (_effect.state = effect.memoizedState), - effect.mode & 2) - ) - try { - startLayoutEffectTimer(), - _effect.componentWillUnmount(); - } finally { - recordLayoutEffectDuration(effect); - } - else _effect.componentWillUnmount(); - } catch (error) { - captureCommitPhaseError(current, root, error); - } - break; - case 5: - safelyDetachRef(current, root); - break; - case 4: - createChildNodeSet(current.stateNode.containerInfo); - } - if (null !== node.child) - (node.child.return = node), (node = node.child); - else { - if (node === childToDelete) break; - for (; null === node.sibling; ) { - if (null === node.return || node.return === childToDelete) - break a; - node = node.return; - } - node.sibling.return = node.return; - node = node.sibling; - } - } - var alternate = childToDelete.alternate; - null !== alternate && (alternate.return = null); - childToDelete.return = null; + commitHookEffectListUnmount(3, finishedWork, finishedWork.return), + commitHookEffectListMount(3, finishedWork); } catch (error) { - captureCommitPhaseError(childToDelete, root, error); + captureCommitPhaseError(finishedWork, finishedWork.return, error); } - } - firstChild = root.child; - if (0 !== (root.subtreeFlags & 12854) && null !== firstChild) - (firstChild.return = root), (nextEffect = firstChild); - else - for (; null !== nextEffect; ) { - root = nextEffect; - try { - var flags = root.flags; - if (flags & 512) { - var current$jscomp$0 = root.alternate; - if (null !== current$jscomp$0) { - firstChild = current$jscomp$0; - var currentRef = firstChild.ref; - if (null !== currentRef) - if ("function" === typeof currentRef) - if (firstChild.mode & 2) - try { - startLayoutEffectTimer(), currentRef(null); - } finally { - recordLayoutEffectDuration(firstChild); - } - else currentRef(null); - else currentRef.current = null; - } + if (finishedWork.mode & 2) { + try { + startLayoutEffectTimer(), + commitHookEffectListUnmount(5, finishedWork, finishedWork.return); + } catch (error$87) { + captureCommitPhaseError( + finishedWork, + finishedWork.return, + error$87 + ); } - if (flags & 8192) - switch (root.tag) { - case 13: - if (null !== root.memoizedState) { - var current$89 = root.alternate; - if (null === current$89 || null === current$89.memoizedState) - globalMostRecentFallbackTime = now(); - } - } - switch (flags & 4102) { - case 2: - root.flags &= -3; - break; - case 6: - root.flags &= -3; - commitWork(root.alternate, root); - break; - case 4096: - root.flags &= -4097; - break; - case 4100: - root.flags &= -4097; - commitWork(root.alternate, root); - break; - case 4: - commitWork(root.alternate, root); + recordLayoutEffectDuration(finishedWork); + } else + try { + commitHookEffectListUnmount(5, finishedWork, finishedWork.return); + } catch (error$88) { + captureCommitPhaseError( + finishedWork, + finishedWork.return, + error$88 + ); } - } catch (error) { - captureCommitPhaseError(root, root.return, error); - } - firstChild = root.sibling; - if (null !== firstChild) { - firstChild.return = root.return; - nextEffect = firstChild; - break; - } - nextEffect = root.return; } + break; + case 1: + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + flags & 512 && + null !== current && + safelyDetachRef(current, current.return); + break; + case 5: + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + flags & 512 && + null !== current && + safelyDetachRef(current, current.return); + break; + case 6: + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + break; + case 3: + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + break; + case 4: + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + break; + case 13: + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + root = finishedWork.child; + root.flags & 8192 && + null !== root.memoizedState && + (null === root.alternate || null === root.alternate.memoizedState) && + (globalMostRecentFallbackTime = now()); + flags & 4 && attachSuspenseRetryListeners(finishedWork); + break; + case 22: + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + break; + case 19: + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + flags & 4 && attachSuspenseRetryListeners(finishedWork); + break; + case 21: + break; + default: + recursivelyTraverseMutationEffects(root, finishedWork), + commitReconciliationEffects(finishedWork); } - inProgressRoot = inProgressLanes = null; +} +function commitReconciliationEffects(finishedWork) { + var flags = finishedWork.flags; + flags & 2 && (finishedWork.flags &= -3); + flags & 4096 && (finishedWork.flags &= -4097); } function commitLayoutEffects(finishedWork, root, committedLanes) { inProgressLanes = committedLanes; @@ -6288,22 +6548,22 @@ function commitLayoutEffects(finishedWork, root, committedLanes) { commitUpdateQueue(committedLanes, updateQueue, instance); break; case 3: - var updateQueue$85 = committedLanes.updateQueue; - if (null !== updateQueue$85) { - var instance$86 = null; + var updateQueue$83 = committedLanes.updateQueue; + if (null !== updateQueue$83) { + var instance$84 = null; if (null !== committedLanes.child) switch (committedLanes.child.tag) { case 5: - instance$86 = + instance$84 = committedLanes.child.stateNode.canonical; break; case 1: - instance$86 = committedLanes.child.stateNode; + instance$84 = committedLanes.child.stateNode; } commitUpdateQueue( committedLanes, - updateQueue$85, - instance$86 + updateQueue$83, + instance$84 ); } break; @@ -6322,7 +6582,7 @@ function commitLayoutEffects(finishedWork, root, committedLanes) { onCommit = _finishedWork$memoize2.onCommit, onRender = _finishedWork$memoize2.onRender, effectDuration = committedLanes.stateNode.effectDuration; - instance$86 = commitTime; + instance$84 = commitTime; current = null === current ? "mount" : "update"; currentUpdateIsNested && (current = "nested-update"); "function" === typeof onRender && @@ -6332,14 +6592,14 @@ function commitLayoutEffects(finishedWork, root, committedLanes) { committedLanes.actualDuration, committedLanes.treeBaseDuration, committedLanes.actualStartTime, - instance$86 + instance$84 ); "function" === typeof onCommit && onCommit( committedLanes.memoizedProps.id, current, effectDuration, - instance$86 + instance$84 ); enqueuePendingPassiveProfilerEffect(committedLanes); var parentFiber = committedLanes.return; @@ -6362,6 +6622,7 @@ function commitLayoutEffects(finishedWork, root, committedLanes) { case 21: case 22: case 23: + case 25: break; default: throw Error( @@ -6369,27 +6630,27 @@ function commitLayoutEffects(finishedWork, root, committedLanes) { ); } if (committedLanes.flags & 512) { - instance$86 = void 0; + instance$84 = void 0; current = committedLanes; var ref = current.ref; if (null !== ref) { var instance$jscomp$0 = current.stateNode; switch (current.tag) { case 5: - instance$86 = instance$jscomp$0.canonical; + instance$84 = instance$jscomp$0.canonical; break; default: - instance$86 = instance$jscomp$0; + instance$84 = instance$jscomp$0; } if ("function" === typeof ref) if (current.mode & 2) try { - startLayoutEffectTimer(), ref(instance$86); + startLayoutEffectTimer(), ref(instance$84); } finally { recordLayoutEffectDuration(current); } - else ref(instance$86); - else ref.current = instance$86; + else ref(instance$84); + else ref.current = instance$84; } } } catch (error) { @@ -6404,10 +6665,10 @@ function commitLayoutEffects(finishedWork, root, committedLanes) { nextEffect = null; break; } - instance$86 = committedLanes.sibling; - if (null !== instance$86) { - instance$86.return = committedLanes.return; - nextEffect = instance$86; + instance$84 = committedLanes.sibling; + if (null !== instance$84) { + instance$84.return = committedLanes.return; + nextEffect = instance$84; break; } nextEffect = committedLanes.return; @@ -6433,6 +6694,7 @@ var ceil = Math.ceil, workInProgressRootRecoverableErrors = null, globalMostRecentFallbackTime = 0, workInProgressRootRenderTargetTime = Infinity, + workInProgressTransitions = null, hasUncaughtError = !1, firstUncaughtError = null, legacyErrorBoundariesThatAlreadyFailed = null, @@ -6458,10 +6720,7 @@ function requestUpdateLane(fiber) { if (null !== ReactCurrentBatchConfig.transition) return ( 0 === currentEventTransitionLane && - ((fiber = nextTransitionLane), - (nextTransitionLane <<= 1), - 0 === (nextTransitionLane & 4194240) && (nextTransitionLane = 64), - (currentEventTransitionLane = fiber)), + (currentEventTransitionLane = claimNextTransitionLane()), currentEventTransitionLane ); fiber = currentUpdatePriority; @@ -6518,6 +6777,13 @@ function markUpdateLaneFromFiberToRoot(sourceFiber, lane) { (sourceFiber = sourceFiber.return); return 3 === alternate.tag ? alternate.stateNode : null; } +function isInterleavedUpdate(fiber) { + return ( + (null !== workInProgressRoot || null !== interleavedQueues) && + 0 !== (fiber.mode & 1) && + 0 === (executionContext & 2) + ); +} function ensureRootIsScheduled(root, currentTime) { for ( var existingCallbackNode = root.callbackNode, @@ -6621,6 +6887,7 @@ function performConcurrentWorkOnRoot(root, didTimeout) { memoizedUpdaters.clear()); movePendingFibersToMemoized(root, didTimeout); } + workInProgressTransitions = null; workInProgressRootRenderTargetTime = now() + 500; prepareFreshStack(root, didTimeout); } @@ -6679,7 +6946,11 @@ function performConcurrentWorkOnRoot(root, didTimeout) { case 1: throw Error("Root did not complete. This is a bug in React."); case 2: - commitRoot(root, workInProgressRootRecoverableErrors); + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); break; case 3: markRootSuspended$1(root, lanes); @@ -6696,12 +6967,21 @@ function performConcurrentWorkOnRoot(root, didTimeout) { break; } root.timeoutHandle = scheduleTimeout( - commitRoot.bind(null, root, workInProgressRootRecoverableErrors), + commitRoot.bind( + null, + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ), didTimeout ); break; } - commitRoot(root, workInProgressRootRecoverableErrors); + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); break; case 4: markRootSuspended$1(root, lanes); @@ -6732,15 +7012,28 @@ function performConcurrentWorkOnRoot(root, didTimeout) { : 1960 * ceil(lanes / 1960)) - lanes; if (10 < lanes) { root.timeoutHandle = scheduleTimeout( - commitRoot.bind(null, root, workInProgressRootRecoverableErrors), + commitRoot.bind( + null, + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ), lanes ); break; } - commitRoot(root, workInProgressRootRecoverableErrors); + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); break; case 5: - commitRoot(root, workInProgressRootRecoverableErrors); + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); break; default: throw Error("Unknown root exit status."); @@ -6760,15 +7053,17 @@ function recoverFromConcurrentError(root, errorRetryLanes) { 2 !== root && ((errorRetryLanes = workInProgressRootRecoverableErrors), (workInProgressRootRecoverableErrors = errorsFromFirstAttempt), - null !== errorRetryLanes && - (null === workInProgressRootRecoverableErrors - ? (workInProgressRootRecoverableErrors = errorRetryLanes) - : workInProgressRootRecoverableErrors.push.apply( - workInProgressRootRecoverableErrors, - errorRetryLanes - ))); + null !== errorRetryLanes && queueRecoverableErrors(errorRetryLanes)); return root; } +function queueRecoverableErrors(errors) { + null === workInProgressRootRecoverableErrors + ? (workInProgressRootRecoverableErrors = errors) + : workInProgressRootRecoverableErrors.push.apply( + workInProgressRootRecoverableErrors, + errors + ); +} function isRenderConsistentWithExternalStores(finishedWork) { for (var node = finishedWork; ; ) { if (node.flags & 16384) { @@ -6840,7 +7135,11 @@ function performSyncWorkOnRoot(root) { throw Error("Root did not complete. This is a bug in React."); root.finishedWork = root.current.alternate; root.finishedLanes = lanes; - commitRoot(root, workInProgressRootRecoverableErrors); + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); ensureRootIsScheduled(root, now()); return null; } @@ -7079,12 +7378,12 @@ function handleError(root$jscomp$0, thrownValue) { root.flags |= 65536; thrownValue &= -thrownValue; root.lanes |= thrownValue; - var update$33 = createClassErrorUpdate( + var update$34 = createClassErrorUpdate( root, wakeable, thrownValue ); - enqueueCapturedUpdate(root, update$33); + enqueueCapturedUpdate(root, update$34); break a; } } @@ -7131,6 +7430,7 @@ function renderRootSync(root, lanes) { memoizedUpdaters.clear()); movePendingFibersToMemoized(root, lanes); } + workInProgressTransitions = null; prepareFreshStack(root, lanes); } do @@ -7225,50 +7525,60 @@ function completeUnitOfWork(unitOfWork) { } while (null !== completedWork); 0 === workInProgressRootExitStatus && (workInProgressRootExitStatus = 5); } -function commitRoot(root, recoverableErrors) { +function commitRoot(root, recoverableErrors, transitions) { var previousUpdateLanePriority = currentUpdatePriority, prevTransition = ReactCurrentBatchConfig$2.transition; try { (ReactCurrentBatchConfig$2.transition = null), (currentUpdatePriority = 1), - commitRootImpl(root, recoverableErrors, previousUpdateLanePriority); + commitRootImpl( + root, + recoverableErrors, + transitions, + previousUpdateLanePriority + ); } finally { (ReactCurrentBatchConfig$2.transition = prevTransition), (currentUpdatePriority = previousUpdateLanePriority); } return null; } -function commitRootImpl(root, recoverableErrors, renderPriorityLevel) { +function commitRootImpl( + root, + recoverableErrors, + transitions, + renderPriorityLevel +) { do flushPassiveEffects(); while (null !== rootWithPendingPassiveEffects); if (0 !== (executionContext & 6)) throw Error("Should not already be working."); - var finishedWork = root.finishedWork, - lanes = root.finishedLanes; - if (null === finishedWork) return null; + transitions = root.finishedWork; + var lanes = root.finishedLanes; + if (null === transitions) return null; root.finishedWork = null; root.finishedLanes = 0; - if (finishedWork === root.current) + if (transitions === root.current) throw Error( "Cannot commit the same tree as before. This error is likely caused by a bug in React. Please file an issue." ); root.callbackNode = null; root.callbackPriority = 0; - var remainingLanes = finishedWork.lanes | finishedWork.childLanes; + var remainingLanes = transitions.lanes | transitions.childLanes; markRootFinished(root, remainingLanes); root === workInProgressRoot && ((workInProgress = workInProgressRoot = null), (workInProgressRootRenderLanes = 0)); - (0 === (finishedWork.subtreeFlags & 2064) && - 0 === (finishedWork.flags & 2064)) || + (0 === (transitions.subtreeFlags & 2064) && + 0 === (transitions.flags & 2064)) || rootDoesHavePassiveEffects || ((rootDoesHavePassiveEffects = !0), scheduleCallback$1(NormalPriority, function() { flushPassiveEffects(); return null; })); - remainingLanes = 0 !== (finishedWork.flags & 15990); - if (0 !== (finishedWork.subtreeFlags & 15990) || remainingLanes) { + remainingLanes = 0 !== (transitions.flags & 15990); + if (0 !== (transitions.subtreeFlags & 15990) || remainingLanes) { remainingLanes = ReactCurrentBatchConfig$2.transition; ReactCurrentBatchConfig$2.transition = null; var previousPriority = currentUpdatePriority; @@ -7276,32 +7586,32 @@ function commitRootImpl(root, recoverableErrors, renderPriorityLevel) { var prevExecutionContext = executionContext; executionContext |= 4; ReactCurrentOwner$2.current = null; - commitBeforeMutationEffects(root, finishedWork); + commitBeforeMutationEffects(root, transitions); commitTime = now$1(); - commitMutationEffects(root, finishedWork, lanes); - root.current = finishedWork; - commitLayoutEffects(finishedWork, root, lanes); + commitMutationEffects(root, transitions, lanes); + root.current = transitions; + commitLayoutEffects(transitions, root, lanes); requestPaint(); executionContext = prevExecutionContext; currentUpdatePriority = previousPriority; ReactCurrentBatchConfig$2.transition = remainingLanes; - } else (root.current = finishedWork), (commitTime = now$1()); + } else (root.current = transitions), (commitTime = now$1()); rootDoesHavePassiveEffects && ((rootDoesHavePassiveEffects = !1), (rootWithPendingPassiveEffects = root), (pendingPassiveEffectsLanes = lanes)); remainingLanes = root.pendingLanes; 0 === remainingLanes && (legacyErrorBoundariesThatAlreadyFailed = null); - onCommitRoot(finishedWork.stateNode, renderPriorityLevel); + onCommitRoot(transitions.stateNode, renderPriorityLevel); isDevToolsPresent && root.memoizedUpdaters.clear(); ensureRootIsScheduled(root, now()); if (null !== recoverableErrors) for ( - renderPriorityLevel = root.onRecoverableError, finishedWork = 0; - finishedWork < recoverableErrors.length; - finishedWork++ + renderPriorityLevel = root.onRecoverableError, transitions = 0; + transitions < recoverableErrors.length; + transitions++ ) - renderPriorityLevel(recoverableErrors[finishedWork]); + renderPriorityLevel(recoverableErrors[transitions]); if (hasUncaughtError) throw ((hasUncaughtError = !1), (root = firstUncaughtError), @@ -7602,21 +7912,43 @@ function pingSuspendedRoot(root, wakeable, pingedLanes) { : (workInProgressRootPingedLanes |= pingedLanes)); ensureRootIsScheduled(root, wakeable); } -function resolveRetryWakeable(boundaryFiber, wakeable) { - var retryCache = boundaryFiber.stateNode; - null !== retryCache && retryCache.delete(wakeable); - wakeable = 0; - 0 === wakeable && +function retryTimedOutBoundary(boundaryFiber, retryLane) { + 0 === retryLane && (0 === (boundaryFiber.mode & 1) - ? (wakeable = 1) - : ((wakeable = nextRetryLane), + ? (retryLane = 1) + : ((retryLane = nextRetryLane), (nextRetryLane <<= 1), 0 === (nextRetryLane & 130023424) && (nextRetryLane = 4194304))); - retryCache = requestEventTime(); - boundaryFiber = markUpdateLaneFromFiberToRoot(boundaryFiber, wakeable); + var eventTime = requestEventTime(); + boundaryFiber = markUpdateLaneFromFiberToRoot(boundaryFiber, retryLane); null !== boundaryFiber && - (markRootUpdated(boundaryFiber, wakeable, retryCache), - ensureRootIsScheduled(boundaryFiber, retryCache)); + (markRootUpdated(boundaryFiber, retryLane, eventTime), + ensureRootIsScheduled(boundaryFiber, eventTime)); +} +function retryDehydratedSuspenseBoundary(boundaryFiber) { + var suspenseState = boundaryFiber.memoizedState, + retryLane = 0; + null !== suspenseState && (retryLane = suspenseState.retryLane); + retryTimedOutBoundary(boundaryFiber, retryLane); +} +function resolveRetryWakeable(boundaryFiber, wakeable) { + var retryLane = 0; + switch (boundaryFiber.tag) { + case 13: + var retryCache = boundaryFiber.stateNode; + var suspenseState = boundaryFiber.memoizedState; + null !== suspenseState && (retryLane = suspenseState.retryLane); + break; + case 19: + retryCache = boundaryFiber.stateNode; + break; + default: + throw Error( + "Pinged unknown suspense boundary type. This is probably a bug in React." + ); + } + null !== retryCache && retryCache.delete(wakeable); + retryTimedOutBoundary(boundaryFiber, retryLane); } var beginWork$1; beginWork$1 = function(current, workInProgress, renderLanes) { @@ -7646,10 +7978,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { switch (workInProgress.tag) { case 2: var Component = workInProgress.type; - null !== current && - ((current.alternate = null), - (workInProgress.alternate = null), - (workInProgress.flags |= 2)); + resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress); current = workInProgress.pendingProps; var context = getMaskedContext( workInProgress, @@ -7703,10 +8032,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { case 16: Component = workInProgress.elementType; a: { - null !== current && - ((current.alternate = null), - (workInProgress.alternate = null), - (workInProgress.flags |= 2)); + resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress); current = workInProgress.pendingProps; context = Component._init; Component = context(Component._payload); @@ -7812,7 +8138,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { return ( pushHostContext(workInProgress), (Component = workInProgress.pendingProps.children), - markRef$1(current, workInProgress), + markRef(current, workInProgress), reconcileChildren(current, workInProgress, Component, renderLanes), workInProgress.child ); @@ -7910,24 +8236,24 @@ beginWork$1 = function(current, workInProgress, renderLanes) { } } else for ( - newValue = workInProgress.child, - null !== newValue && (newValue.return = workInProgress); - null !== newValue; + hasContext = workInProgress.child, + null !== hasContext && (hasContext.return = workInProgress); + null !== hasContext; ) { - var list = newValue.dependencies; + var list = hasContext.dependencies; if (null !== list) { - hasContext = newValue.child; + newValue = hasContext.child; for ( var dependency = list.firstContext; null !== dependency; ) { if (dependency.context === Component) { - if (1 === newValue.tag) { + if (1 === hasContext.tag) { dependency = createUpdate(-1, renderLanes & -renderLanes); dependency.tag = 2; - var updateQueue = newValue.updateQueue; + var updateQueue = hasContext.updateQueue; if (null !== updateQueue) { updateQueue = updateQueue.shared; var pending = updateQueue.pending; @@ -7938,11 +8264,11 @@ beginWork$1 = function(current, workInProgress, renderLanes) { updateQueue.pending = dependency; } } - newValue.lanes |= renderLanes; - dependency = newValue.alternate; + hasContext.lanes |= renderLanes; + dependency = hasContext.alternate; null !== dependency && (dependency.lanes |= renderLanes); scheduleContextWorkOnParentPath( - newValue.return, + hasContext.return, renderLanes, workInProgress ); @@ -7951,29 +8277,43 @@ beginWork$1 = function(current, workInProgress, renderLanes) { } dependency = dependency.next; } - } else - hasContext = - 10 === newValue.tag - ? newValue.type === workInProgress.type - ? null - : newValue.child - : newValue.child; - if (null !== hasContext) hasContext.return = newValue; + } else if (10 === hasContext.tag) + newValue = + hasContext.type === workInProgress.type + ? null + : hasContext.child; + else if (18 === hasContext.tag) { + newValue = hasContext.return; + if (null === newValue) + throw Error( + "We just came from a parent so we must have had a parent. This is a bug in React." + ); + newValue.lanes |= renderLanes; + list = newValue.alternate; + null !== list && (list.lanes |= renderLanes); + scheduleContextWorkOnParentPath( + newValue, + renderLanes, + workInProgress + ); + newValue = hasContext.sibling; + } else newValue = hasContext.child; + if (null !== newValue) newValue.return = hasContext; else - for (hasContext = newValue; null !== hasContext; ) { - if (hasContext === workInProgress) { - hasContext = null; + for (newValue = hasContext; null !== newValue; ) { + if (newValue === workInProgress) { + newValue = null; break; } - newValue = hasContext.sibling; - if (null !== newValue) { - newValue.return = hasContext.return; - hasContext = newValue; + hasContext = newValue.sibling; + if (null !== hasContext) { + hasContext.return = newValue.return; + newValue = hasContext; break; } - hasContext = hasContext.return; + newValue = newValue.return; } - newValue = hasContext; + hasContext = newValue; } reconcileChildren( current, @@ -8024,10 +8364,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { workInProgress.elementType === Component ? context : resolveDefaultProps(Component, context)), - null !== current && - ((current.alternate = null), - (workInProgress.alternate = null), - (workInProgress.flags |= 2)), + resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress), (workInProgress.tag = 1), isContextProvider(Component) ? ((current = !0), pushContextProvider(workInProgress)) @@ -8385,10 +8722,10 @@ batchedUpdatesImpl = function(fn, a) { } }; var roots = new Map(), - devToolsConfig$jscomp$inline_974 = { + devToolsConfig$jscomp$inline_968 = { findFiberByHostInstance: getInstanceFromInstance, bundleType: 0, - version: "18.0.0-experimental-34aa5cfe0-20220329", + version: "18.2.0-next-d300cebde-20220601", rendererPackageName: "react-native-renderer", rendererConfig: { getInspectorDataForViewTag: function() { @@ -8403,11 +8740,11 @@ var roots = new Map(), }.bind(null, findNodeHandle) } }; -var internals$jscomp$inline_1238 = { - bundleType: devToolsConfig$jscomp$inline_974.bundleType, - version: devToolsConfig$jscomp$inline_974.version, - rendererPackageName: devToolsConfig$jscomp$inline_974.rendererPackageName, - rendererConfig: devToolsConfig$jscomp$inline_974.rendererConfig, +var internals$jscomp$inline_1234 = { + bundleType: devToolsConfig$jscomp$inline_968.bundleType, + version: devToolsConfig$jscomp$inline_968.version, + rendererPackageName: devToolsConfig$jscomp$inline_968.rendererPackageName, + rendererConfig: devToolsConfig$jscomp$inline_968.rendererConfig, overrideHookState: null, overrideHookStateDeletePath: null, overrideHookStateRenamePath: null, @@ -8423,26 +8760,26 @@ var internals$jscomp$inline_1238 = { return null === fiber ? null : fiber.stateNode; }, findFiberByHostInstance: - devToolsConfig$jscomp$inline_974.findFiberByHostInstance || + devToolsConfig$jscomp$inline_968.findFiberByHostInstance || emptyFindFiberByHostInstance, findHostInstancesForRefresh: null, scheduleRefresh: null, scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "18.0.0-experimental-34aa5cfe0-20220329" + reconcilerVersion: "18.2.0-next-d300cebde-20220601" }; if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { - var hook$jscomp$inline_1239 = __REACT_DEVTOOLS_GLOBAL_HOOK__; + var hook$jscomp$inline_1235 = __REACT_DEVTOOLS_GLOBAL_HOOK__; if ( - !hook$jscomp$inline_1239.isDisabled && - hook$jscomp$inline_1239.supportsFiber + !hook$jscomp$inline_1235.isDisabled && + hook$jscomp$inline_1235.supportsFiber ) try { - (rendererID = hook$jscomp$inline_1239.inject( - internals$jscomp$inline_1238 + (rendererID = hook$jscomp$inline_1235.inject( + internals$jscomp$inline_1234 )), - (injectedHook = hook$jscomp$inline_1239); + (injectedHook = hook$jscomp$inline_1235); } catch (err) {} } exports.createPortal = function(children, containerTag) { @@ -8499,7 +8836,8 @@ exports.render = function(element, containerTag, callback, concurrentRoot) { element: null, isDehydrated: !1, cache: null, - transitions: null + transitions: null, + pendingSuspenseBoundaries: null }), initializeUpdateQueue(root), (root = concurrentRoot), diff --git a/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js b/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js index fb9a73c8ddb4fc..18a204692a609c 100644 --- a/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js +++ b/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js @@ -8,7 +8,7 @@ * @nolint * @providesModule ReactNativeRenderer-dev * @preventMunge - * @generated SignedSource<<241f2ea4a27fb05d58e884b59ece93fe>> + * @generated SignedSource<<8a3af3b821da6ecad0d3cd1faee60e8f>> */ 'use strict'; @@ -3064,7 +3064,6 @@ function set(key, value) { var enableSchedulingProfiler = false; var enableProfilerTimer = true; var enableProfilerCommitHooks = true; -var enableLazyElements = false; var warnAboutStringRefs = false; var enableSuspenseAvoidThisFallback = false; var enableNewReconciler = false; @@ -3327,9 +3326,6 @@ var Placement = var Update = /* */ 4; -var PlacementAndUpdate = - /* */ - Placement | Update; var ChildDeletion = /* */ 16; @@ -3357,9 +3353,6 @@ var Passive = var Hydrating = /* */ 4096; -var HydratingAndUpdate = - /* */ - Hydrating | Update; var Visibility = /* */ 8192; @@ -4518,13 +4511,13 @@ var InputContinuousHydrationLane = /* */ 2; var InputContinuousLane = - /* */ + /* */ 4; var DefaultHydrationLane = /* */ 8; var DefaultLane = - /* */ + /* */ 16; var TransitionHydrationLane = /* */ @@ -4603,13 +4596,13 @@ var SelectiveHydrationLane = /* */ 134217728; var NonIdleLanes = - /* */ + /* */ 268435455; var IdleHydrationLane = /* */ 268435456; var IdleLane = - /* */ + /* */ 536870912; var OffscreenLane = /* */ @@ -4942,6 +4935,10 @@ function includesNonIdleWork(lanes) { function includesOnlyRetries(lanes) { return (lanes & RetryLanes) === lanes; } +function includesOnlyNonUrgentLanes(lanes) { + var UrgentLanes = SyncLane | InputContinuousLane | DefaultLane; + return (lanes & UrgentLanes) === NoLanes; +} function includesOnlyTransitions(lanes) { return (lanes & TransitionLanes) === lanes; } @@ -4959,7 +4956,7 @@ function includesExpiredLane(root, lanes) { return (lanes & root.expiredLanes) !== NoLanes; } function isTransitionLane(lane) { - return (lane & TransitionLanes) !== 0; + return (lane & TransitionLanes) !== NoLanes; } function claimNextTransitionLane() { // Cycle through the lanes, assigning each new transition to the next lane. @@ -4968,7 +4965,7 @@ function claimNextTransitionLane() { var lane = nextTransitionLane; nextTransitionLane <<= 1; - if ((nextTransitionLane & TransitionLanes) === 0) { + if ((nextTransitionLane & TransitionLanes) === NoLanes) { nextTransitionLane = TransitionLane1; } @@ -4978,7 +4975,7 @@ function claimNextRetryLane() { var lane = nextRetryLane; nextRetryLane <<= 1; - if ((nextRetryLane & RetryLanes) === 0) { + if ((nextRetryLane & RetryLanes) === NoLanes) { nextRetryLane = RetryLane1; } @@ -5080,8 +5077,8 @@ function markRootFinished(root, remainingLanes) { var noLongerPendingLanes = root.pendingLanes & ~remainingLanes; root.pendingLanes = remainingLanes; // Let's try everything again - root.suspendedLanes = 0; - root.pingedLanes = 0; + root.suspendedLanes = NoLanes; + root.pingedLanes = NoLanes; root.expiredLanes &= remainingLanes; root.mutableReadLanes &= remainingLanes; root.entangledLanes &= remainingLanes; @@ -5131,6 +5128,63 @@ function markRootEntangled(root, entangledLanes) { lanes &= ~lane; } } +function getBumpedLaneForHydration(root, renderLanes) { + var renderLane = getHighestPriorityLane(renderLanes); + var lane; + + switch (renderLane) { + case InputContinuousLane: + lane = InputContinuousHydrationLane; + break; + + case DefaultLane: + lane = DefaultHydrationLane; + break; + + case TransitionLane1: + case TransitionLane2: + case TransitionLane3: + case TransitionLane4: + case TransitionLane5: + case TransitionLane6: + case TransitionLane7: + case TransitionLane8: + case TransitionLane9: + case TransitionLane10: + case TransitionLane11: + case TransitionLane12: + case TransitionLane13: + case TransitionLane14: + case TransitionLane15: + case TransitionLane16: + case RetryLane1: + case RetryLane2: + case RetryLane3: + case RetryLane4: + case RetryLane5: + lane = TransitionHydrationLane; + break; + + case IdleLane: + lane = IdleHydrationLane; + break; + + default: + // Everything else is already either a hydration lane, or shouldn't + // be retried at a hydration lane. + lane = NoLane; + break; + } // Check if the lane we chose is suspended. If so, that indicates that we + // already attempted and failed to hydrate at that level. Also check if we're + // already rendering that lane, which is rare but could happen. + + if ((lane & (root.suspendedLanes | renderLanes)) !== NoLane) { + // Give up trying to hydrate and fall back to client render. + return NoLane; + } + + return lane; +} function addFiberToLanesMap(root, fiber, lanes) { if (!isDevToolsPresent) { return; @@ -5173,6 +5227,11 @@ function movePendingFibersToMemoized(root, lanes) { lanes &= ~lane; } } +function getTransitionsForLanes(root, lanes) { + { + return null; + } +} var DiscreteEventPriority = SyncLane; var ContinuousEventPriority = InputContinuousLane; @@ -5223,7 +5282,11 @@ function shim() { } // Hydration (when unsupported) var isSuspenseInstancePending = shim; var isSuspenseInstanceFallback = shim; +var getSuspenseInstanceFallbackErrorDetails = shim; +var registerSuspenseInstanceRetry = shim; var hydrateTextInstance = shim; +var clearSuspenseBoundary = shim; +var clearSuspenseBoundaryFromContainer = shim; var errorHydratingContainer = shim; var getViewConfigForType = @@ -6227,6 +6290,125 @@ function isRootDehydrated(root) { return currentState.isDehydrated; } +// TODO: Use the unified fiber stack module instead of this local one? +// Intentionally not using it yet to derisk the initial implementation, because +// the way we push/pop these values is a bit unusual. If there's a mistake, I'd +// rather the ids be wrong than crash the whole reconciler. +var forkStack = []; +var forkStackIndex = 0; +var treeForkProvider = null; +var treeForkCount = 0; +var idStack = []; +var idStackIndex = 0; +var treeContextProvider = null; +var treeContextId = 1; +var treeContextOverflow = ""; + +function popTreeContext(workInProgress) { + // Restore the previous values. + // This is a bit more complicated than other context-like modules in Fiber + // because the same Fiber may appear on the stack multiple times and for + // different reasons. We have to keep popping until the work-in-progress is + // no longer at the top of the stack. + while (workInProgress === treeForkProvider) { + treeForkProvider = forkStack[--forkStackIndex]; + forkStack[forkStackIndex] = null; + treeForkCount = forkStack[--forkStackIndex]; + forkStack[forkStackIndex] = null; + } + + while (workInProgress === treeContextProvider) { + treeContextProvider = idStack[--idStackIndex]; + idStack[idStackIndex] = null; + treeContextOverflow = idStack[--idStackIndex]; + idStack[idStackIndex] = null; + treeContextId = idStack[--idStackIndex]; + idStack[idStackIndex] = null; + } +} + +var isHydrating = false; // This flag allows for warning supression when we expect there to be mismatches +// due to earlier mismatches or a suspended fiber. + +var didSuspendOrErrorDEV = false; // Hydration errors that were thrown inside this boundary + +var hydrationErrors = null; +function didSuspendOrErrorWhileHydratingDEV() { + { + return didSuspendOrErrorDEV; + } +} + +function reenterHydrationStateFromDehydratedSuspenseInstance( + fiber, + suspenseInstance, + treeContext +) { + { + return false; + } +} + +function prepareToHydrateHostInstance( + fiber, + rootContainerInstance, + hostContext +) { + { + throw new Error( + "Expected prepareToHydrateHostInstance() to never be called. " + + "This error is likely caused by a bug in React. Please file an issue." + ); + } +} + +function prepareToHydrateHostTextInstance(fiber) { + { + throw new Error( + "Expected prepareToHydrateHostTextInstance() to never be called. " + + "This error is likely caused by a bug in React. Please file an issue." + ); + } + var shouldUpdate = hydrateTextInstance(); +} + +function prepareToHydrateHostSuspenseInstance(fiber) { + { + throw new Error( + "Expected prepareToHydrateHostSuspenseInstance() to never be called. " + + "This error is likely caused by a bug in React. Please file an issue." + ); + } +} + +function popHydrationState(fiber) { + { + return false; + } +} + +function upgradeHydrationErrorsToRecoverable() { + if (hydrationErrors !== null) { + // Successfully completed a forced client render. The errors that occurred + // during the hydration attempt are now recovered. We will log them in + // commit phase, once the entire tree has finished. + queueRecoverableErrors(hydrationErrors); + hydrationErrors = null; + } +} + +function getIsHydrating() { + return isHydrating; +} + +function queueHydrationError(error) { + if (hydrationErrors === null) { + hydrationErrors = [error]; + } else { + hydrationErrors.push(error); + } +} + var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig; var NoTransition = null; function requestCurrentTransition() { @@ -6362,11 +6544,17 @@ function resetCurrentFiber() { } function setCurrentFiber(fiber) { { - ReactDebugCurrentFrame$1.getCurrentStack = getCurrentFiberStackInDev; + ReactDebugCurrentFrame$1.getCurrentStack = + fiber === null ? null : getCurrentFiberStackInDev; current = fiber; isRendering = false; } } +function getCurrentFiber() { + { + return current; + } +} function setIsRendering(rendering) { { isRendering = rendering; @@ -7006,6 +7194,34 @@ function propagateContextChange_eager(workInProgress, context, renderLanes) { } else if (fiber.tag === ContextProvider) { // Don't scan deeper if this is a matching provider nextFiber = fiber.type === workInProgress.type ? null : fiber.child; + } else if (fiber.tag === DehydratedFragment) { + // If a dehydrated suspense boundary is in this subtree, we don't know + // if it will have any context consumers in it. The best we can do is + // mark it as having updates. + var parentSuspense = fiber.return; + + if (parentSuspense === null) { + throw new Error( + "We just came from a parent so we must have had a parent. This is a bug in React." + ); + } + + parentSuspense.lanes = mergeLanes(parentSuspense.lanes, renderLanes); + var _alternate = parentSuspense.alternate; + + if (_alternate !== null) { + _alternate.lanes = mergeLanes(_alternate.lanes, renderLanes); + } // This is intentionally passing this fiber as the parent + // because we want to schedule this fiber as having work + // on its children. We'll use the childLanes on + // this fiber to indicate that a context has changed. + + scheduleContextWorkOnParentPath( + parentSuspense, + renderLanes, + workInProgress + ); + nextFiber = fiber.sibling; } else { // Traverse down. nextFiber = fiber.child; @@ -7122,6 +7338,9 @@ function pushInterleavedQueue(queue) { interleavedQueues.push(queue); } } +function hasInterleavedUpdates() { + return interleavedQueues !== null; +} function enqueueInterleavedUpdates() { // Transfer the interleaved updates onto the main queue. Each queue has a // `pending` field and an `interleaved` field. When they are not null, they @@ -8745,78 +8964,6 @@ function updateClassInstance( return shouldUpdate; } -// TODO: Use the unified fiber stack module instead of this local one? -// Intentionally not using it yet to derisk the initial implementation, because -// the way we push/pop these values is a bit unusual. If there's a mistake, I'd -// rather the ids be wrong than crash the whole reconciler. -var forkStack = []; -var forkStackIndex = 0; -var treeForkProvider = null; -var treeForkCount = 0; -var idStack = []; -var idStackIndex = 0; -var treeContextProvider = null; -var treeContextId = 1; -var treeContextOverflow = ""; - -function popTreeContext(workInProgress) { - // Restore the previous values. - // This is a bit more complicated than other context-like modules in Fiber - // because the same Fiber may appear on the stack multiple times and for - // different reasons. We have to keep popping until the work-in-progress is - // no longer at the top of the stack. - while (workInProgress === treeForkProvider) { - treeForkProvider = forkStack[--forkStackIndex]; - forkStack[forkStackIndex] = null; - treeForkCount = forkStack[--forkStackIndex]; - forkStack[forkStackIndex] = null; - } - - while (workInProgress === treeContextProvider) { - treeContextProvider = idStack[--idStackIndex]; - idStack[idStackIndex] = null; - treeContextOverflow = idStack[--idStackIndex]; - idStack[idStackIndex] = null; - treeContextId = idStack[--idStackIndex]; - idStack[idStackIndex] = null; - } -} - -var isHydrating = false; - -function prepareToHydrateHostInstance( - fiber, - rootContainerInstance, - hostContext -) { - { - throw new Error( - "Expected prepareToHydrateHostInstance() to never be called. " + - "This error is likely caused by a bug in React. Please file an issue." - ); - } -} - -function prepareToHydrateHostTextInstance(fiber) { - { - throw new Error( - "Expected prepareToHydrateHostTextInstance() to never be called. " + - "This error is likely caused by a bug in React. Please file an issue." - ); - } - var shouldUpdate = hydrateTextInstance(); -} - -function popHydrationState(fiber) { - { - return false; - } -} - -function getIsHydrating() { - return isHydrating; -} - var didWarnAboutMaps; var didWarnAboutGenerators; var didWarnAboutStringRefs; @@ -9029,6 +9176,12 @@ function warnOnFunctionType(returnFiber) { ); } } + +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. @@ -9170,7 +9323,10 @@ function ChildReconciler(shouldTrackSideEffects) { // 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. - enableLazyElements + (typeof elementType === "object" && + elementType !== null && + elementType.$$typeof === REACT_LAZY_TYPE && + resolveLazy(elementType) === current.type) ) { // Move based on index var existing = useFiber(current, element.props); @@ -9267,6 +9423,12 @@ function ChildReconciler(shouldTrackSideEffects) { _created2.return = returnFiber; return _created2; } + + case REACT_LAZY_TYPE: { + var payload = newChild._payload; + var init = newChild._init; + return createChild(returnFiber, init(payload), lanes); + } } if (isArray(newChild) || getIteratorFn(newChild)) { @@ -9328,6 +9490,12 @@ function ChildReconciler(shouldTrackSideEffects) { return null; } } + + case REACT_LAZY_TYPE: { + var payload = newChild._payload; + var init = newChild._init; + return updateSlot(returnFiber, oldFiber, init(payload), lanes); + } } if (isArray(newChild) || getIteratorFn(newChild)) { @@ -9386,6 +9554,17 @@ function ChildReconciler(shouldTrackSideEffects) { return updatePortal(returnFiber, _matchedFiber2, newChild, lanes); } + + case REACT_LAZY_TYPE: + var payload = newChild._payload; + var init = newChild._init; + return updateFromMap( + existingChildren, + returnFiber, + newIdx, + init(payload), + lanes + ); } if (isArray(newChild) || getIteratorFn(newChild)) { @@ -9452,6 +9631,12 @@ function ChildReconciler(shouldTrackSideEffects) { ); break; + + case REACT_LAZY_TYPE: + var payload = child._payload; + var init = child._init; + warnOnInvalidKey(init(payload), knownKeys, returnFiber); + break; } } @@ -9893,7 +10078,10 @@ function ChildReconciler(shouldTrackSideEffects) { // 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. - enableLazyElements + (typeof elementType === "object" && + elementType !== null && + elementType.$$typeof === REACT_LAZY_TYPE && + resolveLazy(elementType) === child.type) ) { deleteRemainingChildren(returnFiber, child.sibling); @@ -10022,6 +10210,17 @@ function ChildReconciler(shouldTrackSideEffects) { 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)) { @@ -11541,66 +11740,72 @@ function updateMemo(nextCreate, deps) { } function mountDeferredValue(value) { - var _mountState = mountState(value), - prevValue = _mountState[0], - setValue = _mountState[1]; + var hook = mountWorkInProgressHook(); + hook.memoizedState = value; + return value; +} - mountEffect( - function() { - var prevTransition = ReactCurrentBatchConfig$1.transition; - ReactCurrentBatchConfig$1.transition = {}; +function updateDeferredValue(value) { + var hook = updateWorkInProgressHook(); + var resolvedCurrentHook = currentHook; + var prevValue = resolvedCurrentHook.memoizedState; + return updateDeferredValueImpl(hook, prevValue, value); +} - try { - setValue(value); - } finally { - ReactCurrentBatchConfig$1.transition = prevTransition; - } - }, - [value] - ); - return prevValue; -} +function rerenderDeferredValue(value) { + var hook = updateWorkInProgressHook(); -function updateDeferredValue(value) { - var _updateState = updateState(), - prevValue = _updateState[0], - setValue = _updateState[1]; + 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); + } +} - updateEffect( - function() { - var prevTransition = ReactCurrentBatchConfig$1.transition; - ReactCurrentBatchConfig$1.transition = {}; +function updateDeferredValueImpl(hook, prevValue, value) { + var shouldDeferValue = !includesOnlyNonUrgentLanes(renderLanes); - try { - setValue(value); - } finally { - ReactCurrentBatchConfig$1.transition = prevTransition; - } - }, - [value] - ); - return prevValue; -} + 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. -function rerenderDeferredValue(value) { - var _rerenderState = rerenderState(), - prevValue = _rerenderState[0], - setValue = _rerenderState[1]; + hook.baseState = true; + } // Reuse the previous value - updateEffect( - function() { - var prevTransition = ReactCurrentBatchConfig$1.transition; - ReactCurrentBatchConfig$1.transition = {}; + 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(); + } - try { - setValue(value); - } finally { - ReactCurrentBatchConfig$1.transition = prevTransition; - } - }, - [value] - ); - return prevValue; + hook.memoizedState = value; + return value; + } } function startTransition(setPending, callback, options) { @@ -11643,9 +11848,9 @@ function startTransition(setPending, callback, options) { } function mountTransition() { - var _mountState2 = mountState(false), - isPending = _mountState2[0], - setPending = _mountState2[1]; // The `start` method never changes. + var _mountState = mountState(false), + isPending = _mountState[0], + setPending = _mountState[1]; // The `start` method never changes. var start = startTransition.bind(null, setPending); var hook = mountWorkInProgressHook(); @@ -11654,8 +11859,8 @@ function mountTransition() { } function updateTransition() { - var _updateState2 = updateState(), - isPending = _updateState2[0]; + var _updateState = updateState(), + isPending = _updateState[0]; var hook = updateWorkInProgressHook(); var start = hook.memoizedState; @@ -11663,8 +11868,8 @@ function updateTransition() { } function rerenderTransition() { - var _rerenderState2 = rerenderState(), - isPending = _rerenderState2[0]; + var _rerenderState = rerenderState(), + isPending = _rerenderState[0]; var hook = updateWorkInProgressHook(); var start = hook.memoizedState; @@ -13474,3606 +13679,3989 @@ function getSuspendedCache() { } // This function is called when a Suspense boundary suspends. It returns the } -function markUpdate(workInProgress) { - // Tag the fiber with an update effect. This turns a Placement into - // a PlacementAndUpdate. - workInProgress.flags |= Update; +var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner; +var didReceiveUpdate = false; +var didWarnAboutBadClass; +var didWarnAboutModulePatternComponent; +var didWarnAboutContextTypeOnFunctionComponent; +var didWarnAboutGetDerivedStateOnFunctionComponent; +var didWarnAboutFunctionRefs; +var didWarnAboutReassigningProps; +var didWarnAboutRevealOrder; +var didWarnAboutTailOptions; + +{ + didWarnAboutBadClass = {}; + didWarnAboutModulePatternComponent = {}; + didWarnAboutContextTypeOnFunctionComponent = {}; + didWarnAboutGetDerivedStateOnFunctionComponent = {}; + didWarnAboutFunctionRefs = {}; + didWarnAboutReassigningProps = false; + didWarnAboutRevealOrder = {}; + didWarnAboutTailOptions = {}; } -function markRef(workInProgress) { - workInProgress.flags |= Ref; +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 + ); + } } -var appendAllChildren; -var updateHostContainer; -var updateHostComponent; -var updateHostText; +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. -{ - // Mutation mode - appendAllChildren = function( - parent, + workInProgress.child = reconcileChildFibers( 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; + null, + nextChildren, + renderLanes + ); +} - while (node !== null) { - if (node.tag === HostComponent || node.tag === HostText) { - appendInitialChild(parent, node.stateNode); - } else if (node.tag === HostPortal); - else if (node.child !== null) { - node.child.return = node; - node = node.child; - continue; - } +function 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 (node === workInProgress) { - return; + if (innerPropTypes) { + checkPropTypes( + innerPropTypes, + nextProps, // Resolved props + "prop", + getComponentNameFromType(Component) + ); } + } + } - while (node.sibling === null) { - if (node.return === null || node.return === workInProgress) { - return; - } + var render = Component.render; + var ref = workInProgress.ref; // The rest is a fork of updateFunctionComponent - node = node.return; - } + var nextChildren; + prepareToReadContext(workInProgress, renderLanes); - node.sibling.return = node.return; - node = node.sibling; - } - }; + { + ReactCurrentOwner$1.current = workInProgress; + setIsRendering(true); + nextChildren = renderWithHooks( + current, + workInProgress, + render, + nextProps, + ref, + renderLanes + ); - updateHostContainer = function(current, workInProgress) { - // Noop - }; + setIsRendering(false); + } - updateHostComponent = function( - current, - workInProgress, - type, - newProps, - rootContainerInstance - ) { - // If we have an alternate, that means this is an update and we need to - // schedule a side-effect to do the updates. - var oldProps = current.memoizedProps; + if (current !== null && !didReceiveUpdate) { + bailoutHooks(current, workInProgress, renderLanes); + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); + } - if (oldProps === newProps) { - // In mutation mode, this is sufficient for a bailout because - // we won't touch this node even if children changed. - return; - } // If we get updated because one of our children updated, we don't - // have newProps so we'll have to reuse them. - // TODO: Split the update API as separate for the props vs. children. - // Even better would be if children weren't special cased at all tho. + workInProgress.flags |= PerformedWork; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; +} - var instance = workInProgress.stateNode; - var currentHostContext = getHostContext(); // TODO: Experiencing an error where oldProps is null. Suggests a host - // component is hitting the resume path. Figure out why. Possibly - // related to `hidden`. +function updateMemoComponent( + current, + workInProgress, + Component, + nextProps, + renderLanes +) { + if (current === null) { + var type = Component.type; - var updatePayload = prepareUpdate(); // TODO: Type this specific to this type of component. + if ( + isSimpleFunctionComponent(type) && + Component.compare === null && // SimpleMemoComponent codepath doesn't resolve outer props either. + Component.defaultProps === undefined + ) { + var resolvedType = type; - workInProgress.updateQueue = updatePayload; // If the update payload indicates that there is a change or if there - // is a new ref we mark this as an update. All the work is done in commitWork. + { + 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. - if (updatePayload) { - markUpdate(workInProgress); - } - }; + workInProgress.tag = SimpleMemoComponent; + workInProgress.type = resolvedType; - updateHostText = function(current, workInProgress, oldText, newText) { - // If the text differs, mark it as an update. All the work in done in commitWork. - if (oldText !== newText) { - markUpdate(workInProgress); - } - }; -} - -function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { - switch (renderState.tailMode) { - case "hidden": { - // Any insertions at the end of the tail list after this point - // should be invisible. If there are already mounted boundaries - // anything before them are not considered for collapsing. - // Therefore we need to go through the whole tail to find if - // there are any. - var tailNode = renderState.tail; - var lastTailNode = null; - - while (tailNode !== null) { - if (tailNode.alternate !== null) { - lastTailNode = tailNode; - } - - tailNode = tailNode.sibling; - } // Next we're simply going to delete all insertions after the - // last rendered item. - - if (lastTailNode === null) { - // All remaining items in the tail are insertions. - renderState.tail = null; - } else { - // Detach the insertion after the last node that was already - // inserted. - lastTailNode.sibling = null; + { + validateFunctionComponentInDev(workInProgress, type); } - break; + return updateSimpleMemoComponent( + current, + workInProgress, + resolvedType, + nextProps, + renderLanes + ); } - case "collapsed": { - // Any insertions at the end of the tail list after this point - // should be invisible. If there are already mounted boundaries - // anything before them are not considered for collapsing. - // Therefore we need to go through the whole tail to find if - // there are any. - var _tailNode = renderState.tail; - var _lastTailNode = null; - - while (_tailNode !== null) { - if (_tailNode.alternate !== null) { - _lastTailNode = _tailNode; - } - - _tailNode = _tailNode.sibling; - } // Next we're simply going to delete all insertions after the - // last rendered item. + { + var innerPropTypes = type.propTypes; - if (_lastTailNode === null) { - // All remaining items in the tail are insertions. - if (!hasRenderedATailFallback && renderState.tail !== null) { - // We suspended during the head. We want to show at least one - // row at the tail. So we'll keep on and cut off the rest. - renderState.tail.sibling = null; - } else { - renderState.tail = null; - } - } else { - // Detach the insertion after the last node that was already - // inserted. - _lastTailNode.sibling = null; + if (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) + ); } - - break; } + + var child = createFiberFromTypeAndProps( + Component.type, + null, + nextProps, + workInProgress, + workInProgress.mode, + renderLanes + ); + child.ref = workInProgress.ref; + child.return = workInProgress; + workInProgress.child = child; + return child; } -} -function bubbleProperties(completedWork) { - var didBailout = - completedWork.alternate !== null && - completedWork.alternate.child === completedWork.child; - var newChildLanes = NoLanes; - var subtreeFlags = NoFlags; + { + var _type = Component.type; + var _innerPropTypes = _type.propTypes; - 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 (_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) + ); + } + } - 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. + var currentChild = current.child; // This is always exactly one child - actualDuration += child.actualDuration; - treeBaseDuration += child.treeBaseDuration; - child = child.sibling; - } + var hasScheduledUpdateOrContext = checkScheduledUpdateOrContext( + current, + renderLanes + ); - completedWork.actualDuration = actualDuration; - completedWork.treeBaseDuration = treeBaseDuration; - } else { - var _child = completedWork.child; + 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 - 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 compare = Component.compare; + compare = compare !== null ? compare : shallowEqual; - _child.return = completedWork; - _child = _child.sibling; - } + if (compare(prevProps, nextProps) && current.ref === workInProgress.ref) { + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); } + } // React DevTools reads this flag. - completedWork.subtreeFlags |= subtreeFlags; - } else { - // Bubble up the earliest expiration time. - if ((completedWork.mode & ProfileMode) !== NoMode) { - // In profiling mode, resetChildExpirationTime is also used to reset - // profiler durations. - var _treeBaseDuration = completedWork.selfBaseDuration; - var _child2 = completedWork.child; - - while (_child2 !== null) { - newChildLanes = mergeLanes( - newChildLanes, - mergeLanes(_child2.lanes, _child2.childLanes) - ); // "Static" flags share the lifetime of the fiber/hook they belong to, - // so we should bubble those up even during a bailout. All the other - // flags have a lifetime only of a single render + commit, so we should - // ignore them. + workInProgress.flags |= PerformedWork; + var newChild = createWorkInProgress(currentChild, nextProps); + newChild.ref = workInProgress.ref; + newChild.return = workInProgress; + workInProgress.child = newChild; + return newChild; +} - subtreeFlags |= _child2.subtreeFlags & StaticMask; - subtreeFlags |= _child2.flags & StaticMask; - _treeBaseDuration += _child2.treeBaseDuration; - _child2 = _child2.sibling; - } +function updateSimpleMemoComponent( + current, + workInProgress, + Component, + nextProps, + renderLanes +) { + // TODO: current can be non-null here even if the component + // hasn't yet mounted. This happens when the inner render suspends. + // We'll need to figure out if this is fine or can cause issues. + { + if (workInProgress.type !== workInProgress.elementType) { + // Lazy component props can't be validated in createElement + // because they're only guaranteed to be resolved here. + var outerMemoType = workInProgress.elementType; - completedWork.treeBaseDuration = _treeBaseDuration; - } else { - var _child3 = completedWork.child; + if (outerMemoType.$$typeof === REACT_LAZY_TYPE) { + // We warn when you define propTypes on lazy() + // so let's just skip over it to find memo() outer wrapper. + // Inner props for memo are validated later. + var lazyComponent = outerMemoType; + var payload = lazyComponent._payload; + var init = lazyComponent._init; - while (_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. + try { + outerMemoType = init(payload); + } catch (x) { + outerMemoType = null; + } // Inner propTypes will be validated in the function component path. - subtreeFlags |= _child3.subtreeFlags & StaticMask; - subtreeFlags |= _child3.flags & StaticMask; // Update the return pointer so the tree is consistent. This is a code - // smell because it assumes the commit phase is never concurrent with - // the render phase. Will address during refactor to alternate model. + var outerPropTypes = outerMemoType && outerMemoType.propTypes; - _child3.return = completedWork; - _child3 = _child3.sibling; + if (outerPropTypes) { + checkPropTypes( + outerPropTypes, + nextProps, // Resolved (SimpleMemoComponent has no defaultProps) + "prop", + getComponentNameFromType(outerMemoType) + ); + } } } - - completedWork.subtreeFlags |= subtreeFlags; } - completedWork.childLanes = newChildLanes; - return didBailout; -} - -function completeWork(current, workInProgress, renderLanes) { - var newProps = workInProgress.pendingProps; // Note: This intentionally doesn't check if we're hydrating because comparing - // to the current tree provider fiber is just as fast and less error-prone. - // Ideally we would have a special version of the work loop only - // for hydration. - - popTreeContext(workInProgress); + if (current !== null) { + var prevProps = current.memoizedProps; - switch (workInProgress.tag) { - case IndeterminateComponent: - case LazyComponent: - case SimpleMemoComponent: - case FunctionComponent: - case ForwardRef: - case Fragment: - case Mode: - case Profiler: - case ContextConsumer: - case MemoComponent: - bubbleProperties(workInProgress); - return null; + if ( + 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. - case ClassComponent: { - var Component = workInProgress.type; + workInProgress.pendingProps = nextProps = prevProps; - if (isContextProvider(Component)) { - popContext(workInProgress); + if (!checkScheduledUpdateOrContext(current, renderLanes)) { + // The pending lanes were cleared at the beginning of beginWork. We're + // about to bail out, but there might be other lanes that weren't + // included in the current render. Usually, the priority level of the + // remaining updates is accumulated during the evaluation of the + // component (i.e. when processing the update queue). But since since + // we're bailing out early *without* evaluating the component, we need + // to account for it here, too. Reset to the value of the current fiber. + // NOTE: This only applies to SimpleMemoComponent, not MemoComponent, + // because a MemoComponent fiber does not have hooks or an update queue; + // rather, it wraps around an inner component, which may or may not + // contains hooks. + // TODO: Move the reset at in beginWork out of the common path so that + // this is no longer necessary. + workInProgress.lanes = current.lanes; + return bailoutOnAlreadyFinishedWork( + current, + workInProgress, + renderLanes + ); + } else if ((current.flags & ForceUpdateForLegacySuspense) !== NoFlags) { + // This is a special case that only exists for legacy mode. + // See https://github.com/facebook/react/pull/19216. + didReceiveUpdate = true; } - - bubbleProperties(workInProgress); - return null; } + } - case HostRoot: { - var fiberRoot = workInProgress.stateNode; + return updateFunctionComponent( + current, + workInProgress, + Component, + nextProps, + renderLanes + ); +} - popHostContainer(workInProgress); - popTopLevelContextObject(workInProgress); - resetWorkInProgressVersions(); +function updateOffscreenComponent(current, workInProgress, renderLanes) { + var nextProps = workInProgress.pendingProps; + var nextChildren = nextProps.children; + var prevState = current !== null ? current.memoizedState : null; - if (fiberRoot.pendingContext) { - fiberRoot.context = fiberRoot.pendingContext; - fiberRoot.pendingContext = null; - } + if (nextProps.mode === "hidden" || enableLegacyHidden) { + // Rendering a hidden tree. + if ((workInProgress.mode & ConcurrentMode) === NoMode) { + // In legacy sync mode, don't defer the subtree. Render it now. + // TODO: Consider how Offscreen should work with transitions in the future + var nextState = { + baseLanes: NoLanes, + cachePool: null, + transitions: null + }; + workInProgress.memoizedState = nextState; - if (current === null || current.child === null) { - // If we hydrated, pop so that we can delete any remaining children - // that weren't hydrated. - var wasHydrated = popHydrationState(); + pushRenderLanes(workInProgress, renderLanes); + } else if (!includesSomeLane(renderLanes, OffscreenLane)) { + var spawnedCachePool = null; // We're hidden, and we're not rendering at Offscreen. We will bail out + // and resume this tree later. - 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; + var nextBaseLanes; - if ( - // Check if this is a client root - !prevState.isDehydrated || // Check if we reverted to client rendering (e.g. due to an error) - (workInProgress.flags & ForceClientRender) !== NoFlags - ) { - // Schedule an effect to clear this container at the start of the - // next commit. This handles the case of React rendering into a - // container with previous children. It's also safe to do for - // updates too, because current.child would only be null if the - // previous render was null (so the container would already - // be empty). - workInProgress.flags |= Snapshot; // If this was a forced client render, there may have been - } - } - } - } + if (prevState !== null) { + var prevBaseLanes = prevState.baseLanes; + nextBaseLanes = mergeLanes(prevBaseLanes, renderLanes); + } else { + nextBaseLanes = renderLanes; + } // Schedule this fiber to re-render at offscreen priority. Then bailout. + + workInProgress.lanes = workInProgress.childLanes = laneToLanes( + OffscreenLane + ); + var _nextState = { + baseLanes: nextBaseLanes, + cachePool: spawnedCachePool, + transitions: null + }; + workInProgress.memoizedState = _nextState; + workInProgress.updateQueue = null; + // to avoid a push/pop misalignment. + + pushRenderLanes(workInProgress, nextBaseLanes); - updateHostContainer(current, workInProgress); - bubbleProperties(workInProgress); return null; - } + } else { + // This is the second render. The surrounding visible content has already + // committed. Now we resume rendering the hidden tree. + // Rendering at offscreen, so we can clear the base lanes. + var _nextState2 = { + baseLanes: NoLanes, + cachePool: null, + transitions: null + }; + workInProgress.memoizedState = _nextState2; // Push the lanes that were skipped when we bailed out. - case HostComponent: { - popHostContext(workInProgress); - var rootContainerInstance = getRootHostContainer(); - var type = workInProgress.type; + var subtreeRenderLanes = + prevState !== null ? prevState.baseLanes : renderLanes; - if (current !== null && workInProgress.stateNode != null) { - updateHostComponent( - current, - workInProgress, - type, - newProps, - rootContainerInstance - ); + pushRenderLanes(workInProgress, subtreeRenderLanes); + } + } else { + // Rendering a visible tree. + var _subtreeRenderLanes; - 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 (prevState !== null) { + // We're going from hidden -> visible. + _subtreeRenderLanes = mergeLanes(prevState.baseLanes, renderLanes); - bubbleProperties(workInProgress); - return null; - } + workInProgress.memoizedState = null; + } else { + // We weren't previously hidden, and we still aren't, so there's nothing + // special to do. Need to push to the stack regardless, though, to avoid + // a push/pop misalignment. + _subtreeRenderLanes = renderLanes; + } - var currentHostContext = getHostContext(); // TODO: Move createInstance to beginWork and keep it on a context - // "stack" as the parent. Then append children as we go in beginWork - // or completeWork depending on whether we want to add them top->down or - // bottom->up. Top->down is faster in IE11. + pushRenderLanes(workInProgress, _subtreeRenderLanes); + } - var _wasHydrated = popHydrationState(); + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; +} // Note: These happen to have identical begin phases, for now. We shouldn't hold - if (_wasHydrated) { - // TODO: Move this and createInstance step into the beginPhase - // to consolidate. - if (prepareToHydrateHostInstance()) { - // If changes to the hydrated node need to be applied at the - // commit-phase we mark this as such. - markUpdate(workInProgress); - } - } else { - var instance = createInstance( - type, - newProps, - rootContainerInstance, - currentHostContext, - workInProgress - ); - appendAllChildren(instance, workInProgress, false, false); - workInProgress.stateNode = instance; // Certain renderers require commit-time effects for initial mount. - // (eg DOM renderer supports auto-focus for certain elements). - // Make sure such renderers get scheduled for later work. +function updateFragment(current, workInProgress, renderLanes) { + var nextChildren = workInProgress.pendingProps; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; +} - if (finalizeInitialChildren(instance)) { - markUpdate(workInProgress); - } - } +function updateMode(current, workInProgress, renderLanes) { + var nextChildren = workInProgress.pendingProps.children; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; +} - if (workInProgress.ref !== null) { - // If there is a ref on a host node we need to schedule a callback - markRef(workInProgress); - } - } +function updateProfiler(current, workInProgress, renderLanes) { + { + workInProgress.flags |= Update; - bubbleProperties(workInProgress); - return null; + { + // Reset effect durations for the next eventual effect phase. + // These are reset during render to allow the DevTools commit hook a chance to read them, + var stateNode = workInProgress.stateNode; + stateNode.effectDuration = 0; + stateNode.passiveEffectDuration = 0; } + } - 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 nextProps = workInProgress.pendingProps; + var nextChildren = nextProps.children; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; +} - var _rootContainerInstance = getRootHostContainer(); +function markRef(current, workInProgress) { + var ref = workInProgress.ref; - var _currentHostContext = getHostContext(); + if ( + (current === null && ref !== null) || + (current !== null && current.ref !== ref) + ) { + // Schedule a Ref effect + workInProgress.flags |= Ref; + } +} - var _wasHydrated2 = popHydrationState(); +function updateFunctionComponent( + current, + workInProgress, + Component, + nextProps, + renderLanes +) { + { + if (workInProgress.type !== workInProgress.elementType) { + // Lazy component props can't be validated in createElement + // because they're only guaranteed to be resolved here. + var innerPropTypes = Component.propTypes; - if (_wasHydrated2) { - if (prepareToHydrateHostTextInstance()) { - markUpdate(workInProgress); - } - } else { - workInProgress.stateNode = createTextInstance( - newText, - _rootContainerInstance, - _currentHostContext, - workInProgress - ); - } + if (innerPropTypes) { + checkPropTypes( + innerPropTypes, + nextProps, // Resolved props + "prop", + getComponentNameFromType(Component) + ); } - - bubbleProperties(workInProgress); - return null; } + } - case SuspenseComponent: { - popSuspenseContext(workInProgress); - var nextState = workInProgress.memoizedState; + var context; - if ((workInProgress.flags & DidCapture) !== NoFlags) { - // Something suspended. Re-render with the fallback children. - workInProgress.lanes = renderLanes; // Do not reset the effect list. + { + var unmaskedContext = getUnmaskedContext(workInProgress, Component, true); + context = getMaskedContext(workInProgress, unmaskedContext); + } - if ((workInProgress.mode & ProfileMode) !== NoMode) { - transferActualDuration(workInProgress); - } // Don't bubble properties in this case. + var nextChildren; + prepareToReadContext(workInProgress, renderLanes); - return workInProgress; - } + { + ReactCurrentOwner$1.current = workInProgress; + setIsRendering(true); + nextChildren = renderWithHooks( + current, + workInProgress, + Component, + nextProps, + context, + renderLanes + ); - var nextDidTimeout = nextState !== null; - var prevDidTimeout = false; + setIsRendering(false); + } - if (current === null); - else { - var _prevState = current.memoizedState; - prevDidTimeout = _prevState !== null; - } - // 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 && !prevDidTimeout) { - var _offscreenFiber = workInProgress.child; - _offscreenFiber.flags |= Visibility; // TODO: This will still suspend a synchronous tree if anything - // in the concurrent tree already suspended during this render. - // This is a known bug. - - if ((workInProgress.mode & ConcurrentMode) !== NoMode) { - // TODO: Move this back to throwException because this is too late - // if this is a large tree which is common for initial loads. We - // don't know if we should restart a render or not until we get - // this marker, and this is too late. - // If this render already had a ping or lower pri updates, - // and this is the first time we know we're going to suspend we - // should be able to immediately restart from within throwException. - var hasInvisibleChildContext = - current === null && - (workInProgress.memoizedProps.unstable_avoidThisFallback !== true || - !enableSuspenseAvoidThisFallback); + if (current !== null && !didReceiveUpdate) { + bailoutHooks(current, workInProgress, renderLanes); + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); + } - if ( - hasInvisibleChildContext || - hasSuspenseContext( - suspenseStackCursor.current, - InvisibleParentSuspenseContext - ) - ) { - // If this was in an invisible tree or a new render, then showing - // this boundary is ok. - renderDidSuspend(); - } else { - // Otherwise, we're going to have to hide content so we should - // suspend for longer if possible. - renderDidSuspendDelayIfPossible(); - } - } - } + workInProgress.flags |= PerformedWork; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; +} - var wakeables = workInProgress.updateQueue; +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 (wakeables !== null) { - // Schedule an effect to attach a retry listener to the promise. - // TODO: Move to passive phase - workInProgress.flags |= Update; + var tempInstance = new ctor( + workInProgress.memoizedProps, + _instance.context + ); + var state = tempInstance.state; + + _instance.updater.enqueueSetState(_instance, state, null); + + break; } - bubbleProperties(workInProgress); + case true: { + workInProgress.flags |= DidCapture; + workInProgress.flags |= ShouldCapture; // eslint-disable-next-line react-internal/prod-error-codes - { - 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 _primaryChildFragment2 = workInProgress.child; + var error$1 = new Error("Simulated error coming from DevTools"); + var lane = pickArbitraryLane(renderLanes); + workInProgress.lanes = mergeLanes(workInProgress.lanes, lane); // Schedule the error boundary to re-render using updated state - if (_primaryChildFragment2 !== null) { - // $FlowFixMe Flow doesn't support type casting in combination with the -= operator - workInProgress.treeBaseDuration -= - _primaryChildFragment2.treeBaseDuration; - } - } - } + var update = createClassErrorUpdate( + workInProgress, + createCapturedValue(error$1, workInProgress), + lane + ); + enqueueCapturedUpdate(workInProgress, update); + break; } - - return null; } - case HostPortal: - popHostContainer(workInProgress); - updateHostContainer(current, workInProgress); + 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 (current === null) { - preparePortalMount(workInProgress.stateNode.containerInfo); + if (innerPropTypes) { + checkPropTypes( + innerPropTypes, + nextProps, // Resolved props + "prop", + getComponentNameFromType(Component) + ); } + } + } // Push context providers early to prevent context stack mismatches. + // During mounting we don't know the child context yet as the instance doesn't exist. + // We will invalidate the child context in finishClassComponent() right after rendering. - bubbleProperties(workInProgress); - return null; + var hasContext; - case ContextProvider: - // Pop provider fiber - var context = workInProgress.type._context; - popProvider(context, workInProgress); - bubbleProperties(workInProgress); - return null; + if (isContextProvider(Component)) { + hasContext = true; + pushContextProvider(workInProgress); + } else { + hasContext = false; + } - 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; + prepareToReadContext(workInProgress, renderLanes); + var instance = workInProgress.stateNode; + var shouldUpdate; - if (isContextProvider(_Component)) { - popContext(workInProgress); - } + if (instance === null) { + resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress); // In the initial pass we might need to construct the instance. - bubbleProperties(workInProgress); - return null; - } + constructClassInstance(workInProgress, Component, nextProps); + mountClassInstance(workInProgress, Component, nextProps, renderLanes); + shouldUpdate = true; + } else if (current === null) { + // In a resume, we'll already have an instance we can reuse. + shouldUpdate = resumeMountClassInstance( + workInProgress, + Component, + nextProps, + renderLanes + ); + } else { + shouldUpdate = updateClassInstance( + current, + workInProgress, + Component, + nextProps, + renderLanes + ); + } - case SuspenseListComponent: { - popSuspenseContext(workInProgress); - var renderState = workInProgress.memoizedState; + var nextUnitOfWork = finishClassComponent( + current, + workInProgress, + Component, + shouldUpdate, + hasContext, + renderLanes + ); - if (renderState === null) { - // We're running in the default, "independent" mode. - // We don't do anything in this mode. - bubbleProperties(workInProgress); - return null; - } + { + var inst = workInProgress.stateNode; - var didSuspendAlready = (workInProgress.flags & DidCapture) !== NoFlags; - var renderedTail = renderState.rendering; + 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 (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); + didWarnAboutReassigningProps = true; + } + } - if (!cannotBeSuspended) { - var row = workInProgress.child; + return nextUnitOfWork; +} - while (row !== null) { - var suspended = findFirstSuspended(row); +function finishClassComponent( + current, + workInProgress, + Component, + shouldUpdate, + hasContext, + renderLanes +) { + // Refs should update even if shouldComponentUpdate returns false + markRef(current, workInProgress); + var didCaptureError = (workInProgress.flags & DidCapture) !== NoFlags; - if (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. + if (!shouldUpdate && !didCaptureError) { + // Context providers should defer to sCU for rendering + if (hasContext) { + invalidateContextProvider(workInProgress, Component, false); + } - var newThenables = suspended.updateQueue; + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); + } - 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. + var instance = workInProgress.stateNode; // Rerender - workInProgress.subtreeFlags = NoFlags; - resetChildFibers(workInProgress, renderLanes); // Set up the Suspense Context to force suspense and immediately - // rerender the children. + ReactCurrentOwner$1.current = workInProgress; + var nextChildren; - pushSuspenseContext( - workInProgress, - setShallowSuspenseContext( - suspenseStackCursor.current, - ForceSuspenseFallback - ) - ); // Don't bubble properties in this case. + 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; - return workInProgress.child; - } + { + stopProfilerTimerIfRunning(); + } + } else { + { + setIsRendering(true); + nextChildren = instance.render(); - row = row.sibling; - } - } + setIsRendering(false); + } + } // React DevTools reads this flag. - if (renderState.tail !== null && now() > getRenderTargetTime()) { - // We have already passed our CPU deadline but we still have rows - // left in the tail. We'll just give up further attempts to render - // the main content and only render fallbacks. - workInProgress.flags |= DidCapture; - didSuspendAlready = true; - cutOffTailIfNeeded(renderState, false); // Since nothing actually suspended, there will nothing to ping this - // to get it started back up to attempt the next item. While in terms - // of priority this work has the same priority as this current render, - // it's not part of the same transition once the transition has - // committed. If it's sync, we still want to yield so that it can be - // painted. Conceptually, this is really the same as pinging. - // We can use any RetryLane even if it's the one currently rendering - // since we're leaving it behind on this node. + workInProgress.flags |= PerformedWork; - 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 (current !== null && didCaptureError) { + // If we're recovering from an error, reconcile without reusing any of + // the existing children. Conceptually, the normal children and the children + // that are shown on error are two different sets, so we shouldn't reuse + // normal children even if their identities match. + forceUnmountCurrentAndReconcile( + current, + workInProgress, + nextChildren, + renderLanes + ); + } else { + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + } // Memoize state using the values we just used to render. + // TODO: Restructure so we never read values from the instance. - if (_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. + workInProgress.memoizedState = instance.state; // The context might have changed so we need to recalculate it. - var _newThenables = _suspended.updateQueue; + if (hasContext) { + invalidateContextProvider(workInProgress, Component, true); + } - if (_newThenables !== null) { - workInProgress.updateQueue = _newThenables; - workInProgress.flags |= Update; - } + return workInProgress.child; +} - cutOffTailIfNeeded(renderState, true); // This might have been modified. +function pushHostRootContext(workInProgress) { + var root = workInProgress.stateNode; - if ( - renderState.tail === null && - renderState.tailMode === "hidden" && - !renderedTail.alternate && - !getIsHydrating() // We don't cut it if we're hydrating. - ) { - // We're done. - bubbleProperties(workInProgress); - return null; - } - } else if ( - // The time it took to render last row is greater than the remaining - // time we have to render. So rendering one more row would likely - // exceed it. - now() * 2 - renderState.renderingStartTime > - getRenderTargetTime() && - renderLanes !== OffscreenLane - ) { - // We have now passed our CPU deadline and we'll just give up further - // attempts to render the main content and only render fallbacks. - // The assumption is that this is usually faster. - workInProgress.flags |= DidCapture; - didSuspendAlready = true; - cutOffTailIfNeeded(renderState, false); // Since nothing actually suspended, there will nothing to ping this - // to get it started back up to attempt the next item. While in terms - // of priority this work has the same priority as this current render, - // it's not part of the same transition once the transition has - // committed. If it's sync, we still want to yield so that it can be - // painted. Conceptually, this is really the same as pinging. - // We can use any RetryLane even if it's the one currently rendering - // since we're leaving it behind on this node. + if (root.pendingContext) { + pushTopLevelContextObject( + workInProgress, + root.pendingContext, + root.pendingContext !== root.context + ); + } else if (root.context) { + // Should always be set + pushTopLevelContextObject(workInProgress, root.context, false); + } - workInProgress.lanes = SomeRetryLane; - } - } + pushHostContainer(workInProgress, root.containerInfo); +} - 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 updateHostRoot(current, workInProgress, renderLanes) { + pushHostRootContext(workInProgress); - if (previousSibling !== null) { - previousSibling.sibling = renderedTail; - } else { - workInProgress.child = renderedTail; - } + if (current === null) { + throw new Error("Should have a current fiber. This is a bug in React."); + } - renderState.last = renderedTail; - } - } + var nextProps = workInProgress.pendingProps; + var prevState = workInProgress.memoizedState; + var prevChildren = prevState.element; + cloneUpdateQueue(current, workInProgress); + processUpdateQueue(workInProgress, nextProps, null, renderLanes); + var nextState = workInProgress.memoizedState; + var root = workInProgress.stateNode; + // being called "element". - if (renderState.tail !== null) { - // We still have tail rows to render. - // Pop a row. - var next = renderState.tail; - renderState.rendering = next; - renderState.tail = next.sibling; - renderState.renderingStartTime = now(); - next.sibling = null; // Restore the context. - // TODO: We can probably just avoid popping it instead and only - // setting it the first time we go from not suspended to suspended. + var nextChildren = nextState.element; - var suspenseContext = suspenseStackCursor.current; + { + if (nextChildren === prevChildren) { + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); + } - if (didSuspendAlready) { - suspenseContext = setShallowSuspenseContext( - suspenseContext, - ForceSuspenseFallback - ); - } else { - suspenseContext = setDefaultShallowSuspenseContext(suspenseContext); - } + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + } - pushSuspenseContext(workInProgress, suspenseContext); // Do a pass over the next row. - // Don't bubble properties in this case. + return workInProgress.child; +} - return next; - } +function updateHostComponent(current, workInProgress, renderLanes) { + pushHostContext(workInProgress); - bubbleProperties(workInProgress); - return null; - } + var type = workInProgress.type; + var nextProps = workInProgress.pendingProps; + var prevProps = current !== null ? current.memoizedProps : null; + var nextChildren = nextProps.children; - case ScopeComponent: { - break; - } + 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; + } - case OffscreenComponent: - case LegacyHiddenComponent: { - popRenderLanes(workInProgress); - var _nextState = workInProgress.memoizedState; - var nextIsHidden = _nextState !== null; + markRef(current, workInProgress); + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; +} - if (current !== null) { - var _prevState2 = current.memoizedState; - var prevIsHidden = _prevState2 !== null; +function updateHostText(current, workInProgress) { + // immediately after. - if ( - prevIsHidden !== nextIsHidden && // LegacyHidden doesn't do any hiding — it only pre-renders. - !enableLegacyHidden - ) { - workInProgress.flags |= Visibility; - } + return null; +} + +function mountLazyComponent( + _current, + workInProgress, + elementType, + renderLanes +) { + resetSuspendedCurrentOnMountInLegacyMode(_current, workInProgress); + var props = workInProgress.pendingProps; + var lazyComponent = elementType; + var payload = lazyComponent._payload; + var init = lazyComponent._init; + var Component = init(payload); // Store the unwrapped component in the type. + + workInProgress.type = Component; + var resolvedTag = (workInProgress.tag = resolveLazyComponentTag(Component)); + var resolvedProps = resolveDefaultProps(Component, props); + var child; + + switch (resolvedTag) { + case FunctionComponent: { + { + validateFunctionComponentInDev(workInProgress, Component); + workInProgress.type = Component = resolveFunctionForHotReloading( + Component + ); } - if (!nextIsHidden || (workInProgress.mode & ConcurrentMode) === NoMode) { - bubbleProperties(workInProgress); - } else { - // Don't bubble properties for hidden children unless we're rendering - // at offscreen priority. - if (includesSomeLane(subtreeRenderLanes, OffscreenLane)) { - bubbleProperties(workInProgress); + child = updateFunctionComponent( + null, + workInProgress, + Component, + resolvedProps, + renderLanes + ); + return child; + } - { - // Check if there was an insertion or update in the hidden subtree. - // If so, we need to hide those nodes in the commit phase, so - // schedule a visibility effect. - if (workInProgress.subtreeFlags & (Placement | Update)) { - workInProgress.flags |= Visibility; - } - } - } + case ClassComponent: { + { + workInProgress.type = Component = resolveClassForHotReloading( + Component + ); } - return null; + child = updateClassComponent( + null, + workInProgress, + Component, + resolvedProps, + renderLanes + ); + return child; } - case CacheComponent: { - return null; + case ForwardRef: { + { + workInProgress.type = Component = resolveForwardRefForHotReloading( + Component + ); + } + + child = updateForwardRef( + null, + workInProgress, + Component, + resolvedProps, + renderLanes + ); + return child; } - case TracingMarkerComponent: { - return null; + case MemoComponent: { + { + if (workInProgress.type !== workInProgress.elementType) { + var outerPropTypes = Component.propTypes; + + if (outerPropTypes) { + checkPropTypes( + outerPropTypes, + resolvedProps, // Resolved for outer only + "prop", + getComponentNameFromType(Component) + ); + } + } + } + + child = updateMemoComponent( + null, + workInProgress, + Component, + resolveDefaultProps(Component.type, resolvedProps), // The inner type can have defaults too + renderLanes + ); + return child; } } + var hint = ""; + + { + if ( + Component !== null && + typeof Component === "object" && + Component.$$typeof === REACT_LAZY_TYPE + ) { + hint = " Did you wrap a component in React.lazy() more than once?"; + } + } // This message intentionally doesn't mention ForwardRef or MemoComponent + // because the fact that it's a separate type of work is an + // implementation detail. + throw new Error( - "Unknown unit of work tag (" + - workInProgress.tag + - "). This error is likely caused by a bug in " + - "React. Please file an issue." + "Element type is invalid. Received a promise that resolves to: " + + Component + + ". " + + ("Lazy element type must resolve to a class or function." + hint) ); } -var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner; -var didReceiveUpdate = false; -var didWarnAboutBadClass; -var didWarnAboutModulePatternComponent; -var didWarnAboutContextTypeOnFunctionComponent; -var didWarnAboutGetDerivedStateOnFunctionComponent; -var didWarnAboutFunctionRefs; -var didWarnAboutReassigningProps; -var didWarnAboutRevealOrder; -var didWarnAboutTailOptions; +function mountIncompleteClassComponent( + _current, + workInProgress, + Component, + nextProps, + renderLanes +) { + resetSuspendedCurrentOnMountInLegacyMode(_current, workInProgress); // Promote the fiber to a class and try rendering again. -{ - didWarnAboutBadClass = {}; - didWarnAboutModulePatternComponent = {}; - didWarnAboutContextTypeOnFunctionComponent = {}; - didWarnAboutGetDerivedStateOnFunctionComponent = {}; - didWarnAboutFunctionRefs = {}; - didWarnAboutReassigningProps = false; - didWarnAboutRevealOrder = {}; - didWarnAboutTailOptions = {}; -} + 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 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 - ); + var hasContext; + + if (isContextProvider(Component)) { + hasContext = true; + pushContextProvider(workInProgress); } 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 - ); + hasContext = false; } -} -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, + prepareToReadContext(workInProgress, renderLanes); + constructClassInstance(workInProgress, Component, nextProps); + mountClassInstance(workInProgress, Component, nextProps, renderLanes); + return finishClassComponent( null, - renderLanes - ); // In the second pass, we mount the new children. The trick here is that we - // pass null in place of where we usually pass the current child set. This has - // the effect of remounting all children regardless of whether their - // identities match. - - workInProgress.child = reconcileChildFibers( workInProgress, - null, - nextChildren, + Component, + true, + hasContext, renderLanes ); } -function updateForwardRef( - current, +function mountIndeterminateComponent( + _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. + resetSuspendedCurrentOnMountInLegacyMode(_current, workInProgress); + var props = workInProgress.pendingProps; + var context; + { - if (workInProgress.type !== workInProgress.elementType) { - // Lazy component props can't be validated in createElement - // because they're only guaranteed to be resolved here. - var innerPropTypes = Component.propTypes; + var unmaskedContext = getUnmaskedContext(workInProgress, Component, false); + context = getMaskedContext(workInProgress, unmaskedContext); + } - if (innerPropTypes) { - checkPropTypes( - innerPropTypes, - nextProps, // Resolved props - "prop", - getComponentNameFromType(Component) + prepareToReadContext(workInProgress, renderLanes); + var value; + + { + if ( + Component.prototype && + typeof Component.prototype.render === "function" + ) { + var componentName = getComponentNameFromType(Component) || "Unknown"; + + if (!didWarnAboutBadClass[componentName]) { + error( + "The <%s /> component appears to have a render method, but doesn't extend React.Component. " + + "This is likely to cause errors. Change %s to extend React.Component instead.", + componentName, + componentName ); + + didWarnAboutBadClass[componentName] = true; } } - } - var render = Component.render; - var ref = workInProgress.ref; // The rest is a fork of updateFunctionComponent + if (workInProgress.mode & StrictLegacyMode) { + ReactStrictModeWarnings.recordLegacyContextWarning(workInProgress, null); + } - var nextChildren; - prepareToReadContext(workInProgress, renderLanes); + setIsRendering(true); + ReactCurrentOwner$1.current = workInProgress; + value = renderWithHooks( + null, + workInProgress, + Component, + props, + context, + renderLanes + ); + setIsRendering(false); + } + + workInProgress.flags |= PerformedWork; { - ReactCurrentOwner$1.current = workInProgress; - setIsRendering(true); - nextChildren = renderWithHooks( - current, + // Support for module components is deprecated and is removed behind a flag. + // Whether or not it would crash later, we want to show a good message in DEV first. + if ( + typeof value === "object" && + value !== null && + typeof value.render === "function" && + value.$$typeof === undefined + ) { + var _componentName = getComponentNameFromType(Component) || "Unknown"; + + if (!didWarnAboutModulePatternComponent[_componentName]) { + error( + "The <%s /> component appears to be a function component that returns a class instance. " + + "Change %s to a class that extends React.Component instead. " + + "If you can't use a class try assigning the prototype on the function as a workaround. " + + "`%s.prototype = React.Component.prototype`. Don't use an arrow function since it " + + "cannot be called with `new` by React.", + _componentName, + _componentName, + _componentName + ); + + didWarnAboutModulePatternComponent[_componentName] = true; + } + } + } + + if ( + // Run these checks in production only if the flag is off. + // Eventually we'll delete this branch altogether. + typeof value === "object" && + value !== null && + typeof value.render === "function" && + value.$$typeof === undefined + ) { + { + var _componentName2 = getComponentNameFromType(Component) || "Unknown"; + + if (!didWarnAboutModulePatternComponent[_componentName2]) { + error( + "The <%s /> component appears to be a function component that returns a class instance. " + + "Change %s to a class that extends React.Component instead. " + + "If you can't use a class try assigning the prototype on the function as a workaround. " + + "`%s.prototype = React.Component.prototype`. Don't use an arrow function since it " + + "cannot be called with `new` by React.", + _componentName2, + _componentName2, + _componentName2 + ); + + didWarnAboutModulePatternComponent[_componentName2] = true; + } + } // Proceed under the assumption that this is a class instance + + workInProgress.tag = ClassComponent; // Throw out any hooks that were used. + + workInProgress.memoizedState = null; + workInProgress.updateQueue = null; // Push context providers early to prevent context stack mismatches. + // During mounting we don't know the child context yet as the instance doesn't exist. + // We will invalidate the child context in finishClassComponent() right after rendering. + + var hasContext = false; + + if (isContextProvider(Component)) { + hasContext = true; + pushContextProvider(workInProgress); + } else { + hasContext = false; + } + + workInProgress.memoizedState = + value.state !== null && value.state !== undefined ? value.state : null; + initializeUpdateQueue(workInProgress); + adoptClassInstance(workInProgress, value); + mountClassInstance(workInProgress, Component, props, renderLanes); + return finishClassComponent( + null, workInProgress, - render, - nextProps, - ref, + Component, + true, + hasContext, renderLanes ); + } else { + // Proceed under the assumption that this is a function component + workInProgress.tag = FunctionComponent; - setIsRendering(false); - } + reconcileChildren(null, workInProgress, value, renderLanes); - if (current !== null && !didReceiveUpdate) { - bailoutHooks(current, workInProgress, renderLanes); - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); - } + { + validateFunctionComponentInDev(workInProgress, Component); + } - workInProgress.flags |= PerformedWork; - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; + return workInProgress.child; + } } -function updateMemoComponent( - current, - workInProgress, - Component, - nextProps, - renderLanes -) { - if (current === null) { - var type = Component.type; +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 ( - isSimpleFunctionComponent(type) && - Component.compare === null && // SimpleMemoComponent codepath doesn't resolve outer props either. - Component.defaultProps === undefined - ) { - var resolvedType = type; + if (workInProgress.ref !== null) { + var info = ""; + var ownerName = getCurrentFiberOwnerNameInDevOrNull(); - { - 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. + if (ownerName) { + info += "\n\nCheck the render method of `" + ownerName + "`."; + } - workInProgress.tag = SimpleMemoComponent; - workInProgress.type = resolvedType; + var warningKey = ownerName || ""; + var debugSource = workInProgress._debugSource; - { - validateFunctionComponentInDev(workInProgress, type); + if (debugSource) { + warningKey = debugSource.fileName + ":" + debugSource.lineNumber; } - return updateSimpleMemoComponent( - current, - workInProgress, - resolvedType, - nextProps, - renderLanes - ); + 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 + ); + } } - { - var innerPropTypes = type.propTypes; + if (typeof Component.getDerivedStateFromProps === "function") { + var _componentName3 = getComponentNameFromType(Component) || "Unknown"; - if (innerPropTypes) { - // Inner memo component props aren't currently validated in createElement. - // We could move it there, but we'd still need this for lazy code path. - checkPropTypes( - innerPropTypes, - nextProps, // Resolved props - "prop", - getComponentNameFromType(type) + if (!didWarnAboutGetDerivedStateOnFunctionComponent[_componentName3]) { + error( + "%s: Function components do not support getDerivedStateFromProps.", + _componentName3 ); + + didWarnAboutGetDerivedStateOnFunctionComponent[_componentName3] = true; } } - var child = createFiberFromTypeAndProps( - Component.type, - null, - nextProps, - workInProgress, - workInProgress.mode, - renderLanes - ); - child.ref = workInProgress.ref; - child.return = workInProgress; - workInProgress.child = child; - return child; - } + if ( + typeof Component.contextType === "object" && + Component.contextType !== null + ) { + var _componentName4 = getComponentNameFromType(Component) || "Unknown"; - { - var _type = Component.type; - var _innerPropTypes = _type.propTypes; + if (!didWarnAboutContextTypeOnFunctionComponent[_componentName4]) { + error( + "%s: Function components do not support contextType.", + _componentName4 + ); - 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) - ); + didWarnAboutContextTypeOnFunctionComponent[_componentName4] = true; + } } } +} - var currentChild = current.child; // This is always exactly one child - - var hasScheduledUpdateOrContext = checkScheduledUpdateOrContext( - current, - renderLanes - ); - - if (!hasScheduledUpdateOrContext) { - // This will be the props with resolved defaultProps, - // unlike current.memoizedProps which will be the unresolved ones. - var prevProps = currentChild.memoizedProps; // Default to shallow comparison +var SUSPENDED_MARKER = { + dehydrated: null, + treeContext: null, + retryLane: NoLane +}; - var compare = Component.compare; - compare = compare !== null ? compare : shallowEqual; +function mountSuspenseOffscreenState(renderLanes) { + return { + baseLanes: renderLanes, + cachePool: getSuspendedCache(), + transitions: null + }; +} - if (compare(prevProps, nextProps) && current.ref === workInProgress.ref) { - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); - } - } // React DevTools reads this flag. +function updateSuspenseOffscreenState(prevOffscreenState, renderLanes) { + var cachePool = null; - workInProgress.flags |= PerformedWork; - var newChild = createWorkInProgress(currentChild, nextProps); - newChild.ref = workInProgress.ref; - newChild.return = workInProgress; - workInProgress.child = newChild; - return newChild; -} + return { + baseLanes: mergeLanes(prevOffscreenState.baseLanes, renderLanes), + cachePool: cachePool, + transitions: prevOffscreenState.transitions + }; +} // TODO: Probably should inline this back -function updateSimpleMemoComponent( +function shouldRemainOnFallback( + suspenseContext, current, workInProgress, - Component, - nextProps, renderLanes ) { - // TODO: current can be non-null here even if the component - // hasn't yet mounted. This happens when the inner render suspends. - // We'll need to figure out if this is fine or can cause issues. + // If we're already showing a fallback, there are cases where we need to + // remain on that fallback regardless of whether the content has resolved. + // For example, SuspenseList coordinates when nested content appears. + if (current !== null) { + var suspenseState = current.memoizedState; + + if (suspenseState === null) { + // Currently showing content. Don't hide it, even if ForceSuspenseFallback + // is true. More precise name might be "ForceRemainSuspenseFallback". + // Note: This is a factoring smell. Can't remain on a fallback if there's + // no fallback to remain on. + return false; + } + } // Not currently showing content. Consult the Suspense context. + + return hasSuspenseContext(suspenseContext, ForceSuspenseFallback); +} + +function getRemainingWorkInPrimaryTree(current, renderLanes) { + // TODO: Should not remove render lanes that were pinged during this render + return removeLanes(current.childLanes, renderLanes); +} + +function updateSuspenseComponent(current, workInProgress, renderLanes) { + var nextProps = workInProgress.pendingProps; // This is used by DevTools to force a boundary to suspend. + { - if (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 (shouldSuspend(workInProgress)) { + workInProgress.flags |= DidCapture; + } + } - if (outerMemoType.$$typeof === REACT_LAZY_TYPE) { - // We warn when you define propTypes on lazy() - // so let's just skip over it to find memo() outer wrapper. - // Inner props for memo are validated later. - var lazyComponent = outerMemoType; - var payload = lazyComponent._payload; - var init = lazyComponent._init; + var suspenseContext = suspenseStackCursor.current; + var showFallback = false; + var didSuspend = (workInProgress.flags & DidCapture) !== NoFlags; + + if (didSuspend || shouldRemainOnFallback(suspenseContext, current)) { + // Something in this boundary's subtree already suspended. Switch to + // rendering the fallback children. + showFallback = true; + workInProgress.flags &= ~DidCapture; + } else { + // Attempting the main content + if (current === null || current.memoizedState !== null) { + // This is a new mount or this boundary is already showing a fallback state. + // Mark this subtree context as having at least one invisible parent that could + // handle the fallback state. + // Avoided boundaries are not considered since they cannot handle preferred fallback states. + { + suspenseContext = addSubtreeSuspenseContext( + suspenseContext, + InvisibleParentSuspenseContext + ); + } + } + } - try { - outerMemoType = init(payload); - } catch (x) { - outerMemoType = null; - } // Inner propTypes will be validated in the function component path. + suspenseContext = setDefaultShallowSuspenseContext(suspenseContext); + pushSuspenseContext(workInProgress, suspenseContext); // OK, the next part is confusing. We're about to reconcile the Suspense + // boundary's children. This involves some custom reconciliation logic. Two + // main reasons this is so complicated. + // + // First, Legacy Mode has different semantics for backwards compatibility. The + // primary tree will commit in an inconsistent state, so when we do the + // second pass to render the fallback, we do some exceedingly, uh, clever + // hacks to make that not totally break. Like transferring effects and + // deletions from hidden tree. In Concurrent Mode, it's much simpler, + // because we bailout on the primary tree completely and leave it in its old + // state, no effects. Same as what we do for Offscreen (except that + // Offscreen doesn't have the first render pass). + // + // Second is hydration. During hydration, the Suspense fiber has a slightly + // different layout, where the child points to a dehydrated fragment, which + // contains the DOM rendered by the server. + // + // Third, even if you set all that aside, Suspense is like error boundaries in + // that we first we try to render one tree, and if that fails, we render again + // and switch to a different tree. Like a try/catch block. So we have to track + // which branch we're currently rendering. Ideally we would model this using + // a stack. - var outerPropTypes = outerMemoType && outerMemoType.propTypes; + if (current === null) { + var suspenseState = workInProgress.memoizedState; - if (outerPropTypes) { - checkPropTypes( - outerPropTypes, - nextProps, // Resolved (SimpleMemoComponent has no defaultProps) - "prop", - getComponentNameFromType(outerMemoType) - ); - } + if (suspenseState !== null) { + var dehydrated = suspenseState.dehydrated; + + if (dehydrated !== null) { + return mountDehydratedSuspenseComponent(workInProgress); } } - } - if (current !== null) { - var prevProps = current.memoizedProps; + var nextPrimaryChildren = nextProps.children; + var nextFallbackChildren = nextProps.fallback; - if ( - shallowEqual(prevProps, nextProps) && - current.ref === workInProgress.ref && // Prevent bailout if the implementation changed due to hot reload. - workInProgress.type === current.type - ) { - didReceiveUpdate = false; + if (showFallback) { + var fallbackFragment = mountSuspenseFallbackChildren( + workInProgress, + nextPrimaryChildren, + nextFallbackChildren, + renderLanes + ); + var primaryChildFragment = workInProgress.child; + primaryChildFragment.memoizedState = mountSuspenseOffscreenState( + renderLanes + ); + workInProgress.memoizedState = SUSPENDED_MARKER; - 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( + return fallbackFragment; + } else { + return mountSuspensePrimaryChildren(workInProgress, nextPrimaryChildren); + } + } else { + // This is an update. + // Special path for hydration + var prevState = current.memoizedState; + + if (prevState !== null) { + var _dehydrated = prevState.dehydrated; + + if (_dehydrated !== null) { + return updateDehydratedSuspenseComponent( current, workInProgress, + didSuspend, + nextProps, + _dehydrated, + prevState, renderLanes ); - } else if ((current.flags & ForceUpdateForLegacySuspense) !== NoFlags) { - // This is a special case that only exists for legacy mode. - // See https://github.com/facebook/react/pull/19216. - didReceiveUpdate = true; } } + + if (showFallback) { + var _nextFallbackChildren = nextProps.fallback; + var _nextPrimaryChildren = nextProps.children; + var fallbackChildFragment = updateSuspenseFallbackChildren( + current, + workInProgress, + _nextPrimaryChildren, + _nextFallbackChildren, + renderLanes + ); + var _primaryChildFragment2 = workInProgress.child; + var prevOffscreenState = current.child.memoizedState; + _primaryChildFragment2.memoizedState = + prevOffscreenState === null + ? mountSuspenseOffscreenState(renderLanes) + : updateSuspenseOffscreenState(prevOffscreenState, renderLanes); + + _primaryChildFragment2.childLanes = getRemainingWorkInPrimaryTree( + current, + renderLanes + ); + workInProgress.memoizedState = SUSPENDED_MARKER; + return fallbackChildFragment; + } else { + var _nextPrimaryChildren2 = nextProps.children; + + var _primaryChildFragment3 = updateSuspensePrimaryChildren( + current, + workInProgress, + _nextPrimaryChildren2, + renderLanes + ); + + workInProgress.memoizedState = null; + return _primaryChildFragment3; + } } +} - return updateFunctionComponent( - current, - workInProgress, - Component, - nextProps, - renderLanes +function mountSuspensePrimaryChildren( + workInProgress, + primaryChildren, + renderLanes +) { + var mode = workInProgress.mode; + var primaryChildProps = { + mode: "visible", + children: primaryChildren + }; + var primaryChildFragment = mountWorkInProgressOffscreenFiber( + primaryChildProps, + mode ); + primaryChildFragment.return = workInProgress; + workInProgress.child = primaryChildFragment; + return primaryChildFragment; } -function updateOffscreenComponent(current, workInProgress, renderLanes) { - var nextProps = workInProgress.pendingProps; - var nextChildren = nextProps.children; - var prevState = current !== null ? current.memoizedState : null; +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 (nextProps.mode === "hidden" || enableLegacyHidden) { - // Rendering a hidden tree. - if ((workInProgress.mode & ConcurrentMode) === NoMode) { - // In legacy sync mode, don't defer the subtree. Render it now. - var nextState = { - baseLanes: NoLanes, - cachePool: null - }; - workInProgress.memoizedState = nextState; + 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; - pushRenderLanes(workInProgress, renderLanes); - } else if (!includesSomeLane(renderLanes, OffscreenLane)) { - var spawnedCachePool = null; // We're hidden, and we're not rendering at Offscreen. We will bail out - // and resume this tree later. + 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; + } - var nextBaseLanes; + fallbackChildFragment = createFiberFromFragment( + fallbackChildren, + mode, + renderLanes, + null + ); + } else { + primaryChildFragment = mountWorkInProgressOffscreenFiber( + primaryChildProps, + mode + ); + fallbackChildFragment = createFiberFromFragment( + fallbackChildren, + mode, + renderLanes, + null + ); + } - if (prevState !== null) { - var prevBaseLanes = prevState.baseLanes; - nextBaseLanes = mergeLanes(prevBaseLanes, renderLanes); - } else { - nextBaseLanes = renderLanes; - } // Schedule this fiber to re-render at offscreen priority. Then bailout. + primaryChildFragment.return = workInProgress; + fallbackChildFragment.return = workInProgress; + primaryChildFragment.sibling = fallbackChildFragment; + workInProgress.child = primaryChildFragment; + return fallbackChildFragment; +} - workInProgress.lanes = workInProgress.childLanes = laneToLanes( - OffscreenLane - ); - var _nextState = { - baseLanes: nextBaseLanes, - cachePool: spawnedCachePool - }; - workInProgress.memoizedState = _nextState; - workInProgress.updateQueue = null; - // to avoid a push/pop misalignment. +function mountWorkInProgressOffscreenFiber(offscreenProps, mode, renderLanes) { + // The props argument to `createFiberFromOffscreen` is `any` typed, so we use + // this wrapper function to constrain it. + return createFiberFromOffscreen(offscreenProps, mode, NoLanes, null); +} + +function updateWorkInProgressOffscreenFiber(current, offscreenProps) { + // The props argument to `createWorkInProgress` is `any` typed, so we use this + // wrapper function to constrain it. + return createWorkInProgress(current, offscreenProps); +} + +function updateSuspensePrimaryChildren( + current, + workInProgress, + primaryChildren, + renderLanes +) { + var currentPrimaryChildFragment = current.child; + var currentFallbackChildFragment = currentPrimaryChildFragment.sibling; + var primaryChildFragment = updateWorkInProgressOffscreenFiber( + currentPrimaryChildFragment, + { + mode: "visible", + children: primaryChildren + } + ); + + if ((workInProgress.mode & ConcurrentMode) === NoMode) { + primaryChildFragment.lanes = renderLanes; + } - pushRenderLanes(workInProgress, nextBaseLanes); + primaryChildFragment.return = workInProgress; + primaryChildFragment.sibling = null; - return null; + if (currentFallbackChildFragment !== null) { + // Delete the fallback child fragment + var deletions = workInProgress.deletions; + + if (deletions === null) { + workInProgress.deletions = [currentFallbackChildFragment]; + workInProgress.flags |= ChildDeletion; } else { - // This is the second render. The surrounding visible content has already - // committed. Now we resume rendering the hidden tree. - // Rendering at offscreen, so we can clear the base lanes. - var _nextState2 = { - baseLanes: NoLanes, - cachePool: null - }; - workInProgress.memoizedState = _nextState2; // Push the lanes that were skipped when we bailed out. + deletions.push(currentFallbackChildFragment); + } + } - var subtreeRenderLanes = - prevState !== null ? prevState.baseLanes : renderLanes; + workInProgress.child = primaryChildFragment; + return primaryChildFragment; +} - pushRenderLanes(workInProgress, subtreeRenderLanes); - } - } else { - // Rendering a visible tree. - var _subtreeRenderLanes; +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 (prevState !== null) { - // We're going from hidden -> visible. - _subtreeRenderLanes = mergeLanes(prevState.baseLanes, renderLanes); + 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.memoizedState = null; - } else { - // We weren't previously hidden, and we still aren't, so there's nothing - // special to do. Need to push to the stack regardless, though, to avoid - // a push/pop misalignment. - _subtreeRenderLanes = renderLanes; - } + if (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. - pushRenderLanes(workInProgress, _subtreeRenderLanes); + workInProgress.deletions = null; + } else { + primaryChildFragment = updateWorkInProgressOffscreenFiber( + currentPrimaryChildFragment, + primaryChildProps + ); // Since we're reusing a current tree, we need to reuse the flags, too. + // (We don't do this in legacy mode, because in legacy mode we don't re-use + // the current tree; see previous branch.) + + primaryChildFragment.subtreeFlags = + currentPrimaryChildFragment.subtreeFlags & StaticMask; } - { - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; + var fallbackChildFragment; + + if (currentFallbackChildFragment !== null) { + fallbackChildFragment = createWorkInProgress( + currentFallbackChildFragment, + fallbackChildren + ); + } else { + fallbackChildFragment = createFiberFromFragment( + fallbackChildren, + mode, + renderLanes, + null + ); // Needs a placement effect because the parent (the Suspense boundary) already + // mounted but this is a new fiber. + + fallbackChildFragment.flags |= Placement; } -} -function updateFragment(current, workInProgress, renderLanes) { - var nextChildren = workInProgress.pendingProps; - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; + fallbackChildFragment.return = workInProgress; + primaryChildFragment.return = workInProgress; + primaryChildFragment.sibling = fallbackChildFragment; + workInProgress.child = primaryChildFragment; + return fallbackChildFragment; } -function updateMode(current, workInProgress, renderLanes) { - var nextChildren = workInProgress.pendingProps.children; - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; +function retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, + recoverableError +) { + // Falling back to client rendering. Because this has performance + // implications, it's considered a recoverable error, even though the user + // likely won't observe anything wrong with the UI. + // + // The error is passed in as an argument to enforce that every caller provide + // a custom message, or explicitly opt out (currently the only path that opts + // out is legacy mode; every concurrent path provides an error). + if (recoverableError !== null) { + queueHydrationError(recoverableError); + } // This will add the old fiber to the deletion list + + reconcileChildFibers(workInProgress, current.child, null, renderLanes); // We're now not suspended nor dehydrated. + + var nextProps = workInProgress.pendingProps; + var primaryChildren = nextProps.children; + var primaryChildFragment = mountSuspensePrimaryChildren( + workInProgress, + primaryChildren + ); // Needs a placement effect because the parent (the Suspense boundary) already + // mounted but this is a new fiber. + + primaryChildFragment.flags |= Placement; + workInProgress.memoizedState = null; + return primaryChildFragment; } -function updateProfiler(current, workInProgress, renderLanes) { - { - workInProgress.flags |= Update; +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. - { - // 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; - } + fallbackChildFragment.flags |= Placement; + primaryChildFragment.return = workInProgress; + fallbackChildFragment.return = workInProgress; + primaryChildFragment.sibling = fallbackChildFragment; + workInProgress.child = primaryChildFragment; + + if ((workInProgress.mode & ConcurrentMode) !== NoMode) { + // We will have dropped the effect list which contains the + // deletion. We need to reconcile to delete the current child. + reconcileChildFibers(workInProgress, current.child, null, renderLanes); } - var nextProps = workInProgress.pendingProps; - var nextChildren = nextProps.children; - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; + return fallbackChildFragment; } -function markRef$1(current, workInProgress) { - var ref = workInProgress.ref; +function mountDehydratedSuspenseComponent( + workInProgress, + suspenseInstance, + renderLanes +) { + // During the first pass, we'll bail out and not drill into the children. + // Instead, we'll leave the content in place and try to hydrate it later. + if ((workInProgress.mode & ConcurrentMode) === NoMode) { + { + error( + "Cannot hydrate Suspense in legacy mode. Switch from " + + "ReactDOM.hydrate(element, container) to " + + "ReactDOMClient.hydrateRoot(container, )" + + ".render(element) or remove the Suspense components from " + + "the server rendered components." + ); + } - if ( - (current === null && ref !== null) || - (current !== null && current.ref !== ref) - ) { - // Schedule a Ref effect - workInProgress.flags |= Ref; + workInProgress.lanes = laneToLanes(SyncLane); + } else if (isSuspenseInstanceFallback()) { + // This is a client-only boundary. Since we won't get any content from the server + // for this, we need to schedule that at a higher priority based on when it would + // have timed out. In theory we could render it in this pass but it would have the + // wrong priority associated with it and will prevent hydration of parent path. + // Instead, we'll leave work left on it to render it in a separate commit. + // TODO This time should be the time at which the server rendered response that is + // a parent to this boundary was displayed. However, since we currently don't have + // a protocol to transfer that time, we'll just estimate it by using the current + // time. This will mean that Suspense timeouts are slightly shifted to later than + // they should be. + // Schedule a normal pri update to render this content. + workInProgress.lanes = laneToLanes(DefaultHydrationLane); + } else { + // We'll continue hydrating the rest at offscreen priority since we'll already + // be showing the right content coming from the server, it is no rush. + workInProgress.lanes = laneToLanes(OffscreenLane); } + + return null; } -function updateFunctionComponent( +function updateDehydratedSuspenseComponent( current, workInProgress, - Component, + didSuspend, nextProps, + suspenseInstance, + suspenseState, 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 (!didSuspend) { + if ((workInProgress.mode & ConcurrentMode) === NoMode) { + return retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, // TODO: When we delete legacy mode, we should make this error argument + // required — every concurrent mode path that causes hydration to + // de-opt to client rendering should have an error message. + null + ); + } - if (innerPropTypes) { - checkPropTypes( - innerPropTypes, - nextProps, // Resolved props - "prop", - getComponentNameFromType(Component) - ); - } + 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 _getSuspenseInstanceF = getSuspenseInstanceFallbackErrorDetails(), + errorMessage = _getSuspenseInstanceF.errorMessage; + + var error = errorMessage // eslint-disable-next-line react-internal/prod-error-codes + ? new Error(errorMessage) + : new Error( + "The server could not finish this Suspense boundary, likely " + + "due to an error during server rendering. Switched to " + + "client rendering." + ); + return retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, + error + ); } - } + // any context has changed, we need to treat is as if the input might have changed. - var context; + var hasContextChanged = includesSomeLane(renderLanes, current.childLanes); - { - var unmaskedContext = getUnmaskedContext(workInProgress, Component, true); - context = getMaskedContext(workInProgress, unmaskedContext); - } + 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(); - var nextChildren; - prepareToReadContext(workInProgress, renderLanes); + if (root !== null) { + var attemptHydrationAtLane = getBumpedLaneForHydration( + root, + renderLanes + ); - { - ReactCurrentOwner$1.current = workInProgress; - setIsRendering(true); - nextChildren = renderWithHooks( - current, - workInProgress, - Component, - nextProps, - context, - renderLanes - ); + if ( + attemptHydrationAtLane !== NoLane && + attemptHydrationAtLane !== suspenseState.retryLane + ) { + // Intentionally mutating since this render will get interrupted. This + // is one of the very rare times where we mutate the current tree + // during the render phase. + suspenseState.retryLane = attemptHydrationAtLane; // TODO: Ideally this would inherit the event time of the current render + + var eventTime = NoTimestamp; + scheduleUpdateOnFiber(current, attemptHydrationAtLane, eventTime); + } + } // If we have scheduled higher pri work above, this will probably just abort the render + // since we now have higher priority work, but in case it doesn't, we need to prepare to + // render something, if we time out. Even if that requires us to delete everything and + // skip hydration. + // Delay having to do this as long as the suspense timeout allows us. + + renderDidSuspendDelayIfPossible(); + return retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, + new Error( + "This Suspense boundary received an update before it finished " + + "hydrating. This caused the boundary to switch to client rendering. " + + "The usual way to fix this is to wrap the original update " + + "in startTransition." + ) + ); + } else if (isSuspenseInstancePending()) { + // This component is still pending more data from the server, so we can't hydrate its + // content. We treat it as if this component suspended itself. It might seem as if + // we could just try to render it client-side instead. However, this will perform a + // lot of unnecessary work and is unlikely to complete since it often will suspend + // on missing data anyway. Additionally, the server might be able to render more + // than we can on the client yet. In that case we'd end up with more fallback states + // on the client than if we just leave it alone. If the server times out or errors + // these should update this boundary to the permanent Fallback state instead. + // Mark it as having captured (i.e. suspended). + workInProgress.flags |= DidCapture; // Leave the child in place. I.e. the dehydrated fragment. + + workInProgress.child = current.child; // Register a callback to retry this boundary once the server has sent the result. + + var retry = retryDehydratedSuspenseBoundary.bind(null, current); + registerSuspenseInstanceRetry(); + return null; + } else { + // This is the first attempt. + reenterHydrationStateFromDehydratedSuspenseInstance( + workInProgress, + suspenseInstance, + suspenseState.treeContext + ); + var primaryChildren = nextProps.children; + var primaryChildFragment = mountSuspensePrimaryChildren( + workInProgress, + primaryChildren + ); // Mark the children as hydrating. This is a fast path to know whether this + // tree is part of a hydrating tree. This is used to determine if a child + // node has fully mounted yet, and for scheduling event replaying. + // Conceptually this is similar to Placement in that a new subtree is + // inserted into the React tree here. It just happens to not need DOM + // mutations because it already exists. + + primaryChildFragment.flags |= Hydrating; + return primaryChildFragment; + } + } else { + // This is the second render pass. We already attempted to hydrated, but + // something either suspended or errored. + if (workInProgress.flags & ForceClientRender) { + // Something errored during hydration. Try again without hydrating. + workInProgress.flags &= ~ForceClientRender; + return retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, + new Error( + "There was an error while hydrating this Suspense boundary. " + + "Switched to client rendering." + ) + ); + } else if (workInProgress.memoizedState !== null) { + // Something suspended and we should still be in dehydrated mode. + // Leave the existing child in place. + workInProgress.child = current.child; // The dehydrated completion pass expects this flag to be there + // but the normal suspense pass doesn't. - setIsRendering(false); + workInProgress.flags |= DidCapture; + return null; + } else { + // Suspended but we should no longer be in dehydrated mode. + // Therefore we now have to render the fallback. + var nextPrimaryChildren = nextProps.children; + var nextFallbackChildren = nextProps.fallback; + var fallbackChildFragment = mountSuspenseFallbackAfterRetryWithoutHydrating( + current, + workInProgress, + nextPrimaryChildren, + nextFallbackChildren, + renderLanes + ); + var _primaryChildFragment4 = workInProgress.child; + _primaryChildFragment4.memoizedState = mountSuspenseOffscreenState( + renderLanes + ); + workInProgress.memoizedState = SUSPENDED_MARKER; + return fallbackChildFragment; + } } +} - if (current !== null && !didReceiveUpdate) { - bailoutHooks(current, workInProgress, renderLanes); - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); +function scheduleSuspenseWorkOnFiber(fiber, renderLanes, propagationRoot) { + fiber.lanes = mergeLanes(fiber.lanes, renderLanes); + var alternate = fiber.alternate; + + if (alternate !== null) { + alternate.lanes = mergeLanes(alternate.lanes, renderLanes); } - workInProgress.flags |= PerformedWork; - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; + scheduleContextWorkOnParentPath(fiber.return, renderLanes, propagationRoot); } -function updateClassComponent( - current, +function propagateSuspenseContextChange( workInProgress, - Component, - nextProps, + firstChild, 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; + // 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; - _instance.updater.enqueueSetState(_instance, state, null); + while (node !== null) { + if (node.tag === SuspenseComponent) { + var state = node.memoizedState; - break; + 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; + } - 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 + if (node === workInProgress) { + return; + } - var update = createClassErrorUpdate( - workInProgress, - createCapturedValue(error$1, workInProgress), - lane - ); - enqueueCapturedUpdate(workInProgress, update); - break; + while (node.sibling === null) { + if (node.return === null || node.return === workInProgress) { + return; } + + node = node.return; } - 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; + node.sibling.return = node.return; + node = node.sibling; + } +} - if (innerPropTypes) { - checkPropTypes( - innerPropTypes, - nextProps, // Resolved props - "prop", - getComponentNameFromType(Component) - ); - } - } - } // Push context providers early to prevent context stack mismatches. - // During mounting we don't know the child context yet as the instance doesn't exist. - // We will invalidate the child context in finishClassComponent() right after rendering. +function 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 hasContext; + while (row !== null) { + var currentRow = row.alternate; // New rows can't be content rows. - if (isContextProvider(Component)) { - hasContext = true; - pushContextProvider(workInProgress); - } else { - hasContext = false; + if (currentRow !== null && findFirstSuspended(currentRow) === null) { + lastContentRow = row; + } + + row = row.sibling; } - prepareToReadContext(workInProgress, renderLanes); - var instance = workInProgress.stateNode; - var shouldUpdate; + return lastContentRow; +} - if (instance === null) { - if (current !== null) { - // A class component without an instance only mounts if it suspended - // inside a non-concurrent tree, in an inconsistent state. We want to - // treat it like a new mount, even though an empty version of it already - // committed. Disconnect the alternate pointers. - current.alternate = null; - workInProgress.alternate = null; // Since this is conceptually a new fiber, schedule a Placement effect +function validateRevealOrder(revealOrder) { + { + if ( + revealOrder !== undefined && + revealOrder !== "forwards" && + revealOrder !== "backwards" && + revealOrder !== "together" && + !didWarnAboutRevealOrder[revealOrder] + ) { + didWarnAboutRevealOrder[revealOrder] = true; - workInProgress.flags |= Placement; - } // In the initial pass we might need to construct the instance. + 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() + ); - constructClassInstance(workInProgress, Component, nextProps); - mountClassInstance(workInProgress, Component, nextProps, renderLanes); - shouldUpdate = true; - } else if (current === null) { - // In a resume, we'll already have an instance we can reuse. - shouldUpdate = resumeMountClassInstance( - workInProgress, - Component, - nextProps, - renderLanes - ); - } else { - shouldUpdate = updateClassInstance( - current, - workInProgress, - Component, - nextProps, - renderLanes - ); - } + break; + } - var nextUnitOfWork = finishClassComponent( - current, - workInProgress, - Component, - shouldUpdate, - hasContext, - renderLanes - ); + case "forward": + case "backward": { + error( + '"%s" is not a valid value for revealOrder on . ' + + 'React uses the -s suffix in the spelling. Use "%ss" instead.', + revealOrder, + revealOrder.toLowerCase() + ); + + break; + } + + default: + error( + '"%s" is not a supported revealOrder on . ' + + 'Did you mean "together", "forwards" or "backwards"?', + revealOrder + ); + + break; + } + } else { + error( + "%s is not a supported value for revealOrder on . " + + 'Did you mean "together", "forwards" or "backwards"?', + revealOrder + ); + } + } + } +} +function validateTailOptions(tailMode, revealOrder) { { - var inst = workInProgress.stateNode; + if (tailMode !== undefined && !didWarnAboutTailOptions[tailMode]) { + if (tailMode !== "collapsed" && tailMode !== "hidden") { + didWarnAboutTailOptions[tailMode] = true; - 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" + '"%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 ); } - - didWarnAboutReassigningProps = true; } } - - return nextUnitOfWork; } -function finishClassComponent( - current, - workInProgress, - Component, - shouldUpdate, - hasContext, - renderLanes -) { - // Refs should update even if shouldComponentUpdate returns false - markRef$1(current, workInProgress); - var didCaptureError = (workInProgress.flags & DidCapture) !== NoFlags; +function validateSuspenseListNestedChild(childSlot, index) { + { + var isAnArray = isArray(childSlot); + var isIterable = + !isAnArray && typeof getIteratorFn(childSlot) === "function"; - if (!shouldUpdate && !didCaptureError) { - // Context providers should defer to sCU for rendering - if (hasContext) { - invalidateContextProvider(workInProgress, Component, false); - } + if (isAnArray || isIterable) { + var type = isAnArray ? "array" : "iterable"; - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); + error( + "A nested %s was passed to row #%s in . Wrap it in " + + "an additional SuspenseList to configure its revealOrder: " + + " ... " + + "{%s} ... " + + "", + type, + index, + type + ); + + return false; + } } - var instance = workInProgress.stateNode; // Rerender + return true; +} - ReactCurrentOwner$1.current = workInProgress; - var nextChildren; +function validateSuspenseListChildren(children, revealOrder) { + { + if ( + (revealOrder === "forwards" || revealOrder === "backwards") && + children !== undefined && + children !== null && + children !== false + ) { + if (isArray(children)) { + for (var i = 0; i < children.length; i++) { + if (!validateSuspenseListNestedChild(children[i], i)) { + return; + } + } + } else { + var iteratorFn = getIteratorFn(children); - if ( - 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 (typeof iteratorFn === "function") { + var childrenIterator = iteratorFn.call(children); - { - stopProfilerTimerIfRunning(); - } - } else { - { - setIsRendering(true); - nextChildren = instance.render(); + if (childrenIterator) { + var step = childrenIterator.next(); + var _i = 0; - setIsRendering(false); + 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 + ); + } + } } - } // React DevTools reads this flag. + } +} - workInProgress.flags |= PerformedWork; +function initSuspenseListRenderState( + workInProgress, + isBackwards, + tail, + lastContentRow, + tailMode +) { + var renderState = workInProgress.memoizedState; - 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 + if (renderState === null) { + workInProgress.memoizedState = { + isBackwards: isBackwards, + rendering: null, + renderingStartTime: 0, + last: lastContentRow, + tail: tail, + tailMode: tailMode + }; + } else { + // We can reuse the existing object from previous renders. + renderState.isBackwards = isBackwards; + renderState.rendering = null; + renderState.renderingStartTime = 0; + renderState.last = lastContentRow; + renderState.tail = tail; + renderState.tailMode = tailMode; + } +} // This can end up rendering this component multiple passes. +// The first pass splits the children fibers into two sets. A head and tail. +// We first render the head. If anything is in fallback state, we do another +// pass through beginWork to rerender all children (including the tail) with +// the force suspend context. If the first render didn't have anything in +// in fallback state. Then we render each row in the tail one-by-one. +// That happens in the completeWork phase without going back to beginWork. + +function updateSuspenseListComponent(current, workInProgress, renderLanes) { + var nextProps = workInProgress.pendingProps; + var revealOrder = nextProps.revealOrder; + var tailMode = nextProps.tail; + var newChildren = nextProps.children; + validateRevealOrder(revealOrder); + validateTailOptions(tailMode, revealOrder); + validateSuspenseListChildren(newChildren, revealOrder); + reconcileChildren(current, workInProgress, newChildren, renderLanes); + var suspenseContext = suspenseStackCursor.current; + var shouldForceFallback = hasSuspenseContext( + suspenseContext, + ForceSuspenseFallback + ); + + if (shouldForceFallback) { + suspenseContext = setShallowSuspenseContext( + suspenseContext, + ForceSuspenseFallback ); + workInProgress.flags |= DidCapture; } else { - 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. + var didSuspendBefore = + current !== null && (current.flags & DidCapture) !== NoFlags; - workInProgress.memoizedState = instance.state; // The context might have changed so we need to recalculate it. + if (didSuspendBefore) { + // If we previously forced a fallback, we need to schedule work + // on any nested boundaries to let them know to try to render + // again. This is the same as context updating. + propagateSuspenseContextChange( + workInProgress, + workInProgress.child, + renderLanes + ); + } - if (hasContext) { - invalidateContextProvider(workInProgress, Component, true); + suspenseContext = setDefaultShallowSuspenseContext(suspenseContext); } - return workInProgress.child; -} + pushSuspenseContext(workInProgress, suspenseContext); -function pushHostRootContext(workInProgress) { - var root = workInProgress.stateNode; + if ((workInProgress.mode & ConcurrentMode) === NoMode) { + // In legacy mode, SuspenseList doesn't work so we just + // use make it a noop by treating it as the default revealOrder. + workInProgress.memoizedState = null; + } else { + switch (revealOrder) { + case "forwards": { + var lastContentRow = findLastContentRow(workInProgress.child); + var tail; - if (root.pendingContext) { - pushTopLevelContextObject( - workInProgress, - root.pendingContext, - root.pendingContext !== root.context - ); - } else if (root.context) { - // Should always be set - pushTopLevelContextObject(workInProgress, root.context, false); - } + 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; + } - pushHostContainer(workInProgress, root.containerInfo); -} + initSuspenseListRenderState( + workInProgress, + false, // isBackwards + tail, + lastContentRow, + tailMode + ); + break; + } -function updateHostRoot(current, workInProgress, renderLanes) { - pushHostRootContext(workInProgress); + case "backwards": { + // We're going to find the first row that has existing content. + // At the same time we're going to reverse the list of everything + // we pass in the meantime. That's going to be our tail in reverse + // order. + var _tail = null; + var row = workInProgress.child; + workInProgress.child = null; - if (current === null) { - throw new Error("Should have a current fiber. This is a bug in React."); - } + while (row !== null) { + var currentRow = row.alternate; // New rows can't be content rows. + + if (currentRow !== null && findFirstSuspended(currentRow) === null) { + // This is the beginning of the main content. + workInProgress.child = row; + break; + } + + var nextRow = row.sibling; + row.sibling = _tail; + _tail = row; + row = nextRow; + } // TODO: If workInProgress.child is null, we can continue on the tail immediately. - var nextProps = workInProgress.pendingProps; - var prevState = workInProgress.memoizedState; - var prevChildren = prevState.element; - cloneUpdateQueue(current, workInProgress); - processUpdateQueue(workInProgress, nextProps, null, renderLanes); - var nextState = workInProgress.memoizedState; - var root = workInProgress.stateNode; - // being called "element". + initSuspenseListRenderState( + workInProgress, + true, // isBackwards + _tail, + null, // last + tailMode + ); + break; + } - var nextChildren = nextState.element; + case "together": { + initSuspenseListRenderState( + workInProgress, + false, // isBackwards + null, // tail + null, // last + undefined + ); + break; + } - { - if (nextChildren === prevChildren) { - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); + default: { + // The default reveal order is the same as not having + // a boundary. + workInProgress.memoizedState = null; + } } - - reconcileChildren(current, workInProgress, nextChildren, renderLanes); } return workInProgress.child; } -function updateHostComponent$1(current, workInProgress, renderLanes) { - pushHostContext(workInProgress); - - var type = workInProgress.type; - var nextProps = workInProgress.pendingProps; - var prevProps = current !== null ? current.memoizedProps : null; - var nextChildren = nextProps.children; +function updatePortalComponent(current, workInProgress, renderLanes) { + pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); + var nextChildren = workInProgress.pendingProps; - 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; + 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); } - markRef$1(current, workInProgress); - reconcileChildren(current, workInProgress, nextChildren, renderLanes); return workInProgress.child; } -function updateHostText$1(current, workInProgress) { - // immediately after. - - return null; -} - -function mountLazyComponent( - _current, - workInProgress, - elementType, - renderLanes -) { - if (_current !== null) { - // A lazy component only mounts if it suspended inside a non- - // concurrent tree, in an inconsistent state. We want to treat it like - // a new mount, even though an empty version of it already committed. - // Disconnect the alternate pointers. - _current.alternate = null; - workInProgress.alternate = null; // Since this is conceptually a new fiber, schedule a Placement effect - - workInProgress.flags |= Placement; - } +var hasWarnedAboutUsingNoValuePropOnContextProvider = false; - 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. +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; - workInProgress.type = Component; - var resolvedTag = (workInProgress.tag = resolveLazyComponentTag(Component)); - var resolvedProps = resolveDefaultProps(Component, props); - var child; + { + if (!("value" in newProps)) { + if (!hasWarnedAboutUsingNoValuePropOnContextProvider) { + hasWarnedAboutUsingNoValuePropOnContextProvider = true; - switch (resolvedTag) { - case FunctionComponent: { - { - validateFunctionComponentInDev(workInProgress, Component); - workInProgress.type = Component = resolveFunctionForHotReloading( - Component + error( + "The `value` prop is required for the ``. Did you misspell it or forget to pass it?" ); } - - child = updateFunctionComponent( - null, - workInProgress, - Component, - resolvedProps, - renderLanes - ); - return child; } - case ClassComponent: { - { - workInProgress.type = Component = resolveClassForHotReloading( - Component - ); - } + var providerPropTypes = workInProgress.type.propTypes; - child = updateClassComponent( - null, - workInProgress, - Component, - resolvedProps, - renderLanes - ); - return child; + if (providerPropTypes) { + checkPropTypes(providerPropTypes, newProps, "prop", "Context.Provider"); } + } - case ForwardRef: { - { - workInProgress.type = Component = resolveForwardRefForHotReloading( - Component - ); - } - - child = updateForwardRef( - null, - workInProgress, - Component, - resolvedProps, - renderLanes - ); - return child; - } + pushProvider(workInProgress, context, newValue); - case MemoComponent: { - { - if (workInProgress.type !== workInProgress.elementType) { - var outerPropTypes = Component.propTypes; + { + if (oldProps !== null) { + var oldValue = oldProps.value; - if (outerPropTypes) { - checkPropTypes( - outerPropTypes, - resolvedProps, // Resolved for outer only - "prop", - getComponentNameFromType(Component) - ); - } + if (objectIs(oldValue, newValue)) { + // No change. Bailout early if children are the same. + if (oldProps.children === newProps.children && !hasContextChanged()) { + return bailoutOnAlreadyFinishedWork( + current, + workInProgress, + renderLanes + ); } + } else { + // The context value changed. Search for matching consumers and schedule + // them to update. + propagateContextChange(workInProgress, context, renderLanes); } - - child = updateMemoComponent( - null, - workInProgress, - Component, - resolveDefaultProps(Component.type, resolvedProps), // The inner type can have defaults too - renderLanes - ); - return child; } } - var hint = ""; - - { - if ( - Component !== null && - typeof Component === "object" && - Component.$$typeof === REACT_LAZY_TYPE - ) { - hint = " Did you wrap a component in React.lazy() more than once?"; - } - } // This message intentionally doesn't mention ForwardRef or MemoComponent - // because the fact that it's a separate type of work is an - // implementation detail. - - throw new Error( - "Element type is invalid. Received a promise that resolves to: " + - Component + - ". " + - ("Lazy element type must resolve to a class or function." + hint) - ); + var newChildren = newProps.children; + reconcileChildren(current, workInProgress, newChildren, renderLanes); + return workInProgress.child; } -function mountIncompleteClassComponent( - _current, - workInProgress, - Component, - nextProps, - renderLanes -) { - if (_current !== null) { - // An incomplete component only mounts if it suspended inside a non- - // concurrent tree, in an inconsistent state. We want to treat it like - // a new mount, even though an empty version of it already committed. - // Disconnect the alternate pointers. - _current.alternate = null; - workInProgress.alternate = null; // Since this is conceptually a new fiber, schedule a Placement effect - - workInProgress.flags |= Placement; - } // Promote the fiber to a class and try rendering again. - - workInProgress.tag = ClassComponent; // The rest of this function is a fork of `updateClassComponent` - // Push context providers early to prevent context stack mismatches. - // During mounting we don't know the child context yet as the instance doesn't exist. - // We will invalidate the child context in finishClassComponent() right after rendering. - - var hasContext; - - if (isContextProvider(Component)) { - hasContext = true; - pushContextProvider(workInProgress); - } else { - hasContext = false; - } +var hasWarnedAboutUsingContextAsConsumer = false; - prepareToReadContext(workInProgress, renderLanes); - constructClassInstance(workInProgress, Component, nextProps); - mountClassInstance(workInProgress, Component, nextProps, renderLanes); - return finishClassComponent( - null, - workInProgress, - Component, - true, - hasContext, - 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. -function mountIndeterminateComponent( - _current, - workInProgress, - Component, - renderLanes -) { - if (_current !== null) { - // An indeterminate component only mounts if it suspended inside a non- - // concurrent tree, in an inconsistent state. We want to treat it like - // a new mount, even though an empty version of it already committed. - // Disconnect the alternate pointers. - _current.alternate = null; - workInProgress.alternate = null; // Since this is conceptually a new fiber, schedule a Placement effect + { + if (context._context === undefined) { + // This may be because it's a Context (rather than a Consumer). + // Or it may be because it's older React where they're the same thing. + // We only want to warn if we're sure it's a new React. + if (context !== context.Consumer) { + if (!hasWarnedAboutUsingContextAsConsumer) { + hasWarnedAboutUsingContextAsConsumer = true; - workInProgress.flags |= Placement; + 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 props = workInProgress.pendingProps; - var context; + var newProps = workInProgress.pendingProps; + var render = newProps.children; { - var unmaskedContext = getUnmaskedContext(workInProgress, Component, false); - context = getMaskedContext(workInProgress, unmaskedContext); + if (typeof render !== "function") { + error( + "A context consumer was rendered with multiple children, or a child " + + "that isn't a function. A context consumer expects a single child " + + "that is a function. If you did pass a function, make sure there " + + "is no trailing or leading whitespace around it." + ); + } } prepareToReadContext(workInProgress, renderLanes); - var value; - - { - if ( - Component.prototype && - typeof Component.prototype.render === "function" - ) { - var componentName = getComponentNameFromType(Component) || "Unknown"; - - if (!didWarnAboutBadClass[componentName]) { - error( - "The <%s /> component appears to have a render method, but doesn't extend React.Component. " + - "This is likely to cause errors. Change %s to extend React.Component instead.", - componentName, - componentName - ); - - didWarnAboutBadClass[componentName] = true; - } - } + var newValue = readContext(context); - if (workInProgress.mode & StrictLegacyMode) { - ReactStrictModeWarnings.recordLegacyContextWarning(workInProgress, null); - } + var newChildren; - setIsRendering(true); + { ReactCurrentOwner$1.current = workInProgress; - value = renderWithHooks( - null, - workInProgress, - Component, - props, - context, - renderLanes - ); + setIsRendering(true); + newChildren = render(newValue); setIsRendering(false); } workInProgress.flags |= PerformedWork; + reconcileChildren(current, workInProgress, newChildren, renderLanes); + return workInProgress.child; +} - { - // 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 markWorkInProgressReceivedUpdate() { + didReceiveUpdate = true; +} - 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 - ); +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 - didWarnAboutModulePatternComponent[_componentName] = true; - } + workInProgress.flags |= Placement; } } +} - 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 - ) { +function bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) { + if (current !== null) { + // Reuse previous dependencies + workInProgress.dependencies = current.dependencies; + } + + { + // Don't update "base" render times for bailouts. + stopProfilerTimerIfRunning(); + } + + markSkippedUpdateLanes(workInProgress.lanes); // Check if the children have any pending work. + + if (!includesSomeLane(renderLanes, workInProgress.childLanes)) { + // The children don't have any work either. We can skip them. + // TODO: Once we add back resuming, we should check if the children are + // a work-in-progress set. If so, we need to transfer their effects. { - var _componentName2 = getComponentNameFromType(Component) || "Unknown"; + return null; + } + } // This fiber doesn't have work, but its subtree does. Clone the child + // fibers and continue. - 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 - ); + cloneChildFibers(current, workInProgress); + return workInProgress.child; +} - didWarnAboutModulePatternComponent[_componentName2] = true; +function remountFiber(current, oldWorkInProgress, newWorkInProgress) { + { + var returnFiber = oldWorkInProgress.return; + + if (returnFiber === null) { + // eslint-disable-next-line react-internal/prod-error-codes + throw new Error("Cannot swap the root fiber."); + } // Disconnect from the old current. + // It will get deleted. + + current.alternate = null; + oldWorkInProgress.alternate = null; // Connect to the new tree. + + newWorkInProgress.index = oldWorkInProgress.index; + newWorkInProgress.sibling = oldWorkInProgress.sibling; + newWorkInProgress.return = oldWorkInProgress.return; + newWorkInProgress.ref = oldWorkInProgress.ref; // Replace the child/sibling pointers above it. + + if (oldWorkInProgress === returnFiber.child) { + returnFiber.child = newWorkInProgress; + } else { + var prevSibling = returnFiber.child; + + if (prevSibling === null) { + // eslint-disable-next-line react-internal/prod-error-codes + throw new Error("Expected parent to have a child."); } - } // Proceed under the assumption that this is a class instance - workInProgress.tag = ClassComponent; // Throw out any hooks that were used. + while (prevSibling.sibling !== oldWorkInProgress) { + prevSibling = prevSibling.sibling; - 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. + if (prevSibling === null) { + // eslint-disable-next-line react-internal/prod-error-codes + throw new Error("Expected to find the previous sibling."); + } + } - var hasContext = false; + 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 (isContextProvider(Component)) { - hasContext = true; - pushContextProvider(workInProgress); + var deletions = returnFiber.deletions; + + if (deletions === null) { + returnFiber.deletions = [current]; + returnFiber.flags |= ChildDeletion; } else { - hasContext = false; + deletions.push(current); } - 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; + newWorkInProgress.flags |= Placement; // Restart work from the new fiber. + + return newWorkInProgress; + } +} + +function checkScheduledUpdateOrContext(current, renderLanes) { + // Before performing an early bailout, we must check if there are pending + // updates or context. + var updateLanes = current.lanes; + + if (includesSomeLane(updateLanes, renderLanes)) { + return true; + } // No pending update, but because context is propagated lazily, we need + + return false; +} + +function attemptEarlyBailoutIfNoScheduledUpdate( + current, + workInProgress, + renderLanes +) { + // This fiber does not have any pending work. Bailout without entering + // the begin phase. There's still some bookkeeping we that needs to be done + // in this optimized path, mostly pushing stuff onto the stack. + switch (workInProgress.tag) { + case HostRoot: + pushHostRootContext(workInProgress); + var root = workInProgress.stateNode; + break; - reconcileChildren(null, workInProgress, value, renderLanes); + case HostComponent: + pushHostContext(workInProgress); + break; - { - validateFunctionComponentInDev(workInProgress, Component); + case ClassComponent: { + var Component = workInProgress.type; + + if (isContextProvider(Component)) { + pushContextProvider(workInProgress); + } + + break; } - return workInProgress.child; - } -} + case HostPortal: + pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); + break; -function validateFunctionComponentInDev(workInProgress, Component) { - { - if (Component) { - if (Component.childContextTypes) { - error( - "%s(...): childContextTypes cannot be defined on a function component.", - Component.displayName || Component.name || "Component" - ); - } + case ContextProvider: { + var newValue = workInProgress.memoizedProps.value; + var context = workInProgress.type._context; + pushProvider(workInProgress, context, newValue); + break; } - if (workInProgress.ref !== null) { - var info = ""; - var ownerName = getCurrentFiberOwnerNameInDevOrNull(); + case Profiler: + { + // Profiler should only call onRender when one of its descendants actually rendered. + var hasChildWork = includesSomeLane( + renderLanes, + workInProgress.childLanes + ); - if (ownerName) { - info += "\n\nCheck the render method of `" + ownerName + "`."; + if (hasChildWork) { + workInProgress.flags |= Update; + } + + { + // Reset effect durations for the next eventual effect phase. + // These are reset during render to allow the DevTools commit hook a chance to read them, + var stateNode = workInProgress.stateNode; + stateNode.effectDuration = 0; + stateNode.passiveEffectDuration = 0; + } } - var warningKey = ownerName || ""; - var debugSource = workInProgress._debugSource; + break; - if (debugSource) { - warningKey = debugSource.fileName + ":" + debugSource.lineNumber; - } + case SuspenseComponent: { + var state = workInProgress.memoizedState; - if (!didWarnAboutFunctionRefs[warningKey]) { - didWarnAboutFunctionRefs[warningKey] = true; + if (state !== null) { + if (state.dehydrated !== null) { + pushSuspenseContext( + workInProgress, + setDefaultShallowSuspenseContext(suspenseStackCursor.current) + ); // We know that this component will suspend again because if it has + // been unsuspended it has committed as a resolved Suspense component. + // If it needs to be retried, it should have work scheduled on it. - error( - "Function components cannot be given refs. " + - "Attempts to access this ref will fail. " + - "Did you mean to use React.forwardRef()?%s", - info - ); - } - } + workInProgress.flags |= DidCapture; // We should never render the children of a dehydrated boundary until we + // upgrade it. We return null instead of bailoutOnAlreadyFinishedWork. - if (typeof Component.getDerivedStateFromProps === "function") { - var _componentName3 = getComponentNameFromType(Component) || "Unknown"; + return null; + } // If this boundary is currently timed out, we need to decide + // whether to retry the primary children, or to skip over it and + // go straight to the fallback. Check the priority of the primary + // child fragment. - if (!didWarnAboutGetDerivedStateOnFunctionComponent[_componentName3]) { - error( - "%s: Function components do not support getDerivedStateFromProps.", - _componentName3 - ); + var primaryChildFragment = workInProgress.child; + var primaryChildLanes = primaryChildFragment.childLanes; - didWarnAboutGetDerivedStateOnFunctionComponent[_componentName3] = true; - } - } + if (includesSomeLane(renderLanes, primaryChildLanes)) { + // The primary children have pending work. Use the normal path + // to attempt to render the primary children again. + return updateSuspenseComponent(current, workInProgress, renderLanes); + } else { + // The primary child fragment does not have pending work marked + // on it + pushSuspenseContext( + workInProgress, + setDefaultShallowSuspenseContext(suspenseStackCursor.current) + ); // The primary children do not have pending work with sufficient + // priority. Bailout. - if ( - typeof Component.contextType === "object" && - Component.contextType !== null - ) { - var _componentName4 = getComponentNameFromType(Component) || "Unknown"; + var child = bailoutOnAlreadyFinishedWork( + current, + workInProgress, + renderLanes + ); - if (!didWarnAboutContextTypeOnFunctionComponent[_componentName4]) { - error( - "%s: Function components do not support contextType.", - _componentName4 + if (child !== null) { + // The fallback children have pending work. Skip over the + // primary children and work on the fallback. + return child.sibling; + } else { + // Note: We can return `null` here because we already checked + // whether there were nested context consumers, via the call to + // `bailoutOnAlreadyFinishedWork` above. + return null; + } + } + } else { + pushSuspenseContext( + workInProgress, + setDefaultShallowSuspenseContext(suspenseStackCursor.current) ); - - didWarnAboutContextTypeOnFunctionComponent[_componentName4] = true; } - } - } -} - -var SUSPENDED_MARKER = { - dehydrated: null, - treeContext: null, - retryLane: NoLane -}; -function mountSuspenseOffscreenState(renderLanes) { - return { - baseLanes: renderLanes, - cachePool: getSuspendedCache() - }; -} + break; + } -function updateSuspenseOffscreenState(prevOffscreenState, renderLanes) { - var cachePool = null; + case SuspenseListComponent: { + var didSuspendBefore = (current.flags & DidCapture) !== NoFlags; - return { - baseLanes: mergeLanes(prevOffscreenState.baseLanes, renderLanes), - cachePool: cachePool - }; -} // TODO: Probably should inline this back + var _hasChildWork = includesSomeLane( + renderLanes, + workInProgress.childLanes + ); -function shouldRemainOnFallback( - suspenseContext, - current, - workInProgress, - renderLanes -) { - // If we're already showing a fallback, there are cases where we need to - // remain on that fallback regardless of whether the content has resolved. - // For example, SuspenseList coordinates when nested content appears. - if (current !== null) { - var suspenseState = current.memoizedState; + if (didSuspendBefore) { + if (_hasChildWork) { + // If something was in fallback state last time, and we have all the + // same children then we're still in progressive loading state. + // Something might get unblocked by state updates or retries in the + // tree which will affect the tail. So we need to use the normal + // path to compute the correct tail. + return updateSuspenseListComponent( + current, + workInProgress, + renderLanes + ); + } // If none of the children had any work, that means that none of + // them got retried so they'll still be blocked in the same way + // as before. We can fast bail out. - if (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. + workInProgress.flags |= DidCapture; + } // If nothing suspended before and we're rendering the same children, + // then the tail doesn't matter. Anything new that suspends will work + // in the "together" mode, so we can continue from the state we had. - return hasSuspenseContext(suspenseContext, ForceSuspenseFallback); -} + var renderState = workInProgress.memoizedState; -function getRemainingWorkInPrimaryTree(current, renderLanes) { - // TODO: Should not remove render lanes that were pinged during this render - return removeLanes(current.childLanes, renderLanes); -} + 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; + } -function updateSuspenseComponent(current, workInProgress, renderLanes) { - var nextProps = workInProgress.pendingProps; // This is used by DevTools to force a boundary to suspend. + pushSuspenseContext(workInProgress, suspenseStackCursor.current); - { - if (shouldSuspend(workInProgress)) { - workInProgress.flags |= DidCapture; + 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; + } } - } - - var suspenseContext = suspenseStackCursor.current; - var showFallback = false; - var didSuspend = (workInProgress.flags & DidCapture) !== NoFlags; - if (didSuspend || shouldRemainOnFallback(suspenseContext, current)) { - // Something in this boundary's subtree already suspended. Switch to - // rendering the fallback children. - showFallback = true; - workInProgress.flags &= ~DidCapture; - } else { - // Attempting the main content - if (current === null || current.memoizedState !== null) { - // This is a new mount or this boundary is already showing a fallback state. - // Mark this subtree context as having at least one invisible parent that could - // handle the fallback state. - // Avoided boundaries are not considered since they cannot handle preferred fallback states. - { - suspenseContext = addSubtreeSuspenseContext( - suspenseContext, - InvisibleParentSuspenseContext - ); - } + 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); } } - suspenseContext = setDefaultShallowSuspenseContext(suspenseContext); - pushSuspenseContext(workInProgress, suspenseContext); // OK, the next part is confusing. We're about to reconcile the Suspense - // boundary's children. This involves some custom reconciliation logic. Two - // main reasons this is so complicated. - // - // First, Legacy Mode has different semantics for backwards compatibility. The - // primary tree will commit in an inconsistent state, so when we do the - // second pass to render the fallback, we do some exceedingly, uh, clever - // hacks to make that not totally break. Like transferring effects and - // deletions from hidden tree. In Concurrent Mode, it's much simpler, - // because we bailout on the primary tree completely and leave it in its old - // state, no effects. Same as what we do for Offscreen (except that - // Offscreen doesn't have the first render pass). - // - // Second is hydration. During hydration, the Suspense fiber has a slightly - // different layout, where the child points to a dehydrated fragment, which - // contains the DOM rendered by the server. - // - // Third, even if you set all that aside, Suspense is like error boundaries in - // that we first we try to render one tree, and if that fails, we render again - // and switch to a different tree. Like a try/catch block. So we have to track - // which branch we're currently rendering. Ideally we would model this using - // a stack. - - if (current === null) { - var nextPrimaryChildren = nextProps.children; - var nextFallbackChildren = nextProps.fallback; + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); +} - if (showFallback) { - var fallbackFragment = mountSuspenseFallbackChildren( +function beginWork(current, workInProgress, renderLanes) { + { + if (workInProgress._debugNeedsRemount && current !== null) { + // This will restart the begin phase with a new fiber. + return remountFiber( + current, workInProgress, - nextPrimaryChildren, - nextFallbackChildren, - renderLanes - ); - var primaryChildFragment = workInProgress.child; - primaryChildFragment.memoizedState = mountSuspenseOffscreenState( - renderLanes + createFiberFromTypeAndProps( + workInProgress.type, + workInProgress.key, + workInProgress.pendingProps, + workInProgress._debugOwner || null, + workInProgress.mode, + workInProgress.lanes + ) ); - workInProgress.memoizedState = SUSPENDED_MARKER; - return fallbackFragment; - } else { - return mountSuspensePrimaryChildren(workInProgress, nextPrimaryChildren); } - } else { - // This is an update. - // If the current fiber has a SuspenseState, that means it's already showing - // a fallback. - var prevState = current.memoizedState; - - if (prevState !== null) { - if (showFallback) { - var _nextFallbackChildren2 = nextProps.fallback; - var _nextPrimaryChildren2 = nextProps.children; - - var _fallbackChildFragment = updateSuspenseFallbackChildren( - current, - workInProgress, - _nextPrimaryChildren2, - _nextFallbackChildren2, - renderLanes - ); - - var _primaryChildFragment3 = workInProgress.child; - var prevOffscreenState = current.child.memoizedState; - _primaryChildFragment3.memoizedState = - prevOffscreenState === null - ? mountSuspenseOffscreenState(renderLanes) - : updateSuspenseOffscreenState(prevOffscreenState, renderLanes); - _primaryChildFragment3.childLanes = getRemainingWorkInPrimaryTree( - current, - renderLanes - ); - workInProgress.memoizedState = SUSPENDED_MARKER; - return _fallbackChildFragment; - } else { - var _nextPrimaryChildren3 = nextProps.children; + } - var _primaryChildFragment4 = updateSuspensePrimaryChildren( - current, - workInProgress, - _nextPrimaryChildren3, - renderLanes - ); + if (current !== null) { + var oldProps = current.memoizedProps; + var newProps = workInProgress.pendingProps; - workInProgress.memoizedState = null; - return _primaryChildFragment4; - } + 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 { - // The current tree is not already showing a fallback. - if (showFallback) { - // Timed out. - var _nextFallbackChildren3 = nextProps.fallback; - var _nextPrimaryChildren4 = nextProps.children; + // Neither props nor legacy context changes. Check if there's a pending + // update or context change. + var hasScheduledUpdateOrContext = checkScheduledUpdateOrContext( + current, + renderLanes + ); - var _fallbackChildFragment2 = updateSuspenseFallbackChildren( + if ( + !hasScheduledUpdateOrContext && // If this is the second pass of an error or suspense boundary, there + // may not be work scheduled on `current`, so we check for this flag. + (workInProgress.flags & DidCapture) === NoFlags + ) { + // No pending updates or context. Bail out now. + didReceiveUpdate = false; + return attemptEarlyBailoutIfNoScheduledUpdate( current, workInProgress, - _nextPrimaryChildren4, - _nextFallbackChildren3, renderLanes ); + } - var _primaryChildFragment5 = workInProgress.child; - var _prevOffscreenState = current.child.memoizedState; - _primaryChildFragment5.memoizedState = - _prevOffscreenState === null - ? mountSuspenseOffscreenState(renderLanes) - : updateSuspenseOffscreenState(_prevOffscreenState, renderLanes); - _primaryChildFragment5.childLanes = getRemainingWorkInPrimaryTree( - current, - renderLanes - ); // Skip the primary children, and continue working on the - // fallback children. - - workInProgress.memoizedState = SUSPENDED_MARKER; - return _fallbackChildFragment2; + if ((current.flags & ForceUpdateForLegacySuspense) !== NoFlags) { + // This is a special case that only exists for legacy mode. + // See https://github.com/facebook/react/pull/19216. + didReceiveUpdate = true; } else { - // Still haven't timed out. Continue rendering the children, like we - // normally do. - var _nextPrimaryChildren5 = nextProps.children; - - var _primaryChildFragment6 = updateSuspensePrimaryChildren( - current, - workInProgress, - _nextPrimaryChildren5, - renderLanes - ); - - workInProgress.memoizedState = null; - return _primaryChildFragment6; + // 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 mountSuspensePrimaryChildren( - workInProgress, - primaryChildren, - renderLanes -) { - var mode = workInProgress.mode; - var primaryChildProps = { - mode: "visible", - children: primaryChildren - }; - var primaryChildFragment = mountWorkInProgressOffscreenFiber( - primaryChildProps, - mode - ); - primaryChildFragment.return = workInProgress; - workInProgress.child = primaryChildFragment; - return primaryChildFragment; -} - -function mountSuspenseFallbackChildren( - workInProgress, - primaryChildren, - fallbackChildren, - renderLanes -) { - var mode = workInProgress.mode; - var progressedPrimaryFragment = workInProgress.child; - var primaryChildProps = { - mode: "hidden", - children: primaryChildren - }; - var primaryChildFragment; - var fallbackChildFragment; - - if ( - (mode & ConcurrentMode) === NoMode && - progressedPrimaryFragment !== null - ) { - // In legacy mode, we commit the primary tree as if it successfully - // completed, even though it's in an inconsistent state. - primaryChildFragment = progressedPrimaryFragment; - primaryChildFragment.childLanes = NoLanes; - primaryChildFragment.pendingProps = primaryChildProps; - - if (workInProgress.mode & ProfileMode) { - // Reset the durations from the first pass so they aren't included in the - // final amounts. This seems counterintuitive, since we're intentionally - // not measuring part of the render phase, but this makes it match what we - // do in Concurrent Mode. - primaryChildFragment.actualDuration = 0; - primaryChildFragment.actualStartTime = -1; - primaryChildFragment.selfBaseDuration = 0; - primaryChildFragment.treeBaseDuration = 0; - } - - fallbackChildFragment = createFiberFromFragment( - fallbackChildren, - mode, - renderLanes, - null - ); } else { - primaryChildFragment = mountWorkInProgressOffscreenFiber( - primaryChildProps, - mode - ); - fallbackChildFragment = createFiberFromFragment( - fallbackChildren, - mode, - renderLanes, - null - ); - } - - primaryChildFragment.return = workInProgress; - fallbackChildFragment.return = workInProgress; - primaryChildFragment.sibling = fallbackChildFragment; - workInProgress.child = primaryChildFragment; - return fallbackChildFragment; -} + 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 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); -} + workInProgress.lanes = NoLanes; -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); -} + switch (workInProgress.tag) { + case IndeterminateComponent: { + return mountIndeterminateComponent( + current, + workInProgress, + workInProgress.type, + renderLanes + ); + } -function updateSuspensePrimaryChildren( - current, - workInProgress, - primaryChildren, - renderLanes -) { - var currentPrimaryChildFragment = current.child; - var currentFallbackChildFragment = currentPrimaryChildFragment.sibling; - var primaryChildFragment = updateWorkInProgressOffscreenFiber( - currentPrimaryChildFragment, - { - mode: "visible", - children: primaryChildren + case LazyComponent: { + var elementType = workInProgress.elementType; + return mountLazyComponent( + current, + workInProgress, + elementType, + renderLanes + ); } - ); - if ((workInProgress.mode & ConcurrentMode) === NoMode) { - primaryChildFragment.lanes = renderLanes; - } + 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 + ); + } - primaryChildFragment.return = workInProgress; - primaryChildFragment.sibling = null; + case ClassComponent: { + var _Component = workInProgress.type; + var _unresolvedProps = workInProgress.pendingProps; - if (currentFallbackChildFragment !== null) { - // Delete the fallback child fragment - var deletions = workInProgress.deletions; + var _resolvedProps = + workInProgress.elementType === _Component + ? _unresolvedProps + : resolveDefaultProps(_Component, _unresolvedProps); - if (deletions === null) { - workInProgress.deletions = [currentFallbackChildFragment]; - workInProgress.flags |= ChildDeletion; - } else { - deletions.push(currentFallbackChildFragment); + return updateClassComponent( + current, + workInProgress, + _Component, + _resolvedProps, + renderLanes + ); } - } - workInProgress.child = primaryChildFragment; - return primaryChildFragment; -} + case HostRoot: + return updateHostRoot(current, workInProgress, renderLanes); -function updateSuspenseFallbackChildren( - current, - workInProgress, - primaryChildren, - fallbackChildren, - renderLanes -) { - var mode = workInProgress.mode; - var currentPrimaryChildFragment = current.child; - var currentFallbackChildFragment = currentPrimaryChildFragment.sibling; - var primaryChildProps = { - mode: "hidden", - children: primaryChildren - }; - var primaryChildFragment; + case HostComponent: + return updateHostComponent(current, workInProgress, renderLanes); - 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; + case HostText: + return updateHostText(); - 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; - } - // However, since we're going to remain on the fallback, we no longer want - // to delete it. + case SuspenseComponent: + return updateSuspenseComponent(current, workInProgress, renderLanes); - workInProgress.deletions = null; - } else { - primaryChildFragment = updateWorkInProgressOffscreenFiber( - currentPrimaryChildFragment, - primaryChildProps - ); - // (We don't do this in legacy mode, because in legacy mode we don't re-use - // the current tree; see previous branch.) + case HostPortal: + return updatePortalComponent(current, workInProgress, renderLanes); - primaryChildFragment.subtreeFlags = - currentPrimaryChildFragment.subtreeFlags & StaticMask; - } + case ForwardRef: { + var type = workInProgress.type; + var _unresolvedProps2 = workInProgress.pendingProps; - var fallbackChildFragment; + var _resolvedProps2 = + workInProgress.elementType === type + ? _unresolvedProps2 + : resolveDefaultProps(type, _unresolvedProps2); - 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. + return updateForwardRef( + current, + workInProgress, + type, + _resolvedProps2, + renderLanes + ); + } - fallbackChildFragment.flags |= Placement; - } + case Fragment: + return updateFragment(current, workInProgress, renderLanes); - fallbackChildFragment.return = workInProgress; - primaryChildFragment.return = workInProgress; - primaryChildFragment.sibling = fallbackChildFragment; - workInProgress.child = primaryChildFragment; - return fallbackChildFragment; -} + case Mode: + return updateMode(current, workInProgress, renderLanes); -function scheduleSuspenseWorkOnFiber(fiber, renderLanes, propagationRoot) { - fiber.lanes = mergeLanes(fiber.lanes, renderLanes); - var alternate = fiber.alternate; + case Profiler: + return updateProfiler(current, workInProgress, renderLanes); - if (alternate !== null) { - alternate.lanes = mergeLanes(alternate.lanes, renderLanes); - } + case ContextProvider: + return updateContextProvider(current, workInProgress, renderLanes); - scheduleContextWorkOnParentPath(fiber.return, renderLanes, propagationRoot); -} + case ContextConsumer: + return updateContextConsumer(current, workInProgress, renderLanes); -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; + case MemoComponent: { + var _type2 = workInProgress.type; + var _unresolvedProps3 = workInProgress.pendingProps; // Resolve outer props first, then resolve inner props. - while (node !== null) { - if (node.tag === SuspenseComponent) { - var state = node.memoizedState; + var _resolvedProps3 = resolveDefaultProps(_type2, _unresolvedProps3); - if (state !== null) { - scheduleSuspenseWorkOnFiber(node, renderLanes, workInProgress); + { + if (workInProgress.type !== workInProgress.elementType) { + var outerPropTypes = _type2.propTypes; + + if (outerPropTypes) { + checkPropTypes( + outerPropTypes, + _resolvedProps3, // Resolved for outer only + "prop", + getComponentNameFromType(_type2) + ); + } + } } - } else if (node.tag === SuspenseListComponent) { - // If the tail is hidden there might not be an Suspense boundaries - // to schedule work on. In this case we have to schedule it on the - // list itself. - // We don't have to traverse to the children of the list since - // the list will propagate the change when it rerenders. - scheduleSuspenseWorkOnFiber(node, renderLanes, workInProgress); - } else if (node.child !== null) { - node.child.return = node; - node = node.child; - continue; - } - if (node === workInProgress) { - return; + _resolvedProps3 = resolveDefaultProps(_type2.type, _resolvedProps3); + return updateMemoComponent( + current, + workInProgress, + _type2, + _resolvedProps3, + renderLanes + ); } - while (node.sibling === null) { - if (node.return === null || node.return === workInProgress) { - return; - } - - node = node.return; + case SimpleMemoComponent: { + return updateSimpleMemoComponent( + current, + workInProgress, + workInProgress.type, + workInProgress.pendingProps, + renderLanes + ); } - node.sibling.return = node.return; - node = node.sibling; - } -} + case IncompleteClassComponent: { + var _Component2 = workInProgress.type; + var _unresolvedProps4 = workInProgress.pendingProps; -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 _resolvedProps4 = + workInProgress.elementType === _Component2 + ? _unresolvedProps4 + : resolveDefaultProps(_Component2, _unresolvedProps4); - while (row !== null) { - var currentRow = row.alternate; // New rows can't be content rows. + return mountIncompleteClassComponent( + current, + workInProgress, + _Component2, + _resolvedProps4, + renderLanes + ); + } - if (currentRow !== null && findFirstSuspended(currentRow) === null) { - lastContentRow = row; + case SuspenseListComponent: { + return updateSuspenseListComponent(current, workInProgress, renderLanes); } - row = row.sibling; + case ScopeComponent: { + break; + } + + case OffscreenComponent: { + return updateOffscreenComponent(current, workInProgress, renderLanes); + } } - return lastContentRow; + 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 validateRevealOrder(revealOrder) { - { - if ( - revealOrder !== undefined && - revealOrder !== "forwards" && - revealOrder !== "backwards" && - revealOrder !== "together" && - !didWarnAboutRevealOrder[revealOrder] - ) { - didWarnAboutRevealOrder[revealOrder] = true; +function markUpdate(workInProgress) { + // Tag the fiber with an update effect. This turns a Placement into + // a PlacementAndUpdate. + workInProgress.flags |= Update; +} - if (typeof revealOrder === "string") { - switch (revealOrder.toLowerCase()) { - case "together": - case "forwards": - case "backwards": { - error( - '"%s" is not a valid value for revealOrder on . ' + - 'Use lowercase "%s" instead.', - revealOrder, - revealOrder.toLowerCase() - ); +function markRef$1(workInProgress) { + workInProgress.flags |= Ref; +} - break; - } +var appendAllChildren; +var updateHostContainer; +var updateHostComponent$1; +var updateHostText$1; - 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() - ); +{ + // Mutation mode + appendAllChildren = function( + parent, + workInProgress, + needsVisibilityToggle, + isHidden + ) { + // We only have the top Fiber that was created but we need recurse down its + // children to find all the terminal nodes. + var node = workInProgress.child; - break; - } + while (node !== null) { + if (node.tag === HostComponent || node.tag === HostText) { + appendInitialChild(parent, node.stateNode); + } else if (node.tag === HostPortal); + else if (node.child !== null) { + node.child.return = node; + node = node.child; + continue; + } - default: - error( - '"%s" is not a supported revealOrder on . ' + - 'Did you mean "together", "forwards" or "backwards"?', - revealOrder - ); + if (node === workInProgress) { + return; + } - break; + while (node.sibling === null) { + if (node.return === null || node.return === workInProgress) { + return; } - } else { - error( - "%s is not a supported value for revealOrder on . " + - 'Did you mean "together", "forwards" or "backwards"?', - revealOrder - ); + + node = node.return; } + + node.sibling.return = node.return; + node = node.sibling; } - } -} + }; -function validateTailOptions(tailMode, revealOrder) { - { - if (tailMode !== undefined && !didWarnAboutTailOptions[tailMode]) { - if (tailMode !== "collapsed" && tailMode !== "hidden") { - didWarnAboutTailOptions[tailMode] = true; + updateHostContainer = function(current, workInProgress) { + // Noop + }; - 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; + updateHostComponent$1 = function( + current, + workInProgress, + type, + newProps, + rootContainerInstance + ) { + // If we have an alternate, that means this is an update and we need to + // schedule a side-effect to do the updates. + var oldProps = current.memoizedProps; - error( - ' is only valid if revealOrder is ' + - '"forwards" or "backwards". ' + - 'Did you mean to specify revealOrder="forwards"?', - tailMode - ); - } - } - } -} + if (oldProps === newProps) { + // In mutation mode, this is sufficient for a bailout because + // we won't touch this node even if children changed. + return; + } // If we get updated because one of our children updated, we don't + // have newProps so we'll have to reuse them. + // TODO: Split the update API as separate for the props vs. children. + // Even better would be if children weren't special cased at all tho. -function validateSuspenseListNestedChild(childSlot, index) { - { - var isAnArray = isArray(childSlot); - var isIterable = - !isAnArray && typeof getIteratorFn(childSlot) === "function"; + var instance = workInProgress.stateNode; + var currentHostContext = getHostContext(); // TODO: Experiencing an error where oldProps is null. Suggests a host + // component is hitting the resume path. Figure out why. Possibly + // related to `hidden`. - if (isAnArray || isIterable) { - var type = isAnArray ? "array" : "iterable"; + var updatePayload = prepareUpdate(); // TODO: Type this specific to this type of component. - error( - "A nested %s was passed to row #%s in . Wrap it in " + - "an additional SuspenseList to configure its revealOrder: " + - " ... " + - "{%s} ... " + - "", - type, - index, - type - ); + workInProgress.updateQueue = updatePayload; // If the update payload indicates that there is a change or if there + // is a new ref we mark this as an update. All the work is done in commitWork. - return false; + if (updatePayload) { + markUpdate(workInProgress); } - } + }; - return true; + updateHostText$1 = function(current, workInProgress, oldText, newText) { + // If the text differs, mark it as an update. All the work in done in commitWork. + if (oldText !== newText) { + markUpdate(workInProgress); + } + }; } -function 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; - } +function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { + switch (renderState.tailMode) { + case "hidden": { + // Any insertions at the end of the tail list after this point + // should be invisible. If there are already mounted boundaries + // anything before them are not considered for collapsing. + // Therefore we need to go through the whole tail to find if + // there are any. + var tailNode = renderState.tail; + var lastTailNode = null; + + while (tailNode !== null) { + if (tailNode.alternate !== null) { + lastTailNode = tailNode; } + + tailNode = tailNode.sibling; + } // Next we're simply going to delete all insertions after the + // last rendered item. + + if (lastTailNode === null) { + // All remaining items in the tail are insertions. + renderState.tail = null; } else { - var iteratorFn = getIteratorFn(children); + // Detach the insertion after the last node that was already + // inserted. + lastTailNode.sibling = null; + } - if (typeof iteratorFn === "function") { - var childrenIterator = iteratorFn.call(children); + break; + } - if (childrenIterator) { - var step = childrenIterator.next(); - var _i = 0; + case "collapsed": { + // Any insertions at the end of the tail list after this point + // should be invisible. If there are already mounted boundaries + // anything before them are not considered for collapsing. + // Therefore we need to go through the whole tail to find if + // there are any. + var _tailNode = renderState.tail; + var _lastTailNode = null; + + while (_tailNode !== null) { + if (_tailNode.alternate !== null) { + _lastTailNode = _tailNode; + } - for (; !step.done; step = childrenIterator.next()) { - if (!validateSuspenseListNestedChild(step.value, _i)) { - return; - } + _tailNode = _tailNode.sibling; + } // Next we're simply going to delete all insertions after the + // last rendered item. - _i++; - } - } + if (_lastTailNode === null) { + // All remaining items in the tail are insertions. + if (!hasRenderedATailFallback && renderState.tail !== null) { + // We suspended during the head. We want to show at least one + // row at the tail. So we'll keep on and cut off the rest. + renderState.tail.sibling = null; } else { - 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 - ); + renderState.tail = null; } + } else { + // Detach the insertion after the last node that was already + // inserted. + _lastTailNode.sibling = null; } + + break; } } } -function initSuspenseListRenderState( - workInProgress, - isBackwards, - tail, - lastContentRow, - tailMode -) { - var renderState = workInProgress.memoizedState; +function bubbleProperties(completedWork) { + var didBailout = + completedWork.alternate !== null && + completedWork.alternate.child === completedWork.child; + var newChildLanes = NoLanes; + var subtreeFlags = NoFlags; - 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 (!didBailout) { + // Bubble up the earliest expiration time. + if ((completedWork.mode & ProfileMode) !== NoMode) { + // In profiling mode, resetChildExpirationTime is also used to reset + // profiler durations. + var actualDuration = completedWork.actualDuration; + var treeBaseDuration = completedWork.selfBaseDuration; + var child = completedWork.child; -function updateSuspenseListComponent(current, workInProgress, renderLanes) { - var nextProps = workInProgress.pendingProps; - var revealOrder = nextProps.revealOrder; - var tailMode = nextProps.tail; - var newChildren = nextProps.children; - validateRevealOrder(revealOrder); - validateTailOptions(tailMode, revealOrder); - validateSuspenseListChildren(newChildren, revealOrder); - reconcileChildren(current, workInProgress, newChildren, renderLanes); - var suspenseContext = suspenseStackCursor.current; - var shouldForceFallback = hasSuspenseContext( - suspenseContext, - ForceSuspenseFallback - ); + 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. - if (shouldForceFallback) { - suspenseContext = setShallowSuspenseContext( - suspenseContext, - ForceSuspenseFallback - ); - workInProgress.flags |= DidCapture; - } else { - var didSuspendBefore = - current !== null && (current.flags & DidCapture) !== NoFlags; + actualDuration += child.actualDuration; + treeBaseDuration += child.treeBaseDuration; + child = child.sibling; + } - if (didSuspendBefore) { - // If we previously forced a fallback, we need to schedule work - // on any nested boundaries to let them know to try to render - // again. This is the same as context updating. - propagateSuspenseContextChange( - workInProgress, - workInProgress.child, - renderLanes - ); - } + completedWork.actualDuration = actualDuration; + completedWork.treeBaseDuration = treeBaseDuration; + } else { + var _child = completedWork.child; - suspenseContext = setDefaultShallowSuspenseContext(suspenseContext); - } + 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. - pushSuspenseContext(workInProgress, suspenseContext); + _child.return = completedWork; + _child = _child.sibling; + } + } - if ((workInProgress.mode & ConcurrentMode) === NoMode) { - // In legacy mode, SuspenseList doesn't work so we just - // use make it a noop by treating it as the default revealOrder. - workInProgress.memoizedState = null; + completedWork.subtreeFlags |= subtreeFlags; } else { - switch (revealOrder) { - case "forwards": { - var lastContentRow = findLastContentRow(workInProgress.child); - var tail; + // 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; - 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; - } + 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. - initSuspenseListRenderState( - workInProgress, - false, // isBackwards - tail, - lastContentRow, - tailMode - ); - break; + subtreeFlags |= _child2.subtreeFlags & StaticMask; + subtreeFlags |= _child2.flags & StaticMask; + _treeBaseDuration += _child2.treeBaseDuration; + _child2 = _child2.sibling; } - case "backwards": { - // We're going to find the first row that has existing content. - // At the same time we're going to reverse the list of everything - // we pass in the meantime. That's going to be our tail in reverse - // order. - var _tail = null; - var row = workInProgress.child; - workInProgress.child = null; - - while (row !== null) { - var currentRow = row.alternate; // New rows can't be content rows. - - if (currentRow !== null && findFirstSuspended(currentRow) === null) { - // This is the beginning of the main content. - workInProgress.child = row; - break; - } - - var nextRow = row.sibling; - row.sibling = _tail; - _tail = row; - row = nextRow; - } // TODO: If workInProgress.child is null, we can continue on the tail immediately. + completedWork.treeBaseDuration = _treeBaseDuration; + } else { + var _child3 = completedWork.child; - initSuspenseListRenderState( - workInProgress, - true, // isBackwards - _tail, - null, // last - tailMode - ); - break; - } + while (_child3 !== null) { + newChildLanes = mergeLanes( + newChildLanes, + mergeLanes(_child3.lanes, _child3.childLanes) + ); // "Static" flags share the lifetime of the fiber/hook they belong to, + // so we should bubble those up even during a bailout. All the other + // flags have a lifetime only of a single render + commit, so we should + // ignore them. - case "together": { - initSuspenseListRenderState( - workInProgress, - false, // isBackwards - null, // tail - null, // last - undefined - ); - break; - } + 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. - default: { - // The default reveal order is the same as not having - // a boundary. - workInProgress.memoizedState = null; + _child3.return = completedWork; + _child3 = _child3.sibling; } } - } - - return workInProgress.child; -} - -function updatePortalComponent(current, workInProgress, renderLanes) { - pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); - var nextChildren = workInProgress.pendingProps; - if (current === null) { - // Portals are special because we don't append the children during mount - // but at commit. Therefore we need to track insertions which the normal - // flow doesn't do during mount. This doesn't happen at the root because - // the root always starts with a "current" with a null child. - // TODO: Consider unifying this with how the root works. - workInProgress.child = reconcileChildFibers( - workInProgress, - null, - nextChildren, - renderLanes - ); - } else { - reconcileChildren(current, workInProgress, nextChildren, renderLanes); + completedWork.subtreeFlags |= subtreeFlags; } - return workInProgress.child; + completedWork.childLanes = newChildLanes; + return didBailout; } -var hasWarnedAboutUsingNoValuePropOnContextProvider = false; - -function updateContextProvider(current, workInProgress, renderLanes) { - var providerType = workInProgress.type; - var context = providerType._context; - var newProps = workInProgress.pendingProps; - var oldProps = workInProgress.memoizedProps; - var newValue = newProps.value; - - { - if (!("value" in newProps)) { - if (!hasWarnedAboutUsingNoValuePropOnContextProvider) { - hasWarnedAboutUsingNoValuePropOnContextProvider = true; +function completeDehydratedSuspenseBoundary( + current, + workInProgress, + nextState +) { + var wasHydrated = popHydrationState(); - error( - "The `value` prop is required for the ``. Did you misspell it or forget to pass it?" + if (nextState !== null && nextState.dehydrated !== null) { + // We might be inside a hydration state the first time we're picking up this + // Suspense boundary, and also after we've reentered it for further hydration. + if (current === null) { + if (!wasHydrated) { + throw new Error( + "A dehydrated suspense component was completed without a hydrated node. " + + "This is probably a bug in React." ); } - } - - var providerPropTypes = workInProgress.type.propTypes; - if (providerPropTypes) { - checkPropTypes(providerPropTypes, newProps, "prop", "Context.Provider"); - } - } + prepareToHydrateHostSuspenseInstance(); + bubbleProperties(workInProgress); - pushProvider(workInProgress, context, newValue); + { + if ((workInProgress.mode & ProfileMode) !== NoMode) { + var isTimedOutSuspense = nextState !== null; - { - if (oldProps !== null) { - var oldValue = oldProps.value; + if (isTimedOutSuspense) { + // Don't count time spent in a timed out Suspense subtree as part of the base duration. + var primaryChildFragment = workInProgress.child; - if (objectIs(oldValue, newValue)) { - // No change. Bailout early if children are the same. - if (oldProps.children === newProps.children && !hasContextChanged()) { - return bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderLanes - ); + if (primaryChildFragment !== null) { + // $FlowFixMe Flow doesn't support type casting in combination with the -= operator + workInProgress.treeBaseDuration -= + primaryChildFragment.treeBaseDuration; + } + } } - } 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; -} + return false; + } else { + if ((workInProgress.flags & DidCapture) === NoFlags) { + // This boundary did not suspend so it's now hydrated and unsuspended. + workInProgress.memoizedState = null; + } // If nothing suspended, we need to schedule an effect to mark this boundary + // as having hydrated so events know that they're free to be invoked. + // It's also a signal to replay events and the suspense callback. + // If something suspended, schedule an effect to attach retry listeners. + // So we might as well always mark this. -var hasWarnedAboutUsingContextAsConsumer = false; + workInProgress.flags |= Update; + bubbleProperties(workInProgress); -function updateContextConsumer(current, workInProgress, renderLanes) { - var context = workInProgress.type; // The logic below for Context differs depending on PROD or DEV mode. In - // DEV mode, we create a separate object for Context.Consumer that acts - // like a proxy to Context. This proxy object adds unnecessary code in PROD - // so we use the old behaviour (Context.Consumer references Context) to - // reduce size and overhead. The separate object references context via - // a property called "_context", which also gives us the ability to check - // in DEV mode if this property exists or not and warn if it does not. + { + if ((workInProgress.mode & ProfileMode) !== NoMode) { + var _isTimedOutSuspense = nextState !== null; - { - if (context._context === undefined) { - // This may be because it's a Context (rather than a Consumer). - // Or it may be because it's older React where they're the same thing. - // We only want to warn if we're sure it's a new React. - if (context !== context.Consumer) { - if (!hasWarnedAboutUsingContextAsConsumer) { - hasWarnedAboutUsingContextAsConsumer = true; + if (_isTimedOutSuspense) { + // Don't count time spent in a timed out Suspense subtree as part of the base duration. + var _primaryChildFragment = workInProgress.child; - error( - "Rendering directly is not supported and will be removed in " + - "a future major release. Did you mean to render instead?" - ); + if (_primaryChildFragment !== null) { + // $FlowFixMe Flow doesn't support type casting in combination with the -= operator + workInProgress.treeBaseDuration -= + _primaryChildFragment.treeBaseDuration; + } + } } } - } else { - context = context._context; - } - } - - var newProps = workInProgress.pendingProps; - var render = newProps.children; - { - if (typeof render !== "function") { - error( - "A context consumer was rendered with multiple children, or a child " + - "that isn't a function. A context consumer expects a single child " + - "that is a function. If you did pass a function, make sure there " + - "is no trailing or leading whitespace around it." - ); + return false; } - } - - prepareToReadContext(workInProgress, renderLanes); - var newValue = readContext(context); - - var newChildren; + } 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 - { - ReactCurrentOwner$1.current = workInProgress; - setIsRendering(true); - newChildren = render(newValue); - setIsRendering(false); + return true; } - - workInProgress.flags |= PerformedWork; - reconcileChildren(current, workInProgress, newChildren, renderLanes); - return workInProgress.child; } -function markWorkInProgressReceivedUpdate() { - didReceiveUpdate = true; -} - -function bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) { - if (current !== null) { - // Reuse previous dependencies - workInProgress.dependencies = current.dependencies; - } - - { - // Don't update "base" render times for bailouts. - stopProfilerTimerIfRunning(); - } +function completeWork(current, workInProgress, renderLanes) { + var newProps = workInProgress.pendingProps; // Note: This intentionally doesn't check if we're hydrating because comparing + // to the current tree provider fiber is just as fast and less error-prone. + // Ideally we would have a special version of the work loop only + // for hydration. - markSkippedUpdateLanes(workInProgress.lanes); // Check if the children have any pending work. + popTreeContext(workInProgress); - 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. - { + 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; - } - } // This fiber doesn't have work, but its subtree does. Clone the child - // fibers and continue. - cloneChildFibers(current, workInProgress); - return workInProgress.child; -} + case ClassComponent: { + var Component = workInProgress.type; -function remountFiber(current, oldWorkInProgress, newWorkInProgress) { - { - var returnFiber = oldWorkInProgress.return; + if (isContextProvider(Component)) { + popContext(workInProgress); + } - if (returnFiber === null) { - // eslint-disable-next-line react-internal/prod-error-codes - throw new Error("Cannot swap the root fiber."); - } // Disconnect from the old current. - // It will get deleted. + bubbleProperties(workInProgress); + return null; + } - current.alternate = null; - oldWorkInProgress.alternate = null; // Connect to the new tree. + case HostRoot: { + var fiberRoot = workInProgress.stateNode; + popHostContainer(workInProgress); + popTopLevelContextObject(workInProgress); + resetWorkInProgressVersions(); - newWorkInProgress.index = oldWorkInProgress.index; - newWorkInProgress.sibling = oldWorkInProgress.sibling; - newWorkInProgress.return = oldWorkInProgress.return; - newWorkInProgress.ref = oldWorkInProgress.ref; // Replace the child/sibling pointers above it. + if (fiberRoot.pendingContext) { + fiberRoot.context = fiberRoot.pendingContext; + fiberRoot.pendingContext = null; + } - if (oldWorkInProgress === returnFiber.child) { - returnFiber.child = newWorkInProgress; - } else { - var prevSibling = returnFiber.child; + if (current === null || current.child === null) { + // If we hydrated, pop so that we can delete any remaining children + // that weren't hydrated. + var wasHydrated = popHydrationState(); - if (prevSibling === null) { - // eslint-disable-next-line react-internal/prod-error-codes - throw new Error("Expected parent to have a child."); - } + 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; - while (prevSibling.sibling !== oldWorkInProgress) { - prevSibling = prevSibling.sibling; + if ( + // Check if this is a client root + !prevState.isDehydrated || // Check if we reverted to client rendering (e.g. due to an error) + (workInProgress.flags & ForceClientRender) !== NoFlags + ) { + // Schedule an effect to clear this container at the start of the + // next commit. This handles the case of React rendering into a + // container with previous children. It's also safe to do for + // updates too, because current.child would only be null if the + // previous render was null (so the container would already + // be empty). + workInProgress.flags |= Snapshot; // If this was a forced client render, there may have been + // recoverable errors during first hydration attempt. If so, add + // them to a queue so we can log them in the commit phase. - if (prevSibling === null) { - // eslint-disable-next-line react-internal/prod-error-codes - throw new Error("Expected to find the previous sibling."); + upgradeHydrationErrorsToRecoverable(); + } + } } } - prevSibling.sibling = newWorkInProgress; - } // Delete the old fiber and place the new one. - // Since the old fiber is disconnected, we have to schedule it manually. - - var deletions = returnFiber.deletions; + updateHostContainer(current, workInProgress); + bubbleProperties(workInProgress); - if (deletions === null) { - returnFiber.deletions = [current]; - returnFiber.flags |= ChildDeletion; - } else { - deletions.push(current); + return null; } - newWorkInProgress.flags |= Placement; // Restart work from the new fiber. + case HostComponent: { + popHostContext(workInProgress); + var rootContainerInstance = getRootHostContainer(); + var type = workInProgress.type; - return newWorkInProgress; - } -} + if (current !== null && workInProgress.stateNode != null) { + updateHostComponent$1( + current, + workInProgress, + type, + newProps, + rootContainerInstance + ); -function checkScheduledUpdateOrContext(current, renderLanes) { - // Before performing an early bailout, we must check if there are pending - // updates or context. - var updateLanes = current.lanes; + if (current.ref !== workInProgress.ref) { + markRef$1(workInProgress); + } + } else { + if (!newProps) { + if (workInProgress.stateNode === null) { + throw new Error( + "We must have new props for new mounts. This error is likely " + + "caused by a bug in React. Please file an issue." + ); + } // This can happen when we abort work. - if (includesSomeLane(updateLanes, renderLanes)) { - return true; - } // No pending update, but because context is propagated lazily, we need + bubbleProperties(workInProgress); + return null; + } - return false; -} + var currentHostContext = getHostContext(); // TODO: Move createInstance to beginWork and keep it on a context + // "stack" as the parent. Then append children as we go in beginWork + // or completeWork depending on whether we want to add them top->down or + // bottom->up. Top->down is faster in IE11. -function attemptEarlyBailoutIfNoScheduledUpdate( - current, - workInProgress, - renderLanes -) { - // This fiber does not have any pending work. Bailout without entering - // the begin phase. There's still some bookkeeping we that needs to be done - // in this optimized path, mostly pushing stuff onto the stack. - switch (workInProgress.tag) { - case HostRoot: - pushHostRootContext(workInProgress); - var root = workInProgress.stateNode; - break; + var _wasHydrated = popHydrationState(); - case HostComponent: - pushHostContext(workInProgress); - break; + if (_wasHydrated) { + // TODO: Move this and createInstance step into the beginPhase + // to consolidate. + if (prepareToHydrateHostInstance()) { + // If changes to the hydrated node need to be applied at the + // commit-phase we mark this as such. + markUpdate(workInProgress); + } + } else { + var instance = createInstance( + type, + newProps, + rootContainerInstance, + currentHostContext, + workInProgress + ); + appendAllChildren(instance, workInProgress, false, false); + workInProgress.stateNode = instance; // Certain renderers require commit-time effects for initial mount. + // (eg DOM renderer supports auto-focus for certain elements). + // Make sure such renderers get scheduled for later work. - case ClassComponent: { - var Component = workInProgress.type; + if (finalizeInitialChildren(instance)) { + markUpdate(workInProgress); + } + } - if (isContextProvider(Component)) { - pushContextProvider(workInProgress); + if (workInProgress.ref !== null) { + // If there is a ref on a host node we need to schedule a callback + markRef$1(workInProgress); + } } - break; + bubbleProperties(workInProgress); + return null; } - 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; - } + case HostText: { + var newText = newProps; - case Profiler: - { - // Profiler should only call onRender when one of its descendants actually rendered. - var hasChildWork = includesSomeLane( - renderLanes, - workInProgress.childLanes - ); + if (current && workInProgress.stateNode != null) { + var oldText = current.memoizedProps; // If we have an alternate, that means this is an update and we need + // to schedule a side-effect to do the updates. - if (hasChildWork) { - workInProgress.flags |= Update; + updateHostText$1(current, workInProgress, oldText, newText); + } else { + if (typeof newText !== "string") { + if (workInProgress.stateNode === null) { + throw new Error( + "We must have new props for new mounts. This error is likely " + + "caused by a bug in React. Please file an issue." + ); + } // This can happen when we abort work. } - { - // 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 _rootContainerInstance = getRootHostContainer(); - break; + var _currentHostContext = getHostContext(); - case SuspenseComponent: { - var state = workInProgress.memoizedState; + var _wasHydrated2 = popHydrationState(); - if (state !== null) { - // whether to retry the primary children, or to skip over it and - // go straight to the fallback. Check the priority of the primary - // child fragment. + if (_wasHydrated2) { + if (prepareToHydrateHostTextInstance()) { + markUpdate(workInProgress); + } + } else { + workInProgress.stateNode = createTextInstance( + newText, + _rootContainerInstance, + _currentHostContext, + workInProgress + ); + } + } - var primaryChildFragment = workInProgress.child; - var primaryChildLanes = primaryChildFragment.childLanes; + bubbleProperties(workInProgress); + return null; + } - if (includesSomeLane(renderLanes, primaryChildLanes)) { - // The primary children have pending work. Use the normal path - // to attempt to render the primary children again. - return updateSuspenseComponent(current, workInProgress, renderLanes); - } else { - // The primary child fragment does not have pending work marked - // on it - pushSuspenseContext( - workInProgress, - setDefaultShallowSuspenseContext(suspenseStackCursor.current) - ); // The primary children do not have pending work with sufficient - // priority. Bailout. + case SuspenseComponent: { + popSuspenseContext(workInProgress); + var nextState = workInProgress.memoizedState; // Special path for dehydrated boundaries. We may eventually move this + // to its own fiber type so that we can add other kinds of hydration + // boundaries that aren't associated with a Suspense tree. In anticipation + // of such a refactor, all the hydration logic is contained in + // this branch. - var child = bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderLanes - ); + if ( + current === null || + (current.memoizedState !== null && + current.memoizedState.dehydrated !== null) + ) { + var fallthroughToNormalSuspensePath = completeDehydratedSuspenseBoundary( + current, + workInProgress, + nextState + ); - if (child !== null) { - // The fallback children have pending work. Skip over the - // primary children and work on the fallback. - return child.sibling; + 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 { - // Note: We can return `null` here because we already checked - // whether there were nested context consumers, via the call to - // `bailoutOnAlreadyFinishedWork` above. + // Did not finish hydrating, either because this is the initial + // render or because something suspended. return null; } - } - } else { - pushSuspenseContext( - workInProgress, - setDefaultShallowSuspenseContext(suspenseStackCursor.current) - ); + } // Continue with the normal Suspense path. } - break; - } + if ((workInProgress.flags & DidCapture) !== NoFlags) { + // Something suspended. Re-render with the fallback children. + workInProgress.lanes = renderLanes; // Do not reset the effect list. - case SuspenseListComponent: { - var didSuspendBefore = (current.flags & DidCapture) !== NoFlags; + if ((workInProgress.mode & ProfileMode) !== NoMode) { + transferActualDuration(workInProgress); + } // Don't bubble properties in this case. - var _hasChildWork = includesSomeLane( - renderLanes, - workInProgress.childLanes - ); + return workInProgress; + } - if (didSuspendBefore) { - if (_hasChildWork) { - // If something was in fallback state last time, and we have all the - // same children then we're still in progressive loading state. - // Something might get unblocked by state updates or retries in the - // tree which will affect the tail. So we need to use the normal - // path to compute the correct tail. - return updateSuspenseListComponent( - current, - workInProgress, - renderLanes - ); - } // If none of the children had any work, that means that none of - // them got retried so they'll still be blocked in the same way - // as before. We can fast bail out. + var nextDidTimeout = nextState !== null; + var prevDidTimeout = current !== null && current.memoizedState !== null; + // a passive effect, which is when we process the transitions + + if (nextDidTimeout !== prevDidTimeout) { + // an effect to toggle the subtree's visibility. When we switch from + // fallback -> primary, the inner Offscreen fiber schedules this effect + // as part of its normal complete phase. But when we switch from + // primary -> fallback, the inner Offscreen fiber does not have a complete + // phase. So we need to schedule its effect here. + // + // We also use this flag to connect/disconnect the effects, but the same + // logic applies: when re-connecting, the Offscreen fiber's complete + // phase will handle scheduling the effect. It's only when the fallback + // is active that we have to do anything special. + + if (nextDidTimeout) { + var _offscreenFiber2 = workInProgress.child; + _offscreenFiber2.flags |= Visibility; // TODO: This will still suspend a synchronous tree if anything + // in the concurrent tree already suspended during this render. + // This is a known bug. + + if ((workInProgress.mode & ConcurrentMode) !== NoMode) { + // TODO: Move this back to throwException because this is too late + // if this is a large tree which is common for initial loads. We + // don't know if we should restart a render or not until we get + // this marker, and this is too late. + // If this render already had a ping or lower pri updates, + // and this is the first time we know we're going to suspend we + // should be able to immediately restart from within throwException. + var hasInvisibleChildContext = + current === null && + (workInProgress.memoizedProps.unstable_avoidThisFallback !== + true || + !enableSuspenseAvoidThisFallback); - 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 ( + hasInvisibleChildContext || + hasSuspenseContext( + suspenseStackCursor.current, + InvisibleParentSuspenseContext + ) + ) { + // If this was in an invisible tree or a new render, then showing + // this boundary is ok. + renderDidSuspend(); + } else { + // Otherwise, we're going to have to hide content so we should + // suspend for longer if possible. + renderDidSuspendDelayIfPossible(); + } + } + } + } - var renderState = workInProgress.memoizedState; + var wakeables = workInProgress.updateQueue; - if (renderState !== null) { - // Reset to the "together" mode in case we've started a different - // update in the past but didn't complete it. - renderState.rendering = null; - renderState.tail = null; - renderState.lastEffect = null; + if (wakeables !== null) { + // Schedule an effect to attach a retry listener to the promise. + // TODO: Move to passive phase + workInProgress.flags |= Update; } - pushSuspenseContext(workInProgress, suspenseStackCursor.current); + bubbleProperties(workInProgress); - if (_hasChildWork) { - break; - } else { - // If none of the children had any work, that means that none of - // them got retried so they'll still be blocked in the same way - // as before. We can fast bail out. - return null; + { + if ((workInProgress.mode & ProfileMode) !== NoMode) { + if (nextDidTimeout) { + // Don't count time spent in a timed out Suspense subtree as part of the base duration. + var primaryChildFragment = workInProgress.child; + + if (primaryChildFragment !== null) { + // $FlowFixMe Flow doesn't support type casting in combination with the -= operator + workInProgress.treeBaseDuration -= + primaryChildFragment.treeBaseDuration; + } + } + } } - } - case 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 null; } - } - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); -} + case HostPortal: + popHostContainer(workInProgress); + updateHostContainer(current, workInProgress); -function beginWork(current, workInProgress, renderLanes) { - { - if (workInProgress._debugNeedsRemount && current !== null) { - // This will restart the begin phase with a new fiber. - return remountFiber( - current, - workInProgress, - createFiberFromTypeAndProps( - workInProgress.type, - workInProgress.key, - workInProgress.pendingProps, - workInProgress._debugOwner || null, - workInProgress.mode, - workInProgress.lanes - ) - ); - } - } + if (current === null) { + preparePortalMount(workInProgress.stateNode.containerInfo); + } - if (current !== null) { - var oldProps = current.memoizedProps; - var newProps = workInProgress.pendingProps; + bubbleProperties(workInProgress); + return null; - 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 - ); + case ContextProvider: + // Pop provider fiber + var context = workInProgress.type._context; + popProvider(context, workInProgress); + bubbleProperties(workInProgress); + return null; - if ( - !hasScheduledUpdateOrContext && // If this is the second pass of an error or suspense boundary, there - // may not be work scheduled on `current`, so we check for this flag. - (workInProgress.flags & DidCapture) === NoFlags - ) { - // No pending updates or context. Bail out now. - didReceiveUpdate = false; - return attemptEarlyBailoutIfNoScheduledUpdate( - current, - workInProgress, - renderLanes - ); - } + 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 ((current.flags & ForceUpdateForLegacySuspense) !== NoFlags) { - // This is a special case that only exists for legacy mode. - // See https://github.com/facebook/react/pull/19216. - didReceiveUpdate = true; - } else { - // An update was scheduled on this fiber, but there are no new props - // nor legacy context. Set this to false. If an update queue or context - // consumer produces a changed value, it will set this to true. Otherwise, - // the component will assume the children have not changed and bail out. - didReceiveUpdate = false; + if (isContextProvider(_Component)) { + popContext(workInProgress); } + + bubbleProperties(workInProgress); + return null; } - } 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; + case SuspenseListComponent: { + popSuspenseContext(workInProgress); + var renderState = workInProgress.memoizedState; - switch (workInProgress.tag) { - case IndeterminateComponent: { - return mountIndeterminateComponent( - current, - workInProgress, - workInProgress.type, - renderLanes - ); - } + if (renderState === null) { + // We're running in the default, "independent" mode. + // We don't do anything in this mode. + bubbleProperties(workInProgress); + return null; + } - case LazyComponent: { - var elementType = workInProgress.elementType; - return mountLazyComponent( - current, - workInProgress, - elementType, - renderLanes - ); - } + var didSuspendAlready = (workInProgress.flags & DidCapture) !== NoFlags; + var renderedTail = renderState.rendering; - case FunctionComponent: { - var Component = workInProgress.type; - var unresolvedProps = workInProgress.pendingProps; - var resolvedProps = - workInProgress.elementType === Component - ? unresolvedProps - : resolveDefaultProps(Component, unresolvedProps); - return updateFunctionComponent( - current, - workInProgress, - Component, - resolvedProps, - renderLanes - ); - } + if (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); - case ClassComponent: { - var _Component = workInProgress.type; - var _unresolvedProps = workInProgress.pendingProps; + if (!cannotBeSuspended) { + var row = workInProgress.child; - var _resolvedProps = - workInProgress.elementType === _Component - ? _unresolvedProps - : resolveDefaultProps(_Component, _unresolvedProps); + while (row !== null) { + var suspended = findFirstSuspended(row); - return updateClassComponent( - current, - workInProgress, - _Component, - _resolvedProps, - renderLanes - ); - } + 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 HostRoot: - return updateHostRoot(current, workInProgress, renderLanes); + var newThenables = suspended.updateQueue; + + if (newThenables !== null) { + workInProgress.updateQueue = newThenables; + workInProgress.flags |= Update; + } // Rerender the whole list, but this time, we'll force fallbacks + // to stay in place. + // Reset the effect flags before doing the second pass since that's now invalid. + // Reset the child fibers to their original state. + + workInProgress.subtreeFlags = NoFlags; + resetChildFibers(workInProgress, renderLanes); // Set up the Suspense Context to force suspense and immediately + // rerender the children. + + pushSuspenseContext( + workInProgress, + setShallowSuspenseContext( + suspenseStackCursor.current, + ForceSuspenseFallback + ) + ); // Don't bubble properties in this case. - case HostComponent: - return updateHostComponent$1(current, workInProgress, renderLanes); + return workInProgress.child; + } - case HostText: - return updateHostText$1(); + row = row.sibling; + } + } - case SuspenseComponent: - return updateSuspenseComponent(current, workInProgress, renderLanes); + if (renderState.tail !== null && now() > getRenderTargetTime()) { + // We have already passed our CPU deadline but we still have rows + // left in the tail. We'll just give up further attempts to render + // the main content and only render fallbacks. + workInProgress.flags |= DidCapture; + didSuspendAlready = true; + cutOffTailIfNeeded(renderState, false); // Since nothing actually suspended, there will nothing to ping this + // to get it started back up to attempt the next item. While in terms + // of priority this work has the same priority as this current render, + // it's not part of the same transition once the transition has + // committed. If it's sync, we still want to yield so that it can be + // painted. Conceptually, this is really the same as pinging. + // We can use any RetryLane even if it's the one currently rendering + // since we're leaving it behind on this node. - case HostPortal: - return updatePortalComponent(current, workInProgress, renderLanes); + 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); - case ForwardRef: { - var type = workInProgress.type; - var _unresolvedProps2 = workInProgress.pendingProps; + 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 _resolvedProps2 = - workInProgress.elementType === type - ? _unresolvedProps2 - : resolveDefaultProps(type, _unresolvedProps2); + var _newThenables = _suspended.updateQueue; - return updateForwardRef( - current, - workInProgress, - type, - _resolvedProps2, - renderLanes - ); - } + if (_newThenables !== null) { + workInProgress.updateQueue = _newThenables; + workInProgress.flags |= Update; + } - case Fragment: - return updateFragment(current, workInProgress, renderLanes); + cutOffTailIfNeeded(renderState, true); // This might have been modified. - case Mode: - return updateMode(current, workInProgress, renderLanes); + if ( + renderState.tail === null && + renderState.tailMode === "hidden" && + !renderedTail.alternate && + !getIsHydrating() // We don't cut it if we're hydrating. + ) { + // We're done. + bubbleProperties(workInProgress); + return null; + } + } else if ( + // The time it took to render last row is greater than the remaining + // time we have to render. So rendering one more row would likely + // exceed it. + now() * 2 - renderState.renderingStartTime > + getRenderTargetTime() && + renderLanes !== OffscreenLane + ) { + // We have now passed our CPU deadline and we'll just give up further + // attempts to render the main content and only render fallbacks. + // The assumption is that this is usually faster. + workInProgress.flags |= DidCapture; + didSuspendAlready = true; + cutOffTailIfNeeded(renderState, false); // Since nothing actually suspended, there will nothing to ping this + // to get it started back up to attempt the next item. While in terms + // of priority this work has the same priority as this current render, + // it's not part of the same transition once the transition has + // committed. If it's sync, we still want to yield so that it can be + // painted. Conceptually, this is really the same as pinging. + // We can use any RetryLane even if it's the one currently rendering + // since we're leaving it behind on this node. - case Profiler: - return updateProfiler(current, workInProgress, renderLanes); + workInProgress.lanes = SomeRetryLane; + } + } - case ContextProvider: - return updateContextProvider(current, workInProgress, renderLanes); + 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; - case ContextConsumer: - return updateContextConsumer(current, workInProgress, renderLanes); + if (previousSibling !== null) { + previousSibling.sibling = renderedTail; + } else { + workInProgress.child = renderedTail; + } - case MemoComponent: { - var _type2 = workInProgress.type; - var _unresolvedProps3 = workInProgress.pendingProps; // Resolve outer props first, then resolve inner props. + renderState.last = renderedTail; + } + } - var _resolvedProps3 = resolveDefaultProps(_type2, _unresolvedProps3); + if (renderState.tail !== null) { + // We still have tail rows to render. + // Pop a row. + var next = renderState.tail; + renderState.rendering = next; + renderState.tail = next.sibling; + renderState.renderingStartTime = now(); + next.sibling = null; // Restore the context. + // TODO: We can probably just avoid popping it instead and only + // setting it the first time we go from not suspended to suspended. - { - if (workInProgress.type !== workInProgress.elementType) { - var outerPropTypes = _type2.propTypes; + var suspenseContext = suspenseStackCursor.current; - if (outerPropTypes) { - checkPropTypes( - outerPropTypes, - _resolvedProps3, // Resolved for outer only - "prop", - getComponentNameFromType(_type2) - ); - } + if (didSuspendAlready) { + suspenseContext = setShallowSuspenseContext( + suspenseContext, + ForceSuspenseFallback + ); + } else { + suspenseContext = setDefaultShallowSuspenseContext(suspenseContext); } + + pushSuspenseContext(workInProgress, suspenseContext); // Do a pass over the next row. + // Don't bubble properties in this case. + + return next; } - _resolvedProps3 = resolveDefaultProps(_type2.type, _resolvedProps3); - return updateMemoComponent( - current, - workInProgress, - _type2, - _resolvedProps3, - renderLanes - ); + bubbleProperties(workInProgress); + return null; } - case SimpleMemoComponent: { - return updateSimpleMemoComponent( - current, - workInProgress, - workInProgress.type, - workInProgress.pendingProps, - renderLanes - ); + case ScopeComponent: { + break; } - case IncompleteClassComponent: { - var _Component2 = workInProgress.type; - var _unresolvedProps4 = workInProgress.pendingProps; + case OffscreenComponent: + case LegacyHiddenComponent: { + popRenderLanes(workInProgress); + var _nextState = workInProgress.memoizedState; + var nextIsHidden = _nextState !== null; - var _resolvedProps4 = - workInProgress.elementType === _Component2 - ? _unresolvedProps4 - : resolveDefaultProps(_Component2, _unresolvedProps4); + if (current !== null) { + var _prevState = current.memoizedState; + var prevIsHidden = _prevState !== null; - return mountIncompleteClassComponent( - current, - workInProgress, - _Component2, - _resolvedProps4, - renderLanes - ); - } + if ( + prevIsHidden !== nextIsHidden && // LegacyHidden doesn't do any hiding — it only pre-renders. + !enableLegacyHidden + ) { + workInProgress.flags |= Visibility; + } + } - case SuspenseListComponent: { - return updateSuspenseListComponent(current, workInProgress, renderLanes); + if (!nextIsHidden || (workInProgress.mode & ConcurrentMode) === NoMode) { + bubbleProperties(workInProgress); + } else { + // Don't bubble properties for hidden children unless we're rendering + // at offscreen priority. + if (includesSomeLane(subtreeRenderLanes, OffscreenLane)) { + bubbleProperties(workInProgress); + + { + // Check if there was an insertion or update in the hidden subtree. + // If so, we need to hide those nodes in the commit phase, so + // schedule a visibility effect. + if (workInProgress.subtreeFlags & (Placement | Update)) { + workInProgress.flags |= Visibility; + } + } + } + } + return null; } - case ScopeComponent: { - break; + case CacheComponent: { + return null; } - case OffscreenComponent: { - return updateOffscreenComponent(current, workInProgress, renderLanes); + case TracingMarkerComponent: { + return null; } } @@ -17116,6 +17704,7 @@ function unwindWork(current, workInProgress, renderLanes) { } case HostRoot: { + var root = workInProgress.stateNode; popHostContainer(workInProgress); popTopLevelContextObject(workInProgress); resetWorkInProgressVersions(); @@ -17142,6 +17731,16 @@ function unwindWork(current, workInProgress, renderLanes) { case SuspenseComponent: { popSuspenseContext(workInProgress); + var suspenseState = workInProgress.memoizedState; + + if (suspenseState !== null && suspenseState.dehydrated !== null) { + if (workInProgress.alternate === null) { + throw new Error( + "Threw in newly mounted dehydrated component. This is likely a bug in " + + "React. Please file an issue." + ); + } + } var _flags2 = workInProgress.flags; @@ -17177,7 +17776,6 @@ function unwindWork(current, workInProgress, renderLanes) { case OffscreenComponent: case LegacyHiddenComponent: popRenderLanes(workInProgress); - return null; case CacheComponent: @@ -17207,6 +17805,7 @@ function unwindInterruptedWork(current, interruptedWork, renderLanes) { } case HostRoot: { + var root = interruptedWork.stateNode; popHostContainer(interruptedWork); popTopLevelContextObject(interruptedWork); resetWorkInProgressVersions(); @@ -17238,7 +17837,6 @@ function unwindInterruptedWork(current, interruptedWork, renderLanes) { case OffscreenComponent: case LegacyHiddenComponent: popRenderLanes(interruptedWork); - break; } } @@ -17253,7 +17851,6 @@ var nextEffect = null; // Used for Profiling builds to track updaters. var inProgressLanes = null; var inProgressRoot = null; - function reportUncaughtErrorInDEV(error) { // Wrapping each small part of the commit phase into a guarded // callback is a bit too slow (https://github.com/facebook/react/pull/21666). @@ -17292,7 +17889,6 @@ function safelyCallComponentWillUnmount( try { callComponentWillUnmountWithTimer(current, instance); } catch (error) { - reportUncaughtErrorInDEV(error); captureCommitPhaseError(current, nearestMountedAncestor, error); } } // Capture errors so they don't interrupt mounting. @@ -17320,7 +17916,6 @@ function safelyDetachRef(current, nearestMountedAncestor) { retVal = ref(null); } } catch (error) { - reportUncaughtErrorInDEV(error); captureCommitPhaseError(current, nearestMountedAncestor, error); } @@ -17343,7 +17938,6 @@ function safelyCallDestroy(current, nearestMountedAncestor, destroy) { try { destroy(); } catch (error) { - reportUncaughtErrorInDEV(error); captureCommitPhaseError(current, nearestMountedAncestor, error); } } @@ -17371,7 +17965,7 @@ function commitBeforeMutationEffects_begin() { (fiber.subtreeFlags & BeforeMutationMask) !== NoFlags && child !== null ) { - ensureCorrectReturnPointer(child, fiber); + child.return = fiber; nextEffect = child; } else { commitBeforeMutationEffects_complete(); @@ -17387,7 +17981,6 @@ function commitBeforeMutationEffects_complete() { try { commitBeforeMutationEffectsOnFiber(fiber); } catch (error) { - reportUncaughtErrorInDEV(error); captureCommitPhaseError(fiber, fiber.return, error); } @@ -17395,7 +17988,7 @@ function commitBeforeMutationEffects_complete() { var sibling = fiber.sibling; if (sibling !== null) { - ensureCorrectReturnPointer(sibling, fiber.return); + sibling.return = fiber.return; nextEffect = sibling; return; } @@ -17529,7 +18122,19 @@ function commitHookEffectListUnmount( effect.destroy = undefined; if (destroy !== undefined) { + { + if ((flags & Insertion) !== NoFlags$1) { + setIsRunningInsertionEffect(true); + } + } + safelyCallDestroy(finishedWork, nearestMountedAncestor, destroy); + + { + if ((flags & Insertion) !== NoFlags$1) { + setIsRunningInsertionEffect(false); + } + } } } @@ -17549,8 +18154,21 @@ function commitHookEffectListMount(flags, finishedWork) { do { if ((effect.tag & flags) === flags) { var create = effect.create; + + { + if ((flags & Insertion) !== NoFlags$1) { + setIsRunningInsertionEffect(true); + } + } + effect.destroy = create(); + { + if ((flags & Insertion) !== NoFlags$1) { + setIsRunningInsertionEffect(false); + } + } + { var destroy = effect.destroy; @@ -17964,7 +18582,8 @@ function commitLayoutEffectOnFiber( case IncompleteClassComponent: case ScopeComponent: case OffscreenComponent: - case LegacyHiddenComponent: { + case LegacyHiddenComponent: + case TracingMarkerComponent: { break; } @@ -17998,22 +18617,31 @@ function hideOrUnhideAllChildren(finishedWork, isHidden) { if (node.tag === HostComponent) { if (hostSubtreeRoot === null) { hostSubtreeRoot = node; - var instance = node.stateNode; - if (isHidden) { - hideInstance(instance); - } else { - unhideInstance(node.stateNode, node.memoizedProps); + try { + var instance = node.stateNode; + + if (isHidden) { + hideInstance(instance); + } else { + unhideInstance(node.stateNode, node.memoizedProps); + } + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); } } } else if (node.tag === HostText) { if (hostSubtreeRoot === null) { - var _instance3 = node.stateNode; + try { + var _instance3 = node.stateNode; - if (isHidden) { - hideTextInstance(); - } else { - unhideTextInstance(_instance3, node.memoizedProps); + if (isHidden) { + hideTextInstance(_instance3); + } else { + unhideTextInstance(_instance3, node.memoizedProps); + } + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); } } } else if ( @@ -18109,153 +18737,6 @@ function commitAttachRef(finishedWork) { } } -function commitDetachRef(current) { - var currentRef = current.ref; - - if (currentRef !== null) { - if (typeof currentRef === "function") { - if (current.mode & ProfileMode) { - try { - startLayoutEffectTimer(); - currentRef(null); - } finally { - recordLayoutEffectDuration(current); - } - } else { - currentRef(null); - } - } else { - currentRef.current = null; - } - } -} // User-originating errors (lifecycles and refs) should not interrupt -// deletion, so don't let them throw. Host-originating errors should -// interrupt deletion, so it's okay - -function commitUnmount(finishedRoot, current, nearestMountedAncestor) { - onCommitUnmount(current); - - switch (current.tag) { - case FunctionComponent: - case ForwardRef: - case MemoComponent: - case SimpleMemoComponent: { - var updateQueue = current.updateQueue; - - if (updateQueue !== null) { - var lastEffect = updateQueue.lastEffect; - - if (lastEffect !== null) { - var firstEffect = lastEffect.next; - var effect = firstEffect; - - do { - var _effect = effect, - destroy = _effect.destroy, - tag = _effect.tag; - - if (destroy !== undefined) { - if ((tag & Insertion) !== NoFlags$1) { - safelyCallDestroy(current, nearestMountedAncestor, destroy); - } else if ((tag & Layout) !== NoFlags$1) { - if (current.mode & ProfileMode) { - startLayoutEffectTimer(); - safelyCallDestroy(current, nearestMountedAncestor, destroy); - recordLayoutEffectDuration(current); - } else { - safelyCallDestroy(current, nearestMountedAncestor, destroy); - } - } - } - - effect = effect.next; - } while (effect !== firstEffect); - } - } - - return; - } - - case ClassComponent: { - safelyDetachRef(current, nearestMountedAncestor); - var instance = current.stateNode; - - if (typeof instance.componentWillUnmount === "function") { - safelyCallComponentWillUnmount( - current, - nearestMountedAncestor, - instance - ); - } - - return; - } - - case HostComponent: { - safelyDetachRef(current, nearestMountedAncestor); - return; - } - - case HostPortal: { - // TODO: this is recursive. - // We are also not using this parent because - // the portal will get pushed immediately. - { - unmountHostComponents(finishedRoot, current, nearestMountedAncestor); - } - - return; - } - - case DehydratedFragment: { - return; - } - - case ScopeComponent: { - return; - } - } -} - -function commitNestedUnmounts(finishedRoot, root, nearestMountedAncestor) { - // While we're inside a removed host node we don't want to call - // removeChild on the inner nodes because they're removed by the top - // call anyway. We also want to call componentWillUnmount on all - // composites before this host node is removed from the tree. Therefore - // we do an inner loop while we're still inside the host node. - var node = root; - - while (true) { - commitUnmount(finishedRoot, node, nearestMountedAncestor); // Visit children because they may contain more composite or host nodes. - // Skip portals because commitUnmount() currently visits them recursively. - - if ( - node.child !== null && // If we use mutation we drill down into portals using commitUnmount above. - // If we don't use mutation we drill down into portals here instead. - node.tag !== HostPortal - ) { - node.child.return = node; - node = node.child; - continue; - } - - if (node === root) { - return; - } - - while (node.sibling === null) { - if (node.return === null || node.return === root) { - return; - } - - node = node.return; - } - - node.sibling.return = node.return; - node = node.sibling; - } -} - 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. @@ -18505,231 +18986,282 @@ function insertOrAppendPlacementNode(node, before, parent) { } } } -} - -function unmountHostComponents(finishedRoot, current, nearestMountedAncestor) { - // We only have the top Fiber that was deleted but we need to recurse down its - // children to find all the terminal nodes. - var node = current; // Each iteration, currentParent is populated with node's host parent if not - // currentParentIsValid. +} // These are tracked on the stack as we recursively traverse a +// deleted subtree. +// TODO: Update these during the whole mutation phase, not just during +// a deletion. - var currentParentIsValid = false; // Note: these two variables *must* always be updated together. +var hostParent = null; +var hostParentIsContainer = false; - var currentParent; - var currentParentIsContainer; - - while (true) { - if (!currentParentIsValid) { - var parent = node.return; - - findParent: while (true) { - if (parent === null) { - throw new Error( - "Expected to find a host parent. This error is likely caused by " + - "a bug in React. Please file an issue." - ); +function commitDeletionEffects(root, returnFiber, deletedFiber) { + { + // We only have the top Fiber that was deleted but we need to recurse down its + // children to find all the terminal nodes. + // Recursively delete all host nodes from the parent, detach refs, clean + // up mounted layout effects, and call componentWillUnmount. + // We only need to remove the topmost host child in each branch. But then we + // still need to keep traversing to unmount effects, refs, and cWU. TODO: We + // could split this into two separate traversals functions, where the second + // one doesn't include any removeChild logic. This is maybe the same + // function as "disappearLayoutEffects" (or whatever that turns into after + // the layout phase is refactored to use recursion). + // Before starting, find the nearest host parent on the stack so we know + // which instance/container to remove the children from. + // TODO: Instead of searching up the fiber return path on every deletion, we + // can track the nearest host component on the JS stack as we traverse the + // tree during the commit phase. This would make insertions faster, too. + var parent = returnFiber; + + findParent: while (parent !== null) { + switch (parent.tag) { + case HostComponent: { + hostParent = parent.stateNode; + hostParentIsContainer = false; + break findParent; } - var parentStateNode = parent.stateNode; - - switch (parent.tag) { - case HostComponent: - currentParent = parentStateNode; - currentParentIsContainer = false; - break findParent; - - case HostRoot: - currentParent = parentStateNode.containerInfo; - currentParentIsContainer = true; - break findParent; - - case HostPortal: - currentParent = parentStateNode.containerInfo; - currentParentIsContainer = true; - break findParent; + case HostRoot: { + hostParent = parent.stateNode.containerInfo; + hostParentIsContainer = true; + break findParent; } - parent = parent.return; - } - - currentParentIsValid = true; - } - - if (node.tag === HostComponent || node.tag === HostText) { - commitNestedUnmounts(finishedRoot, node, nearestMountedAncestor); // After all the children have unmounted, it is now safe to remove the - // node from the tree. - - if (currentParentIsContainer) { - removeChildFromContainer(currentParent, node.stateNode); - } else { - removeChild(currentParent, node.stateNode); - } // Don't visit children because we already visited them. - } else if (node.tag === HostPortal) { - if (node.child !== null) { - // When we go into a portal, it becomes the parent to remove from. - // We will reassign it back when we pop the portal on the way up. - currentParent = node.stateNode.containerInfo; - currentParentIsContainer = true; // Visit children because portals might contain host components. - - node.child.return = node; - node = node.child; - continue; + case HostPortal: { + hostParent = parent.stateNode.containerInfo; + hostParentIsContainer = true; + break findParent; + } } - } else { - commitUnmount(finishedRoot, node, nearestMountedAncestor); // Visit children because we may find more host components below. - if (node.child !== null) { - node.child.return = node; - node = node.child; - continue; - } + parent = parent.return; } - if (node === current) { - return; + if (hostParent === null) { + throw new Error( + "Expected to find a host parent. This error is likely caused by " + + "a bug in React. Please file an issue." + ); } - while (node.sibling === null) { - if (node.return === null || node.return === current) { - return; - } + commitDeletionEffectsOnFiber(root, returnFiber, deletedFiber); + hostParent = null; + hostParentIsContainer = false; + } - node = node.return; + detachFiberMutation(deletedFiber); +} - if (node.tag === HostPortal) { - // When we go out of the portal, we need to restore the parent. - // Since we don't keep a stack of them, we will search for it. - currentParentIsValid = false; - } - } +function recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + parent +) { + // TODO: Use a static flag to skip trees that don't have unmount effects + var child = parent.child; - node.sibling.return = node.return; - node = node.sibling; + while (child !== null) { + commitDeletionEffectsOnFiber(finishedRoot, nearestMountedAncestor, child); + child = child.sibling; } } -function commitDeletion(finishedRoot, current, nearestMountedAncestor) { - { - // Recursively delete all host nodes from the parent. - // Detach refs and call componentWillUnmount() on the whole subtree. - unmountHostComponents(finishedRoot, current, nearestMountedAncestor); - } - - detachFiberMutation(current); -} +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 commitWork(current, finishedWork) { - switch (finishedWork.tag) { - case FunctionComponent: - case ForwardRef: - case MemoComponent: - case SimpleMemoComponent: { - commitHookEffectListUnmount( - Insertion | HasEffect, - finishedWork, - finishedWork.return - ); - commitHookEffectListMount(Insertion | HasEffect, finishedWork); // 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. + switch (deletedFiber.tag) { + case HostComponent: { + { + safelyDetachRef(deletedFiber, nearestMountedAncestor); + } // Intentional fallthrough to next branch + } + // eslint-disable-next-line-no-fallthrough - if (finishedWork.mode & ProfileMode) { - try { - startLayoutEffectTimer(); - commitHookEffectListUnmount( - Layout | HasEffect, - finishedWork, - finishedWork.return - ); - } finally { - recordLayoutEffectDuration(finishedWork); - } - } else { - commitHookEffectListUnmount( - Layout | HasEffect, - finishedWork, - finishedWork.return + case HostText: { + // We only need to remove the nearest host child. Set the host parent + // to `null` on the stack to indicate that nested children don't + // need to be removed. + { + var prevHostParent = hostParent; + var prevHostParentIsContainer = hostParentIsContainer; + hostParent = null; + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber ); + hostParent = prevHostParent; + hostParentIsContainer = prevHostParentIsContainer; + + if (hostParent !== null) { + // Now that all the child effects have unmounted, we can remove the + // node from the tree. + if (hostParentIsContainer) { + removeChildFromContainer(hostParent, deletedFiber.stateNode); + } else { + removeChild(hostParent, deletedFiber.stateNode); + } + } } return; } - case ClassComponent: { - return; - } - - case HostComponent: { - var instance = finishedWork.stateNode; - - if (instance != null) { - // Commit the work prepared earlier. - var newProps = finishedWork.memoizedProps; // For hydration we reuse the update path but we treat the oldProps - // as the newProps. The updatePayload will contain the real change in - // this case. - - var oldProps = current !== null ? current.memoizedProps : newProps; - var type = finishedWork.type; // TODO: Type the updateQueue to be specific to host components. - - var updatePayload = finishedWork.updateQueue; - finishedWork.updateQueue = null; + case DehydratedFragment: { + // Delete the dehydrated suspense boundary and all of its content. - if (updatePayload !== null) { - commitUpdate(instance, updatePayload, type, oldProps, newProps); + { + if (hostParent !== null) { + if (hostParentIsContainer) { + clearSuspenseBoundaryFromContainer( + hostParent, + deletedFiber.stateNode + ); + } else { + clearSuspenseBoundary(hostParent, deletedFiber.stateNode); + } } } return; } - case HostText: { - if (finishedWork.stateNode === null) { - throw new Error( - "This should have a text node initialized. This error is likely " + - "caused by a bug in React. Please file an issue." + case HostPortal: { + { + // When we go into a portal, it becomes the parent to remove from. + var _prevHostParent = hostParent; + var _prevHostParentIsContainer = hostParentIsContainer; + hostParent = deletedFiber.stateNode.containerInfo; + hostParentIsContainer = true; + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber ); + hostParent = _prevHostParent; + hostParentIsContainer = _prevHostParentIsContainer; } - var textInstance = finishedWork.stateNode; - var newText = finishedWork.memoizedProps; // For hydration we reuse the update path but we treat the oldProps - // as the newProps. The updatePayload will contain the real change in - // this case. - - var oldText = current !== null ? current.memoizedProps : newText; - commitTextUpdate(textInstance, oldText, newText); return; } - case HostRoot: { + case FunctionComponent: + case ForwardRef: + case MemoComponent: + case SimpleMemoComponent: { + { + var updateQueue = deletedFiber.updateQueue; + + if (updateQueue !== null) { + var lastEffect = updateQueue.lastEffect; + + if (lastEffect !== null) { + var firstEffect = lastEffect.next; + var effect = firstEffect; + + do { + var _effect = effect, + destroy = _effect.destroy, + tag = _effect.tag; + + if (destroy !== undefined) { + if ((tag & Insertion) !== NoFlags$1) { + safelyCallDestroy( + deletedFiber, + nearestMountedAncestor, + destroy + ); + } else if ((tag & Layout) !== NoFlags$1) { + if (deletedFiber.mode & ProfileMode) { + startLayoutEffectTimer(); + safelyCallDestroy( + deletedFiber, + nearestMountedAncestor, + destroy + ); + recordLayoutEffectDuration(deletedFiber); + } else { + safelyCallDestroy( + deletedFiber, + nearestMountedAncestor, + destroy + ); + } + } + } + + effect = effect.next; + } while (effect !== firstEffect); + } + } + } + + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); return; } - case Profiler: { + case ClassComponent: { + { + safelyDetachRef(deletedFiber, nearestMountedAncestor); + var instance = deletedFiber.stateNode; + + if (typeof instance.componentWillUnmount === "function") { + safelyCallComponentWillUnmount( + deletedFiber, + nearestMountedAncestor, + instance + ); + } + } + + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); return; } - case SuspenseComponent: { - commitSuspenseCallback(finishedWork); - attachSuspenseRetryListeners(finishedWork); + case ScopeComponent: { + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); return; } - case SuspenseListComponent: { - attachSuspenseRetryListeners(finishedWork); - return; + case OffscreenComponent: { + { + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + } + + break; } - case IncompleteClassComponent: { + default: { + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); return; } } - - throw new Error( - "This unit of work tag should not have side-effects. This error is " + - "likely caused by a bug in React. Please file an issue." - ); } function commitSuspenseCallback(finishedWork) { @@ -18776,121 +19308,279 @@ function attachSuspenseRetryListeners(finishedWork) { }); } } // This function detects when a Suspense boundary goes from visible to hidden. - -function commitResetTextContent(current) { - resetTextContent(current.stateNode); -} - -function commitMutationEffects(root, firstChild, committedLanes) { +function commitMutationEffects(root, finishedWork, committedLanes) { inProgressLanes = committedLanes; inProgressRoot = root; - nextEffect = firstChild; - commitMutationEffects_begin(root, committedLanes); + setCurrentFiber(finishedWork); + commitMutationEffectsOnFiber(finishedWork, root); + setCurrentFiber(finishedWork); inProgressLanes = null; inProgressRoot = null; } -function commitMutationEffects_begin(root, lanes) { - while (nextEffect !== null) { - var fiber = nextEffect; // TODO: Should wrap this in flags check, too, as optimization +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); + } + } + } + + var prevDebugFiber = getCurrentFiber(); - var deletions = fiber.deletions; + if (parentFiber.subtreeFlags & MutationMask) { + var child = parentFiber.child; - if (deletions !== null) { - for (var i = 0; i < deletions.length; i++) { - var childToDelete = deletions[i]; + while (child !== null) { + setCurrentFiber(child); + commitMutationEffectsOnFiber(child, root); + child = child.sibling; + } + } + + setCurrentFiber(prevDebugFiber); +} + +function commitMutationEffectsOnFiber(finishedWork, root, lanes) { + var current = finishedWork.alternate; + var flags = finishedWork.flags; // The effect flag should be checked *after* we refine the type of fiber, + // because the fiber tag is more specific. An exception is any flag related + // to reconcilation, because those can be set on all fiber types. + + switch (finishedWork.tag) { + case FunctionComponent: + case ForwardRef: + case MemoComponent: + case SimpleMemoComponent: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + if (flags & Update) { try { - commitDeletion(root, childToDelete, fiber); + commitHookEffectListUnmount( + Insertion | HasEffect, + finishedWork, + finishedWork.return + ); + commitHookEffectListMount(Insertion | HasEffect, finishedWork); } catch (error) { - reportUncaughtErrorInDEV(error); - captureCommitPhaseError(childToDelete, fiber, error); + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } // Layout effects are destroyed during the mutation phase so that all + // destroy functions for all fibers are called before any create functions. + // This prevents sibling component effects from interfering with each other, + // e.g. a destroy function in one component should never override a ref set + // by a create function in another component during the same commit. + + if (finishedWork.mode & ProfileMode) { + try { + startLayoutEffectTimer(); + commitHookEffectListUnmount( + Layout | HasEffect, + finishedWork, + finishedWork.return + ); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } + + recordLayoutEffectDuration(finishedWork); + } else { + try { + commitHookEffectListUnmount( + Layout | HasEffect, + finishedWork, + finishedWork.return + ); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } } } + + return; } - var child = fiber.child; + case ClassComponent: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); - if ((fiber.subtreeFlags & MutationMask) !== NoFlags && child !== null) { - ensureCorrectReturnPointer(child, fiber); - nextEffect = child; - } else { - commitMutationEffects_complete(root, lanes); + if (flags & Ref) { + if (current !== null) { + safelyDetachRef(current, current.return); + } + } + + return; } - } -} -function commitMutationEffects_complete(root, lanes) { - while (nextEffect !== null) { - var fiber = nextEffect; - setCurrentFiber(fiber); + case HostComponent: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); - try { - commitMutationEffectsOnFiber(fiber, root, lanes); - } catch (error) { - reportUncaughtErrorInDEV(error); - captureCommitPhaseError(fiber, fiber.return, error); - } + if (flags & Ref) { + if (current !== null) { + safelyDetachRef(current, current.return); + } + } - resetCurrentFiber(); - var sibling = fiber.sibling; + { + // TODO: ContentReset gets cleared by the children during the commit + // phase. This is a refactor hazard because it means we must read + // flags the flags after `commitReconciliationEffects` has already run; + // the order matters. We should refactor so that ContentReset does not + // rely on mutating the flag during commit. Like by setting a flag + // during the render phase instead. + if (finishedWork.flags & ContentReset) { + var instance = finishedWork.stateNode; + + try { + resetTextContent(instance); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } + } + + if (flags & Update) { + var _instance4 = finishedWork.stateNode; + + if (_instance4 != null) { + // Commit the work prepared earlier. + var newProps = finishedWork.memoizedProps; // For hydration we reuse the update path but we treat the oldProps + // as the newProps. The updatePayload will contain the real change in + // this case. + + var oldProps = current !== null ? current.memoizedProps : newProps; + var type = finishedWork.type; // TODO: Type the updateQueue to be specific to host components. + + var updatePayload = finishedWork.updateQueue; + finishedWork.updateQueue = null; + + if (updatePayload !== null) { + try { + commitUpdate( + _instance4, + updatePayload, + type, + oldProps, + newProps, + finishedWork + ); + } catch (error) { + captureCommitPhaseError( + finishedWork, + finishedWork.return, + error + ); + } + } + } + } + } - if (sibling !== null) { - ensureCorrectReturnPointer(sibling, fiber.return); - nextEffect = sibling; return; } - nextEffect = fiber.return; - } -} + case HostText: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); -function commitMutationEffectsOnFiber(finishedWork, root, lanes) { - // TODO: The factoring of this phase could probably be improved. Consider - // switching on the type of work before checking the flags. That's what - // we do in all the other phases. I think this one is only different - // because of the shared reconciliation logic below. - var flags = finishedWork.flags; + if (flags & Update) { + { + if (finishedWork.stateNode === null) { + throw new Error( + "This should have a text node initialized. This error is likely " + + "caused by a bug in React. Please file an issue." + ); + } - if (flags & ContentReset) { - commitResetTextContent(finishedWork); - } + var textInstance = finishedWork.stateNode; + var newText = finishedWork.memoizedProps; // For hydration we reuse the update path but we treat the oldProps + // as the newProps. The updatePayload will contain the real change in + // this case. - if (flags & Ref) { - var current = finishedWork.alternate; + var oldText = current !== null ? current.memoizedProps : newText; - if (current !== null) { - commitDetachRef(current); + try { + commitTextUpdate(textInstance, oldText, newText); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } + } + } + + return; } - } - if (flags & Visibility) { - switch (finishedWork.tag) { - case SuspenseComponent: { - var newState = finishedWork.memoizedState; + case HostRoot: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + + return; + } + + case HostPortal: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(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 _current = finishedWork.alternate; - var wasHidden = _current !== null && _current.memoizedState !== null; + 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); + } + + attachSuspenseRetryListeners(finishedWork); } - case OffscreenComponent: { - var _newState = finishedWork.memoizedState; + return; + } - var _isHidden = _newState !== null; + case OffscreenComponent: { + var _wasHidden = current !== null && current.memoizedState !== null; + + { + recursivelyTraverseMutationEffects(root, finishedWork); + } - var _current2 = finishedWork.alternate; + commitReconciliationEffects(finishedWork); + + if (flags & Visibility) { + var _newState = finishedWork.memoizedState; - var _wasHidden = _current2 !== null && _current2.memoizedState !== null; + var _isHidden = _newState !== null; var offscreenBoundary = finishedWork; @@ -18900,55 +19590,54 @@ function commitMutationEffectsOnFiber(finishedWork, root, lanes) { hideOrUnhideAllChildren(offscreenBoundary, _isHidden); } } + + return; } - } // The following switch statement is only concerned about placement, - // updates, and deletions. To avoid needing to add a case for every possible - // bitmap value, we remove the secondary effects from the effect tag and - // switch on that value. - var primaryFlags = flags & (Placement | Update | Hydrating); + case SuspenseListComponent: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); - switch (primaryFlags) { - case Placement: { - commitPlacement(finishedWork); // Clear the "placement" from effect tag so that we know that this is - // inserted, before any life-cycles like componentDidMount gets called. - // TODO: findDOMNode doesn't rely on this any more but isMounted does - // and isMounted is deprecated anyway so we should be able to kill this. + if (flags & Update) { + attachSuspenseRetryListeners(finishedWork); + } - finishedWork.flags &= ~Placement; - break; + return; } - case PlacementAndUpdate: { - // Placement - commitPlacement(finishedWork); // Clear the "placement" from effect tag so that we know that this is - // inserted, before any life-cycles like componentDidMount gets called. - - finishedWork.flags &= ~Placement; // Update - - var _current3 = finishedWork.alternate; - commitWork(_current3, finishedWork); - break; + case ScopeComponent: { + return; } - case Hydrating: { - finishedWork.flags &= ~Hydrating; - break; + default: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + return; } + } +} - case HydratingAndUpdate: { - finishedWork.flags &= ~Hydrating; // Update +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; - var _current4 = finishedWork.alternate; - commitWork(_current4, finishedWork); - break; - } + if (flags & Placement) { + try { + commitPlacement(finishedWork); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } // Clear the "placement" from effect tag so that we know that this is + // inserted, before any life-cycles like componentDidMount gets called. + // TODO: findDOMNode doesn't rely on this any more but isMounted does + // and isMounted is deprecated anyway so we should be able to kill this. - case Update: { - var _current5 = finishedWork.alternate; - commitWork(_current5, finishedWork); - break; - } + finishedWork.flags &= ~Placement; + } + + if (flags & Hydrating) { + finishedWork.flags &= ~Hydrating; } } @@ -18970,7 +19659,7 @@ function commitLayoutEffects_begin(subtreeRoot, root, committedLanes) { var firstChild = fiber.child; if ((fiber.subtreeFlags & LayoutMask) !== NoFlags && firstChild !== null) { - ensureCorrectReturnPointer(firstChild, fiber); + firstChild.return = fiber; nextEffect = firstChild; } else { commitLayoutMountEffects_complete(subtreeRoot, root, committedLanes); @@ -18989,7 +19678,6 @@ function commitLayoutMountEffects_complete(subtreeRoot, root, committedLanes) { try { commitLayoutEffectOnFiber(root, current, fiber, committedLanes); } catch (error) { - reportUncaughtErrorInDEV(error); captureCommitPhaseError(fiber, fiber.return, error); } @@ -19004,7 +19692,7 @@ function commitLayoutMountEffects_complete(subtreeRoot, root, committedLanes) { var sibling = fiber.sibling; if (sibling !== null) { - ensureCorrectReturnPointer(sibling, fiber.return); + sibling.return = fiber.return; nextEffect = sibling; return; } @@ -19013,26 +19701,51 @@ function commitLayoutMountEffects_complete(subtreeRoot, root, committedLanes) { } } -function commitPassiveMountEffects(root, finishedWork) { +function commitPassiveMountEffects( + root, + finishedWork, + committedLanes, + committedTransitions +) { nextEffect = finishedWork; - commitPassiveMountEffects_begin(finishedWork, root); + commitPassiveMountEffects_begin( + finishedWork, + root, + committedLanes, + committedTransitions + ); } -function commitPassiveMountEffects_begin(subtreeRoot, root) { +function commitPassiveMountEffects_begin( + subtreeRoot, + root, + committedLanes, + committedTransitions +) { while (nextEffect !== null) { var fiber = nextEffect; var firstChild = fiber.child; if ((fiber.subtreeFlags & PassiveMask) !== NoFlags && firstChild !== null) { - ensureCorrectReturnPointer(firstChild, fiber); + firstChild.return = fiber; nextEffect = firstChild; } else { - commitPassiveMountEffects_complete(subtreeRoot, root); + commitPassiveMountEffects_complete( + subtreeRoot, + root, + committedLanes, + committedTransitions + ); } } } -function commitPassiveMountEffects_complete(subtreeRoot, root) { +function commitPassiveMountEffects_complete( + subtreeRoot, + root, + committedLanes, + committedTransitions +) { while (nextEffect !== null) { var fiber = nextEffect; @@ -19040,9 +19753,13 @@ function commitPassiveMountEffects_complete(subtreeRoot, root) { setCurrentFiber(fiber); try { - commitPassiveMountOnFiber(root, fiber); + commitPassiveMountOnFiber( + root, + fiber, + committedLanes, + committedTransitions + ); } catch (error) { - reportUncaughtErrorInDEV(error); captureCommitPhaseError(fiber, fiber.return, error); } @@ -19057,7 +19774,7 @@ function commitPassiveMountEffects_complete(subtreeRoot, root) { var sibling = fiber.sibling; if (sibling !== null) { - ensureCorrectReturnPointer(sibling, fiber.return); + sibling.return = fiber.return; nextEffect = sibling; return; } @@ -19066,7 +19783,12 @@ function commitPassiveMountEffects_complete(subtreeRoot, root) { } } -function commitPassiveMountOnFiber(finishedRoot, finishedWork) { +function commitPassiveMountOnFiber( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions +) { switch (finishedWork.tag) { case FunctionComponent: case ForwardRef: @@ -19145,7 +19867,7 @@ function commitPassiveUnmountEffects_begin() { } if ((fiber.subtreeFlags & PassiveMask) !== NoFlags && child !== null) { - ensureCorrectReturnPointer(child, fiber); + child.return = fiber; nextEffect = child; } else { commitPassiveUnmountEffects_complete(); @@ -19166,7 +19888,7 @@ function commitPassiveUnmountEffects_complete() { var sibling = fiber.sibling; if (sibling !== null) { - ensureCorrectReturnPointer(sibling, fiber.return); + sibling.return = fiber.return; nextEffect = sibling; return; } @@ -19216,7 +19938,7 @@ function commitPassiveUnmountEffectsInsideOfDeletedTree_begin( // do this, still need to handle `deletedTreeCleanUpLevel` correctly.) if (child !== null) { - ensureCorrectReturnPointer(child, fiber); + child.return = fiber; nextEffect = child; } else { commitPassiveUnmountEffectsInsideOfDeletedTree_complete( @@ -19247,7 +19969,7 @@ function commitPassiveUnmountEffectsInsideOfDeletedTree_complete( } if (sibling !== null) { - ensureCorrectReturnPointer(sibling, returnFiber); + sibling.return = returnFiber; nextEffect = sibling; return; } @@ -19275,23 +19997,6 @@ function commitPassiveUnmountInsideDeletedTreeOnFiber( break; } } -} - -var didWarnWrongReturnPointer = false; - -function ensureCorrectReturnPointer(fiber, expectedReturnFiber) { - { - if (!didWarnWrongReturnPointer && fiber.return !== expectedReturnFiber) { - didWarnWrongReturnPointer = true; - - error( - "Internal React error: Return pointer is inconsistent " + "with parent." - ); - } - } // TODO: Remove this assignment once we're confident that it won't break - // anything, by checking the warning logs for the above invariant - - fiber.return = expectedReturnFiber; } // TODO: Reuse reappearLayoutEffects traversal here? var COMPONENT_TYPE = 0; @@ -19417,6 +20122,7 @@ var workInProgressRootRenderTargetTime = Infinity; // How long a render is suppo // suspense heuristics and opt out of rendering more content. var RENDER_TIMEOUT_MS = 500; +var workInProgressTransitions = null; function resetRenderTimer() { workInProgressRootRenderTargetTime = now() + RENDER_TIMEOUT_MS; @@ -19432,17 +20138,22 @@ var rootDoesHavePassiveEffects = false; var rootWithPendingPassiveEffects = null; var pendingPassiveEffectsLanes = NoLanes; var pendingPassiveProfilerEffects = []; +var pendingPassiveTransitions = null; // Use these to prevent an infinite loop of nested updates var NESTED_UPDATE_LIMIT = 50; var nestedUpdateCount = 0; var rootWithNestedUpdates = null; +var isFlushingPassiveEffects = false; +var didScheduleUpdateDuringPassiveEffects = false; var NESTED_PASSIVE_UPDATE_LIMIT = 50; -var nestedPassiveUpdateCount = 0; // If two updates are scheduled within the same event, we should treat their +var nestedPassiveUpdateCount = 0; +var rootWithPassiveNestedUpdates = null; // If two updates are scheduled within the same event, we should treat their // event times as simultaneous, even if the actual clock time has advanced // between the first and second call. var currentEventTime = NoTimestamp; var currentEventTransitionLane = NoLanes; +var isRunningInsertionEffect = false; function getWorkInProgressRoot() { return workInProgressRoot; } @@ -19545,10 +20256,23 @@ function requestRetryLane(fiber) { function scheduleUpdateOnFiber(fiber, lane, eventTime) { checkForNestedUpdates(); + + { + if (isRunningInsertionEffect) { + error("useInsertionEffect must not schedule updates."); + } + } + var root = markUpdateLaneFromFiberToRoot(fiber, lane); if (root === null) { return null; + } + + { + if (isFlushingPassiveEffects) { + didScheduleUpdateDuringPassiveEffects = true; + } } // Mark that the root has a pending update. markRootUpdated(root, lane, eventTime); @@ -19675,7 +20399,12 @@ function isInterleavedUpdate(fiber, lane) { // TODO: Optimize slightly by comparing to root that fiber belongs to. // Requires some refactoring. Not a big deal though since it's rare for // concurrent apps to have more than a single root. - workInProgressRoot !== null && + (workInProgressRoot !== null || // If the interleaved updates queue hasn't been cleared yet, then + // we should treat this as an interleaved update, too. This is also a + // defensive coding measure in case a new update comes in between when + // rendering has finished and when the interleaved updates are transferred + // to the main queue. + hasInterleavedUpdates()) && (fiber.mode & ConcurrentMode) !== NoMode && // If this is a render phase update (i.e. UNSAFE_componentWillReceiveProps), // then don't treat this as an interleaved update. This pattern is // accompanied by a warning but we haven't fully deprecated it yet. We can @@ -20009,7 +20738,11 @@ 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(root, workInProgressRootRecoverableErrors); + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); break; } @@ -20049,14 +20782,23 @@ function finishConcurrentRender(root, exitStatus, lanes) { // immediately, wait for more data to arrive. root.timeoutHandle = scheduleTimeout( - commitRoot.bind(null, root, workInProgressRootRecoverableErrors), + commitRoot.bind( + null, + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ), msUntilTimeout ); break; } } // The work expired. Commit immediately. - commitRoot(root, workInProgressRootRecoverableErrors); + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); break; } @@ -20087,20 +20829,33 @@ function finishConcurrentRender(root, exitStatus, lanes) { // Instead of committing the fallback immediately, wait for more data // to arrive. root.timeoutHandle = scheduleTimeout( - commitRoot.bind(null, root, workInProgressRootRecoverableErrors), + commitRoot.bind( + null, + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ), _msUntilTimeout ); break; } } // Commit the placeholder. - commitRoot(root, workInProgressRootRecoverableErrors); + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); break; } case RootCompleted: { // The work completed. Ready to commit. - commitRoot(root, workInProgressRootRecoverableErrors); + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); break; } @@ -20235,7 +20990,11 @@ function performSyncWorkOnRoot(root) { var finishedWork = root.current.alternate; root.finishedWork = finishedWork; root.finishedLanes = lanes; - commitRoot(root, workInProgressRootRecoverableErrors); // Before exiting, make sure there's a callback scheduled for the next + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); // Before exiting, make sure there's a callback scheduled for the next // pending level. ensureRootIsScheduled(root, now()); @@ -20542,6 +21301,8 @@ function renderRootSync(root, lanes) { movePendingFibersToMemoized(root, lanes); } } + + workInProgressTransitions = getTransitionsForLanes(); prepareFreshStack(root, lanes); } @@ -20602,6 +21363,8 @@ function renderRootConcurrent(root, lanes) { movePendingFibersToMemoized(root, lanes); } } + + workInProgressTransitions = getTransitionsForLanes(); resetRenderTimer(); prepareFreshStack(root, lanes); } @@ -20760,7 +21523,7 @@ function completeUnitOfWork(unitOfWork) { } } -function commitRoot(root, recoverableErrors) { +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(); @@ -20769,7 +21532,12 @@ function commitRoot(root, recoverableErrors) { try { ReactCurrentBatchConfig$2.transition = null; setCurrentUpdatePriority(DiscreteEventPriority); - commitRootImpl(root, recoverableErrors, previousUpdateLanePriority); + commitRootImpl( + root, + recoverableErrors, + transitions, + previousUpdateLanePriority + ); } finally { ReactCurrentBatchConfig$2.transition = prevTransition; setCurrentUpdatePriority(previousUpdateLanePriority); @@ -20778,7 +21546,12 @@ function commitRoot(root, recoverableErrors) { return null; } -function commitRootImpl(root, recoverableErrors, renderPriorityLevel) { +function commitRootImpl( + root, + recoverableErrors, + transitions, + renderPriorityLevel +) { do { // `flushPassiveEffects` will call `flushSyncUpdateQueue` at the end, which // means `flushPassiveEffects` will sometimes result in additional @@ -20846,6 +21619,13 @@ function commitRootImpl(root, recoverableErrors, renderPriorityLevel) { ) { if (!rootDoesHavePassiveEffects) { rootDoesHavePassiveEffects = true; + // to store it in pendingPassiveTransitions until they get processed + // We need to pass this through as an argument to commitRoot + // because workInProgressTransitions might have changed between + // the previous render and commit if we throttle the commit + // with setTimeout + + pendingPassiveTransitions = transitions; scheduleCallback$1(NormalPriority, function() { flushPassiveEffects(); // This render triggered passive effects: release the root cache pool // *after* passive effects fire to avoid freeing a cache pool that may @@ -20929,6 +21709,11 @@ function commitRootImpl(root, recoverableErrors, renderPriorityLevel) { rootDoesHavePassiveEffects = false; rootWithPendingPassiveEffects = root; pendingPassiveEffectsLanes = lanes; + } else { + { + nestedPassiveUpdateCount = 0; + rootWithPassiveNestedUpdates = null; + } } // Read this again, since an effect might have updated it remainingLanes = root.pendingLanes; // Check if there's remaining work on this root @@ -21056,9 +21841,12 @@ function enqueuePendingPassiveProfilerEffect(fiber) { function flushPassiveEffectsImpl() { if (rootWithPendingPassiveEffects === null) { return false; - } + } // Cache and clear the transitions flag + var transitions = pendingPassiveTransitions; + pendingPassiveTransitions = null; var root = rootWithPendingPassiveEffects; + var lanes = pendingPassiveEffectsLanes; rootWithPendingPassiveEffects = null; // TODO: This is sometimes out of sync with rootWithPendingPassiveEffects. // Figure out why and fix it. It's not causing any known issues (probably // because it's only used for profiling), but it's a refactor hazard. @@ -21069,10 +21857,15 @@ function flushPassiveEffectsImpl() { throw new Error("Cannot flush passive effects while already rendering."); } + { + isFlushingPassiveEffects = true; + didScheduleUpdateDuringPassiveEffects = false; + } + var prevExecutionContext = executionContext; executionContext |= CommitContext; commitPassiveUnmountEffects(root.current); - commitPassiveMountEffects(root, root.current); // TODO: Move to commitPassiveMountEffects + commitPassiveMountEffects(root, root.current, lanes, transitions); // TODO: Move to commitPassiveMountEffects { var profilerEffects = pendingPassiveProfilerEffects; @@ -21085,11 +21878,25 @@ function flushPassiveEffectsImpl() { } executionContext = prevExecutionContext; - flushSyncCallbacks(); // If additional passive effects were scheduled, increment a counter. If this - // exceeds the limit, we'll fire a warning. + flushSyncCallbacks(); + + { + // If additional passive effects were scheduled, increment a counter. If this + // exceeds the limit, we'll fire a warning. + if (didScheduleUpdateDuringPassiveEffects) { + if (root === rootWithPassiveNestedUpdates) { + nestedPassiveUpdateCount++; + } else { + nestedPassiveUpdateCount = 0; + rootWithPassiveNestedUpdates = root; + } + } else { + nestedPassiveUpdateCount = 0; + } - nestedPassiveUpdateCount = - rootWithPendingPassiveEffects === null ? 0 : nestedPassiveUpdateCount + 1; // TODO: Move to commitPassiveMountEffects + isFlushingPassiveEffects = false; + didScheduleUpdateDuringPassiveEffects = false; + } // TODO: Move to commitPassiveMountEffects onPostCommitRoot(root); @@ -21139,6 +21946,11 @@ function captureCommitPhaseErrorOnRoot(rootFiber, sourceFiber, error) { } function captureCommitPhaseError(sourceFiber, nearestMountedAncestor, error$1) { + { + reportUncaughtErrorInDEV(error$1); + setIsRunningInsertionEffect(false); + } + if (sourceFiber.tag === HostRoot) { // Error was thrown at the root. There is no parent, so the root // itself should capture it. @@ -21263,13 +22075,42 @@ function retryTimedOutBoundary(boundaryFiber, retryLane) { ensureRootIsScheduled(root, eventTime); } } + +function retryDehydratedSuspenseBoundary(boundaryFiber) { + var suspenseState = boundaryFiber.memoizedState; + var retryLane = NoLane; + + if (suspenseState !== null) { + retryLane = suspenseState.retryLane; + } + + retryTimedOutBoundary(boundaryFiber, retryLane); +} function resolveRetryWakeable(boundaryFiber, wakeable) { var retryLane = NoLane; // Default var retryCache; - { - retryCache = boundaryFiber.stateNode; + switch (boundaryFiber.tag) { + case SuspenseComponent: + retryCache = boundaryFiber.stateNode; + var suspenseState = boundaryFiber.memoizedState; + + if (suspenseState !== null) { + retryLane = suspenseState.retryLane; + } + + break; + + case SuspenseListComponent: + retryCache = boundaryFiber.stateNode; + break; + + default: + throw new Error( + "Pinged unknown suspense boundary type. " + + "This is probably a bug in React." + ); } if (retryCache !== null) { @@ -21320,6 +22161,7 @@ function checkForNestedUpdates() { { if (nestedPassiveUpdateCount > NESTED_PASSIVE_UPDATE_LIMIT) { nestedPassiveUpdateCount = 0; + rootWithPassiveNestedUpdates = null; error( "Maximum update depth exceeded. This can happen when a component " + @@ -21423,11 +22265,13 @@ var beginWork$1; return beginWork(current, unitOfWork, lanes); } catch (originalError) { if ( - originalError !== null && - typeof originalError === "object" && - typeof originalError.then === "function" + didSuspendOrErrorWhileHydratingDEV() || + (originalError !== null && + typeof originalError === "object" && + typeof originalError.then === "function") ) { - // Don't replay promises. Treat everything else like an error. + // Don't replay promises. + // Don't replay errors if we are hydrating and have already suspended or handled an error throw originalError; } // Keep this code in sync with handleError; any changes here must have // corresponding changes there. @@ -21653,6 +22497,12 @@ function warnIfSuspenseResolutionNotWrappedWithActDEV(root) { } } +function setIsRunningInsertionEffect(isRunning) { + { + isRunningInsertionEffect = isRunning; + } +} + /* eslint-disable react-internal/prod-error-codes */ var resolveFamily = null; // $FlowFixMe Flow gets confused by a WeakSet feature check below. @@ -22787,7 +23637,8 @@ function createFiberRoot( isDehydrated: hydrate, cache: null, // not enabled yet - transitions: null + transitions: null, + pendingSuspenseBoundaries: null }; uninitializedFiber.memoizedState = _initialState; } @@ -22796,7 +23647,7 @@ function createFiberRoot( return root; } -var ReactVersion = "18.0.0-experimental-34aa5cfe0-20220329"; +var ReactVersion = "18.2.0-next-d300cebde-20220601"; function createPortal( children, diff --git a/Libraries/Renderer/implementations/ReactNativeRenderer-prod.js b/Libraries/Renderer/implementations/ReactNativeRenderer-prod.js index 99e8fc66bc97bd..5e26abc86f4451 100644 --- a/Libraries/Renderer/implementations/ReactNativeRenderer-prod.js +++ b/Libraries/Renderer/implementations/ReactNativeRenderer-prod.js @@ -8,7 +8,7 @@ * @nolint * @providesModule ReactNativeRenderer-prod * @preventMunge - * @generated SignedSource<<08a279093988c36b477bd72fa59e144d>> + * @generated SignedSource<<9f59a543175acb00b00023e9ed7d8c38>> */ "use strict"; @@ -1017,7 +1017,7 @@ eventPluginOrder = Array.prototype.slice.call([ "ReactNativeBridgeEventPlugin" ]); recomputePluginOrdering(); -var injectedNamesToPlugins$jscomp$inline_220 = { +var injectedNamesToPlugins$jscomp$inline_225 = { ResponderEventPlugin: ResponderEventPlugin, ReactNativeBridgeEventPlugin: { eventTypes: {}, @@ -1063,33 +1063,33 @@ var injectedNamesToPlugins$jscomp$inline_220 = { } } }, - isOrderingDirty$jscomp$inline_221 = !1, - pluginName$jscomp$inline_222; -for (pluginName$jscomp$inline_222 in injectedNamesToPlugins$jscomp$inline_220) + isOrderingDirty$jscomp$inline_226 = !1, + pluginName$jscomp$inline_227; +for (pluginName$jscomp$inline_227 in injectedNamesToPlugins$jscomp$inline_225) if ( - injectedNamesToPlugins$jscomp$inline_220.hasOwnProperty( - pluginName$jscomp$inline_222 + injectedNamesToPlugins$jscomp$inline_225.hasOwnProperty( + pluginName$jscomp$inline_227 ) ) { - var pluginModule$jscomp$inline_223 = - injectedNamesToPlugins$jscomp$inline_220[pluginName$jscomp$inline_222]; + var pluginModule$jscomp$inline_228 = + injectedNamesToPlugins$jscomp$inline_225[pluginName$jscomp$inline_227]; if ( - !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_222) || - namesToPlugins[pluginName$jscomp$inline_222] !== - pluginModule$jscomp$inline_223 + !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_227) || + namesToPlugins[pluginName$jscomp$inline_227] !== + pluginModule$jscomp$inline_228 ) { - if (namesToPlugins[pluginName$jscomp$inline_222]) + if (namesToPlugins[pluginName$jscomp$inline_227]) throw Error( "EventPluginRegistry: Cannot inject two different event plugins using the same name, `" + - (pluginName$jscomp$inline_222 + "`.") + (pluginName$jscomp$inline_227 + "`.") ); namesToPlugins[ - pluginName$jscomp$inline_222 - ] = pluginModule$jscomp$inline_223; - isOrderingDirty$jscomp$inline_221 = !0; + pluginName$jscomp$inline_227 + ] = pluginModule$jscomp$inline_228; + isOrderingDirty$jscomp$inline_226 = !0; } } -isOrderingDirty$jscomp$inline_221 && recomputePluginOrdering(); +isOrderingDirty$jscomp$inline_226 && recomputePluginOrdering(); var instanceCache = new Map(), instanceProps = new Map(); function getInstanceFromTag(tag) { @@ -1923,6 +1923,12 @@ function getLanesToRetrySynchronouslyOnError(root) { root = root.pendingLanes & -1073741825; return 0 !== root ? root : root & 1073741824 ? 1073741824 : 0; } +function claimNextTransitionLane() { + var lane = nextTransitionLane; + nextTransitionLane <<= 1; + 0 === (nextTransitionLane & 4194240) && (nextTransitionLane = 64); + return lane; +} function createLaneMap(initial) { for (var laneMap = [], i = 0; 31 > i; i++) laneMap.push(initial); return laneMap; @@ -2152,7 +2158,28 @@ function flushSyncCallbacks() { } return null; } -var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig; +var forkStack = [], + forkStackIndex = 0, + treeForkProvider = null, + idStack = [], + idStackIndex = 0, + treeContextProvider = null; +function popTreeContext(workInProgress) { + for (; workInProgress === treeForkProvider; ) + (treeForkProvider = forkStack[--forkStackIndex]), + (forkStack[forkStackIndex] = null), + --forkStackIndex, + (forkStack[forkStackIndex] = null); + for (; workInProgress === treeContextProvider; ) + (treeContextProvider = idStack[--idStackIndex]), + (idStack[idStackIndex] = null), + --idStackIndex, + (idStack[idStackIndex] = null), + --idStackIndex, + (idStack[idStackIndex] = null); +} +var hydrationErrors = null, + ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig; function shallowEqual(objA, objB) { if (objectIs(objA, objB)) return !0; if ( @@ -2309,9 +2336,7 @@ function enqueueUpdate(fiber, update) { var updateQueue = fiber.updateQueue; null !== updateQueue && ((updateQueue = updateQueue.shared), - null !== workInProgressRoot && - 0 !== (fiber.mode & 1) && - 0 === (executionContext & 2) + isInterleavedUpdate(fiber) ? ((fiber = updateQueue.interleaved), null === fiber ? ((update.next = update), @@ -2679,26 +2704,6 @@ function mountClassInstance(workInProgress, ctor, newProps, renderLanes) { "function" === typeof instance.componentDidMount && (workInProgress.flags |= 4); } -var forkStack = [], - forkStackIndex = 0, - treeForkProvider = null, - idStack = [], - idStackIndex = 0, - treeContextProvider = null; -function popTreeContext(workInProgress) { - for (; workInProgress === treeForkProvider; ) - (treeForkProvider = forkStack[--forkStackIndex]), - (forkStack[forkStackIndex] = null), - --forkStackIndex, - (forkStack[forkStackIndex] = null); - for (; workInProgress === treeContextProvider; ) - (treeContextProvider = idStack[--idStackIndex]), - (idStack[idStackIndex] = null), - --idStackIndex, - (idStack[idStackIndex] = null), - --idStackIndex, - (idStack[idStackIndex] = null); -} function coerceRef(returnFiber, current, element) { returnFiber = element.ref; if ( @@ -2761,6 +2766,10 @@ function throwOnInvalidObjectType(returnFiber, newChild) { "). If you meant to render a collection of children, use an array instead." ); } +function resolveLazy(lazyType) { + var init = lazyType._init; + return init(lazyType._payload); +} function ChildReconciler(shouldTrackSideEffects) { function deleteChild(returnFiber, childToDelete) { if (shouldTrackSideEffects) { @@ -2833,7 +2842,14 @@ function ChildReconciler(shouldTrackSideEffects) { lanes, element.key ); - if (null !== current && current.elementType === elementType) + if ( + null !== current && + (current.elementType === elementType || + ("object" === typeof elementType && + null !== elementType && + elementType.$$typeof === REACT_LAZY_TYPE && + resolveLazy(elementType) === current.type)) + ) return ( (lanes = useFiber(current, element.props)), (lanes.ref = coerceRef(returnFiber, current, element)), @@ -2924,6 +2940,9 @@ function ChildReconciler(shouldTrackSideEffects) { (newChild.return = returnFiber), newChild ); + case REACT_LAZY_TYPE: + var init = newChild._init; + return createChild(returnFiber, init(newChild._payload), lanes); } if (isArrayImpl(newChild) || getIteratorFn(newChild)) return ( @@ -2959,6 +2978,11 @@ function ChildReconciler(shouldTrackSideEffects) { return newChild.key === key ? updatePortal(returnFiber, oldFiber, newChild, lanes) : null; + case REACT_LAZY_TYPE: + return ( + (key = newChild._init), + updateSlot(returnFiber, oldFiber, key(newChild._payload), lanes) + ); } if (isArrayImpl(newChild) || getIteratorFn(newChild)) return null !== key @@ -3001,6 +3025,15 @@ function ChildReconciler(shouldTrackSideEffects) { ) || null), updatePortal(returnFiber, existingChildren, newChild, lanes) ); + case REACT_LAZY_TYPE: + var init = newChild._init; + return updateFromMap( + existingChildren, + returnFiber, + newIdx, + init(newChild._payload), + lanes + ); } if (isArrayImpl(newChild) || getIteratorFn(newChild)) return ( @@ -3178,7 +3211,12 @@ function ChildReconciler(shouldTrackSideEffects) { }); return iteratorFn; } - return function(returnFiber, currentFirstChild, newChild, lanes) { + function reconcileChildFibers( + returnFiber, + currentFirstChild, + newChild, + lanes + ) { "object" === typeof newChild && null !== newChild && newChild.type === REACT_FRAGMENT_TYPE && @@ -3206,7 +3244,13 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber = currentFirstChild; break a; } - } else if (child.elementType === key) { + } else if ( + child.elementType === key || + ("object" === typeof key && + null !== key && + key.$$typeof === REACT_LAZY_TYPE && + resolveLazy(key) === child.type) + ) { deleteRemainingChildren(returnFiber, child.sibling); currentFirstChild = useFiber(child, newChild.props); currentFirstChild.ref = coerceRef( @@ -3287,6 +3331,16 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber = currentFirstChild; } return placeSingleChild(returnFiber); + case REACT_LAZY_TYPE: + return ( + (child = newChild._init), + reconcileChildFibers( + returnFiber, + currentFirstChild, + child(newChild._payload), + lanes + ) + ); } if (isArrayImpl(newChild)) return reconcileChildrenArray( @@ -3322,7 +3376,8 @@ function ChildReconciler(shouldTrackSideEffects) { (returnFiber = currentFirstChild)), placeSingleChild(returnFiber)) : deleteRemainingChildren(returnFiber, currentFirstChild); - }; + } + return reconcileChildFibers; } var reconcileChildFibers = ChildReconciler(!0), mountChildFibers = ChildReconciler(!1), @@ -3809,6 +3864,19 @@ function updateMemo(nextCreate, deps) { hook.memoizedState = [nextCreate, deps]; return nextCreate; } +function updateDeferredValueImpl(hook, prevValue, value) { + if (0 === (renderLanes & 21)) + return ( + hook.baseState && ((hook.baseState = !1), (didReceiveUpdate = !0)), + (hook.memoizedState = value) + ); + objectIs(value, prevValue) || + ((value = claimNextTransitionLane()), + (currentlyRenderingFiber$1.lanes |= value), + (workInProgressRootSkippedLanes |= value), + (hook.baseState = !0)); + return prevValue; +} function startTransition(setPending, callback) { var previousPriority = currentUpdatePriority; currentUpdatePriority = @@ -3890,9 +3958,7 @@ function enqueueRenderPhaseUpdate(queue, update) { queue.pending = update; } function enqueueUpdate$1(fiber, queue, update) { - null !== workInProgressRoot && - 0 !== (fiber.mode & 1) && - 0 === (executionContext & 2) + isInterleavedUpdate(fiber) ? ((fiber = queue.interleaved), null === fiber ? ((update.next = update), @@ -3997,29 +4063,14 @@ var ContextOnlyDispatcher = { useState: mountState, useDebugValue: mountDebugValue, useDeferredValue: function(value) { - var _mountState = mountState(value), - prevValue = _mountState[0], - setValue = _mountState[1]; - mountEffect( - function() { - var prevTransition = ReactCurrentBatchConfig$1.transition; - ReactCurrentBatchConfig$1.transition = {}; - try { - setValue(value); - } finally { - ReactCurrentBatchConfig$1.transition = prevTransition; - } - }, - [value] - ); - return prevValue; + return (mountWorkInProgressHook().memoizedState = value); }, useTransition: function() { - var _mountState2 = mountState(!1), - isPending = _mountState2[0]; - _mountState2 = startTransition.bind(null, _mountState2[1]); - mountWorkInProgressHook().memoizedState = _mountState2; - return [isPending, _mountState2]; + var _mountState = mountState(!1), + isPending = _mountState[0]; + _mountState = startTransition.bind(null, _mountState[1]); + mountWorkInProgressHook().memoizedState = _mountState; + return [isPending, _mountState]; }, useMutableSource: function() {}, useSyncExternalStore: function(subscribe, getSnapshot) { @@ -4073,22 +4124,8 @@ var ContextOnlyDispatcher = { }, useDebugValue: mountDebugValue, useDeferredValue: function(value) { - var _updateState = updateReducer(basicStateReducer), - prevValue = _updateState[0], - setValue = _updateState[1]; - updateEffect( - function() { - var prevTransition = ReactCurrentBatchConfig$1.transition; - ReactCurrentBatchConfig$1.transition = {}; - try { - setValue(value); - } finally { - ReactCurrentBatchConfig$1.transition = prevTransition; - } - }, - [value] - ); - return prevValue; + var hook = updateWorkInProgressHook(); + return updateDeferredValueImpl(hook, currentHook.memoizedState, value); }, useTransition: function() { var isPending = updateReducer(basicStateReducer)[0], @@ -4116,22 +4153,10 @@ var ContextOnlyDispatcher = { }, useDebugValue: mountDebugValue, useDeferredValue: function(value) { - var _rerenderState = rerenderReducer(basicStateReducer), - prevValue = _rerenderState[0], - setValue = _rerenderState[1]; - updateEffect( - function() { - var prevTransition = ReactCurrentBatchConfig$1.transition; - ReactCurrentBatchConfig$1.transition = {}; - try { - setValue(value); - } finally { - ReactCurrentBatchConfig$1.transition = prevTransition; - } - }, - [value] - ); - return prevValue; + var hook = updateWorkInProgressHook(); + return null === currentHook + ? (hook.memoizedState = value) + : updateDeferredValueImpl(hook, currentHook.memoizedState, value); }, useTransition: function() { var isPending = rerenderReducer(basicStateReducer)[0], @@ -4228,454 +4253,72 @@ function attachPingListener(root, wakeable, lanes) { (root = pingSuspendedRoot.bind(null, root, wakeable, lanes)), wakeable.then(root, root)); } -var appendAllChildren, updateHostContainer, updateHostComponent, updateHostText; -appendAllChildren = function(parent, workInProgress) { - for (var node = workInProgress.child; null !== node; ) { - if (5 === node.tag || 6 === node.tag) parent._children.push(node.stateNode); - else if (4 !== node.tag && null !== node.child) { - node.child.return = node; - node = node.child; - continue; - } - if (node === workInProgress) break; - for (; null === node.sibling; ) { - if (null === node.return || node.return === workInProgress) return; - node = node.return; - } - node.sibling.return = node.return; - node = node.sibling; - } -}; -updateHostContainer = function() {}; -updateHostComponent = function(current, workInProgress, type, newProps) { - current.memoizedProps !== newProps && - (requiredContext(contextStackCursor$1.current), - (workInProgress.updateQueue = UPDATE_SIGNAL)) && - (workInProgress.flags |= 4); -}; -updateHostText = function(current, workInProgress, oldText, newText) { - oldText !== newText && (workInProgress.flags |= 4); -}; -function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { - switch (renderState.tailMode) { - case "hidden": - hasRenderedATailFallback = renderState.tail; - for (var lastTailNode = null; null !== hasRenderedATailFallback; ) - null !== hasRenderedATailFallback.alternate && - (lastTailNode = hasRenderedATailFallback), - (hasRenderedATailFallback = hasRenderedATailFallback.sibling); - null === lastTailNode - ? (renderState.tail = null) - : (lastTailNode.sibling = null); - break; - case "collapsed": - lastTailNode = renderState.tail; - for (var lastTailNode$35 = null; null !== lastTailNode; ) - null !== lastTailNode.alternate && (lastTailNode$35 = lastTailNode), - (lastTailNode = lastTailNode.sibling); - null === lastTailNode$35 - ? hasRenderedATailFallback || null === renderState.tail - ? (renderState.tail = null) - : (renderState.tail.sibling = null) - : (lastTailNode$35.sibling = null); - } +var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner, + didReceiveUpdate = !1; +function reconcileChildren(current, workInProgress, nextChildren, renderLanes) { + workInProgress.child = + null === current + ? mountChildFibers(workInProgress, null, nextChildren, renderLanes) + : reconcileChildFibers( + workInProgress, + current.child, + nextChildren, + renderLanes + ); } -function bubbleProperties(completedWork) { - var didBailout = - null !== completedWork.alternate && - completedWork.alternate.child === completedWork.child, - newChildLanes = 0, - subtreeFlags = 0; - if (didBailout) - for (var child$36 = completedWork.child; null !== child$36; ) - (newChildLanes |= child$36.lanes | child$36.childLanes), - (subtreeFlags |= child$36.subtreeFlags & 14680064), - (subtreeFlags |= child$36.flags & 14680064), - (child$36.return = completedWork), - (child$36 = child$36.sibling); - else - for (child$36 = completedWork.child; null !== child$36; ) - (newChildLanes |= child$36.lanes | child$36.childLanes), - (subtreeFlags |= child$36.subtreeFlags), - (subtreeFlags |= child$36.flags), - (child$36.return = completedWork), - (child$36 = child$36.sibling); - completedWork.subtreeFlags |= subtreeFlags; - completedWork.childLanes = newChildLanes; - return didBailout; +function updateForwardRef( + current, + workInProgress, + Component, + nextProps, + renderLanes +) { + Component = Component.render; + var ref = workInProgress.ref; + prepareToReadContext(workInProgress, renderLanes); + nextProps = renderWithHooks( + current, + workInProgress, + Component, + nextProps, + ref, + renderLanes + ); + if (null !== current && !didReceiveUpdate) + return ( + (workInProgress.updateQueue = current.updateQueue), + (workInProgress.flags &= -2053), + (current.lanes &= ~renderLanes), + bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) + ); + workInProgress.flags |= 1; + reconcileChildren(current, workInProgress, nextProps, renderLanes); + return workInProgress.child; } -function completeWork(current, workInProgress, renderLanes) { - var newProps = workInProgress.pendingProps; - popTreeContext(workInProgress); - switch (workInProgress.tag) { - case 2: - case 16: - case 15: - case 0: - case 11: - case 7: - case 8: - case 12: - case 9: - case 14: - return bubbleProperties(workInProgress), null; - case 1: - return ( - isContextProvider(workInProgress.type) && popContext(), - bubbleProperties(workInProgress), - null - ); - case 3: +function updateMemoComponent( + current, + workInProgress, + Component, + nextProps, + renderLanes +) { + if (null === current) { + var type = Component.type; + if ( + "function" === typeof type && + !shouldConstruct(type) && + void 0 === type.defaultProps && + null === Component.compare && + void 0 === Component.defaultProps + ) return ( - (newProps = workInProgress.stateNode), - popHostContainer(), - pop(didPerformWorkStackCursor), - pop(contextStackCursor), - resetWorkInProgressVersions(), - newProps.pendingContext && - ((newProps.context = newProps.pendingContext), - (newProps.pendingContext = null)), - (null !== current && null !== current.child) || - null === current || - (current.memoizedState.isDehydrated && - 0 === (workInProgress.flags & 256)) || - (workInProgress.flags |= 1024), - updateHostContainer(current, workInProgress), - bubbleProperties(workInProgress), - null - ); - case 5: - popHostContext(workInProgress); - renderLanes = requiredContext(rootInstanceStackCursor.current); - var type = workInProgress.type; - if (null !== current && null != workInProgress.stateNode) - updateHostComponent( + (workInProgress.tag = 15), + (workInProgress.type = type), + updateSimpleMemoComponent( current, workInProgress, type, - newProps, - renderLanes - ), - current.ref !== workInProgress.ref && (workInProgress.flags |= 512); - else { - if (!newProps) { - if (null === workInProgress.stateNode) - throw Error( - "We must have new props for new mounts. This error is likely caused by a bug in React. Please file an issue." - ); - bubbleProperties(workInProgress); - return null; - } - requiredContext(contextStackCursor$1.current); - current = allocateTag(); - type = getViewConfigForType(type); - var updatePayload = diffProperties( - null, - emptyObject, - newProps, - type.validAttributes - ); - ReactNativePrivateInterface.UIManager.createView( - current, - type.uiViewClassName, - renderLanes, - updatePayload - ); - renderLanes = new ReactNativeFiberHostComponent( - current, - type, - workInProgress - ); - instanceCache.set(current, workInProgress); - instanceProps.set(current, newProps); - appendAllChildren(renderLanes, workInProgress, !1, !1); - workInProgress.stateNode = renderLanes; - finalizeInitialChildren(renderLanes) && (workInProgress.flags |= 4); - null !== workInProgress.ref && (workInProgress.flags |= 512); - } - bubbleProperties(workInProgress); - return null; - case 6: - if (current && null != workInProgress.stateNode) - updateHostText( - current, - workInProgress, - current.memoizedProps, - newProps - ); - else { - if ("string" !== typeof newProps && null === workInProgress.stateNode) - throw Error( - "We must have new props for new mounts. This error is likely caused by a bug in React. Please file an issue." - ); - current = requiredContext(rootInstanceStackCursor.current); - if (!requiredContext(contextStackCursor$1.current).isInAParentText) - throw Error( - "Text strings must be rendered within a component." - ); - renderLanes = allocateTag(); - ReactNativePrivateInterface.UIManager.createView( - renderLanes, - "RCTRawText", - current, - { text: newProps } - ); - instanceCache.set(renderLanes, workInProgress); - workInProgress.stateNode = renderLanes; - } - bubbleProperties(workInProgress); - return null; - case 13: - pop(suspenseStackCursor); - newProps = workInProgress.memoizedState; - if (0 !== (workInProgress.flags & 128)) - return (workInProgress.lanes = renderLanes), workInProgress; - renderLanes = !1; - null !== current && (renderLanes = null !== current.memoizedState); - null === newProps || - renderLanes || - ((workInProgress.child.flags |= 8192), - 0 !== (workInProgress.mode & 1) && - (null === current || 0 !== (suspenseStackCursor.current & 1) - ? 0 === workInProgressRootExitStatus && - (workInProgressRootExitStatus = 3) - : renderDidSuspendDelayIfPossible())); - null !== workInProgress.updateQueue && (workInProgress.flags |= 4); - bubbleProperties(workInProgress); - return null; - case 4: - return ( - popHostContainer(), - updateHostContainer(current, workInProgress), - bubbleProperties(workInProgress), - null - ); - case 10: - return ( - popProvider(workInProgress.type._context), - bubbleProperties(workInProgress), - null - ); - case 17: - return ( - isContextProvider(workInProgress.type) && popContext(), - bubbleProperties(workInProgress), - null - ); - case 19: - pop(suspenseStackCursor); - type = workInProgress.memoizedState; - if (null === type) return bubbleProperties(workInProgress), null; - newProps = 0 !== (workInProgress.flags & 128); - updatePayload = type.rendering; - if (null === updatePayload) - if (newProps) cutOffTailIfNeeded(type, !1); - else { - if ( - 0 !== workInProgressRootExitStatus || - (null !== current && 0 !== (current.flags & 128)) - ) - for (current = workInProgress.child; null !== current; ) { - updatePayload = findFirstSuspended(current); - if (null !== updatePayload) { - workInProgress.flags |= 128; - cutOffTailIfNeeded(type, !1); - current = updatePayload.updateQueue; - null !== current && - ((workInProgress.updateQueue = current), - (workInProgress.flags |= 4)); - workInProgress.subtreeFlags = 0; - current = renderLanes; - for (newProps = workInProgress.child; null !== newProps; ) - (renderLanes = newProps), - (type = current), - (renderLanes.flags &= 14680066), - (updatePayload = renderLanes.alternate), - null === updatePayload - ? ((renderLanes.childLanes = 0), - (renderLanes.lanes = type), - (renderLanes.child = null), - (renderLanes.subtreeFlags = 0), - (renderLanes.memoizedProps = null), - (renderLanes.memoizedState = null), - (renderLanes.updateQueue = null), - (renderLanes.dependencies = null), - (renderLanes.stateNode = null)) - : ((renderLanes.childLanes = updatePayload.childLanes), - (renderLanes.lanes = updatePayload.lanes), - (renderLanes.child = updatePayload.child), - (renderLanes.subtreeFlags = 0), - (renderLanes.deletions = null), - (renderLanes.memoizedProps = - updatePayload.memoizedProps), - (renderLanes.memoizedState = - updatePayload.memoizedState), - (renderLanes.updateQueue = updatePayload.updateQueue), - (renderLanes.type = updatePayload.type), - (type = updatePayload.dependencies), - (renderLanes.dependencies = - null === type - ? null - : { - lanes: type.lanes, - firstContext: type.firstContext - })), - (newProps = newProps.sibling); - push( - suspenseStackCursor, - (suspenseStackCursor.current & 1) | 2 - ); - return workInProgress.child; - } - current = current.sibling; - } - null !== type.tail && - now() > workInProgressRootRenderTargetTime && - ((workInProgress.flags |= 128), - (newProps = !0), - cutOffTailIfNeeded(type, !1), - (workInProgress.lanes = 4194304)); - } - else { - if (!newProps) - if ( - ((current = findFirstSuspended(updatePayload)), null !== current) - ) { - if ( - ((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 && - !updatePayload.alternate) - ) - return bubbleProperties(workInProgress), null; - } else - 2 * now() - type.renderingStartTime > - workInProgressRootRenderTargetTime && - 1073741824 !== renderLanes && - ((workInProgress.flags |= 128), - (newProps = !0), - cutOffTailIfNeeded(type, !1), - (workInProgress.lanes = 4194304)); - type.isBackwards - ? ((updatePayload.sibling = workInProgress.child), - (workInProgress.child = updatePayload)) - : ((current = type.last), - null !== current - ? (current.sibling = updatePayload) - : (workInProgress.child = updatePayload), - (type.last = updatePayload)); - } - if (null !== type.tail) - return ( - (workInProgress = type.tail), - (type.rendering = workInProgress), - (type.tail = workInProgress.sibling), - (type.renderingStartTime = now()), - (workInProgress.sibling = null), - (current = suspenseStackCursor.current), - push(suspenseStackCursor, newProps ? (current & 1) | 2 : current & 1), - workInProgress - ); - bubbleProperties(workInProgress); - return null; - case 22: - case 23: - return ( - popRenderLanes(), - (newProps = null !== workInProgress.memoizedState), - null !== current && - (null !== current.memoizedState) !== newProps && - (workInProgress.flags |= 8192), - newProps && 0 !== (workInProgress.mode & 1) - ? 0 !== (subtreeRenderLanes & 1073741824) && - (bubbleProperties(workInProgress), - workInProgress.subtreeFlags & 6 && (workInProgress.flags |= 8192)) - : bubbleProperties(workInProgress), - null - ); - case 24: - return null; - case 25: - return null; - } - throw Error( - "Unknown unit of work tag (" + - workInProgress.tag + - "). This error is likely caused by a bug in React. Please file an issue." - ); -} -var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner, - didReceiveUpdate = !1; -function reconcileChildren(current, workInProgress, nextChildren, renderLanes) { - workInProgress.child = - null === current - ? mountChildFibers(workInProgress, null, nextChildren, renderLanes) - : reconcileChildFibers( - workInProgress, - current.child, - nextChildren, - renderLanes - ); -} -function updateForwardRef( - current, - workInProgress, - Component, - nextProps, - renderLanes -) { - Component = Component.render; - var ref = workInProgress.ref; - prepareToReadContext(workInProgress, renderLanes); - nextProps = renderWithHooks( - current, - workInProgress, - Component, - nextProps, - ref, - renderLanes - ); - if (null !== current && !didReceiveUpdate) - return ( - (workInProgress.updateQueue = current.updateQueue), - (workInProgress.flags &= -2053), - (current.lanes &= ~renderLanes), - bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) - ); - workInProgress.flags |= 1; - reconcileChildren(current, workInProgress, nextProps, renderLanes); - return workInProgress.child; -} -function updateMemoComponent( - current, - workInProgress, - Component, - nextProps, - renderLanes -) { - if (null === current) { - var type = Component.type; - if ( - "function" === typeof type && - !shouldConstruct(type) && - void 0 === type.defaultProps && - null === Component.compare && - void 0 === Component.defaultProps - ) - return ( - (workInProgress.tag = 15), - (workInProgress.type = type), - updateSimpleMemoComponent( - current, - workInProgress, - type, - nextProps, + nextProps, renderLanes ) ); @@ -4712,18 +4355,24 @@ function updateSimpleMemoComponent( nextProps, renderLanes ) { - if ( - null !== current && - shallowEqual(current.memoizedProps, nextProps) && - current.ref === workInProgress.ref - ) - if (((didReceiveUpdate = !1), 0 !== (current.lanes & renderLanes))) - 0 !== (current.flags & 131072) && (didReceiveUpdate = !0); - else - return ( - (workInProgress.lanes = current.lanes), - bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) - ); + if (null !== current) { + var prevProps = current.memoizedProps; + if ( + shallowEqual(prevProps, nextProps) && + current.ref === workInProgress.ref + ) + if ( + ((didReceiveUpdate = !1), + (workInProgress.pendingProps = nextProps = prevProps), + 0 !== (current.lanes & renderLanes)) + ) + 0 !== (current.flags & 131072) && (didReceiveUpdate = !0); + else + return ( + (workInProgress.lanes = current.lanes), + bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) + ); + } return updateFunctionComponent( current, workInProgress, @@ -4738,7 +4387,11 @@ function updateOffscreenComponent(current, workInProgress, renderLanes) { prevState = null !== current ? current.memoizedState : null; if ("hidden" === nextProps.mode) if (0 === (workInProgress.mode & 1)) - (workInProgress.memoizedState = { baseLanes: 0, cachePool: null }), + (workInProgress.memoizedState = { + baseLanes: 0, + cachePool: null, + transitions: null + }), push(subtreeRenderLanesCursor, subtreeRenderLanes), (subtreeRenderLanes |= renderLanes); else { @@ -4751,14 +4404,19 @@ function updateOffscreenComponent(current, workInProgress, renderLanes) { (workInProgress.lanes = workInProgress.childLanes = 1073741824), (workInProgress.memoizedState = { baseLanes: current, - cachePool: null + cachePool: null, + transitions: null }), (workInProgress.updateQueue = null), push(subtreeRenderLanesCursor, subtreeRenderLanes), (subtreeRenderLanes |= current), null ); - workInProgress.memoizedState = { baseLanes: 0, cachePool: null }; + workInProgress.memoizedState = { + baseLanes: 0, + cachePool: null, + transitions: null + }; nextProps = null !== prevState ? prevState.baseLanes : renderLanes; push(subtreeRenderLanesCursor, subtreeRenderLanes); subtreeRenderLanes |= nextProps; @@ -4773,7 +4431,7 @@ function updateOffscreenComponent(current, workInProgress, renderLanes) { reconcileChildren(current, workInProgress, nextChildren, renderLanes); return workInProgress.child; } -function markRef$1(current, workInProgress) { +function markRef(current, workInProgress) { var ref = workInProgress.ref; if ( (null === current && null !== ref) || @@ -4825,10 +4483,7 @@ function updateClassComponent( } else hasContext = !1; prepareToReadContext(workInProgress, renderLanes); if (null === workInProgress.stateNode) - null !== current && - ((current.alternate = null), - (workInProgress.alternate = null), - (workInProgress.flags |= 2)), + resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress), constructClassInstance(workInProgress, Component, nextProps), mountClassInstance(workInProgress, Component, nextProps, renderLanes), (nextProps = !0); @@ -5022,7 +4677,7 @@ function finishClassComponent( hasContext, renderLanes ) { - markRef$1(current, workInProgress); + markRef(current, workInProgress); var didCaptureError = 0 !== (workInProgress.flags & 128); if (!shouldUpdate && !didCaptureError) return ( @@ -5068,14 +4723,15 @@ function pushHostRootContext(workInProgress) { } var SUSPENDED_MARKER = { dehydrated: null, treeContext: null, retryLane: 0 }; function mountSuspenseOffscreenState(renderLanes) { - return { baseLanes: renderLanes, cachePool: null }; + return { baseLanes: renderLanes, cachePool: null, transitions: null }; } function updateSuspenseComponent(current, workInProgress, renderLanes) { var nextProps = workInProgress.pendingProps, suspenseContext = suspenseStackCursor.current, showFallback = !1, + didSuspend = 0 !== (workInProgress.flags & 128), JSCompiler_temp; - (JSCompiler_temp = 0 !== (workInProgress.flags & 128)) || + (JSCompiler_temp = didSuspend) || (JSCompiler_temp = null !== current && null === current.memoizedState ? !1 @@ -5085,167 +4741,297 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { suspenseContext |= 1; push(suspenseStackCursor, suspenseContext & 1); if (null === current) { - suspenseContext = nextProps.children; - current = nextProps.fallback; - if (showFallback) + current = workInProgress.memoizedState; + if (null !== current && null !== current.dehydrated) return ( - (showFallback = workInProgress.mode), - (nextProps = workInProgress.child), - (suspenseContext = { mode: "hidden", children: suspenseContext }), - 0 === (showFallback & 1) && null !== nextProps - ? ((nextProps.childLanes = 0), - (nextProps.pendingProps = suspenseContext)) - : (nextProps = createFiberFromOffscreen( - suspenseContext, - showFallback, + 0 === (workInProgress.mode & 1) + ? (workInProgress.lanes = 1) + : shim() + ? (workInProgress.lanes = 8) + : (workInProgress.lanes = 1073741824), + null + ); + didSuspend = nextProps.children; + current = nextProps.fallback; + return showFallback + ? ((nextProps = workInProgress.mode), + (showFallback = workInProgress.child), + (didSuspend = { mode: "hidden", children: didSuspend }), + 0 === (nextProps & 1) && null !== showFallback + ? ((showFallback.childLanes = 0), + (showFallback.pendingProps = didSuspend)) + : (showFallback = createFiberFromOffscreen( + didSuspend, + nextProps, 0, null )), (current = createFiberFromFragment( current, - showFallback, + nextProps, renderLanes, null )), - (nextProps.return = workInProgress), + (showFallback.return = workInProgress), (current.return = workInProgress), - (nextProps.sibling = current), - (workInProgress.child = nextProps), + (showFallback.sibling = current), + (workInProgress.child = showFallback), (workInProgress.child.memoizedState = mountSuspenseOffscreenState( renderLanes )), (workInProgress.memoizedState = SUSPENDED_MARKER), - current - ); - renderLanes = createFiberFromOffscreen( - { mode: "visible", children: suspenseContext }, - workInProgress.mode, - 0, - null - ); - renderLanes.return = workInProgress; - return (workInProgress.child = renderLanes); + current) + : mountSuspensePrimaryChildren(workInProgress, didSuspend); } - if (null !== current.memoizedState) { - if (showFallback) - return ( - (showFallback = updateSuspenseFallbackChildren( - current, - workInProgress, - nextProps.children, - nextProps.fallback, - renderLanes - )), - (nextProps = workInProgress.child), - (suspenseContext = current.child.memoizedState), - (nextProps.memoizedState = - null === suspenseContext - ? mountSuspenseOffscreenState(renderLanes) - : { - baseLanes: suspenseContext.baseLanes | renderLanes, - cachePool: null - }), - (nextProps.childLanes = current.childLanes & ~renderLanes), - (workInProgress.memoizedState = SUSPENDED_MARKER), - showFallback - ); - renderLanes = updateSuspensePrimaryChildren( + suspenseContext = current.memoizedState; + if ( + null !== suspenseContext && + ((JSCompiler_temp = suspenseContext.dehydrated), null !== JSCompiler_temp) + ) + return updateDehydratedSuspenseComponent( current, workInProgress, - nextProps.children, + didSuspend, + nextProps, + JSCompiler_temp, + suspenseContext, renderLanes ); - workInProgress.memoizedState = null; - return renderLanes; + if (showFallback) { + showFallback = nextProps.fallback; + didSuspend = workInProgress.mode; + suspenseContext = current.child; + JSCompiler_temp = suspenseContext.sibling; + var primaryChildProps = { mode: "hidden", children: nextProps.children }; + 0 === (didSuspend & 1) && workInProgress.child !== suspenseContext + ? ((nextProps = workInProgress.child), + (nextProps.childLanes = 0), + (nextProps.pendingProps = primaryChildProps), + (workInProgress.deletions = null)) + : ((nextProps = createWorkInProgress(suspenseContext, primaryChildProps)), + (nextProps.subtreeFlags = suspenseContext.subtreeFlags & 14680064)); + null !== JSCompiler_temp + ? (showFallback = createWorkInProgress(JSCompiler_temp, showFallback)) + : ((showFallback = createFiberFromFragment( + showFallback, + didSuspend, + renderLanes, + null + )), + (showFallback.flags |= 2)); + showFallback.return = workInProgress; + nextProps.return = workInProgress; + nextProps.sibling = showFallback; + workInProgress.child = nextProps; + nextProps = showFallback; + showFallback = workInProgress.child; + didSuspend = current.child.memoizedState; + didSuspend = + null === didSuspend + ? mountSuspenseOffscreenState(renderLanes) + : { + baseLanes: didSuspend.baseLanes | renderLanes, + cachePool: null, + transitions: didSuspend.transitions + }; + showFallback.memoizedState = didSuspend; + showFallback.childLanes = current.childLanes & ~renderLanes; + workInProgress.memoizedState = SUSPENDED_MARKER; + return nextProps; } - if (showFallback) - return ( - (showFallback = updateSuspenseFallbackChildren( - current, - workInProgress, - nextProps.children, - nextProps.fallback, - renderLanes - )), - (nextProps = workInProgress.child), - (suspenseContext = current.child.memoizedState), - (nextProps.memoizedState = - null === suspenseContext - ? mountSuspenseOffscreenState(renderLanes) - : { - baseLanes: suspenseContext.baseLanes | renderLanes, - cachePool: null - }), - (nextProps.childLanes = current.childLanes & ~renderLanes), - (workInProgress.memoizedState = SUSPENDED_MARKER), - showFallback - ); - renderLanes = updateSuspensePrimaryChildren( - current, - workInProgress, - nextProps.children, - renderLanes - ); - workInProgress.memoizedState = null; - return renderLanes; -} -function updateSuspensePrimaryChildren( - current, - workInProgress, - primaryChildren, - renderLanes -) { - var currentPrimaryChildFragment = current.child; - current = currentPrimaryChildFragment.sibling; - primaryChildren = createWorkInProgress(currentPrimaryChildFragment, { + showFallback = current.child; + current = showFallback.sibling; + nextProps = createWorkInProgress(showFallback, { mode: "visible", - children: primaryChildren + children: nextProps.children }); - 0 === (workInProgress.mode & 1) && (primaryChildren.lanes = renderLanes); - primaryChildren.return = workInProgress; - primaryChildren.sibling = null; + 0 === (workInProgress.mode & 1) && (nextProps.lanes = renderLanes); + nextProps.return = workInProgress; + nextProps.sibling = null; null !== current && ((renderLanes = workInProgress.deletions), null === renderLanes ? ((workInProgress.deletions = [current]), (workInProgress.flags |= 16)) : renderLanes.push(current)); + workInProgress.child = nextProps; + workInProgress.memoizedState = null; + return nextProps; +} +function mountSuspensePrimaryChildren(workInProgress, primaryChildren) { + primaryChildren = createFiberFromOffscreen( + { mode: "visible", children: primaryChildren }, + workInProgress.mode, + 0, + null + ); + primaryChildren.return = workInProgress; return (workInProgress.child = primaryChildren); } -function updateSuspenseFallbackChildren( +function retrySuspenseComponentWithoutHydrating( current, workInProgress, - primaryChildren, - fallbackChildren, + renderLanes, + recoverableError +) { + null !== recoverableError && + (null === hydrationErrors + ? (hydrationErrors = [recoverableError]) + : hydrationErrors.push(recoverableError)); + reconcileChildFibers(workInProgress, current.child, null, renderLanes); + current = mountSuspensePrimaryChildren( + workInProgress, + workInProgress.pendingProps.children + ); + current.flags |= 2; + workInProgress.memoizedState = null; + return current; +} +function updateDehydratedSuspenseComponent( + current, + workInProgress, + didSuspend, + nextProps, + suspenseInstance, + suspenseState, renderLanes ) { - var mode = workInProgress.mode; - current = current.child; - var currentFallbackChildFragment = current.sibling, - primaryChildProps = { mode: "hidden", children: primaryChildren }; - 0 === (mode & 1) && workInProgress.child !== current - ? ((primaryChildren = workInProgress.child), - (primaryChildren.childLanes = 0), - (primaryChildren.pendingProps = primaryChildProps), - (workInProgress.deletions = null)) - : ((primaryChildren = createWorkInProgress(current, primaryChildProps)), - (primaryChildren.subtreeFlags = current.subtreeFlags & 14680064)); - null !== currentFallbackChildFragment - ? (fallbackChildren = createWorkInProgress( - currentFallbackChildFragment, - fallbackChildren - )) - : ((fallbackChildren = createFiberFromFragment( - fallbackChildren, - mode, - renderLanes, + if (didSuspend) { + if (workInProgress.flags & 256) + return ( + (workInProgress.flags &= -257), + retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, + Error( + "There was an error while hydrating this Suspense boundary. Switched to client rendering." + ) + ) + ); + if (null !== workInProgress.memoizedState) + return ( + (workInProgress.child = current.child), + (workInProgress.flags |= 128), null - )), - (fallbackChildren.flags |= 2)); - fallbackChildren.return = workInProgress; - primaryChildren.return = workInProgress; - primaryChildren.sibling = fallbackChildren; - workInProgress.child = primaryChildren; - return fallbackChildren; + ); + suspenseState = nextProps.fallback; + didSuspend = workInProgress.mode; + nextProps = createFiberFromOffscreen( + { mode: "visible", children: nextProps.children }, + didSuspend, + 0, + null + ); + suspenseState = createFiberFromFragment( + suspenseState, + didSuspend, + renderLanes, + null + ); + suspenseState.flags |= 2; + nextProps.return = workInProgress; + suspenseState.return = workInProgress; + nextProps.sibling = suspenseState; + workInProgress.child = nextProps; + 0 !== (workInProgress.mode & 1) && + reconcileChildFibers(workInProgress, current.child, null, renderLanes); + workInProgress.child.memoizedState = mountSuspenseOffscreenState( + renderLanes + ); + workInProgress.memoizedState = SUSPENDED_MARKER; + return suspenseState; + } + if (0 === (workInProgress.mode & 1)) + return retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, + null + ); + if (shim()) + return ( + (suspenseState = shim().errorMessage), + retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, + suspenseState + ? Error(suspenseState) + : Error( + "The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering." + ) + ) + ); + didSuspend = 0 !== (renderLanes & current.childLanes); + if (didReceiveUpdate || didSuspend) { + nextProps = workInProgressRoot; + if (null !== nextProps) { + switch (renderLanes & -renderLanes) { + case 4: + didSuspend = 2; + break; + case 16: + didSuspend = 8; + break; + 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: + case 8388608: + case 16777216: + case 33554432: + case 67108864: + didSuspend = 32; + break; + case 536870912: + didSuspend = 268435456; + break; + default: + didSuspend = 0; + } + nextProps = + 0 !== (didSuspend & (nextProps.suspendedLanes | renderLanes)) + ? 0 + : didSuspend; + 0 !== nextProps && + nextProps !== suspenseState.retryLane && + ((suspenseState.retryLane = nextProps), + scheduleUpdateOnFiber(current, nextProps, -1)); + } + renderDidSuspendDelayIfPossible(); + return retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, + Error( + "This Suspense boundary received an update before it finished hydrating. This caused the boundary to switch to client rendering. The usual way to fix this is to wrap the original update in startTransition." + ) + ); + } + if (shim()) + return ( + (workInProgress.flags |= 128), + (workInProgress.child = current.child), + retryDehydratedSuspenseBoundary.bind(null, current), + shim(), + null + ); + current = mountSuspensePrimaryChildren(workInProgress, nextProps.children); + current.flags |= 4096; + return current; } function scheduleSuspenseWorkOnFiber(fiber, renderLanes, propagationRoot) { fiber.lanes |= renderLanes; @@ -5364,6 +5150,13 @@ function updateSuspenseListComponent(current, workInProgress, renderLanes) { } return workInProgress.child; } +function resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress) { + 0 === (workInProgress.mode & 1) && + null !== current && + ((current.alternate = null), + (workInProgress.alternate = null), + (workInProgress.flags |= 2)); +} function bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) { null !== current && (workInProgress.dependencies = current.dependencies); workInProgressRootSkippedLanes |= workInProgress.lanes; @@ -5411,7 +5204,14 @@ function attemptEarlyBailoutIfNoScheduledUpdate( context._currentValue = nextValue; break; case 13: - if (null !== workInProgress.memoizedState) { + context = workInProgress.memoizedState; + if (null !== context) { + if (null !== context.dehydrated) + return ( + push(suspenseStackCursor, suspenseStackCursor.current & 1), + (workInProgress.flags |= 128), + null + ); if (0 !== (renderLanes & workInProgress.child.childLanes)) return updateSuspenseComponent(current, workInProgress, renderLanes); push(suspenseStackCursor, suspenseStackCursor.current & 1); @@ -5435,22 +5235,432 @@ function attemptEarlyBailoutIfNoScheduledUpdate( ); workInProgress.flags |= 128; } - nextValue = workInProgress.memoizedState; - null !== nextValue && - ((nextValue.rendering = null), - (nextValue.tail = null), - (nextValue.lastEffect = null)); - push(suspenseStackCursor, suspenseStackCursor.current); - if (context) break; - else return null; + nextValue = workInProgress.memoizedState; + null !== nextValue && + ((nextValue.rendering = null), + (nextValue.tail = null), + (nextValue.lastEffect = null)); + push(suspenseStackCursor, suspenseStackCursor.current); + if (context) break; + else return null; + case 22: + case 23: + return ( + (workInProgress.lanes = 0), + updateOffscreenComponent(current, workInProgress, renderLanes) + ); + } + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); +} +var appendAllChildren, + updateHostContainer, + updateHostComponent$1, + updateHostText$1; +appendAllChildren = function(parent, workInProgress) { + for (var node = workInProgress.child; null !== node; ) { + if (5 === node.tag || 6 === node.tag) parent._children.push(node.stateNode); + else if (4 !== node.tag && null !== node.child) { + node.child.return = node; + node = node.child; + continue; + } + if (node === workInProgress) break; + for (; null === node.sibling; ) { + if (null === node.return || node.return === workInProgress) return; + node = node.return; + } + node.sibling.return = node.return; + node = node.sibling; + } +}; +updateHostContainer = function() {}; +updateHostComponent$1 = function(current, workInProgress, type, newProps) { + current.memoizedProps !== newProps && + (requiredContext(contextStackCursor$1.current), + (workInProgress.updateQueue = UPDATE_SIGNAL)) && + (workInProgress.flags |= 4); +}; +updateHostText$1 = function(current, workInProgress, oldText, newText) { + oldText !== newText && (workInProgress.flags |= 4); +}; +function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { + switch (renderState.tailMode) { + case "hidden": + hasRenderedATailFallback = renderState.tail; + for (var lastTailNode = null; null !== hasRenderedATailFallback; ) + null !== hasRenderedATailFallback.alternate && + (lastTailNode = hasRenderedATailFallback), + (hasRenderedATailFallback = hasRenderedATailFallback.sibling); + null === lastTailNode + ? (renderState.tail = null) + : (lastTailNode.sibling = null); + break; + case "collapsed": + lastTailNode = renderState.tail; + for (var lastTailNode$60 = null; null !== lastTailNode; ) + null !== lastTailNode.alternate && (lastTailNode$60 = lastTailNode), + (lastTailNode = lastTailNode.sibling); + null === lastTailNode$60 + ? hasRenderedATailFallback || null === renderState.tail + ? (renderState.tail = null) + : (renderState.tail.sibling = null) + : (lastTailNode$60.sibling = null); + } +} +function bubbleProperties(completedWork) { + var didBailout = + null !== completedWork.alternate && + completedWork.alternate.child === completedWork.child, + newChildLanes = 0, + subtreeFlags = 0; + if (didBailout) + for (var child$61 = completedWork.child; null !== child$61; ) + (newChildLanes |= child$61.lanes | child$61.childLanes), + (subtreeFlags |= child$61.subtreeFlags & 14680064), + (subtreeFlags |= child$61.flags & 14680064), + (child$61.return = completedWork), + (child$61 = child$61.sibling); + else + for (child$61 = completedWork.child; null !== child$61; ) + (newChildLanes |= child$61.lanes | child$61.childLanes), + (subtreeFlags |= child$61.subtreeFlags), + (subtreeFlags |= child$61.flags), + (child$61.return = completedWork), + (child$61 = child$61.sibling); + completedWork.subtreeFlags |= subtreeFlags; + completedWork.childLanes = newChildLanes; + return didBailout; +} +function completeWork(current, workInProgress, renderLanes) { + var newProps = workInProgress.pendingProps; + popTreeContext(workInProgress); + switch (workInProgress.tag) { + case 2: + case 16: + case 15: + case 0: + case 11: + case 7: + case 8: + case 12: + case 9: + case 14: + return bubbleProperties(workInProgress), null; + case 1: + return ( + isContextProvider(workInProgress.type) && popContext(), + bubbleProperties(workInProgress), + null + ); + case 3: + return ( + (renderLanes = workInProgress.stateNode), + popHostContainer(), + pop(didPerformWorkStackCursor), + pop(contextStackCursor), + resetWorkInProgressVersions(), + renderLanes.pendingContext && + ((renderLanes.context = renderLanes.pendingContext), + (renderLanes.pendingContext = null)), + (null !== current && null !== current.child) || + null === current || + (current.memoizedState.isDehydrated && + 0 === (workInProgress.flags & 256)) || + ((workInProgress.flags |= 1024), + null !== hydrationErrors && + (queueRecoverableErrors(hydrationErrors), + (hydrationErrors = null))), + updateHostContainer(current, workInProgress), + bubbleProperties(workInProgress), + null + ); + case 5: + popHostContext(workInProgress); + renderLanes = requiredContext(rootInstanceStackCursor.current); + var type = workInProgress.type; + if (null !== current && null != workInProgress.stateNode) + updateHostComponent$1( + current, + workInProgress, + type, + newProps, + renderLanes + ), + current.ref !== workInProgress.ref && (workInProgress.flags |= 512); + else { + if (!newProps) { + if (null === workInProgress.stateNode) + throw Error( + "We must have new props for new mounts. This error is likely caused by a bug in React. Please file an issue." + ); + bubbleProperties(workInProgress); + return null; + } + requiredContext(contextStackCursor$1.current); + current = allocateTag(); + type = getViewConfigForType(type); + var updatePayload = diffProperties( + null, + emptyObject, + newProps, + type.validAttributes + ); + ReactNativePrivateInterface.UIManager.createView( + current, + type.uiViewClassName, + renderLanes, + updatePayload + ); + renderLanes = new ReactNativeFiberHostComponent( + current, + type, + workInProgress + ); + instanceCache.set(current, workInProgress); + instanceProps.set(current, newProps); + appendAllChildren(renderLanes, workInProgress, !1, !1); + workInProgress.stateNode = renderLanes; + finalizeInitialChildren(renderLanes) && (workInProgress.flags |= 4); + null !== workInProgress.ref && (workInProgress.flags |= 512); + } + bubbleProperties(workInProgress); + return null; + case 6: + if (current && null != workInProgress.stateNode) + updateHostText$1( + current, + workInProgress, + current.memoizedProps, + newProps + ); + else { + if ("string" !== typeof newProps && null === workInProgress.stateNode) + throw Error( + "We must have new props for new mounts. This error is likely caused by a bug in React. Please file an issue." + ); + current = requiredContext(rootInstanceStackCursor.current); + if (!requiredContext(contextStackCursor$1.current).isInAParentText) + throw Error( + "Text strings must be rendered within a component." + ); + renderLanes = allocateTag(); + ReactNativePrivateInterface.UIManager.createView( + renderLanes, + "RCTRawText", + current, + { text: newProps } + ); + instanceCache.set(renderLanes, workInProgress); + workInProgress.stateNode = renderLanes; + } + bubbleProperties(workInProgress); + return null; + case 13: + pop(suspenseStackCursor); + newProps = workInProgress.memoizedState; + if ( + null === current || + (null !== current.memoizedState && + null !== current.memoizedState.dehydrated) + ) { + if (null !== newProps && null !== newProps.dehydrated) { + if (null === current) { + throw Error( + "A dehydrated suspense component was completed without a hydrated node. This is probably a bug in React." + ); + throw Error( + "Expected prepareToHydrateHostSuspenseInstance() to never be called. This error is likely caused by a bug in React. Please file an issue." + ); + } + 0 === (workInProgress.flags & 128) && + (workInProgress.memoizedState = null); + workInProgress.flags |= 4; + bubbleProperties(workInProgress); + type = !1; + } else + null !== hydrationErrors && + (queueRecoverableErrors(hydrationErrors), (hydrationErrors = null)), + (type = !0); + if (!type) return workInProgress.flags & 65536 ? workInProgress : null; + } + if (0 !== (workInProgress.flags & 128)) + return (workInProgress.lanes = renderLanes), workInProgress; + renderLanes = null !== newProps; + renderLanes !== (null !== current && null !== current.memoizedState) && + renderLanes && + ((workInProgress.child.flags |= 8192), + 0 !== (workInProgress.mode & 1) && + (null === current || 0 !== (suspenseStackCursor.current & 1) + ? 0 === workInProgressRootExitStatus && + (workInProgressRootExitStatus = 3) + : renderDidSuspendDelayIfPossible())); + null !== workInProgress.updateQueue && (workInProgress.flags |= 4); + bubbleProperties(workInProgress); + return null; + case 4: + return ( + popHostContainer(), + updateHostContainer(current, workInProgress), + bubbleProperties(workInProgress), + null + ); + case 10: + return ( + popProvider(workInProgress.type._context), + bubbleProperties(workInProgress), + null + ); + case 17: + return ( + isContextProvider(workInProgress.type) && popContext(), + bubbleProperties(workInProgress), + null + ); + case 19: + pop(suspenseStackCursor); + type = workInProgress.memoizedState; + if (null === type) return bubbleProperties(workInProgress), null; + newProps = 0 !== (workInProgress.flags & 128); + updatePayload = type.rendering; + if (null === updatePayload) + if (newProps) cutOffTailIfNeeded(type, !1); + else { + if ( + 0 !== workInProgressRootExitStatus || + (null !== current && 0 !== (current.flags & 128)) + ) + for (current = workInProgress.child; null !== current; ) { + updatePayload = findFirstSuspended(current); + if (null !== updatePayload) { + workInProgress.flags |= 128; + cutOffTailIfNeeded(type, !1); + current = updatePayload.updateQueue; + null !== current && + ((workInProgress.updateQueue = current), + (workInProgress.flags |= 4)); + workInProgress.subtreeFlags = 0; + current = renderLanes; + for (renderLanes = workInProgress.child; null !== renderLanes; ) + (newProps = renderLanes), + (type = current), + (newProps.flags &= 14680066), + (updatePayload = newProps.alternate), + null === updatePayload + ? ((newProps.childLanes = 0), + (newProps.lanes = type), + (newProps.child = null), + (newProps.subtreeFlags = 0), + (newProps.memoizedProps = null), + (newProps.memoizedState = null), + (newProps.updateQueue = null), + (newProps.dependencies = null), + (newProps.stateNode = null)) + : ((newProps.childLanes = updatePayload.childLanes), + (newProps.lanes = updatePayload.lanes), + (newProps.child = updatePayload.child), + (newProps.subtreeFlags = 0), + (newProps.deletions = null), + (newProps.memoizedProps = updatePayload.memoizedProps), + (newProps.memoizedState = updatePayload.memoizedState), + (newProps.updateQueue = updatePayload.updateQueue), + (newProps.type = updatePayload.type), + (type = updatePayload.dependencies), + (newProps.dependencies = + null === type + ? null + : { + lanes: type.lanes, + firstContext: type.firstContext + })), + (renderLanes = renderLanes.sibling); + push( + suspenseStackCursor, + (suspenseStackCursor.current & 1) | 2 + ); + return workInProgress.child; + } + current = current.sibling; + } + null !== type.tail && + now() > workInProgressRootRenderTargetTime && + ((workInProgress.flags |= 128), + (newProps = !0), + cutOffTailIfNeeded(type, !1), + (workInProgress.lanes = 4194304)); + } + else { + if (!newProps) + if ( + ((current = findFirstSuspended(updatePayload)), null !== current) + ) { + if ( + ((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 && + !updatePayload.alternate) + ) + return bubbleProperties(workInProgress), null; + } else + 2 * now() - type.renderingStartTime > + workInProgressRootRenderTargetTime && + 1073741824 !== renderLanes && + ((workInProgress.flags |= 128), + (newProps = !0), + cutOffTailIfNeeded(type, !1), + (workInProgress.lanes = 4194304)); + type.isBackwards + ? ((updatePayload.sibling = workInProgress.child), + (workInProgress.child = updatePayload)) + : ((current = type.last), + null !== current + ? (current.sibling = updatePayload) + : (workInProgress.child = updatePayload), + (type.last = updatePayload)); + } + if (null !== type.tail) + return ( + (workInProgress = type.tail), + (type.rendering = workInProgress), + (type.tail = workInProgress.sibling), + (type.renderingStartTime = now()), + (workInProgress.sibling = null), + (current = suspenseStackCursor.current), + push(suspenseStackCursor, newProps ? (current & 1) | 2 : current & 1), + workInProgress + ); + bubbleProperties(workInProgress); + return null; case 22: case 23: return ( - (workInProgress.lanes = 0), - updateOffscreenComponent(current, workInProgress, renderLanes) + popRenderLanes(), + (renderLanes = null !== workInProgress.memoizedState), + null !== current && + (null !== current.memoizedState) !== renderLanes && + (workInProgress.flags |= 8192), + renderLanes && 0 !== (workInProgress.mode & 1) + ? 0 !== (subtreeRenderLanes & 1073741824) && + (bubbleProperties(workInProgress), + workInProgress.subtreeFlags & 6 && (workInProgress.flags |= 8192)) + : bubbleProperties(workInProgress), + null ); + case 24: + return null; + case 25: + return null; } - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); + throw Error( + "Unknown unit of work tag (" + + workInProgress.tag + + "). This error is likely caused by a bug in React. Please file an issue." + ); } function unwindWork(current, workInProgress) { popTreeContext(workInProgress); @@ -5477,13 +5687,20 @@ function unwindWork(current, workInProgress) { case 5: return popHostContext(workInProgress), null; case 13: - return ( - pop(suspenseStackCursor), - (current = workInProgress.flags), - current & 65536 - ? ((workInProgress.flags = (current & -65537) | 128), workInProgress) - : null - ); + pop(suspenseStackCursor); + current = workInProgress.memoizedState; + if ( + null !== current && + null !== current.dehydrated && + null === workInProgress.alternate + ) + throw Error( + "Threw in newly mounted dehydrated component. This is likely a bug in React. Please file an issue." + ); + current = workInProgress.flags; + return current & 65536 + ? ((workInProgress.flags = (current & -65537) | 128), workInProgress) + : null; case 19: return pop(suspenseStackCursor), null; case 4: @@ -5607,61 +5824,13 @@ function commitHookEffectListMount(flags, finishedWork) { var effect = (finishedWork = finishedWork.next); do { if ((effect.tag & flags) === flags) { - var create$77 = effect.create; - effect.destroy = create$77(); + var create$73 = effect.create; + effect.destroy = create$73(); } effect = effect.next; } while (effect !== finishedWork); } } -function commitUnmount(finishedRoot, current, nearestMountedAncestor) { - if (injectedHook && "function" === typeof injectedHook.onCommitFiberUnmount) - try { - injectedHook.onCommitFiberUnmount(rendererID, current); - } catch (err) {} - switch (current.tag) { - case 0: - case 11: - case 14: - case 15: - finishedRoot = current.updateQueue; - if ( - null !== finishedRoot && - ((finishedRoot = finishedRoot.lastEffect), null !== finishedRoot) - ) { - var effect = (finishedRoot = finishedRoot.next); - do { - var _effect = effect, - destroy = _effect.destroy; - _effect = _effect.tag; - void 0 !== destroy && - (0 !== (_effect & 2) - ? safelyCallDestroy(current, nearestMountedAncestor, destroy) - : 0 !== (_effect & 4) && - safelyCallDestroy(current, nearestMountedAncestor, destroy)); - effect = effect.next; - } while (effect !== finishedRoot); - } - break; - case 1: - safelyDetachRef(current, nearestMountedAncestor); - finishedRoot = current.stateNode; - if ("function" === typeof finishedRoot.componentWillUnmount) - try { - (finishedRoot.props = current.memoizedProps), - (finishedRoot.state = current.memoizedState), - finishedRoot.componentWillUnmount(); - } catch (error) { - captureCommitPhaseError(current, nearestMountedAncestor, error); - } - break; - case 5: - safelyDetachRef(current, nearestMountedAncestor); - break; - case 4: - unmountHostComponents(finishedRoot, current, nearestMountedAncestor); - } -} function detachFiberAfterEffects(fiber) { var alternate = fiber.alternate; null !== alternate && @@ -5700,40 +5869,6 @@ function getHostSibling(fiber) { if (!(fiber.flags & 2)) return fiber.stateNode; } } -function commitPlacement(finishedWork) { - a: { - for (var parent = finishedWork.return; null !== parent; ) { - if (isHostParent(parent)) break a; - parent = parent.return; - } - throw Error( - "Expected to find a host parent. This error is likely caused by a bug in React. Please file an issue." - ); - } - var parentFiber = parent; - switch (parentFiber.tag) { - case 5: - parent = parentFiber.stateNode; - parentFiber.flags & 32 && (parentFiber.flags &= -33); - parentFiber = getHostSibling(finishedWork); - insertOrAppendPlacementNode(finishedWork, parentFiber, parent); - break; - case 3: - case 4: - parent = parentFiber.stateNode.containerInfo; - parentFiber = getHostSibling(finishedWork); - insertOrAppendPlacementNodeIntoContainer( - finishedWork, - parentFiber, - parent - ); - break; - default: - throw Error( - "Invalid host parent fiber. This error is likely caused by a bug in React. Please file an issue." - ); - } -} function insertOrAppendPlacementNodeIntoContainer(node, before, parent) { var tag = node.tag; if (5 === tag || 6 === tag) @@ -5785,216 +5920,184 @@ function insertOrAppendPlacementNode(node, before, parent) { } else (before = "number" === typeof node ? node : node._nativeTag), (tag = parent._children), - (index = tag.indexOf(node)), - 0 <= index - ? (tag.splice(index, 1), - tag.push(node), - ReactNativePrivateInterface.UIManager.manageChildren( - parent._nativeTag, - [index], - [tag.length - 1], - [], - [], - [] - )) - : (tag.push(node), - ReactNativePrivateInterface.UIManager.manageChildren( - parent._nativeTag, - [], - [], - [before], - [tag.length - 1], - [] - )); - else if (4 !== tag && ((node = node.child), null !== node)) - for ( - insertOrAppendPlacementNode(node, before, parent), node = node.sibling; - null !== node; - - ) - insertOrAppendPlacementNode(node, before, parent), (node = node.sibling); -} -function unmountHostComponents( - finishedRoot$jscomp$0, - current, - nearestMountedAncestor$jscomp$0 -) { - for ( - var node = current, - currentParentIsValid = !1, - currentParent, - currentParentIsContainer; - ; - - ) { - if (!currentParentIsValid) { - currentParentIsValid = node.return; - a: for (;;) { - if (null === currentParentIsValid) - throw Error( - "Expected to find a host parent. This error is likely caused by a bug in React. Please file an issue." - ); - currentParent = currentParentIsValid.stateNode; - switch (currentParentIsValid.tag) { - case 5: - currentParentIsContainer = !1; - break a; - case 3: - currentParent = currentParent.containerInfo; - currentParentIsContainer = !0; - break a; - case 4: - currentParent = currentParent.containerInfo; - currentParentIsContainer = !0; - break a; - } - currentParentIsValid = currentParentIsValid.return; - } - currentParentIsValid = !0; - } - if (5 === node.tag || 6 === node.tag) { - a: for ( - var finishedRoot = finishedRoot$jscomp$0, - root = node, - nearestMountedAncestor = nearestMountedAncestor$jscomp$0, - node$jscomp$0 = root; - ; - - ) - if ( - (commitUnmount(finishedRoot, node$jscomp$0, nearestMountedAncestor), - null !== node$jscomp$0.child && 4 !== node$jscomp$0.tag) - ) - (node$jscomp$0.child.return = node$jscomp$0), - (node$jscomp$0 = node$jscomp$0.child); - else { - if (node$jscomp$0 === root) break a; - for (; null === node$jscomp$0.sibling; ) { - if (null === node$jscomp$0.return || node$jscomp$0.return === root) - break a; - node$jscomp$0 = node$jscomp$0.return; - } - node$jscomp$0.sibling.return = node$jscomp$0.return; - node$jscomp$0 = node$jscomp$0.sibling; - } - currentParentIsContainer - ? ((finishedRoot = currentParent), - recursivelyUncacheFiberNode(node.stateNode), - ReactNativePrivateInterface.UIManager.manageChildren( - finishedRoot, - [], - [], - [], - [], - [0] - )) - : ((finishedRoot = currentParent), - (nearestMountedAncestor = node.stateNode), - recursivelyUncacheFiberNode(nearestMountedAncestor), - (root = finishedRoot._children), - (nearestMountedAncestor = root.indexOf(nearestMountedAncestor)), - root.splice(nearestMountedAncestor, 1), - ReactNativePrivateInterface.UIManager.manageChildren( - finishedRoot._nativeTag, - [], - [], - [], - [], - [nearestMountedAncestor] - )); - } else if (4 === node.tag) { - if (null !== node.child) { - currentParent = node.stateNode.containerInfo; - currentParentIsContainer = !0; - node.child.return = node; - node = node.child; - continue; - } - } else if ( - (commitUnmount( - finishedRoot$jscomp$0, - node, - nearestMountedAncestor$jscomp$0 - ), - null !== node.child) - ) { - node.child.return = node; - node = node.child; - continue; - } - if (node === current) break; - for (; null === node.sibling; ) { - if (null === node.return || node.return === current) return; - node = node.return; - 4 === node.tag && (currentParentIsValid = !1); - } - node.sibling.return = node.return; - node = node.sibling; - } + (index = tag.indexOf(node)), + 0 <= index + ? (tag.splice(index, 1), + tag.push(node), + ReactNativePrivateInterface.UIManager.manageChildren( + parent._nativeTag, + [index], + [tag.length - 1], + [], + [], + [] + )) + : (tag.push(node), + ReactNativePrivateInterface.UIManager.manageChildren( + parent._nativeTag, + [], + [], + [before], + [tag.length - 1], + [] + )); + else if (4 !== tag && ((node = node.child), null !== node)) + for ( + insertOrAppendPlacementNode(node, before, parent), node = node.sibling; + null !== node; + + ) + insertOrAppendPlacementNode(node, before, parent), (node = node.sibling); } -function commitWork(current, finishedWork) { - switch (finishedWork.tag) { +var hostParent = null, + hostParentIsContainer = !1; +function recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + parent +) { + for (parent = parent.child; null !== parent; ) + commitDeletionEffectsOnFiber(finishedRoot, nearestMountedAncestor, parent), + (parent = parent.sibling); +} +function commitDeletionEffectsOnFiber( + finishedRoot, + nearestMountedAncestor, + deletedFiber +) { + if (injectedHook && "function" === typeof injectedHook.onCommitFiberUnmount) + try { + injectedHook.onCommitFiberUnmount(rendererID, deletedFiber); + } catch (err) {} + switch (deletedFiber.tag) { + case 5: + safelyDetachRef(deletedFiber, nearestMountedAncestor); + case 6: + var prevHostParent = hostParent, + prevHostParentIsContainer = hostParentIsContainer; + hostParent = null; + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + hostParent = prevHostParent; + hostParentIsContainer = prevHostParentIsContainer; + null !== hostParent && + (hostParentIsContainer + ? ((finishedRoot = hostParent), + recursivelyUncacheFiberNode(deletedFiber.stateNode), + ReactNativePrivateInterface.UIManager.manageChildren( + finishedRoot, + [], + [], + [], + [], + [0] + )) + : ((finishedRoot = hostParent), + (nearestMountedAncestor = deletedFiber.stateNode), + recursivelyUncacheFiberNode(nearestMountedAncestor), + (deletedFiber = finishedRoot._children), + (nearestMountedAncestor = deletedFiber.indexOf( + nearestMountedAncestor + )), + deletedFiber.splice(nearestMountedAncestor, 1), + ReactNativePrivateInterface.UIManager.manageChildren( + finishedRoot._nativeTag, + [], + [], + [], + [], + [nearestMountedAncestor] + ))); + break; + case 18: + null !== hostParent && shim(hostParent, deletedFiber.stateNode); + break; + case 4: + prevHostParent = hostParent; + prevHostParentIsContainer = hostParentIsContainer; + hostParent = deletedFiber.stateNode.containerInfo; + hostParentIsContainer = !0; + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + hostParent = prevHostParent; + hostParentIsContainer = prevHostParentIsContainer; + break; case 0: case 11: case 14: case 15: - commitHookEffectListUnmount(3, finishedWork, finishedWork.return); - commitHookEffectListMount(3, finishedWork); - commitHookEffectListUnmount(5, finishedWork, finishedWork.return); - return; - case 1: - return; - case 5: - var instance = finishedWork.stateNode; - if (null != instance) { - var newProps = finishedWork.memoizedProps; - current = null !== current ? current.memoizedProps : newProps; - var updatePayload = finishedWork.updateQueue; - finishedWork.updateQueue = null; - null !== updatePayload && - ((finishedWork = instance.viewConfig), - instanceProps.set(instance._nativeTag, newProps), - (newProps = diffProperties( - null, - current, - newProps, - finishedWork.validAttributes - )), - null != newProps && - ReactNativePrivateInterface.UIManager.updateView( - instance._nativeTag, - finishedWork.uiViewClassName, - newProps - )); + prevHostParent = deletedFiber.updateQueue; + if ( + null !== prevHostParent && + ((prevHostParent = prevHostParent.lastEffect), null !== prevHostParent) + ) { + prevHostParentIsContainer = prevHostParent = prevHostParent.next; + do { + var _effect = prevHostParentIsContainer, + destroy = _effect.destroy; + _effect = _effect.tag; + void 0 !== destroy && + (0 !== (_effect & 2) + ? safelyCallDestroy(deletedFiber, nearestMountedAncestor, destroy) + : 0 !== (_effect & 4) && + safelyCallDestroy( + deletedFiber, + nearestMountedAncestor, + destroy + )); + prevHostParentIsContainer = prevHostParentIsContainer.next; + } while (prevHostParentIsContainer !== prevHostParent); } - return; - case 6: - if (null === finishedWork.stateNode) - throw Error( - "This should have a text node initialized. This error is likely caused by a bug in React. Please file an issue." - ); - ReactNativePrivateInterface.UIManager.updateView( - finishedWork.stateNode, - "RCTRawText", - { text: finishedWork.memoizedProps } + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + break; + case 1: + safelyDetachRef(deletedFiber, nearestMountedAncestor); + prevHostParent = deletedFiber.stateNode; + if ("function" === typeof prevHostParent.componentWillUnmount) + try { + (prevHostParent.props = deletedFiber.memoizedProps), + (prevHostParent.state = deletedFiber.memoizedState), + prevHostParent.componentWillUnmount(); + } catch (error) { + captureCommitPhaseError(deletedFiber, nearestMountedAncestor, error); + } + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + break; + case 21: + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + break; + case 22: + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + break; + default: + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber ); - return; - case 3: - return; - case 12: - return; - case 13: - attachSuspenseRetryListeners(finishedWork); - return; - case 19: - attachSuspenseRetryListeners(finishedWork); - return; - case 17: - return; } - throw Error( - "This unit of work tag should not have side-effects. This error is likely caused by a bug in React. Please file an issue." - ); } function attachSuspenseRetryListeners(finishedWork) { var wakeables = finishedWork.updateQueue; @@ -6010,153 +6113,307 @@ function attachSuspenseRetryListeners(finishedWork) { }); } } -function commitMutationEffects(root, firstChild) { - for (nextEffect = firstChild; null !== nextEffect; ) { - firstChild = nextEffect; - var deletions = firstChild.deletions; - if (null !== deletions) - for (var i = 0; i < deletions.length; i++) { - var childToDelete = deletions[i]; +function recursivelyTraverseMutationEffects(root$jscomp$0, parentFiber) { + var deletions = parentFiber.deletions; + if (null !== deletions) + for (var i = 0; i < deletions.length; i++) { + var childToDelete = deletions[i]; + try { + var root = root$jscomp$0, + returnFiber = parentFiber, + parent = returnFiber; + a: for (; null !== parent; ) { + switch (parent.tag) { + case 5: + hostParent = parent.stateNode; + hostParentIsContainer = !1; + break a; + case 3: + hostParent = parent.stateNode.containerInfo; + hostParentIsContainer = !0; + break a; + case 4: + hostParent = parent.stateNode.containerInfo; + hostParentIsContainer = !0; + break a; + } + parent = parent.return; + } + if (null === hostParent) + throw Error( + "Expected to find a host parent. This error is likely caused by a bug in React. Please file an issue." + ); + commitDeletionEffectsOnFiber(root, returnFiber, childToDelete); + hostParent = null; + hostParentIsContainer = !1; + var alternate = childToDelete.alternate; + null !== alternate && (alternate.return = null); + childToDelete.return = null; + } catch (error) { + captureCommitPhaseError(childToDelete, parentFiber, error); + } + } + if (parentFiber.subtreeFlags & 12854) + for (parentFiber = parentFiber.child; null !== parentFiber; ) + commitMutationEffectsOnFiber(parentFiber, root$jscomp$0), + (parentFiber = parentFiber.sibling); +} +function commitMutationEffectsOnFiber(finishedWork, root) { + var current = finishedWork.alternate, + flags = finishedWork.flags; + switch (finishedWork.tag) { + case 0: + case 11: + case 14: + case 15: + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + if (flags & 4) { try { - unmountHostComponents(root, childToDelete, firstChild); - var alternate = childToDelete.alternate; - null !== alternate && (alternate.return = null); - childToDelete.return = null; + commitHookEffectListUnmount(3, finishedWork, finishedWork.return), + commitHookEffectListMount(3, finishedWork); } catch (error) { - captureCommitPhaseError(childToDelete, firstChild, error); + captureCommitPhaseError(finishedWork, finishedWork.return, error); } - } - deletions = firstChild.child; - if (0 !== (firstChild.subtreeFlags & 12854) && null !== deletions) - (deletions.return = firstChild), (nextEffect = deletions); - else - for (; null !== nextEffect; ) { - firstChild = nextEffect; try { - var flags = firstChild.flags; - if (flags & 512) { - var current = firstChild.alternate; - if (null !== current) { - var currentRef = current.ref; - null !== currentRef && - ("function" === typeof currentRef - ? currentRef(null) - : (currentRef.current = null)); + commitHookEffectListUnmount(5, finishedWork, finishedWork.return); + } catch (error$83) { + captureCommitPhaseError(finishedWork, finishedWork.return, error$83); + } + } + break; + case 1: + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + flags & 512 && + null !== current && + safelyDetachRef(current, current.return); + break; + case 5: + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + flags & 512 && + null !== current && + safelyDetachRef(current, current.return); + if (flags & 4) { + var instance$85 = finishedWork.stateNode; + if (null != instance$85) { + var newProps = finishedWork.memoizedProps, + oldProps = null !== current ? current.memoizedProps : newProps, + updatePayload = finishedWork.updateQueue; + finishedWork.updateQueue = null; + if (null !== updatePayload) + try { + var viewConfig = instance$85.viewConfig; + instanceProps.set(instance$85._nativeTag, newProps); + var updatePayload$jscomp$0 = diffProperties( + null, + oldProps, + newProps, + viewConfig.validAttributes + ); + null != updatePayload$jscomp$0 && + ReactNativePrivateInterface.UIManager.updateView( + instance$85._nativeTag, + viewConfig.uiViewClassName, + updatePayload$jscomp$0 + ); + } catch (error$86) { + captureCommitPhaseError( + finishedWork, + finishedWork.return, + error$86 + ); } - } - if (flags & 8192) - switch (firstChild.tag) { - case 13: - if (null !== firstChild.memoizedState) { - var current$84 = firstChild.alternate; - if (null === current$84 || null === current$84.memoizedState) - globalMostRecentFallbackTime = now(); - } - break; - case 22: - a: { - deletions = firstChild; - var isHidden = null !== firstChild.memoizedState; - i = null; - for (childToDelete = deletions; ; ) { - if (5 === childToDelete.tag) { - if (null === i) { - i = childToDelete; - var instance = childToDelete.stateNode; - if (isHidden) { - var instance$jscomp$0 = instance, - viewConfig = instance$jscomp$0.viewConfig; - var updatePayload = diffProperties( - null, - emptyObject, - { style: { display: "none" } }, - viewConfig.validAttributes - ); - ReactNativePrivateInterface.UIManager.updateView( - instance$jscomp$0._nativeTag, - viewConfig.uiViewClassName, - updatePayload - ); - } else { - var instance$jscomp$1 = childToDelete.stateNode, - props = childToDelete.memoizedProps, - viewConfig$jscomp$0 = instance$jscomp$1.viewConfig, - prevProps = assign({}, props, { - style: [props.style, { display: "none" }] - }); - var updatePayload$jscomp$0 = diffProperties( - null, - prevProps, - props, - viewConfig$jscomp$0.validAttributes - ); - ReactNativePrivateInterface.UIManager.updateView( - instance$jscomp$1._nativeTag, - viewConfig$jscomp$0.uiViewClassName, - updatePayload$jscomp$0 - ); - } - } - } else if (6 === childToDelete.tag) { - if (null === i) throw Error("Not yet implemented."); - } else if ( - ((22 !== childToDelete.tag && 23 !== childToDelete.tag) || - null === childToDelete.memoizedState || - childToDelete === deletions) && - null !== childToDelete.child - ) { - childToDelete.child.return = childToDelete; - childToDelete = childToDelete.child; - continue; - } - if (childToDelete === deletions) break; - for (; null === childToDelete.sibling; ) { - if ( - null === childToDelete.return || - childToDelete.return === deletions - ) - break a; - i === childToDelete && (i = null); - childToDelete = childToDelete.return; - } - i === childToDelete && (i = null); - childToDelete.sibling.return = childToDelete.return; - childToDelete = childToDelete.sibling; - } + } + } + break; + case 6: + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + if (flags & 4) { + if (null === finishedWork.stateNode) + throw Error( + "This should have a text node initialized. This error is likely caused by a bug in React. Please file an issue." + ); + viewConfig = finishedWork.stateNode; + updatePayload$jscomp$0 = finishedWork.memoizedProps; + try { + ReactNativePrivateInterface.UIManager.updateView( + viewConfig, + "RCTRawText", + { text: updatePayload$jscomp$0 } + ); + } catch (error$87) { + captureCommitPhaseError(finishedWork, finishedWork.return, error$87); + } + } + break; + case 3: + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + break; + case 4: + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + break; + case 13: + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + viewConfig = finishedWork.child; + viewConfig.flags & 8192 && + null !== viewConfig.memoizedState && + (null === viewConfig.alternate || + null === viewConfig.alternate.memoizedState) && + (globalMostRecentFallbackTime = now()); + flags & 4 && attachSuspenseRetryListeners(finishedWork); + break; + case 22: + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + if (flags & 8192) + a: for ( + viewConfig = null !== finishedWork.memoizedState, + updatePayload$jscomp$0 = null, + current = finishedWork; + ; + + ) { + if (5 === current.tag) { + if (null === updatePayload$jscomp$0) { + updatePayload$jscomp$0 = current; + try { + if (((instance$85 = current.stateNode), viewConfig)) + (newProps = instance$85.viewConfig), + (oldProps = diffProperties( + null, + emptyObject, + { style: { display: "none" } }, + newProps.validAttributes + )), + ReactNativePrivateInterface.UIManager.updateView( + instance$85._nativeTag, + newProps.uiViewClassName, + oldProps + ); + else { + updatePayload = current.stateNode; + var props = current.memoizedProps, + viewConfig$jscomp$0 = updatePayload.viewConfig, + prevProps = assign({}, props, { + style: [props.style, { display: "none" }] + }); + var updatePayload$jscomp$1 = diffProperties( + null, + prevProps, + props, + viewConfig$jscomp$0.validAttributes + ); + ReactNativePrivateInterface.UIManager.updateView( + updatePayload._nativeTag, + viewConfig$jscomp$0.uiViewClassName, + updatePayload$jscomp$1 + ); } + } catch (error) { + captureCommitPhaseError( + finishedWork, + finishedWork.return, + error + ); + } } - switch (flags & 4102) { - case 2: - commitPlacement(firstChild); - firstChild.flags &= -3; - break; - case 6: - commitPlacement(firstChild); - firstChild.flags &= -3; - commitWork(firstChild.alternate, firstChild); - break; - case 4096: - firstChild.flags &= -4097; - break; - case 4100: - firstChild.flags &= -4097; - commitWork(firstChild.alternate, firstChild); - break; - case 4: - commitWork(firstChild.alternate, firstChild); + } else if (6 === current.tag) { + if (null === updatePayload$jscomp$0) + try { + throw Error("Not yet implemented."); + } catch (error$78) { + captureCommitPhaseError( + finishedWork, + finishedWork.return, + error$78 + ); + } + } else if ( + ((22 !== current.tag && 23 !== current.tag) || + null === current.memoizedState || + current === finishedWork) && + null !== current.child + ) { + current.child.return = current; + current = current.child; + continue; } - } catch (error) { - captureCommitPhaseError(firstChild, firstChild.return, error); + if (current === finishedWork) break a; + for (; null === current.sibling; ) { + if (null === current.return || current.return === finishedWork) + break a; + updatePayload$jscomp$0 === current && + (updatePayload$jscomp$0 = null); + current = current.return; + } + updatePayload$jscomp$0 === current && (updatePayload$jscomp$0 = null); + current.sibling.return = current.return; + current = current.sibling; } - deletions = firstChild.sibling; - if (null !== deletions) { - deletions.return = firstChild.return; - nextEffect = deletions; - break; + break; + case 19: + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + flags & 4 && attachSuspenseRetryListeners(finishedWork); + break; + case 21: + break; + default: + recursivelyTraverseMutationEffects(root, finishedWork), + commitReconciliationEffects(finishedWork); + } +} +function commitReconciliationEffects(finishedWork) { + var flags = finishedWork.flags; + if (flags & 2) { + try { + a: { + for (var parent = finishedWork.return; null !== parent; ) { + if (isHostParent(parent)) { + var JSCompiler_inline_result = parent; + break a; + } + parent = parent.return; } - nextEffect = firstChild.return; + throw Error( + "Expected to find a host parent. This error is likely caused by a bug in React. Please file an issue." + ); + } + switch (JSCompiler_inline_result.tag) { + case 5: + var parent$jscomp$0 = JSCompiler_inline_result.stateNode; + JSCompiler_inline_result.flags & 32 && + (JSCompiler_inline_result.flags &= -33); + var before = getHostSibling(finishedWork); + insertOrAppendPlacementNode(finishedWork, before, parent$jscomp$0); + break; + case 3: + case 4: + var parent$79 = JSCompiler_inline_result.stateNode.containerInfo, + before$80 = getHostSibling(finishedWork); + insertOrAppendPlacementNodeIntoContainer( + finishedWork, + before$80, + parent$79 + ); + break; + default: + throw Error( + "Invalid host parent fiber. This error is likely caused by a bug in React. Please file an issue." + ); } + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } + finishedWork.flags &= -3; } + flags & 4096 && (finishedWork.flags &= -4097); } function commitLayoutEffects(finishedWork) { for (nextEffect = finishedWork; null !== nextEffect; ) { @@ -6200,8 +6457,8 @@ function commitLayoutEffects(finishedWork) { commitUpdateQueue(firstChild, updateQueue, instance); break; case 3: - var updateQueue$78 = firstChild.updateQueue; - if (null !== updateQueue$78) { + var updateQueue$74 = firstChild.updateQueue; + if (null !== updateQueue$74) { current = null; if (null !== firstChild.child) switch (firstChild.child.tag) { @@ -6211,7 +6468,7 @@ function commitLayoutEffects(finishedWork) { case 1: current = firstChild.child.stateNode; } - commitUpdateQueue(firstChild, updateQueue$78, current); + commitUpdateQueue(firstChild, updateQueue$74, current); } break; case 5: @@ -6229,6 +6486,7 @@ function commitLayoutEffects(finishedWork) { case 21: case 22: case 23: + case 25: break; default: throw Error( @@ -6289,6 +6547,7 @@ var ceil = Math.ceil, workInProgressRootRecoverableErrors = null, globalMostRecentFallbackTime = 0, workInProgressRootRenderTargetTime = Infinity, + workInProgressTransitions = null, hasUncaughtError = !1, firstUncaughtError = null, legacyErrorBoundariesThatAlreadyFailed = null, @@ -6313,10 +6572,7 @@ function requestUpdateLane(fiber) { if (null !== ReactCurrentBatchConfig.transition) return ( 0 === currentEventTransitionLane && - ((fiber = nextTransitionLane), - (nextTransitionLane <<= 1), - 0 === (nextTransitionLane & 4194240) && (nextTransitionLane = 64), - (currentEventTransitionLane = fiber)), + (currentEventTransitionLane = claimNextTransitionLane()), currentEventTransitionLane ); fiber = currentUpdatePriority; @@ -6359,6 +6615,13 @@ function markUpdateLaneFromFiberToRoot(sourceFiber, lane) { (sourceFiber = sourceFiber.return); return 3 === alternate.tag ? alternate.stateNode : null; } +function isInterleavedUpdate(fiber) { + return ( + (null !== workInProgressRoot || null !== interleavedQueues) && + 0 !== (fiber.mode & 1) && + 0 === (executionContext & 2) + ); +} function ensureRootIsScheduled(root, currentTime) { for ( var existingCallbackNode = root.callbackNode, @@ -6454,7 +6717,8 @@ function performConcurrentWorkOnRoot(root, didTimeout) { workInProgressRoot !== root || workInProgressRootRenderLanes !== didTimeout ) - (workInProgressRootRenderTargetTime = now() + 500), + (workInProgressTransitions = null), + (workInProgressRootRenderTargetTime = now() + 500), prepareFreshStack(root, didTimeout); do try { @@ -6511,7 +6775,11 @@ function performConcurrentWorkOnRoot(root, didTimeout) { case 1: throw Error("Root did not complete. This is a bug in React."); case 2: - commitRoot(root, workInProgressRootRecoverableErrors); + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); break; case 3: markRootSuspended$1(root, lanes); @@ -6528,12 +6796,21 @@ function performConcurrentWorkOnRoot(root, didTimeout) { break; } root.timeoutHandle = scheduleTimeout( - commitRoot.bind(null, root, workInProgressRootRecoverableErrors), + commitRoot.bind( + null, + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ), didTimeout ); break; } - commitRoot(root, workInProgressRootRecoverableErrors); + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); break; case 4: markRootSuspended$1(root, lanes); @@ -6564,15 +6841,28 @@ function performConcurrentWorkOnRoot(root, didTimeout) { : 1960 * ceil(lanes / 1960)) - lanes; if (10 < lanes) { root.timeoutHandle = scheduleTimeout( - commitRoot.bind(null, root, workInProgressRootRecoverableErrors), + commitRoot.bind( + null, + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ), lanes ); break; } - commitRoot(root, workInProgressRootRecoverableErrors); + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); break; case 5: - commitRoot(root, workInProgressRootRecoverableErrors); + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); break; default: throw Error("Unknown root exit status."); @@ -6592,15 +6882,17 @@ function recoverFromConcurrentError(root, errorRetryLanes) { 2 !== root && ((errorRetryLanes = workInProgressRootRecoverableErrors), (workInProgressRootRecoverableErrors = errorsFromFirstAttempt), - null !== errorRetryLanes && - (null === workInProgressRootRecoverableErrors - ? (workInProgressRootRecoverableErrors = errorRetryLanes) - : workInProgressRootRecoverableErrors.push.apply( - workInProgressRootRecoverableErrors, - errorRetryLanes - ))); + null !== errorRetryLanes && queueRecoverableErrors(errorRetryLanes)); return root; } +function queueRecoverableErrors(errors) { + null === workInProgressRootRecoverableErrors + ? (workInProgressRootRecoverableErrors = errors) + : workInProgressRootRecoverableErrors.push.apply( + workInProgressRootRecoverableErrors, + errors + ); +} function isRenderConsistentWithExternalStores(finishedWork) { for (var node = finishedWork; ; ) { if (node.flags & 16384) { @@ -6670,7 +6962,11 @@ function performSyncWorkOnRoot(root) { throw Error("Root did not complete. This is a bug in React."); root.finishedWork = root.current.alternate; root.finishedLanes = lanes; - commitRoot(root, workInProgressRootRecoverableErrors); + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); ensureRootIsScheduled(root, now()); return null; } @@ -6906,12 +7202,12 @@ function handleError(root$jscomp$0, thrownValue) { root.flags |= 65536; thrownValue &= -thrownValue; root.lanes |= thrownValue; - var update$33 = createClassErrorUpdate( + var update$34 = createClassErrorUpdate( root, wakeable, thrownValue ); - enqueueCapturedUpdate(root, update$33); + enqueueCapturedUpdate(root, update$34); break a; } } @@ -6950,8 +7246,8 @@ function renderRootSync(root, lanes) { var prevExecutionContext = executionContext; executionContext |= 2; var prevDispatcher = pushDispatcher(); - (workInProgressRoot === root && workInProgressRootRenderLanes === lanes) || - prepareFreshStack(root, lanes); + if (workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes) + (workInProgressTransitions = null), prepareFreshStack(root, lanes); do try { workLoopSync(); @@ -7023,50 +7319,60 @@ function completeUnitOfWork(unitOfWork) { } while (null !== completedWork); 0 === workInProgressRootExitStatus && (workInProgressRootExitStatus = 5); } -function commitRoot(root, recoverableErrors) { +function commitRoot(root, recoverableErrors, transitions) { var previousUpdateLanePriority = currentUpdatePriority, prevTransition = ReactCurrentBatchConfig$2.transition; try { (ReactCurrentBatchConfig$2.transition = null), (currentUpdatePriority = 1), - commitRootImpl(root, recoverableErrors, previousUpdateLanePriority); + commitRootImpl( + root, + recoverableErrors, + transitions, + previousUpdateLanePriority + ); } finally { (ReactCurrentBatchConfig$2.transition = prevTransition), (currentUpdatePriority = previousUpdateLanePriority); } return null; } -function commitRootImpl(root, recoverableErrors, renderPriorityLevel) { +function commitRootImpl( + root, + recoverableErrors, + transitions, + renderPriorityLevel +) { do flushPassiveEffects(); while (null !== rootWithPendingPassiveEffects); if (0 !== (executionContext & 6)) throw Error("Should not already be working."); - var finishedWork = root.finishedWork, - lanes = root.finishedLanes; - if (null === finishedWork) return null; + transitions = root.finishedWork; + var lanes = root.finishedLanes; + if (null === transitions) return null; root.finishedWork = null; root.finishedLanes = 0; - if (finishedWork === root.current) + if (transitions === root.current) throw Error( "Cannot commit the same tree as before. This error is likely caused by a bug in React. Please file an issue." ); root.callbackNode = null; root.callbackPriority = 0; - var remainingLanes = finishedWork.lanes | finishedWork.childLanes; + var remainingLanes = transitions.lanes | transitions.childLanes; markRootFinished(root, remainingLanes); root === workInProgressRoot && ((workInProgress = workInProgressRoot = null), (workInProgressRootRenderLanes = 0)); - (0 === (finishedWork.subtreeFlags & 2064) && - 0 === (finishedWork.flags & 2064)) || + (0 === (transitions.subtreeFlags & 2064) && + 0 === (transitions.flags & 2064)) || rootDoesHavePassiveEffects || ((rootDoesHavePassiveEffects = !0), scheduleCallback$1(NormalPriority, function() { flushPassiveEffects(); return null; })); - remainingLanes = 0 !== (finishedWork.flags & 15990); - if (0 !== (finishedWork.subtreeFlags & 15990) || remainingLanes) { + remainingLanes = 0 !== (transitions.flags & 15990); + if (0 !== (transitions.subtreeFlags & 15990) || remainingLanes) { remainingLanes = ReactCurrentBatchConfig$2.transition; ReactCurrentBatchConfig$2.transition = null; var previousPriority = currentUpdatePriority; @@ -7074,30 +7380,30 @@ function commitRootImpl(root, recoverableErrors, renderPriorityLevel) { var prevExecutionContext = executionContext; executionContext |= 4; ReactCurrentOwner$2.current = null; - commitBeforeMutationEffects(root, finishedWork); - commitMutationEffects(root, finishedWork, lanes); - root.current = finishedWork; - commitLayoutEffects(finishedWork, root, lanes); + commitBeforeMutationEffects(root, transitions); + commitMutationEffectsOnFiber(transitions, root); + root.current = transitions; + commitLayoutEffects(transitions, root, lanes); requestPaint(); executionContext = prevExecutionContext; currentUpdatePriority = previousPriority; ReactCurrentBatchConfig$2.transition = remainingLanes; - } else root.current = finishedWork; + } else root.current = transitions; rootDoesHavePassiveEffects && ((rootDoesHavePassiveEffects = !1), (rootWithPendingPassiveEffects = root), (pendingPassiveEffectsLanes = lanes)); remainingLanes = root.pendingLanes; 0 === remainingLanes && (legacyErrorBoundariesThatAlreadyFailed = null); - onCommitRoot(finishedWork.stateNode, renderPriorityLevel); + onCommitRoot(transitions.stateNode, renderPriorityLevel); ensureRootIsScheduled(root, now()); if (null !== recoverableErrors) for ( - renderPriorityLevel = root.onRecoverableError, finishedWork = 0; - finishedWork < recoverableErrors.length; - finishedWork++ + renderPriorityLevel = root.onRecoverableError, transitions = 0; + transitions < recoverableErrors.length; + transitions++ ) - renderPriorityLevel(recoverableErrors[finishedWork]); + renderPriorityLevel(recoverableErrors[transitions]); if (hasUncaughtError) throw ((hasUncaughtError = !1), (root = firstUncaughtError), @@ -7332,21 +7638,43 @@ function pingSuspendedRoot(root, wakeable, pingedLanes) { : (workInProgressRootPingedLanes |= pingedLanes)); ensureRootIsScheduled(root, wakeable); } -function resolveRetryWakeable(boundaryFiber, wakeable) { - var retryCache = boundaryFiber.stateNode; - null !== retryCache && retryCache.delete(wakeable); - wakeable = 0; - 0 === wakeable && +function retryTimedOutBoundary(boundaryFiber, retryLane) { + 0 === retryLane && (0 === (boundaryFiber.mode & 1) - ? (wakeable = 1) - : ((wakeable = nextRetryLane), + ? (retryLane = 1) + : ((retryLane = nextRetryLane), (nextRetryLane <<= 1), 0 === (nextRetryLane & 130023424) && (nextRetryLane = 4194304))); - retryCache = requestEventTime(); - boundaryFiber = markUpdateLaneFromFiberToRoot(boundaryFiber, wakeable); + var eventTime = requestEventTime(); + boundaryFiber = markUpdateLaneFromFiberToRoot(boundaryFiber, retryLane); null !== boundaryFiber && - (markRootUpdated(boundaryFiber, wakeable, retryCache), - ensureRootIsScheduled(boundaryFiber, retryCache)); + (markRootUpdated(boundaryFiber, retryLane, eventTime), + ensureRootIsScheduled(boundaryFiber, eventTime)); +} +function retryDehydratedSuspenseBoundary(boundaryFiber) { + var suspenseState = boundaryFiber.memoizedState, + retryLane = 0; + null !== suspenseState && (retryLane = suspenseState.retryLane); + retryTimedOutBoundary(boundaryFiber, retryLane); +} +function resolveRetryWakeable(boundaryFiber, wakeable) { + var retryLane = 0; + switch (boundaryFiber.tag) { + case 13: + var retryCache = boundaryFiber.stateNode; + var suspenseState = boundaryFiber.memoizedState; + null !== suspenseState && (retryLane = suspenseState.retryLane); + break; + case 19: + retryCache = boundaryFiber.stateNode; + break; + default: + throw Error( + "Pinged unknown suspense boundary type. This is probably a bug in React." + ); + } + null !== retryCache && retryCache.delete(wakeable); + retryTimedOutBoundary(boundaryFiber, retryLane); } var beginWork$1; beginWork$1 = function(current, workInProgress, renderLanes) { @@ -7376,10 +7704,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { switch (workInProgress.tag) { case 2: var Component = workInProgress.type; - null !== current && - ((current.alternate = null), - (workInProgress.alternate = null), - (workInProgress.flags |= 2)); + resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress); current = workInProgress.pendingProps; var context = getMaskedContext( workInProgress, @@ -7433,10 +7758,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { case 16: Component = workInProgress.elementType; a: { - null !== current && - ((current.alternate = null), - (workInProgress.alternate = null), - (workInProgress.flags |= 2)); + resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress); current = workInProgress.pendingProps; context = Component._init; Component = context(Component._payload); @@ -7542,7 +7864,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { return ( pushHostContext(workInProgress), (Component = workInProgress.pendingProps.children), - markRef$1(current, workInProgress), + markRef(current, workInProgress), reconcileChildren(current, workInProgress, Component, renderLanes), workInProgress.child ); @@ -7636,24 +7958,24 @@ beginWork$1 = function(current, workInProgress, renderLanes) { } } else for ( - newValue = workInProgress.child, - null !== newValue && (newValue.return = workInProgress); - null !== newValue; + hasContext = workInProgress.child, + null !== hasContext && (hasContext.return = workInProgress); + null !== hasContext; ) { - var list = newValue.dependencies; + var list = hasContext.dependencies; if (null !== list) { - hasContext = newValue.child; + newValue = hasContext.child; for ( var dependency = list.firstContext; null !== dependency; ) { if (dependency.context === Component) { - if (1 === newValue.tag) { + if (1 === hasContext.tag) { dependency = createUpdate(-1, renderLanes & -renderLanes); dependency.tag = 2; - var updateQueue = newValue.updateQueue; + var updateQueue = hasContext.updateQueue; if (null !== updateQueue) { updateQueue = updateQueue.shared; var pending = updateQueue.pending; @@ -7664,11 +7986,11 @@ beginWork$1 = function(current, workInProgress, renderLanes) { updateQueue.pending = dependency; } } - newValue.lanes |= renderLanes; - dependency = newValue.alternate; + hasContext.lanes |= renderLanes; + dependency = hasContext.alternate; null !== dependency && (dependency.lanes |= renderLanes); scheduleContextWorkOnParentPath( - newValue.return, + hasContext.return, renderLanes, workInProgress ); @@ -7677,29 +7999,43 @@ beginWork$1 = function(current, workInProgress, renderLanes) { } dependency = dependency.next; } - } else - hasContext = - 10 === newValue.tag - ? newValue.type === workInProgress.type - ? null - : newValue.child - : newValue.child; - if (null !== hasContext) hasContext.return = newValue; + } else if (10 === hasContext.tag) + newValue = + hasContext.type === workInProgress.type + ? null + : hasContext.child; + else if (18 === hasContext.tag) { + newValue = hasContext.return; + if (null === newValue) + throw Error( + "We just came from a parent so we must have had a parent. This is a bug in React." + ); + newValue.lanes |= renderLanes; + list = newValue.alternate; + null !== list && (list.lanes |= renderLanes); + scheduleContextWorkOnParentPath( + newValue, + renderLanes, + workInProgress + ); + newValue = hasContext.sibling; + } else newValue = hasContext.child; + if (null !== newValue) newValue.return = hasContext; else - for (hasContext = newValue; null !== hasContext; ) { - if (hasContext === workInProgress) { - hasContext = null; + for (newValue = hasContext; null !== newValue; ) { + if (newValue === workInProgress) { + newValue = null; break; } - newValue = hasContext.sibling; - if (null !== newValue) { - newValue.return = hasContext.return; - hasContext = newValue; + hasContext = newValue.sibling; + if (null !== hasContext) { + hasContext.return = newValue.return; + newValue = hasContext; break; } - hasContext = hasContext.return; + newValue = newValue.return; } - newValue = hasContext; + hasContext = newValue; } reconcileChildren( current, @@ -7750,10 +8086,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { workInProgress.elementType === Component ? context : resolveDefaultProps(Component, context)), - null !== current && - ((current.alternate = null), - (workInProgress.alternate = null), - (workInProgress.flags |= 2)), + resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress), (workInProgress.tag = 1), isContextProvider(Component) ? ((current = !0), pushContextProvider(workInProgress)) @@ -8100,10 +8433,10 @@ batchedUpdatesImpl = function(fn, a) { } }; var roots = new Map(), - devToolsConfig$jscomp$inline_963 = { + devToolsConfig$jscomp$inline_967 = { findFiberByHostInstance: getInstanceFromTag, bundleType: 0, - version: "18.0.0-experimental-34aa5cfe0-20220329", + version: "18.2.0-next-d300cebde-20220601", rendererPackageName: "react-native-renderer", rendererConfig: { getInspectorDataForViewTag: function() { @@ -8118,11 +8451,11 @@ var roots = new Map(), }.bind(null, findNodeHandle) } }; -var internals$jscomp$inline_1217 = { - bundleType: devToolsConfig$jscomp$inline_963.bundleType, - version: devToolsConfig$jscomp$inline_963.version, - rendererPackageName: devToolsConfig$jscomp$inline_963.rendererPackageName, - rendererConfig: devToolsConfig$jscomp$inline_963.rendererConfig, +var internals$jscomp$inline_1239 = { + bundleType: devToolsConfig$jscomp$inline_967.bundleType, + version: devToolsConfig$jscomp$inline_967.version, + rendererPackageName: devToolsConfig$jscomp$inline_967.rendererPackageName, + rendererConfig: devToolsConfig$jscomp$inline_967.rendererConfig, overrideHookState: null, overrideHookStateDeletePath: null, overrideHookStateRenamePath: null, @@ -8138,26 +8471,26 @@ var internals$jscomp$inline_1217 = { return null === fiber ? null : fiber.stateNode; }, findFiberByHostInstance: - devToolsConfig$jscomp$inline_963.findFiberByHostInstance || + devToolsConfig$jscomp$inline_967.findFiberByHostInstance || emptyFindFiberByHostInstance, findHostInstancesForRefresh: null, scheduleRefresh: null, scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "18.0.0-experimental-34aa5cfe0-20220329" + reconcilerVersion: "18.2.0-next-d300cebde-20220601" }; if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { - var hook$jscomp$inline_1218 = __REACT_DEVTOOLS_GLOBAL_HOOK__; + var hook$jscomp$inline_1240 = __REACT_DEVTOOLS_GLOBAL_HOOK__; if ( - !hook$jscomp$inline_1218.isDisabled && - hook$jscomp$inline_1218.supportsFiber + !hook$jscomp$inline_1240.isDisabled && + hook$jscomp$inline_1240.supportsFiber ) try { - (rendererID = hook$jscomp$inline_1218.inject( - internals$jscomp$inline_1217 + (rendererID = hook$jscomp$inline_1240.inject( + internals$jscomp$inline_1239 )), - (injectedHook = hook$jscomp$inline_1218); + (injectedHook = hook$jscomp$inline_1240); } catch (err) {} } exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = { @@ -8212,7 +8545,8 @@ exports.render = function(element, containerTag, callback) { element: null, isDehydrated: !1, cache: null, - transitions: null + transitions: null, + pendingSuspenseBoundaries: null }; initializeUpdateQueue(JSCompiler_inline_result); roots.set(containerTag, root); diff --git a/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.js b/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.js index 917bd003a1c6e2..3a9a2679c42a49 100644 --- a/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.js +++ b/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.js @@ -8,7 +8,7 @@ * @nolint * @providesModule ReactNativeRenderer-profiling * @preventMunge - * @generated SignedSource<<06200cf762f5eb0f48046de454a64107>> + * @generated SignedSource<<2bf865cebf1e47b3fc0284498b4571db>> */ @@ -1028,7 +1028,7 @@ eventPluginOrder = Array.prototype.slice.call([ "ReactNativeBridgeEventPlugin" ]); recomputePluginOrdering(); -var injectedNamesToPlugins$jscomp$inline_228 = { +var injectedNamesToPlugins$jscomp$inline_236 = { ResponderEventPlugin: ResponderEventPlugin, ReactNativeBridgeEventPlugin: { eventTypes: {}, @@ -1074,33 +1074,33 @@ var injectedNamesToPlugins$jscomp$inline_228 = { } } }, - isOrderingDirty$jscomp$inline_229 = !1, - pluginName$jscomp$inline_230; -for (pluginName$jscomp$inline_230 in injectedNamesToPlugins$jscomp$inline_228) + isOrderingDirty$jscomp$inline_237 = !1, + pluginName$jscomp$inline_238; +for (pluginName$jscomp$inline_238 in injectedNamesToPlugins$jscomp$inline_236) if ( - injectedNamesToPlugins$jscomp$inline_228.hasOwnProperty( - pluginName$jscomp$inline_230 + injectedNamesToPlugins$jscomp$inline_236.hasOwnProperty( + pluginName$jscomp$inline_238 ) ) { - var pluginModule$jscomp$inline_231 = - injectedNamesToPlugins$jscomp$inline_228[pluginName$jscomp$inline_230]; + var pluginModule$jscomp$inline_239 = + injectedNamesToPlugins$jscomp$inline_236[pluginName$jscomp$inline_238]; if ( - !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_230) || - namesToPlugins[pluginName$jscomp$inline_230] !== - pluginModule$jscomp$inline_231 + !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_238) || + namesToPlugins[pluginName$jscomp$inline_238] !== + pluginModule$jscomp$inline_239 ) { - if (namesToPlugins[pluginName$jscomp$inline_230]) + if (namesToPlugins[pluginName$jscomp$inline_238]) throw Error( "EventPluginRegistry: Cannot inject two different event plugins using the same name, `" + - (pluginName$jscomp$inline_230 + "`.") + (pluginName$jscomp$inline_238 + "`.") ); namesToPlugins[ - pluginName$jscomp$inline_230 - ] = pluginModule$jscomp$inline_231; - isOrderingDirty$jscomp$inline_229 = !0; + pluginName$jscomp$inline_238 + ] = pluginModule$jscomp$inline_239; + isOrderingDirty$jscomp$inline_237 = !0; } } -isOrderingDirty$jscomp$inline_229 && recomputePluginOrdering(); +isOrderingDirty$jscomp$inline_237 && recomputePluginOrdering(); var instanceCache = new Map(), instanceProps = new Map(); function getInstanceFromTag(tag) { @@ -1952,6 +1952,12 @@ function getLanesToRetrySynchronouslyOnError(root) { root = root.pendingLanes & -1073741825; return 0 !== root ? root : root & 1073741824 ? 1073741824 : 0; } +function claimNextTransitionLane() { + var lane = nextTransitionLane; + nextTransitionLane <<= 1; + 0 === (nextTransitionLane & 4194240) && (nextTransitionLane = 64); + return lane; +} function createLaneMap(initial) { for (var laneMap = [], i = 0; 31 > i; i++) laneMap.push(initial); return laneMap; @@ -2211,7 +2217,28 @@ function flushSyncCallbacks() { } return null; } -var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig; +var forkStack = [], + forkStackIndex = 0, + treeForkProvider = null, + idStack = [], + idStackIndex = 0, + treeContextProvider = null; +function popTreeContext(workInProgress) { + for (; workInProgress === treeForkProvider; ) + (treeForkProvider = forkStack[--forkStackIndex]), + (forkStack[forkStackIndex] = null), + --forkStackIndex, + (forkStack[forkStackIndex] = null); + for (; workInProgress === treeContextProvider; ) + (treeContextProvider = idStack[--idStackIndex]), + (idStack[idStackIndex] = null), + --idStackIndex, + (idStack[idStackIndex] = null), + --idStackIndex, + (idStack[idStackIndex] = null); +} +var hydrationErrors = null, + ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig; function shallowEqual(objA, objB) { if (objectIs(objA, objB)) return !0; if ( @@ -2368,9 +2395,7 @@ function enqueueUpdate(fiber, update) { var updateQueue = fiber.updateQueue; null !== updateQueue && ((updateQueue = updateQueue.shared), - null !== workInProgressRoot && - 0 !== (fiber.mode & 1) && - 0 === (executionContext & 2) + isInterleavedUpdate(fiber) ? ((fiber = updateQueue.interleaved), null === fiber ? ((update.next = update), @@ -2738,26 +2763,6 @@ function mountClassInstance(workInProgress, ctor, newProps, renderLanes) { "function" === typeof instance.componentDidMount && (workInProgress.flags |= 4); } -var forkStack = [], - forkStackIndex = 0, - treeForkProvider = null, - idStack = [], - idStackIndex = 0, - treeContextProvider = null; -function popTreeContext(workInProgress) { - for (; workInProgress === treeForkProvider; ) - (treeForkProvider = forkStack[--forkStackIndex]), - (forkStack[forkStackIndex] = null), - --forkStackIndex, - (forkStack[forkStackIndex] = null); - for (; workInProgress === treeContextProvider; ) - (treeContextProvider = idStack[--idStackIndex]), - (idStack[idStackIndex] = null), - --idStackIndex, - (idStack[idStackIndex] = null), - --idStackIndex, - (idStack[idStackIndex] = null); -} function coerceRef(returnFiber, current, element) { returnFiber = element.ref; if ( @@ -2820,6 +2825,10 @@ function throwOnInvalidObjectType(returnFiber, newChild) { "). If you meant to render a collection of children, use an array instead." ); } +function resolveLazy(lazyType) { + var init = lazyType._init; + return init(lazyType._payload); +} function ChildReconciler(shouldTrackSideEffects) { function deleteChild(returnFiber, childToDelete) { if (shouldTrackSideEffects) { @@ -2892,7 +2901,14 @@ function ChildReconciler(shouldTrackSideEffects) { lanes, element.key ); - if (null !== current && current.elementType === elementType) + if ( + null !== current && + (current.elementType === elementType || + ("object" === typeof elementType && + null !== elementType && + elementType.$$typeof === REACT_LAZY_TYPE && + resolveLazy(elementType) === current.type)) + ) return ( (lanes = useFiber(current, element.props)), (lanes.ref = coerceRef(returnFiber, current, element)), @@ -2983,6 +2999,9 @@ function ChildReconciler(shouldTrackSideEffects) { (newChild.return = returnFiber), newChild ); + case REACT_LAZY_TYPE: + var init = newChild._init; + return createChild(returnFiber, init(newChild._payload), lanes); } if (isArrayImpl(newChild) || getIteratorFn(newChild)) return ( @@ -3018,6 +3037,11 @@ function ChildReconciler(shouldTrackSideEffects) { return newChild.key === key ? updatePortal(returnFiber, oldFiber, newChild, lanes) : null; + case REACT_LAZY_TYPE: + return ( + (key = newChild._init), + updateSlot(returnFiber, oldFiber, key(newChild._payload), lanes) + ); } if (isArrayImpl(newChild) || getIteratorFn(newChild)) return null !== key @@ -3060,6 +3084,15 @@ function ChildReconciler(shouldTrackSideEffects) { ) || null), updatePortal(returnFiber, existingChildren, newChild, lanes) ); + case REACT_LAZY_TYPE: + var init = newChild._init; + return updateFromMap( + existingChildren, + returnFiber, + newIdx, + init(newChild._payload), + lanes + ); } if (isArrayImpl(newChild) || getIteratorFn(newChild)) return ( @@ -3237,7 +3270,12 @@ function ChildReconciler(shouldTrackSideEffects) { }); return iteratorFn; } - return function(returnFiber, currentFirstChild, newChild, lanes) { + function reconcileChildFibers( + returnFiber, + currentFirstChild, + newChild, + lanes + ) { "object" === typeof newChild && null !== newChild && newChild.type === REACT_FRAGMENT_TYPE && @@ -3265,7 +3303,13 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber = currentFirstChild; break a; } - } else if (child.elementType === key) { + } else if ( + child.elementType === key || + ("object" === typeof key && + null !== key && + key.$$typeof === REACT_LAZY_TYPE && + resolveLazy(key) === child.type) + ) { deleteRemainingChildren(returnFiber, child.sibling); currentFirstChild = useFiber(child, newChild.props); currentFirstChild.ref = coerceRef( @@ -3346,6 +3390,16 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber = currentFirstChild; } return placeSingleChild(returnFiber); + case REACT_LAZY_TYPE: + return ( + (child = newChild._init), + reconcileChildFibers( + returnFiber, + currentFirstChild, + child(newChild._payload), + lanes + ) + ); } if (isArrayImpl(newChild)) return reconcileChildrenArray( @@ -3381,7 +3435,8 @@ function ChildReconciler(shouldTrackSideEffects) { (returnFiber = currentFirstChild)), placeSingleChild(returnFiber)) : deleteRemainingChildren(returnFiber, currentFirstChild); - }; + } + return reconcileChildFibers; } var reconcileChildFibers = ChildReconciler(!0), mountChildFibers = ChildReconciler(!1), @@ -3868,6 +3923,19 @@ function updateMemo(nextCreate, deps) { hook.memoizedState = [nextCreate, deps]; return nextCreate; } +function updateDeferredValueImpl(hook, prevValue, value) { + if (0 === (renderLanes & 21)) + return ( + hook.baseState && ((hook.baseState = !1), (didReceiveUpdate = !0)), + (hook.memoizedState = value) + ); + objectIs(value, prevValue) || + ((value = claimNextTransitionLane()), + (currentlyRenderingFiber$1.lanes |= value), + (workInProgressRootSkippedLanes |= value), + (hook.baseState = !0)); + return prevValue; +} function startTransition(setPending, callback) { var previousPriority = currentUpdatePriority; currentUpdatePriority = @@ -3949,9 +4017,7 @@ function enqueueRenderPhaseUpdate(queue, update) { queue.pending = update; } function enqueueUpdate$1(fiber, queue, update) { - null !== workInProgressRoot && - 0 !== (fiber.mode & 1) && - 0 === (executionContext & 2) + isInterleavedUpdate(fiber) ? ((fiber = queue.interleaved), null === fiber ? ((update.next = update), @@ -4056,29 +4122,14 @@ var ContextOnlyDispatcher = { useState: mountState, useDebugValue: mountDebugValue, useDeferredValue: function(value) { - var _mountState = mountState(value), - prevValue = _mountState[0], - setValue = _mountState[1]; - mountEffect( - function() { - var prevTransition = ReactCurrentBatchConfig$1.transition; - ReactCurrentBatchConfig$1.transition = {}; - try { - setValue(value); - } finally { - ReactCurrentBatchConfig$1.transition = prevTransition; - } - }, - [value] - ); - return prevValue; + return (mountWorkInProgressHook().memoizedState = value); }, useTransition: function() { - var _mountState2 = mountState(!1), - isPending = _mountState2[0]; - _mountState2 = startTransition.bind(null, _mountState2[1]); - mountWorkInProgressHook().memoizedState = _mountState2; - return [isPending, _mountState2]; + var _mountState = mountState(!1), + isPending = _mountState[0]; + _mountState = startTransition.bind(null, _mountState[1]); + mountWorkInProgressHook().memoizedState = _mountState; + return [isPending, _mountState]; }, useMutableSource: function() {}, useSyncExternalStore: function(subscribe, getSnapshot) { @@ -4132,22 +4183,8 @@ var ContextOnlyDispatcher = { }, useDebugValue: mountDebugValue, useDeferredValue: function(value) { - var _updateState = updateReducer(basicStateReducer), - prevValue = _updateState[0], - setValue = _updateState[1]; - updateEffect( - function() { - var prevTransition = ReactCurrentBatchConfig$1.transition; - ReactCurrentBatchConfig$1.transition = {}; - try { - setValue(value); - } finally { - ReactCurrentBatchConfig$1.transition = prevTransition; - } - }, - [value] - ); - return prevValue; + var hook = updateWorkInProgressHook(); + return updateDeferredValueImpl(hook, currentHook.memoizedState, value); }, useTransition: function() { var isPending = updateReducer(basicStateReducer)[0], @@ -4175,22 +4212,10 @@ var ContextOnlyDispatcher = { }, useDebugValue: mountDebugValue, useDeferredValue: function(value) { - var _rerenderState = rerenderReducer(basicStateReducer), - prevValue = _rerenderState[0], - setValue = _rerenderState[1]; - updateEffect( - function() { - var prevTransition = ReactCurrentBatchConfig$1.transition; - ReactCurrentBatchConfig$1.transition = {}; - try { - setValue(value); - } finally { - ReactCurrentBatchConfig$1.transition = prevTransition; - } - }, - [value] - ); - return prevValue; + var hook = updateWorkInProgressHook(); + return null === currentHook + ? (hook.memoizedState = value) + : updateDeferredValueImpl(hook, currentHook.memoizedState, value); }, useTransition: function() { var isPending = rerenderReducer(basicStateReducer)[0], @@ -4346,503 +4371,72 @@ function attachPingListener(root, wakeable, lanes) { isDevToolsPresent && restorePendingUpdaters(root, lanes), wakeable.then(pingCache, pingCache)); } -var appendAllChildren, updateHostContainer, updateHostComponent, updateHostText; -appendAllChildren = function(parent, workInProgress) { - for (var node = workInProgress.child; null !== node; ) { - if (5 === node.tag || 6 === node.tag) parent._children.push(node.stateNode); - else if (4 !== node.tag && null !== node.child) { - node.child.return = node; - node = node.child; - continue; - } - if (node === workInProgress) break; - for (; null === node.sibling; ) { - if (null === node.return || node.return === workInProgress) return; - node = node.return; - } - node.sibling.return = node.return; - node = node.sibling; - } -}; -updateHostContainer = function() {}; -updateHostComponent = function(current, workInProgress, type, newProps) { - current.memoizedProps !== newProps && - (requiredContext(contextStackCursor$1.current), - (workInProgress.updateQueue = UPDATE_SIGNAL)) && - (workInProgress.flags |= 4); -}; -updateHostText = function(current, workInProgress, oldText, newText) { - oldText !== newText && (workInProgress.flags |= 4); -}; -function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { - switch (renderState.tailMode) { - case "hidden": - hasRenderedATailFallback = renderState.tail; - for (var lastTailNode = null; null !== hasRenderedATailFallback; ) - null !== hasRenderedATailFallback.alternate && - (lastTailNode = hasRenderedATailFallback), - (hasRenderedATailFallback = hasRenderedATailFallback.sibling); - null === lastTailNode - ? (renderState.tail = null) - : (lastTailNode.sibling = null); - break; - case "collapsed": - lastTailNode = renderState.tail; - for (var lastTailNode$37 = null; null !== lastTailNode; ) - null !== lastTailNode.alternate && (lastTailNode$37 = lastTailNode), - (lastTailNode = lastTailNode.sibling); - null === lastTailNode$37 - ? hasRenderedATailFallback || null === renderState.tail - ? (renderState.tail = null) - : (renderState.tail.sibling = null) - : (lastTailNode$37.sibling = null); - } +var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner, + didReceiveUpdate = !1; +function reconcileChildren(current, workInProgress, nextChildren, renderLanes) { + workInProgress.child = + null === current + ? mountChildFibers(workInProgress, null, nextChildren, renderLanes) + : reconcileChildFibers( + workInProgress, + current.child, + nextChildren, + renderLanes + ); } -function bubbleProperties(completedWork) { - var didBailout = - null !== completedWork.alternate && - completedWork.alternate.child === completedWork.child, - newChildLanes = 0, - subtreeFlags = 0; - if (didBailout) - if (0 !== (completedWork.mode & 2)) { - for ( - var treeBaseDuration$39 = completedWork.selfBaseDuration, - child$40 = completedWork.child; - null !== child$40; - - ) - (newChildLanes |= child$40.lanes | child$40.childLanes), - (subtreeFlags |= child$40.subtreeFlags & 14680064), - (subtreeFlags |= child$40.flags & 14680064), - (treeBaseDuration$39 += child$40.treeBaseDuration), - (child$40 = child$40.sibling); - completedWork.treeBaseDuration = treeBaseDuration$39; - } else - for ( - treeBaseDuration$39 = completedWork.child; - null !== treeBaseDuration$39; - - ) - (newChildLanes |= - treeBaseDuration$39.lanes | treeBaseDuration$39.childLanes), - (subtreeFlags |= treeBaseDuration$39.subtreeFlags & 14680064), - (subtreeFlags |= treeBaseDuration$39.flags & 14680064), - (treeBaseDuration$39.return = completedWork), - (treeBaseDuration$39 = treeBaseDuration$39.sibling); - else if (0 !== (completedWork.mode & 2)) { - treeBaseDuration$39 = completedWork.actualDuration; - child$40 = completedWork.selfBaseDuration; - for (var child = completedWork.child; null !== child; ) - (newChildLanes |= child.lanes | child.childLanes), - (subtreeFlags |= child.subtreeFlags), - (subtreeFlags |= child.flags), - (treeBaseDuration$39 += child.actualDuration), - (child$40 += child.treeBaseDuration), - (child = child.sibling); - completedWork.actualDuration = treeBaseDuration$39; - completedWork.treeBaseDuration = child$40; - } else - for ( - treeBaseDuration$39 = completedWork.child; - null !== treeBaseDuration$39; - - ) - (newChildLanes |= - treeBaseDuration$39.lanes | treeBaseDuration$39.childLanes), - (subtreeFlags |= treeBaseDuration$39.subtreeFlags), - (subtreeFlags |= treeBaseDuration$39.flags), - (treeBaseDuration$39.return = completedWork), - (treeBaseDuration$39 = treeBaseDuration$39.sibling); - completedWork.subtreeFlags |= subtreeFlags; - completedWork.childLanes = newChildLanes; - return didBailout; +function updateForwardRef( + current, + workInProgress, + Component, + nextProps, + renderLanes +) { + Component = Component.render; + var ref = workInProgress.ref; + prepareToReadContext(workInProgress, renderLanes); + nextProps = renderWithHooks( + current, + workInProgress, + Component, + nextProps, + ref, + renderLanes + ); + if (null !== current && !didReceiveUpdate) + return ( + (workInProgress.updateQueue = current.updateQueue), + (workInProgress.flags &= -2053), + (current.lanes &= ~renderLanes), + bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) + ); + workInProgress.flags |= 1; + reconcileChildren(current, workInProgress, nextProps, renderLanes); + return workInProgress.child; } -function completeWork(current, workInProgress, renderLanes) { - var newProps = workInProgress.pendingProps; - popTreeContext(workInProgress); - switch (workInProgress.tag) { - case 2: - case 16: - case 15: - case 0: - case 11: - case 7: - case 8: - case 12: - case 9: - case 14: - return bubbleProperties(workInProgress), null; - case 1: - return ( - isContextProvider(workInProgress.type) && popContext(), - bubbleProperties(workInProgress), - null - ); - case 3: +function updateMemoComponent( + current, + workInProgress, + Component, + nextProps, + renderLanes +) { + if (null === current) { + var type = Component.type; + if ( + "function" === typeof type && + !shouldConstruct(type) && + void 0 === type.defaultProps && + null === Component.compare && + void 0 === Component.defaultProps + ) return ( - (newProps = workInProgress.stateNode), - popHostContainer(), - pop(didPerformWorkStackCursor), - pop(contextStackCursor), - resetWorkInProgressVersions(), - newProps.pendingContext && - ((newProps.context = newProps.pendingContext), - (newProps.pendingContext = null)), - (null !== current && null !== current.child) || - null === current || - (current.memoizedState.isDehydrated && - 0 === (workInProgress.flags & 256)) || - (workInProgress.flags |= 1024), - updateHostContainer(current, workInProgress), - bubbleProperties(workInProgress), - null - ); - case 5: - popHostContext(workInProgress); - renderLanes = requiredContext(rootInstanceStackCursor.current); - var type = workInProgress.type; - if (null !== current && null != workInProgress.stateNode) - updateHostComponent( + (workInProgress.tag = 15), + (workInProgress.type = type), + updateSimpleMemoComponent( current, workInProgress, type, - newProps, - renderLanes - ), - current.ref !== workInProgress.ref && (workInProgress.flags |= 512); - else { - if (!newProps) { - if (null === workInProgress.stateNode) - throw Error( - "We must have new props for new mounts. This error is likely caused by a bug in React. Please file an issue." - ); - bubbleProperties(workInProgress); - return null; - } - requiredContext(contextStackCursor$1.current); - current = allocateTag(); - type = getViewConfigForType(type); - var updatePayload = diffProperties( - null, - emptyObject, - newProps, - type.validAttributes - ); - ReactNativePrivateInterface.UIManager.createView( - current, - type.uiViewClassName, - renderLanes, - updatePayload - ); - renderLanes = new ReactNativeFiberHostComponent( - current, - type, - workInProgress - ); - instanceCache.set(current, workInProgress); - instanceProps.set(current, newProps); - appendAllChildren(renderLanes, workInProgress, !1, !1); - workInProgress.stateNode = renderLanes; - finalizeInitialChildren(renderLanes) && (workInProgress.flags |= 4); - null !== workInProgress.ref && (workInProgress.flags |= 512); - } - bubbleProperties(workInProgress); - return null; - case 6: - if (current && null != workInProgress.stateNode) - updateHostText( - current, - workInProgress, - current.memoizedProps, - newProps - ); - else { - if ("string" !== typeof newProps && null === workInProgress.stateNode) - throw Error( - "We must have new props for new mounts. This error is likely caused by a bug in React. Please file an issue." - ); - current = requiredContext(rootInstanceStackCursor.current); - if (!requiredContext(contextStackCursor$1.current).isInAParentText) - throw Error( - "Text strings must be rendered within a component." - ); - renderLanes = allocateTag(); - ReactNativePrivateInterface.UIManager.createView( - renderLanes, - "RCTRawText", - current, - { text: newProps } - ); - instanceCache.set(renderLanes, workInProgress); - workInProgress.stateNode = renderLanes; - } - bubbleProperties(workInProgress); - return null; - case 13: - pop(suspenseStackCursor); - newProps = workInProgress.memoizedState; - if (0 !== (workInProgress.flags & 128)) - return ( - (workInProgress.lanes = renderLanes), - 0 !== (workInProgress.mode & 2) && - transferActualDuration(workInProgress), - workInProgress - ); - newProps = null !== newProps; - renderLanes = !1; - null !== current && (renderLanes = null !== current.memoizedState); - newProps && - !renderLanes && - ((workInProgress.child.flags |= 8192), - 0 !== (workInProgress.mode & 1) && - (null === current || 0 !== (suspenseStackCursor.current & 1) - ? 0 === workInProgressRootExitStatus && - (workInProgressRootExitStatus = 3) - : renderDidSuspendDelayIfPossible())); - null !== workInProgress.updateQueue && (workInProgress.flags |= 4); - bubbleProperties(workInProgress); - 0 !== (workInProgress.mode & 2) && - newProps && - ((current = workInProgress.child), - null !== current && - (workInProgress.treeBaseDuration -= current.treeBaseDuration)); - return null; - case 4: - return ( - popHostContainer(), - updateHostContainer(current, workInProgress), - bubbleProperties(workInProgress), - null - ); - case 10: - return ( - popProvider(workInProgress.type._context), - bubbleProperties(workInProgress), - null - ); - case 17: - return ( - isContextProvider(workInProgress.type) && popContext(), - bubbleProperties(workInProgress), - null - ); - case 19: - pop(suspenseStackCursor); - type = workInProgress.memoizedState; - if (null === type) return bubbleProperties(workInProgress), null; - newProps = 0 !== (workInProgress.flags & 128); - updatePayload = type.rendering; - if (null === updatePayload) - if (newProps) cutOffTailIfNeeded(type, !1); - else { - if ( - 0 !== workInProgressRootExitStatus || - (null !== current && 0 !== (current.flags & 128)) - ) - for (current = workInProgress.child; null !== current; ) { - updatePayload = findFirstSuspended(current); - if (null !== updatePayload) { - workInProgress.flags |= 128; - cutOffTailIfNeeded(type, !1); - current = updatePayload.updateQueue; - null !== current && - ((workInProgress.updateQueue = current), - (workInProgress.flags |= 4)); - workInProgress.subtreeFlags = 0; - current = renderLanes; - for (newProps = workInProgress.child; null !== newProps; ) - (renderLanes = newProps), - (updatePayload = current), - (renderLanes.flags &= 14680066), - (type = renderLanes.alternate), - null === type - ? ((renderLanes.childLanes = 0), - (renderLanes.lanes = updatePayload), - (renderLanes.child = null), - (renderLanes.subtreeFlags = 0), - (renderLanes.memoizedProps = null), - (renderLanes.memoizedState = null), - (renderLanes.updateQueue = null), - (renderLanes.dependencies = null), - (renderLanes.stateNode = null), - (renderLanes.selfBaseDuration = 0), - (renderLanes.treeBaseDuration = 0)) - : ((renderLanes.childLanes = type.childLanes), - (renderLanes.lanes = type.lanes), - (renderLanes.child = type.child), - (renderLanes.subtreeFlags = 0), - (renderLanes.deletions = null), - (renderLanes.memoizedProps = type.memoizedProps), - (renderLanes.memoizedState = type.memoizedState), - (renderLanes.updateQueue = type.updateQueue), - (renderLanes.type = type.type), - (updatePayload = type.dependencies), - (renderLanes.dependencies = - null === updatePayload - ? null - : { - lanes: updatePayload.lanes, - firstContext: updatePayload.firstContext - }), - (renderLanes.selfBaseDuration = type.selfBaseDuration), - (renderLanes.treeBaseDuration = type.treeBaseDuration)), - (newProps = newProps.sibling); - push( - suspenseStackCursor, - (suspenseStackCursor.current & 1) | 2 - ); - return workInProgress.child; - } - current = current.sibling; - } - null !== type.tail && - now() > workInProgressRootRenderTargetTime && - ((workInProgress.flags |= 128), - (newProps = !0), - cutOffTailIfNeeded(type, !1), - (workInProgress.lanes = 4194304)); - } - else { - if (!newProps) - if ( - ((current = findFirstSuspended(updatePayload)), null !== current) - ) { - if ( - ((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 && - !updatePayload.alternate) - ) - return bubbleProperties(workInProgress), null; - } else - 2 * now() - type.renderingStartTime > - workInProgressRootRenderTargetTime && - 1073741824 !== renderLanes && - ((workInProgress.flags |= 128), - (newProps = !0), - cutOffTailIfNeeded(type, !1), - (workInProgress.lanes = 4194304)); - type.isBackwards - ? ((updatePayload.sibling = workInProgress.child), - (workInProgress.child = updatePayload)) - : ((current = type.last), - null !== current - ? (current.sibling = updatePayload) - : (workInProgress.child = updatePayload), - (type.last = updatePayload)); - } - if (null !== type.tail) - return ( - (workInProgress = type.tail), - (type.rendering = workInProgress), - (type.tail = workInProgress.sibling), - (type.renderingStartTime = now()), - (workInProgress.sibling = null), - (current = suspenseStackCursor.current), - push(suspenseStackCursor, newProps ? (current & 1) | 2 : current & 1), - workInProgress - ); - bubbleProperties(workInProgress); - return null; - case 22: - case 23: - return ( - popRenderLanes(), - (newProps = null !== workInProgress.memoizedState), - null !== current && - (null !== current.memoizedState) !== newProps && - (workInProgress.flags |= 8192), - newProps && 0 !== (workInProgress.mode & 1) - ? 0 !== (subtreeRenderLanes & 1073741824) && - (bubbleProperties(workInProgress), - workInProgress.subtreeFlags & 6 && (workInProgress.flags |= 8192)) - : bubbleProperties(workInProgress), - null - ); - case 24: - return null; - case 25: - return null; - } - throw Error( - "Unknown unit of work tag (" + - workInProgress.tag + - "). This error is likely caused by a bug in React. Please file an issue." - ); -} -var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner, - didReceiveUpdate = !1; -function reconcileChildren(current, workInProgress, nextChildren, renderLanes) { - workInProgress.child = - null === current - ? mountChildFibers(workInProgress, null, nextChildren, renderLanes) - : reconcileChildFibers( - workInProgress, - current.child, - nextChildren, - renderLanes - ); -} -function updateForwardRef( - current, - workInProgress, - Component, - nextProps, - renderLanes -) { - Component = Component.render; - var ref = workInProgress.ref; - prepareToReadContext(workInProgress, renderLanes); - nextProps = renderWithHooks( - current, - workInProgress, - Component, - nextProps, - ref, - renderLanes - ); - if (null !== current && !didReceiveUpdate) - return ( - (workInProgress.updateQueue = current.updateQueue), - (workInProgress.flags &= -2053), - (current.lanes &= ~renderLanes), - bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) - ); - workInProgress.flags |= 1; - reconcileChildren(current, workInProgress, nextProps, renderLanes); - return workInProgress.child; -} -function updateMemoComponent( - current, - workInProgress, - Component, - nextProps, - renderLanes -) { - if (null === current) { - var type = Component.type; - if ( - "function" === typeof type && - !shouldConstruct(type) && - void 0 === type.defaultProps && - null === Component.compare && - void 0 === Component.defaultProps - ) - return ( - (workInProgress.tag = 15), - (workInProgress.type = type), - updateSimpleMemoComponent( - current, - workInProgress, - type, - nextProps, + nextProps, renderLanes ) ); @@ -4879,18 +4473,24 @@ function updateSimpleMemoComponent( nextProps, renderLanes ) { - if ( - null !== current && - shallowEqual(current.memoizedProps, nextProps) && - current.ref === workInProgress.ref - ) - if (((didReceiveUpdate = !1), 0 !== (current.lanes & renderLanes))) - 0 !== (current.flags & 131072) && (didReceiveUpdate = !0); - else - return ( - (workInProgress.lanes = current.lanes), - bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) - ); + if (null !== current) { + var prevProps = current.memoizedProps; + if ( + shallowEqual(prevProps, nextProps) && + current.ref === workInProgress.ref + ) + if ( + ((didReceiveUpdate = !1), + (workInProgress.pendingProps = nextProps = prevProps), + 0 !== (current.lanes & renderLanes)) + ) + 0 !== (current.flags & 131072) && (didReceiveUpdate = !0); + else + return ( + (workInProgress.lanes = current.lanes), + bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) + ); + } return updateFunctionComponent( current, workInProgress, @@ -4905,7 +4505,11 @@ function updateOffscreenComponent(current, workInProgress, renderLanes) { prevState = null !== current ? current.memoizedState : null; if ("hidden" === nextProps.mode) if (0 === (workInProgress.mode & 1)) - (workInProgress.memoizedState = { baseLanes: 0, cachePool: null }), + (workInProgress.memoizedState = { + baseLanes: 0, + cachePool: null, + transitions: null + }), push(subtreeRenderLanesCursor, subtreeRenderLanes), (subtreeRenderLanes |= renderLanes); else { @@ -4918,14 +4522,19 @@ function updateOffscreenComponent(current, workInProgress, renderLanes) { (workInProgress.lanes = workInProgress.childLanes = 1073741824), (workInProgress.memoizedState = { baseLanes: current, - cachePool: null + cachePool: null, + transitions: null }), (workInProgress.updateQueue = null), push(subtreeRenderLanesCursor, subtreeRenderLanes), (subtreeRenderLanes |= current), null ); - workInProgress.memoizedState = { baseLanes: 0, cachePool: null }; + workInProgress.memoizedState = { + baseLanes: 0, + cachePool: null, + transitions: null + }; nextProps = null !== prevState ? prevState.baseLanes : renderLanes; push(subtreeRenderLanesCursor, subtreeRenderLanes); subtreeRenderLanes |= nextProps; @@ -4940,7 +4549,7 @@ function updateOffscreenComponent(current, workInProgress, renderLanes) { reconcileChildren(current, workInProgress, nextChildren, renderLanes); return workInProgress.child; } -function markRef$1(current, workInProgress) { +function markRef(current, workInProgress) { var ref = workInProgress.ref; if ( (null === current && null !== ref) || @@ -4992,10 +4601,7 @@ function updateClassComponent( } else hasContext = !1; prepareToReadContext(workInProgress, renderLanes); if (null === workInProgress.stateNode) - null !== current && - ((current.alternate = null), - (workInProgress.alternate = null), - (workInProgress.flags |= 2)), + resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress), constructClassInstance(workInProgress, Component, nextProps), mountClassInstance(workInProgress, Component, nextProps, renderLanes), (nextProps = !0); @@ -5189,7 +4795,7 @@ function finishClassComponent( hasContext, renderLanes ) { - markRef$1(current, workInProgress); + markRef(current, workInProgress); var didCaptureError = 0 !== (workInProgress.flags & 128); if (!shouldUpdate && !didCaptureError) return ( @@ -5239,14 +4845,15 @@ function pushHostRootContext(workInProgress) { } var SUSPENDED_MARKER = { dehydrated: null, treeContext: null, retryLane: 0 }; function mountSuspenseOffscreenState(renderLanes) { - return { baseLanes: renderLanes, cachePool: null }; + return { baseLanes: renderLanes, cachePool: null, transitions: null }; } function updateSuspenseComponent(current, workInProgress, renderLanes) { var nextProps = workInProgress.pendingProps, suspenseContext = suspenseStackCursor.current, showFallback = !1, + didSuspend = 0 !== (workInProgress.flags & 128), JSCompiler_temp; - (JSCompiler_temp = 0 !== (workInProgress.flags & 128)) || + (JSCompiler_temp = didSuspend) || (JSCompiler_temp = null !== current && null === current.memoizedState ? !1 @@ -5256,177 +4863,307 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { suspenseContext |= 1; push(suspenseStackCursor, suspenseContext & 1); if (null === current) { - suspenseContext = nextProps.children; - current = nextProps.fallback; - if (showFallback) + current = workInProgress.memoizedState; + if (null !== current && null !== current.dehydrated) return ( - (showFallback = workInProgress.mode), - (nextProps = workInProgress.child), - (suspenseContext = { mode: "hidden", children: suspenseContext }), - 0 === (showFallback & 1) && null !== nextProps - ? ((nextProps.childLanes = 0), - (nextProps.pendingProps = suspenseContext), + 0 === (workInProgress.mode & 1) + ? (workInProgress.lanes = 1) + : shim() + ? (workInProgress.lanes = 8) + : (workInProgress.lanes = 1073741824), + null + ); + didSuspend = nextProps.children; + current = nextProps.fallback; + return showFallback + ? ((nextProps = workInProgress.mode), + (showFallback = workInProgress.child), + (didSuspend = { mode: "hidden", children: didSuspend }), + 0 === (nextProps & 1) && null !== showFallback + ? ((showFallback.childLanes = 0), + (showFallback.pendingProps = didSuspend), workInProgress.mode & 2 && - ((nextProps.actualDuration = 0), - (nextProps.actualStartTime = -1), - (nextProps.selfBaseDuration = 0), - (nextProps.treeBaseDuration = 0))) - : (nextProps = createFiberFromOffscreen( - suspenseContext, - showFallback, + ((showFallback.actualDuration = 0), + (showFallback.actualStartTime = -1), + (showFallback.selfBaseDuration = 0), + (showFallback.treeBaseDuration = 0))) + : (showFallback = createFiberFromOffscreen( + didSuspend, + nextProps, 0, null )), (current = createFiberFromFragment( current, - showFallback, + nextProps, renderLanes, null )), - (nextProps.return = workInProgress), + (showFallback.return = workInProgress), (current.return = workInProgress), - (nextProps.sibling = current), - (workInProgress.child = nextProps), + (showFallback.sibling = current), + (workInProgress.child = showFallback), (workInProgress.child.memoizedState = mountSuspenseOffscreenState( renderLanes )), (workInProgress.memoizedState = SUSPENDED_MARKER), - current - ); - renderLanes = createFiberFromOffscreen( - { mode: "visible", children: suspenseContext }, - workInProgress.mode, - 0, - null - ); - renderLanes.return = workInProgress; - return (workInProgress.child = renderLanes); + current) + : mountSuspensePrimaryChildren(workInProgress, didSuspend); } - if (null !== current.memoizedState) { - if (showFallback) - return ( - (showFallback = updateSuspenseFallbackChildren( - current, - workInProgress, - nextProps.children, - nextProps.fallback, - renderLanes - )), - (nextProps = workInProgress.child), - (suspenseContext = current.child.memoizedState), - (nextProps.memoizedState = - null === suspenseContext - ? mountSuspenseOffscreenState(renderLanes) - : { - baseLanes: suspenseContext.baseLanes | renderLanes, - cachePool: null - }), - (nextProps.childLanes = current.childLanes & ~renderLanes), - (workInProgress.memoizedState = SUSPENDED_MARKER), - showFallback - ); - renderLanes = updateSuspensePrimaryChildren( + suspenseContext = current.memoizedState; + if ( + null !== suspenseContext && + ((JSCompiler_temp = suspenseContext.dehydrated), null !== JSCompiler_temp) + ) + return updateDehydratedSuspenseComponent( current, workInProgress, - nextProps.children, + didSuspend, + nextProps, + JSCompiler_temp, + suspenseContext, renderLanes ); - workInProgress.memoizedState = null; - return renderLanes; + if (showFallback) { + showFallback = nextProps.fallback; + didSuspend = workInProgress.mode; + suspenseContext = current.child; + JSCompiler_temp = suspenseContext.sibling; + var primaryChildProps = { mode: "hidden", children: nextProps.children }; + 0 === (didSuspend & 1) && workInProgress.child !== suspenseContext + ? ((nextProps = workInProgress.child), + (nextProps.childLanes = 0), + (nextProps.pendingProps = primaryChildProps), + workInProgress.mode & 2 && + ((nextProps.actualDuration = 0), + (nextProps.actualStartTime = -1), + (nextProps.selfBaseDuration = suspenseContext.selfBaseDuration), + (nextProps.treeBaseDuration = suspenseContext.treeBaseDuration)), + (workInProgress.deletions = null)) + : ((nextProps = createWorkInProgress(suspenseContext, primaryChildProps)), + (nextProps.subtreeFlags = suspenseContext.subtreeFlags & 14680064)); + null !== JSCompiler_temp + ? (showFallback = createWorkInProgress(JSCompiler_temp, showFallback)) + : ((showFallback = createFiberFromFragment( + showFallback, + didSuspend, + renderLanes, + null + )), + (showFallback.flags |= 2)); + showFallback.return = workInProgress; + nextProps.return = workInProgress; + nextProps.sibling = showFallback; + workInProgress.child = nextProps; + nextProps = showFallback; + showFallback = workInProgress.child; + didSuspend = current.child.memoizedState; + didSuspend = + null === didSuspend + ? mountSuspenseOffscreenState(renderLanes) + : { + baseLanes: didSuspend.baseLanes | renderLanes, + cachePool: null, + transitions: didSuspend.transitions + }; + showFallback.memoizedState = didSuspend; + showFallback.childLanes = current.childLanes & ~renderLanes; + workInProgress.memoizedState = SUSPENDED_MARKER; + return nextProps; } - if (showFallback) - return ( - (showFallback = updateSuspenseFallbackChildren( - current, - workInProgress, - nextProps.children, - nextProps.fallback, - renderLanes - )), - (nextProps = workInProgress.child), - (suspenseContext = current.child.memoizedState), - (nextProps.memoizedState = - null === suspenseContext - ? mountSuspenseOffscreenState(renderLanes) - : { - baseLanes: suspenseContext.baseLanes | renderLanes, - cachePool: null - }), - (nextProps.childLanes = current.childLanes & ~renderLanes), - (workInProgress.memoizedState = SUSPENDED_MARKER), - showFallback - ); - renderLanes = updateSuspensePrimaryChildren( - current, - workInProgress, - nextProps.children, - renderLanes - ); - workInProgress.memoizedState = null; - return renderLanes; -} -function updateSuspensePrimaryChildren( - current, - workInProgress, - primaryChildren, - renderLanes -) { - var currentPrimaryChildFragment = current.child; - current = currentPrimaryChildFragment.sibling; - primaryChildren = createWorkInProgress(currentPrimaryChildFragment, { + showFallback = current.child; + current = showFallback.sibling; + nextProps = createWorkInProgress(showFallback, { mode: "visible", - children: primaryChildren + children: nextProps.children }); - 0 === (workInProgress.mode & 1) && (primaryChildren.lanes = renderLanes); - primaryChildren.return = workInProgress; - primaryChildren.sibling = null; + 0 === (workInProgress.mode & 1) && (nextProps.lanes = renderLanes); + nextProps.return = workInProgress; + nextProps.sibling = null; null !== current && ((renderLanes = workInProgress.deletions), null === renderLanes ? ((workInProgress.deletions = [current]), (workInProgress.flags |= 16)) : renderLanes.push(current)); + workInProgress.child = nextProps; + workInProgress.memoizedState = null; + return nextProps; +} +function mountSuspensePrimaryChildren(workInProgress, primaryChildren) { + primaryChildren = createFiberFromOffscreen( + { mode: "visible", children: primaryChildren }, + workInProgress.mode, + 0, + null + ); + primaryChildren.return = workInProgress; return (workInProgress.child = primaryChildren); } -function updateSuspenseFallbackChildren( +function retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, + recoverableError +) { + null !== recoverableError && + (null === hydrationErrors + ? (hydrationErrors = [recoverableError]) + : hydrationErrors.push(recoverableError)); + reconcileChildFibers(workInProgress, current.child, null, renderLanes); + current = mountSuspensePrimaryChildren( + workInProgress, + workInProgress.pendingProps.children + ); + current.flags |= 2; + workInProgress.memoizedState = null; + return current; +} +function updateDehydratedSuspenseComponent( current, workInProgress, - primaryChildren, - fallbackChildren, + didSuspend, + nextProps, + suspenseInstance, + suspenseState, renderLanes ) { - var mode = workInProgress.mode; - current = current.child; - var currentFallbackChildFragment = current.sibling, - primaryChildProps = { mode: "hidden", children: primaryChildren }; - 0 === (mode & 1) && workInProgress.child !== current - ? ((primaryChildren = workInProgress.child), - (primaryChildren.childLanes = 0), - (primaryChildren.pendingProps = primaryChildProps), - workInProgress.mode & 2 && - ((primaryChildren.actualDuration = 0), - (primaryChildren.actualStartTime = -1), - (primaryChildren.selfBaseDuration = current.selfBaseDuration), - (primaryChildren.treeBaseDuration = current.treeBaseDuration)), - (workInProgress.deletions = null)) - : ((primaryChildren = createWorkInProgress(current, primaryChildProps)), - (primaryChildren.subtreeFlags = current.subtreeFlags & 14680064)); - null !== currentFallbackChildFragment - ? (fallbackChildren = createWorkInProgress( - currentFallbackChildFragment, - fallbackChildren - )) - : ((fallbackChildren = createFiberFromFragment( - fallbackChildren, - mode, - renderLanes, + if (didSuspend) { + if (workInProgress.flags & 256) + return ( + (workInProgress.flags &= -257), + retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, + Error( + "There was an error while hydrating this Suspense boundary. Switched to client rendering." + ) + ) + ); + if (null !== workInProgress.memoizedState) + return ( + (workInProgress.child = current.child), + (workInProgress.flags |= 128), null - )), - (fallbackChildren.flags |= 2)); - fallbackChildren.return = workInProgress; - primaryChildren.return = workInProgress; - primaryChildren.sibling = fallbackChildren; - workInProgress.child = primaryChildren; - return fallbackChildren; + ); + suspenseState = nextProps.fallback; + didSuspend = workInProgress.mode; + nextProps = createFiberFromOffscreen( + { mode: "visible", children: nextProps.children }, + didSuspend, + 0, + null + ); + suspenseState = createFiberFromFragment( + suspenseState, + didSuspend, + renderLanes, + null + ); + suspenseState.flags |= 2; + nextProps.return = workInProgress; + suspenseState.return = workInProgress; + nextProps.sibling = suspenseState; + workInProgress.child = nextProps; + 0 !== (workInProgress.mode & 1) && + reconcileChildFibers(workInProgress, current.child, null, renderLanes); + workInProgress.child.memoizedState = mountSuspenseOffscreenState( + renderLanes + ); + workInProgress.memoizedState = SUSPENDED_MARKER; + return suspenseState; + } + if (0 === (workInProgress.mode & 1)) + return retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, + null + ); + if (shim()) + return ( + (suspenseState = shim().errorMessage), + retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, + suspenseState + ? Error(suspenseState) + : Error( + "The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering." + ) + ) + ); + didSuspend = 0 !== (renderLanes & current.childLanes); + if (didReceiveUpdate || didSuspend) { + nextProps = workInProgressRoot; + if (null !== nextProps) { + switch (renderLanes & -renderLanes) { + case 4: + didSuspend = 2; + break; + case 16: + didSuspend = 8; + break; + 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: + case 8388608: + case 16777216: + case 33554432: + case 67108864: + didSuspend = 32; + break; + case 536870912: + didSuspend = 268435456; + break; + default: + didSuspend = 0; + } + nextProps = + 0 !== (didSuspend & (nextProps.suspendedLanes | renderLanes)) + ? 0 + : didSuspend; + 0 !== nextProps && + nextProps !== suspenseState.retryLane && + ((suspenseState.retryLane = nextProps), + scheduleUpdateOnFiber(current, nextProps, -1)); + } + renderDidSuspendDelayIfPossible(); + return retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, + Error( + "This Suspense boundary received an update before it finished hydrating. This caused the boundary to switch to client rendering. The usual way to fix this is to wrap the original update in startTransition." + ) + ); + } + if (shim()) + return ( + (workInProgress.flags |= 128), + (workInProgress.child = current.child), + retryDehydratedSuspenseBoundary.bind(null, current), + shim(), + null + ); + current = mountSuspensePrimaryChildren(workInProgress, nextProps.children); + current.flags |= 4096; + return current; } function scheduleSuspenseWorkOnFiber(fiber, renderLanes, propagationRoot) { fiber.lanes |= renderLanes; @@ -5545,6 +5282,13 @@ function updateSuspenseListComponent(current, workInProgress, renderLanes) { } return workInProgress.child; } +function resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress) { + 0 === (workInProgress.mode & 1) && + null !== current && + ((current.alternate = null), + (workInProgress.alternate = null), + (workInProgress.flags |= 2)); +} function bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) { null !== current && (workInProgress.dependencies = current.dependencies); profilerStartTime = -1; @@ -5565,81 +5309,553 @@ function bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) { (renderLanes.return = workInProgress); renderLanes.sibling = null; } - return workInProgress.child; + return workInProgress.child; +} +function attemptEarlyBailoutIfNoScheduledUpdate( + current, + workInProgress, + renderLanes +) { + switch (workInProgress.tag) { + case 3: + pushHostRootContext(workInProgress); + break; + case 5: + pushHostContext(workInProgress); + break; + case 1: + isContextProvider(workInProgress.type) && + pushContextProvider(workInProgress); + break; + case 4: + pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); + break; + case 10: + var context = workInProgress.type._context, + nextValue = workInProgress.memoizedProps.value; + push(valueCursor, context._currentValue); + context._currentValue = nextValue; + break; + case 12: + 0 !== (renderLanes & workInProgress.childLanes) && + (workInProgress.flags |= 4); + context = workInProgress.stateNode; + context.effectDuration = 0; + context.passiveEffectDuration = 0; + break; + case 13: + context = workInProgress.memoizedState; + if (null !== context) { + if (null !== context.dehydrated) + return ( + push(suspenseStackCursor, suspenseStackCursor.current & 1), + (workInProgress.flags |= 128), + null + ); + if (0 !== (renderLanes & workInProgress.child.childLanes)) + return updateSuspenseComponent(current, workInProgress, renderLanes); + push(suspenseStackCursor, suspenseStackCursor.current & 1); + current = bailoutOnAlreadyFinishedWork( + current, + workInProgress, + renderLanes + ); + return null !== current ? current.sibling : null; + } + push(suspenseStackCursor, suspenseStackCursor.current & 1); + break; + case 19: + context = 0 !== (renderLanes & workInProgress.childLanes); + if (0 !== (current.flags & 128)) { + if (context) + return updateSuspenseListComponent( + current, + workInProgress, + renderLanes + ); + workInProgress.flags |= 128; + } + nextValue = workInProgress.memoizedState; + null !== nextValue && + ((nextValue.rendering = null), + (nextValue.tail = null), + (nextValue.lastEffect = null)); + push(suspenseStackCursor, suspenseStackCursor.current); + if (context) break; + else return null; + case 22: + case 23: + return ( + (workInProgress.lanes = 0), + updateOffscreenComponent(current, workInProgress, renderLanes) + ); + } + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); +} +var appendAllChildren, + updateHostContainer, + updateHostComponent$1, + updateHostText$1; +appendAllChildren = function(parent, workInProgress) { + for (var node = workInProgress.child; null !== node; ) { + if (5 === node.tag || 6 === node.tag) parent._children.push(node.stateNode); + else if (4 !== node.tag && null !== node.child) { + node.child.return = node; + node = node.child; + continue; + } + if (node === workInProgress) break; + for (; null === node.sibling; ) { + if (null === node.return || node.return === workInProgress) return; + node = node.return; + } + node.sibling.return = node.return; + node = node.sibling; + } +}; +updateHostContainer = function() {}; +updateHostComponent$1 = function(current, workInProgress, type, newProps) { + current.memoizedProps !== newProps && + (requiredContext(contextStackCursor$1.current), + (workInProgress.updateQueue = UPDATE_SIGNAL)) && + (workInProgress.flags |= 4); +}; +updateHostText$1 = function(current, workInProgress, oldText, newText) { + oldText !== newText && (workInProgress.flags |= 4); +}; +function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { + switch (renderState.tailMode) { + case "hidden": + hasRenderedATailFallback = renderState.tail; + for (var lastTailNode = null; null !== hasRenderedATailFallback; ) + null !== hasRenderedATailFallback.alternate && + (lastTailNode = hasRenderedATailFallback), + (hasRenderedATailFallback = hasRenderedATailFallback.sibling); + null === lastTailNode + ? (renderState.tail = null) + : (lastTailNode.sibling = null); + break; + case "collapsed": + lastTailNode = renderState.tail; + for (var lastTailNode$63 = null; null !== lastTailNode; ) + null !== lastTailNode.alternate && (lastTailNode$63 = lastTailNode), + (lastTailNode = lastTailNode.sibling); + null === lastTailNode$63 + ? hasRenderedATailFallback || null === renderState.tail + ? (renderState.tail = null) + : (renderState.tail.sibling = null) + : (lastTailNode$63.sibling = null); + } } -function attemptEarlyBailoutIfNoScheduledUpdate( - current, - workInProgress, - renderLanes -) { +function bubbleProperties(completedWork) { + var didBailout = + null !== completedWork.alternate && + completedWork.alternate.child === completedWork.child, + newChildLanes = 0, + subtreeFlags = 0; + if (didBailout) + if (0 !== (completedWork.mode & 2)) { + for ( + var treeBaseDuration$65 = completedWork.selfBaseDuration, + child$66 = completedWork.child; + null !== child$66; + + ) + (newChildLanes |= child$66.lanes | child$66.childLanes), + (subtreeFlags |= child$66.subtreeFlags & 14680064), + (subtreeFlags |= child$66.flags & 14680064), + (treeBaseDuration$65 += child$66.treeBaseDuration), + (child$66 = child$66.sibling); + completedWork.treeBaseDuration = treeBaseDuration$65; + } else + for ( + treeBaseDuration$65 = completedWork.child; + null !== treeBaseDuration$65; + + ) + (newChildLanes |= + treeBaseDuration$65.lanes | treeBaseDuration$65.childLanes), + (subtreeFlags |= treeBaseDuration$65.subtreeFlags & 14680064), + (subtreeFlags |= treeBaseDuration$65.flags & 14680064), + (treeBaseDuration$65.return = completedWork), + (treeBaseDuration$65 = treeBaseDuration$65.sibling); + else if (0 !== (completedWork.mode & 2)) { + treeBaseDuration$65 = completedWork.actualDuration; + child$66 = completedWork.selfBaseDuration; + for (var child = completedWork.child; null !== child; ) + (newChildLanes |= child.lanes | child.childLanes), + (subtreeFlags |= child.subtreeFlags), + (subtreeFlags |= child.flags), + (treeBaseDuration$65 += child.actualDuration), + (child$66 += child.treeBaseDuration), + (child = child.sibling); + completedWork.actualDuration = treeBaseDuration$65; + completedWork.treeBaseDuration = child$66; + } else + for ( + treeBaseDuration$65 = completedWork.child; + null !== treeBaseDuration$65; + + ) + (newChildLanes |= + treeBaseDuration$65.lanes | treeBaseDuration$65.childLanes), + (subtreeFlags |= treeBaseDuration$65.subtreeFlags), + (subtreeFlags |= treeBaseDuration$65.flags), + (treeBaseDuration$65.return = completedWork), + (treeBaseDuration$65 = treeBaseDuration$65.sibling); + completedWork.subtreeFlags |= subtreeFlags; + completedWork.childLanes = newChildLanes; + return didBailout; +} +function completeWork(current, workInProgress, renderLanes) { + var newProps = workInProgress.pendingProps; + popTreeContext(workInProgress); switch (workInProgress.tag) { + case 2: + case 16: + case 15: + case 0: + case 11: + case 7: + case 8: + case 12: + case 9: + case 14: + return bubbleProperties(workInProgress), null; + case 1: + return ( + isContextProvider(workInProgress.type) && popContext(), + bubbleProperties(workInProgress), + null + ); case 3: - pushHostRootContext(workInProgress); - break; + return ( + (renderLanes = workInProgress.stateNode), + popHostContainer(), + pop(didPerformWorkStackCursor), + pop(contextStackCursor), + resetWorkInProgressVersions(), + renderLanes.pendingContext && + ((renderLanes.context = renderLanes.pendingContext), + (renderLanes.pendingContext = null)), + (null !== current && null !== current.child) || + null === current || + (current.memoizedState.isDehydrated && + 0 === (workInProgress.flags & 256)) || + ((workInProgress.flags |= 1024), + null !== hydrationErrors && + (queueRecoverableErrors(hydrationErrors), + (hydrationErrors = null))), + updateHostContainer(current, workInProgress), + bubbleProperties(workInProgress), + null + ); case 5: - pushHostContext(workInProgress); - break; - case 1: - isContextProvider(workInProgress.type) && - pushContextProvider(workInProgress); - break; - case 4: - pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); - break; - case 10: - var context = workInProgress.type._context, - nextValue = workInProgress.memoizedProps.value; - push(valueCursor, context._currentValue); - context._currentValue = nextValue; - break; - case 12: - 0 !== (renderLanes & workInProgress.childLanes) && - (workInProgress.flags |= 4); - context = workInProgress.stateNode; - context.effectDuration = 0; - context.passiveEffectDuration = 0; - break; - case 13: - if (null !== workInProgress.memoizedState) { - if (0 !== (renderLanes & workInProgress.child.childLanes)) - return updateSuspenseComponent(current, workInProgress, renderLanes); - push(suspenseStackCursor, suspenseStackCursor.current & 1); - current = bailoutOnAlreadyFinishedWork( + popHostContext(workInProgress); + renderLanes = requiredContext(rootInstanceStackCursor.current); + var type = workInProgress.type; + if (null !== current && null != workInProgress.stateNode) + updateHostComponent$1( current, workInProgress, + type, + newProps, renderLanes + ), + current.ref !== workInProgress.ref && (workInProgress.flags |= 512); + else { + if (!newProps) { + if (null === workInProgress.stateNode) + throw Error( + "We must have new props for new mounts. This error is likely caused by a bug in React. Please file an issue." + ); + bubbleProperties(workInProgress); + return null; + } + requiredContext(contextStackCursor$1.current); + current = allocateTag(); + type = getViewConfigForType(type); + var updatePayload = diffProperties( + null, + emptyObject, + newProps, + type.validAttributes ); - return null !== current ? current.sibling : null; + ReactNativePrivateInterface.UIManager.createView( + current, + type.uiViewClassName, + renderLanes, + updatePayload + ); + renderLanes = new ReactNativeFiberHostComponent( + current, + type, + workInProgress + ); + instanceCache.set(current, workInProgress); + instanceProps.set(current, newProps); + appendAllChildren(renderLanes, workInProgress, !1, !1); + workInProgress.stateNode = renderLanes; + finalizeInitialChildren(renderLanes) && (workInProgress.flags |= 4); + null !== workInProgress.ref && (workInProgress.flags |= 512); } - push(suspenseStackCursor, suspenseStackCursor.current & 1); - break; + bubbleProperties(workInProgress); + return null; + case 6: + if (current && null != workInProgress.stateNode) + updateHostText$1( + current, + workInProgress, + current.memoizedProps, + newProps + ); + else { + if ("string" !== typeof newProps && null === workInProgress.stateNode) + throw Error( + "We must have new props for new mounts. This error is likely caused by a bug in React. Please file an issue." + ); + current = requiredContext(rootInstanceStackCursor.current); + if (!requiredContext(contextStackCursor$1.current).isInAParentText) + throw Error( + "Text strings must be rendered within a component." + ); + renderLanes = allocateTag(); + ReactNativePrivateInterface.UIManager.createView( + renderLanes, + "RCTRawText", + current, + { text: newProps } + ); + instanceCache.set(renderLanes, workInProgress); + workInProgress.stateNode = renderLanes; + } + bubbleProperties(workInProgress); + return null; + case 13: + pop(suspenseStackCursor); + newProps = workInProgress.memoizedState; + if ( + null === current || + (null !== current.memoizedState && + null !== current.memoizedState.dehydrated) + ) { + if (null !== newProps && null !== newProps.dehydrated) { + if (null === current) { + throw Error( + "A dehydrated suspense component was completed without a hydrated node. This is probably a bug in React." + ); + throw Error( + "Expected prepareToHydrateHostSuspenseInstance() to never be called. This error is likely caused by a bug in React. Please file an issue." + ); + } + 0 === (workInProgress.flags & 128) && + (workInProgress.memoizedState = null); + workInProgress.flags |= 4; + bubbleProperties(workInProgress); + 0 !== (workInProgress.mode & 2) && + null !== newProps && + ((type = workInProgress.child), + null !== type && + (workInProgress.treeBaseDuration -= type.treeBaseDuration)); + type = !1; + } else + null !== hydrationErrors && + (queueRecoverableErrors(hydrationErrors), (hydrationErrors = null)), + (type = !0); + if (!type) return workInProgress.flags & 65536 ? workInProgress : null; + } + if (0 !== (workInProgress.flags & 128)) + return ( + (workInProgress.lanes = renderLanes), + 0 !== (workInProgress.mode & 2) && + transferActualDuration(workInProgress), + workInProgress + ); + renderLanes = null !== newProps; + renderLanes !== (null !== current && null !== current.memoizedState) && + renderLanes && + ((workInProgress.child.flags |= 8192), + 0 !== (workInProgress.mode & 1) && + (null === current || 0 !== (suspenseStackCursor.current & 1) + ? 0 === workInProgressRootExitStatus && + (workInProgressRootExitStatus = 3) + : renderDidSuspendDelayIfPossible())); + null !== workInProgress.updateQueue && (workInProgress.flags |= 4); + bubbleProperties(workInProgress); + 0 !== (workInProgress.mode & 2) && + renderLanes && + ((current = workInProgress.child), + null !== current && + (workInProgress.treeBaseDuration -= current.treeBaseDuration)); + return null; + case 4: + return ( + popHostContainer(), + updateHostContainer(current, workInProgress), + bubbleProperties(workInProgress), + null + ); + case 10: + return ( + popProvider(workInProgress.type._context), + bubbleProperties(workInProgress), + null + ); + case 17: + return ( + isContextProvider(workInProgress.type) && popContext(), + bubbleProperties(workInProgress), + null + ); case 19: - context = 0 !== (renderLanes & workInProgress.childLanes); - if (0 !== (current.flags & 128)) { - if (context) - return updateSuspenseListComponent( - current, - workInProgress, - renderLanes - ); - workInProgress.flags |= 128; + pop(suspenseStackCursor); + type = workInProgress.memoizedState; + if (null === type) return bubbleProperties(workInProgress), null; + newProps = 0 !== (workInProgress.flags & 128); + updatePayload = type.rendering; + if (null === updatePayload) + if (newProps) cutOffTailIfNeeded(type, !1); + else { + if ( + 0 !== workInProgressRootExitStatus || + (null !== current && 0 !== (current.flags & 128)) + ) + for (current = workInProgress.child; null !== current; ) { + updatePayload = findFirstSuspended(current); + if (null !== updatePayload) { + workInProgress.flags |= 128; + cutOffTailIfNeeded(type, !1); + current = updatePayload.updateQueue; + null !== current && + ((workInProgress.updateQueue = current), + (workInProgress.flags |= 4)); + workInProgress.subtreeFlags = 0; + current = renderLanes; + for (renderLanes = workInProgress.child; null !== renderLanes; ) + (newProps = renderLanes), + (updatePayload = current), + (newProps.flags &= 14680066), + (type = newProps.alternate), + null === type + ? ((newProps.childLanes = 0), + (newProps.lanes = updatePayload), + (newProps.child = null), + (newProps.subtreeFlags = 0), + (newProps.memoizedProps = null), + (newProps.memoizedState = null), + (newProps.updateQueue = null), + (newProps.dependencies = null), + (newProps.stateNode = null), + (newProps.selfBaseDuration = 0), + (newProps.treeBaseDuration = 0)) + : ((newProps.childLanes = type.childLanes), + (newProps.lanes = type.lanes), + (newProps.child = type.child), + (newProps.subtreeFlags = 0), + (newProps.deletions = null), + (newProps.memoizedProps = type.memoizedProps), + (newProps.memoizedState = type.memoizedState), + (newProps.updateQueue = type.updateQueue), + (newProps.type = type.type), + (updatePayload = type.dependencies), + (newProps.dependencies = + null === updatePayload + ? null + : { + lanes: updatePayload.lanes, + firstContext: updatePayload.firstContext + }), + (newProps.selfBaseDuration = type.selfBaseDuration), + (newProps.treeBaseDuration = type.treeBaseDuration)), + (renderLanes = renderLanes.sibling); + push( + suspenseStackCursor, + (suspenseStackCursor.current & 1) | 2 + ); + return workInProgress.child; + } + current = current.sibling; + } + null !== type.tail && + now() > workInProgressRootRenderTargetTime && + ((workInProgress.flags |= 128), + (newProps = !0), + cutOffTailIfNeeded(type, !1), + (workInProgress.lanes = 4194304)); + } + else { + if (!newProps) + if ( + ((current = findFirstSuspended(updatePayload)), null !== current) + ) { + if ( + ((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 && + !updatePayload.alternate) + ) + return bubbleProperties(workInProgress), null; + } else + 2 * now() - type.renderingStartTime > + workInProgressRootRenderTargetTime && + 1073741824 !== renderLanes && + ((workInProgress.flags |= 128), + (newProps = !0), + cutOffTailIfNeeded(type, !1), + (workInProgress.lanes = 4194304)); + type.isBackwards + ? ((updatePayload.sibling = workInProgress.child), + (workInProgress.child = updatePayload)) + : ((current = type.last), + null !== current + ? (current.sibling = updatePayload) + : (workInProgress.child = updatePayload), + (type.last = updatePayload)); } - nextValue = workInProgress.memoizedState; - null !== nextValue && - ((nextValue.rendering = null), - (nextValue.tail = null), - (nextValue.lastEffect = null)); - push(suspenseStackCursor, suspenseStackCursor.current); - if (context) break; - else return null; + if (null !== type.tail) + return ( + (workInProgress = type.tail), + (type.rendering = workInProgress), + (type.tail = workInProgress.sibling), + (type.renderingStartTime = now()), + (workInProgress.sibling = null), + (current = suspenseStackCursor.current), + push(suspenseStackCursor, newProps ? (current & 1) | 2 : current & 1), + workInProgress + ); + bubbleProperties(workInProgress); + return null; case 22: case 23: return ( - (workInProgress.lanes = 0), - updateOffscreenComponent(current, workInProgress, renderLanes) + popRenderLanes(), + (renderLanes = null !== workInProgress.memoizedState), + null !== current && + (null !== current.memoizedState) !== renderLanes && + (workInProgress.flags |= 8192), + renderLanes && 0 !== (workInProgress.mode & 1) + ? 0 !== (subtreeRenderLanes & 1073741824) && + (bubbleProperties(workInProgress), + workInProgress.subtreeFlags & 6 && (workInProgress.flags |= 8192)) + : bubbleProperties(workInProgress), + null ); + case 24: + return null; + case 25: + return null; } - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); + throw Error( + "Unknown unit of work tag (" + + workInProgress.tag + + "). This error is likely caused by a bug in React. Please file an issue." + ); } function unwindWork(current, workInProgress) { popTreeContext(workInProgress); @@ -5669,16 +5885,23 @@ function unwindWork(current, workInProgress) { case 5: return popHostContext(workInProgress), null; case 13: - return ( - pop(suspenseStackCursor), - (current = workInProgress.flags), - current & 65536 - ? ((workInProgress.flags = (current & -65537) | 128), - 0 !== (workInProgress.mode & 2) && - transferActualDuration(workInProgress), - workInProgress) - : null - ); + pop(suspenseStackCursor); + current = workInProgress.memoizedState; + if ( + null !== current && + null !== current.dehydrated && + null === workInProgress.alternate + ) + throw Error( + "Threw in newly mounted dehydrated component. This is likely a bug in React. Please file an issue." + ); + current = workInProgress.flags; + return current & 65536 + ? ((workInProgress.flags = (current & -65537) | 128), + 0 !== (workInProgress.mode & 2) && + transferActualDuration(workInProgress), + workInProgress) + : null; case 19: return pop(suspenseStackCursor), null; case 4: @@ -5810,77 +6033,13 @@ function commitHookEffectListMount(flags, finishedWork) { var effect = (finishedWork = finishedWork.next); do { if ((effect.tag & flags) === flags) { - var create$83 = effect.create; - effect.destroy = create$83(); + var create$81 = effect.create; + effect.destroy = create$81(); } effect = effect.next; } while (effect !== finishedWork); } } -function commitUnmount(finishedRoot, current, nearestMountedAncestor) { - if (injectedHook && "function" === typeof injectedHook.onCommitFiberUnmount) - try { - injectedHook.onCommitFiberUnmount(rendererID, current); - } catch (err) {} - switch (current.tag) { - case 0: - case 11: - case 14: - case 15: - finishedRoot = current.updateQueue; - if ( - null !== finishedRoot && - ((finishedRoot = finishedRoot.lastEffect), null !== finishedRoot) - ) { - var effect = (finishedRoot = finishedRoot.next); - do { - var _effect = effect, - destroy = _effect.destroy; - _effect = _effect.tag; - void 0 !== destroy && - (0 !== (_effect & 2) - ? safelyCallDestroy(current, nearestMountedAncestor, destroy) - : 0 !== (_effect & 4) && - (current.mode & 2 - ? (startLayoutEffectTimer(), - safelyCallDestroy(current, nearestMountedAncestor, destroy), - recordLayoutEffectDuration(current)) - : safelyCallDestroy( - current, - nearestMountedAncestor, - destroy - ))); - effect = effect.next; - } while (effect !== finishedRoot); - } - break; - case 1: - safelyDetachRef(current, nearestMountedAncestor); - finishedRoot = current.stateNode; - if ("function" === typeof finishedRoot.componentWillUnmount) - try { - if ( - ((finishedRoot.props = current.memoizedProps), - (finishedRoot.state = current.memoizedState), - current.mode & 2) - ) - try { - startLayoutEffectTimer(), finishedRoot.componentWillUnmount(); - } finally { - recordLayoutEffectDuration(current); - } - else finishedRoot.componentWillUnmount(); - } catch (error) { - captureCommitPhaseError(current, nearestMountedAncestor, error); - } - break; - case 5: - safelyDetachRef(current, nearestMountedAncestor); - break; - case 4: - unmountHostComponents(finishedRoot, current, nearestMountedAncestor); - } -} function detachFiberAfterEffects(fiber) { var alternate = fiber.alternate; null !== alternate && @@ -5919,40 +6078,6 @@ function getHostSibling(fiber) { if (!(fiber.flags & 2)) return fiber.stateNode; } } -function commitPlacement(finishedWork) { - a: { - for (var parent = finishedWork.return; null !== parent; ) { - if (isHostParent(parent)) break a; - parent = parent.return; - } - throw Error( - "Expected to find a host parent. This error is likely caused by a bug in React. Please file an issue." - ); - } - var parentFiber = parent; - switch (parentFiber.tag) { - case 5: - parent = parentFiber.stateNode; - parentFiber.flags & 32 && (parentFiber.flags &= -33); - parentFiber = getHostSibling(finishedWork); - insertOrAppendPlacementNode(finishedWork, parentFiber, parent); - break; - case 3: - case 4: - parent = parentFiber.stateNode.containerInfo; - parentFiber = getHostSibling(finishedWork); - insertOrAppendPlacementNodeIntoContainer( - finishedWork, - parentFiber, - parent - ); - break; - default: - throw Error( - "Invalid host parent fiber. This error is likely caused by a bug in React. Please file an issue." - ); - } -} function insertOrAppendPlacementNodeIntoContainer(node, before, parent) { var tag = node.tag; if (5 === tag || 6 === tag) @@ -6033,194 +6158,171 @@ function insertOrAppendPlacementNode(node, before, parent) { ) insertOrAppendPlacementNode(node, before, parent), (node = node.sibling); } -function unmountHostComponents( - finishedRoot$jscomp$0, - current, - nearestMountedAncestor$jscomp$0 +var hostParent = null, + hostParentIsContainer = !1; +function recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + parent ) { - for ( - var node = current, - currentParentIsValid = !1, - currentParent, - currentParentIsContainer; - ; - - ) { - if (!currentParentIsValid) { - currentParentIsValid = node.return; - a: for (;;) { - if (null === currentParentIsValid) - throw Error( - "Expected to find a host parent. This error is likely caused by a bug in React. Please file an issue." - ); - currentParent = currentParentIsValid.stateNode; - switch (currentParentIsValid.tag) { - case 5: - currentParentIsContainer = !1; - break a; - case 3: - currentParent = currentParent.containerInfo; - currentParentIsContainer = !0; - break a; - case 4: - currentParent = currentParent.containerInfo; - currentParentIsContainer = !0; - break a; - } - currentParentIsValid = currentParentIsValid.return; - } - currentParentIsValid = !0; - } - if (5 === node.tag || 6 === node.tag) { - a: for ( - var finishedRoot = finishedRoot$jscomp$0, - root = node, - nearestMountedAncestor = nearestMountedAncestor$jscomp$0, - node$jscomp$0 = root; - ; - - ) - if ( - (commitUnmount(finishedRoot, node$jscomp$0, nearestMountedAncestor), - null !== node$jscomp$0.child && 4 !== node$jscomp$0.tag) - ) - (node$jscomp$0.child.return = node$jscomp$0), - (node$jscomp$0 = node$jscomp$0.child); - else { - if (node$jscomp$0 === root) break a; - for (; null === node$jscomp$0.sibling; ) { - if (null === node$jscomp$0.return || node$jscomp$0.return === root) - break a; - node$jscomp$0 = node$jscomp$0.return; - } - node$jscomp$0.sibling.return = node$jscomp$0.return; - node$jscomp$0 = node$jscomp$0.sibling; - } - currentParentIsContainer - ? ((finishedRoot = currentParent), - recursivelyUncacheFiberNode(node.stateNode), - ReactNativePrivateInterface.UIManager.manageChildren( - finishedRoot, - [], - [], - [], - [], - [0] - )) - : ((finishedRoot = currentParent), - (nearestMountedAncestor = node.stateNode), - recursivelyUncacheFiberNode(nearestMountedAncestor), - (root = finishedRoot._children), - (nearestMountedAncestor = root.indexOf(nearestMountedAncestor)), - root.splice(nearestMountedAncestor, 1), - ReactNativePrivateInterface.UIManager.manageChildren( - finishedRoot._nativeTag, - [], - [], - [], - [], - [nearestMountedAncestor] - )); - } else if (4 === node.tag) { - if (null !== node.child) { - currentParent = node.stateNode.containerInfo; - currentParentIsContainer = !0; - node.child.return = node; - node = node.child; - continue; - } - } else if ( - (commitUnmount( - finishedRoot$jscomp$0, - node, - nearestMountedAncestor$jscomp$0 - ), - null !== node.child) - ) { - node.child.return = node; - node = node.child; - continue; - } - if (node === current) break; - for (; null === node.sibling; ) { - if (null === node.return || node.return === current) return; - node = node.return; - 4 === node.tag && (currentParentIsValid = !1); - } - node.sibling.return = node.return; - node = node.sibling; - } -} -function commitWork(current, finishedWork) { - switch (finishedWork.tag) { + for (parent = parent.child; null !== parent; ) + commitDeletionEffectsOnFiber(finishedRoot, nearestMountedAncestor, parent), + (parent = parent.sibling); +} +function commitDeletionEffectsOnFiber( + finishedRoot, + nearestMountedAncestor, + deletedFiber +) { + if (injectedHook && "function" === typeof injectedHook.onCommitFiberUnmount) + try { + injectedHook.onCommitFiberUnmount(rendererID, deletedFiber); + } catch (err) {} + switch (deletedFiber.tag) { + case 5: + safelyDetachRef(deletedFiber, nearestMountedAncestor); + case 6: + var prevHostParent = hostParent, + prevHostParentIsContainer = hostParentIsContainer; + hostParent = null; + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + hostParent = prevHostParent; + hostParentIsContainer = prevHostParentIsContainer; + null !== hostParent && + (hostParentIsContainer + ? ((finishedRoot = hostParent), + recursivelyUncacheFiberNode(deletedFiber.stateNode), + ReactNativePrivateInterface.UIManager.manageChildren( + finishedRoot, + [], + [], + [], + [], + [0] + )) + : ((finishedRoot = hostParent), + (nearestMountedAncestor = deletedFiber.stateNode), + recursivelyUncacheFiberNode(nearestMountedAncestor), + (deletedFiber = finishedRoot._children), + (nearestMountedAncestor = deletedFiber.indexOf( + nearestMountedAncestor + )), + deletedFiber.splice(nearestMountedAncestor, 1), + ReactNativePrivateInterface.UIManager.manageChildren( + finishedRoot._nativeTag, + [], + [], + [], + [], + [nearestMountedAncestor] + ))); + break; + case 18: + null !== hostParent && shim(hostParent, deletedFiber.stateNode); + break; + case 4: + prevHostParent = hostParent; + prevHostParentIsContainer = hostParentIsContainer; + hostParent = deletedFiber.stateNode.containerInfo; + hostParentIsContainer = !0; + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + hostParent = prevHostParent; + hostParentIsContainer = prevHostParentIsContainer; + break; case 0: case 11: case 14: case 15: - commitHookEffectListUnmount(3, finishedWork, finishedWork.return); - commitHookEffectListMount(3, finishedWork); - if (finishedWork.mode & 2) + prevHostParent = deletedFiber.updateQueue; + if ( + null !== prevHostParent && + ((prevHostParent = prevHostParent.lastEffect), null !== prevHostParent) + ) { + prevHostParentIsContainer = prevHostParent = prevHostParent.next; + do { + var _effect = prevHostParentIsContainer, + destroy = _effect.destroy; + _effect = _effect.tag; + void 0 !== destroy && + (0 !== (_effect & 2) + ? safelyCallDestroy(deletedFiber, nearestMountedAncestor, destroy) + : 0 !== (_effect & 4) && + (deletedFiber.mode & 2 + ? (startLayoutEffectTimer(), + safelyCallDestroy( + deletedFiber, + nearestMountedAncestor, + destroy + ), + recordLayoutEffectDuration(deletedFiber)) + : safelyCallDestroy( + deletedFiber, + nearestMountedAncestor, + destroy + ))); + prevHostParentIsContainer = prevHostParentIsContainer.next; + } while (prevHostParentIsContainer !== prevHostParent); + } + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + break; + case 1: + safelyDetachRef(deletedFiber, nearestMountedAncestor); + prevHostParent = deletedFiber.stateNode; + if ("function" === typeof prevHostParent.componentWillUnmount) try { - startLayoutEffectTimer(), - commitHookEffectListUnmount(5, finishedWork, finishedWork.return); - } finally { - recordLayoutEffectDuration(finishedWork); + if ( + ((prevHostParent.props = deletedFiber.memoizedProps), + (prevHostParent.state = deletedFiber.memoizedState), + deletedFiber.mode & 2) + ) + try { + startLayoutEffectTimer(), prevHostParent.componentWillUnmount(); + } finally { + recordLayoutEffectDuration(deletedFiber); + } + else prevHostParent.componentWillUnmount(); + } catch (error) { + captureCommitPhaseError(deletedFiber, nearestMountedAncestor, error); } - else commitHookEffectListUnmount(5, finishedWork, finishedWork.return); - return; - case 1: - return; - case 5: - var instance = finishedWork.stateNode; - if (null != instance) { - var newProps = finishedWork.memoizedProps; - current = null !== current ? current.memoizedProps : newProps; - var updatePayload = finishedWork.updateQueue; - finishedWork.updateQueue = null; - null !== updatePayload && - ((finishedWork = instance.viewConfig), - instanceProps.set(instance._nativeTag, newProps), - (newProps = diffProperties( - null, - current, - newProps, - finishedWork.validAttributes - )), - null != newProps && - ReactNativePrivateInterface.UIManager.updateView( - instance._nativeTag, - finishedWork.uiViewClassName, - newProps - )); - } - return; - case 6: - if (null === finishedWork.stateNode) - throw Error( - "This should have a text node initialized. This error is likely caused by a bug in React. Please file an issue." - ); - ReactNativePrivateInterface.UIManager.updateView( - finishedWork.stateNode, - "RCTRawText", - { text: finishedWork.memoizedProps } + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + break; + case 21: + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + break; + case 22: + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + break; + default: + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber ); - return; - case 3: - return; - case 12: - return; - case 13: - attachSuspenseRetryListeners(finishedWork); - return; - case 19: - attachSuspenseRetryListeners(finishedWork); - return; - case 17: - return; } - throw Error( - "This unit of work tag should not have side-effects. This error is likely caused by a bug in React. Please file an issue." - ); } function attachSuspenseRetryListeners(finishedWork) { var wakeables = finishedWork.updateQueue; @@ -6245,163 +6347,330 @@ function attachSuspenseRetryListeners(finishedWork) { }); } } -function commitMutationEffects(root, firstChild, committedLanes) { +function commitMutationEffects(root, finishedWork, committedLanes) { inProgressLanes = committedLanes; inProgressRoot = root; - for (nextEffect = firstChild; null !== nextEffect; ) { - firstChild = nextEffect; - committedLanes = firstChild.deletions; - if (null !== committedLanes) - for (var i = 0; i < committedLanes.length; i++) { - var childToDelete = committedLanes[i]; + commitMutationEffectsOnFiber(finishedWork, root); + inProgressRoot = inProgressLanes = null; +} +function recursivelyTraverseMutationEffects(root$jscomp$0, parentFiber) { + var deletions = parentFiber.deletions; + if (null !== deletions) + for (var i = 0; i < deletions.length; i++) { + var childToDelete = deletions[i]; + try { + var root = root$jscomp$0, + returnFiber = parentFiber, + parent = returnFiber; + a: for (; null !== parent; ) { + switch (parent.tag) { + case 5: + hostParent = parent.stateNode; + hostParentIsContainer = !1; + break a; + case 3: + hostParent = parent.stateNode.containerInfo; + hostParentIsContainer = !0; + break a; + case 4: + hostParent = parent.stateNode.containerInfo; + hostParentIsContainer = !0; + break a; + } + parent = parent.return; + } + if (null === hostParent) + throw Error( + "Expected to find a host parent. This error is likely caused by a bug in React. Please file an issue." + ); + commitDeletionEffectsOnFiber(root, returnFiber, childToDelete); + hostParent = null; + hostParentIsContainer = !1; + var alternate = childToDelete.alternate; + null !== alternate && (alternate.return = null); + childToDelete.return = null; + } catch (error) { + captureCommitPhaseError(childToDelete, parentFiber, error); + } + } + if (parentFiber.subtreeFlags & 12854) + for (parentFiber = parentFiber.child; null !== parentFiber; ) + commitMutationEffectsOnFiber(parentFiber, root$jscomp$0), + (parentFiber = parentFiber.sibling); +} +function commitMutationEffectsOnFiber(finishedWork, root) { + var current = finishedWork.alternate, + flags = finishedWork.flags; + switch (finishedWork.tag) { + case 0: + case 11: + case 14: + case 15: + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + if (flags & 4) { try { - unmountHostComponents(root, childToDelete, firstChild); - var alternate = childToDelete.alternate; - null !== alternate && (alternate.return = null); - childToDelete.return = null; + commitHookEffectListUnmount(3, finishedWork, finishedWork.return), + commitHookEffectListMount(3, finishedWork); } catch (error) { - captureCommitPhaseError(childToDelete, firstChild, error); + captureCommitPhaseError(finishedWork, finishedWork.return, error); } + if (finishedWork.mode & 2) { + try { + startLayoutEffectTimer(), + commitHookEffectListUnmount(5, finishedWork, finishedWork.return); + } catch (error$93) { + captureCommitPhaseError( + finishedWork, + finishedWork.return, + error$93 + ); + } + recordLayoutEffectDuration(finishedWork); + } else + try { + commitHookEffectListUnmount(5, finishedWork, finishedWork.return); + } catch (error$94) { + captureCommitPhaseError( + finishedWork, + finishedWork.return, + error$94 + ); + } } - committedLanes = firstChild.child; - if (0 !== (firstChild.subtreeFlags & 12854) && null !== committedLanes) - (committedLanes.return = firstChild), (nextEffect = committedLanes); - else - for (; null !== nextEffect; ) { - firstChild = nextEffect; - try { - var flags = firstChild.flags; - if (flags & 512) { - var current = firstChild.alternate; - if (null !== current) { - committedLanes = current; - var currentRef = committedLanes.ref; - if (null !== currentRef) - if ("function" === typeof currentRef) - if (committedLanes.mode & 2) - try { - startLayoutEffectTimer(), currentRef(null); - } finally { - recordLayoutEffectDuration(committedLanes); - } - else currentRef(null); - else currentRef.current = null; + break; + case 1: + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + flags & 512 && + null !== current && + safelyDetachRef(current, current.return); + break; + case 5: + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + flags & 512 && + null !== current && + safelyDetachRef(current, current.return); + if (flags & 4) { + var instance$96 = finishedWork.stateNode; + if (null != instance$96) { + var newProps = finishedWork.memoizedProps, + oldProps = null !== current ? current.memoizedProps : newProps, + updatePayload = finishedWork.updateQueue; + finishedWork.updateQueue = null; + if (null !== updatePayload) + try { + var viewConfig = instance$96.viewConfig; + instanceProps.set(instance$96._nativeTag, newProps); + var updatePayload$jscomp$0 = diffProperties( + null, + oldProps, + newProps, + viewConfig.validAttributes + ); + null != updatePayload$jscomp$0 && + ReactNativePrivateInterface.UIManager.updateView( + instance$96._nativeTag, + viewConfig.uiViewClassName, + updatePayload$jscomp$0 + ); + } catch (error$97) { + captureCommitPhaseError( + finishedWork, + finishedWork.return, + error$97 + ); } - } - if (flags & 8192) - switch (firstChild.tag) { - case 13: - if (null !== firstChild.memoizedState) { - var current$92 = firstChild.alternate; - if (null === current$92 || null === current$92.memoizedState) - globalMostRecentFallbackTime = now(); - } - break; - case 22: - a: { - committedLanes = firstChild; - var isHidden = null !== firstChild.memoizedState; - i = null; - for (childToDelete = committedLanes; ; ) { - if (5 === childToDelete.tag) { - if (null === i) { - i = childToDelete; - var instance = childToDelete.stateNode; - if (isHidden) { - var instance$jscomp$0 = instance, - viewConfig = instance$jscomp$0.viewConfig; - var updatePayload = diffProperties( - null, - emptyObject, - { style: { display: "none" } }, - viewConfig.validAttributes - ); - ReactNativePrivateInterface.UIManager.updateView( - instance$jscomp$0._nativeTag, - viewConfig.uiViewClassName, - updatePayload - ); - } else { - var instance$jscomp$1 = childToDelete.stateNode, - props = childToDelete.memoizedProps, - viewConfig$jscomp$0 = instance$jscomp$1.viewConfig, - prevProps = assign({}, props, { - style: [props.style, { display: "none" }] - }); - var updatePayload$jscomp$0 = diffProperties( - null, - prevProps, - props, - viewConfig$jscomp$0.validAttributes - ); - ReactNativePrivateInterface.UIManager.updateView( - instance$jscomp$1._nativeTag, - viewConfig$jscomp$0.uiViewClassName, - updatePayload$jscomp$0 - ); - } - } - } else if (6 === childToDelete.tag) { - if (null === i) throw Error("Not yet implemented."); - } else if ( - ((22 !== childToDelete.tag && 23 !== childToDelete.tag) || - null === childToDelete.memoizedState || - childToDelete === committedLanes) && - null !== childToDelete.child - ) { - childToDelete.child.return = childToDelete; - childToDelete = childToDelete.child; - continue; - } - if (childToDelete === committedLanes) break; - for (; null === childToDelete.sibling; ) { - if ( - null === childToDelete.return || - childToDelete.return === committedLanes - ) - break a; - i === childToDelete && (i = null); - childToDelete = childToDelete.return; - } - i === childToDelete && (i = null); - childToDelete.sibling.return = childToDelete.return; - childToDelete = childToDelete.sibling; - } + } + } + break; + case 6: + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + if (flags & 4) { + if (null === finishedWork.stateNode) + throw Error( + "This should have a text node initialized. This error is likely caused by a bug in React. Please file an issue." + ); + viewConfig = finishedWork.stateNode; + updatePayload$jscomp$0 = finishedWork.memoizedProps; + try { + ReactNativePrivateInterface.UIManager.updateView( + viewConfig, + "RCTRawText", + { text: updatePayload$jscomp$0 } + ); + } catch (error$98) { + captureCommitPhaseError(finishedWork, finishedWork.return, error$98); + } + } + break; + case 3: + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + break; + case 4: + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + break; + case 13: + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + viewConfig = finishedWork.child; + viewConfig.flags & 8192 && + null !== viewConfig.memoizedState && + (null === viewConfig.alternate || + null === viewConfig.alternate.memoizedState) && + (globalMostRecentFallbackTime = now()); + flags & 4 && attachSuspenseRetryListeners(finishedWork); + break; + case 22: + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + if (flags & 8192) + a: for ( + viewConfig = null !== finishedWork.memoizedState, + updatePayload$jscomp$0 = null, + current = finishedWork; + ; + + ) { + if (5 === current.tag) { + if (null === updatePayload$jscomp$0) { + updatePayload$jscomp$0 = current; + try { + if (((instance$96 = current.stateNode), viewConfig)) + (newProps = instance$96.viewConfig), + (oldProps = diffProperties( + null, + emptyObject, + { style: { display: "none" } }, + newProps.validAttributes + )), + ReactNativePrivateInterface.UIManager.updateView( + instance$96._nativeTag, + newProps.uiViewClassName, + oldProps + ); + else { + updatePayload = current.stateNode; + var props = current.memoizedProps, + viewConfig$jscomp$0 = updatePayload.viewConfig, + prevProps = assign({}, props, { + style: [props.style, { display: "none" }] + }); + var updatePayload$jscomp$1 = diffProperties( + null, + prevProps, + props, + viewConfig$jscomp$0.validAttributes + ); + ReactNativePrivateInterface.UIManager.updateView( + updatePayload._nativeTag, + viewConfig$jscomp$0.uiViewClassName, + updatePayload$jscomp$1 + ); } + } catch (error) { + captureCommitPhaseError( + finishedWork, + finishedWork.return, + error + ); + } } - switch (flags & 4102) { - case 2: - commitPlacement(firstChild); - firstChild.flags &= -3; - break; - case 6: - commitPlacement(firstChild); - firstChild.flags &= -3; - commitWork(firstChild.alternate, firstChild); - break; - case 4096: - firstChild.flags &= -4097; - break; - case 4100: - firstChild.flags &= -4097; - commitWork(firstChild.alternate, firstChild); - break; - case 4: - commitWork(firstChild.alternate, firstChild); + } else if (6 === current.tag) { + if (null === updatePayload$jscomp$0) + try { + throw Error("Not yet implemented."); + } catch (error$88) { + captureCommitPhaseError( + finishedWork, + finishedWork.return, + error$88 + ); + } + } else if ( + ((22 !== current.tag && 23 !== current.tag) || + null === current.memoizedState || + current === finishedWork) && + null !== current.child + ) { + current.child.return = current; + current = current.child; + continue; } - } catch (error) { - captureCommitPhaseError(firstChild, firstChild.return, error); + if (current === finishedWork) break a; + for (; null === current.sibling; ) { + if (null === current.return || current.return === finishedWork) + break a; + updatePayload$jscomp$0 === current && + (updatePayload$jscomp$0 = null); + current = current.return; + } + updatePayload$jscomp$0 === current && (updatePayload$jscomp$0 = null); + current.sibling.return = current.return; + current = current.sibling; } - committedLanes = firstChild.sibling; - if (null !== committedLanes) { - committedLanes.return = firstChild.return; - nextEffect = committedLanes; - break; + break; + case 19: + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + flags & 4 && attachSuspenseRetryListeners(finishedWork); + break; + case 21: + break; + default: + recursivelyTraverseMutationEffects(root, finishedWork), + commitReconciliationEffects(finishedWork); + } +} +function commitReconciliationEffects(finishedWork) { + var flags = finishedWork.flags; + if (flags & 2) { + try { + a: { + for (var parent = finishedWork.return; null !== parent; ) { + if (isHostParent(parent)) { + var JSCompiler_inline_result = parent; + break a; + } + parent = parent.return; } - nextEffect = firstChild.return; + throw Error( + "Expected to find a host parent. This error is likely caused by a bug in React. Please file an issue." + ); + } + switch (JSCompiler_inline_result.tag) { + case 5: + var parent$jscomp$0 = JSCompiler_inline_result.stateNode; + JSCompiler_inline_result.flags & 32 && + (JSCompiler_inline_result.flags &= -33); + var before = getHostSibling(finishedWork); + insertOrAppendPlacementNode(finishedWork, before, parent$jscomp$0); + break; + case 3: + case 4: + var parent$89 = JSCompiler_inline_result.stateNode.containerInfo, + before$90 = getHostSibling(finishedWork); + insertOrAppendPlacementNodeIntoContainer( + finishedWork, + before$90, + parent$89 + ); + break; + default: + throw Error( + "Invalid host parent fiber. This error is likely caused by a bug in React. Please file an issue." + ); } + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } + finishedWork.flags &= -3; } - inProgressRoot = inProgressLanes = null; + flags & 4096 && (finishedWork.flags &= -4097); } function commitLayoutEffects(finishedWork, root, committedLanes) { inProgressLanes = committedLanes; @@ -6477,21 +6746,21 @@ function commitLayoutEffects(finishedWork, root, committedLanes) { commitUpdateQueue(committedLanes, updateQueue, instance); break; case 3: - var updateQueue$85 = committedLanes.updateQueue; - if (null !== updateQueue$85) { - var instance$86 = null; + var updateQueue$83 = committedLanes.updateQueue; + if (null !== updateQueue$83) { + var instance$84 = null; if (null !== committedLanes.child) switch (committedLanes.child.tag) { case 5: - instance$86 = committedLanes.child.stateNode; + instance$84 = committedLanes.child.stateNode; break; case 1: - instance$86 = committedLanes.child.stateNode; + instance$84 = committedLanes.child.stateNode; } commitUpdateQueue( committedLanes, - updateQueue$85, - instance$86 + updateQueue$83, + instance$84 ); } break; @@ -6506,7 +6775,7 @@ function commitLayoutEffects(finishedWork, root, committedLanes) { onCommit = _finishedWork$memoize2.onCommit, onRender = _finishedWork$memoize2.onRender, effectDuration = committedLanes.stateNode.effectDuration; - instance$86 = commitTime; + instance$84 = commitTime; current = null === current ? "mount" : "update"; currentUpdateIsNested && (current = "nested-update"); "function" === typeof onRender && @@ -6516,14 +6785,14 @@ function commitLayoutEffects(finishedWork, root, committedLanes) { committedLanes.actualDuration, committedLanes.treeBaseDuration, committedLanes.actualStartTime, - instance$86 + instance$84 ); "function" === typeof onCommit && onCommit( committedLanes.memoizedProps.id, current, effectDuration, - instance$86 + instance$84 ); enqueuePendingPassiveProfilerEffect(committedLanes); var parentFiber = committedLanes.return; @@ -6546,6 +6815,7 @@ function commitLayoutEffects(finishedWork, root, committedLanes) { case 21: case 22: case 23: + case 25: break; default: throw Error( @@ -6553,27 +6823,27 @@ function commitLayoutEffects(finishedWork, root, committedLanes) { ); } if (committedLanes.flags & 512) { - instance$86 = void 0; + instance$84 = void 0; current = committedLanes; var ref = current.ref; if (null !== ref) { var instance$jscomp$0 = current.stateNode; switch (current.tag) { case 5: - instance$86 = instance$jscomp$0; + instance$84 = instance$jscomp$0; break; default: - instance$86 = instance$jscomp$0; + instance$84 = instance$jscomp$0; } if ("function" === typeof ref) if (current.mode & 2) try { - startLayoutEffectTimer(), ref(instance$86); + startLayoutEffectTimer(), ref(instance$84); } finally { recordLayoutEffectDuration(current); } - else ref(instance$86); - else ref.current = instance$86; + else ref(instance$84); + else ref.current = instance$84; } } } catch (error) { @@ -6588,10 +6858,10 @@ function commitLayoutEffects(finishedWork, root, committedLanes) { nextEffect = null; break; } - instance$86 = committedLanes.sibling; - if (null !== instance$86) { - instance$86.return = committedLanes.return; - nextEffect = instance$86; + instance$84 = committedLanes.sibling; + if (null !== instance$84) { + instance$84.return = committedLanes.return; + nextEffect = instance$84; break; } nextEffect = committedLanes.return; @@ -6617,6 +6887,7 @@ var ceil = Math.ceil, workInProgressRootRecoverableErrors = null, globalMostRecentFallbackTime = 0, workInProgressRootRenderTargetTime = Infinity, + workInProgressTransitions = null, hasUncaughtError = !1, firstUncaughtError = null, legacyErrorBoundariesThatAlreadyFailed = null, @@ -6642,10 +6913,7 @@ function requestUpdateLane(fiber) { if (null !== ReactCurrentBatchConfig.transition) return ( 0 === currentEventTransitionLane && - ((fiber = nextTransitionLane), - (nextTransitionLane <<= 1), - 0 === (nextTransitionLane & 4194240) && (nextTransitionLane = 64), - (currentEventTransitionLane = fiber)), + (currentEventTransitionLane = claimNextTransitionLane()), currentEventTransitionLane ); fiber = currentUpdatePriority; @@ -6689,6 +6957,13 @@ function markUpdateLaneFromFiberToRoot(sourceFiber, lane) { (sourceFiber = sourceFiber.return); return 3 === alternate.tag ? alternate.stateNode : null; } +function isInterleavedUpdate(fiber) { + return ( + (null !== workInProgressRoot || null !== interleavedQueues) && + 0 !== (fiber.mode & 1) && + 0 === (executionContext & 2) + ); +} function ensureRootIsScheduled(root, currentTime) { for ( var existingCallbackNode = root.callbackNode, @@ -6792,6 +7067,7 @@ function performConcurrentWorkOnRoot(root, didTimeout) { memoizedUpdaters.clear()); movePendingFibersToMemoized(root, didTimeout); } + workInProgressTransitions = null; workInProgressRootRenderTargetTime = now() + 500; prepareFreshStack(root, didTimeout); } @@ -6850,7 +7126,11 @@ function performConcurrentWorkOnRoot(root, didTimeout) { case 1: throw Error("Root did not complete. This is a bug in React."); case 2: - commitRoot(root, workInProgressRootRecoverableErrors); + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); break; case 3: markRootSuspended$1(root, lanes); @@ -6867,12 +7147,21 @@ function performConcurrentWorkOnRoot(root, didTimeout) { break; } root.timeoutHandle = scheduleTimeout( - commitRoot.bind(null, root, workInProgressRootRecoverableErrors), + commitRoot.bind( + null, + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ), didTimeout ); break; } - commitRoot(root, workInProgressRootRecoverableErrors); + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); break; case 4: markRootSuspended$1(root, lanes); @@ -6903,15 +7192,28 @@ function performConcurrentWorkOnRoot(root, didTimeout) { : 1960 * ceil(lanes / 1960)) - lanes; if (10 < lanes) { root.timeoutHandle = scheduleTimeout( - commitRoot.bind(null, root, workInProgressRootRecoverableErrors), + commitRoot.bind( + null, + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ), lanes ); break; } - commitRoot(root, workInProgressRootRecoverableErrors); + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); break; case 5: - commitRoot(root, workInProgressRootRecoverableErrors); + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); break; default: throw Error("Unknown root exit status."); @@ -6931,15 +7233,17 @@ function recoverFromConcurrentError(root, errorRetryLanes) { 2 !== root && ((errorRetryLanes = workInProgressRootRecoverableErrors), (workInProgressRootRecoverableErrors = errorsFromFirstAttempt), - null !== errorRetryLanes && - (null === workInProgressRootRecoverableErrors - ? (workInProgressRootRecoverableErrors = errorRetryLanes) - : workInProgressRootRecoverableErrors.push.apply( - workInProgressRootRecoverableErrors, - errorRetryLanes - ))); + null !== errorRetryLanes && queueRecoverableErrors(errorRetryLanes)); return root; } +function queueRecoverableErrors(errors) { + null === workInProgressRootRecoverableErrors + ? (workInProgressRootRecoverableErrors = errors) + : workInProgressRootRecoverableErrors.push.apply( + workInProgressRootRecoverableErrors, + errors + ); +} function isRenderConsistentWithExternalStores(finishedWork) { for (var node = finishedWork; ; ) { if (node.flags & 16384) { @@ -7011,7 +7315,11 @@ function performSyncWorkOnRoot(root) { throw Error("Root did not complete. This is a bug in React."); root.finishedWork = root.current.alternate; root.finishedLanes = lanes; - commitRoot(root, workInProgressRootRecoverableErrors); + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); ensureRootIsScheduled(root, now()); return null; } @@ -7250,12 +7558,12 @@ function handleError(root$jscomp$0, thrownValue) { root.flags |= 65536; thrownValue &= -thrownValue; root.lanes |= thrownValue; - var update$35 = createClassErrorUpdate( + var update$36 = createClassErrorUpdate( root, wakeable, thrownValue ); - enqueueCapturedUpdate(root, update$35); + enqueueCapturedUpdate(root, update$36); break a; } } @@ -7302,6 +7610,7 @@ function renderRootSync(root, lanes) { memoizedUpdaters.clear()); movePendingFibersToMemoized(root, lanes); } + workInProgressTransitions = null; prepareFreshStack(root, lanes); } do @@ -7396,50 +7705,60 @@ function completeUnitOfWork(unitOfWork) { } while (null !== completedWork); 0 === workInProgressRootExitStatus && (workInProgressRootExitStatus = 5); } -function commitRoot(root, recoverableErrors) { +function commitRoot(root, recoverableErrors, transitions) { var previousUpdateLanePriority = currentUpdatePriority, prevTransition = ReactCurrentBatchConfig$2.transition; try { (ReactCurrentBatchConfig$2.transition = null), (currentUpdatePriority = 1), - commitRootImpl(root, recoverableErrors, previousUpdateLanePriority); + commitRootImpl( + root, + recoverableErrors, + transitions, + previousUpdateLanePriority + ); } finally { (ReactCurrentBatchConfig$2.transition = prevTransition), (currentUpdatePriority = previousUpdateLanePriority); } return null; } -function commitRootImpl(root, recoverableErrors, renderPriorityLevel) { +function commitRootImpl( + root, + recoverableErrors, + transitions, + renderPriorityLevel +) { do flushPassiveEffects(); while (null !== rootWithPendingPassiveEffects); if (0 !== (executionContext & 6)) throw Error("Should not already be working."); - var finishedWork = root.finishedWork, - lanes = root.finishedLanes; - if (null === finishedWork) return null; + transitions = root.finishedWork; + var lanes = root.finishedLanes; + if (null === transitions) return null; root.finishedWork = null; root.finishedLanes = 0; - if (finishedWork === root.current) + if (transitions === root.current) throw Error( "Cannot commit the same tree as before. This error is likely caused by a bug in React. Please file an issue." ); root.callbackNode = null; root.callbackPriority = 0; - var remainingLanes = finishedWork.lanes | finishedWork.childLanes; + var remainingLanes = transitions.lanes | transitions.childLanes; markRootFinished(root, remainingLanes); root === workInProgressRoot && ((workInProgress = workInProgressRoot = null), (workInProgressRootRenderLanes = 0)); - (0 === (finishedWork.subtreeFlags & 2064) && - 0 === (finishedWork.flags & 2064)) || + (0 === (transitions.subtreeFlags & 2064) && + 0 === (transitions.flags & 2064)) || rootDoesHavePassiveEffects || ((rootDoesHavePassiveEffects = !0), scheduleCallback$1(NormalPriority, function() { flushPassiveEffects(); return null; })); - remainingLanes = 0 !== (finishedWork.flags & 15990); - if (0 !== (finishedWork.subtreeFlags & 15990) || remainingLanes) { + remainingLanes = 0 !== (transitions.flags & 15990); + if (0 !== (transitions.subtreeFlags & 15990) || remainingLanes) { remainingLanes = ReactCurrentBatchConfig$2.transition; ReactCurrentBatchConfig$2.transition = null; var previousPriority = currentUpdatePriority; @@ -7447,32 +7766,32 @@ function commitRootImpl(root, recoverableErrors, renderPriorityLevel) { var prevExecutionContext = executionContext; executionContext |= 4; ReactCurrentOwner$2.current = null; - commitBeforeMutationEffects(root, finishedWork); + commitBeforeMutationEffects(root, transitions); commitTime = now$1(); - commitMutationEffects(root, finishedWork, lanes); - root.current = finishedWork; - commitLayoutEffects(finishedWork, root, lanes); + commitMutationEffects(root, transitions, lanes); + root.current = transitions; + commitLayoutEffects(transitions, root, lanes); requestPaint(); executionContext = prevExecutionContext; currentUpdatePriority = previousPriority; ReactCurrentBatchConfig$2.transition = remainingLanes; - } else (root.current = finishedWork), (commitTime = now$1()); + } else (root.current = transitions), (commitTime = now$1()); rootDoesHavePassiveEffects && ((rootDoesHavePassiveEffects = !1), (rootWithPendingPassiveEffects = root), (pendingPassiveEffectsLanes = lanes)); remainingLanes = root.pendingLanes; 0 === remainingLanes && (legacyErrorBoundariesThatAlreadyFailed = null); - onCommitRoot(finishedWork.stateNode, renderPriorityLevel); + onCommitRoot(transitions.stateNode, renderPriorityLevel); isDevToolsPresent && root.memoizedUpdaters.clear(); ensureRootIsScheduled(root, now()); if (null !== recoverableErrors) for ( - renderPriorityLevel = root.onRecoverableError, finishedWork = 0; - finishedWork < recoverableErrors.length; - finishedWork++ + renderPriorityLevel = root.onRecoverableError, transitions = 0; + transitions < recoverableErrors.length; + transitions++ ) - renderPriorityLevel(recoverableErrors[finishedWork]); + renderPriorityLevel(recoverableErrors[transitions]); if (hasUncaughtError) throw ((hasUncaughtError = !1), (root = firstUncaughtError), @@ -7773,21 +8092,43 @@ function pingSuspendedRoot(root, wakeable, pingedLanes) { : (workInProgressRootPingedLanes |= pingedLanes)); ensureRootIsScheduled(root, wakeable); } -function resolveRetryWakeable(boundaryFiber, wakeable) { - var retryCache = boundaryFiber.stateNode; - null !== retryCache && retryCache.delete(wakeable); - wakeable = 0; - 0 === wakeable && +function retryTimedOutBoundary(boundaryFiber, retryLane) { + 0 === retryLane && (0 === (boundaryFiber.mode & 1) - ? (wakeable = 1) - : ((wakeable = nextRetryLane), + ? (retryLane = 1) + : ((retryLane = nextRetryLane), (nextRetryLane <<= 1), 0 === (nextRetryLane & 130023424) && (nextRetryLane = 4194304))); - retryCache = requestEventTime(); - boundaryFiber = markUpdateLaneFromFiberToRoot(boundaryFiber, wakeable); + var eventTime = requestEventTime(); + boundaryFiber = markUpdateLaneFromFiberToRoot(boundaryFiber, retryLane); null !== boundaryFiber && - (markRootUpdated(boundaryFiber, wakeable, retryCache), - ensureRootIsScheduled(boundaryFiber, retryCache)); + (markRootUpdated(boundaryFiber, retryLane, eventTime), + ensureRootIsScheduled(boundaryFiber, eventTime)); +} +function retryDehydratedSuspenseBoundary(boundaryFiber) { + var suspenseState = boundaryFiber.memoizedState, + retryLane = 0; + null !== suspenseState && (retryLane = suspenseState.retryLane); + retryTimedOutBoundary(boundaryFiber, retryLane); +} +function resolveRetryWakeable(boundaryFiber, wakeable) { + var retryLane = 0; + switch (boundaryFiber.tag) { + case 13: + var retryCache = boundaryFiber.stateNode; + var suspenseState = boundaryFiber.memoizedState; + null !== suspenseState && (retryLane = suspenseState.retryLane); + break; + case 19: + retryCache = boundaryFiber.stateNode; + break; + default: + throw Error( + "Pinged unknown suspense boundary type. This is probably a bug in React." + ); + } + null !== retryCache && retryCache.delete(wakeable); + retryTimedOutBoundary(boundaryFiber, retryLane); } var beginWork$1; beginWork$1 = function(current, workInProgress, renderLanes) { @@ -7817,10 +8158,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { switch (workInProgress.tag) { case 2: var Component = workInProgress.type; - null !== current && - ((current.alternate = null), - (workInProgress.alternate = null), - (workInProgress.flags |= 2)); + resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress); current = workInProgress.pendingProps; var context = getMaskedContext( workInProgress, @@ -7874,10 +8212,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { case 16: Component = workInProgress.elementType; a: { - null !== current && - ((current.alternate = null), - (workInProgress.alternate = null), - (workInProgress.flags |= 2)); + resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress); current = workInProgress.pendingProps; context = Component._init; Component = context(Component._payload); @@ -7983,7 +8318,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { return ( pushHostContext(workInProgress), (Component = workInProgress.pendingProps.children), - markRef$1(current, workInProgress), + markRef(current, workInProgress), reconcileChildren(current, workInProgress, Component, renderLanes), workInProgress.child ); @@ -8081,24 +8416,24 @@ beginWork$1 = function(current, workInProgress, renderLanes) { } } else for ( - newValue = workInProgress.child, - null !== newValue && (newValue.return = workInProgress); - null !== newValue; + hasContext = workInProgress.child, + null !== hasContext && (hasContext.return = workInProgress); + null !== hasContext; ) { - var list = newValue.dependencies; + var list = hasContext.dependencies; if (null !== list) { - hasContext = newValue.child; + newValue = hasContext.child; for ( var dependency = list.firstContext; null !== dependency; ) { if (dependency.context === Component) { - if (1 === newValue.tag) { + if (1 === hasContext.tag) { dependency = createUpdate(-1, renderLanes & -renderLanes); dependency.tag = 2; - var updateQueue = newValue.updateQueue; + var updateQueue = hasContext.updateQueue; if (null !== updateQueue) { updateQueue = updateQueue.shared; var pending = updateQueue.pending; @@ -8109,11 +8444,11 @@ beginWork$1 = function(current, workInProgress, renderLanes) { updateQueue.pending = dependency; } } - newValue.lanes |= renderLanes; - dependency = newValue.alternate; + hasContext.lanes |= renderLanes; + dependency = hasContext.alternate; null !== dependency && (dependency.lanes |= renderLanes); scheduleContextWorkOnParentPath( - newValue.return, + hasContext.return, renderLanes, workInProgress ); @@ -8122,29 +8457,43 @@ beginWork$1 = function(current, workInProgress, renderLanes) { } dependency = dependency.next; } - } else - hasContext = - 10 === newValue.tag - ? newValue.type === workInProgress.type - ? null - : newValue.child - : newValue.child; - if (null !== hasContext) hasContext.return = newValue; + } else if (10 === hasContext.tag) + newValue = + hasContext.type === workInProgress.type + ? null + : hasContext.child; + else if (18 === hasContext.tag) { + newValue = hasContext.return; + if (null === newValue) + throw Error( + "We just came from a parent so we must have had a parent. This is a bug in React." + ); + newValue.lanes |= renderLanes; + list = newValue.alternate; + null !== list && (list.lanes |= renderLanes); + scheduleContextWorkOnParentPath( + newValue, + renderLanes, + workInProgress + ); + newValue = hasContext.sibling; + } else newValue = hasContext.child; + if (null !== newValue) newValue.return = hasContext; else - for (hasContext = newValue; null !== hasContext; ) { - if (hasContext === workInProgress) { - hasContext = null; + for (newValue = hasContext; null !== newValue; ) { + if (newValue === workInProgress) { + newValue = null; break; } - newValue = hasContext.sibling; - if (null !== newValue) { - newValue.return = hasContext.return; - hasContext = newValue; + hasContext = newValue.sibling; + if (null !== hasContext) { + hasContext.return = newValue.return; + newValue = hasContext; break; } - hasContext = hasContext.return; + newValue = newValue.return; } - newValue = hasContext; + hasContext = newValue; } reconcileChildren( current, @@ -8195,10 +8544,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { workInProgress.elementType === Component ? context : resolveDefaultProps(Component, context)), - null !== current && - ((current.alternate = null), - (workInProgress.alternate = null), - (workInProgress.flags |= 2)), + resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress), (workInProgress.tag = 1), isContextProvider(Component) ? ((current = !0), pushContextProvider(workInProgress)) @@ -8563,10 +8909,10 @@ batchedUpdatesImpl = function(fn, a) { } }; var roots = new Map(), - devToolsConfig$jscomp$inline_1003 = { + devToolsConfig$jscomp$inline_1010 = { findFiberByHostInstance: getInstanceFromTag, bundleType: 0, - version: "18.0.0-experimental-34aa5cfe0-20220329", + version: "18.2.0-next-d300cebde-20220601", rendererPackageName: "react-native-renderer", rendererConfig: { getInspectorDataForViewTag: function() { @@ -8581,11 +8927,11 @@ var roots = new Map(), }.bind(null, findNodeHandle) } }; -var internals$jscomp$inline_1277 = { - bundleType: devToolsConfig$jscomp$inline_1003.bundleType, - version: devToolsConfig$jscomp$inline_1003.version, - rendererPackageName: devToolsConfig$jscomp$inline_1003.rendererPackageName, - rendererConfig: devToolsConfig$jscomp$inline_1003.rendererConfig, +var internals$jscomp$inline_1302 = { + 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, @@ -8601,26 +8947,26 @@ var internals$jscomp$inline_1277 = { return null === fiber ? null : fiber.stateNode; }, findFiberByHostInstance: - devToolsConfig$jscomp$inline_1003.findFiberByHostInstance || + devToolsConfig$jscomp$inline_1010.findFiberByHostInstance || emptyFindFiberByHostInstance, findHostInstancesForRefresh: null, scheduleRefresh: null, scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "18.0.0-experimental-34aa5cfe0-20220329" + reconcilerVersion: "18.2.0-next-d300cebde-20220601" }; if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { - var hook$jscomp$inline_1278 = __REACT_DEVTOOLS_GLOBAL_HOOK__; + var hook$jscomp$inline_1303 = __REACT_DEVTOOLS_GLOBAL_HOOK__; if ( - !hook$jscomp$inline_1278.isDisabled && - hook$jscomp$inline_1278.supportsFiber + !hook$jscomp$inline_1303.isDisabled && + hook$jscomp$inline_1303.supportsFiber ) try { - (rendererID = hook$jscomp$inline_1278.inject( - internals$jscomp$inline_1277 + (rendererID = hook$jscomp$inline_1303.inject( + internals$jscomp$inline_1302 )), - (injectedHook = hook$jscomp$inline_1278); + (injectedHook = hook$jscomp$inline_1303); } catch (err) {} } exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = { @@ -8682,7 +9028,8 @@ exports.render = function(element, containerTag, callback) { element: null, isDehydrated: !1, cache: null, - transitions: null + transitions: null, + pendingSuspenseBoundaries: null }; initializeUpdateQueue(JSCompiler_inline_result); roots.set(containerTag, root); diff --git a/package.json b/package.json index 9a5909bbe52f8a..f68f1854ad7d1b 100644 --- a/package.json +++ b/package.json @@ -102,7 +102,7 @@ "repo-config" ], "peerDependencies": { - "react": "18.0.0" + "react": "18.1.0" }, "dependencies": { "@jest/create-cache-key-function": "^27.0.1", @@ -130,9 +130,9 @@ "react-devtools-core": "4.24.0", "react-native-gradle-plugin": "^0.0.7", "react-refresh": "^0.4.0", - "react-shallow-renderer": "16.14.1", + "react-shallow-renderer": "^16.15.0", "regenerator-runtime": "^0.13.2", - "scheduler": "^0.21.0", + "scheduler": "^0.22.0", "stacktrace-parser": "^0.1.3", "use-sync-external-store": "^1.0.0", "whatwg-fetch": "^3.0.0", @@ -140,8 +140,8 @@ }, "devDependencies": { "flow-bin": "^0.179.0", - "react": "18.0.0", - "react-test-renderer": "^18.0.0" + "react": "18.1.0", + "react-test-renderer": "^18.1.0" }, "codegenConfig": { "libraries": [ diff --git a/packages/rn-tester/package.json b/packages/rn-tester/package.json index 6fbbfdb387c1d5..aa37800cc1bd0a 100644 --- a/packages/rn-tester/package.json +++ b/packages/rn-tester/package.json @@ -23,7 +23,7 @@ "nullthrows": "^1.1.1" }, "peerDependencies": { - "react": "18.0.0", + "react": "18.1.0", "react-native": "*" }, "devDependencies": { diff --git a/repo-config/package.json b/repo-config/package.json index 7380ee93f12534..76fc9111cb6941 100644 --- a/repo-config/package.json +++ b/repo-config/package.json @@ -43,9 +43,9 @@ "metro-memory-fs": "0.71.0", "mkdirp": "^0.5.1", "prettier": "^2.4.1", - "react": "18.0.0", + "react": "18.1.0", "react-native-codegen": "^0.70.0", - "react-test-renderer": "18.0.0", + "react-test-renderer": "18.1.0", "shelljs": "^0.8.5", "signedsource": "^1.0.0", "ws": "^6.1.4", diff --git a/template/package.json b/template/package.json index daf46a72426165..bb0dedf3d3723b 100644 --- a/template/package.json +++ b/template/package.json @@ -10,7 +10,7 @@ "lint": "eslint ." }, "dependencies": { - "react": "18.0.0", + "react": "18.1.0", "react-native": "1000.0.0" }, "devDependencies": { @@ -21,7 +21,7 @@ "eslint": "^7.32.0", "jest": "^26.6.3", "metro-react-native-babel-preset": "^0.71.0", - "react-test-renderer": "18.0.0" + "react-test-renderer": "18.1.0" }, "jest": { "preset": "react-native" diff --git a/yarn.lock b/yarn.lock index 4acfe144c055ca..2c62e6722cf459 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5965,47 +5965,47 @@ react-devtools-core@4.24.0: shell-quote "^1.6.1" ws "^7" -"react-is@^16.12.0 || ^17.0.0", react-is@^17.0.1: - version "17.0.2" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" - integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== +"react-is@^16.12.0 || ^17.0.0 || ^18.0.0", react-is@^18.1.0: + version "18.1.0" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.1.0.tgz#61aaed3096d30eacf2a2127118b5b41387d32a67" + integrity sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg== react-is@^16.8.1, react-is@^16.8.4: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== -react-is@^18.0.0: - version "18.0.0" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.0.0.tgz#026f6c4a27dbe33bf4a35655b9e1327c4e55e3f5" - integrity sha512-yUcBYdBBbo3QiPsgYDcfQcIkGZHfxOaoE6HLSnr1sPzMhdyxusbfKOSUbSd/ocGi32dxcj366PsTj+5oggeKKw== +react-is@^17.0.1: + version "17.0.2" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" + integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== react-refresh@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.4.0.tgz#d421f9bd65e0e4b9822a399f14ac56bda9c92292" integrity sha512-bacjSio8GOtzNZKZZM6EWqbhlbb6pr28JWJWFTLwEBKvPIBRo6/Ob68D2EWZA2VyTdQxAh+TRnCYOPNKsQiXTA== -react-shallow-renderer@16.14.1, react-shallow-renderer@^16.13.1: - version "16.14.1" - resolved "https://registry.yarnpkg.com/react-shallow-renderer/-/react-shallow-renderer-16.14.1.tgz#bf0d02df8a519a558fd9b8215442efa5c840e124" - integrity sha512-rkIMcQi01/+kxiTE9D3fdS959U1g7gs+/rborw++42m1O9FAQiNI/UNRZExVUoAOprn4umcXf+pFRou8i4zuBg== +react-shallow-renderer@^16.15.0: + version "16.15.0" + resolved "https://registry.yarnpkg.com/react-shallow-renderer/-/react-shallow-renderer-16.15.0.tgz#48fb2cf9b23d23cde96708fe5273a7d3446f4457" + integrity sha512-oScf2FqQ9LFVQgA73vr86xl2NaOIX73rh+YFqcOp68CWj56tSfgtGKrEbyhCj0rSijyG9M1CYprTh39fBi5hzA== dependencies: object-assign "^4.1.1" - react-is "^16.12.0 || ^17.0.0" + react-is "^16.12.0 || ^17.0.0 || ^18.0.0" -react-test-renderer@18.0.0, react-test-renderer@^18.0.0: - version "18.0.0" - resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-18.0.0.tgz#fa403d625ea9478a70ace43db88833f6c3a5bb4c" - integrity sha512-SyZTP/FSkwfiKOZuTZiISzsrC8A80KNlQ8PyyoGoOq+VzMAab6Em1POK/CiX3+XyXG6oiJa1C53zYDbdrJu9fw== +react-test-renderer@18.1.0, react-test-renderer@^18.1.0: + version "18.1.0" + resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-18.1.0.tgz#35b75754834cf9ab517b6813db94aee0a6b545c3" + integrity sha512-OfuueprJFW7h69GN+kr4Ywin7stcuqaYAt1g7airM5cUgP0BoF5G5CXsPGmXeDeEkncb2fqYNECO4y18sSqphg== dependencies: - react-is "^18.0.0" - react-shallow-renderer "^16.13.1" - scheduler "^0.21.0" + react-is "^18.1.0" + react-shallow-renderer "^16.15.0" + scheduler "^0.22.0" -react@18.0.0: - version "18.0.0" - resolved "https://registry.yarnpkg.com/react/-/react-18.0.0.tgz#b468736d1f4a5891f38585ba8e8fb29f91c3cb96" - integrity sha512-x+VL6wbT4JRVPm7EGxXhZ8w8LTROaxPXOqhlGyVSrv0sB1jkyFGgXxJ8LVoPRLvPR6/CIZGFmfzqUa2NYeMr2A== +react@18.1.0: + version "18.1.0" + resolved "https://registry.yarnpkg.com/react/-/react-18.1.0.tgz#6f8620382decb17fdc5cc223a115e2adbf104890" + integrity sha512-4oL8ivCz5ZEPyclFQXaNksK3adutVS8l2xzZU0cqEFrE9Sb7fC0EFK5uEk74wIreL1DERyjvsU915j1pcT2uEQ== dependencies: loose-envify "^1.1.0" @@ -6383,10 +6383,10 @@ saxes@^5.0.1: dependencies: xmlchars "^2.2.0" -scheduler@^0.21.0: - version "0.21.0" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.21.0.tgz#6fd2532ff5a6d877b6edb12f00d8ab7e8f308820" - integrity sha512-1r87x5fz9MXqswA2ERLo0EbOAU74DpIUO090gIasYTqlVoJeMcl+Z1Rg7WHz+qtPujhS/hGIt9kxZOYBV3faRQ== +scheduler@^0.22.0: + version "0.22.0" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.22.0.tgz#83a5d63594edf074add9a7198b1bae76c3db01b8" + integrity sha512-6QAm1BgQI88NPYymgGQLCZgvep4FyePDWFpXVK+zNSUgHwlqpJy8VEh8Et0KxTACS4VWwMousBElAZOH9nkkoQ== dependencies: loose-envify "^1.1.0"