From db78d9be3481083cd54ae284bbb7f25a1d69bf7d Mon Sep 17 00:00:00 2001 From: josephsavona Date: Tue, 25 Apr 2023 22:05:15 +0000 Subject: [PATCH] Handle line endings correctly on Windows in build script for RN (#26727) ## Summary We added some post-processing in the build for RN in #26616 that broke for users on Windows due to how line endings were handled to the regular expression to insert some directives in the docblock. This fixes that problem, reported in #26697 as well. ## How did you test this change? Verified files are still built correctly on Mac/Linux. Will ask for help to test on Windows. DiffTrain build for [f87e97a0a67fa7cfd7e6f2ec985621c0e825cb23](https://github.com/facebook/react/commit/f87e97a0a67fa7cfd7e6f2ec985621c0e825cb23) --- compiled/facebook-www/REVISION | 2 +- compiled/facebook-www/React-dev.modern.js | 2 +- compiled/facebook-www/ReactART-dev.classic.js | 1467 +- compiled/facebook-www/ReactART-dev.modern.js | 1467 +- .../facebook-www/ReactART-prod.classic.js | 945 +- compiled/facebook-www/ReactART-prod.modern.js | 945 +- compiled/facebook-www/ReactDOM-dev.classic.js | 2639 ++-- compiled/facebook-www/ReactDOM-dev.modern.js | 4327 +++--- .../facebook-www/ReactDOM-prod.classic.js | 2251 ++- compiled/facebook-www/ReactDOM-prod.modern.js | 3259 +++-- .../ReactDOM-profiling.classic.js | 2320 ++-- .../facebook-www/ReactDOM-profiling.modern.js | 3304 +++-- .../ReactDOMServer-dev.classic.js | 597 +- .../facebook-www/ReactDOMServer-dev.modern.js | 597 +- .../ReactDOMServer-prod.classic.js | 762 +- .../ReactDOMServer-prod.modern.js | 762 +- .../ReactDOMServerStreaming-dev.modern.js | 587 +- .../ReactDOMServerStreaming-prod.modern.js | 758 +- .../ReactDOMTesting-dev.classic.js | 11263 ++++++++-------- .../ReactDOMTesting-dev.modern.js | 4331 +++--- .../ReactDOMTesting-prod.classic.js | 4613 ++++--- .../ReactDOMTesting-prod.modern.js | 3259 +++-- .../ReactFlightDOMRelayClient-dev.classic.js | 98 +- .../ReactFlightDOMRelayClient-dev.modern.js | 98 +- .../ReactFlightDOMRelayClient-prod.classic.js | 103 +- .../ReactFlightDOMRelayClient-prod.modern.js | 103 +- .../ReactFlightDOMRelayServer-dev.classic.js | 299 +- .../ReactFlightDOMRelayServer-dev.modern.js | 299 +- .../ReactFlightDOMRelayServer-prod.classic.js | 221 +- .../ReactFlightDOMRelayServer-prod.modern.js | 221 +- .../ReactTestRenderer-dev.classic.js | 1398 +- .../ReactTestRenderer-dev.modern.js | 1398 +- compiled/facebook-www/WARNINGS | 11 + .../facebook-www/eslint-plugin-react-hooks.js | 2 +- 34 files changed, 28522 insertions(+), 26186 deletions(-) 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