diff --git a/compiled/facebook-www/REVISION b/compiled/facebook-www/REVISION index ed2edef52e..30e2f1820b 100644 --- a/compiled/facebook-www/REVISION +++ b/compiled/facebook-www/REVISION @@ -1 +1 @@ -ded4a785b875d384f78efa28279550d86d93f54f +f87e97a0a67fa7cfd7e6f2ec985621c0e825cb23 diff --git a/compiled/facebook-www/React-dev.modern.js b/compiled/facebook-www/React-dev.modern.js index 1a04d8df17..29c939942a 100644 --- a/compiled/facebook-www/React-dev.modern.js +++ b/compiled/facebook-www/React-dev.modern.js @@ -27,7 +27,7 @@ if ( } "use strict"; -var ReactVersion = "18.3.0-www-modern-95e6ae95"; +var ReactVersion = "18.3.0-www-modern-bcc00dd5"; // ATTENTION // When adding new symbols to this file, diff --git a/compiled/facebook-www/ReactART-dev.classic.js b/compiled/facebook-www/ReactART-dev.classic.js index da31ddca01..4998181069 100644 --- a/compiled/facebook-www/ReactART-dev.classic.js +++ b/compiled/facebook-www/ReactART-dev.classic.js @@ -69,7 +69,7 @@ function _assertThisInitialized(self) { return self; } -var ReactVersion = "18.3.0-www-classic-daf8f3c7"; +var ReactVersion = "18.3.0-www-classic-0a3d97ff"; var LegacyRoot = 0; var ConcurrentRoot = 1; @@ -165,9 +165,7 @@ var ReactSharedInternals = // Re-export dynamic flags from the www version. var dynamicFeatureFlags = require("ReactFeatureFlags"); -var revertRemovalOfSiblingPrerendering = - dynamicFeatureFlags.revertRemovalOfSiblingPrerendering, - replayFailedUnitOfWorkWithInvokeGuardedCallback = +var replayFailedUnitOfWorkWithInvokeGuardedCallback = dynamicFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback, enableDebugTracing = dynamicFeatureFlags.enableDebugTracing, enableUseRefAccessWarning = dynamicFeatureFlags.enableUseRefAccessWarning, @@ -178,7 +176,9 @@ var revertRemovalOfSiblingPrerendering = enableTransitionTracing = dynamicFeatureFlags.enableTransitionTracing, enableDeferRootSchedulingToMicrotask = dynamicFeatureFlags.enableDeferRootSchedulingToMicrotask, - diffInCommitPhase = dynamicFeatureFlags.diffInCommitPhase; // On WWW, false is used for a new modern build. + diffInCommitPhase = dynamicFeatureFlags.diffInCommitPhase, + enableAsyncActions = dynamicFeatureFlags.enableAsyncActions, + alwaysThrottleRetries = dynamicFeatureFlags.alwaysThrottleRetries; // On WWW, false is used for a new modern build. var enableProfilerTimer = true; var enableProfilerCommitHooks = true; var enableProfilerNestedUpdatePhase = true; @@ -1924,24 +1924,6 @@ function getNextLanes(root, wipLanes) { return nextLanes; } -function getMostRecentEventTime(root, lanes) { - var eventTimes = root.eventTimes; - var mostRecentEventTime = NoTimestamp; - - while (lanes > 0) { - var index = pickArbitraryLaneIndex(lanes); - var lane = 1 << index; - var eventTime = eventTimes[index]; - - if (eventTime > mostRecentEventTime) { - mostRecentEventTime = eventTime; - } - - lanes &= ~lane; - } - - return mostRecentEventTime; -} function computeExpirationTime(lane, currentTime) { switch (lane) { @@ -2179,7 +2161,7 @@ function createLaneMap(initial) { return laneMap; } -function markRootUpdated(root, updateLane, eventTime) { +function markRootUpdated(root, updateLane) { root.pendingLanes |= updateLane; // If there are any suspended transitions, it's possible this new update // could unblock them. Clear the suspended lanes so that we can try rendering // them again. @@ -2197,12 +2179,6 @@ function markRootUpdated(root, updateLane, eventTime) { root.suspendedLanes = NoLanes; root.pingedLanes = NoLanes; } - - var eventTimes = root.eventTimes; - var index = laneToIndex(updateLane); // We can always overwrite an existing timestamp because we prefer the most - // recent event, and we assume time is monotonically increasing. - - eventTimes[index] = eventTime; } function markRootSuspended$1(root, suspendedLanes) { root.suspendedLanes |= suspendedLanes; @@ -2235,7 +2211,6 @@ function markRootFinished(root, remainingLanes) { root.entangledLanes &= remainingLanes; root.errorRecoveryDisabledLanes &= remainingLanes; var entanglements = root.entanglements; - var eventTimes = root.eventTimes; var expirationTimes = root.expirationTimes; var hiddenUpdates = root.hiddenUpdates; // Clear the lanes that no longer have pending work @@ -2245,7 +2220,6 @@ function markRootFinished(root, remainingLanes) { var index = pickArbitraryLaneIndex(lanes); var lane = 1 << index; entanglements[index] = NoLanes; - eventTimes[index] = NoTimestamp; expirationTimes[index] = NoTimestamp; var hiddenUpdatesForLane = hiddenUpdates[index]; @@ -2864,6 +2838,9 @@ function shouldSetTextContent(type, props) { } function getCurrentEventPriority() { return DefaultEventPriority; +} +function shouldAttemptEagerTransition() { + return false; } // The ART renderer is secondary to the React DOM renderer. var warnsIfNotActing = false; @@ -2935,7 +2912,7 @@ function preloadInstance(type, props) { } function waitForCommitToBeReady() { return null; -} // eslint-disable-next-line no-undef +} var ReactCurrentDispatcher$2 = ReactSharedInternals.ReactCurrentDispatcher; var prefix; @@ -7333,6 +7310,497 @@ function warnAboutMultipleRenderersDEV(mutableSource) { } } // Eager reads the version of a mutable source and stores it on the root. +var ReactCurrentActQueue$2 = ReactSharedInternals.ReactCurrentActQueue; // A linked list of all the roots with pending work. In an idiomatic app, +// there's only a single root, but we do support multi root apps, hence this +// extra complexity. But this module is optimized for the single root case. + +var firstScheduledRoot = null; +var lastScheduledRoot = null; // Used to prevent redundant mircotasks from being scheduled. + +var didScheduleMicrotask = false; // `act` "microtasks" are scheduled on the `act` queue instead of an actual +// microtask, so we have to dedupe those separately. This wouldn't be an issue +// if we required all `act` calls to be awaited, which we might in the future. + +var didScheduleMicrotask_act = false; // Used to quickly bail out of flushSync if there's no sync work to do. + +var mightHavePendingSyncWork = false; +var isFlushingWork = false; +var currentEventTransitionLane = NoLane; +function ensureRootIsScheduled(root) { + // This function is called whenever a root receives an update. It does two + // things 1) it ensures the root is in the root schedule, and 2) it ensures + // there's a pending microtask to process the root schedule. + // + // Most of the actual scheduling logic does not happen until + // `scheduleTaskForRootDuringMicrotask` runs. + // Add the root to the schedule + if (root === lastScheduledRoot || root.next !== null); + else { + if (lastScheduledRoot === null) { + firstScheduledRoot = lastScheduledRoot = root; + } else { + lastScheduledRoot.next = root; + lastScheduledRoot = root; + } + } // Any time a root received an update, we set this to true until the next time + // we process the schedule. If it's false, then we can quickly exit flushSync + // without consulting the schedule. + + mightHavePendingSyncWork = true; // At the end of the current event, go through each of the roots and ensure + // there's a task scheduled for each one at the correct priority. + + if (ReactCurrentActQueue$2.current !== null) { + // We're inside an `act` scope. + if (!didScheduleMicrotask_act) { + didScheduleMicrotask_act = true; + scheduleImmediateTask(processRootScheduleInMicrotask); + } + } else { + if (!didScheduleMicrotask) { + didScheduleMicrotask = true; + scheduleImmediateTask(processRootScheduleInMicrotask); + } + } + + if (!enableDeferRootSchedulingToMicrotask) { + // While this flag is disabled, we schedule the render task immediately + // instead of waiting a microtask. + // TODO: We need to land enableDeferRootSchedulingToMicrotask ASAP to + // unblock additional features we have planned. + scheduleTaskForRootDuringMicrotask(root, now$1()); + } + + if (ReactCurrentActQueue$2.isBatchingLegacy && root.tag === LegacyRoot) { + // Special `act` case: Record whenever a legacy update is scheduled. + ReactCurrentActQueue$2.didScheduleLegacyUpdate = true; + } +} +function flushSyncWorkOnAllRoots() { + // This is allowed to be called synchronously, but the caller should check + // the execution context first. + flushSyncWorkAcrossRoots_impl(false); +} +function flushSyncWorkOnLegacyRootsOnly() { + // This is allowed to be called synchronously, but the caller should check + // the execution context first. + flushSyncWorkAcrossRoots_impl(true); +} + +function flushSyncWorkAcrossRoots_impl(onlyLegacy) { + if (isFlushingWork) { + // Prevent reentrancy. + // TODO: Is this overly defensive? The callers must check the execution + // context first regardless. + return; + } + + if (!mightHavePendingSyncWork) { + // Fast path. There's no sync work to do. + return; + } + + var workInProgressRoot = getWorkInProgressRoot(); + var workInProgressRootRenderLanes = getWorkInProgressRootRenderLanes(); // There may or may not be synchronous work scheduled. Let's check. + + var didPerformSomeWork; + var errors = null; + isFlushingWork = true; + + do { + didPerformSomeWork = false; + var root = firstScheduledRoot; + + while (root !== null) { + if (onlyLegacy && root.tag !== LegacyRoot); + else { + var nextLanes = getNextLanes( + root, + root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes + ); + + if (includesSyncLane(nextLanes)) { + // This root has pending sync work. Flush it now. + try { + // TODO: Pass nextLanes as an argument instead of computing it again + // inside performSyncWorkOnRoot. + didPerformSomeWork = true; + performSyncWorkOnRoot(root); + } catch (error) { + // Collect errors so we can rethrow them at the end + if (errors === null) { + errors = [error]; + } else { + errors.push(error); + } + } + } + } + + root = root.next; + } + } while (didPerformSomeWork); + + isFlushingWork = false; // If any errors were thrown, rethrow them right before exiting. + // TODO: Consider returning these to the caller, to allow them to decide + // how/when to rethrow. + + if (errors !== null) { + if (errors.length > 1) { + if (typeof AggregateError === "function") { + // eslint-disable-next-line no-undef + throw new AggregateError(errors); + } else { + for (var i = 1; i < errors.length; i++) { + scheduleImmediateTask(throwError.bind(null, errors[i])); + } + + var firstError = errors[0]; + throw firstError; + } + } else { + var error = errors[0]; + throw error; + } + } +} + +function throwError(error) { + throw error; +} + +function processRootScheduleInMicrotask() { + // This function is always called inside a microtask. It should never be + // called synchronously. + didScheduleMicrotask = false; + + { + didScheduleMicrotask_act = false; + } // We'll recompute this as we iterate through all the roots and schedule them. + + mightHavePendingSyncWork = false; + var currentTime = now$1(); + var prev = null; + var root = firstScheduledRoot; + + while (root !== null) { + var next = root.next; + + if ( + currentEventTransitionLane !== NoLane && + shouldAttemptEagerTransition() + ) { + markRootEntangled(root, mergeLanes(currentEventTransitionLane, SyncLane)); + } + + var nextLanes = scheduleTaskForRootDuringMicrotask(root, currentTime); + + if (nextLanes === NoLane) { + // This root has no more pending work. Remove it from the schedule. To + // guard against subtle reentrancy bugs, this microtask is the only place + // we do this — you can add roots to the schedule whenever, but you can + // only remove them here. + // Null this out so we know it's been removed from the schedule. + root.next = null; + + if (prev === null) { + // This is the new head of the list + firstScheduledRoot = next; + } else { + prev.next = next; + } + + if (next === null) { + // This is the new tail of the list + lastScheduledRoot = prev; + } + } else { + // This root still has work. Keep it in the list. + prev = root; + + if (includesSyncLane(nextLanes)) { + mightHavePendingSyncWork = true; + } + } + + root = next; + } + + currentEventTransitionLane = NoLane; // At the end of the microtask, flush any pending synchronous work. This has + // to come at the end, because it does actual rendering work that might throw. + + flushSyncWorkOnAllRoots(); +} + +function scheduleTaskForRootDuringMicrotask(root, currentTime) { + // This function is always called inside a microtask, or at the very end of a + // rendering task right before we yield to the main thread. It should never be + // called synchronously. + // + // TODO: Unless enableDeferRootSchedulingToMicrotask is off. We need to land + // that ASAP to unblock additional features we have planned. + // + // This function also never performs React work synchronously; it should + // only schedule work to be performed later, in a separate task or microtask. + // Check if any lanes are being starved by other work. If so, mark them as + // expired so we know to work on those next. + markStarvedLanesAsExpired(root, currentTime); // Determine the next lanes to work on, and their priority. + + var workInProgressRoot = getWorkInProgressRoot(); + var workInProgressRootRenderLanes = getWorkInProgressRootRenderLanes(); + var nextLanes = getNextLanes( + root, + root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes + ); + var existingCallbackNode = root.callbackNode; + + if ( + // Check if there's nothing to work on + nextLanes === NoLanes || // If this root is currently suspended and waiting for data to resolve, don't + // schedule a task to render it. We'll either wait for a ping, or wait to + // receive an update. + // + // Suspended render phase + (root === workInProgressRoot && isWorkLoopSuspendedOnData()) || // Suspended commit phase + root.cancelPendingCommit !== null + ) { + // Fast path: There's nothing to work on. + if (existingCallbackNode !== null) { + cancelCallback(existingCallbackNode); + } + + root.callbackNode = null; + root.callbackPriority = NoLane; + return NoLane; + } // Schedule a new callback in the host environment. + + if (includesSyncLane(nextLanes)) { + // Synchronous work is always flushed at the end of the microtask, so we + // don't need to schedule an additional task. + if (existingCallbackNode !== null) { + cancelCallback(existingCallbackNode); + } + + root.callbackPriority = SyncLane; + root.callbackNode = null; + return SyncLane; + } else { + // We use the highest priority lane to represent the priority of the callback. + var existingCallbackPriority = root.callbackPriority; + var newCallbackPriority = getHighestPriorityLane(nextLanes); + + if ( + newCallbackPriority === existingCallbackPriority && // Special case related to `act`. If the currently scheduled task is a + // Scheduler task, rather than an `act` task, cancel it and re-schedule + // on the `act` queue. + !( + ReactCurrentActQueue$2.current !== null && + existingCallbackNode !== fakeActCallbackNode$1 + ) + ) { + // The priority hasn't changed. We can reuse the existing task. + return newCallbackPriority; + } else { + // Cancel the existing callback. We'll schedule a new one below. + cancelCallback(existingCallbackNode); + } + + var schedulerPriorityLevel; + + switch (lanesToEventPriority(nextLanes)) { + case DiscreteEventPriority: + schedulerPriorityLevel = ImmediatePriority; + break; + + case ContinuousEventPriority: + schedulerPriorityLevel = UserBlockingPriority; + break; + + case DefaultEventPriority: + schedulerPriorityLevel = NormalPriority$1; + break; + + case IdleEventPriority: + schedulerPriorityLevel = IdlePriority; + break; + + default: + schedulerPriorityLevel = NormalPriority$1; + break; + } + + var newCallbackNode = scheduleCallback$2( + schedulerPriorityLevel, + performConcurrentWorkOnRoot.bind(null, root) + ); + root.callbackPriority = newCallbackPriority; + root.callbackNode = newCallbackNode; + return newCallbackPriority; + } +} + +function getContinuationForRoot(root, originalCallbackNode) { + // This is called at the end of `performConcurrentWorkOnRoot` to determine + // if we need to schedule a continuation task. + // + // Usually `scheduleTaskForRootDuringMicrotask` only runs inside a microtask; + // however, since most of the logic for determining if we need a continuation + // versus a new task is the same, we cheat a bit and call it here. This is + // only safe to do because we know we're at the end of the browser task. + // So although it's not an actual microtask, it might as well be. + scheduleTaskForRootDuringMicrotask(root, now$1()); + + if (root.callbackNode === originalCallbackNode) { + // The task node scheduled for this root is the same one that's + // currently executed. Need to return a continuation. + return performConcurrentWorkOnRoot.bind(null, root); + } + + return null; +} +var fakeActCallbackNode$1 = {}; + +function scheduleCallback$2(priorityLevel, callback) { + if (ReactCurrentActQueue$2.current !== null) { + // Special case: We're inside an `act` scope (a testing utility). + // Instead of scheduling work in the host environment, add it to a + // fake internal queue that's managed by the `act` implementation. + ReactCurrentActQueue$2.current.push(callback); + return fakeActCallbackNode$1; + } else { + return scheduleCallback$3(priorityLevel, callback); + } +} + +function cancelCallback(callbackNode) { + if (callbackNode === fakeActCallbackNode$1); + else if (callbackNode !== null) { + cancelCallback$1(callbackNode); + } +} + +function scheduleImmediateTask(cb) { + if (ReactCurrentActQueue$2.current !== null) { + // Special case: Inside an `act` scope, we push microtasks to the fake `act` + // callback queue. This is because we currently support calling `act` + // without awaiting the result. The plan is to deprecate that, and require + // that you always await the result so that the microtasks have a chance to + // run. But it hasn't happened yet. + ReactCurrentActQueue$2.current.push(function () { + cb(); + return null; + }); + } // TODO: Can we land supportsMicrotasks? Which environments don't support it? + // Alternatively, can we move this check to the host config? + + { + // If microtasks are not supported, use Scheduler. + scheduleCallback$3(ImmediatePriority, cb); + } +} + +function requestTransitionLane() { + // The algorithm for assigning an update to a lane should be stable for all + // updates at the same priority within the same event. To do this, the + // inputs to the algorithm must be the same. + // + // The trick we use is to cache the first of each of these inputs within an + // event. Then reset the cached values once we can be sure the event is + // over. Our heuristic for that is whenever we enter a concurrent work loop. + if (currentEventTransitionLane === NoLane) { + // All transitions within the same event are assigned the same lane. + currentEventTransitionLane = claimNextTransitionLane(); + } + + return currentEventTransitionLane; +} + +var currentAsyncAction = null; +function requestAsyncActionContext(actionReturnValue) { + if ( + actionReturnValue !== null && + typeof actionReturnValue === "object" && + typeof actionReturnValue.then === "function" + ) { + // This is an async action. + // + // Return a thenable that resolves once the action scope (i.e. the async + // function passed to startTransition) has finished running. The fulfilled + // value is `false` to represent that the action is not pending. + var thenable = actionReturnValue; + + if (currentAsyncAction === null) { + // There's no outer async action scope. Create a new one. + var asyncAction = { + lane: requestTransitionLane(), + listeners: [], + count: 0, + status: "pending", + value: false, + reason: undefined, + then: function (resolve) { + asyncAction.listeners.push(resolve); + } + }; + attachPingListeners(thenable, asyncAction); + currentAsyncAction = asyncAction; + return asyncAction; + } else { + // Inherit the outer scope. + var _asyncAction = currentAsyncAction; + attachPingListeners(thenable, _asyncAction); + return _asyncAction; + } + } else { + // This is not an async action, but it may be part of an outer async action. + if (currentAsyncAction === null) { + // There's no outer async action scope. + return false; + } else { + // Inherit the outer scope. + return currentAsyncAction; + } + } +} +function peekAsyncActionContext() { + return currentAsyncAction; +} + +function attachPingListeners(thenable, asyncAction) { + asyncAction.count++; + thenable.then( + function () { + if (--asyncAction.count === 0) { + var fulfilledAsyncAction = asyncAction; + fulfilledAsyncAction.status = "fulfilled"; + completeAsyncActionScope(asyncAction); + } + }, + function (error) { + if (--asyncAction.count === 0) { + var rejectedAsyncAction = asyncAction; + rejectedAsyncAction.status = "rejected"; + rejectedAsyncAction.reason = error; + completeAsyncActionScope(asyncAction); + } + } + ); + return asyncAction; +} + +function completeAsyncActionScope(action) { + if (currentAsyncAction === action) { + currentAsyncAction = null; + } + + var listeners = action.listeners; + action.listeners = []; + + for (var i = 0; i < listeners.length; i++) { + var listener = listeners[i]; + listener(false); + } +} + var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, ReactCurrentBatchConfig$2 = ReactSharedInternals.ReactCurrentBatchConfig; var didWarnAboutMismatchedHooksForComponent; @@ -8007,38 +8475,42 @@ var createFunctionComponentUpdateQueue; }; } +function useThenable(thenable) { + // Track the position of the thenable within this fiber. + var index = thenableIndexCounter; + thenableIndexCounter += 1; + + if (thenableState === null) { + thenableState = createThenableState(); + } + + var result = trackUsedThenable(thenableState, thenable, index); + + if ( + currentlyRenderingFiber$1.alternate === null && + (workInProgressHook === null + ? currentlyRenderingFiber$1.memoizedState === null + : workInProgressHook.next === null) + ) { + // Initial render, and either this is the first time the component is + // called, or there were no Hooks called after this use() the previous + // time (perhaps because it threw). Subsequent Hook calls should use the + // mount dispatcher. + { + ReactCurrentDispatcher$1.current = HooksDispatcherOnMountInDEV; + } + } + + return result; +} + function use(usable) { if (usable !== null && typeof usable === "object") { // $FlowFixMe[method-unbinding] if (typeof usable.then === "function") { // This is a thenable. - var thenable = usable; // Track the position of the thenable within this fiber. - - var index = thenableIndexCounter; - thenableIndexCounter += 1; - - if (thenableState === null) { - thenableState = createThenableState(); - } - - var result = trackUsedThenable(thenableState, thenable, index); - - if ( - currentlyRenderingFiber$1.alternate === null && - (workInProgressHook === null - ? currentlyRenderingFiber$1.memoizedState === null - : workInProgressHook.next === null) - ) { - // Initial render, and either this is the first time the component is - // called, or there were no Hooks called after this use() the previous - // time (perhaps because it threw). Subsequent Hook calls should use the - // mount dispatcher. - { - ReactCurrentDispatcher$1.current = HooksDispatcherOnMountInDEV; - } - } - - return result; + var thenable = usable; + return useThenable(thenable); } else if ( usable.$$typeof === REACT_CONTEXT_TYPE || usable.$$typeof === REACT_SERVER_CONTEXT_TYPE @@ -8808,7 +9280,7 @@ function forceStoreRerender(fiber) { var root = enqueueConcurrentRenderForLane(fiber, SyncLane); if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + scheduleUpdateOnFiber(root, fiber, SyncLane); } } @@ -9345,8 +9817,35 @@ function startTransition(setPending, callback, options) { } try { - setPending(false); - callback(); + if (enableAsyncActions) { + var returnValue = callback(); // `isPending` is either `false` or a thenable that resolves to `false`, + // depending on whether the action scope is an async function. In the + // async case, the resulting render will suspend until the async action + // scope has finished. + + var isPending = requestAsyncActionContext(returnValue); + setPending(isPending); + } else { + // Async actions are not enabled. + setPending(false); + callback(); + } + } catch (error) { + if (enableAsyncActions) { + // This is a trick to get the `useTransition` hook to rethrow the error. + // When it unwraps the thenable with the `use` algorithm, the error + // will be thrown. + var rejectedThenable = { + then: function () {}, + status: "rejected", + reason: error + }; + setPending(rejectedThenable); + } else { + // The error rethrowing behavior is only enabled when the async actions + // feature is on, even for sync actions. + throw error; + } } finally { setCurrentUpdatePriority(previousPriority); ReactCurrentBatchConfig$2.transition = prevTransition; @@ -9371,30 +9870,37 @@ function startTransition(setPending, callback, options) { function mountTransition() { var _mountState = mountState(false), - isPending = _mountState[0], setPending = _mountState[1]; // The `start` method never changes. var start = startTransition.bind(null, setPending); var hook = mountWorkInProgressHook(); hook.memoizedState = start; - return [isPending, start]; + return [false, start]; } function updateTransition() { var _updateState = updateState(), - isPending = _updateState[0]; + booleanOrThenable = _updateState[0]; var hook = updateWorkInProgressHook(); var start = hook.memoizedState; + var isPending = + typeof booleanOrThenable === "boolean" + ? booleanOrThenable // This will suspend until the async action scope has finished. + : useThenable(booleanOrThenable); return [isPending, start]; } function rerenderTransition() { var _rerenderState = rerenderState(), - isPending = _rerenderState[0]; + booleanOrThenable = _rerenderState[0]; var hook = updateWorkInProgressHook(); var start = hook.memoizedState; + var isPending = + typeof booleanOrThenable === "boolean" + ? booleanOrThenable // This will suspend until the async action scope has finished. + : useThenable(booleanOrThenable); return [isPending, start]; } @@ -9455,8 +9961,7 @@ function refreshCache(fiber, seedKey, seedValue) { var root = enqueueUpdate(provider, refreshUpdate, lane); if (root !== null) { - var eventTime = requestEventTime(); - scheduleUpdateOnFiber(root, provider, lane, eventTime); + scheduleUpdateOnFiber(root, provider, lane); entangleTransitions(root, provider, lane); } // TODO: If a refresh never commits, the new cache created here must be // released. A simple case is start refreshing a cache boundary, but then @@ -9510,8 +10015,7 @@ function dispatchReducerAction(fiber, queue, action) { var root = enqueueConcurrentHookUpdate(fiber, queue, update, lane); if (root !== null) { - var eventTime = requestEventTime(); - scheduleUpdateOnFiber(root, fiber, lane, eventTime); + scheduleUpdateOnFiber(root, fiber, lane); entangleTransitionUpdate(root, queue, lane); } } @@ -9594,8 +10098,7 @@ function dispatchSetState(fiber, queue, action) { var root = enqueueConcurrentHookUpdate(fiber, queue, update, lane); if (root !== null) { - var eventTime = requestEventTime(); - scheduleUpdateOnFiber(root, fiber, lane, eventTime); + scheduleUpdateOnFiber(root, fiber, lane); entangleTransitionUpdate(root, queue, lane); } } @@ -9666,6 +10169,7 @@ function markUpdateInDevTools(fiber, lane, action) { var ContextOnlyDispatcher = { readContext: readContext, + use: use, useCallback: throwInvalidHookError, useContext: throwInvalidHookError, useEffect: throwInvalidHookError, @@ -9688,10 +10192,6 @@ var ContextOnlyDispatcher = { ContextOnlyDispatcher.useCacheRefresh = throwInvalidHookError; } -{ - ContextOnlyDispatcher.use = throwInvalidHookError; -} - { ContextOnlyDispatcher.useMemoCache = throwInvalidHookError; } @@ -9731,6 +10231,7 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; readContext: function (context) { return readContext(context); }, + use: use, useCallback: function (callback, deps) { currentHookNameInDev = "useCallback"; mountHookTypesDev(); @@ -9851,10 +10352,6 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; }; } - { - HooksDispatcherOnMountInDEV.use = use; - } - { HooksDispatcherOnMountInDEV.useMemoCache = useMemoCache; } @@ -9873,6 +10370,7 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; readContext: function (context) { return readContext(context); }, + use: use, useCallback: function (callback, deps) { currentHookNameInDev = "useCallback"; updateHookTypesDev(); @@ -9988,10 +10486,6 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; }; } - { - HooksDispatcherOnMountWithHookTypesInDEV.use = use; - } - { HooksDispatcherOnMountWithHookTypesInDEV.useMemoCache = useMemoCache; } @@ -10009,6 +10503,7 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; readContext: function (context) { return readContext(context); }, + use: use, useCallback: function (callback, deps) { currentHookNameInDev = "useCallback"; updateHookTypesDev(); @@ -10123,10 +10618,6 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; }; } - { - HooksDispatcherOnUpdateInDEV.use = use; - } - { HooksDispatcherOnUpdateInDEV.useMemoCache = useMemoCache; } @@ -10145,6 +10636,7 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; readContext: function (context) { return readContext(context); }, + use: use, useCallback: function (callback, deps) { currentHookNameInDev = "useCallback"; updateHookTypesDev(); @@ -10260,10 +10752,6 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; }; } - { - HooksDispatcherOnRerenderInDEV.use = use; - } - { HooksDispatcherOnRerenderInDEV.useMemoCache = useMemoCache; } @@ -10283,6 +10771,10 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; warnInvalidContextAccess(); return readContext(context); }, + use: function (usable) { + warnInvalidHookAccess(); + return use(usable); + }, useCallback: function (callback, deps) { currentHookNameInDev = "useCallback"; warnInvalidHookAccess(); @@ -10414,13 +10906,6 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; }; } - { - InvalidNestedHooksDispatcherOnMountInDEV.use = function (usable) { - warnInvalidHookAccess(); - return use(usable); - }; - } - { InvalidNestedHooksDispatcherOnMountInDEV.useMemoCache = function (size) { warnInvalidHookAccess(); @@ -10443,6 +10928,10 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; warnInvalidContextAccess(); return readContext(context); }, + use: function (usable) { + warnInvalidHookAccess(); + return use(usable); + }, useCallback: function (callback, deps) { currentHookNameInDev = "useCallback"; warnInvalidHookAccess(); @@ -10574,13 +11063,6 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; }; } - { - InvalidNestedHooksDispatcherOnUpdateInDEV.use = function (usable) { - warnInvalidHookAccess(); - return use(usable); - }; - } - { InvalidNestedHooksDispatcherOnUpdateInDEV.useMemoCache = function (size) { warnInvalidHookAccess(); @@ -10603,6 +11085,10 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; warnInvalidContextAccess(); return readContext(context); }, + use: function (usable) { + warnInvalidHookAccess(); + return use(usable); + }, useCallback: function (callback, deps) { currentHookNameInDev = "useCallback"; warnInvalidHookAccess(); @@ -10734,13 +11220,6 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; }; } - { - InvalidNestedHooksDispatcherOnRerenderInDEV.use = function (usable) { - warnInvalidHookAccess(); - return use(usable); - }; - } - { InvalidNestedHooksDispatcherOnRerenderInDEV.useMemoCache = function (size) { warnInvalidHookAccess(); @@ -11082,8 +11561,7 @@ var classComponentUpdater = { var root = enqueueUpdate(fiber, update, lane); if (root !== null) { - var eventTime = requestEventTime(); - scheduleUpdateOnFiber(root, fiber, lane, eventTime); + scheduleUpdateOnFiber(root, fiber, lane); entangleTransitions(root, fiber, lane); } @@ -11118,8 +11596,7 @@ var classComponentUpdater = { var root = enqueueUpdate(fiber, update, lane); if (root !== null) { - var eventTime = requestEventTime(); - scheduleUpdateOnFiber(root, fiber, lane, eventTime); + scheduleUpdateOnFiber(root, fiber, lane); entangleTransitions(root, fiber, lane); } @@ -11154,8 +11631,7 @@ var classComponentUpdater = { var root = enqueueUpdate(fiber, update, lane); if (root !== null) { - var eventTime = requestEventTime(); - scheduleUpdateOnFiber(root, fiber, lane, eventTime); + scheduleUpdateOnFiber(root, fiber, lane); entangleTransitions(root, fiber, lane); } @@ -15099,16 +15575,9 @@ function updateDehydratedSuspenseComponent( // 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; + suspenseState.retryLane = attemptHydrationAtLane; enqueueConcurrentRenderForLane(current, attemptHydrationAtLane); - scheduleUpdateOnFiber( - root, - current, - attemptHydrationAtLane, - eventTime - ); // Throw a special object that signals to the work loop that it should + scheduleUpdateOnFiber(root, current, attemptHydrationAtLane); // Throw a special object that signals to the work loop that it should // interrupt the current render. // // Because we're inside a React-only execution stack, we don't @@ -17113,7 +17582,7 @@ var AbortControllerLocal = }; // Intentionally not named imports because Rollup would // use dynamic dispatch for CommonJS interop named imports. -var scheduleCallback$2 = Scheduler.unstable_scheduleCallback, +var scheduleCallback$1 = Scheduler.unstable_scheduleCallback, NormalPriority = Scheduler.unstable_NormalPriority; var CacheContext = { $$typeof: REACT_CONTEXT_TYPE, @@ -17169,7 +17638,7 @@ function releaseCache(cache) { } if (cache.refCount === 0) { - scheduleCallback$2(NormalPriority, function () { + scheduleCallback$1(NormalPriority, function () { cache.controller.abort(); }); } @@ -20994,7 +21463,7 @@ function detachOffscreenInstance(instance) { if (root !== null) { instance._pendingVisibility |= OffscreenDetached; - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + scheduleUpdateOnFiber(root, fiber, SyncLane); } } function attachOffscreenInstance(instance) { @@ -21015,7 +21484,7 @@ function attachOffscreenInstance(instance) { if (root !== null) { instance._pendingVisibility &= ~OffscreenDetached; - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + scheduleUpdateOnFiber(root, fiber, SyncLane); } } @@ -23085,7 +23554,7 @@ if (typeof Symbol === "function" && Symbol.for) { symbolFor("selector.text"); } -var ReactCurrentActQueue$2 = ReactSharedInternals.ReactCurrentActQueue; +var ReactCurrentActQueue$1 = ReactSharedInternals.ReactCurrentActQueue; function isLegacyActEnvironment(fiber) { { // Legacy mode. We preserve the behavior of React 17's act. It assumes an @@ -23108,7 +23577,7 @@ function isConcurrentActEnvironment() { if ( !isReactActEnvironmentGlobal && - ReactCurrentActQueue$2.current !== null + ReactCurrentActQueue$1.current !== null ) { // TODO: Include link to relevant documentation page. error( @@ -23121,384 +23590,6 @@ function isConcurrentActEnvironment() { } } -var ReactCurrentActQueue$1 = ReactSharedInternals.ReactCurrentActQueue; // A linked list of all the roots with pending work. In an idiomatic app, -// there's only a single root, but we do support multi root apps, hence this -// extra complexity. But this module is optimized for the single root case. - -var firstScheduledRoot = null; -var lastScheduledRoot = null; // Used to prevent redundant mircotasks from being scheduled. - -var didScheduleMicrotask = false; // `act` "microtasks" are scheduled on the `act` queue instead of an actual -// microtask, so we have to dedupe those separately. This wouldn't be an issue -// if we required all `act` calls to be awaited, which we might in the future. - -var didScheduleMicrotask_act = false; // Used to quickly bail out of flushSync if there's no sync work to do. - -var mightHavePendingSyncWork = false; -var isFlushingWork = false; -function ensureRootIsScheduled(root) { - // This function is called whenever a root receives an update. It does two - // things 1) it ensures the root is in the root schedule, and 2) it ensures - // there's a pending microtask to process the root schedule. - // - // Most of the actual scheduling logic does not happen until - // `scheduleTaskForRootDuringMicrotask` runs. - // Add the root to the schedule - if (root === lastScheduledRoot || root.next !== null); - else { - if (lastScheduledRoot === null) { - firstScheduledRoot = lastScheduledRoot = root; - } else { - lastScheduledRoot.next = root; - lastScheduledRoot = root; - } - } // Any time a root received an update, we set this to true until the next time - // we process the schedule. If it's false, then we can quickly exit flushSync - // without consulting the schedule. - - mightHavePendingSyncWork = true; // At the end of the current event, go through each of the roots and ensure - // there's a task scheduled for each one at the correct priority. - - if (ReactCurrentActQueue$1.current !== null) { - // We're inside an `act` scope. - if (!didScheduleMicrotask_act) { - didScheduleMicrotask_act = true; - scheduleImmediateTask(processRootScheduleInMicrotask); - } - } else { - if (!didScheduleMicrotask) { - didScheduleMicrotask = true; - scheduleImmediateTask(processRootScheduleInMicrotask); - } - } - - if (!enableDeferRootSchedulingToMicrotask) { - // While this flag is disabled, we schedule the render task immediately - // instead of waiting a microtask. - // TODO: We need to land enableDeferRootSchedulingToMicrotask ASAP to - // unblock additional features we have planned. - scheduleTaskForRootDuringMicrotask(root, now$1()); - } - - if (ReactCurrentActQueue$1.isBatchingLegacy && root.tag === LegacyRoot) { - // Special `act` case: Record whenever a legacy update is scheduled. - ReactCurrentActQueue$1.didScheduleLegacyUpdate = true; - } -} -function flushSyncWorkOnAllRoots() { - // This is allowed to be called synchronously, but the caller should check - // the execution context first. - flushSyncWorkAcrossRoots_impl(false); -} -function flushSyncWorkOnLegacyRootsOnly() { - // This is allowed to be called synchronously, but the caller should check - // the execution context first. - flushSyncWorkAcrossRoots_impl(true); -} - -function flushSyncWorkAcrossRoots_impl(onlyLegacy) { - if (isFlushingWork) { - // Prevent reentrancy. - // TODO: Is this overly defensive? The callers must check the execution - // context first regardless. - return; - } - - if (!mightHavePendingSyncWork) { - // Fast path. There's no sync work to do. - return; - } - - var workInProgressRoot = getWorkInProgressRoot(); - var workInProgressRootRenderLanes = getWorkInProgressRootRenderLanes(); // There may or may not be synchronous work scheduled. Let's check. - - var didPerformSomeWork; - var errors = null; - isFlushingWork = true; - - do { - didPerformSomeWork = false; - var root = firstScheduledRoot; - - while (root !== null) { - if (onlyLegacy && root.tag !== LegacyRoot); - else { - var nextLanes = getNextLanes( - root, - root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes - ); - - if (includesSyncLane(nextLanes)) { - // This root has pending sync work. Flush it now. - try { - // TODO: Pass nextLanes as an argument instead of computing it again - // inside performSyncWorkOnRoot. - didPerformSomeWork = true; - performSyncWorkOnRoot(root); - } catch (error) { - // Collect errors so we can rethrow them at the end - if (errors === null) { - errors = [error]; - } else { - errors.push(error); - } - } - } - } - - root = root.next; - } - } while (didPerformSomeWork); - - isFlushingWork = false; // If any errors were thrown, rethrow them right before exiting. - // TODO: Consider returning these to the caller, to allow them to decide - // how/when to rethrow. - - if (errors !== null) { - if (errors.length > 1) { - if (typeof AggregateError === "function") { - // eslint-disable-next-line no-undef - throw new AggregateError(errors); - } else { - for (var i = 1; i < errors.length; i++) { - scheduleImmediateTask(throwError.bind(null, errors[i])); - } - - var firstError = errors[0]; - throw firstError; - } - } else { - var error = errors[0]; - throw error; - } - } -} - -function throwError(error) { - throw error; -} - -function processRootScheduleInMicrotask() { - // This function is always called inside a microtask. It should never be - // called synchronously. - didScheduleMicrotask = false; - - { - didScheduleMicrotask_act = false; - } // We'll recompute this as we iterate through all the roots and schedule them. - - mightHavePendingSyncWork = false; - var currentTime = now$1(); - var prev = null; - var root = firstScheduledRoot; - - while (root !== null) { - var next = root.next; - var nextLanes = scheduleTaskForRootDuringMicrotask(root, currentTime); - - if (nextLanes === NoLane) { - // This root has no more pending work. Remove it from the schedule. To - // guard against subtle reentrancy bugs, this microtask is the only place - // we do this — you can add roots to the schedule whenever, but you can - // only remove them here. - // Null this out so we know it's been removed from the schedule. - root.next = null; - - if (prev === null) { - // This is the new head of the list - firstScheduledRoot = next; - } else { - prev.next = next; - } - - if (next === null) { - // This is the new tail of the list - lastScheduledRoot = prev; - } - } else { - // This root still has work. Keep it in the list. - prev = root; - - if (includesSyncLane(nextLanes)) { - mightHavePendingSyncWork = true; - } - } - - root = next; - } // At the end of the microtask, flush any pending synchronous work. This has - // to come at the end, because it does actual rendering work that might throw. - - flushSyncWorkOnAllRoots(); -} - -function scheduleTaskForRootDuringMicrotask(root, currentTime) { - // This function is always called inside a microtask, or at the very end of a - // rendering task right before we yield to the main thread. It should never be - // called synchronously. - // - // TODO: Unless enableDeferRootSchedulingToMicrotask is off. We need to land - // that ASAP to unblock additional features we have planned. - // - // This function also never performs React work synchronously; it should - // only schedule work to be performed later, in a separate task or microtask. - // Check if any lanes are being starved by other work. If so, mark them as - // expired so we know to work on those next. - markStarvedLanesAsExpired(root, currentTime); // Determine the next lanes to work on, and their priority. - - var workInProgressRoot = getWorkInProgressRoot(); - var workInProgressRootRenderLanes = getWorkInProgressRootRenderLanes(); - var nextLanes = getNextLanes( - root, - root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes - ); - var existingCallbackNode = root.callbackNode; - - if ( - // Check if there's nothing to work on - nextLanes === NoLanes || // If this root is currently suspended and waiting for data to resolve, don't - // schedule a task to render it. We'll either wait for a ping, or wait to - // receive an update. - // - // Suspended render phase - (root === workInProgressRoot && isWorkLoopSuspendedOnData()) || // Suspended commit phase - root.cancelPendingCommit !== null - ) { - // Fast path: There's nothing to work on. - if (existingCallbackNode !== null) { - cancelCallback(existingCallbackNode); - } - - root.callbackNode = null; - root.callbackPriority = NoLane; - return NoLane; - } // Schedule a new callback in the host environment. - - if (includesSyncLane(nextLanes)) { - // Synchronous work is always flushed at the end of the microtask, so we - // don't need to schedule an additional task. - if (existingCallbackNode !== null) { - cancelCallback(existingCallbackNode); - } - - root.callbackPriority = SyncLane; - root.callbackNode = null; - return SyncLane; - } else { - // We use the highest priority lane to represent the priority of the callback. - var existingCallbackPriority = root.callbackPriority; - var newCallbackPriority = getHighestPriorityLane(nextLanes); - - if ( - newCallbackPriority === existingCallbackPriority && // Special case related to `act`. If the currently scheduled task is a - // Scheduler task, rather than an `act` task, cancel it and re-schedule - // on the `act` queue. - !( - ReactCurrentActQueue$1.current !== null && - existingCallbackNode !== fakeActCallbackNode$1 - ) - ) { - // The priority hasn't changed. We can reuse the existing task. - return newCallbackPriority; - } else { - // Cancel the existing callback. We'll schedule a new one below. - cancelCallback(existingCallbackNode); - } - - var schedulerPriorityLevel; - - switch (lanesToEventPriority(nextLanes)) { - case DiscreteEventPriority: - schedulerPriorityLevel = ImmediatePriority; - break; - - case ContinuousEventPriority: - schedulerPriorityLevel = UserBlockingPriority; - break; - - case DefaultEventPriority: - schedulerPriorityLevel = NormalPriority$1; - break; - - case IdleEventPriority: - schedulerPriorityLevel = IdlePriority; - break; - - default: - schedulerPriorityLevel = NormalPriority$1; - break; - } - - var newCallbackNode = scheduleCallback$1( - schedulerPriorityLevel, - performConcurrentWorkOnRoot.bind(null, root) - ); - root.callbackPriority = newCallbackPriority; - root.callbackNode = newCallbackNode; - return newCallbackPriority; - } -} - -function getContinuationForRoot(root, originalCallbackNode) { - // This is called at the end of `performConcurrentWorkOnRoot` to determine - // if we need to schedule a continuation task. - // - // Usually `scheduleTaskForRootDuringMicrotask` only runs inside a microtask; - // however, since most of the logic for determining if we need a continuation - // versus a new task is the same, we cheat a bit and call it here. This is - // only safe to do because we know we're at the end of the browser task. - // So although it's not an actual microtask, it might as well be. - scheduleTaskForRootDuringMicrotask(root, now$1()); - - if (root.callbackNode === originalCallbackNode) { - // The task node scheduled for this root is the same one that's - // currently executed. Need to return a continuation. - return performConcurrentWorkOnRoot.bind(null, root); - } - - return null; -} -var fakeActCallbackNode$1 = {}; - -function scheduleCallback$1(priorityLevel, callback) { - if (ReactCurrentActQueue$1.current !== null) { - // Special case: We're inside an `act` scope (a testing utility). - // Instead of scheduling work in the host environment, add it to a - // fake internal queue that's managed by the `act` implementation. - ReactCurrentActQueue$1.current.push(callback); - return fakeActCallbackNode$1; - } else { - return scheduleCallback$3(priorityLevel, callback); - } -} - -function cancelCallback(callbackNode) { - if (callbackNode === fakeActCallbackNode$1); - else if (callbackNode !== null) { - cancelCallback$1(callbackNode); - } -} - -function scheduleImmediateTask(cb) { - if (ReactCurrentActQueue$1.current !== null) { - // Special case: Inside an `act` scope, we push microtasks to the fake `act` - // callback queue. This is because we currently support calling `act` - // without awaiting the result. The plan is to deprecate that, and require - // that you always await the result so that the microtasks have a chance to - // run. But it hasn't happened yet. - ReactCurrentActQueue$1.current.push(function () { - cb(); - return null; - }); - } // TODO: Can we land supportsMicrotasks? Which environments don't support it? - // Alternatively, can we move this check to the host config? - - { - // If microtasks are not supported, use Scheduler. - scheduleCallback$3(ImmediatePriority, cb); - } -} - -var ceil = Math.ceil; var PossiblyWeakMap = typeof WeakMap === "function" ? WeakMap : Map; var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher, ReactCurrentCache = ReactSharedInternals.ReactCurrentCache, @@ -23763,12 +23854,7 @@ var isFlushingPassiveEffects = false; var didScheduleUpdateDuringPassiveEffects = false; var NESTED_PASSIVE_UPDATE_LIMIT = 50; var nestedPassiveUpdateCount = 0; -var rootWithPassiveNestedUpdates = null; // If two updates are scheduled within the same event, we should treat their -// event times as simultaneous, even if the actual clock time has advanced -// between the first and second call. - -var currentEventTime = NoTimestamp; -var currentEventTransitionLane = NoLanes; +var rootWithPassiveNestedUpdates = null; var isRunningInsertionEffect = false; function getWorkInProgressRoot() { return workInProgressRoot; @@ -23779,20 +23865,6 @@ function getWorkInProgressRootRenderLanes() { function isWorkLoopSuspendedOnData() { return workInProgressSuspendedReason === SuspendedOnData; } -function requestEventTime() { - if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { - // We're inside React, so it's fine to read the actual time. - return now$1(); - } // We're not inside React, so we may be in the middle of a browser event. - - if (currentEventTime !== NoTimestamp) { - // Use the same start time for all updates until we enter React again. - return currentEventTime; - } // This is the first update since React yielded. Compute a new start time. - - currentEventTime = now$1(); - return currentEventTime; -} function requestUpdateLane(fiber) { // Special cases var mode = fiber.mode; @@ -23826,20 +23898,14 @@ function requestUpdateLane(fiber) { } transition._updatedFibers.add(fiber); - } // The algorithm for assigning an update to a lane should be stable for all - // updates at the same priority within the same event. To do this, the - // inputs to the algorithm must be the same. - // - // The trick we use is to cache the first of each of these inputs within an - // event. Then reset the cached values once we can be sure the event is - // over. Our heuristic for that is whenever we enter a concurrent work loop. - - if (currentEventTransitionLane === NoLane) { - // All transitions within the same event are assigned the same lane. - currentEventTransitionLane = claimNextTransitionLane(); } - return currentEventTransitionLane; + var asyncAction = peekAsyncActionContext(); + return asyncAction !== null // We're inside an async action scope. Reuse the same lane. + ? asyncAction.lane // We may or may not be inside an async action scope. If we are, this + : // is the first update in that scope. Either way, we need to get a + // fresh transition lane. + requestTransitionLane(); } // Updates originating inside certain React methods, like flushSync, have // their priority set by tracking it with a context variable. // @@ -23876,7 +23942,7 @@ function requestRetryLane(fiber) { return claimNextRetryLane(); } -function scheduleUpdateOnFiber(root, fiber, lane, eventTime) { +function scheduleUpdateOnFiber(root, fiber, lane) { { if (isRunningInsertionEffect) { error("useInsertionEffect must not schedule updates."); @@ -23902,7 +23968,7 @@ function scheduleUpdateOnFiber(root, fiber, lane, eventTime) { markRootSuspended(root, workInProgressRootRenderLanes); } // Mark that the root has a pending update. - markRootUpdated(root, lane, eventTime); + markRootUpdated(root, lane); if ( (executionContext & RenderContext) !== NoLanes && @@ -24014,11 +24080,7 @@ function isUnsafeClassRenderPhaseUpdate(fiber) { function performConcurrentWorkOnRoot(root, didTimeout) { { resetNestedUpdateFlag(); - } // Since we know we're in a React event, we can clear the current - // event time. The next update will compute a new event time. - - currentEventTime = NoTimestamp; - currentEventTransitionLane = NoLanes; + } if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { throw new Error("Should not already be working."); @@ -24244,133 +24306,30 @@ function queueRecoverableErrors(errors) { } function finishConcurrentRender(root, exitStatus, finishedWork, lanes) { + // TODO: The fact that most of these branches are identical suggests that some + // of the exit statuses are not best modeled as exit statuses and should be + // tracked orthogonally. switch (exitStatus) { case RootInProgress: case RootFatalErrored: { throw new Error("Root did not complete. This is a bug in React."); } - case RootErrored: { - // We should have already attempted to retry this tree. If we reached - // this point, it errored again. Commit it. - commitRootWhenReady( - root, - finishedWork, - workInProgressRootRecoverableErrors, - workInProgressTransitions, - lanes - ); - break; - } - - case RootSuspended: { - markRootSuspended(root, lanes); // We have an acceptable loading state. We need to figure out if we - // should immediately commit it or wait a bit. - - if ( - includesOnlyRetries(lanes) && // do not delay if we're inside an act() scope - !shouldForceFlushFallbacksInDEV() - ) { - // This render only included retries, no updates. Throttle committing - // retries so that we don't show too many loading states too quickly. - var msUntilTimeout = - globalMostRecentFallbackTime + FALLBACK_THROTTLE_MS - now$1(); // Don't bother with a very short suspense time. - - if (msUntilTimeout > 10) { - var nextLanes = getNextLanes(root, NoLanes); - - if (nextLanes !== NoLanes) { - // There's additional work on this root. - break; - } // The render is suspended, it hasn't timed out, and there's no - // lower priority work to do. Instead of committing the fallback - // immediately, wait for more data to arrive. - - root.timeoutHandle = scheduleTimeout( - commitRootWhenReady.bind( - null, - root, - finishedWork, - workInProgressRootRecoverableErrors, - workInProgressTransitions, - lanes - ), - msUntilTimeout - ); - break; - } - } // The work expired. Commit immediately. - - commitRootWhenReady( - root, - finishedWork, - workInProgressRootRecoverableErrors, - workInProgressTransitions, - lanes - ); - break; - } - case RootSuspendedWithDelay: { - markRootSuspended(root, lanes); - if (includesOnlyTransitions(lanes)) { // This is a transition, so we should exit without committing a // placeholder and without scheduling a timeout. Delay indefinitely // until we receive more data. - break; - } - - if (!shouldForceFlushFallbacksInDEV()) { - // This is not a transition, but we did trigger an avoided state. - // Schedule a placeholder to display after a short delay, using the Just - // Noticeable Difference. - // TODO: Is the JND optimization worth the added complexity? If this is - // the only reason we track the event time, then probably not. - // Consider removing. - var mostRecentEventTime = getMostRecentEventTime(root, lanes); - var eventTimeMs = mostRecentEventTime; - var timeElapsedMs = now$1() - eventTimeMs; - - var _msUntilTimeout = jnd(timeElapsedMs) - timeElapsedMs; // Don't bother with a very short suspense time. - - if (_msUntilTimeout > 10) { - // Instead of committing the fallback immediately, wait for more data - // to arrive. - root.timeoutHandle = scheduleTimeout( - commitRootWhenReady.bind( - null, - root, - finishedWork, - workInProgressRootRecoverableErrors, - workInProgressTransitions, - lanes - ), - _msUntilTimeout - ); - break; - } + markRootSuspended(root, lanes); + return; } // Commit the placeholder. - commitRootWhenReady( - root, - finishedWork, - workInProgressRootRecoverableErrors, - workInProgressTransitions, - lanes - ); break; } + case RootErrored: + case RootSuspended: case RootCompleted: { - // The work completed. - commitRootWhenReady( - root, - finishedWork, - workInProgressRootRecoverableErrors, - workInProgressTransitions, - lanes - ); break; } @@ -24378,6 +24337,61 @@ function finishConcurrentRender(root, exitStatus, finishedWork, lanes) { throw new Error("Unknown root exit status."); } } + + if (shouldForceFlushFallbacksInDEV()) { + // We're inside an `act` scope. Commit immediately. + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); + } else { + if ( + includesOnlyRetries(lanes) && + (alwaysThrottleRetries || exitStatus === RootSuspended) + ) { + // This render only included retries, no updates. Throttle committing + // retries so that we don't show too many loading states too quickly. + var msUntilTimeout = + globalMostRecentFallbackTime + FALLBACK_THROTTLE_MS - now$1(); // Don't bother with a very short suspense time. + + if (msUntilTimeout > 10) { + markRootSuspended(root, lanes); + var nextLanes = getNextLanes(root, NoLanes); + + if (nextLanes !== NoLanes) { + // There's additional work we can do on this root. We might as well + // attempt to work on that while we're suspended. + return; + } // The render is suspended, it hasn't timed out, and there's no + // lower priority work to do. Instead of committing the fallback + // immediately, wait for more data to arrive. + // TODO: Combine retry throttling with Suspensey commits. Right now they + // run one after the other. + + root.timeoutHandle = scheduleTimeout( + commitRootWhenReady.bind( + null, + root, + finishedWork, + workInProgressRootRecoverableErrors, + workInProgressTransitions, + lanes + ), + msUntilTimeout + ); + return; + } + } + + commitRootWhenReady( + root, + finishedWork, + workInProgressRootRecoverableErrors, + workInProgressTransitions, + lanes + ); + } } function commitRootWhenReady( @@ -24387,6 +24401,8 @@ function commitRootWhenReady( transitions, lanes ) { + // TODO: Combine retry throttling with Suspensey commits. Right now they run + // one after the other. if (includesOnlyNonUrgentLanes(lanes)) { // the suspensey resources. The renderer is responsible for accumulating // all the load events. This all happens in a single synchronous @@ -24406,22 +24422,14 @@ function commitRootWhenReady( // us that it's ready. This will be canceled if we start work on the // root again. root.cancelPendingCommit = schedulePendingCommit( - commitRoot.bind( - null, - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ) + commitRoot.bind(null, root, recoverableErrors, transitions) ); + markRootSuspended(root, lanes); return; } } // Otherwise, commit immediately. - commitRoot( - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ); + commitRoot(root, recoverableErrors, transitions); } function isRenderConsistentWithExternalStores(finishedWork) { @@ -25458,6 +25466,16 @@ function replaySuspendedUnitOfWork(unitOfWork) { break; } + case HostComponent: { + // Some host components are stateful (that's how we implement form + // actions) but we don't bother to reuse the memoized state because it's + // not worth the extra code. The main reason to reuse the previous hooks + // is to reuse uncached promises, but we happen to know that the only + // promises that a host component might suspend on are definitely cached + // because they are controlled by us. So don't bother. + resetHooksOnUnwind(); // Fallthrough to the next branch. + } + default: { // Other types besides function components are reset completely before // being replayed. Currently this only happens when a Usable type is @@ -25563,28 +25581,14 @@ function completeUnitOfWork(unitOfWork) { var completedWork = unitOfWork; do { - if (revertRemovalOfSiblingPrerendering) { + { if ((completedWork.flags & Incomplete) !== NoFlags$1) { - // This fiber did not complete, because one of its children did not - // complete. Switch to unwinding the stack instead of completing it. - // - // The reason "unwind" and "complete" is interleaved is because when - // something suspends, we continue rendering the siblings even though - // they will be replaced by a fallback. - // TODO: Disable sibling prerendering, then remove this branch. - unwindUnitOfWork(completedWork); - return; - } - } else { - { - if ((completedWork.flags & Incomplete) !== NoFlags$1) { - // NOTE: If we re-enable sibling prerendering in some cases, this branch - // is where we would switch to the unwinding path. - error( - "Internal React error: Expected this fiber to be complete, but " + - "it isn't. It should have been unwound. This is a bug in React." - ); - } + // NOTE: If we re-enable sibling prerendering in some cases, this branch + // is where we would switch to the unwinding path. + error( + "Internal React error: Expected this fiber to be complete, but " + + "it isn't. It should have been unwound. This is a bug in React." + ); } } // The current, flushed, state of this fiber is the alternate. Ideally // nothing should rely on this, but relying on it here means that we don't @@ -25683,23 +25687,10 @@ function unwindUnitOfWork(unitOfWork) { returnFiber.flags |= Incomplete; returnFiber.subtreeFlags = NoFlags$1; returnFiber.deletions = null; - } - - if (revertRemovalOfSiblingPrerendering) { - // If there are siblings, work on them now even though they're going to be - // replaced by a fallback. We're "prerendering" them. Historically our - // rationale for this behavior has been to initiate any lazy data requests - // in the siblings, and also to warm up the CPU cache. - // TODO: Don't prerender siblings. With `use`, we suspend the work loop - // until the data has resolved, anyway. - var siblingFiber = incompleteWork.sibling; - - if (siblingFiber !== null) { - // This branch will return us to the normal work loop. - workInProgress = siblingFiber; - return; - } - } // Otherwise, return to the parent + } // NOTE: If we re-enable sibling prerendering in some cases, here we + // would switch to the normal completion path: check if a sibling + // exists, and if so, begin work on it. + // Otherwise, return to the parent // $FlowFixMe[incompatible-type] we bail out when we get a null incompleteWork = returnFiber; // Update the next thing we're working on in case something throws. @@ -26296,10 +26287,9 @@ function captureCommitPhaseErrorOnRoot(rootFiber, sourceFiber, error) { var errorInfo = createCapturedValueAtFiber(error, sourceFiber); var update = createRootErrorUpdate(rootFiber, errorInfo, SyncLane); var root = enqueueUpdate(rootFiber, update, SyncLane); - var eventTime = requestEventTime(); if (root !== null) { - markRootUpdated(root, SyncLane, eventTime); + markRootUpdated(root, SyncLane); ensureRootIsScheduled(root); } } @@ -26335,10 +26325,9 @@ function captureCommitPhaseError(sourceFiber, nearestMountedAncestor, error$1) { var errorInfo = createCapturedValueAtFiber(error$1, sourceFiber); var update = createClassErrorUpdate(fiber, errorInfo, SyncLane); var root = enqueueUpdate(fiber, update, SyncLane); - var eventTime = requestEventTime(); if (root !== null) { - markRootUpdated(root, SyncLane, eventTime); + markRootUpdated(root, SyncLane); ensureRootIsScheduled(root); } @@ -26464,11 +26453,10 @@ function retryTimedOutBoundary(boundaryFiber, retryLane) { retryLane = requestRetryLane(boundaryFiber); } // TODO: Special case idle priority? - var eventTime = requestEventTime(); var root = enqueueConcurrentRenderForLane(boundaryFiber, retryLane); if (root !== null) { - markRootUpdated(root, retryLane, eventTime); + markRootUpdated(root, retryLane); ensureRootIsScheduled(root); } } @@ -26523,32 +26511,7 @@ function resolveRetryWakeable(boundaryFiber, wakeable) { } retryTimedOutBoundary(boundaryFiber, retryLane); -} // Computes the next Just Noticeable Difference (JND) boundary. -// The theory is that a person can't tell the difference between small differences in time. -// Therefore, if we wait a bit longer than necessary that won't translate to a noticeable -// difference in the experience. However, waiting for longer might mean that we can avoid -// showing an intermediate loading state. The longer we have already waited, the harder it -// is to tell small differences in time. Therefore, the longer we've already waited, -// the longer we can wait additionally. At some point we have to give up though. -// We pick a train model where the next boundary commits at a consistent schedule. -// These particular numbers are vague estimates. We expect to adjust them based on research. - -function jnd(timeElapsed) { - return timeElapsed < 120 - ? 120 - : timeElapsed < 480 - ? 480 - : timeElapsed < 1080 - ? 1080 - : timeElapsed < 1920 - ? 1920 - : timeElapsed < 3000 - ? 3000 - : timeElapsed < 4320 - ? 4320 - : ceil(timeElapsed / 1960) * 1960; } - function throwIfInfiniteUpdateLoopDetected() { if (nestedUpdateCount > NESTED_UPDATE_LIMIT) { nestedUpdateCount = 0; @@ -27229,7 +27192,7 @@ function scheduleFibersWithFamiliesRecursively( var root = enqueueConcurrentRenderForLane(fiber, SyncLane); if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + scheduleUpdateOnFiber(root, fiber, SyncLane); } } @@ -28123,7 +28086,6 @@ function FiberRootNode( this.next = null; this.callbackNode = null; this.callbackPriority = NoLane; - this.eventTimes = createLaneMap(NoLanes); this.expirationTimes = createLaneMap(NoTimestamp); this.pendingLanes = NoLanes; this.suspendedLanes = NoLanes; @@ -28361,8 +28323,7 @@ function updateContainer(element, container, parentComponent, callback) { var root = enqueueUpdate(current$1, update, lane); if (root !== null) { - var eventTime = requestEventTime(); - scheduleUpdateOnFiber(root, current$1, lane, eventTime); + scheduleUpdateOnFiber(root, current$1, lane); entangleTransitions(root, current$1, lane); } @@ -28510,7 +28471,7 @@ var setSuspenseHandler = null; var root = enqueueConcurrentRenderForLane(fiber, SyncLane); if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + scheduleUpdateOnFiber(root, fiber, SyncLane); } } }; @@ -28531,7 +28492,7 @@ var setSuspenseHandler = null; var root = enqueueConcurrentRenderForLane(fiber, SyncLane); if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + scheduleUpdateOnFiber(root, fiber, SyncLane); } } }; @@ -28552,7 +28513,7 @@ var setSuspenseHandler = null; var root = enqueueConcurrentRenderForLane(fiber, SyncLane); if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + scheduleUpdateOnFiber(root, fiber, SyncLane); } } }; // Support DevTools props for function components, forwardRef, memo, host components, etc. @@ -28567,7 +28528,7 @@ var setSuspenseHandler = null; var root = enqueueConcurrentRenderForLane(fiber, SyncLane); if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + scheduleUpdateOnFiber(root, fiber, SyncLane); } }; @@ -28581,7 +28542,7 @@ var setSuspenseHandler = null; var root = enqueueConcurrentRenderForLane(fiber, SyncLane); if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + scheduleUpdateOnFiber(root, fiber, SyncLane); } }; @@ -28595,7 +28556,7 @@ var setSuspenseHandler = null; var root = enqueueConcurrentRenderForLane(fiber, SyncLane); if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + scheduleUpdateOnFiber(root, fiber, SyncLane); } }; @@ -28603,7 +28564,7 @@ var setSuspenseHandler = null; var root = enqueueConcurrentRenderForLane(fiber, SyncLane); if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + scheduleUpdateOnFiber(root, fiber, SyncLane); } }; diff --git a/compiled/facebook-www/ReactART-dev.modern.js b/compiled/facebook-www/ReactART-dev.modern.js index 5ebe69b840..117a93606c 100644 --- a/compiled/facebook-www/ReactART-dev.modern.js +++ b/compiled/facebook-www/ReactART-dev.modern.js @@ -69,7 +69,7 @@ function _assertThisInitialized(self) { return self; } -var ReactVersion = "18.3.0-www-modern-ae1f3bca"; +var ReactVersion = "18.3.0-www-modern-85c16289"; var LegacyRoot = 0; var ConcurrentRoot = 1; @@ -165,9 +165,7 @@ var ReactSharedInternals = // Re-export dynamic flags from the www version. var dynamicFeatureFlags = require("ReactFeatureFlags"); -var revertRemovalOfSiblingPrerendering = - dynamicFeatureFlags.revertRemovalOfSiblingPrerendering, - replayFailedUnitOfWorkWithInvokeGuardedCallback = +var replayFailedUnitOfWorkWithInvokeGuardedCallback = dynamicFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback, enableDebugTracing = dynamicFeatureFlags.enableDebugTracing, enableUseRefAccessWarning = dynamicFeatureFlags.enableUseRefAccessWarning, @@ -178,7 +176,9 @@ var revertRemovalOfSiblingPrerendering = enableTransitionTracing = dynamicFeatureFlags.enableTransitionTracing, enableDeferRootSchedulingToMicrotask = dynamicFeatureFlags.enableDeferRootSchedulingToMicrotask, - diffInCommitPhase = dynamicFeatureFlags.diffInCommitPhase; // On WWW, true is used for a new modern build. + diffInCommitPhase = dynamicFeatureFlags.diffInCommitPhase, + enableAsyncActions = dynamicFeatureFlags.enableAsyncActions, + alwaysThrottleRetries = dynamicFeatureFlags.alwaysThrottleRetries; // On WWW, true is used for a new modern build. var enableProfilerTimer = true; var enableProfilerCommitHooks = true; var enableProfilerNestedUpdatePhase = true; @@ -1921,24 +1921,6 @@ function getNextLanes(root, wipLanes) { return nextLanes; } -function getMostRecentEventTime(root, lanes) { - var eventTimes = root.eventTimes; - var mostRecentEventTime = NoTimestamp; - - while (lanes > 0) { - var index = pickArbitraryLaneIndex(lanes); - var lane = 1 << index; - var eventTime = eventTimes[index]; - - if (eventTime > mostRecentEventTime) { - mostRecentEventTime = eventTime; - } - - lanes &= ~lane; - } - - return mostRecentEventTime; -} function computeExpirationTime(lane, currentTime) { switch (lane) { @@ -2176,7 +2158,7 @@ function createLaneMap(initial) { return laneMap; } -function markRootUpdated(root, updateLane, eventTime) { +function markRootUpdated(root, updateLane) { root.pendingLanes |= updateLane; // If there are any suspended transitions, it's possible this new update // could unblock them. Clear the suspended lanes so that we can try rendering // them again. @@ -2194,12 +2176,6 @@ function markRootUpdated(root, updateLane, eventTime) { root.suspendedLanes = NoLanes; root.pingedLanes = NoLanes; } - - var eventTimes = root.eventTimes; - var index = laneToIndex(updateLane); // We can always overwrite an existing timestamp because we prefer the most - // recent event, and we assume time is monotonically increasing. - - eventTimes[index] = eventTime; } function markRootSuspended$1(root, suspendedLanes) { root.suspendedLanes |= suspendedLanes; @@ -2232,7 +2208,6 @@ function markRootFinished(root, remainingLanes) { root.entangledLanes &= remainingLanes; root.errorRecoveryDisabledLanes &= remainingLanes; var entanglements = root.entanglements; - var eventTimes = root.eventTimes; var expirationTimes = root.expirationTimes; var hiddenUpdates = root.hiddenUpdates; // Clear the lanes that no longer have pending work @@ -2242,7 +2217,6 @@ function markRootFinished(root, remainingLanes) { var index = pickArbitraryLaneIndex(lanes); var lane = 1 << index; entanglements[index] = NoLanes; - eventTimes[index] = NoTimestamp; expirationTimes[index] = NoTimestamp; var hiddenUpdatesForLane = hiddenUpdates[index]; @@ -2861,6 +2835,9 @@ function shouldSetTextContent(type, props) { } function getCurrentEventPriority() { return DefaultEventPriority; +} +function shouldAttemptEagerTransition() { + return false; } // The ART renderer is secondary to the React DOM renderer. var warnsIfNotActing = false; @@ -2932,7 +2909,7 @@ function preloadInstance(type, props) { } function waitForCommitToBeReady() { return null; -} // eslint-disable-next-line no-undef +} var ReactCurrentDispatcher$2 = ReactSharedInternals.ReactCurrentDispatcher; var prefix; @@ -7089,6 +7066,497 @@ function warnAboutMultipleRenderersDEV(mutableSource) { } } // Eager reads the version of a mutable source and stores it on the root. +var ReactCurrentActQueue$2 = ReactSharedInternals.ReactCurrentActQueue; // A linked list of all the roots with pending work. In an idiomatic app, +// there's only a single root, but we do support multi root apps, hence this +// extra complexity. But this module is optimized for the single root case. + +var firstScheduledRoot = null; +var lastScheduledRoot = null; // Used to prevent redundant mircotasks from being scheduled. + +var didScheduleMicrotask = false; // `act` "microtasks" are scheduled on the `act` queue instead of an actual +// microtask, so we have to dedupe those separately. This wouldn't be an issue +// if we required all `act` calls to be awaited, which we might in the future. + +var didScheduleMicrotask_act = false; // Used to quickly bail out of flushSync if there's no sync work to do. + +var mightHavePendingSyncWork = false; +var isFlushingWork = false; +var currentEventTransitionLane = NoLane; +function ensureRootIsScheduled(root) { + // This function is called whenever a root receives an update. It does two + // things 1) it ensures the root is in the root schedule, and 2) it ensures + // there's a pending microtask to process the root schedule. + // + // Most of the actual scheduling logic does not happen until + // `scheduleTaskForRootDuringMicrotask` runs. + // Add the root to the schedule + if (root === lastScheduledRoot || root.next !== null); + else { + if (lastScheduledRoot === null) { + firstScheduledRoot = lastScheduledRoot = root; + } else { + lastScheduledRoot.next = root; + lastScheduledRoot = root; + } + } // Any time a root received an update, we set this to true until the next time + // we process the schedule. If it's false, then we can quickly exit flushSync + // without consulting the schedule. + + mightHavePendingSyncWork = true; // At the end of the current event, go through each of the roots and ensure + // there's a task scheduled for each one at the correct priority. + + if (ReactCurrentActQueue$2.current !== null) { + // We're inside an `act` scope. + if (!didScheduleMicrotask_act) { + didScheduleMicrotask_act = true; + scheduleImmediateTask(processRootScheduleInMicrotask); + } + } else { + if (!didScheduleMicrotask) { + didScheduleMicrotask = true; + scheduleImmediateTask(processRootScheduleInMicrotask); + } + } + + if (!enableDeferRootSchedulingToMicrotask) { + // While this flag is disabled, we schedule the render task immediately + // instead of waiting a microtask. + // TODO: We need to land enableDeferRootSchedulingToMicrotask ASAP to + // unblock additional features we have planned. + scheduleTaskForRootDuringMicrotask(root, now$1()); + } + + if (ReactCurrentActQueue$2.isBatchingLegacy && root.tag === LegacyRoot) { + // Special `act` case: Record whenever a legacy update is scheduled. + ReactCurrentActQueue$2.didScheduleLegacyUpdate = true; + } +} +function flushSyncWorkOnAllRoots() { + // This is allowed to be called synchronously, but the caller should check + // the execution context first. + flushSyncWorkAcrossRoots_impl(false); +} +function flushSyncWorkOnLegacyRootsOnly() { + // This is allowed to be called synchronously, but the caller should check + // the execution context first. + flushSyncWorkAcrossRoots_impl(true); +} + +function flushSyncWorkAcrossRoots_impl(onlyLegacy) { + if (isFlushingWork) { + // Prevent reentrancy. + // TODO: Is this overly defensive? The callers must check the execution + // context first regardless. + return; + } + + if (!mightHavePendingSyncWork) { + // Fast path. There's no sync work to do. + return; + } + + var workInProgressRoot = getWorkInProgressRoot(); + var workInProgressRootRenderLanes = getWorkInProgressRootRenderLanes(); // There may or may not be synchronous work scheduled. Let's check. + + var didPerformSomeWork; + var errors = null; + isFlushingWork = true; + + do { + didPerformSomeWork = false; + var root = firstScheduledRoot; + + while (root !== null) { + if (onlyLegacy && root.tag !== LegacyRoot); + else { + var nextLanes = getNextLanes( + root, + root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes + ); + + if (includesSyncLane(nextLanes)) { + // This root has pending sync work. Flush it now. + try { + // TODO: Pass nextLanes as an argument instead of computing it again + // inside performSyncWorkOnRoot. + didPerformSomeWork = true; + performSyncWorkOnRoot(root); + } catch (error) { + // Collect errors so we can rethrow them at the end + if (errors === null) { + errors = [error]; + } else { + errors.push(error); + } + } + } + } + + root = root.next; + } + } while (didPerformSomeWork); + + isFlushingWork = false; // If any errors were thrown, rethrow them right before exiting. + // TODO: Consider returning these to the caller, to allow them to decide + // how/when to rethrow. + + if (errors !== null) { + if (errors.length > 1) { + if (typeof AggregateError === "function") { + // eslint-disable-next-line no-undef + throw new AggregateError(errors); + } else { + for (var i = 1; i < errors.length; i++) { + scheduleImmediateTask(throwError.bind(null, errors[i])); + } + + var firstError = errors[0]; + throw firstError; + } + } else { + var error = errors[0]; + throw error; + } + } +} + +function throwError(error) { + throw error; +} + +function processRootScheduleInMicrotask() { + // This function is always called inside a microtask. It should never be + // called synchronously. + didScheduleMicrotask = false; + + { + didScheduleMicrotask_act = false; + } // We'll recompute this as we iterate through all the roots and schedule them. + + mightHavePendingSyncWork = false; + var currentTime = now$1(); + var prev = null; + var root = firstScheduledRoot; + + while (root !== null) { + var next = root.next; + + if ( + currentEventTransitionLane !== NoLane && + shouldAttemptEagerTransition() + ) { + markRootEntangled(root, mergeLanes(currentEventTransitionLane, SyncLane)); + } + + var nextLanes = scheduleTaskForRootDuringMicrotask(root, currentTime); + + if (nextLanes === NoLane) { + // This root has no more pending work. Remove it from the schedule. To + // guard against subtle reentrancy bugs, this microtask is the only place + // we do this — you can add roots to the schedule whenever, but you can + // only remove them here. + // Null this out so we know it's been removed from the schedule. + root.next = null; + + if (prev === null) { + // This is the new head of the list + firstScheduledRoot = next; + } else { + prev.next = next; + } + + if (next === null) { + // This is the new tail of the list + lastScheduledRoot = prev; + } + } else { + // This root still has work. Keep it in the list. + prev = root; + + if (includesSyncLane(nextLanes)) { + mightHavePendingSyncWork = true; + } + } + + root = next; + } + + currentEventTransitionLane = NoLane; // At the end of the microtask, flush any pending synchronous work. This has + // to come at the end, because it does actual rendering work that might throw. + + flushSyncWorkOnAllRoots(); +} + +function scheduleTaskForRootDuringMicrotask(root, currentTime) { + // This function is always called inside a microtask, or at the very end of a + // rendering task right before we yield to the main thread. It should never be + // called synchronously. + // + // TODO: Unless enableDeferRootSchedulingToMicrotask is off. We need to land + // that ASAP to unblock additional features we have planned. + // + // This function also never performs React work synchronously; it should + // only schedule work to be performed later, in a separate task or microtask. + // Check if any lanes are being starved by other work. If so, mark them as + // expired so we know to work on those next. + markStarvedLanesAsExpired(root, currentTime); // Determine the next lanes to work on, and their priority. + + var workInProgressRoot = getWorkInProgressRoot(); + var workInProgressRootRenderLanes = getWorkInProgressRootRenderLanes(); + var nextLanes = getNextLanes( + root, + root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes + ); + var existingCallbackNode = root.callbackNode; + + if ( + // Check if there's nothing to work on + nextLanes === NoLanes || // If this root is currently suspended and waiting for data to resolve, don't + // schedule a task to render it. We'll either wait for a ping, or wait to + // receive an update. + // + // Suspended render phase + (root === workInProgressRoot && isWorkLoopSuspendedOnData()) || // Suspended commit phase + root.cancelPendingCommit !== null + ) { + // Fast path: There's nothing to work on. + if (existingCallbackNode !== null) { + cancelCallback(existingCallbackNode); + } + + root.callbackNode = null; + root.callbackPriority = NoLane; + return NoLane; + } // Schedule a new callback in the host environment. + + if (includesSyncLane(nextLanes)) { + // Synchronous work is always flushed at the end of the microtask, so we + // don't need to schedule an additional task. + if (existingCallbackNode !== null) { + cancelCallback(existingCallbackNode); + } + + root.callbackPriority = SyncLane; + root.callbackNode = null; + return SyncLane; + } else { + // We use the highest priority lane to represent the priority of the callback. + var existingCallbackPriority = root.callbackPriority; + var newCallbackPriority = getHighestPriorityLane(nextLanes); + + if ( + newCallbackPriority === existingCallbackPriority && // Special case related to `act`. If the currently scheduled task is a + // Scheduler task, rather than an `act` task, cancel it and re-schedule + // on the `act` queue. + !( + ReactCurrentActQueue$2.current !== null && + existingCallbackNode !== fakeActCallbackNode$1 + ) + ) { + // The priority hasn't changed. We can reuse the existing task. + return newCallbackPriority; + } else { + // Cancel the existing callback. We'll schedule a new one below. + cancelCallback(existingCallbackNode); + } + + var schedulerPriorityLevel; + + switch (lanesToEventPriority(nextLanes)) { + case DiscreteEventPriority: + schedulerPriorityLevel = ImmediatePriority; + break; + + case ContinuousEventPriority: + schedulerPriorityLevel = UserBlockingPriority; + break; + + case DefaultEventPriority: + schedulerPriorityLevel = NormalPriority$1; + break; + + case IdleEventPriority: + schedulerPriorityLevel = IdlePriority; + break; + + default: + schedulerPriorityLevel = NormalPriority$1; + break; + } + + var newCallbackNode = scheduleCallback$2( + schedulerPriorityLevel, + performConcurrentWorkOnRoot.bind(null, root) + ); + root.callbackPriority = newCallbackPriority; + root.callbackNode = newCallbackNode; + return newCallbackPriority; + } +} + +function getContinuationForRoot(root, originalCallbackNode) { + // This is called at the end of `performConcurrentWorkOnRoot` to determine + // if we need to schedule a continuation task. + // + // Usually `scheduleTaskForRootDuringMicrotask` only runs inside a microtask; + // however, since most of the logic for determining if we need a continuation + // versus a new task is the same, we cheat a bit and call it here. This is + // only safe to do because we know we're at the end of the browser task. + // So although it's not an actual microtask, it might as well be. + scheduleTaskForRootDuringMicrotask(root, now$1()); + + if (root.callbackNode === originalCallbackNode) { + // The task node scheduled for this root is the same one that's + // currently executed. Need to return a continuation. + return performConcurrentWorkOnRoot.bind(null, root); + } + + return null; +} +var fakeActCallbackNode$1 = {}; + +function scheduleCallback$2(priorityLevel, callback) { + if (ReactCurrentActQueue$2.current !== null) { + // Special case: We're inside an `act` scope (a testing utility). + // Instead of scheduling work in the host environment, add it to a + // fake internal queue that's managed by the `act` implementation. + ReactCurrentActQueue$2.current.push(callback); + return fakeActCallbackNode$1; + } else { + return scheduleCallback$3(priorityLevel, callback); + } +} + +function cancelCallback(callbackNode) { + if (callbackNode === fakeActCallbackNode$1); + else if (callbackNode !== null) { + cancelCallback$1(callbackNode); + } +} + +function scheduleImmediateTask(cb) { + if (ReactCurrentActQueue$2.current !== null) { + // Special case: Inside an `act` scope, we push microtasks to the fake `act` + // callback queue. This is because we currently support calling `act` + // without awaiting the result. The plan is to deprecate that, and require + // that you always await the result so that the microtasks have a chance to + // run. But it hasn't happened yet. + ReactCurrentActQueue$2.current.push(function () { + cb(); + return null; + }); + } // TODO: Can we land supportsMicrotasks? Which environments don't support it? + // Alternatively, can we move this check to the host config? + + { + // If microtasks are not supported, use Scheduler. + scheduleCallback$3(ImmediatePriority, cb); + } +} + +function requestTransitionLane() { + // The algorithm for assigning an update to a lane should be stable for all + // updates at the same priority within the same event. To do this, the + // inputs to the algorithm must be the same. + // + // The trick we use is to cache the first of each of these inputs within an + // event. Then reset the cached values once we can be sure the event is + // over. Our heuristic for that is whenever we enter a concurrent work loop. + if (currentEventTransitionLane === NoLane) { + // All transitions within the same event are assigned the same lane. + currentEventTransitionLane = claimNextTransitionLane(); + } + + return currentEventTransitionLane; +} + +var currentAsyncAction = null; +function requestAsyncActionContext(actionReturnValue) { + if ( + actionReturnValue !== null && + typeof actionReturnValue === "object" && + typeof actionReturnValue.then === "function" + ) { + // This is an async action. + // + // Return a thenable that resolves once the action scope (i.e. the async + // function passed to startTransition) has finished running. The fulfilled + // value is `false` to represent that the action is not pending. + var thenable = actionReturnValue; + + if (currentAsyncAction === null) { + // There's no outer async action scope. Create a new one. + var asyncAction = { + lane: requestTransitionLane(), + listeners: [], + count: 0, + status: "pending", + value: false, + reason: undefined, + then: function (resolve) { + asyncAction.listeners.push(resolve); + } + }; + attachPingListeners(thenable, asyncAction); + currentAsyncAction = asyncAction; + return asyncAction; + } else { + // Inherit the outer scope. + var _asyncAction = currentAsyncAction; + attachPingListeners(thenable, _asyncAction); + return _asyncAction; + } + } else { + // This is not an async action, but it may be part of an outer async action. + if (currentAsyncAction === null) { + // There's no outer async action scope. + return false; + } else { + // Inherit the outer scope. + return currentAsyncAction; + } + } +} +function peekAsyncActionContext() { + return currentAsyncAction; +} + +function attachPingListeners(thenable, asyncAction) { + asyncAction.count++; + thenable.then( + function () { + if (--asyncAction.count === 0) { + var fulfilledAsyncAction = asyncAction; + fulfilledAsyncAction.status = "fulfilled"; + completeAsyncActionScope(asyncAction); + } + }, + function (error) { + if (--asyncAction.count === 0) { + var rejectedAsyncAction = asyncAction; + rejectedAsyncAction.status = "rejected"; + rejectedAsyncAction.reason = error; + completeAsyncActionScope(asyncAction); + } + } + ); + return asyncAction; +} + +function completeAsyncActionScope(action) { + if (currentAsyncAction === action) { + currentAsyncAction = null; + } + + var listeners = action.listeners; + action.listeners = []; + + for (var i = 0; i < listeners.length; i++) { + var listener = listeners[i]; + listener(false); + } +} + var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, ReactCurrentBatchConfig$2 = ReactSharedInternals.ReactCurrentBatchConfig; var didWarnAboutMismatchedHooksForComponent; @@ -7763,38 +8231,42 @@ var createFunctionComponentUpdateQueue; }; } +function useThenable(thenable) { + // Track the position of the thenable within this fiber. + var index = thenableIndexCounter; + thenableIndexCounter += 1; + + if (thenableState === null) { + thenableState = createThenableState(); + } + + var result = trackUsedThenable(thenableState, thenable, index); + + if ( + currentlyRenderingFiber$1.alternate === null && + (workInProgressHook === null + ? currentlyRenderingFiber$1.memoizedState === null + : workInProgressHook.next === null) + ) { + // Initial render, and either this is the first time the component is + // called, or there were no Hooks called after this use() the previous + // time (perhaps because it threw). Subsequent Hook calls should use the + // mount dispatcher. + { + ReactCurrentDispatcher$1.current = HooksDispatcherOnMountInDEV; + } + } + + return result; +} + function use(usable) { if (usable !== null && typeof usable === "object") { // $FlowFixMe[method-unbinding] if (typeof usable.then === "function") { // This is a thenable. - var thenable = usable; // Track the position of the thenable within this fiber. - - var index = thenableIndexCounter; - thenableIndexCounter += 1; - - if (thenableState === null) { - thenableState = createThenableState(); - } - - var result = trackUsedThenable(thenableState, thenable, index); - - if ( - currentlyRenderingFiber$1.alternate === null && - (workInProgressHook === null - ? currentlyRenderingFiber$1.memoizedState === null - : workInProgressHook.next === null) - ) { - // Initial render, and either this is the first time the component is - // called, or there were no Hooks called after this use() the previous - // time (perhaps because it threw). Subsequent Hook calls should use the - // mount dispatcher. - { - ReactCurrentDispatcher$1.current = HooksDispatcherOnMountInDEV; - } - } - - return result; + var thenable = usable; + return useThenable(thenable); } else if ( usable.$$typeof === REACT_CONTEXT_TYPE || usable.$$typeof === REACT_SERVER_CONTEXT_TYPE @@ -8564,7 +9036,7 @@ function forceStoreRerender(fiber) { var root = enqueueConcurrentRenderForLane(fiber, SyncLane); if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + scheduleUpdateOnFiber(root, fiber, SyncLane); } } @@ -9101,8 +9573,35 @@ function startTransition(setPending, callback, options) { } try { - setPending(false); - callback(); + if (enableAsyncActions) { + var returnValue = callback(); // `isPending` is either `false` or a thenable that resolves to `false`, + // depending on whether the action scope is an async function. In the + // async case, the resulting render will suspend until the async action + // scope has finished. + + var isPending = requestAsyncActionContext(returnValue); + setPending(isPending); + } else { + // Async actions are not enabled. + setPending(false); + callback(); + } + } catch (error) { + if (enableAsyncActions) { + // This is a trick to get the `useTransition` hook to rethrow the error. + // When it unwraps the thenable with the `use` algorithm, the error + // will be thrown. + var rejectedThenable = { + then: function () {}, + status: "rejected", + reason: error + }; + setPending(rejectedThenable); + } else { + // The error rethrowing behavior is only enabled when the async actions + // feature is on, even for sync actions. + throw error; + } } finally { setCurrentUpdatePriority(previousPriority); ReactCurrentBatchConfig$2.transition = prevTransition; @@ -9127,30 +9626,37 @@ function startTransition(setPending, callback, options) { function mountTransition() { var _mountState = mountState(false), - isPending = _mountState[0], setPending = _mountState[1]; // The `start` method never changes. var start = startTransition.bind(null, setPending); var hook = mountWorkInProgressHook(); hook.memoizedState = start; - return [isPending, start]; + return [false, start]; } function updateTransition() { var _updateState = updateState(), - isPending = _updateState[0]; + booleanOrThenable = _updateState[0]; var hook = updateWorkInProgressHook(); var start = hook.memoizedState; + var isPending = + typeof booleanOrThenable === "boolean" + ? booleanOrThenable // This will suspend until the async action scope has finished. + : useThenable(booleanOrThenable); return [isPending, start]; } function rerenderTransition() { var _rerenderState = rerenderState(), - isPending = _rerenderState[0]; + booleanOrThenable = _rerenderState[0]; var hook = updateWorkInProgressHook(); var start = hook.memoizedState; + var isPending = + typeof booleanOrThenable === "boolean" + ? booleanOrThenable // This will suspend until the async action scope has finished. + : useThenable(booleanOrThenable); return [isPending, start]; } @@ -9211,8 +9717,7 @@ function refreshCache(fiber, seedKey, seedValue) { var root = enqueueUpdate(provider, refreshUpdate, lane); if (root !== null) { - var eventTime = requestEventTime(); - scheduleUpdateOnFiber(root, provider, lane, eventTime); + scheduleUpdateOnFiber(root, provider, lane); entangleTransitions(root, provider, lane); } // TODO: If a refresh never commits, the new cache created here must be // released. A simple case is start refreshing a cache boundary, but then @@ -9266,8 +9771,7 @@ function dispatchReducerAction(fiber, queue, action) { var root = enqueueConcurrentHookUpdate(fiber, queue, update, lane); if (root !== null) { - var eventTime = requestEventTime(); - scheduleUpdateOnFiber(root, fiber, lane, eventTime); + scheduleUpdateOnFiber(root, fiber, lane); entangleTransitionUpdate(root, queue, lane); } } @@ -9350,8 +9854,7 @@ function dispatchSetState(fiber, queue, action) { var root = enqueueConcurrentHookUpdate(fiber, queue, update, lane); if (root !== null) { - var eventTime = requestEventTime(); - scheduleUpdateOnFiber(root, fiber, lane, eventTime); + scheduleUpdateOnFiber(root, fiber, lane); entangleTransitionUpdate(root, queue, lane); } } @@ -9422,6 +9925,7 @@ function markUpdateInDevTools(fiber, lane, action) { var ContextOnlyDispatcher = { readContext: readContext, + use: use, useCallback: throwInvalidHookError, useContext: throwInvalidHookError, useEffect: throwInvalidHookError, @@ -9444,10 +9948,6 @@ var ContextOnlyDispatcher = { ContextOnlyDispatcher.useCacheRefresh = throwInvalidHookError; } -{ - ContextOnlyDispatcher.use = throwInvalidHookError; -} - { ContextOnlyDispatcher.useMemoCache = throwInvalidHookError; } @@ -9487,6 +9987,7 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; readContext: function (context) { return readContext(context); }, + use: use, useCallback: function (callback, deps) { currentHookNameInDev = "useCallback"; mountHookTypesDev(); @@ -9607,10 +10108,6 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; }; } - { - HooksDispatcherOnMountInDEV.use = use; - } - { HooksDispatcherOnMountInDEV.useMemoCache = useMemoCache; } @@ -9629,6 +10126,7 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; readContext: function (context) { return readContext(context); }, + use: use, useCallback: function (callback, deps) { currentHookNameInDev = "useCallback"; updateHookTypesDev(); @@ -9744,10 +10242,6 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; }; } - { - HooksDispatcherOnMountWithHookTypesInDEV.use = use; - } - { HooksDispatcherOnMountWithHookTypesInDEV.useMemoCache = useMemoCache; } @@ -9765,6 +10259,7 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; readContext: function (context) { return readContext(context); }, + use: use, useCallback: function (callback, deps) { currentHookNameInDev = "useCallback"; updateHookTypesDev(); @@ -9879,10 +10374,6 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; }; } - { - HooksDispatcherOnUpdateInDEV.use = use; - } - { HooksDispatcherOnUpdateInDEV.useMemoCache = useMemoCache; } @@ -9901,6 +10392,7 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; readContext: function (context) { return readContext(context); }, + use: use, useCallback: function (callback, deps) { currentHookNameInDev = "useCallback"; updateHookTypesDev(); @@ -10016,10 +10508,6 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; }; } - { - HooksDispatcherOnRerenderInDEV.use = use; - } - { HooksDispatcherOnRerenderInDEV.useMemoCache = useMemoCache; } @@ -10039,6 +10527,10 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; warnInvalidContextAccess(); return readContext(context); }, + use: function (usable) { + warnInvalidHookAccess(); + return use(usable); + }, useCallback: function (callback, deps) { currentHookNameInDev = "useCallback"; warnInvalidHookAccess(); @@ -10170,13 +10662,6 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; }; } - { - InvalidNestedHooksDispatcherOnMountInDEV.use = function (usable) { - warnInvalidHookAccess(); - return use(usable); - }; - } - { InvalidNestedHooksDispatcherOnMountInDEV.useMemoCache = function (size) { warnInvalidHookAccess(); @@ -10199,6 +10684,10 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; warnInvalidContextAccess(); return readContext(context); }, + use: function (usable) { + warnInvalidHookAccess(); + return use(usable); + }, useCallback: function (callback, deps) { currentHookNameInDev = "useCallback"; warnInvalidHookAccess(); @@ -10330,13 +10819,6 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; }; } - { - InvalidNestedHooksDispatcherOnUpdateInDEV.use = function (usable) { - warnInvalidHookAccess(); - return use(usable); - }; - } - { InvalidNestedHooksDispatcherOnUpdateInDEV.useMemoCache = function (size) { warnInvalidHookAccess(); @@ -10359,6 +10841,10 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; warnInvalidContextAccess(); return readContext(context); }, + use: function (usable) { + warnInvalidHookAccess(); + return use(usable); + }, useCallback: function (callback, deps) { currentHookNameInDev = "useCallback"; warnInvalidHookAccess(); @@ -10490,13 +10976,6 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; }; } - { - InvalidNestedHooksDispatcherOnRerenderInDEV.use = function (usable) { - warnInvalidHookAccess(); - return use(usable); - }; - } - { InvalidNestedHooksDispatcherOnRerenderInDEV.useMemoCache = function (size) { warnInvalidHookAccess(); @@ -10836,8 +11315,7 @@ var classComponentUpdater = { var root = enqueueUpdate(fiber, update, lane); if (root !== null) { - var eventTime = requestEventTime(); - scheduleUpdateOnFiber(root, fiber, lane, eventTime); + scheduleUpdateOnFiber(root, fiber, lane); entangleTransitions(root, fiber, lane); } @@ -10872,8 +11350,7 @@ var classComponentUpdater = { var root = enqueueUpdate(fiber, update, lane); if (root !== null) { - var eventTime = requestEventTime(); - scheduleUpdateOnFiber(root, fiber, lane, eventTime); + scheduleUpdateOnFiber(root, fiber, lane); entangleTransitions(root, fiber, lane); } @@ -10908,8 +11385,7 @@ var classComponentUpdater = { var root = enqueueUpdate(fiber, update, lane); if (root !== null) { - var eventTime = requestEventTime(); - scheduleUpdateOnFiber(root, fiber, lane, eventTime); + scheduleUpdateOnFiber(root, fiber, lane); entangleTransitions(root, fiber, lane); } @@ -14799,16 +15275,9 @@ function updateDehydratedSuspenseComponent( // 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; + suspenseState.retryLane = attemptHydrationAtLane; enqueueConcurrentRenderForLane(current, attemptHydrationAtLane); - scheduleUpdateOnFiber( - root, - current, - attemptHydrationAtLane, - eventTime - ); // Throw a special object that signals to the work loop that it should + scheduleUpdateOnFiber(root, current, attemptHydrationAtLane); // Throw a special object that signals to the work loop that it should // interrupt the current render. // // Because we're inside a React-only execution stack, we don't @@ -16807,7 +17276,7 @@ var AbortControllerLocal = }; // Intentionally not named imports because Rollup would // use dynamic dispatch for CommonJS interop named imports. -var scheduleCallback$2 = Scheduler.unstable_scheduleCallback, +var scheduleCallback$1 = Scheduler.unstable_scheduleCallback, NormalPriority = Scheduler.unstable_NormalPriority; var CacheContext = { $$typeof: REACT_CONTEXT_TYPE, @@ -16863,7 +17332,7 @@ function releaseCache(cache) { } if (cache.refCount === 0) { - scheduleCallback$2(NormalPriority, function () { + scheduleCallback$1(NormalPriority, function () { cache.controller.abort(); }); } @@ -20659,7 +21128,7 @@ function detachOffscreenInstance(instance) { if (root !== null) { instance._pendingVisibility |= OffscreenDetached; - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + scheduleUpdateOnFiber(root, fiber, SyncLane); } } function attachOffscreenInstance(instance) { @@ -20680,7 +21149,7 @@ function attachOffscreenInstance(instance) { if (root !== null) { instance._pendingVisibility &= ~OffscreenDetached; - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + scheduleUpdateOnFiber(root, fiber, SyncLane); } } @@ -22750,7 +23219,7 @@ if (typeof Symbol === "function" && Symbol.for) { symbolFor("selector.text"); } -var ReactCurrentActQueue$2 = ReactSharedInternals.ReactCurrentActQueue; +var ReactCurrentActQueue$1 = ReactSharedInternals.ReactCurrentActQueue; function isLegacyActEnvironment(fiber) { { // Legacy mode. We preserve the behavior of React 17's act. It assumes an @@ -22773,7 +23242,7 @@ function isConcurrentActEnvironment() { if ( !isReactActEnvironmentGlobal && - ReactCurrentActQueue$2.current !== null + ReactCurrentActQueue$1.current !== null ) { // TODO: Include link to relevant documentation page. error( @@ -22786,384 +23255,6 @@ function isConcurrentActEnvironment() { } } -var ReactCurrentActQueue$1 = ReactSharedInternals.ReactCurrentActQueue; // A linked list of all the roots with pending work. In an idiomatic app, -// there's only a single root, but we do support multi root apps, hence this -// extra complexity. But this module is optimized for the single root case. - -var firstScheduledRoot = null; -var lastScheduledRoot = null; // Used to prevent redundant mircotasks from being scheduled. - -var didScheduleMicrotask = false; // `act` "microtasks" are scheduled on the `act` queue instead of an actual -// microtask, so we have to dedupe those separately. This wouldn't be an issue -// if we required all `act` calls to be awaited, which we might in the future. - -var didScheduleMicrotask_act = false; // Used to quickly bail out of flushSync if there's no sync work to do. - -var mightHavePendingSyncWork = false; -var isFlushingWork = false; -function ensureRootIsScheduled(root) { - // This function is called whenever a root receives an update. It does two - // things 1) it ensures the root is in the root schedule, and 2) it ensures - // there's a pending microtask to process the root schedule. - // - // Most of the actual scheduling logic does not happen until - // `scheduleTaskForRootDuringMicrotask` runs. - // Add the root to the schedule - if (root === lastScheduledRoot || root.next !== null); - else { - if (lastScheduledRoot === null) { - firstScheduledRoot = lastScheduledRoot = root; - } else { - lastScheduledRoot.next = root; - lastScheduledRoot = root; - } - } // Any time a root received an update, we set this to true until the next time - // we process the schedule. If it's false, then we can quickly exit flushSync - // without consulting the schedule. - - mightHavePendingSyncWork = true; // At the end of the current event, go through each of the roots and ensure - // there's a task scheduled for each one at the correct priority. - - if (ReactCurrentActQueue$1.current !== null) { - // We're inside an `act` scope. - if (!didScheduleMicrotask_act) { - didScheduleMicrotask_act = true; - scheduleImmediateTask(processRootScheduleInMicrotask); - } - } else { - if (!didScheduleMicrotask) { - didScheduleMicrotask = true; - scheduleImmediateTask(processRootScheduleInMicrotask); - } - } - - if (!enableDeferRootSchedulingToMicrotask) { - // While this flag is disabled, we schedule the render task immediately - // instead of waiting a microtask. - // TODO: We need to land enableDeferRootSchedulingToMicrotask ASAP to - // unblock additional features we have planned. - scheduleTaskForRootDuringMicrotask(root, now$1()); - } - - if (ReactCurrentActQueue$1.isBatchingLegacy && root.tag === LegacyRoot) { - // Special `act` case: Record whenever a legacy update is scheduled. - ReactCurrentActQueue$1.didScheduleLegacyUpdate = true; - } -} -function flushSyncWorkOnAllRoots() { - // This is allowed to be called synchronously, but the caller should check - // the execution context first. - flushSyncWorkAcrossRoots_impl(false); -} -function flushSyncWorkOnLegacyRootsOnly() { - // This is allowed to be called synchronously, but the caller should check - // the execution context first. - flushSyncWorkAcrossRoots_impl(true); -} - -function flushSyncWorkAcrossRoots_impl(onlyLegacy) { - if (isFlushingWork) { - // Prevent reentrancy. - // TODO: Is this overly defensive? The callers must check the execution - // context first regardless. - return; - } - - if (!mightHavePendingSyncWork) { - // Fast path. There's no sync work to do. - return; - } - - var workInProgressRoot = getWorkInProgressRoot(); - var workInProgressRootRenderLanes = getWorkInProgressRootRenderLanes(); // There may or may not be synchronous work scheduled. Let's check. - - var didPerformSomeWork; - var errors = null; - isFlushingWork = true; - - do { - didPerformSomeWork = false; - var root = firstScheduledRoot; - - while (root !== null) { - if (onlyLegacy && root.tag !== LegacyRoot); - else { - var nextLanes = getNextLanes( - root, - root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes - ); - - if (includesSyncLane(nextLanes)) { - // This root has pending sync work. Flush it now. - try { - // TODO: Pass nextLanes as an argument instead of computing it again - // inside performSyncWorkOnRoot. - didPerformSomeWork = true; - performSyncWorkOnRoot(root); - } catch (error) { - // Collect errors so we can rethrow them at the end - if (errors === null) { - errors = [error]; - } else { - errors.push(error); - } - } - } - } - - root = root.next; - } - } while (didPerformSomeWork); - - isFlushingWork = false; // If any errors were thrown, rethrow them right before exiting. - // TODO: Consider returning these to the caller, to allow them to decide - // how/when to rethrow. - - if (errors !== null) { - if (errors.length > 1) { - if (typeof AggregateError === "function") { - // eslint-disable-next-line no-undef - throw new AggregateError(errors); - } else { - for (var i = 1; i < errors.length; i++) { - scheduleImmediateTask(throwError.bind(null, errors[i])); - } - - var firstError = errors[0]; - throw firstError; - } - } else { - var error = errors[0]; - throw error; - } - } -} - -function throwError(error) { - throw error; -} - -function processRootScheduleInMicrotask() { - // This function is always called inside a microtask. It should never be - // called synchronously. - didScheduleMicrotask = false; - - { - didScheduleMicrotask_act = false; - } // We'll recompute this as we iterate through all the roots and schedule them. - - mightHavePendingSyncWork = false; - var currentTime = now$1(); - var prev = null; - var root = firstScheduledRoot; - - while (root !== null) { - var next = root.next; - var nextLanes = scheduleTaskForRootDuringMicrotask(root, currentTime); - - if (nextLanes === NoLane) { - // This root has no more pending work. Remove it from the schedule. To - // guard against subtle reentrancy bugs, this microtask is the only place - // we do this — you can add roots to the schedule whenever, but you can - // only remove them here. - // Null this out so we know it's been removed from the schedule. - root.next = null; - - if (prev === null) { - // This is the new head of the list - firstScheduledRoot = next; - } else { - prev.next = next; - } - - if (next === null) { - // This is the new tail of the list - lastScheduledRoot = prev; - } - } else { - // This root still has work. Keep it in the list. - prev = root; - - if (includesSyncLane(nextLanes)) { - mightHavePendingSyncWork = true; - } - } - - root = next; - } // At the end of the microtask, flush any pending synchronous work. This has - // to come at the end, because it does actual rendering work that might throw. - - flushSyncWorkOnAllRoots(); -} - -function scheduleTaskForRootDuringMicrotask(root, currentTime) { - // This function is always called inside a microtask, or at the very end of a - // rendering task right before we yield to the main thread. It should never be - // called synchronously. - // - // TODO: Unless enableDeferRootSchedulingToMicrotask is off. We need to land - // that ASAP to unblock additional features we have planned. - // - // This function also never performs React work synchronously; it should - // only schedule work to be performed later, in a separate task or microtask. - // Check if any lanes are being starved by other work. If so, mark them as - // expired so we know to work on those next. - markStarvedLanesAsExpired(root, currentTime); // Determine the next lanes to work on, and their priority. - - var workInProgressRoot = getWorkInProgressRoot(); - var workInProgressRootRenderLanes = getWorkInProgressRootRenderLanes(); - var nextLanes = getNextLanes( - root, - root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes - ); - var existingCallbackNode = root.callbackNode; - - if ( - // Check if there's nothing to work on - nextLanes === NoLanes || // If this root is currently suspended and waiting for data to resolve, don't - // schedule a task to render it. We'll either wait for a ping, or wait to - // receive an update. - // - // Suspended render phase - (root === workInProgressRoot && isWorkLoopSuspendedOnData()) || // Suspended commit phase - root.cancelPendingCommit !== null - ) { - // Fast path: There's nothing to work on. - if (existingCallbackNode !== null) { - cancelCallback(existingCallbackNode); - } - - root.callbackNode = null; - root.callbackPriority = NoLane; - return NoLane; - } // Schedule a new callback in the host environment. - - if (includesSyncLane(nextLanes)) { - // Synchronous work is always flushed at the end of the microtask, so we - // don't need to schedule an additional task. - if (existingCallbackNode !== null) { - cancelCallback(existingCallbackNode); - } - - root.callbackPriority = SyncLane; - root.callbackNode = null; - return SyncLane; - } else { - // We use the highest priority lane to represent the priority of the callback. - var existingCallbackPriority = root.callbackPriority; - var newCallbackPriority = getHighestPriorityLane(nextLanes); - - if ( - newCallbackPriority === existingCallbackPriority && // Special case related to `act`. If the currently scheduled task is a - // Scheduler task, rather than an `act` task, cancel it and re-schedule - // on the `act` queue. - !( - ReactCurrentActQueue$1.current !== null && - existingCallbackNode !== fakeActCallbackNode$1 - ) - ) { - // The priority hasn't changed. We can reuse the existing task. - return newCallbackPriority; - } else { - // Cancel the existing callback. We'll schedule a new one below. - cancelCallback(existingCallbackNode); - } - - var schedulerPriorityLevel; - - switch (lanesToEventPriority(nextLanes)) { - case DiscreteEventPriority: - schedulerPriorityLevel = ImmediatePriority; - break; - - case ContinuousEventPriority: - schedulerPriorityLevel = UserBlockingPriority; - break; - - case DefaultEventPriority: - schedulerPriorityLevel = NormalPriority$1; - break; - - case IdleEventPriority: - schedulerPriorityLevel = IdlePriority; - break; - - default: - schedulerPriorityLevel = NormalPriority$1; - break; - } - - var newCallbackNode = scheduleCallback$1( - schedulerPriorityLevel, - performConcurrentWorkOnRoot.bind(null, root) - ); - root.callbackPriority = newCallbackPriority; - root.callbackNode = newCallbackNode; - return newCallbackPriority; - } -} - -function getContinuationForRoot(root, originalCallbackNode) { - // This is called at the end of `performConcurrentWorkOnRoot` to determine - // if we need to schedule a continuation task. - // - // Usually `scheduleTaskForRootDuringMicrotask` only runs inside a microtask; - // however, since most of the logic for determining if we need a continuation - // versus a new task is the same, we cheat a bit and call it here. This is - // only safe to do because we know we're at the end of the browser task. - // So although it's not an actual microtask, it might as well be. - scheduleTaskForRootDuringMicrotask(root, now$1()); - - if (root.callbackNode === originalCallbackNode) { - // The task node scheduled for this root is the same one that's - // currently executed. Need to return a continuation. - return performConcurrentWorkOnRoot.bind(null, root); - } - - return null; -} -var fakeActCallbackNode$1 = {}; - -function scheduleCallback$1(priorityLevel, callback) { - if (ReactCurrentActQueue$1.current !== null) { - // Special case: We're inside an `act` scope (a testing utility). - // Instead of scheduling work in the host environment, add it to a - // fake internal queue that's managed by the `act` implementation. - ReactCurrentActQueue$1.current.push(callback); - return fakeActCallbackNode$1; - } else { - return scheduleCallback$3(priorityLevel, callback); - } -} - -function cancelCallback(callbackNode) { - if (callbackNode === fakeActCallbackNode$1); - else if (callbackNode !== null) { - cancelCallback$1(callbackNode); - } -} - -function scheduleImmediateTask(cb) { - if (ReactCurrentActQueue$1.current !== null) { - // Special case: Inside an `act` scope, we push microtasks to the fake `act` - // callback queue. This is because we currently support calling `act` - // without awaiting the result. The plan is to deprecate that, and require - // that you always await the result so that the microtasks have a chance to - // run. But it hasn't happened yet. - ReactCurrentActQueue$1.current.push(function () { - cb(); - return null; - }); - } // TODO: Can we land supportsMicrotasks? Which environments don't support it? - // Alternatively, can we move this check to the host config? - - { - // If microtasks are not supported, use Scheduler. - scheduleCallback$3(ImmediatePriority, cb); - } -} - -var ceil = Math.ceil; var PossiblyWeakMap = typeof WeakMap === "function" ? WeakMap : Map; var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher, ReactCurrentCache = ReactSharedInternals.ReactCurrentCache, @@ -23428,12 +23519,7 @@ var isFlushingPassiveEffects = false; var didScheduleUpdateDuringPassiveEffects = false; var NESTED_PASSIVE_UPDATE_LIMIT = 50; var nestedPassiveUpdateCount = 0; -var rootWithPassiveNestedUpdates = null; // If two updates are scheduled within the same event, we should treat their -// event times as simultaneous, even if the actual clock time has advanced -// between the first and second call. - -var currentEventTime = NoTimestamp; -var currentEventTransitionLane = NoLanes; +var rootWithPassiveNestedUpdates = null; var isRunningInsertionEffect = false; function getWorkInProgressRoot() { return workInProgressRoot; @@ -23444,20 +23530,6 @@ function getWorkInProgressRootRenderLanes() { function isWorkLoopSuspendedOnData() { return workInProgressSuspendedReason === SuspendedOnData; } -function requestEventTime() { - if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { - // We're inside React, so it's fine to read the actual time. - return now$1(); - } // We're not inside React, so we may be in the middle of a browser event. - - if (currentEventTime !== NoTimestamp) { - // Use the same start time for all updates until we enter React again. - return currentEventTime; - } // This is the first update since React yielded. Compute a new start time. - - currentEventTime = now$1(); - return currentEventTime; -} function requestUpdateLane(fiber) { // Special cases var mode = fiber.mode; @@ -23491,20 +23563,14 @@ function requestUpdateLane(fiber) { } transition._updatedFibers.add(fiber); - } // The algorithm for assigning an update to a lane should be stable for all - // updates at the same priority within the same event. To do this, the - // inputs to the algorithm must be the same. - // - // The trick we use is to cache the first of each of these inputs within an - // event. Then reset the cached values once we can be sure the event is - // over. Our heuristic for that is whenever we enter a concurrent work loop. - - if (currentEventTransitionLane === NoLane) { - // All transitions within the same event are assigned the same lane. - currentEventTransitionLane = claimNextTransitionLane(); } - return currentEventTransitionLane; + var asyncAction = peekAsyncActionContext(); + return asyncAction !== null // We're inside an async action scope. Reuse the same lane. + ? asyncAction.lane // We may or may not be inside an async action scope. If we are, this + : // is the first update in that scope. Either way, we need to get a + // fresh transition lane. + requestTransitionLane(); } // Updates originating inside certain React methods, like flushSync, have // their priority set by tracking it with a context variable. // @@ -23541,7 +23607,7 @@ function requestRetryLane(fiber) { return claimNextRetryLane(); } -function scheduleUpdateOnFiber(root, fiber, lane, eventTime) { +function scheduleUpdateOnFiber(root, fiber, lane) { { if (isRunningInsertionEffect) { error("useInsertionEffect must not schedule updates."); @@ -23567,7 +23633,7 @@ function scheduleUpdateOnFiber(root, fiber, lane, eventTime) { markRootSuspended(root, workInProgressRootRenderLanes); } // Mark that the root has a pending update. - markRootUpdated(root, lane, eventTime); + markRootUpdated(root, lane); if ( (executionContext & RenderContext) !== NoLanes && @@ -23679,11 +23745,7 @@ function isUnsafeClassRenderPhaseUpdate(fiber) { function performConcurrentWorkOnRoot(root, didTimeout) { { resetNestedUpdateFlag(); - } // Since we know we're in a React event, we can clear the current - // event time. The next update will compute a new event time. - - currentEventTime = NoTimestamp; - currentEventTransitionLane = NoLanes; + } if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { throw new Error("Should not already be working."); @@ -23909,133 +23971,30 @@ function queueRecoverableErrors(errors) { } function finishConcurrentRender(root, exitStatus, finishedWork, lanes) { + // TODO: The fact that most of these branches are identical suggests that some + // of the exit statuses are not best modeled as exit statuses and should be + // tracked orthogonally. switch (exitStatus) { case RootInProgress: case RootFatalErrored: { throw new Error("Root did not complete. This is a bug in React."); } - case RootErrored: { - // We should have already attempted to retry this tree. If we reached - // this point, it errored again. Commit it. - commitRootWhenReady( - root, - finishedWork, - workInProgressRootRecoverableErrors, - workInProgressTransitions, - lanes - ); - break; - } - - case RootSuspended: { - markRootSuspended(root, lanes); // We have an acceptable loading state. We need to figure out if we - // should immediately commit it or wait a bit. - - if ( - includesOnlyRetries(lanes) && // do not delay if we're inside an act() scope - !shouldForceFlushFallbacksInDEV() - ) { - // This render only included retries, no updates. Throttle committing - // retries so that we don't show too many loading states too quickly. - var msUntilTimeout = - globalMostRecentFallbackTime + FALLBACK_THROTTLE_MS - now$1(); // Don't bother with a very short suspense time. - - if (msUntilTimeout > 10) { - var nextLanes = getNextLanes(root, NoLanes); - - if (nextLanes !== NoLanes) { - // There's additional work on this root. - break; - } // The render is suspended, it hasn't timed out, and there's no - // lower priority work to do. Instead of committing the fallback - // immediately, wait for more data to arrive. - - root.timeoutHandle = scheduleTimeout( - commitRootWhenReady.bind( - null, - root, - finishedWork, - workInProgressRootRecoverableErrors, - workInProgressTransitions, - lanes - ), - msUntilTimeout - ); - break; - } - } // The work expired. Commit immediately. - - commitRootWhenReady( - root, - finishedWork, - workInProgressRootRecoverableErrors, - workInProgressTransitions, - lanes - ); - break; - } - case RootSuspendedWithDelay: { - markRootSuspended(root, lanes); - if (includesOnlyTransitions(lanes)) { // This is a transition, so we should exit without committing a // placeholder and without scheduling a timeout. Delay indefinitely // until we receive more data. - break; - } - - if (!shouldForceFlushFallbacksInDEV()) { - // This is not a transition, but we did trigger an avoided state. - // Schedule a placeholder to display after a short delay, using the Just - // Noticeable Difference. - // TODO: Is the JND optimization worth the added complexity? If this is - // the only reason we track the event time, then probably not. - // Consider removing. - var mostRecentEventTime = getMostRecentEventTime(root, lanes); - var eventTimeMs = mostRecentEventTime; - var timeElapsedMs = now$1() - eventTimeMs; - - var _msUntilTimeout = jnd(timeElapsedMs) - timeElapsedMs; // Don't bother with a very short suspense time. - - if (_msUntilTimeout > 10) { - // Instead of committing the fallback immediately, wait for more data - // to arrive. - root.timeoutHandle = scheduleTimeout( - commitRootWhenReady.bind( - null, - root, - finishedWork, - workInProgressRootRecoverableErrors, - workInProgressTransitions, - lanes - ), - _msUntilTimeout - ); - break; - } + markRootSuspended(root, lanes); + return; } // Commit the placeholder. - commitRootWhenReady( - root, - finishedWork, - workInProgressRootRecoverableErrors, - workInProgressTransitions, - lanes - ); break; } + case RootErrored: + case RootSuspended: case RootCompleted: { - // The work completed. - commitRootWhenReady( - root, - finishedWork, - workInProgressRootRecoverableErrors, - workInProgressTransitions, - lanes - ); break; } @@ -24043,6 +24002,61 @@ function finishConcurrentRender(root, exitStatus, finishedWork, lanes) { throw new Error("Unknown root exit status."); } } + + if (shouldForceFlushFallbacksInDEV()) { + // We're inside an `act` scope. Commit immediately. + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); + } else { + if ( + includesOnlyRetries(lanes) && + (alwaysThrottleRetries || exitStatus === RootSuspended) + ) { + // This render only included retries, no updates. Throttle committing + // retries so that we don't show too many loading states too quickly. + var msUntilTimeout = + globalMostRecentFallbackTime + FALLBACK_THROTTLE_MS - now$1(); // Don't bother with a very short suspense time. + + if (msUntilTimeout > 10) { + markRootSuspended(root, lanes); + var nextLanes = getNextLanes(root, NoLanes); + + if (nextLanes !== NoLanes) { + // There's additional work we can do on this root. We might as well + // attempt to work on that while we're suspended. + return; + } // The render is suspended, it hasn't timed out, and there's no + // lower priority work to do. Instead of committing the fallback + // immediately, wait for more data to arrive. + // TODO: Combine retry throttling with Suspensey commits. Right now they + // run one after the other. + + root.timeoutHandle = scheduleTimeout( + commitRootWhenReady.bind( + null, + root, + finishedWork, + workInProgressRootRecoverableErrors, + workInProgressTransitions, + lanes + ), + msUntilTimeout + ); + return; + } + } + + commitRootWhenReady( + root, + finishedWork, + workInProgressRootRecoverableErrors, + workInProgressTransitions, + lanes + ); + } } function commitRootWhenReady( @@ -24052,6 +24066,8 @@ function commitRootWhenReady( transitions, lanes ) { + // TODO: Combine retry throttling with Suspensey commits. Right now they run + // one after the other. if (includesOnlyNonUrgentLanes(lanes)) { // the suspensey resources. The renderer is responsible for accumulating // all the load events. This all happens in a single synchronous @@ -24071,22 +24087,14 @@ function commitRootWhenReady( // us that it's ready. This will be canceled if we start work on the // root again. root.cancelPendingCommit = schedulePendingCommit( - commitRoot.bind( - null, - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ) + commitRoot.bind(null, root, recoverableErrors, transitions) ); + markRootSuspended(root, lanes); return; } } // Otherwise, commit immediately. - commitRoot( - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ); + commitRoot(root, recoverableErrors, transitions); } function isRenderConsistentWithExternalStores(finishedWork) { @@ -25118,6 +25126,16 @@ function replaySuspendedUnitOfWork(unitOfWork) { break; } + case HostComponent: { + // Some host components are stateful (that's how we implement form + // actions) but we don't bother to reuse the memoized state because it's + // not worth the extra code. The main reason to reuse the previous hooks + // is to reuse uncached promises, but we happen to know that the only + // promises that a host component might suspend on are definitely cached + // because they are controlled by us. So don't bother. + resetHooksOnUnwind(); // Fallthrough to the next branch. + } + default: { // Other types besides function components are reset completely before // being replayed. Currently this only happens when a Usable type is @@ -25223,28 +25241,14 @@ function completeUnitOfWork(unitOfWork) { var completedWork = unitOfWork; do { - if (revertRemovalOfSiblingPrerendering) { + { if ((completedWork.flags & Incomplete) !== NoFlags$1) { - // This fiber did not complete, because one of its children did not - // complete. Switch to unwinding the stack instead of completing it. - // - // The reason "unwind" and "complete" is interleaved is because when - // something suspends, we continue rendering the siblings even though - // they will be replaced by a fallback. - // TODO: Disable sibling prerendering, then remove this branch. - unwindUnitOfWork(completedWork); - return; - } - } else { - { - if ((completedWork.flags & Incomplete) !== NoFlags$1) { - // NOTE: If we re-enable sibling prerendering in some cases, this branch - // is where we would switch to the unwinding path. - error( - "Internal React error: Expected this fiber to be complete, but " + - "it isn't. It should have been unwound. This is a bug in React." - ); - } + // NOTE: If we re-enable sibling prerendering in some cases, this branch + // is where we would switch to the unwinding path. + error( + "Internal React error: Expected this fiber to be complete, but " + + "it isn't. It should have been unwound. This is a bug in React." + ); } } // The current, flushed, state of this fiber is the alternate. Ideally // nothing should rely on this, but relying on it here means that we don't @@ -25343,23 +25347,10 @@ function unwindUnitOfWork(unitOfWork) { returnFiber.flags |= Incomplete; returnFiber.subtreeFlags = NoFlags$1; returnFiber.deletions = null; - } - - if (revertRemovalOfSiblingPrerendering) { - // If there are siblings, work on them now even though they're going to be - // replaced by a fallback. We're "prerendering" them. Historically our - // rationale for this behavior has been to initiate any lazy data requests - // in the siblings, and also to warm up the CPU cache. - // TODO: Don't prerender siblings. With `use`, we suspend the work loop - // until the data has resolved, anyway. - var siblingFiber = incompleteWork.sibling; - - if (siblingFiber !== null) { - // This branch will return us to the normal work loop. - workInProgress = siblingFiber; - return; - } - } // Otherwise, return to the parent + } // NOTE: If we re-enable sibling prerendering in some cases, here we + // would switch to the normal completion path: check if a sibling + // exists, and if so, begin work on it. + // Otherwise, return to the parent // $FlowFixMe[incompatible-type] we bail out when we get a null incompleteWork = returnFiber; // Update the next thing we're working on in case something throws. @@ -25956,10 +25947,9 @@ function captureCommitPhaseErrorOnRoot(rootFiber, sourceFiber, error) { var errorInfo = createCapturedValueAtFiber(error, sourceFiber); var update = createRootErrorUpdate(rootFiber, errorInfo, SyncLane); var root = enqueueUpdate(rootFiber, update, SyncLane); - var eventTime = requestEventTime(); if (root !== null) { - markRootUpdated(root, SyncLane, eventTime); + markRootUpdated(root, SyncLane); ensureRootIsScheduled(root); } } @@ -25995,10 +25985,9 @@ function captureCommitPhaseError(sourceFiber, nearestMountedAncestor, error$1) { var errorInfo = createCapturedValueAtFiber(error$1, sourceFiber); var update = createClassErrorUpdate(fiber, errorInfo, SyncLane); var root = enqueueUpdate(fiber, update, SyncLane); - var eventTime = requestEventTime(); if (root !== null) { - markRootUpdated(root, SyncLane, eventTime); + markRootUpdated(root, SyncLane); ensureRootIsScheduled(root); } @@ -26124,11 +26113,10 @@ function retryTimedOutBoundary(boundaryFiber, retryLane) { retryLane = requestRetryLane(boundaryFiber); } // TODO: Special case idle priority? - var eventTime = requestEventTime(); var root = enqueueConcurrentRenderForLane(boundaryFiber, retryLane); if (root !== null) { - markRootUpdated(root, retryLane, eventTime); + markRootUpdated(root, retryLane); ensureRootIsScheduled(root); } } @@ -26183,32 +26171,7 @@ function resolveRetryWakeable(boundaryFiber, wakeable) { } retryTimedOutBoundary(boundaryFiber, retryLane); -} // Computes the next Just Noticeable Difference (JND) boundary. -// The theory is that a person can't tell the difference between small differences in time. -// Therefore, if we wait a bit longer than necessary that won't translate to a noticeable -// difference in the experience. However, waiting for longer might mean that we can avoid -// showing an intermediate loading state. The longer we have already waited, the harder it -// is to tell small differences in time. Therefore, the longer we've already waited, -// the longer we can wait additionally. At some point we have to give up though. -// We pick a train model where the next boundary commits at a consistent schedule. -// These particular numbers are vague estimates. We expect to adjust them based on research. - -function jnd(timeElapsed) { - return timeElapsed < 120 - ? 120 - : timeElapsed < 480 - ? 480 - : timeElapsed < 1080 - ? 1080 - : timeElapsed < 1920 - ? 1920 - : timeElapsed < 3000 - ? 3000 - : timeElapsed < 4320 - ? 4320 - : ceil(timeElapsed / 1960) * 1960; } - function throwIfInfiniteUpdateLoopDetected() { if (nestedUpdateCount > NESTED_UPDATE_LIMIT) { nestedUpdateCount = 0; @@ -26889,7 +26852,7 @@ function scheduleFibersWithFamiliesRecursively( var root = enqueueConcurrentRenderForLane(fiber, SyncLane); if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + scheduleUpdateOnFiber(root, fiber, SyncLane); } } @@ -27783,7 +27746,6 @@ function FiberRootNode( this.next = null; this.callbackNode = null; this.callbackPriority = NoLane; - this.eventTimes = createLaneMap(NoLanes); this.expirationTimes = createLaneMap(NoTimestamp); this.pendingLanes = NoLanes; this.suspendedLanes = NoLanes; @@ -28021,8 +27983,7 @@ function updateContainer(element, container, parentComponent, callback) { var root = enqueueUpdate(current$1, update, lane); if (root !== null) { - var eventTime = requestEventTime(); - scheduleUpdateOnFiber(root, current$1, lane, eventTime); + scheduleUpdateOnFiber(root, current$1, lane); entangleTransitions(root, current$1, lane); } @@ -28170,7 +28131,7 @@ var setSuspenseHandler = null; var root = enqueueConcurrentRenderForLane(fiber, SyncLane); if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + scheduleUpdateOnFiber(root, fiber, SyncLane); } } }; @@ -28191,7 +28152,7 @@ var setSuspenseHandler = null; var root = enqueueConcurrentRenderForLane(fiber, SyncLane); if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + scheduleUpdateOnFiber(root, fiber, SyncLane); } } }; @@ -28212,7 +28173,7 @@ var setSuspenseHandler = null; var root = enqueueConcurrentRenderForLane(fiber, SyncLane); if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + scheduleUpdateOnFiber(root, fiber, SyncLane); } } }; // Support DevTools props for function components, forwardRef, memo, host components, etc. @@ -28227,7 +28188,7 @@ var setSuspenseHandler = null; var root = enqueueConcurrentRenderForLane(fiber, SyncLane); if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + scheduleUpdateOnFiber(root, fiber, SyncLane); } }; @@ -28241,7 +28202,7 @@ var setSuspenseHandler = null; var root = enqueueConcurrentRenderForLane(fiber, SyncLane); if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + scheduleUpdateOnFiber(root, fiber, SyncLane); } }; @@ -28255,7 +28216,7 @@ var setSuspenseHandler = null; var root = enqueueConcurrentRenderForLane(fiber, SyncLane); if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + scheduleUpdateOnFiber(root, fiber, SyncLane); } }; @@ -28263,7 +28224,7 @@ var setSuspenseHandler = null; var root = enqueueConcurrentRenderForLane(fiber, SyncLane); if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + scheduleUpdateOnFiber(root, fiber, SyncLane); } }; diff --git a/compiled/facebook-www/ReactART-prod.classic.js b/compiled/facebook-www/ReactART-prod.classic.js index f18111ccc9..173c933916 100644 --- a/compiled/facebook-www/ReactART-prod.classic.js +++ b/compiled/facebook-www/ReactART-prod.classic.js @@ -63,8 +63,6 @@ function formatProdErrorMessage(code) { var ReactSharedInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, dynamicFeatureFlags = require("ReactFeatureFlags"), - revertRemovalOfSiblingPrerendering = - dynamicFeatureFlags.revertRemovalOfSiblingPrerendering, enableDebugTracing = dynamicFeatureFlags.enableDebugTracing, enableUseRefAccessWarning = dynamicFeatureFlags.enableUseRefAccessWarning, enableLazyContextPropagation = @@ -74,6 +72,8 @@ var ReactSharedInternals = enableDeferRootSchedulingToMicrotask = dynamicFeatureFlags.enableDeferRootSchedulingToMicrotask, diffInCommitPhase = dynamicFeatureFlags.diffInCommitPhase, + enableAsyncActions = dynamicFeatureFlags.enableAsyncActions, + alwaysThrottleRetries = dynamicFeatureFlags.alwaysThrottleRetries, REACT_ELEMENT_TYPE = Symbol.for("react.element"), REACT_PORTAL_TYPE = Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"), @@ -554,13 +554,10 @@ function createLaneMap(initial) { for (var laneMap = [], i = 0; 31 > i; i++) laneMap.push(initial); return laneMap; } -function markRootUpdated(root, updateLane, eventTime) { +function markRootUpdated(root, updateLane) { root.pendingLanes |= updateLane; 536870912 !== updateLane && ((root.suspendedLanes = 0), (root.pingedLanes = 0)); - root = root.eventTimes; - updateLane = 31 - clz32(updateLane); - root[updateLane] = eventTime; } function markRootFinished(root, remainingLanes) { var noLongerPendingLanes = root.pendingLanes & ~remainingLanes; @@ -572,22 +569,20 @@ function markRootFinished(root, remainingLanes) { root.entangledLanes &= remainingLanes; root.errorRecoveryDisabledLanes &= remainingLanes; remainingLanes = root.entanglements; - var eventTimes = root.eventTimes, - expirationTimes = root.expirationTimes; + var expirationTimes = root.expirationTimes; for (root = root.hiddenUpdates; 0 < noLongerPendingLanes; ) { - var index$5 = 31 - clz32(noLongerPendingLanes), - lane = 1 << index$5; - remainingLanes[index$5] = 0; - eventTimes[index$5] = -1; - expirationTimes[index$5] = -1; - var hiddenUpdatesForLane = root[index$5]; + var index$4 = 31 - clz32(noLongerPendingLanes), + lane = 1 << index$4; + remainingLanes[index$4] = 0; + expirationTimes[index$4] = -1; + var hiddenUpdatesForLane = root[index$4]; if (null !== hiddenUpdatesForLane) for ( - root[index$5] = null, index$5 = 0; - index$5 < hiddenUpdatesForLane.length; - index$5++ + root[index$4] = null, index$4 = 0; + index$4 < hiddenUpdatesForLane.length; + index$4++ ) { - var update = hiddenUpdatesForLane[index$5]; + var update = hiddenUpdatesForLane[index$4]; null !== update && (update.lane &= -1073741825); } noLongerPendingLanes &= ~lane; @@ -596,21 +591,21 @@ function markRootFinished(root, remainingLanes) { function markRootEntangled(root, entangledLanes) { var rootEntangledLanes = (root.entangledLanes |= entangledLanes); for (root = root.entanglements; rootEntangledLanes; ) { - var index$6 = 31 - clz32(rootEntangledLanes), - lane = 1 << index$6; - (lane & entangledLanes) | (root[index$6] & entangledLanes) && - (root[index$6] |= entangledLanes); + var index$5 = 31 - clz32(rootEntangledLanes), + lane = 1 << index$5; + (lane & entangledLanes) | (root[index$5] & entangledLanes) && + (root[index$5] |= entangledLanes); rootEntangledLanes &= ~lane; } } function getTransitionsForLanes(root, lanes) { if (!enableTransitionTracing) return null; for (var transitionsForLanes = []; 0 < lanes; ) { - var index$8 = 31 - clz32(lanes), - lane = 1 << index$8; - index$8 = root.transitionLanes[index$8]; - null !== index$8 && - index$8.forEach(function (transition) { + var index$7 = 31 - clz32(lanes), + lane = 1 << index$7; + index$7 = root.transitionLanes[index$7]; + null !== index$7 && + index$7.forEach(function (transition) { transitionsForLanes.push(transition); }); lanes &= ~lane; @@ -620,10 +615,10 @@ function getTransitionsForLanes(root, lanes) { function clearTransitionsForLanes(root, lanes) { if (enableTransitionTracing) for (; 0 < lanes; ) { - var index$9 = 31 - clz32(lanes), - lane = 1 << index$9; - null !== root.transitionLanes[index$9] && - (root.transitionLanes[index$9] = null); + var index$8 = 31 - clz32(lanes), + lane = 1 << index$8; + null !== root.transitionLanes[index$8] && + (root.transitionLanes[index$8] = null); lanes &= ~lane; } } @@ -845,16 +840,16 @@ function describeNativeComponentFrame(fn, construct) { } else { try { construct.call(); - } catch (x$10) { - control = x$10; + } catch (x$9) { + control = x$9; } fn.call(construct.prototype); } else { try { throw Error(); - } catch (x$11) { - control = x$11; + } catch (x$10) { + control = x$10; } fn(); } @@ -2264,6 +2259,261 @@ function resetWorkInProgressVersions() { workInProgressSources[i]._workInProgressVersionSecondary = null; workInProgressSources.length = 0; } +var firstScheduledRoot = null, + lastScheduledRoot = null, + didScheduleMicrotask = !1, + mightHavePendingSyncWork = !1, + isFlushingWork = !1, + currentEventTransitionLane = 0; +function ensureRootIsScheduled(root) { + root !== lastScheduledRoot && + null === root.next && + (null === lastScheduledRoot + ? (firstScheduledRoot = lastScheduledRoot = root) + : (lastScheduledRoot = lastScheduledRoot.next = root)); + mightHavePendingSyncWork = !0; + didScheduleMicrotask || + ((didScheduleMicrotask = !0), + scheduleCallback$3(ImmediatePriority, processRootScheduleInMicrotask)); + enableDeferRootSchedulingToMicrotask || + scheduleTaskForRootDuringMicrotask(root, now()); +} +function flushSyncWorkAcrossRoots_impl(onlyLegacy) { + if (!isFlushingWork && mightHavePendingSyncWork) { + var workInProgressRoot$jscomp$0 = workInProgressRoot, + workInProgressRootRenderLanes$jscomp$0 = workInProgressRootRenderLanes, + errors = null; + isFlushingWork = !0; + do { + var didPerformSomeWork = !1; + for (var root = firstScheduledRoot; null !== root; ) { + if ( + (!onlyLegacy || 0 === root.tag) && + 0 !== + (getNextLanes( + root, + root === workInProgressRoot$jscomp$0 + ? workInProgressRootRenderLanes$jscomp$0 + : 0 + ) & + 3) + ) + try { + didPerformSomeWork = !0; + var root$jscomp$0 = root; + if (0 !== (executionContext & 6)) + throw Error(formatProdErrorMessage(327)); + flushPassiveEffects(); + var lanes = getNextLanes(root$jscomp$0, 0); + if (0 !== (lanes & 3)) { + var exitStatus = renderRootSync(root$jscomp$0, lanes); + if (0 !== root$jscomp$0.tag && 2 === exitStatus) { + var originallyAttemptedLanes = lanes, + errorRetryLanes = getLanesToRetrySynchronouslyOnError( + root$jscomp$0, + originallyAttemptedLanes + ); + 0 !== errorRetryLanes && + ((lanes = errorRetryLanes), + (exitStatus = recoverFromConcurrentError( + root$jscomp$0, + originallyAttemptedLanes, + errorRetryLanes + ))); + } + if (1 === exitStatus) + throw ( + ((originallyAttemptedLanes = workInProgressRootFatalError), + prepareFreshStack(root$jscomp$0, 0), + markRootSuspended(root$jscomp$0, lanes), + ensureRootIsScheduled(root$jscomp$0), + originallyAttemptedLanes) + ); + 6 === exitStatus + ? markRootSuspended(root$jscomp$0, lanes) + : ((root$jscomp$0.finishedWork = + root$jscomp$0.current.alternate), + (root$jscomp$0.finishedLanes = lanes), + commitRoot( + root$jscomp$0, + workInProgressRootRecoverableErrors, + workInProgressTransitions + )); + } + ensureRootIsScheduled(root$jscomp$0); + } catch (error) { + null === errors ? (errors = [error]) : errors.push(error); + } + root = root.next; + } + } while (didPerformSomeWork); + isFlushingWork = !1; + if (null !== errors) { + if (1 < errors.length) { + if ("function" === typeof AggregateError) + throw new AggregateError(errors); + for (onlyLegacy = 1; onlyLegacy < errors.length; onlyLegacy++) + (workInProgressRoot$jscomp$0 = throwError.bind( + null, + errors[onlyLegacy] + )), + scheduleCallback$3(ImmediatePriority, workInProgressRoot$jscomp$0); + } + throw errors[0]; + } + } +} +function throwError(error) { + throw error; +} +function processRootScheduleInMicrotask() { + mightHavePendingSyncWork = didScheduleMicrotask = !1; + for ( + var currentTime = now(), prev = null, root = firstScheduledRoot; + null !== root; + + ) { + var next = root.next, + nextLanes = scheduleTaskForRootDuringMicrotask(root, currentTime); + 0 === nextLanes + ? ((root.next = null), + null === prev ? (firstScheduledRoot = next) : (prev.next = next), + null === next && (lastScheduledRoot = prev)) + : ((prev = root), + 0 !== (nextLanes & 3) && (mightHavePendingSyncWork = !0)); + root = next; + } + currentEventTransitionLane = 0; + flushSyncWorkAcrossRoots_impl(!1); +} +function scheduleTaskForRootDuringMicrotask(root, currentTime) { + for ( + var suspendedLanes = root.suspendedLanes, + pingedLanes = root.pingedLanes, + expirationTimes = root.expirationTimes, + lanes = root.pendingLanes & -125829121; + 0 < lanes; + + ) { + var index$2 = 31 - clz32(lanes), + lane = 1 << index$2, + expirationTime = expirationTimes[index$2]; + if (-1 === expirationTime) { + if (0 === (lane & suspendedLanes) || 0 !== (lane & pingedLanes)) + expirationTimes[index$2] = computeExpirationTime(lane, currentTime); + } else expirationTime <= currentTime && (root.expiredLanes |= lane); + lanes &= ~lane; + } + currentTime = workInProgressRoot; + suspendedLanes = workInProgressRootRenderLanes; + suspendedLanes = getNextLanes( + root, + root === currentTime ? suspendedLanes : 0 + ); + pingedLanes = root.callbackNode; + if ( + 0 === suspendedLanes || + (root === currentTime && 2 === workInProgressSuspendedReason) || + null !== root.cancelPendingCommit + ) + return ( + null !== pingedLanes && + null !== pingedLanes && + cancelCallback$1(pingedLanes), + (root.callbackNode = null), + (root.callbackPriority = 0) + ); + if (0 !== (suspendedLanes & 3)) + return ( + null !== pingedLanes && + null !== pingedLanes && + cancelCallback$1(pingedLanes), + (root.callbackPriority = 2), + (root.callbackNode = null), + 2 + ); + currentTime = suspendedLanes & -suspendedLanes; + if (currentTime === root.callbackPriority) return currentTime; + null !== pingedLanes && cancelCallback$1(pingedLanes); + switch (lanesToEventPriority(suspendedLanes)) { + case 2: + suspendedLanes = ImmediatePriority; + break; + case 8: + suspendedLanes = UserBlockingPriority; + break; + case 32: + suspendedLanes = NormalPriority$1; + break; + case 536870912: + suspendedLanes = IdlePriority; + break; + default: + suspendedLanes = NormalPriority$1; + } + pingedLanes = performConcurrentWorkOnRoot.bind(null, root); + suspendedLanes = scheduleCallback$3(suspendedLanes, pingedLanes); + root.callbackPriority = currentTime; + root.callbackNode = suspendedLanes; + return currentTime; +} +function requestTransitionLane() { + 0 === currentEventTransitionLane && + (currentEventTransitionLane = claimNextTransitionLane()); + return currentEventTransitionLane; +} +var currentAsyncAction = null; +function requestAsyncActionContext(actionReturnValue) { + if ( + null !== actionReturnValue && + "object" === typeof actionReturnValue && + "function" === typeof actionReturnValue.then + ) { + if (null === currentAsyncAction) { + var asyncAction = { + lane: requestTransitionLane(), + listeners: [], + count: 0, + status: "pending", + value: !1, + reason: void 0, + then: function (resolve) { + asyncAction.listeners.push(resolve); + } + }; + attachPingListeners(actionReturnValue, asyncAction); + return (currentAsyncAction = asyncAction); + } + var asyncAction$28 = currentAsyncAction; + attachPingListeners(actionReturnValue, asyncAction$28); + return asyncAction$28; + } + return null === currentAsyncAction ? !1 : currentAsyncAction; +} +function attachPingListeners(thenable, asyncAction) { + asyncAction.count++; + thenable.then( + function () { + 0 === --asyncAction.count && + ((asyncAction.status = "fulfilled"), + completeAsyncActionScope(asyncAction)); + }, + function (error) { + 0 === --asyncAction.count && + ((asyncAction.status = "rejected"), + (asyncAction.reason = error), + completeAsyncActionScope(asyncAction)); + } + ); + return asyncAction; +} +function completeAsyncActionScope(action) { + currentAsyncAction === action && (currentAsyncAction = null); + var listeners = action.listeners; + action.listeners = []; + for (action = 0; action < listeners.length; action++) + (0, listeners[action])(!1); +} var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, ReactCurrentBatchConfig$2 = ReactSharedInternals.ReactCurrentBatchConfig, renderLanes$1 = 0, @@ -2418,20 +2668,21 @@ var createFunctionComponentUpdateQueue; createFunctionComponentUpdateQueue = function () { return { lastEffect: null, events: null, stores: null, memoCache: null }; }; +function useThenable(thenable) { + var index = thenableIndexCounter; + thenableIndexCounter += 1; + null === thenableState && (thenableState = []); + thenable = trackUsedThenable(thenableState, thenable, index); + null === currentlyRenderingFiber$1.alternate && + (null === workInProgressHook + ? null === currentlyRenderingFiber$1.memoizedState + : null === workInProgressHook.next) && + (ReactCurrentDispatcher$1.current = HooksDispatcherOnMount); + return thenable; +} function use(usable) { if (null !== usable && "object" === typeof usable) { - if ("function" === typeof usable.then) { - var index$28 = thenableIndexCounter; - thenableIndexCounter += 1; - null === thenableState && (thenableState = []); - usable = trackUsedThenable(thenableState, usable, index$28); - null === currentlyRenderingFiber$1.alternate && - (null === workInProgressHook - ? null === currentlyRenderingFiber$1.memoizedState - : null === workInProgressHook.next) && - (ReactCurrentDispatcher$1.current = HooksDispatcherOnMount); - return usable; - } + if ("function" === typeof usable.then) return useThenable(usable); if ( usable.$$typeof === REACT_CONTEXT_TYPE || usable.$$typeof === REACT_SERVER_CONTEXT_TYPE @@ -2728,7 +2979,7 @@ function checkIfSnapshotChanged(inst) { } function forceStoreRerender(fiber) { var root = enqueueConcurrentRenderForLane(fiber, 2); - null !== root && scheduleUpdateOnFiber(root, fiber, 2, -1); + null !== root && scheduleUpdateOnFiber(root, fiber, 2); } function mountState(initialState) { var hook = mountWorkInProgressHook(); @@ -2893,7 +3144,15 @@ function startTransition(setPending, callback, options) { ((ReactCurrentBatchConfig$2.transition.name = options.name), (ReactCurrentBatchConfig$2.transition.startTime = now())); try { - setPending(!1), callback(); + if (enableAsyncActions) { + var returnValue = callback(), + isPending = requestAsyncActionContext(returnValue); + setPending(isPending); + } else setPending(!1), callback(); + } catch (error) { + if (enableAsyncActions) + setPending({ then: function () {}, status: "rejected", reason: error }); + else throw error; } finally { (currentUpdatePriority = previousPriority), (ReactCurrentBatchConfig$2.transition = prevTransition); @@ -2913,11 +3172,9 @@ function refreshCache(fiber, seedKey, seedValue) { var lane = requestUpdateLane(provider); fiber = createUpdate(lane); var root = enqueueUpdate(provider, fiber, lane); - if (null !== root) { - var eventTime = requestEventTime(); - scheduleUpdateOnFiber(root, provider, lane, eventTime); - entangleTransitions(root, provider, lane); - } + null !== root && + (scheduleUpdateOnFiber(root, provider, lane), + entangleTransitions(root, provider, lane)); provider = createCache(); null !== seedKey && void 0 !== seedKey && @@ -2938,16 +3195,13 @@ function dispatchReducerAction(fiber, queue, action) { eagerState: null, next: null }; - if (isRenderPhaseUpdate(fiber)) enqueueRenderPhaseUpdate(queue, action); - else if ( - (enqueueUpdate$1(fiber, queue, action, lane), - (action = getRootForUpdatedFiber(fiber)), - null !== action) - ) { - var eventTime = requestEventTime(); - scheduleUpdateOnFiber(action, fiber, lane, eventTime); - entangleTransitionUpdate(action, queue, lane); - } + isRenderPhaseUpdate(fiber) + ? enqueueRenderPhaseUpdate(queue, action) + : (enqueueUpdate$1(fiber, queue, action, lane), + (action = getRootForUpdatedFiber(fiber)), + null !== action && + (scheduleUpdateOnFiber(action, fiber, lane), + entangleTransitionUpdate(action, queue, lane))); } function dispatchSetState(fiber, queue, action) { var lane = requestUpdateLane(fiber), @@ -2982,8 +3236,7 @@ function dispatchSetState(fiber, queue, action) { enqueueUpdate$1(fiber, queue, update, lane); action = getRootForUpdatedFiber(fiber); null !== action && - ((update = requestEventTime()), - scheduleUpdateOnFiber(action, fiber, lane, update), + (scheduleUpdateOnFiber(action, fiber, lane), entangleTransitionUpdate(action, queue, lane)); } } @@ -3014,6 +3267,7 @@ function entangleTransitionUpdate(root, queue, lane) { } var ContextOnlyDispatcher = { readContext: readContext, + use: use, useCallback: throwInvalidHookError, useContext: throwInvalidHookError, useEffect: throwInvalidHookError, @@ -3032,11 +3286,11 @@ var ContextOnlyDispatcher = { useId: throwInvalidHookError }; ContextOnlyDispatcher.useCacheRefresh = throwInvalidHookError; -ContextOnlyDispatcher.use = throwInvalidHookError; ContextOnlyDispatcher.useMemoCache = throwInvalidHookError; ContextOnlyDispatcher.useEffectEvent = throwInvalidHookError; var HooksDispatcherOnMount = { readContext: readContext, + use: use, useCallback: function (callback, deps) { mountWorkInProgressHook().memoizedState = [ callback, @@ -3104,11 +3358,10 @@ var HooksDispatcherOnMount = { return (mountWorkInProgressHook().memoizedState = value); }, useTransition: function () { - var _mountState = mountState(!1), - isPending = _mountState[0]; - _mountState = startTransition.bind(null, _mountState[1]); - mountWorkInProgressHook().memoizedState = _mountState; - return [isPending, _mountState]; + var setPending = mountState(!1)[1]; + setPending = startTransition.bind(null, setPending); + mountWorkInProgressHook().memoizedState = setPending; + return [!1, setPending]; }, useMutableSource: function (source, getSnapshot, subscribe) { var hook = mountWorkInProgressHook(); @@ -3157,7 +3410,6 @@ var HooksDispatcherOnMount = { )); } }; -HooksDispatcherOnMount.use = use; HooksDispatcherOnMount.useMemoCache = useMemoCache; HooksDispatcherOnMount.useEffectEvent = function (callback) { var hook = mountWorkInProgressHook(), @@ -3170,6 +3422,7 @@ HooksDispatcherOnMount.useEffectEvent = function (callback) { }; var HooksDispatcherOnUpdate = { readContext: readContext, + use: use, useCallback: updateCallback, useContext: readContext, useEffect: updateEffect, @@ -3188,9 +3441,14 @@ var HooksDispatcherOnUpdate = { return updateDeferredValueImpl(hook, currentHook.memoizedState, value); }, useTransition: function () { - var isPending = updateReducer(basicStateReducer)[0], + var booleanOrThenable = updateReducer(basicStateReducer)[0], start = updateWorkInProgressHook().memoizedState; - return [isPending, start]; + return [ + "boolean" === typeof booleanOrThenable + ? booleanOrThenable + : useThenable(booleanOrThenable), + start + ]; }, useMutableSource: updateMutableSource, useSyncExternalStore: updateSyncExternalStore, @@ -3198,10 +3456,10 @@ var HooksDispatcherOnUpdate = { }; HooksDispatcherOnUpdate.useCacheRefresh = updateRefresh; HooksDispatcherOnUpdate.useMemoCache = useMemoCache; -HooksDispatcherOnUpdate.use = use; HooksDispatcherOnUpdate.useEffectEvent = updateEvent; var HooksDispatcherOnRerender = { readContext: readContext, + use: use, useCallback: updateCallback, useContext: readContext, useEffect: updateEffect, @@ -3222,16 +3480,20 @@ var HooksDispatcherOnRerender = { : updateDeferredValueImpl(hook, currentHook.memoizedState, value); }, useTransition: function () { - var isPending = rerenderReducer(basicStateReducer)[0], + var booleanOrThenable = rerenderReducer(basicStateReducer)[0], start = updateWorkInProgressHook().memoizedState; - return [isPending, start]; + return [ + "boolean" === typeof booleanOrThenable + ? booleanOrThenable + : useThenable(booleanOrThenable), + start + ]; }, useMutableSource: updateMutableSource, useSyncExternalStore: updateSyncExternalStore, useId: updateId }; HooksDispatcherOnRerender.useCacheRefresh = updateRefresh; -HooksDispatcherOnRerender.use = use; HooksDispatcherOnRerender.useMemoCache = useMemoCache; HooksDispatcherOnRerender.useEffectEvent = updateEvent; function resolveDefaultProps(Component, baseProps) { @@ -3275,8 +3537,7 @@ var classComponentUpdater = { void 0 !== callback && null !== callback && (update.callback = callback); payload = enqueueUpdate(inst, update, lane); null !== payload && - ((callback = requestEventTime()), - scheduleUpdateOnFiber(payload, inst, lane, callback), + (scheduleUpdateOnFiber(payload, inst, lane), entangleTransitions(payload, inst, lane)); }, enqueueReplaceState: function (inst, payload, callback) { @@ -3288,8 +3549,7 @@ var classComponentUpdater = { void 0 !== callback && null !== callback && (update.callback = callback); payload = enqueueUpdate(inst, update, lane); null !== payload && - ((callback = requestEventTime()), - scheduleUpdateOnFiber(payload, inst, lane, callback), + (scheduleUpdateOnFiber(payload, inst, lane), entangleTransitions(payload, inst, lane)); }, enqueueForceUpdate: function (inst, callback) { @@ -3300,8 +3560,7 @@ var classComponentUpdater = { void 0 !== callback && null !== callback && (update.callback = callback); callback = enqueueUpdate(inst, update, lane); null !== callback && - ((update = requestEventTime()), - scheduleUpdateOnFiber(callback, inst, lane, update), + (scheduleUpdateOnFiber(callback, inst, lane), entangleTransitions(callback, inst, lane)); } }; @@ -4528,7 +4787,7 @@ function updateDehydratedSuspenseComponent( throw ( ((suspenseState.retryLane = didSuspend), enqueueConcurrentRenderForLane(current, didSuspend), - scheduleUpdateOnFiber(nextProps, current, didSuspend, -1), + scheduleUpdateOnFiber(nextProps, current, didSuspend), SelectiveHydrationException) ); } @@ -5083,7 +5342,7 @@ var AbortControllerLocal = }); }; }, - scheduleCallback$2 = Scheduler.unstable_scheduleCallback, + scheduleCallback$1 = Scheduler.unstable_scheduleCallback, NormalPriority = Scheduler.unstable_NormalPriority, CacheContext = { $$typeof: REACT_CONTEXT_TYPE, @@ -5105,7 +5364,7 @@ function createCache() { function releaseCache(cache) { cache.refCount--; 0 === cache.refCount && - scheduleCallback$2(NormalPriority, function () { + scheduleCallback$1(NormalPriority, function () { cache.controller.abort(); }); } @@ -6554,7 +6813,7 @@ function detachOffscreenInstance(instance) { var root = enqueueConcurrentRenderForLane(fiber, 2); null !== root && ((instance._pendingVisibility |= 2), - scheduleUpdateOnFiber(root, fiber, 2, -1)); + scheduleUpdateOnFiber(root, fiber, 2)); } } function attachOffscreenInstance(instance) { @@ -6564,7 +6823,7 @@ function attachOffscreenInstance(instance) { var root = enqueueConcurrentRenderForLane(fiber, 2); null !== root && ((instance._pendingVisibility &= -3), - scheduleUpdateOnFiber(root, fiber, 2, -1)); + scheduleUpdateOnFiber(root, fiber, 2)); } } function attachSuspenseRetryListeners(finishedWork, wakeables) { @@ -7667,203 +7926,6 @@ var DefaultCacheDispatcher = { return cacheForType; } }, - firstScheduledRoot = null, - lastScheduledRoot = null, - didScheduleMicrotask = !1, - mightHavePendingSyncWork = !1, - isFlushingWork = !1; -function ensureRootIsScheduled(root) { - root !== lastScheduledRoot && - null === root.next && - (null === lastScheduledRoot - ? (firstScheduledRoot = lastScheduledRoot = root) - : (lastScheduledRoot = lastScheduledRoot.next = root)); - mightHavePendingSyncWork = !0; - didScheduleMicrotask || - ((didScheduleMicrotask = !0), - scheduleCallback$3(ImmediatePriority, processRootScheduleInMicrotask)); - enableDeferRootSchedulingToMicrotask || - scheduleTaskForRootDuringMicrotask(root, now()); -} -function flushSyncWorkAcrossRoots_impl(onlyLegacy) { - if (!isFlushingWork && mightHavePendingSyncWork) { - var workInProgressRoot$jscomp$0 = workInProgressRoot, - workInProgressRootRenderLanes$jscomp$0 = workInProgressRootRenderLanes, - errors = null; - isFlushingWork = !0; - do { - var didPerformSomeWork = !1; - for (var root = firstScheduledRoot; null !== root; ) { - if ( - (!onlyLegacy || 0 === root.tag) && - 0 !== - (getNextLanes( - root, - root === workInProgressRoot$jscomp$0 - ? workInProgressRootRenderLanes$jscomp$0 - : 0 - ) & - 3) - ) - try { - didPerformSomeWork = !0; - var root$jscomp$0 = root; - if (0 !== (executionContext & 6)) - throw Error(formatProdErrorMessage(327)); - flushPassiveEffects(); - var lanes = getNextLanes(root$jscomp$0, 0); - if (0 !== (lanes & 3)) { - var exitStatus = renderRootSync(root$jscomp$0, lanes); - if (0 !== root$jscomp$0.tag && 2 === exitStatus) { - var originallyAttemptedLanes = lanes, - errorRetryLanes = getLanesToRetrySynchronouslyOnError( - root$jscomp$0, - originallyAttemptedLanes - ); - 0 !== errorRetryLanes && - ((lanes = errorRetryLanes), - (exitStatus = recoverFromConcurrentError( - root$jscomp$0, - originallyAttemptedLanes, - errorRetryLanes - ))); - } - if (1 === exitStatus) - throw ( - ((originallyAttemptedLanes = workInProgressRootFatalError), - prepareFreshStack(root$jscomp$0, 0), - markRootSuspended(root$jscomp$0, lanes), - ensureRootIsScheduled(root$jscomp$0), - originallyAttemptedLanes) - ); - 6 === exitStatus - ? markRootSuspended(root$jscomp$0, lanes) - : ((root$jscomp$0.finishedWork = - root$jscomp$0.current.alternate), - (root$jscomp$0.finishedLanes = lanes), - commitRoot( - root$jscomp$0, - workInProgressRootRecoverableErrors, - workInProgressTransitions - )); - } - ensureRootIsScheduled(root$jscomp$0); - } catch (error) { - null === errors ? (errors = [error]) : errors.push(error); - } - root = root.next; - } - } while (didPerformSomeWork); - isFlushingWork = !1; - if (null !== errors) { - if (1 < errors.length) { - if ("function" === typeof AggregateError) - throw new AggregateError(errors); - for (onlyLegacy = 1; onlyLegacy < errors.length; onlyLegacy++) - (workInProgressRoot$jscomp$0 = throwError.bind( - null, - errors[onlyLegacy] - )), - scheduleCallback$3(ImmediatePriority, workInProgressRoot$jscomp$0); - } - throw errors[0]; - } - } -} -function throwError(error) { - throw error; -} -function processRootScheduleInMicrotask() { - mightHavePendingSyncWork = didScheduleMicrotask = !1; - for ( - var currentTime = now(), prev = null, root = firstScheduledRoot; - null !== root; - - ) { - var next = root.next, - nextLanes = scheduleTaskForRootDuringMicrotask(root, currentTime); - 0 === nextLanes - ? ((root.next = null), - null === prev ? (firstScheduledRoot = next) : (prev.next = next), - null === next && (lastScheduledRoot = prev)) - : ((prev = root), - 0 !== (nextLanes & 3) && (mightHavePendingSyncWork = !0)); - root = next; - } - flushSyncWorkAcrossRoots_impl(!1); -} -function scheduleTaskForRootDuringMicrotask(root, currentTime) { - for ( - var suspendedLanes = root.suspendedLanes, - pingedLanes = root.pingedLanes, - expirationTimes = root.expirationTimes, - lanes = root.pendingLanes & -125829121; - 0 < lanes; - - ) { - var index$3 = 31 - clz32(lanes), - lane = 1 << index$3, - expirationTime = expirationTimes[index$3]; - if (-1 === expirationTime) { - if (0 === (lane & suspendedLanes) || 0 !== (lane & pingedLanes)) - expirationTimes[index$3] = computeExpirationTime(lane, currentTime); - } else expirationTime <= currentTime && (root.expiredLanes |= lane); - lanes &= ~lane; - } - currentTime = workInProgressRoot; - suspendedLanes = workInProgressRootRenderLanes; - suspendedLanes = getNextLanes( - root, - root === currentTime ? suspendedLanes : 0 - ); - pingedLanes = root.callbackNode; - if ( - 0 === suspendedLanes || - (root === currentTime && 2 === workInProgressSuspendedReason) || - null !== root.cancelPendingCommit - ) - return ( - null !== pingedLanes && - null !== pingedLanes && - cancelCallback$1(pingedLanes), - (root.callbackNode = null), - (root.callbackPriority = 0) - ); - if (0 !== (suspendedLanes & 3)) - return ( - null !== pingedLanes && - null !== pingedLanes && - cancelCallback$1(pingedLanes), - (root.callbackPriority = 2), - (root.callbackNode = null), - 2 - ); - currentTime = suspendedLanes & -suspendedLanes; - if (currentTime === root.callbackPriority) return currentTime; - null !== pingedLanes && cancelCallback$1(pingedLanes); - switch (lanesToEventPriority(suspendedLanes)) { - case 2: - suspendedLanes = ImmediatePriority; - break; - case 8: - suspendedLanes = UserBlockingPriority; - break; - case 32: - suspendedLanes = NormalPriority$1; - break; - case 536870912: - suspendedLanes = IdlePriority; - break; - default: - suspendedLanes = NormalPriority$1; - } - pingedLanes = performConcurrentWorkOnRoot.bind(null, root); - suspendedLanes = scheduleCallback$3(suspendedLanes, pingedLanes); - root.callbackPriority = currentTime; - root.callbackNode = suspendedLanes; - return currentTime; -} -var ceil = Math.ceil, PossiblyWeakMap = "function" === typeof WeakMap ? WeakMap : Map, ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher, ReactCurrentCache = ReactSharedInternals.ReactCurrentCache, @@ -7959,52 +8021,43 @@ var hasUncaughtError = !1, pendingPassiveEffectsRemainingLanes = 0, pendingPassiveTransitions = null, nestedUpdateCount = 0, - rootWithNestedUpdates = null, - currentEventTime = -1, - currentEventTransitionLane = 0; -function requestEventTime() { - return 0 !== (executionContext & 6) - ? now() - : -1 !== currentEventTime - ? currentEventTime - : (currentEventTime = now()); -} + rootWithNestedUpdates = null; function requestUpdateLane(fiber) { if (0 === (fiber.mode & 1)) return 2; if (0 !== (executionContext & 2) && 0 !== workInProgressRootRenderLanes) return workInProgressRootRenderLanes & -workInProgressRootRenderLanes; if (null !== ReactCurrentBatchConfig$1.transition) return ( - 0 === currentEventTransitionLane && - (currentEventTransitionLane = claimNextTransitionLane()), - currentEventTransitionLane + (fiber = currentAsyncAction), + null !== fiber ? fiber.lane : requestTransitionLane() ); fiber = currentUpdatePriority; return 0 !== fiber ? fiber : 32; } -function scheduleUpdateOnFiber(root, fiber, lane, eventTime) { +function scheduleUpdateOnFiber(root, fiber, lane) { if ( (root === workInProgressRoot && 2 === workInProgressSuspendedReason) || null !== root.cancelPendingCommit ) prepareFreshStack(root, 0), markRootSuspended(root, workInProgressRootRenderLanes); - markRootUpdated(root, lane, eventTime); + markRootUpdated(root, lane); if (0 === (executionContext & 2) || root !== workInProgressRoot) { - if ( - enableTransitionTracing && - ((eventTime = ReactCurrentBatchConfig.transition), - null !== eventTime && - null != eventTime.name && - (-1 === eventTime.startTime && (eventTime.startTime = now()), - enableTransitionTracing)) - ) { - var transitionLanesMap = root.transitionLanes, - index$7 = 31 - clz32(lane), - transitions = transitionLanesMap[index$7]; - null === transitions && (transitions = new Set()); - transitions.add(eventTime); - transitionLanesMap[index$7] = transitions; + if (enableTransitionTracing) { + var transition = ReactCurrentBatchConfig.transition; + if ( + null !== transition && + null != transition.name && + (-1 === transition.startTime && (transition.startTime = now()), + enableTransitionTracing) + ) { + var transitionLanesMap = root.transitionLanes, + index$6 = 31 - clz32(lane), + transitions = transitionLanesMap[index$6]; + null === transitions && (transitions = new Set()); + transitions.add(transition); + transitionLanesMap[index$6] = transitions; + } } root === workInProgressRoot && (0 === (executionContext & 2) && @@ -8020,8 +8073,6 @@ function scheduleUpdateOnFiber(root, fiber, lane, eventTime) { } } function performConcurrentWorkOnRoot(root, didTimeout) { - currentEventTime = -1; - currentEventTransitionLane = 0; if (0 !== (executionContext & 6)) throw Error(formatProdErrorMessage(327)); var originalCallbackNode = root.callbackNode; if (flushPassiveEffects() && root.callbackNode !== originalCallbackNode) @@ -8071,16 +8122,16 @@ function performConcurrentWorkOnRoot(root, didTimeout) { exitStatus = renderRootSync(root, lanes); if (2 === exitStatus) { errorRetryLanes = lanes; - var errorRetryLanes$129 = getLanesToRetrySynchronouslyOnError( + var errorRetryLanes$128 = getLanesToRetrySynchronouslyOnError( root, errorRetryLanes ); - 0 !== errorRetryLanes$129 && - ((lanes = errorRetryLanes$129), + 0 !== errorRetryLanes$128 && + ((lanes = errorRetryLanes$128), (exitStatus = recoverFromConcurrentError( root, errorRetryLanes, - errorRetryLanes$129 + errorRetryLanes$128 ))); } if (1 === exitStatus) @@ -8094,109 +8145,52 @@ function performConcurrentWorkOnRoot(root, didTimeout) { } root.finishedWork = didTimeout; root.finishedLanes = lanes; - switch (exitStatus) { - case 0: - case 1: - throw Error(formatProdErrorMessage(345)); - case 2: - commitRootWhenReady( - root, - didTimeout, - workInProgressRootRecoverableErrors, - workInProgressTransitions, - lanes - ); - break; - case 3: - markRootSuspended(root, lanes); - if ( - (lanes & 125829120) === lanes && - ((exitStatus = globalMostRecentFallbackTime + 500 - now()), - 10 < exitStatus) - ) { - if (0 !== getNextLanes(root, 0)) break; - root.timeoutHandle = scheduleTimeout( - commitRootWhenReady.bind( - null, - root, - didTimeout, - workInProgressRootRecoverableErrors, - workInProgressTransitions, - lanes - ), - exitStatus - ); + a: { + switch (exitStatus) { + case 0: + case 1: + throw Error(formatProdErrorMessage(345)); + case 4: + if ((lanes & 8388480) === lanes) { + markRootSuspended(root, lanes); + break a; + } break; - } - commitRootWhenReady( - root, - didTimeout, - workInProgressRootRecoverableErrors, - workInProgressTransitions, - lanes - ); - break; - case 4: - markRootSuspended(root, lanes); - if ((lanes & 8388480) === lanes) break; - exitStatus = lanes; - errorRetryLanes = root.eventTimes; - for (errorRetryLanes$129 = -1; 0 < exitStatus; ) { - var index$2 = 31 - clz32(exitStatus), - lane = 1 << index$2; - index$2 = errorRetryLanes[index$2]; - index$2 > errorRetryLanes$129 && (errorRetryLanes$129 = index$2); - exitStatus &= ~lane; - } - exitStatus = errorRetryLanes$129; - exitStatus = now() - exitStatus; - exitStatus = - (120 > exitStatus - ? 120 - : 480 > exitStatus - ? 480 - : 1080 > exitStatus - ? 1080 - : 1920 > exitStatus - ? 1920 - : 3e3 > exitStatus - ? 3e3 - : 4320 > exitStatus - ? 4320 - : 1960 * ceil(exitStatus / 1960)) - exitStatus; - if (10 < exitStatus) { - root.timeoutHandle = scheduleTimeout( - commitRootWhenReady.bind( - null, - root, - didTimeout, - workInProgressRootRecoverableErrors, - workInProgressTransitions, - lanes - ), - exitStatus - ); + case 2: + case 3: + case 5: break; - } - commitRootWhenReady( - root, - didTimeout, - workInProgressRootRecoverableErrors, - workInProgressTransitions, - lanes + default: + throw Error(formatProdErrorMessage(329)); + } + if ( + (lanes & 125829120) === lanes && + (alwaysThrottleRetries || 3 === exitStatus) && + ((exitStatus = globalMostRecentFallbackTime + 500 - now()), + 10 < exitStatus) + ) { + markRootSuspended(root, lanes); + if (0 !== getNextLanes(root, 0)) break a; + root.timeoutHandle = scheduleTimeout( + commitRootWhenReady.bind( + null, + root, + didTimeout, + workInProgressRootRecoverableErrors, + workInProgressTransitions, + lanes + ), + exitStatus ); - break; - case 5: - commitRootWhenReady( - root, - didTimeout, - workInProgressRootRecoverableErrors, - workInProgressTransitions, - lanes - ); - break; - default: - throw Error(formatProdErrorMessage(329)); + break a; + } + commitRootWhenReady( + root, + didTimeout, + workInProgressRootRecoverableErrors, + workInProgressTransitions, + lanes + ); } } } @@ -8247,11 +8241,7 @@ function commitRootWhenReady( lanes ) { 0 === (lanes & 42) && accumulateSuspenseyCommitOnFiber(finishedWork); - commitRoot( - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ); + commitRoot(root, recoverableErrors, transitions); } function isRenderConsistentWithExternalStores(finishedWork) { for (var node = finishedWork; ; ) { @@ -8293,9 +8283,9 @@ function markRootSuspended(root, suspendedLanes) { root.suspendedLanes |= suspendedLanes; root.pingedLanes &= ~suspendedLanes; for (root = root.expirationTimes; 0 < suspendedLanes; ) { - var index$4 = 31 - clz32(suspendedLanes), - lane = 1 << index$4; - root[index$4] = -1; + var index$3 = 31 - clz32(suspendedLanes), + lane = 1 << index$3; + root[index$3] = -1; suspendedLanes &= ~lane; } } @@ -8423,8 +8413,8 @@ function renderRootSync(root, lanes) { } workLoopSync(); break; - } catch (thrownValue$132) { - handleThrow(root, thrownValue$132); + } catch (thrownValue$130) { + handleThrow(root, thrownValue$130); } while (1); resetContextDependencies(); @@ -8528,8 +8518,8 @@ function renderRootConcurrent(root, lanes) { } workLoopConcurrent(); break; - } catch (thrownValue$134) { - handleThrow(root, thrownValue$134); + } catch (thrownValue$132) { + handleThrow(root, thrownValue$132); } while (1); resetContextDependencies(); @@ -8594,6 +8584,8 @@ function replaySuspendedUnitOfWork(unitOfWork) { workInProgressRootRenderLanes ); break; + case 5: + resetHooksOnUnwind(); default: unwindInterruptedWork(current, unitOfWork), (unitOfWork = workInProgress = @@ -8777,21 +8769,31 @@ function throwAndUnwindWorkLoop(unitOfWork, thrownValue) { } catch (error) { throw ((workInProgress = returnFiber), error); } - unitOfWork.flags & 32768 - ? unwindUnitOfWork(unitOfWork) - : completeUnitOfWork(unitOfWork); + if (unitOfWork.flags & 32768) + a: { + do { + returnFiber = unwindWork(unitOfWork.alternate, unitOfWork); + if (null !== returnFiber) { + returnFiber.flags &= 32767; + workInProgress = returnFiber; + break a; + } + unitOfWork = unitOfWork.return; + null !== unitOfWork && + ((unitOfWork.flags |= 32768), + (unitOfWork.subtreeFlags = 0), + (unitOfWork.deletions = null)); + workInProgress = unitOfWork; + } while (null !== unitOfWork); + workInProgressRootExitStatus = 6; + workInProgress = null; + } + else completeUnitOfWork(unitOfWork); } } function completeUnitOfWork(unitOfWork) { var completedWork = unitOfWork; do { - if ( - revertRemovalOfSiblingPrerendering && - 0 !== (completedWork.flags & 32768) - ) { - unwindUnitOfWork(completedWork); - return; - } unitOfWork = completedWork.return; var next = completeWork( completedWork.alternate, @@ -8811,29 +8813,6 @@ function completeUnitOfWork(unitOfWork) { } while (null !== completedWork); 0 === workInProgressRootExitStatus && (workInProgressRootExitStatus = 5); } -function unwindUnitOfWork(unitOfWork) { - do { - var next = unwindWork(unitOfWork.alternate, unitOfWork); - if (null !== next) { - next.flags &= 32767; - workInProgress = next; - return; - } - next = unitOfWork.return; - null !== next && - ((next.flags |= 32768), (next.subtreeFlags = 0), (next.deletions = null)); - if ( - revertRemovalOfSiblingPrerendering && - ((unitOfWork = unitOfWork.sibling), null !== unitOfWork) - ) { - workInProgress = unitOfWork; - return; - } - workInProgress = unitOfWork = next; - } while (null !== unitOfWork); - workInProgressRootExitStatus = 6; - workInProgress = null; -} function commitRoot(root, recoverableErrors, transitions) { var previousUpdateLanePriority = currentUpdatePriority, prevTransition = ReactCurrentBatchConfig.transition; @@ -9014,10 +8993,8 @@ function captureCommitPhaseErrorOnRoot(rootFiber, sourceFiber, error) { sourceFiber = createCapturedValueAtFiber(error, sourceFiber); sourceFiber = createRootErrorUpdate(rootFiber, sourceFiber, 2); rootFiber = enqueueUpdate(rootFiber, sourceFiber, 2); - sourceFiber = requestEventTime(); null !== rootFiber && - (markRootUpdated(rootFiber, 2, sourceFiber), - ensureRootIsScheduled(rootFiber)); + (markRootUpdated(rootFiber, 2), ensureRootIsScheduled(rootFiber)); } function captureCommitPhaseError(sourceFiber, nearestMountedAncestor, error) { if (3 === sourceFiber.tag) @@ -9051,9 +9028,8 @@ function captureCommitPhaseError(sourceFiber, nearestMountedAncestor, error) { sourceFiber, 2 ); - sourceFiber = requestEventTime(); null !== nearestMountedAncestor && - (markRootUpdated(nearestMountedAncestor, 2, sourceFiber), + (markRootUpdated(nearestMountedAncestor, 2), ensureRootIsScheduled(nearestMountedAncestor)); break; } @@ -9095,10 +9071,9 @@ function pingSuspendedRoot(root, wakeable, pingedLanes) { function retryTimedOutBoundary(boundaryFiber, retryLane) { 0 === retryLane && (retryLane = 0 === (boundaryFiber.mode & 1) ? 2 : claimNextRetryLane()); - var eventTime = requestEventTime(); boundaryFiber = enqueueConcurrentRenderForLane(boundaryFiber, retryLane); null !== boundaryFiber && - (markRootUpdated(boundaryFiber, retryLane, eventTime), + (markRootUpdated(boundaryFiber, retryLane), ensureRootIsScheduled(boundaryFiber)); } function retryDehydratedSuspenseBoundary(boundaryFiber) { @@ -9868,7 +9843,6 @@ function FiberRootNode( this.cancelPendingCommit = null; this.callbackPriority = 0; - this.eventTimes = createLaneMap(0); this.expirationTimes = createLaneMap(-1); this.entangledLanes = this.errorRecoveryDisabledLanes = @@ -9949,8 +9923,7 @@ function updateContainer(element, container, parentComponent, callback) { null !== callback && (container.callback = callback); element = enqueueUpdate(current, container, lane); null !== element && - ((callback = requestEventTime()), - scheduleUpdateOnFiber(element, current, lane, callback), + (scheduleUpdateOnFiber(element, current, lane), entangleTransitions(element, current, lane)); return lane; } @@ -10078,10 +10051,10 @@ var slice = Array.prototype.slice, return null; }, bundleType: 0, - version: "18.3.0-www-classic-9e45a6d4", + version: "18.3.0-www-classic-f817b2e4", rendererPackageName: "react-art" }; -var internals$jscomp$inline_1344 = { +var internals$jscomp$inline_1335 = { bundleType: devToolsConfig$jscomp$inline_1170.bundleType, version: devToolsConfig$jscomp$inline_1170.version, rendererPackageName: devToolsConfig$jscomp$inline_1170.rendererPackageName, @@ -10109,19 +10082,19 @@ var internals$jscomp$inline_1344 = { scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "18.3.0-www-classic-9e45a6d4" + reconcilerVersion: "18.3.0-www-classic-f817b2e4" }; if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { - var hook$jscomp$inline_1345 = __REACT_DEVTOOLS_GLOBAL_HOOK__; + var hook$jscomp$inline_1336 = __REACT_DEVTOOLS_GLOBAL_HOOK__; if ( - !hook$jscomp$inline_1345.isDisabled && - hook$jscomp$inline_1345.supportsFiber + !hook$jscomp$inline_1336.isDisabled && + hook$jscomp$inline_1336.supportsFiber ) try { - (rendererID = hook$jscomp$inline_1345.inject( - internals$jscomp$inline_1344 + (rendererID = hook$jscomp$inline_1336.inject( + internals$jscomp$inline_1335 )), - (injectedHook = hook$jscomp$inline_1345); + (injectedHook = hook$jscomp$inline_1336); } catch (err) {} } var Path = Mode$1.Path; diff --git a/compiled/facebook-www/ReactART-prod.modern.js b/compiled/facebook-www/ReactART-prod.modern.js index 0a1d8eb237..0d7b91bf24 100644 --- a/compiled/facebook-www/ReactART-prod.modern.js +++ b/compiled/facebook-www/ReactART-prod.modern.js @@ -63,8 +63,6 @@ function formatProdErrorMessage(code) { var ReactSharedInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, dynamicFeatureFlags = require("ReactFeatureFlags"), - revertRemovalOfSiblingPrerendering = - dynamicFeatureFlags.revertRemovalOfSiblingPrerendering, enableDebugTracing = dynamicFeatureFlags.enableDebugTracing, enableUseRefAccessWarning = dynamicFeatureFlags.enableUseRefAccessWarning, enableLazyContextPropagation = @@ -74,6 +72,8 @@ var ReactSharedInternals = enableDeferRootSchedulingToMicrotask = dynamicFeatureFlags.enableDeferRootSchedulingToMicrotask, diffInCommitPhase = dynamicFeatureFlags.diffInCommitPhase, + enableAsyncActions = dynamicFeatureFlags.enableAsyncActions, + alwaysThrottleRetries = dynamicFeatureFlags.alwaysThrottleRetries, REACT_ELEMENT_TYPE = Symbol.for("react.element"), REACT_PORTAL_TYPE = Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"), @@ -438,13 +438,10 @@ function createLaneMap(initial) { for (var laneMap = [], i = 0; 31 > i; i++) laneMap.push(initial); return laneMap; } -function markRootUpdated(root, updateLane, eventTime) { +function markRootUpdated(root, updateLane) { root.pendingLanes |= updateLane; 536870912 !== updateLane && ((root.suspendedLanes = 0), (root.pingedLanes = 0)); - root = root.eventTimes; - updateLane = 31 - clz32(updateLane); - root[updateLane] = eventTime; } function markRootFinished(root, remainingLanes) { var noLongerPendingLanes = root.pendingLanes & ~remainingLanes; @@ -456,22 +453,20 @@ function markRootFinished(root, remainingLanes) { root.entangledLanes &= remainingLanes; root.errorRecoveryDisabledLanes &= remainingLanes; remainingLanes = root.entanglements; - var eventTimes = root.eventTimes, - expirationTimes = root.expirationTimes; + var expirationTimes = root.expirationTimes; for (root = root.hiddenUpdates; 0 < noLongerPendingLanes; ) { - var index$5 = 31 - clz32(noLongerPendingLanes), - lane = 1 << index$5; - remainingLanes[index$5] = 0; - eventTimes[index$5] = -1; - expirationTimes[index$5] = -1; - var hiddenUpdatesForLane = root[index$5]; + var index$4 = 31 - clz32(noLongerPendingLanes), + lane = 1 << index$4; + remainingLanes[index$4] = 0; + expirationTimes[index$4] = -1; + var hiddenUpdatesForLane = root[index$4]; if (null !== hiddenUpdatesForLane) for ( - root[index$5] = null, index$5 = 0; - index$5 < hiddenUpdatesForLane.length; - index$5++ + root[index$4] = null, index$4 = 0; + index$4 < hiddenUpdatesForLane.length; + index$4++ ) { - var update = hiddenUpdatesForLane[index$5]; + var update = hiddenUpdatesForLane[index$4]; null !== update && (update.lane &= -1073741825); } noLongerPendingLanes &= ~lane; @@ -480,21 +475,21 @@ function markRootFinished(root, remainingLanes) { function markRootEntangled(root, entangledLanes) { var rootEntangledLanes = (root.entangledLanes |= entangledLanes); for (root = root.entanglements; rootEntangledLanes; ) { - var index$6 = 31 - clz32(rootEntangledLanes), - lane = 1 << index$6; - (lane & entangledLanes) | (root[index$6] & entangledLanes) && - (root[index$6] |= entangledLanes); + var index$5 = 31 - clz32(rootEntangledLanes), + lane = 1 << index$5; + (lane & entangledLanes) | (root[index$5] & entangledLanes) && + (root[index$5] |= entangledLanes); rootEntangledLanes &= ~lane; } } function getTransitionsForLanes(root, lanes) { if (!enableTransitionTracing) return null; for (var transitionsForLanes = []; 0 < lanes; ) { - var index$8 = 31 - clz32(lanes), - lane = 1 << index$8; - index$8 = root.transitionLanes[index$8]; - null !== index$8 && - index$8.forEach(function (transition) { + var index$7 = 31 - clz32(lanes), + lane = 1 << index$7; + index$7 = root.transitionLanes[index$7]; + null !== index$7 && + index$7.forEach(function (transition) { transitionsForLanes.push(transition); }); lanes &= ~lane; @@ -504,10 +499,10 @@ function getTransitionsForLanes(root, lanes) { function clearTransitionsForLanes(root, lanes) { if (enableTransitionTracing) for (; 0 < lanes; ) { - var index$9 = 31 - clz32(lanes), - lane = 1 << index$9; - null !== root.transitionLanes[index$9] && - (root.transitionLanes[index$9] = null); + var index$8 = 31 - clz32(lanes), + lane = 1 << index$8; + null !== root.transitionLanes[index$8] && + (root.transitionLanes[index$8] = null); lanes &= ~lane; } } @@ -729,16 +724,16 @@ function describeNativeComponentFrame(fn, construct) { } else { try { construct.call(); - } catch (x$10) { - control = x$10; + } catch (x$9) { + control = x$9; } fn.call(construct.prototype); } else { try { throw Error(); - } catch (x$11) { - control = x$11; + } catch (x$10) { + control = x$10; } fn(); } @@ -2070,6 +2065,261 @@ function resetWorkInProgressVersions() { workInProgressSources[i]._workInProgressVersionSecondary = null; workInProgressSources.length = 0; } +var firstScheduledRoot = null, + lastScheduledRoot = null, + didScheduleMicrotask = !1, + mightHavePendingSyncWork = !1, + isFlushingWork = !1, + currentEventTransitionLane = 0; +function ensureRootIsScheduled(root) { + root !== lastScheduledRoot && + null === root.next && + (null === lastScheduledRoot + ? (firstScheduledRoot = lastScheduledRoot = root) + : (lastScheduledRoot = lastScheduledRoot.next = root)); + mightHavePendingSyncWork = !0; + didScheduleMicrotask || + ((didScheduleMicrotask = !0), + scheduleCallback$3(ImmediatePriority, processRootScheduleInMicrotask)); + enableDeferRootSchedulingToMicrotask || + scheduleTaskForRootDuringMicrotask(root, now()); +} +function flushSyncWorkAcrossRoots_impl(onlyLegacy) { + if (!isFlushingWork && mightHavePendingSyncWork) { + var workInProgressRoot$jscomp$0 = workInProgressRoot, + workInProgressRootRenderLanes$jscomp$0 = workInProgressRootRenderLanes, + errors = null; + isFlushingWork = !0; + do { + var didPerformSomeWork = !1; + for (var root = firstScheduledRoot; null !== root; ) { + if ( + (!onlyLegacy || 0 === root.tag) && + 0 !== + (getNextLanes( + root, + root === workInProgressRoot$jscomp$0 + ? workInProgressRootRenderLanes$jscomp$0 + : 0 + ) & + 3) + ) + try { + didPerformSomeWork = !0; + var root$jscomp$0 = root; + if (0 !== (executionContext & 6)) + throw Error(formatProdErrorMessage(327)); + flushPassiveEffects(); + var lanes = getNextLanes(root$jscomp$0, 0); + if (0 !== (lanes & 3)) { + var exitStatus = renderRootSync(root$jscomp$0, lanes); + if (0 !== root$jscomp$0.tag && 2 === exitStatus) { + var originallyAttemptedLanes = lanes, + errorRetryLanes = getLanesToRetrySynchronouslyOnError( + root$jscomp$0, + originallyAttemptedLanes + ); + 0 !== errorRetryLanes && + ((lanes = errorRetryLanes), + (exitStatus = recoverFromConcurrentError( + root$jscomp$0, + originallyAttemptedLanes, + errorRetryLanes + ))); + } + if (1 === exitStatus) + throw ( + ((originallyAttemptedLanes = workInProgressRootFatalError), + prepareFreshStack(root$jscomp$0, 0), + markRootSuspended(root$jscomp$0, lanes), + ensureRootIsScheduled(root$jscomp$0), + originallyAttemptedLanes) + ); + 6 === exitStatus + ? markRootSuspended(root$jscomp$0, lanes) + : ((root$jscomp$0.finishedWork = + root$jscomp$0.current.alternate), + (root$jscomp$0.finishedLanes = lanes), + commitRoot( + root$jscomp$0, + workInProgressRootRecoverableErrors, + workInProgressTransitions + )); + } + ensureRootIsScheduled(root$jscomp$0); + } catch (error) { + null === errors ? (errors = [error]) : errors.push(error); + } + root = root.next; + } + } while (didPerformSomeWork); + isFlushingWork = !1; + if (null !== errors) { + if (1 < errors.length) { + if ("function" === typeof AggregateError) + throw new AggregateError(errors); + for (onlyLegacy = 1; onlyLegacy < errors.length; onlyLegacy++) + (workInProgressRoot$jscomp$0 = throwError.bind( + null, + errors[onlyLegacy] + )), + scheduleCallback$3(ImmediatePriority, workInProgressRoot$jscomp$0); + } + throw errors[0]; + } + } +} +function throwError(error) { + throw error; +} +function processRootScheduleInMicrotask() { + mightHavePendingSyncWork = didScheduleMicrotask = !1; + for ( + var currentTime = now(), prev = null, root = firstScheduledRoot; + null !== root; + + ) { + var next = root.next, + nextLanes = scheduleTaskForRootDuringMicrotask(root, currentTime); + 0 === nextLanes + ? ((root.next = null), + null === prev ? (firstScheduledRoot = next) : (prev.next = next), + null === next && (lastScheduledRoot = prev)) + : ((prev = root), + 0 !== (nextLanes & 3) && (mightHavePendingSyncWork = !0)); + root = next; + } + currentEventTransitionLane = 0; + flushSyncWorkAcrossRoots_impl(!1); +} +function scheduleTaskForRootDuringMicrotask(root, currentTime) { + for ( + var suspendedLanes = root.suspendedLanes, + pingedLanes = root.pingedLanes, + expirationTimes = root.expirationTimes, + lanes = root.pendingLanes & -125829121; + 0 < lanes; + + ) { + var index$2 = 31 - clz32(lanes), + lane = 1 << index$2, + expirationTime = expirationTimes[index$2]; + if (-1 === expirationTime) { + if (0 === (lane & suspendedLanes) || 0 !== (lane & pingedLanes)) + expirationTimes[index$2] = computeExpirationTime(lane, currentTime); + } else expirationTime <= currentTime && (root.expiredLanes |= lane); + lanes &= ~lane; + } + currentTime = workInProgressRoot; + suspendedLanes = workInProgressRootRenderLanes; + suspendedLanes = getNextLanes( + root, + root === currentTime ? suspendedLanes : 0 + ); + pingedLanes = root.callbackNode; + if ( + 0 === suspendedLanes || + (root === currentTime && 2 === workInProgressSuspendedReason) || + null !== root.cancelPendingCommit + ) + return ( + null !== pingedLanes && + null !== pingedLanes && + cancelCallback$1(pingedLanes), + (root.callbackNode = null), + (root.callbackPriority = 0) + ); + if (0 !== (suspendedLanes & 3)) + return ( + null !== pingedLanes && + null !== pingedLanes && + cancelCallback$1(pingedLanes), + (root.callbackPriority = 2), + (root.callbackNode = null), + 2 + ); + currentTime = suspendedLanes & -suspendedLanes; + if (currentTime === root.callbackPriority) return currentTime; + null !== pingedLanes && cancelCallback$1(pingedLanes); + switch (lanesToEventPriority(suspendedLanes)) { + case 2: + suspendedLanes = ImmediatePriority; + break; + case 8: + suspendedLanes = UserBlockingPriority; + break; + case 32: + suspendedLanes = NormalPriority$1; + break; + case 536870912: + suspendedLanes = IdlePriority; + break; + default: + suspendedLanes = NormalPriority$1; + } + pingedLanes = performConcurrentWorkOnRoot.bind(null, root); + suspendedLanes = scheduleCallback$3(suspendedLanes, pingedLanes); + root.callbackPriority = currentTime; + root.callbackNode = suspendedLanes; + return currentTime; +} +function requestTransitionLane() { + 0 === currentEventTransitionLane && + (currentEventTransitionLane = claimNextTransitionLane()); + return currentEventTransitionLane; +} +var currentAsyncAction = null; +function requestAsyncActionContext(actionReturnValue) { + if ( + null !== actionReturnValue && + "object" === typeof actionReturnValue && + "function" === typeof actionReturnValue.then + ) { + if (null === currentAsyncAction) { + var asyncAction = { + lane: requestTransitionLane(), + listeners: [], + count: 0, + status: "pending", + value: !1, + reason: void 0, + then: function (resolve) { + asyncAction.listeners.push(resolve); + } + }; + attachPingListeners(actionReturnValue, asyncAction); + return (currentAsyncAction = asyncAction); + } + var asyncAction$28 = currentAsyncAction; + attachPingListeners(actionReturnValue, asyncAction$28); + return asyncAction$28; + } + return null === currentAsyncAction ? !1 : currentAsyncAction; +} +function attachPingListeners(thenable, asyncAction) { + asyncAction.count++; + thenable.then( + function () { + 0 === --asyncAction.count && + ((asyncAction.status = "fulfilled"), + completeAsyncActionScope(asyncAction)); + }, + function (error) { + 0 === --asyncAction.count && + ((asyncAction.status = "rejected"), + (asyncAction.reason = error), + completeAsyncActionScope(asyncAction)); + } + ); + return asyncAction; +} +function completeAsyncActionScope(action) { + currentAsyncAction === action && (currentAsyncAction = null); + var listeners = action.listeners; + action.listeners = []; + for (action = 0; action < listeners.length; action++) + (0, listeners[action])(!1); +} var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, ReactCurrentBatchConfig$2 = ReactSharedInternals.ReactCurrentBatchConfig, renderLanes$1 = 0, @@ -2224,20 +2474,21 @@ var createFunctionComponentUpdateQueue; createFunctionComponentUpdateQueue = function () { return { lastEffect: null, events: null, stores: null, memoCache: null }; }; +function useThenable(thenable) { + var index = thenableIndexCounter; + thenableIndexCounter += 1; + null === thenableState && (thenableState = []); + thenable = trackUsedThenable(thenableState, thenable, index); + null === currentlyRenderingFiber$1.alternate && + (null === workInProgressHook + ? null === currentlyRenderingFiber$1.memoizedState + : null === workInProgressHook.next) && + (ReactCurrentDispatcher$1.current = HooksDispatcherOnMount); + return thenable; +} function use(usable) { if (null !== usable && "object" === typeof usable) { - if ("function" === typeof usable.then) { - var index$28 = thenableIndexCounter; - thenableIndexCounter += 1; - null === thenableState && (thenableState = []); - usable = trackUsedThenable(thenableState, usable, index$28); - null === currentlyRenderingFiber$1.alternate && - (null === workInProgressHook - ? null === currentlyRenderingFiber$1.memoizedState - : null === workInProgressHook.next) && - (ReactCurrentDispatcher$1.current = HooksDispatcherOnMount); - return usable; - } + if ("function" === typeof usable.then) return useThenable(usable); if ( usable.$$typeof === REACT_CONTEXT_TYPE || usable.$$typeof === REACT_SERVER_CONTEXT_TYPE @@ -2534,7 +2785,7 @@ function checkIfSnapshotChanged(inst) { } function forceStoreRerender(fiber) { var root = enqueueConcurrentRenderForLane(fiber, 2); - null !== root && scheduleUpdateOnFiber(root, fiber, 2, -1); + null !== root && scheduleUpdateOnFiber(root, fiber, 2); } function mountState(initialState) { var hook = mountWorkInProgressHook(); @@ -2699,7 +2950,15 @@ function startTransition(setPending, callback, options) { ((ReactCurrentBatchConfig$2.transition.name = options.name), (ReactCurrentBatchConfig$2.transition.startTime = now())); try { - setPending(!1), callback(); + if (enableAsyncActions) { + var returnValue = callback(), + isPending = requestAsyncActionContext(returnValue); + setPending(isPending); + } else setPending(!1), callback(); + } catch (error) { + if (enableAsyncActions) + setPending({ then: function () {}, status: "rejected", reason: error }); + else throw error; } finally { (currentUpdatePriority = previousPriority), (ReactCurrentBatchConfig$2.transition = prevTransition); @@ -2719,11 +2978,9 @@ function refreshCache(fiber, seedKey, seedValue) { var lane = requestUpdateLane(provider); fiber = createUpdate(lane); var root = enqueueUpdate(provider, fiber, lane); - if (null !== root) { - var eventTime = requestEventTime(); - scheduleUpdateOnFiber(root, provider, lane, eventTime); - entangleTransitions(root, provider, lane); - } + null !== root && + (scheduleUpdateOnFiber(root, provider, lane), + entangleTransitions(root, provider, lane)); provider = createCache(); null !== seedKey && void 0 !== seedKey && @@ -2744,16 +3001,13 @@ function dispatchReducerAction(fiber, queue, action) { eagerState: null, next: null }; - if (isRenderPhaseUpdate(fiber)) enqueueRenderPhaseUpdate(queue, action); - else if ( - (enqueueUpdate$1(fiber, queue, action, lane), - (action = getRootForUpdatedFiber(fiber)), - null !== action) - ) { - var eventTime = requestEventTime(); - scheduleUpdateOnFiber(action, fiber, lane, eventTime); - entangleTransitionUpdate(action, queue, lane); - } + isRenderPhaseUpdate(fiber) + ? enqueueRenderPhaseUpdate(queue, action) + : (enqueueUpdate$1(fiber, queue, action, lane), + (action = getRootForUpdatedFiber(fiber)), + null !== action && + (scheduleUpdateOnFiber(action, fiber, lane), + entangleTransitionUpdate(action, queue, lane))); } function dispatchSetState(fiber, queue, action) { var lane = requestUpdateLane(fiber), @@ -2788,8 +3042,7 @@ function dispatchSetState(fiber, queue, action) { enqueueUpdate$1(fiber, queue, update, lane); action = getRootForUpdatedFiber(fiber); null !== action && - ((update = requestEventTime()), - scheduleUpdateOnFiber(action, fiber, lane, update), + (scheduleUpdateOnFiber(action, fiber, lane), entangleTransitionUpdate(action, queue, lane)); } } @@ -2820,6 +3073,7 @@ function entangleTransitionUpdate(root, queue, lane) { } var ContextOnlyDispatcher = { readContext: readContext, + use: use, useCallback: throwInvalidHookError, useContext: throwInvalidHookError, useEffect: throwInvalidHookError, @@ -2838,11 +3092,11 @@ var ContextOnlyDispatcher = { useId: throwInvalidHookError }; ContextOnlyDispatcher.useCacheRefresh = throwInvalidHookError; -ContextOnlyDispatcher.use = throwInvalidHookError; ContextOnlyDispatcher.useMemoCache = throwInvalidHookError; ContextOnlyDispatcher.useEffectEvent = throwInvalidHookError; var HooksDispatcherOnMount = { readContext: readContext, + use: use, useCallback: function (callback, deps) { mountWorkInProgressHook().memoizedState = [ callback, @@ -2910,11 +3164,10 @@ var HooksDispatcherOnMount = { return (mountWorkInProgressHook().memoizedState = value); }, useTransition: function () { - var _mountState = mountState(!1), - isPending = _mountState[0]; - _mountState = startTransition.bind(null, _mountState[1]); - mountWorkInProgressHook().memoizedState = _mountState; - return [isPending, _mountState]; + var setPending = mountState(!1)[1]; + setPending = startTransition.bind(null, setPending); + mountWorkInProgressHook().memoizedState = setPending; + return [!1, setPending]; }, useMutableSource: function (source, getSnapshot, subscribe) { var hook = mountWorkInProgressHook(); @@ -2963,7 +3216,6 @@ var HooksDispatcherOnMount = { )); } }; -HooksDispatcherOnMount.use = use; HooksDispatcherOnMount.useMemoCache = useMemoCache; HooksDispatcherOnMount.useEffectEvent = function (callback) { var hook = mountWorkInProgressHook(), @@ -2976,6 +3228,7 @@ HooksDispatcherOnMount.useEffectEvent = function (callback) { }; var HooksDispatcherOnUpdate = { readContext: readContext, + use: use, useCallback: updateCallback, useContext: readContext, useEffect: updateEffect, @@ -2994,9 +3247,14 @@ var HooksDispatcherOnUpdate = { return updateDeferredValueImpl(hook, currentHook.memoizedState, value); }, useTransition: function () { - var isPending = updateReducer(basicStateReducer)[0], + var booleanOrThenable = updateReducer(basicStateReducer)[0], start = updateWorkInProgressHook().memoizedState; - return [isPending, start]; + return [ + "boolean" === typeof booleanOrThenable + ? booleanOrThenable + : useThenable(booleanOrThenable), + start + ]; }, useMutableSource: updateMutableSource, useSyncExternalStore: updateSyncExternalStore, @@ -3004,10 +3262,10 @@ var HooksDispatcherOnUpdate = { }; HooksDispatcherOnUpdate.useCacheRefresh = updateRefresh; HooksDispatcherOnUpdate.useMemoCache = useMemoCache; -HooksDispatcherOnUpdate.use = use; HooksDispatcherOnUpdate.useEffectEvent = updateEvent; var HooksDispatcherOnRerender = { readContext: readContext, + use: use, useCallback: updateCallback, useContext: readContext, useEffect: updateEffect, @@ -3028,16 +3286,20 @@ var HooksDispatcherOnRerender = { : updateDeferredValueImpl(hook, currentHook.memoizedState, value); }, useTransition: function () { - var isPending = rerenderReducer(basicStateReducer)[0], + var booleanOrThenable = rerenderReducer(basicStateReducer)[0], start = updateWorkInProgressHook().memoizedState; - return [isPending, start]; + return [ + "boolean" === typeof booleanOrThenable + ? booleanOrThenable + : useThenable(booleanOrThenable), + start + ]; }, useMutableSource: updateMutableSource, useSyncExternalStore: updateSyncExternalStore, useId: updateId }; HooksDispatcherOnRerender.useCacheRefresh = updateRefresh; -HooksDispatcherOnRerender.use = use; HooksDispatcherOnRerender.useMemoCache = useMemoCache; HooksDispatcherOnRerender.useEffectEvent = updateEvent; function resolveDefaultProps(Component, baseProps) { @@ -3081,8 +3343,7 @@ var classComponentUpdater = { void 0 !== callback && null !== callback && (update.callback = callback); payload = enqueueUpdate(inst, update, lane); null !== payload && - ((callback = requestEventTime()), - scheduleUpdateOnFiber(payload, inst, lane, callback), + (scheduleUpdateOnFiber(payload, inst, lane), entangleTransitions(payload, inst, lane)); }, enqueueReplaceState: function (inst, payload, callback) { @@ -3094,8 +3355,7 @@ var classComponentUpdater = { void 0 !== callback && null !== callback && (update.callback = callback); payload = enqueueUpdate(inst, update, lane); null !== payload && - ((callback = requestEventTime()), - scheduleUpdateOnFiber(payload, inst, lane, callback), + (scheduleUpdateOnFiber(payload, inst, lane), entangleTransitions(payload, inst, lane)); }, enqueueForceUpdate: function (inst, callback) { @@ -3106,8 +3366,7 @@ var classComponentUpdater = { void 0 !== callback && null !== callback && (update.callback = callback); callback = enqueueUpdate(inst, update, lane); null !== callback && - ((update = requestEventTime()), - scheduleUpdateOnFiber(callback, inst, lane, update), + (scheduleUpdateOnFiber(callback, inst, lane), entangleTransitions(callback, inst, lane)); } }; @@ -4287,7 +4546,7 @@ function updateDehydratedSuspenseComponent( throw ( ((suspenseState.retryLane = didSuspend), enqueueConcurrentRenderForLane(current, didSuspend), - scheduleUpdateOnFiber(nextProps, current, didSuspend, -1), + scheduleUpdateOnFiber(nextProps, current, didSuspend), SelectiveHydrationException) ); } @@ -4838,7 +5097,7 @@ var AbortControllerLocal = }); }; }, - scheduleCallback$2 = Scheduler.unstable_scheduleCallback, + scheduleCallback$1 = Scheduler.unstable_scheduleCallback, NormalPriority = Scheduler.unstable_NormalPriority, CacheContext = { $$typeof: REACT_CONTEXT_TYPE, @@ -4860,7 +5119,7 @@ function createCache() { function releaseCache(cache) { cache.refCount--; 0 === cache.refCount && - scheduleCallback$2(NormalPriority, function () { + scheduleCallback$1(NormalPriority, function () { cache.controller.abort(); }); } @@ -6290,7 +6549,7 @@ function detachOffscreenInstance(instance) { var root = enqueueConcurrentRenderForLane(fiber, 2); null !== root && ((instance._pendingVisibility |= 2), - scheduleUpdateOnFiber(root, fiber, 2, -1)); + scheduleUpdateOnFiber(root, fiber, 2)); } } function attachOffscreenInstance(instance) { @@ -6300,7 +6559,7 @@ function attachOffscreenInstance(instance) { var root = enqueueConcurrentRenderForLane(fiber, 2); null !== root && ((instance._pendingVisibility &= -3), - scheduleUpdateOnFiber(root, fiber, 2, -1)); + scheduleUpdateOnFiber(root, fiber, 2)); } } function attachSuspenseRetryListeners(finishedWork, wakeables) { @@ -7403,203 +7662,6 @@ var DefaultCacheDispatcher = { return cacheForType; } }, - firstScheduledRoot = null, - lastScheduledRoot = null, - didScheduleMicrotask = !1, - mightHavePendingSyncWork = !1, - isFlushingWork = !1; -function ensureRootIsScheduled(root) { - root !== lastScheduledRoot && - null === root.next && - (null === lastScheduledRoot - ? (firstScheduledRoot = lastScheduledRoot = root) - : (lastScheduledRoot = lastScheduledRoot.next = root)); - mightHavePendingSyncWork = !0; - didScheduleMicrotask || - ((didScheduleMicrotask = !0), - scheduleCallback$3(ImmediatePriority, processRootScheduleInMicrotask)); - enableDeferRootSchedulingToMicrotask || - scheduleTaskForRootDuringMicrotask(root, now()); -} -function flushSyncWorkAcrossRoots_impl(onlyLegacy) { - if (!isFlushingWork && mightHavePendingSyncWork) { - var workInProgressRoot$jscomp$0 = workInProgressRoot, - workInProgressRootRenderLanes$jscomp$0 = workInProgressRootRenderLanes, - errors = null; - isFlushingWork = !0; - do { - var didPerformSomeWork = !1; - for (var root = firstScheduledRoot; null !== root; ) { - if ( - (!onlyLegacy || 0 === root.tag) && - 0 !== - (getNextLanes( - root, - root === workInProgressRoot$jscomp$0 - ? workInProgressRootRenderLanes$jscomp$0 - : 0 - ) & - 3) - ) - try { - didPerformSomeWork = !0; - var root$jscomp$0 = root; - if (0 !== (executionContext & 6)) - throw Error(formatProdErrorMessage(327)); - flushPassiveEffects(); - var lanes = getNextLanes(root$jscomp$0, 0); - if (0 !== (lanes & 3)) { - var exitStatus = renderRootSync(root$jscomp$0, lanes); - if (0 !== root$jscomp$0.tag && 2 === exitStatus) { - var originallyAttemptedLanes = lanes, - errorRetryLanes = getLanesToRetrySynchronouslyOnError( - root$jscomp$0, - originallyAttemptedLanes - ); - 0 !== errorRetryLanes && - ((lanes = errorRetryLanes), - (exitStatus = recoverFromConcurrentError( - root$jscomp$0, - originallyAttemptedLanes, - errorRetryLanes - ))); - } - if (1 === exitStatus) - throw ( - ((originallyAttemptedLanes = workInProgressRootFatalError), - prepareFreshStack(root$jscomp$0, 0), - markRootSuspended(root$jscomp$0, lanes), - ensureRootIsScheduled(root$jscomp$0), - originallyAttemptedLanes) - ); - 6 === exitStatus - ? markRootSuspended(root$jscomp$0, lanes) - : ((root$jscomp$0.finishedWork = - root$jscomp$0.current.alternate), - (root$jscomp$0.finishedLanes = lanes), - commitRoot( - root$jscomp$0, - workInProgressRootRecoverableErrors, - workInProgressTransitions - )); - } - ensureRootIsScheduled(root$jscomp$0); - } catch (error) { - null === errors ? (errors = [error]) : errors.push(error); - } - root = root.next; - } - } while (didPerformSomeWork); - isFlushingWork = !1; - if (null !== errors) { - if (1 < errors.length) { - if ("function" === typeof AggregateError) - throw new AggregateError(errors); - for (onlyLegacy = 1; onlyLegacy < errors.length; onlyLegacy++) - (workInProgressRoot$jscomp$0 = throwError.bind( - null, - errors[onlyLegacy] - )), - scheduleCallback$3(ImmediatePriority, workInProgressRoot$jscomp$0); - } - throw errors[0]; - } - } -} -function throwError(error) { - throw error; -} -function processRootScheduleInMicrotask() { - mightHavePendingSyncWork = didScheduleMicrotask = !1; - for ( - var currentTime = now(), prev = null, root = firstScheduledRoot; - null !== root; - - ) { - var next = root.next, - nextLanes = scheduleTaskForRootDuringMicrotask(root, currentTime); - 0 === nextLanes - ? ((root.next = null), - null === prev ? (firstScheduledRoot = next) : (prev.next = next), - null === next && (lastScheduledRoot = prev)) - : ((prev = root), - 0 !== (nextLanes & 3) && (mightHavePendingSyncWork = !0)); - root = next; - } - flushSyncWorkAcrossRoots_impl(!1); -} -function scheduleTaskForRootDuringMicrotask(root, currentTime) { - for ( - var suspendedLanes = root.suspendedLanes, - pingedLanes = root.pingedLanes, - expirationTimes = root.expirationTimes, - lanes = root.pendingLanes & -125829121; - 0 < lanes; - - ) { - var index$3 = 31 - clz32(lanes), - lane = 1 << index$3, - expirationTime = expirationTimes[index$3]; - if (-1 === expirationTime) { - if (0 === (lane & suspendedLanes) || 0 !== (lane & pingedLanes)) - expirationTimes[index$3] = computeExpirationTime(lane, currentTime); - } else expirationTime <= currentTime && (root.expiredLanes |= lane); - lanes &= ~lane; - } - currentTime = workInProgressRoot; - suspendedLanes = workInProgressRootRenderLanes; - suspendedLanes = getNextLanes( - root, - root === currentTime ? suspendedLanes : 0 - ); - pingedLanes = root.callbackNode; - if ( - 0 === suspendedLanes || - (root === currentTime && 2 === workInProgressSuspendedReason) || - null !== root.cancelPendingCommit - ) - return ( - null !== pingedLanes && - null !== pingedLanes && - cancelCallback$1(pingedLanes), - (root.callbackNode = null), - (root.callbackPriority = 0) - ); - if (0 !== (suspendedLanes & 3)) - return ( - null !== pingedLanes && - null !== pingedLanes && - cancelCallback$1(pingedLanes), - (root.callbackPriority = 2), - (root.callbackNode = null), - 2 - ); - currentTime = suspendedLanes & -suspendedLanes; - if (currentTime === root.callbackPriority) return currentTime; - null !== pingedLanes && cancelCallback$1(pingedLanes); - switch (lanesToEventPriority(suspendedLanes)) { - case 2: - suspendedLanes = ImmediatePriority; - break; - case 8: - suspendedLanes = UserBlockingPriority; - break; - case 32: - suspendedLanes = NormalPriority$1; - break; - case 536870912: - suspendedLanes = IdlePriority; - break; - default: - suspendedLanes = NormalPriority$1; - } - pingedLanes = performConcurrentWorkOnRoot.bind(null, root); - suspendedLanes = scheduleCallback$3(suspendedLanes, pingedLanes); - root.callbackPriority = currentTime; - root.callbackNode = suspendedLanes; - return currentTime; -} -var ceil = Math.ceil, PossiblyWeakMap = "function" === typeof WeakMap ? WeakMap : Map, ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher, ReactCurrentCache = ReactSharedInternals.ReactCurrentCache, @@ -7695,52 +7757,43 @@ var hasUncaughtError = !1, pendingPassiveEffectsRemainingLanes = 0, pendingPassiveTransitions = null, nestedUpdateCount = 0, - rootWithNestedUpdates = null, - currentEventTime = -1, - currentEventTransitionLane = 0; -function requestEventTime() { - return 0 !== (executionContext & 6) - ? now() - : -1 !== currentEventTime - ? currentEventTime - : (currentEventTime = now()); -} + rootWithNestedUpdates = null; function requestUpdateLane(fiber) { if (0 === (fiber.mode & 1)) return 2; if (0 !== (executionContext & 2) && 0 !== workInProgressRootRenderLanes) return workInProgressRootRenderLanes & -workInProgressRootRenderLanes; if (null !== ReactCurrentBatchConfig$1.transition) return ( - 0 === currentEventTransitionLane && - (currentEventTransitionLane = claimNextTransitionLane()), - currentEventTransitionLane + (fiber = currentAsyncAction), + null !== fiber ? fiber.lane : requestTransitionLane() ); fiber = currentUpdatePriority; return 0 !== fiber ? fiber : 32; } -function scheduleUpdateOnFiber(root, fiber, lane, eventTime) { +function scheduleUpdateOnFiber(root, fiber, lane) { if ( (root === workInProgressRoot && 2 === workInProgressSuspendedReason) || null !== root.cancelPendingCommit ) prepareFreshStack(root, 0), markRootSuspended(root, workInProgressRootRenderLanes); - markRootUpdated(root, lane, eventTime); + markRootUpdated(root, lane); if (0 === (executionContext & 2) || root !== workInProgressRoot) { - if ( - enableTransitionTracing && - ((eventTime = ReactCurrentBatchConfig.transition), - null !== eventTime && - null != eventTime.name && - (-1 === eventTime.startTime && (eventTime.startTime = now()), - enableTransitionTracing)) - ) { - var transitionLanesMap = root.transitionLanes, - index$7 = 31 - clz32(lane), - transitions = transitionLanesMap[index$7]; - null === transitions && (transitions = new Set()); - transitions.add(eventTime); - transitionLanesMap[index$7] = transitions; + if (enableTransitionTracing) { + var transition = ReactCurrentBatchConfig.transition; + if ( + null !== transition && + null != transition.name && + (-1 === transition.startTime && (transition.startTime = now()), + enableTransitionTracing) + ) { + var transitionLanesMap = root.transitionLanes, + index$6 = 31 - clz32(lane), + transitions = transitionLanesMap[index$6]; + null === transitions && (transitions = new Set()); + transitions.add(transition); + transitionLanesMap[index$6] = transitions; + } } root === workInProgressRoot && (0 === (executionContext & 2) && @@ -7756,8 +7809,6 @@ function scheduleUpdateOnFiber(root, fiber, lane, eventTime) { } } function performConcurrentWorkOnRoot(root, didTimeout) { - currentEventTime = -1; - currentEventTransitionLane = 0; if (0 !== (executionContext & 6)) throw Error(formatProdErrorMessage(327)); var originalCallbackNode = root.callbackNode; if (flushPassiveEffects() && root.callbackNode !== originalCallbackNode) @@ -7807,16 +7858,16 @@ function performConcurrentWorkOnRoot(root, didTimeout) { exitStatus = renderRootSync(root, lanes); if (2 === exitStatus) { errorRetryLanes = lanes; - var errorRetryLanes$128 = getLanesToRetrySynchronouslyOnError( + var errorRetryLanes$127 = getLanesToRetrySynchronouslyOnError( root, errorRetryLanes ); - 0 !== errorRetryLanes$128 && - ((lanes = errorRetryLanes$128), + 0 !== errorRetryLanes$127 && + ((lanes = errorRetryLanes$127), (exitStatus = recoverFromConcurrentError( root, errorRetryLanes, - errorRetryLanes$128 + errorRetryLanes$127 ))); } if (1 === exitStatus) @@ -7830,109 +7881,52 @@ function performConcurrentWorkOnRoot(root, didTimeout) { } root.finishedWork = didTimeout; root.finishedLanes = lanes; - switch (exitStatus) { - case 0: - case 1: - throw Error(formatProdErrorMessage(345)); - case 2: - commitRootWhenReady( - root, - didTimeout, - workInProgressRootRecoverableErrors, - workInProgressTransitions, - lanes - ); - break; - case 3: - markRootSuspended(root, lanes); - if ( - (lanes & 125829120) === lanes && - ((exitStatus = globalMostRecentFallbackTime + 500 - now()), - 10 < exitStatus) - ) { - if (0 !== getNextLanes(root, 0)) break; - root.timeoutHandle = scheduleTimeout( - commitRootWhenReady.bind( - null, - root, - didTimeout, - workInProgressRootRecoverableErrors, - workInProgressTransitions, - lanes - ), - exitStatus - ); + a: { + switch (exitStatus) { + case 0: + case 1: + throw Error(formatProdErrorMessage(345)); + case 4: + if ((lanes & 8388480) === lanes) { + markRootSuspended(root, lanes); + break a; + } break; - } - commitRootWhenReady( - root, - didTimeout, - workInProgressRootRecoverableErrors, - workInProgressTransitions, - lanes - ); - break; - case 4: - markRootSuspended(root, lanes); - if ((lanes & 8388480) === lanes) break; - exitStatus = lanes; - errorRetryLanes = root.eventTimes; - for (errorRetryLanes$128 = -1; 0 < exitStatus; ) { - var index$2 = 31 - clz32(exitStatus), - lane = 1 << index$2; - index$2 = errorRetryLanes[index$2]; - index$2 > errorRetryLanes$128 && (errorRetryLanes$128 = index$2); - exitStatus &= ~lane; - } - exitStatus = errorRetryLanes$128; - exitStatus = now() - exitStatus; - exitStatus = - (120 > exitStatus - ? 120 - : 480 > exitStatus - ? 480 - : 1080 > exitStatus - ? 1080 - : 1920 > exitStatus - ? 1920 - : 3e3 > exitStatus - ? 3e3 - : 4320 > exitStatus - ? 4320 - : 1960 * ceil(exitStatus / 1960)) - exitStatus; - if (10 < exitStatus) { - root.timeoutHandle = scheduleTimeout( - commitRootWhenReady.bind( - null, - root, - didTimeout, - workInProgressRootRecoverableErrors, - workInProgressTransitions, - lanes - ), - exitStatus - ); + case 2: + case 3: + case 5: break; - } - commitRootWhenReady( - root, - didTimeout, - workInProgressRootRecoverableErrors, - workInProgressTransitions, - lanes + default: + throw Error(formatProdErrorMessage(329)); + } + if ( + (lanes & 125829120) === lanes && + (alwaysThrottleRetries || 3 === exitStatus) && + ((exitStatus = globalMostRecentFallbackTime + 500 - now()), + 10 < exitStatus) + ) { + markRootSuspended(root, lanes); + if (0 !== getNextLanes(root, 0)) break a; + root.timeoutHandle = scheduleTimeout( + commitRootWhenReady.bind( + null, + root, + didTimeout, + workInProgressRootRecoverableErrors, + workInProgressTransitions, + lanes + ), + exitStatus ); - break; - case 5: - commitRootWhenReady( - root, - didTimeout, - workInProgressRootRecoverableErrors, - workInProgressTransitions, - lanes - ); - break; - default: - throw Error(formatProdErrorMessage(329)); + break a; + } + commitRootWhenReady( + root, + didTimeout, + workInProgressRootRecoverableErrors, + workInProgressTransitions, + lanes + ); } } } @@ -7983,11 +7977,7 @@ function commitRootWhenReady( lanes ) { 0 === (lanes & 42) && accumulateSuspenseyCommitOnFiber(finishedWork); - commitRoot( - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ); + commitRoot(root, recoverableErrors, transitions); } function isRenderConsistentWithExternalStores(finishedWork) { for (var node = finishedWork; ; ) { @@ -8029,9 +8019,9 @@ function markRootSuspended(root, suspendedLanes) { root.suspendedLanes |= suspendedLanes; root.pingedLanes &= ~suspendedLanes; for (root = root.expirationTimes; 0 < suspendedLanes; ) { - var index$4 = 31 - clz32(suspendedLanes), - lane = 1 << index$4; - root[index$4] = -1; + var index$3 = 31 - clz32(suspendedLanes), + lane = 1 << index$3; + root[index$3] = -1; suspendedLanes &= ~lane; } } @@ -8159,8 +8149,8 @@ function renderRootSync(root, lanes) { } workLoopSync(); break; - } catch (thrownValue$131) { - handleThrow(root, thrownValue$131); + } catch (thrownValue$129) { + handleThrow(root, thrownValue$129); } while (1); resetContextDependencies(); @@ -8264,8 +8254,8 @@ function renderRootConcurrent(root, lanes) { } workLoopConcurrent(); break; - } catch (thrownValue$133) { - handleThrow(root, thrownValue$133); + } catch (thrownValue$131) { + handleThrow(root, thrownValue$131); } while (1); resetContextDependencies(); @@ -8326,6 +8316,8 @@ function replaySuspendedUnitOfWork(unitOfWork) { workInProgressRootRenderLanes ); break; + case 5: + resetHooksOnUnwind(); default: unwindInterruptedWork(current, unitOfWork), (unitOfWork = workInProgress = @@ -8509,21 +8501,31 @@ function throwAndUnwindWorkLoop(unitOfWork, thrownValue) { } catch (error) { throw ((workInProgress = returnFiber), error); } - unitOfWork.flags & 32768 - ? unwindUnitOfWork(unitOfWork) - : completeUnitOfWork(unitOfWork); + if (unitOfWork.flags & 32768) + a: { + do { + returnFiber = unwindWork(unitOfWork.alternate, unitOfWork); + if (null !== returnFiber) { + returnFiber.flags &= 32767; + workInProgress = returnFiber; + break a; + } + unitOfWork = unitOfWork.return; + null !== unitOfWork && + ((unitOfWork.flags |= 32768), + (unitOfWork.subtreeFlags = 0), + (unitOfWork.deletions = null)); + workInProgress = unitOfWork; + } while (null !== unitOfWork); + workInProgressRootExitStatus = 6; + workInProgress = null; + } + else completeUnitOfWork(unitOfWork); } } function completeUnitOfWork(unitOfWork) { var completedWork = unitOfWork; do { - if ( - revertRemovalOfSiblingPrerendering && - 0 !== (completedWork.flags & 32768) - ) { - unwindUnitOfWork(completedWork); - return; - } unitOfWork = completedWork.return; var next = completeWork( completedWork.alternate, @@ -8543,29 +8545,6 @@ function completeUnitOfWork(unitOfWork) { } while (null !== completedWork); 0 === workInProgressRootExitStatus && (workInProgressRootExitStatus = 5); } -function unwindUnitOfWork(unitOfWork) { - do { - var next = unwindWork(unitOfWork.alternate, unitOfWork); - if (null !== next) { - next.flags &= 32767; - workInProgress = next; - return; - } - next = unitOfWork.return; - null !== next && - ((next.flags |= 32768), (next.subtreeFlags = 0), (next.deletions = null)); - if ( - revertRemovalOfSiblingPrerendering && - ((unitOfWork = unitOfWork.sibling), null !== unitOfWork) - ) { - workInProgress = unitOfWork; - return; - } - workInProgress = unitOfWork = next; - } while (null !== unitOfWork); - workInProgressRootExitStatus = 6; - workInProgress = null; -} function commitRoot(root, recoverableErrors, transitions) { var previousUpdateLanePriority = currentUpdatePriority, prevTransition = ReactCurrentBatchConfig.transition; @@ -8746,10 +8725,8 @@ function captureCommitPhaseErrorOnRoot(rootFiber, sourceFiber, error) { sourceFiber = createCapturedValueAtFiber(error, sourceFiber); sourceFiber = createRootErrorUpdate(rootFiber, sourceFiber, 2); rootFiber = enqueueUpdate(rootFiber, sourceFiber, 2); - sourceFiber = requestEventTime(); null !== rootFiber && - (markRootUpdated(rootFiber, 2, sourceFiber), - ensureRootIsScheduled(rootFiber)); + (markRootUpdated(rootFiber, 2), ensureRootIsScheduled(rootFiber)); } function captureCommitPhaseError(sourceFiber, nearestMountedAncestor, error) { if (3 === sourceFiber.tag) @@ -8783,9 +8760,8 @@ function captureCommitPhaseError(sourceFiber, nearestMountedAncestor, error) { sourceFiber, 2 ); - sourceFiber = requestEventTime(); null !== nearestMountedAncestor && - (markRootUpdated(nearestMountedAncestor, 2, sourceFiber), + (markRootUpdated(nearestMountedAncestor, 2), ensureRootIsScheduled(nearestMountedAncestor)); break; } @@ -8827,10 +8803,9 @@ function pingSuspendedRoot(root, wakeable, pingedLanes) { function retryTimedOutBoundary(boundaryFiber, retryLane) { 0 === retryLane && (retryLane = 0 === (boundaryFiber.mode & 1) ? 2 : claimNextRetryLane()); - var eventTime = requestEventTime(); boundaryFiber = enqueueConcurrentRenderForLane(boundaryFiber, retryLane); null !== boundaryFiber && - (markRootUpdated(boundaryFiber, retryLane, eventTime), + (markRootUpdated(boundaryFiber, retryLane), ensureRootIsScheduled(boundaryFiber)); } function retryDehydratedSuspenseBoundary(boundaryFiber) { @@ -9573,7 +9548,6 @@ function FiberRootNode( this.cancelPendingCommit = null; this.callbackPriority = 0; - this.eventTimes = createLaneMap(0); this.expirationTimes = createLaneMap(-1); this.entangledLanes = this.errorRecoveryDisabledLanes = @@ -9614,8 +9588,7 @@ function updateContainer(element, container, parentComponent, callback) { null !== callback && (container.callback = callback); element = enqueueUpdate(parentComponent, container, lane); null !== element && - ((callback = requestEventTime()), - scheduleUpdateOnFiber(element, parentComponent, lane, callback), + (scheduleUpdateOnFiber(element, parentComponent, lane), entangleTransitions(element, parentComponent, lane)); return lane; } @@ -9743,10 +9716,10 @@ var slice = Array.prototype.slice, return null; }, bundleType: 0, - version: "18.3.0-www-modern-52157a92", + version: "18.3.0-www-modern-cbca888b", rendererPackageName: "react-art" }; -var internals$jscomp$inline_1324 = { +var internals$jscomp$inline_1315 = { bundleType: devToolsConfig$jscomp$inline_1150.bundleType, version: devToolsConfig$jscomp$inline_1150.version, rendererPackageName: devToolsConfig$jscomp$inline_1150.rendererPackageName, @@ -9774,19 +9747,19 @@ var internals$jscomp$inline_1324 = { scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "18.3.0-www-modern-52157a92" + reconcilerVersion: "18.3.0-www-modern-cbca888b" }; if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { - var hook$jscomp$inline_1325 = __REACT_DEVTOOLS_GLOBAL_HOOK__; + var hook$jscomp$inline_1316 = __REACT_DEVTOOLS_GLOBAL_HOOK__; if ( - !hook$jscomp$inline_1325.isDisabled && - hook$jscomp$inline_1325.supportsFiber + !hook$jscomp$inline_1316.isDisabled && + hook$jscomp$inline_1316.supportsFiber ) try { - (rendererID = hook$jscomp$inline_1325.inject( - internals$jscomp$inline_1324 + (rendererID = hook$jscomp$inline_1316.inject( + internals$jscomp$inline_1315 )), - (injectedHook = hook$jscomp$inline_1325); + (injectedHook = hook$jscomp$inline_1316); } catch (err) {} } var Path = Mode$1.Path; diff --git a/compiled/facebook-www/ReactDOM-dev.classic.js b/compiled/facebook-www/ReactDOM-dev.classic.js index 819277ee33..1f8785def5 100644 --- a/compiled/facebook-www/ReactDOM-dev.classic.js +++ b/compiled/facebook-www/ReactDOM-dev.classic.js @@ -129,8 +129,6 @@ var disableInputAttributeSyncing = disableIEWorkarounds = dynamicFeatureFlags.disableIEWorkarounds, enableTrustedTypesIntegration = dynamicFeatureFlags.enableTrustedTypesIntegration, - revertRemovalOfSiblingPrerendering = - dynamicFeatureFlags.revertRemovalOfSiblingPrerendering, replayFailedUnitOfWorkWithInvokeGuardedCallback = dynamicFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback, enableLegacyFBSupport = dynamicFeatureFlags.enableLegacyFBSupport, @@ -145,7 +143,9 @@ var disableInputAttributeSyncing = dynamicFeatureFlags.enableCustomElementPropertySupport, enableDeferRootSchedulingToMicrotask = dynamicFeatureFlags.enableDeferRootSchedulingToMicrotask, - diffInCommitPhase = dynamicFeatureFlags.diffInCommitPhase; // On WWW, false is used for a new modern build. + diffInCommitPhase = dynamicFeatureFlags.diffInCommitPhase, + enableAsyncActions = dynamicFeatureFlags.enableAsyncActions, + alwaysThrottleRetries = dynamicFeatureFlags.alwaysThrottleRetries; // On WWW, false is used for a new modern build. var enableProfilerTimer = true; var enableProfilerCommitHooks = true; var enableProfilerNestedUpdatePhase = true; @@ -2084,24 +2084,6 @@ function getNextLanes(root, wipLanes) { return nextLanes; } -function getMostRecentEventTime(root, lanes) { - var eventTimes = root.eventTimes; - var mostRecentEventTime = NoTimestamp; - - while (lanes > 0) { - var index = pickArbitraryLaneIndex(lanes); - var lane = 1 << index; - var eventTime = eventTimes[index]; - - if (eventTime > mostRecentEventTime) { - mostRecentEventTime = eventTime; - } - - lanes &= ~lane; - } - - return mostRecentEventTime; -} function computeExpirationTime(lane, currentTime) { switch (lane) { @@ -2348,7 +2330,7 @@ function createLaneMap(initial) { return laneMap; } -function markRootUpdated(root, updateLane, eventTime) { +function markRootUpdated(root, updateLane) { root.pendingLanes |= updateLane; // If there are any suspended transitions, it's possible this new update // could unblock them. Clear the suspended lanes so that we can try rendering // them again. @@ -2366,12 +2348,6 @@ function markRootUpdated(root, updateLane, eventTime) { root.suspendedLanes = NoLanes; root.pingedLanes = NoLanes; } - - var eventTimes = root.eventTimes; - var index = laneToIndex(updateLane); // We can always overwrite an existing timestamp because we prefer the most - // recent event, and we assume time is monotonically increasing. - - eventTimes[index] = eventTime; } function markRootSuspended$1(root, suspendedLanes) { root.suspendedLanes |= suspendedLanes; @@ -2404,7 +2380,6 @@ function markRootFinished(root, remainingLanes) { root.entangledLanes &= remainingLanes; root.errorRecoveryDisabledLanes &= remainingLanes; var entanglements = root.entanglements; - var eventTimes = root.eventTimes; var expirationTimes = root.expirationTimes; var hiddenUpdates = root.hiddenUpdates; // Clear the lanes that no longer have pending work @@ -2414,7 +2389,6 @@ function markRootFinished(root, remainingLanes) { var index = pickArbitraryLaneIndex(lanes); var lane = 1 << index; entanglements[index] = NoLanes; - eventTimes[index] = NoTimestamp; expirationTimes[index] = NoTimestamp; var hiddenUpdatesForLane = hiddenUpdates[index]; @@ -2840,14 +2814,6 @@ function checkFormFieldValueStringCoercion(value) { } } -var Internals = { - usingClientEntryPoint: false, - Events: null, - Dispatcher: { - current: null - } -}; - var allNativeEvents = new Set(); { @@ -3170,7 +3136,7 @@ function setValueForNamespacedAttribute(node, namespace, name, value) { function setValueForPropertyOnCustomComponent(node, name, value) { if (name[0] === "o" && name[1] === "n") { var useCapture = name.endsWith("Capture"); - var eventName = name.substr(2, useCapture ? name.length - 9 : undefined); + var eventName = name.slice(2, useCapture ? name.length - 7 : undefined); var prevProps = getFiberCurrentPropsFromNode(node); var prevValue = prevProps != null ? prevProps[name] : null; @@ -3740,6 +3706,21 @@ function getActiveElement(doc) { } } +// When passing user input into querySelector(All) the embedded string must not alter +// the semantics of the query. This escape function is safe to use when we know the +// provided value is going to be wrapped in double quotes as part of an attribute selector +// Do not use it anywhere else +// we escape double quotes and backslashes +var escapeSelectorAttributeValueInsideDoubleQuotesRegex = /[\n\"\\]/g; +function escapeSelectorAttributeValueInsideDoubleQuotes(value) { + return value.replace( + escapeSelectorAttributeValueInsideDoubleQuotesRegex, + function (ch) { + return "\\" + ch.charCodeAt(0).toString(16) + " "; + } + ); +} + var didWarnValueDefaultValue$1 = false; var didWarnCheckedDefaultChecked = false; /** @@ -3810,9 +3791,30 @@ function updateInput( lastDefaultValue, checked, defaultChecked, - type + type, + name ) { - var node = element; + var node = element; // Temporarily disconnect the input from any radio buttons. + // Changing the type or name as the same time as changing the checked value + // needs to be atomically applied. We can only ensure that by disconnecting + // the name while do the mutations and then reapply the name after that's done. + + node.name = ""; + + if ( + type != null && + typeof type !== "function" && + typeof type !== "symbol" && + typeof type !== "boolean" + ) { + { + checkAttributeStringCoercion(type, "type"); + } + + node.type = type; + } else { + node.removeAttribute("type"); + } if (value != null) { if (type === "number") { @@ -3831,7 +3833,6 @@ function updateInput( // Submit/reset inputs need the attribute removed completely to avoid // blank-text buttons. node.removeAttribute("value"); - return; } if (disableInputAttributeSyncing) { @@ -3878,6 +3879,21 @@ function updateInput( if (checked != null && node.checked !== !!checked) { node.checked = checked; } + + if ( + name != null && + typeof name !== "function" && + typeof name !== "symbol" && + typeof name !== "boolean" + ) { + { + checkAttributeStringCoercion(name, "name"); + } + + node.name = toString(getToStringValue(name)); + } else { + node.removeAttribute("name"); + } } function initInput( element, @@ -3886,10 +3902,24 @@ function initInput( checked, defaultChecked, type, + name, isHydrating ) { var node = element; + if ( + type != null && + typeof type !== "function" && + typeof type !== "symbol" && + typeof type !== "boolean" + ) { + { + checkAttributeStringCoercion(type, "type"); + } + + node.type = type; + } + if (value != null || defaultValue != null) { var isButton = type === "submit" || type === "reset"; // Avoid setting value attribute on submit/reset inputs as it overrides the // default value provided by the browser. See: #12872 @@ -3952,12 +3982,6 @@ function initInput( // Reference: https://bugs.chromium.org/p/chromium/issues/detail?id=608416 // We need to temporarily unset name to avoid disrupting radio button groups. - var name = node.name; - - if (name !== "") { - node.name = ""; - } - var checkedOrDefault = checked != null ? checked : defaultChecked; // TODO: This 'function' or 'symbol' check isn't replicated in other places // so this semantic is inconsistent. @@ -3991,9 +4015,18 @@ function initInput( // 3. Otherwise, false node.defaultChecked = !node.defaultChecked; node.defaultChecked = !!initialChecked; - } + } // Name needs to be set at the end so that it applies atomically to connected radio buttons. + + if ( + name != null && + typeof name !== "function" && + typeof name !== "symbol" && + typeof name !== "boolean" + ) { + { + checkAttributeStringCoercion(name, "name"); + } - if (name !== "") { node.name = name; } } @@ -4006,7 +4039,8 @@ function restoreControlledInputState(element, props) { props.defaultValue, props.checked, props.defaultChecked, - props.type + props.type, + props.name ); var name = props.name; @@ -4028,7 +4062,9 @@ function restoreControlledInputState(element, props) { } var group = queryRoot.querySelectorAll( - "input[name=" + JSON.stringify("" + name) + '][type="radio"]' + 'input[name="' + + escapeSelectorAttributeValueInsideDoubleQuotes("" + name) + + '"][type="radio"]' ); for (var i = 0; i < group.length; i++) { @@ -4062,7 +4098,8 @@ function restoreControlledInputState(element, props) { otherProps.defaultValue, otherProps.checked, otherProps.defaultChecked, - otherProps.type + otherProps.type, + otherProps.name ); } } @@ -4927,35 +4964,8 @@ function validateTextNesting(childText, parentTag) { } } -var HTML_NAMESPACE = "http://www.w3.org/1999/xhtml"; var MATH_NAMESPACE = "http://www.w3.org/1998/Math/MathML"; -var SVG_NAMESPACE = "http://www.w3.org/2000/svg"; // Assumes there is no parent namespace. - -function getIntrinsicNamespace(type) { - switch (type) { - case "svg": - return SVG_NAMESPACE; - - case "math": - return MATH_NAMESPACE; - - default: - return HTML_NAMESPACE; - } -} -function getChildNamespace(parentNamespace, type) { - if (parentNamespace == null || parentNamespace === HTML_NAMESPACE) { - // No (or default) parent namespace: potential entry point. - return getIntrinsicNamespace(type); - } - - if (parentNamespace === SVG_NAMESPACE && type === "foreignObject") { - // We're leaving SVG. - return HTML_NAMESPACE; - } // By default, pass namespace below. - - return parentNamespace; -} +var SVG_NAMESPACE = "http://www.w3.org/2000/svg"; var reusableSVGContainer; @@ -6557,7 +6567,7 @@ function validateProperty(tagName, name, value, eventRegistry) { warnedProperties[name] = true; return true; - } // We can't rely on the event system being injected on the server. + } if (eventRegistry != null) { var registrationNameDependencies = @@ -11852,6 +11862,515 @@ function registerMutableSourceForHydration(root, mutableSource) { } } +var ReactCurrentActQueue$2 = ReactSharedInternals.ReactCurrentActQueue; // A linked list of all the roots with pending work. In an idiomatic app, +// there's only a single root, but we do support multi root apps, hence this +// extra complexity. But this module is optimized for the single root case. + +var firstScheduledRoot = null; +var lastScheduledRoot = null; // Used to prevent redundant mircotasks from being scheduled. + +var didScheduleMicrotask = false; // `act` "microtasks" are scheduled on the `act` queue instead of an actual +// microtask, so we have to dedupe those separately. This wouldn't be an issue +// if we required all `act` calls to be awaited, which we might in the future. + +var didScheduleMicrotask_act = false; // Used to quickly bail out of flushSync if there's no sync work to do. + +var mightHavePendingSyncWork = false; +var isFlushingWork = false; +var currentEventTransitionLane = NoLane; +function ensureRootIsScheduled(root) { + // This function is called whenever a root receives an update. It does two + // things 1) it ensures the root is in the root schedule, and 2) it ensures + // there's a pending microtask to process the root schedule. + // + // Most of the actual scheduling logic does not happen until + // `scheduleTaskForRootDuringMicrotask` runs. + // Add the root to the schedule + if (root === lastScheduledRoot || root.next !== null); + else { + if (lastScheduledRoot === null) { + firstScheduledRoot = lastScheduledRoot = root; + } else { + lastScheduledRoot.next = root; + lastScheduledRoot = root; + } + } // Any time a root received an update, we set this to true until the next time + // we process the schedule. If it's false, then we can quickly exit flushSync + // without consulting the schedule. + + mightHavePendingSyncWork = true; // At the end of the current event, go through each of the roots and ensure + // there's a task scheduled for each one at the correct priority. + + if (ReactCurrentActQueue$2.current !== null) { + // We're inside an `act` scope. + if (!didScheduleMicrotask_act) { + didScheduleMicrotask_act = true; + scheduleImmediateTask(processRootScheduleInMicrotask); + } + } else { + if (!didScheduleMicrotask) { + didScheduleMicrotask = true; + scheduleImmediateTask(processRootScheduleInMicrotask); + } + } + + if (!enableDeferRootSchedulingToMicrotask) { + // While this flag is disabled, we schedule the render task immediately + // instead of waiting a microtask. + // TODO: We need to land enableDeferRootSchedulingToMicrotask ASAP to + // unblock additional features we have planned. + scheduleTaskForRootDuringMicrotask(root, now$1()); + } + + if (ReactCurrentActQueue$2.isBatchingLegacy && root.tag === LegacyRoot) { + // Special `act` case: Record whenever a legacy update is scheduled. + ReactCurrentActQueue$2.didScheduleLegacyUpdate = true; + } +} +function flushSyncWorkOnAllRoots() { + // This is allowed to be called synchronously, but the caller should check + // the execution context first. + flushSyncWorkAcrossRoots_impl(false); +} +function flushSyncWorkOnLegacyRootsOnly() { + // This is allowed to be called synchronously, but the caller should check + // the execution context first. + flushSyncWorkAcrossRoots_impl(true); +} + +function flushSyncWorkAcrossRoots_impl(onlyLegacy) { + if (isFlushingWork) { + // Prevent reentrancy. + // TODO: Is this overly defensive? The callers must check the execution + // context first regardless. + return; + } + + if (!mightHavePendingSyncWork) { + // Fast path. There's no sync work to do. + return; + } + + var workInProgressRoot = getWorkInProgressRoot(); + var workInProgressRootRenderLanes = getWorkInProgressRootRenderLanes(); // There may or may not be synchronous work scheduled. Let's check. + + var didPerformSomeWork; + var errors = null; + isFlushingWork = true; + + do { + didPerformSomeWork = false; + var root = firstScheduledRoot; + + while (root !== null) { + if (onlyLegacy && root.tag !== LegacyRoot); + else { + var nextLanes = getNextLanes( + root, + root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes + ); + + if (includesSyncLane(nextLanes)) { + // This root has pending sync work. Flush it now. + try { + // TODO: Pass nextLanes as an argument instead of computing it again + // inside performSyncWorkOnRoot. + didPerformSomeWork = true; + performSyncWorkOnRoot(root); + } catch (error) { + // Collect errors so we can rethrow them at the end + if (errors === null) { + errors = [error]; + } else { + errors.push(error); + } + } + } + } + + root = root.next; + } + } while (didPerformSomeWork); + + isFlushingWork = false; // If any errors were thrown, rethrow them right before exiting. + // TODO: Consider returning these to the caller, to allow them to decide + // how/when to rethrow. + + if (errors !== null) { + if (errors.length > 1) { + if (typeof AggregateError === "function") { + // eslint-disable-next-line no-undef + throw new AggregateError(errors); + } else { + for (var i = 1; i < errors.length; i++) { + scheduleImmediateTask(throwError.bind(null, errors[i])); + } + + var firstError = errors[0]; + throw firstError; + } + } else { + var error = errors[0]; + throw error; + } + } +} + +function throwError(error) { + throw error; +} + +function processRootScheduleInMicrotask() { + // This function is always called inside a microtask. It should never be + // called synchronously. + didScheduleMicrotask = false; + + { + didScheduleMicrotask_act = false; + } // We'll recompute this as we iterate through all the roots and schedule them. + + mightHavePendingSyncWork = false; + var currentTime = now$1(); + var prev = null; + var root = firstScheduledRoot; + + while (root !== null) { + var next = root.next; + + if ( + currentEventTransitionLane !== NoLane && + shouldAttemptEagerTransition() + ) { + markRootEntangled(root, mergeLanes(currentEventTransitionLane, SyncLane)); + } + + var nextLanes = scheduleTaskForRootDuringMicrotask(root, currentTime); + + if (nextLanes === NoLane) { + // This root has no more pending work. Remove it from the schedule. To + // guard against subtle reentrancy bugs, this microtask is the only place + // we do this — you can add roots to the schedule whenever, but you can + // only remove them here. + // Null this out so we know it's been removed from the schedule. + root.next = null; + + if (prev === null) { + // This is the new head of the list + firstScheduledRoot = next; + } else { + prev.next = next; + } + + if (next === null) { + // This is the new tail of the list + lastScheduledRoot = prev; + } + } else { + // This root still has work. Keep it in the list. + prev = root; + + if (includesSyncLane(nextLanes)) { + mightHavePendingSyncWork = true; + } + } + + root = next; + } + + currentEventTransitionLane = NoLane; // At the end of the microtask, flush any pending synchronous work. This has + // to come at the end, because it does actual rendering work that might throw. + + flushSyncWorkOnAllRoots(); +} + +function scheduleTaskForRootDuringMicrotask(root, currentTime) { + // This function is always called inside a microtask, or at the very end of a + // rendering task right before we yield to the main thread. It should never be + // called synchronously. + // + // TODO: Unless enableDeferRootSchedulingToMicrotask is off. We need to land + // that ASAP to unblock additional features we have planned. + // + // This function also never performs React work synchronously; it should + // only schedule work to be performed later, in a separate task or microtask. + // Check if any lanes are being starved by other work. If so, mark them as + // expired so we know to work on those next. + markStarvedLanesAsExpired(root, currentTime); // Determine the next lanes to work on, and their priority. + + var workInProgressRoot = getWorkInProgressRoot(); + var workInProgressRootRenderLanes = getWorkInProgressRootRenderLanes(); + var nextLanes = getNextLanes( + root, + root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes + ); + var existingCallbackNode = root.callbackNode; + + if ( + // Check if there's nothing to work on + nextLanes === NoLanes || // If this root is currently suspended and waiting for data to resolve, don't + // schedule a task to render it. We'll either wait for a ping, or wait to + // receive an update. + // + // Suspended render phase + (root === workInProgressRoot && isWorkLoopSuspendedOnData()) || // Suspended commit phase + root.cancelPendingCommit !== null + ) { + // Fast path: There's nothing to work on. + if (existingCallbackNode !== null) { + cancelCallback(existingCallbackNode); + } + + root.callbackNode = null; + root.callbackPriority = NoLane; + return NoLane; + } // Schedule a new callback in the host environment. + + if (includesSyncLane(nextLanes)) { + // Synchronous work is always flushed at the end of the microtask, so we + // don't need to schedule an additional task. + if (existingCallbackNode !== null) { + cancelCallback(existingCallbackNode); + } + + root.callbackPriority = SyncLane; + root.callbackNode = null; + return SyncLane; + } else { + // We use the highest priority lane to represent the priority of the callback. + var existingCallbackPriority = root.callbackPriority; + var newCallbackPriority = getHighestPriorityLane(nextLanes); + + if ( + newCallbackPriority === existingCallbackPriority && // Special case related to `act`. If the currently scheduled task is a + // Scheduler task, rather than an `act` task, cancel it and re-schedule + // on the `act` queue. + !( + ReactCurrentActQueue$2.current !== null && + existingCallbackNode !== fakeActCallbackNode$1 + ) + ) { + // The priority hasn't changed. We can reuse the existing task. + return newCallbackPriority; + } else { + // Cancel the existing callback. We'll schedule a new one below. + cancelCallback(existingCallbackNode); + } + + var schedulerPriorityLevel; + + switch (lanesToEventPriority(nextLanes)) { + case DiscreteEventPriority: + schedulerPriorityLevel = ImmediatePriority; + break; + + case ContinuousEventPriority: + schedulerPriorityLevel = UserBlockingPriority; + break; + + case DefaultEventPriority: + schedulerPriorityLevel = NormalPriority$1; + break; + + case IdleEventPriority: + schedulerPriorityLevel = IdlePriority; + break; + + default: + schedulerPriorityLevel = NormalPriority$1; + break; + } + + var newCallbackNode = scheduleCallback$2( + schedulerPriorityLevel, + performConcurrentWorkOnRoot.bind(null, root) + ); + root.callbackPriority = newCallbackPriority; + root.callbackNode = newCallbackNode; + return newCallbackPriority; + } +} + +function getContinuationForRoot(root, originalCallbackNode) { + // This is called at the end of `performConcurrentWorkOnRoot` to determine + // if we need to schedule a continuation task. + // + // Usually `scheduleTaskForRootDuringMicrotask` only runs inside a microtask; + // however, since most of the logic for determining if we need a continuation + // versus a new task is the same, we cheat a bit and call it here. This is + // only safe to do because we know we're at the end of the browser task. + // So although it's not an actual microtask, it might as well be. + scheduleTaskForRootDuringMicrotask(root, now$1()); + + if (root.callbackNode === originalCallbackNode) { + // The task node scheduled for this root is the same one that's + // currently executed. Need to return a continuation. + return performConcurrentWorkOnRoot.bind(null, root); + } + + return null; +} +var fakeActCallbackNode$1 = {}; + +function scheduleCallback$2(priorityLevel, callback) { + if (ReactCurrentActQueue$2.current !== null) { + // Special case: We're inside an `act` scope (a testing utility). + // Instead of scheduling work in the host environment, add it to a + // fake internal queue that's managed by the `act` implementation. + ReactCurrentActQueue$2.current.push(callback); + return fakeActCallbackNode$1; + } else { + return scheduleCallback$3(priorityLevel, callback); + } +} + +function cancelCallback(callbackNode) { + if (callbackNode === fakeActCallbackNode$1); + else if (callbackNode !== null) { + cancelCallback$1(callbackNode); + } +} + +function scheduleImmediateTask(cb) { + if (ReactCurrentActQueue$2.current !== null) { + // Special case: Inside an `act` scope, we push microtasks to the fake `act` + // callback queue. This is because we currently support calling `act` + // without awaiting the result. The plan is to deprecate that, and require + // that you always await the result so that the microtasks have a chance to + // run. But it hasn't happened yet. + ReactCurrentActQueue$2.current.push(function () { + cb(); + return null; + }); + } // TODO: Can we land supportsMicrotasks? Which environments don't support it? + // Alternatively, can we move this check to the host config? + + { + scheduleMicrotask(function () { + // In Safari, appending an iframe forces microtasks to run. + // https://github.com/facebook/react/issues/22459 + // We don't support running callbacks in the middle of render + // or commit so we need to check against that. + var executionContext = getExecutionContext(); + + if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { + // Note that this would still prematurely flush the callbacks + // if this happens outside render or commit phase (e.g. in an event). + // Intentionally using a macrotask instead of a microtask here. This is + // wrong semantically but it prevents an infinite loop. The bug is + // Safari's, not ours, so we just do our best to not crash even though + // the behavior isn't completely correct. + scheduleCallback$3(ImmediatePriority, cb); + return; + } + + cb(); + }); + } +} + +function requestTransitionLane() { + // The algorithm for assigning an update to a lane should be stable for all + // updates at the same priority within the same event. To do this, the + // inputs to the algorithm must be the same. + // + // The trick we use is to cache the first of each of these inputs within an + // event. Then reset the cached values once we can be sure the event is + // over. Our heuristic for that is whenever we enter a concurrent work loop. + if (currentEventTransitionLane === NoLane) { + // All transitions within the same event are assigned the same lane. + currentEventTransitionLane = claimNextTransitionLane(); + } + + return currentEventTransitionLane; +} + +var currentAsyncAction = null; +function requestAsyncActionContext(actionReturnValue) { + if ( + actionReturnValue !== null && + typeof actionReturnValue === "object" && + typeof actionReturnValue.then === "function" + ) { + // This is an async action. + // + // Return a thenable that resolves once the action scope (i.e. the async + // function passed to startTransition) has finished running. The fulfilled + // value is `false` to represent that the action is not pending. + var thenable = actionReturnValue; + + if (currentAsyncAction === null) { + // There's no outer async action scope. Create a new one. + var asyncAction = { + lane: requestTransitionLane(), + listeners: [], + count: 0, + status: "pending", + value: false, + reason: undefined, + then: function (resolve) { + asyncAction.listeners.push(resolve); + } + }; + attachPingListeners(thenable, asyncAction); + currentAsyncAction = asyncAction; + return asyncAction; + } else { + // Inherit the outer scope. + var _asyncAction = currentAsyncAction; + attachPingListeners(thenable, _asyncAction); + return _asyncAction; + } + } else { + // This is not an async action, but it may be part of an outer async action. + if (currentAsyncAction === null) { + // There's no outer async action scope. + return false; + } else { + // Inherit the outer scope. + return currentAsyncAction; + } + } +} +function peekAsyncActionContext() { + return currentAsyncAction; +} + +function attachPingListeners(thenable, asyncAction) { + asyncAction.count++; + thenable.then( + function () { + if (--asyncAction.count === 0) { + var fulfilledAsyncAction = asyncAction; + fulfilledAsyncAction.status = "fulfilled"; + completeAsyncActionScope(asyncAction); + } + }, + function (error) { + if (--asyncAction.count === 0) { + var rejectedAsyncAction = asyncAction; + rejectedAsyncAction.status = "rejected"; + rejectedAsyncAction.reason = error; + completeAsyncActionScope(asyncAction); + } + } + ); + return asyncAction; +} + +function completeAsyncActionScope(action) { + if (currentAsyncAction === action) { + currentAsyncAction = null; + } + + var listeners = action.listeners; + action.listeners = []; + + for (var i = 0; i < listeners.length; i++) { + var listener = listeners[i]; + listener(false); + } +} + var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, ReactCurrentBatchConfig$3 = ReactSharedInternals.ReactCurrentBatchConfig; var didWarnAboutMismatchedHooksForComponent; @@ -12354,7 +12873,6 @@ function renderWithHooksAgain(workInProgress, Component, props, secondArg) { return children; } - function checkDidRenderIdHook() { // This should be called immediately after every renderWithHooks call. // Conceptually, it's part of the return value of renderWithHooks; it's only a @@ -12538,38 +13056,42 @@ var createFunctionComponentUpdateQueue; }; } +function useThenable(thenable) { + // Track the position of the thenable within this fiber. + var index = thenableIndexCounter; + thenableIndexCounter += 1; + + if (thenableState === null) { + thenableState = createThenableState(); + } + + var result = trackUsedThenable(thenableState, thenable, index); + + if ( + currentlyRenderingFiber$1.alternate === null && + (workInProgressHook === null + ? currentlyRenderingFiber$1.memoizedState === null + : workInProgressHook.next === null) + ) { + // Initial render, and either this is the first time the component is + // called, or there were no Hooks called after this use() the previous + // time (perhaps because it threw). Subsequent Hook calls should use the + // mount dispatcher. + { + ReactCurrentDispatcher$1.current = HooksDispatcherOnMountInDEV; + } + } + + return result; +} + function use(usable) { if (usable !== null && typeof usable === "object") { // $FlowFixMe[method-unbinding] if (typeof usable.then === "function") { // This is a thenable. - var thenable = usable; // Track the position of the thenable within this fiber. - - var index = thenableIndexCounter; - thenableIndexCounter += 1; - - if (thenableState === null) { - thenableState = createThenableState(); - } - - var result = trackUsedThenable(thenableState, thenable, index); - - if ( - currentlyRenderingFiber$1.alternate === null && - (workInProgressHook === null - ? currentlyRenderingFiber$1.memoizedState === null - : workInProgressHook.next === null) - ) { - // Initial render, and either this is the first time the component is - // called, or there were no Hooks called after this use() the previous - // time (perhaps because it threw). Subsequent Hook calls should use the - // mount dispatcher. - { - ReactCurrentDispatcher$1.current = HooksDispatcherOnMountInDEV; - } - } - - return result; + var thenable = usable; + return useThenable(thenable); } else if ( usable.$$typeof === REACT_CONTEXT_TYPE || usable.$$typeof === REACT_SERVER_CONTEXT_TYPE @@ -13361,7 +13883,7 @@ function forceStoreRerender(fiber) { var root = enqueueConcurrentRenderForLane(fiber, SyncLane); if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + scheduleUpdateOnFiber(root, fiber, SyncLane); } } @@ -13898,8 +14420,35 @@ function startTransition(setPending, callback, options) { } try { - setPending(false); - callback(); + if (enableAsyncActions) { + var returnValue = callback(); // `isPending` is either `false` or a thenable that resolves to `false`, + // depending on whether the action scope is an async function. In the + // async case, the resulting render will suspend until the async action + // scope has finished. + + var isPending = requestAsyncActionContext(returnValue); + setPending(isPending); + } else { + // Async actions are not enabled. + setPending(false); + callback(); + } + } catch (error) { + if (enableAsyncActions) { + // This is a trick to get the `useTransition` hook to rethrow the error. + // When it unwraps the thenable with the `use` algorithm, the error + // will be thrown. + var rejectedThenable = { + then: function () {}, + status: "rejected", + reason: error + }; + setPending(rejectedThenable); + } else { + // The error rethrowing behavior is only enabled when the async actions + // feature is on, even for sync actions. + throw error; + } } finally { setCurrentUpdatePriority(previousPriority); ReactCurrentBatchConfig$3.transition = prevTransition; @@ -13924,30 +14473,37 @@ function startTransition(setPending, callback, options) { function mountTransition() { var _mountState = mountState(false), - isPending = _mountState[0], setPending = _mountState[1]; // The `start` method never changes. var start = startTransition.bind(null, setPending); var hook = mountWorkInProgressHook(); hook.memoizedState = start; - return [isPending, start]; + return [false, start]; } function updateTransition() { var _updateState = updateState(), - isPending = _updateState[0]; + booleanOrThenable = _updateState[0]; var hook = updateWorkInProgressHook(); var start = hook.memoizedState; + var isPending = + typeof booleanOrThenable === "boolean" + ? booleanOrThenable // This will suspend until the async action scope has finished. + : useThenable(booleanOrThenable); return [isPending, start]; } function rerenderTransition() { var _rerenderState = rerenderState(), - isPending = _rerenderState[0]; + booleanOrThenable = _rerenderState[0]; var hook = updateWorkInProgressHook(); var start = hook.memoizedState; + var isPending = + typeof booleanOrThenable === "boolean" + ? booleanOrThenable // This will suspend until the async action scope has finished. + : useThenable(booleanOrThenable); return [isPending, start]; } @@ -14022,8 +14578,7 @@ function refreshCache(fiber, seedKey, seedValue) { var root = enqueueUpdate(provider, refreshUpdate, lane); if (root !== null) { - var eventTime = requestEventTime(); - scheduleUpdateOnFiber(root, provider, lane, eventTime); + scheduleUpdateOnFiber(root, provider, lane); entangleTransitions(root, provider, lane); } // TODO: If a refresh never commits, the new cache created here must be // released. A simple case is start refreshing a cache boundary, but then @@ -14077,8 +14632,7 @@ function dispatchReducerAction(fiber, queue, action) { var root = enqueueConcurrentHookUpdate(fiber, queue, update, lane); if (root !== null) { - var eventTime = requestEventTime(); - scheduleUpdateOnFiber(root, fiber, lane, eventTime); + scheduleUpdateOnFiber(root, fiber, lane); entangleTransitionUpdate(root, queue, lane); } } @@ -14161,8 +14715,7 @@ function dispatchSetState(fiber, queue, action) { var root = enqueueConcurrentHookUpdate(fiber, queue, update, lane); if (root !== null) { - var eventTime = requestEventTime(); - scheduleUpdateOnFiber(root, fiber, lane, eventTime); + scheduleUpdateOnFiber(root, fiber, lane); entangleTransitionUpdate(root, queue, lane); } } @@ -14233,6 +14786,7 @@ function markUpdateInDevTools(fiber, lane, action) { var ContextOnlyDispatcher = { readContext: readContext, + use: use, useCallback: throwInvalidHookError, useContext: throwInvalidHookError, useEffect: throwInvalidHookError, @@ -14255,10 +14809,6 @@ var ContextOnlyDispatcher = { ContextOnlyDispatcher.useCacheRefresh = throwInvalidHookError; } -{ - ContextOnlyDispatcher.use = throwInvalidHookError; -} - { ContextOnlyDispatcher.useMemoCache = throwInvalidHookError; } @@ -14298,6 +14848,7 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; readContext: function (context) { return readContext(context); }, + use: use, useCallback: function (callback, deps) { currentHookNameInDev = "useCallback"; mountHookTypesDev(); @@ -14418,10 +14969,6 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; }; } - { - HooksDispatcherOnMountInDEV.use = use; - } - { HooksDispatcherOnMountInDEV.useMemoCache = useMemoCache; } @@ -14440,6 +14987,7 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; readContext: function (context) { return readContext(context); }, + use: use, useCallback: function (callback, deps) { currentHookNameInDev = "useCallback"; updateHookTypesDev(); @@ -14555,10 +15103,6 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; }; } - { - HooksDispatcherOnMountWithHookTypesInDEV.use = use; - } - { HooksDispatcherOnMountWithHookTypesInDEV.useMemoCache = useMemoCache; } @@ -14576,6 +15120,7 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; readContext: function (context) { return readContext(context); }, + use: use, useCallback: function (callback, deps) { currentHookNameInDev = "useCallback"; updateHookTypesDev(); @@ -14690,10 +15235,6 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; }; } - { - HooksDispatcherOnUpdateInDEV.use = use; - } - { HooksDispatcherOnUpdateInDEV.useMemoCache = useMemoCache; } @@ -14712,6 +15253,7 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; readContext: function (context) { return readContext(context); }, + use: use, useCallback: function (callback, deps) { currentHookNameInDev = "useCallback"; updateHookTypesDev(); @@ -14827,10 +15369,6 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; }; } - { - HooksDispatcherOnRerenderInDEV.use = use; - } - { HooksDispatcherOnRerenderInDEV.useMemoCache = useMemoCache; } @@ -14850,6 +15388,10 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; warnInvalidContextAccess(); return readContext(context); }, + use: function (usable) { + warnInvalidHookAccess(); + return use(usable); + }, useCallback: function (callback, deps) { currentHookNameInDev = "useCallback"; warnInvalidHookAccess(); @@ -14981,13 +15523,6 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; }; } - { - InvalidNestedHooksDispatcherOnMountInDEV.use = function (usable) { - warnInvalidHookAccess(); - return use(usable); - }; - } - { InvalidNestedHooksDispatcherOnMountInDEV.useMemoCache = function (size) { warnInvalidHookAccess(); @@ -15010,6 +15545,10 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; warnInvalidContextAccess(); return readContext(context); }, + use: function (usable) { + warnInvalidHookAccess(); + return use(usable); + }, useCallback: function (callback, deps) { currentHookNameInDev = "useCallback"; warnInvalidHookAccess(); @@ -15141,13 +15680,6 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; }; } - { - InvalidNestedHooksDispatcherOnUpdateInDEV.use = function (usable) { - warnInvalidHookAccess(); - return use(usable); - }; - } - { InvalidNestedHooksDispatcherOnUpdateInDEV.useMemoCache = function (size) { warnInvalidHookAccess(); @@ -15170,6 +15702,10 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; warnInvalidContextAccess(); return readContext(context); }, + use: function (usable) { + warnInvalidHookAccess(); + return use(usable); + }, useCallback: function (callback, deps) { currentHookNameInDev = "useCallback"; warnInvalidHookAccess(); @@ -15301,13 +15837,6 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; }; } - { - InvalidNestedHooksDispatcherOnRerenderInDEV.use = function (usable) { - warnInvalidHookAccess(); - return use(usable); - }; - } - { InvalidNestedHooksDispatcherOnRerenderInDEV.useMemoCache = function (size) { warnInvalidHookAccess(); @@ -15649,8 +16178,7 @@ var classComponentUpdater = { var root = enqueueUpdate(fiber, update, lane); if (root !== null) { - var eventTime = requestEventTime(); - scheduleUpdateOnFiber(root, fiber, lane, eventTime); + scheduleUpdateOnFiber(root, fiber, lane); entangleTransitions(root, fiber, lane); } @@ -15685,8 +16213,7 @@ var classComponentUpdater = { var root = enqueueUpdate(fiber, update, lane); if (root !== null) { - var eventTime = requestEventTime(); - scheduleUpdateOnFiber(root, fiber, lane, eventTime); + scheduleUpdateOnFiber(root, fiber, lane); entangleTransitions(root, fiber, lane); } @@ -15721,8 +16248,7 @@ var classComponentUpdater = { var root = enqueueUpdate(fiber, update, lane); if (root !== null) { - var eventTime = requestEventTime(); - scheduleUpdateOnFiber(root, fiber, lane, eventTime); + scheduleUpdateOnFiber(root, fiber, lane); entangleTransitions(root, fiber, lane); } @@ -19970,16 +20496,9 @@ function updateDehydratedSuspenseComponent( // 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; + suspenseState.retryLane = attemptHydrationAtLane; enqueueConcurrentRenderForLane(current, attemptHydrationAtLane); - scheduleUpdateOnFiber( - root, - current, - attemptHydrationAtLane, - eventTime - ); // Throw a special object that signals to the work loop that it should + scheduleUpdateOnFiber(root, current, attemptHydrationAtLane); // Throw a special object that signals to the work loop that it should // interrupt the current render. // // Because we're inside a React-only execution stack, we don't @@ -22010,7 +22529,7 @@ var AbortControllerLocal = }; // Intentionally not named imports because Rollup would // use dynamic dispatch for CommonJS interop named imports. -var scheduleCallback$2 = Scheduler.unstable_scheduleCallback, +var scheduleCallback$1 = Scheduler.unstable_scheduleCallback, NormalPriority = Scheduler.unstable_NormalPriority; var CacheContext = { $$typeof: REACT_CONTEXT_TYPE, @@ -22066,7 +22585,7 @@ function releaseCache(cache) { } if (cache.refCount === 0) { - scheduleCallback$2(NormalPriority, function () { + scheduleCallback$1(NormalPriority, function () { cache.controller.abort(); }); } @@ -26309,7 +26828,7 @@ function detachOffscreenInstance(instance) { if (root !== null) { instance._pendingVisibility |= OffscreenDetached; - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + scheduleUpdateOnFiber(root, fiber, SyncLane); } } function attachOffscreenInstance(instance) { @@ -26330,7 +26849,7 @@ function attachOffscreenInstance(instance) { if (root !== null) { instance._pendingVisibility &= ~OffscreenDetached; - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + scheduleUpdateOnFiber(root, fiber, SyncLane); } } @@ -28568,7 +29087,7 @@ function onCommitRoot() { } } -var ReactCurrentActQueue$2 = ReactSharedInternals.ReactCurrentActQueue; +var ReactCurrentActQueue$1 = ReactSharedInternals.ReactCurrentActQueue; function isLegacyActEnvironment(fiber) { { // Legacy mode. We preserve the behavior of React 17's act. It assumes an @@ -28593,7 +29112,7 @@ function isConcurrentActEnvironment() { if ( !isReactActEnvironmentGlobal && - ReactCurrentActQueue$2.current !== null + ReactCurrentActQueue$1.current !== null ) { // TODO: Include link to relevant documentation page. error( @@ -28624,402 +29143,6 @@ function schedulePostPaintCallback(callback) { } } -var ReactCurrentActQueue$1 = ReactSharedInternals.ReactCurrentActQueue; // A linked list of all the roots with pending work. In an idiomatic app, -// there's only a single root, but we do support multi root apps, hence this -// extra complexity. But this module is optimized for the single root case. - -var firstScheduledRoot = null; -var lastScheduledRoot = null; // Used to prevent redundant mircotasks from being scheduled. - -var didScheduleMicrotask = false; // `act` "microtasks" are scheduled on the `act` queue instead of an actual -// microtask, so we have to dedupe those separately. This wouldn't be an issue -// if we required all `act` calls to be awaited, which we might in the future. - -var didScheduleMicrotask_act = false; // Used to quickly bail out of flushSync if there's no sync work to do. - -var mightHavePendingSyncWork = false; -var isFlushingWork = false; -function ensureRootIsScheduled(root) { - // This function is called whenever a root receives an update. It does two - // things 1) it ensures the root is in the root schedule, and 2) it ensures - // there's a pending microtask to process the root schedule. - // - // Most of the actual scheduling logic does not happen until - // `scheduleTaskForRootDuringMicrotask` runs. - // Add the root to the schedule - if (root === lastScheduledRoot || root.next !== null); - else { - if (lastScheduledRoot === null) { - firstScheduledRoot = lastScheduledRoot = root; - } else { - lastScheduledRoot.next = root; - lastScheduledRoot = root; - } - } // Any time a root received an update, we set this to true until the next time - // we process the schedule. If it's false, then we can quickly exit flushSync - // without consulting the schedule. - - mightHavePendingSyncWork = true; // At the end of the current event, go through each of the roots and ensure - // there's a task scheduled for each one at the correct priority. - - if (ReactCurrentActQueue$1.current !== null) { - // We're inside an `act` scope. - if (!didScheduleMicrotask_act) { - didScheduleMicrotask_act = true; - scheduleImmediateTask(processRootScheduleInMicrotask); - } - } else { - if (!didScheduleMicrotask) { - didScheduleMicrotask = true; - scheduleImmediateTask(processRootScheduleInMicrotask); - } - } - - if (!enableDeferRootSchedulingToMicrotask) { - // While this flag is disabled, we schedule the render task immediately - // instead of waiting a microtask. - // TODO: We need to land enableDeferRootSchedulingToMicrotask ASAP to - // unblock additional features we have planned. - scheduleTaskForRootDuringMicrotask(root, now$1()); - } - - if (ReactCurrentActQueue$1.isBatchingLegacy && root.tag === LegacyRoot) { - // Special `act` case: Record whenever a legacy update is scheduled. - ReactCurrentActQueue$1.didScheduleLegacyUpdate = true; - } -} -function flushSyncWorkOnAllRoots() { - // This is allowed to be called synchronously, but the caller should check - // the execution context first. - flushSyncWorkAcrossRoots_impl(false); -} -function flushSyncWorkOnLegacyRootsOnly() { - // This is allowed to be called synchronously, but the caller should check - // the execution context first. - flushSyncWorkAcrossRoots_impl(true); -} - -function flushSyncWorkAcrossRoots_impl(onlyLegacy) { - if (isFlushingWork) { - // Prevent reentrancy. - // TODO: Is this overly defensive? The callers must check the execution - // context first regardless. - return; - } - - if (!mightHavePendingSyncWork) { - // Fast path. There's no sync work to do. - return; - } - - var workInProgressRoot = getWorkInProgressRoot(); - var workInProgressRootRenderLanes = getWorkInProgressRootRenderLanes(); // There may or may not be synchronous work scheduled. Let's check. - - var didPerformSomeWork; - var errors = null; - isFlushingWork = true; - - do { - didPerformSomeWork = false; - var root = firstScheduledRoot; - - while (root !== null) { - if (onlyLegacy && root.tag !== LegacyRoot); - else { - var nextLanes = getNextLanes( - root, - root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes - ); - - if (includesSyncLane(nextLanes)) { - // This root has pending sync work. Flush it now. - try { - // TODO: Pass nextLanes as an argument instead of computing it again - // inside performSyncWorkOnRoot. - didPerformSomeWork = true; - performSyncWorkOnRoot(root); - } catch (error) { - // Collect errors so we can rethrow them at the end - if (errors === null) { - errors = [error]; - } else { - errors.push(error); - } - } - } - } - - root = root.next; - } - } while (didPerformSomeWork); - - isFlushingWork = false; // If any errors were thrown, rethrow them right before exiting. - // TODO: Consider returning these to the caller, to allow them to decide - // how/when to rethrow. - - if (errors !== null) { - if (errors.length > 1) { - if (typeof AggregateError === "function") { - // eslint-disable-next-line no-undef - throw new AggregateError(errors); - } else { - for (var i = 1; i < errors.length; i++) { - scheduleImmediateTask(throwError.bind(null, errors[i])); - } - - var firstError = errors[0]; - throw firstError; - } - } else { - var error = errors[0]; - throw error; - } - } -} - -function throwError(error) { - throw error; -} - -function processRootScheduleInMicrotask() { - // This function is always called inside a microtask. It should never be - // called synchronously. - didScheduleMicrotask = false; - - { - didScheduleMicrotask_act = false; - } // We'll recompute this as we iterate through all the roots and schedule them. - - mightHavePendingSyncWork = false; - var currentTime = now$1(); - var prev = null; - var root = firstScheduledRoot; - - while (root !== null) { - var next = root.next; - var nextLanes = scheduleTaskForRootDuringMicrotask(root, currentTime); - - if (nextLanes === NoLane) { - // This root has no more pending work. Remove it from the schedule. To - // guard against subtle reentrancy bugs, this microtask is the only place - // we do this — you can add roots to the schedule whenever, but you can - // only remove them here. - // Null this out so we know it's been removed from the schedule. - root.next = null; - - if (prev === null) { - // This is the new head of the list - firstScheduledRoot = next; - } else { - prev.next = next; - } - - if (next === null) { - // This is the new tail of the list - lastScheduledRoot = prev; - } - } else { - // This root still has work. Keep it in the list. - prev = root; - - if (includesSyncLane(nextLanes)) { - mightHavePendingSyncWork = true; - } - } - - root = next; - } // At the end of the microtask, flush any pending synchronous work. This has - // to come at the end, because it does actual rendering work that might throw. - - flushSyncWorkOnAllRoots(); -} - -function scheduleTaskForRootDuringMicrotask(root, currentTime) { - // This function is always called inside a microtask, or at the very end of a - // rendering task right before we yield to the main thread. It should never be - // called synchronously. - // - // TODO: Unless enableDeferRootSchedulingToMicrotask is off. We need to land - // that ASAP to unblock additional features we have planned. - // - // This function also never performs React work synchronously; it should - // only schedule work to be performed later, in a separate task or microtask. - // Check if any lanes are being starved by other work. If so, mark them as - // expired so we know to work on those next. - markStarvedLanesAsExpired(root, currentTime); // Determine the next lanes to work on, and their priority. - - var workInProgressRoot = getWorkInProgressRoot(); - var workInProgressRootRenderLanes = getWorkInProgressRootRenderLanes(); - var nextLanes = getNextLanes( - root, - root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes - ); - var existingCallbackNode = root.callbackNode; - - if ( - // Check if there's nothing to work on - nextLanes === NoLanes || // If this root is currently suspended and waiting for data to resolve, don't - // schedule a task to render it. We'll either wait for a ping, or wait to - // receive an update. - // - // Suspended render phase - (root === workInProgressRoot && isWorkLoopSuspendedOnData()) || // Suspended commit phase - root.cancelPendingCommit !== null - ) { - // Fast path: There's nothing to work on. - if (existingCallbackNode !== null) { - cancelCallback(existingCallbackNode); - } - - root.callbackNode = null; - root.callbackPriority = NoLane; - return NoLane; - } // Schedule a new callback in the host environment. - - if (includesSyncLane(nextLanes)) { - // Synchronous work is always flushed at the end of the microtask, so we - // don't need to schedule an additional task. - if (existingCallbackNode !== null) { - cancelCallback(existingCallbackNode); - } - - root.callbackPriority = SyncLane; - root.callbackNode = null; - return SyncLane; - } else { - // We use the highest priority lane to represent the priority of the callback. - var existingCallbackPriority = root.callbackPriority; - var newCallbackPriority = getHighestPriorityLane(nextLanes); - - if ( - newCallbackPriority === existingCallbackPriority && // Special case related to `act`. If the currently scheduled task is a - // Scheduler task, rather than an `act` task, cancel it and re-schedule - // on the `act` queue. - !( - ReactCurrentActQueue$1.current !== null && - existingCallbackNode !== fakeActCallbackNode$1 - ) - ) { - // The priority hasn't changed. We can reuse the existing task. - return newCallbackPriority; - } else { - // Cancel the existing callback. We'll schedule a new one below. - cancelCallback(existingCallbackNode); - } - - var schedulerPriorityLevel; - - switch (lanesToEventPriority(nextLanes)) { - case DiscreteEventPriority: - schedulerPriorityLevel = ImmediatePriority; - break; - - case ContinuousEventPriority: - schedulerPriorityLevel = UserBlockingPriority; - break; - - case DefaultEventPriority: - schedulerPriorityLevel = NormalPriority$1; - break; - - case IdleEventPriority: - schedulerPriorityLevel = IdlePriority; - break; - - default: - schedulerPriorityLevel = NormalPriority$1; - break; - } - - var newCallbackNode = scheduleCallback$1( - schedulerPriorityLevel, - performConcurrentWorkOnRoot.bind(null, root) - ); - root.callbackPriority = newCallbackPriority; - root.callbackNode = newCallbackNode; - return newCallbackPriority; - } -} - -function getContinuationForRoot(root, originalCallbackNode) { - // This is called at the end of `performConcurrentWorkOnRoot` to determine - // if we need to schedule a continuation task. - // - // Usually `scheduleTaskForRootDuringMicrotask` only runs inside a microtask; - // however, since most of the logic for determining if we need a continuation - // versus a new task is the same, we cheat a bit and call it here. This is - // only safe to do because we know we're at the end of the browser task. - // So although it's not an actual microtask, it might as well be. - scheduleTaskForRootDuringMicrotask(root, now$1()); - - if (root.callbackNode === originalCallbackNode) { - // The task node scheduled for this root is the same one that's - // currently executed. Need to return a continuation. - return performConcurrentWorkOnRoot.bind(null, root); - } - - return null; -} -var fakeActCallbackNode$1 = {}; - -function scheduleCallback$1(priorityLevel, callback) { - if (ReactCurrentActQueue$1.current !== null) { - // Special case: We're inside an `act` scope (a testing utility). - // Instead of scheduling work in the host environment, add it to a - // fake internal queue that's managed by the `act` implementation. - ReactCurrentActQueue$1.current.push(callback); - return fakeActCallbackNode$1; - } else { - return scheduleCallback$3(priorityLevel, callback); - } -} - -function cancelCallback(callbackNode) { - if (callbackNode === fakeActCallbackNode$1); - else if (callbackNode !== null) { - cancelCallback$1(callbackNode); - } -} - -function scheduleImmediateTask(cb) { - if (ReactCurrentActQueue$1.current !== null) { - // Special case: Inside an `act` scope, we push microtasks to the fake `act` - // callback queue. This is because we currently support calling `act` - // without awaiting the result. The plan is to deprecate that, and require - // that you always await the result so that the microtasks have a chance to - // run. But it hasn't happened yet. - ReactCurrentActQueue$1.current.push(function () { - cb(); - return null; - }); - } // TODO: Can we land supportsMicrotasks? Which environments don't support it? - // Alternatively, can we move this check to the host config? - - { - scheduleMicrotask(function () { - // In Safari, appending an iframe forces microtasks to run. - // https://github.com/facebook/react/issues/22459 - // We don't support running callbacks in the middle of render - // or commit so we need to check against that. - var executionContext = getExecutionContext(); - - if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { - // Note that this would still prematurely flush the callbacks - // if this happens outside render or commit phase (e.g. in an event). - // Intentionally using a macrotask instead of a microtask here. This is - // wrong semantically but it prevents an infinite loop. The bug is - // Safari's, not ours, so we just do our best to not crash even though - // the behavior isn't completely correct. - scheduleCallback$3(ImmediatePriority, cb); - return; - } - - cb(); - }); - } -} - -var ceil = Math.ceil; var PossiblyWeakMap = typeof WeakMap === "function" ? WeakMap : Map; var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher, ReactCurrentCache = ReactSharedInternals.ReactCurrentCache, @@ -29284,12 +29407,7 @@ var isFlushingPassiveEffects = false; var didScheduleUpdateDuringPassiveEffects = false; var NESTED_PASSIVE_UPDATE_LIMIT = 50; var nestedPassiveUpdateCount = 0; -var rootWithPassiveNestedUpdates = null; // If two updates are scheduled within the same event, we should treat their -// event times as simultaneous, even if the actual clock time has advanced -// between the first and second call. - -var currentEventTime = NoTimestamp; -var currentEventTransitionLane = NoLanes; +var rootWithPassiveNestedUpdates = null; var isRunningInsertionEffect = false; function getWorkInProgressRoot() { return workInProgressRoot; @@ -29300,20 +29418,6 @@ function getWorkInProgressRootRenderLanes() { function isWorkLoopSuspendedOnData() { return workInProgressSuspendedReason === SuspendedOnData; } -function requestEventTime() { - if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { - // We're inside React, so it's fine to read the actual time. - return now$1(); - } // We're not inside React, so we may be in the middle of a browser event. - - if (currentEventTime !== NoTimestamp) { - // Use the same start time for all updates until we enter React again. - return currentEventTime; - } // This is the first update since React yielded. Compute a new start time. - - currentEventTime = now$1(); - return currentEventTime; -} function requestUpdateLane(fiber) { // Special cases var mode = fiber.mode; @@ -29347,20 +29451,14 @@ function requestUpdateLane(fiber) { } transition._updatedFibers.add(fiber); - } // The algorithm for assigning an update to a lane should be stable for all - // updates at the same priority within the same event. To do this, the - // inputs to the algorithm must be the same. - // - // The trick we use is to cache the first of each of these inputs within an - // event. Then reset the cached values once we can be sure the event is - // over. Our heuristic for that is whenever we enter a concurrent work loop. - - if (currentEventTransitionLane === NoLane) { - // All transitions within the same event are assigned the same lane. - currentEventTransitionLane = claimNextTransitionLane(); } - return currentEventTransitionLane; + var asyncAction = peekAsyncActionContext(); + return asyncAction !== null // We're inside an async action scope. Reuse the same lane. + ? asyncAction.lane // We may or may not be inside an async action scope. If we are, this + : // is the first update in that scope. Either way, we need to get a + // fresh transition lane. + requestTransitionLane(); } // Updates originating inside certain React methods, like flushSync, have // their priority set by tracking it with a context variable. // @@ -29397,7 +29495,7 @@ function requestRetryLane(fiber) { return claimNextRetryLane(); } -function scheduleUpdateOnFiber(root, fiber, lane, eventTime) { +function scheduleUpdateOnFiber(root, fiber, lane) { { if (isRunningInsertionEffect) { error("useInsertionEffect must not schedule updates."); @@ -29423,7 +29521,7 @@ function scheduleUpdateOnFiber(root, fiber, lane, eventTime) { markRootSuspended(root, workInProgressRootRenderLanes); } // Mark that the root has a pending update. - markRootUpdated(root, lane, eventTime); + markRootUpdated(root, lane); if ( (executionContext & RenderContext) !== NoLanes && @@ -29525,7 +29623,7 @@ function scheduleUpdateOnFiber(root, fiber, lane, eventTime) { } } } -function scheduleInitialHydrationOnRoot(root, lane, eventTime) { +function scheduleInitialHydrationOnRoot(root, lane) { // This is a special fork of scheduleUpdateOnFiber that is only used to // schedule the initial hydration of a root that has just been created. Most // of the stuff in scheduleUpdateOnFiber can be skipped. @@ -29537,7 +29635,7 @@ function scheduleInitialHydrationOnRoot(root, lane, eventTime) { // match what was rendered on the server. var current = root.current; current.lanes = lane; - markRootUpdated(root, lane, eventTime); + markRootUpdated(root, lane); ensureRootIsScheduled(root); } function isUnsafeClassRenderPhaseUpdate(fiber) { @@ -29550,11 +29648,7 @@ function isUnsafeClassRenderPhaseUpdate(fiber) { function performConcurrentWorkOnRoot(root, didTimeout) { { resetNestedUpdateFlag(); - } // Since we know we're in a React event, we can clear the current - // event time. The next update will compute a new event time. - - currentEventTime = NoTimestamp; - currentEventTransitionLane = NoLanes; + } if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { throw new Error("Should not already be working."); @@ -29780,133 +29874,30 @@ function queueRecoverableErrors(errors) { } function finishConcurrentRender(root, exitStatus, finishedWork, lanes) { + // TODO: The fact that most of these branches are identical suggests that some + // of the exit statuses are not best modeled as exit statuses and should be + // tracked orthogonally. switch (exitStatus) { case RootInProgress: case RootFatalErrored: { throw new Error("Root did not complete. This is a bug in React."); } - case RootErrored: { - // We should have already attempted to retry this tree. If we reached - // this point, it errored again. Commit it. - commitRootWhenReady( - root, - finishedWork, - workInProgressRootRecoverableErrors, - workInProgressTransitions, - lanes - ); - break; - } - - case RootSuspended: { - markRootSuspended(root, lanes); // We have an acceptable loading state. We need to figure out if we - // should immediately commit it or wait a bit. - - if ( - includesOnlyRetries(lanes) && // do not delay if we're inside an act() scope - !shouldForceFlushFallbacksInDEV() - ) { - // This render only included retries, no updates. Throttle committing - // retries so that we don't show too many loading states too quickly. - var msUntilTimeout = - globalMostRecentFallbackTime + FALLBACK_THROTTLE_MS - now$1(); // Don't bother with a very short suspense time. - - if (msUntilTimeout > 10) { - var nextLanes = getNextLanes(root, NoLanes); - - if (nextLanes !== NoLanes) { - // There's additional work on this root. - break; - } // The render is suspended, it hasn't timed out, and there's no - // lower priority work to do. Instead of committing the fallback - // immediately, wait for more data to arrive. - - root.timeoutHandle = scheduleTimeout( - commitRootWhenReady.bind( - null, - root, - finishedWork, - workInProgressRootRecoverableErrors, - workInProgressTransitions, - lanes - ), - msUntilTimeout - ); - break; - } - } // The work expired. Commit immediately. - - commitRootWhenReady( - root, - finishedWork, - workInProgressRootRecoverableErrors, - workInProgressTransitions, - lanes - ); - break; - } - case RootSuspendedWithDelay: { - markRootSuspended(root, lanes); - if (includesOnlyTransitions(lanes)) { // This is a transition, so we should exit without committing a // placeholder and without scheduling a timeout. Delay indefinitely // until we receive more data. - break; - } - - if (!shouldForceFlushFallbacksInDEV()) { - // This is not a transition, but we did trigger an avoided state. - // Schedule a placeholder to display after a short delay, using the Just - // Noticeable Difference. - // TODO: Is the JND optimization worth the added complexity? If this is - // the only reason we track the event time, then probably not. - // Consider removing. - var mostRecentEventTime = getMostRecentEventTime(root, lanes); - var eventTimeMs = mostRecentEventTime; - var timeElapsedMs = now$1() - eventTimeMs; - - var _msUntilTimeout = jnd(timeElapsedMs) - timeElapsedMs; // Don't bother with a very short suspense time. - - if (_msUntilTimeout > 10) { - // Instead of committing the fallback immediately, wait for more data - // to arrive. - root.timeoutHandle = scheduleTimeout( - commitRootWhenReady.bind( - null, - root, - finishedWork, - workInProgressRootRecoverableErrors, - workInProgressTransitions, - lanes - ), - _msUntilTimeout - ); - break; - } + markRootSuspended(root, lanes); + return; } // Commit the placeholder. - commitRootWhenReady( - root, - finishedWork, - workInProgressRootRecoverableErrors, - workInProgressTransitions, - lanes - ); break; } + case RootErrored: + case RootSuspended: case RootCompleted: { - // The work completed. - commitRootWhenReady( - root, - finishedWork, - workInProgressRootRecoverableErrors, - workInProgressTransitions, - lanes - ); break; } @@ -29914,6 +29905,61 @@ function finishConcurrentRender(root, exitStatus, finishedWork, lanes) { throw new Error("Unknown root exit status."); } } + + if (shouldForceFlushFallbacksInDEV()) { + // We're inside an `act` scope. Commit immediately. + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions + ); + } else { + if ( + includesOnlyRetries(lanes) && + (alwaysThrottleRetries || exitStatus === RootSuspended) + ) { + // This render only included retries, no updates. Throttle committing + // retries so that we don't show too many loading states too quickly. + var msUntilTimeout = + globalMostRecentFallbackTime + FALLBACK_THROTTLE_MS - now$1(); // Don't bother with a very short suspense time. + + if (msUntilTimeout > 10) { + markRootSuspended(root, lanes); + var nextLanes = getNextLanes(root, NoLanes); + + if (nextLanes !== NoLanes) { + // There's additional work we can do on this root. We might as well + // attempt to work on that while we're suspended. + return; + } // The render is suspended, it hasn't timed out, and there's no + // lower priority work to do. Instead of committing the fallback + // immediately, wait for more data to arrive. + // TODO: Combine retry throttling with Suspensey commits. Right now they + // run one after the other. + + root.timeoutHandle = scheduleTimeout( + commitRootWhenReady.bind( + null, + root, + finishedWork, + workInProgressRootRecoverableErrors, + workInProgressTransitions, + lanes + ), + msUntilTimeout + ); + return; + } + } + + commitRootWhenReady( + root, + finishedWork, + workInProgressRootRecoverableErrors, + workInProgressTransitions, + lanes + ); + } } function commitRootWhenReady( @@ -29923,6 +29969,8 @@ function commitRootWhenReady( transitions, lanes ) { + // TODO: Combine retry throttling with Suspensey commits. Right now they run + // one after the other. if (includesOnlyNonUrgentLanes(lanes)) { // Before committing, ask the renderer whether the host tree is ready. // If it's not, we'll wait until it notifies us. @@ -29945,22 +29993,14 @@ function commitRootWhenReady( // us that it's ready. This will be canceled if we start work on the // root again. root.cancelPendingCommit = schedulePendingCommit( - commitRoot.bind( - null, - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ) + commitRoot.bind(null, root, recoverableErrors, transitions) ); + markRootSuspended(root, lanes); return; } } // Otherwise, commit immediately. - commitRoot( - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions - ); + commitRoot(root, recoverableErrors, transitions); } function isRenderConsistentWithExternalStores(finishedWork) { @@ -30446,7 +30486,6 @@ function shouldRemainOnPreviousScreen() { } function pushDispatcher(container) { - prepareRendererToRender(container); var prevDispatcher = ReactCurrentDispatcher.current; ReactCurrentDispatcher.current = ContextOnlyDispatcher; @@ -30461,7 +30500,6 @@ function pushDispatcher(container) { } function popDispatcher(prevDispatcher) { - resetRendererAfterRender(); ReactCurrentDispatcher.current = prevDispatcher; } @@ -30539,7 +30577,7 @@ function renderHasNotSuspendedYet() { function renderRootSync(root, lanes) { var prevExecutionContext = executionContext; executionContext |= RenderContext; - var prevDispatcher = pushDispatcher(root.containerInfo); + var prevDispatcher = pushDispatcher(); var prevCacheDispatcher = pushCacheDispatcher(); // If the root or lanes have changed, throw out the existing stack // and prepare a fresh one. Otherwise we'll continue where we left off. @@ -30660,7 +30698,7 @@ function workLoopSync() { function renderRootConcurrent(root, lanes) { var prevExecutionContext = executionContext; executionContext |= RenderContext; - var prevDispatcher = pushDispatcher(root.containerInfo); + var prevDispatcher = pushDispatcher(); var prevCacheDispatcher = pushCacheDispatcher(); // If the root or lanes have changed, throw out the existing stack // and prepare a fresh one. Otherwise we'll continue where we left off. @@ -31037,6 +31075,16 @@ function replaySuspendedUnitOfWork(unitOfWork) { break; } + case HostComponent: { + // Some host components are stateful (that's how we implement form + // actions) but we don't bother to reuse the memoized state because it's + // not worth the extra code. The main reason to reuse the previous hooks + // is to reuse uncached promises, but we happen to know that the only + // promises that a host component might suspend on are definitely cached + // because they are controlled by us. So don't bother. + resetHooksOnUnwind(); // Fallthrough to the next branch. + } + default: { // Other types besides function components are reset completely before // being replayed. Currently this only happens when a Usable type is @@ -31142,28 +31190,14 @@ function completeUnitOfWork(unitOfWork) { var completedWork = unitOfWork; do { - if (revertRemovalOfSiblingPrerendering) { + { if ((completedWork.flags & Incomplete) !== NoFlags$1) { - // This fiber did not complete, because one of its children did not - // complete. Switch to unwinding the stack instead of completing it. - // - // The reason "unwind" and "complete" is interleaved is because when - // something suspends, we continue rendering the siblings even though - // they will be replaced by a fallback. - // TODO: Disable sibling prerendering, then remove this branch. - unwindUnitOfWork(completedWork); - return; - } - } else { - { - if ((completedWork.flags & Incomplete) !== NoFlags$1) { - // NOTE: If we re-enable sibling prerendering in some cases, this branch - // is where we would switch to the unwinding path. - error( - "Internal React error: Expected this fiber to be complete, but " + - "it isn't. It should have been unwound. This is a bug in React." - ); - } + // NOTE: If we re-enable sibling prerendering in some cases, this branch + // is where we would switch to the unwinding path. + error( + "Internal React error: Expected this fiber to be complete, but " + + "it isn't. It should have been unwound. This is a bug in React." + ); } } // The current, flushed, state of this fiber is the alternate. Ideally // nothing should rely on this, but relying on it here means that we don't @@ -31262,23 +31296,10 @@ function unwindUnitOfWork(unitOfWork) { returnFiber.flags |= Incomplete; returnFiber.subtreeFlags = NoFlags$1; returnFiber.deletions = null; - } - - if (revertRemovalOfSiblingPrerendering) { - // If there are siblings, work on them now even though they're going to be - // replaced by a fallback. We're "prerendering" them. Historically our - // rationale for this behavior has been to initiate any lazy data requests - // in the siblings, and also to warm up the CPU cache. - // TODO: Don't prerender siblings. With `use`, we suspend the work loop - // until the data has resolved, anyway. - var siblingFiber = incompleteWork.sibling; - - if (siblingFiber !== null) { - // This branch will return us to the normal work loop. - workInProgress = siblingFiber; - return; - } - } // Otherwise, return to the parent + } // NOTE: If we re-enable sibling prerendering in some cases, here we + // would switch to the normal completion path: check if a sibling + // exists, and if so, begin work on it. + // Otherwise, return to the parent // $FlowFixMe[incompatible-type] we bail out when we get a null incompleteWork = returnFiber; // Update the next thing we're working on in case something throws. @@ -31922,10 +31943,9 @@ function captureCommitPhaseErrorOnRoot(rootFiber, sourceFiber, error) { var errorInfo = createCapturedValueAtFiber(error, sourceFiber); var update = createRootErrorUpdate(rootFiber, errorInfo, SyncLane); var root = enqueueUpdate(rootFiber, update, SyncLane); - var eventTime = requestEventTime(); if (root !== null) { - markRootUpdated(root, SyncLane, eventTime); + markRootUpdated(root, SyncLane); ensureRootIsScheduled(root); } } @@ -31961,10 +31981,9 @@ function captureCommitPhaseError(sourceFiber, nearestMountedAncestor, error$1) { var errorInfo = createCapturedValueAtFiber(error$1, sourceFiber); var update = createClassErrorUpdate(fiber, errorInfo, SyncLane); var root = enqueueUpdate(fiber, update, SyncLane); - var eventTime = requestEventTime(); if (root !== null) { - markRootUpdated(root, SyncLane, eventTime); + markRootUpdated(root, SyncLane); ensureRootIsScheduled(root); } @@ -32090,11 +32109,10 @@ function retryTimedOutBoundary(boundaryFiber, retryLane) { retryLane = requestRetryLane(boundaryFiber); } // TODO: Special case idle priority? - var eventTime = requestEventTime(); var root = enqueueConcurrentRenderForLane(boundaryFiber, retryLane); if (root !== null) { - markRootUpdated(root, retryLane, eventTime); + markRootUpdated(root, retryLane); ensureRootIsScheduled(root); } } @@ -32149,32 +32167,7 @@ function resolveRetryWakeable(boundaryFiber, wakeable) { } retryTimedOutBoundary(boundaryFiber, retryLane); -} // Computes the next Just Noticeable Difference (JND) boundary. -// The theory is that a person can't tell the difference between small differences in time. -// Therefore, if we wait a bit longer than necessary that won't translate to a noticeable -// difference in the experience. However, waiting for longer might mean that we can avoid -// showing an intermediate loading state. The longer we have already waited, the harder it -// is to tell small differences in time. Therefore, the longer we've already waited, -// the longer we can wait additionally. At some point we have to give up though. -// We pick a train model where the next boundary commits at a consistent schedule. -// These particular numbers are vague estimates. We expect to adjust them based on research. - -function jnd(timeElapsed) { - return timeElapsed < 120 - ? 120 - : timeElapsed < 480 - ? 480 - : timeElapsed < 1080 - ? 1080 - : timeElapsed < 1920 - ? 1920 - : timeElapsed < 3000 - ? 3000 - : timeElapsed < 4320 - ? 4320 - : ceil(timeElapsed / 1960) * 1960; } - function throwIfInfiniteUpdateLoopDetected() { if (nestedUpdateCount > NESTED_UPDATE_LIMIT) { nestedUpdateCount = 0; @@ -32855,7 +32848,7 @@ function scheduleFibersWithFamiliesRecursively( var root = enqueueConcurrentRenderForLane(fiber, SyncLane); if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + scheduleUpdateOnFiber(root, fiber, SyncLane); } } @@ -33768,7 +33761,6 @@ function FiberRootNode( this.next = null; this.callbackNode = null; this.callbackPriority = NoLane; - this.eventTimes = createLaneMap(NoLanes); this.expirationTimes = createLaneMap(NoTimestamp); this.pendingLanes = NoLanes; this.suspendedLanes = NoLanes; @@ -33899,7 +33891,7 @@ function createFiberRoot( return root; } -var ReactVersion = "18.3.0-www-classic-a8459f07"; +var ReactVersion = "18.3.0-www-classic-bb796e31"; function createPortal$1( children, @@ -34085,9 +34077,8 @@ function createHydrationContainer( var update = createUpdate(lane); update.callback = callback !== undefined && callback !== null ? callback : null; - var eventTime = requestEventTime(); enqueueUpdate(current, update, lane); - scheduleInitialHydrationOnRoot(root, lane, eventTime); + scheduleInitialHydrationOnRoot(root, lane); return root; } function updateContainer(element, container, parentComponent, callback) { @@ -34149,8 +34140,7 @@ function updateContainer(element, container, parentComponent, callback) { var root = enqueueUpdate(current$1, update, lane); if (root !== null) { - var eventTime = requestEventTime(); - scheduleUpdateOnFiber(root, current$1, lane, eventTime); + scheduleUpdateOnFiber(root, current$1, lane); entangleTransitions(root, current$1, lane); } @@ -34191,8 +34181,7 @@ function attemptSynchronousHydration(fiber) { var root = enqueueConcurrentRenderForLane(fiber, SyncLane); if (root !== null) { - var eventTime = requestEventTime(); - scheduleUpdateOnFiber(root, fiber, SyncLane, eventTime); + scheduleUpdateOnFiber(root, fiber, SyncLane); } }); // If we're still blocked after this, we need to increase // the priority of any promises resolving within this @@ -34238,8 +34227,7 @@ function attemptContinuousHydration(fiber) { var root = enqueueConcurrentRenderForLane(fiber, lane); if (root !== null) { - var eventTime = requestEventTime(); - scheduleUpdateOnFiber(root, fiber, lane, eventTime); + scheduleUpdateOnFiber(root, fiber, lane); } markRetryLaneIfNotHydrated(fiber, lane); @@ -34255,8 +34243,7 @@ function attemptHydrationAtCurrentPriority(fiber) { var root = enqueueConcurrentRenderForLane(fiber, lane); if (root !== null) { - var eventTime = requestEventTime(); - scheduleUpdateOnFiber(root, fiber, lane, eventTime); + scheduleUpdateOnFiber(root, fiber, lane); } markRetryLaneIfNotHydrated(fiber, lane); @@ -34412,7 +34399,7 @@ var setSuspenseHandler = null; var root = enqueueConcurrentRenderForLane(fiber, SyncLane); if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + scheduleUpdateOnFiber(root, fiber, SyncLane); } } }; @@ -34433,7 +34420,7 @@ var setSuspenseHandler = null; var root = enqueueConcurrentRenderForLane(fiber, SyncLane); if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + scheduleUpdateOnFiber(root, fiber, SyncLane); } } }; @@ -34454,7 +34441,7 @@ var setSuspenseHandler = null; var root = enqueueConcurrentRenderForLane(fiber, SyncLane); if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + scheduleUpdateOnFiber(root, fiber, SyncLane); } } }; // Support DevTools props for function components, forwardRef, memo, host components, etc. @@ -34469,7 +34456,7 @@ var setSuspenseHandler = null; var root = enqueueConcurrentRenderForLane(fiber, SyncLane); if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + scheduleUpdateOnFiber(root, fiber, SyncLane); } }; @@ -34483,7 +34470,7 @@ var setSuspenseHandler = null; var root = enqueueConcurrentRenderForLane(fiber, SyncLane); if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + scheduleUpdateOnFiber(root, fiber, SyncLane); } }; @@ -34497,7 +34484,7 @@ var setSuspenseHandler = null; var root = enqueueConcurrentRenderForLane(fiber, SyncLane); if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + scheduleUpdateOnFiber(root, fiber, SyncLane); } }; @@ -34505,7 +34492,7 @@ var setSuspenseHandler = null; var root = enqueueConcurrentRenderForLane(fiber, SyncLane); if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); + scheduleUpdateOnFiber(root, fiber, SyncLane); } }; @@ -37108,6 +37095,8 @@ function extractEvents$1( // Firefox creates a keypress event for function keys too. This removes // the unwanted keypress events. Enter is however both printable and // non-printable. One would expect Tab to be as well (but it isn't). + // TODO: Fixed in https://bugzilla.mozilla.org/show_bug.cgi?id=968056. Can + // probably remove. if (getEventCharCode(nativeEvent) === 0) { return; } @@ -37137,6 +37126,8 @@ function extractEvents$1( case "click": // Firefox creates a click event on right mouse clicks. This removes the // unwanted click events. + // TODO: Fixed in https://phabricator.services.mozilla.com/D26793. Can + // probably remove. if (nativeEvent.button === 2) { return; } @@ -38182,6 +38173,10 @@ function getListenerSetKey(domEventName, capture) { var didWarnControlledToUncontrolled = false; var didWarnUncontrolledToControlled = false; var didWarnInvalidHydration = false; +var didWarnFormActionType = false; +var didWarnFormActionName = false; +var didWarnFormActionTarget = false; +var didWarnFormActionMethod = false; var canDiffStyleForHydrationWarning; { @@ -38221,6 +38216,109 @@ function validatePropertiesInDevelopment(type, props) { } } +function validateFormActionInDevelopment(tag, key, value, props) { + { + if (value == null) { + return; + } + + if (tag === "form") { + if (key === "formAction") { + error( + "You can only pass the formAction prop to or