diff --git a/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react-test-renderer/cjs/ReactTestRenderer-dev.js b/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react-test-renderer/cjs/ReactTestRenderer-dev.js index 7d183fcd8f3db..c24024d654bc4 100644 --- a/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react-test-renderer/cjs/ReactTestRenderer-dev.js +++ b/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react-test-renderer/cjs/ReactTestRenderer-dev.js @@ -7,7 +7,7 @@ * @noflow * @nolint * @preventMunge - * @generated SignedSource<> + * @generated SignedSource<<6f91cae5b10795257ddec042012ed6d4>> */ "use strict"; @@ -3086,3673 +3086,3665 @@ if (__DEV__) { } } - var UpdateState = 0; - var ReplaceState = 1; - var ForceUpdate = 2; - var CaptureUpdate = 3; // Global state that is reset at the beginning of calling `processUpdateQueue`. - // It should only be read right after calling `processUpdateQueue`, via - // `checkHasForceUpdateAfterProcessing`. + var ReactCurrentActQueue$3 = 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 hasForceUpdate = false; - var didWarnUpdateInsideUpdate; - var currentlyProcessingQueue; + var firstScheduledRoot = null; + var lastScheduledRoot = null; // Used to prevent redundant mircotasks from being scheduled. - { - didWarnUpdateInsideUpdate = false; - currentlyProcessingQueue = null; - } + 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. - function initializeUpdateQueue(fiber) { - var queue = { - baseState: fiber.memoizedState, - firstBaseUpdate: null, - lastBaseUpdate: null, - shared: { - pending: null, - lanes: NoLanes, - hiddenCallbacks: null - }, - callbacks: null - }; - fiber.updateQueue = queue; - } - function cloneUpdateQueue(current, workInProgress) { - // Clone the update queue from current. Unless it's already a clone. - var queue = workInProgress.updateQueue; - var currentQueue = current.updateQueue; + var didScheduleMicrotask_act = false; // Used to quickly bail out of flushSync if there's no sync work to do. - if (queue === currentQueue) { - var clone = { - baseState: currentQueue.baseState, - firstBaseUpdate: currentQueue.firstBaseUpdate, - lastBaseUpdate: currentQueue.lastBaseUpdate, - shared: currentQueue.shared, - callbacks: null - }; - workInProgress.updateQueue = clone; + 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$3.current !== null) { + // We're inside an `act` scope. + if (!didScheduleMicrotask_act) { + didScheduleMicrotask_act = true; + scheduleImmediateTask(processRootScheduleInMicrotask); + } + } else { + if (!didScheduleMicrotask) { + didScheduleMicrotask = true; + scheduleImmediateTask(processRootScheduleInMicrotask); + } + } + + if (ReactCurrentActQueue$3.isBatchingLegacy && root.tag === LegacyRoot) { + // Special `act` case: Record whenever a legacy update is scheduled. + ReactCurrentActQueue$3.didScheduleLegacyUpdate = true; } } - function createUpdate(lane) { - var update = { - lane: lane, - tag: UpdateState, - payload: null, - callback: null, - next: null - }; - return update; + 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 enqueueUpdate(fiber, update, lane) { - var updateQueue = fiber.updateQueue; - if (updateQueue === null) { - // Only occurs if the fiber has been unmounted. - return null; + function flushSyncWorkAcrossRoots_impl(onlyLegacy) { + if (isFlushingWork) { + // Prevent reentrancy. + // TODO: Is this overly defensive? The callers must check the execution + // context first regardless. + return; } - var sharedQueue = updateQueue.shared; + if (!mightHavePendingSyncWork) { + // Fast path. There's no sync work to do. + return; + } // There may or may not be synchronous work scheduled. Let's check. - { - if ( - currentlyProcessingQueue === sharedQueue && - !didWarnUpdateInsideUpdate - ) { - var componentName = getComponentNameFromFiber(fiber); + var didPerformSomeWork; + var errors = null; + isFlushingWork = true; - error( - "An update (setState, replaceState, or forceUpdate) was scheduled " + - "from inside an update function. Update functions should be pure, " + - "with zero side-effects. Consider using componentDidUpdate or a " + - "callback.\n\nPlease update the following component: %s", - componentName - ); + do { + didPerformSomeWork = false; + var root = firstScheduledRoot; - didWarnUpdateInsideUpdate = true; - } - } + while (root !== null) { + if (onlyLegacy && root.tag !== LegacyRoot); + else { + var workInProgressRoot = getWorkInProgressRoot(); + var workInProgressRootRenderLanes = + getWorkInProgressRootRenderLanes(); + var nextLanes = getNextLanes( + root, + root === workInProgressRoot + ? workInProgressRootRenderLanes + : NoLanes + ); - if (isUnsafeClassRenderPhaseUpdate()) { - // This is an unsafe render phase update. Add directly to the update - // queue so we can process it immediately during the current render. - var pending = sharedQueue.pending; + if (includesSyncLane(nextLanes)) { + // This root has pending sync work. Flush it now. + try { + didPerformSomeWork = true; + performSyncWorkOnRoot(root, nextLanes); + } catch (error) { + // Collect errors so we can rethrow them at the end + if (errors === null) { + errors = [error]; + } else { + errors.push(error); + } + } + } + } - if (pending === null) { - // This is the first update. Create a circular list. - update.next = update; - } else { - update.next = pending.next; - pending.next = update; + root = root.next; } + } while (didPerformSomeWork); - sharedQueue.pending = update; // Update the childLanes even though we're most likely already rendering - // this fiber. This is for backwards compatibility in the case where you - // update a different component during render phase than the one that is - // currently renderings (a pattern that is accompanied by a warning). + 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. - return unsafe_markUpdateLaneFromFiberToRoot(fiber, lane); - } else { - return enqueueConcurrentClassUpdate(fiber, sharedQueue, update, lane); - } - } - function entangleTransitions(root, fiber, lane) { - var updateQueue = fiber.updateQueue; + 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])); + } - if (updateQueue === null) { - // Only occurs if the fiber has been unmounted. - return; + var firstError = errors[0]; + throw firstError; + } + } else { + var error = errors[0]; + throw error; + } } + } - var sharedQueue = updateQueue.shared; - - if (isTransitionLane(lane)) { - var queueLanes = sharedQueue.lanes; // If any entangled lanes are no longer pending on the root, then they must - // have finished. We can remove them from the shared queue, which represents - // a superset of the actually pending lanes. In some cases we may entangle - // more than we need to, but that's OK. In fact it's worse if we *don't* - // entangle when we should. + function throwError(error) { + throw error; + } - queueLanes = intersectLanes(queueLanes, root.pendingLanes); // Entangle the new transition lane with the other transition lanes. + function processRootScheduleInMicrotask() { + // This function is always called inside a microtask. It should never be + // called synchronously. + didScheduleMicrotask = false; - var newQueueLanes = mergeLanes(queueLanes, lane); - sharedQueue.lanes = newQueueLanes; // Even if queue.lanes already include lane, we don't know for certain if - // the lane finished since the last time we entangled it. So we need to - // entangle it again, just to be sure. + { + didScheduleMicrotask_act = false; + } // We'll recompute this as we iterate through all the roots and schedule them. - markRootEntangled(root, newQueueLanes); - } - } - function enqueueCapturedUpdate(workInProgress, capturedUpdate) { - // Captured updates are updates that are thrown by a child during the render - // phase. They should be discarded if the render is aborted. Therefore, - // we should only put them on the work-in-progress queue, not the current one. - var queue = workInProgress.updateQueue; // Check if the work-in-progress queue is a clone. + mightHavePendingSyncWork = false; + var currentTime = now$1(); + var prev = null; + var root = firstScheduledRoot; - var current = workInProgress.alternate; + while (root !== null) { + var next = root.next; - if (current !== null) { - var currentQueue = current.updateQueue; - - if (queue === currentQueue) { - // The work-in-progress queue is the same as current. This happens when - // we bail out on a parent fiber that then captures an error thrown by - // a child. Since we want to append the update only to the work-in - // -progress queue, we need to clone the updates. We usually clone during - // processUpdateQueue, but that didn't happen in this case because we - // skipped over the parent when we bailed out. - var newFirst = null; - var newLast = null; - var firstBaseUpdate = queue.firstBaseUpdate; - - if (firstBaseUpdate !== null) { - // Loop through the updates and clone them. - var update = firstBaseUpdate; - - do { - var clone = { - lane: update.lane, - tag: update.tag, - payload: update.payload, - // When this update is rebased, we should not fire its - // callback again. - callback: null, - next: null - }; + if ( + currentEventTransitionLane !== NoLane && + shouldAttemptEagerTransition() + ) { + // A transition was scheduled during an event, but we're going to try to + // render it synchronously anyway. We do this during a popstate event to + // preserve the scroll position of the previous page. + upgradePendingLaneToSync(root, currentEventTransitionLane); + } - if (newLast === null) { - newFirst = newLast = clone; - } else { - newLast.next = clone; - newLast = clone; - } // $FlowFixMe[incompatible-type] we bail out when we get a null + var nextLanes = scheduleTaskForRootDuringMicrotask(root, currentTime); - update = update.next; - } while (update !== null); // Append the captured update the end of the cloned list. + 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 (newLast === null) { - newFirst = newLast = capturedUpdate; - } else { - newLast.next = capturedUpdate; - newLast = capturedUpdate; - } + if (prev === null) { + // This is the new head of the list + firstScheduledRoot = next; } else { - // There are no base updates. - newFirst = newLast = capturedUpdate; + prev.next = next; } - queue = { - baseState: currentQueue.baseState, - firstBaseUpdate: newFirst, - lastBaseUpdate: newLast, - shared: currentQueue.shared, - callbacks: currentQueue.callbacks - }; - workInProgress.updateQueue = queue; - return; - } - } // Append the update to the end of the list. + 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; - var lastBaseUpdate = queue.lastBaseUpdate; + if (includesSyncLane(nextLanes)) { + mightHavePendingSyncWork = true; + } + } - if (lastBaseUpdate === null) { - queue.firstBaseUpdate = capturedUpdate; - } else { - lastBaseUpdate.next = capturedUpdate; + root = next; } - queue.lastBaseUpdate = capturedUpdate; - } + 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. - function getStateFromUpdate( - workInProgress, - queue, - update, - prevState, - nextProps, - instance - ) { - switch (update.tag) { - case ReplaceState: { - var payload = update.payload; + flushSyncWorkOnAllRoots(); + } - if (typeof payload === "function") { - // Updater function - { - enterDisallowedContextReadInDEV(); - } + 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 nextState = payload.call(instance, prevState, nextProps); + var workInProgressRoot = getWorkInProgressRoot(); + var workInProgressRootRenderLanes = getWorkInProgressRootRenderLanes(); + var nextLanes = getNextLanes( + root, + root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes + ); + var existingCallbackNode = root.callbackNode; - { - exitDisallowedContextReadInDEV(); - } + 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); + } - return nextState; - } // State object + root.callbackNode = null; + root.callbackPriority = NoLane; + return NoLane; + } // Schedule a new callback in the host environment. - return payload; + 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); } - case CaptureUpdate: { - workInProgress.flags = - (workInProgress.flags & ~ShouldCapture) | DidCapture; + 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$3.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); } - // Intentional fallthrough - case UpdateState: { - var _payload = update.payload; - var partialState; + var schedulerPriorityLevel; - if (typeof _payload === "function") { - // Updater function - { - enterDisallowedContextReadInDEV(); - } + switch (lanesToEventPriority(nextLanes)) { + case DiscreteEventPriority: + schedulerPriorityLevel = ImmediatePriority; + break; - partialState = _payload.call(instance, prevState, nextProps); + case ContinuousEventPriority: + schedulerPriorityLevel = UserBlockingPriority; + break; - { - exitDisallowedContextReadInDEV(); - } - } else { - // Partial state object - partialState = _payload; - } + case DefaultEventPriority: + schedulerPriorityLevel = NormalPriority$1; + break; - if (partialState === null || partialState === undefined) { - // Null and undefined are treated as no-ops. - return prevState; - } // Merge the partial state and the previous state. + case IdleEventPriority: + schedulerPriorityLevel = IdlePriority; + break; - return assign({}, prevState, partialState); + default: + schedulerPriorityLevel = NormalPriority$1; + break; } - case ForceUpdate: { - hasForceUpdate = true; - return prevState; - } + var newCallbackNode = scheduleCallback$2( + schedulerPriorityLevel, + performConcurrentWorkOnRoot.bind(null, root) + ); + root.callbackPriority = newCallbackPriority; + root.callbackNode = newCallbackNode; + return newCallbackPriority; } - - return prevState; } - function processUpdateQueue(workInProgress, props, instance, renderLanes) { - // This is always non-null on a ClassComponent or HostRoot - var queue = workInProgress.updateQueue; - hasForceUpdate = false; + 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()); - { - currentlyProcessingQueue = queue.shared; - } - - var firstBaseUpdate = queue.firstBaseUpdate; - var lastBaseUpdate = queue.lastBaseUpdate; // Check if there are pending updates. If so, transfer them to the base queue. - - var pendingQueue = queue.shared.pending; - - if (pendingQueue !== null) { - queue.shared.pending = null; // The pending queue is circular. Disconnect the pointer between first - // and last so that it's non-circular. - - var lastPendingUpdate = pendingQueue; - var firstPendingUpdate = lastPendingUpdate.next; - lastPendingUpdate.next = null; // Append pending updates to base queue - - if (lastBaseUpdate === null) { - firstBaseUpdate = firstPendingUpdate; - } else { - lastBaseUpdate.next = firstPendingUpdate; - } - - lastBaseUpdate = lastPendingUpdate; // If there's a current queue, and it's different from the base queue, then - // we need to transfer the updates to that queue, too. Because the base - // queue is a singly-linked list with no cycles, we can append to both - // lists and take advantage of structural sharing. - // TODO: Pass `current` as argument + if (root.callbackNode === originalCallbackNode) { + // The task node scheduled for this root is the same one that's + // currently executed. Need to return a continuation. + return performConcurrentWorkOnRoot.bind(null, root); + } - var current = workInProgress.alternate; + return null; + } + var fakeActCallbackNode$1 = {}; - if (current !== null) { - // This is always non-null on a ClassComponent or HostRoot - var currentQueue = current.updateQueue; - var currentLastBaseUpdate = currentQueue.lastBaseUpdate; + function scheduleCallback$2(priorityLevel, callback) { + if (ReactCurrentActQueue$3.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$3.current.push(callback); + return fakeActCallbackNode$1; + } else { + return scheduleCallback$3(priorityLevel, callback); + } + } - if (currentLastBaseUpdate !== lastBaseUpdate) { - if (currentLastBaseUpdate === null) { - currentQueue.firstBaseUpdate = firstPendingUpdate; - } else { - currentLastBaseUpdate.next = firstPendingUpdate; - } + function cancelCallback(callbackNode) { + if (callbackNode === fakeActCallbackNode$1); + else if (callbackNode !== null) { + cancelCallback$1(callbackNode); + } + } - currentQueue.lastBaseUpdate = lastPendingUpdate; - } - } - } // These values may change as we process the queue. + function scheduleImmediateTask(cb) { + if (ReactCurrentActQueue$3.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$3.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 (firstBaseUpdate !== null) { - // Iterate through the list of updates to compute the result. - var newState = queue.baseState; // TODO: Don't need to accumulate this. Instead, we can remove renderLanes - // from the original lanes. + { + // If microtasks are not supported, use Scheduler. + scheduleCallback$3(ImmediatePriority, cb); + } + } - var newLanes = NoLanes; - var newBaseState = null; - var newFirstBaseUpdate = null; - var newLastBaseUpdate = null; - var update = firstBaseUpdate; + 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(); + } - do { - // An extra OffscreenLane bit is added to updates that were made to - // a hidden tree, so that we can distinguish them from updates that were - // already there when the tree was hidden. - var updateLane = removeLanes(update.lane, OffscreenLane); - var isHiddenUpdate = updateLane !== update.lane; // Check if this update was made while the tree was hidden. If so, then - // it's not a "base" update and we should disregard the extra base lanes - // that were added to renderLanes when we entered the Offscreen tree. + return currentEventTransitionLane; + } - var shouldSkipUpdate = isHiddenUpdate - ? !isSubsetOfLanes(getWorkInProgressRootRenderLanes(), updateLane) - : !isSubsetOfLanes(renderLanes, updateLane); + // transition updates that occur while the async action is still in progress + // are treated as part of the action. + // + // The ideal behavior would be to treat each async function as an independent + // action. However, without a mechanism like AsyncContext, we can't tell which + // action an update corresponds to. So instead, we entangle them all into one. + // The listeners to notify once the entangled scope completes. - if (shouldSkipUpdate) { - // Priority is insufficient. Skip this update. If this is the first - // skipped update, the previous update/state is the new base - // update/state. - var clone = { - lane: updateLane, - tag: update.tag, - payload: update.payload, - callback: update.callback, - next: null - }; + var currentEntangledListeners = null; // The number of pending async actions in the entangled scope. - if (newLastBaseUpdate === null) { - newFirstBaseUpdate = newLastBaseUpdate = clone; - newBaseState = newState; - } else { - newLastBaseUpdate = newLastBaseUpdate.next = clone; - } // Update the remaining priority in the queue. + var currentEntangledPendingCount = 0; // The transition lane shared by all updates in the entangled scope. - newLanes = mergeLanes(newLanes, updateLane); - } else { - // This update does have sufficient priority. - if (newLastBaseUpdate !== null) { - var _clone = { - // This update is going to be committed so we never want uncommit - // it. Using NoLane works because 0 is a subset of all bitmasks, so - // this will never be skipped by the check above. - lane: NoLane, - tag: update.tag, - payload: update.payload, - // When this update is rebased, we should not fire its - // callback again. - callback: null, - next: null - }; - newLastBaseUpdate = newLastBaseUpdate.next = _clone; - } // Process this update. + var currentEntangledLane = NoLane; // A thenable that resolves when the entangled scope completes. It does not + // resolve to a particular value because it's only used for suspending the UI + // until the async action scope has completed. - newState = getStateFromUpdate( - workInProgress, - queue, - update, - newState, - props, - instance - ); - var callback = update.callback; + var currentEntangledActionThenable = null; + function entangleAsyncAction(thenable) { + // `thenable` is the return value of the async action scope function. Create + // a combined thenable that resolves once every entangled scope function + // has finished. + if (currentEntangledListeners === null) { + // There's no outer async action scope. Create a new one. + var entangledListeners = (currentEntangledListeners = []); + currentEntangledPendingCount = 0; + currentEntangledLane = requestTransitionLane(); + var entangledThenable = { + status: "pending", + value: undefined, + then: function (resolve) { + entangledListeners.push(resolve); + } + }; + currentEntangledActionThenable = entangledThenable; + } - if (callback !== null) { - workInProgress.flags |= Callback; + currentEntangledPendingCount++; + thenable.then(pingEngtangledActionScope, pingEngtangledActionScope); + return thenable; + } - if (isHiddenUpdate) { - workInProgress.flags |= Visibility; - } + function pingEngtangledActionScope() { + if ( + currentEntangledListeners !== null && + --currentEntangledPendingCount === 0 + ) { + // All the actions have finished. Close the entangled async action scope + // and notify all the listeners. + if (currentEntangledActionThenable !== null) { + var fulfilledThenable = currentEntangledActionThenable; + fulfilledThenable.status = "fulfilled"; + } - var callbacks = queue.callbacks; + var listeners = currentEntangledListeners; + currentEntangledListeners = null; + currentEntangledLane = NoLane; + currentEntangledActionThenable = null; - if (callbacks === null) { - queue.callbacks = [callback]; - } else { - callbacks.push(callback); - } - } - } // $FlowFixMe[incompatible-type] we bail out when we get a null + for (var i = 0; i < listeners.length; i++) { + var listener = listeners[i]; + listener(); + } + } + } - update = update.next; + function chainThenableValue(thenable, result) { + // Equivalent to: Promise.resolve(thenable).then(() => result), except we can + // cheat a bit since we know that that this thenable is only ever consumed + // by React. + // + // We don't technically require promise support on the client yet, hence this + // extra code. + var listeners = []; + var thenableWithOverride = { + status: "pending", + value: null, + reason: null, + then: function (resolve) { + listeners.push(resolve); + } + }; + thenable.then( + function (value) { + var fulfilledThenable = thenableWithOverride; + fulfilledThenable.status = "fulfilled"; + fulfilledThenable.value = result; - if (update === null) { - pendingQueue = queue.shared.pending; + for (var i = 0; i < listeners.length; i++) { + var listener = listeners[i]; + listener(result); + } + }, + function (error) { + var rejectedThenable = thenableWithOverride; + rejectedThenable.status = "rejected"; + rejectedThenable.reason = error; - if (pendingQueue === null) { - break; - } else { - // An update was scheduled from inside a reducer. Add the new - // pending updates to the end of the list and keep processing. - var _lastPendingUpdate = pendingQueue; // Intentionally unsound. Pending updates form a circular list, but we - // unravel them when transferring them to the base queue. + for (var i = 0; i < listeners.length; i++) { + var listener = listeners[i]; // This is a perf hack where we call the `onFulfill` ping function + // instead of `onReject`, because we know that React is the only + // consumer of these promises, and it passes the same listener to both. + // We also know that it will read the error directly off the + // `.reason` field. - var _firstPendingUpdate = _lastPendingUpdate.next; - _lastPendingUpdate.next = null; - update = _firstPendingUpdate; - queue.lastBaseUpdate = _lastPendingUpdate; - queue.shared.pending = null; - } + listener(undefined); } - } while (true); - - if (newLastBaseUpdate === null) { - newBaseState = newState; } + ); + return thenableWithOverride; + } + function peekEntangledActionLane() { + return currentEntangledLane; + } + function peekEntangledActionThenable() { + return currentEntangledActionThenable; + } - queue.baseState = newBaseState; - queue.firstBaseUpdate = newFirstBaseUpdate; - queue.lastBaseUpdate = newLastBaseUpdate; + var UpdateState = 0; + var ReplaceState = 1; + var ForceUpdate = 2; + var CaptureUpdate = 3; // Global state that is reset at the beginning of calling `processUpdateQueue`. + // It should only be read right after calling `processUpdateQueue`, via + // `checkHasForceUpdateAfterProcessing`. - if (firstBaseUpdate === null) { - // `queue.lanes` is used for entangling transitions. We can set it back to - // zero once the queue is empty. - queue.shared.lanes = NoLanes; - } // Set the remaining expiration time to be whatever is remaining in the queue. - // This should be fine because the only two other things that contribute to - // expiration time are props and context. We're already in the middle of the - // begin phase by the time we start processing the queue, so we've already - // dealt with the props. Context in components that specify - // shouldComponentUpdate is tricky; but we'll have to account for - // that regardless. + var hasForceUpdate = false; + var didWarnUpdateInsideUpdate; + var currentlyProcessingQueue; - markSkippedUpdateLanes(newLanes); - workInProgress.lanes = newLanes; - workInProgress.memoizedState = newState; - } + { + didWarnUpdateInsideUpdate = false; + currentlyProcessingQueue = null; + } - { - currentlyProcessingQueue = null; + function initializeUpdateQueue(fiber) { + var queue = { + baseState: fiber.memoizedState, + firstBaseUpdate: null, + lastBaseUpdate: null, + shared: { + pending: null, + lanes: NoLanes, + hiddenCallbacks: null + }, + callbacks: null + }; + fiber.updateQueue = queue; + } + function cloneUpdateQueue(current, workInProgress) { + // Clone the update queue from current. Unless it's already a clone. + var queue = workInProgress.updateQueue; + var currentQueue = current.updateQueue; + + if (queue === currentQueue) { + var clone = { + baseState: currentQueue.baseState, + firstBaseUpdate: currentQueue.firstBaseUpdate, + lastBaseUpdate: currentQueue.lastBaseUpdate, + shared: currentQueue.shared, + callbacks: null + }; + workInProgress.updateQueue = clone; } } + function createUpdate(lane) { + var update = { + lane: lane, + tag: UpdateState, + payload: null, + callback: null, + next: null + }; + return update; + } + function enqueueUpdate(fiber, update, lane) { + var updateQueue = fiber.updateQueue; - function callCallback(callback, context) { - if (typeof callback !== "function") { - throw new Error( - "Invalid argument passed as callback. Expected a function. Instead " + - ("received: " + callback) - ); + if (updateQueue === null) { + // Only occurs if the fiber has been unmounted. + return null; } - callback.call(context); - } + var sharedQueue = updateQueue.shared; - function resetHasForceUpdateBeforeProcessing() { - hasForceUpdate = false; - } - function checkHasForceUpdateAfterProcessing() { - return hasForceUpdate; - } - function deferHiddenCallbacks(updateQueue) { - // When an update finishes on a hidden component, its callback should not - // be fired until/unless the component is made visible again. Stash the - // callback on the shared queue object so it can be fired later. - var newHiddenCallbacks = updateQueue.callbacks; + { + if ( + currentlyProcessingQueue === sharedQueue && + !didWarnUpdateInsideUpdate + ) { + var componentName = getComponentNameFromFiber(fiber); - if (newHiddenCallbacks !== null) { - var existingHiddenCallbacks = updateQueue.shared.hiddenCallbacks; + error( + "An update (setState, replaceState, or forceUpdate) was scheduled " + + "from inside an update function. Update functions should be pure, " + + "with zero side-effects. Consider using componentDidUpdate or a " + + "callback.\n\nPlease update the following component: %s", + componentName + ); - if (existingHiddenCallbacks === null) { - updateQueue.shared.hiddenCallbacks = newHiddenCallbacks; - } else { - updateQueue.shared.hiddenCallbacks = - existingHiddenCallbacks.concat(newHiddenCallbacks); + didWarnUpdateInsideUpdate = true; } } - } - function commitHiddenCallbacks(updateQueue, context) { - // This component is switching from hidden -> visible. Commit any callbacks - // that were previously deferred. - var hiddenCallbacks = updateQueue.shared.hiddenCallbacks; - if (hiddenCallbacks !== null) { - updateQueue.shared.hiddenCallbacks = null; + if (isUnsafeClassRenderPhaseUpdate()) { + // This is an unsafe render phase update. Add directly to the update + // queue so we can process it immediately during the current render. + var pending = sharedQueue.pending; - for (var i = 0; i < hiddenCallbacks.length; i++) { - var callback = hiddenCallbacks[i]; - callCallback(callback, context); + if (pending === null) { + // This is the first update. Create a circular list. + update.next = update; + } else { + update.next = pending.next; + pending.next = update; } - } - } - function commitCallbacks(updateQueue, context) { - var callbacks = updateQueue.callbacks; - if (callbacks !== null) { - updateQueue.callbacks = null; + sharedQueue.pending = update; // Update the childLanes even though we're most likely already rendering + // this fiber. This is for backwards compatibility in the case where you + // update a different component during render phase than the one that is + // currently renderings (a pattern that is accompanied by a warning). - for (var i = 0; i < callbacks.length; i++) { - var callback = callbacks[i]; - callCallback(callback, context); - } + return unsafe_markUpdateLaneFromFiberToRoot(fiber, lane); + } else { + return enqueueConcurrentClassUpdate(fiber, sharedQueue, update, lane); } } + function entangleTransitions(root, fiber, lane) { + var updateQueue = fiber.updateQueue; - /** - * Performs equality by iterating through keys on an object and returning false - * when any key has values which are not strictly equal between the arguments. - * Returns true when the values of all keys are strictly equal. - */ - - function shallowEqual(objA, objB) { - if (objectIs(objA, objB)) { - return true; + if (updateQueue === null) { + // Only occurs if the fiber has been unmounted. + return; } - if ( - typeof objA !== "object" || - objA === null || - typeof objB !== "object" || - objB === null - ) { - return false; - } + var sharedQueue = updateQueue.shared; - var keysA = Object.keys(objA); - var keysB = Object.keys(objB); + if (isTransitionLane(lane)) { + var queueLanes = sharedQueue.lanes; // If any entangled lanes are no longer pending on the root, then they must + // have finished. We can remove them from the shared queue, which represents + // a superset of the actually pending lanes. In some cases we may entangle + // more than we need to, but that's OK. In fact it's worse if we *don't* + // entangle when we should. - if (keysA.length !== keysB.length) { - return false; - } // Test for A's keys different from B. + queueLanes = intersectLanes(queueLanes, root.pendingLanes); // Entangle the new transition lane with the other transition lanes. - for (var i = 0; i < keysA.length; i++) { - var currentKey = keysA[i]; + var newQueueLanes = mergeLanes(queueLanes, lane); + sharedQueue.lanes = newQueueLanes; // Even if queue.lanes already include lane, we don't know for certain if + // the lane finished since the last time we entangled it. So we need to + // entangle it again, just to be sure. - if ( - !hasOwnProperty.call(objB, currentKey) || // $FlowFixMe[incompatible-use] lost refinement of `objB` - !objectIs(objA[currentKey], objB[currentKey]) - ) { - return false; - } + markRootEntangled(root, newQueueLanes); } - - return true; } + function enqueueCapturedUpdate(workInProgress, capturedUpdate) { + // Captured updates are updates that are thrown by a child during the render + // phase. They should be discarded if the render is aborted. Therefore, + // we should only put them on the work-in-progress queue, not the current one. + var queue = workInProgress.updateQueue; // Check if the work-in-progress queue is a clone. - function describeFiber(fiber) { - var owner = fiber._debugOwner ? fiber._debugOwner.type : null; - var source = fiber._debugSource; + var current = workInProgress.alternate; - switch (fiber.tag) { - case HostHoistable: - case HostSingleton: - case HostComponent: - return describeBuiltInComponentFrame(fiber.type, source, owner); + if (current !== null) { + var currentQueue = current.updateQueue; - case LazyComponent: - return describeBuiltInComponentFrame("Lazy", source, owner); + if (queue === currentQueue) { + // The work-in-progress queue is the same as current. This happens when + // we bail out on a parent fiber that then captures an error thrown by + // a child. Since we want to append the update only to the work-in + // -progress queue, we need to clone the updates. We usually clone during + // processUpdateQueue, but that didn't happen in this case because we + // skipped over the parent when we bailed out. + var newFirst = null; + var newLast = null; + var firstBaseUpdate = queue.firstBaseUpdate; - case SuspenseComponent: - return describeBuiltInComponentFrame("Suspense", source, owner); + if (firstBaseUpdate !== null) { + // Loop through the updates and clone them. + var update = firstBaseUpdate; - case SuspenseListComponent: - return describeBuiltInComponentFrame("SuspenseList", source, owner); + do { + var clone = { + lane: update.lane, + tag: update.tag, + payload: update.payload, + // When this update is rebased, we should not fire its + // callback again. + callback: null, + next: null + }; - case FunctionComponent: - case IndeterminateComponent: - case SimpleMemoComponent: - return describeFunctionComponentFrame(fiber.type, source, owner); + if (newLast === null) { + newFirst = newLast = clone; + } else { + newLast.next = clone; + newLast = clone; + } // $FlowFixMe[incompatible-type] we bail out when we get a null - case ForwardRef: - return describeFunctionComponentFrame( - fiber.type.render, - source, - owner - ); + update = update.next; + } while (update !== null); // Append the captured update the end of the cloned list. - case ClassComponent: - return describeClassComponentFrame(fiber.type, source, owner); + if (newLast === null) { + newFirst = newLast = capturedUpdate; + } else { + newLast.next = capturedUpdate; + newLast = capturedUpdate; + } + } else { + // There are no base updates. + newFirst = newLast = capturedUpdate; + } - default: - return ""; + queue = { + baseState: currentQueue.baseState, + firstBaseUpdate: newFirst, + lastBaseUpdate: newLast, + shared: currentQueue.shared, + callbacks: currentQueue.callbacks + }; + workInProgress.updateQueue = queue; + return; + } + } // Append the update to the end of the list. + + var lastBaseUpdate = queue.lastBaseUpdate; + + if (lastBaseUpdate === null) { + queue.firstBaseUpdate = capturedUpdate; + } else { + lastBaseUpdate.next = capturedUpdate; } + + queue.lastBaseUpdate = capturedUpdate; } - function getStackByFiberInDevAndProd(workInProgress) { - try { - var info = ""; - var node = workInProgress; + function getStateFromUpdate( + workInProgress, + queue, + update, + prevState, + nextProps, + instance + ) { + switch (update.tag) { + case ReplaceState: { + var payload = update.payload; - do { - info += describeFiber(node); // $FlowFixMe[incompatible-type] we bail out when we get a null + if (typeof payload === "function") { + // Updater function + { + enterDisallowedContextReadInDEV(); + } - node = node.return; - } while (node); + var nextState = payload.call(instance, prevState, nextProps); - return info; - } catch (x) { - return "\nError generating stack: " + x.message + "\n" + x.stack; - } - } + { + exitDisallowedContextReadInDEV(); + } - var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; - var current = null; - var isRendering = false; - function getCurrentFiberOwnerNameInDevOrNull() { - { - if (current === null) { - return null; + return nextState; + } // State object + + return payload; } - var owner = current._debugOwner; + case CaptureUpdate: { + workInProgress.flags = + (workInProgress.flags & ~ShouldCapture) | DidCapture; + } + // Intentional fallthrough - if (owner !== null && typeof owner !== "undefined") { - return getComponentNameFromFiber(owner); + case UpdateState: { + var _payload = update.payload; + var partialState; + + if (typeof _payload === "function") { + // Updater function + { + enterDisallowedContextReadInDEV(); + } + + partialState = _payload.call(instance, prevState, nextProps); + + { + exitDisallowedContextReadInDEV(); + } + } else { + // Partial state object + partialState = _payload; + } + + if (partialState === null || partialState === undefined) { + // Null and undefined are treated as no-ops. + return prevState; + } // Merge the partial state and the previous state. + + return assign({}, prevState, partialState); + } + + case ForceUpdate: { + hasForceUpdate = true; + return prevState; } } - return null; + return prevState; } - function getCurrentFiberStackInDev() { - { - if (current === null) { - return ""; - } // Safe because if current fiber exists, we are reconciling, - // and it is guaranteed to be the work-in-progress version. + var didReadFromEntangledAsyncAction = false; // Each call to processUpdateQueue should be accompanied by a call to this. It's + // only in a separate function because in updateHostRoot, it must happen after + // all the context stacks have been pushed to, to prevent a stack mismatch. A + // bit unfortunate. - return getStackByFiberInDevAndProd(current); - } - } + function suspendIfUpdateReadFromEntangledAsyncAction() { + // Check if this update is part of a pending async action. If so, we'll + // need to suspend until the action has finished, so that it's batched + // together with future updates in the same action. + // TODO: Once we support hooks inside useMemo (or an equivalent + // memoization boundary like Forget), hoist this logic so that it only + // suspends if the memo boundary produces a new value. + if (didReadFromEntangledAsyncAction) { + var entangledActionThenable = peekEntangledActionThenable(); - function resetCurrentFiber() { - { - ReactDebugCurrentFrame.getCurrentStack = null; - current = null; - isRendering = false; - } - } - function setCurrentFiber(fiber) { - { - ReactDebugCurrentFrame.getCurrentStack = - fiber === null ? null : getCurrentFiberStackInDev; - current = fiber; - isRendering = false; - } - } - function getCurrentFiber() { - { - return current; + if (entangledActionThenable !== null) { + // TODO: Instead of the throwing the thenable directly, throw a + // special object like `use` does so we can detect if it's captured + // by userspace. + throw entangledActionThenable; + } } } - function setIsRendering(rendering) { + function processUpdateQueue(workInProgress, props, instance, renderLanes) { + didReadFromEntangledAsyncAction = false; // This is always non-null on a ClassComponent or HostRoot + + var queue = workInProgress.updateQueue; + hasForceUpdate = false; + { - isRendering = rendering; + currentlyProcessingQueue = queue.shared; } - } - var ReactStrictModeWarnings = { - recordUnsafeLifecycleWarnings: function (fiber, instance) {}, - flushPendingUnsafeLifecycleWarnings: function () {}, - recordLegacyContextWarning: function (fiber, instance) {}, - flushLegacyContextWarning: function () {}, - discardPendingWarnings: function () {} - }; + var firstBaseUpdate = queue.firstBaseUpdate; + var lastBaseUpdate = queue.lastBaseUpdate; // Check if there are pending updates. If so, transfer them to the base queue. - { - var findStrictRoot = function (fiber) { - var maybeStrictRoot = null; - var node = fiber; + var pendingQueue = queue.shared.pending; - while (node !== null) { - if (node.mode & StrictLegacyMode) { - maybeStrictRoot = node; - } + if (pendingQueue !== null) { + queue.shared.pending = null; // The pending queue is circular. Disconnect the pointer between first + // and last so that it's non-circular. - node = node.return; + var lastPendingUpdate = pendingQueue; + var firstPendingUpdate = lastPendingUpdate.next; + lastPendingUpdate.next = null; // Append pending updates to base queue + + if (lastBaseUpdate === null) { + firstBaseUpdate = firstPendingUpdate; + } else { + lastBaseUpdate.next = firstPendingUpdate; } - return maybeStrictRoot; - }; + lastBaseUpdate = lastPendingUpdate; // If there's a current queue, and it's different from the base queue, then + // we need to transfer the updates to that queue, too. Because the base + // queue is a singly-linked list with no cycles, we can append to both + // lists and take advantage of structural sharing. + // TODO: Pass `current` as argument - var setToSortedString = function (set) { - var array = []; - set.forEach(function (value) { - array.push(value); - }); - return array.sort().join(", "); - }; + var current = workInProgress.alternate; - var pendingComponentWillMountWarnings = []; - var pendingUNSAFE_ComponentWillMountWarnings = []; - var pendingComponentWillReceivePropsWarnings = []; - var pendingUNSAFE_ComponentWillReceivePropsWarnings = []; - var pendingComponentWillUpdateWarnings = []; - var pendingUNSAFE_ComponentWillUpdateWarnings = []; // Tracks components we have already warned about. + if (current !== null) { + // This is always non-null on a ClassComponent or HostRoot + var currentQueue = current.updateQueue; + var currentLastBaseUpdate = currentQueue.lastBaseUpdate; - var didWarnAboutUnsafeLifecycles = new Set(); + if (currentLastBaseUpdate !== lastBaseUpdate) { + if (currentLastBaseUpdate === null) { + currentQueue.firstBaseUpdate = firstPendingUpdate; + } else { + currentLastBaseUpdate.next = firstPendingUpdate; + } - ReactStrictModeWarnings.recordUnsafeLifecycleWarnings = function ( - fiber, - instance - ) { - // Dedupe strategy: Warn once per component. - if (didWarnAboutUnsafeLifecycles.has(fiber.type)) { - return; + currentQueue.lastBaseUpdate = lastPendingUpdate; + } } + } // These values may change as we process the queue. - if ( - typeof instance.componentWillMount === "function" && // Don't warn about react-lifecycles-compat polyfilled components. - instance.componentWillMount.__suppressDeprecationWarning !== true - ) { - pendingComponentWillMountWarnings.push(fiber); - } + if (firstBaseUpdate !== null) { + // Iterate through the list of updates to compute the result. + var newState = queue.baseState; // TODO: Don't need to accumulate this. Instead, we can remove renderLanes + // from the original lanes. - if ( - fiber.mode & StrictLegacyMode && - typeof instance.UNSAFE_componentWillMount === "function" - ) { - pendingUNSAFE_ComponentWillMountWarnings.push(fiber); - } + var newLanes = NoLanes; + var newBaseState = null; + var newFirstBaseUpdate = null; + var newLastBaseUpdate = null; + var update = firstBaseUpdate; - if ( - typeof instance.componentWillReceiveProps === "function" && - instance.componentWillReceiveProps.__suppressDeprecationWarning !== - true - ) { - pendingComponentWillReceivePropsWarnings.push(fiber); - } - - if ( - fiber.mode & StrictLegacyMode && - typeof instance.UNSAFE_componentWillReceiveProps === "function" - ) { - pendingUNSAFE_ComponentWillReceivePropsWarnings.push(fiber); - } + do { + // An extra OffscreenLane bit is added to updates that were made to + // a hidden tree, so that we can distinguish them from updates that were + // already there when the tree was hidden. + var updateLane = removeLanes(update.lane, OffscreenLane); + var isHiddenUpdate = updateLane !== update.lane; // Check if this update was made while the tree was hidden. If so, then + // it's not a "base" update and we should disregard the extra base lanes + // that were added to renderLanes when we entered the Offscreen tree. - if ( - typeof instance.componentWillUpdate === "function" && - instance.componentWillUpdate.__suppressDeprecationWarning !== true - ) { - pendingComponentWillUpdateWarnings.push(fiber); - } + var shouldSkipUpdate = isHiddenUpdate + ? !isSubsetOfLanes(getWorkInProgressRootRenderLanes(), updateLane) + : !isSubsetOfLanes(renderLanes, updateLane); - if ( - fiber.mode & StrictLegacyMode && - typeof instance.UNSAFE_componentWillUpdate === "function" - ) { - pendingUNSAFE_ComponentWillUpdateWarnings.push(fiber); - } - }; + if (shouldSkipUpdate) { + // Priority is insufficient. Skip this update. If this is the first + // skipped update, the previous update/state is the new base + // update/state. + var clone = { + lane: updateLane, + tag: update.tag, + payload: update.payload, + callback: update.callback, + next: null + }; - ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings = - function () { - // We do an initial pass to gather component names - var componentWillMountUniqueNames = new Set(); + if (newLastBaseUpdate === null) { + newFirstBaseUpdate = newLastBaseUpdate = clone; + newBaseState = newState; + } else { + newLastBaseUpdate = newLastBaseUpdate.next = clone; + } // Update the remaining priority in the queue. - if (pendingComponentWillMountWarnings.length > 0) { - pendingComponentWillMountWarnings.forEach(function (fiber) { - componentWillMountUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingComponentWillMountWarnings = []; - } + newLanes = mergeLanes(newLanes, updateLane); + } else { + // This update does have sufficient priority. + // Check if this update is part of a pending async action. If so, + // we'll need to suspend until the action has finished, so that it's + // batched together with future updates in the same action. + if ( + updateLane !== NoLane && + updateLane === peekEntangledActionLane() + ) { + didReadFromEntangledAsyncAction = true; + } - var UNSAFE_componentWillMountUniqueNames = new Set(); + if (newLastBaseUpdate !== null) { + var _clone = { + // This update is going to be committed so we never want uncommit + // it. Using NoLane works because 0 is a subset of all bitmasks, so + // this will never be skipped by the check above. + lane: NoLane, + tag: update.tag, + payload: update.payload, + // When this update is rebased, we should not fire its + // callback again. + callback: null, + next: null + }; + newLastBaseUpdate = newLastBaseUpdate.next = _clone; + } // Process this update. - if (pendingUNSAFE_ComponentWillMountWarnings.length > 0) { - pendingUNSAFE_ComponentWillMountWarnings.forEach(function (fiber) { - UNSAFE_componentWillMountUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingUNSAFE_ComponentWillMountWarnings = []; - } + newState = getStateFromUpdate( + workInProgress, + queue, + update, + newState, + props, + instance + ); + var callback = update.callback; - var componentWillReceivePropsUniqueNames = new Set(); + if (callback !== null) { + workInProgress.flags |= Callback; - if (pendingComponentWillReceivePropsWarnings.length > 0) { - pendingComponentWillReceivePropsWarnings.forEach(function (fiber) { - componentWillReceivePropsUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingComponentWillReceivePropsWarnings = []; - } + if (isHiddenUpdate) { + workInProgress.flags |= Visibility; + } - var UNSAFE_componentWillReceivePropsUniqueNames = new Set(); + var callbacks = queue.callbacks; - if (pendingUNSAFE_ComponentWillReceivePropsWarnings.length > 0) { - pendingUNSAFE_ComponentWillReceivePropsWarnings.forEach( - function (fiber) { - UNSAFE_componentWillReceivePropsUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); + if (callbacks === null) { + queue.callbacks = [callback]; + } else { + callbacks.push(callback); } - ); - pendingUNSAFE_ComponentWillReceivePropsWarnings = []; - } + } + } // $FlowFixMe[incompatible-type] we bail out when we get a null - var componentWillUpdateUniqueNames = new Set(); + update = update.next; - if (pendingComponentWillUpdateWarnings.length > 0) { - pendingComponentWillUpdateWarnings.forEach(function (fiber) { - componentWillUpdateUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingComponentWillUpdateWarnings = []; - } + if (update === null) { + pendingQueue = queue.shared.pending; - var UNSAFE_componentWillUpdateUniqueNames = new Set(); + if (pendingQueue === null) { + break; + } else { + // An update was scheduled from inside a reducer. Add the new + // pending updates to the end of the list and keep processing. + var _lastPendingUpdate = pendingQueue; // Intentionally unsound. Pending updates form a circular list, but we + // unravel them when transferring them to the base queue. - if (pendingUNSAFE_ComponentWillUpdateWarnings.length > 0) { - pendingUNSAFE_ComponentWillUpdateWarnings.forEach(function (fiber) { - UNSAFE_componentWillUpdateUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingUNSAFE_ComponentWillUpdateWarnings = []; - } // Finally, we flush all the warnings - // UNSAFE_ ones before the deprecated ones, since they'll be 'louder' + var _firstPendingUpdate = _lastPendingUpdate.next; + _lastPendingUpdate.next = null; + update = _firstPendingUpdate; + queue.lastBaseUpdate = _lastPendingUpdate; + queue.shared.pending = null; + } + } + } while (true); - if (UNSAFE_componentWillMountUniqueNames.size > 0) { - var sortedNames = setToSortedString( - UNSAFE_componentWillMountUniqueNames - ); + if (newLastBaseUpdate === null) { + newBaseState = newState; + } - error( - "Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code. " + - "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + - "* Move code with side effects to componentDidMount, and set initial state in the constructor.\n" + - "\nPlease update the following components: %s", - sortedNames - ); - } + queue.baseState = newBaseState; + queue.firstBaseUpdate = newFirstBaseUpdate; + queue.lastBaseUpdate = newLastBaseUpdate; - if (UNSAFE_componentWillReceivePropsUniqueNames.size > 0) { - var _sortedNames = setToSortedString( - UNSAFE_componentWillReceivePropsUniqueNames - ); + if (firstBaseUpdate === null) { + // `queue.lanes` is used for entangling transitions. We can set it back to + // zero once the queue is empty. + queue.shared.lanes = NoLanes; + } // Set the remaining expiration time to be whatever is remaining in the queue. + // This should be fine because the only two other things that contribute to + // expiration time are props and context. We're already in the middle of the + // begin phase by the time we start processing the queue, so we've already + // dealt with the props. Context in components that specify + // shouldComponentUpdate is tricky; but we'll have to account for + // that regardless. - error( - "Using UNSAFE_componentWillReceiveProps in strict mode is not recommended " + - "and may indicate bugs in your code. " + - "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + - "* Move data fetching code or side effects to componentDidUpdate.\n" + - "* If you're updating state whenever props change, " + - "refactor your code to use memoization techniques or move it to " + - "static getDerivedStateFromProps. Learn more at: https://reactjs.org/link/derived-state\n" + - "\nPlease update the following components: %s", - _sortedNames - ); - } + markSkippedUpdateLanes(newLanes); + workInProgress.lanes = newLanes; + workInProgress.memoizedState = newState; + } - if (UNSAFE_componentWillUpdateUniqueNames.size > 0) { - var _sortedNames2 = setToSortedString( - UNSAFE_componentWillUpdateUniqueNames - ); + { + currentlyProcessingQueue = null; + } + } - error( - "Using UNSAFE_componentWillUpdate in strict mode is not recommended " + - "and may indicate bugs in your code. " + - "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + - "* Move data fetching code or side effects to componentDidUpdate.\n" + - "\nPlease update the following components: %s", - _sortedNames2 - ); - } + function callCallback(callback, context) { + if (typeof callback !== "function") { + throw new Error( + "Invalid argument passed as callback. Expected a function. Instead " + + ("received: " + callback) + ); + } - if (componentWillMountUniqueNames.size > 0) { - var _sortedNames3 = setToSortedString( - componentWillMountUniqueNames - ); + callback.call(context); + } - warn( - "componentWillMount has been renamed, and is not recommended for use. " + - "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + - "* Move code with side effects to componentDidMount, and set initial state in the constructor.\n" + - "* Rename componentWillMount to UNSAFE_componentWillMount to suppress " + - "this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. " + - "To rename all deprecated lifecycles to their new names, you can run " + - "`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n" + - "\nPlease update the following components: %s", - _sortedNames3 - ); - } + function resetHasForceUpdateBeforeProcessing() { + hasForceUpdate = false; + } + function checkHasForceUpdateAfterProcessing() { + return hasForceUpdate; + } + function deferHiddenCallbacks(updateQueue) { + // When an update finishes on a hidden component, its callback should not + // be fired until/unless the component is made visible again. Stash the + // callback on the shared queue object so it can be fired later. + var newHiddenCallbacks = updateQueue.callbacks; - if (componentWillReceivePropsUniqueNames.size > 0) { - var _sortedNames4 = setToSortedString( - componentWillReceivePropsUniqueNames - ); + if (newHiddenCallbacks !== null) { + var existingHiddenCallbacks = updateQueue.shared.hiddenCallbacks; - warn( - "componentWillReceiveProps has been renamed, and is not recommended for use. " + - "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + - "* Move data fetching code or side effects to componentDidUpdate.\n" + - "* If you're updating state whenever props change, refactor your " + - "code to use memoization techniques or move it to " + - "static getDerivedStateFromProps. Learn more at: https://reactjs.org/link/derived-state\n" + - "* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress " + - "this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. " + - "To rename all deprecated lifecycles to their new names, you can run " + - "`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n" + - "\nPlease update the following components: %s", - _sortedNames4 - ); - } + if (existingHiddenCallbacks === null) { + updateQueue.shared.hiddenCallbacks = newHiddenCallbacks; + } else { + updateQueue.shared.hiddenCallbacks = + existingHiddenCallbacks.concat(newHiddenCallbacks); + } + } + } + function commitHiddenCallbacks(updateQueue, context) { + // This component is switching from hidden -> visible. Commit any callbacks + // that were previously deferred. + var hiddenCallbacks = updateQueue.shared.hiddenCallbacks; - if (componentWillUpdateUniqueNames.size > 0) { - var _sortedNames5 = setToSortedString( - componentWillUpdateUniqueNames - ); + if (hiddenCallbacks !== null) { + updateQueue.shared.hiddenCallbacks = null; - warn( - "componentWillUpdate has been renamed, and is not recommended for use. " + - "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + - "* Move data fetching code or side effects to componentDidUpdate.\n" + - "* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress " + - "this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. " + - "To rename all deprecated lifecycles to their new names, you can run " + - "`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n" + - "\nPlease update the following components: %s", - _sortedNames5 - ); - } - }; + for (var i = 0; i < hiddenCallbacks.length; i++) { + var callback = hiddenCallbacks[i]; + callCallback(callback, context); + } + } + } + function commitCallbacks(updateQueue, context) { + var callbacks = updateQueue.callbacks; - var pendingLegacyContextWarning = new Map(); // Tracks components we have already warned about. + if (callbacks !== null) { + updateQueue.callbacks = null; - var didWarnAboutLegacyContext = new Set(); + for (var i = 0; i < callbacks.length; i++) { + var callback = callbacks[i]; + callCallback(callback, context); + } + } + } - ReactStrictModeWarnings.recordLegacyContextWarning = function ( - fiber, - instance - ) { - var strictRoot = findStrictRoot(fiber); + /** + * Performs equality by iterating through keys on an object and returning false + * when any key has values which are not strictly equal between the arguments. + * Returns true when the values of all keys are strictly equal. + */ - if (strictRoot === null) { - error( - "Expected to find a StrictMode component in a strict mode tree. " + - "This error is likely caused by a bug in React. Please file an issue." - ); + function shallowEqual(objA, objB) { + if (objectIs(objA, objB)) { + return true; + } - return; - } // Dedup strategy: Warn once per component. + if ( + typeof objA !== "object" || + objA === null || + typeof objB !== "object" || + objB === null + ) { + return false; + } - if (didWarnAboutLegacyContext.has(fiber.type)) { - return; - } + var keysA = Object.keys(objA); + var keysB = Object.keys(objB); - var warningsForRoot = pendingLegacyContextWarning.get(strictRoot); + if (keysA.length !== keysB.length) { + return false; + } // Test for A's keys different from B. + + for (var i = 0; i < keysA.length; i++) { + var currentKey = keysA[i]; if ( - fiber.type.contextTypes != null || - fiber.type.childContextTypes != null || - (instance !== null && typeof instance.getChildContext === "function") + !hasOwnProperty.call(objB, currentKey) || // $FlowFixMe[incompatible-use] lost refinement of `objB` + !objectIs(objA[currentKey], objB[currentKey]) ) { - if (warningsForRoot === undefined) { - warningsForRoot = []; - pendingLegacyContextWarning.set(strictRoot, warningsForRoot); - } - - warningsForRoot.push(fiber); + return false; } - }; + } - ReactStrictModeWarnings.flushLegacyContextWarning = function () { - pendingLegacyContextWarning.forEach(function (fiberArray, strictRoot) { - if (fiberArray.length === 0) { - return; - } + return true; + } - var firstFiber = fiberArray[0]; - var uniqueNames = new Set(); - fiberArray.forEach(function (fiber) { - uniqueNames.add(getComponentNameFromFiber(fiber) || "Component"); - didWarnAboutLegacyContext.add(fiber.type); - }); - var sortedNames = setToSortedString(uniqueNames); + function describeFiber(fiber) { + var owner = fiber._debugOwner ? fiber._debugOwner.type : null; + var source = fiber._debugSource; - try { - setCurrentFiber(firstFiber); + switch (fiber.tag) { + case HostHoistable: + case HostSingleton: + case HostComponent: + return describeBuiltInComponentFrame(fiber.type, source, owner); - error( - "Legacy context API has been detected within a strict-mode tree." + - "\n\nThe old API will be supported in all 16.x releases, but applications " + - "using it should migrate to the new version." + - "\n\nPlease update the following components: %s" + - "\n\nLearn more about this warning here: https://reactjs.org/link/legacy-context", - sortedNames - ); - } finally { - resetCurrentFiber(); - } - }); - }; + case LazyComponent: + return describeBuiltInComponentFrame("Lazy", source, owner); - ReactStrictModeWarnings.discardPendingWarnings = function () { - pendingComponentWillMountWarnings = []; - pendingUNSAFE_ComponentWillMountWarnings = []; - pendingComponentWillReceivePropsWarnings = []; - pendingUNSAFE_ComponentWillReceivePropsWarnings = []; - pendingComponentWillUpdateWarnings = []; - pendingUNSAFE_ComponentWillUpdateWarnings = []; - pendingLegacyContextWarning = new Map(); - }; - } + case SuspenseComponent: + return describeBuiltInComponentFrame("Suspense", source, owner); - /* - * The `'' + value` pattern (used in perf-sensitive code) throws for Symbol - * and Temporal.* types. See https://github.com/facebook/react/pull/22064. - * - * The functions in this module will throw an easier-to-understand, - * easier-to-debug exception with a clear errors message message explaining the - * problem. (Instead of a confusing exception thrown inside the implementation - * of the `value` object). - */ - // $FlowFixMe[incompatible-return] only called in DEV, so void return is not possible. - function typeName(value) { - { - // toStringTag is needed for namespaced types like Temporal.Instant - var hasToStringTag = typeof Symbol === "function" && Symbol.toStringTag; - var type = - (hasToStringTag && value[Symbol.toStringTag]) || - value.constructor.name || - "Object"; // $FlowFixMe[incompatible-return] + case SuspenseListComponent: + return describeBuiltInComponentFrame("SuspenseList", source, owner); - return type; - } - } // $FlowFixMe[incompatible-return] only called in DEV, so void return is not possible. + case FunctionComponent: + case IndeterminateComponent: + case SimpleMemoComponent: + return describeFunctionComponentFrame(fiber.type, source, owner); - function willCoercionThrow(value) { - { - try { - testStringCoercion(value); - return false; - } catch (e) { - return true; - } + case ForwardRef: + return describeFunctionComponentFrame( + fiber.type.render, + source, + owner + ); + + case ClassComponent: + return describeClassComponentFrame(fiber.type, source, owner); + + default: + return ""; } } - function testStringCoercion(value) { - // If you ended up here by following an exception call stack, here's what's - // happened: you supplied an object or symbol value to React (as a prop, key, - // DOM attribute, CSS property, string ref, etc.) and when React tried to - // coerce it to a string using `'' + value`, an exception was thrown. - // - // The most common types that will cause this exception are `Symbol` instances - // and Temporal objects like `Temporal.Instant`. But any object that has a - // `valueOf` or `[Symbol.toPrimitive]` method that throws will also cause this - // exception. (Library authors do this to prevent users from using built-in - // numeric operators like `+` or comparison operators like `>=` because custom - // methods are needed to perform accurate arithmetic or comparison.) - // - // To fix the problem, coerce this object or symbol value to a string before - // passing it to React. The most reliable way is usually `String(value)`. - // - // To find which value is throwing, check the browser or debugger console. - // Before this exception was thrown, there should be `console.error` output - // that shows the type (Symbol, Temporal.PlainDate, etc.) that caused the - // problem and how that type was used: key, atrribute, input value prop, etc. - // In most cases, this console output also shows the component and its - // ancestor components where the exception happened. - // - // eslint-disable-next-line react-internal/safe-string-coercion - return "" + value; + function getStackByFiberInDevAndProd(workInProgress) { + try { + var info = ""; + var node = workInProgress; + + do { + info += describeFiber(node); // $FlowFixMe[incompatible-type] we bail out when we get a null + + node = node.return; + } while (node); + + return info; + } catch (x) { + return "\nError generating stack: " + x.message + "\n" + x.stack; + } } - function checkPropStringCoercion(value, propName) { + + var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; + var current = null; + var isRendering = false; + function getCurrentFiberOwnerNameInDevOrNull() { { - if (willCoercionThrow(value)) { - error( - "The provided `%s` prop is an unsupported type %s." + - " This value must be coerced to a string before using it here.", - propName, - typeName(value) - ); + if (current === null) { + return null; + } - return testStringCoercion(value); // throw (to help callers find troubleshooting comments) + var owner = current._debugOwner; + + if (owner !== null && typeof owner !== "undefined") { + return getComponentNameFromFiber(owner); } } + + return null; } - var ReactCurrentActQueue$3 = ReactSharedInternals.ReactCurrentActQueue; // An error that is thrown (e.g. by `use`) to trigger Suspense. If we - // detect this is caught by userspace, we'll log a warning in development. + function getCurrentFiberStackInDev() { + { + if (current === null) { + return ""; + } // Safe because if current fiber exists, we are reconciling, + // and it is guaranteed to be the work-in-progress version. - var SuspenseException = new Error( - "Suspense Exception: This is not a real error! It's an implementation " + - "detail of `use` to interrupt the current render. You must either " + - "rethrow it immediately, or move the `use` call outside of the " + - "`try/catch` block. Capturing without rethrowing will lead to " + - "unexpected behavior.\n\n" + - "To handle async errors, wrap your component in an error boundary, or " + - "call the promise's `.catch` method and pass the result to `use`" - ); - var SuspenseyCommitException = new Error( - "Suspense Exception: This is not a real error, and should not leak into " + - "userspace. If you're seeing this, it's likely a bug in React." - ); // This is a noop thenable that we use to trigger a fallback in throwException. - // TODO: It would be better to refactor throwException into multiple functions - // so we can trigger a fallback directly without having to check the type. But - // for now this will do. + return getStackByFiberInDevAndProd(current); + } + } - var noopSuspenseyCommitThenable = { - then: function () { - { - error( - "Internal React error: A listener was unexpectedly attached to a " + - '"noop" thenable. This is a bug in React. Please file an issue.' - ); - } + function resetCurrentFiber() { + { + ReactDebugCurrentFrame.getCurrentStack = null; + current = null; + isRendering = false; } - }; - function createThenableState() { - // The ThenableState is created the first time a component suspends. If it - // suspends again, we'll reuse the same state. - return []; } - function isThenableResolved(thenable) { - var status = thenable.status; - return status === "fulfilled" || status === "rejected"; + function setCurrentFiber(fiber) { + { + ReactDebugCurrentFrame.getCurrentStack = + fiber === null ? null : getCurrentFiberStackInDev; + current = fiber; + isRendering = false; + } } - - function noop() {} - - function trackUsedThenable(thenableState, thenable, index) { - if (ReactCurrentActQueue$3.current !== null) { - ReactCurrentActQueue$3.didUsePromise = true; + function getCurrentFiber() { + { + return current; + } + } + function setIsRendering(rendering) { + { + isRendering = rendering; } + } - var previous = thenableState[index]; + var ReactStrictModeWarnings = { + recordUnsafeLifecycleWarnings: function (fiber, instance) {}, + flushPendingUnsafeLifecycleWarnings: function () {}, + recordLegacyContextWarning: function (fiber, instance) {}, + flushLegacyContextWarning: function () {}, + discardPendingWarnings: function () {} + }; - if (previous === undefined) { - thenableState.push(thenable); - } else { - if (previous !== thenable) { - // Reuse the previous thenable, and drop the new one. We can assume - // they represent the same value, because components are idempotent. - // Avoid an unhandled rejection errors for the Promises that we'll - // intentionally ignore. - thenable.then(noop, noop); - thenable = previous; - } - } // We use an expando to track the status and result of a thenable so that we - // can synchronously unwrap the value. Think of this as an extension of the - // Promise API, or a custom interface that is a superset of Thenable. - // - // If the thenable doesn't have a status, set it to "pending" and attach - // a listener that will update its status and result when it resolves. + { + var findStrictRoot = function (fiber) { + var maybeStrictRoot = null; + var node = fiber; - switch (thenable.status) { - case "fulfilled": { - var fulfilledValue = thenable.value; - return fulfilledValue; - } + while (node !== null) { + if (node.mode & StrictLegacyMode) { + maybeStrictRoot = node; + } - case "rejected": { - var rejectedError = thenable.reason; - checkIfUseWrappedInAsyncCatch(rejectedError); - throw rejectedError; + node = node.return; } - default: { - if (typeof thenable.status === "string") { - // Only instrument the thenable if the status if not defined. If - // it's defined, but an unknown value, assume it's been instrumented by - // some custom userspace implementation. We treat it as "pending". - // Attach a dummy listener, to ensure that any lazy initialization can - // happen. Flight lazily parses JSON when the value is actually awaited. - thenable.then(noop, noop); - } else { - // This is an uncached thenable that we haven't seen before. - // Detect infinite ping loops caused by uncached promises. - var root = getWorkInProgressRoot(); + return maybeStrictRoot; + }; - if (root !== null && root.shellSuspendCounter > 100) { - // This root has suspended repeatedly in the shell without making any - // progress (i.e. committing something). This is highly suggestive of - // an infinite ping loop, often caused by an accidental Async Client - // Component. - // - // During a transition, we can suspend the work loop until the promise - // to resolve, but this is a sync render, so that's not an option. We - // also can't show a fallback, because none was provided. So our last - // resort is to throw an error. - // - // TODO: Remove this error in a future release. Other ways of handling - // this case include forcing a concurrent render, or putting the whole - // root into offscreen mode. - throw new Error( - "async/await is not yet supported in Client Components, only " + - "Server Components. This error is often caused by accidentally " + - "adding `'use client'` to a module that was originally written " + - "for the server." - ); - } + var setToSortedString = function (set) { + var array = []; + set.forEach(function (value) { + array.push(value); + }); + return array.sort().join(", "); + }; - var pendingThenable = thenable; - pendingThenable.status = "pending"; - pendingThenable.then( - function (fulfilledValue) { - if (thenable.status === "pending") { - var fulfilledThenable = thenable; - fulfilledThenable.status = "fulfilled"; - fulfilledThenable.value = fulfilledValue; - } - }, - function (error) { - if (thenable.status === "pending") { - var rejectedThenable = thenable; - rejectedThenable.status = "rejected"; - rejectedThenable.reason = error; - } - } - ); // Check one more time in case the thenable resolved synchronously. + var pendingComponentWillMountWarnings = []; + var pendingUNSAFE_ComponentWillMountWarnings = []; + var pendingComponentWillReceivePropsWarnings = []; + var pendingUNSAFE_ComponentWillReceivePropsWarnings = []; + var pendingComponentWillUpdateWarnings = []; + var pendingUNSAFE_ComponentWillUpdateWarnings = []; // Tracks components we have already warned about. - switch (thenable.status) { - case "fulfilled": { - var fulfilledThenable = thenable; - return fulfilledThenable.value; - } + var didWarnAboutUnsafeLifecycles = new Set(); - case "rejected": { - var rejectedThenable = thenable; - var _rejectedError = rejectedThenable.reason; - checkIfUseWrappedInAsyncCatch(_rejectedError); - throw _rejectedError; - } - } - } // Suspend. - // - // Throwing here is an implementation detail that allows us to unwind the - // call stack. But we shouldn't allow it to leak into userspace. Throw an - // opaque placeholder value instead of the actual thenable. If it doesn't - // get captured by the work loop, log a warning, because that means - // something in userspace must have caught it. + ReactStrictModeWarnings.recordUnsafeLifecycleWarnings = function ( + fiber, + instance + ) { + // Dedupe strategy: Warn once per component. + if (didWarnAboutUnsafeLifecycles.has(fiber.type)) { + return; + } - suspendedThenable = thenable; - - { - needsToResetSuspendedThenableDEV = true; - } + if ( + typeof instance.componentWillMount === "function" && // Don't warn about react-lifecycles-compat polyfilled components. + instance.componentWillMount.__suppressDeprecationWarning !== true + ) { + pendingComponentWillMountWarnings.push(fiber); + } - throw SuspenseException; + if ( + fiber.mode & StrictLegacyMode && + typeof instance.UNSAFE_componentWillMount === "function" + ) { + pendingUNSAFE_ComponentWillMountWarnings.push(fiber); } - } - } - // passed to the rest of the Suspense implementation — which, for historical - // reasons, expects to receive a thenable. - var suspendedThenable = null; - var needsToResetSuspendedThenableDEV = false; - function getSuspendedThenable() { - // This is called right after `use` suspends by throwing an exception. `use` - // throws an opaque value instead of the thenable itself so that it can't be - // caught in userspace. Then the work loop accesses the actual thenable using - // this function. - if (suspendedThenable === null) { - throw new Error( - "Expected a suspended thenable. This is a bug in React. Please file " + - "an issue." - ); - } + if ( + typeof instance.componentWillReceiveProps === "function" && + instance.componentWillReceiveProps.__suppressDeprecationWarning !== + true + ) { + pendingComponentWillReceivePropsWarnings.push(fiber); + } - var thenable = suspendedThenable; - suspendedThenable = null; + if ( + fiber.mode & StrictLegacyMode && + typeof instance.UNSAFE_componentWillReceiveProps === "function" + ) { + pendingUNSAFE_ComponentWillReceivePropsWarnings.push(fiber); + } - { - needsToResetSuspendedThenableDEV = false; - } + if ( + typeof instance.componentWillUpdate === "function" && + instance.componentWillUpdate.__suppressDeprecationWarning !== true + ) { + pendingComponentWillUpdateWarnings.push(fiber); + } - return thenable; - } - function checkIfUseWrappedInTryCatch() { - { - // This was set right before SuspenseException was thrown, and it should - // have been cleared when the exception was handled. If it wasn't, - // it must have been caught by userspace. - if (needsToResetSuspendedThenableDEV) { - needsToResetSuspendedThenableDEV = false; - return true; + if ( + fiber.mode & StrictLegacyMode && + typeof instance.UNSAFE_componentWillUpdate === "function" + ) { + pendingUNSAFE_ComponentWillUpdateWarnings.push(fiber); } - } + }; - return false; - } - function checkIfUseWrappedInAsyncCatch(rejectedReason) { - // This check runs in prod, too, because it prevents a more confusing - // downstream error, where SuspenseException is caught by a promise and - // thrown asynchronously. - // TODO: Another way to prevent SuspenseException from leaking into an async - // execution context is to check the dispatcher every time `use` is called, - // or some equivalent. That might be preferable for other reasons, too, since - // it matches how we prevent similar mistakes for other hooks. - if (rejectedReason === SuspenseException) { - throw new Error( - "Hooks are not supported inside an async component. This " + - "error is often caused by accidentally adding `'use client'` " + - "to a module that was originally written for the server." - ); - } - } + ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings = + function () { + // We do an initial pass to gather component names + var componentWillMountUniqueNames = new Set(); - var thenableState$1 = null; - var thenableIndexCounter$1 = 0; - var didWarnAboutMaps; - var didWarnAboutGenerators; - var didWarnAboutStringRefs; - var ownerHasKeyUseWarning; - var ownerHasFunctionTypeWarning; + if (pendingComponentWillMountWarnings.length > 0) { + pendingComponentWillMountWarnings.forEach(function (fiber) { + componentWillMountUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingComponentWillMountWarnings = []; + } - var warnForMissingKey = function (child, returnFiber) {}; + var UNSAFE_componentWillMountUniqueNames = new Set(); - { - didWarnAboutMaps = false; - didWarnAboutGenerators = false; - didWarnAboutStringRefs = {}; - /** - * Warn if there's no key explicitly set on dynamic arrays of children or - * object keys are not valid. This allows us to keep track of children between - * updates. - */ + if (pendingUNSAFE_ComponentWillMountWarnings.length > 0) { + pendingUNSAFE_ComponentWillMountWarnings.forEach(function (fiber) { + UNSAFE_componentWillMountUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingUNSAFE_ComponentWillMountWarnings = []; + } - ownerHasKeyUseWarning = {}; - ownerHasFunctionTypeWarning = {}; + var componentWillReceivePropsUniqueNames = new Set(); - warnForMissingKey = function (child, returnFiber) { - if (child === null || typeof child !== "object") { - return; - } + if (pendingComponentWillReceivePropsWarnings.length > 0) { + pendingComponentWillReceivePropsWarnings.forEach(function (fiber) { + componentWillReceivePropsUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingComponentWillReceivePropsWarnings = []; + } - if (!child._store || child._store.validated || child.key != null) { - return; - } + var UNSAFE_componentWillReceivePropsUniqueNames = new Set(); - if (typeof child._store !== "object") { - throw new Error( - "React Component in warnForMissingKey should have a _store. " + - "This error is likely caused by a bug in React. Please file an issue." - ); - } // $FlowFixMe[cannot-write] unable to narrow type from mixed to writable object + if (pendingUNSAFE_ComponentWillReceivePropsWarnings.length > 0) { + pendingUNSAFE_ComponentWillReceivePropsWarnings.forEach( + function (fiber) { + UNSAFE_componentWillReceivePropsUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + } + ); + pendingUNSAFE_ComponentWillReceivePropsWarnings = []; + } - child._store.validated = true; - var componentName = - getComponentNameFromFiber(returnFiber) || "Component"; + var componentWillUpdateUniqueNames = new Set(); - if (ownerHasKeyUseWarning[componentName]) { - return; - } + if (pendingComponentWillUpdateWarnings.length > 0) { + pendingComponentWillUpdateWarnings.forEach(function (fiber) { + componentWillUpdateUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingComponentWillUpdateWarnings = []; + } - ownerHasKeyUseWarning[componentName] = true; + var UNSAFE_componentWillUpdateUniqueNames = new Set(); - error( - "Each child in a list should have a unique " + - '"key" prop. See https://reactjs.org/link/warning-keys for ' + - "more information." - ); - }; - } + if (pendingUNSAFE_ComponentWillUpdateWarnings.length > 0) { + pendingUNSAFE_ComponentWillUpdateWarnings.forEach(function (fiber) { + UNSAFE_componentWillUpdateUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingUNSAFE_ComponentWillUpdateWarnings = []; + } // Finally, we flush all the warnings + // UNSAFE_ ones before the deprecated ones, since they'll be 'louder' - function isReactClass(type) { - return type.prototype && type.prototype.isReactComponent; - } + if (UNSAFE_componentWillMountUniqueNames.size > 0) { + var sortedNames = setToSortedString( + UNSAFE_componentWillMountUniqueNames + ); - function unwrapThenable(thenable) { - var index = thenableIndexCounter$1; - thenableIndexCounter$1 += 1; + error( + "Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code. " + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + + "* Move code with side effects to componentDidMount, and set initial state in the constructor.\n" + + "\nPlease update the following components: %s", + sortedNames + ); + } - if (thenableState$1 === null) { - thenableState$1 = createThenableState(); - } + if (UNSAFE_componentWillReceivePropsUniqueNames.size > 0) { + var _sortedNames = setToSortedString( + UNSAFE_componentWillReceivePropsUniqueNames + ); - return trackUsedThenable(thenableState$1, thenable, index); - } + error( + "Using UNSAFE_componentWillReceiveProps in strict mode is not recommended " + + "and may indicate bugs in your code. " + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + + "* Move data fetching code or side effects to componentDidUpdate.\n" + + "* If you're updating state whenever props change, " + + "refactor your code to use memoization techniques or move it to " + + "static getDerivedStateFromProps. Learn more at: https://reactjs.org/link/derived-state\n" + + "\nPlease update the following components: %s", + _sortedNames + ); + } - function coerceRef(returnFiber, current, element) { - var mixedRef = element.ref; + if (UNSAFE_componentWillUpdateUniqueNames.size > 0) { + var _sortedNames2 = setToSortedString( + UNSAFE_componentWillUpdateUniqueNames + ); - if ( - mixedRef !== null && - typeof mixedRef !== "function" && - typeof mixedRef !== "object" - ) { - { - if ( - // We warn in ReactElement.js if owner and self are equal for string refs - // because these cannot be automatically converted to an arrow function - // using a codemod. Therefore, we don't have to warn about string refs again. - !( - element._owner && - element._self && - element._owner.stateNode !== element._self - ) && // Will already throw with "Function components cannot have string refs" - !(element._owner && element._owner.tag !== ClassComponent) && // Will already warn with "Function components cannot be given refs" - !( - typeof element.type === "function" && !isReactClass(element.type) - ) && // Will already throw with "Element ref was specified as a string (someStringRef) but no owner was set" - element._owner - ) { - var componentName = - getComponentNameFromFiber(returnFiber) || "Component"; - - if (!didWarnAboutStringRefs[componentName]) { - error( - 'Component "%s" contains the string ref "%s". Support for string refs ' + - "will be removed in a future major release. We recommend using " + - "useRef() or createRef() instead. " + - "Learn more about using refs safely here: " + - "https://reactjs.org/link/strict-mode-string-ref", - componentName, - mixedRef - ); - - didWarnAboutStringRefs[componentName] = true; - } - } - } - - if (element._owner) { - var owner = element._owner; - var inst; - - if (owner) { - var ownerFiber = owner; - - if (ownerFiber.tag !== ClassComponent) { - throw new Error( - "Function components cannot have string refs. " + - "We recommend using useRef() instead. " + - "Learn more about using refs safely here: " + - "https://reactjs.org/link/strict-mode-string-ref" - ); - } - - inst = ownerFiber.stateNode; + error( + "Using UNSAFE_componentWillUpdate in strict mode is not recommended " + + "and may indicate bugs in your code. " + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + + "* Move data fetching code or side effects to componentDidUpdate.\n" + + "\nPlease update the following components: %s", + _sortedNames2 + ); } - if (!inst) { - throw new Error( - "Missing owner for string ref " + - mixedRef + - ". This error is likely caused by a " + - "bug in React. Please file an issue." + if (componentWillMountUniqueNames.size > 0) { + var _sortedNames3 = setToSortedString( + componentWillMountUniqueNames ); - } // Assigning this to a const so Flow knows it won't change in the closure - - var resolvedInst = inst; - { - checkPropStringCoercion(mixedRef, "ref"); + warn( + "componentWillMount has been renamed, and is not recommended for use. " + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + + "* Move code with side effects to componentDidMount, and set initial state in the constructor.\n" + + "* Rename componentWillMount to UNSAFE_componentWillMount to suppress " + + "this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. " + + "To rename all deprecated lifecycles to their new names, you can run " + + "`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n" + + "\nPlease update the following components: %s", + _sortedNames3 + ); } - var stringRef = "" + mixedRef; // Check if previous string ref matches new string ref + if (componentWillReceivePropsUniqueNames.size > 0) { + var _sortedNames4 = setToSortedString( + componentWillReceivePropsUniqueNames + ); - if ( - current !== null && - current.ref !== null && - typeof current.ref === "function" && - current.ref._stringRef === stringRef - ) { - return current.ref; + warn( + "componentWillReceiveProps has been renamed, and is not recommended for use. " + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + + "* Move data fetching code or side effects to componentDidUpdate.\n" + + "* If you're updating state whenever props change, refactor your " + + "code to use memoization techniques or move it to " + + "static getDerivedStateFromProps. Learn more at: https://reactjs.org/link/derived-state\n" + + "* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress " + + "this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. " + + "To rename all deprecated lifecycles to their new names, you can run " + + "`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n" + + "\nPlease update the following components: %s", + _sortedNames4 + ); } - var ref = function (value) { - var refs = resolvedInst.refs; - - if (value === null) { - delete refs[stringRef]; - } else { - refs[stringRef] = value; - } - }; - - ref._stringRef = stringRef; - return ref; - } else { - if (typeof mixedRef !== "string") { - throw new Error( - "Expected ref to be a function, a string, an object returned by React.createRef(), or null." + if (componentWillUpdateUniqueNames.size > 0) { + var _sortedNames5 = setToSortedString( + componentWillUpdateUniqueNames ); - } - if (!element._owner) { - throw new Error( - "Element ref was specified as a string (" + - mixedRef + - ") but no owner was set. This could happen for one of" + - " the following reasons:\n" + - "1. You may be adding a ref to a function component\n" + - "2. You may be adding a ref to a component that was not created inside a component's render method\n" + - "3. You have multiple copies of React loaded\n" + - "See https://reactjs.org/link/refs-must-have-owner for more information." + warn( + "componentWillUpdate has been renamed, and is not recommended for use. " + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + + "* Move data fetching code or side effects to componentDidUpdate.\n" + + "* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress " + + "this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. " + + "To rename all deprecated lifecycles to their new names, you can run " + + "`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n" + + "\nPlease update the following components: %s", + _sortedNames5 ); } - } - } - - return mixedRef; - } - - function throwOnInvalidObjectType(returnFiber, newChild) { - // $FlowFixMe[method-unbinding] - var childString = Object.prototype.toString.call(newChild); - throw new Error( - "Objects are not valid as a React child (found: " + - (childString === "[object Object]" - ? "object with keys {" + Object.keys(newChild).join(", ") + "}" - : childString) + - "). " + - "If you meant to render a collection of children, use an array " + - "instead." - ); - } - - function warnOnFunctionType(returnFiber) { - { - var componentName = - getComponentNameFromFiber(returnFiber) || "Component"; + }; - if (ownerHasFunctionTypeWarning[componentName]) { - return; - } + var pendingLegacyContextWarning = new Map(); // Tracks components we have already warned about. - ownerHasFunctionTypeWarning[componentName] = true; + var didWarnAboutLegacyContext = new Set(); - error( - "Functions are not valid as a React child. This may happen if " + - "you return a Component instead of from render. " + - "Or maybe you meant to call this function rather than return it." - ); - } - } + ReactStrictModeWarnings.recordLegacyContextWarning = function ( + fiber, + instance + ) { + var strictRoot = findStrictRoot(fiber); - function resolveLazy(lazyType) { - var payload = lazyType._payload; - var init = lazyType._init; - return init(payload); - } // This wrapper function exists because I expect to clone the code in each path - // to be able to optimize each path individually by branching early. This needs - // a compiler or we can do it manually. Helpers that don't need this branching - // live outside of this function. + if (strictRoot === null) { + error( + "Expected to find a StrictMode component in a strict mode tree. " + + "This error is likely caused by a bug in React. Please file an issue." + ); - function createChildReconciler(shouldTrackSideEffects) { - function deleteChild(returnFiber, childToDelete) { - if (!shouldTrackSideEffects) { - // Noop. return; - } - - var deletions = returnFiber.deletions; + } // Dedup strategy: Warn once per component. - if (deletions === null) { - returnFiber.deletions = [childToDelete]; - returnFiber.flags |= ChildDeletion; - } else { - deletions.push(childToDelete); + if (didWarnAboutLegacyContext.has(fiber.type)) { + return; } - } - function deleteRemainingChildren(returnFiber, currentFirstChild) { - if (!shouldTrackSideEffects) { - // Noop. - return null; - } // TODO: For the shouldClone case, this could be micro-optimized a bit by - // assuming that after the first child we've already added everything. + var warningsForRoot = pendingLegacyContextWarning.get(strictRoot); - var childToDelete = currentFirstChild; + if ( + fiber.type.contextTypes != null || + fiber.type.childContextTypes != null || + (instance !== null && typeof instance.getChildContext === "function") + ) { + if (warningsForRoot === undefined) { + warningsForRoot = []; + pendingLegacyContextWarning.set(strictRoot, warningsForRoot); + } - while (childToDelete !== null) { - deleteChild(returnFiber, childToDelete); - childToDelete = childToDelete.sibling; + warningsForRoot.push(fiber); } + }; - return null; - } + ReactStrictModeWarnings.flushLegacyContextWarning = function () { + pendingLegacyContextWarning.forEach(function (fiberArray, strictRoot) { + if (fiberArray.length === 0) { + return; + } - function mapRemainingChildren(returnFiber, currentFirstChild) { - // Add the remaining children to a temporary map so that we can find them by - // keys quickly. Implicit (null) keys get added to this set with their index - // instead. - var existingChildren = new Map(); - var existingChild = currentFirstChild; + var firstFiber = fiberArray[0]; + var uniqueNames = new Set(); + fiberArray.forEach(function (fiber) { + uniqueNames.add(getComponentNameFromFiber(fiber) || "Component"); + didWarnAboutLegacyContext.add(fiber.type); + }); + var sortedNames = setToSortedString(uniqueNames); - while (existingChild !== null) { - if (existingChild.key !== null) { - existingChildren.set(existingChild.key, existingChild); - } else { - existingChildren.set(existingChild.index, existingChild); + try { + setCurrentFiber(firstFiber); + + error( + "Legacy context API has been detected within a strict-mode tree." + + "\n\nThe old API will be supported in all 16.x releases, but applications " + + "using it should migrate to the new version." + + "\n\nPlease update the following components: %s" + + "\n\nLearn more about this warning here: https://reactjs.org/link/legacy-context", + sortedNames + ); + } finally { + resetCurrentFiber(); } + }); + }; - existingChild = existingChild.sibling; - } + ReactStrictModeWarnings.discardPendingWarnings = function () { + pendingComponentWillMountWarnings = []; + pendingUNSAFE_ComponentWillMountWarnings = []; + pendingComponentWillReceivePropsWarnings = []; + pendingUNSAFE_ComponentWillReceivePropsWarnings = []; + pendingComponentWillUpdateWarnings = []; + pendingUNSAFE_ComponentWillUpdateWarnings = []; + pendingLegacyContextWarning = new Map(); + }; + } - return existingChildren; - } + /* + * The `'' + value` pattern (used in perf-sensitive code) throws for Symbol + * and Temporal.* types. See https://github.com/facebook/react/pull/22064. + * + * The functions in this module will throw an easier-to-understand, + * easier-to-debug exception with a clear errors message message explaining the + * problem. (Instead of a confusing exception thrown inside the implementation + * of the `value` object). + */ + // $FlowFixMe[incompatible-return] only called in DEV, so void return is not possible. + function typeName(value) { + { + // toStringTag is needed for namespaced types like Temporal.Instant + var hasToStringTag = typeof Symbol === "function" && Symbol.toStringTag; + var type = + (hasToStringTag && value[Symbol.toStringTag]) || + value.constructor.name || + "Object"; // $FlowFixMe[incompatible-return] - function useFiber(fiber, pendingProps) { - // We currently set sibling to null and index to 0 here because it is easy - // to forget to do before returning it. E.g. for the single child case. - var clone = createWorkInProgress(fiber, pendingProps); - clone.index = 0; - clone.sibling = null; - return clone; + return type; } + } // $FlowFixMe[incompatible-return] only called in DEV, so void return is not possible. - function placeChild(newFiber, lastPlacedIndex, newIndex) { - newFiber.index = newIndex; - - if (!shouldTrackSideEffects) { - // During hydration, the useId algorithm needs to know which fibers are - // part of a list of children (arrays, iterators). - newFiber.flags |= Forked; - return lastPlacedIndex; + function willCoercionThrow(value) { + { + try { + testStringCoercion(value); + return false; + } catch (e) { + return true; } + } + } - var current = newFiber.alternate; - - if (current !== null) { - var oldIndex = current.index; + function testStringCoercion(value) { + // If you ended up here by following an exception call stack, here's what's + // happened: you supplied an object or symbol value to React (as a prop, key, + // DOM attribute, CSS property, string ref, etc.) and when React tried to + // coerce it to a string using `'' + value`, an exception was thrown. + // + // The most common types that will cause this exception are `Symbol` instances + // and Temporal objects like `Temporal.Instant`. But any object that has a + // `valueOf` or `[Symbol.toPrimitive]` method that throws will also cause this + // exception. (Library authors do this to prevent users from using built-in + // numeric operators like `+` or comparison operators like `>=` because custom + // methods are needed to perform accurate arithmetic or comparison.) + // + // To fix the problem, coerce this object or symbol value to a string before + // passing it to React. The most reliable way is usually `String(value)`. + // + // To find which value is throwing, check the browser or debugger console. + // Before this exception was thrown, there should be `console.error` output + // that shows the type (Symbol, Temporal.PlainDate, etc.) that caused the + // problem and how that type was used: key, atrribute, input value prop, etc. + // In most cases, this console output also shows the component and its + // ancestor components where the exception happened. + // + // eslint-disable-next-line react-internal/safe-string-coercion + return "" + value; + } + function checkPropStringCoercion(value, propName) { + { + if (willCoercionThrow(value)) { + error( + "The provided `%s` prop is an unsupported type %s." + + " This value must be coerced to a string before using it here.", + propName, + typeName(value) + ); - if (oldIndex < lastPlacedIndex) { - // This is a move. - newFiber.flags |= Placement | PlacementDEV; - return lastPlacedIndex; - } else { - // This item can stay in place. - return oldIndex; - } - } else { - // This is an insertion. - newFiber.flags |= Placement | PlacementDEV; - return lastPlacedIndex; + return testStringCoercion(value); // throw (to help callers find troubleshooting comments) } } + } - function placeSingleChild(newFiber) { - // This is simpler for the single child case. We only need to do a - // placement for inserting new children. - if (shouldTrackSideEffects && newFiber.alternate === null) { - newFiber.flags |= Placement | PlacementDEV; - } + var ReactCurrentActQueue$2 = ReactSharedInternals.ReactCurrentActQueue; // An error that is thrown (e.g. by `use`) to trigger Suspense. If we + // detect this is caught by userspace, we'll log a warning in development. - return newFiber; - } + var SuspenseException = new Error( + "Suspense Exception: This is not a real error! It's an implementation " + + "detail of `use` to interrupt the current render. You must either " + + "rethrow it immediately, or move the `use` call outside of the " + + "`try/catch` block. Capturing without rethrowing will lead to " + + "unexpected behavior.\n\n" + + "To handle async errors, wrap your component in an error boundary, or " + + "call the promise's `.catch` method and pass the result to `use`" + ); + var SuspenseyCommitException = new Error( + "Suspense Exception: This is not a real error, and should not leak into " + + "userspace. If you're seeing this, it's likely a bug in React." + ); // This is a noop thenable that we use to trigger a fallback in throwException. + // TODO: It would be better to refactor throwException into multiple functions + // so we can trigger a fallback directly without having to check the type. But + // for now this will do. - function updateTextNode(returnFiber, current, textContent, lanes) { - if (current === null || current.tag !== HostText) { - // Insert - var created = createFiberFromText( - textContent, - returnFiber.mode, - lanes + var noopSuspenseyCommitThenable = { + then: function () { + { + error( + "Internal React error: A listener was unexpectedly attached to a " + + '"noop" thenable. This is a bug in React. Please file an issue.' ); - created.return = returnFiber; - return created; - } else { - // Update - var existing = useFiber(current, textContent); - existing.return = returnFiber; - return existing; } } + }; + function createThenableState() { + // The ThenableState is created the first time a component suspends. If it + // suspends again, we'll reuse the same state. + return []; + } + function isThenableResolved(thenable) { + var status = thenable.status; + return status === "fulfilled" || status === "rejected"; + } - function updateElement(returnFiber, current, element, lanes) { - var elementType = element.type; + function noop() {} - if (elementType === REACT_FRAGMENT_TYPE) { - return updateFragment( - returnFiber, - current, - element.props.children, - lanes, - element.key - ); - } + function trackUsedThenable(thenableState, thenable, index) { + if (ReactCurrentActQueue$2.current !== null) { + ReactCurrentActQueue$2.didUsePromise = true; + } - if (current !== null) { - if ( - current.elementType === elementType || // Keep this check inline so it only runs on the false path: - isCompatibleFamilyForHotReloading(current, element) || // Lazy types should reconcile their resolved type. - // We need to do this after the Hot Reloading check above, - // because hot reloading has different semantics than prod because - // it doesn't resuspend. So we can't let the call below suspend. - (typeof elementType === "object" && - elementType !== null && - elementType.$$typeof === REACT_LAZY_TYPE && - resolveLazy(elementType) === current.type) - ) { - // Move based on index - var existing = useFiber(current, element.props); - existing.ref = coerceRef(returnFiber, current, element); - existing.return = returnFiber; + var previous = thenableState[index]; - { - existing._debugSource = element._source; - existing._debugOwner = element._owner; - } + if (previous === undefined) { + thenableState.push(thenable); + } else { + if (previous !== thenable) { + // Reuse the previous thenable, and drop the new one. We can assume + // they represent the same value, because components are idempotent. + // Avoid an unhandled rejection errors for the Promises that we'll + // intentionally ignore. + thenable.then(noop, noop); + thenable = previous; + } + } // We use an expando to track the status and result of a thenable so that we + // can synchronously unwrap the value. Think of this as an extension of the + // Promise API, or a custom interface that is a superset of Thenable. + // + // If the thenable doesn't have a status, set it to "pending" and attach + // a listener that will update its status and result when it resolves. - return existing; - } - } // Insert + switch (thenable.status) { + case "fulfilled": { + var fulfilledValue = thenable.value; + return fulfilledValue; + } - var created = createFiberFromElement(element, returnFiber.mode, lanes); - created.ref = coerceRef(returnFiber, current, element); - created.return = returnFiber; - return created; - } - - function updatePortal(returnFiber, current, portal, lanes) { - if ( - current === null || - current.tag !== HostPortal || - current.stateNode.containerInfo !== portal.containerInfo || - current.stateNode.implementation !== portal.implementation - ) { - // Insert - var created = createFiberFromPortal(portal, returnFiber.mode, lanes); - created.return = returnFiber; - return created; - } else { - // Update - var existing = useFiber(current, portal.children || []); - existing.return = returnFiber; - return existing; - } - } - - function updateFragment(returnFiber, current, fragment, lanes, key) { - if (current === null || current.tag !== Fragment) { - // Insert - var created = createFiberFromFragment( - fragment, - returnFiber.mode, - lanes, - key - ); - created.return = returnFiber; - return created; - } else { - // Update - var existing = useFiber(current, fragment); - existing.return = returnFiber; - return existing; + case "rejected": { + var rejectedError = thenable.reason; + checkIfUseWrappedInAsyncCatch(rejectedError); + throw rejectedError; } - } - function createChild(returnFiber, newChild, lanes) { - if ( - (typeof newChild === "string" && newChild !== "") || - typeof newChild === "number" - ) { - // Text nodes don't have keys. If the previous node is implicitly keyed - // we can continue to replace it without aborting even if it is not a text - // node. - var created = createFiberFromText( - "" + newChild, - returnFiber.mode, - lanes - ); - created.return = returnFiber; - return created; - } + default: { + if (typeof thenable.status === "string") { + // Only instrument the thenable if the status if not defined. If + // it's defined, but an unknown value, assume it's been instrumented by + // some custom userspace implementation. We treat it as "pending". + // Attach a dummy listener, to ensure that any lazy initialization can + // happen. Flight lazily parses JSON when the value is actually awaited. + thenable.then(noop, noop); + } else { + // This is an uncached thenable that we haven't seen before. + // Detect infinite ping loops caused by uncached promises. + var root = getWorkInProgressRoot(); - if (typeof newChild === "object" && newChild !== null) { - switch (newChild.$$typeof) { - case REACT_ELEMENT_TYPE: { - var _created = createFiberFromElement( - newChild, - returnFiber.mode, - lanes + if (root !== null && root.shellSuspendCounter > 100) { + // This root has suspended repeatedly in the shell without making any + // progress (i.e. committing something). This is highly suggestive of + // an infinite ping loop, often caused by an accidental Async Client + // Component. + // + // During a transition, we can suspend the work loop until the promise + // to resolve, but this is a sync render, so that's not an option. We + // also can't show a fallback, because none was provided. So our last + // resort is to throw an error. + // + // TODO: Remove this error in a future release. Other ways of handling + // this case include forcing a concurrent render, or putting the whole + // root into offscreen mode. + throw new Error( + "async/await is not yet supported in Client Components, only " + + "Server Components. This error is often caused by accidentally " + + "adding `'use client'` to a module that was originally written " + + "for the server." ); - - _created.ref = coerceRef(returnFiber, null, newChild); - _created.return = returnFiber; - return _created; } - case REACT_PORTAL_TYPE: { - var _created2 = createFiberFromPortal( - newChild, - returnFiber.mode, - lanes - ); + var pendingThenable = thenable; + pendingThenable.status = "pending"; + pendingThenable.then( + function (fulfilledValue) { + if (thenable.status === "pending") { + var fulfilledThenable = thenable; + fulfilledThenable.status = "fulfilled"; + fulfilledThenable.value = fulfilledValue; + } + }, + function (error) { + if (thenable.status === "pending") { + var rejectedThenable = thenable; + rejectedThenable.status = "rejected"; + rejectedThenable.reason = error; + } + } + ); // Check one more time in case the thenable resolved synchronously. - _created2.return = returnFiber; - return _created2; - } + switch (thenable.status) { + case "fulfilled": { + var fulfilledThenable = thenable; + return fulfilledThenable.value; + } - case REACT_LAZY_TYPE: { - var payload = newChild._payload; - var init = newChild._init; - return createChild(returnFiber, init(payload), lanes); + case "rejected": { + var rejectedThenable = thenable; + var _rejectedError = rejectedThenable.reason; + checkIfUseWrappedInAsyncCatch(_rejectedError); + throw _rejectedError; + } } - } - - if (isArray(newChild) || getIteratorFn(newChild)) { - var _created3 = createFiberFromFragment( - newChild, - returnFiber.mode, - lanes, - null - ); - - _created3.return = returnFiber; - return _created3; - } // Usable node types + } // Suspend. // - // Unwrap the inner value and recursively call this function again. + // Throwing here is an implementation detail that allows us to unwind the + // call stack. But we shouldn't allow it to leak into userspace. Throw an + // opaque placeholder value instead of the actual thenable. If it doesn't + // get captured by the work loop, log a warning, because that means + // something in userspace must have caught it. - if (typeof newChild.then === "function") { - var thenable = newChild; - return createChild(returnFiber, unwrapThenable(thenable), lanes); - } + suspendedThenable = thenable; - if ( - newChild.$$typeof === REACT_CONTEXT_TYPE || - newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE - ) { - var context = newChild; - return createChild( - returnFiber, - readContextDuringReconcilation(returnFiber, context, lanes), - lanes - ); + { + needsToResetSuspendedThenableDEV = true; } - throwOnInvalidObjectType(returnFiber, newChild); - } - - { - if (typeof newChild === "function") { - warnOnFunctionType(returnFiber); - } + throw SuspenseException; } + } + } + // passed to the rest of the Suspense implementation — which, for historical + // reasons, expects to receive a thenable. - return null; + var suspendedThenable = null; + var needsToResetSuspendedThenableDEV = false; + function getSuspendedThenable() { + // This is called right after `use` suspends by throwing an exception. `use` + // throws an opaque value instead of the thenable itself so that it can't be + // caught in userspace. Then the work loop accesses the actual thenable using + // this function. + if (suspendedThenable === null) { + throw new Error( + "Expected a suspended thenable. This is a bug in React. Please file " + + "an issue." + ); } - function updateSlot(returnFiber, oldFiber, newChild, lanes) { - // Update the fiber if the keys match, otherwise return null. - var key = oldFiber !== null ? oldFiber.key : null; + var thenable = suspendedThenable; + suspendedThenable = null; - if ( - (typeof newChild === "string" && newChild !== "") || - typeof newChild === "number" - ) { - // Text nodes don't have keys. If the previous node is implicitly keyed - // we can continue to replace it without aborting even if it is not a text - // node. - if (key !== null) { - return null; - } + { + needsToResetSuspendedThenableDEV = false; + } - return updateTextNode(returnFiber, oldFiber, "" + newChild, lanes); + return thenable; + } + function checkIfUseWrappedInTryCatch() { + { + // This was set right before SuspenseException was thrown, and it should + // have been cleared when the exception was handled. If it wasn't, + // it must have been caught by userspace. + if (needsToResetSuspendedThenableDEV) { + needsToResetSuspendedThenableDEV = false; + return true; } + } - if (typeof newChild === "object" && newChild !== null) { - switch (newChild.$$typeof) { - case REACT_ELEMENT_TYPE: { - if (newChild.key === key) { - return updateElement(returnFiber, oldFiber, newChild, lanes); - } else { - return null; - } - } - - case REACT_PORTAL_TYPE: { - if (newChild.key === key) { - return updatePortal(returnFiber, oldFiber, newChild, lanes); - } else { - return null; - } - } - - case REACT_LAZY_TYPE: { - var payload = newChild._payload; - var init = newChild._init; - return updateSlot(returnFiber, oldFiber, init(payload), lanes); - } - } + return false; + } + function checkIfUseWrappedInAsyncCatch(rejectedReason) { + // This check runs in prod, too, because it prevents a more confusing + // downstream error, where SuspenseException is caught by a promise and + // thrown asynchronously. + // TODO: Another way to prevent SuspenseException from leaking into an async + // execution context is to check the dispatcher every time `use` is called, + // or some equivalent. That might be preferable for other reasons, too, since + // it matches how we prevent similar mistakes for other hooks. + if (rejectedReason === SuspenseException) { + throw new Error( + "Hooks are not supported inside an async component. This " + + "error is often caused by accidentally adding `'use client'` " + + "to a module that was originally written for the server." + ); + } + } - if (isArray(newChild) || getIteratorFn(newChild)) { - if (key !== null) { - return null; - } + var thenableState$1 = null; + var thenableIndexCounter$1 = 0; + var didWarnAboutMaps; + var didWarnAboutGenerators; + var didWarnAboutStringRefs; + var ownerHasKeyUseWarning; + var ownerHasFunctionTypeWarning; - return updateFragment(returnFiber, oldFiber, newChild, lanes, null); - } // Usable node types - // - // Unwrap the inner value and recursively call this function again. + var warnForMissingKey = function (child, returnFiber) {}; - if (typeof newChild.then === "function") { - var thenable = newChild; - return updateSlot( - returnFiber, - oldFiber, - unwrapThenable(thenable), - lanes - ); - } + { + didWarnAboutMaps = false; + didWarnAboutGenerators = false; + didWarnAboutStringRefs = {}; + /** + * Warn if there's no key explicitly set on dynamic arrays of children or + * object keys are not valid. This allows us to keep track of children between + * updates. + */ - if ( - newChild.$$typeof === REACT_CONTEXT_TYPE || - newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE - ) { - var context = newChild; - return updateSlot( - returnFiber, - oldFiber, - readContextDuringReconcilation(returnFiber, context, lanes), - lanes - ); - } + ownerHasKeyUseWarning = {}; + ownerHasFunctionTypeWarning = {}; - throwOnInvalidObjectType(returnFiber, newChild); + warnForMissingKey = function (child, returnFiber) { + if (child === null || typeof child !== "object") { + return; } - { - if (typeof newChild === "function") { - warnOnFunctionType(returnFiber); - } + if (!child._store || child._store.validated || child.key != null) { + return; } - return null; - } - - function updateFromMap( - existingChildren, - returnFiber, - newIdx, - newChild, - lanes - ) { - if ( - (typeof newChild === "string" && newChild !== "") || - typeof newChild === "number" - ) { - // Text nodes don't have keys, so we neither have to check the old nor - // new node for the key. If both are text nodes, they match. - var matchedFiber = existingChildren.get(newIdx) || null; - return updateTextNode( - returnFiber, - matchedFiber, - "" + newChild, - lanes + if (typeof child._store !== "object") { + throw new Error( + "React Component in warnForMissingKey should have a _store. " + + "This error is likely caused by a bug in React. Please file an issue." ); + } // $FlowFixMe[cannot-write] unable to narrow type from mixed to writable object + + child._store.validated = true; + var componentName = + getComponentNameFromFiber(returnFiber) || "Component"; + + if (ownerHasKeyUseWarning[componentName]) { + return; } - if (typeof newChild === "object" && newChild !== null) { - switch (newChild.$$typeof) { - case REACT_ELEMENT_TYPE: { - var _matchedFiber = - existingChildren.get( - newChild.key === null ? newIdx : newChild.key - ) || null; + ownerHasKeyUseWarning[componentName] = true; - return updateElement(returnFiber, _matchedFiber, newChild, lanes); - } + error( + "Each child in a list should have a unique " + + '"key" prop. See https://reactjs.org/link/warning-keys for ' + + "more information." + ); + }; + } - case REACT_PORTAL_TYPE: { - var _matchedFiber2 = - existingChildren.get( - newChild.key === null ? newIdx : newChild.key - ) || null; + function isReactClass(type) { + return type.prototype && type.prototype.isReactComponent; + } - return updatePortal(returnFiber, _matchedFiber2, newChild, lanes); - } + function unwrapThenable(thenable) { + var index = thenableIndexCounter$1; + thenableIndexCounter$1 += 1; - case REACT_LAZY_TYPE: - var payload = newChild._payload; - var init = newChild._init; - return updateFromMap( - existingChildren, - returnFiber, - newIdx, - init(payload), - lanes + if (thenableState$1 === null) { + thenableState$1 = createThenableState(); + } + + return trackUsedThenable(thenableState$1, thenable, index); + } + + function coerceRef(returnFiber, current, element) { + var mixedRef = element.ref; + + if ( + mixedRef !== null && + typeof mixedRef !== "function" && + typeof mixedRef !== "object" + ) { + { + if ( + // We warn in ReactElement.js if owner and self are equal for string refs + // because these cannot be automatically converted to an arrow function + // using a codemod. Therefore, we don't have to warn about string refs again. + !( + element._owner && + element._self && + element._owner.stateNode !== element._self + ) && // Will already throw with "Function components cannot have string refs" + !(element._owner && element._owner.tag !== ClassComponent) && // Will already warn with "Function components cannot be given refs" + !( + typeof element.type === "function" && !isReactClass(element.type) + ) && // Will already throw with "Element ref was specified as a string (someStringRef) but no owner was set" + element._owner + ) { + var componentName = + getComponentNameFromFiber(returnFiber) || "Component"; + + if (!didWarnAboutStringRefs[componentName]) { + error( + 'Component "%s" contains the string ref "%s". Support for string refs ' + + "will be removed in a future major release. We recommend using " + + "useRef() or createRef() instead. " + + "Learn more about using refs safely here: " + + "https://reactjs.org/link/strict-mode-string-ref", + componentName, + mixedRef ); + + didWarnAboutStringRefs[componentName] = true; + } } + } - if (isArray(newChild) || getIteratorFn(newChild)) { - var _matchedFiber3 = existingChildren.get(newIdx) || null; + if (element._owner) { + var owner = element._owner; + var inst; - return updateFragment( - returnFiber, - _matchedFiber3, - newChild, - lanes, - null - ); - } // Usable node types - // - // Unwrap the inner value and recursively call this function again. + if (owner) { + var ownerFiber = owner; - if (typeof newChild.then === "function") { - var thenable = newChild; - return updateFromMap( - existingChildren, - returnFiber, - newIdx, - unwrapThenable(thenable), - lanes - ); + if (ownerFiber.tag !== ClassComponent) { + throw new Error( + "Function components cannot have string refs. " + + "We recommend using useRef() instead. " + + "Learn more about using refs safely here: " + + "https://reactjs.org/link/strict-mode-string-ref" + ); + } + + inst = ownerFiber.stateNode; } - if ( - newChild.$$typeof === REACT_CONTEXT_TYPE || - newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE - ) { - var context = newChild; - return updateFromMap( - existingChildren, - returnFiber, - newIdx, - readContextDuringReconcilation(returnFiber, context, lanes), - lanes + if (!inst) { + throw new Error( + "Missing owner for string ref " + + mixedRef + + ". This error is likely caused by a " + + "bug in React. Please file an issue." ); - } + } // Assigning this to a const so Flow knows it won't change in the closure - throwOnInvalidObjectType(returnFiber, newChild); - } + var resolvedInst = inst; - { - if (typeof newChild === "function") { - warnOnFunctionType(returnFiber); + { + checkPropStringCoercion(mixedRef, "ref"); } - } - return null; - } - /** - * Warns if there is a duplicate or missing key - */ + var stringRef = "" + mixedRef; // Check if previous string ref matches new string ref - function warnOnInvalidKey(child, knownKeys, returnFiber) { - { - if (typeof child !== "object" || child === null) { - return knownKeys; + if ( + current !== null && + current.ref !== null && + typeof current.ref === "function" && + current.ref._stringRef === stringRef + ) { + return current.ref; } - switch (child.$$typeof) { - case REACT_ELEMENT_TYPE: - case REACT_PORTAL_TYPE: - warnForMissingKey(child, returnFiber); - var key = child.key; + var ref = function (value) { + var refs = resolvedInst.refs; - if (typeof key !== "string") { - break; - } + if (value === null) { + delete refs[stringRef]; + } else { + refs[stringRef] = value; + } + }; + + ref._stringRef = stringRef; + return ref; + } else { + if (typeof mixedRef !== "string") { + throw new Error( + "Expected ref to be a function, a string, an object returned by React.createRef(), or null." + ); + } - if (knownKeys === null) { - knownKeys = new Set(); - knownKeys.add(key); - break; - } + if (!element._owner) { + throw new Error( + "Element ref was specified as a string (" + + mixedRef + + ") but no owner was set. This could happen for one of" + + " the following reasons:\n" + + "1. You may be adding a ref to a function component\n" + + "2. You may be adding a ref to a component that was not created inside a component's render method\n" + + "3. You have multiple copies of React loaded\n" + + "See https://reactjs.org/link/refs-must-have-owner for more information." + ); + } + } + } - if (!knownKeys.has(key)) { - knownKeys.add(key); - break; - } + return mixedRef; + } - error( - "Encountered two children with the same key, `%s`. " + - "Keys should be unique so that components maintain their identity " + - "across updates. Non-unique keys may cause children to be " + - "duplicated and/or omitted — the behavior is unsupported and " + - "could change in a future version.", - key - ); + function throwOnInvalidObjectType(returnFiber, newChild) { + // $FlowFixMe[method-unbinding] + var childString = Object.prototype.toString.call(newChild); + throw new Error( + "Objects are not valid as a React child (found: " + + (childString === "[object Object]" + ? "object with keys {" + Object.keys(newChild).join(", ") + "}" + : childString) + + "). " + + "If you meant to render a collection of children, use an array " + + "instead." + ); + } - break; + function warnOnFunctionType(returnFiber) { + { + var componentName = + getComponentNameFromFiber(returnFiber) || "Component"; - case REACT_LAZY_TYPE: - var payload = child._payload; - var init = child._init; - warnOnInvalidKey(init(payload), knownKeys, returnFiber); - break; - } + if (ownerHasFunctionTypeWarning[componentName]) { + return; } - return knownKeys; + ownerHasFunctionTypeWarning[componentName] = true; + + error( + "Functions are not valid as a React child. This may happen if " + + "you return a Component instead of from render. " + + "Or maybe you meant to call this function rather than return it." + ); } + } - function reconcileChildrenArray( - returnFiber, - currentFirstChild, - newChildren, - lanes - ) { - // This algorithm can't optimize by searching from both ends since we - // don't have backpointers on fibers. I'm trying to see how far we can get - // with that model. If it ends up not being worth the tradeoffs, we can - // add it later. - // Even with a two ended optimization, we'd want to optimize for the case - // where there are few changes and brute force the comparison instead of - // going for the Map. It'd like to explore hitting that path first in - // forward-only mode and only go for the Map once we notice that we need - // lots of look ahead. This doesn't handle reversal as well as two ended - // search but that's unusual. Besides, for the two ended optimization to - // work on Iterables, we'd need to copy the whole set. - // In this first iteration, we'll just live with hitting the bad case - // (adding everything to a Map) in for every insert/move. - // If you change this code, also update reconcileChildrenIterator() which - // uses the same algorithm. - { - // First, validate keys. - var knownKeys = null; + function resolveLazy(lazyType) { + var payload = lazyType._payload; + var init = lazyType._init; + return init(payload); + } // This wrapper function exists because I expect to clone the code in each path + // to be able to optimize each path individually by branching early. This needs + // a compiler or we can do it manually. Helpers that don't need this branching + // live outside of this function. - for (var i = 0; i < newChildren.length; i++) { - var child = newChildren[i]; - knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); - } + function createChildReconciler(shouldTrackSideEffects) { + function deleteChild(returnFiber, childToDelete) { + if (!shouldTrackSideEffects) { + // Noop. + return; } - var resultingFirstChild = null; - var previousNewFiber = null; - var oldFiber = currentFirstChild; - var lastPlacedIndex = 0; - var newIdx = 0; - var nextOldFiber = null; + var deletions = returnFiber.deletions; - for (; oldFiber !== null && newIdx < newChildren.length; newIdx++) { - if (oldFiber.index > newIdx) { - nextOldFiber = oldFiber; - oldFiber = null; - } else { - nextOldFiber = oldFiber.sibling; - } + if (deletions === null) { + returnFiber.deletions = [childToDelete]; + returnFiber.flags |= ChildDeletion; + } else { + deletions.push(childToDelete); + } + } - var newFiber = updateSlot( - returnFiber, - oldFiber, - newChildren[newIdx], - lanes - ); + function deleteRemainingChildren(returnFiber, currentFirstChild) { + if (!shouldTrackSideEffects) { + // Noop. + return null; + } // TODO: For the shouldClone case, this could be micro-optimized a bit by + // assuming that after the first child we've already added everything. - if (newFiber === null) { - // TODO: This breaks on empty slots like null children. That's - // unfortunate because it triggers the slow path all the time. We need - // a better way to communicate whether this was a miss or null, - // boolean, undefined, etc. - if (oldFiber === null) { - oldFiber = nextOldFiber; - } + var childToDelete = currentFirstChild; - break; - } + while (childToDelete !== null) { + deleteChild(returnFiber, childToDelete); + childToDelete = childToDelete.sibling; + } - if (shouldTrackSideEffects) { - if (oldFiber && newFiber.alternate === null) { - // We matched the slot, but we didn't reuse the existing fiber, so we - // need to delete the existing child. - deleteChild(returnFiber, oldFiber); - } - } + return null; + } - lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx); + function mapRemainingChildren(returnFiber, currentFirstChild) { + // Add the remaining children to a temporary map so that we can find them by + // keys quickly. Implicit (null) keys get added to this set with their index + // instead. + var existingChildren = new Map(); + var existingChild = currentFirstChild; - if (previousNewFiber === null) { - // TODO: Move out of the loop. This only happens for the first run. - resultingFirstChild = newFiber; + while (existingChild !== null) { + if (existingChild.key !== null) { + existingChildren.set(existingChild.key, existingChild); } else { - // TODO: Defer siblings if we're not at the right index for this slot. - // I.e. if we had null values before, then we want to defer this - // for each null value. However, we also don't want to call updateSlot - // with the previous one. - previousNewFiber.sibling = newFiber; + existingChildren.set(existingChild.index, existingChild); } - previousNewFiber = newFiber; - oldFiber = nextOldFiber; + existingChild = existingChild.sibling; } - if (newIdx === newChildren.length) { - // We've reached the end of the new children. We can delete the rest. - deleteRemainingChildren(returnFiber, oldFiber); + return existingChildren; + } - return resultingFirstChild; - } + function useFiber(fiber, pendingProps) { + // We currently set sibling to null and index to 0 here because it is easy + // to forget to do before returning it. E.g. for the single child case. + var clone = createWorkInProgress(fiber, pendingProps); + clone.index = 0; + clone.sibling = null; + return clone; + } - if (oldFiber === null) { - // If we don't have any more existing children we can choose a fast path - // since the rest will all be insertions. - for (; newIdx < newChildren.length; newIdx++) { - var _newFiber = createChild( - returnFiber, - newChildren[newIdx], - lanes - ); + function placeChild(newFiber, lastPlacedIndex, newIndex) { + newFiber.index = newIndex; - if (_newFiber === null) { - continue; - } + if (!shouldTrackSideEffects) { + // During hydration, the useId algorithm needs to know which fibers are + // part of a list of children (arrays, iterators). + newFiber.flags |= Forked; + return lastPlacedIndex; + } - lastPlacedIndex = placeChild(_newFiber, lastPlacedIndex, newIdx); + var current = newFiber.alternate; - if (previousNewFiber === null) { - // TODO: Move out of the loop. This only happens for the first run. - resultingFirstChild = _newFiber; - } else { - previousNewFiber.sibling = _newFiber; - } + if (current !== null) { + var oldIndex = current.index; - previousNewFiber = _newFiber; + if (oldIndex < lastPlacedIndex) { + // This is a move. + newFiber.flags |= Placement | PlacementDEV; + return lastPlacedIndex; + } else { + // This item can stay in place. + return oldIndex; } + } else { + // This is an insertion. + newFiber.flags |= Placement | PlacementDEV; + return lastPlacedIndex; + } + } - return resultingFirstChild; - } // Add all children to a key map for quick lookups. + function placeSingleChild(newFiber) { + // This is simpler for the single child case. We only need to do a + // placement for inserting new children. + if (shouldTrackSideEffects && newFiber.alternate === null) { + newFiber.flags |= Placement | PlacementDEV; + } - var existingChildren = mapRemainingChildren(returnFiber, oldFiber); // Keep scanning and use the map to restore deleted items as moves. + return newFiber; + } - for (; newIdx < newChildren.length; newIdx++) { - var _newFiber2 = updateFromMap( - existingChildren, - returnFiber, - newIdx, - newChildren[newIdx], + function updateTextNode(returnFiber, current, textContent, lanes) { + if (current === null || current.tag !== HostText) { + // Insert + var created = createFiberFromText( + textContent, + returnFiber.mode, lanes ); + created.return = returnFiber; + return created; + } else { + // Update + var existing = useFiber(current, textContent); + existing.return = returnFiber; + return existing; + } + } - if (_newFiber2 !== null) { - if (shouldTrackSideEffects) { - if (_newFiber2.alternate !== null) { - // The new fiber is a work in progress, but if there exists a - // current, that means that we reused the fiber. We need to delete - // it from the child list so that we don't add it to the deletion - // list. - existingChildren.delete( - _newFiber2.key === null ? newIdx : _newFiber2.key - ); - } - } + function updateElement(returnFiber, current, element, lanes) { + var elementType = element.type; - lastPlacedIndex = placeChild(_newFiber2, lastPlacedIndex, newIdx); + if (elementType === REACT_FRAGMENT_TYPE) { + return updateFragment( + returnFiber, + current, + element.props.children, + lanes, + element.key + ); + } - if (previousNewFiber === null) { - resultingFirstChild = _newFiber2; - } else { - previousNewFiber.sibling = _newFiber2; + if (current !== null) { + if ( + current.elementType === elementType || // Keep this check inline so it only runs on the false path: + isCompatibleFamilyForHotReloading(current, element) || // Lazy types should reconcile their resolved type. + // We need to do this after the Hot Reloading check above, + // because hot reloading has different semantics than prod because + // it doesn't resuspend. So we can't let the call below suspend. + (typeof elementType === "object" && + elementType !== null && + elementType.$$typeof === REACT_LAZY_TYPE && + resolveLazy(elementType) === current.type) + ) { + // Move based on index + var existing = useFiber(current, element.props); + existing.ref = coerceRef(returnFiber, current, element); + existing.return = returnFiber; + + { + existing._debugSource = element._source; + existing._debugOwner = element._owner; } - previousNewFiber = _newFiber2; + return existing; } - } + } // Insert - if (shouldTrackSideEffects) { - // Any existing children that weren't consumed above were deleted. We need - // to add them to the deletion list. - existingChildren.forEach(function (child) { - return deleteChild(returnFiber, child); - }); - } + var created = createFiberFromElement(element, returnFiber.mode, lanes); + created.ref = coerceRef(returnFiber, current, element); + created.return = returnFiber; + return created; + } - return resultingFirstChild; + function updatePortal(returnFiber, current, portal, lanes) { + if ( + current === null || + current.tag !== HostPortal || + current.stateNode.containerInfo !== portal.containerInfo || + current.stateNode.implementation !== portal.implementation + ) { + // Insert + var created = createFiberFromPortal(portal, returnFiber.mode, lanes); + created.return = returnFiber; + return created; + } else { + // Update + var existing = useFiber(current, portal.children || []); + existing.return = returnFiber; + return existing; + } } - function reconcileChildrenIterator( - returnFiber, - currentFirstChild, - newChildrenIterable, - lanes - ) { - // This is the same implementation as reconcileChildrenArray(), - // but using the iterator instead. - var iteratorFn = getIteratorFn(newChildrenIterable); + function updateFragment(returnFiber, current, fragment, lanes, key) { + if (current === null || current.tag !== Fragment) { + // Insert + var created = createFiberFromFragment( + fragment, + returnFiber.mode, + lanes, + key + ); + created.return = returnFiber; + return created; + } else { + // Update + var existing = useFiber(current, fragment); + existing.return = returnFiber; + return existing; + } + } - if (typeof iteratorFn !== "function") { - throw new Error( - "An object is not an iterable. This error is likely caused by a bug in " + - "React. Please file an issue." + function createChild(returnFiber, newChild, lanes) { + if ( + (typeof newChild === "string" && newChild !== "") || + typeof newChild === "number" + ) { + // Text nodes don't have keys. If the previous node is implicitly keyed + // we can continue to replace it without aborting even if it is not a text + // node. + var created = createFiberFromText( + "" + newChild, + returnFiber.mode, + lanes ); + created.return = returnFiber; + return created; } - { - // We don't support rendering Generators because it's a mutation. - // See https://github.com/facebook/react/issues/12995 - if ( - typeof Symbol === "function" && // $FlowFixMe[prop-missing] Flow doesn't know about toStringTag - newChildrenIterable[Symbol.toStringTag] === "Generator" - ) { - if (!didWarnAboutGenerators) { - error( - "Using Generators as children is unsupported and will likely yield " + - "unexpected results because enumerating a generator mutates it. " + - "You may convert it to an array with `Array.from()` or the " + - "`[...spread]` operator before rendering. Keep in mind " + - "you might need to polyfill these features for older browsers." + if (typeof newChild === "object" && newChild !== null) { + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE: { + var _created = createFiberFromElement( + newChild, + returnFiber.mode, + lanes ); - } - - didWarnAboutGenerators = true; - } // Warn about using Maps as children - if (newChildrenIterable.entries === iteratorFn) { - if (!didWarnAboutMaps) { - error( - "Using Maps as children is not supported. " + - "Use an array of keyed ReactElements instead." - ); + _created.ref = coerceRef(returnFiber, null, newChild); + _created.return = returnFiber; + return _created; } - didWarnAboutMaps = true; - } // First, validate keys. - // We'll get a different iterator later for the main pass. - - var _newChildren = iteratorFn.call(newChildrenIterable); - - if (_newChildren) { - var knownKeys = null; + case REACT_PORTAL_TYPE: { + var _created2 = createFiberFromPortal( + newChild, + returnFiber.mode, + lanes + ); - var _step = _newChildren.next(); + _created2.return = returnFiber; + return _created2; + } - for (; !_step.done; _step = _newChildren.next()) { - var child = _step.value; - knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); + case REACT_LAZY_TYPE: { + var payload = newChild._payload; + var init = newChild._init; + return createChild(returnFiber, init(payload), lanes); } } - } - var newChildren = iteratorFn.call(newChildrenIterable); + if (isArray(newChild) || getIteratorFn(newChild)) { + var _created3 = createFiberFromFragment( + newChild, + returnFiber.mode, + lanes, + null + ); - if (newChildren == null) { - throw new Error("An iterable object provided no iterator."); - } + _created3.return = returnFiber; + return _created3; + } // Usable node types + // + // Unwrap the inner value and recursively call this function again. - var resultingFirstChild = null; - var previousNewFiber = null; - var oldFiber = currentFirstChild; - var lastPlacedIndex = 0; - var newIdx = 0; - var nextOldFiber = null; - var step = newChildren.next(); + if (typeof newChild.then === "function") { + var thenable = newChild; + return createChild(returnFiber, unwrapThenable(thenable), lanes); + } - for ( - ; - oldFiber !== null && !step.done; - newIdx++, step = newChildren.next() - ) { - if (oldFiber.index > newIdx) { - nextOldFiber = oldFiber; - oldFiber = null; - } else { - nextOldFiber = oldFiber.sibling; + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) { + var context = newChild; + return createChild( + returnFiber, + readContextDuringReconcilation(returnFiber, context, lanes), + lanes + ); } - var newFiber = updateSlot(returnFiber, oldFiber, step.value, lanes); - - if (newFiber === null) { - // TODO: This breaks on empty slots like null children. That's - // unfortunate because it triggers the slow path all the time. We need - // a better way to communicate whether this was a miss or null, - // boolean, undefined, etc. - if (oldFiber === null) { - oldFiber = nextOldFiber; - } + throwOnInvalidObjectType(returnFiber, newChild); + } - break; + { + if (typeof newChild === "function") { + warnOnFunctionType(returnFiber); } + } - if (shouldTrackSideEffects) { - if (oldFiber && newFiber.alternate === null) { - // We matched the slot, but we didn't reuse the existing fiber, so we - // need to delete the existing child. - deleteChild(returnFiber, oldFiber); - } - } + return null; + } - lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx); + function updateSlot(returnFiber, oldFiber, newChild, lanes) { + // Update the fiber if the keys match, otherwise return null. + var key = oldFiber !== null ? oldFiber.key : null; - if (previousNewFiber === null) { - // TODO: Move out of the loop. This only happens for the first run. - resultingFirstChild = newFiber; - } else { - // TODO: Defer siblings if we're not at the right index for this slot. - // I.e. if we had null values before, then we want to defer this - // for each null value. However, we also don't want to call updateSlot - // with the previous one. - previousNewFiber.sibling = newFiber; + if ( + (typeof newChild === "string" && newChild !== "") || + typeof newChild === "number" + ) { + // Text nodes don't have keys. If the previous node is implicitly keyed + // we can continue to replace it without aborting even if it is not a text + // node. + if (key !== null) { + return null; } - previousNewFiber = newFiber; - oldFiber = nextOldFiber; + return updateTextNode(returnFiber, oldFiber, "" + newChild, lanes); } - if (step.done) { - // We've reached the end of the new children. We can delete the rest. - deleteRemainingChildren(returnFiber, oldFiber); + if (typeof newChild === "object" && newChild !== null) { + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE: { + if (newChild.key === key) { + return updateElement(returnFiber, oldFiber, newChild, lanes); + } else { + return null; + } + } - return resultingFirstChild; - } + case REACT_PORTAL_TYPE: { + if (newChild.key === key) { + return updatePortal(returnFiber, oldFiber, newChild, lanes); + } else { + return null; + } + } - if (oldFiber === null) { - // If we don't have any more existing children we can choose a fast path - // since the rest will all be insertions. - for (; !step.done; newIdx++, step = newChildren.next()) { - var _newFiber3 = createChild(returnFiber, step.value, lanes); + case REACT_LAZY_TYPE: { + var payload = newChild._payload; + var init = newChild._init; + return updateSlot(returnFiber, oldFiber, init(payload), lanes); + } + } - if (_newFiber3 === null) { - continue; + if (isArray(newChild) || getIteratorFn(newChild)) { + if (key !== null) { + return null; } - lastPlacedIndex = placeChild(_newFiber3, lastPlacedIndex, newIdx); + return updateFragment(returnFiber, oldFiber, newChild, lanes, null); + } // Usable node types + // + // Unwrap the inner value and recursively call this function again. - if (previousNewFiber === null) { - // TODO: Move out of the loop. This only happens for the first run. - resultingFirstChild = _newFiber3; - } else { - previousNewFiber.sibling = _newFiber3; - } + if (typeof newChild.then === "function") { + var thenable = newChild; + return updateSlot( + returnFiber, + oldFiber, + unwrapThenable(thenable), + lanes + ); + } - previousNewFiber = _newFiber3; + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) { + var context = newChild; + return updateSlot( + returnFiber, + oldFiber, + readContextDuringReconcilation(returnFiber, context, lanes), + lanes + ); } - return resultingFirstChild; - } // Add all children to a key map for quick lookups. + throwOnInvalidObjectType(returnFiber, newChild); + } - var existingChildren = mapRemainingChildren(returnFiber, oldFiber); // Keep scanning and use the map to restore deleted items as moves. + { + if (typeof newChild === "function") { + warnOnFunctionType(returnFiber); + } + } - for (; !step.done; newIdx++, step = newChildren.next()) { - var _newFiber4 = updateFromMap( - existingChildren, + return null; + } + + function updateFromMap( + existingChildren, + returnFiber, + newIdx, + newChild, + lanes + ) { + if ( + (typeof newChild === "string" && newChild !== "") || + typeof newChild === "number" + ) { + // Text nodes don't have keys, so we neither have to check the old nor + // new node for the key. If both are text nodes, they match. + var matchedFiber = existingChildren.get(newIdx) || null; + return updateTextNode( returnFiber, - newIdx, - step.value, + matchedFiber, + "" + newChild, lanes ); + } - if (_newFiber4 !== null) { - if (shouldTrackSideEffects) { - if (_newFiber4.alternate !== null) { - // The new fiber is a work in progress, but if there exists a - // current, that means that we reused the fiber. We need to delete - // it from the child list so that we don't add it to the deletion - // list. - existingChildren.delete( - _newFiber4.key === null ? newIdx : _newFiber4.key - ); - } + if (typeof newChild === "object" && newChild !== null) { + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE: { + var _matchedFiber = + existingChildren.get( + newChild.key === null ? newIdx : newChild.key + ) || null; + + return updateElement(returnFiber, _matchedFiber, newChild, lanes); } - lastPlacedIndex = placeChild(_newFiber4, lastPlacedIndex, newIdx); + case REACT_PORTAL_TYPE: { + var _matchedFiber2 = + existingChildren.get( + newChild.key === null ? newIdx : newChild.key + ) || null; - if (previousNewFiber === null) { - resultingFirstChild = _newFiber4; - } else { - previousNewFiber.sibling = _newFiber4; + return updatePortal(returnFiber, _matchedFiber2, newChild, lanes); } - previousNewFiber = _newFiber4; + case REACT_LAZY_TYPE: + var payload = newChild._payload; + var init = newChild._init; + return updateFromMap( + existingChildren, + returnFiber, + newIdx, + init(payload), + lanes + ); } - } - - if (shouldTrackSideEffects) { - // Any existing children that weren't consumed above were deleted. We need - // to add them to the deletion list. - existingChildren.forEach(function (child) { - return deleteChild(returnFiber, child); - }); - } - - return resultingFirstChild; - } - - function reconcileSingleTextNode( - returnFiber, - currentFirstChild, - textContent, - lanes - ) { - // There's no need to check for keys on text nodes since we don't have a - // way to define them. - if (currentFirstChild !== null && currentFirstChild.tag === HostText) { - // We already have an existing node so let's just update it and delete - // the rest. - deleteRemainingChildren(returnFiber, currentFirstChild.sibling); - var existing = useFiber(currentFirstChild, textContent); - existing.return = returnFiber; - return existing; - } // The existing first child is not a text node so we need to create one - // and delete the existing ones. - deleteRemainingChildren(returnFiber, currentFirstChild); - var created = createFiberFromText(textContent, returnFiber.mode, lanes); - created.return = returnFiber; - return created; - } + if (isArray(newChild) || getIteratorFn(newChild)) { + var _matchedFiber3 = existingChildren.get(newIdx) || null; - function reconcileSingleElement( - returnFiber, - currentFirstChild, - element, - lanes - ) { - var key = element.key; - var child = currentFirstChild; + return updateFragment( + returnFiber, + _matchedFiber3, + newChild, + lanes, + null + ); + } // Usable node types + // + // Unwrap the inner value and recursively call this function again. - while (child !== null) { - // TODO: If key === null and child.key === null, then this only applies to - // the first item in the list. - if (child.key === key) { - var elementType = element.type; + if (typeof newChild.then === "function") { + var thenable = newChild; + return updateFromMap( + existingChildren, + returnFiber, + newIdx, + unwrapThenable(thenable), + lanes + ); + } - if (elementType === REACT_FRAGMENT_TYPE) { - if (child.tag === Fragment) { - deleteRemainingChildren(returnFiber, child.sibling); - var existing = useFiber(child, element.props.children); - existing.return = returnFiber; + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) { + var context = newChild; + return updateFromMap( + existingChildren, + returnFiber, + newIdx, + readContextDuringReconcilation(returnFiber, context, lanes), + lanes + ); + } - { - existing._debugSource = element._source; - existing._debugOwner = element._owner; - } + throwOnInvalidObjectType(returnFiber, newChild); + } - return existing; - } - } else { - if ( - child.elementType === elementType || // Keep this check inline so it only runs on the false path: - isCompatibleFamilyForHotReloading(child, element) || // Lazy types should reconcile their resolved type. - // We need to do this after the Hot Reloading check above, - // because hot reloading has different semantics than prod because - // it doesn't resuspend. So we can't let the call below suspend. - (typeof elementType === "object" && - elementType !== null && - elementType.$$typeof === REACT_LAZY_TYPE && - resolveLazy(elementType) === child.type) - ) { - deleteRemainingChildren(returnFiber, child.sibling); + { + if (typeof newChild === "function") { + warnOnFunctionType(returnFiber); + } + } - var _existing = useFiber(child, element.props); + return null; + } + /** + * Warns if there is a duplicate or missing key + */ - _existing.ref = coerceRef(returnFiber, child, element); - _existing.return = returnFiber; + function warnOnInvalidKey(child, knownKeys, returnFiber) { + { + if (typeof child !== "object" || child === null) { + return knownKeys; + } - { - _existing._debugSource = element._source; - _existing._debugOwner = element._owner; - } + switch (child.$$typeof) { + case REACT_ELEMENT_TYPE: + case REACT_PORTAL_TYPE: + warnForMissingKey(child, returnFiber); + var key = child.key; - return _existing; + if (typeof key !== "string") { + break; } - } // Didn't match. - - deleteRemainingChildren(returnFiber, child); - break; - } else { - deleteChild(returnFiber, child); - } - child = child.sibling; - } + if (knownKeys === null) { + knownKeys = new Set(); + knownKeys.add(key); + break; + } - if (element.type === REACT_FRAGMENT_TYPE) { - var created = createFiberFromFragment( - element.props.children, - returnFiber.mode, - lanes, - element.key - ); - created.return = returnFiber; - return created; - } else { - var _created4 = createFiberFromElement( - element, - returnFiber.mode, - lanes - ); + if (!knownKeys.has(key)) { + knownKeys.add(key); + break; + } - _created4.ref = coerceRef(returnFiber, currentFirstChild, element); - _created4.return = returnFiber; - return _created4; - } - } + error( + "Encountered two children with the same key, `%s`. " + + "Keys should be unique so that components maintain their identity " + + "across updates. Non-unique keys may cause children to be " + + "duplicated and/or omitted — the behavior is unsupported and " + + "could change in a future version.", + key + ); - function reconcileSinglePortal( - returnFiber, - currentFirstChild, - portal, - lanes - ) { - var key = portal.key; - var child = currentFirstChild; + break; - while (child !== null) { - // TODO: If key === null and child.key === null, then this only applies to - // the first item in the list. - if (child.key === key) { - if ( - child.tag === HostPortal && - child.stateNode.containerInfo === portal.containerInfo && - child.stateNode.implementation === portal.implementation - ) { - deleteRemainingChildren(returnFiber, child.sibling); - var existing = useFiber(child, portal.children || []); - existing.return = returnFiber; - return existing; - } else { - deleteRemainingChildren(returnFiber, child); + case REACT_LAZY_TYPE: + var payload = child._payload; + var init = child._init; + warnOnInvalidKey(init(payload), knownKeys, returnFiber); break; - } - } else { - deleteChild(returnFiber, child); } - - child = child.sibling; } - var created = createFiberFromPortal(portal, returnFiber.mode, lanes); - created.return = returnFiber; - return created; - } // This API will tag the children with the side-effect of the reconciliation - // itself. They will be added to the side-effect list as we pass through the - // children and the parent. + return knownKeys; + } - function reconcileChildFibersImpl( + function reconcileChildrenArray( returnFiber, currentFirstChild, - newChild, + newChildren, lanes ) { - // This function is not recursive. - // If the top level item is an array, we treat it as a set of children, - // not as a fragment. Nested arrays on the other hand will be treated as - // fragment nodes. Recursion happens at the normal flow. - // Handle top level unkeyed fragments as if they were arrays. - // This leads to an ambiguity between <>{[...]} and <>.... - // We treat the ambiguous cases above the same. - // TODO: Let's use recursion like we do for Usable nodes? - var isUnkeyedTopLevelFragment = - typeof newChild === "object" && - newChild !== null && - newChild.type === REACT_FRAGMENT_TYPE && - newChild.key === null; + // This algorithm can't optimize by searching from both ends since we + // don't have backpointers on fibers. I'm trying to see how far we can get + // with that model. If it ends up not being worth the tradeoffs, we can + // add it later. + // Even with a two ended optimization, we'd want to optimize for the case + // where there are few changes and brute force the comparison instead of + // going for the Map. It'd like to explore hitting that path first in + // forward-only mode and only go for the Map once we notice that we need + // lots of look ahead. This doesn't handle reversal as well as two ended + // search but that's unusual. Besides, for the two ended optimization to + // work on Iterables, we'd need to copy the whole set. + // In this first iteration, we'll just live with hitting the bad case + // (adding everything to a Map) in for every insert/move. + // If you change this code, also update reconcileChildrenIterator() which + // uses the same algorithm. + { + // First, validate keys. + var knownKeys = null; - if (isUnkeyedTopLevelFragment) { - newChild = newChild.props.children; - } // Handle object types + for (var i = 0; i < newChildren.length; i++) { + var child = newChildren[i]; + knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); + } + } - if (typeof newChild === "object" && newChild !== null) { - switch (newChild.$$typeof) { - case REACT_ELEMENT_TYPE: - return placeSingleChild( - reconcileSingleElement( - returnFiber, - currentFirstChild, - newChild, - lanes - ) - ); + var resultingFirstChild = null; + var previousNewFiber = null; + var oldFiber = currentFirstChild; + var lastPlacedIndex = 0; + var newIdx = 0; + var nextOldFiber = null; - case REACT_PORTAL_TYPE: - return placeSingleChild( - reconcileSinglePortal( - returnFiber, - currentFirstChild, - newChild, - lanes - ) - ); + for (; oldFiber !== null && newIdx < newChildren.length; newIdx++) { + if (oldFiber.index > newIdx) { + nextOldFiber = oldFiber; + oldFiber = null; + } else { + nextOldFiber = oldFiber.sibling; + } - case REACT_LAZY_TYPE: - var payload = newChild._payload; - var init = newChild._init; // TODO: This function is supposed to be non-recursive. + var newFiber = updateSlot( + returnFiber, + oldFiber, + newChildren[newIdx], + lanes + ); - return reconcileChildFibers( - returnFiber, - currentFirstChild, - init(payload), - lanes - ); + if (newFiber === null) { + // TODO: This breaks on empty slots like null children. That's + // unfortunate because it triggers the slow path all the time. We need + // a better way to communicate whether this was a miss or null, + // boolean, undefined, etc. + if (oldFiber === null) { + oldFiber = nextOldFiber; + } + + break; } - if (isArray(newChild)) { - return reconcileChildrenArray( - returnFiber, - currentFirstChild, - newChild, - lanes - ); + if (shouldTrackSideEffects) { + if (oldFiber && newFiber.alternate === null) { + // We matched the slot, but we didn't reuse the existing fiber, so we + // need to delete the existing child. + deleteChild(returnFiber, oldFiber); + } } - if (getIteratorFn(newChild)) { - return reconcileChildrenIterator( - returnFiber, - currentFirstChild, - newChild, - lanes - ); - } // Usables are a valid React node type. When React encounters a Usable in - // a child position, it unwraps it using the same algorithm as `use`. For - // example, for promises, React will throw an exception to unwind the - // stack, then replay the component once the promise resolves. - // - // A difference from `use` is that React will keep unwrapping the value - // until it reaches a non-Usable type. - // - // e.g. Usable>> should resolve to T - // - // The structure is a bit unfortunate. Ideally, we shouldn't need to - // replay the entire begin phase of the parent fiber in order to reconcile - // the children again. This would require a somewhat significant refactor, - // because reconcilation happens deep within the begin phase, and - // depending on the type of work, not always at the end. We should - // consider as an future improvement. + lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx); - if (typeof newChild.then === "function") { - var thenable = newChild; - return reconcileChildFibersImpl( - returnFiber, - currentFirstChild, - unwrapThenable(thenable), - lanes - ); + if (previousNewFiber === null) { + // TODO: Move out of the loop. This only happens for the first run. + resultingFirstChild = newFiber; + } else { + // TODO: Defer siblings if we're not at the right index for this slot. + // I.e. if we had null values before, then we want to defer this + // for each null value. However, we also don't want to call updateSlot + // with the previous one. + previousNewFiber.sibling = newFiber; } - if ( - newChild.$$typeof === REACT_CONTEXT_TYPE || - newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE - ) { - var context = newChild; - return reconcileChildFibersImpl( + previousNewFiber = newFiber; + oldFiber = nextOldFiber; + } + + if (newIdx === newChildren.length) { + // We've reached the end of the new children. We can delete the rest. + deleteRemainingChildren(returnFiber, oldFiber); + + return resultingFirstChild; + } + + if (oldFiber === null) { + // If we don't have any more existing children we can choose a fast path + // since the rest will all be insertions. + for (; newIdx < newChildren.length; newIdx++) { + var _newFiber = createChild( returnFiber, - currentFirstChild, - readContextDuringReconcilation(returnFiber, context, lanes), + newChildren[newIdx], lanes ); + + if (_newFiber === null) { + continue; + } + + lastPlacedIndex = placeChild(_newFiber, lastPlacedIndex, newIdx); + + if (previousNewFiber === null) { + // TODO: Move out of the loop. This only happens for the first run. + resultingFirstChild = _newFiber; + } else { + previousNewFiber.sibling = _newFiber; + } + + previousNewFiber = _newFiber; } - throwOnInvalidObjectType(returnFiber, newChild); - } + return resultingFirstChild; + } // Add all children to a key map for quick lookups. - if ( - (typeof newChild === "string" && newChild !== "") || - typeof newChild === "number" - ) { - return placeSingleChild( - reconcileSingleTextNode( - returnFiber, - currentFirstChild, - "" + newChild, - lanes - ) + var existingChildren = mapRemainingChildren(returnFiber, oldFiber); // Keep scanning and use the map to restore deleted items as moves. + + for (; newIdx < newChildren.length; newIdx++) { + var _newFiber2 = updateFromMap( + existingChildren, + returnFiber, + newIdx, + newChildren[newIdx], + lanes ); - } - { - if (typeof newChild === "function") { - warnOnFunctionType(returnFiber); + if (_newFiber2 !== null) { + if (shouldTrackSideEffects) { + if (_newFiber2.alternate !== null) { + // The new fiber is a work in progress, but if there exists a + // current, that means that we reused the fiber. We need to delete + // it from the child list so that we don't add it to the deletion + // list. + existingChildren.delete( + _newFiber2.key === null ? newIdx : _newFiber2.key + ); + } + } + + lastPlacedIndex = placeChild(_newFiber2, lastPlacedIndex, newIdx); + + if (previousNewFiber === null) { + resultingFirstChild = _newFiber2; + } else { + previousNewFiber.sibling = _newFiber2; + } + + previousNewFiber = _newFiber2; } - } // Remaining cases are all treated as empty. + } - return deleteRemainingChildren(returnFiber, currentFirstChild); + if (shouldTrackSideEffects) { + // Any existing children that weren't consumed above were deleted. We need + // to add them to the deletion list. + existingChildren.forEach(function (child) { + return deleteChild(returnFiber, child); + }); + } + + return resultingFirstChild; } - function reconcileChildFibers( + function reconcileChildrenIterator( returnFiber, currentFirstChild, - newChild, + newChildrenIterable, lanes ) { - // This indirection only exists so we can reset `thenableState` at the end. - // It should get inlined by Closure. - thenableIndexCounter$1 = 0; - var firstChildFiber = reconcileChildFibersImpl( - returnFiber, - currentFirstChild, - newChild, - lanes - ); - thenableState$1 = null; // Don't bother to reset `thenableIndexCounter` to 0 because it always gets - // set at the beginning. - - return firstChildFiber; - } - - return reconcileChildFibers; - } + // This is the same implementation as reconcileChildrenArray(), + // but using the iterator instead. + var iteratorFn = getIteratorFn(newChildrenIterable); - var reconcileChildFibers = createChildReconciler(true); - var mountChildFibers = createChildReconciler(false); - function resetChildReconcilerOnUnwind() { - // On unwind, clear any pending thenables that were used. - thenableState$1 = null; - thenableIndexCounter$1 = 0; - } - function cloneChildFibers(current, workInProgress) { - if (current !== null && workInProgress.child !== current.child) { - throw new Error("Resuming work not yet implemented."); - } + if (typeof iteratorFn !== "function") { + throw new Error( + "An object is not an iterable. This error is likely caused by a bug in " + + "React. Please file an issue." + ); + } - if (workInProgress.child === null) { - return; - } + { + // We don't support rendering Generators because it's a mutation. + // See https://github.com/facebook/react/issues/12995 + if ( + typeof Symbol === "function" && // $FlowFixMe[prop-missing] Flow doesn't know about toStringTag + newChildrenIterable[Symbol.toStringTag] === "Generator" + ) { + if (!didWarnAboutGenerators) { + error( + "Using Generators as children is unsupported and will likely yield " + + "unexpected results because enumerating a generator mutates it. " + + "You may convert it to an array with `Array.from()` or the " + + "`[...spread]` operator before rendering. Keep in mind " + + "you might need to polyfill these features for older browsers." + ); + } - var currentChild = workInProgress.child; - var newChild = createWorkInProgress( - currentChild, - currentChild.pendingProps - ); - workInProgress.child = newChild; - newChild.return = workInProgress; + didWarnAboutGenerators = true; + } // Warn about using Maps as children - while (currentChild.sibling !== null) { - currentChild = currentChild.sibling; - newChild = newChild.sibling = createWorkInProgress( - currentChild, - currentChild.pendingProps - ); - newChild.return = workInProgress; - } + if (newChildrenIterable.entries === iteratorFn) { + if (!didWarnAboutMaps) { + error( + "Using Maps as children is not supported. " + + "Use an array of keyed ReactElements instead." + ); + } - newChild.sibling = null; - } // Reset a workInProgress child set to prepare it for a second pass. + didWarnAboutMaps = true; + } // First, validate keys. + // We'll get a different iterator later for the main pass. - function resetChildFibers(workInProgress, lanes) { - var child = workInProgress.child; + var _newChildren = iteratorFn.call(newChildrenIterable); - while (child !== null) { - resetWorkInProgress(child, lanes); - child = child.sibling; - } - } + if (_newChildren) { + var knownKeys = null; - // TODO: This isn't being used yet, but it's intended to replace the - // InvisibleParentContext that is currently managed by SuspenseContext. + var _step = _newChildren.next(); - var currentTreeHiddenStackCursor = createCursor(null); - var prevEntangledRenderLanesCursor = createCursor(NoLanes); - function pushHiddenContext(fiber, context) { - var prevEntangledRenderLanes = getEntangledRenderLanes(); - push(prevEntangledRenderLanesCursor, prevEntangledRenderLanes, fiber); - push(currentTreeHiddenStackCursor, context, fiber); // When rendering a subtree that's currently hidden, we must include all - // lanes that would have rendered if the hidden subtree hadn't been deferred. - // That is, in order to reveal content from hidden -> visible, we must commit - // all the updates that we skipped when we originally hid the tree. + for (; !_step.done; _step = _newChildren.next()) { + var child = _step.value; + knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); + } + } + } - setEntangledRenderLanes( - mergeLanes(prevEntangledRenderLanes, context.baseLanes) - ); - } - function reuseHiddenContextOnStack(fiber) { - // This subtree is not currently hidden, so we don't need to add any lanes - // to the render lanes. But we still need to push something to avoid a - // context mismatch. Reuse the existing context on the stack. - push(prevEntangledRenderLanesCursor, getEntangledRenderLanes(), fiber); - push( - currentTreeHiddenStackCursor, - currentTreeHiddenStackCursor.current, - fiber - ); - } - function popHiddenContext(fiber) { - // Restore the previous render lanes from the stack - setEntangledRenderLanes(prevEntangledRenderLanesCursor.current); - pop(currentTreeHiddenStackCursor, fiber); - pop(prevEntangledRenderLanesCursor, fiber); - } - function isCurrentTreeHidden() { - return currentTreeHiddenStackCursor.current !== null; - } + var newChildren = iteratorFn.call(newChildrenIterable); - // suspends, i.e. it's the nearest `catch` block on the stack. + if (newChildren == null) { + throw new Error("An iterable object provided no iterator."); + } - var suspenseHandlerStackCursor = createCursor(null); // Represents the outermost boundary that is not visible in the current tree. - // Everything above this is the "shell". When this is null, it means we're - // rendering in the shell of the app. If it's non-null, it means we're rendering - // deeper than the shell, inside a new tree that wasn't already visible. - // - // The main way we use this concept is to determine whether showing a fallback - // would result in a desirable or undesirable loading state. Activing a fallback - // in the shell is considered an undersirable loading state, because it would - // mean hiding visible (albeit stale) content in the current tree — we prefer to - // show the stale content, rather than switch to a fallback. But showing a - // fallback in a new tree is fine, because there's no stale content to - // prefer instead. + var resultingFirstChild = null; + var previousNewFiber = null; + var oldFiber = currentFirstChild; + var lastPlacedIndex = 0; + var newIdx = 0; + var nextOldFiber = null; + var step = newChildren.next(); - var shellBoundary = null; - function getShellBoundary() { - return shellBoundary; - } - function pushPrimaryTreeSuspenseHandler(handler) { - // TODO: Pass as argument - var current = handler.alternate; - // propagated a single level. For example, when ForceSuspenseFallback is set, - // it should only force the nearest Suspense boundary into fallback mode. + for ( + ; + oldFiber !== null && !step.done; + newIdx++, step = newChildren.next() + ) { + if (oldFiber.index > newIdx) { + nextOldFiber = oldFiber; + oldFiber = null; + } else { + nextOldFiber = oldFiber.sibling; + } - pushSuspenseListContext( - handler, - setDefaultShallowSuspenseListContext(suspenseStackCursor.current) - ); // Experimental feature: Some Suspense boundaries are marked as having an - // to push a nested Suspense handler, because it will get replaced by the - // outer fallback, anyway. Consider this as a future optimization. + var newFiber = updateSlot(returnFiber, oldFiber, step.value, lanes); - push(suspenseHandlerStackCursor, handler, handler); + if (newFiber === null) { + // TODO: This breaks on empty slots like null children. That's + // unfortunate because it triggers the slow path all the time. We need + // a better way to communicate whether this was a miss or null, + // boolean, undefined, etc. + if (oldFiber === null) { + oldFiber = nextOldFiber; + } - if (shellBoundary === null) { - if (current === null || isCurrentTreeHidden()) { - // This boundary is not visible in the current UI. - shellBoundary = handler; - } else { - var prevState = current.memoizedState; + break; + } - if (prevState !== null) { - // This boundary is showing a fallback in the current UI. - shellBoundary = handler; + if (shouldTrackSideEffects) { + if (oldFiber && newFiber.alternate === null) { + // We matched the slot, but we didn't reuse the existing fiber, so we + // need to delete the existing child. + deleteChild(returnFiber, oldFiber); + } + } + + lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx); + + if (previousNewFiber === null) { + // TODO: Move out of the loop. This only happens for the first run. + resultingFirstChild = newFiber; + } else { + // TODO: Defer siblings if we're not at the right index for this slot. + // I.e. if we had null values before, then we want to defer this + // for each null value. However, we also don't want to call updateSlot + // with the previous one. + previousNewFiber.sibling = newFiber; } + + previousNewFiber = newFiber; + oldFiber = nextOldFiber; } - } - } - function pushFallbackTreeSuspenseHandler(fiber) { - // We're about to render the fallback. If something in the fallback suspends, - // it's akin to throwing inside of a `catch` block. This boundary should not - // capture. Reuse the existing handler on the stack. - reuseSuspenseHandlerOnStack(fiber); - } - function pushOffscreenSuspenseHandler(fiber) { - if (fiber.tag === OffscreenComponent) { - // A SuspenseList context is only pushed here to avoid a push/pop mismatch. - // Reuse the current value on the stack. - // TODO: We can avoid needing to push here by by forking popSuspenseHandler - // into separate functions for Suspense and Offscreen. - pushSuspenseListContext(fiber, suspenseStackCursor.current); - push(suspenseHandlerStackCursor, fiber, fiber); - if (shellBoundary !== null); - else { - var current = fiber.alternate; + if (step.done) { + // We've reached the end of the new children. We can delete the rest. + deleteRemainingChildren(returnFiber, oldFiber); - if (current !== null) { - var prevState = current.memoizedState; + return resultingFirstChild; + } - if (prevState !== null) { - // This is the first boundary in the stack that's already showing - // a fallback. So everything outside is considered the shell. - shellBoundary = fiber; + if (oldFiber === null) { + // If we don't have any more existing children we can choose a fast path + // since the rest will all be insertions. + for (; !step.done; newIdx++, step = newChildren.next()) { + var _newFiber3 = createChild(returnFiber, step.value, lanes); + + if (_newFiber3 === null) { + continue; } - } - } - } else { - // This is a LegacyHidden component. - reuseSuspenseHandlerOnStack(fiber); - } - } - function reuseSuspenseHandlerOnStack(fiber) { - pushSuspenseListContext(fiber, suspenseStackCursor.current); - push(suspenseHandlerStackCursor, getSuspenseHandler(), fiber); - } - function getSuspenseHandler() { - return suspenseHandlerStackCursor.current; - } - function popSuspenseHandler(fiber) { - pop(suspenseHandlerStackCursor, fiber); - if (shellBoundary === fiber) { - // Popping back into the shell. - shellBoundary = null; - } + lastPlacedIndex = placeChild(_newFiber3, lastPlacedIndex, newIdx); - popSuspenseListContext(fiber); - } // SuspenseList context - // TODO: Move to a separate module? We may change the SuspenseList - // implementation to hide/show in the commit phase, anyway. + if (previousNewFiber === null) { + // TODO: Move out of the loop. This only happens for the first run. + resultingFirstChild = _newFiber3; + } else { + previousNewFiber.sibling = _newFiber3; + } - var DefaultSuspenseContext = 0; - var SubtreeSuspenseContextMask = 1; // ForceSuspenseFallback can be used by SuspenseList to force newly added - // items into their fallback state during one of the render passes. + previousNewFiber = _newFiber3; + } - var ForceSuspenseFallback = 2; - var suspenseStackCursor = createCursor(DefaultSuspenseContext); - function hasSuspenseListContext(parentContext, flag) { - return (parentContext & flag) !== 0; - } - function setDefaultShallowSuspenseListContext(parentContext) { - return parentContext & SubtreeSuspenseContextMask; - } - function setShallowSuspenseListContext(parentContext, shallowContext) { - return (parentContext & SubtreeSuspenseContextMask) | shallowContext; - } - function pushSuspenseListContext(fiber, newContext) { - push(suspenseStackCursor, newContext, fiber); - } - function popSuspenseListContext(fiber) { - pop(suspenseStackCursor, fiber); - } + return resultingFirstChild; + } // Add all children to a key map for quick lookups. - // A non-null SuspenseState means that it is blocked for one reason or another. - // - A non-null dehydrated field means it's blocked pending hydration. - // - A non-null dehydrated field can use isSuspenseInstancePending or - // isSuspenseInstanceFallback to query the reason for being dehydrated. - // - A null dehydrated field means it's blocked by something suspending and - // we're currently showing a fallback instead. + var existingChildren = mapRemainingChildren(returnFiber, oldFiber); // Keep scanning and use the map to restore deleted items as moves. - function findFirstSuspended(row) { - var node = row; + for (; !step.done; newIdx++, step = newChildren.next()) { + var _newFiber4 = updateFromMap( + existingChildren, + returnFiber, + newIdx, + step.value, + lanes + ); - while (node !== null) { - if (node.tag === SuspenseComponent) { - var state = node.memoizedState; + if (_newFiber4 !== null) { + if (shouldTrackSideEffects) { + if (_newFiber4.alternate !== null) { + // The new fiber is a work in progress, but if there exists a + // current, that means that we reused the fiber. We need to delete + // it from the child list so that we don't add it to the deletion + // list. + existingChildren.delete( + _newFiber4.key === null ? newIdx : _newFiber4.key + ); + } + } - if (state !== null) { - var dehydrated = state.dehydrated; + lastPlacedIndex = placeChild(_newFiber4, lastPlacedIndex, newIdx); - if ( - dehydrated === null || - isSuspenseInstancePending() || - isSuspenseInstanceFallback() - ) { - return node; + if (previousNewFiber === null) { + resultingFirstChild = _newFiber4; + } else { + previousNewFiber.sibling = _newFiber4; } - } - } else if ( - node.tag === SuspenseListComponent && // revealOrder undefined can't be trusted because it don't - // keep track of whether it suspended or not. - node.memoizedProps.revealOrder !== undefined - ) { - var didSuspend = (node.flags & DidCapture) !== NoFlags$1; - if (didSuspend) { - return node; + previousNewFiber = _newFiber4; } - } else if (node.child !== null) { - node.child.return = node; - node = node.child; - continue; } - if (node === row) { - return null; + if (shouldTrackSideEffects) { + // Any existing children that weren't consumed above were deleted. We need + // to add them to the deletion list. + existingChildren.forEach(function (child) { + return deleteChild(returnFiber, child); + }); } - while (node.sibling === null) { - if (node.return === null || node.return === row) { - return null; - } + return resultingFirstChild; + } - node = node.return; - } + function reconcileSingleTextNode( + returnFiber, + currentFirstChild, + textContent, + lanes + ) { + // There's no need to check for keys on text nodes since we don't have a + // way to define them. + if (currentFirstChild !== null && currentFirstChild.tag === HostText) { + // We already have an existing node so let's just update it and delete + // the rest. + deleteRemainingChildren(returnFiber, currentFirstChild.sibling); + var existing = useFiber(currentFirstChild, textContent); + existing.return = returnFiber; + return existing; + } // The existing first child is not a text node so we need to create one + // and delete the existing ones. - node.sibling.return = node.return; - node = node.sibling; + deleteRemainingChildren(returnFiber, currentFirstChild); + var created = createFiberFromText(textContent, returnFiber.mode, lanes); + created.return = returnFiber; + return created; } - return null; - } + function reconcileSingleElement( + returnFiber, + currentFirstChild, + element, + lanes + ) { + var key = element.key; + var child = currentFirstChild; - var NoFlags = - /* */ - 0; // Represents whether effect should fire. + while (child !== null) { + // TODO: If key === null and child.key === null, then this only applies to + // the first item in the list. + if (child.key === key) { + var elementType = element.type; - var HasEffect = - /* */ - 1; // Represents the phase in which the effect (not the clean-up) fires. + if (elementType === REACT_FRAGMENT_TYPE) { + if (child.tag === Fragment) { + deleteRemainingChildren(returnFiber, child.sibling); + var existing = useFiber(child, element.props.children); + existing.return = returnFiber; - var Insertion = - /* */ - 2; - var Layout = - /* */ - 4; - var Passive = - /* */ - 8; + { + existing._debugSource = element._source; + existing._debugOwner = element._owner; + } - 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. + return existing; + } + } else { + if ( + child.elementType === elementType || // Keep this check inline so it only runs on the false path: + isCompatibleFamilyForHotReloading(child, element) || // Lazy types should reconcile their resolved type. + // We need to do this after the Hot Reloading check above, + // because hot reloading has different semantics than prod because + // it doesn't resuspend. So we can't let the call below suspend. + (typeof elementType === "object" && + elementType !== null && + elementType.$$typeof === REACT_LAZY_TYPE && + resolveLazy(elementType) === child.type) + ) { + deleteRemainingChildren(returnFiber, child.sibling); - var firstScheduledRoot = null; - var lastScheduledRoot = null; // Used to prevent redundant mircotasks from being scheduled. + var _existing = useFiber(child, element.props); - 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. + _existing.ref = coerceRef(returnFiber, child, element); + _existing.return = returnFiber; - var didScheduleMicrotask_act = false; // Used to quickly bail out of flushSync if there's no sync work to do. + { + _existing._debugSource = element._source; + _existing._debugOwner = element._owner; + } - 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. + return _existing; + } + } // Didn't match. - 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. + deleteRemainingChildren(returnFiber, child); + break; + } else { + deleteChild(returnFiber, child); + } - 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); + child = child.sibling; } - } - - 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; - } // 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 workInProgressRoot = getWorkInProgressRoot(); - var workInProgressRootRenderLanes = - getWorkInProgressRootRenderLanes(); - var nextLanes = getNextLanes( - root, - root === workInProgressRoot - ? workInProgressRootRenderLanes - : NoLanes - ); + if (element.type === REACT_FRAGMENT_TYPE) { + var created = createFiberFromFragment( + element.props.children, + returnFiber.mode, + lanes, + element.key + ); + created.return = returnFiber; + return created; + } else { + var _created4 = createFiberFromElement( + element, + returnFiber.mode, + lanes + ); - if (includesSyncLane(nextLanes)) { - // This root has pending sync work. Flush it now. - try { - didPerformSomeWork = true; - performSyncWorkOnRoot(root, nextLanes); - } catch (error) { - // Collect errors so we can rethrow them at the end - if (errors === null) { - errors = [error]; - } else { - errors.push(error); - } - } + _created4.ref = coerceRef(returnFiber, currentFirstChild, element); + _created4.return = returnFiber; + return _created4; + } + } + + function reconcileSinglePortal( + returnFiber, + currentFirstChild, + portal, + lanes + ) { + var key = portal.key; + var child = currentFirstChild; + + while (child !== null) { + // TODO: If key === null and child.key === null, then this only applies to + // the first item in the list. + if (child.key === key) { + if ( + child.tag === HostPortal && + child.stateNode.containerInfo === portal.containerInfo && + child.stateNode.implementation === portal.implementation + ) { + deleteRemainingChildren(returnFiber, child.sibling); + var existing = useFiber(child, portal.children || []); + existing.return = returnFiber; + return existing; + } else { + deleteRemainingChildren(returnFiber, child); + break; } + } else { + deleteChild(returnFiber, child); } - root = root.next; + child = child.sibling; } - } 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. + var created = createFiberFromPortal(portal, returnFiber.mode, lanes); + created.return = returnFiber; + return created; + } // This API will tag the children with the side-effect of the reconciliation + // itself. They will be added to the side-effect list as we pass through the + // children and the parent. - 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])); - } + function reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + newChild, + lanes + ) { + // This function is not recursive. + // If the top level item is an array, we treat it as a set of children, + // not as a fragment. Nested arrays on the other hand will be treated as + // fragment nodes. Recursion happens at the normal flow. + // Handle top level unkeyed fragments as if they were arrays. + // This leads to an ambiguity between <>{[...]} and <>.... + // We treat the ambiguous cases above the same. + // TODO: Let's use recursion like we do for Usable nodes? + var isUnkeyedTopLevelFragment = + typeof newChild === "object" && + newChild !== null && + newChild.type === REACT_FRAGMENT_TYPE && + newChild.key === null; - var firstError = errors[0]; - throw firstError; + if (isUnkeyedTopLevelFragment) { + newChild = newChild.props.children; + } // Handle object types + + if (typeof newChild === "object" && newChild !== null) { + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE: + return placeSingleChild( + reconcileSingleElement( + returnFiber, + currentFirstChild, + newChild, + lanes + ) + ); + + case REACT_PORTAL_TYPE: + return placeSingleChild( + reconcileSinglePortal( + returnFiber, + currentFirstChild, + newChild, + lanes + ) + ); + + case REACT_LAZY_TYPE: + var payload = newChild._payload; + var init = newChild._init; // TODO: This function is supposed to be non-recursive. + + return reconcileChildFibers( + returnFiber, + currentFirstChild, + init(payload), + lanes + ); } - } else { - var error = errors[0]; - throw error; - } - } - } - function throwError(error) { - throw error; - } + if (isArray(newChild)) { + return reconcileChildrenArray( + returnFiber, + currentFirstChild, + newChild, + lanes + ); + } - function processRootScheduleInMicrotask() { - // This function is always called inside a microtask. It should never be - // called synchronously. - didScheduleMicrotask = false; + if (getIteratorFn(newChild)) { + return reconcileChildrenIterator( + returnFiber, + currentFirstChild, + newChild, + lanes + ); + } // Usables are a valid React node type. When React encounters a Usable in + // a child position, it unwraps it using the same algorithm as `use`. For + // example, for promises, React will throw an exception to unwind the + // stack, then replay the component once the promise resolves. + // + // A difference from `use` is that React will keep unwrapping the value + // until it reaches a non-Usable type. + // + // e.g. Usable>> should resolve to T + // + // The structure is a bit unfortunate. Ideally, we shouldn't need to + // replay the entire begin phase of the parent fiber in order to reconcile + // the children again. This would require a somewhat significant refactor, + // because reconcilation happens deep within the begin phase, and + // depending on the type of work, not always at the end. We should + // consider as an future improvement. - { - didScheduleMicrotask_act = false; - } // We'll recompute this as we iterate through all the roots and schedule them. + if (typeof newChild.then === "function") { + var thenable = newChild; + return reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + unwrapThenable(thenable), + lanes + ); + } - mightHavePendingSyncWork = false; - var currentTime = now$1(); - var prev = null; - var root = firstScheduledRoot; + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) { + var context = newChild; + return reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + readContextDuringReconcilation(returnFiber, context, lanes), + lanes + ); + } - while (root !== null) { - var next = root.next; + throwOnInvalidObjectType(returnFiber, newChild); + } if ( - currentEventTransitionLane !== NoLane && - shouldAttemptEagerTransition() + (typeof newChild === "string" && newChild !== "") || + typeof newChild === "number" ) { - // A transition was scheduled during an event, but we're going to try to - // render it synchronously anyway. We do this during a popstate event to - // preserve the scroll position of the previous page. - upgradePendingLaneToSync(root, currentEventTransitionLane); + return placeSingleChild( + reconcileSingleTextNode( + returnFiber, + currentFirstChild, + "" + newChild, + lanes + ) + ); } - 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 (typeof newChild === "function") { + warnOnFunctionType(returnFiber); } + } // Remaining cases are all treated as empty. - 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; + return deleteRemainingChildren(returnFiber, currentFirstChild); + } - if (includesSyncLane(nextLanes)) { - mightHavePendingSyncWork = true; - } - } + function reconcileChildFibers( + returnFiber, + currentFirstChild, + newChild, + lanes + ) { + // This indirection only exists so we can reset `thenableState` at the end. + // It should get inlined by Closure. + thenableIndexCounter$1 = 0; + var firstChildFiber = reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + newChild, + lanes + ); + thenableState$1 = null; // Don't bother to reset `thenableIndexCounter` to 0 because it always gets + // set at the beginning. - root = next; + return firstChildFiber; } - 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. + return reconcileChildFibers; + } - flushSyncWorkOnAllRoots(); + var reconcileChildFibers = createChildReconciler(true); + var mountChildFibers = createChildReconciler(false); + function resetChildReconcilerOnUnwind() { + // On unwind, clear any pending thenables that were used. + thenableState$1 = null; + thenableIndexCounter$1 = 0; } + function cloneChildFibers(current, workInProgress) { + if (current !== null && workInProgress.child !== current.child) { + throw new Error("Resuming work not yet implemented."); + } - 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. + if (workInProgress.child === null) { + return; + } - var workInProgressRoot = getWorkInProgressRoot(); - var workInProgressRootRenderLanes = getWorkInProgressRootRenderLanes(); - var nextLanes = getNextLanes( - root, - root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes + var currentChild = workInProgress.child; + var newChild = createWorkInProgress( + currentChild, + currentChild.pendingProps ); - var existingCallbackNode = root.callbackNode; + workInProgress.child = newChild; + newChild.return = workInProgress; - 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); - } + while (currentChild.sibling !== null) { + currentChild = currentChild.sibling; + newChild = newChild.sibling = createWorkInProgress( + currentChild, + currentChild.pendingProps + ); + newChild.return = workInProgress; + } - root.callbackNode = null; - root.callbackPriority = NoLane; - return NoLane; - } // Schedule a new callback in the host environment. + newChild.sibling = null; + } // Reset a workInProgress child set to prepare it for a second pass. - 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); - } + function resetChildFibers(workInProgress, lanes) { + var child = workInProgress.child; - 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); + while (child !== null) { + resetWorkInProgress(child, lanes); + child = child.sibling; + } + } - 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); - } + // TODO: This isn't being used yet, but it's intended to replace the + // InvisibleParentContext that is currently managed by SuspenseContext. - var schedulerPriorityLevel; + var currentTreeHiddenStackCursor = createCursor(null); + var prevEntangledRenderLanesCursor = createCursor(NoLanes); + function pushHiddenContext(fiber, context) { + var prevEntangledRenderLanes = getEntangledRenderLanes(); + push(prevEntangledRenderLanesCursor, prevEntangledRenderLanes, fiber); + push(currentTreeHiddenStackCursor, context, fiber); // When rendering a subtree that's currently hidden, we must include all + // lanes that would have rendered if the hidden subtree hadn't been deferred. + // That is, in order to reveal content from hidden -> visible, we must commit + // all the updates that we skipped when we originally hid the tree. - switch (lanesToEventPriority(nextLanes)) { - case DiscreteEventPriority: - schedulerPriorityLevel = ImmediatePriority; - break; + setEntangledRenderLanes( + mergeLanes(prevEntangledRenderLanes, context.baseLanes) + ); + } + function reuseHiddenContextOnStack(fiber) { + // This subtree is not currently hidden, so we don't need to add any lanes + // to the render lanes. But we still need to push something to avoid a + // context mismatch. Reuse the existing context on the stack. + push(prevEntangledRenderLanesCursor, getEntangledRenderLanes(), fiber); + push( + currentTreeHiddenStackCursor, + currentTreeHiddenStackCursor.current, + fiber + ); + } + function popHiddenContext(fiber) { + // Restore the previous render lanes from the stack + setEntangledRenderLanes(prevEntangledRenderLanesCursor.current); + pop(currentTreeHiddenStackCursor, fiber); + pop(prevEntangledRenderLanesCursor, fiber); + } + function isCurrentTreeHidden() { + return currentTreeHiddenStackCursor.current !== null; + } - case ContinuousEventPriority: - schedulerPriorityLevel = UserBlockingPriority; - break; + // suspends, i.e. it's the nearest `catch` block on the stack. - case DefaultEventPriority: - schedulerPriorityLevel = NormalPriority$1; - break; + var suspenseHandlerStackCursor = createCursor(null); // Represents the outermost boundary that is not visible in the current tree. + // Everything above this is the "shell". When this is null, it means we're + // rendering in the shell of the app. If it's non-null, it means we're rendering + // deeper than the shell, inside a new tree that wasn't already visible. + // + // The main way we use this concept is to determine whether showing a fallback + // would result in a desirable or undesirable loading state. Activing a fallback + // in the shell is considered an undersirable loading state, because it would + // mean hiding visible (albeit stale) content in the current tree — we prefer to + // show the stale content, rather than switch to a fallback. But showing a + // fallback in a new tree is fine, because there's no stale content to + // prefer instead. - case IdleEventPriority: - schedulerPriorityLevel = IdlePriority; - break; + var shellBoundary = null; + function getShellBoundary() { + return shellBoundary; + } + function pushPrimaryTreeSuspenseHandler(handler) { + // TODO: Pass as argument + var current = handler.alternate; + // propagated a single level. For example, when ForceSuspenseFallback is set, + // it should only force the nearest Suspense boundary into fallback mode. - default: - schedulerPriorityLevel = NormalPriority$1; - break; - } + pushSuspenseListContext( + handler, + setDefaultShallowSuspenseListContext(suspenseStackCursor.current) + ); // Experimental feature: Some Suspense boundaries are marked as having an + // to push a nested Suspense handler, because it will get replaced by the + // outer fallback, anyway. Consider this as a future optimization. - var newCallbackNode = scheduleCallback$2( - schedulerPriorityLevel, - performConcurrentWorkOnRoot.bind(null, root) - ); - root.callbackPriority = newCallbackPriority; - root.callbackNode = newCallbackNode; - return newCallbackPriority; - } - } + push(suspenseHandlerStackCursor, handler, handler); - 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 (shellBoundary === null) { + if (current === null || isCurrentTreeHidden()) { + // This boundary is not visible in the current UI. + shellBoundary = handler; + } else { + var prevState = current.memoizedState; - 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); + if (prevState !== null) { + // This boundary is showing a fallback in the current UI. + shellBoundary = handler; + } + } } - - return null; } - var fakeActCallbackNode$1 = {}; + function pushFallbackTreeSuspenseHandler(fiber) { + // We're about to render the fallback. If something in the fallback suspends, + // it's akin to throwing inside of a `catch` block. This boundary should not + // capture. Reuse the existing handler on the stack. + reuseSuspenseHandlerOnStack(fiber); + } + function pushOffscreenSuspenseHandler(fiber) { + if (fiber.tag === OffscreenComponent) { + // A SuspenseList context is only pushed here to avoid a push/pop mismatch. + // Reuse the current value on the stack. + // TODO: We can avoid needing to push here by by forking popSuspenseHandler + // into separate functions for Suspense and Offscreen. + pushSuspenseListContext(fiber, suspenseStackCursor.current); + push(suspenseHandlerStackCursor, fiber, fiber); + + if (shellBoundary !== null); + else { + var current = fiber.alternate; - 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; + if (current !== null) { + var prevState = current.memoizedState; + + if (prevState !== null) { + // This is the first boundary in the stack that's already showing + // a fallback. So everything outside is considered the shell. + shellBoundary = fiber; + } + } + } } else { - return scheduleCallback$3(priorityLevel, callback); + // This is a LegacyHidden component. + reuseSuspenseHandlerOnStack(fiber); } } - - function cancelCallback(callbackNode) { - if (callbackNode === fakeActCallbackNode$1); - else if (callbackNode !== null) { - cancelCallback$1(callbackNode); - } + function reuseSuspenseHandlerOnStack(fiber) { + pushSuspenseListContext(fiber, suspenseStackCursor.current); + push(suspenseHandlerStackCursor, getSuspenseHandler(), fiber); } - - 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 getSuspenseHandler() { + return suspenseHandlerStackCursor.current; } + function popSuspenseHandler(fiber) { + pop(suspenseHandlerStackCursor, fiber); - 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(); + if (shellBoundary === fiber) { + // Popping back into the shell. + shellBoundary = null; } - return currentEventTransitionLane; - } + popSuspenseListContext(fiber); + } // SuspenseList context + // TODO: Move to a separate module? We may change the SuspenseList + // implementation to hide/show in the commit phase, anyway. - // transition updates that occur while the async action is still in progress - // are treated as part of the action. - // - // The ideal behavior would be to treat each async function as an independent - // action. However, without a mechanism like AsyncContext, we can't tell which - // action an update corresponds to. So instead, we entangle them all into one. - // The listeners to notify once the entangled scope completes. + var DefaultSuspenseContext = 0; + var SubtreeSuspenseContextMask = 1; // ForceSuspenseFallback can be used by SuspenseList to force newly added + // items into their fallback state during one of the render passes. - var currentEntangledListeners = null; // The number of pending async actions in the entangled scope. + var ForceSuspenseFallback = 2; + var suspenseStackCursor = createCursor(DefaultSuspenseContext); + function hasSuspenseListContext(parentContext, flag) { + return (parentContext & flag) !== 0; + } + function setDefaultShallowSuspenseListContext(parentContext) { + return parentContext & SubtreeSuspenseContextMask; + } + function setShallowSuspenseListContext(parentContext, shallowContext) { + return (parentContext & SubtreeSuspenseContextMask) | shallowContext; + } + function pushSuspenseListContext(fiber, newContext) { + push(suspenseStackCursor, newContext, fiber); + } + function popSuspenseListContext(fiber) { + pop(suspenseStackCursor, fiber); + } - var currentEntangledPendingCount = 0; // The transition lane shared by all updates in the entangled scope. + // A non-null SuspenseState means that it is blocked for one reason or another. + // - A non-null dehydrated field means it's blocked pending hydration. + // - A non-null dehydrated field can use isSuspenseInstancePending or + // isSuspenseInstanceFallback to query the reason for being dehydrated. + // - A null dehydrated field means it's blocked by something suspending and + // we're currently showing a fallback instead. - var currentEntangledLane = NoLane; - function requestAsyncActionContext( - actionReturnValue, // If this is provided, this resulting thenable resolves to this value instead - // of the return value of the action. This is a perf trick to avoid composing - // an extra async function. - overrideReturnValue - ) { - // 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. - var thenable = actionReturnValue; - var entangledListeners; + function findFirstSuspended(row) { + var node = row; - if (currentEntangledListeners === null) { - // There's no outer async action scope. Create a new one. - entangledListeners = currentEntangledListeners = []; - currentEntangledPendingCount = 0; - currentEntangledLane = requestTransitionLane(); - } else { - entangledListeners = currentEntangledListeners; - } + while (node !== null) { + if (node.tag === SuspenseComponent) { + var state = node.memoizedState; - currentEntangledPendingCount++; // Create a thenable that represents the result of this action, but doesn't - // resolve until the entire entangled scope has finished. - // - // Expressed using promises: - // const [thisResult] = await Promise.all([thisAction, entangledAction]); - // return thisResult; - - var resultThenable = createResultThenable(entangledListeners); - var resultStatus = "pending"; - var resultValue; - var rejectedReason; - thenable.then( - function (value) { - resultStatus = "fulfilled"; - resultValue = - overrideReturnValue !== null ? overrideReturnValue : value; - pingEngtangledActionScope(); - }, - function (error) { - resultStatus = "rejected"; - rejectedReason = error; - pingEngtangledActionScope(); - } - ); // Attach a listener to fill in the result. - - entangledListeners.push(function () { - switch (resultStatus) { - case "fulfilled": { - var fulfilledThenable = resultThenable; - fulfilledThenable.status = "fulfilled"; - fulfilledThenable.value = resultValue; - break; - } + if (state !== null) { + var dehydrated = state.dehydrated; - case "rejected": { - var rejectedThenable = resultThenable; - rejectedThenable.status = "rejected"; - rejectedThenable.reason = rejectedReason; - break; + if ( + dehydrated === null || + isSuspenseInstancePending() || + isSuspenseInstanceFallback() + ) { + return node; + } } + } else if ( + node.tag === SuspenseListComponent && // revealOrder undefined can't be trusted because it don't + // keep track of whether it suspended or not. + node.memoizedProps.revealOrder !== undefined + ) { + var didSuspend = (node.flags & DidCapture) !== NoFlags$1; - case "pending": - default: { - // The listener above should have been called first, so `resultStatus` - // should already be set to the correct value. - throw new Error( - "Thenable should have already resolved. This " + - "is a bug in React." - ); + if (didSuspend) { + return node; } + } else if (node.child !== null) { + node.child.return = node; + node = node.child; + continue; } - }); - return resultThenable; - } - function requestSyncActionContext( - actionReturnValue, // If this is provided, this resulting thenable resolves to this value instead - // of the return value of the action. This is a perf trick to avoid composing - // an extra async function. - overrideReturnValue - ) { - var resultValue = - overrideReturnValue !== null ? overrideReturnValue : actionReturnValue; // This is not an async action, but it may be part of an outer async action. - if (currentEntangledListeners === null) { - return resultValue; - } else { - // Return a thenable that does not resolve until the entangled actions - // have finished. - var entangledListeners = currentEntangledListeners; - var resultThenable = createResultThenable(entangledListeners); - entangledListeners.push(function () { - var fulfilledThenable = resultThenable; - fulfilledThenable.status = "fulfilled"; - fulfilledThenable.value = resultValue; - }); - return resultThenable; - } - } + if (node === row) { + return null; + } - function pingEngtangledActionScope() { - if ( - currentEntangledListeners !== null && - --currentEntangledPendingCount === 0 - ) { - // All the actions have finished. Close the entangled async action scope - // and notify all the listeners. - var listeners = currentEntangledListeners; - currentEntangledListeners = null; - currentEntangledLane = NoLane; + while (node.sibling === null) { + if (node.return === null || node.return === row) { + return null; + } - for (var i = 0; i < listeners.length; i++) { - var listener = listeners[i]; - listener(); + node = node.return; } + + node.sibling.return = node.return; + node = node.sibling; } - } - function createResultThenable(entangledListeners) { - // Waits for the entangled async action to complete, then resolves to the - // result of an individual action. - var resultThenable = { - status: "pending", - value: null, - reason: null, - then: function (resolve) { - // This is a bit of a cheat. `resolve` expects a value of type `S` to be - // passed, but because we're instrumenting the `status` field ourselves, - // and we know this thenable will only be used by React, we also know - // the value isn't actually needed. So we add the resolve function - // directly to the entangled listeners. - // - // This is also why we don't need to check if the thenable is still - // pending; the Suspense implementation already performs that check. - var ping = resolve; - entangledListeners.push(ping); - } - }; - return resultThenable; + return null; } - function peekEntangledActionLane() { - return currentEntangledLane; - } + var NoFlags = + /* */ + 0; // Represents whether effect should fire. + + var HasEffect = + /* */ + 1; // Represents the phase in which the effect (not the clean-up) fires. + + var Insertion = + /* */ + 2; + var Layout = + /* */ + 4; + var Passive = + /* */ + 8; var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, ReactCurrentBatchConfig$2 = ReactSharedInternals.ReactCurrentBatchConfig; @@ -7702,6 +7694,7 @@ if (__DEV__) { var newBaseQueueFirst = null; var newBaseQueueLast = null; var update = first; + var didReadFromEntangledAsyncAction = false; do { // An extra OffscreenLane bit is added to updates that were made to @@ -7745,7 +7738,16 @@ if (__DEV__) { markSkippedUpdateLanes(updateLane); } else { // This update does have sufficient priority. - // Check if this is an optimistic update. + // Check if this update is part of a pending async action. If so, + // we'll need to suspend until the action has finished, so that it's + // batched together with future updates in the same action. + if ( + updateLane !== NoLane && + updateLane === peekEntangledActionLane() + ) { + didReadFromEntangledAsyncAction = true; + } // Check if this is an optimistic update. + var revertLane = update.revertLane; if (revertLane === NoLane) { @@ -7837,7 +7839,23 @@ if (__DEV__) { // different from the current state. if (!objectIs(newState, hook.memoizedState)) { - markWorkInProgressReceivedUpdate(); + markWorkInProgressReceivedUpdate(); // Check if this update is part of a pending async action. If so, we'll + // need to suspend until the action has finished, so that it's batched + // together with future updates in the same action. + // TODO: Once we support hooks inside useMemo (or an equivalent + // memoization boundary like Forget), hoist this logic so that it only + // suspends if the memo boundary produces a new value. + + if (didReadFromEntangledAsyncAction) { + var entangledActionThenable = peekEntangledActionThenable(); + + if (entangledActionThenable !== null) { + // TODO: Instead of the throwing the thenable directly, throw a + // special object like `use` does so we can detect if it's captured + // by userspace. + throw entangledActionThenable; + } + } } hook.memoizedState = newState; @@ -8297,14 +8315,10 @@ if (__DEV__) { return finishRunningFormStateAction(actionQueue, setState); } ); - var entangledResult = requestAsyncActionContext(thenable, null); - setState(entangledResult); + entangleAsyncAction(thenable); + setState(thenable); } else { - // This is either `returnValue` or a thenable that resolves to - // `returnValue`, depending on whether we're inside an async action scope. - var _entangledResult = requestSyncActionContext(returnValue, null); - - setState(_entangledResult); + setState(returnValue); var nextState = returnValue; actionQueue.state = nextState; finishRunningFormStateAction(actionQueue, setState); @@ -8895,24 +8909,17 @@ if (__DEV__) { typeof returnValue === "object" && typeof returnValue.then === "function" ) { - var thenable = returnValue; // This is a thenable that resolves to `finishedState` once the async - // action scope has finished. + var thenable = returnValue; + entangleAsyncAction(thenable); // Create a thenable that resolves to `finishedState` once the async + // action has completed. - var entangledResult = requestAsyncActionContext( + var thenableForFinishedState = chainThenableValue( thenable, finishedState ); - dispatchSetState(fiber, queue, entangledResult); + dispatchSetState(fiber, queue, thenableForFinishedState); } else { - // This is either `finishedState` or a thenable that resolves to - // `finishedState`, depending on whether we're inside an async - // action scope. - var _entangledResult2 = requestSyncActionContext( - returnValue, - finishedState - ); - - dispatchSetState(fiber, queue, _entangledResult2); + dispatchSetState(fiber, queue, finishedState); } } } catch (error) { @@ -11454,6 +11461,7 @@ if (__DEV__) { // process them now. processUpdateQueue(workInProgress, newProps, instance, renderLanes); + suspendIfUpdateReadFromEntangledAsyncAction(); instance.state = workInProgress.memoizedState; } @@ -11521,6 +11529,7 @@ if (__DEV__) { var oldState = workInProgress.memoizedState; var newState = (instance.state = oldState); processUpdateQueue(workInProgress, newProps, instance, renderLanes); + suspendIfUpdateReadFromEntangledAsyncAction(); newState = workInProgress.memoizedState; if ( @@ -11673,6 +11682,7 @@ if (__DEV__) { var oldState = workInProgress.memoizedState; var newState = (instance.state = oldState); processUpdateQueue(workInProgress, newProps, instance, renderLanes); + suspendIfUpdateReadFromEntangledAsyncAction(); newState = workInProgress.memoizedState; if ( @@ -12223,7 +12233,7 @@ if (__DEV__) { } } - return; + return false; } case OffscreenComponent: { @@ -12258,7 +12268,7 @@ if (__DEV__) { attachPingListener(root, wakeable, rootRenderLanes); } - return; + return false; } } } @@ -12281,7 +12291,7 @@ if (__DEV__) { // and potentially log a warning. Revisit this for a future release. attachPingListener(root, wakeable, rootRenderLanes); renderDidSuspendDelayIfPossible(); - return; + return false; } else { // In a legacy root, suspending without a boundary is always an error. var uncaughtSuspenseError = new Error( @@ -12301,6 +12311,12 @@ if (__DEV__) { // over and traverse parent path again, this time treating the exception // as an error. + if (returnFiber === null) { + // There's no return fiber, which means the root errored. This should never + // happen. Return `true` to trigger a fatal error (panic). + return true; + } + var workInProgress = returnFiber; do { @@ -12316,7 +12332,7 @@ if (__DEV__) { lane ); enqueueCapturedUpdate(workInProgress, update); - return; + return false; } case ClassComponent: @@ -12345,7 +12361,7 @@ if (__DEV__) { ); enqueueCapturedUpdate(workInProgress, _update); - return; + return false; } break; @@ -12353,6 +12369,8 @@ if (__DEV__) { workInProgress = workInProgress.return; } while (workInProgress !== null); + + return false; } var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner; // A special exception that's used to unwind the stack when an update flows @@ -12963,6 +12981,7 @@ if (__DEV__) { if (includesSomeLane(current.lanes, renderLanes)) { cloneUpdateQueue(current, workInProgress); processUpdateQueue(workInProgress, null, null, renderLanes); + suspendIfUpdateReadFromEntangledAsyncAction(); } var prevState = current.memoizedState; @@ -13394,7 +13413,11 @@ if (__DEV__) { // The root cache refreshed. propagateContextChange(workInProgress, CacheContext, renderLanes); } - } // Caution: React DevTools currently depends on this property + } // This would ideally go inside processUpdateQueue, but because it suspends, + // it needs to happen after the `pushCacheProvider` call above to avoid a + // context stack mismatch. A bit unfortunate. + + suspendIfUpdateReadFromEntangledAsyncAction(); // Caution: React DevTools currently depends on this property // being called "element". var nextChildren = nextState.element; @@ -22672,7 +22695,7 @@ if (__DEV__) { // Unwind then continue with the normal work loop. workInProgressSuspendedReason = NotSuspended; workInProgressThrownValue = null; - throwAndUnwindWorkLoop(unitOfWork, thrownValue); + throwAndUnwindWorkLoop(root, unitOfWork, thrownValue); break; } } @@ -22755,7 +22778,7 @@ if (__DEV__) { // Unwind then continue with the normal work loop. workInProgressSuspendedReason = NotSuspended; workInProgressThrownValue = null; - throwAndUnwindWorkLoop(unitOfWork, thrownValue); + throwAndUnwindWorkLoop(root, unitOfWork, thrownValue); break; } @@ -22820,7 +22843,7 @@ if (__DEV__) { // Otherwise, unwind then continue with the normal work loop. workInProgressSuspendedReason = NotSuspended; workInProgressThrownValue = null; - throwAndUnwindWorkLoop(unitOfWork, thrownValue); + throwAndUnwindWorkLoop(root, unitOfWork, thrownValue); } break; @@ -22885,7 +22908,7 @@ if (__DEV__) { workInProgressSuspendedReason = NotSuspended; workInProgressThrownValue = null; - throwAndUnwindWorkLoop(unitOfWork, thrownValue); + throwAndUnwindWorkLoop(root, unitOfWork, thrownValue); break; } @@ -22896,7 +22919,7 @@ if (__DEV__) { // always unwind. workInProgressSuspendedReason = NotSuspended; workInProgressThrownValue = null; - throwAndUnwindWorkLoop(unitOfWork, thrownValue); + throwAndUnwindWorkLoop(root, unitOfWork, thrownValue); break; } @@ -23115,7 +23138,7 @@ if (__DEV__) { ReactCurrentOwner.current = null; } - function throwAndUnwindWorkLoop(unitOfWork, thrownValue) { + function throwAndUnwindWorkLoop(root, unitOfWork, thrownValue) { // This is a fork of performUnitOfWork specifcally for unwinding a fiber // that threw an exception. // @@ -23124,40 +23147,33 @@ if (__DEV__) { resetSuspendedWorkLoopOnUnwind(unitOfWork); var returnFiber = unitOfWork.return; - if (returnFiber === null || workInProgressRoot === null) { - // Expected to be working on a non-root fiber. This is a fatal error - // because there's no ancestor that can handle it; the root is - // supposed to capture all errors that weren't caught by an error - // boundary. - workInProgressRootExitStatus = RootFatalErrored; - workInProgressRootFatalError = thrownValue; // Set `workInProgress` to null. This represents advancing to the next - // sibling, or the parent if there are no siblings. But since the root - // has no siblings nor a parent, we set it to null. Usually this is - // handled by `completeUnitOfWork` or `unwindWork`, but since we're - // intentionally not calling those, we need set it here. - // TODO: Consider calling `unwindWork` to pop the contexts. - - workInProgress = null; - return; - } - try { // Find and mark the nearest Suspense or error boundary that can handle // this "exception". - throwException( - workInProgressRoot, + var didFatal = throwException( + root, returnFiber, unitOfWork, thrownValue, workInProgressRootRenderLanes ); + + if (didFatal) { + panicOnRootError(thrownValue); + return; + } } catch (error) { // We had trouble processing the error. An example of this happening is // when accessing the `componentDidCatch` property of an error boundary // throws an error. A weird edge case. There's a regression test for this. // To prevent an infinite loop, bubble the error up to the next parent. - workInProgress = returnFiber; - throw error; + if (returnFiber !== null) { + workInProgress = returnFiber; + throw error; + } else { + panicOnRootError(thrownValue); + return; + } } if (unitOfWork.flags & Incomplete) { @@ -23177,6 +23193,22 @@ if (__DEV__) { } } + function panicOnRootError(error) { + // There's no ancestor that can handle this exception. This should never + // happen because the root is supposed to capture all errors that weren't + // caught by an error boundary. This is a fatal error, or panic condition, + // because we've run out of ways to recover. + workInProgressRootExitStatus = RootFatalErrored; + workInProgressRootFatalError = error; // Set `workInProgress` to null. This represents advancing to the next + // sibling, or the parent if there are no siblings. But since the root + // has no siblings nor a parent, we set it to null. Usually this is + // handled by `completeUnitOfWork` or `unwindWork`, but since we're + // intentionally not calling those, we need set it here. + // TODO: Consider calling `unwindWork` to pop the contexts. + + workInProgress = null; + } + function completeUnitOfWork(unitOfWork) { // Attempt to complete the current unit of work, then move to the next // sibling. If there are no more siblings, return to the parent fiber. @@ -25540,7 +25572,7 @@ if (__DEV__) { return root; } - var ReactVersion = "18.3.0-canary-2efb14260-20240124"; + var ReactVersion = "18.3.0-canary-11c9fd0c5-20240124"; // Might add PROFILE later. diff --git a/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react-test-renderer/cjs/ReactTestRenderer-prod.js b/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react-test-renderer/cjs/ReactTestRenderer-prod.js index 43af05c397046..6a3faf1adfe45 100644 --- a/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react-test-renderer/cjs/ReactTestRenderer-prod.js +++ b/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react-test-renderer/cjs/ReactTestRenderer-prod.js @@ -7,7 +7,7 @@ * @noflow * @nolint * @preventMunge - * @generated SignedSource<> + * @generated SignedSource<<9932d13e942d3ba6b8d1169bf8e60373>> */ "use strict"; @@ -786,6 +786,276 @@ function getRootForUpdatedFiber(sourceFiber) { (sourceFiber = parent), (parent = sourceFiber.return); return 3 === sourceFiber.tag ? sourceFiber.stateNode : null; } +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)); +} +function flushSyncWorkAcrossRoots_impl(onlyLegacy) { + if (!isFlushingWork && mightHavePendingSyncWork) { + var errors = null; + isFlushingWork = !0; + do { + var didPerformSomeWork = !1; + for (var root = firstScheduledRoot; null !== root; ) { + if (!onlyLegacy || 0 === root.tag) { + var workInProgressRootRenderLanes$7 = workInProgressRootRenderLanes, + nextLanes = getNextLanes( + root, + root === workInProgressRoot ? workInProgressRootRenderLanes$7 : 0 + ); + if (0 !== (nextLanes & 3)) + try { + didPerformSomeWork = !0; + workInProgressRootRenderLanes$7 = root; + if (0 !== (executionContext & 6)) + throw Error("Should not already be working."); + if (!flushPassiveEffects()) { + var exitStatus = renderRootSync( + workInProgressRootRenderLanes$7, + nextLanes + ); + if ( + 0 !== workInProgressRootRenderLanes$7.tag && + 2 === exitStatus + ) { + var originallyAttemptedLanes = nextLanes, + errorRetryLanes = getLanesToRetrySynchronouslyOnError( + workInProgressRootRenderLanes$7, + originallyAttemptedLanes + ); + 0 !== errorRetryLanes && + ((nextLanes = errorRetryLanes), + (exitStatus = recoverFromConcurrentError( + workInProgressRootRenderLanes$7, + originallyAttemptedLanes, + errorRetryLanes + ))); + } + if (1 === exitStatus) + throw ( + ((originallyAttemptedLanes = workInProgressRootFatalError), + prepareFreshStack(workInProgressRootRenderLanes$7, 0), + markRootSuspended( + workInProgressRootRenderLanes$7, + nextLanes, + 0 + ), + ensureRootIsScheduled(workInProgressRootRenderLanes$7), + originallyAttemptedLanes) + ); + 6 === exitStatus + ? markRootSuspended( + workInProgressRootRenderLanes$7, + nextLanes, + workInProgressDeferredLane + ) + : ((workInProgressRootRenderLanes$7.finishedWork = + workInProgressRootRenderLanes$7.current.alternate), + (workInProgressRootRenderLanes$7.finishedLanes = nextLanes), + commitRoot( + workInProgressRootRenderLanes$7, + workInProgressRootRecoverableErrors, + workInProgressTransitions, + workInProgressDeferredLane + )); + } + ensureRootIsScheduled(workInProgressRootRenderLanes$7); + } 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++) + (didPerformSomeWork = throwError.bind(null, errors[onlyLegacy])), + scheduleCallback$3(ImmediatePriority, didPerformSomeWork); + } + 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 & -62914561; + 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 268435456: + 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() { + if (0 === currentEventTransitionLane) { + var lane = nextTransitionLane; + nextTransitionLane <<= 1; + 0 === (nextTransitionLane & 4194176) && (nextTransitionLane = 128); + currentEventTransitionLane = lane; + } + return currentEventTransitionLane; +} +var currentEntangledListeners = null, + currentEntangledPendingCount = 0, + currentEntangledLane = 0, + currentEntangledActionThenable = null; +function entangleAsyncAction(thenable) { + if (null === currentEntangledListeners) { + var entangledListeners = (currentEntangledListeners = []); + currentEntangledPendingCount = 0; + currentEntangledLane = requestTransitionLane(); + currentEntangledActionThenable = { + status: "pending", + value: void 0, + then: function (resolve) { + entangledListeners.push(resolve); + } + }; + } + currentEntangledPendingCount++; + thenable.then(pingEngtangledActionScope, pingEngtangledActionScope); + return thenable; +} +function pingEngtangledActionScope() { + if ( + null !== currentEntangledListeners && + 0 === --currentEntangledPendingCount + ) { + null !== currentEntangledActionThenable && + (currentEntangledActionThenable.status = "fulfilled"); + var listeners = currentEntangledListeners; + currentEntangledListeners = null; + currentEntangledLane = 0; + currentEntangledActionThenable = null; + for (var i = 0; i < listeners.length; i++) (0, listeners[i])(); + } +} +function chainThenableValue(thenable, result) { + var listeners = [], + thenableWithOverride = { + status: "pending", + value: null, + reason: null, + then: function (resolve) { + listeners.push(resolve); + } + }; + thenable.then( + function () { + thenableWithOverride.status = "fulfilled"; + thenableWithOverride.value = result; + for (var i = 0; i < listeners.length; i++) (0, listeners[i])(result); + }, + function (error) { + thenableWithOverride.status = "rejected"; + thenableWithOverride.reason = error; + for (error = 0; error < listeners.length; error++) + (0, listeners[error])(void 0); + } + ); + return thenableWithOverride; +} var hasForceUpdate = !1; function initializeUpdateQueue(fiber) { fiber.updateQueue = { @@ -881,12 +1151,20 @@ function enqueueCapturedUpdate(workInProgress, capturedUpdate) { : (workInProgress.next = capturedUpdate); queue.lastBaseUpdate = capturedUpdate; } +var didReadFromEntangledAsyncAction = !1; +function suspendIfUpdateReadFromEntangledAsyncAction() { + if (didReadFromEntangledAsyncAction) { + var entangledActionThenable = currentEntangledActionThenable; + if (null !== entangledActionThenable) throw entangledActionThenable; + } +} function processUpdateQueue( workInProgress$jscomp$0, props, instance$jscomp$0, renderLanes ) { + didReadFromEntangledAsyncAction = !1; var queue = workInProgress$jscomp$0.updateQueue; hasForceUpdate = !1; var firstBaseUpdate = queue.firstBaseUpdate, @@ -924,6 +1202,9 @@ function processUpdateQueue( ? (workInProgressRootRenderLanes & updateLane) === updateLane : (renderLanes & updateLane) === updateLane ) { + 0 !== updateLane && + updateLane === currentEntangledLane && + (didReadFromEntangledAsyncAction = !0); null !== current && (current = current.next = { @@ -1907,379 +2188,91 @@ function createChildReconciler(shouldTrackSideEffects) { thenableIndexCounter$1 = 0; returnFiber = reconcileChildFibersImpl( returnFiber, - currentFirstChild, - newChild, - lanes - ); - thenableState$1 = null; - return returnFiber; - } - return reconcileChildFibers; -} -var reconcileChildFibers = createChildReconciler(!0), - mountChildFibers = createChildReconciler(!1), - currentTreeHiddenStackCursor = createCursor(null), - prevEntangledRenderLanesCursor = createCursor(0); -function pushHiddenContext(fiber, context) { - fiber = entangledRenderLanes; - push(prevEntangledRenderLanesCursor, fiber); - push(currentTreeHiddenStackCursor, context); - entangledRenderLanes = fiber | context.baseLanes; -} -function reuseHiddenContextOnStack() { - push(prevEntangledRenderLanesCursor, entangledRenderLanes); - push(currentTreeHiddenStackCursor, currentTreeHiddenStackCursor.current); -} -function popHiddenContext() { - entangledRenderLanes = prevEntangledRenderLanesCursor.current; - pop(currentTreeHiddenStackCursor); - pop(prevEntangledRenderLanesCursor); -} -var suspenseHandlerStackCursor = createCursor(null), - shellBoundary = null; -function pushPrimaryTreeSuspenseHandler(handler) { - var current = handler.alternate; - push(suspenseStackCursor, suspenseStackCursor.current & 1); - push(suspenseHandlerStackCursor, handler); - null === shellBoundary && - (null === current || null !== currentTreeHiddenStackCursor.current - ? (shellBoundary = handler) - : null !== current.memoizedState && (shellBoundary = handler)); -} -function pushOffscreenSuspenseHandler(fiber) { - if (22 === fiber.tag) { - if ( - (push(suspenseStackCursor, suspenseStackCursor.current), - push(suspenseHandlerStackCursor, fiber), - null === shellBoundary) - ) { - var current = fiber.alternate; - null !== current && - null !== current.memoizedState && - (shellBoundary = fiber); - } - } else reuseSuspenseHandlerOnStack(fiber); -} -function reuseSuspenseHandlerOnStack() { - push(suspenseStackCursor, suspenseStackCursor.current); - push(suspenseHandlerStackCursor, suspenseHandlerStackCursor.current); -} -function popSuspenseHandler(fiber) { - pop(suspenseHandlerStackCursor); - shellBoundary === fiber && (shellBoundary = null); - pop(suspenseStackCursor); -} -var suspenseStackCursor = createCursor(0); -function findFirstSuspended(row) { - for (var node = row; null !== node; ) { - if (13 === node.tag) { - var state = node.memoizedState; - if (null !== state && (null === state.dehydrated || shim$1() || shim$1())) - return node; - } else if (19 === node.tag && void 0 !== node.memoizedProps.revealOrder) { - if (0 !== (node.flags & 128)) return node; - } else if (null !== node.child) { - node.child.return = node; - node = node.child; - continue; - } - if (node === row) break; - for (; null === node.sibling; ) { - if (null === node.return || node.return === row) return null; - node = node.return; - } - node.sibling.return = node.return; - node = node.sibling; - } - return null; -} -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)); -} -function flushSyncWorkAcrossRoots_impl(onlyLegacy) { - if (!isFlushingWork && mightHavePendingSyncWork) { - var errors = null; - isFlushingWork = !0; - do { - var didPerformSomeWork = !1; - for (var root = firstScheduledRoot; null !== root; ) { - if (!onlyLegacy || 0 === root.tag) { - var workInProgressRootRenderLanes$24 = workInProgressRootRenderLanes, - nextLanes = getNextLanes( - root, - root === workInProgressRoot ? workInProgressRootRenderLanes$24 : 0 - ); - if (0 !== (nextLanes & 3)) - try { - didPerformSomeWork = !0; - workInProgressRootRenderLanes$24 = root; - if (0 !== (executionContext & 6)) - throw Error("Should not already be working."); - if (!flushPassiveEffects()) { - var exitStatus = renderRootSync( - workInProgressRootRenderLanes$24, - nextLanes - ); - if ( - 0 !== workInProgressRootRenderLanes$24.tag && - 2 === exitStatus - ) { - var originallyAttemptedLanes = nextLanes, - errorRetryLanes = getLanesToRetrySynchronouslyOnError( - workInProgressRootRenderLanes$24, - originallyAttemptedLanes - ); - 0 !== errorRetryLanes && - ((nextLanes = errorRetryLanes), - (exitStatus = recoverFromConcurrentError( - workInProgressRootRenderLanes$24, - originallyAttemptedLanes, - errorRetryLanes - ))); - } - if (1 === exitStatus) - throw ( - ((originallyAttemptedLanes = workInProgressRootFatalError), - prepareFreshStack(workInProgressRootRenderLanes$24, 0), - markRootSuspended( - workInProgressRootRenderLanes$24, - nextLanes, - 0 - ), - ensureRootIsScheduled(workInProgressRootRenderLanes$24), - originallyAttemptedLanes) - ); - 6 === exitStatus - ? markRootSuspended( - workInProgressRootRenderLanes$24, - nextLanes, - workInProgressDeferredLane - ) - : ((workInProgressRootRenderLanes$24.finishedWork = - workInProgressRootRenderLanes$24.current.alternate), - (workInProgressRootRenderLanes$24.finishedLanes = - nextLanes), - commitRoot( - workInProgressRootRenderLanes$24, - workInProgressRootRecoverableErrors, - workInProgressTransitions, - workInProgressDeferredLane - )); - } - ensureRootIsScheduled(workInProgressRootRenderLanes$24); - } 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++) - (didPerformSomeWork = throwError.bind(null, errors[onlyLegacy])), - scheduleCallback$3(ImmediatePriority, didPerformSomeWork); - } - 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 & -62914561; - 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 + currentFirstChild, + newChild, + lanes ); - 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 268435456: - suspendedLanes = IdlePriority; - break; - default: - suspendedLanes = NormalPriority$1; + thenableState$1 = null; + return returnFiber; } - pingedLanes = performConcurrentWorkOnRoot.bind(null, root); - suspendedLanes = scheduleCallback$3(suspendedLanes, pingedLanes); - root.callbackPriority = currentTime; - root.callbackNode = suspendedLanes; - return currentTime; + return reconcileChildFibers; } -function requestTransitionLane() { - if (0 === currentEventTransitionLane) { - var lane = nextTransitionLane; - nextTransitionLane <<= 1; - 0 === (nextTransitionLane & 4194176) && (nextTransitionLane = 128); - currentEventTransitionLane = lane; - } - return currentEventTransitionLane; +var reconcileChildFibers = createChildReconciler(!0), + mountChildFibers = createChildReconciler(!1), + currentTreeHiddenStackCursor = createCursor(null), + prevEntangledRenderLanesCursor = createCursor(0); +function pushHiddenContext(fiber, context) { + fiber = entangledRenderLanes; + push(prevEntangledRenderLanesCursor, fiber); + push(currentTreeHiddenStackCursor, context); + entangledRenderLanes = fiber | context.baseLanes; } -var currentEntangledListeners = null, - currentEntangledPendingCount = 0, - currentEntangledLane = 0; -function requestAsyncActionContext(actionReturnValue, overrideReturnValue) { - if (null === currentEntangledListeners) { - var entangledListeners = (currentEntangledListeners = []); - currentEntangledPendingCount = 0; - currentEntangledLane = requestTransitionLane(); - } else entangledListeners = currentEntangledListeners; - currentEntangledPendingCount++; - var resultThenable = createResultThenable(entangledListeners), - resultStatus = "pending", - resultValue, - rejectedReason; - actionReturnValue.then( - function (value) { - resultStatus = "fulfilled"; - resultValue = null !== overrideReturnValue ? overrideReturnValue : value; - pingEngtangledActionScope(); - }, - function (error) { - resultStatus = "rejected"; - rejectedReason = error; - pingEngtangledActionScope(); - } - ); - entangledListeners.push(function () { - switch (resultStatus) { - case "fulfilled": - resultThenable.status = "fulfilled"; - resultThenable.value = resultValue; - break; - case "rejected": - resultThenable.status = "rejected"; - resultThenable.reason = rejectedReason; - break; - default: - throw Error( - "Thenable should have already resolved. This is a bug in React." - ); +function reuseHiddenContextOnStack() { + push(prevEntangledRenderLanesCursor, entangledRenderLanes); + push(currentTreeHiddenStackCursor, currentTreeHiddenStackCursor.current); +} +function popHiddenContext() { + entangledRenderLanes = prevEntangledRenderLanesCursor.current; + pop(currentTreeHiddenStackCursor); + pop(prevEntangledRenderLanesCursor); +} +var suspenseHandlerStackCursor = createCursor(null), + shellBoundary = null; +function pushPrimaryTreeSuspenseHandler(handler) { + var current = handler.alternate; + push(suspenseStackCursor, suspenseStackCursor.current & 1); + push(suspenseHandlerStackCursor, handler); + null === shellBoundary && + (null === current || null !== currentTreeHiddenStackCursor.current + ? (shellBoundary = handler) + : null !== current.memoizedState && (shellBoundary = handler)); +} +function pushOffscreenSuspenseHandler(fiber) { + if (22 === fiber.tag) { + if ( + (push(suspenseStackCursor, suspenseStackCursor.current), + push(suspenseHandlerStackCursor, fiber), + null === shellBoundary) + ) { + var current = fiber.alternate; + null !== current && + null !== current.memoizedState && + (shellBoundary = fiber); } - }); - return resultThenable; -} -function requestSyncActionContext(actionReturnValue, overrideReturnValue) { - var resultValue = - null !== overrideReturnValue ? overrideReturnValue : actionReturnValue; - if (null === currentEntangledListeners) return resultValue; - actionReturnValue = currentEntangledListeners; - var resultThenable = createResultThenable(actionReturnValue); - actionReturnValue.push(function () { - resultThenable.status = "fulfilled"; - resultThenable.value = resultValue; - }); - return resultThenable; + } else reuseSuspenseHandlerOnStack(fiber); } -function pingEngtangledActionScope() { - if ( - null !== currentEntangledListeners && - 0 === --currentEntangledPendingCount - ) { - var listeners = currentEntangledListeners; - currentEntangledListeners = null; - for (var i = (currentEntangledLane = 0); i < listeners.length; i++) - (0, listeners[i])(); - } +function reuseSuspenseHandlerOnStack() { + push(suspenseStackCursor, suspenseStackCursor.current); + push(suspenseHandlerStackCursor, suspenseHandlerStackCursor.current); } -function createResultThenable(entangledListeners) { - return { - status: "pending", - value: null, - reason: null, - then: function (resolve) { - entangledListeners.push(resolve); +function popSuspenseHandler(fiber) { + pop(suspenseHandlerStackCursor); + shellBoundary === fiber && (shellBoundary = null); + pop(suspenseStackCursor); +} +var suspenseStackCursor = createCursor(0); +function findFirstSuspended(row) { + for (var node = row; null !== node; ) { + if (13 === node.tag) { + var state = node.memoizedState; + if (null !== state && (null === state.dehydrated || shim$1() || shim$1())) + return node; + } else if (19 === node.tag && void 0 !== node.memoizedProps.revealOrder) { + if (0 !== (node.flags & 128)) return node; + } else if (null !== node.child) { + node.child.return = node; + node = node.child; + continue; } - }; + if (node === row) break; + for (; null === node.sibling; ) { + if (null === node.return || node.return === row) return null; + node = node.return; + } + node.sibling.return = node.return; + node = node.sibling; + } + return null; } var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, ReactCurrentBatchConfig$2 = ReactSharedInternals.ReactCurrentBatchConfig, @@ -2537,7 +2530,8 @@ function updateReducerImpl(hook, current, reducer) { current = baseQueue.next; var newBaseQueueFirst = (baseFirst = null), newBaseQueueLast = null, - update = current; + update = current, + didReadFromEntangledAsyncAction$26 = !1; do { var updateLane = update.lane & -536870913; if ( @@ -2545,6 +2539,9 @@ function updateReducerImpl(hook, current, reducer) { ? (workInProgressRootRenderLanes & updateLane) === updateLane : (renderLanes & updateLane) === updateLane ) { + 0 !== updateLane && + updateLane === currentEntangledLane && + (didReadFromEntangledAsyncAction$26 = !0); updateLane = update.revertLane; if (0 === updateLane) null !== newBaseQueueLast && @@ -2561,7 +2558,7 @@ function updateReducerImpl(hook, current, reducer) { update = update.next; continue; } else { - var clone$27 = { + var clone$28 = { lane: 0, revertLane: update.revertLane, action: update.action, @@ -2570,9 +2567,9 @@ function updateReducerImpl(hook, current, reducer) { next: null }; null === newBaseQueueLast - ? ((newBaseQueueFirst = newBaseQueueLast = clone$27), + ? ((newBaseQueueFirst = newBaseQueueLast = clone$28), (baseFirst = pendingQueue)) - : (newBaseQueueLast = newBaseQueueLast.next = clone$27); + : (newBaseQueueLast = newBaseQueueLast.next = clone$28); currentlyRenderingFiber$1.lanes |= updateLane; workInProgressRootSkippedLanes |= updateLane; } @@ -2583,7 +2580,7 @@ function updateReducerImpl(hook, current, reducer) { ? update.eagerState : reducer(pendingQueue, updateLane); } else - (clone$27 = { + (clone$28 = { lane: updateLane, revertLane: update.revertLane, action: update.action, @@ -2592,9 +2589,9 @@ function updateReducerImpl(hook, current, reducer) { next: null }), null === newBaseQueueLast - ? ((newBaseQueueFirst = newBaseQueueLast = clone$27), + ? ((newBaseQueueFirst = newBaseQueueLast = clone$28), (baseFirst = pendingQueue)) - : (newBaseQueueLast = newBaseQueueLast.next = clone$27), + : (newBaseQueueLast = newBaseQueueLast.next = clone$28), (currentlyRenderingFiber$1.lanes |= updateLane), (workInProgressRootSkippedLanes |= updateLane); update = update.next; @@ -2602,7 +2599,13 @@ function updateReducerImpl(hook, current, reducer) { null === newBaseQueueLast ? (baseFirst = pendingQueue) : (newBaseQueueLast.next = newBaseQueueFirst); - objectIs(pendingQueue, hook.memoizedState) || (didReceiveUpdate = !0); + if ( + !objectIs(pendingQueue, hook.memoizedState) && + ((didReceiveUpdate = !0), + didReadFromEntangledAsyncAction$26 && + ((reducer = currentEntangledActionThenable), null !== reducer)) + ) + throw reducer; hook.memoizedState = pendingQueue; hook.baseState = baseFirst; hook.baseQueue = newBaseQueueLast; @@ -2746,28 +2749,23 @@ function runFormStateAction(actionQueue, setState, payload) { ReactCurrentBatchConfig$2.transition = {}; try { var returnValue = action(prevState, payload); - if ( - null !== returnValue && - "object" === typeof returnValue && - "function" === typeof returnValue.then - ) { - returnValue.then( - function (nextState) { - actionQueue.state = nextState; - finishRunningFormStateAction(actionQueue, setState); - }, - function () { - return finishRunningFormStateAction(actionQueue, setState); - } - ); - var entangledResult = requestAsyncActionContext(returnValue, null); - setState(entangledResult); - } else { - var entangledResult$29 = requestSyncActionContext(returnValue, null); - setState(entangledResult$29); - actionQueue.state = returnValue; - finishRunningFormStateAction(actionQueue, setState); - } + null !== returnValue && + "object" === typeof returnValue && + "function" === typeof returnValue.then + ? (returnValue.then( + function (nextState) { + actionQueue.state = nextState; + finishRunningFormStateAction(actionQueue, setState); + }, + function () { + return finishRunningFormStateAction(actionQueue, setState); + } + ), + entangleAsyncAction(returnValue), + setState(returnValue)) + : (setState(returnValue), + (actionQueue.state = returnValue), + finishRunningFormStateAction(actionQueue, setState)); } catch (error) { setState({ then: function () {}, status: "rejected", reason: error }), finishRunningFormStateAction(actionQueue, setState); @@ -2948,18 +2946,13 @@ function startTransition(fiber, queue, pendingState, finishedState, callback) { "object" === typeof returnValue && "function" === typeof returnValue.then ) { - var entangledResult = requestAsyncActionContext( - returnValue, - finishedState - ); - dispatchSetState(fiber, queue, entangledResult); - } else { - var entangledResult$31 = requestSyncActionContext( + entangleAsyncAction(returnValue); + var thenableForFinishedState = chainThenableValue( returnValue, finishedState ); - dispatchSetState(fiber, queue, entangledResult$31); - } + dispatchSetState(fiber, queue, thenableForFinishedState); + } else dispatchSetState(fiber, queue, finishedState); } catch (error) { dispatchSetState(fiber, queue, { then: function () {}, @@ -3560,6 +3553,7 @@ function mountClassInstance(workInProgress, ctor, newProps, renderLanes) { ctor !== instance.state && classComponentUpdater.enqueueReplaceState(instance, instance.state, null), processUpdateQueue(workInProgress, newProps, instance, renderLanes), + suspendIfUpdateReadFromEntangledAsyncAction(), (instance.state = workInProgress.memoizedState)); "function" === typeof instance.componentDidMount && (workInProgress.flags |= 4194308); @@ -3631,6 +3625,153 @@ function createClassErrorUpdate(fiber, errorInfo, lane) { }); return lane; } +function throwException( + root, + returnFiber, + sourceFiber, + value, + rootRenderLanes +) { + sourceFiber.flags |= 32768; + if ( + null !== value && + "object" === typeof value && + "function" === typeof value.then + ) { + var tag = sourceFiber.tag; + 0 !== (sourceFiber.mode & 1) || + (0 !== tag && 11 !== tag && 15 !== tag) || + ((tag = sourceFiber.alternate) + ? ((sourceFiber.updateQueue = tag.updateQueue), + (sourceFiber.memoizedState = tag.memoizedState), + (sourceFiber.lanes = tag.lanes)) + : ((sourceFiber.updateQueue = null), + (sourceFiber.memoizedState = null))); + tag = suspenseHandlerStackCursor.current; + if (null !== tag) { + switch (tag.tag) { + case 13: + return ( + sourceFiber.mode & 1 && + (null === shellBoundary + ? renderDidSuspendDelayIfPossible() + : null === tag.alternate && + 0 === workInProgressRootExitStatus && + (workInProgressRootExitStatus = 3)), + (tag.flags &= -257), + 0 === (tag.mode & 1) + ? tag === returnFiber + ? (tag.flags |= 65536) + : ((tag.flags |= 128), + (sourceFiber.flags |= 131072), + (sourceFiber.flags &= -52805), + 1 === sourceFiber.tag && + (null === sourceFiber.alternate + ? (sourceFiber.tag = 17) + : ((returnFiber = createUpdate(2)), + (returnFiber.tag = 2), + enqueueUpdate(sourceFiber, returnFiber, 2))), + (sourceFiber.lanes |= 2)) + : ((tag.flags |= 65536), (tag.lanes = rootRenderLanes)), + value === noopSuspenseyCommitThenable + ? (tag.flags |= 16384) + : ((returnFiber = tag.updateQueue), + null === returnFiber + ? (tag.updateQueue = new Set([value])) + : returnFiber.add(value), + tag.mode & 1 && + attachPingListener(root, value, rootRenderLanes)), + !1 + ); + case 22: + if (tag.mode & 1) + return ( + (tag.flags |= 65536), + value === noopSuspenseyCommitThenable + ? (tag.flags |= 16384) + : ((returnFiber = tag.updateQueue), + null === returnFiber + ? ((returnFiber = { + transitions: null, + markerInstances: null, + retryQueue: new Set([value]) + }), + (tag.updateQueue = returnFiber)) + : ((sourceFiber = returnFiber.retryQueue), + null === sourceFiber + ? (returnFiber.retryQueue = new Set([value])) + : sourceFiber.add(value)), + attachPingListener(root, value, rootRenderLanes)), + !1 + ); + } + throw Error( + "Unexpected Suspense handler tag (" + + tag.tag + + "). This is a bug in React." + ); + } + if (1 === root.tag) + return ( + attachPingListener(root, value, rootRenderLanes), + renderDidSuspendDelayIfPossible(), + !1 + ); + value = Error( + "A component suspended while responding to synchronous input. This will cause the UI to be replaced with a loading indicator. To fix, updates that suspend should be wrapped with startTransition." + ); + } + root = value = createCapturedValueAtFiber(value, sourceFiber); + 4 !== workInProgressRootExitStatus && (workInProgressRootExitStatus = 2); + null === workInProgressRootConcurrentErrors + ? (workInProgressRootConcurrentErrors = [root]) + : workInProgressRootConcurrentErrors.push(root); + if (null === returnFiber) return !0; + root = returnFiber; + do { + switch (root.tag) { + case 3: + return ( + (root.flags |= 65536), + (rootRenderLanes &= -rootRenderLanes), + (root.lanes |= rootRenderLanes), + (rootRenderLanes = createRootErrorUpdate( + root, + value, + rootRenderLanes + )), + enqueueCapturedUpdate(root, rootRenderLanes), + !1 + ); + case 1: + if ( + ((returnFiber = value), + (sourceFiber = root.type), + (tag = root.stateNode), + 0 === (root.flags & 128) && + ("function" === typeof sourceFiber.getDerivedStateFromError || + (null !== tag && + "function" === typeof tag.componentDidCatch && + (null === legacyErrorBoundariesThatAlreadyFailed || + !legacyErrorBoundariesThatAlreadyFailed.has(tag))))) + ) + return ( + (root.flags |= 65536), + (rootRenderLanes &= -rootRenderLanes), + (root.lanes |= rootRenderLanes), + (rootRenderLanes = createClassErrorUpdate( + root, + returnFiber, + rootRenderLanes + )), + enqueueCapturedUpdate(root, rootRenderLanes), + !1 + ); + } + root = root.return; + } while (null !== root); + return !1; +} var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner, SelectiveHydrationException = Error( "This is not a real error. It's an implementation detail of React's selective hydration feature. If this leaks into userspace, it's a bug in React. Please file an issue." @@ -3946,6 +4087,7 @@ function updateClassComponent( var oldState = workInProgress.memoizedState; instance.state = oldState; processUpdateQueue(workInProgress, nextProps, instance, renderLanes); + suspendIfUpdateReadFromEntangledAsyncAction(); oldContext = workInProgress.memoizedState; oldProps !== nextProps || oldState !== oldContext || @@ -4025,6 +4167,7 @@ function updateClassComponent( oldState = workInProgress.memoizedState; instance.state = oldState; processUpdateQueue(workInProgress, nextProps, instance, renderLanes); + suspendIfUpdateReadFromEntangledAsyncAction(); var newState = workInProgress.memoizedState; oldProps !== hasNewLifecycles || oldState !== newState || @@ -4948,14 +5091,14 @@ function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { break; case "collapsed": lastTailNode = renderState.tail; - for (var lastTailNode$63 = null; null !== lastTailNode; ) - null !== lastTailNode.alternate && (lastTailNode$63 = lastTailNode), + for (var lastTailNode$62 = null; null !== lastTailNode; ) + null !== lastTailNode.alternate && (lastTailNode$62 = lastTailNode), (lastTailNode = lastTailNode.sibling); - null === lastTailNode$63 + null === lastTailNode$62 ? hasRenderedATailFallback || null === renderState.tail ? (renderState.tail = null) : (renderState.tail.sibling = null) - : (lastTailNode$63.sibling = null); + : (lastTailNode$62.sibling = null); } } function bubbleProperties(completedWork) { @@ -4965,19 +5108,19 @@ function bubbleProperties(completedWork) { newChildLanes = 0, subtreeFlags = 0; if (didBailout) - for (var child$64 = completedWork.child; null !== child$64; ) - (newChildLanes |= child$64.lanes | child$64.childLanes), - (subtreeFlags |= child$64.subtreeFlags & 31457280), - (subtreeFlags |= child$64.flags & 31457280), - (child$64.return = completedWork), - (child$64 = child$64.sibling); + for (var child$63 = completedWork.child; null !== child$63; ) + (newChildLanes |= child$63.lanes | child$63.childLanes), + (subtreeFlags |= child$63.subtreeFlags & 31457280), + (subtreeFlags |= child$63.flags & 31457280), + (child$63.return = completedWork), + (child$63 = child$63.sibling); else - for (child$64 = completedWork.child; null !== child$64; ) - (newChildLanes |= child$64.lanes | child$64.childLanes), - (subtreeFlags |= child$64.subtreeFlags), - (subtreeFlags |= child$64.flags), - (child$64.return = completedWork), - (child$64 = child$64.sibling); + for (child$63 = completedWork.child; null !== child$63; ) + (newChildLanes |= child$63.lanes | child$63.childLanes), + (subtreeFlags |= child$63.subtreeFlags), + (subtreeFlags |= child$63.flags), + (child$63.return = completedWork), + (child$63 = child$63.sibling); completedWork.subtreeFlags |= subtreeFlags; completedWork.childLanes = newChildLanes; return didBailout; @@ -5138,11 +5281,11 @@ function completeWork(current, workInProgress, renderLanes) { null !== newProps.alternate.memoizedState && null !== newProps.alternate.memoizedState.cachePool && (index = newProps.alternate.memoizedState.cachePool.pool); - var cache$68 = null; + var cache$67 = null; null !== newProps.memoizedState && null !== newProps.memoizedState.cachePool && - (cache$68 = newProps.memoizedState.cachePool.pool); - cache$68 !== index && (newProps.flags |= 2048); + (cache$67 = newProps.memoizedState.cachePool.pool); + cache$67 !== index && (newProps.flags |= 2048); } renderLanes !== current && renderLanes && @@ -5169,8 +5312,8 @@ function completeWork(current, workInProgress, renderLanes) { index = workInProgress.memoizedState; if (null === index) return bubbleProperties(workInProgress), null; newProps = 0 !== (workInProgress.flags & 128); - cache$68 = index.rendering; - if (null === cache$68) + cache$67 = index.rendering; + if (null === cache$67) if (newProps) cutOffTailIfNeeded(index, !1); else { if ( @@ -5178,11 +5321,11 @@ function completeWork(current, workInProgress, renderLanes) { (null !== current && 0 !== (current.flags & 128)) ) for (current = workInProgress.child; null !== current; ) { - cache$68 = findFirstSuspended(current); - if (null !== cache$68) { + cache$67 = findFirstSuspended(current); + if (null !== cache$67) { workInProgress.flags |= 128; cutOffTailIfNeeded(index, !1); - current = cache$68.updateQueue; + current = cache$67.updateQueue; workInProgress.updateQueue = current; scheduleRetryEffect(workInProgress, current); workInProgress.subtreeFlags = 0; @@ -5207,7 +5350,7 @@ function completeWork(current, workInProgress, renderLanes) { } else { if (!newProps) - if (((current = findFirstSuspended(cache$68)), null !== current)) { + if (((current = findFirstSuspended(cache$67)), null !== current)) { if ( ((workInProgress.flags |= 128), (newProps = !0), @@ -5217,7 +5360,7 @@ function completeWork(current, workInProgress, renderLanes) { cutOffTailIfNeeded(index, !0), null === index.tail && "hidden" === index.tailMode && - !cache$68.alternate) + !cache$67.alternate) ) return bubbleProperties(workInProgress), null; } else @@ -5229,13 +5372,13 @@ function completeWork(current, workInProgress, renderLanes) { cutOffTailIfNeeded(index, !1), (workInProgress.lanes = 4194304)); index.isBackwards - ? ((cache$68.sibling = workInProgress.child), - (workInProgress.child = cache$68)) + ? ((cache$67.sibling = workInProgress.child), + (workInProgress.child = cache$67)) : ((current = index.last), null !== current - ? (current.sibling = cache$68) - : (workInProgress.child = cache$68), - (index.last = cache$68)); + ? (current.sibling = cache$67) + : (workInProgress.child = cache$67), + (index.last = cache$67)); } if (null !== index.tail) return ( @@ -5448,8 +5591,8 @@ function safelyDetachRef(current, nearestMountedAncestor) { else if ("function" === typeof ref) try { ref(null); - } catch (error$84) { - captureCommitPhaseError(current, nearestMountedAncestor, error$84); + } catch (error$83) { + captureCommitPhaseError(current, nearestMountedAncestor, error$83); } else ref.current = null; } @@ -5555,10 +5698,10 @@ function commitHookEffectListMount(flags, finishedWork) { var effect = (finishedWork = finishedWork.next); do { if ((effect.tag & flags) === flags) { - var create$85 = effect.create, + var create$84 = effect.create, inst = effect.inst; - create$85 = create$85(); - inst.destroy = create$85; + create$84 = create$84(); + inst.destroy = create$84; } effect = effect.next; } while (effect !== finishedWork); @@ -5612,11 +5755,11 @@ function commitLayoutEffectOnFiber(finishedRoot, current, finishedWork) { current, finishedRoot.__reactInternalSnapshotBeforeUpdate ); - } catch (error$86) { + } catch (error$85) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$86 + error$85 ); } } @@ -5993,8 +6136,8 @@ function commitMutationEffectsOnFiber(finishedWork, root) { } try { commitHookEffectListUnmount(5, finishedWork, finishedWork.return); - } catch (error$94) { - captureCommitPhaseError(finishedWork, finishedWork.return, error$94); + } catch (error$93) { + captureCommitPhaseError(finishedWork, finishedWork.return, error$93); } } break; @@ -6032,8 +6175,8 @@ function commitMutationEffectsOnFiber(finishedWork, root) { finishedWork.updateQueue = null; try { (flags.type = type), (flags.props = existingHiddenCallbacks); - } catch (error$97) { - captureCommitPhaseError(finishedWork, finishedWork.return, error$97); + } catch (error$96) { + captureCommitPhaseError(finishedWork, finishedWork.return, error$96); } } break; @@ -6049,8 +6192,8 @@ function commitMutationEffectsOnFiber(finishedWork, root) { existingHiddenCallbacks = finishedWork.memoizedProps; try { flags.text = existingHiddenCallbacks; - } catch (error$98) { - captureCommitPhaseError(finishedWork, finishedWork.return, error$98); + } catch (error$97) { + captureCommitPhaseError(finishedWork, finishedWork.return, error$97); } } break; @@ -6134,11 +6277,11 @@ function commitMutationEffectsOnFiber(finishedWork, root) { wasHidden.stateNode.isHidden = existingHiddenCallbacks ? !0 : !1; - } catch (error$88) { + } catch (error$87) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$88 + error$87 ); } } else if ( @@ -6216,12 +6359,12 @@ function commitReconciliationEffects(finishedWork) { break; case 3: case 4: - var parent$89 = JSCompiler_inline_result.stateNode.containerInfo, - before$90 = getHostSibling(finishedWork); + var parent$88 = JSCompiler_inline_result.stateNode.containerInfo, + before$89 = getHostSibling(finishedWork); insertOrAppendPlacementNodeIntoContainer( finishedWork, - before$90, - parent$89 + before$89, + parent$88 ); break; default: @@ -7290,13 +7433,13 @@ function renderRootSync(root, lanes) { default: (workInProgressSuspendedReason = 0), (workInProgressThrownValue = null), - throwAndUnwindWorkLoop(unitOfWork, thrownValue); + throwAndUnwindWorkLoop(root, unitOfWork, thrownValue); } } workLoopSync(); break; - } catch (thrownValue$106) { - handleThrow(root, thrownValue$106); + } catch (thrownValue$105) { + handleThrow(root, thrownValue$105); } while (1); lanes && root.shellSuspendCounter++; @@ -7334,7 +7477,7 @@ function renderRootConcurrent(root, lanes) { case 1: workInProgressSuspendedReason = 0; workInProgressThrownValue = null; - throwAndUnwindWorkLoop(lanes, thrownValue); + throwAndUnwindWorkLoop(root, lanes, thrownValue); break; case 2: if (isThenableResolved(thrownValue)) { @@ -7364,7 +7507,7 @@ function renderRootConcurrent(root, lanes) { replaySuspendedUnitOfWork(lanes)) : ((workInProgressSuspendedReason = 0), (workInProgressThrownValue = null), - throwAndUnwindWorkLoop(lanes, thrownValue)); + throwAndUnwindWorkLoop(root, lanes, thrownValue)); break; case 5: switch (workInProgress.tag) { @@ -7387,12 +7530,12 @@ function renderRootConcurrent(root, lanes) { } workInProgressSuspendedReason = 0; workInProgressThrownValue = null; - throwAndUnwindWorkLoop(lanes, thrownValue); + throwAndUnwindWorkLoop(root, lanes, thrownValue); break; case 6: workInProgressSuspendedReason = 0; workInProgressThrownValue = null; - throwAndUnwindWorkLoop(lanes, thrownValue); + throwAndUnwindWorkLoop(root, lanes, thrownValue); break; case 8: resetWorkInProgressStack(); @@ -7404,8 +7547,8 @@ function renderRootConcurrent(root, lanes) { } workLoopConcurrent(); break; - } catch (thrownValue$108) { - handleThrow(root, thrownValue$108); + } catch (thrownValue$107) { + handleThrow(root, thrownValue$107); } while (1); resetContextDependencies(); @@ -7484,191 +7627,55 @@ function replaySuspendedUnitOfWork(unitOfWork) { : (workInProgress = current); ReactCurrentOwner.current = null; } -function throwAndUnwindWorkLoop(unitOfWork, thrownValue) { +function throwAndUnwindWorkLoop(root, unitOfWork, thrownValue) { resetContextDependencies(); resetHooksOnUnwind(unitOfWork); thenableState$1 = null; thenableIndexCounter$1 = 0; var returnFiber = unitOfWork.return; - if (null === returnFiber || null === workInProgressRoot) - (workInProgressRootExitStatus = 1), - (workInProgressRootFatalError = thrownValue), - (workInProgress = null); - else { - try { - a: { - var root = workInProgressRoot, - value = thrownValue; - thrownValue = workInProgressRootRenderLanes; - unitOfWork.flags |= 32768; - if ( - null !== value && - "object" === typeof value && - "function" === typeof value.then - ) { - var wakeable = value, - tag = unitOfWork.tag; - if ( - 0 === (unitOfWork.mode & 1) && - (0 === tag || 11 === tag || 15 === tag) - ) { - var currentSource = unitOfWork.alternate; - currentSource - ? ((unitOfWork.updateQueue = currentSource.updateQueue), - (unitOfWork.memoizedState = currentSource.memoizedState), - (unitOfWork.lanes = currentSource.lanes)) - : ((unitOfWork.updateQueue = null), - (unitOfWork.memoizedState = null)); - } - var suspenseBoundary = suspenseHandlerStackCursor.current; - if (null !== suspenseBoundary) { - switch (suspenseBoundary.tag) { - case 13: - unitOfWork.mode & 1 && - (null === shellBoundary - ? renderDidSuspendDelayIfPossible() - : null === suspenseBoundary.alternate && - 0 === workInProgressRootExitStatus && - (workInProgressRootExitStatus = 3)); - suspenseBoundary.flags &= -257; - if (0 === (suspenseBoundary.mode & 1)) - if (suspenseBoundary === returnFiber) - suspenseBoundary.flags |= 65536; - else { - suspenseBoundary.flags |= 128; - unitOfWork.flags |= 131072; - unitOfWork.flags &= -52805; - if (1 === unitOfWork.tag) - if (null === unitOfWork.alternate) unitOfWork.tag = 17; - else { - var update = createUpdate(2); - update.tag = 2; - enqueueUpdate(unitOfWork, update, 2); - } - unitOfWork.lanes |= 2; - } - else - (suspenseBoundary.flags |= 65536), - (suspenseBoundary.lanes = thrownValue); - if (wakeable === noopSuspenseyCommitThenable) - suspenseBoundary.flags |= 16384; - else { - var retryQueue = suspenseBoundary.updateQueue; - null === retryQueue - ? (suspenseBoundary.updateQueue = new Set([wakeable])) - : retryQueue.add(wakeable); - suspenseBoundary.mode & 1 && - attachPingListener(root, wakeable, thrownValue); - } - break a; - case 22: - if (suspenseBoundary.mode & 1) { - suspenseBoundary.flags |= 65536; - if (wakeable === noopSuspenseyCommitThenable) - suspenseBoundary.flags |= 16384; - else { - var offscreenQueue = suspenseBoundary.updateQueue; - if (null === offscreenQueue) { - var newOffscreenQueue = { - transitions: null, - markerInstances: null, - retryQueue: new Set([wakeable]) - }; - suspenseBoundary.updateQueue = newOffscreenQueue; - } else { - var retryQueue$33 = offscreenQueue.retryQueue; - null === retryQueue$33 - ? (offscreenQueue.retryQueue = new Set([wakeable])) - : retryQueue$33.add(wakeable); - } - attachPingListener(root, wakeable, thrownValue); - } - break a; - } - } - throw Error( - "Unexpected Suspense handler tag (" + - suspenseBoundary.tag + - "). This is a bug in React." - ); - } - if (1 === root.tag) { - attachPingListener(root, wakeable, thrownValue); - renderDidSuspendDelayIfPossible(); - break a; - } else - value = Error( - "A component suspended while responding to synchronous input. This will cause the UI to be replaced with a loading indicator. To fix, updates that suspend should be wrapped with startTransition." - ); - } - root = value = createCapturedValueAtFiber(value, unitOfWork); - 4 !== workInProgressRootExitStatus && - (workInProgressRootExitStatus = 2); - null === workInProgressRootConcurrentErrors - ? (workInProgressRootConcurrentErrors = [root]) - : workInProgressRootConcurrentErrors.push(root); - root = returnFiber; - do { - switch (root.tag) { - case 3: - var errorInfo = value; - root.flags |= 65536; - thrownValue &= -thrownValue; - root.lanes |= thrownValue; - var update$jscomp$0 = createRootErrorUpdate( - root, - errorInfo, - thrownValue - ); - enqueueCapturedUpdate(root, update$jscomp$0); - break a; - case 1: - tag = value; - var ctor = root.type, - instance = root.stateNode; - if ( - 0 === (root.flags & 128) && - ("function" === typeof ctor.getDerivedStateFromError || - (null !== instance && - "function" === typeof instance.componentDidCatch && - (null === legacyErrorBoundariesThatAlreadyFailed || - !legacyErrorBoundariesThatAlreadyFailed.has(instance)))) - ) { - root.flags |= 65536; - update$jscomp$0 = thrownValue & -thrownValue; - root.lanes |= update$jscomp$0; - errorInfo = createClassErrorUpdate(root, tag, update$jscomp$0); - enqueueCapturedUpdate(root, errorInfo); - break a; - } - } - root = root.return; - } while (null !== root); - } - } catch (error) { - throw ((workInProgress = returnFiber), error); + try { + if ( + throwException( + root, + returnFiber, + unitOfWork, + thrownValue, + workInProgressRootRenderLanes + ) + ) { + workInProgressRootExitStatus = 1; + workInProgressRootFatalError = thrownValue; + workInProgress = null; + return; } - 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); + } catch (error) { + if (null !== returnFiber) throw ((workInProgress = returnFiber), error); + workInProgressRootExitStatus = 1; + workInProgressRootFatalError = thrownValue; + workInProgress = null; + return; } + if (unitOfWork.flags & 32768) + a: { + root = unitOfWork; + do { + unitOfWork = unwindWork(root.alternate, root); + if (null !== unitOfWork) { + unitOfWork.flags &= 32767; + workInProgress = unitOfWork; + break a; + } + root = root.return; + null !== root && + ((root.flags |= 32768), + (root.subtreeFlags = 0), + (root.deletions = null)); + workInProgress = root; + } while (null !== root); + workInProgressRootExitStatus = 6; + workInProgress = null; + } + else completeUnitOfWork(unitOfWork); } function completeUnitOfWork(unitOfWork) { var completedWork = unitOfWork; @@ -8161,6 +8168,7 @@ beginWork = function (current, workInProgress, renderLanes) { pushProvider(workInProgress, CacheContext, nextCache); nextCache !== context.cache && propagateContextChange(workInProgress, CacheContext, renderLanes); + suspendIfUpdateReadFromEntangledAsyncAction(); context = hasContext.element; context === Component ? (workInProgress = bailoutOnAlreadyFinishedWork( @@ -8378,7 +8386,8 @@ beginWork = function (current, workInProgress, renderLanes) { pushProvider(workInProgress, CacheContext, context)) : (0 !== (current.lanes & renderLanes) && (cloneUpdateQueue(current, workInProgress), - processUpdateQueue(workInProgress, null, null, renderLanes)), + processUpdateQueue(workInProgress, null, null, renderLanes), + suspendIfUpdateReadFromEntangledAsyncAction()), (context = current.memoizedState), (hasContext = workInProgress.memoizedState), context.parent !== Component @@ -9117,19 +9126,19 @@ function wrapFiber(fiber) { fiberToWrapper.set(fiber, wrapper)); return wrapper; } -var devToolsConfig$jscomp$inline_1037 = { +var devToolsConfig$jscomp$inline_1031 = { findFiberByHostInstance: function () { throw Error("TestRenderer does not support findFiberByHostInstance()"); }, bundleType: 0, - version: "18.3.0-canary-2efb14260-20240124", + version: "18.3.0-canary-11c9fd0c5-20240124", rendererPackageName: "react-test-renderer" }; -var internals$jscomp$inline_1230 = { - bundleType: devToolsConfig$jscomp$inline_1037.bundleType, - version: devToolsConfig$jscomp$inline_1037.version, - rendererPackageName: devToolsConfig$jscomp$inline_1037.rendererPackageName, - rendererConfig: devToolsConfig$jscomp$inline_1037.rendererConfig, +var internals$jscomp$inline_1207 = { + bundleType: devToolsConfig$jscomp$inline_1031.bundleType, + version: devToolsConfig$jscomp$inline_1031.version, + rendererPackageName: devToolsConfig$jscomp$inline_1031.rendererPackageName, + rendererConfig: devToolsConfig$jscomp$inline_1031.rendererConfig, overrideHookState: null, overrideHookStateDeletePath: null, overrideHookStateRenamePath: null, @@ -9146,26 +9155,26 @@ var internals$jscomp$inline_1230 = { return null === fiber ? null : fiber.stateNode; }, findFiberByHostInstance: - devToolsConfig$jscomp$inline_1037.findFiberByHostInstance || + devToolsConfig$jscomp$inline_1031.findFiberByHostInstance || emptyFindFiberByHostInstance, findHostInstancesForRefresh: null, scheduleRefresh: null, scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "18.3.0-canary-2efb14260-20240124" + reconcilerVersion: "18.3.0-canary-11c9fd0c5-20240124" }; if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { - var hook$jscomp$inline_1231 = __REACT_DEVTOOLS_GLOBAL_HOOK__; + var hook$jscomp$inline_1208 = __REACT_DEVTOOLS_GLOBAL_HOOK__; if ( - !hook$jscomp$inline_1231.isDisabled && - hook$jscomp$inline_1231.supportsFiber + !hook$jscomp$inline_1208.isDisabled && + hook$jscomp$inline_1208.supportsFiber ) try { - (rendererID = hook$jscomp$inline_1231.inject( - internals$jscomp$inline_1230 + (rendererID = hook$jscomp$inline_1208.inject( + internals$jscomp$inline_1207 )), - (injectedHook = hook$jscomp$inline_1231); + (injectedHook = hook$jscomp$inline_1208); } catch (err) {} } exports._Scheduler = Scheduler; diff --git a/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react-test-renderer/cjs/ReactTestRenderer-profiling.js b/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react-test-renderer/cjs/ReactTestRenderer-profiling.js index 6f69e920e56ad..481ce28566fd8 100644 --- a/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react-test-renderer/cjs/ReactTestRenderer-profiling.js +++ b/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react-test-renderer/cjs/ReactTestRenderer-profiling.js @@ -7,7 +7,7 @@ * @noflow * @nolint * @preventMunge - * @generated SignedSource<> + * @generated SignedSource<> */ "use strict"; @@ -804,6 +804,278 @@ function getRootForUpdatedFiber(sourceFiber) { (sourceFiber = parent), (parent = sourceFiber.return); return 3 === sourceFiber.tag ? sourceFiber.stateNode : null; } +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)); +} +function flushSyncWorkAcrossRoots_impl(onlyLegacy) { + if (!isFlushingWork && mightHavePendingSyncWork) { + var errors = null; + isFlushingWork = !0; + do { + var didPerformSomeWork = !1; + for (var root = firstScheduledRoot; null !== root; ) { + if (!onlyLegacy || 0 === root.tag) { + var workInProgressRootRenderLanes$7 = workInProgressRootRenderLanes, + nextLanes = getNextLanes( + root, + root === workInProgressRoot ? workInProgressRootRenderLanes$7 : 0 + ); + if (0 !== (nextLanes & 3)) + try { + didPerformSomeWork = !0; + workInProgressRootRenderLanes$7 = root; + if (0 !== (executionContext & 6)) + throw Error("Should not already be working."); + if (!flushPassiveEffects()) { + currentUpdateIsNested = nestedUpdateScheduled; + nestedUpdateScheduled = !1; + var exitStatus = renderRootSync( + workInProgressRootRenderLanes$7, + nextLanes + ); + if ( + 0 !== workInProgressRootRenderLanes$7.tag && + 2 === exitStatus + ) { + var originallyAttemptedLanes = nextLanes, + errorRetryLanes = getLanesToRetrySynchronouslyOnError( + workInProgressRootRenderLanes$7, + originallyAttemptedLanes + ); + 0 !== errorRetryLanes && + ((nextLanes = errorRetryLanes), + (exitStatus = recoverFromConcurrentError( + workInProgressRootRenderLanes$7, + originallyAttemptedLanes, + errorRetryLanes + ))); + } + if (1 === exitStatus) + throw ( + ((originallyAttemptedLanes = workInProgressRootFatalError), + prepareFreshStack(workInProgressRootRenderLanes$7, 0), + markRootSuspended( + workInProgressRootRenderLanes$7, + nextLanes, + 0 + ), + ensureRootIsScheduled(workInProgressRootRenderLanes$7), + originallyAttemptedLanes) + ); + 6 === exitStatus + ? markRootSuspended( + workInProgressRootRenderLanes$7, + nextLanes, + workInProgressDeferredLane + ) + : ((workInProgressRootRenderLanes$7.finishedWork = + workInProgressRootRenderLanes$7.current.alternate), + (workInProgressRootRenderLanes$7.finishedLanes = nextLanes), + commitRoot( + workInProgressRootRenderLanes$7, + workInProgressRootRecoverableErrors, + workInProgressTransitions, + workInProgressDeferredLane + )); + } + ensureRootIsScheduled(workInProgressRootRenderLanes$7); + } 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++) + (didPerformSomeWork = throwError.bind(null, errors[onlyLegacy])), + scheduleCallback$3(ImmediatePriority, didPerformSomeWork); + } + throw errors[0]; + } + } +} +function throwError(error) { + throw error; +} +function processRootScheduleInMicrotask() { + mightHavePendingSyncWork = didScheduleMicrotask = !1; + for ( + var currentTime = now$1(), 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 & -62914561; + 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 268435456: + 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() { + if (0 === currentEventTransitionLane) { + var lane = nextTransitionLane; + nextTransitionLane <<= 1; + 0 === (nextTransitionLane & 4194176) && (nextTransitionLane = 128); + currentEventTransitionLane = lane; + } + return currentEventTransitionLane; +} +var currentEntangledListeners = null, + currentEntangledPendingCount = 0, + currentEntangledLane = 0, + currentEntangledActionThenable = null; +function entangleAsyncAction(thenable) { + if (null === currentEntangledListeners) { + var entangledListeners = (currentEntangledListeners = []); + currentEntangledPendingCount = 0; + currentEntangledLane = requestTransitionLane(); + currentEntangledActionThenable = { + status: "pending", + value: void 0, + then: function (resolve) { + entangledListeners.push(resolve); + } + }; + } + currentEntangledPendingCount++; + thenable.then(pingEngtangledActionScope, pingEngtangledActionScope); + return thenable; +} +function pingEngtangledActionScope() { + if ( + null !== currentEntangledListeners && + 0 === --currentEntangledPendingCount + ) { + null !== currentEntangledActionThenable && + (currentEntangledActionThenable.status = "fulfilled"); + var listeners = currentEntangledListeners; + currentEntangledListeners = null; + currentEntangledLane = 0; + currentEntangledActionThenable = null; + for (var i = 0; i < listeners.length; i++) (0, listeners[i])(); + } +} +function chainThenableValue(thenable, result) { + var listeners = [], + thenableWithOverride = { + status: "pending", + value: null, + reason: null, + then: function (resolve) { + listeners.push(resolve); + } + }; + thenable.then( + function () { + thenableWithOverride.status = "fulfilled"; + thenableWithOverride.value = result; + for (var i = 0; i < listeners.length; i++) (0, listeners[i])(result); + }, + function (error) { + thenableWithOverride.status = "rejected"; + thenableWithOverride.reason = error; + for (error = 0; error < listeners.length; error++) + (0, listeners[error])(void 0); + } + ); + return thenableWithOverride; +} var hasForceUpdate = !1; function initializeUpdateQueue(fiber) { fiber.updateQueue = { @@ -899,12 +1171,20 @@ function enqueueCapturedUpdate(workInProgress, capturedUpdate) { : (workInProgress.next = capturedUpdate); queue.lastBaseUpdate = capturedUpdate; } +var didReadFromEntangledAsyncAction = !1; +function suspendIfUpdateReadFromEntangledAsyncAction() { + if (didReadFromEntangledAsyncAction) { + var entangledActionThenable = currentEntangledActionThenable; + if (null !== entangledActionThenable) throw entangledActionThenable; + } +} function processUpdateQueue( workInProgress$jscomp$0, props, instance$jscomp$0, renderLanes ) { + didReadFromEntangledAsyncAction = !1; var queue = workInProgress$jscomp$0.updateQueue; hasForceUpdate = !1; var firstBaseUpdate = queue.firstBaseUpdate, @@ -942,6 +1222,9 @@ function processUpdateQueue( ? (workInProgressRootRenderLanes & updateLane) === updateLane : (renderLanes & updateLane) === updateLane ) { + 0 !== updateLane && + updateLane === currentEntangledLane && + (didReadFromEntangledAsyncAction = !0); null !== current && (current = current.next = { @@ -1922,384 +2205,94 @@ function createChildReconciler(shouldTrackSideEffects) { newChild, lanes ) { - thenableIndexCounter$1 = 0; - returnFiber = reconcileChildFibersImpl( - returnFiber, - currentFirstChild, - newChild, - lanes - ); - thenableState$1 = null; - return returnFiber; - } - return reconcileChildFibers; -} -var reconcileChildFibers = createChildReconciler(!0), - mountChildFibers = createChildReconciler(!1), - currentTreeHiddenStackCursor = createCursor(null), - prevEntangledRenderLanesCursor = createCursor(0); -function pushHiddenContext(fiber, context) { - fiber = entangledRenderLanes; - push(prevEntangledRenderLanesCursor, fiber); - push(currentTreeHiddenStackCursor, context); - entangledRenderLanes = fiber | context.baseLanes; -} -function reuseHiddenContextOnStack() { - push(prevEntangledRenderLanesCursor, entangledRenderLanes); - push(currentTreeHiddenStackCursor, currentTreeHiddenStackCursor.current); -} -function popHiddenContext() { - entangledRenderLanes = prevEntangledRenderLanesCursor.current; - pop(currentTreeHiddenStackCursor); - pop(prevEntangledRenderLanesCursor); -} -var suspenseHandlerStackCursor = createCursor(null), - shellBoundary = null; -function pushPrimaryTreeSuspenseHandler(handler) { - var current = handler.alternate; - push(suspenseStackCursor, suspenseStackCursor.current & 1); - push(suspenseHandlerStackCursor, handler); - null === shellBoundary && - (null === current || null !== currentTreeHiddenStackCursor.current - ? (shellBoundary = handler) - : null !== current.memoizedState && (shellBoundary = handler)); -} -function pushOffscreenSuspenseHandler(fiber) { - if (22 === fiber.tag) { - if ( - (push(suspenseStackCursor, suspenseStackCursor.current), - push(suspenseHandlerStackCursor, fiber), - null === shellBoundary) - ) { - var current = fiber.alternate; - null !== current && - null !== current.memoizedState && - (shellBoundary = fiber); - } - } else reuseSuspenseHandlerOnStack(fiber); -} -function reuseSuspenseHandlerOnStack() { - push(suspenseStackCursor, suspenseStackCursor.current); - push(suspenseHandlerStackCursor, suspenseHandlerStackCursor.current); -} -function popSuspenseHandler(fiber) { - pop(suspenseHandlerStackCursor); - shellBoundary === fiber && (shellBoundary = null); - pop(suspenseStackCursor); -} -var suspenseStackCursor = createCursor(0); -function findFirstSuspended(row) { - for (var node = row; null !== node; ) { - if (13 === node.tag) { - var state = node.memoizedState; - if (null !== state && (null === state.dehydrated || shim$1() || shim$1())) - return node; - } else if (19 === node.tag && void 0 !== node.memoizedProps.revealOrder) { - if (0 !== (node.flags & 128)) return node; - } else if (null !== node.child) { - node.child.return = node; - node = node.child; - continue; - } - if (node === row) break; - for (; null === node.sibling; ) { - if (null === node.return || node.return === row) return null; - node = node.return; - } - node.sibling.return = node.return; - node = node.sibling; - } - return null; -} -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)); -} -function flushSyncWorkAcrossRoots_impl(onlyLegacy) { - if (!isFlushingWork && mightHavePendingSyncWork) { - var errors = null; - isFlushingWork = !0; - do { - var didPerformSomeWork = !1; - for (var root = firstScheduledRoot; null !== root; ) { - if (!onlyLegacy || 0 === root.tag) { - var workInProgressRootRenderLanes$24 = workInProgressRootRenderLanes, - nextLanes = getNextLanes( - root, - root === workInProgressRoot ? workInProgressRootRenderLanes$24 : 0 - ); - if (0 !== (nextLanes & 3)) - try { - didPerformSomeWork = !0; - workInProgressRootRenderLanes$24 = root; - if (0 !== (executionContext & 6)) - throw Error("Should not already be working."); - if (!flushPassiveEffects()) { - currentUpdateIsNested = nestedUpdateScheduled; - nestedUpdateScheduled = !1; - var exitStatus = renderRootSync( - workInProgressRootRenderLanes$24, - nextLanes - ); - if ( - 0 !== workInProgressRootRenderLanes$24.tag && - 2 === exitStatus - ) { - var originallyAttemptedLanes = nextLanes, - errorRetryLanes = getLanesToRetrySynchronouslyOnError( - workInProgressRootRenderLanes$24, - originallyAttemptedLanes - ); - 0 !== errorRetryLanes && - ((nextLanes = errorRetryLanes), - (exitStatus = recoverFromConcurrentError( - workInProgressRootRenderLanes$24, - originallyAttemptedLanes, - errorRetryLanes - ))); - } - if (1 === exitStatus) - throw ( - ((originallyAttemptedLanes = workInProgressRootFatalError), - prepareFreshStack(workInProgressRootRenderLanes$24, 0), - markRootSuspended( - workInProgressRootRenderLanes$24, - nextLanes, - 0 - ), - ensureRootIsScheduled(workInProgressRootRenderLanes$24), - originallyAttemptedLanes) - ); - 6 === exitStatus - ? markRootSuspended( - workInProgressRootRenderLanes$24, - nextLanes, - workInProgressDeferredLane - ) - : ((workInProgressRootRenderLanes$24.finishedWork = - workInProgressRootRenderLanes$24.current.alternate), - (workInProgressRootRenderLanes$24.finishedLanes = - nextLanes), - commitRoot( - workInProgressRootRenderLanes$24, - workInProgressRootRecoverableErrors, - workInProgressTransitions, - workInProgressDeferredLane - )); - } - ensureRootIsScheduled(workInProgressRootRenderLanes$24); - } 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++) - (didPerformSomeWork = throwError.bind(null, errors[onlyLegacy])), - scheduleCallback$3(ImmediatePriority, didPerformSomeWork); - } - throw errors[0]; - } - } -} -function throwError(error) { - throw error; -} -function processRootScheduleInMicrotask() { - mightHavePendingSyncWork = didScheduleMicrotask = !1; - for ( - var currentTime = now$1(), 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 & -62914561; - 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 268435456: - suspendedLanes = IdlePriority; - break; - default: - suspendedLanes = NormalPriority$1; + thenableIndexCounter$1 = 0; + returnFiber = reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + newChild, + lanes + ); + thenableState$1 = null; + return returnFiber; } - pingedLanes = performConcurrentWorkOnRoot.bind(null, root); - suspendedLanes = scheduleCallback$3(suspendedLanes, pingedLanes); - root.callbackPriority = currentTime; - root.callbackNode = suspendedLanes; - return currentTime; + return reconcileChildFibers; } -function requestTransitionLane() { - if (0 === currentEventTransitionLane) { - var lane = nextTransitionLane; - nextTransitionLane <<= 1; - 0 === (nextTransitionLane & 4194176) && (nextTransitionLane = 128); - currentEventTransitionLane = lane; - } - return currentEventTransitionLane; +var reconcileChildFibers = createChildReconciler(!0), + mountChildFibers = createChildReconciler(!1), + currentTreeHiddenStackCursor = createCursor(null), + prevEntangledRenderLanesCursor = createCursor(0); +function pushHiddenContext(fiber, context) { + fiber = entangledRenderLanes; + push(prevEntangledRenderLanesCursor, fiber); + push(currentTreeHiddenStackCursor, context); + entangledRenderLanes = fiber | context.baseLanes; } -var currentEntangledListeners = null, - currentEntangledPendingCount = 0, - currentEntangledLane = 0; -function requestAsyncActionContext(actionReturnValue, overrideReturnValue) { - if (null === currentEntangledListeners) { - var entangledListeners = (currentEntangledListeners = []); - currentEntangledPendingCount = 0; - currentEntangledLane = requestTransitionLane(); - } else entangledListeners = currentEntangledListeners; - currentEntangledPendingCount++; - var resultThenable = createResultThenable(entangledListeners), - resultStatus = "pending", - resultValue, - rejectedReason; - actionReturnValue.then( - function (value) { - resultStatus = "fulfilled"; - resultValue = null !== overrideReturnValue ? overrideReturnValue : value; - pingEngtangledActionScope(); - }, - function (error) { - resultStatus = "rejected"; - rejectedReason = error; - pingEngtangledActionScope(); - } - ); - entangledListeners.push(function () { - switch (resultStatus) { - case "fulfilled": - resultThenable.status = "fulfilled"; - resultThenable.value = resultValue; - break; - case "rejected": - resultThenable.status = "rejected"; - resultThenable.reason = rejectedReason; - break; - default: - throw Error( - "Thenable should have already resolved. This is a bug in React." - ); +function reuseHiddenContextOnStack() { + push(prevEntangledRenderLanesCursor, entangledRenderLanes); + push(currentTreeHiddenStackCursor, currentTreeHiddenStackCursor.current); +} +function popHiddenContext() { + entangledRenderLanes = prevEntangledRenderLanesCursor.current; + pop(currentTreeHiddenStackCursor); + pop(prevEntangledRenderLanesCursor); +} +var suspenseHandlerStackCursor = createCursor(null), + shellBoundary = null; +function pushPrimaryTreeSuspenseHandler(handler) { + var current = handler.alternate; + push(suspenseStackCursor, suspenseStackCursor.current & 1); + push(suspenseHandlerStackCursor, handler); + null === shellBoundary && + (null === current || null !== currentTreeHiddenStackCursor.current + ? (shellBoundary = handler) + : null !== current.memoizedState && (shellBoundary = handler)); +} +function pushOffscreenSuspenseHandler(fiber) { + if (22 === fiber.tag) { + if ( + (push(suspenseStackCursor, suspenseStackCursor.current), + push(suspenseHandlerStackCursor, fiber), + null === shellBoundary) + ) { + var current = fiber.alternate; + null !== current && + null !== current.memoizedState && + (shellBoundary = fiber); } - }); - return resultThenable; -} -function requestSyncActionContext(actionReturnValue, overrideReturnValue) { - var resultValue = - null !== overrideReturnValue ? overrideReturnValue : actionReturnValue; - if (null === currentEntangledListeners) return resultValue; - actionReturnValue = currentEntangledListeners; - var resultThenable = createResultThenable(actionReturnValue); - actionReturnValue.push(function () { - resultThenable.status = "fulfilled"; - resultThenable.value = resultValue; - }); - return resultThenable; + } else reuseSuspenseHandlerOnStack(fiber); } -function pingEngtangledActionScope() { - if ( - null !== currentEntangledListeners && - 0 === --currentEntangledPendingCount - ) { - var listeners = currentEntangledListeners; - currentEntangledListeners = null; - for (var i = (currentEntangledLane = 0); i < listeners.length; i++) - (0, listeners[i])(); - } +function reuseSuspenseHandlerOnStack() { + push(suspenseStackCursor, suspenseStackCursor.current); + push(suspenseHandlerStackCursor, suspenseHandlerStackCursor.current); } -function createResultThenable(entangledListeners) { - return { - status: "pending", - value: null, - reason: null, - then: function (resolve) { - entangledListeners.push(resolve); +function popSuspenseHandler(fiber) { + pop(suspenseHandlerStackCursor); + shellBoundary === fiber && (shellBoundary = null); + pop(suspenseStackCursor); +} +var suspenseStackCursor = createCursor(0); +function findFirstSuspended(row) { + for (var node = row; null !== node; ) { + if (13 === node.tag) { + var state = node.memoizedState; + if (null !== state && (null === state.dehydrated || shim$1() || shim$1())) + return node; + } else if (19 === node.tag && void 0 !== node.memoizedProps.revealOrder) { + if (0 !== (node.flags & 128)) return node; + } else if (null !== node.child) { + node.child.return = node; + node = node.child; + continue; } - }; + if (node === row) break; + for (; null === node.sibling; ) { + if (null === node.return || node.return === row) return null; + node = node.return; + } + node.sibling.return = node.return; + node = node.sibling; + } + return null; } var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, ReactCurrentBatchConfig$2 = ReactSharedInternals.ReactCurrentBatchConfig, @@ -2557,7 +2550,8 @@ function updateReducerImpl(hook, current, reducer) { current = baseQueue.next; var newBaseQueueFirst = (baseFirst = null), newBaseQueueLast = null, - update = current; + update = current, + didReadFromEntangledAsyncAction$26 = !1; do { var updateLane = update.lane & -536870913; if ( @@ -2565,6 +2559,9 @@ function updateReducerImpl(hook, current, reducer) { ? (workInProgressRootRenderLanes & updateLane) === updateLane : (renderLanes & updateLane) === updateLane ) { + 0 !== updateLane && + updateLane === currentEntangledLane && + (didReadFromEntangledAsyncAction$26 = !0); updateLane = update.revertLane; if (0 === updateLane) null !== newBaseQueueLast && @@ -2581,7 +2578,7 @@ function updateReducerImpl(hook, current, reducer) { update = update.next; continue; } else { - var clone$27 = { + var clone$28 = { lane: 0, revertLane: update.revertLane, action: update.action, @@ -2590,9 +2587,9 @@ function updateReducerImpl(hook, current, reducer) { next: null }; null === newBaseQueueLast - ? ((newBaseQueueFirst = newBaseQueueLast = clone$27), + ? ((newBaseQueueFirst = newBaseQueueLast = clone$28), (baseFirst = pendingQueue)) - : (newBaseQueueLast = newBaseQueueLast.next = clone$27); + : (newBaseQueueLast = newBaseQueueLast.next = clone$28); currentlyRenderingFiber$1.lanes |= updateLane; workInProgressRootSkippedLanes |= updateLane; } @@ -2603,7 +2600,7 @@ function updateReducerImpl(hook, current, reducer) { ? update.eagerState : reducer(pendingQueue, updateLane); } else - (clone$27 = { + (clone$28 = { lane: updateLane, revertLane: update.revertLane, action: update.action, @@ -2612,9 +2609,9 @@ function updateReducerImpl(hook, current, reducer) { next: null }), null === newBaseQueueLast - ? ((newBaseQueueFirst = newBaseQueueLast = clone$27), + ? ((newBaseQueueFirst = newBaseQueueLast = clone$28), (baseFirst = pendingQueue)) - : (newBaseQueueLast = newBaseQueueLast.next = clone$27), + : (newBaseQueueLast = newBaseQueueLast.next = clone$28), (currentlyRenderingFiber$1.lanes |= updateLane), (workInProgressRootSkippedLanes |= updateLane); update = update.next; @@ -2622,7 +2619,13 @@ function updateReducerImpl(hook, current, reducer) { null === newBaseQueueLast ? (baseFirst = pendingQueue) : (newBaseQueueLast.next = newBaseQueueFirst); - objectIs(pendingQueue, hook.memoizedState) || (didReceiveUpdate = !0); + if ( + !objectIs(pendingQueue, hook.memoizedState) && + ((didReceiveUpdate = !0), + didReadFromEntangledAsyncAction$26 && + ((reducer = currentEntangledActionThenable), null !== reducer)) + ) + throw reducer; hook.memoizedState = pendingQueue; hook.baseState = baseFirst; hook.baseQueue = newBaseQueueLast; @@ -2766,28 +2769,23 @@ function runFormStateAction(actionQueue, setState, payload) { ReactCurrentBatchConfig$2.transition = {}; try { var returnValue = action(prevState, payload); - if ( - null !== returnValue && - "object" === typeof returnValue && - "function" === typeof returnValue.then - ) { - returnValue.then( - function (nextState) { - actionQueue.state = nextState; - finishRunningFormStateAction(actionQueue, setState); - }, - function () { - return finishRunningFormStateAction(actionQueue, setState); - } - ); - var entangledResult = requestAsyncActionContext(returnValue, null); - setState(entangledResult); - } else { - var entangledResult$29 = requestSyncActionContext(returnValue, null); - setState(entangledResult$29); - actionQueue.state = returnValue; - finishRunningFormStateAction(actionQueue, setState); - } + null !== returnValue && + "object" === typeof returnValue && + "function" === typeof returnValue.then + ? (returnValue.then( + function (nextState) { + actionQueue.state = nextState; + finishRunningFormStateAction(actionQueue, setState); + }, + function () { + return finishRunningFormStateAction(actionQueue, setState); + } + ), + entangleAsyncAction(returnValue), + setState(returnValue)) + : (setState(returnValue), + (actionQueue.state = returnValue), + finishRunningFormStateAction(actionQueue, setState)); } catch (error) { setState({ then: function () {}, status: "rejected", reason: error }), finishRunningFormStateAction(actionQueue, setState); @@ -2968,18 +2966,13 @@ function startTransition(fiber, queue, pendingState, finishedState, callback) { "object" === typeof returnValue && "function" === typeof returnValue.then ) { - var entangledResult = requestAsyncActionContext( - returnValue, - finishedState - ); - dispatchSetState(fiber, queue, entangledResult); - } else { - var entangledResult$31 = requestSyncActionContext( + entangleAsyncAction(returnValue); + var thenableForFinishedState = chainThenableValue( returnValue, finishedState ); - dispatchSetState(fiber, queue, entangledResult$31); - } + dispatchSetState(fiber, queue, thenableForFinishedState); + } else dispatchSetState(fiber, queue, finishedState); } catch (error) { dispatchSetState(fiber, queue, { then: function () {}, @@ -3642,6 +3635,7 @@ function mountClassInstance(workInProgress, ctor, newProps, renderLanes) { ctor !== instance.state && classComponentUpdater.enqueueReplaceState(instance, instance.state, null), processUpdateQueue(workInProgress, newProps, instance, renderLanes), + suspendIfUpdateReadFromEntangledAsyncAction(), (instance.state = workInProgress.memoizedState)); "function" === typeof instance.componentDidMount && (workInProgress.flags |= 4194308); @@ -3713,6 +3707,153 @@ function createClassErrorUpdate(fiber, errorInfo, lane) { }); return lane; } +function throwException( + root, + returnFiber, + sourceFiber, + value, + rootRenderLanes +) { + sourceFiber.flags |= 32768; + if ( + null !== value && + "object" === typeof value && + "function" === typeof value.then + ) { + var tag = sourceFiber.tag; + 0 !== (sourceFiber.mode & 1) || + (0 !== tag && 11 !== tag && 15 !== tag) || + ((tag = sourceFiber.alternate) + ? ((sourceFiber.updateQueue = tag.updateQueue), + (sourceFiber.memoizedState = tag.memoizedState), + (sourceFiber.lanes = tag.lanes)) + : ((sourceFiber.updateQueue = null), + (sourceFiber.memoizedState = null))); + tag = suspenseHandlerStackCursor.current; + if (null !== tag) { + switch (tag.tag) { + case 13: + return ( + sourceFiber.mode & 1 && + (null === shellBoundary + ? renderDidSuspendDelayIfPossible() + : null === tag.alternate && + 0 === workInProgressRootExitStatus && + (workInProgressRootExitStatus = 3)), + (tag.flags &= -257), + 0 === (tag.mode & 1) + ? tag === returnFiber + ? (tag.flags |= 65536) + : ((tag.flags |= 128), + (sourceFiber.flags |= 131072), + (sourceFiber.flags &= -52805), + 1 === sourceFiber.tag && + (null === sourceFiber.alternate + ? (sourceFiber.tag = 17) + : ((returnFiber = createUpdate(2)), + (returnFiber.tag = 2), + enqueueUpdate(sourceFiber, returnFiber, 2))), + (sourceFiber.lanes |= 2)) + : ((tag.flags |= 65536), (tag.lanes = rootRenderLanes)), + value === noopSuspenseyCommitThenable + ? (tag.flags |= 16384) + : ((returnFiber = tag.updateQueue), + null === returnFiber + ? (tag.updateQueue = new Set([value])) + : returnFiber.add(value), + tag.mode & 1 && + attachPingListener(root, value, rootRenderLanes)), + !1 + ); + case 22: + if (tag.mode & 1) + return ( + (tag.flags |= 65536), + value === noopSuspenseyCommitThenable + ? (tag.flags |= 16384) + : ((returnFiber = tag.updateQueue), + null === returnFiber + ? ((returnFiber = { + transitions: null, + markerInstances: null, + retryQueue: new Set([value]) + }), + (tag.updateQueue = returnFiber)) + : ((sourceFiber = returnFiber.retryQueue), + null === sourceFiber + ? (returnFiber.retryQueue = new Set([value])) + : sourceFiber.add(value)), + attachPingListener(root, value, rootRenderLanes)), + !1 + ); + } + throw Error( + "Unexpected Suspense handler tag (" + + tag.tag + + "). This is a bug in React." + ); + } + if (1 === root.tag) + return ( + attachPingListener(root, value, rootRenderLanes), + renderDidSuspendDelayIfPossible(), + !1 + ); + value = Error( + "A component suspended while responding to synchronous input. This will cause the UI to be replaced with a loading indicator. To fix, updates that suspend should be wrapped with startTransition." + ); + } + root = value = createCapturedValueAtFiber(value, sourceFiber); + 4 !== workInProgressRootExitStatus && (workInProgressRootExitStatus = 2); + null === workInProgressRootConcurrentErrors + ? (workInProgressRootConcurrentErrors = [root]) + : workInProgressRootConcurrentErrors.push(root); + if (null === returnFiber) return !0; + root = returnFiber; + do { + switch (root.tag) { + case 3: + return ( + (root.flags |= 65536), + (rootRenderLanes &= -rootRenderLanes), + (root.lanes |= rootRenderLanes), + (rootRenderLanes = createRootErrorUpdate( + root, + value, + rootRenderLanes + )), + enqueueCapturedUpdate(root, rootRenderLanes), + !1 + ); + case 1: + if ( + ((returnFiber = value), + (sourceFiber = root.type), + (tag = root.stateNode), + 0 === (root.flags & 128) && + ("function" === typeof sourceFiber.getDerivedStateFromError || + (null !== tag && + "function" === typeof tag.componentDidCatch && + (null === legacyErrorBoundariesThatAlreadyFailed || + !legacyErrorBoundariesThatAlreadyFailed.has(tag))))) + ) + return ( + (root.flags |= 65536), + (rootRenderLanes &= -rootRenderLanes), + (root.lanes |= rootRenderLanes), + (rootRenderLanes = createClassErrorUpdate( + root, + returnFiber, + rootRenderLanes + )), + enqueueCapturedUpdate(root, rootRenderLanes), + !1 + ); + } + root = root.return; + } while (null !== root); + return !1; +} var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner, SelectiveHydrationException = Error( "This is not a real error. It's an implementation detail of React's selective hydration feature. If this leaks into userspace, it's a bug in React. Please file an issue." @@ -4028,6 +4169,7 @@ function updateClassComponent( var oldState = workInProgress.memoizedState; instance.state = oldState; processUpdateQueue(workInProgress, nextProps, instance, renderLanes); + suspendIfUpdateReadFromEntangledAsyncAction(); oldContext = workInProgress.memoizedState; oldProps !== nextProps || oldState !== oldContext || @@ -4107,6 +4249,7 @@ function updateClassComponent( oldState = workInProgress.memoizedState; instance.state = oldState; processUpdateQueue(workInProgress, nextProps, instance, renderLanes); + suspendIfUpdateReadFromEntangledAsyncAction(); var newState = workInProgress.memoizedState; oldProps !== hasNewLifecycles || oldState !== newState || @@ -5054,14 +5197,14 @@ function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { break; case "collapsed": lastTailNode = renderState.tail; - for (var lastTailNode$64 = null; null !== lastTailNode; ) - null !== lastTailNode.alternate && (lastTailNode$64 = lastTailNode), + for (var lastTailNode$63 = null; null !== lastTailNode; ) + null !== lastTailNode.alternate && (lastTailNode$63 = lastTailNode), (lastTailNode = lastTailNode.sibling); - null === lastTailNode$64 + null === lastTailNode$63 ? hasRenderedATailFallback || null === renderState.tail ? (renderState.tail = null) : (renderState.tail.sibling = null) - : (lastTailNode$64.sibling = null); + : (lastTailNode$63.sibling = null); } } function bubbleProperties(completedWork) { @@ -5073,53 +5216,53 @@ function bubbleProperties(completedWork) { if (didBailout) if (0 !== (completedWork.mode & 2)) { for ( - var treeBaseDuration$66 = completedWork.selfBaseDuration, - child$67 = completedWork.child; - null !== child$67; + var treeBaseDuration$65 = completedWork.selfBaseDuration, + child$66 = completedWork.child; + null !== child$66; ) - (newChildLanes |= child$67.lanes | child$67.childLanes), - (subtreeFlags |= child$67.subtreeFlags & 31457280), - (subtreeFlags |= child$67.flags & 31457280), - (treeBaseDuration$66 += child$67.treeBaseDuration), - (child$67 = child$67.sibling); - completedWork.treeBaseDuration = treeBaseDuration$66; + (newChildLanes |= child$66.lanes | child$66.childLanes), + (subtreeFlags |= child$66.subtreeFlags & 31457280), + (subtreeFlags |= child$66.flags & 31457280), + (treeBaseDuration$65 += child$66.treeBaseDuration), + (child$66 = child$66.sibling); + completedWork.treeBaseDuration = treeBaseDuration$65; } else for ( - treeBaseDuration$66 = completedWork.child; - null !== treeBaseDuration$66; + treeBaseDuration$65 = completedWork.child; + null !== treeBaseDuration$65; ) (newChildLanes |= - treeBaseDuration$66.lanes | treeBaseDuration$66.childLanes), - (subtreeFlags |= treeBaseDuration$66.subtreeFlags & 31457280), - (subtreeFlags |= treeBaseDuration$66.flags & 31457280), - (treeBaseDuration$66.return = completedWork), - (treeBaseDuration$66 = treeBaseDuration$66.sibling); + treeBaseDuration$65.lanes | treeBaseDuration$65.childLanes), + (subtreeFlags |= treeBaseDuration$65.subtreeFlags & 31457280), + (subtreeFlags |= treeBaseDuration$65.flags & 31457280), + (treeBaseDuration$65.return = completedWork), + (treeBaseDuration$65 = treeBaseDuration$65.sibling); else if (0 !== (completedWork.mode & 2)) { - treeBaseDuration$66 = completedWork.actualDuration; - child$67 = completedWork.selfBaseDuration; + treeBaseDuration$65 = completedWork.actualDuration; + child$66 = completedWork.selfBaseDuration; for (var child = completedWork.child; null !== child; ) (newChildLanes |= child.lanes | child.childLanes), (subtreeFlags |= child.subtreeFlags), (subtreeFlags |= child.flags), - (treeBaseDuration$66 += child.actualDuration), - (child$67 += child.treeBaseDuration), + (treeBaseDuration$65 += child.actualDuration), + (child$66 += child.treeBaseDuration), (child = child.sibling); - completedWork.actualDuration = treeBaseDuration$66; - completedWork.treeBaseDuration = child$67; + completedWork.actualDuration = treeBaseDuration$65; + completedWork.treeBaseDuration = child$66; } else for ( - treeBaseDuration$66 = completedWork.child; - null !== treeBaseDuration$66; + treeBaseDuration$65 = completedWork.child; + null !== treeBaseDuration$65; ) (newChildLanes |= - treeBaseDuration$66.lanes | treeBaseDuration$66.childLanes), - (subtreeFlags |= treeBaseDuration$66.subtreeFlags), - (subtreeFlags |= treeBaseDuration$66.flags), - (treeBaseDuration$66.return = completedWork), - (treeBaseDuration$66 = treeBaseDuration$66.sibling); + treeBaseDuration$65.lanes | treeBaseDuration$65.childLanes), + (subtreeFlags |= treeBaseDuration$65.subtreeFlags), + (subtreeFlags |= treeBaseDuration$65.flags), + (treeBaseDuration$65.return = completedWork), + (treeBaseDuration$65 = treeBaseDuration$65.sibling); completedWork.subtreeFlags |= subtreeFlags; completedWork.childLanes = newChildLanes; return didBailout; @@ -5290,11 +5433,11 @@ function completeWork(current, workInProgress, renderLanes) { null !== newProps.alternate.memoizedState && null !== newProps.alternate.memoizedState.cachePool && (index = newProps.alternate.memoizedState.cachePool.pool); - var cache$74 = null; + var cache$73 = null; null !== newProps.memoizedState && null !== newProps.memoizedState.cachePool && - (cache$74 = newProps.memoizedState.cachePool.pool); - cache$74 !== index && (newProps.flags |= 2048); + (cache$73 = newProps.memoizedState.cachePool.pool); + cache$73 !== index && (newProps.flags |= 2048); } renderLanes !== current && renderLanes && @@ -5326,8 +5469,8 @@ function completeWork(current, workInProgress, renderLanes) { index = workInProgress.memoizedState; if (null === index) return bubbleProperties(workInProgress), null; newProps = 0 !== (workInProgress.flags & 128); - cache$74 = index.rendering; - if (null === cache$74) + cache$73 = index.rendering; + if (null === cache$73) if (newProps) cutOffTailIfNeeded(index, !1); else { if ( @@ -5335,11 +5478,11 @@ function completeWork(current, workInProgress, renderLanes) { (null !== current && 0 !== (current.flags & 128)) ) for (current = workInProgress.child; null !== current; ) { - cache$74 = findFirstSuspended(current); - if (null !== cache$74) { + cache$73 = findFirstSuspended(current); + if (null !== cache$73) { workInProgress.flags |= 128; cutOffTailIfNeeded(index, !1); - current = cache$74.updateQueue; + current = cache$73.updateQueue; workInProgress.updateQueue = current; scheduleRetryEffect(workInProgress, current); workInProgress.subtreeFlags = 0; @@ -5364,7 +5507,7 @@ function completeWork(current, workInProgress, renderLanes) { } else { if (!newProps) - if (((current = findFirstSuspended(cache$74)), null !== current)) { + if (((current = findFirstSuspended(cache$73)), null !== current)) { if ( ((workInProgress.flags |= 128), (newProps = !0), @@ -5374,7 +5517,7 @@ function completeWork(current, workInProgress, renderLanes) { cutOffTailIfNeeded(index, !0), null === index.tail && "hidden" === index.tailMode && - !cache$74.alternate) + !cache$73.alternate) ) return bubbleProperties(workInProgress), null; } else @@ -5386,13 +5529,13 @@ function completeWork(current, workInProgress, renderLanes) { cutOffTailIfNeeded(index, !1), (workInProgress.lanes = 4194304)); index.isBackwards - ? ((cache$74.sibling = workInProgress.child), - (workInProgress.child = cache$74)) + ? ((cache$73.sibling = workInProgress.child), + (workInProgress.child = cache$73)) : ((current = index.last), null !== current - ? (current.sibling = cache$74) - : (workInProgress.child = cache$74), - (index.last = cache$74)); + ? (current.sibling = cache$73) + : (workInProgress.child = cache$73), + (index.last = cache$73)); } if (null !== index.tail) return ( @@ -5646,8 +5789,8 @@ function safelyDetachRef(current, nearestMountedAncestor) { recordLayoutEffectDuration(current); } else ref(null); - } catch (error$90) { - captureCommitPhaseError(current, nearestMountedAncestor, error$90); + } catch (error$89) { + captureCommitPhaseError(current, nearestMountedAncestor, error$89); } else ref.current = null; } @@ -5753,10 +5896,10 @@ function commitHookEffectListMount(flags, finishedWork) { var effect = (finishedWork = finishedWork.next); do { if ((effect.tag & flags) === flags) { - var create$91 = effect.create, + var create$90 = effect.create, inst = effect.inst; - create$91 = create$91(); - inst.destroy = create$91; + create$90 = create$90(); + inst.destroy = create$90; } effect = effect.next; } while (effect !== finishedWork); @@ -5774,8 +5917,8 @@ function commitHookLayoutEffects(finishedWork, hookFlags) { } else try { commitHookEffectListMount(hookFlags, finishedWork); - } catch (error$93) { - captureCommitPhaseError(finishedWork, finishedWork.return, error$93); + } catch (error$92) { + captureCommitPhaseError(finishedWork, finishedWork.return, error$92); } } function commitClassCallbacks(finishedWork) { @@ -5855,11 +5998,11 @@ function commitLayoutEffectOnFiber(finishedRoot, current, finishedWork) { } else try { finishedRoot.componentDidMount(); - } catch (error$94) { + } catch (error$93) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$94 + error$93 ); } else { @@ -5876,11 +6019,11 @@ function commitLayoutEffectOnFiber(finishedRoot, current, finishedWork) { current, finishedRoot.__reactInternalSnapshotBeforeUpdate ); - } catch (error$95) { + } catch (error$94) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$95 + error$94 ); } recordLayoutEffectDuration(finishedWork); @@ -5891,11 +6034,11 @@ function commitLayoutEffectOnFiber(finishedRoot, current, finishedWork) { current, finishedRoot.__reactInternalSnapshotBeforeUpdate ); - } catch (error$96) { + } catch (error$95) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$96 + error$95 ); } } @@ -6282,22 +6425,22 @@ function commitMutationEffectsOnFiber(finishedWork, root) { try { startLayoutEffectTimer(), commitHookEffectListUnmount(5, finishedWork, finishedWork.return); - } catch (error$105) { + } catch (error$104) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$105 + error$104 ); } recordLayoutEffectDuration(finishedWork); } else try { commitHookEffectListUnmount(5, finishedWork, finishedWork.return); - } catch (error$106) { + } catch (error$105) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$106 + error$105 ); } } @@ -6336,8 +6479,8 @@ function commitMutationEffectsOnFiber(finishedWork, root) { finishedWork.updateQueue = null; try { (flags.type = type), (flags.props = existingHiddenCallbacks); - } catch (error$109) { - captureCommitPhaseError(finishedWork, finishedWork.return, error$109); + } catch (error$108) { + captureCommitPhaseError(finishedWork, finishedWork.return, error$108); } } break; @@ -6353,8 +6496,8 @@ function commitMutationEffectsOnFiber(finishedWork, root) { existingHiddenCallbacks = finishedWork.memoizedProps; try { flags.text = existingHiddenCallbacks; - } catch (error$110) { - captureCommitPhaseError(finishedWork, finishedWork.return, error$110); + } catch (error$109) { + captureCommitPhaseError(finishedWork, finishedWork.return, error$109); } } break; @@ -6438,11 +6581,11 @@ function commitMutationEffectsOnFiber(finishedWork, root) { wasHidden.stateNode.isHidden = existingHiddenCallbacks ? !0 : !1; - } catch (error$99) { + } catch (error$98) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$99 + error$98 ); } } else if ( @@ -6520,12 +6663,12 @@ function commitReconciliationEffects(finishedWork) { break; case 3: case 4: - var parent$100 = JSCompiler_inline_result.stateNode.containerInfo, - before$101 = getHostSibling(finishedWork); + var parent$99 = JSCompiler_inline_result.stateNode.containerInfo, + before$100 = getHostSibling(finishedWork); insertOrAppendPlacementNodeIntoContainer( finishedWork, - before$101, - parent$100 + before$100, + parent$99 ); break; default: @@ -6705,8 +6848,8 @@ function commitHookPassiveMountEffects(finishedWork, hookFlags) { } else try { commitHookEffectListMount(hookFlags, finishedWork); - } catch (error$114) { - captureCommitPhaseError(finishedWork, finishedWork.return, error$114); + } catch (error$113) { + captureCommitPhaseError(finishedWork, finishedWork.return, error$113); } } function commitOffscreenPassiveMountEffects(current, finishedWork) { @@ -7634,13 +7777,13 @@ function renderRootSync(root, lanes) { default: (workInProgressSuspendedReason = 0), (workInProgressThrownValue = null), - throwAndUnwindWorkLoop(unitOfWork, thrownValue); + throwAndUnwindWorkLoop(root, unitOfWork, thrownValue); } } workLoopSync(); break; - } catch (thrownValue$119) { - handleThrow(root, thrownValue$119); + } catch (thrownValue$118) { + handleThrow(root, thrownValue$118); } while (1); lanes && root.shellSuspendCounter++; @@ -7678,7 +7821,7 @@ function renderRootConcurrent(root, lanes) { case 1: workInProgressSuspendedReason = 0; workInProgressThrownValue = null; - throwAndUnwindWorkLoop(lanes, thrownValue); + throwAndUnwindWorkLoop(root, lanes, thrownValue); break; case 2: if (isThenableResolved(thrownValue)) { @@ -7708,7 +7851,7 @@ function renderRootConcurrent(root, lanes) { replaySuspendedUnitOfWork(lanes)) : ((workInProgressSuspendedReason = 0), (workInProgressThrownValue = null), - throwAndUnwindWorkLoop(lanes, thrownValue)); + throwAndUnwindWorkLoop(root, lanes, thrownValue)); break; case 5: switch (workInProgress.tag) { @@ -7731,12 +7874,12 @@ function renderRootConcurrent(root, lanes) { } workInProgressSuspendedReason = 0; workInProgressThrownValue = null; - throwAndUnwindWorkLoop(lanes, thrownValue); + throwAndUnwindWorkLoop(root, lanes, thrownValue); break; case 6: workInProgressSuspendedReason = 0; workInProgressThrownValue = null; - throwAndUnwindWorkLoop(lanes, thrownValue); + throwAndUnwindWorkLoop(root, lanes, thrownValue); break; case 8: resetWorkInProgressStack(); @@ -7748,8 +7891,8 @@ function renderRootConcurrent(root, lanes) { } workLoopConcurrent(); break; - } catch (thrownValue$121) { - handleThrow(root, thrownValue$121); + } catch (thrownValue$120) { + handleThrow(root, thrownValue$120); } while (1); resetContextDependencies(); @@ -7838,199 +7981,63 @@ function replaySuspendedUnitOfWork(unitOfWork) { : (workInProgress = current); ReactCurrentOwner.current = null; } -function throwAndUnwindWorkLoop(unitOfWork, thrownValue) { +function throwAndUnwindWorkLoop(root, unitOfWork, thrownValue) { resetContextDependencies(); resetHooksOnUnwind(unitOfWork); thenableState$1 = null; thenableIndexCounter$1 = 0; var returnFiber = unitOfWork.return; - if (null === returnFiber || null === workInProgressRoot) - (workInProgressRootExitStatus = 1), - (workInProgressRootFatalError = thrownValue), - (workInProgress = null); - else { - try { - a: { - var root = workInProgressRoot, - value = thrownValue; - thrownValue = workInProgressRootRenderLanes; - unitOfWork.flags |= 32768; - if ( - null !== value && - "object" === typeof value && - "function" === typeof value.then - ) { - var wakeable = value, - tag = unitOfWork.tag; - if ( - 0 === (unitOfWork.mode & 1) && - (0 === tag || 11 === tag || 15 === tag) - ) { - var currentSource = unitOfWork.alternate; - currentSource - ? ((unitOfWork.updateQueue = currentSource.updateQueue), - (unitOfWork.memoizedState = currentSource.memoizedState), - (unitOfWork.lanes = currentSource.lanes)) - : ((unitOfWork.updateQueue = null), - (unitOfWork.memoizedState = null)); - } - var suspenseBoundary = suspenseHandlerStackCursor.current; - if (null !== suspenseBoundary) { - switch (suspenseBoundary.tag) { - case 13: - unitOfWork.mode & 1 && - (null === shellBoundary - ? renderDidSuspendDelayIfPossible() - : null === suspenseBoundary.alternate && - 0 === workInProgressRootExitStatus && - (workInProgressRootExitStatus = 3)); - suspenseBoundary.flags &= -257; - if (0 === (suspenseBoundary.mode & 1)) - if (suspenseBoundary === returnFiber) - suspenseBoundary.flags |= 65536; - else { - suspenseBoundary.flags |= 128; - unitOfWork.flags |= 131072; - unitOfWork.flags &= -52805; - if (1 === unitOfWork.tag) - if (null === unitOfWork.alternate) unitOfWork.tag = 17; - else { - var update = createUpdate(2); - update.tag = 2; - enqueueUpdate(unitOfWork, update, 2); - } - unitOfWork.lanes |= 2; - } - else - (suspenseBoundary.flags |= 65536), - (suspenseBoundary.lanes = thrownValue); - if (wakeable === noopSuspenseyCommitThenable) - suspenseBoundary.flags |= 16384; - else { - var retryQueue = suspenseBoundary.updateQueue; - null === retryQueue - ? (suspenseBoundary.updateQueue = new Set([wakeable])) - : retryQueue.add(wakeable); - suspenseBoundary.mode & 1 && - attachPingListener(root, wakeable, thrownValue); - } - break a; - case 22: - if (suspenseBoundary.mode & 1) { - suspenseBoundary.flags |= 65536; - if (wakeable === noopSuspenseyCommitThenable) - suspenseBoundary.flags |= 16384; - else { - var offscreenQueue = suspenseBoundary.updateQueue; - if (null === offscreenQueue) { - var newOffscreenQueue = { - transitions: null, - markerInstances: null, - retryQueue: new Set([wakeable]) - }; - suspenseBoundary.updateQueue = newOffscreenQueue; - } else { - var retryQueue$33 = offscreenQueue.retryQueue; - null === retryQueue$33 - ? (offscreenQueue.retryQueue = new Set([wakeable])) - : retryQueue$33.add(wakeable); - } - attachPingListener(root, wakeable, thrownValue); - } - break a; - } - } - throw Error( - "Unexpected Suspense handler tag (" + - suspenseBoundary.tag + - "). This is a bug in React." - ); - } - if (1 === root.tag) { - attachPingListener(root, wakeable, thrownValue); - renderDidSuspendDelayIfPossible(); - break a; - } else - value = Error( - "A component suspended while responding to synchronous input. This will cause the UI to be replaced with a loading indicator. To fix, updates that suspend should be wrapped with startTransition." - ); - } - root = value = createCapturedValueAtFiber(value, unitOfWork); - 4 !== workInProgressRootExitStatus && - (workInProgressRootExitStatus = 2); - null === workInProgressRootConcurrentErrors - ? (workInProgressRootConcurrentErrors = [root]) - : workInProgressRootConcurrentErrors.push(root); - root = returnFiber; - do { - switch (root.tag) { - case 3: - var errorInfo = value; - root.flags |= 65536; - thrownValue &= -thrownValue; - root.lanes |= thrownValue; - var update$jscomp$0 = createRootErrorUpdate( - root, - errorInfo, - thrownValue - ); - enqueueCapturedUpdate(root, update$jscomp$0); - break a; - case 1: - tag = value; - var ctor = root.type, - instance = root.stateNode; - if ( - 0 === (root.flags & 128) && - ("function" === typeof ctor.getDerivedStateFromError || - (null !== instance && - "function" === typeof instance.componentDidCatch && - (null === legacyErrorBoundariesThatAlreadyFailed || - !legacyErrorBoundariesThatAlreadyFailed.has(instance)))) - ) { - root.flags |= 65536; - update$jscomp$0 = thrownValue & -thrownValue; - root.lanes |= update$jscomp$0; - errorInfo = createClassErrorUpdate(root, tag, update$jscomp$0); - enqueueCapturedUpdate(root, errorInfo); - break a; - } - } - root = root.return; - } while (null !== root); - } - } catch (error) { - throw ((workInProgress = returnFiber), error); + try { + if ( + throwException( + root, + returnFiber, + unitOfWork, + thrownValue, + workInProgressRootRenderLanes + ) + ) { + workInProgressRootExitStatus = 1; + workInProgressRootFatalError = thrownValue; + workInProgress = null; + return; } - if (unitOfWork.flags & 32768) - a: { - do { - returnFiber = unwindWork(unitOfWork.alternate, unitOfWork); - if (null !== returnFiber) { - returnFiber.flags &= 32767; - workInProgress = returnFiber; - break a; - } - if (0 !== (unitOfWork.mode & 2)) { - stopProfilerTimerIfRunningAndRecordDelta(unitOfWork, !1); - returnFiber = unitOfWork.actualDuration; - for (update$jscomp$0 = unitOfWork.child; null !== update$jscomp$0; ) - (returnFiber += update$jscomp$0.actualDuration), - (update$jscomp$0 = update$jscomp$0.sibling); - unitOfWork.actualDuration = returnFiber; - } - 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); + } catch (error) { + if (null !== returnFiber) throw ((workInProgress = returnFiber), error); + workInProgressRootExitStatus = 1; + workInProgressRootFatalError = thrownValue; + workInProgress = null; + return; } + if (unitOfWork.flags & 32768) + a: { + root = unitOfWork; + do { + unitOfWork = unwindWork(root.alternate, root); + if (null !== unitOfWork) { + unitOfWork.flags &= 32767; + workInProgress = unitOfWork; + break a; + } + if (0 !== (root.mode & 2)) { + stopProfilerTimerIfRunningAndRecordDelta(root, !1); + unitOfWork = root.actualDuration; + for (thrownValue = root.child; null !== thrownValue; ) + (unitOfWork += thrownValue.actualDuration), + (thrownValue = thrownValue.sibling); + root.actualDuration = unitOfWork; + } + root = root.return; + null !== root && + ((root.flags |= 32768), + (root.subtreeFlags = 0), + (root.deletions = null)); + workInProgress = root; + } while (null !== root); + workInProgressRootExitStatus = 6; + workInProgress = null; + } + else completeUnitOfWork(unitOfWork); } function completeUnitOfWork(unitOfWork) { var completedWork = unitOfWork; @@ -8223,11 +8230,11 @@ function flushPassiveEffects() { _finishedWork$memoize = finishedWork.memoizedProps, id = _finishedWork$memoize.id, onPostCommit = _finishedWork$memoize.onPostCommit, - commitTime$92 = commitTime, + commitTime$91 = commitTime, phase = null === finishedWork.alternate ? "mount" : "update"; currentUpdateIsNested && (phase = "nested-update"); "function" === typeof onPostCommit && - onPostCommit(id, phase, passiveEffectDuration, commitTime$92); + onPostCommit(id, phase, passiveEffectDuration, commitTime$91); var parentFiber = finishedWork.return; b: for (; null !== parentFiber; ) { switch (parentFiber.tag) { @@ -8571,6 +8578,7 @@ beginWork = function (current, workInProgress, renderLanes) { pushProvider(workInProgress, CacheContext, nextCache); nextCache !== context.cache && propagateContextChange(workInProgress, CacheContext, renderLanes); + suspendIfUpdateReadFromEntangledAsyncAction(); context = hasContext.element; context === Component ? (workInProgress = bailoutOnAlreadyFinishedWork( @@ -8792,7 +8800,8 @@ beginWork = function (current, workInProgress, renderLanes) { pushProvider(workInProgress, CacheContext, context)) : (0 !== (current.lanes & renderLanes) && (cloneUpdateQueue(current, workInProgress), - processUpdateQueue(workInProgress, null, null, renderLanes)), + processUpdateQueue(workInProgress, null, null, renderLanes), + suspendIfUpdateReadFromEntangledAsyncAction()), (context = current.memoizedState), (hasContext = workInProgress.memoizedState), context.parent !== Component @@ -9545,19 +9554,19 @@ function wrapFiber(fiber) { fiberToWrapper.set(fiber, wrapper)); return wrapper; } -var devToolsConfig$jscomp$inline_1079 = { +var devToolsConfig$jscomp$inline_1073 = { findFiberByHostInstance: function () { throw Error("TestRenderer does not support findFiberByHostInstance()"); }, bundleType: 0, - version: "18.3.0-canary-2efb14260-20240124", + version: "18.3.0-canary-11c9fd0c5-20240124", rendererPackageName: "react-test-renderer" }; -var internals$jscomp$inline_1271 = { - bundleType: devToolsConfig$jscomp$inline_1079.bundleType, - version: devToolsConfig$jscomp$inline_1079.version, - rendererPackageName: devToolsConfig$jscomp$inline_1079.rendererPackageName, - rendererConfig: devToolsConfig$jscomp$inline_1079.rendererConfig, +var internals$jscomp$inline_1248 = { + bundleType: devToolsConfig$jscomp$inline_1073.bundleType, + version: devToolsConfig$jscomp$inline_1073.version, + rendererPackageName: devToolsConfig$jscomp$inline_1073.rendererPackageName, + rendererConfig: devToolsConfig$jscomp$inline_1073.rendererConfig, overrideHookState: null, overrideHookStateDeletePath: null, overrideHookStateRenamePath: null, @@ -9574,26 +9583,26 @@ var internals$jscomp$inline_1271 = { return null === fiber ? null : fiber.stateNode; }, findFiberByHostInstance: - devToolsConfig$jscomp$inline_1079.findFiberByHostInstance || + devToolsConfig$jscomp$inline_1073.findFiberByHostInstance || emptyFindFiberByHostInstance, findHostInstancesForRefresh: null, scheduleRefresh: null, scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "18.3.0-canary-2efb14260-20240124" + reconcilerVersion: "18.3.0-canary-11c9fd0c5-20240124" }; if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { - var hook$jscomp$inline_1272 = __REACT_DEVTOOLS_GLOBAL_HOOK__; + var hook$jscomp$inline_1249 = __REACT_DEVTOOLS_GLOBAL_HOOK__; if ( - !hook$jscomp$inline_1272.isDisabled && - hook$jscomp$inline_1272.supportsFiber + !hook$jscomp$inline_1249.isDisabled && + hook$jscomp$inline_1249.supportsFiber ) try { - (rendererID = hook$jscomp$inline_1272.inject( - internals$jscomp$inline_1271 + (rendererID = hook$jscomp$inline_1249.inject( + internals$jscomp$inline_1248 )), - (injectedHook = hook$jscomp$inline_1272); + (injectedHook = hook$jscomp$inline_1249); } catch (err) {} } exports._Scheduler = Scheduler; diff --git a/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/cjs/React-dev.js b/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/cjs/React-dev.js index b52f346cc19db..651aa2f7efd68 100644 --- a/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/cjs/React-dev.js +++ b/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/cjs/React-dev.js @@ -24,7 +24,7 @@ if (__DEV__) { ) { __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(new Error()); } - var ReactVersion = "18.3.0-canary-2efb14260-20240124"; + var ReactVersion = "18.3.0-canary-11c9fd0c5-20240124"; // ATTENTION // When adding new symbols to this file, diff --git a/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/cjs/React-prod.js b/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/cjs/React-prod.js index 74cad9e105353..dd73f635a8f6a 100644 --- a/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/cjs/React-prod.js +++ b/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/cjs/React-prod.js @@ -539,4 +539,4 @@ exports.useSyncExternalStore = function ( exports.useTransition = function () { return ReactCurrentDispatcher.current.useTransition(); }; -exports.version = "18.3.0-canary-2efb14260-20240124"; +exports.version = "18.3.0-canary-11c9fd0c5-20240124"; diff --git a/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/cjs/React-profiling.js b/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/cjs/React-profiling.js index e26e2d5a7a1fc..ddbc237f7aeb0 100644 --- a/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/cjs/React-profiling.js +++ b/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/cjs/React-profiling.js @@ -535,7 +535,7 @@ exports.useSyncExternalStore = function ( exports.useTransition = function () { return ReactCurrentDispatcher.current.useTransition(); }; -exports.version = "18.3.0-canary-2efb14260-20240124"; +exports.version = "18.3.0-canary-11c9fd0c5-20240124"; "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && diff --git a/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/REVISION b/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/REVISION index ec305d21b4333..60b652c8dec48 100644 --- a/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/REVISION +++ b/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/REVISION @@ -1 +1 @@ -2efb1426067322cdb08304432b3ac849dee52bd9 +11c9fd0c53133f24f5270d36591b65b8fc2ebd25 diff --git a/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactFabric-dev.fb.js b/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactFabric-dev.fb.js index 59ece46dca009..c2dd4dd531c6b 100644 --- a/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactFabric-dev.fb.js +++ b/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactFabric-dev.fb.js @@ -7,7 +7,7 @@ * @noflow * @nolint * @preventMunge - * @generated SignedSource<<3bbc5516aa8fca4c50bd6b2679dc8923>> + * @generated SignedSource<<98889e37108bba6b8b4772891a2513c5>> */ "use strict"; @@ -6846,3738 +6846,3730 @@ to return true:wantsResponderID| | } } - var UpdateState = 0; - var ReplaceState = 1; - var ForceUpdate = 2; - var CaptureUpdate = 3; // Global state that is reset at the beginning of calling `processUpdateQueue`. - // It should only be read right after calling `processUpdateQueue`, via - // `checkHasForceUpdateAfterProcessing`. + var ReactCurrentActQueue$3 = 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 hasForceUpdate = false; - var didWarnUpdateInsideUpdate; - var currentlyProcessingQueue; + var firstScheduledRoot = null; + var lastScheduledRoot = null; // Used to prevent redundant mircotasks from being scheduled. - { - didWarnUpdateInsideUpdate = false; - currentlyProcessingQueue = null; - } + 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. - function initializeUpdateQueue(fiber) { - var queue = { - baseState: fiber.memoizedState, - firstBaseUpdate: null, - lastBaseUpdate: null, - shared: { - pending: null, - lanes: NoLanes, - hiddenCallbacks: null - }, - callbacks: null - }; - fiber.updateQueue = queue; - } - function cloneUpdateQueue(current, workInProgress) { - // Clone the update queue from current. Unless it's already a clone. - var queue = workInProgress.updateQueue; - var currentQueue = current.updateQueue; + var didScheduleMicrotask_act = false; // Used to quickly bail out of flushSync if there's no sync work to do. - if (queue === currentQueue) { - var clone = { - baseState: currentQueue.baseState, - firstBaseUpdate: currentQueue.firstBaseUpdate, - lastBaseUpdate: currentQueue.lastBaseUpdate, - shared: currentQueue.shared, - callbacks: null - }; - workInProgress.updateQueue = clone; + 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$3.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$3.isBatchingLegacy && root.tag === LegacyRoot) { + // Special `act` case: Record whenever a legacy update is scheduled. + ReactCurrentActQueue$3.didScheduleLegacyUpdate = true; } } - function createUpdate(lane) { - var update = { - lane: lane, - tag: UpdateState, - payload: null, - callback: null, - next: null - }; - return update; + 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 enqueueUpdate(fiber, update, lane) { - var updateQueue = fiber.updateQueue; - if (updateQueue === null) { - // Only occurs if the fiber has been unmounted. - return null; + function flushSyncWorkAcrossRoots_impl(onlyLegacy) { + if (isFlushingWork) { + // Prevent reentrancy. + // TODO: Is this overly defensive? The callers must check the execution + // context first regardless. + return; } - var sharedQueue = updateQueue.shared; + if (!mightHavePendingSyncWork) { + // Fast path. There's no sync work to do. + return; + } // There may or may not be synchronous work scheduled. Let's check. - { - if ( - currentlyProcessingQueue === sharedQueue && - !didWarnUpdateInsideUpdate - ) { - var componentName = getComponentNameFromFiber(fiber); + var didPerformSomeWork; + var errors = null; + isFlushingWork = true; - error( - "An update (setState, replaceState, or forceUpdate) was scheduled " + - "from inside an update function. Update functions should be pure, " + - "with zero side-effects. Consider using componentDidUpdate or a " + - "callback.\n\nPlease update the following component: %s", - componentName - ); + do { + didPerformSomeWork = false; + var root = firstScheduledRoot; - didWarnUpdateInsideUpdate = true; - } - } + while (root !== null) { + if (onlyLegacy && root.tag !== LegacyRoot); + else { + var workInProgressRoot = getWorkInProgressRoot(); + var workInProgressRootRenderLanes = + getWorkInProgressRootRenderLanes(); + var nextLanes = getNextLanes( + root, + root === workInProgressRoot + ? workInProgressRootRenderLanes + : NoLanes + ); - if (isUnsafeClassRenderPhaseUpdate()) { - // This is an unsafe render phase update. Add directly to the update - // queue so we can process it immediately during the current render. - var pending = sharedQueue.pending; + if (includesSyncLane(nextLanes)) { + // This root has pending sync work. Flush it now. + try { + didPerformSomeWork = true; + performSyncWorkOnRoot(root, nextLanes); + } catch (error) { + // Collect errors so we can rethrow them at the end + if (errors === null) { + errors = [error]; + } else { + errors.push(error); + } + } + } + } - if (pending === null) { - // This is the first update. Create a circular list. - update.next = update; - } else { - update.next = pending.next; - pending.next = update; + root = root.next; } + } while (didPerformSomeWork); - sharedQueue.pending = update; // Update the childLanes even though we're most likely already rendering - // this fiber. This is for backwards compatibility in the case where you - // update a different component during render phase than the one that is - // currently renderings (a pattern that is accompanied by a warning). + 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. - return unsafe_markUpdateLaneFromFiberToRoot(fiber, lane); - } else { - return enqueueConcurrentClassUpdate(fiber, sharedQueue, update, lane); + 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 entangleTransitions(root, fiber, lane) { - var updateQueue = fiber.updateQueue; - if (updateQueue === null) { - // Only occurs if the fiber has been unmounted. - return; - } + function throwError(error) { + throw error; + } - var sharedQueue = updateQueue.shared; + function processRootScheduleInMicrotask() { + // This function is always called inside a microtask. It should never be + // called synchronously. + didScheduleMicrotask = false; - if (isTransitionLane(lane)) { - var queueLanes = sharedQueue.lanes; // If any entangled lanes are no longer pending on the root, then they must - // have finished. We can remove them from the shared queue, which represents - // a superset of the actually pending lanes. In some cases we may entangle - // more than we need to, but that's OK. In fact it's worse if we *don't* - // entangle when we should. + { + didScheduleMicrotask_act = false; + } // We'll recompute this as we iterate through all the roots and schedule them. - queueLanes = intersectLanes(queueLanes, root.pendingLanes); // Entangle the new transition lane with the other transition lanes. + mightHavePendingSyncWork = false; + var currentTime = now$1(); + var prev = null; + var root = firstScheduledRoot; - var newQueueLanes = mergeLanes(queueLanes, lane); - sharedQueue.lanes = newQueueLanes; // Even if queue.lanes already include lane, we don't know for certain if - // the lane finished since the last time we entangled it. So we need to - // entangle it again, just to be sure. + while (root !== null) { + var next = root.next; - markRootEntangled(root, newQueueLanes); - } - } - function enqueueCapturedUpdate(workInProgress, capturedUpdate) { - // Captured updates are updates that are thrown by a child during the render - // phase. They should be discarded if the render is aborted. Therefore, - // we should only put them on the work-in-progress queue, not the current one. - var queue = workInProgress.updateQueue; // Check if the work-in-progress queue is a clone. - - var current = workInProgress.alternate; - - if (current !== null) { - var currentQueue = current.updateQueue; - - if (queue === currentQueue) { - // The work-in-progress queue is the same as current. This happens when - // we bail out on a parent fiber that then captures an error thrown by - // a child. Since we want to append the update only to the work-in - // -progress queue, we need to clone the updates. We usually clone during - // processUpdateQueue, but that didn't happen in this case because we - // skipped over the parent when we bailed out. - var newFirst = null; - var newLast = null; - var firstBaseUpdate = queue.firstBaseUpdate; - - if (firstBaseUpdate !== null) { - // Loop through the updates and clone them. - var update = firstBaseUpdate; - - do { - var clone = { - lane: update.lane, - tag: update.tag, - payload: update.payload, - // When this update is rebased, we should not fire its - // callback again. - callback: null, - next: null - }; + if ( + currentEventTransitionLane !== NoLane && + shouldAttemptEagerTransition() + ) { + // A transition was scheduled during an event, but we're going to try to + // render it synchronously anyway. We do this during a popstate event to + // preserve the scroll position of the previous page. + upgradePendingLaneToSync(root, currentEventTransitionLane); + } - if (newLast === null) { - newFirst = newLast = clone; - } else { - newLast.next = clone; - newLast = clone; - } // $FlowFixMe[incompatible-type] we bail out when we get a null + var nextLanes = scheduleTaskForRootDuringMicrotask(root, currentTime); - update = update.next; - } while (update !== null); // Append the captured update the end of the cloned list. + 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 (newLast === null) { - newFirst = newLast = capturedUpdate; - } else { - newLast.next = capturedUpdate; - newLast = capturedUpdate; - } + if (prev === null) { + // This is the new head of the list + firstScheduledRoot = next; } else { - // There are no base updates. - newFirst = newLast = capturedUpdate; + prev.next = next; } - queue = { - baseState: currentQueue.baseState, - firstBaseUpdate: newFirst, - lastBaseUpdate: newLast, - shared: currentQueue.shared, - callbacks: currentQueue.callbacks - }; - workInProgress.updateQueue = queue; - return; - } - } // Append the update to the end of the list. + 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; - var lastBaseUpdate = queue.lastBaseUpdate; + if (includesSyncLane(nextLanes)) { + mightHavePendingSyncWork = true; + } + } - if (lastBaseUpdate === null) { - queue.firstBaseUpdate = capturedUpdate; - } else { - lastBaseUpdate.next = capturedUpdate; + root = next; } - queue.lastBaseUpdate = capturedUpdate; - } - - function getStateFromUpdate( - workInProgress, - queue, - update, - prevState, - nextProps, - instance - ) { - switch (update.tag) { - case ReplaceState: { - var payload = update.payload; - - if (typeof payload === "function") { - // Updater function - { - enterDisallowedContextReadInDEV(); - } - - var nextState = payload.call(instance, prevState, nextProps); - - { - if (workInProgress.mode & StrictLegacyMode) { - setIsStrictModeForDevtools(true); + 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. - try { - payload.call(instance, prevState, nextProps); - } finally { - setIsStrictModeForDevtools(false); - } - } + flushSyncWorkOnAllRoots(); + } - exitDisallowedContextReadInDEV(); - } + 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. - return nextState; - } // State object + var workInProgressRoot = getWorkInProgressRoot(); + var workInProgressRootRenderLanes = getWorkInProgressRootRenderLanes(); + var nextLanes = getNextLanes( + root, + root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes + ); + var existingCallbackNode = root.callbackNode; - return payload; + 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); } - case CaptureUpdate: { - workInProgress.flags = - (workInProgress.flags & ~ShouldCapture) | DidCapture; + 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); } - // Intentional fallthrough - case UpdateState: { - var _payload = update.payload; - var partialState; + 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 (typeof _payload === "function") { - // Updater function - { - enterDisallowedContextReadInDEV(); - } + 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$3.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); + } - partialState = _payload.call(instance, prevState, nextProps); + var schedulerPriorityLevel; - { - if (workInProgress.mode & StrictLegacyMode) { - setIsStrictModeForDevtools(true); + switch (lanesToEventPriority(nextLanes)) { + case DiscreteEventPriority: + schedulerPriorityLevel = ImmediatePriority; + break; - try { - _payload.call(instance, prevState, nextProps); - } finally { - setIsStrictModeForDevtools(false); - } - } + case ContinuousEventPriority: + schedulerPriorityLevel = UserBlockingPriority; + break; - exitDisallowedContextReadInDEV(); - } - } else { - // Partial state object - partialState = _payload; - } + case DefaultEventPriority: + schedulerPriorityLevel = NormalPriority; + break; - if (partialState === null || partialState === undefined) { - // Null and undefined are treated as no-ops. - return prevState; - } // Merge the partial state and the previous state. + case IdleEventPriority: + schedulerPriorityLevel = IdlePriority; + break; - return assign({}, prevState, partialState); + default: + schedulerPriorityLevel = NormalPriority; + break; } - case ForceUpdate: { - hasForceUpdate = true; - return prevState; - } + var newCallbackNode = scheduleCallback$1( + schedulerPriorityLevel, + performConcurrentWorkOnRoot.bind(null, root) + ); + root.callbackPriority = newCallbackPriority; + root.callbackNode = newCallbackNode; + return newCallbackPriority; } - - return prevState; } - function processUpdateQueue(workInProgress, props, instance, renderLanes) { - // This is always non-null on a ClassComponent or HostRoot - var queue = workInProgress.updateQueue; - hasForceUpdate = false; + 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()); - { - currentlyProcessingQueue = queue.shared; + if (root.callbackNode === originalCallbackNode) { + // The task node scheduled for this root is the same one that's + // currently executed. Need to return a continuation. + return performConcurrentWorkOnRoot.bind(null, root); } - var firstBaseUpdate = queue.firstBaseUpdate; - var lastBaseUpdate = queue.lastBaseUpdate; // Check if there are pending updates. If so, transfer them to the base queue. + return null; + } + var fakeActCallbackNode$1 = {}; - var pendingQueue = queue.shared.pending; + function scheduleCallback$1(priorityLevel, callback) { + if (ReactCurrentActQueue$3.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$3.current.push(callback); + return fakeActCallbackNode$1; + } else { + return scheduleCallback$2(priorityLevel, callback); + } + } - if (pendingQueue !== null) { - queue.shared.pending = null; // The pending queue is circular. Disconnect the pointer between first - // and last so that it's non-circular. + function cancelCallback(callbackNode) { + if (callbackNode === fakeActCallbackNode$1); + else if (callbackNode !== null) { + cancelCallback$1(callbackNode); + } + } - var lastPendingUpdate = pendingQueue; - var firstPendingUpdate = lastPendingUpdate.next; - lastPendingUpdate.next = null; // Append pending updates to base queue + function scheduleImmediateTask(cb) { + if (ReactCurrentActQueue$3.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$3.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 (lastBaseUpdate === null) { - firstBaseUpdate = firstPendingUpdate; - } else { - lastBaseUpdate.next = firstPendingUpdate; - } + if (supportsMicrotasks) { + 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(); - lastBaseUpdate = lastPendingUpdate; // If there's a current queue, and it's different from the base queue, then - // we need to transfer the updates to that queue, too. Because the base - // queue is a singly-linked list with no cycles, we can append to both - // lists and take advantage of structural sharing. - // TODO: Pass `current` as argument + if ( + (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$2(ImmediatePriority, cb); + return; + } - var current = workInProgress.alternate; + cb(); + }); + } else { + // If microtasks are not supported, use Scheduler. + scheduleCallback$2(ImmediatePriority, cb); + } + } - if (current !== null) { - // This is always non-null on a ClassComponent or HostRoot - var currentQueue = current.updateQueue; - var currentLastBaseUpdate = currentQueue.lastBaseUpdate; + 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(); + } - if (currentLastBaseUpdate !== lastBaseUpdate) { - if (currentLastBaseUpdate === null) { - currentQueue.firstBaseUpdate = firstPendingUpdate; - } else { - currentLastBaseUpdate.next = firstPendingUpdate; - } + return currentEventTransitionLane; + } - currentQueue.lastBaseUpdate = lastPendingUpdate; - } - } - } // These values may change as we process the queue. + // transition updates that occur while the async action is still in progress + // are treated as part of the action. + // + // The ideal behavior would be to treat each async function as an independent + // action. However, without a mechanism like AsyncContext, we can't tell which + // action an update corresponds to. So instead, we entangle them all into one. + // The listeners to notify once the entangled scope completes. - if (firstBaseUpdate !== null) { - // Iterate through the list of updates to compute the result. - var newState = queue.baseState; // TODO: Don't need to accumulate this. Instead, we can remove renderLanes - // from the original lanes. + var currentEntangledListeners = null; // The number of pending async actions in the entangled scope. - var newLanes = NoLanes; - var newBaseState = null; - var newFirstBaseUpdate = null; - var newLastBaseUpdate = null; - var update = firstBaseUpdate; + var currentEntangledPendingCount = 0; // The transition lane shared by all updates in the entangled scope. - do { - // An extra OffscreenLane bit is added to updates that were made to - // a hidden tree, so that we can distinguish them from updates that were - // already there when the tree was hidden. - var updateLane = removeLanes(update.lane, OffscreenLane); - var isHiddenUpdate = updateLane !== update.lane; // Check if this update was made while the tree was hidden. If so, then - // it's not a "base" update and we should disregard the extra base lanes - // that were added to renderLanes when we entered the Offscreen tree. + var currentEntangledLane = NoLane; // A thenable that resolves when the entangled scope completes. It does not + // resolve to a particular value because it's only used for suspending the UI + // until the async action scope has completed. - var shouldSkipUpdate = isHiddenUpdate - ? !isSubsetOfLanes(getWorkInProgressRootRenderLanes(), updateLane) - : !isSubsetOfLanes(renderLanes, updateLane); + var currentEntangledActionThenable = null; + function entangleAsyncAction(thenable) { + // `thenable` is the return value of the async action scope function. Create + // a combined thenable that resolves once every entangled scope function + // has finished. + if (currentEntangledListeners === null) { + // There's no outer async action scope. Create a new one. + var entangledListeners = (currentEntangledListeners = []); + currentEntangledPendingCount = 0; + currentEntangledLane = requestTransitionLane(); + var entangledThenable = { + status: "pending", + value: undefined, + then: function (resolve) { + entangledListeners.push(resolve); + } + }; + currentEntangledActionThenable = entangledThenable; + } - if (shouldSkipUpdate) { - // Priority is insufficient. Skip this update. If this is the first - // skipped update, the previous update/state is the new base - // update/state. - var clone = { - lane: updateLane, - tag: update.tag, - payload: update.payload, - callback: update.callback, - next: null - }; + currentEntangledPendingCount++; + thenable.then(pingEngtangledActionScope, pingEngtangledActionScope); + return thenable; + } - if (newLastBaseUpdate === null) { - newFirstBaseUpdate = newLastBaseUpdate = clone; - newBaseState = newState; - } else { - newLastBaseUpdate = newLastBaseUpdate.next = clone; - } // Update the remaining priority in the queue. + function pingEngtangledActionScope() { + if ( + currentEntangledListeners !== null && + --currentEntangledPendingCount === 0 + ) { + // All the actions have finished. Close the entangled async action scope + // and notify all the listeners. + if (currentEntangledActionThenable !== null) { + var fulfilledThenable = currentEntangledActionThenable; + fulfilledThenable.status = "fulfilled"; + } - newLanes = mergeLanes(newLanes, updateLane); - } else { - // This update does have sufficient priority. - if (newLastBaseUpdate !== null) { - var _clone = { - // This update is going to be committed so we never want uncommit - // it. Using NoLane works because 0 is a subset of all bitmasks, so - // this will never be skipped by the check above. - lane: NoLane, - tag: update.tag, - payload: update.payload, - // When this update is rebased, we should not fire its - // callback again. - callback: null, - next: null - }; - newLastBaseUpdate = newLastBaseUpdate.next = _clone; - } // Process this update. + var listeners = currentEntangledListeners; + currentEntangledListeners = null; + currentEntangledLane = NoLane; + currentEntangledActionThenable = null; - newState = getStateFromUpdate( - workInProgress, - queue, - update, - newState, - props, - instance - ); - var callback = update.callback; + for (var i = 0; i < listeners.length; i++) { + var listener = listeners[i]; + listener(); + } + } + } - if (callback !== null) { - workInProgress.flags |= Callback; + function chainThenableValue(thenable, result) { + // Equivalent to: Promise.resolve(thenable).then(() => result), except we can + // cheat a bit since we know that that this thenable is only ever consumed + // by React. + // + // We don't technically require promise support on the client yet, hence this + // extra code. + var listeners = []; + var thenableWithOverride = { + status: "pending", + value: null, + reason: null, + then: function (resolve) { + listeners.push(resolve); + } + }; + thenable.then( + function (value) { + var fulfilledThenable = thenableWithOverride; + fulfilledThenable.status = "fulfilled"; + fulfilledThenable.value = result; - if (isHiddenUpdate) { - workInProgress.flags |= Visibility; - } + for (var i = 0; i < listeners.length; i++) { + var listener = listeners[i]; + listener(result); + } + }, + function (error) { + var rejectedThenable = thenableWithOverride; + rejectedThenable.status = "rejected"; + rejectedThenable.reason = error; - var callbacks = queue.callbacks; + for (var i = 0; i < listeners.length; i++) { + var listener = listeners[i]; // This is a perf hack where we call the `onFulfill` ping function + // instead of `onReject`, because we know that React is the only + // consumer of these promises, and it passes the same listener to both. + // We also know that it will read the error directly off the + // `.reason` field. - if (callbacks === null) { - queue.callbacks = [callback]; - } else { - callbacks.push(callback); - } - } - } // $FlowFixMe[incompatible-type] we bail out when we get a null - - update = update.next; - - if (update === null) { - pendingQueue = queue.shared.pending; - - if (pendingQueue === null) { - break; - } else { - // An update was scheduled from inside a reducer. Add the new - // pending updates to the end of the list and keep processing. - var _lastPendingUpdate = pendingQueue; // Intentionally unsound. Pending updates form a circular list, but we - // unravel them when transferring them to the base queue. - - var _firstPendingUpdate = _lastPendingUpdate.next; - _lastPendingUpdate.next = null; - update = _firstPendingUpdate; - queue.lastBaseUpdate = _lastPendingUpdate; - queue.shared.pending = null; - } + listener(undefined); } - } while (true); - - if (newLastBaseUpdate === null) { - newBaseState = newState; } + ); + return thenableWithOverride; + } + function peekEntangledActionLane() { + return currentEntangledLane; + } + function peekEntangledActionThenable() { + return currentEntangledActionThenable; + } - queue.baseState = newBaseState; - queue.firstBaseUpdate = newFirstBaseUpdate; - queue.lastBaseUpdate = newLastBaseUpdate; + var UpdateState = 0; + var ReplaceState = 1; + var ForceUpdate = 2; + var CaptureUpdate = 3; // Global state that is reset at the beginning of calling `processUpdateQueue`. + // It should only be read right after calling `processUpdateQueue`, via + // `checkHasForceUpdateAfterProcessing`. - if (firstBaseUpdate === null) { - // `queue.lanes` is used for entangling transitions. We can set it back to - // zero once the queue is empty. - queue.shared.lanes = NoLanes; - } // Set the remaining expiration time to be whatever is remaining in the queue. - // This should be fine because the only two other things that contribute to - // expiration time are props and context. We're already in the middle of the - // begin phase by the time we start processing the queue, so we've already - // dealt with the props. Context in components that specify - // shouldComponentUpdate is tricky; but we'll have to account for - // that regardless. + var hasForceUpdate = false; + var didWarnUpdateInsideUpdate; + var currentlyProcessingQueue; - markSkippedUpdateLanes(newLanes); - workInProgress.lanes = newLanes; - workInProgress.memoizedState = newState; - } + { + didWarnUpdateInsideUpdate = false; + currentlyProcessingQueue = null; + } - { - currentlyProcessingQueue = null; + function initializeUpdateQueue(fiber) { + var queue = { + baseState: fiber.memoizedState, + firstBaseUpdate: null, + lastBaseUpdate: null, + shared: { + pending: null, + lanes: NoLanes, + hiddenCallbacks: null + }, + callbacks: null + }; + fiber.updateQueue = queue; + } + function cloneUpdateQueue(current, workInProgress) { + // Clone the update queue from current. Unless it's already a clone. + var queue = workInProgress.updateQueue; + var currentQueue = current.updateQueue; + + if (queue === currentQueue) { + var clone = { + baseState: currentQueue.baseState, + firstBaseUpdate: currentQueue.firstBaseUpdate, + lastBaseUpdate: currentQueue.lastBaseUpdate, + shared: currentQueue.shared, + callbacks: null + }; + workInProgress.updateQueue = clone; } } + function createUpdate(lane) { + var update = { + lane: lane, + tag: UpdateState, + payload: null, + callback: null, + next: null + }; + return update; + } + function enqueueUpdate(fiber, update, lane) { + var updateQueue = fiber.updateQueue; - function callCallback(callback, context) { - if (typeof callback !== "function") { - throw new Error( - "Invalid argument passed as callback. Expected a function. Instead " + - ("received: " + callback) - ); + if (updateQueue === null) { + // Only occurs if the fiber has been unmounted. + return null; } - callback.call(context); - } + var sharedQueue = updateQueue.shared; - function resetHasForceUpdateBeforeProcessing() { - hasForceUpdate = false; - } - function checkHasForceUpdateAfterProcessing() { - return hasForceUpdate; - } - function deferHiddenCallbacks(updateQueue) { - // When an update finishes on a hidden component, its callback should not - // be fired until/unless the component is made visible again. Stash the - // callback on the shared queue object so it can be fired later. - var newHiddenCallbacks = updateQueue.callbacks; + { + if ( + currentlyProcessingQueue === sharedQueue && + !didWarnUpdateInsideUpdate + ) { + var componentName = getComponentNameFromFiber(fiber); - if (newHiddenCallbacks !== null) { - var existingHiddenCallbacks = updateQueue.shared.hiddenCallbacks; + error( + "An update (setState, replaceState, or forceUpdate) was scheduled " + + "from inside an update function. Update functions should be pure, " + + "with zero side-effects. Consider using componentDidUpdate or a " + + "callback.\n\nPlease update the following component: %s", + componentName + ); - if (existingHiddenCallbacks === null) { - updateQueue.shared.hiddenCallbacks = newHiddenCallbacks; - } else { - updateQueue.shared.hiddenCallbacks = - existingHiddenCallbacks.concat(newHiddenCallbacks); + didWarnUpdateInsideUpdate = true; } } - } - function commitHiddenCallbacks(updateQueue, context) { - // This component is switching from hidden -> visible. Commit any callbacks - // that were previously deferred. - var hiddenCallbacks = updateQueue.shared.hiddenCallbacks; - if (hiddenCallbacks !== null) { - updateQueue.shared.hiddenCallbacks = null; + if (isUnsafeClassRenderPhaseUpdate()) { + // This is an unsafe render phase update. Add directly to the update + // queue so we can process it immediately during the current render. + var pending = sharedQueue.pending; - for (var i = 0; i < hiddenCallbacks.length; i++) { - var callback = hiddenCallbacks[i]; - callCallback(callback, context); + if (pending === null) { + // This is the first update. Create a circular list. + update.next = update; + } else { + update.next = pending.next; + pending.next = update; } - } - } - function commitCallbacks(updateQueue, context) { - var callbacks = updateQueue.callbacks; - if (callbacks !== null) { - updateQueue.callbacks = null; + sharedQueue.pending = update; // Update the childLanes even though we're most likely already rendering + // this fiber. This is for backwards compatibility in the case where you + // update a different component during render phase than the one that is + // currently renderings (a pattern that is accompanied by a warning). - for (var i = 0; i < callbacks.length; i++) { - var callback = callbacks[i]; - callCallback(callback, context); - } + return unsafe_markUpdateLaneFromFiberToRoot(fiber, lane); + } else { + return enqueueConcurrentClassUpdate(fiber, sharedQueue, update, lane); } } + function entangleTransitions(root, fiber, lane) { + var updateQueue = fiber.updateQueue; - /** - * Performs equality by iterating through keys on an object and returning false - * when any key has values which are not strictly equal between the arguments. - * Returns true when the values of all keys are strictly equal. - */ - - function shallowEqual(objA, objB) { - if (objectIs(objA, objB)) { - return true; + if (updateQueue === null) { + // Only occurs if the fiber has been unmounted. + return; } - if ( - typeof objA !== "object" || - objA === null || - typeof objB !== "object" || - objB === null - ) { - return false; - } + var sharedQueue = updateQueue.shared; - var keysA = Object.keys(objA); - var keysB = Object.keys(objB); + if (isTransitionLane(lane)) { + var queueLanes = sharedQueue.lanes; // If any entangled lanes are no longer pending on the root, then they must + // have finished. We can remove them from the shared queue, which represents + // a superset of the actually pending lanes. In some cases we may entangle + // more than we need to, but that's OK. In fact it's worse if we *don't* + // entangle when we should. - if (keysA.length !== keysB.length) { - return false; - } // Test for A's keys different from B. + queueLanes = intersectLanes(queueLanes, root.pendingLanes); // Entangle the new transition lane with the other transition lanes. - for (var i = 0; i < keysA.length; i++) { - var currentKey = keysA[i]; + var newQueueLanes = mergeLanes(queueLanes, lane); + sharedQueue.lanes = newQueueLanes; // Even if queue.lanes already include lane, we don't know for certain if + // the lane finished since the last time we entangled it. So we need to + // entangle it again, just to be sure. - if ( - !hasOwnProperty.call(objB, currentKey) || // $FlowFixMe[incompatible-use] lost refinement of `objB` - !objectIs(objA[currentKey], objB[currentKey]) - ) { - return false; - } + markRootEntangled(root, newQueueLanes); } - - return true; } + function enqueueCapturedUpdate(workInProgress, capturedUpdate) { + // Captured updates are updates that are thrown by a child during the render + // phase. They should be discarded if the render is aborted. Therefore, + // we should only put them on the work-in-progress queue, not the current one. + var queue = workInProgress.updateQueue; // Check if the work-in-progress queue is a clone. - function describeFiber(fiber) { - var owner = fiber._debugOwner ? fiber._debugOwner.type : null; - var source = fiber._debugSource; - - switch (fiber.tag) { - case HostHoistable: - case HostSingleton: - case HostComponent: - return describeBuiltInComponentFrame(fiber.type, source, owner); + var current = workInProgress.alternate; - case LazyComponent: - return describeBuiltInComponentFrame("Lazy", source, owner); + if (current !== null) { + var currentQueue = current.updateQueue; - case SuspenseComponent: - return describeBuiltInComponentFrame("Suspense", source, owner); + if (queue === currentQueue) { + // The work-in-progress queue is the same as current. This happens when + // we bail out on a parent fiber that then captures an error thrown by + // a child. Since we want to append the update only to the work-in + // -progress queue, we need to clone the updates. We usually clone during + // processUpdateQueue, but that didn't happen in this case because we + // skipped over the parent when we bailed out. + var newFirst = null; + var newLast = null; + var firstBaseUpdate = queue.firstBaseUpdate; - case SuspenseListComponent: - return describeBuiltInComponentFrame("SuspenseList", source, owner); + if (firstBaseUpdate !== null) { + // Loop through the updates and clone them. + var update = firstBaseUpdate; - case FunctionComponent: - case IndeterminateComponent: - case SimpleMemoComponent: - return describeFunctionComponentFrame(fiber.type, source, owner); + do { + var clone = { + lane: update.lane, + tag: update.tag, + payload: update.payload, + // When this update is rebased, we should not fire its + // callback again. + callback: null, + next: null + }; - case ForwardRef: - return describeFunctionComponentFrame( - fiber.type.render, - source, - owner - ); + if (newLast === null) { + newFirst = newLast = clone; + } else { + newLast.next = clone; + newLast = clone; + } // $FlowFixMe[incompatible-type] we bail out when we get a null - case ClassComponent: - return describeClassComponentFrame(fiber.type, source, owner); + update = update.next; + } while (update !== null); // Append the captured update the end of the cloned list. - default: - return ""; + if (newLast === null) { + newFirst = newLast = capturedUpdate; + } else { + newLast.next = capturedUpdate; + newLast = capturedUpdate; + } + } else { + // There are no base updates. + newFirst = newLast = capturedUpdate; + } + + queue = { + baseState: currentQueue.baseState, + firstBaseUpdate: newFirst, + lastBaseUpdate: newLast, + shared: currentQueue.shared, + callbacks: currentQueue.callbacks + }; + workInProgress.updateQueue = queue; + return; + } + } // Append the update to the end of the list. + + var lastBaseUpdate = queue.lastBaseUpdate; + + if (lastBaseUpdate === null) { + queue.firstBaseUpdate = capturedUpdate; + } else { + lastBaseUpdate.next = capturedUpdate; } + + queue.lastBaseUpdate = capturedUpdate; } - function getStackByFiberInDevAndProd(workInProgress) { - try { - var info = ""; - var node = workInProgress; + function getStateFromUpdate( + workInProgress, + queue, + update, + prevState, + nextProps, + instance + ) { + switch (update.tag) { + case ReplaceState: { + var payload = update.payload; - do { - info += describeFiber(node); // $FlowFixMe[incompatible-type] we bail out when we get a null + if (typeof payload === "function") { + // Updater function + { + enterDisallowedContextReadInDEV(); + } - node = node.return; - } while (node); + var nextState = payload.call(instance, prevState, nextProps); - return info; - } catch (x) { - return "\nError generating stack: " + x.message + "\n" + x.stack; - } - } + { + if (workInProgress.mode & StrictLegacyMode) { + setIsStrictModeForDevtools(true); - var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; - var current = null; - var isRendering = false; - function getCurrentFiberOwnerNameInDevOrNull() { - { - if (current === null) { - return null; + try { + payload.call(instance, prevState, nextProps); + } finally { + setIsStrictModeForDevtools(false); + } + } + + exitDisallowedContextReadInDEV(); + } + + return nextState; + } // State object + + return payload; } - var owner = current._debugOwner; + case CaptureUpdate: { + workInProgress.flags = + (workInProgress.flags & ~ShouldCapture) | DidCapture; + } + // Intentional fallthrough - if (owner !== null && typeof owner !== "undefined") { - return getComponentNameFromFiber(owner); + case UpdateState: { + var _payload = update.payload; + var partialState; + + if (typeof _payload === "function") { + // Updater function + { + enterDisallowedContextReadInDEV(); + } + + partialState = _payload.call(instance, prevState, nextProps); + + { + if (workInProgress.mode & StrictLegacyMode) { + setIsStrictModeForDevtools(true); + + try { + _payload.call(instance, prevState, nextProps); + } finally { + setIsStrictModeForDevtools(false); + } + } + + exitDisallowedContextReadInDEV(); + } + } else { + // Partial state object + partialState = _payload; + } + + if (partialState === null || partialState === undefined) { + // Null and undefined are treated as no-ops. + return prevState; + } // Merge the partial state and the previous state. + + return assign({}, prevState, partialState); + } + + case ForceUpdate: { + hasForceUpdate = true; + return prevState; } } - return null; + return prevState; } - function getCurrentFiberStackInDev() { - { - if (current === null) { - return ""; - } // Safe because if current fiber exists, we are reconciling, - // and it is guaranteed to be the work-in-progress version. + var didReadFromEntangledAsyncAction = false; // Each call to processUpdateQueue should be accompanied by a call to this. It's + // only in a separate function because in updateHostRoot, it must happen after + // all the context stacks have been pushed to, to prevent a stack mismatch. A + // bit unfortunate. - return getStackByFiberInDevAndProd(current); - } - } + function suspendIfUpdateReadFromEntangledAsyncAction() { + // Check if this update is part of a pending async action. If so, we'll + // need to suspend until the action has finished, so that it's batched + // together with future updates in the same action. + // TODO: Once we support hooks inside useMemo (or an equivalent + // memoization boundary like Forget), hoist this logic so that it only + // suspends if the memo boundary produces a new value. + if (didReadFromEntangledAsyncAction) { + var entangledActionThenable = peekEntangledActionThenable(); - function resetCurrentFiber() { - { - ReactDebugCurrentFrame.getCurrentStack = null; - current = null; - isRendering = false; - } - } - function setCurrentFiber(fiber) { - { - ReactDebugCurrentFrame.getCurrentStack = - fiber === null ? null : getCurrentFiberStackInDev; - current = fiber; - isRendering = false; - } - } - function getCurrentFiber() { - { - return current; + if (entangledActionThenable !== null) { + // TODO: Instead of the throwing the thenable directly, throw a + // special object like `use` does so we can detect if it's captured + // by userspace. + throw entangledActionThenable; + } } } - function setIsRendering(rendering) { + function processUpdateQueue(workInProgress, props, instance, renderLanes) { + didReadFromEntangledAsyncAction = false; // This is always non-null on a ClassComponent or HostRoot + + var queue = workInProgress.updateQueue; + hasForceUpdate = false; + { - isRendering = rendering; + currentlyProcessingQueue = queue.shared; } - } - var ReactStrictModeWarnings = { - recordUnsafeLifecycleWarnings: function (fiber, instance) {}, - flushPendingUnsafeLifecycleWarnings: function () {}, - recordLegacyContextWarning: function (fiber, instance) {}, - flushLegacyContextWarning: function () {}, - discardPendingWarnings: function () {} - }; + var firstBaseUpdate = queue.firstBaseUpdate; + var lastBaseUpdate = queue.lastBaseUpdate; // Check if there are pending updates. If so, transfer them to the base queue. - { - var findStrictRoot = function (fiber) { - var maybeStrictRoot = null; - var node = fiber; + var pendingQueue = queue.shared.pending; - while (node !== null) { - if (node.mode & StrictLegacyMode) { - maybeStrictRoot = node; - } + if (pendingQueue !== null) { + queue.shared.pending = null; // The pending queue is circular. Disconnect the pointer between first + // and last so that it's non-circular. - node = node.return; + var lastPendingUpdate = pendingQueue; + var firstPendingUpdate = lastPendingUpdate.next; + lastPendingUpdate.next = null; // Append pending updates to base queue + + if (lastBaseUpdate === null) { + firstBaseUpdate = firstPendingUpdate; + } else { + lastBaseUpdate.next = firstPendingUpdate; } - return maybeStrictRoot; - }; - - var setToSortedString = function (set) { - var array = []; - set.forEach(function (value) { - array.push(value); - }); - return array.sort().join(", "); - }; - - var pendingComponentWillMountWarnings = []; - var pendingUNSAFE_ComponentWillMountWarnings = []; - var pendingComponentWillReceivePropsWarnings = []; - var pendingUNSAFE_ComponentWillReceivePropsWarnings = []; - var pendingComponentWillUpdateWarnings = []; - var pendingUNSAFE_ComponentWillUpdateWarnings = []; // Tracks components we have already warned about. - - var didWarnAboutUnsafeLifecycles = new Set(); + lastBaseUpdate = lastPendingUpdate; // If there's a current queue, and it's different from the base queue, then + // we need to transfer the updates to that queue, too. Because the base + // queue is a singly-linked list with no cycles, we can append to both + // lists and take advantage of structural sharing. + // TODO: Pass `current` as argument - ReactStrictModeWarnings.recordUnsafeLifecycleWarnings = function ( - fiber, - instance - ) { - // Dedupe strategy: Warn once per component. - if (didWarnAboutUnsafeLifecycles.has(fiber.type)) { - return; - } + var current = workInProgress.alternate; - if ( - typeof instance.componentWillMount === "function" && // Don't warn about react-lifecycles-compat polyfilled components. - instance.componentWillMount.__suppressDeprecationWarning !== true - ) { - pendingComponentWillMountWarnings.push(fiber); - } + if (current !== null) { + // This is always non-null on a ClassComponent or HostRoot + var currentQueue = current.updateQueue; + var currentLastBaseUpdate = currentQueue.lastBaseUpdate; - if ( - fiber.mode & StrictLegacyMode && - typeof instance.UNSAFE_componentWillMount === "function" - ) { - pendingUNSAFE_ComponentWillMountWarnings.push(fiber); - } + if (currentLastBaseUpdate !== lastBaseUpdate) { + if (currentLastBaseUpdate === null) { + currentQueue.firstBaseUpdate = firstPendingUpdate; + } else { + currentLastBaseUpdate.next = firstPendingUpdate; + } - if ( - typeof instance.componentWillReceiveProps === "function" && - instance.componentWillReceiveProps.__suppressDeprecationWarning !== - true - ) { - pendingComponentWillReceivePropsWarnings.push(fiber); + currentQueue.lastBaseUpdate = lastPendingUpdate; + } } + } // These values may change as we process the queue. - if ( - fiber.mode & StrictLegacyMode && - typeof instance.UNSAFE_componentWillReceiveProps === "function" - ) { - pendingUNSAFE_ComponentWillReceivePropsWarnings.push(fiber); - } + if (firstBaseUpdate !== null) { + // Iterate through the list of updates to compute the result. + var newState = queue.baseState; // TODO: Don't need to accumulate this. Instead, we can remove renderLanes + // from the original lanes. - if ( - typeof instance.componentWillUpdate === "function" && - instance.componentWillUpdate.__suppressDeprecationWarning !== true - ) { - pendingComponentWillUpdateWarnings.push(fiber); - } + var newLanes = NoLanes; + var newBaseState = null; + var newFirstBaseUpdate = null; + var newLastBaseUpdate = null; + var update = firstBaseUpdate; - if ( - fiber.mode & StrictLegacyMode && - typeof instance.UNSAFE_componentWillUpdate === "function" - ) { - pendingUNSAFE_ComponentWillUpdateWarnings.push(fiber); - } - }; + do { + // An extra OffscreenLane bit is added to updates that were made to + // a hidden tree, so that we can distinguish them from updates that were + // already there when the tree was hidden. + var updateLane = removeLanes(update.lane, OffscreenLane); + var isHiddenUpdate = updateLane !== update.lane; // Check if this update was made while the tree was hidden. If so, then + // it's not a "base" update and we should disregard the extra base lanes + // that were added to renderLanes when we entered the Offscreen tree. - ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings = - function () { - // We do an initial pass to gather component names - var componentWillMountUniqueNames = new Set(); + var shouldSkipUpdate = isHiddenUpdate + ? !isSubsetOfLanes(getWorkInProgressRootRenderLanes(), updateLane) + : !isSubsetOfLanes(renderLanes, updateLane); - if (pendingComponentWillMountWarnings.length > 0) { - pendingComponentWillMountWarnings.forEach(function (fiber) { - componentWillMountUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingComponentWillMountWarnings = []; - } + if (shouldSkipUpdate) { + // Priority is insufficient. Skip this update. If this is the first + // skipped update, the previous update/state is the new base + // update/state. + var clone = { + lane: updateLane, + tag: update.tag, + payload: update.payload, + callback: update.callback, + next: null + }; - var UNSAFE_componentWillMountUniqueNames = new Set(); + if (newLastBaseUpdate === null) { + newFirstBaseUpdate = newLastBaseUpdate = clone; + newBaseState = newState; + } else { + newLastBaseUpdate = newLastBaseUpdate.next = clone; + } // Update the remaining priority in the queue. - if (pendingUNSAFE_ComponentWillMountWarnings.length > 0) { - pendingUNSAFE_ComponentWillMountWarnings.forEach(function (fiber) { - UNSAFE_componentWillMountUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingUNSAFE_ComponentWillMountWarnings = []; - } + newLanes = mergeLanes(newLanes, updateLane); + } else { + // This update does have sufficient priority. + // Check if this update is part of a pending async action. If so, + // we'll need to suspend until the action has finished, so that it's + // batched together with future updates in the same action. + if ( + updateLane !== NoLane && + updateLane === peekEntangledActionLane() + ) { + didReadFromEntangledAsyncAction = true; + } - var componentWillReceivePropsUniqueNames = new Set(); + if (newLastBaseUpdate !== null) { + var _clone = { + // This update is going to be committed so we never want uncommit + // it. Using NoLane works because 0 is a subset of all bitmasks, so + // this will never be skipped by the check above. + lane: NoLane, + tag: update.tag, + payload: update.payload, + // When this update is rebased, we should not fire its + // callback again. + callback: null, + next: null + }; + newLastBaseUpdate = newLastBaseUpdate.next = _clone; + } // Process this update. - if (pendingComponentWillReceivePropsWarnings.length > 0) { - pendingComponentWillReceivePropsWarnings.forEach(function (fiber) { - componentWillReceivePropsUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingComponentWillReceivePropsWarnings = []; - } + newState = getStateFromUpdate( + workInProgress, + queue, + update, + newState, + props, + instance + ); + var callback = update.callback; - var UNSAFE_componentWillReceivePropsUniqueNames = new Set(); + if (callback !== null) { + workInProgress.flags |= Callback; - if (pendingUNSAFE_ComponentWillReceivePropsWarnings.length > 0) { - pendingUNSAFE_ComponentWillReceivePropsWarnings.forEach( - function (fiber) { - UNSAFE_componentWillReceivePropsUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); + if (isHiddenUpdate) { + workInProgress.flags |= Visibility; } - ); - pendingUNSAFE_ComponentWillReceivePropsWarnings = []; - } - var componentWillUpdateUniqueNames = new Set(); + var callbacks = queue.callbacks; - if (pendingComponentWillUpdateWarnings.length > 0) { - pendingComponentWillUpdateWarnings.forEach(function (fiber) { - componentWillUpdateUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingComponentWillUpdateWarnings = []; - } + if (callbacks === null) { + queue.callbacks = [callback]; + } else { + callbacks.push(callback); + } + } + } // $FlowFixMe[incompatible-type] we bail out when we get a null - var UNSAFE_componentWillUpdateUniqueNames = new Set(); + update = update.next; - if (pendingUNSAFE_ComponentWillUpdateWarnings.length > 0) { - pendingUNSAFE_ComponentWillUpdateWarnings.forEach(function (fiber) { - UNSAFE_componentWillUpdateUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingUNSAFE_ComponentWillUpdateWarnings = []; - } // Finally, we flush all the warnings - // UNSAFE_ ones before the deprecated ones, since they'll be 'louder' + if (update === null) { + pendingQueue = queue.shared.pending; - if (UNSAFE_componentWillMountUniqueNames.size > 0) { - var sortedNames = setToSortedString( - UNSAFE_componentWillMountUniqueNames - ); + if (pendingQueue === null) { + break; + } else { + // An update was scheduled from inside a reducer. Add the new + // pending updates to the end of the list and keep processing. + var _lastPendingUpdate = pendingQueue; // Intentionally unsound. Pending updates form a circular list, but we + // unravel them when transferring them to the base queue. - error( - "Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code. " + - "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + - "* Move code with side effects to componentDidMount, and set initial state in the constructor.\n" + - "\nPlease update the following components: %s", - sortedNames - ); + var _firstPendingUpdate = _lastPendingUpdate.next; + _lastPendingUpdate.next = null; + update = _firstPendingUpdate; + queue.lastBaseUpdate = _lastPendingUpdate; + queue.shared.pending = null; + } } + } while (true); - if (UNSAFE_componentWillReceivePropsUniqueNames.size > 0) { - var _sortedNames = setToSortedString( - UNSAFE_componentWillReceivePropsUniqueNames - ); + if (newLastBaseUpdate === null) { + newBaseState = newState; + } - error( - "Using UNSAFE_componentWillReceiveProps in strict mode is not recommended " + - "and may indicate bugs in your code. " + - "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + - "* Move data fetching code or side effects to componentDidUpdate.\n" + - "* If you're updating state whenever props change, " + - "refactor your code to use memoization techniques or move it to " + - "static getDerivedStateFromProps. Learn more at: https://reactjs.org/link/derived-state\n" + - "\nPlease update the following components: %s", - _sortedNames - ); - } + queue.baseState = newBaseState; + queue.firstBaseUpdate = newFirstBaseUpdate; + queue.lastBaseUpdate = newLastBaseUpdate; - if (UNSAFE_componentWillUpdateUniqueNames.size > 0) { - var _sortedNames2 = setToSortedString( - UNSAFE_componentWillUpdateUniqueNames - ); + if (firstBaseUpdate === null) { + // `queue.lanes` is used for entangling transitions. We can set it back to + // zero once the queue is empty. + queue.shared.lanes = NoLanes; + } // Set the remaining expiration time to be whatever is remaining in the queue. + // This should be fine because the only two other things that contribute to + // expiration time are props and context. We're already in the middle of the + // begin phase by the time we start processing the queue, so we've already + // dealt with the props. Context in components that specify + // shouldComponentUpdate is tricky; but we'll have to account for + // that regardless. - error( - "Using UNSAFE_componentWillUpdate in strict mode is not recommended " + - "and may indicate bugs in your code. " + - "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + - "* Move data fetching code or side effects to componentDidUpdate.\n" + - "\nPlease update the following components: %s", - _sortedNames2 - ); - } + markSkippedUpdateLanes(newLanes); + workInProgress.lanes = newLanes; + workInProgress.memoizedState = newState; + } - if (componentWillMountUniqueNames.size > 0) { - var _sortedNames3 = setToSortedString( - componentWillMountUniqueNames - ); + { + currentlyProcessingQueue = null; + } + } - warn( - "componentWillMount has been renamed, and is not recommended for use. " + - "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + - "* Move code with side effects to componentDidMount, and set initial state in the constructor.\n" + - "* Rename componentWillMount to UNSAFE_componentWillMount to suppress " + - "this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. " + - "To rename all deprecated lifecycles to their new names, you can run " + - "`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n" + - "\nPlease update the following components: %s", - _sortedNames3 - ); - } + function callCallback(callback, context) { + if (typeof callback !== "function") { + throw new Error( + "Invalid argument passed as callback. Expected a function. Instead " + + ("received: " + callback) + ); + } - if (componentWillReceivePropsUniqueNames.size > 0) { - var _sortedNames4 = setToSortedString( - componentWillReceivePropsUniqueNames - ); + callback.call(context); + } - warn( - "componentWillReceiveProps has been renamed, and is not recommended for use. " + - "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + - "* Move data fetching code or side effects to componentDidUpdate.\n" + - "* If you're updating state whenever props change, refactor your " + - "code to use memoization techniques or move it to " + - "static getDerivedStateFromProps. Learn more at: https://reactjs.org/link/derived-state\n" + - "* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress " + - "this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. " + - "To rename all deprecated lifecycles to their new names, you can run " + - "`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n" + - "\nPlease update the following components: %s", - _sortedNames4 - ); - } + function resetHasForceUpdateBeforeProcessing() { + hasForceUpdate = false; + } + function checkHasForceUpdateAfterProcessing() { + return hasForceUpdate; + } + function deferHiddenCallbacks(updateQueue) { + // When an update finishes on a hidden component, its callback should not + // be fired until/unless the component is made visible again. Stash the + // callback on the shared queue object so it can be fired later. + var newHiddenCallbacks = updateQueue.callbacks; - if (componentWillUpdateUniqueNames.size > 0) { - var _sortedNames5 = setToSortedString( - componentWillUpdateUniqueNames - ); + if (newHiddenCallbacks !== null) { + var existingHiddenCallbacks = updateQueue.shared.hiddenCallbacks; - warn( - "componentWillUpdate has been renamed, and is not recommended for use. " + - "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + - "* Move data fetching code or side effects to componentDidUpdate.\n" + - "* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress " + - "this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. " + - "To rename all deprecated lifecycles to their new names, you can run " + - "`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n" + - "\nPlease update the following components: %s", - _sortedNames5 - ); - } - }; + if (existingHiddenCallbacks === null) { + updateQueue.shared.hiddenCallbacks = newHiddenCallbacks; + } else { + updateQueue.shared.hiddenCallbacks = + existingHiddenCallbacks.concat(newHiddenCallbacks); + } + } + } + function commitHiddenCallbacks(updateQueue, context) { + // This component is switching from hidden -> visible. Commit any callbacks + // that were previously deferred. + var hiddenCallbacks = updateQueue.shared.hiddenCallbacks; - var pendingLegacyContextWarning = new Map(); // Tracks components we have already warned about. + if (hiddenCallbacks !== null) { + updateQueue.shared.hiddenCallbacks = null; - var didWarnAboutLegacyContext = new Set(); + for (var i = 0; i < hiddenCallbacks.length; i++) { + var callback = hiddenCallbacks[i]; + callCallback(callback, context); + } + } + } + function commitCallbacks(updateQueue, context) { + var callbacks = updateQueue.callbacks; - ReactStrictModeWarnings.recordLegacyContextWarning = function ( - fiber, - instance - ) { - var strictRoot = findStrictRoot(fiber); + if (callbacks !== null) { + updateQueue.callbacks = null; - if (strictRoot === null) { - error( - "Expected to find a StrictMode component in a strict mode tree. " + - "This error is likely caused by a bug in React. Please file an issue." - ); + for (var i = 0; i < callbacks.length; i++) { + var callback = callbacks[i]; + callCallback(callback, context); + } + } + } - return; - } // Dedup strategy: Warn once per component. + /** + * Performs equality by iterating through keys on an object and returning false + * when any key has values which are not strictly equal between the arguments. + * Returns true when the values of all keys are strictly equal. + */ - if (didWarnAboutLegacyContext.has(fiber.type)) { - return; - } + function shallowEqual(objA, objB) { + if (objectIs(objA, objB)) { + return true; + } - var warningsForRoot = pendingLegacyContextWarning.get(strictRoot); + if ( + typeof objA !== "object" || + objA === null || + typeof objB !== "object" || + objB === null + ) { + return false; + } + + var keysA = Object.keys(objA); + var keysB = Object.keys(objB); + + if (keysA.length !== keysB.length) { + return false; + } // Test for A's keys different from B. + + for (var i = 0; i < keysA.length; i++) { + var currentKey = keysA[i]; if ( - fiber.type.contextTypes != null || - fiber.type.childContextTypes != null || - (instance !== null && typeof instance.getChildContext === "function") + !hasOwnProperty.call(objB, currentKey) || // $FlowFixMe[incompatible-use] lost refinement of `objB` + !objectIs(objA[currentKey], objB[currentKey]) ) { - if (warningsForRoot === undefined) { - warningsForRoot = []; - pendingLegacyContextWarning.set(strictRoot, warningsForRoot); - } - - warningsForRoot.push(fiber); + return false; } - }; + } - ReactStrictModeWarnings.flushLegacyContextWarning = function () { - pendingLegacyContextWarning.forEach(function (fiberArray, strictRoot) { - if (fiberArray.length === 0) { - return; - } + return true; + } - var firstFiber = fiberArray[0]; - var uniqueNames = new Set(); - fiberArray.forEach(function (fiber) { - uniqueNames.add(getComponentNameFromFiber(fiber) || "Component"); - didWarnAboutLegacyContext.add(fiber.type); - }); - var sortedNames = setToSortedString(uniqueNames); + function describeFiber(fiber) { + var owner = fiber._debugOwner ? fiber._debugOwner.type : null; + var source = fiber._debugSource; - try { - setCurrentFiber(firstFiber); + switch (fiber.tag) { + case HostHoistable: + case HostSingleton: + case HostComponent: + return describeBuiltInComponentFrame(fiber.type, source, owner); - error( - "Legacy context API has been detected within a strict-mode tree." + - "\n\nThe old API will be supported in all 16.x releases, but applications " + - "using it should migrate to the new version." + - "\n\nPlease update the following components: %s" + - "\n\nLearn more about this warning here: https://reactjs.org/link/legacy-context", - sortedNames - ); - } finally { - resetCurrentFiber(); - } - }); - }; + case LazyComponent: + return describeBuiltInComponentFrame("Lazy", source, owner); - ReactStrictModeWarnings.discardPendingWarnings = function () { - pendingComponentWillMountWarnings = []; - pendingUNSAFE_ComponentWillMountWarnings = []; - pendingComponentWillReceivePropsWarnings = []; - pendingUNSAFE_ComponentWillReceivePropsWarnings = []; - pendingComponentWillUpdateWarnings = []; - pendingUNSAFE_ComponentWillUpdateWarnings = []; - pendingLegacyContextWarning = new Map(); - }; - } + case SuspenseComponent: + return describeBuiltInComponentFrame("Suspense", source, owner); - /* - * The `'' + value` pattern (used in perf-sensitive code) throws for Symbol - * and Temporal.* types. See https://github.com/facebook/react/pull/22064. - * - * The functions in this module will throw an easier-to-understand, - * easier-to-debug exception with a clear errors message message explaining the - * problem. (Instead of a confusing exception thrown inside the implementation - * of the `value` object). - */ - // $FlowFixMe[incompatible-return] only called in DEV, so void return is not possible. - function typeName(value) { - { - // toStringTag is needed for namespaced types like Temporal.Instant - var hasToStringTag = typeof Symbol === "function" && Symbol.toStringTag; - var type = - (hasToStringTag && value[Symbol.toStringTag]) || - value.constructor.name || - "Object"; // $FlowFixMe[incompatible-return] + case SuspenseListComponent: + return describeBuiltInComponentFrame("SuspenseList", source, owner); - return type; - } - } // $FlowFixMe[incompatible-return] only called in DEV, so void return is not possible. + case FunctionComponent: + case IndeterminateComponent: + case SimpleMemoComponent: + return describeFunctionComponentFrame(fiber.type, source, owner); - function willCoercionThrow(value) { - { - try { - testStringCoercion(value); - return false; - } catch (e) { - return true; - } + case ForwardRef: + return describeFunctionComponentFrame( + fiber.type.render, + source, + owner + ); + + case ClassComponent: + return describeClassComponentFrame(fiber.type, source, owner); + + default: + return ""; } } - function testStringCoercion(value) { - // If you ended up here by following an exception call stack, here's what's - // happened: you supplied an object or symbol value to React (as a prop, key, - // DOM attribute, CSS property, string ref, etc.) and when React tried to - // coerce it to a string using `'' + value`, an exception was thrown. - // - // The most common types that will cause this exception are `Symbol` instances - // and Temporal objects like `Temporal.Instant`. But any object that has a - // `valueOf` or `[Symbol.toPrimitive]` method that throws will also cause this - // exception. (Library authors do this to prevent users from using built-in - // numeric operators like `+` or comparison operators like `>=` because custom - // methods are needed to perform accurate arithmetic or comparison.) - // - // To fix the problem, coerce this object or symbol value to a string before - // passing it to React. The most reliable way is usually `String(value)`. - // - // To find which value is throwing, check the browser or debugger console. - // Before this exception was thrown, there should be `console.error` output - // that shows the type (Symbol, Temporal.PlainDate, etc.) that caused the - // problem and how that type was used: key, atrribute, input value prop, etc. - // In most cases, this console output also shows the component and its - // ancestor components where the exception happened. - // - // eslint-disable-next-line react-internal/safe-string-coercion - return "" + value; - } - function checkKeyStringCoercion(value) { - { - if (willCoercionThrow(value)) { - error( - "The provided key is an unsupported type %s." + - " This value must be coerced to a string before using it here.", - typeName(value) - ); + function getStackByFiberInDevAndProd(workInProgress) { + try { + var info = ""; + var node = workInProgress; - return testStringCoercion(value); // throw (to help callers find troubleshooting comments) - } + do { + info += describeFiber(node); // $FlowFixMe[incompatible-type] we bail out when we get a null + + node = node.return; + } while (node); + + return info; + } catch (x) { + return "\nError generating stack: " + x.message + "\n" + x.stack; } } - function checkPropStringCoercion(value, propName) { + + var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; + var current = null; + var isRendering = false; + function getCurrentFiberOwnerNameInDevOrNull() { { - if (willCoercionThrow(value)) { - error( - "The provided `%s` prop is an unsupported type %s." + - " This value must be coerced to a string before using it here.", - propName, - typeName(value) - ); + if (current === null) { + return null; + } - return testStringCoercion(value); // throw (to help callers find troubleshooting comments) + var owner = current._debugOwner; + + if (owner !== null && typeof owner !== "undefined") { + return getComponentNameFromFiber(owner); } } + + return null; } - var ReactCurrentActQueue$3 = ReactSharedInternals.ReactCurrentActQueue; // An error that is thrown (e.g. by `use`) to trigger Suspense. If we - // detect this is caught by userspace, we'll log a warning in development. + function getCurrentFiberStackInDev() { + { + if (current === null) { + return ""; + } // Safe because if current fiber exists, we are reconciling, + // and it is guaranteed to be the work-in-progress version. - var SuspenseException = new Error( - "Suspense Exception: This is not a real error! It's an implementation " + - "detail of `use` to interrupt the current render. You must either " + - "rethrow it immediately, or move the `use` call outside of the " + - "`try/catch` block. Capturing without rethrowing will lead to " + - "unexpected behavior.\n\n" + - "To handle async errors, wrap your component in an error boundary, or " + - "call the promise's `.catch` method and pass the result to `use`" - ); - var SuspenseyCommitException = new Error( - "Suspense Exception: This is not a real error, and should not leak into " + - "userspace. If you're seeing this, it's likely a bug in React." - ); // This is a noop thenable that we use to trigger a fallback in throwException. - // TODO: It would be better to refactor throwException into multiple functions - // so we can trigger a fallback directly without having to check the type. But - // for now this will do. + return getStackByFiberInDevAndProd(current); + } + } - var noopSuspenseyCommitThenable = { - then: function () { - { - error( - "Internal React error: A listener was unexpectedly attached to a " + - '"noop" thenable. This is a bug in React. Please file an issue.' - ); - } + function resetCurrentFiber() { + { + ReactDebugCurrentFrame.getCurrentStack = null; + current = null; + isRendering = false; } - }; - function createThenableState() { - // The ThenableState is created the first time a component suspends. If it - // suspends again, we'll reuse the same state. - return []; } - function isThenableResolved(thenable) { - var status = thenable.status; - return status === "fulfilled" || status === "rejected"; + function setCurrentFiber(fiber) { + { + ReactDebugCurrentFrame.getCurrentStack = + fiber === null ? null : getCurrentFiberStackInDev; + current = fiber; + isRendering = false; + } } - - function noop() {} - - function trackUsedThenable(thenableState, thenable, index) { - if (ReactCurrentActQueue$3.current !== null) { - ReactCurrentActQueue$3.didUsePromise = true; + function getCurrentFiber() { + { + return current; } + } + function setIsRendering(rendering) { + { + isRendering = rendering; + } + } - var previous = thenableState[index]; + var ReactStrictModeWarnings = { + recordUnsafeLifecycleWarnings: function (fiber, instance) {}, + flushPendingUnsafeLifecycleWarnings: function () {}, + recordLegacyContextWarning: function (fiber, instance) {}, + flushLegacyContextWarning: function () {}, + discardPendingWarnings: function () {} + }; - if (previous === undefined) { - thenableState.push(thenable); - } else { - if (previous !== thenable) { - // Reuse the previous thenable, and drop the new one. We can assume - // they represent the same value, because components are idempotent. - // Avoid an unhandled rejection errors for the Promises that we'll - // intentionally ignore. - thenable.then(noop, noop); - thenable = previous; - } - } // We use an expando to track the status and result of a thenable so that we - // can synchronously unwrap the value. Think of this as an extension of the - // Promise API, or a custom interface that is a superset of Thenable. - // - // If the thenable doesn't have a status, set it to "pending" and attach - // a listener that will update its status and result when it resolves. + { + var findStrictRoot = function (fiber) { + var maybeStrictRoot = null; + var node = fiber; - switch (thenable.status) { - case "fulfilled": { - var fulfilledValue = thenable.value; - return fulfilledValue; - } + while (node !== null) { + if (node.mode & StrictLegacyMode) { + maybeStrictRoot = node; + } - case "rejected": { - var rejectedError = thenable.reason; - checkIfUseWrappedInAsyncCatch(rejectedError); - throw rejectedError; + node = node.return; } - default: { - if (typeof thenable.status === "string") { - // Only instrument the thenable if the status if not defined. If - // it's defined, but an unknown value, assume it's been instrumented by - // some custom userspace implementation. We treat it as "pending". - // Attach a dummy listener, to ensure that any lazy initialization can - // happen. Flight lazily parses JSON when the value is actually awaited. - thenable.then(noop, noop); - } else { - // This is an uncached thenable that we haven't seen before. - // Detect infinite ping loops caused by uncached promises. - var root = getWorkInProgressRoot(); + return maybeStrictRoot; + }; - if (root !== null && root.shellSuspendCounter > 100) { - // This root has suspended repeatedly in the shell without making any - // progress (i.e. committing something). This is highly suggestive of - // an infinite ping loop, often caused by an accidental Async Client - // Component. - // - // During a transition, we can suspend the work loop until the promise - // to resolve, but this is a sync render, so that's not an option. We - // also can't show a fallback, because none was provided. So our last - // resort is to throw an error. - // - // TODO: Remove this error in a future release. Other ways of handling - // this case include forcing a concurrent render, or putting the whole - // root into offscreen mode. - throw new Error( - "async/await is not yet supported in Client Components, only " + - "Server Components. This error is often caused by accidentally " + - "adding `'use client'` to a module that was originally written " + - "for the server." - ); - } - - var pendingThenable = thenable; - pendingThenable.status = "pending"; - pendingThenable.then( - function (fulfilledValue) { - if (thenable.status === "pending") { - var fulfilledThenable = thenable; - fulfilledThenable.status = "fulfilled"; - fulfilledThenable.value = fulfilledValue; - } - }, - function (error) { - if (thenable.status === "pending") { - var rejectedThenable = thenable; - rejectedThenable.status = "rejected"; - rejectedThenable.reason = error; - } - } - ); // Check one more time in case the thenable resolved synchronously. + var setToSortedString = function (set) { + var array = []; + set.forEach(function (value) { + array.push(value); + }); + return array.sort().join(", "); + }; - switch (thenable.status) { - case "fulfilled": { - var fulfilledThenable = thenable; - return fulfilledThenable.value; - } + var pendingComponentWillMountWarnings = []; + var pendingUNSAFE_ComponentWillMountWarnings = []; + var pendingComponentWillReceivePropsWarnings = []; + var pendingUNSAFE_ComponentWillReceivePropsWarnings = []; + var pendingComponentWillUpdateWarnings = []; + var pendingUNSAFE_ComponentWillUpdateWarnings = []; // Tracks components we have already warned about. - case "rejected": { - var rejectedThenable = thenable; - var _rejectedError = rejectedThenable.reason; - checkIfUseWrappedInAsyncCatch(_rejectedError); - throw _rejectedError; - } - } - } // Suspend. - // - // Throwing here is an implementation detail that allows us to unwind the - // call stack. But we shouldn't allow it to leak into userspace. Throw an - // opaque placeholder value instead of the actual thenable. If it doesn't - // get captured by the work loop, log a warning, because that means - // something in userspace must have caught it. + var didWarnAboutUnsafeLifecycles = new Set(); - suspendedThenable = thenable; + ReactStrictModeWarnings.recordUnsafeLifecycleWarnings = function ( + fiber, + instance + ) { + // Dedupe strategy: Warn once per component. + if (didWarnAboutUnsafeLifecycles.has(fiber.type)) { + return; + } - { - needsToResetSuspendedThenableDEV = true; - } + if ( + typeof instance.componentWillMount === "function" && // Don't warn about react-lifecycles-compat polyfilled components. + instance.componentWillMount.__suppressDeprecationWarning !== true + ) { + pendingComponentWillMountWarnings.push(fiber); + } - throw SuspenseException; + if ( + fiber.mode & StrictLegacyMode && + typeof instance.UNSAFE_componentWillMount === "function" + ) { + pendingUNSAFE_ComponentWillMountWarnings.push(fiber); } - } - } - // passed to the rest of the Suspense implementation — which, for historical - // reasons, expects to receive a thenable. - var suspendedThenable = null; - var needsToResetSuspendedThenableDEV = false; - function getSuspendedThenable() { - // This is called right after `use` suspends by throwing an exception. `use` - // throws an opaque value instead of the thenable itself so that it can't be - // caught in userspace. Then the work loop accesses the actual thenable using - // this function. - if (suspendedThenable === null) { - throw new Error( - "Expected a suspended thenable. This is a bug in React. Please file " + - "an issue." - ); - } + if ( + typeof instance.componentWillReceiveProps === "function" && + instance.componentWillReceiveProps.__suppressDeprecationWarning !== + true + ) { + pendingComponentWillReceivePropsWarnings.push(fiber); + } - var thenable = suspendedThenable; - suspendedThenable = null; + if ( + fiber.mode & StrictLegacyMode && + typeof instance.UNSAFE_componentWillReceiveProps === "function" + ) { + pendingUNSAFE_ComponentWillReceivePropsWarnings.push(fiber); + } - { - needsToResetSuspendedThenableDEV = false; - } + if ( + typeof instance.componentWillUpdate === "function" && + instance.componentWillUpdate.__suppressDeprecationWarning !== true + ) { + pendingComponentWillUpdateWarnings.push(fiber); + } - return thenable; - } - function checkIfUseWrappedInTryCatch() { - { - // This was set right before SuspenseException was thrown, and it should - // have been cleared when the exception was handled. If it wasn't, - // it must have been caught by userspace. - if (needsToResetSuspendedThenableDEV) { - needsToResetSuspendedThenableDEV = false; - return true; + if ( + fiber.mode & StrictLegacyMode && + typeof instance.UNSAFE_componentWillUpdate === "function" + ) { + pendingUNSAFE_ComponentWillUpdateWarnings.push(fiber); } - } + }; - return false; - } - function checkIfUseWrappedInAsyncCatch(rejectedReason) { - // This check runs in prod, too, because it prevents a more confusing - // downstream error, where SuspenseException is caught by a promise and - // thrown asynchronously. - // TODO: Another way to prevent SuspenseException from leaking into an async - // execution context is to check the dispatcher every time `use` is called, - // or some equivalent. That might be preferable for other reasons, too, since - // it matches how we prevent similar mistakes for other hooks. - if (rejectedReason === SuspenseException) { - throw new Error( - "Hooks are not supported inside an async component. This " + - "error is often caused by accidentally adding `'use client'` " + - "to a module that was originally written for the server." - ); - } - } + ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings = + function () { + // We do an initial pass to gather component names + var componentWillMountUniqueNames = new Set(); - var thenableState$1 = null; - var thenableIndexCounter$1 = 0; - var didWarnAboutMaps; - var didWarnAboutGenerators; - var didWarnAboutStringRefs; - var ownerHasKeyUseWarning; - var ownerHasFunctionTypeWarning; + if (pendingComponentWillMountWarnings.length > 0) { + pendingComponentWillMountWarnings.forEach(function (fiber) { + componentWillMountUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingComponentWillMountWarnings = []; + } - var warnForMissingKey = function (child, returnFiber) {}; + var UNSAFE_componentWillMountUniqueNames = new Set(); - { - didWarnAboutMaps = false; - didWarnAboutGenerators = false; - didWarnAboutStringRefs = {}; - /** - * Warn if there's no key explicitly set on dynamic arrays of children or - * object keys are not valid. This allows us to keep track of children between - * updates. - */ + if (pendingUNSAFE_ComponentWillMountWarnings.length > 0) { + pendingUNSAFE_ComponentWillMountWarnings.forEach(function (fiber) { + UNSAFE_componentWillMountUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingUNSAFE_ComponentWillMountWarnings = []; + } - ownerHasKeyUseWarning = {}; - ownerHasFunctionTypeWarning = {}; + var componentWillReceivePropsUniqueNames = new Set(); - warnForMissingKey = function (child, returnFiber) { - if (child === null || typeof child !== "object") { - return; - } + if (pendingComponentWillReceivePropsWarnings.length > 0) { + pendingComponentWillReceivePropsWarnings.forEach(function (fiber) { + componentWillReceivePropsUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingComponentWillReceivePropsWarnings = []; + } - if (!child._store || child._store.validated || child.key != null) { - return; - } + var UNSAFE_componentWillReceivePropsUniqueNames = new Set(); - if (typeof child._store !== "object") { - throw new Error( - "React Component in warnForMissingKey should have a _store. " + - "This error is likely caused by a bug in React. Please file an issue." - ); - } // $FlowFixMe[cannot-write] unable to narrow type from mixed to writable object + if (pendingUNSAFE_ComponentWillReceivePropsWarnings.length > 0) { + pendingUNSAFE_ComponentWillReceivePropsWarnings.forEach( + function (fiber) { + UNSAFE_componentWillReceivePropsUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + } + ); + pendingUNSAFE_ComponentWillReceivePropsWarnings = []; + } - child._store.validated = true; - var componentName = - getComponentNameFromFiber(returnFiber) || "Component"; + var componentWillUpdateUniqueNames = new Set(); - if (ownerHasKeyUseWarning[componentName]) { - return; - } - - ownerHasKeyUseWarning[componentName] = true; - - error( - "Each child in a list should have a unique " + - '"key" prop. See https://reactjs.org/link/warning-keys for ' + - "more information." - ); - }; - } + if (pendingComponentWillUpdateWarnings.length > 0) { + pendingComponentWillUpdateWarnings.forEach(function (fiber) { + componentWillUpdateUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingComponentWillUpdateWarnings = []; + } - function isReactClass(type) { - return type.prototype && type.prototype.isReactComponent; - } + var UNSAFE_componentWillUpdateUniqueNames = new Set(); - function unwrapThenable(thenable) { - var index = thenableIndexCounter$1; - thenableIndexCounter$1 += 1; + if (pendingUNSAFE_ComponentWillUpdateWarnings.length > 0) { + pendingUNSAFE_ComponentWillUpdateWarnings.forEach(function (fiber) { + UNSAFE_componentWillUpdateUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingUNSAFE_ComponentWillUpdateWarnings = []; + } // Finally, we flush all the warnings + // UNSAFE_ ones before the deprecated ones, since they'll be 'louder' - if (thenableState$1 === null) { - thenableState$1 = createThenableState(); - } + if (UNSAFE_componentWillMountUniqueNames.size > 0) { + var sortedNames = setToSortedString( + UNSAFE_componentWillMountUniqueNames + ); - return trackUsedThenable(thenableState$1, thenable, index); - } + error( + "Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code. " + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + + "* Move code with side effects to componentDidMount, and set initial state in the constructor.\n" + + "\nPlease update the following components: %s", + sortedNames + ); + } - function coerceRef(returnFiber, current, element) { - var mixedRef = element.ref; + if (UNSAFE_componentWillReceivePropsUniqueNames.size > 0) { + var _sortedNames = setToSortedString( + UNSAFE_componentWillReceivePropsUniqueNames + ); - if ( - mixedRef !== null && - typeof mixedRef !== "function" && - typeof mixedRef !== "object" - ) { - { - if ( - // We warn in ReactElement.js if owner and self are equal for string refs - // because these cannot be automatically converted to an arrow function - // using a codemod. Therefore, we don't have to warn about string refs again. - !( - element._owner && - element._self && - element._owner.stateNode !== element._self - ) && // Will already throw with "Function components cannot have string refs" - !(element._owner && element._owner.tag !== ClassComponent) && // Will already warn with "Function components cannot be given refs" - !( - typeof element.type === "function" && !isReactClass(element.type) - ) && // Will already throw with "Element ref was specified as a string (someStringRef) but no owner was set" - element._owner - ) { - var componentName = - getComponentNameFromFiber(returnFiber) || "Component"; + error( + "Using UNSAFE_componentWillReceiveProps in strict mode is not recommended " + + "and may indicate bugs in your code. " + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + + "* Move data fetching code or side effects to componentDidUpdate.\n" + + "* If you're updating state whenever props change, " + + "refactor your code to use memoization techniques or move it to " + + "static getDerivedStateFromProps. Learn more at: https://reactjs.org/link/derived-state\n" + + "\nPlease update the following components: %s", + _sortedNames + ); + } - if (!didWarnAboutStringRefs[componentName]) { - error( - 'Component "%s" contains the string ref "%s". Support for string refs ' + - "will be removed in a future major release. We recommend using " + - "useRef() or createRef() instead. " + - "Learn more about using refs safely here: " + - "https://reactjs.org/link/strict-mode-string-ref", - componentName, - mixedRef - ); + if (UNSAFE_componentWillUpdateUniqueNames.size > 0) { + var _sortedNames2 = setToSortedString( + UNSAFE_componentWillUpdateUniqueNames + ); - didWarnAboutStringRefs[componentName] = true; - } + error( + "Using UNSAFE_componentWillUpdate in strict mode is not recommended " + + "and may indicate bugs in your code. " + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + + "* Move data fetching code or side effects to componentDidUpdate.\n" + + "\nPlease update the following components: %s", + _sortedNames2 + ); } - } - if (element._owner) { - var owner = element._owner; - var inst; + if (componentWillMountUniqueNames.size > 0) { + var _sortedNames3 = setToSortedString( + componentWillMountUniqueNames + ); - if (owner) { - var ownerFiber = owner; + warn( + "componentWillMount has been renamed, and is not recommended for use. " + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + + "* Move code with side effects to componentDidMount, and set initial state in the constructor.\n" + + "* Rename componentWillMount to UNSAFE_componentWillMount to suppress " + + "this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. " + + "To rename all deprecated lifecycles to their new names, you can run " + + "`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n" + + "\nPlease update the following components: %s", + _sortedNames3 + ); + } - if (ownerFiber.tag !== ClassComponent) { - throw new Error( - "Function components cannot have string refs. " + - "We recommend using useRef() instead. " + - "Learn more about using refs safely here: " + - "https://reactjs.org/link/strict-mode-string-ref" - ); - } + if (componentWillReceivePropsUniqueNames.size > 0) { + var _sortedNames4 = setToSortedString( + componentWillReceivePropsUniqueNames + ); - inst = ownerFiber.stateNode; + warn( + "componentWillReceiveProps has been renamed, and is not recommended for use. " + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + + "* Move data fetching code or side effects to componentDidUpdate.\n" + + "* If you're updating state whenever props change, refactor your " + + "code to use memoization techniques or move it to " + + "static getDerivedStateFromProps. Learn more at: https://reactjs.org/link/derived-state\n" + + "* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress " + + "this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. " + + "To rename all deprecated lifecycles to their new names, you can run " + + "`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n" + + "\nPlease update the following components: %s", + _sortedNames4 + ); } - if (!inst) { - throw new Error( - "Missing owner for string ref " + - mixedRef + - ". This error is likely caused by a " + - "bug in React. Please file an issue." + if (componentWillUpdateUniqueNames.size > 0) { + var _sortedNames5 = setToSortedString( + componentWillUpdateUniqueNames ); - } // Assigning this to a const so Flow knows it won't change in the closure - - var resolvedInst = inst; - { - checkPropStringCoercion(mixedRef, "ref"); + warn( + "componentWillUpdate has been renamed, and is not recommended for use. " + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + + "* Move data fetching code or side effects to componentDidUpdate.\n" + + "* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress " + + "this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. " + + "To rename all deprecated lifecycles to their new names, you can run " + + "`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n" + + "\nPlease update the following components: %s", + _sortedNames5 + ); } + }; - var stringRef = "" + mixedRef; // Check if previous string ref matches new string ref + var pendingLegacyContextWarning = new Map(); // Tracks components we have already warned about. - if ( - current !== null && - current.ref !== null && - typeof current.ref === "function" && - current.ref._stringRef === stringRef - ) { - return current.ref; - } + var didWarnAboutLegacyContext = new Set(); - var ref = function (value) { - var refs = resolvedInst.refs; + ReactStrictModeWarnings.recordLegacyContextWarning = function ( + fiber, + instance + ) { + var strictRoot = findStrictRoot(fiber); - if (value === null) { - delete refs[stringRef]; - } else { - refs[stringRef] = value; - } - }; + if (strictRoot === null) { + error( + "Expected to find a StrictMode component in a strict mode tree. " + + "This error is likely caused by a bug in React. Please file an issue." + ); - ref._stringRef = stringRef; - return ref; - } else { - if (typeof mixedRef !== "string") { - throw new Error( - "Expected ref to be a function, a string, an object returned by React.createRef(), or null." - ); - } + return; + } // Dedup strategy: Warn once per component. - if (!element._owner) { - throw new Error( - "Element ref was specified as a string (" + - mixedRef + - ") but no owner was set. This could happen for one of" + - " the following reasons:\n" + - "1. You may be adding a ref to a function component\n" + - "2. You may be adding a ref to a component that was not created inside a component's render method\n" + - "3. You have multiple copies of React loaded\n" + - "See https://reactjs.org/link/refs-must-have-owner for more information." - ); - } + if (didWarnAboutLegacyContext.has(fiber.type)) { + return; } - } - return mixedRef; - } + var warningsForRoot = pendingLegacyContextWarning.get(strictRoot); - function throwOnInvalidObjectType(returnFiber, newChild) { - // $FlowFixMe[method-unbinding] - var childString = Object.prototype.toString.call(newChild); - throw new Error( - "Objects are not valid as a React child (found: " + - (childString === "[object Object]" - ? "object with keys {" + Object.keys(newChild).join(", ") + "}" - : childString) + - "). " + - "If you meant to render a collection of children, use an array " + - "instead." - ); - } - - function warnOnFunctionType(returnFiber) { - { - var componentName = - getComponentNameFromFiber(returnFiber) || "Component"; + if ( + fiber.type.contextTypes != null || + fiber.type.childContextTypes != null || + (instance !== null && typeof instance.getChildContext === "function") + ) { + if (warningsForRoot === undefined) { + warningsForRoot = []; + pendingLegacyContextWarning.set(strictRoot, warningsForRoot); + } - if (ownerHasFunctionTypeWarning[componentName]) { - return; + warningsForRoot.push(fiber); } + }; - ownerHasFunctionTypeWarning[componentName] = true; - - error( - "Functions are not valid as a React child. This may happen if " + - "you return a Component instead of from render. " + - "Or maybe you meant to call this function rather than return it." - ); - } - } + ReactStrictModeWarnings.flushLegacyContextWarning = function () { + pendingLegacyContextWarning.forEach(function (fiberArray, strictRoot) { + if (fiberArray.length === 0) { + return; + } - function resolveLazy(lazyType) { - var payload = lazyType._payload; - var init = lazyType._init; - return init(payload); - } // This wrapper function exists because I expect to clone the code in each path - // to be able to optimize each path individually by branching early. This needs - // a compiler or we can do it manually. Helpers that don't need this branching - // live outside of this function. + var firstFiber = fiberArray[0]; + var uniqueNames = new Set(); + fiberArray.forEach(function (fiber) { + uniqueNames.add(getComponentNameFromFiber(fiber) || "Component"); + didWarnAboutLegacyContext.add(fiber.type); + }); + var sortedNames = setToSortedString(uniqueNames); - function createChildReconciler(shouldTrackSideEffects) { - function deleteChild(returnFiber, childToDelete) { - if (!shouldTrackSideEffects) { - // Noop. - return; - } + try { + setCurrentFiber(firstFiber); - var deletions = returnFiber.deletions; + error( + "Legacy context API has been detected within a strict-mode tree." + + "\n\nThe old API will be supported in all 16.x releases, but applications " + + "using it should migrate to the new version." + + "\n\nPlease update the following components: %s" + + "\n\nLearn more about this warning here: https://reactjs.org/link/legacy-context", + sortedNames + ); + } finally { + resetCurrentFiber(); + } + }); + }; - if (deletions === null) { - returnFiber.deletions = [childToDelete]; - returnFiber.flags |= ChildDeletion; - } else { - deletions.push(childToDelete); - } - } + ReactStrictModeWarnings.discardPendingWarnings = function () { + pendingComponentWillMountWarnings = []; + pendingUNSAFE_ComponentWillMountWarnings = []; + pendingComponentWillReceivePropsWarnings = []; + pendingUNSAFE_ComponentWillReceivePropsWarnings = []; + pendingComponentWillUpdateWarnings = []; + pendingUNSAFE_ComponentWillUpdateWarnings = []; + pendingLegacyContextWarning = new Map(); + }; + } - function deleteRemainingChildren(returnFiber, currentFirstChild) { - if (!shouldTrackSideEffects) { - // Noop. - return null; - } // TODO: For the shouldClone case, this could be micro-optimized a bit by - // assuming that after the first child we've already added everything. + /* + * The `'' + value` pattern (used in perf-sensitive code) throws for Symbol + * and Temporal.* types. See https://github.com/facebook/react/pull/22064. + * + * The functions in this module will throw an easier-to-understand, + * easier-to-debug exception with a clear errors message message explaining the + * problem. (Instead of a confusing exception thrown inside the implementation + * of the `value` object). + */ + // $FlowFixMe[incompatible-return] only called in DEV, so void return is not possible. + function typeName(value) { + { + // toStringTag is needed for namespaced types like Temporal.Instant + var hasToStringTag = typeof Symbol === "function" && Symbol.toStringTag; + var type = + (hasToStringTag && value[Symbol.toStringTag]) || + value.constructor.name || + "Object"; // $FlowFixMe[incompatible-return] - var childToDelete = currentFirstChild; + return type; + } + } // $FlowFixMe[incompatible-return] only called in DEV, so void return is not possible. - while (childToDelete !== null) { - deleteChild(returnFiber, childToDelete); - childToDelete = childToDelete.sibling; + function willCoercionThrow(value) { + { + try { + testStringCoercion(value); + return false; + } catch (e) { + return true; } - - return null; } + } - function mapRemainingChildren(returnFiber, currentFirstChild) { - // Add the remaining children to a temporary map so that we can find them by - // keys quickly. Implicit (null) keys get added to this set with their index - // instead. - var existingChildren = new Map(); - var existingChild = currentFirstChild; - - while (existingChild !== null) { - if (existingChild.key !== null) { - existingChildren.set(existingChild.key, existingChild); - } else { - existingChildren.set(existingChild.index, existingChild); - } + function testStringCoercion(value) { + // If you ended up here by following an exception call stack, here's what's + // happened: you supplied an object or symbol value to React (as a prop, key, + // DOM attribute, CSS property, string ref, etc.) and when React tried to + // coerce it to a string using `'' + value`, an exception was thrown. + // + // The most common types that will cause this exception are `Symbol` instances + // and Temporal objects like `Temporal.Instant`. But any object that has a + // `valueOf` or `[Symbol.toPrimitive]` method that throws will also cause this + // exception. (Library authors do this to prevent users from using built-in + // numeric operators like `+` or comparison operators like `>=` because custom + // methods are needed to perform accurate arithmetic or comparison.) + // + // To fix the problem, coerce this object or symbol value to a string before + // passing it to React. The most reliable way is usually `String(value)`. + // + // To find which value is throwing, check the browser or debugger console. + // Before this exception was thrown, there should be `console.error` output + // that shows the type (Symbol, Temporal.PlainDate, etc.) that caused the + // problem and how that type was used: key, atrribute, input value prop, etc. + // In most cases, this console output also shows the component and its + // ancestor components where the exception happened. + // + // eslint-disable-next-line react-internal/safe-string-coercion + return "" + value; + } + function checkKeyStringCoercion(value) { + { + if (willCoercionThrow(value)) { + error( + "The provided key is an unsupported type %s." + + " This value must be coerced to a string before using it here.", + typeName(value) + ); - existingChild = existingChild.sibling; + return testStringCoercion(value); // throw (to help callers find troubleshooting comments) } - - return existingChildren; } + } + function checkPropStringCoercion(value, propName) { + { + if (willCoercionThrow(value)) { + error( + "The provided `%s` prop is an unsupported type %s." + + " This value must be coerced to a string before using it here.", + propName, + typeName(value) + ); - function useFiber(fiber, pendingProps) { - // We currently set sibling to null and index to 0 here because it is easy - // to forget to do before returning it. E.g. for the single child case. - var clone = createWorkInProgress(fiber, pendingProps); - clone.index = 0; - clone.sibling = null; - return clone; + return testStringCoercion(value); // throw (to help callers find troubleshooting comments) + } } + } - function placeChild(newFiber, lastPlacedIndex, newIndex) { - newFiber.index = newIndex; + var ReactCurrentActQueue$2 = ReactSharedInternals.ReactCurrentActQueue; // An error that is thrown (e.g. by `use`) to trigger Suspense. If we + // detect this is caught by userspace, we'll log a warning in development. - if (!shouldTrackSideEffects) { - // During hydration, the useId algorithm needs to know which fibers are - // part of a list of children (arrays, iterators). - newFiber.flags |= Forked; - return lastPlacedIndex; + var SuspenseException = new Error( + "Suspense Exception: This is not a real error! It's an implementation " + + "detail of `use` to interrupt the current render. You must either " + + "rethrow it immediately, or move the `use` call outside of the " + + "`try/catch` block. Capturing without rethrowing will lead to " + + "unexpected behavior.\n\n" + + "To handle async errors, wrap your component in an error boundary, or " + + "call the promise's `.catch` method and pass the result to `use`" + ); + var SuspenseyCommitException = new Error( + "Suspense Exception: This is not a real error, and should not leak into " + + "userspace. If you're seeing this, it's likely a bug in React." + ); // This is a noop thenable that we use to trigger a fallback in throwException. + // TODO: It would be better to refactor throwException into multiple functions + // so we can trigger a fallback directly without having to check the type. But + // for now this will do. + + var noopSuspenseyCommitThenable = { + then: function () { + { + error( + "Internal React error: A listener was unexpectedly attached to a " + + '"noop" thenable. This is a bug in React. Please file an issue.' + ); } + } + }; + function createThenableState() { + // The ThenableState is created the first time a component suspends. If it + // suspends again, we'll reuse the same state. + return []; + } + function isThenableResolved(thenable) { + var status = thenable.status; + return status === "fulfilled" || status === "rejected"; + } - var current = newFiber.alternate; + function noop() {} - if (current !== null) { - var oldIndex = current.index; + function trackUsedThenable(thenableState, thenable, index) { + if (ReactCurrentActQueue$2.current !== null) { + ReactCurrentActQueue$2.didUsePromise = true; + } - if (oldIndex < lastPlacedIndex) { - // This is a move. - newFiber.flags |= Placement | PlacementDEV; - return lastPlacedIndex; - } else { - // This item can stay in place. - return oldIndex; - } - } else { - // This is an insertion. - newFiber.flags |= Placement | PlacementDEV; - return lastPlacedIndex; - } - } + var previous = thenableState[index]; - function placeSingleChild(newFiber) { - // This is simpler for the single child case. We only need to do a - // placement for inserting new children. - if (shouldTrackSideEffects && newFiber.alternate === null) { - newFiber.flags |= Placement | PlacementDEV; + if (previous === undefined) { + thenableState.push(thenable); + } else { + if (previous !== thenable) { + // Reuse the previous thenable, and drop the new one. We can assume + // they represent the same value, because components are idempotent. + // Avoid an unhandled rejection errors for the Promises that we'll + // intentionally ignore. + thenable.then(noop, noop); + thenable = previous; } + } // We use an expando to track the status and result of a thenable so that we + // can synchronously unwrap the value. Think of this as an extension of the + // Promise API, or a custom interface that is a superset of Thenable. + // + // If the thenable doesn't have a status, set it to "pending" and attach + // a listener that will update its status and result when it resolves. - return newFiber; - } + switch (thenable.status) { + case "fulfilled": { + var fulfilledValue = thenable.value; + return fulfilledValue; + } - function updateTextNode(returnFiber, current, textContent, lanes) { - if (current === null || current.tag !== HostText) { - // Insert - var created = createFiberFromText( - textContent, - returnFiber.mode, - lanes - ); - created.return = returnFiber; - return created; - } else { - // Update - var existing = useFiber(current, textContent); - existing.return = returnFiber; - return existing; + case "rejected": { + var rejectedError = thenable.reason; + checkIfUseWrappedInAsyncCatch(rejectedError); + throw rejectedError; } - } - function updateElement(returnFiber, current, element, lanes) { - var elementType = element.type; + default: { + if (typeof thenable.status === "string") { + // Only instrument the thenable if the status if not defined. If + // it's defined, but an unknown value, assume it's been instrumented by + // some custom userspace implementation. We treat it as "pending". + // Attach a dummy listener, to ensure that any lazy initialization can + // happen. Flight lazily parses JSON when the value is actually awaited. + thenable.then(noop, noop); + } else { + // This is an uncached thenable that we haven't seen before. + // Detect infinite ping loops caused by uncached promises. + var root = getWorkInProgressRoot(); - if (elementType === REACT_FRAGMENT_TYPE) { - return updateFragment( - returnFiber, - current, - element.props.children, - lanes, - element.key - ); - } + if (root !== null && root.shellSuspendCounter > 100) { + // This root has suspended repeatedly in the shell without making any + // progress (i.e. committing something). This is highly suggestive of + // an infinite ping loop, often caused by an accidental Async Client + // Component. + // + // During a transition, we can suspend the work loop until the promise + // to resolve, but this is a sync render, so that's not an option. We + // also can't show a fallback, because none was provided. So our last + // resort is to throw an error. + // + // TODO: Remove this error in a future release. Other ways of handling + // this case include forcing a concurrent render, or putting the whole + // root into offscreen mode. + throw new Error( + "async/await is not yet supported in Client Components, only " + + "Server Components. This error is often caused by accidentally " + + "adding `'use client'` to a module that was originally written " + + "for the server." + ); + } - if (current !== null) { - if ( - current.elementType === elementType || // Keep this check inline so it only runs on the false path: - isCompatibleFamilyForHotReloading(current, element) || // Lazy types should reconcile their resolved type. - // We need to do this after the Hot Reloading check above, - // because hot reloading has different semantics than prod because - // it doesn't resuspend. So we can't let the call below suspend. - (typeof elementType === "object" && - elementType !== null && - elementType.$$typeof === REACT_LAZY_TYPE && - resolveLazy(elementType) === current.type) - ) { - // Move based on index - var existing = useFiber(current, element.props); - existing.ref = coerceRef(returnFiber, current, element); - existing.return = returnFiber; + var pendingThenable = thenable; + pendingThenable.status = "pending"; + pendingThenable.then( + function (fulfilledValue) { + if (thenable.status === "pending") { + var fulfilledThenable = thenable; + fulfilledThenable.status = "fulfilled"; + fulfilledThenable.value = fulfilledValue; + } + }, + function (error) { + if (thenable.status === "pending") { + var rejectedThenable = thenable; + rejectedThenable.status = "rejected"; + rejectedThenable.reason = error; + } + } + ); // Check one more time in case the thenable resolved synchronously. - { - existing._debugSource = element._source; - existing._debugOwner = element._owner; + switch (thenable.status) { + case "fulfilled": { + var fulfilledThenable = thenable; + return fulfilledThenable.value; + } + + case "rejected": { + var rejectedThenable = thenable; + var _rejectedError = rejectedThenable.reason; + checkIfUseWrappedInAsyncCatch(_rejectedError); + throw _rejectedError; + } } + } // Suspend. + // + // Throwing here is an implementation detail that allows us to unwind the + // call stack. But we shouldn't allow it to leak into userspace. Throw an + // opaque placeholder value instead of the actual thenable. If it doesn't + // get captured by the work loop, log a warning, because that means + // something in userspace must have caught it. - return existing; + suspendedThenable = thenable; + + { + needsToResetSuspendedThenableDEV = true; } - } // Insert - var created = createFiberFromElement(element, returnFiber.mode, lanes); - created.ref = coerceRef(returnFiber, current, element); - created.return = returnFiber; - return created; + throw SuspenseException; + } } + } + // passed to the rest of the Suspense implementation — which, for historical + // reasons, expects to receive a thenable. - function updatePortal(returnFiber, current, portal, lanes) { - if ( - current === null || - current.tag !== HostPortal || - current.stateNode.containerInfo !== portal.containerInfo || - current.stateNode.implementation !== portal.implementation - ) { - // Insert - var created = createFiberFromPortal(portal, returnFiber.mode, lanes); - created.return = returnFiber; - return created; - } else { - // Update - var existing = useFiber(current, portal.children || []); - existing.return = returnFiber; - return existing; - } + var suspendedThenable = null; + var needsToResetSuspendedThenableDEV = false; + function getSuspendedThenable() { + // This is called right after `use` suspends by throwing an exception. `use` + // throws an opaque value instead of the thenable itself so that it can't be + // caught in userspace. Then the work loop accesses the actual thenable using + // this function. + if (suspendedThenable === null) { + throw new Error( + "Expected a suspended thenable. This is a bug in React. Please file " + + "an issue." + ); } - function updateFragment(returnFiber, current, fragment, lanes, key) { - if (current === null || current.tag !== Fragment) { - // Insert - var created = createFiberFromFragment( - fragment, - returnFiber.mode, - lanes, - key - ); - created.return = returnFiber; - return created; - } else { - // Update - var existing = useFiber(current, fragment); - existing.return = returnFiber; - return existing; - } + var thenable = suspendedThenable; + suspendedThenable = null; + + { + needsToResetSuspendedThenableDEV = false; } - function createChild(returnFiber, newChild, lanes) { - if ( - (typeof newChild === "string" && newChild !== "") || - typeof newChild === "number" - ) { - // Text nodes don't have keys. If the previous node is implicitly keyed - // we can continue to replace it without aborting even if it is not a text - // node. - var created = createFiberFromText( - "" + newChild, - returnFiber.mode, - lanes - ); - created.return = returnFiber; - return created; + return thenable; + } + function checkIfUseWrappedInTryCatch() { + { + // This was set right before SuspenseException was thrown, and it should + // have been cleared when the exception was handled. If it wasn't, + // it must have been caught by userspace. + if (needsToResetSuspendedThenableDEV) { + needsToResetSuspendedThenableDEV = false; + return true; } + } - if (typeof newChild === "object" && newChild !== null) { - switch (newChild.$$typeof) { - case REACT_ELEMENT_TYPE: { - var _created = createFiberFromElement( - newChild, - returnFiber.mode, - lanes - ); + return false; + } + function checkIfUseWrappedInAsyncCatch(rejectedReason) { + // This check runs in prod, too, because it prevents a more confusing + // downstream error, where SuspenseException is caught by a promise and + // thrown asynchronously. + // TODO: Another way to prevent SuspenseException from leaking into an async + // execution context is to check the dispatcher every time `use` is called, + // or some equivalent. That might be preferable for other reasons, too, since + // it matches how we prevent similar mistakes for other hooks. + if (rejectedReason === SuspenseException) { + throw new Error( + "Hooks are not supported inside an async component. This " + + "error is often caused by accidentally adding `'use client'` " + + "to a module that was originally written for the server." + ); + } + } - _created.ref = coerceRef(returnFiber, null, newChild); - _created.return = returnFiber; - return _created; - } + var thenableState$1 = null; + var thenableIndexCounter$1 = 0; + var didWarnAboutMaps; + var didWarnAboutGenerators; + var didWarnAboutStringRefs; + var ownerHasKeyUseWarning; + var ownerHasFunctionTypeWarning; - case REACT_PORTAL_TYPE: { - var _created2 = createFiberFromPortal( - newChild, - returnFiber.mode, - lanes - ); + var warnForMissingKey = function (child, returnFiber) {}; - _created2.return = returnFiber; - return _created2; - } + { + didWarnAboutMaps = false; + didWarnAboutGenerators = false; + didWarnAboutStringRefs = {}; + /** + * Warn if there's no key explicitly set on dynamic arrays of children or + * object keys are not valid. This allows us to keep track of children between + * updates. + */ - case REACT_LAZY_TYPE: { - var payload = newChild._payload; - var init = newChild._init; - return createChild(returnFiber, init(payload), lanes); - } - } + ownerHasKeyUseWarning = {}; + ownerHasFunctionTypeWarning = {}; - if (isArray(newChild) || getIteratorFn(newChild)) { - var _created3 = createFiberFromFragment( - newChild, - returnFiber.mode, - lanes, - null - ); + warnForMissingKey = function (child, returnFiber) { + if (child === null || typeof child !== "object") { + return; + } - _created3.return = returnFiber; - return _created3; - } // Usable node types - // - // Unwrap the inner value and recursively call this function again. + if (!child._store || child._store.validated || child.key != null) { + return; + } - if (typeof newChild.then === "function") { - var thenable = newChild; - return createChild(returnFiber, unwrapThenable(thenable), lanes); - } + if (typeof child._store !== "object") { + throw new Error( + "React Component in warnForMissingKey should have a _store. " + + "This error is likely caused by a bug in React. Please file an issue." + ); + } // $FlowFixMe[cannot-write] unable to narrow type from mixed to writable object - if ( - newChild.$$typeof === REACT_CONTEXT_TYPE || - newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE - ) { - var context = newChild; - return createChild( - returnFiber, - readContextDuringReconcilation(returnFiber, context, lanes), - lanes - ); - } + child._store.validated = true; + var componentName = + getComponentNameFromFiber(returnFiber) || "Component"; - throwOnInvalidObjectType(returnFiber, newChild); + if (ownerHasKeyUseWarning[componentName]) { + return; } - { - if (typeof newChild === "function") { - warnOnFunctionType(returnFiber); - } - } + ownerHasKeyUseWarning[componentName] = true; - return null; - } + error( + "Each child in a list should have a unique " + + '"key" prop. See https://reactjs.org/link/warning-keys for ' + + "more information." + ); + }; + } - function updateSlot(returnFiber, oldFiber, newChild, lanes) { - // Update the fiber if the keys match, otherwise return null. - var key = oldFiber !== null ? oldFiber.key : null; + function isReactClass(type) { + return type.prototype && type.prototype.isReactComponent; + } - if ( - (typeof newChild === "string" && newChild !== "") || - typeof newChild === "number" - ) { - // Text nodes don't have keys. If the previous node is implicitly keyed - // we can continue to replace it without aborting even if it is not a text - // node. - if (key !== null) { - return null; - } + function unwrapThenable(thenable) { + var index = thenableIndexCounter$1; + thenableIndexCounter$1 += 1; - return updateTextNode(returnFiber, oldFiber, "" + newChild, lanes); - } + if (thenableState$1 === null) { + thenableState$1 = createThenableState(); + } - if (typeof newChild === "object" && newChild !== null) { - switch (newChild.$$typeof) { - case REACT_ELEMENT_TYPE: { - if (newChild.key === key) { - return updateElement(returnFiber, oldFiber, newChild, lanes); - } else { - return null; - } - } + return trackUsedThenable(thenableState$1, thenable, index); + } - case REACT_PORTAL_TYPE: { - if (newChild.key === key) { - return updatePortal(returnFiber, oldFiber, newChild, lanes); - } else { - return null; - } - } + function coerceRef(returnFiber, current, element) { + var mixedRef = element.ref; - case REACT_LAZY_TYPE: { - var payload = newChild._payload; - var init = newChild._init; - return updateSlot(returnFiber, oldFiber, init(payload), lanes); + if ( + mixedRef !== null && + typeof mixedRef !== "function" && + typeof mixedRef !== "object" + ) { + { + if ( + // We warn in ReactElement.js if owner and self are equal for string refs + // because these cannot be automatically converted to an arrow function + // using a codemod. Therefore, we don't have to warn about string refs again. + !( + element._owner && + element._self && + element._owner.stateNode !== element._self + ) && // Will already throw with "Function components cannot have string refs" + !(element._owner && element._owner.tag !== ClassComponent) && // Will already warn with "Function components cannot be given refs" + !( + typeof element.type === "function" && !isReactClass(element.type) + ) && // Will already throw with "Element ref was specified as a string (someStringRef) but no owner was set" + element._owner + ) { + var componentName = + getComponentNameFromFiber(returnFiber) || "Component"; + + if (!didWarnAboutStringRefs[componentName]) { + error( + 'Component "%s" contains the string ref "%s". Support for string refs ' + + "will be removed in a future major release. We recommend using " + + "useRef() or createRef() instead. " + + "Learn more about using refs safely here: " + + "https://reactjs.org/link/strict-mode-string-ref", + componentName, + mixedRef + ); + + didWarnAboutStringRefs[componentName] = true; } } + } - if (isArray(newChild) || getIteratorFn(newChild)) { - if (key !== null) { - return null; + if (element._owner) { + var owner = element._owner; + var inst; + + if (owner) { + var ownerFiber = owner; + + if (ownerFiber.tag !== ClassComponent) { + throw new Error( + "Function components cannot have string refs. " + + "We recommend using useRef() instead. " + + "Learn more about using refs safely here: " + + "https://reactjs.org/link/strict-mode-string-ref" + ); } - return updateFragment(returnFiber, oldFiber, newChild, lanes, null); - } // Usable node types - // - // Unwrap the inner value and recursively call this function again. + inst = ownerFiber.stateNode; + } - if (typeof newChild.then === "function") { - var thenable = newChild; - return updateSlot( - returnFiber, - oldFiber, - unwrapThenable(thenable), - lanes + if (!inst) { + throw new Error( + "Missing owner for string ref " + + mixedRef + + ". This error is likely caused by a " + + "bug in React. Please file an issue." ); + } // Assigning this to a const so Flow knows it won't change in the closure + + var resolvedInst = inst; + + { + checkPropStringCoercion(mixedRef, "ref"); } + var stringRef = "" + mixedRef; // Check if previous string ref matches new string ref + if ( - newChild.$$typeof === REACT_CONTEXT_TYPE || - newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE - ) { - var context = newChild; - return updateSlot( - returnFiber, - oldFiber, - readContextDuringReconcilation(returnFiber, context, lanes), - lanes - ); + current !== null && + current.ref !== null && + typeof current.ref === "function" && + current.ref._stringRef === stringRef + ) { + return current.ref; } - throwOnInvalidObjectType(returnFiber, newChild); - } + var ref = function (value) { + var refs = resolvedInst.refs; - { - if (typeof newChild === "function") { - warnOnFunctionType(returnFiber); - } - } + if (value === null) { + delete refs[stringRef]; + } else { + refs[stringRef] = value; + } + }; - return null; - } + ref._stringRef = stringRef; + return ref; + } else { + if (typeof mixedRef !== "string") { + throw new Error( + "Expected ref to be a function, a string, an object returned by React.createRef(), or null." + ); + } - function updateFromMap( - existingChildren, - returnFiber, - newIdx, - newChild, - lanes - ) { - if ( - (typeof newChild === "string" && newChild !== "") || - typeof newChild === "number" - ) { - // Text nodes don't have keys, so we neither have to check the old nor - // new node for the key. If both are text nodes, they match. - var matchedFiber = existingChildren.get(newIdx) || null; - return updateTextNode( - returnFiber, - matchedFiber, - "" + newChild, - lanes - ); + if (!element._owner) { + throw new Error( + "Element ref was specified as a string (" + + mixedRef + + ") but no owner was set. This could happen for one of" + + " the following reasons:\n" + + "1. You may be adding a ref to a function component\n" + + "2. You may be adding a ref to a component that was not created inside a component's render method\n" + + "3. You have multiple copies of React loaded\n" + + "See https://reactjs.org/link/refs-must-have-owner for more information." + ); + } } + } - if (typeof newChild === "object" && newChild !== null) { - switch (newChild.$$typeof) { - case REACT_ELEMENT_TYPE: { - var _matchedFiber = - existingChildren.get( - newChild.key === null ? newIdx : newChild.key - ) || null; + return mixedRef; + } - return updateElement(returnFiber, _matchedFiber, newChild, lanes); - } + function throwOnInvalidObjectType(returnFiber, newChild) { + // $FlowFixMe[method-unbinding] + var childString = Object.prototype.toString.call(newChild); + throw new Error( + "Objects are not valid as a React child (found: " + + (childString === "[object Object]" + ? "object with keys {" + Object.keys(newChild).join(", ") + "}" + : childString) + + "). " + + "If you meant to render a collection of children, use an array " + + "instead." + ); + } - case REACT_PORTAL_TYPE: { - var _matchedFiber2 = - existingChildren.get( - newChild.key === null ? newIdx : newChild.key - ) || null; + function warnOnFunctionType(returnFiber) { + { + var componentName = + getComponentNameFromFiber(returnFiber) || "Component"; - return updatePortal(returnFiber, _matchedFiber2, newChild, lanes); - } + if (ownerHasFunctionTypeWarning[componentName]) { + return; + } - case REACT_LAZY_TYPE: - var payload = newChild._payload; - var init = newChild._init; - return updateFromMap( - existingChildren, - returnFiber, - newIdx, - init(payload), - lanes - ); - } + ownerHasFunctionTypeWarning[componentName] = true; - if (isArray(newChild) || getIteratorFn(newChild)) { - var _matchedFiber3 = existingChildren.get(newIdx) || null; + error( + "Functions are not valid as a React child. This may happen if " + + "you return a Component instead of from render. " + + "Or maybe you meant to call this function rather than return it." + ); + } + } - return updateFragment( - returnFiber, - _matchedFiber3, - newChild, - lanes, - null - ); - } // Usable node types - // - // Unwrap the inner value and recursively call this function again. + function resolveLazy(lazyType) { + var payload = lazyType._payload; + var init = lazyType._init; + return init(payload); + } // This wrapper function exists because I expect to clone the code in each path + // to be able to optimize each path individually by branching early. This needs + // a compiler or we can do it manually. Helpers that don't need this branching + // live outside of this function. - if (typeof newChild.then === "function") { - var thenable = newChild; - return updateFromMap( - existingChildren, - returnFiber, - newIdx, - unwrapThenable(thenable), - lanes - ); - } + function createChildReconciler(shouldTrackSideEffects) { + function deleteChild(returnFiber, childToDelete) { + if (!shouldTrackSideEffects) { + // Noop. + return; + } - if ( - newChild.$$typeof === REACT_CONTEXT_TYPE || - newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE - ) { - var context = newChild; - return updateFromMap( - existingChildren, - returnFiber, - newIdx, - readContextDuringReconcilation(returnFiber, context, lanes), - lanes - ); - } + var deletions = returnFiber.deletions; - throwOnInvalidObjectType(returnFiber, newChild); + if (deletions === null) { + returnFiber.deletions = [childToDelete]; + returnFiber.flags |= ChildDeletion; + } else { + deletions.push(childToDelete); } + } - { - if (typeof newChild === "function") { - warnOnFunctionType(returnFiber); - } + function deleteRemainingChildren(returnFiber, currentFirstChild) { + if (!shouldTrackSideEffects) { + // Noop. + return null; + } // TODO: For the shouldClone case, this could be micro-optimized a bit by + // assuming that after the first child we've already added everything. + + var childToDelete = currentFirstChild; + + while (childToDelete !== null) { + deleteChild(returnFiber, childToDelete); + childToDelete = childToDelete.sibling; } return null; } - /** - * Warns if there is a duplicate or missing key - */ - function warnOnInvalidKey(child, knownKeys, returnFiber) { - { - if (typeof child !== "object" || child === null) { - return knownKeys; + function mapRemainingChildren(returnFiber, currentFirstChild) { + // Add the remaining children to a temporary map so that we can find them by + // keys quickly. Implicit (null) keys get added to this set with their index + // instead. + var existingChildren = new Map(); + var existingChild = currentFirstChild; + + while (existingChild !== null) { + if (existingChild.key !== null) { + existingChildren.set(existingChild.key, existingChild); + } else { + existingChildren.set(existingChild.index, existingChild); } - switch (child.$$typeof) { - case REACT_ELEMENT_TYPE: - case REACT_PORTAL_TYPE: - warnForMissingKey(child, returnFiber); - var key = child.key; + existingChild = existingChild.sibling; + } - if (typeof key !== "string") { - break; - } + return existingChildren; + } - if (knownKeys === null) { - knownKeys = new Set(); - knownKeys.add(key); - break; - } + function useFiber(fiber, pendingProps) { + // We currently set sibling to null and index to 0 here because it is easy + // to forget to do before returning it. E.g. for the single child case. + var clone = createWorkInProgress(fiber, pendingProps); + clone.index = 0; + clone.sibling = null; + return clone; + } - if (!knownKeys.has(key)) { - knownKeys.add(key); - break; - } + function placeChild(newFiber, lastPlacedIndex, newIndex) { + newFiber.index = newIndex; - error( - "Encountered two children with the same key, `%s`. " + - "Keys should be unique so that components maintain their identity " + - "across updates. Non-unique keys may cause children to be " + - "duplicated and/or omitted — the behavior is unsupported and " + - "could change in a future version.", - key - ); - - break; - - case REACT_LAZY_TYPE: - var payload = child._payload; - var init = child._init; - warnOnInvalidKey(init(payload), knownKeys, returnFiber); - break; - } + if (!shouldTrackSideEffects) { + // During hydration, the useId algorithm needs to know which fibers are + // part of a list of children (arrays, iterators). + newFiber.flags |= Forked; + return lastPlacedIndex; } - return knownKeys; - } + var current = newFiber.alternate; - function reconcileChildrenArray( - returnFiber, - currentFirstChild, - newChildren, - lanes - ) { - // This algorithm can't optimize by searching from both ends since we - // don't have backpointers on fibers. I'm trying to see how far we can get - // with that model. If it ends up not being worth the tradeoffs, we can - // add it later. - // Even with a two ended optimization, we'd want to optimize for the case - // where there are few changes and brute force the comparison instead of - // going for the Map. It'd like to explore hitting that path first in - // forward-only mode and only go for the Map once we notice that we need - // lots of look ahead. This doesn't handle reversal as well as two ended - // search but that's unusual. Besides, for the two ended optimization to - // work on Iterables, we'd need to copy the whole set. - // In this first iteration, we'll just live with hitting the bad case - // (adding everything to a Map) in for every insert/move. - // If you change this code, also update reconcileChildrenIterator() which - // uses the same algorithm. - { - // First, validate keys. - var knownKeys = null; + if (current !== null) { + var oldIndex = current.index; - for (var i = 0; i < newChildren.length; i++) { - var child = newChildren[i]; - knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); + if (oldIndex < lastPlacedIndex) { + // This is a move. + newFiber.flags |= Placement | PlacementDEV; + return lastPlacedIndex; + } else { + // This item can stay in place. + return oldIndex; } + } else { + // This is an insertion. + newFiber.flags |= Placement | PlacementDEV; + return lastPlacedIndex; } + } - var resultingFirstChild = null; - var previousNewFiber = null; - var oldFiber = currentFirstChild; - var lastPlacedIndex = 0; - var newIdx = 0; - var nextOldFiber = null; + function placeSingleChild(newFiber) { + // This is simpler for the single child case. We only need to do a + // placement for inserting new children. + if (shouldTrackSideEffects && newFiber.alternate === null) { + newFiber.flags |= Placement | PlacementDEV; + } - for (; oldFiber !== null && newIdx < newChildren.length; newIdx++) { - if (oldFiber.index > newIdx) { - nextOldFiber = oldFiber; - oldFiber = null; - } else { - nextOldFiber = oldFiber.sibling; - } + return newFiber; + } - var newFiber = updateSlot( - returnFiber, - oldFiber, - newChildren[newIdx], + function updateTextNode(returnFiber, current, textContent, lanes) { + if (current === null || current.tag !== HostText) { + // Insert + var created = createFiberFromText( + textContent, + returnFiber.mode, lanes ); + created.return = returnFiber; + return created; + } else { + // Update + var existing = useFiber(current, textContent); + existing.return = returnFiber; + return existing; + } + } - if (newFiber === null) { - // TODO: This breaks on empty slots like null children. That's - // unfortunate because it triggers the slow path all the time. We need - // a better way to communicate whether this was a miss or null, - // boolean, undefined, etc. - if (oldFiber === null) { - oldFiber = nextOldFiber; - } + function updateElement(returnFiber, current, element, lanes) { + var elementType = element.type; - break; - } + if (elementType === REACT_FRAGMENT_TYPE) { + return updateFragment( + returnFiber, + current, + element.props.children, + lanes, + element.key + ); + } - if (shouldTrackSideEffects) { - if (oldFiber && newFiber.alternate === null) { - // We matched the slot, but we didn't reuse the existing fiber, so we - // need to delete the existing child. - deleteChild(returnFiber, oldFiber); - } - } + if (current !== null) { + if ( + current.elementType === elementType || // Keep this check inline so it only runs on the false path: + isCompatibleFamilyForHotReloading(current, element) || // Lazy types should reconcile their resolved type. + // We need to do this after the Hot Reloading check above, + // because hot reloading has different semantics than prod because + // it doesn't resuspend. So we can't let the call below suspend. + (typeof elementType === "object" && + elementType !== null && + elementType.$$typeof === REACT_LAZY_TYPE && + resolveLazy(elementType) === current.type) + ) { + // Move based on index + var existing = useFiber(current, element.props); + existing.ref = coerceRef(returnFiber, current, element); + existing.return = returnFiber; - lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx); + { + existing._debugSource = element._source; + existing._debugOwner = element._owner; + } - if (previousNewFiber === null) { - // TODO: Move out of the loop. This only happens for the first run. - resultingFirstChild = newFiber; - } else { - // TODO: Defer siblings if we're not at the right index for this slot. - // I.e. if we had null values before, then we want to defer this - // for each null value. However, we also don't want to call updateSlot - // with the previous one. - previousNewFiber.sibling = newFiber; + return existing; } + } // Insert - previousNewFiber = newFiber; - oldFiber = nextOldFiber; + var created = createFiberFromElement(element, returnFiber.mode, lanes); + created.ref = coerceRef(returnFiber, current, element); + created.return = returnFiber; + return created; + } + + function updatePortal(returnFiber, current, portal, lanes) { + if ( + current === null || + current.tag !== HostPortal || + current.stateNode.containerInfo !== portal.containerInfo || + current.stateNode.implementation !== portal.implementation + ) { + // Insert + var created = createFiberFromPortal(portal, returnFiber.mode, lanes); + created.return = returnFiber; + return created; + } else { + // Update + var existing = useFiber(current, portal.children || []); + existing.return = returnFiber; + return existing; } + } - if (newIdx === newChildren.length) { - // We've reached the end of the new children. We can delete the rest. - deleteRemainingChildren(returnFiber, oldFiber); + function updateFragment(returnFiber, current, fragment, lanes, key) { + if (current === null || current.tag !== Fragment) { + // Insert + var created = createFiberFromFragment( + fragment, + returnFiber.mode, + lanes, + key + ); + created.return = returnFiber; + return created; + } else { + // Update + var existing = useFiber(current, fragment); + existing.return = returnFiber; + return existing; + } + } - return resultingFirstChild; + function createChild(returnFiber, newChild, lanes) { + if ( + (typeof newChild === "string" && newChild !== "") || + typeof newChild === "number" + ) { + // Text nodes don't have keys. If the previous node is implicitly keyed + // we can continue to replace it without aborting even if it is not a text + // node. + var created = createFiberFromText( + "" + newChild, + returnFiber.mode, + lanes + ); + created.return = returnFiber; + return created; } - if (oldFiber === null) { - // If we don't have any more existing children we can choose a fast path - // since the rest will all be insertions. - for (; newIdx < newChildren.length; newIdx++) { - var _newFiber = createChild( - returnFiber, - newChildren[newIdx], - lanes - ); + if (typeof newChild === "object" && newChild !== null) { + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE: { + var _created = createFiberFromElement( + newChild, + returnFiber.mode, + lanes + ); - if (_newFiber === null) { - continue; + _created.ref = coerceRef(returnFiber, null, newChild); + _created.return = returnFiber; + return _created; } - lastPlacedIndex = placeChild(_newFiber, lastPlacedIndex, newIdx); + case REACT_PORTAL_TYPE: { + var _created2 = createFiberFromPortal( + newChild, + returnFiber.mode, + lanes + ); - if (previousNewFiber === null) { - // TODO: Move out of the loop. This only happens for the first run. - resultingFirstChild = _newFiber; - } else { - previousNewFiber.sibling = _newFiber; + _created2.return = returnFiber; + return _created2; } - previousNewFiber = _newFiber; + case REACT_LAZY_TYPE: { + var payload = newChild._payload; + var init = newChild._init; + return createChild(returnFiber, init(payload), lanes); + } } - return resultingFirstChild; - } // Add all children to a key map for quick lookups. - - var existingChildren = mapRemainingChildren(returnFiber, oldFiber); // Keep scanning and use the map to restore deleted items as moves. - - for (; newIdx < newChildren.length; newIdx++) { - var _newFiber2 = updateFromMap( - existingChildren, - returnFiber, - newIdx, - newChildren[newIdx], - lanes - ); - - if (_newFiber2 !== null) { - if (shouldTrackSideEffects) { - if (_newFiber2.alternate !== null) { - // The new fiber is a work in progress, but if there exists a - // current, that means that we reused the fiber. We need to delete - // it from the child list so that we don't add it to the deletion - // list. - existingChildren.delete( - _newFiber2.key === null ? newIdx : _newFiber2.key - ); - } - } + if (isArray(newChild) || getIteratorFn(newChild)) { + var _created3 = createFiberFromFragment( + newChild, + returnFiber.mode, + lanes, + null + ); - lastPlacedIndex = placeChild(_newFiber2, lastPlacedIndex, newIdx); + _created3.return = returnFiber; + return _created3; + } // Usable node types + // + // Unwrap the inner value and recursively call this function again. - if (previousNewFiber === null) { - resultingFirstChild = _newFiber2; - } else { - previousNewFiber.sibling = _newFiber2; - } + if (typeof newChild.then === "function") { + var thenable = newChild; + return createChild(returnFiber, unwrapThenable(thenable), lanes); + } - previousNewFiber = _newFiber2; + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) { + var context = newChild; + return createChild( + returnFiber, + readContextDuringReconcilation(returnFiber, context, lanes), + lanes + ); } + + throwOnInvalidObjectType(returnFiber, newChild); } - if (shouldTrackSideEffects) { - // Any existing children that weren't consumed above were deleted. We need - // to add them to the deletion list. - existingChildren.forEach(function (child) { - return deleteChild(returnFiber, child); - }); + { + if (typeof newChild === "function") { + warnOnFunctionType(returnFiber); + } } - return resultingFirstChild; + return null; } - function reconcileChildrenIterator( - returnFiber, - currentFirstChild, - newChildrenIterable, - lanes - ) { - // This is the same implementation as reconcileChildrenArray(), - // but using the iterator instead. - var iteratorFn = getIteratorFn(newChildrenIterable); + function updateSlot(returnFiber, oldFiber, newChild, lanes) { + // Update the fiber if the keys match, otherwise return null. + var key = oldFiber !== null ? oldFiber.key : null; - if (typeof iteratorFn !== "function") { - throw new Error( - "An object is not an iterable. This error is likely caused by a bug in " + - "React. Please file an issue." - ); + if ( + (typeof newChild === "string" && newChild !== "") || + typeof newChild === "number" + ) { + // Text nodes don't have keys. If the previous node is implicitly keyed + // we can continue to replace it without aborting even if it is not a text + // node. + if (key !== null) { + return null; + } + + return updateTextNode(returnFiber, oldFiber, "" + newChild, lanes); } - { - // We don't support rendering Generators because it's a mutation. - // See https://github.com/facebook/react/issues/12995 - if ( - typeof Symbol === "function" && // $FlowFixMe[prop-missing] Flow doesn't know about toStringTag - newChildrenIterable[Symbol.toStringTag] === "Generator" - ) { - if (!didWarnAboutGenerators) { - error( - "Using Generators as children is unsupported and will likely yield " + - "unexpected results because enumerating a generator mutates it. " + - "You may convert it to an array with `Array.from()` or the " + - "`[...spread]` operator before rendering. Keep in mind " + - "you might need to polyfill these features for older browsers." - ); + if (typeof newChild === "object" && newChild !== null) { + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE: { + if (newChild.key === key) { + return updateElement(returnFiber, oldFiber, newChild, lanes); + } else { + return null; + } } - didWarnAboutGenerators = true; - } // Warn about using Maps as children - - if (newChildrenIterable.entries === iteratorFn) { - if (!didWarnAboutMaps) { - error( - "Using Maps as children is not supported. " + - "Use an array of keyed ReactElements instead." - ); + case REACT_PORTAL_TYPE: { + if (newChild.key === key) { + return updatePortal(returnFiber, oldFiber, newChild, lanes); + } else { + return null; + } } - didWarnAboutMaps = true; - } // First, validate keys. - // We'll get a different iterator later for the main pass. - - var _newChildren = iteratorFn.call(newChildrenIterable); - - if (_newChildren) { - var knownKeys = null; - - var _step = _newChildren.next(); - - for (; !_step.done; _step = _newChildren.next()) { - var child = _step.value; - knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); + case REACT_LAZY_TYPE: { + var payload = newChild._payload; + var init = newChild._init; + return updateSlot(returnFiber, oldFiber, init(payload), lanes); } } - } - - var newChildren = iteratorFn.call(newChildrenIterable); - - if (newChildren == null) { - throw new Error("An iterable object provided no iterator."); - } - - var resultingFirstChild = null; - var previousNewFiber = null; - var oldFiber = currentFirstChild; - var lastPlacedIndex = 0; - var newIdx = 0; - var nextOldFiber = null; - var step = newChildren.next(); - - for ( - ; - oldFiber !== null && !step.done; - newIdx++, step = newChildren.next() - ) { - if (oldFiber.index > newIdx) { - nextOldFiber = oldFiber; - oldFiber = null; - } else { - nextOldFiber = oldFiber.sibling; - } - - var newFiber = updateSlot(returnFiber, oldFiber, step.value, lanes); - if (newFiber === null) { - // TODO: This breaks on empty slots like null children. That's - // unfortunate because it triggers the slow path all the time. We need - // a better way to communicate whether this was a miss or null, - // boolean, undefined, etc. - if (oldFiber === null) { - oldFiber = nextOldFiber; + if (isArray(newChild) || getIteratorFn(newChild)) { + if (key !== null) { + return null; } - break; + return updateFragment(returnFiber, oldFiber, newChild, lanes, null); + } // Usable node types + // + // Unwrap the inner value and recursively call this function again. + + if (typeof newChild.then === "function") { + var thenable = newChild; + return updateSlot( + returnFiber, + oldFiber, + unwrapThenable(thenable), + lanes + ); } - if (shouldTrackSideEffects) { - if (oldFiber && newFiber.alternate === null) { - // We matched the slot, but we didn't reuse the existing fiber, so we - // need to delete the existing child. - deleteChild(returnFiber, oldFiber); - } + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) { + var context = newChild; + return updateSlot( + returnFiber, + oldFiber, + readContextDuringReconcilation(returnFiber, context, lanes), + lanes + ); } - lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx); + throwOnInvalidObjectType(returnFiber, newChild); + } - if (previousNewFiber === null) { - // TODO: Move out of the loop. This only happens for the first run. - resultingFirstChild = newFiber; - } else { - // TODO: Defer siblings if we're not at the right index for this slot. - // I.e. if we had null values before, then we want to defer this - // for each null value. However, we also don't want to call updateSlot - // with the previous one. - previousNewFiber.sibling = newFiber; + { + if (typeof newChild === "function") { + warnOnFunctionType(returnFiber); } - - previousNewFiber = newFiber; - oldFiber = nextOldFiber; } - if (step.done) { - // We've reached the end of the new children. We can delete the rest. - deleteRemainingChildren(returnFiber, oldFiber); + return null; + } - return resultingFirstChild; + function updateFromMap( + existingChildren, + returnFiber, + newIdx, + newChild, + lanes + ) { + if ( + (typeof newChild === "string" && newChild !== "") || + typeof newChild === "number" + ) { + // Text nodes don't have keys, so we neither have to check the old nor + // new node for the key. If both are text nodes, they match. + var matchedFiber = existingChildren.get(newIdx) || null; + return updateTextNode( + returnFiber, + matchedFiber, + "" + newChild, + lanes + ); } - if (oldFiber === null) { - // If we don't have any more existing children we can choose a fast path - // since the rest will all be insertions. - for (; !step.done; newIdx++, step = newChildren.next()) { - var _newFiber3 = createChild(returnFiber, step.value, lanes); + if (typeof newChild === "object" && newChild !== null) { + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE: { + var _matchedFiber = + existingChildren.get( + newChild.key === null ? newIdx : newChild.key + ) || null; - if (_newFiber3 === null) { - continue; + return updateElement(returnFiber, _matchedFiber, newChild, lanes); } - lastPlacedIndex = placeChild(_newFiber3, lastPlacedIndex, newIdx); + case REACT_PORTAL_TYPE: { + var _matchedFiber2 = + existingChildren.get( + newChild.key === null ? newIdx : newChild.key + ) || null; - if (previousNewFiber === null) { - // TODO: Move out of the loop. This only happens for the first run. - resultingFirstChild = _newFiber3; - } else { - previousNewFiber.sibling = _newFiber3; + return updatePortal(returnFiber, _matchedFiber2, newChild, lanes); } - previousNewFiber = _newFiber3; + case REACT_LAZY_TYPE: + var payload = newChild._payload; + var init = newChild._init; + return updateFromMap( + existingChildren, + returnFiber, + newIdx, + init(payload), + lanes + ); } - return resultingFirstChild; - } // Add all children to a key map for quick lookups. - - var existingChildren = mapRemainingChildren(returnFiber, oldFiber); // Keep scanning and use the map to restore deleted items as moves. - - for (; !step.done; newIdx++, step = newChildren.next()) { - var _newFiber4 = updateFromMap( - existingChildren, - returnFiber, - newIdx, - step.value, - lanes - ); - - if (_newFiber4 !== null) { - if (shouldTrackSideEffects) { - if (_newFiber4.alternate !== null) { - // The new fiber is a work in progress, but if there exists a - // current, that means that we reused the fiber. We need to delete - // it from the child list so that we don't add it to the deletion - // list. - existingChildren.delete( - _newFiber4.key === null ? newIdx : _newFiber4.key - ); - } - } + if (isArray(newChild) || getIteratorFn(newChild)) { + var _matchedFiber3 = existingChildren.get(newIdx) || null; - lastPlacedIndex = placeChild(_newFiber4, lastPlacedIndex, newIdx); + return updateFragment( + returnFiber, + _matchedFiber3, + newChild, + lanes, + null + ); + } // Usable node types + // + // Unwrap the inner value and recursively call this function again. - if (previousNewFiber === null) { - resultingFirstChild = _newFiber4; - } else { - previousNewFiber.sibling = _newFiber4; - } + if (typeof newChild.then === "function") { + var thenable = newChild; + return updateFromMap( + existingChildren, + returnFiber, + newIdx, + unwrapThenable(thenable), + lanes + ); + } - previousNewFiber = _newFiber4; + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) { + var context = newChild; + return updateFromMap( + existingChildren, + returnFiber, + newIdx, + readContextDuringReconcilation(returnFiber, context, lanes), + lanes + ); } - } - if (shouldTrackSideEffects) { - // Any existing children that weren't consumed above were deleted. We need - // to add them to the deletion list. - existingChildren.forEach(function (child) { - return deleteChild(returnFiber, child); - }); + throwOnInvalidObjectType(returnFiber, newChild); } - return resultingFirstChild; - } - - function reconcileSingleTextNode( - returnFiber, - currentFirstChild, - textContent, - lanes - ) { - // There's no need to check for keys on text nodes since we don't have a - // way to define them. - if (currentFirstChild !== null && currentFirstChild.tag === HostText) { - // We already have an existing node so let's just update it and delete - // the rest. - deleteRemainingChildren(returnFiber, currentFirstChild.sibling); - var existing = useFiber(currentFirstChild, textContent); - existing.return = returnFiber; - return existing; - } // The existing first child is not a text node so we need to create one - // and delete the existing ones. + { + if (typeof newChild === "function") { + warnOnFunctionType(returnFiber); + } + } - deleteRemainingChildren(returnFiber, currentFirstChild); - var created = createFiberFromText(textContent, returnFiber.mode, lanes); - created.return = returnFiber; - return created; + return null; } + /** + * Warns if there is a duplicate or missing key + */ - function reconcileSingleElement( - returnFiber, - currentFirstChild, - element, - lanes - ) { - var key = element.key; - var child = currentFirstChild; + function warnOnInvalidKey(child, knownKeys, returnFiber) { + { + if (typeof child !== "object" || child === null) { + return knownKeys; + } - while (child !== null) { - // TODO: If key === null and child.key === null, then this only applies to - // the first item in the list. - if (child.key === key) { - var elementType = element.type; + switch (child.$$typeof) { + case REACT_ELEMENT_TYPE: + case REACT_PORTAL_TYPE: + warnForMissingKey(child, returnFiber); + var key = child.key; - if (elementType === REACT_FRAGMENT_TYPE) { - if (child.tag === Fragment) { - deleteRemainingChildren(returnFiber, child.sibling); - var existing = useFiber(child, element.props.children); - existing.return = returnFiber; + if (typeof key !== "string") { + break; + } - { - existing._debugSource = element._source; - existing._debugOwner = element._owner; - } + if (knownKeys === null) { + knownKeys = new Set(); + knownKeys.add(key); + break; + } - return existing; + if (!knownKeys.has(key)) { + knownKeys.add(key); + break; } - } else { - if ( - child.elementType === elementType || // Keep this check inline so it only runs on the false path: - isCompatibleFamilyForHotReloading(child, element) || // Lazy types should reconcile their resolved type. - // We need to do this after the Hot Reloading check above, - // because hot reloading has different semantics than prod because - // it doesn't resuspend. So we can't let the call below suspend. - (typeof elementType === "object" && - elementType !== null && - elementType.$$typeof === REACT_LAZY_TYPE && - resolveLazy(elementType) === child.type) - ) { - deleteRemainingChildren(returnFiber, child.sibling); - var _existing = useFiber(child, element.props); + error( + "Encountered two children with the same key, `%s`. " + + "Keys should be unique so that components maintain their identity " + + "across updates. Non-unique keys may cause children to be " + + "duplicated and/or omitted — the behavior is unsupported and " + + "could change in a future version.", + key + ); - _existing.ref = coerceRef(returnFiber, child, element); - _existing.return = returnFiber; + break; - { - _existing._debugSource = element._source; - _existing._debugOwner = element._owner; - } + case REACT_LAZY_TYPE: + var payload = child._payload; + var init = child._init; + warnOnInvalidKey(init(payload), knownKeys, returnFiber); + break; + } + } - return _existing; - } - } // Didn't match. + return knownKeys; + } - deleteRemainingChildren(returnFiber, child); - break; - } else { - deleteChild(returnFiber, child); - } - - child = child.sibling; - } - - if (element.type === REACT_FRAGMENT_TYPE) { - var created = createFiberFromFragment( - element.props.children, - returnFiber.mode, - lanes, - element.key - ); - created.return = returnFiber; - return created; - } else { - var _created4 = createFiberFromElement( - element, - returnFiber.mode, - lanes - ); - - _created4.ref = coerceRef(returnFiber, currentFirstChild, element); - _created4.return = returnFiber; - return _created4; - } - } - - function reconcileSinglePortal( + function reconcileChildrenArray( returnFiber, currentFirstChild, - portal, + newChildren, lanes ) { - var key = portal.key; - var child = currentFirstChild; + // This algorithm can't optimize by searching from both ends since we + // don't have backpointers on fibers. I'm trying to see how far we can get + // with that model. If it ends up not being worth the tradeoffs, we can + // add it later. + // Even with a two ended optimization, we'd want to optimize for the case + // where there are few changes and brute force the comparison instead of + // going for the Map. It'd like to explore hitting that path first in + // forward-only mode and only go for the Map once we notice that we need + // lots of look ahead. This doesn't handle reversal as well as two ended + // search but that's unusual. Besides, for the two ended optimization to + // work on Iterables, we'd need to copy the whole set. + // In this first iteration, we'll just live with hitting the bad case + // (adding everything to a Map) in for every insert/move. + // If you change this code, also update reconcileChildrenIterator() which + // uses the same algorithm. + { + // First, validate keys. + var knownKeys = null; - while (child !== null) { - // TODO: If key === null and child.key === null, then this only applies to - // the first item in the list. - if (child.key === key) { - if ( - child.tag === HostPortal && - child.stateNode.containerInfo === portal.containerInfo && - child.stateNode.implementation === portal.implementation - ) { - deleteRemainingChildren(returnFiber, child.sibling); - var existing = useFiber(child, portal.children || []); - existing.return = returnFiber; - return existing; - } else { - deleteRemainingChildren(returnFiber, child); - break; - } - } else { - deleteChild(returnFiber, child); + for (var i = 0; i < newChildren.length; i++) { + var child = newChildren[i]; + knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); } - - child = child.sibling; } - var created = createFiberFromPortal(portal, returnFiber.mode, lanes); - created.return = returnFiber; - return created; - } // This API will tag the children with the side-effect of the reconciliation - // itself. They will be added to the side-effect list as we pass through the - // children and the parent. - - function reconcileChildFibersImpl( - returnFiber, - currentFirstChild, - newChild, - lanes - ) { - // This function is not recursive. - // If the top level item is an array, we treat it as a set of children, - // not as a fragment. Nested arrays on the other hand will be treated as - // fragment nodes. Recursion happens at the normal flow. - // Handle top level unkeyed fragments as if they were arrays. - // This leads to an ambiguity between <>{[...]} and <>.... - // We treat the ambiguous cases above the same. - // TODO: Let's use recursion like we do for Usable nodes? - var isUnkeyedTopLevelFragment = - typeof newChild === "object" && - newChild !== null && - newChild.type === REACT_FRAGMENT_TYPE && - newChild.key === null; - - if (isUnkeyedTopLevelFragment) { - newChild = newChild.props.children; - } // Handle object types + var resultingFirstChild = null; + var previousNewFiber = null; + var oldFiber = currentFirstChild; + var lastPlacedIndex = 0; + var newIdx = 0; + var nextOldFiber = null; - if (typeof newChild === "object" && newChild !== null) { - switch (newChild.$$typeof) { - case REACT_ELEMENT_TYPE: - return placeSingleChild( - reconcileSingleElement( - returnFiber, - currentFirstChild, - newChild, - lanes - ) - ); + for (; oldFiber !== null && newIdx < newChildren.length; newIdx++) { + if (oldFiber.index > newIdx) { + nextOldFiber = oldFiber; + oldFiber = null; + } else { + nextOldFiber = oldFiber.sibling; + } - case REACT_PORTAL_TYPE: - return placeSingleChild( - reconcileSinglePortal( - returnFiber, - currentFirstChild, - newChild, - lanes - ) - ); + var newFiber = updateSlot( + returnFiber, + oldFiber, + newChildren[newIdx], + lanes + ); - case REACT_LAZY_TYPE: - var payload = newChild._payload; - var init = newChild._init; // TODO: This function is supposed to be non-recursive. + if (newFiber === null) { + // TODO: This breaks on empty slots like null children. That's + // unfortunate because it triggers the slow path all the time. We need + // a better way to communicate whether this was a miss or null, + // boolean, undefined, etc. + if (oldFiber === null) { + oldFiber = nextOldFiber; + } - return reconcileChildFibers( - returnFiber, - currentFirstChild, - init(payload), - lanes - ); + break; } - if (isArray(newChild)) { - return reconcileChildrenArray( - returnFiber, - currentFirstChild, - newChild, - lanes - ); + if (shouldTrackSideEffects) { + if (oldFiber && newFiber.alternate === null) { + // We matched the slot, but we didn't reuse the existing fiber, so we + // need to delete the existing child. + deleteChild(returnFiber, oldFiber); + } } - if (getIteratorFn(newChild)) { - return reconcileChildrenIterator( - returnFiber, - currentFirstChild, - newChild, - lanes - ); - } // Usables are a valid React node type. When React encounters a Usable in - // a child position, it unwraps it using the same algorithm as `use`. For - // example, for promises, React will throw an exception to unwind the - // stack, then replay the component once the promise resolves. - // - // A difference from `use` is that React will keep unwrapping the value - // until it reaches a non-Usable type. - // - // e.g. Usable>> should resolve to T - // - // The structure is a bit unfortunate. Ideally, we shouldn't need to - // replay the entire begin phase of the parent fiber in order to reconcile - // the children again. This would require a somewhat significant refactor, - // because reconcilation happens deep within the begin phase, and - // depending on the type of work, not always at the end. We should - // consider as an future improvement. + lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx); - if (typeof newChild.then === "function") { - var thenable = newChild; - return reconcileChildFibersImpl( - returnFiber, - currentFirstChild, - unwrapThenable(thenable), - lanes - ); + if (previousNewFiber === null) { + // TODO: Move out of the loop. This only happens for the first run. + resultingFirstChild = newFiber; + } else { + // TODO: Defer siblings if we're not at the right index for this slot. + // I.e. if we had null values before, then we want to defer this + // for each null value. However, we also don't want to call updateSlot + // with the previous one. + previousNewFiber.sibling = newFiber; } - if ( - newChild.$$typeof === REACT_CONTEXT_TYPE || - newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE - ) { - var context = newChild; - return reconcileChildFibersImpl( - returnFiber, - currentFirstChild, - readContextDuringReconcilation(returnFiber, context, lanes), - lanes - ); - } + previousNewFiber = newFiber; + oldFiber = nextOldFiber; + } - throwOnInvalidObjectType(returnFiber, newChild); + if (newIdx === newChildren.length) { + // We've reached the end of the new children. We can delete the rest. + deleteRemainingChildren(returnFiber, oldFiber); + + return resultingFirstChild; } - if ( - (typeof newChild === "string" && newChild !== "") || - typeof newChild === "number" - ) { - return placeSingleChild( - reconcileSingleTextNode( + if (oldFiber === null) { + // If we don't have any more existing children we can choose a fast path + // since the rest will all be insertions. + for (; newIdx < newChildren.length; newIdx++) { + var _newFiber = createChild( returnFiber, - currentFirstChild, - "" + newChild, + newChildren[newIdx], lanes - ) - ); - } + ); - { - if (typeof newChild === "function") { - warnOnFunctionType(returnFiber); - } - } // Remaining cases are all treated as empty. + if (_newFiber === null) { + continue; + } - return deleteRemainingChildren(returnFiber, currentFirstChild); - } + lastPlacedIndex = placeChild(_newFiber, lastPlacedIndex, newIdx); - function reconcileChildFibers( - returnFiber, - currentFirstChild, - newChild, - lanes - ) { - // This indirection only exists so we can reset `thenableState` at the end. - // It should get inlined by Closure. - thenableIndexCounter$1 = 0; - var firstChildFiber = reconcileChildFibersImpl( - returnFiber, - currentFirstChild, - newChild, - lanes - ); - thenableState$1 = null; // Don't bother to reset `thenableIndexCounter` to 0 because it always gets - // set at the beginning. + if (previousNewFiber === null) { + // TODO: Move out of the loop. This only happens for the first run. + resultingFirstChild = _newFiber; + } else { + previousNewFiber.sibling = _newFiber; + } - return firstChildFiber; - } + previousNewFiber = _newFiber; + } - return reconcileChildFibers; - } + return resultingFirstChild; + } // Add all children to a key map for quick lookups. - var reconcileChildFibers = createChildReconciler(true); - var mountChildFibers = createChildReconciler(false); - function resetChildReconcilerOnUnwind() { - // On unwind, clear any pending thenables that were used. - thenableState$1 = null; - thenableIndexCounter$1 = 0; - } - function cloneChildFibers(current, workInProgress) { - if (current !== null && workInProgress.child !== current.child) { - throw new Error("Resuming work not yet implemented."); - } + var existingChildren = mapRemainingChildren(returnFiber, oldFiber); // Keep scanning and use the map to restore deleted items as moves. - if (workInProgress.child === null) { - return; - } + for (; newIdx < newChildren.length; newIdx++) { + var _newFiber2 = updateFromMap( + existingChildren, + returnFiber, + newIdx, + newChildren[newIdx], + lanes + ); - var currentChild = workInProgress.child; - var newChild = createWorkInProgress( - currentChild, - currentChild.pendingProps - ); - workInProgress.child = newChild; - newChild.return = workInProgress; + if (_newFiber2 !== null) { + if (shouldTrackSideEffects) { + if (_newFiber2.alternate !== null) { + // The new fiber is a work in progress, but if there exists a + // current, that means that we reused the fiber. We need to delete + // it from the child list so that we don't add it to the deletion + // list. + existingChildren.delete( + _newFiber2.key === null ? newIdx : _newFiber2.key + ); + } + } - while (currentChild.sibling !== null) { - currentChild = currentChild.sibling; - newChild = newChild.sibling = createWorkInProgress( - currentChild, - currentChild.pendingProps - ); - newChild.return = workInProgress; - } + lastPlacedIndex = placeChild(_newFiber2, lastPlacedIndex, newIdx); - newChild.sibling = null; - } // Reset a workInProgress child set to prepare it for a second pass. + if (previousNewFiber === null) { + resultingFirstChild = _newFiber2; + } else { + previousNewFiber.sibling = _newFiber2; + } - function resetChildFibers(workInProgress, lanes) { - var child = workInProgress.child; + previousNewFiber = _newFiber2; + } + } - while (child !== null) { - resetWorkInProgress(child, lanes); - child = child.sibling; + if (shouldTrackSideEffects) { + // Any existing children that weren't consumed above were deleted. We need + // to add them to the deletion list. + existingChildren.forEach(function (child) { + return deleteChild(returnFiber, child); + }); + } + + return resultingFirstChild; } - } - // TODO: This isn't being used yet, but it's intended to replace the - // InvisibleParentContext that is currently managed by SuspenseContext. + function reconcileChildrenIterator( + returnFiber, + currentFirstChild, + newChildrenIterable, + lanes + ) { + // This is the same implementation as reconcileChildrenArray(), + // but using the iterator instead. + var iteratorFn = getIteratorFn(newChildrenIterable); - var currentTreeHiddenStackCursor = createCursor(null); - var prevEntangledRenderLanesCursor = createCursor(NoLanes); - function pushHiddenContext(fiber, context) { - var prevEntangledRenderLanes = getEntangledRenderLanes(); - push(prevEntangledRenderLanesCursor, prevEntangledRenderLanes, fiber); - push(currentTreeHiddenStackCursor, context, fiber); // When rendering a subtree that's currently hidden, we must include all - // lanes that would have rendered if the hidden subtree hadn't been deferred. - // That is, in order to reveal content from hidden -> visible, we must commit - // all the updates that we skipped when we originally hid the tree. + if (typeof iteratorFn !== "function") { + throw new Error( + "An object is not an iterable. This error is likely caused by a bug in " + + "React. Please file an issue." + ); + } - setEntangledRenderLanes( - mergeLanes(prevEntangledRenderLanes, context.baseLanes) - ); - } - function reuseHiddenContextOnStack(fiber) { - // This subtree is not currently hidden, so we don't need to add any lanes - // to the render lanes. But we still need to push something to avoid a - // context mismatch. Reuse the existing context on the stack. - push(prevEntangledRenderLanesCursor, getEntangledRenderLanes(), fiber); - push( - currentTreeHiddenStackCursor, - currentTreeHiddenStackCursor.current, - fiber - ); - } - function popHiddenContext(fiber) { - // Restore the previous render lanes from the stack - setEntangledRenderLanes(prevEntangledRenderLanesCursor.current); - pop(currentTreeHiddenStackCursor, fiber); - pop(prevEntangledRenderLanesCursor, fiber); - } - function isCurrentTreeHidden() { - return currentTreeHiddenStackCursor.current !== null; - } + { + // We don't support rendering Generators because it's a mutation. + // See https://github.com/facebook/react/issues/12995 + if ( + typeof Symbol === "function" && // $FlowFixMe[prop-missing] Flow doesn't know about toStringTag + newChildrenIterable[Symbol.toStringTag] === "Generator" + ) { + if (!didWarnAboutGenerators) { + error( + "Using Generators as children is unsupported and will likely yield " + + "unexpected results because enumerating a generator mutates it. " + + "You may convert it to an array with `Array.from()` or the " + + "`[...spread]` operator before rendering. Keep in mind " + + "you might need to polyfill these features for older browsers." + ); + } - // suspends, i.e. it's the nearest `catch` block on the stack. + didWarnAboutGenerators = true; + } // Warn about using Maps as children - var suspenseHandlerStackCursor = createCursor(null); // Represents the outermost boundary that is not visible in the current tree. - // Everything above this is the "shell". When this is null, it means we're - // rendering in the shell of the app. If it's non-null, it means we're rendering - // deeper than the shell, inside a new tree that wasn't already visible. - // - // The main way we use this concept is to determine whether showing a fallback - // would result in a desirable or undesirable loading state. Activing a fallback - // in the shell is considered an undersirable loading state, because it would - // mean hiding visible (albeit stale) content in the current tree — we prefer to - // show the stale content, rather than switch to a fallback. But showing a - // fallback in a new tree is fine, because there's no stale content to - // prefer instead. + if (newChildrenIterable.entries === iteratorFn) { + if (!didWarnAboutMaps) { + error( + "Using Maps as children is not supported. " + + "Use an array of keyed ReactElements instead." + ); + } - var shellBoundary = null; - function getShellBoundary() { - return shellBoundary; - } - function pushPrimaryTreeSuspenseHandler(handler) { - // TODO: Pass as argument - var current = handler.alternate; - // propagated a single level. For example, when ForceSuspenseFallback is set, - // it should only force the nearest Suspense boundary into fallback mode. + didWarnAboutMaps = true; + } // First, validate keys. + // We'll get a different iterator later for the main pass. - pushSuspenseListContext( - handler, - setDefaultShallowSuspenseListContext(suspenseStackCursor.current) - ); // Experimental feature: Some Suspense boundaries are marked as having an - // to push a nested Suspense handler, because it will get replaced by the - // outer fallback, anyway. Consider this as a future optimization. + var _newChildren = iteratorFn.call(newChildrenIterable); - push(suspenseHandlerStackCursor, handler, handler); + if (_newChildren) { + var knownKeys = null; - if (shellBoundary === null) { - if (current === null || isCurrentTreeHidden()) { - // This boundary is not visible in the current UI. - shellBoundary = handler; - } else { - var prevState = current.memoizedState; + var _step = _newChildren.next(); - if (prevState !== null) { - // This boundary is showing a fallback in the current UI. - shellBoundary = handler; + for (; !_step.done; _step = _newChildren.next()) { + var child = _step.value; + knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); + } } } - } - } - function pushFallbackTreeSuspenseHandler(fiber) { - // We're about to render the fallback. If something in the fallback suspends, - // it's akin to throwing inside of a `catch` block. This boundary should not - // capture. Reuse the existing handler on the stack. - reuseSuspenseHandlerOnStack(fiber); - } - function pushOffscreenSuspenseHandler(fiber) { - if (fiber.tag === OffscreenComponent) { - // A SuspenseList context is only pushed here to avoid a push/pop mismatch. - // Reuse the current value on the stack. - // TODO: We can avoid needing to push here by by forking popSuspenseHandler - // into separate functions for Suspense and Offscreen. - pushSuspenseListContext(fiber, suspenseStackCursor.current); - push(suspenseHandlerStackCursor, fiber, fiber); - - if (shellBoundary !== null); - else { - var current = fiber.alternate; - if (current !== null) { - var prevState = current.memoizedState; + var newChildren = iteratorFn.call(newChildrenIterable); - if (prevState !== null) { - // This is the first boundary in the stack that's already showing - // a fallback. So everything outside is considered the shell. - shellBoundary = fiber; - } - } + if (newChildren == null) { + throw new Error("An iterable object provided no iterator."); } - } else { - // This is a LegacyHidden component. - reuseSuspenseHandlerOnStack(fiber); - } - } - function reuseSuspenseHandlerOnStack(fiber) { - pushSuspenseListContext(fiber, suspenseStackCursor.current); - push(suspenseHandlerStackCursor, getSuspenseHandler(), fiber); - } - function getSuspenseHandler() { - return suspenseHandlerStackCursor.current; - } - function popSuspenseHandler(fiber) { - pop(suspenseHandlerStackCursor, fiber); - - if (shellBoundary === fiber) { - // Popping back into the shell. - shellBoundary = null; - } - - popSuspenseListContext(fiber); - } // SuspenseList context - // TODO: Move to a separate module? We may change the SuspenseList - // implementation to hide/show in the commit phase, anyway. - - var DefaultSuspenseContext = 0; - var SubtreeSuspenseContextMask = 1; // ForceSuspenseFallback can be used by SuspenseList to force newly added - // items into their fallback state during one of the render passes. - var ForceSuspenseFallback = 2; - var suspenseStackCursor = createCursor(DefaultSuspenseContext); - function hasSuspenseListContext(parentContext, flag) { - return (parentContext & flag) !== 0; - } - function setDefaultShallowSuspenseListContext(parentContext) { - return parentContext & SubtreeSuspenseContextMask; - } - function setShallowSuspenseListContext(parentContext, shallowContext) { - return (parentContext & SubtreeSuspenseContextMask) | shallowContext; - } - function pushSuspenseListContext(fiber, newContext) { - push(suspenseStackCursor, newContext, fiber); - } - function popSuspenseListContext(fiber) { - pop(suspenseStackCursor, fiber); - } + var resultingFirstChild = null; + var previousNewFiber = null; + var oldFiber = currentFirstChild; + var lastPlacedIndex = 0; + var newIdx = 0; + var nextOldFiber = null; + var step = newChildren.next(); - // A non-null SuspenseState means that it is blocked for one reason or another. - // - A non-null dehydrated field means it's blocked pending hydration. - // - A non-null dehydrated field can use isSuspenseInstancePending or - // isSuspenseInstanceFallback to query the reason for being dehydrated. - // - A null dehydrated field means it's blocked by something suspending and - // we're currently showing a fallback instead. + for ( + ; + oldFiber !== null && !step.done; + newIdx++, step = newChildren.next() + ) { + if (oldFiber.index > newIdx) { + nextOldFiber = oldFiber; + oldFiber = null; + } else { + nextOldFiber = oldFiber.sibling; + } - function findFirstSuspended(row) { - var node = row; + var newFiber = updateSlot(returnFiber, oldFiber, step.value, lanes); - while (node !== null) { - if (node.tag === SuspenseComponent) { - var state = node.memoizedState; + if (newFiber === null) { + // TODO: This breaks on empty slots like null children. That's + // unfortunate because it triggers the slow path all the time. We need + // a better way to communicate whether this was a miss or null, + // boolean, undefined, etc. + if (oldFiber === null) { + oldFiber = nextOldFiber; + } - if (state !== null) { - var dehydrated = state.dehydrated; + break; + } - if ( - dehydrated === null || - isSuspenseInstancePending() || - isSuspenseInstanceFallback() - ) { - return node; + if (shouldTrackSideEffects) { + if (oldFiber && newFiber.alternate === null) { + // We matched the slot, but we didn't reuse the existing fiber, so we + // need to delete the existing child. + deleteChild(returnFiber, oldFiber); } } - } else if ( - node.tag === SuspenseListComponent && // revealOrder undefined can't be trusted because it don't - // keep track of whether it suspended or not. - node.memoizedProps.revealOrder !== undefined - ) { - var didSuspend = (node.flags & DidCapture) !== NoFlags$1; - if (didSuspend) { - return node; + lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx); + + if (previousNewFiber === null) { + // TODO: Move out of the loop. This only happens for the first run. + resultingFirstChild = newFiber; + } else { + // TODO: Defer siblings if we're not at the right index for this slot. + // I.e. if we had null values before, then we want to defer this + // for each null value. However, we also don't want to call updateSlot + // with the previous one. + previousNewFiber.sibling = newFiber; } - } else if (node.child !== null) { - node.child.return = node; - node = node.child; - continue; - } - if (node === row) { - return null; + previousNewFiber = newFiber; + oldFiber = nextOldFiber; } - while (node.sibling === null) { - if (node.return === null || node.return === row) { - return null; - } + if (step.done) { + // We've reached the end of the new children. We can delete the rest. + deleteRemainingChildren(returnFiber, oldFiber); - node = node.return; + return resultingFirstChild; } - node.sibling.return = node.return; - node = node.sibling; - } + if (oldFiber === null) { + // If we don't have any more existing children we can choose a fast path + // since the rest will all be insertions. + for (; !step.done; newIdx++, step = newChildren.next()) { + var _newFiber3 = createChild(returnFiber, step.value, lanes); - return null; - } + if (_newFiber3 === null) { + continue; + } - var NoFlags = - /* */ - 0; // Represents whether effect should fire. + lastPlacedIndex = placeChild(_newFiber3, lastPlacedIndex, newIdx); - var HasEffect = - /* */ - 1; // Represents the phase in which the effect (not the clean-up) fires. + if (previousNewFiber === null) { + // TODO: Move out of the loop. This only happens for the first run. + resultingFirstChild = _newFiber3; + } else { + previousNewFiber.sibling = _newFiber3; + } - var Insertion = - /* */ - 2; - var Layout = - /* */ - 4; - var Passive = - /* */ - 8; + previousNewFiber = _newFiber3; + } - 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. + return resultingFirstChild; + } // Add all children to a key map for quick lookups. - var firstScheduledRoot = null; - var lastScheduledRoot = null; // Used to prevent redundant mircotasks from being scheduled. + var existingChildren = mapRemainingChildren(returnFiber, oldFiber); // Keep scanning and use the map to restore deleted items as moves. - 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. + for (; !step.done; newIdx++, step = newChildren.next()) { + var _newFiber4 = updateFromMap( + existingChildren, + returnFiber, + newIdx, + step.value, + lanes + ); - var didScheduleMicrotask_act = false; // Used to quickly bail out of flushSync if there's no sync work to do. + if (_newFiber4 !== null) { + if (shouldTrackSideEffects) { + if (_newFiber4.alternate !== null) { + // The new fiber is a work in progress, but if there exists a + // current, that means that we reused the fiber. We need to delete + // it from the child list so that we don't add it to the deletion + // list. + existingChildren.delete( + _newFiber4.key === null ? newIdx : _newFiber4.key + ); + } + } - 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. + lastPlacedIndex = placeChild(_newFiber4, lastPlacedIndex, newIdx); - 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 (previousNewFiber === null) { + resultingFirstChild = _newFiber4; + } else { + previousNewFiber.sibling = _newFiber4; + } - if (ReactCurrentActQueue$2.current !== null) { - // We're inside an `act` scope. - if (!didScheduleMicrotask_act) { - didScheduleMicrotask_act = true; - scheduleImmediateTask(processRootScheduleInMicrotask); + previousNewFiber = _newFiber4; + } } - } else { - if (!didScheduleMicrotask) { - didScheduleMicrotask = true; - scheduleImmediateTask(processRootScheduleInMicrotask); + + if (shouldTrackSideEffects) { + // Any existing children that weren't consumed above were deleted. We need + // to add them to the deletion list. + existingChildren.forEach(function (child) { + return deleteChild(returnFiber, child); + }); } - } - if (!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()); + return resultingFirstChild; } - 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 reconcileSingleTextNode( + returnFiber, + currentFirstChild, + textContent, + lanes + ) { + // There's no need to check for keys on text nodes since we don't have a + // way to define them. + if (currentFirstChild !== null && currentFirstChild.tag === HostText) { + // We already have an existing node so let's just update it and delete + // the rest. + deleteRemainingChildren(returnFiber, currentFirstChild.sibling); + var existing = useFiber(currentFirstChild, textContent); + existing.return = returnFiber; + return existing; + } // The existing first child is not a text node so we need to create one + // and delete the existing ones. - function flushSyncWorkAcrossRoots_impl(onlyLegacy) { - if (isFlushingWork) { - // Prevent reentrancy. - // TODO: Is this overly defensive? The callers must check the execution - // context first regardless. - return; + deleteRemainingChildren(returnFiber, currentFirstChild); + var created = createFiberFromText(textContent, returnFiber.mode, lanes); + created.return = returnFiber; + return created; } - if (!mightHavePendingSyncWork) { - // Fast path. There's no sync work to do. - return; - } // There may or may not be synchronous work scheduled. Let's check. - - var didPerformSomeWork; - var errors = null; - isFlushingWork = true; + function reconcileSingleElement( + returnFiber, + currentFirstChild, + element, + lanes + ) { + var key = element.key; + var child = currentFirstChild; - do { - didPerformSomeWork = false; - var root = firstScheduledRoot; + while (child !== null) { + // TODO: If key === null and child.key === null, then this only applies to + // the first item in the list. + if (child.key === key) { + var elementType = element.type; - while (root !== null) { - if (onlyLegacy && root.tag !== LegacyRoot); - else { - var workInProgressRoot = getWorkInProgressRoot(); - var workInProgressRootRenderLanes = - getWorkInProgressRootRenderLanes(); - var nextLanes = getNextLanes( - root, - root === workInProgressRoot - ? workInProgressRootRenderLanes - : NoLanes - ); + if (elementType === REACT_FRAGMENT_TYPE) { + if (child.tag === Fragment) { + deleteRemainingChildren(returnFiber, child.sibling); + var existing = useFiber(child, element.props.children); + existing.return = returnFiber; - if (includesSyncLane(nextLanes)) { - // This root has pending sync work. Flush it now. - try { - didPerformSomeWork = true; - performSyncWorkOnRoot(root, nextLanes); - } catch (error) { - // Collect errors so we can rethrow them at the end - if (errors === null) { - errors = [error]; - } else { - errors.push(error); + { + existing._debugSource = element._source; + existing._debugOwner = element._owner; } + + return existing; } - } - } + } else { + if ( + child.elementType === elementType || // Keep this check inline so it only runs on the false path: + isCompatibleFamilyForHotReloading(child, element) || // Lazy types should reconcile their resolved type. + // We need to do this after the Hot Reloading check above, + // because hot reloading has different semantics than prod because + // it doesn't resuspend. So we can't let the call below suspend. + (typeof elementType === "object" && + elementType !== null && + elementType.$$typeof === REACT_LAZY_TYPE && + resolveLazy(elementType) === child.type) + ) { + deleteRemainingChildren(returnFiber, child.sibling); - root = root.next; - } - } while (didPerformSomeWork); + var _existing = useFiber(child, element.props); - 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. + _existing.ref = coerceRef(returnFiber, child, element); + _existing.return = returnFiber; - 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])); - } + { + _existing._debugSource = element._source; + _existing._debugOwner = element._owner; + } - var firstError = errors[0]; - throw firstError; + return _existing; + } + } // Didn't match. + + deleteRemainingChildren(returnFiber, child); + break; + } else { + deleteChild(returnFiber, child); } + + child = child.sibling; + } + + if (element.type === REACT_FRAGMENT_TYPE) { + var created = createFiberFromFragment( + element.props.children, + returnFiber.mode, + lanes, + element.key + ); + created.return = returnFiber; + return created; } else { - var error = errors[0]; - throw error; + var _created4 = createFiberFromElement( + element, + returnFiber.mode, + lanes + ); + + _created4.ref = coerceRef(returnFiber, currentFirstChild, element); + _created4.return = returnFiber; + return _created4; } } - } - function throwError(error) { - throw error; - } + function reconcileSinglePortal( + returnFiber, + currentFirstChild, + portal, + lanes + ) { + var key = portal.key; + var child = currentFirstChild; - function processRootScheduleInMicrotask() { - // This function is always called inside a microtask. It should never be - // called synchronously. - didScheduleMicrotask = false; + while (child !== null) { + // TODO: If key === null and child.key === null, then this only applies to + // the first item in the list. + if (child.key === key) { + if ( + child.tag === HostPortal && + child.stateNode.containerInfo === portal.containerInfo && + child.stateNode.implementation === portal.implementation + ) { + deleteRemainingChildren(returnFiber, child.sibling); + var existing = useFiber(child, portal.children || []); + existing.return = returnFiber; + return existing; + } else { + deleteRemainingChildren(returnFiber, child); + break; + } + } else { + deleteChild(returnFiber, child); + } - { - didScheduleMicrotask_act = false; - } // We'll recompute this as we iterate through all the roots and schedule them. + child = child.sibling; + } - mightHavePendingSyncWork = false; - var currentTime = now$1(); - var prev = null; - var root = firstScheduledRoot; + var created = createFiberFromPortal(portal, returnFiber.mode, lanes); + created.return = returnFiber; + return created; + } // This API will tag the children with the side-effect of the reconciliation + // itself. They will be added to the side-effect list as we pass through the + // children and the parent. - while (root !== null) { - var next = root.next; + function reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + newChild, + lanes + ) { + // This function is not recursive. + // If the top level item is an array, we treat it as a set of children, + // not as a fragment. Nested arrays on the other hand will be treated as + // fragment nodes. Recursion happens at the normal flow. + // Handle top level unkeyed fragments as if they were arrays. + // This leads to an ambiguity between <>{[...]} and <>.... + // We treat the ambiguous cases above the same. + // TODO: Let's use recursion like we do for Usable nodes? + var isUnkeyedTopLevelFragment = + typeof newChild === "object" && + newChild !== null && + newChild.type === REACT_FRAGMENT_TYPE && + newChild.key === null; - if ( - currentEventTransitionLane !== NoLane && - shouldAttemptEagerTransition() - ) { - // A transition was scheduled during an event, but we're going to try to - // render it synchronously anyway. We do this during a popstate event to - // preserve the scroll position of the previous page. - upgradePendingLaneToSync(root, currentEventTransitionLane); - } + if (isUnkeyedTopLevelFragment) { + newChild = newChild.props.children; + } // Handle object types - var nextLanes = scheduleTaskForRootDuringMicrotask(root, currentTime); + if (typeof newChild === "object" && newChild !== null) { + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE: + return placeSingleChild( + reconcileSingleElement( + returnFiber, + currentFirstChild, + newChild, + lanes + ) + ); - 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; + case REACT_PORTAL_TYPE: + return placeSingleChild( + reconcileSinglePortal( + returnFiber, + currentFirstChild, + newChild, + lanes + ) + ); - if (prev === null) { - // This is the new head of the list - firstScheduledRoot = next; - } else { - prev.next = next; - } + case REACT_LAZY_TYPE: + var payload = newChild._payload; + var init = newChild._init; // TODO: This function is supposed to be non-recursive. - if (next === null) { - // This is the new tail of the list - lastScheduledRoot = prev; + return reconcileChildFibers( + returnFiber, + currentFirstChild, + init(payload), + lanes + ); } - } else { - // This root still has work. Keep it in the list. - prev = root; - if (includesSyncLane(nextLanes)) { - mightHavePendingSyncWork = true; + if (isArray(newChild)) { + return reconcileChildrenArray( + returnFiber, + currentFirstChild, + newChild, + lanes + ); } - } - 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 (getIteratorFn(newChild)) { + return reconcileChildrenIterator( + returnFiber, + currentFirstChild, + newChild, + lanes + ); + } // Usables are a valid React node type. When React encounters a Usable in + // a child position, it unwraps it using the same algorithm as `use`. For + // example, for promises, React will throw an exception to unwind the + // stack, then replay the component once the promise resolves. + // + // A difference from `use` is that React will keep unwrapping the value + // until it reaches a non-Usable type. + // + // e.g. Usable>> should resolve to T + // + // The structure is a bit unfortunate. Ideally, we shouldn't need to + // replay the entire begin phase of the parent fiber in order to reconcile + // the children again. This would require a somewhat significant refactor, + // because reconcilation happens deep within the begin phase, and + // depending on the type of work, not always at the end. We should + // consider as an future improvement. - if ( - // 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); - } + if (typeof newChild.then === "function") { + var thenable = newChild; + return reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + unwrapThenable(thenable), + lanes + ); + } - root.callbackNode = null; - root.callbackPriority = NoLane; - return NoLane; - } // Schedule a new callback in the host environment. + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) { + var context = newChild; + return reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + readContextDuringReconcilation(returnFiber, context, lanes), + lanes + ); + } - 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); + throwOnInvalidObjectType(returnFiber, newChild); } - 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 - ) + (typeof newChild === "string" && newChild !== "") || + typeof newChild === "number" ) { - // 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); + return placeSingleChild( + reconcileSingleTextNode( + returnFiber, + currentFirstChild, + "" + newChild, + lanes + ) + ); } - var schedulerPriorityLevel; + { + if (typeof newChild === "function") { + warnOnFunctionType(returnFiber); + } + } // Remaining cases are all treated as empty. - switch (lanesToEventPriority(nextLanes)) { - case DiscreteEventPriority: - schedulerPriorityLevel = ImmediatePriority; - break; + return deleteRemainingChildren(returnFiber, currentFirstChild); + } - case ContinuousEventPriority: - schedulerPriorityLevel = UserBlockingPriority; - break; + function reconcileChildFibers( + returnFiber, + currentFirstChild, + newChild, + lanes + ) { + // This indirection only exists so we can reset `thenableState` at the end. + // It should get inlined by Closure. + thenableIndexCounter$1 = 0; + var firstChildFiber = reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + newChild, + lanes + ); + thenableState$1 = null; // Don't bother to reset `thenableIndexCounter` to 0 because it always gets + // set at the beginning. - case DefaultEventPriority: - schedulerPriorityLevel = NormalPriority; - break; + return firstChildFiber; + } - case IdleEventPriority: - schedulerPriorityLevel = IdlePriority; - break; + return reconcileChildFibers; + } - default: - schedulerPriorityLevel = NormalPriority; - break; - } + var reconcileChildFibers = createChildReconciler(true); + var mountChildFibers = createChildReconciler(false); + function resetChildReconcilerOnUnwind() { + // On unwind, clear any pending thenables that were used. + thenableState$1 = null; + thenableIndexCounter$1 = 0; + } + function cloneChildFibers(current, workInProgress) { + if (current !== null && workInProgress.child !== current.child) { + throw new Error("Resuming work not yet implemented."); + } - var newCallbackNode = scheduleCallback$1( - schedulerPriorityLevel, - performConcurrentWorkOnRoot.bind(null, root) + if (workInProgress.child === null) { + return; + } + + var currentChild = workInProgress.child; + var newChild = createWorkInProgress( + currentChild, + currentChild.pendingProps + ); + workInProgress.child = newChild; + newChild.return = workInProgress; + + while (currentChild.sibling !== null) { + currentChild = currentChild.sibling; + newChild = newChild.sibling = createWorkInProgress( + currentChild, + currentChild.pendingProps ); - root.callbackPriority = newCallbackPriority; - root.callbackNode = newCallbackNode; - return newCallbackPriority; + newChild.return = workInProgress; } - } - 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()); + newChild.sibling = null; + } // Reset a workInProgress child set to prepare it for a second pass. - 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); + function resetChildFibers(workInProgress, lanes) { + var child = workInProgress.child; + + while (child !== null) { + resetWorkInProgress(child, lanes); + child = child.sibling; } + } - return null; + // TODO: This isn't being used yet, but it's intended to replace the + // InvisibleParentContext that is currently managed by SuspenseContext. + + var currentTreeHiddenStackCursor = createCursor(null); + var prevEntangledRenderLanesCursor = createCursor(NoLanes); + function pushHiddenContext(fiber, context) { + var prevEntangledRenderLanes = getEntangledRenderLanes(); + push(prevEntangledRenderLanesCursor, prevEntangledRenderLanes, fiber); + push(currentTreeHiddenStackCursor, context, fiber); // When rendering a subtree that's currently hidden, we must include all + // lanes that would have rendered if the hidden subtree hadn't been deferred. + // That is, in order to reveal content from hidden -> visible, we must commit + // all the updates that we skipped when we originally hid the tree. + + setEntangledRenderLanes( + mergeLanes(prevEntangledRenderLanes, context.baseLanes) + ); + } + function reuseHiddenContextOnStack(fiber) { + // This subtree is not currently hidden, so we don't need to add any lanes + // to the render lanes. But we still need to push something to avoid a + // context mismatch. Reuse the existing context on the stack. + push(prevEntangledRenderLanesCursor, getEntangledRenderLanes(), fiber); + push( + currentTreeHiddenStackCursor, + currentTreeHiddenStackCursor.current, + fiber + ); + } + function popHiddenContext(fiber) { + // Restore the previous render lanes from the stack + setEntangledRenderLanes(prevEntangledRenderLanesCursor.current); + pop(currentTreeHiddenStackCursor, fiber); + pop(prevEntangledRenderLanesCursor, fiber); + } + function isCurrentTreeHidden() { + return currentTreeHiddenStackCursor.current !== null; } - var fakeActCallbackNode$1 = {}; - function scheduleCallback$1(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$2(priorityLevel, callback); - } + // suspends, i.e. it's the nearest `catch` block on the stack. + + var suspenseHandlerStackCursor = createCursor(null); // Represents the outermost boundary that is not visible in the current tree. + // Everything above this is the "shell". When this is null, it means we're + // rendering in the shell of the app. If it's non-null, it means we're rendering + // deeper than the shell, inside a new tree that wasn't already visible. + // + // The main way we use this concept is to determine whether showing a fallback + // would result in a desirable or undesirable loading state. Activing a fallback + // in the shell is considered an undersirable loading state, because it would + // mean hiding visible (albeit stale) content in the current tree — we prefer to + // show the stale content, rather than switch to a fallback. But showing a + // fallback in a new tree is fine, because there's no stale content to + // prefer instead. + + var shellBoundary = null; + function getShellBoundary() { + return shellBoundary; } + function pushPrimaryTreeSuspenseHandler(handler) { + // TODO: Pass as argument + var current = handler.alternate; + // propagated a single level. For example, when ForceSuspenseFallback is set, + // it should only force the nearest Suspense boundary into fallback mode. - function cancelCallback(callbackNode) { - if (callbackNode === fakeActCallbackNode$1); - else if (callbackNode !== null) { - cancelCallback$1(callbackNode); + pushSuspenseListContext( + handler, + setDefaultShallowSuspenseListContext(suspenseStackCursor.current) + ); // Experimental feature: Some Suspense boundaries are marked as having an + // to push a nested Suspense handler, because it will get replaced by the + // outer fallback, anyway. Consider this as a future optimization. + + push(suspenseHandlerStackCursor, handler, handler); + + if (shellBoundary === null) { + if (current === null || isCurrentTreeHidden()) { + // This boundary is not visible in the current UI. + shellBoundary = handler; + } else { + var prevState = current.memoizedState; + + if (prevState !== null) { + // This boundary is showing a fallback in the current UI. + shellBoundary = handler; + } + } } } + function pushFallbackTreeSuspenseHandler(fiber) { + // We're about to render the fallback. If something in the fallback suspends, + // it's akin to throwing inside of a `catch` block. This boundary should not + // capture. Reuse the existing handler on the stack. + reuseSuspenseHandlerOnStack(fiber); + } + function pushOffscreenSuspenseHandler(fiber) { + if (fiber.tag === OffscreenComponent) { + // A SuspenseList context is only pushed here to avoid a push/pop mismatch. + // Reuse the current value on the stack. + // TODO: We can avoid needing to push here by by forking popSuspenseHandler + // into separate functions for Suspense and Offscreen. + pushSuspenseListContext(fiber, suspenseStackCursor.current); + push(suspenseHandlerStackCursor, fiber, fiber); - 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 (supportsMicrotasks) { - 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 (shellBoundary !== null); + else { + var current = fiber.alternate; - 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$2(ImmediatePriority, cb); - return; - } + if (current !== null) { + var prevState = current.memoizedState; - cb(); - }); + if (prevState !== null) { + // This is the first boundary in the stack that's already showing + // a fallback. So everything outside is considered the shell. + shellBoundary = fiber; + } + } + } } else { - // If microtasks are not supported, use Scheduler. - scheduleCallback$2(ImmediatePriority, cb); + // This is a LegacyHidden component. + reuseSuspenseHandlerOnStack(fiber); } } + function reuseSuspenseHandlerOnStack(fiber) { + pushSuspenseListContext(fiber, suspenseStackCursor.current); + push(suspenseHandlerStackCursor, getSuspenseHandler(), fiber); + } + function getSuspenseHandler() { + return suspenseHandlerStackCursor.current; + } + function popSuspenseHandler(fiber) { + pop(suspenseHandlerStackCursor, fiber); - 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(); + if (shellBoundary === fiber) { + // Popping back into the shell. + shellBoundary = null; } - return currentEventTransitionLane; - } + popSuspenseListContext(fiber); + } // SuspenseList context + // TODO: Move to a separate module? We may change the SuspenseList + // implementation to hide/show in the commit phase, anyway. - // transition updates that occur while the async action is still in progress - // are treated as part of the action. - // - // The ideal behavior would be to treat each async function as an independent - // action. However, without a mechanism like AsyncContext, we can't tell which - // action an update corresponds to. So instead, we entangle them all into one. - // The listeners to notify once the entangled scope completes. + var DefaultSuspenseContext = 0; + var SubtreeSuspenseContextMask = 1; // ForceSuspenseFallback can be used by SuspenseList to force newly added + // items into their fallback state during one of the render passes. - var currentEntangledListeners = null; // The number of pending async actions in the entangled scope. + var ForceSuspenseFallback = 2; + var suspenseStackCursor = createCursor(DefaultSuspenseContext); + function hasSuspenseListContext(parentContext, flag) { + return (parentContext & flag) !== 0; + } + function setDefaultShallowSuspenseListContext(parentContext) { + return parentContext & SubtreeSuspenseContextMask; + } + function setShallowSuspenseListContext(parentContext, shallowContext) { + return (parentContext & SubtreeSuspenseContextMask) | shallowContext; + } + function pushSuspenseListContext(fiber, newContext) { + push(suspenseStackCursor, newContext, fiber); + } + function popSuspenseListContext(fiber) { + pop(suspenseStackCursor, fiber); + } - var currentEntangledPendingCount = 0; // The transition lane shared by all updates in the entangled scope. + // A non-null SuspenseState means that it is blocked for one reason or another. + // - A non-null dehydrated field means it's blocked pending hydration. + // - A non-null dehydrated field can use isSuspenseInstancePending or + // isSuspenseInstanceFallback to query the reason for being dehydrated. + // - A null dehydrated field means it's blocked by something suspending and + // we're currently showing a fallback instead. - var currentEntangledLane = NoLane; - function requestAsyncActionContext( - actionReturnValue, // If this is provided, this resulting thenable resolves to this value instead - // of the return value of the action. This is a perf trick to avoid composing - // an extra async function. - overrideReturnValue - ) { - // 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. - var thenable = actionReturnValue; - var entangledListeners; + function findFirstSuspended(row) { + var node = row; - if (currentEntangledListeners === null) { - // There's no outer async action scope. Create a new one. - entangledListeners = currentEntangledListeners = []; - currentEntangledPendingCount = 0; - currentEntangledLane = requestTransitionLane(); - } else { - entangledListeners = currentEntangledListeners; - } + while (node !== null) { + if (node.tag === SuspenseComponent) { + var state = node.memoizedState; - currentEntangledPendingCount++; // Create a thenable that represents the result of this action, but doesn't - // resolve until the entire entangled scope has finished. - // - // Expressed using promises: - // const [thisResult] = await Promise.all([thisAction, entangledAction]); - // return thisResult; - - var resultThenable = createResultThenable(entangledListeners); - var resultStatus = "pending"; - var resultValue; - var rejectedReason; - thenable.then( - function (value) { - resultStatus = "fulfilled"; - resultValue = - overrideReturnValue !== null ? overrideReturnValue : value; - pingEngtangledActionScope(); - }, - function (error) { - resultStatus = "rejected"; - rejectedReason = error; - pingEngtangledActionScope(); - } - ); // Attach a listener to fill in the result. - - entangledListeners.push(function () { - switch (resultStatus) { - case "fulfilled": { - var fulfilledThenable = resultThenable; - fulfilledThenable.status = "fulfilled"; - fulfilledThenable.value = resultValue; - break; - } + if (state !== null) { + var dehydrated = state.dehydrated; - case "rejected": { - var rejectedThenable = resultThenable; - rejectedThenable.status = "rejected"; - rejectedThenable.reason = rejectedReason; - break; + if ( + dehydrated === null || + isSuspenseInstancePending() || + isSuspenseInstanceFallback() + ) { + return node; + } } + } else if ( + node.tag === SuspenseListComponent && // revealOrder undefined can't be trusted because it don't + // keep track of whether it suspended or not. + node.memoizedProps.revealOrder !== undefined + ) { + var didSuspend = (node.flags & DidCapture) !== NoFlags$1; - case "pending": - default: { - // The listener above should have been called first, so `resultStatus` - // should already be set to the correct value. - throw new Error( - "Thenable should have already resolved. This " + - "is a bug in React." - ); + if (didSuspend) { + return node; } + } else if (node.child !== null) { + node.child.return = node; + node = node.child; + continue; } - }); - return resultThenable; - } - function requestSyncActionContext( - actionReturnValue, // If this is provided, this resulting thenable resolves to this value instead - // of the return value of the action. This is a perf trick to avoid composing - // an extra async function. - overrideReturnValue - ) { - var resultValue = - overrideReturnValue !== null ? overrideReturnValue : actionReturnValue; // This is not an async action, but it may be part of an outer async action. - if (currentEntangledListeners === null) { - return resultValue; - } else { - // Return a thenable that does not resolve until the entangled actions - // have finished. - var entangledListeners = currentEntangledListeners; - var resultThenable = createResultThenable(entangledListeners); - entangledListeners.push(function () { - var fulfilledThenable = resultThenable; - fulfilledThenable.status = "fulfilled"; - fulfilledThenable.value = resultValue; - }); - return resultThenable; - } - } + if (node === row) { + return null; + } - function pingEngtangledActionScope() { - if ( - currentEntangledListeners !== null && - --currentEntangledPendingCount === 0 - ) { - // All the actions have finished. Close the entangled async action scope - // and notify all the listeners. - var listeners = currentEntangledListeners; - currentEntangledListeners = null; - currentEntangledLane = NoLane; + while (node.sibling === null) { + if (node.return === null || node.return === row) { + return null; + } - for (var i = 0; i < listeners.length; i++) { - var listener = listeners[i]; - listener(); + node = node.return; } + + node.sibling.return = node.return; + node = node.sibling; } - } - function createResultThenable(entangledListeners) { - // Waits for the entangled async action to complete, then resolves to the - // result of an individual action. - var resultThenable = { - status: "pending", - value: null, - reason: null, - then: function (resolve) { - // This is a bit of a cheat. `resolve` expects a value of type `S` to be - // passed, but because we're instrumenting the `status` field ourselves, - // and we know this thenable will only be used by React, we also know - // the value isn't actually needed. So we add the resolve function - // directly to the entangled listeners. - // - // This is also why we don't need to check if the thenable is still - // pending; the Suspense implementation already performs that check. - var ping = resolve; - entangledListeners.push(ping); - } - }; - return resultThenable; + return null; } - function peekEntangledActionLane() { - return currentEntangledLane; - } + var NoFlags = + /* */ + 0; // Represents whether effect should fire. + + var HasEffect = + /* */ + 1; // Represents the phase in which the effect (not the clean-up) fires. + + var Insertion = + /* */ + 2; + var Layout = + /* */ + 4; + var Passive = + /* */ + 8; var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, ReactCurrentBatchConfig$2 = ReactSharedInternals.ReactCurrentBatchConfig; @@ -11515,6 +11507,7 @@ to return true:wantsResponderID| | var newBaseQueueFirst = null; var newBaseQueueLast = null; var update = first; + var didReadFromEntangledAsyncAction = false; do { // An extra OffscreenLane bit is added to updates that were made to @@ -11557,6 +11550,17 @@ to return true:wantsResponderID| | ); markSkippedUpdateLanes(updateLane); } else { + // This update does have sufficient priority. + // Check if this update is part of a pending async action. If so, + // we'll need to suspend until the action has finished, so that it's + // batched together with future updates in the same action. + if ( + updateLane !== NoLane && + updateLane === peekEntangledActionLane() + ) { + didReadFromEntangledAsyncAction = true; + } // Check if this is an optimistic update. + { // This is not an optimistic update, and we're going to apply it now. // But, if there were earlier updates that were skipped, we need to @@ -11603,7 +11607,23 @@ to return true:wantsResponderID| | // different from the current state. if (!objectIs(newState, hook.memoizedState)) { - markWorkInProgressReceivedUpdate(); + markWorkInProgressReceivedUpdate(); // Check if this update is part of a pending async action. If so, we'll + // need to suspend until the action has finished, so that it's batched + // together with future updates in the same action. + // TODO: Once we support hooks inside useMemo (or an equivalent + // memoization boundary like Forget), hoist this logic so that it only + // suspends if the memo boundary produces a new value. + + if (didReadFromEntangledAsyncAction) { + var entangledActionThenable = peekEntangledActionThenable(); + + if (entangledActionThenable !== null) { + // TODO: Instead of the throwing the thenable directly, throw a + // special object like `use` does so we can detect if it's captured + // by userspace. + throw entangledActionThenable; + } + } } hook.memoizedState = newState; @@ -12422,7 +12442,7 @@ to return true:wantsResponderID| | } try { - var returnValue, thenable, entangledResult, _entangledResult2; + var returnValue, thenable, thenableForFinishedState; if (enableAsyncActions); else { // Async actions are not enabled. @@ -14634,6 +14654,7 @@ to return true:wantsResponderID| | // process them now. processUpdateQueue(workInProgress, newProps, instance, renderLanes); + suspendIfUpdateReadFromEntangledAsyncAction(); instance.state = workInProgress.memoizedState; } @@ -14701,6 +14722,7 @@ to return true:wantsResponderID| | var oldState = workInProgress.memoizedState; var newState = (instance.state = oldState); processUpdateQueue(workInProgress, newProps, instance, renderLanes); + suspendIfUpdateReadFromEntangledAsyncAction(); newState = workInProgress.memoizedState; if ( @@ -14853,6 +14875,7 @@ to return true:wantsResponderID| | var oldState = workInProgress.memoizedState; var newState = (instance.state = oldState); processUpdateQueue(workInProgress, newProps, instance, renderLanes); + suspendIfUpdateReadFromEntangledAsyncAction(); newState = workInProgress.memoizedState; if ( @@ -15426,7 +15449,7 @@ to return true:wantsResponderID| | } } - return; + return false; } case OffscreenComponent: { @@ -15461,7 +15484,7 @@ to return true:wantsResponderID| | attachPingListener(root, wakeable, rootRenderLanes); } - return; + return false; } } } @@ -15484,7 +15507,7 @@ to return true:wantsResponderID| | // and potentially log a warning. Revisit this for a future release. attachPingListener(root, wakeable, rootRenderLanes); renderDidSuspendDelayIfPossible(); - return; + return false; } else { // In a legacy root, suspending without a boundary is always an error. var uncaughtSuspenseError = new Error( @@ -15504,6 +15527,12 @@ to return true:wantsResponderID| | // over and traverse parent path again, this time treating the exception // as an error. + if (returnFiber === null) { + // There's no return fiber, which means the root errored. This should never + // happen. Return `true` to trigger a fatal error (panic). + return true; + } + var workInProgress = returnFiber; do { @@ -15519,7 +15548,7 @@ to return true:wantsResponderID| | lane ); enqueueCapturedUpdate(workInProgress, update); - return; + return false; } case ClassComponent: @@ -15548,7 +15577,7 @@ to return true:wantsResponderID| | ); enqueueCapturedUpdate(workInProgress, _update); - return; + return false; } break; @@ -15556,6 +15585,8 @@ to return true:wantsResponderID| | workInProgress = workInProgress.return; } while (workInProgress !== null); + + return false; } var ReactCurrentOwner$2 = ReactSharedInternals.ReactCurrentOwner; // A special exception that's used to unwind the stack when an update flows @@ -16530,6 +16561,10 @@ to return true:wantsResponderID| | cloneUpdateQueue(current, workInProgress); processUpdateQueue(workInProgress, nextProps, null, renderLanes); var nextState = workInProgress.memoizedState; + // it needs to happen after the `pushCacheProvider` call above to avoid a + // context stack mismatch. A bit unfortunate. + + suspendIfUpdateReadFromEntangledAsyncAction(); // Caution: React DevTools currently depends on this property // being called "element". var nextChildren = nextState.element; @@ -24801,7 +24836,7 @@ to return true:wantsResponderID| | // Unwind then continue with the normal work loop. workInProgressSuspendedReason = NotSuspended; workInProgressThrownValue = null; - throwAndUnwindWorkLoop(unitOfWork, thrownValue); + throwAndUnwindWorkLoop(root, unitOfWork, thrownValue); break; } } @@ -24906,7 +24941,7 @@ to return true:wantsResponderID| | // Unwind then continue with the normal work loop. workInProgressSuspendedReason = NotSuspended; workInProgressThrownValue = null; - throwAndUnwindWorkLoop(unitOfWork, thrownValue); + throwAndUnwindWorkLoop(root, unitOfWork, thrownValue); break; } @@ -24971,7 +25006,7 @@ to return true:wantsResponderID| | // Otherwise, unwind then continue with the normal work loop. workInProgressSuspendedReason = NotSuspended; workInProgressThrownValue = null; - throwAndUnwindWorkLoop(unitOfWork, thrownValue); + throwAndUnwindWorkLoop(root, unitOfWork, thrownValue); } break; @@ -25036,7 +25071,7 @@ to return true:wantsResponderID| | workInProgressSuspendedReason = NotSuspended; workInProgressThrownValue = null; - throwAndUnwindWorkLoop(unitOfWork, thrownValue); + throwAndUnwindWorkLoop(root, unitOfWork, thrownValue); break; } @@ -25047,7 +25082,7 @@ to return true:wantsResponderID| | // always unwind. workInProgressSuspendedReason = NotSuspended; workInProgressThrownValue = null; - throwAndUnwindWorkLoop(unitOfWork, thrownValue); + throwAndUnwindWorkLoop(root, unitOfWork, thrownValue); break; } @@ -25275,7 +25310,7 @@ to return true:wantsResponderID| | ReactCurrentOwner$1.current = null; } - function throwAndUnwindWorkLoop(unitOfWork, thrownValue) { + function throwAndUnwindWorkLoop(root, unitOfWork, thrownValue) { // This is a fork of performUnitOfWork specifcally for unwinding a fiber // that threw an exception. // @@ -25284,40 +25319,33 @@ to return true:wantsResponderID| | resetSuspendedWorkLoopOnUnwind(unitOfWork); var returnFiber = unitOfWork.return; - if (returnFiber === null || workInProgressRoot === null) { - // Expected to be working on a non-root fiber. This is a fatal error - // because there's no ancestor that can handle it; the root is - // supposed to capture all errors that weren't caught by an error - // boundary. - workInProgressRootExitStatus = RootFatalErrored; - workInProgressRootFatalError = thrownValue; // Set `workInProgress` to null. This represents advancing to the next - // sibling, or the parent if there are no siblings. But since the root - // has no siblings nor a parent, we set it to null. Usually this is - // handled by `completeUnitOfWork` or `unwindWork`, but since we're - // intentionally not calling those, we need set it here. - // TODO: Consider calling `unwindWork` to pop the contexts. - - workInProgress = null; - return; - } - try { // Find and mark the nearest Suspense or error boundary that can handle // this "exception". - throwException( - workInProgressRoot, + var didFatal = throwException( + root, returnFiber, unitOfWork, thrownValue, workInProgressRootRenderLanes ); + + if (didFatal) { + panicOnRootError(thrownValue); + return; + } } catch (error) { // We had trouble processing the error. An example of this happening is // when accessing the `componentDidCatch` property of an error boundary // throws an error. A weird edge case. There's a regression test for this. // To prevent an infinite loop, bubble the error up to the next parent. - workInProgress = returnFiber; - throw error; + if (returnFiber !== null) { + workInProgress = returnFiber; + throw error; + } else { + panicOnRootError(thrownValue); + return; + } } if (unitOfWork.flags & Incomplete) { @@ -25337,6 +25365,22 @@ to return true:wantsResponderID| | } } + function panicOnRootError(error) { + // There's no ancestor that can handle this exception. This should never + // happen because the root is supposed to capture all errors that weren't + // caught by an error boundary. This is a fatal error, or panic condition, + // because we've run out of ways to recover. + workInProgressRootExitStatus = RootFatalErrored; + workInProgressRootFatalError = error; // Set `workInProgress` to null. This represents advancing to the next + // sibling, or the parent if there are no siblings. But since the root + // has no siblings nor a parent, we set it to null. Usually this is + // handled by `completeUnitOfWork` or `unwindWork`, but since we're + // intentionally not calling those, we need set it here. + // TODO: Consider calling `unwindWork` to pop the contexts. + + workInProgress = null; + } + function completeUnitOfWork(unitOfWork) { // Attempt to complete the current unit of work, then move to the next // sibling. If there are no more siblings, return to the parent fiber. @@ -27838,7 +27882,7 @@ to return true:wantsResponderID| | return root; } - var ReactVersion = "18.3.0-canary-58de2f66"; + var ReactVersion = "18.3.0-canary-2ee1c8bb"; function createPortal$1( children, diff --git a/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactFabric-prod.fb.js b/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactFabric-prod.fb.js index f2ad0a4382ffc..b0d2c4209eace 100644 --- a/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactFabric-prod.fb.js +++ b/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactFabric-prod.fb.js @@ -7,7 +7,7 @@ * @noflow * @nolint * @preventMunge - * @generated SignedSource<<6e407622da5495d67c0b1b946f5635a4>> + * @generated SignedSource<<664105eacf4c13d26fd479b8d2c34d8a>> */ "use strict"; @@ -940,7 +940,7 @@ eventPluginOrder = Array.prototype.slice.call([ "ReactNativeBridgeEventPlugin" ]); recomputePluginOrdering(); -var injectedNamesToPlugins$jscomp$inline_235 = { +var injectedNamesToPlugins$jscomp$inline_236 = { ResponderEventPlugin: ResponderEventPlugin, ReactNativeBridgeEventPlugin: { eventTypes: {}, @@ -986,32 +986,32 @@ var injectedNamesToPlugins$jscomp$inline_235 = { } } }, - isOrderingDirty$jscomp$inline_236 = !1, - pluginName$jscomp$inline_237; -for (pluginName$jscomp$inline_237 in injectedNamesToPlugins$jscomp$inline_235) + isOrderingDirty$jscomp$inline_237 = !1, + pluginName$jscomp$inline_238; +for (pluginName$jscomp$inline_238 in injectedNamesToPlugins$jscomp$inline_236) if ( - injectedNamesToPlugins$jscomp$inline_235.hasOwnProperty( - pluginName$jscomp$inline_237 + injectedNamesToPlugins$jscomp$inline_236.hasOwnProperty( + pluginName$jscomp$inline_238 ) ) { - var pluginModule$jscomp$inline_238 = - injectedNamesToPlugins$jscomp$inline_235[pluginName$jscomp$inline_237]; + var pluginModule$jscomp$inline_239 = + injectedNamesToPlugins$jscomp$inline_236[pluginName$jscomp$inline_238]; if ( - !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_237) || - namesToPlugins[pluginName$jscomp$inline_237] !== - pluginModule$jscomp$inline_238 + !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_238) || + namesToPlugins[pluginName$jscomp$inline_238] !== + pluginModule$jscomp$inline_239 ) { - if (namesToPlugins[pluginName$jscomp$inline_237]) + if (namesToPlugins[pluginName$jscomp$inline_238]) throw Error( "EventPluginRegistry: Cannot inject two different event plugins using the same name, `" + - (pluginName$jscomp$inline_237 + "`.") + (pluginName$jscomp$inline_238 + "`.") ); - namesToPlugins[pluginName$jscomp$inline_237] = - pluginModule$jscomp$inline_238; - isOrderingDirty$jscomp$inline_236 = !0; + namesToPlugins[pluginName$jscomp$inline_238] = + pluginModule$jscomp$inline_239; + isOrderingDirty$jscomp$inline_237 = !0; } } -isOrderingDirty$jscomp$inline_236 && recomputePluginOrdering(); +isOrderingDirty$jscomp$inline_237 && recomputePluginOrdering(); var emptyObject$1 = {}, removedKeys = null, removedKeyCount = 0, @@ -2144,6 +2144,226 @@ function getRootForUpdatedFiber(sourceFiber) { (sourceFiber = parent), (parent = sourceFiber.return); return 3 === sourceFiber.tag ? sourceFiber.stateNode : null; } +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), + scheduleImmediateTask(processRootScheduleInMicrotask)); + enableDeferRootSchedulingToMicrotask || + scheduleTaskForRootDuringMicrotask(root, now()); +} +function flushSyncWorkAcrossRoots_impl(onlyLegacy) { + if (!isFlushingWork && mightHavePendingSyncWork) { + var errors = null; + isFlushingWork = !0; + do { + var didPerformSomeWork = !1; + for (var root = firstScheduledRoot; null !== root; ) { + if (!onlyLegacy || 0 === root.tag) { + var workInProgressRootRenderLanes$9 = workInProgressRootRenderLanes, + nextLanes = getNextLanes( + root, + root === workInProgressRoot ? workInProgressRootRenderLanes$9 : 0 + ); + if (0 !== (nextLanes & 3)) + try { + didPerformSomeWork = !0; + workInProgressRootRenderLanes$9 = root; + if (0 !== (executionContext & 6)) + throw Error("Should not already be working."); + if (!flushPassiveEffects()) { + var exitStatus = renderRootSync( + workInProgressRootRenderLanes$9, + nextLanes + ); + if ( + 0 !== workInProgressRootRenderLanes$9.tag && + 2 === exitStatus + ) { + var originallyAttemptedLanes = nextLanes, + errorRetryLanes = getLanesToRetrySynchronouslyOnError( + workInProgressRootRenderLanes$9, + originallyAttemptedLanes + ); + 0 !== errorRetryLanes && + ((nextLanes = errorRetryLanes), + (exitStatus = recoverFromConcurrentError( + workInProgressRootRenderLanes$9, + originallyAttemptedLanes, + errorRetryLanes + ))); + } + if (1 === exitStatus) + throw ( + ((originallyAttemptedLanes = workInProgressRootFatalError), + prepareFreshStack(workInProgressRootRenderLanes$9, 0), + markRootSuspended( + workInProgressRootRenderLanes$9, + nextLanes, + 0 + ), + ensureRootIsScheduled(workInProgressRootRenderLanes$9), + originallyAttemptedLanes) + ); + 6 === exitStatus + ? markRootSuspended( + workInProgressRootRenderLanes$9, + nextLanes, + workInProgressDeferredLane + ) + : ((workInProgressRootRenderLanes$9.finishedWork = + workInProgressRootRenderLanes$9.current.alternate), + (workInProgressRootRenderLanes$9.finishedLanes = nextLanes), + commitRoot( + workInProgressRootRenderLanes$9, + workInProgressRootRecoverableErrors, + workInProgressTransitions, + workInProgressDeferredLane + )); + } + ensureRootIsScheduled(workInProgressRootRenderLanes$9); + } 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++) + scheduleImmediateTask(throwError.bind(null, errors[onlyLegacy])); + } + 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 & -62914561; + 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; + break; + case 268435456: + suspendedLanes = IdlePriority; + break; + default: + suspendedLanes = NormalPriority; + } + pingedLanes = performConcurrentWorkOnRoot.bind(null, root); + suspendedLanes = scheduleCallback$2(suspendedLanes, pingedLanes); + root.callbackPriority = currentTime; + root.callbackNode = suspendedLanes; + return currentTime; +} +function scheduleImmediateTask(cb) { + useMicrotasksForSchedulingInFabric + ? scheduleMicrotask(function () { + 0 !== (executionContext & 6) + ? scheduleCallback$2(ImmediatePriority, cb) + : cb(); + }) + : scheduleCallback$2(ImmediatePriority, cb); +} +function requestTransitionLane() { + if (0 === currentEventTransitionLane) { + var lane = nextTransitionLane; + nextTransitionLane <<= 1; + 0 === (nextTransitionLane & 4194176) && (nextTransitionLane = 128); + currentEventTransitionLane = lane; + } + return currentEventTransitionLane; +} var hasForceUpdate = !1; function initializeUpdateQueue(fiber) { fiber.updateQueue = { @@ -3351,227 +3571,6 @@ function findFirstSuspended(row) { } return null; } -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), - scheduleImmediateTask(processRootScheduleInMicrotask)); - enableDeferRootSchedulingToMicrotask || - scheduleTaskForRootDuringMicrotask(root, now()); -} -function flushSyncWorkAcrossRoots_impl(onlyLegacy) { - if (!isFlushingWork && mightHavePendingSyncWork) { - var errors = null; - isFlushingWork = !0; - do { - var didPerformSomeWork = !1; - for (var root = firstScheduledRoot; null !== root; ) { - if (!onlyLegacy || 0 === root.tag) { - var workInProgressRootRenderLanes$26 = workInProgressRootRenderLanes, - nextLanes = getNextLanes( - root, - root === workInProgressRoot ? workInProgressRootRenderLanes$26 : 0 - ); - if (0 !== (nextLanes & 3)) - try { - didPerformSomeWork = !0; - workInProgressRootRenderLanes$26 = root; - if (0 !== (executionContext & 6)) - throw Error("Should not already be working."); - if (!flushPassiveEffects()) { - var exitStatus = renderRootSync( - workInProgressRootRenderLanes$26, - nextLanes - ); - if ( - 0 !== workInProgressRootRenderLanes$26.tag && - 2 === exitStatus - ) { - var originallyAttemptedLanes = nextLanes, - errorRetryLanes = getLanesToRetrySynchronouslyOnError( - workInProgressRootRenderLanes$26, - originallyAttemptedLanes - ); - 0 !== errorRetryLanes && - ((nextLanes = errorRetryLanes), - (exitStatus = recoverFromConcurrentError( - workInProgressRootRenderLanes$26, - originallyAttemptedLanes, - errorRetryLanes - ))); - } - if (1 === exitStatus) - throw ( - ((originallyAttemptedLanes = workInProgressRootFatalError), - prepareFreshStack(workInProgressRootRenderLanes$26, 0), - markRootSuspended( - workInProgressRootRenderLanes$26, - nextLanes, - 0 - ), - ensureRootIsScheduled(workInProgressRootRenderLanes$26), - originallyAttemptedLanes) - ); - 6 === exitStatus - ? markRootSuspended( - workInProgressRootRenderLanes$26, - nextLanes, - workInProgressDeferredLane - ) - : ((workInProgressRootRenderLanes$26.finishedWork = - workInProgressRootRenderLanes$26.current.alternate), - (workInProgressRootRenderLanes$26.finishedLanes = - nextLanes), - commitRoot( - workInProgressRootRenderLanes$26, - workInProgressRootRecoverableErrors, - workInProgressTransitions, - workInProgressDeferredLane - )); - } - ensureRootIsScheduled(workInProgressRootRenderLanes$26); - } 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++) - scheduleImmediateTask(throwError.bind(null, errors[onlyLegacy])); - } - 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 & -62914561; - 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; - break; - case 268435456: - suspendedLanes = IdlePriority; - break; - default: - suspendedLanes = NormalPriority; - } - pingedLanes = performConcurrentWorkOnRoot.bind(null, root); - suspendedLanes = scheduleCallback$2(suspendedLanes, pingedLanes); - root.callbackPriority = currentTime; - root.callbackNode = suspendedLanes; - return currentTime; -} -function scheduleImmediateTask(cb) { - useMicrotasksForSchedulingInFabric - ? scheduleMicrotask(function () { - 0 !== (executionContext & 6) - ? scheduleCallback$2(ImmediatePriority, cb) - : cb(); - }) - : scheduleCallback$2(ImmediatePriority, cb); -} -function requestTransitionLane() { - if (0 === currentEventTransitionLane) { - var lane = nextTransitionLane; - nextTransitionLane <<= 1; - 0 === (nextTransitionLane & 4194176) && (nextTransitionLane = 128); - currentEventTransitionLane = lane; - } - return currentEventTransitionLane; -} var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, ReactCurrentBatchConfig$2 = ReactSharedInternals.ReactCurrentBatchConfig, renderLanes = 0, @@ -4666,6 +4665,153 @@ function createClassErrorUpdate(fiber, errorInfo, lane) { }); return lane; } +function throwException( + root, + returnFiber, + sourceFiber, + value, + rootRenderLanes +) { + sourceFiber.flags |= 32768; + if ( + null !== value && + "object" === typeof value && + "function" === typeof value.then + ) { + var tag = sourceFiber.tag; + 0 !== (sourceFiber.mode & 1) || + (0 !== tag && 11 !== tag && 15 !== tag) || + ((tag = sourceFiber.alternate) + ? ((sourceFiber.updateQueue = tag.updateQueue), + (sourceFiber.memoizedState = tag.memoizedState), + (sourceFiber.lanes = tag.lanes)) + : ((sourceFiber.updateQueue = null), + (sourceFiber.memoizedState = null))); + tag = suspenseHandlerStackCursor.current; + if (null !== tag) { + switch (tag.tag) { + case 13: + return ( + sourceFiber.mode & 1 && + (null === shellBoundary + ? renderDidSuspendDelayIfPossible() + : null === tag.alternate && + 0 === workInProgressRootExitStatus && + (workInProgressRootExitStatus = 3)), + (tag.flags &= -257), + 0 === (tag.mode & 1) + ? tag === returnFiber + ? (tag.flags |= 65536) + : ((tag.flags |= 128), + (sourceFiber.flags |= 131072), + (sourceFiber.flags &= -52805), + 1 === sourceFiber.tag && + (null === sourceFiber.alternate + ? (sourceFiber.tag = 17) + : ((returnFiber = createUpdate(2)), + (returnFiber.tag = 2), + enqueueUpdate(sourceFiber, returnFiber, 2))), + (sourceFiber.lanes |= 2)) + : ((tag.flags |= 65536), (tag.lanes = rootRenderLanes)), + value === noopSuspenseyCommitThenable + ? (tag.flags |= 16384) + : ((returnFiber = tag.updateQueue), + null === returnFiber + ? (tag.updateQueue = new Set([value])) + : returnFiber.add(value), + tag.mode & 1 && + attachPingListener(root, value, rootRenderLanes)), + !1 + ); + case 22: + if (tag.mode & 1) + return ( + (tag.flags |= 65536), + value === noopSuspenseyCommitThenable + ? (tag.flags |= 16384) + : ((returnFiber = tag.updateQueue), + null === returnFiber + ? ((returnFiber = { + transitions: null, + markerInstances: null, + retryQueue: new Set([value]) + }), + (tag.updateQueue = returnFiber)) + : ((sourceFiber = returnFiber.retryQueue), + null === sourceFiber + ? (returnFiber.retryQueue = new Set([value])) + : sourceFiber.add(value)), + attachPingListener(root, value, rootRenderLanes)), + !1 + ); + } + throw Error( + "Unexpected Suspense handler tag (" + + tag.tag + + "). This is a bug in React." + ); + } + if (1 === root.tag) + return ( + attachPingListener(root, value, rootRenderLanes), + renderDidSuspendDelayIfPossible(), + !1 + ); + value = Error( + "A component suspended while responding to synchronous input. This will cause the UI to be replaced with a loading indicator. To fix, updates that suspend should be wrapped with startTransition." + ); + } + root = value = createCapturedValueAtFiber(value, sourceFiber); + 4 !== workInProgressRootExitStatus && (workInProgressRootExitStatus = 2); + null === workInProgressRootConcurrentErrors + ? (workInProgressRootConcurrentErrors = [root]) + : workInProgressRootConcurrentErrors.push(root); + if (null === returnFiber) return !0; + root = returnFiber; + do { + switch (root.tag) { + case 3: + return ( + (root.flags |= 65536), + (rootRenderLanes &= -rootRenderLanes), + (root.lanes |= rootRenderLanes), + (rootRenderLanes = createRootErrorUpdate( + root, + value, + rootRenderLanes + )), + enqueueCapturedUpdate(root, rootRenderLanes), + !1 + ); + case 1: + if ( + ((returnFiber = value), + (sourceFiber = root.type), + (tag = root.stateNode), + 0 === (root.flags & 128) && + ("function" === typeof sourceFiber.getDerivedStateFromError || + (null !== tag && + "function" === typeof tag.componentDidCatch && + (null === legacyErrorBoundariesThatAlreadyFailed || + !legacyErrorBoundariesThatAlreadyFailed.has(tag))))) + ) + return ( + (root.flags |= 65536), + (rootRenderLanes &= -rootRenderLanes), + (root.lanes |= rootRenderLanes), + (rootRenderLanes = createClassErrorUpdate( + root, + returnFiber, + rootRenderLanes + )), + enqueueCapturedUpdate(root, rootRenderLanes), + !1 + ); + } + root = root.return; + } while (null !== root); + return !1; +} var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner, SelectiveHydrationException = Error( "This is not a real error. It's an implementation detail of React's selective hydration feature. If this leaks into userspace, it's a bug in React. Please file an issue." @@ -5969,14 +6115,14 @@ function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { break; case "collapsed": lastTailNode = renderState.tail; - for (var lastTailNode$64 = null; null !== lastTailNode; ) - null !== lastTailNode.alternate && (lastTailNode$64 = lastTailNode), + for (var lastTailNode$65 = null; null !== lastTailNode; ) + null !== lastTailNode.alternate && (lastTailNode$65 = lastTailNode), (lastTailNode = lastTailNode.sibling); - null === lastTailNode$64 + null === lastTailNode$65 ? hasRenderedATailFallback || null === renderState.tail ? (renderState.tail = null) : (renderState.tail.sibling = null) - : (lastTailNode$64.sibling = null); + : (lastTailNode$65.sibling = null); } } function bubbleProperties(completedWork) { @@ -5986,19 +6132,19 @@ function bubbleProperties(completedWork) { newChildLanes = 0, subtreeFlags = 0; if (didBailout) - for (var child$65 = completedWork.child; null !== child$65; ) - (newChildLanes |= child$65.lanes | child$65.childLanes), - (subtreeFlags |= child$65.subtreeFlags & 31457280), - (subtreeFlags |= child$65.flags & 31457280), - (child$65.return = completedWork), - (child$65 = child$65.sibling); + for (var child$66 = completedWork.child; null !== child$66; ) + (newChildLanes |= child$66.lanes | child$66.childLanes), + (subtreeFlags |= child$66.subtreeFlags & 31457280), + (subtreeFlags |= child$66.flags & 31457280), + (child$66.return = completedWork), + (child$66 = child$66.sibling); else - for (child$65 = completedWork.child; null !== child$65; ) - (newChildLanes |= child$65.lanes | child$65.childLanes), - (subtreeFlags |= child$65.subtreeFlags), - (subtreeFlags |= child$65.flags), - (child$65.return = completedWork), - (child$65 = child$65.sibling); + for (child$66 = completedWork.child; null !== child$66; ) + (newChildLanes |= child$66.lanes | child$66.childLanes), + (subtreeFlags |= child$66.subtreeFlags), + (subtreeFlags |= child$66.flags), + (child$66.return = completedWork), + (child$66 = child$66.sibling); completedWork.subtreeFlags |= subtreeFlags; completedWork.childLanes = newChildLanes; return didBailout; @@ -6490,8 +6636,8 @@ function safelyDetachRef(current, nearestMountedAncestor) { else if ("function" === typeof ref) try { ref(null); - } catch (error$80) { - captureCommitPhaseError(current, nearestMountedAncestor, error$80); + } catch (error$81) { + captureCommitPhaseError(current, nearestMountedAncestor, error$81); } else ref.current = null; } @@ -6595,10 +6741,10 @@ function commitHookEffectListMount(flags, finishedWork) { var effect = (finishedWork = finishedWork.next); do { if ((effect.tag & flags) === flags) { - var create$81 = effect.create, + var create$82 = effect.create, inst = effect.inst; - create$81 = create$81(); - inst.destroy = create$81; + create$82 = create$82(); + inst.destroy = create$82; } effect = effect.next; } while (effect !== finishedWork); @@ -6661,11 +6807,11 @@ function commitLayoutEffectOnFiber(finishedRoot, current, finishedWork) { current, finishedRoot.__reactInternalSnapshotBeforeUpdate ); - } catch (error$82) { + } catch (error$83) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$82 + error$83 ); } } @@ -6985,8 +7131,8 @@ function commitMutationEffectsOnFiber(finishedWork, root) { } try { commitHookEffectListUnmount(5, finishedWork, finishedWork.return); - } catch (error$84) { - captureCommitPhaseError(finishedWork, finishedWork.return, error$84); + } catch (error$85) { + captureCommitPhaseError(finishedWork, finishedWork.return, error$85); } } break; @@ -7962,13 +8108,13 @@ function renderRootSync(root, lanes) { default: (workInProgressSuspendedReason = 0), (workInProgressThrownValue = null), - throwAndUnwindWorkLoop(unitOfWork, thrownValue); + throwAndUnwindWorkLoop(root, unitOfWork, thrownValue); } } workLoopSync(); break; - } catch (thrownValue$92) { - handleThrow(root, thrownValue$92); + } catch (thrownValue$93) { + handleThrow(root, thrownValue$93); } while (1); lanes && root.shellSuspendCounter++; @@ -8004,7 +8150,7 @@ function renderRootConcurrent(root, lanes) { case 1: workInProgressSuspendedReason = 0; workInProgressThrownValue = null; - throwAndUnwindWorkLoop(lanes, thrownValue); + throwAndUnwindWorkLoop(root, lanes, thrownValue); break; case 2: if (isThenableResolved(thrownValue)) { @@ -8034,7 +8180,7 @@ function renderRootConcurrent(root, lanes) { replaySuspendedUnitOfWork(lanes)) : ((workInProgressSuspendedReason = 0), (workInProgressThrownValue = null), - throwAndUnwindWorkLoop(lanes, thrownValue)); + throwAndUnwindWorkLoop(root, lanes, thrownValue)); break; case 5: switch (workInProgress.tag) { @@ -8057,12 +8203,12 @@ function renderRootConcurrent(root, lanes) { } workInProgressSuspendedReason = 0; workInProgressThrownValue = null; - throwAndUnwindWorkLoop(lanes, thrownValue); + throwAndUnwindWorkLoop(root, lanes, thrownValue); break; case 6: workInProgressSuspendedReason = 0; workInProgressThrownValue = null; - throwAndUnwindWorkLoop(lanes, thrownValue); + throwAndUnwindWorkLoop(root, lanes, thrownValue); break; case 8: resetWorkInProgressStack(); @@ -8074,8 +8220,8 @@ function renderRootConcurrent(root, lanes) { } workLoopConcurrent(); break; - } catch (thrownValue$94) { - handleThrow(root, thrownValue$94); + } catch (thrownValue$95) { + handleThrow(root, thrownValue$95); } while (1); resetContextDependencies(); @@ -8153,191 +8299,55 @@ function replaySuspendedUnitOfWork(unitOfWork) { : (workInProgress = current); ReactCurrentOwner.current = null; } -function throwAndUnwindWorkLoop(unitOfWork, thrownValue) { +function throwAndUnwindWorkLoop(root, unitOfWork, thrownValue) { resetContextDependencies(); resetHooksOnUnwind(unitOfWork); thenableState$1 = null; thenableIndexCounter$1 = 0; var returnFiber = unitOfWork.return; - if (null === returnFiber || null === workInProgressRoot) - (workInProgressRootExitStatus = 1), - (workInProgressRootFatalError = thrownValue), - (workInProgress = null); - else { - try { - a: { - var root = workInProgressRoot, - value = thrownValue; - thrownValue = workInProgressRootRenderLanes; - unitOfWork.flags |= 32768; - if ( - null !== value && - "object" === typeof value && - "function" === typeof value.then - ) { - var wakeable = value, - tag = unitOfWork.tag; - if ( - 0 === (unitOfWork.mode & 1) && - (0 === tag || 11 === tag || 15 === tag) - ) { - var currentSource = unitOfWork.alternate; - currentSource - ? ((unitOfWork.updateQueue = currentSource.updateQueue), - (unitOfWork.memoizedState = currentSource.memoizedState), - (unitOfWork.lanes = currentSource.lanes)) - : ((unitOfWork.updateQueue = null), - (unitOfWork.memoizedState = null)); - } - var suspenseBoundary = suspenseHandlerStackCursor.current; - if (null !== suspenseBoundary) { - switch (suspenseBoundary.tag) { - case 13: - unitOfWork.mode & 1 && - (null === shellBoundary - ? renderDidSuspendDelayIfPossible() - : null === suspenseBoundary.alternate && - 0 === workInProgressRootExitStatus && - (workInProgressRootExitStatus = 3)); - suspenseBoundary.flags &= -257; - if (0 === (suspenseBoundary.mode & 1)) - if (suspenseBoundary === returnFiber) - suspenseBoundary.flags |= 65536; - else { - suspenseBoundary.flags |= 128; - unitOfWork.flags |= 131072; - unitOfWork.flags &= -52805; - if (1 === unitOfWork.tag) - if (null === unitOfWork.alternate) unitOfWork.tag = 17; - else { - var update = createUpdate(2); - update.tag = 2; - enqueueUpdate(unitOfWork, update, 2); - } - unitOfWork.lanes |= 2; - } - else - (suspenseBoundary.flags |= 65536), - (suspenseBoundary.lanes = thrownValue); - if (wakeable === noopSuspenseyCommitThenable) - suspenseBoundary.flags |= 16384; - else { - var retryQueue = suspenseBoundary.updateQueue; - null === retryQueue - ? (suspenseBoundary.updateQueue = new Set([wakeable])) - : retryQueue.add(wakeable); - suspenseBoundary.mode & 1 && - attachPingListener(root, wakeable, thrownValue); - } - break a; - case 22: - if (suspenseBoundary.mode & 1) { - suspenseBoundary.flags |= 65536; - if (wakeable === noopSuspenseyCommitThenable) - suspenseBoundary.flags |= 16384; - else { - var offscreenQueue = suspenseBoundary.updateQueue; - if (null === offscreenQueue) { - var newOffscreenQueue = { - transitions: null, - markerInstances: null, - retryQueue: new Set([wakeable]) - }; - suspenseBoundary.updateQueue = newOffscreenQueue; - } else { - var retryQueue$32 = offscreenQueue.retryQueue; - null === retryQueue$32 - ? (offscreenQueue.retryQueue = new Set([wakeable])) - : retryQueue$32.add(wakeable); - } - attachPingListener(root, wakeable, thrownValue); - } - break a; - } - } - throw Error( - "Unexpected Suspense handler tag (" + - suspenseBoundary.tag + - "). This is a bug in React." - ); - } - if (1 === root.tag) { - attachPingListener(root, wakeable, thrownValue); - renderDidSuspendDelayIfPossible(); - break a; - } else - value = Error( - "A component suspended while responding to synchronous input. This will cause the UI to be replaced with a loading indicator. To fix, updates that suspend should be wrapped with startTransition." - ); - } - root = value = createCapturedValueAtFiber(value, unitOfWork); - 4 !== workInProgressRootExitStatus && - (workInProgressRootExitStatus = 2); - null === workInProgressRootConcurrentErrors - ? (workInProgressRootConcurrentErrors = [root]) - : workInProgressRootConcurrentErrors.push(root); - root = returnFiber; - do { - switch (root.tag) { - case 3: - var errorInfo = value; - root.flags |= 65536; - thrownValue &= -thrownValue; - root.lanes |= thrownValue; - var update$jscomp$0 = createRootErrorUpdate( - root, - errorInfo, - thrownValue - ); - enqueueCapturedUpdate(root, update$jscomp$0); - break a; - case 1: - tag = value; - var ctor = root.type, - instance = root.stateNode; - if ( - 0 === (root.flags & 128) && - ("function" === typeof ctor.getDerivedStateFromError || - (null !== instance && - "function" === typeof instance.componentDidCatch && - (null === legacyErrorBoundariesThatAlreadyFailed || - !legacyErrorBoundariesThatAlreadyFailed.has(instance)))) - ) { - root.flags |= 65536; - update$jscomp$0 = thrownValue & -thrownValue; - root.lanes |= update$jscomp$0; - errorInfo = createClassErrorUpdate(root, tag, update$jscomp$0); - enqueueCapturedUpdate(root, errorInfo); - break a; - } - } - root = root.return; - } while (null !== root); - } - } catch (error) { - throw ((workInProgress = returnFiber), error); + try { + if ( + throwException( + root, + returnFiber, + unitOfWork, + thrownValue, + workInProgressRootRenderLanes + ) + ) { + workInProgressRootExitStatus = 1; + workInProgressRootFatalError = thrownValue; + workInProgress = null; + return; } - 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); + } catch (error) { + if (null !== returnFiber) throw ((workInProgress = returnFiber), error); + workInProgressRootExitStatus = 1; + workInProgressRootFatalError = thrownValue; + workInProgress = null; + return; } + if (unitOfWork.flags & 32768) + a: { + root = unitOfWork; + do { + unitOfWork = unwindWork(root.alternate, root); + if (null !== unitOfWork) { + unitOfWork.flags &= 32767; + workInProgress = unitOfWork; + break a; + } + root = root.return; + null !== root && + ((root.flags |= 32768), + (root.subtreeFlags = 0), + (root.deletions = null)); + workInProgress = root; + } while (null !== root); + workInProgressRootExitStatus = 6; + workInProgress = null; + } + else completeUnitOfWork(unitOfWork); } function completeUnitOfWork(unitOfWork) { var completedWork = unitOfWork; @@ -9550,10 +9560,10 @@ batchedUpdatesImpl = function (fn, a) { } }; var roots = new Map(), - devToolsConfig$jscomp$inline_1054 = { + devToolsConfig$jscomp$inline_1052 = { findFiberByHostInstance: getInstanceFromNode, bundleType: 0, - version: "18.3.0-canary-4aee1a03", + version: "18.3.0-canary-60bc647b", rendererPackageName: "react-native-renderer", rendererConfig: { getInspectorDataForInstance: getInspectorDataForInstance, @@ -9569,11 +9579,11 @@ var roots = new Map(), }.bind(null, findNodeHandle) } }; -var internals$jscomp$inline_1293 = { - bundleType: devToolsConfig$jscomp$inline_1054.bundleType, - version: devToolsConfig$jscomp$inline_1054.version, - rendererPackageName: devToolsConfig$jscomp$inline_1054.rendererPackageName, - rendererConfig: devToolsConfig$jscomp$inline_1054.rendererConfig, +var internals$jscomp$inline_1273 = { + bundleType: devToolsConfig$jscomp$inline_1052.bundleType, + version: devToolsConfig$jscomp$inline_1052.version, + rendererPackageName: devToolsConfig$jscomp$inline_1052.rendererPackageName, + rendererConfig: devToolsConfig$jscomp$inline_1052.rendererConfig, overrideHookState: null, overrideHookStateDeletePath: null, overrideHookStateRenamePath: null, @@ -9589,26 +9599,26 @@ var internals$jscomp$inline_1293 = { return null === fiber ? null : fiber.stateNode; }, findFiberByHostInstance: - devToolsConfig$jscomp$inline_1054.findFiberByHostInstance || + devToolsConfig$jscomp$inline_1052.findFiberByHostInstance || emptyFindFiberByHostInstance, findHostInstancesForRefresh: null, scheduleRefresh: null, scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "18.3.0-canary-4aee1a03" + reconcilerVersion: "18.3.0-canary-60bc647b" }; if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { - var hook$jscomp$inline_1294 = __REACT_DEVTOOLS_GLOBAL_HOOK__; + var hook$jscomp$inline_1274 = __REACT_DEVTOOLS_GLOBAL_HOOK__; if ( - !hook$jscomp$inline_1294.isDisabled && - hook$jscomp$inline_1294.supportsFiber + !hook$jscomp$inline_1274.isDisabled && + hook$jscomp$inline_1274.supportsFiber ) try { - (rendererID = hook$jscomp$inline_1294.inject( - internals$jscomp$inline_1293 + (rendererID = hook$jscomp$inline_1274.inject( + internals$jscomp$inline_1273 )), - (injectedHook = hook$jscomp$inline_1294); + (injectedHook = hook$jscomp$inline_1274); } catch (err) {} } exports.createPortal = function (children, containerTag) { diff --git a/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactFabric-profiling.fb.js b/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactFabric-profiling.fb.js index d347d8e2b319a..61c82586e4c15 100644 --- a/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactFabric-profiling.fb.js +++ b/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactFabric-profiling.fb.js @@ -7,7 +7,7 @@ * @noflow * @nolint * @preventMunge - * @generated SignedSource<> + * @generated SignedSource<> */ "use strict"; @@ -944,7 +944,7 @@ eventPluginOrder = Array.prototype.slice.call([ "ReactNativeBridgeEventPlugin" ]); recomputePluginOrdering(); -var injectedNamesToPlugins$jscomp$inline_251 = { +var injectedNamesToPlugins$jscomp$inline_252 = { ResponderEventPlugin: ResponderEventPlugin, ReactNativeBridgeEventPlugin: { eventTypes: {}, @@ -990,32 +990,32 @@ var injectedNamesToPlugins$jscomp$inline_251 = { } } }, - isOrderingDirty$jscomp$inline_252 = !1, - pluginName$jscomp$inline_253; -for (pluginName$jscomp$inline_253 in injectedNamesToPlugins$jscomp$inline_251) + isOrderingDirty$jscomp$inline_253 = !1, + pluginName$jscomp$inline_254; +for (pluginName$jscomp$inline_254 in injectedNamesToPlugins$jscomp$inline_252) if ( - injectedNamesToPlugins$jscomp$inline_251.hasOwnProperty( - pluginName$jscomp$inline_253 + injectedNamesToPlugins$jscomp$inline_252.hasOwnProperty( + pluginName$jscomp$inline_254 ) ) { - var pluginModule$jscomp$inline_254 = - injectedNamesToPlugins$jscomp$inline_251[pluginName$jscomp$inline_253]; + var pluginModule$jscomp$inline_255 = + injectedNamesToPlugins$jscomp$inline_252[pluginName$jscomp$inline_254]; if ( - !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_253) || - namesToPlugins[pluginName$jscomp$inline_253] !== - pluginModule$jscomp$inline_254 + !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_254) || + namesToPlugins[pluginName$jscomp$inline_254] !== + pluginModule$jscomp$inline_255 ) { - if (namesToPlugins[pluginName$jscomp$inline_253]) + if (namesToPlugins[pluginName$jscomp$inline_254]) throw Error( "EventPluginRegistry: Cannot inject two different event plugins using the same name, `" + - (pluginName$jscomp$inline_253 + "`.") + (pluginName$jscomp$inline_254 + "`.") ); - namesToPlugins[pluginName$jscomp$inline_253] = - pluginModule$jscomp$inline_254; - isOrderingDirty$jscomp$inline_252 = !0; + namesToPlugins[pluginName$jscomp$inline_254] = + pluginModule$jscomp$inline_255; + isOrderingDirty$jscomp$inline_253 = !0; } } -isOrderingDirty$jscomp$inline_252 && recomputePluginOrdering(); +isOrderingDirty$jscomp$inline_253 && recomputePluginOrdering(); var emptyObject$1 = {}, removedKeys = null, removedKeyCount = 0, @@ -2266,6 +2266,229 @@ function getRootForUpdatedFiber(sourceFiber) { (sourceFiber = parent), (parent = sourceFiber.return); return 3 === sourceFiber.tag ? sourceFiber.stateNode : null; } +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), + scheduleImmediateTask(processRootScheduleInMicrotask)); + enableDeferRootSchedulingToMicrotask || + scheduleTaskForRootDuringMicrotask(root, now$1()); +} +function flushSyncWorkAcrossRoots_impl(onlyLegacy) { + if (!isFlushingWork && mightHavePendingSyncWork) { + var errors = null; + isFlushingWork = !0; + do { + var didPerformSomeWork = !1; + for (var root = firstScheduledRoot; null !== root; ) { + if (!onlyLegacy || 0 === root.tag) { + var workInProgressRootRenderLanes$12 = workInProgressRootRenderLanes, + nextLanes = getNextLanes( + root, + root === workInProgressRoot ? workInProgressRootRenderLanes$12 : 0 + ); + if (0 !== (nextLanes & 3)) + try { + didPerformSomeWork = !0; + workInProgressRootRenderLanes$12 = root; + if (0 !== (executionContext & 6)) + throw Error("Should not already be working."); + if (!flushPassiveEffects()) { + currentUpdateIsNested = nestedUpdateScheduled; + nestedUpdateScheduled = !1; + var exitStatus = renderRootSync( + workInProgressRootRenderLanes$12, + nextLanes + ); + if ( + 0 !== workInProgressRootRenderLanes$12.tag && + 2 === exitStatus + ) { + var originallyAttemptedLanes = nextLanes, + errorRetryLanes = getLanesToRetrySynchronouslyOnError( + workInProgressRootRenderLanes$12, + originallyAttemptedLanes + ); + 0 !== errorRetryLanes && + ((nextLanes = errorRetryLanes), + (exitStatus = recoverFromConcurrentError( + workInProgressRootRenderLanes$12, + originallyAttemptedLanes, + errorRetryLanes + ))); + } + if (1 === exitStatus) + throw ( + ((originallyAttemptedLanes = workInProgressRootFatalError), + prepareFreshStack(workInProgressRootRenderLanes$12, 0), + markRootSuspended( + workInProgressRootRenderLanes$12, + nextLanes, + 0 + ), + ensureRootIsScheduled(workInProgressRootRenderLanes$12), + originallyAttemptedLanes) + ); + 6 === exitStatus + ? markRootSuspended( + workInProgressRootRenderLanes$12, + nextLanes, + workInProgressDeferredLane + ) + : ((workInProgressRootRenderLanes$12.finishedWork = + workInProgressRootRenderLanes$12.current.alternate), + (workInProgressRootRenderLanes$12.finishedLanes = + nextLanes), + commitRoot( + workInProgressRootRenderLanes$12, + workInProgressRootRecoverableErrors, + workInProgressTransitions, + workInProgressDeferredLane + )); + } + ensureRootIsScheduled(workInProgressRootRenderLanes$12); + } 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++) + scheduleImmediateTask(throwError.bind(null, errors[onlyLegacy])); + } + throw errors[0]; + } + } +} +function throwError(error) { + throw error; +} +function processRootScheduleInMicrotask() { + mightHavePendingSyncWork = didScheduleMicrotask = !1; + for ( + var currentTime = now$1(), 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 & -62914561; + 0 < lanes; + + ) { + var index$4 = 31 - clz32(lanes), + lane = 1 << index$4, + expirationTime = expirationTimes[index$4]; + if (-1 === expirationTime) { + if (0 === (lane & suspendedLanes) || 0 !== (lane & pingedLanes)) + expirationTimes[index$4] = 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; + break; + case 268435456: + suspendedLanes = IdlePriority; + break; + default: + suspendedLanes = NormalPriority; + } + pingedLanes = performConcurrentWorkOnRoot.bind(null, root); + suspendedLanes = scheduleCallback$2(suspendedLanes, pingedLanes); + root.callbackPriority = currentTime; + root.callbackNode = suspendedLanes; + return currentTime; +} +function scheduleImmediateTask(cb) { + useMicrotasksForSchedulingInFabric + ? scheduleMicrotask(function () { + 0 !== (executionContext & 6) + ? scheduleCallback$2(ImmediatePriority, cb) + : cb(); + }) + : scheduleCallback$2(ImmediatePriority, cb); +} +function requestTransitionLane() { + if (0 === currentEventTransitionLane) { + var lane = nextTransitionLane; + nextTransitionLane <<= 1; + 0 === (nextTransitionLane & 4194176) && (nextTransitionLane = 128); + currentEventTransitionLane = lane; + } + return currentEventTransitionLane; +} var hasForceUpdate = !1; function initializeUpdateQueue(fiber) { fiber.updateQueue = { @@ -3362,339 +3585,116 @@ function createChildReconciler(shouldTrackSideEffects) { return ("string" === typeof newChild && "" !== newChild) || "number" === typeof newChild ? ((newChild = "" + newChild), - null !== currentFirstChild && 6 === currentFirstChild.tag - ? (deleteRemainingChildren(returnFiber, currentFirstChild.sibling), - (currentFirstChild = useFiber(currentFirstChild, newChild)), - (currentFirstChild.return = returnFiber), - (returnFiber = currentFirstChild)) - : (deleteRemainingChildren(returnFiber, currentFirstChild), - (currentFirstChild = createFiberFromText( - newChild, - returnFiber.mode, - lanes - )), - (currentFirstChild.return = returnFiber), - (returnFiber = currentFirstChild)), - placeSingleChild(returnFiber)) - : deleteRemainingChildren(returnFiber, currentFirstChild); - } - function reconcileChildFibers( - returnFiber, - currentFirstChild, - newChild, - lanes - ) { - thenableIndexCounter$1 = 0; - returnFiber = reconcileChildFibersImpl( - returnFiber, - currentFirstChild, - newChild, - lanes - ); - thenableState$1 = null; - return returnFiber; - } - return reconcileChildFibers; -} -var reconcileChildFibers = createChildReconciler(!0), - mountChildFibers = createChildReconciler(!1), - currentTreeHiddenStackCursor = createCursor(null), - prevEntangledRenderLanesCursor = createCursor(0); -function pushHiddenContext(fiber, context) { - fiber = entangledRenderLanes; - push(prevEntangledRenderLanesCursor, fiber); - push(currentTreeHiddenStackCursor, context); - entangledRenderLanes = fiber | context.baseLanes; -} -function reuseHiddenContextOnStack() { - push(prevEntangledRenderLanesCursor, entangledRenderLanes); - push(currentTreeHiddenStackCursor, currentTreeHiddenStackCursor.current); -} -function popHiddenContext() { - entangledRenderLanes = prevEntangledRenderLanesCursor.current; - pop(currentTreeHiddenStackCursor); - pop(prevEntangledRenderLanesCursor); -} -var suspenseHandlerStackCursor = createCursor(null), - shellBoundary = null; -function pushPrimaryTreeSuspenseHandler(handler) { - var current = handler.alternate; - push(suspenseStackCursor, suspenseStackCursor.current & 1); - push(suspenseHandlerStackCursor, handler); - null === shellBoundary && - (null === current || null !== currentTreeHiddenStackCursor.current - ? (shellBoundary = handler) - : null !== current.memoizedState && (shellBoundary = handler)); -} -function pushOffscreenSuspenseHandler(fiber) { - if (22 === fiber.tag) { - if ( - (push(suspenseStackCursor, suspenseStackCursor.current), - push(suspenseHandlerStackCursor, fiber), - null === shellBoundary) - ) { - var current = fiber.alternate; - null !== current && - null !== current.memoizedState && - (shellBoundary = fiber); - } - } else reuseSuspenseHandlerOnStack(fiber); -} -function reuseSuspenseHandlerOnStack() { - push(suspenseStackCursor, suspenseStackCursor.current); - push(suspenseHandlerStackCursor, suspenseHandlerStackCursor.current); -} -function popSuspenseHandler(fiber) { - pop(suspenseHandlerStackCursor); - shellBoundary === fiber && (shellBoundary = null); - pop(suspenseStackCursor); -} -var suspenseStackCursor = createCursor(0); -function findFirstSuspended(row) { - for (var node = row; null !== node; ) { - if (13 === node.tag) { - var state = node.memoizedState; - if (null !== state && (null === state.dehydrated || shim$1() || shim$1())) - return node; - } else if (19 === node.tag && void 0 !== node.memoizedProps.revealOrder) { - if (0 !== (node.flags & 128)) return node; - } else if (null !== node.child) { - node.child.return = node; - node = node.child; - continue; - } - if (node === row) break; - for (; null === node.sibling; ) { - if (null === node.return || node.return === row) return null; - node = node.return; - } - node.sibling.return = node.return; - node = node.sibling; - } - return null; -} -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), - scheduleImmediateTask(processRootScheduleInMicrotask)); - enableDeferRootSchedulingToMicrotask || - scheduleTaskForRootDuringMicrotask(root, now$1()); -} -function flushSyncWorkAcrossRoots_impl(onlyLegacy) { - if (!isFlushingWork && mightHavePendingSyncWork) { - var errors = null; - isFlushingWork = !0; - do { - var didPerformSomeWork = !1; - for (var root = firstScheduledRoot; null !== root; ) { - if (!onlyLegacy || 0 === root.tag) { - var workInProgressRootRenderLanes$29 = workInProgressRootRenderLanes, - nextLanes = getNextLanes( - root, - root === workInProgressRoot ? workInProgressRootRenderLanes$29 : 0 - ); - if (0 !== (nextLanes & 3)) - try { - didPerformSomeWork = !0; - workInProgressRootRenderLanes$29 = root; - if (0 !== (executionContext & 6)) - throw Error("Should not already be working."); - if (!flushPassiveEffects()) { - currentUpdateIsNested = nestedUpdateScheduled; - nestedUpdateScheduled = !1; - var exitStatus = renderRootSync( - workInProgressRootRenderLanes$29, - nextLanes - ); - if ( - 0 !== workInProgressRootRenderLanes$29.tag && - 2 === exitStatus - ) { - var originallyAttemptedLanes = nextLanes, - errorRetryLanes = getLanesToRetrySynchronouslyOnError( - workInProgressRootRenderLanes$29, - originallyAttemptedLanes - ); - 0 !== errorRetryLanes && - ((nextLanes = errorRetryLanes), - (exitStatus = recoverFromConcurrentError( - workInProgressRootRenderLanes$29, - originallyAttemptedLanes, - errorRetryLanes - ))); - } - if (1 === exitStatus) - throw ( - ((originallyAttemptedLanes = workInProgressRootFatalError), - prepareFreshStack(workInProgressRootRenderLanes$29, 0), - markRootSuspended( - workInProgressRootRenderLanes$29, - nextLanes, - 0 - ), - ensureRootIsScheduled(workInProgressRootRenderLanes$29), - originallyAttemptedLanes) - ); - 6 === exitStatus - ? markRootSuspended( - workInProgressRootRenderLanes$29, - nextLanes, - workInProgressDeferredLane - ) - : ((workInProgressRootRenderLanes$29.finishedWork = - workInProgressRootRenderLanes$29.current.alternate), - (workInProgressRootRenderLanes$29.finishedLanes = - nextLanes), - commitRoot( - workInProgressRootRenderLanes$29, - workInProgressRootRecoverableErrors, - workInProgressTransitions, - workInProgressDeferredLane - )); - } - ensureRootIsScheduled(workInProgressRootRenderLanes$29); - } 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++) - scheduleImmediateTask(throwError.bind(null, errors[onlyLegacy])); - } - throw errors[0]; - } - } -} -function throwError(error) { - throw error; -} -function processRootScheduleInMicrotask() { - mightHavePendingSyncWork = didScheduleMicrotask = !1; - for ( - var currentTime = now$1(), 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 & -62914561; - 0 < lanes; - - ) { - var index$4 = 31 - clz32(lanes), - lane = 1 << index$4, - expirationTime = expirationTimes[index$4]; - if (-1 === expirationTime) { - if (0 === (lane & suspendedLanes) || 0 !== (lane & pingedLanes)) - expirationTimes[index$4] = 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 + null !== currentFirstChild && 6 === currentFirstChild.tag + ? (deleteRemainingChildren(returnFiber, currentFirstChild.sibling), + (currentFirstChild = useFiber(currentFirstChild, newChild)), + (currentFirstChild.return = returnFiber), + (returnFiber = currentFirstChild)) + : (deleteRemainingChildren(returnFiber, currentFirstChild), + (currentFirstChild = createFiberFromText( + newChild, + returnFiber.mode, + lanes + )), + (currentFirstChild.return = returnFiber), + (returnFiber = currentFirstChild)), + placeSingleChild(returnFiber)) + : deleteRemainingChildren(returnFiber, currentFirstChild); + } + function reconcileChildFibers( + returnFiber, + currentFirstChild, + newChild, + lanes + ) { + thenableIndexCounter$1 = 0; + returnFiber = reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + newChild, + lanes ); - 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; - break; - case 268435456: - suspendedLanes = IdlePriority; - break; - default: - suspendedLanes = NormalPriority; + thenableState$1 = null; + return returnFiber; } - pingedLanes = performConcurrentWorkOnRoot.bind(null, root); - suspendedLanes = scheduleCallback$2(suspendedLanes, pingedLanes); - root.callbackPriority = currentTime; - root.callbackNode = suspendedLanes; - return currentTime; + return reconcileChildFibers; } -function scheduleImmediateTask(cb) { - useMicrotasksForSchedulingInFabric - ? scheduleMicrotask(function () { - 0 !== (executionContext & 6) - ? scheduleCallback$2(ImmediatePriority, cb) - : cb(); - }) - : scheduleCallback$2(ImmediatePriority, cb); +var reconcileChildFibers = createChildReconciler(!0), + mountChildFibers = createChildReconciler(!1), + currentTreeHiddenStackCursor = createCursor(null), + prevEntangledRenderLanesCursor = createCursor(0); +function pushHiddenContext(fiber, context) { + fiber = entangledRenderLanes; + push(prevEntangledRenderLanesCursor, fiber); + push(currentTreeHiddenStackCursor, context); + entangledRenderLanes = fiber | context.baseLanes; } -function requestTransitionLane() { - if (0 === currentEventTransitionLane) { - var lane = nextTransitionLane; - nextTransitionLane <<= 1; - 0 === (nextTransitionLane & 4194176) && (nextTransitionLane = 128); - currentEventTransitionLane = lane; +function reuseHiddenContextOnStack() { + push(prevEntangledRenderLanesCursor, entangledRenderLanes); + push(currentTreeHiddenStackCursor, currentTreeHiddenStackCursor.current); +} +function popHiddenContext() { + entangledRenderLanes = prevEntangledRenderLanesCursor.current; + pop(currentTreeHiddenStackCursor); + pop(prevEntangledRenderLanesCursor); +} +var suspenseHandlerStackCursor = createCursor(null), + shellBoundary = null; +function pushPrimaryTreeSuspenseHandler(handler) { + var current = handler.alternate; + push(suspenseStackCursor, suspenseStackCursor.current & 1); + push(suspenseHandlerStackCursor, handler); + null === shellBoundary && + (null === current || null !== currentTreeHiddenStackCursor.current + ? (shellBoundary = handler) + : null !== current.memoizedState && (shellBoundary = handler)); +} +function pushOffscreenSuspenseHandler(fiber) { + if (22 === fiber.tag) { + if ( + (push(suspenseStackCursor, suspenseStackCursor.current), + push(suspenseHandlerStackCursor, fiber), + null === shellBoundary) + ) { + var current = fiber.alternate; + null !== current && + null !== current.memoizedState && + (shellBoundary = fiber); + } + } else reuseSuspenseHandlerOnStack(fiber); +} +function reuseSuspenseHandlerOnStack() { + push(suspenseStackCursor, suspenseStackCursor.current); + push(suspenseHandlerStackCursor, suspenseHandlerStackCursor.current); +} +function popSuspenseHandler(fiber) { + pop(suspenseHandlerStackCursor); + shellBoundary === fiber && (shellBoundary = null); + pop(suspenseStackCursor); +} +var suspenseStackCursor = createCursor(0); +function findFirstSuspended(row) { + for (var node = row; null !== node; ) { + if (13 === node.tag) { + var state = node.memoizedState; + if (null !== state && (null === state.dehydrated || shim$1() || shim$1())) + return node; + } else if (19 === node.tag && void 0 !== node.memoizedProps.revealOrder) { + if (0 !== (node.flags & 128)) return node; + } else if (null !== node.child) { + node.child.return = node; + node = node.child; + continue; + } + if (node === row) break; + for (; null === node.sibling; ) { + if (null === node.return || node.return === row) return null; + node = node.return; + } + node.sibling.return = node.return; + node = node.sibling; } - return currentEventTransitionLane; + return null; } var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, ReactCurrentBatchConfig$2 = ReactSharedInternals.ReactCurrentBatchConfig, @@ -4859,6 +4859,154 @@ function createClassErrorUpdate(fiber, errorInfo, lane) { }); return lane; } +function throwException( + root, + returnFiber, + sourceFiber, + value, + rootRenderLanes +) { + sourceFiber.flags |= 32768; + isDevToolsPresent && restorePendingUpdaters(root, rootRenderLanes); + if ( + null !== value && + "object" === typeof value && + "function" === typeof value.then + ) { + var tag = sourceFiber.tag; + 0 !== (sourceFiber.mode & 1) || + (0 !== tag && 11 !== tag && 15 !== tag) || + ((tag = sourceFiber.alternate) + ? ((sourceFiber.updateQueue = tag.updateQueue), + (sourceFiber.memoizedState = tag.memoizedState), + (sourceFiber.lanes = tag.lanes)) + : ((sourceFiber.updateQueue = null), + (sourceFiber.memoizedState = null))); + tag = suspenseHandlerStackCursor.current; + if (null !== tag) { + switch (tag.tag) { + case 13: + return ( + sourceFiber.mode & 1 && + (null === shellBoundary + ? renderDidSuspendDelayIfPossible() + : null === tag.alternate && + 0 === workInProgressRootExitStatus && + (workInProgressRootExitStatus = 3)), + (tag.flags &= -257), + 0 === (tag.mode & 1) + ? tag === returnFiber + ? (tag.flags |= 65536) + : ((tag.flags |= 128), + (sourceFiber.flags |= 131072), + (sourceFiber.flags &= -52805), + 1 === sourceFiber.tag && + (null === sourceFiber.alternate + ? (sourceFiber.tag = 17) + : ((returnFiber = createUpdate(2)), + (returnFiber.tag = 2), + enqueueUpdate(sourceFiber, returnFiber, 2))), + (sourceFiber.lanes |= 2)) + : ((tag.flags |= 65536), (tag.lanes = rootRenderLanes)), + value === noopSuspenseyCommitThenable + ? (tag.flags |= 16384) + : ((returnFiber = tag.updateQueue), + null === returnFiber + ? (tag.updateQueue = new Set([value])) + : returnFiber.add(value), + tag.mode & 1 && + attachPingListener(root, value, rootRenderLanes)), + !1 + ); + case 22: + if (tag.mode & 1) + return ( + (tag.flags |= 65536), + value === noopSuspenseyCommitThenable + ? (tag.flags |= 16384) + : ((returnFiber = tag.updateQueue), + null === returnFiber + ? ((returnFiber = { + transitions: null, + markerInstances: null, + retryQueue: new Set([value]) + }), + (tag.updateQueue = returnFiber)) + : ((sourceFiber = returnFiber.retryQueue), + null === sourceFiber + ? (returnFiber.retryQueue = new Set([value])) + : sourceFiber.add(value)), + attachPingListener(root, value, rootRenderLanes)), + !1 + ); + } + throw Error( + "Unexpected Suspense handler tag (" + + tag.tag + + "). This is a bug in React." + ); + } + if (1 === root.tag) + return ( + attachPingListener(root, value, rootRenderLanes), + renderDidSuspendDelayIfPossible(), + !1 + ); + value = Error( + "A component suspended while responding to synchronous input. This will cause the UI to be replaced with a loading indicator. To fix, updates that suspend should be wrapped with startTransition." + ); + } + root = value = createCapturedValueAtFiber(value, sourceFiber); + 4 !== workInProgressRootExitStatus && (workInProgressRootExitStatus = 2); + null === workInProgressRootConcurrentErrors + ? (workInProgressRootConcurrentErrors = [root]) + : workInProgressRootConcurrentErrors.push(root); + if (null === returnFiber) return !0; + root = returnFiber; + do { + switch (root.tag) { + case 3: + return ( + (root.flags |= 65536), + (rootRenderLanes &= -rootRenderLanes), + (root.lanes |= rootRenderLanes), + (rootRenderLanes = createRootErrorUpdate( + root, + value, + rootRenderLanes + )), + enqueueCapturedUpdate(root, rootRenderLanes), + !1 + ); + case 1: + if ( + ((returnFiber = value), + (sourceFiber = root.type), + (tag = root.stateNode), + 0 === (root.flags & 128) && + ("function" === typeof sourceFiber.getDerivedStateFromError || + (null !== tag && + "function" === typeof tag.componentDidCatch && + (null === legacyErrorBoundariesThatAlreadyFailed || + !legacyErrorBoundariesThatAlreadyFailed.has(tag))))) + ) + return ( + (root.flags |= 65536), + (rootRenderLanes &= -rootRenderLanes), + (root.lanes |= rootRenderLanes), + (rootRenderLanes = createClassErrorUpdate( + root, + returnFiber, + rootRenderLanes + )), + enqueueCapturedUpdate(root, rootRenderLanes), + !1 + ); + } + root = root.return; + } while (null !== root); + return !1; +} var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner, SelectiveHydrationException = Error( "This is not a real error. It's an implementation detail of React's selective hydration feature. If this leaks into userspace, it's a bug in React. Please file an issue." @@ -6193,14 +6341,14 @@ function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { break; case "collapsed": lastTailNode = renderState.tail; - for (var lastTailNode$68 = null; null !== lastTailNode; ) - null !== lastTailNode.alternate && (lastTailNode$68 = lastTailNode), + for (var lastTailNode$69 = null; null !== lastTailNode; ) + null !== lastTailNode.alternate && (lastTailNode$69 = lastTailNode), (lastTailNode = lastTailNode.sibling); - null === lastTailNode$68 + null === lastTailNode$69 ? hasRenderedATailFallback || null === renderState.tail ? (renderState.tail = null) : (renderState.tail.sibling = null) - : (lastTailNode$68.sibling = null); + : (lastTailNode$69.sibling = null); } } function bubbleProperties(completedWork) { @@ -6212,53 +6360,53 @@ function bubbleProperties(completedWork) { if (didBailout) if (0 !== (completedWork.mode & 2)) { for ( - var treeBaseDuration$70 = completedWork.selfBaseDuration, - child$71 = completedWork.child; - null !== child$71; + var treeBaseDuration$71 = completedWork.selfBaseDuration, + child$72 = completedWork.child; + null !== child$72; ) - (newChildLanes |= child$71.lanes | child$71.childLanes), - (subtreeFlags |= child$71.subtreeFlags & 31457280), - (subtreeFlags |= child$71.flags & 31457280), - (treeBaseDuration$70 += child$71.treeBaseDuration), - (child$71 = child$71.sibling); - completedWork.treeBaseDuration = treeBaseDuration$70; + (newChildLanes |= child$72.lanes | child$72.childLanes), + (subtreeFlags |= child$72.subtreeFlags & 31457280), + (subtreeFlags |= child$72.flags & 31457280), + (treeBaseDuration$71 += child$72.treeBaseDuration), + (child$72 = child$72.sibling); + completedWork.treeBaseDuration = treeBaseDuration$71; } else for ( - treeBaseDuration$70 = completedWork.child; - null !== treeBaseDuration$70; + treeBaseDuration$71 = completedWork.child; + null !== treeBaseDuration$71; ) (newChildLanes |= - treeBaseDuration$70.lanes | treeBaseDuration$70.childLanes), - (subtreeFlags |= treeBaseDuration$70.subtreeFlags & 31457280), - (subtreeFlags |= treeBaseDuration$70.flags & 31457280), - (treeBaseDuration$70.return = completedWork), - (treeBaseDuration$70 = treeBaseDuration$70.sibling); + treeBaseDuration$71.lanes | treeBaseDuration$71.childLanes), + (subtreeFlags |= treeBaseDuration$71.subtreeFlags & 31457280), + (subtreeFlags |= treeBaseDuration$71.flags & 31457280), + (treeBaseDuration$71.return = completedWork), + (treeBaseDuration$71 = treeBaseDuration$71.sibling); else if (0 !== (completedWork.mode & 2)) { - treeBaseDuration$70 = completedWork.actualDuration; - child$71 = completedWork.selfBaseDuration; + treeBaseDuration$71 = completedWork.actualDuration; + child$72 = completedWork.selfBaseDuration; for (var child = completedWork.child; null !== child; ) (newChildLanes |= child.lanes | child.childLanes), (subtreeFlags |= child.subtreeFlags), (subtreeFlags |= child.flags), - (treeBaseDuration$70 += child.actualDuration), - (child$71 += child.treeBaseDuration), + (treeBaseDuration$71 += child.actualDuration), + (child$72 += child.treeBaseDuration), (child = child.sibling); - completedWork.actualDuration = treeBaseDuration$70; - completedWork.treeBaseDuration = child$71; + completedWork.actualDuration = treeBaseDuration$71; + completedWork.treeBaseDuration = child$72; } else for ( - treeBaseDuration$70 = completedWork.child; - null !== treeBaseDuration$70; + treeBaseDuration$71 = completedWork.child; + null !== treeBaseDuration$71; ) (newChildLanes |= - treeBaseDuration$70.lanes | treeBaseDuration$70.childLanes), - (subtreeFlags |= treeBaseDuration$70.subtreeFlags), - (subtreeFlags |= treeBaseDuration$70.flags), - (treeBaseDuration$70.return = completedWork), - (treeBaseDuration$70 = treeBaseDuration$70.sibling); + treeBaseDuration$71.lanes | treeBaseDuration$71.childLanes), + (subtreeFlags |= treeBaseDuration$71.subtreeFlags), + (subtreeFlags |= treeBaseDuration$71.flags), + (treeBaseDuration$71.return = completedWork), + (treeBaseDuration$71 = treeBaseDuration$71.sibling); completedWork.subtreeFlags |= subtreeFlags; completedWork.childLanes = newChildLanes; return didBailout; @@ -6809,8 +6957,8 @@ function safelyDetachRef(current, nearestMountedAncestor) { recordLayoutEffectDuration(current); } else ref(null); - } catch (error$89) { - captureCommitPhaseError(current, nearestMountedAncestor, error$89); + } catch (error$90) { + captureCommitPhaseError(current, nearestMountedAncestor, error$90); } else ref.current = null; } @@ -6943,10 +7091,10 @@ function commitHookEffectListMount(flags, finishedWork) { injectedProfilingHooks.markComponentLayoutEffectMountStarted( finishedWork ); - var create$90 = effect.create, + var create$91 = effect.create, inst = effect.inst; - create$90 = create$90(); - inst.destroy = create$90; + create$91 = create$91(); + inst.destroy = create$91; 0 !== (flags & 8) ? null !== injectedProfilingHooks && "function" === @@ -6974,8 +7122,8 @@ function commitHookLayoutEffects(finishedWork, hookFlags) { } else try { commitHookEffectListMount(hookFlags, finishedWork); - } catch (error$92) { - captureCommitPhaseError(finishedWork, finishedWork.return, error$92); + } catch (error$93) { + captureCommitPhaseError(finishedWork, finishedWork.return, error$93); } } function commitClassCallbacks(finishedWork) { @@ -7064,11 +7212,11 @@ function commitLayoutEffectOnFiber(finishedRoot, current, finishedWork) { } else try { finishedRoot.componentDidMount(); - } catch (error$93) { + } catch (error$94) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$93 + error$94 ); } else { @@ -7085,11 +7233,11 @@ function commitLayoutEffectOnFiber(finishedRoot, current, finishedWork) { current, finishedRoot.__reactInternalSnapshotBeforeUpdate ); - } catch (error$94) { + } catch (error$95) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$94 + error$95 ); } recordLayoutEffectDuration(finishedWork); @@ -7100,11 +7248,11 @@ function commitLayoutEffectOnFiber(finishedRoot, current, finishedWork) { current, finishedRoot.__reactInternalSnapshotBeforeUpdate ); - } catch (error$95) { + } catch (error$96) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$95 + error$96 ); } } @@ -7451,22 +7599,22 @@ function commitMutationEffectsOnFiber(finishedWork, root) { try { startLayoutEffectTimer(), commitHookEffectListUnmount(5, finishedWork, finishedWork.return); - } catch (error$98) { + } catch (error$99) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$98 + error$99 ); } recordLayoutEffectDuration(finishedWork); } else try { commitHookEffectListUnmount(5, finishedWork, finishedWork.return); - } catch (error$99) { + } catch (error$100) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$99 + error$100 ); } } @@ -7763,8 +7911,8 @@ function commitHookPassiveMountEffects(finishedWork, hookFlags) { } else try { commitHookEffectListMount(hookFlags, finishedWork); - } catch (error$107) { - captureCommitPhaseError(finishedWork, finishedWork.return, error$107); + } catch (error$108) { + captureCommitPhaseError(finishedWork, finishedWork.return, error$108); } } function recursivelyTraversePassiveMountEffects(root, parentFiber) { @@ -8525,13 +8673,13 @@ function renderRootSync(root, lanes) { default: (workInProgressSuspendedReason = 0), (workInProgressThrownValue = null), - throwAndUnwindWorkLoop(memoizedUpdaters, thrownValue); + throwAndUnwindWorkLoop(root, memoizedUpdaters, thrownValue); } } workLoopSync(); break; - } catch (thrownValue$108) { - handleThrow(root, thrownValue$108); + } catch (thrownValue$109) { + handleThrow(root, thrownValue$109); } while (1); lanes && root.shellSuspendCounter++; @@ -8579,7 +8727,7 @@ function renderRootConcurrent(root, lanes) { case 1: workInProgressSuspendedReason = 0; workInProgressThrownValue = null; - throwAndUnwindWorkLoop(lanes, memoizedUpdaters); + throwAndUnwindWorkLoop(root, lanes, memoizedUpdaters); break; case 2: if (isThenableResolved(memoizedUpdaters)) { @@ -8609,7 +8757,7 @@ function renderRootConcurrent(root, lanes) { replaySuspendedUnitOfWork(lanes)) : ((workInProgressSuspendedReason = 0), (workInProgressThrownValue = null), - throwAndUnwindWorkLoop(lanes, memoizedUpdaters)); + throwAndUnwindWorkLoop(root, lanes, memoizedUpdaters)); break; case 5: switch (workInProgress.tag) { @@ -8632,12 +8780,12 @@ function renderRootConcurrent(root, lanes) { } workInProgressSuspendedReason = 0; workInProgressThrownValue = null; - throwAndUnwindWorkLoop(lanes, memoizedUpdaters); + throwAndUnwindWorkLoop(root, lanes, memoizedUpdaters); break; case 6: workInProgressSuspendedReason = 0; workInProgressThrownValue = null; - throwAndUnwindWorkLoop(lanes, memoizedUpdaters); + throwAndUnwindWorkLoop(root, lanes, memoizedUpdaters); break; case 8: resetWorkInProgressStack(); @@ -8648,8 +8796,8 @@ function renderRootConcurrent(root, lanes) { } workLoopConcurrent(); break; - } catch (thrownValue$110) { - handleThrow(root, thrownValue$110); + } catch (thrownValue$111) { + handleThrow(root, thrownValue$111); } while (1); resetContextDependencies(); @@ -8744,200 +8892,63 @@ function replaySuspendedUnitOfWork(unitOfWork) { : (workInProgress = current); ReactCurrentOwner.current = null; } -function throwAndUnwindWorkLoop(unitOfWork, thrownValue) { +function throwAndUnwindWorkLoop(root, unitOfWork, thrownValue) { resetContextDependencies(); resetHooksOnUnwind(unitOfWork); thenableState$1 = null; thenableIndexCounter$1 = 0; var returnFiber = unitOfWork.return; - if (null === returnFiber || null === workInProgressRoot) - (workInProgressRootExitStatus = 1), - (workInProgressRootFatalError = thrownValue), - (workInProgress = null); - else { - try { - a: { - var root = workInProgressRoot, - value = thrownValue; - thrownValue = workInProgressRootRenderLanes; - unitOfWork.flags |= 32768; - isDevToolsPresent && restorePendingUpdaters(root, thrownValue); - if ( - null !== value && - "object" === typeof value && - "function" === typeof value.then - ) { - var wakeable = value, - tag = unitOfWork.tag; - if ( - 0 === (unitOfWork.mode & 1) && - (0 === tag || 11 === tag || 15 === tag) - ) { - var currentSource = unitOfWork.alternate; - currentSource - ? ((unitOfWork.updateQueue = currentSource.updateQueue), - (unitOfWork.memoizedState = currentSource.memoizedState), - (unitOfWork.lanes = currentSource.lanes)) - : ((unitOfWork.updateQueue = null), - (unitOfWork.memoizedState = null)); - } - var suspenseBoundary = suspenseHandlerStackCursor.current; - if (null !== suspenseBoundary) { - switch (suspenseBoundary.tag) { - case 13: - unitOfWork.mode & 1 && - (null === shellBoundary - ? renderDidSuspendDelayIfPossible() - : null === suspenseBoundary.alternate && - 0 === workInProgressRootExitStatus && - (workInProgressRootExitStatus = 3)); - suspenseBoundary.flags &= -257; - if (0 === (suspenseBoundary.mode & 1)) - if (suspenseBoundary === returnFiber) - suspenseBoundary.flags |= 65536; - else { - suspenseBoundary.flags |= 128; - unitOfWork.flags |= 131072; - unitOfWork.flags &= -52805; - if (1 === unitOfWork.tag) - if (null === unitOfWork.alternate) unitOfWork.tag = 17; - else { - var update = createUpdate(2); - update.tag = 2; - enqueueUpdate(unitOfWork, update, 2); - } - unitOfWork.lanes |= 2; - } - else - (suspenseBoundary.flags |= 65536), - (suspenseBoundary.lanes = thrownValue); - if (wakeable === noopSuspenseyCommitThenable) - suspenseBoundary.flags |= 16384; - else { - var retryQueue = suspenseBoundary.updateQueue; - null === retryQueue - ? (suspenseBoundary.updateQueue = new Set([wakeable])) - : retryQueue.add(wakeable); - suspenseBoundary.mode & 1 && - attachPingListener(root, wakeable, thrownValue); - } - break a; - case 22: - if (suspenseBoundary.mode & 1) { - suspenseBoundary.flags |= 65536; - if (wakeable === noopSuspenseyCommitThenable) - suspenseBoundary.flags |= 16384; - else { - var offscreenQueue = suspenseBoundary.updateQueue; - if (null === offscreenQueue) { - var newOffscreenQueue = { - transitions: null, - markerInstances: null, - retryQueue: new Set([wakeable]) - }; - suspenseBoundary.updateQueue = newOffscreenQueue; - } else { - var retryQueue$35 = offscreenQueue.retryQueue; - null === retryQueue$35 - ? (offscreenQueue.retryQueue = new Set([wakeable])) - : retryQueue$35.add(wakeable); - } - attachPingListener(root, wakeable, thrownValue); - } - break a; - } - } - throw Error( - "Unexpected Suspense handler tag (" + - suspenseBoundary.tag + - "). This is a bug in React." - ); - } - if (1 === root.tag) { - attachPingListener(root, wakeable, thrownValue); - renderDidSuspendDelayIfPossible(); - break a; - } else - value = Error( - "A component suspended while responding to synchronous input. This will cause the UI to be replaced with a loading indicator. To fix, updates that suspend should be wrapped with startTransition." - ); - } - root = value = createCapturedValueAtFiber(value, unitOfWork); - 4 !== workInProgressRootExitStatus && - (workInProgressRootExitStatus = 2); - null === workInProgressRootConcurrentErrors - ? (workInProgressRootConcurrentErrors = [root]) - : workInProgressRootConcurrentErrors.push(root); - root = returnFiber; - do { - switch (root.tag) { - case 3: - var errorInfo = value; - root.flags |= 65536; - thrownValue &= -thrownValue; - root.lanes |= thrownValue; - var update$jscomp$0 = createRootErrorUpdate( - root, - errorInfo, - thrownValue - ); - enqueueCapturedUpdate(root, update$jscomp$0); - break a; - case 1: - tag = value; - var ctor = root.type, - instance = root.stateNode; - if ( - 0 === (root.flags & 128) && - ("function" === typeof ctor.getDerivedStateFromError || - (null !== instance && - "function" === typeof instance.componentDidCatch && - (null === legacyErrorBoundariesThatAlreadyFailed || - !legacyErrorBoundariesThatAlreadyFailed.has(instance)))) - ) { - root.flags |= 65536; - update$jscomp$0 = thrownValue & -thrownValue; - root.lanes |= update$jscomp$0; - errorInfo = createClassErrorUpdate(root, tag, update$jscomp$0); - enqueueCapturedUpdate(root, errorInfo); - break a; - } - } - root = root.return; - } while (null !== root); - } - } catch (error) { - throw ((workInProgress = returnFiber), error); + try { + if ( + throwException( + root, + returnFiber, + unitOfWork, + thrownValue, + workInProgressRootRenderLanes + ) + ) { + workInProgressRootExitStatus = 1; + workInProgressRootFatalError = thrownValue; + workInProgress = null; + return; } - if (unitOfWork.flags & 32768) - a: { - do { - returnFiber = unwindWork(unitOfWork.alternate, unitOfWork); - if (null !== returnFiber) { - returnFiber.flags &= 32767; - workInProgress = returnFiber; - break a; - } - if (0 !== (unitOfWork.mode & 2)) { - stopProfilerTimerIfRunningAndRecordDelta(unitOfWork, !1); - returnFiber = unitOfWork.actualDuration; - for (update$jscomp$0 = unitOfWork.child; null !== update$jscomp$0; ) - (returnFiber += update$jscomp$0.actualDuration), - (update$jscomp$0 = update$jscomp$0.sibling); - unitOfWork.actualDuration = returnFiber; - } - 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); + } catch (error) { + if (null !== returnFiber) throw ((workInProgress = returnFiber), error); + workInProgressRootExitStatus = 1; + workInProgressRootFatalError = thrownValue; + workInProgress = null; + return; } + if (unitOfWork.flags & 32768) + a: { + root = unitOfWork; + do { + unitOfWork = unwindWork(root.alternate, root); + if (null !== unitOfWork) { + unitOfWork.flags &= 32767; + workInProgress = unitOfWork; + break a; + } + if (0 !== (root.mode & 2)) { + stopProfilerTimerIfRunningAndRecordDelta(root, !1); + unitOfWork = root.actualDuration; + for (thrownValue = root.child; null !== thrownValue; ) + (unitOfWork += thrownValue.actualDuration), + (thrownValue = thrownValue.sibling); + root.actualDuration = unitOfWork; + } + root = root.return; + null !== root && + ((root.flags |= 32768), + (root.subtreeFlags = 0), + (root.deletions = null)); + workInProgress = root; + } while (null !== root); + workInProgressRootExitStatus = 6; + workInProgress = null; + } + else completeUnitOfWork(unitOfWork); } function completeUnitOfWork(unitOfWork) { var completedWork = unitOfWork; @@ -9125,11 +9136,11 @@ function flushPassiveEffects() { _finishedWork$memoize = finishedWork.memoizedProps, id = _finishedWork$memoize.id, onPostCommit = _finishedWork$memoize.onPostCommit, - commitTime$91 = commitTime, + commitTime$92 = commitTime, phase = null === finishedWork.alternate ? "mount" : "update"; currentUpdateIsNested && (phase = "nested-update"); "function" === typeof onPostCommit && - onPostCommit(id, phase, passiveEffectDuration, commitTime$91); + onPostCommit(id, phase, passiveEffectDuration, commitTime$92); var parentFiber = finishedWork.return; b: for (; null !== parentFiber; ) { switch (parentFiber.tag) { @@ -10252,10 +10263,10 @@ batchedUpdatesImpl = function (fn, a) { } }; var roots = new Map(), - devToolsConfig$jscomp$inline_1132 = { + devToolsConfig$jscomp$inline_1130 = { findFiberByHostInstance: getInstanceFromNode, bundleType: 0, - version: "18.3.0-canary-575afa21", + version: "18.3.0-canary-0c38bc9b", rendererPackageName: "react-native-renderer", rendererConfig: { getInspectorDataForInstance: getInspectorDataForInstance, @@ -10285,10 +10296,10 @@ var roots = new Map(), } catch (err) {} return hook.checkDCE ? !0 : !1; })({ - bundleType: devToolsConfig$jscomp$inline_1132.bundleType, - version: devToolsConfig$jscomp$inline_1132.version, - rendererPackageName: devToolsConfig$jscomp$inline_1132.rendererPackageName, - rendererConfig: devToolsConfig$jscomp$inline_1132.rendererConfig, + bundleType: devToolsConfig$jscomp$inline_1130.bundleType, + version: devToolsConfig$jscomp$inline_1130.version, + rendererPackageName: devToolsConfig$jscomp$inline_1130.rendererPackageName, + rendererConfig: devToolsConfig$jscomp$inline_1130.rendererConfig, overrideHookState: null, overrideHookStateDeletePath: null, overrideHookStateRenamePath: null, @@ -10304,14 +10315,14 @@ var roots = new Map(), return null === fiber ? null : fiber.stateNode; }, findFiberByHostInstance: - devToolsConfig$jscomp$inline_1132.findFiberByHostInstance || + devToolsConfig$jscomp$inline_1130.findFiberByHostInstance || emptyFindFiberByHostInstance, findHostInstancesForRefresh: null, scheduleRefresh: null, scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "18.3.0-canary-575afa21" + reconcilerVersion: "18.3.0-canary-0c38bc9b" }); exports.createPortal = function (children, containerTag) { return createPortal$1( diff --git a/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactNativeRenderer-dev.fb.js b/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactNativeRenderer-dev.fb.js index 9dc389df37fac..3b09884b58edd 100644 --- a/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactNativeRenderer-dev.fb.js +++ b/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactNativeRenderer-dev.fb.js @@ -7,7 +7,7 @@ * @noflow * @nolint * @preventMunge - * @generated SignedSource<<7117023f3b40093a08a4623516c9c86b>> + * @generated SignedSource<> */ "use strict"; @@ -7142,3714 +7142,3706 @@ to return true:wantsResponderID| | } } - var UpdateState = 0; - var ReplaceState = 1; - var ForceUpdate = 2; - var CaptureUpdate = 3; // Global state that is reset at the beginning of calling `processUpdateQueue`. - // It should only be read right after calling `processUpdateQueue`, via - // `checkHasForceUpdateAfterProcessing`. + var ReactCurrentActQueue$3 = 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 hasForceUpdate = false; - var didWarnUpdateInsideUpdate; - var currentlyProcessingQueue; + var firstScheduledRoot = null; + var lastScheduledRoot = null; // Used to prevent redundant mircotasks from being scheduled. - { - didWarnUpdateInsideUpdate = false; - currentlyProcessingQueue = null; - } + 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. - function initializeUpdateQueue(fiber) { - var queue = { - baseState: fiber.memoizedState, - firstBaseUpdate: null, - lastBaseUpdate: null, - shared: { - pending: null, - lanes: NoLanes, - hiddenCallbacks: null - }, - callbacks: null - }; - fiber.updateQueue = queue; - } - function cloneUpdateQueue(current, workInProgress) { - // Clone the update queue from current. Unless it's already a clone. - var queue = workInProgress.updateQueue; - var currentQueue = current.updateQueue; + var didScheduleMicrotask_act = false; // Used to quickly bail out of flushSync if there's no sync work to do. - if (queue === currentQueue) { - var clone = { - baseState: currentQueue.baseState, - firstBaseUpdate: currentQueue.firstBaseUpdate, - lastBaseUpdate: currentQueue.lastBaseUpdate, - shared: currentQueue.shared, - callbacks: null - }; - workInProgress.updateQueue = clone; + 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$3.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$3.isBatchingLegacy && root.tag === LegacyRoot) { + // Special `act` case: Record whenever a legacy update is scheduled. + ReactCurrentActQueue$3.didScheduleLegacyUpdate = true; } } - function createUpdate(lane) { - var update = { - lane: lane, - tag: UpdateState, - payload: null, - callback: null, - next: null - }; - return update; + 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 enqueueUpdate(fiber, update, lane) { - var updateQueue = fiber.updateQueue; - if (updateQueue === null) { - // Only occurs if the fiber has been unmounted. - return null; + function flushSyncWorkAcrossRoots_impl(onlyLegacy) { + if (isFlushingWork) { + // Prevent reentrancy. + // TODO: Is this overly defensive? The callers must check the execution + // context first regardless. + return; } - var sharedQueue = updateQueue.shared; + if (!mightHavePendingSyncWork) { + // Fast path. There's no sync work to do. + return; + } // There may or may not be synchronous work scheduled. Let's check. - { - if ( - currentlyProcessingQueue === sharedQueue && - !didWarnUpdateInsideUpdate - ) { - var componentName = getComponentNameFromFiber(fiber); + var didPerformSomeWork; + var errors = null; + isFlushingWork = true; - error( - "An update (setState, replaceState, or forceUpdate) was scheduled " + - "from inside an update function. Update functions should be pure, " + - "with zero side-effects. Consider using componentDidUpdate or a " + - "callback.\n\nPlease update the following component: %s", - componentName - ); + do { + didPerformSomeWork = false; + var root = firstScheduledRoot; - didWarnUpdateInsideUpdate = true; - } - } + while (root !== null) { + if (onlyLegacy && root.tag !== LegacyRoot); + else { + var workInProgressRoot = getWorkInProgressRoot(); + var workInProgressRootRenderLanes = + getWorkInProgressRootRenderLanes(); + var nextLanes = getNextLanes( + root, + root === workInProgressRoot + ? workInProgressRootRenderLanes + : NoLanes + ); - if (isUnsafeClassRenderPhaseUpdate()) { - // This is an unsafe render phase update. Add directly to the update - // queue so we can process it immediately during the current render. - var pending = sharedQueue.pending; + if (includesSyncLane(nextLanes)) { + // This root has pending sync work. Flush it now. + try { + didPerformSomeWork = true; + performSyncWorkOnRoot(root, nextLanes); + } catch (error) { + // Collect errors so we can rethrow them at the end + if (errors === null) { + errors = [error]; + } else { + errors.push(error); + } + } + } + } - if (pending === null) { - // This is the first update. Create a circular list. - update.next = update; - } else { - update.next = pending.next; - pending.next = update; + root = root.next; } + } while (didPerformSomeWork); - sharedQueue.pending = update; // Update the childLanes even though we're most likely already rendering - // this fiber. This is for backwards compatibility in the case where you - // update a different component during render phase than the one that is - // currently renderings (a pattern that is accompanied by a warning). + 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. - return unsafe_markUpdateLaneFromFiberToRoot(fiber, lane); - } else { - return enqueueConcurrentClassUpdate(fiber, sharedQueue, update, lane); + 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 entangleTransitions(root, fiber, lane) { - var updateQueue = fiber.updateQueue; - if (updateQueue === null) { - // Only occurs if the fiber has been unmounted. - return; - } + function throwError(error) { + throw error; + } - var sharedQueue = updateQueue.shared; + function processRootScheduleInMicrotask() { + // This function is always called inside a microtask. It should never be + // called synchronously. + didScheduleMicrotask = false; - if (isTransitionLane(lane)) { - var queueLanes = sharedQueue.lanes; // If any entangled lanes are no longer pending on the root, then they must - // have finished. We can remove them from the shared queue, which represents - // a superset of the actually pending lanes. In some cases we may entangle - // more than we need to, but that's OK. In fact it's worse if we *don't* - // entangle when we should. + { + didScheduleMicrotask_act = false; + } // We'll recompute this as we iterate through all the roots and schedule them. - queueLanes = intersectLanes(queueLanes, root.pendingLanes); // Entangle the new transition lane with the other transition lanes. + mightHavePendingSyncWork = false; + var currentTime = now$1(); + var prev = null; + var root = firstScheduledRoot; - var newQueueLanes = mergeLanes(queueLanes, lane); - sharedQueue.lanes = newQueueLanes; // Even if queue.lanes already include lane, we don't know for certain if - // the lane finished since the last time we entangled it. So we need to - // entangle it again, just to be sure. + while (root !== null) { + var next = root.next; - markRootEntangled(root, newQueueLanes); - } - } - function enqueueCapturedUpdate(workInProgress, capturedUpdate) { - // Captured updates are updates that are thrown by a child during the render - // phase. They should be discarded if the render is aborted. Therefore, - // we should only put them on the work-in-progress queue, not the current one. - var queue = workInProgress.updateQueue; // Check if the work-in-progress queue is a clone. - - var current = workInProgress.alternate; - - if (current !== null) { - var currentQueue = current.updateQueue; - - if (queue === currentQueue) { - // The work-in-progress queue is the same as current. This happens when - // we bail out on a parent fiber that then captures an error thrown by - // a child. Since we want to append the update only to the work-in - // -progress queue, we need to clone the updates. We usually clone during - // processUpdateQueue, but that didn't happen in this case because we - // skipped over the parent when we bailed out. - var newFirst = null; - var newLast = null; - var firstBaseUpdate = queue.firstBaseUpdate; - - if (firstBaseUpdate !== null) { - // Loop through the updates and clone them. - var update = firstBaseUpdate; - - do { - var clone = { - lane: update.lane, - tag: update.tag, - payload: update.payload, - // When this update is rebased, we should not fire its - // callback again. - callback: null, - next: null - }; + if ( + currentEventTransitionLane !== NoLane && + shouldAttemptEagerTransition() + ) { + // A transition was scheduled during an event, but we're going to try to + // render it synchronously anyway. We do this during a popstate event to + // preserve the scroll position of the previous page. + upgradePendingLaneToSync(root, currentEventTransitionLane); + } - if (newLast === null) { - newFirst = newLast = clone; - } else { - newLast.next = clone; - newLast = clone; - } // $FlowFixMe[incompatible-type] we bail out when we get a null + var nextLanes = scheduleTaskForRootDuringMicrotask(root, currentTime); - update = update.next; - } while (update !== null); // Append the captured update the end of the cloned list. + 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 (newLast === null) { - newFirst = newLast = capturedUpdate; - } else { - newLast.next = capturedUpdate; - newLast = capturedUpdate; - } + if (prev === null) { + // This is the new head of the list + firstScheduledRoot = next; } else { - // There are no base updates. - newFirst = newLast = capturedUpdate; + prev.next = next; } - queue = { - baseState: currentQueue.baseState, - firstBaseUpdate: newFirst, - lastBaseUpdate: newLast, - shared: currentQueue.shared, - callbacks: currentQueue.callbacks - }; - workInProgress.updateQueue = queue; - return; - } - } // Append the update to the end of the list. + 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; - var lastBaseUpdate = queue.lastBaseUpdate; + if (includesSyncLane(nextLanes)) { + mightHavePendingSyncWork = true; + } + } - if (lastBaseUpdate === null) { - queue.firstBaseUpdate = capturedUpdate; - } else { - lastBaseUpdate.next = capturedUpdate; + root = next; } - queue.lastBaseUpdate = capturedUpdate; - } - - function getStateFromUpdate( - workInProgress, - queue, - update, - prevState, - nextProps, - instance - ) { - switch (update.tag) { - case ReplaceState: { - var payload = update.payload; - - if (typeof payload === "function") { - // Updater function - { - enterDisallowedContextReadInDEV(); - } - - var nextState = payload.call(instance, prevState, nextProps); - - { - if (workInProgress.mode & StrictLegacyMode) { - setIsStrictModeForDevtools(true); + 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. - try { - payload.call(instance, prevState, nextProps); - } finally { - setIsStrictModeForDevtools(false); - } - } + flushSyncWorkOnAllRoots(); + } - exitDisallowedContextReadInDEV(); - } + 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. - return nextState; - } // State object + var workInProgressRoot = getWorkInProgressRoot(); + var workInProgressRootRenderLanes = getWorkInProgressRootRenderLanes(); + var nextLanes = getNextLanes( + root, + root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes + ); + var existingCallbackNode = root.callbackNode; - return payload; + 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); } - case CaptureUpdate: { - workInProgress.flags = - (workInProgress.flags & ~ShouldCapture) | DidCapture; + 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); } - // Intentional fallthrough - case UpdateState: { - var _payload = update.payload; - var partialState; + 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 (typeof _payload === "function") { - // Updater function - { - enterDisallowedContextReadInDEV(); - } + 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$3.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); + } - partialState = _payload.call(instance, prevState, nextProps); + var schedulerPriorityLevel; - { - if (workInProgress.mode & StrictLegacyMode) { - setIsStrictModeForDevtools(true); + switch (lanesToEventPriority(nextLanes)) { + case DiscreteEventPriority: + schedulerPriorityLevel = ImmediatePriority; + break; - try { - _payload.call(instance, prevState, nextProps); - } finally { - setIsStrictModeForDevtools(false); - } - } + case ContinuousEventPriority: + schedulerPriorityLevel = UserBlockingPriority; + break; - exitDisallowedContextReadInDEV(); - } - } else { - // Partial state object - partialState = _payload; - } + case DefaultEventPriority: + schedulerPriorityLevel = NormalPriority; + break; - if (partialState === null || partialState === undefined) { - // Null and undefined are treated as no-ops. - return prevState; - } // Merge the partial state and the previous state. + case IdleEventPriority: + schedulerPriorityLevel = IdlePriority; + break; - return assign({}, prevState, partialState); + default: + schedulerPriorityLevel = NormalPriority; + break; } - case ForceUpdate: { - hasForceUpdate = true; - return prevState; - } + var newCallbackNode = scheduleCallback$1( + schedulerPriorityLevel, + performConcurrentWorkOnRoot.bind(null, root) + ); + root.callbackPriority = newCallbackPriority; + root.callbackNode = newCallbackNode; + return newCallbackPriority; } - - return prevState; } - function processUpdateQueue(workInProgress, props, instance, renderLanes) { - // This is always non-null on a ClassComponent or HostRoot - var queue = workInProgress.updateQueue; - hasForceUpdate = false; + 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()); - { - currentlyProcessingQueue = queue.shared; + if (root.callbackNode === originalCallbackNode) { + // The task node scheduled for this root is the same one that's + // currently executed. Need to return a continuation. + return performConcurrentWorkOnRoot.bind(null, root); } - var firstBaseUpdate = queue.firstBaseUpdate; - var lastBaseUpdate = queue.lastBaseUpdate; // Check if there are pending updates. If so, transfer them to the base queue. + return null; + } + var fakeActCallbackNode$1 = {}; - var pendingQueue = queue.shared.pending; + function scheduleCallback$1(priorityLevel, callback) { + if (ReactCurrentActQueue$3.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$3.current.push(callback); + return fakeActCallbackNode$1; + } else { + return scheduleCallback$2(priorityLevel, callback); + } + } - if (pendingQueue !== null) { - queue.shared.pending = null; // The pending queue is circular. Disconnect the pointer between first - // and last so that it's non-circular. + function cancelCallback(callbackNode) { + if (callbackNode === fakeActCallbackNode$1); + else if (callbackNode !== null) { + cancelCallback$1(callbackNode); + } + } - var lastPendingUpdate = pendingQueue; - var firstPendingUpdate = lastPendingUpdate.next; - lastPendingUpdate.next = null; // Append pending updates to base queue + function scheduleImmediateTask(cb) { + if (ReactCurrentActQueue$3.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$3.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 (lastBaseUpdate === null) { - firstBaseUpdate = firstPendingUpdate; - } else { - lastBaseUpdate.next = firstPendingUpdate; - } + { + // If microtasks are not supported, use Scheduler. + scheduleCallback$2(ImmediatePriority, cb); + } + } - lastBaseUpdate = lastPendingUpdate; // If there's a current queue, and it's different from the base queue, then - // we need to transfer the updates to that queue, too. Because the base - // queue is a singly-linked list with no cycles, we can append to both - // lists and take advantage of structural sharing. - // TODO: Pass `current` as argument + 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(); + } - var current = workInProgress.alternate; + return currentEventTransitionLane; + } - if (current !== null) { - // This is always non-null on a ClassComponent or HostRoot - var currentQueue = current.updateQueue; - var currentLastBaseUpdate = currentQueue.lastBaseUpdate; + // transition updates that occur while the async action is still in progress + // are treated as part of the action. + // + // The ideal behavior would be to treat each async function as an independent + // action. However, without a mechanism like AsyncContext, we can't tell which + // action an update corresponds to. So instead, we entangle them all into one. + // The listeners to notify once the entangled scope completes. - if (currentLastBaseUpdate !== lastBaseUpdate) { - if (currentLastBaseUpdate === null) { - currentQueue.firstBaseUpdate = firstPendingUpdate; - } else { - currentLastBaseUpdate.next = firstPendingUpdate; - } + var currentEntangledListeners = null; // The number of pending async actions in the entangled scope. - currentQueue.lastBaseUpdate = lastPendingUpdate; + var currentEntangledPendingCount = 0; // The transition lane shared by all updates in the entangled scope. + + var currentEntangledLane = NoLane; // A thenable that resolves when the entangled scope completes. It does not + // resolve to a particular value because it's only used for suspending the UI + // until the async action scope has completed. + + var currentEntangledActionThenable = null; + function entangleAsyncAction(thenable) { + // `thenable` is the return value of the async action scope function. Create + // a combined thenable that resolves once every entangled scope function + // has finished. + if (currentEntangledListeners === null) { + // There's no outer async action scope. Create a new one. + var entangledListeners = (currentEntangledListeners = []); + currentEntangledPendingCount = 0; + currentEntangledLane = requestTransitionLane(); + var entangledThenable = { + status: "pending", + value: undefined, + then: function (resolve) { + entangledListeners.push(resolve); } - } - } // These values may change as we process the queue. + }; + currentEntangledActionThenable = entangledThenable; + } - if (firstBaseUpdate !== null) { - // Iterate through the list of updates to compute the result. - var newState = queue.baseState; // TODO: Don't need to accumulate this. Instead, we can remove renderLanes - // from the original lanes. + currentEntangledPendingCount++; + thenable.then(pingEngtangledActionScope, pingEngtangledActionScope); + return thenable; + } - var newLanes = NoLanes; - var newBaseState = null; - var newFirstBaseUpdate = null; - var newLastBaseUpdate = null; - var update = firstBaseUpdate; + function pingEngtangledActionScope() { + if ( + currentEntangledListeners !== null && + --currentEntangledPendingCount === 0 + ) { + // All the actions have finished. Close the entangled async action scope + // and notify all the listeners. + if (currentEntangledActionThenable !== null) { + var fulfilledThenable = currentEntangledActionThenable; + fulfilledThenable.status = "fulfilled"; + } - do { - // An extra OffscreenLane bit is added to updates that were made to - // a hidden tree, so that we can distinguish them from updates that were - // already there when the tree was hidden. - var updateLane = removeLanes(update.lane, OffscreenLane); - var isHiddenUpdate = updateLane !== update.lane; // Check if this update was made while the tree was hidden. If so, then - // it's not a "base" update and we should disregard the extra base lanes - // that were added to renderLanes when we entered the Offscreen tree. + var listeners = currentEntangledListeners; + currentEntangledListeners = null; + currentEntangledLane = NoLane; + currentEntangledActionThenable = null; - var shouldSkipUpdate = isHiddenUpdate - ? !isSubsetOfLanes(getWorkInProgressRootRenderLanes(), updateLane) - : !isSubsetOfLanes(renderLanes, updateLane); + for (var i = 0; i < listeners.length; i++) { + var listener = listeners[i]; + listener(); + } + } + } - if (shouldSkipUpdate) { - // Priority is insufficient. Skip this update. If this is the first - // skipped update, the previous update/state is the new base - // update/state. - var clone = { - lane: updateLane, - tag: update.tag, - payload: update.payload, - callback: update.callback, - next: null - }; + function chainThenableValue(thenable, result) { + // Equivalent to: Promise.resolve(thenable).then(() => result), except we can + // cheat a bit since we know that that this thenable is only ever consumed + // by React. + // + // We don't technically require promise support on the client yet, hence this + // extra code. + var listeners = []; + var thenableWithOverride = { + status: "pending", + value: null, + reason: null, + then: function (resolve) { + listeners.push(resolve); + } + }; + thenable.then( + function (value) { + var fulfilledThenable = thenableWithOverride; + fulfilledThenable.status = "fulfilled"; + fulfilledThenable.value = result; - if (newLastBaseUpdate === null) { - newFirstBaseUpdate = newLastBaseUpdate = clone; - newBaseState = newState; - } else { - newLastBaseUpdate = newLastBaseUpdate.next = clone; - } // Update the remaining priority in the queue. + for (var i = 0; i < listeners.length; i++) { + var listener = listeners[i]; + listener(result); + } + }, + function (error) { + var rejectedThenable = thenableWithOverride; + rejectedThenable.status = "rejected"; + rejectedThenable.reason = error; - newLanes = mergeLanes(newLanes, updateLane); - } else { - // This update does have sufficient priority. - if (newLastBaseUpdate !== null) { - var _clone = { - // This update is going to be committed so we never want uncommit - // it. Using NoLane works because 0 is a subset of all bitmasks, so - // this will never be skipped by the check above. - lane: NoLane, - tag: update.tag, - payload: update.payload, - // When this update is rebased, we should not fire its - // callback again. - callback: null, - next: null - }; - newLastBaseUpdate = newLastBaseUpdate.next = _clone; - } // Process this update. + for (var i = 0; i < listeners.length; i++) { + var listener = listeners[i]; // This is a perf hack where we call the `onFulfill` ping function + // instead of `onReject`, because we know that React is the only + // consumer of these promises, and it passes the same listener to both. + // We also know that it will read the error directly off the + // `.reason` field. - newState = getStateFromUpdate( - workInProgress, - queue, - update, - newState, - props, - instance - ); - var callback = update.callback; + listener(undefined); + } + } + ); + return thenableWithOverride; + } + function peekEntangledActionLane() { + return currentEntangledLane; + } + function peekEntangledActionThenable() { + return currentEntangledActionThenable; + } - if (callback !== null) { - workInProgress.flags |= Callback; + var UpdateState = 0; + var ReplaceState = 1; + var ForceUpdate = 2; + var CaptureUpdate = 3; // Global state that is reset at the beginning of calling `processUpdateQueue`. + // It should only be read right after calling `processUpdateQueue`, via + // `checkHasForceUpdateAfterProcessing`. - if (isHiddenUpdate) { - workInProgress.flags |= Visibility; - } + var hasForceUpdate = false; + var didWarnUpdateInsideUpdate; + var currentlyProcessingQueue; - var callbacks = queue.callbacks; + { + didWarnUpdateInsideUpdate = false; + currentlyProcessingQueue = null; + } - if (callbacks === null) { - queue.callbacks = [callback]; - } else { - callbacks.push(callback); - } - } - } // $FlowFixMe[incompatible-type] we bail out when we get a null - - update = update.next; - - if (update === null) { - pendingQueue = queue.shared.pending; - - if (pendingQueue === null) { - break; - } else { - // An update was scheduled from inside a reducer. Add the new - // pending updates to the end of the list and keep processing. - var _lastPendingUpdate = pendingQueue; // Intentionally unsound. Pending updates form a circular list, but we - // unravel them when transferring them to the base queue. - - var _firstPendingUpdate = _lastPendingUpdate.next; - _lastPendingUpdate.next = null; - update = _firstPendingUpdate; - queue.lastBaseUpdate = _lastPendingUpdate; - queue.shared.pending = null; - } - } - } while (true); - - if (newLastBaseUpdate === null) { - newBaseState = newState; - } - - queue.baseState = newBaseState; - queue.firstBaseUpdate = newFirstBaseUpdate; - queue.lastBaseUpdate = newLastBaseUpdate; - - if (firstBaseUpdate === null) { - // `queue.lanes` is used for entangling transitions. We can set it back to - // zero once the queue is empty. - queue.shared.lanes = NoLanes; - } // Set the remaining expiration time to be whatever is remaining in the queue. - // This should be fine because the only two other things that contribute to - // expiration time are props and context. We're already in the middle of the - // begin phase by the time we start processing the queue, so we've already - // dealt with the props. Context in components that specify - // shouldComponentUpdate is tricky; but we'll have to account for - // that regardless. - - markSkippedUpdateLanes(newLanes); - workInProgress.lanes = newLanes; - workInProgress.memoizedState = newState; - } + function initializeUpdateQueue(fiber) { + var queue = { + baseState: fiber.memoizedState, + firstBaseUpdate: null, + lastBaseUpdate: null, + shared: { + pending: null, + lanes: NoLanes, + hiddenCallbacks: null + }, + callbacks: null + }; + fiber.updateQueue = queue; + } + function cloneUpdateQueue(current, workInProgress) { + // Clone the update queue from current. Unless it's already a clone. + var queue = workInProgress.updateQueue; + var currentQueue = current.updateQueue; - { - currentlyProcessingQueue = null; + if (queue === currentQueue) { + var clone = { + baseState: currentQueue.baseState, + firstBaseUpdate: currentQueue.firstBaseUpdate, + lastBaseUpdate: currentQueue.lastBaseUpdate, + shared: currentQueue.shared, + callbacks: null + }; + workInProgress.updateQueue = clone; } } + function createUpdate(lane) { + var update = { + lane: lane, + tag: UpdateState, + payload: null, + callback: null, + next: null + }; + return update; + } + function enqueueUpdate(fiber, update, lane) { + var updateQueue = fiber.updateQueue; - function callCallback(callback, context) { - if (typeof callback !== "function") { - throw new Error( - "Invalid argument passed as callback. Expected a function. Instead " + - ("received: " + callback) - ); + if (updateQueue === null) { + // Only occurs if the fiber has been unmounted. + return null; } - callback.call(context); - } + var sharedQueue = updateQueue.shared; - function resetHasForceUpdateBeforeProcessing() { - hasForceUpdate = false; - } - function checkHasForceUpdateAfterProcessing() { - return hasForceUpdate; - } - function deferHiddenCallbacks(updateQueue) { - // When an update finishes on a hidden component, its callback should not - // be fired until/unless the component is made visible again. Stash the - // callback on the shared queue object so it can be fired later. - var newHiddenCallbacks = updateQueue.callbacks; + { + if ( + currentlyProcessingQueue === sharedQueue && + !didWarnUpdateInsideUpdate + ) { + var componentName = getComponentNameFromFiber(fiber); - if (newHiddenCallbacks !== null) { - var existingHiddenCallbacks = updateQueue.shared.hiddenCallbacks; + error( + "An update (setState, replaceState, or forceUpdate) was scheduled " + + "from inside an update function. Update functions should be pure, " + + "with zero side-effects. Consider using componentDidUpdate or a " + + "callback.\n\nPlease update the following component: %s", + componentName + ); - if (existingHiddenCallbacks === null) { - updateQueue.shared.hiddenCallbacks = newHiddenCallbacks; - } else { - updateQueue.shared.hiddenCallbacks = - existingHiddenCallbacks.concat(newHiddenCallbacks); + didWarnUpdateInsideUpdate = true; } } - } - function commitHiddenCallbacks(updateQueue, context) { - // This component is switching from hidden -> visible. Commit any callbacks - // that were previously deferred. - var hiddenCallbacks = updateQueue.shared.hiddenCallbacks; - if (hiddenCallbacks !== null) { - updateQueue.shared.hiddenCallbacks = null; + if (isUnsafeClassRenderPhaseUpdate()) { + // This is an unsafe render phase update. Add directly to the update + // queue so we can process it immediately during the current render. + var pending = sharedQueue.pending; - for (var i = 0; i < hiddenCallbacks.length; i++) { - var callback = hiddenCallbacks[i]; - callCallback(callback, context); + if (pending === null) { + // This is the first update. Create a circular list. + update.next = update; + } else { + update.next = pending.next; + pending.next = update; } - } - } - function commitCallbacks(updateQueue, context) { - var callbacks = updateQueue.callbacks; - if (callbacks !== null) { - updateQueue.callbacks = null; + sharedQueue.pending = update; // Update the childLanes even though we're most likely already rendering + // this fiber. This is for backwards compatibility in the case where you + // update a different component during render phase than the one that is + // currently renderings (a pattern that is accompanied by a warning). - for (var i = 0; i < callbacks.length; i++) { - var callback = callbacks[i]; - callCallback(callback, context); - } + return unsafe_markUpdateLaneFromFiberToRoot(fiber, lane); + } else { + return enqueueConcurrentClassUpdate(fiber, sharedQueue, update, lane); } } + function entangleTransitions(root, fiber, lane) { + var updateQueue = fiber.updateQueue; - /** - * Performs equality by iterating through keys on an object and returning false - * when any key has values which are not strictly equal between the arguments. - * Returns true when the values of all keys are strictly equal. - */ - - function shallowEqual(objA, objB) { - if (objectIs(objA, objB)) { - return true; + if (updateQueue === null) { + // Only occurs if the fiber has been unmounted. + return; } - if ( - typeof objA !== "object" || - objA === null || - typeof objB !== "object" || - objB === null - ) { - return false; - } + var sharedQueue = updateQueue.shared; - var keysA = Object.keys(objA); - var keysB = Object.keys(objB); + if (isTransitionLane(lane)) { + var queueLanes = sharedQueue.lanes; // If any entangled lanes are no longer pending on the root, then they must + // have finished. We can remove them from the shared queue, which represents + // a superset of the actually pending lanes. In some cases we may entangle + // more than we need to, but that's OK. In fact it's worse if we *don't* + // entangle when we should. - if (keysA.length !== keysB.length) { - return false; - } // Test for A's keys different from B. + queueLanes = intersectLanes(queueLanes, root.pendingLanes); // Entangle the new transition lane with the other transition lanes. - for (var i = 0; i < keysA.length; i++) { - var currentKey = keysA[i]; + var newQueueLanes = mergeLanes(queueLanes, lane); + sharedQueue.lanes = newQueueLanes; // Even if queue.lanes already include lane, we don't know for certain if + // the lane finished since the last time we entangled it. So we need to + // entangle it again, just to be sure. - if ( - !hasOwnProperty.call(objB, currentKey) || // $FlowFixMe[incompatible-use] lost refinement of `objB` - !objectIs(objA[currentKey], objB[currentKey]) - ) { - return false; - } + markRootEntangled(root, newQueueLanes); } - - return true; } + function enqueueCapturedUpdate(workInProgress, capturedUpdate) { + // Captured updates are updates that are thrown by a child during the render + // phase. They should be discarded if the render is aborted. Therefore, + // we should only put them on the work-in-progress queue, not the current one. + var queue = workInProgress.updateQueue; // Check if the work-in-progress queue is a clone. - function describeFiber(fiber) { - var owner = fiber._debugOwner ? fiber._debugOwner.type : null; - var source = fiber._debugSource; - - switch (fiber.tag) { - case HostHoistable: - case HostSingleton: - case HostComponent: - return describeBuiltInComponentFrame(fiber.type, source, owner); + var current = workInProgress.alternate; - case LazyComponent: - return describeBuiltInComponentFrame("Lazy", source, owner); + if (current !== null) { + var currentQueue = current.updateQueue; - case SuspenseComponent: - return describeBuiltInComponentFrame("Suspense", source, owner); + if (queue === currentQueue) { + // The work-in-progress queue is the same as current. This happens when + // we bail out on a parent fiber that then captures an error thrown by + // a child. Since we want to append the update only to the work-in + // -progress queue, we need to clone the updates. We usually clone during + // processUpdateQueue, but that didn't happen in this case because we + // skipped over the parent when we bailed out. + var newFirst = null; + var newLast = null; + var firstBaseUpdate = queue.firstBaseUpdate; - case SuspenseListComponent: - return describeBuiltInComponentFrame("SuspenseList", source, owner); + if (firstBaseUpdate !== null) { + // Loop through the updates and clone them. + var update = firstBaseUpdate; - case FunctionComponent: - case IndeterminateComponent: - case SimpleMemoComponent: - return describeFunctionComponentFrame(fiber.type, source, owner); + do { + var clone = { + lane: update.lane, + tag: update.tag, + payload: update.payload, + // When this update is rebased, we should not fire its + // callback again. + callback: null, + next: null + }; - case ForwardRef: - return describeFunctionComponentFrame( - fiber.type.render, - source, - owner - ); + if (newLast === null) { + newFirst = newLast = clone; + } else { + newLast.next = clone; + newLast = clone; + } // $FlowFixMe[incompatible-type] we bail out when we get a null - case ClassComponent: - return describeClassComponentFrame(fiber.type, source, owner); + update = update.next; + } while (update !== null); // Append the captured update the end of the cloned list. - default: - return ""; + if (newLast === null) { + newFirst = newLast = capturedUpdate; + } else { + newLast.next = capturedUpdate; + newLast = capturedUpdate; + } + } else { + // There are no base updates. + newFirst = newLast = capturedUpdate; + } + + queue = { + baseState: currentQueue.baseState, + firstBaseUpdate: newFirst, + lastBaseUpdate: newLast, + shared: currentQueue.shared, + callbacks: currentQueue.callbacks + }; + workInProgress.updateQueue = queue; + return; + } + } // Append the update to the end of the list. + + var lastBaseUpdate = queue.lastBaseUpdate; + + if (lastBaseUpdate === null) { + queue.firstBaseUpdate = capturedUpdate; + } else { + lastBaseUpdate.next = capturedUpdate; } + + queue.lastBaseUpdate = capturedUpdate; } - function getStackByFiberInDevAndProd(workInProgress) { - try { - var info = ""; - var node = workInProgress; + function getStateFromUpdate( + workInProgress, + queue, + update, + prevState, + nextProps, + instance + ) { + switch (update.tag) { + case ReplaceState: { + var payload = update.payload; - do { - info += describeFiber(node); // $FlowFixMe[incompatible-type] we bail out when we get a null + if (typeof payload === "function") { + // Updater function + { + enterDisallowedContextReadInDEV(); + } - node = node.return; - } while (node); + var nextState = payload.call(instance, prevState, nextProps); - return info; - } catch (x) { - return "\nError generating stack: " + x.message + "\n" + x.stack; - } - } + { + if (workInProgress.mode & StrictLegacyMode) { + setIsStrictModeForDevtools(true); - var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; - var current = null; - var isRendering = false; - function getCurrentFiberOwnerNameInDevOrNull() { - { - if (current === null) { - return null; + try { + payload.call(instance, prevState, nextProps); + } finally { + setIsStrictModeForDevtools(false); + } + } + + exitDisallowedContextReadInDEV(); + } + + return nextState; + } // State object + + return payload; } - var owner = current._debugOwner; + case CaptureUpdate: { + workInProgress.flags = + (workInProgress.flags & ~ShouldCapture) | DidCapture; + } + // Intentional fallthrough - if (owner !== null && typeof owner !== "undefined") { - return getComponentNameFromFiber(owner); + case UpdateState: { + var _payload = update.payload; + var partialState; + + if (typeof _payload === "function") { + // Updater function + { + enterDisallowedContextReadInDEV(); + } + + partialState = _payload.call(instance, prevState, nextProps); + + { + if (workInProgress.mode & StrictLegacyMode) { + setIsStrictModeForDevtools(true); + + try { + _payload.call(instance, prevState, nextProps); + } finally { + setIsStrictModeForDevtools(false); + } + } + + exitDisallowedContextReadInDEV(); + } + } else { + // Partial state object + partialState = _payload; + } + + if (partialState === null || partialState === undefined) { + // Null and undefined are treated as no-ops. + return prevState; + } // Merge the partial state and the previous state. + + return assign({}, prevState, partialState); + } + + case ForceUpdate: { + hasForceUpdate = true; + return prevState; } } - return null; + return prevState; } - function getCurrentFiberStackInDev() { - { - if (current === null) { - return ""; - } // Safe because if current fiber exists, we are reconciling, - // and it is guaranteed to be the work-in-progress version. + var didReadFromEntangledAsyncAction = false; // Each call to processUpdateQueue should be accompanied by a call to this. It's + // only in a separate function because in updateHostRoot, it must happen after + // all the context stacks have been pushed to, to prevent a stack mismatch. A + // bit unfortunate. - return getStackByFiberInDevAndProd(current); - } - } + function suspendIfUpdateReadFromEntangledAsyncAction() { + // Check if this update is part of a pending async action. If so, we'll + // need to suspend until the action has finished, so that it's batched + // together with future updates in the same action. + // TODO: Once we support hooks inside useMemo (or an equivalent + // memoization boundary like Forget), hoist this logic so that it only + // suspends if the memo boundary produces a new value. + if (didReadFromEntangledAsyncAction) { + var entangledActionThenable = peekEntangledActionThenable(); - function resetCurrentFiber() { - { - ReactDebugCurrentFrame.getCurrentStack = null; - current = null; - isRendering = false; - } - } - function setCurrentFiber(fiber) { - { - ReactDebugCurrentFrame.getCurrentStack = - fiber === null ? null : getCurrentFiberStackInDev; - current = fiber; - isRendering = false; - } - } - function getCurrentFiber() { - { - return current; + if (entangledActionThenable !== null) { + // TODO: Instead of the throwing the thenable directly, throw a + // special object like `use` does so we can detect if it's captured + // by userspace. + throw entangledActionThenable; + } } } - function setIsRendering(rendering) { + function processUpdateQueue(workInProgress, props, instance, renderLanes) { + didReadFromEntangledAsyncAction = false; // This is always non-null on a ClassComponent or HostRoot + + var queue = workInProgress.updateQueue; + hasForceUpdate = false; + { - isRendering = rendering; + currentlyProcessingQueue = queue.shared; } - } - var ReactStrictModeWarnings = { - recordUnsafeLifecycleWarnings: function (fiber, instance) {}, - flushPendingUnsafeLifecycleWarnings: function () {}, - recordLegacyContextWarning: function (fiber, instance) {}, - flushLegacyContextWarning: function () {}, - discardPendingWarnings: function () {} - }; + var firstBaseUpdate = queue.firstBaseUpdate; + var lastBaseUpdate = queue.lastBaseUpdate; // Check if there are pending updates. If so, transfer them to the base queue. - { - var findStrictRoot = function (fiber) { - var maybeStrictRoot = null; - var node = fiber; + var pendingQueue = queue.shared.pending; - while (node !== null) { - if (node.mode & StrictLegacyMode) { - maybeStrictRoot = node; - } + if (pendingQueue !== null) { + queue.shared.pending = null; // The pending queue is circular. Disconnect the pointer between first + // and last so that it's non-circular. - node = node.return; + var lastPendingUpdate = pendingQueue; + var firstPendingUpdate = lastPendingUpdate.next; + lastPendingUpdate.next = null; // Append pending updates to base queue + + if (lastBaseUpdate === null) { + firstBaseUpdate = firstPendingUpdate; + } else { + lastBaseUpdate.next = firstPendingUpdate; } - return maybeStrictRoot; - }; + lastBaseUpdate = lastPendingUpdate; // If there's a current queue, and it's different from the base queue, then + // we need to transfer the updates to that queue, too. Because the base + // queue is a singly-linked list with no cycles, we can append to both + // lists and take advantage of structural sharing. + // TODO: Pass `current` as argument - var setToSortedString = function (set) { - var array = []; - set.forEach(function (value) { - array.push(value); - }); - return array.sort().join(", "); - }; + var current = workInProgress.alternate; - var pendingComponentWillMountWarnings = []; - var pendingUNSAFE_ComponentWillMountWarnings = []; - var pendingComponentWillReceivePropsWarnings = []; - var pendingUNSAFE_ComponentWillReceivePropsWarnings = []; - var pendingComponentWillUpdateWarnings = []; - var pendingUNSAFE_ComponentWillUpdateWarnings = []; // Tracks components we have already warned about. - - var didWarnAboutUnsafeLifecycles = new Set(); - - ReactStrictModeWarnings.recordUnsafeLifecycleWarnings = function ( - fiber, - instance - ) { - // Dedupe strategy: Warn once per component. - if (didWarnAboutUnsafeLifecycles.has(fiber.type)) { - return; - } - - if ( - typeof instance.componentWillMount === "function" && // Don't warn about react-lifecycles-compat polyfilled components. - instance.componentWillMount.__suppressDeprecationWarning !== true - ) { - pendingComponentWillMountWarnings.push(fiber); - } + if (current !== null) { + // This is always non-null on a ClassComponent or HostRoot + var currentQueue = current.updateQueue; + var currentLastBaseUpdate = currentQueue.lastBaseUpdate; - if ( - fiber.mode & StrictLegacyMode && - typeof instance.UNSAFE_componentWillMount === "function" - ) { - pendingUNSAFE_ComponentWillMountWarnings.push(fiber); - } + if (currentLastBaseUpdate !== lastBaseUpdate) { + if (currentLastBaseUpdate === null) { + currentQueue.firstBaseUpdate = firstPendingUpdate; + } else { + currentLastBaseUpdate.next = firstPendingUpdate; + } - if ( - typeof instance.componentWillReceiveProps === "function" && - instance.componentWillReceiveProps.__suppressDeprecationWarning !== - true - ) { - pendingComponentWillReceivePropsWarnings.push(fiber); + currentQueue.lastBaseUpdate = lastPendingUpdate; + } } + } // These values may change as we process the queue. - if ( - fiber.mode & StrictLegacyMode && - typeof instance.UNSAFE_componentWillReceiveProps === "function" - ) { - pendingUNSAFE_ComponentWillReceivePropsWarnings.push(fiber); - } + if (firstBaseUpdate !== null) { + // Iterate through the list of updates to compute the result. + var newState = queue.baseState; // TODO: Don't need to accumulate this. Instead, we can remove renderLanes + // from the original lanes. - if ( - typeof instance.componentWillUpdate === "function" && - instance.componentWillUpdate.__suppressDeprecationWarning !== true - ) { - pendingComponentWillUpdateWarnings.push(fiber); - } + var newLanes = NoLanes; + var newBaseState = null; + var newFirstBaseUpdate = null; + var newLastBaseUpdate = null; + var update = firstBaseUpdate; - if ( - fiber.mode & StrictLegacyMode && - typeof instance.UNSAFE_componentWillUpdate === "function" - ) { - pendingUNSAFE_ComponentWillUpdateWarnings.push(fiber); - } - }; + do { + // An extra OffscreenLane bit is added to updates that were made to + // a hidden tree, so that we can distinguish them from updates that were + // already there when the tree was hidden. + var updateLane = removeLanes(update.lane, OffscreenLane); + var isHiddenUpdate = updateLane !== update.lane; // Check if this update was made while the tree was hidden. If so, then + // it's not a "base" update and we should disregard the extra base lanes + // that were added to renderLanes when we entered the Offscreen tree. - ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings = - function () { - // We do an initial pass to gather component names - var componentWillMountUniqueNames = new Set(); + var shouldSkipUpdate = isHiddenUpdate + ? !isSubsetOfLanes(getWorkInProgressRootRenderLanes(), updateLane) + : !isSubsetOfLanes(renderLanes, updateLane); - if (pendingComponentWillMountWarnings.length > 0) { - pendingComponentWillMountWarnings.forEach(function (fiber) { - componentWillMountUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingComponentWillMountWarnings = []; - } + if (shouldSkipUpdate) { + // Priority is insufficient. Skip this update. If this is the first + // skipped update, the previous update/state is the new base + // update/state. + var clone = { + lane: updateLane, + tag: update.tag, + payload: update.payload, + callback: update.callback, + next: null + }; - var UNSAFE_componentWillMountUniqueNames = new Set(); + if (newLastBaseUpdate === null) { + newFirstBaseUpdate = newLastBaseUpdate = clone; + newBaseState = newState; + } else { + newLastBaseUpdate = newLastBaseUpdate.next = clone; + } // Update the remaining priority in the queue. - if (pendingUNSAFE_ComponentWillMountWarnings.length > 0) { - pendingUNSAFE_ComponentWillMountWarnings.forEach(function (fiber) { - UNSAFE_componentWillMountUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingUNSAFE_ComponentWillMountWarnings = []; - } + newLanes = mergeLanes(newLanes, updateLane); + } else { + // This update does have sufficient priority. + // Check if this update is part of a pending async action. If so, + // we'll need to suspend until the action has finished, so that it's + // batched together with future updates in the same action. + if ( + updateLane !== NoLane && + updateLane === peekEntangledActionLane() + ) { + didReadFromEntangledAsyncAction = true; + } - var componentWillReceivePropsUniqueNames = new Set(); + if (newLastBaseUpdate !== null) { + var _clone = { + // This update is going to be committed so we never want uncommit + // it. Using NoLane works because 0 is a subset of all bitmasks, so + // this will never be skipped by the check above. + lane: NoLane, + tag: update.tag, + payload: update.payload, + // When this update is rebased, we should not fire its + // callback again. + callback: null, + next: null + }; + newLastBaseUpdate = newLastBaseUpdate.next = _clone; + } // Process this update. - if (pendingComponentWillReceivePropsWarnings.length > 0) { - pendingComponentWillReceivePropsWarnings.forEach(function (fiber) { - componentWillReceivePropsUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingComponentWillReceivePropsWarnings = []; - } + newState = getStateFromUpdate( + workInProgress, + queue, + update, + newState, + props, + instance + ); + var callback = update.callback; - var UNSAFE_componentWillReceivePropsUniqueNames = new Set(); + if (callback !== null) { + workInProgress.flags |= Callback; - if (pendingUNSAFE_ComponentWillReceivePropsWarnings.length > 0) { - pendingUNSAFE_ComponentWillReceivePropsWarnings.forEach( - function (fiber) { - UNSAFE_componentWillReceivePropsUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); + if (isHiddenUpdate) { + workInProgress.flags |= Visibility; } - ); - pendingUNSAFE_ComponentWillReceivePropsWarnings = []; - } - var componentWillUpdateUniqueNames = new Set(); + var callbacks = queue.callbacks; - if (pendingComponentWillUpdateWarnings.length > 0) { - pendingComponentWillUpdateWarnings.forEach(function (fiber) { - componentWillUpdateUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingComponentWillUpdateWarnings = []; - } + if (callbacks === null) { + queue.callbacks = [callback]; + } else { + callbacks.push(callback); + } + } + } // $FlowFixMe[incompatible-type] we bail out when we get a null - var UNSAFE_componentWillUpdateUniqueNames = new Set(); + update = update.next; - if (pendingUNSAFE_ComponentWillUpdateWarnings.length > 0) { - pendingUNSAFE_ComponentWillUpdateWarnings.forEach(function (fiber) { - UNSAFE_componentWillUpdateUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingUNSAFE_ComponentWillUpdateWarnings = []; - } // Finally, we flush all the warnings - // UNSAFE_ ones before the deprecated ones, since they'll be 'louder' + if (update === null) { + pendingQueue = queue.shared.pending; - if (UNSAFE_componentWillMountUniqueNames.size > 0) { - var sortedNames = setToSortedString( - UNSAFE_componentWillMountUniqueNames - ); + if (pendingQueue === null) { + break; + } else { + // An update was scheduled from inside a reducer. Add the new + // pending updates to the end of the list and keep processing. + var _lastPendingUpdate = pendingQueue; // Intentionally unsound. Pending updates form a circular list, but we + // unravel them when transferring them to the base queue. - error( - "Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code. " + - "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + - "* Move code with side effects to componentDidMount, and set initial state in the constructor.\n" + - "\nPlease update the following components: %s", - sortedNames - ); + var _firstPendingUpdate = _lastPendingUpdate.next; + _lastPendingUpdate.next = null; + update = _firstPendingUpdate; + queue.lastBaseUpdate = _lastPendingUpdate; + queue.shared.pending = null; + } } + } while (true); - if (UNSAFE_componentWillReceivePropsUniqueNames.size > 0) { - var _sortedNames = setToSortedString( - UNSAFE_componentWillReceivePropsUniqueNames - ); + if (newLastBaseUpdate === null) { + newBaseState = newState; + } - error( - "Using UNSAFE_componentWillReceiveProps in strict mode is not recommended " + - "and may indicate bugs in your code. " + - "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + - "* Move data fetching code or side effects to componentDidUpdate.\n" + - "* If you're updating state whenever props change, " + - "refactor your code to use memoization techniques or move it to " + - "static getDerivedStateFromProps. Learn more at: https://reactjs.org/link/derived-state\n" + - "\nPlease update the following components: %s", - _sortedNames - ); - } + queue.baseState = newBaseState; + queue.firstBaseUpdate = newFirstBaseUpdate; + queue.lastBaseUpdate = newLastBaseUpdate; - if (UNSAFE_componentWillUpdateUniqueNames.size > 0) { - var _sortedNames2 = setToSortedString( - UNSAFE_componentWillUpdateUniqueNames - ); + if (firstBaseUpdate === null) { + // `queue.lanes` is used for entangling transitions. We can set it back to + // zero once the queue is empty. + queue.shared.lanes = NoLanes; + } // Set the remaining expiration time to be whatever is remaining in the queue. + // This should be fine because the only two other things that contribute to + // expiration time are props and context. We're already in the middle of the + // begin phase by the time we start processing the queue, so we've already + // dealt with the props. Context in components that specify + // shouldComponentUpdate is tricky; but we'll have to account for + // that regardless. - error( - "Using UNSAFE_componentWillUpdate in strict mode is not recommended " + - "and may indicate bugs in your code. " + - "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + - "* Move data fetching code or side effects to componentDidUpdate.\n" + - "\nPlease update the following components: %s", - _sortedNames2 - ); - } + markSkippedUpdateLanes(newLanes); + workInProgress.lanes = newLanes; + workInProgress.memoizedState = newState; + } - if (componentWillMountUniqueNames.size > 0) { - var _sortedNames3 = setToSortedString( - componentWillMountUniqueNames - ); + { + currentlyProcessingQueue = null; + } + } - warn( - "componentWillMount has been renamed, and is not recommended for use. " + - "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + - "* Move code with side effects to componentDidMount, and set initial state in the constructor.\n" + - "* Rename componentWillMount to UNSAFE_componentWillMount to suppress " + - "this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. " + - "To rename all deprecated lifecycles to their new names, you can run " + - "`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n" + - "\nPlease update the following components: %s", - _sortedNames3 - ); - } + function callCallback(callback, context) { + if (typeof callback !== "function") { + throw new Error( + "Invalid argument passed as callback. Expected a function. Instead " + + ("received: " + callback) + ); + } - if (componentWillReceivePropsUniqueNames.size > 0) { - var _sortedNames4 = setToSortedString( - componentWillReceivePropsUniqueNames - ); + callback.call(context); + } - warn( - "componentWillReceiveProps has been renamed, and is not recommended for use. " + - "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + - "* Move data fetching code or side effects to componentDidUpdate.\n" + - "* If you're updating state whenever props change, refactor your " + - "code to use memoization techniques or move it to " + - "static getDerivedStateFromProps. Learn more at: https://reactjs.org/link/derived-state\n" + - "* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress " + - "this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. " + - "To rename all deprecated lifecycles to their new names, you can run " + - "`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n" + - "\nPlease update the following components: %s", - _sortedNames4 - ); - } + function resetHasForceUpdateBeforeProcessing() { + hasForceUpdate = false; + } + function checkHasForceUpdateAfterProcessing() { + return hasForceUpdate; + } + function deferHiddenCallbacks(updateQueue) { + // When an update finishes on a hidden component, its callback should not + // be fired until/unless the component is made visible again. Stash the + // callback on the shared queue object so it can be fired later. + var newHiddenCallbacks = updateQueue.callbacks; - if (componentWillUpdateUniqueNames.size > 0) { - var _sortedNames5 = setToSortedString( - componentWillUpdateUniqueNames - ); + if (newHiddenCallbacks !== null) { + var existingHiddenCallbacks = updateQueue.shared.hiddenCallbacks; - warn( - "componentWillUpdate has been renamed, and is not recommended for use. " + - "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + - "* Move data fetching code or side effects to componentDidUpdate.\n" + - "* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress " + - "this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. " + - "To rename all deprecated lifecycles to their new names, you can run " + - "`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n" + - "\nPlease update the following components: %s", - _sortedNames5 - ); - } - }; + if (existingHiddenCallbacks === null) { + updateQueue.shared.hiddenCallbacks = newHiddenCallbacks; + } else { + updateQueue.shared.hiddenCallbacks = + existingHiddenCallbacks.concat(newHiddenCallbacks); + } + } + } + function commitHiddenCallbacks(updateQueue, context) { + // This component is switching from hidden -> visible. Commit any callbacks + // that were previously deferred. + var hiddenCallbacks = updateQueue.shared.hiddenCallbacks; - var pendingLegacyContextWarning = new Map(); // Tracks components we have already warned about. + if (hiddenCallbacks !== null) { + updateQueue.shared.hiddenCallbacks = null; - var didWarnAboutLegacyContext = new Set(); + for (var i = 0; i < hiddenCallbacks.length; i++) { + var callback = hiddenCallbacks[i]; + callCallback(callback, context); + } + } + } + function commitCallbacks(updateQueue, context) { + var callbacks = updateQueue.callbacks; - ReactStrictModeWarnings.recordLegacyContextWarning = function ( - fiber, - instance - ) { - var strictRoot = findStrictRoot(fiber); + if (callbacks !== null) { + updateQueue.callbacks = null; - if (strictRoot === null) { - error( - "Expected to find a StrictMode component in a strict mode tree. " + - "This error is likely caused by a bug in React. Please file an issue." - ); + for (var i = 0; i < callbacks.length; i++) { + var callback = callbacks[i]; + callCallback(callback, context); + } + } + } - return; - } // Dedup strategy: Warn once per component. + /** + * Performs equality by iterating through keys on an object and returning false + * when any key has values which are not strictly equal between the arguments. + * Returns true when the values of all keys are strictly equal. + */ - if (didWarnAboutLegacyContext.has(fiber.type)) { - return; - } + function shallowEqual(objA, objB) { + if (objectIs(objA, objB)) { + return true; + } - var warningsForRoot = pendingLegacyContextWarning.get(strictRoot); + if ( + typeof objA !== "object" || + objA === null || + typeof objB !== "object" || + objB === null + ) { + return false; + } + + var keysA = Object.keys(objA); + var keysB = Object.keys(objB); + + if (keysA.length !== keysB.length) { + return false; + } // Test for A's keys different from B. + + for (var i = 0; i < keysA.length; i++) { + var currentKey = keysA[i]; if ( - fiber.type.contextTypes != null || - fiber.type.childContextTypes != null || - (instance !== null && typeof instance.getChildContext === "function") + !hasOwnProperty.call(objB, currentKey) || // $FlowFixMe[incompatible-use] lost refinement of `objB` + !objectIs(objA[currentKey], objB[currentKey]) ) { - if (warningsForRoot === undefined) { - warningsForRoot = []; - pendingLegacyContextWarning.set(strictRoot, warningsForRoot); - } - - warningsForRoot.push(fiber); + return false; } - }; + } - ReactStrictModeWarnings.flushLegacyContextWarning = function () { - pendingLegacyContextWarning.forEach(function (fiberArray, strictRoot) { - if (fiberArray.length === 0) { - return; - } + return true; + } - var firstFiber = fiberArray[0]; - var uniqueNames = new Set(); - fiberArray.forEach(function (fiber) { - uniqueNames.add(getComponentNameFromFiber(fiber) || "Component"); - didWarnAboutLegacyContext.add(fiber.type); - }); - var sortedNames = setToSortedString(uniqueNames); + function describeFiber(fiber) { + var owner = fiber._debugOwner ? fiber._debugOwner.type : null; + var source = fiber._debugSource; - try { - setCurrentFiber(firstFiber); + switch (fiber.tag) { + case HostHoistable: + case HostSingleton: + case HostComponent: + return describeBuiltInComponentFrame(fiber.type, source, owner); - error( - "Legacy context API has been detected within a strict-mode tree." + - "\n\nThe old API will be supported in all 16.x releases, but applications " + - "using it should migrate to the new version." + - "\n\nPlease update the following components: %s" + - "\n\nLearn more about this warning here: https://reactjs.org/link/legacy-context", - sortedNames - ); - } finally { - resetCurrentFiber(); - } - }); - }; + case LazyComponent: + return describeBuiltInComponentFrame("Lazy", source, owner); - ReactStrictModeWarnings.discardPendingWarnings = function () { - pendingComponentWillMountWarnings = []; - pendingUNSAFE_ComponentWillMountWarnings = []; - pendingComponentWillReceivePropsWarnings = []; - pendingUNSAFE_ComponentWillReceivePropsWarnings = []; - pendingComponentWillUpdateWarnings = []; - pendingUNSAFE_ComponentWillUpdateWarnings = []; - pendingLegacyContextWarning = new Map(); - }; - } + case SuspenseComponent: + return describeBuiltInComponentFrame("Suspense", source, owner); - /* - * The `'' + value` pattern (used in perf-sensitive code) throws for Symbol - * and Temporal.* types. See https://github.com/facebook/react/pull/22064. - * - * The functions in this module will throw an easier-to-understand, - * easier-to-debug exception with a clear errors message message explaining the - * problem. (Instead of a confusing exception thrown inside the implementation - * of the `value` object). - */ - // $FlowFixMe[incompatible-return] only called in DEV, so void return is not possible. - function typeName(value) { - { - // toStringTag is needed for namespaced types like Temporal.Instant - var hasToStringTag = typeof Symbol === "function" && Symbol.toStringTag; - var type = - (hasToStringTag && value[Symbol.toStringTag]) || - value.constructor.name || - "Object"; // $FlowFixMe[incompatible-return] + case SuspenseListComponent: + return describeBuiltInComponentFrame("SuspenseList", source, owner); - return type; - } - } // $FlowFixMe[incompatible-return] only called in DEV, so void return is not possible. + case FunctionComponent: + case IndeterminateComponent: + case SimpleMemoComponent: + return describeFunctionComponentFrame(fiber.type, source, owner); - function willCoercionThrow(value) { - { - try { - testStringCoercion(value); - return false; - } catch (e) { - return true; - } + case ForwardRef: + return describeFunctionComponentFrame( + fiber.type.render, + source, + owner + ); + + case ClassComponent: + return describeClassComponentFrame(fiber.type, source, owner); + + default: + return ""; } } - function testStringCoercion(value) { - // If you ended up here by following an exception call stack, here's what's - // happened: you supplied an object or symbol value to React (as a prop, key, - // DOM attribute, CSS property, string ref, etc.) and when React tried to - // coerce it to a string using `'' + value`, an exception was thrown. - // - // The most common types that will cause this exception are `Symbol` instances - // and Temporal objects like `Temporal.Instant`. But any object that has a - // `valueOf` or `[Symbol.toPrimitive]` method that throws will also cause this - // exception. (Library authors do this to prevent users from using built-in - // numeric operators like `+` or comparison operators like `>=` because custom - // methods are needed to perform accurate arithmetic or comparison.) - // - // To fix the problem, coerce this object or symbol value to a string before - // passing it to React. The most reliable way is usually `String(value)`. - // - // To find which value is throwing, check the browser or debugger console. - // Before this exception was thrown, there should be `console.error` output - // that shows the type (Symbol, Temporal.PlainDate, etc.) that caused the - // problem and how that type was used: key, atrribute, input value prop, etc. - // In most cases, this console output also shows the component and its - // ancestor components where the exception happened. - // - // eslint-disable-next-line react-internal/safe-string-coercion - return "" + value; - } - function checkKeyStringCoercion(value) { - { - if (willCoercionThrow(value)) { - error( - "The provided key is an unsupported type %s." + - " This value must be coerced to a string before using it here.", - typeName(value) - ); + function getStackByFiberInDevAndProd(workInProgress) { + try { + var info = ""; + var node = workInProgress; - return testStringCoercion(value); // throw (to help callers find troubleshooting comments) - } + do { + info += describeFiber(node); // $FlowFixMe[incompatible-type] we bail out when we get a null + + node = node.return; + } while (node); + + return info; + } catch (x) { + return "\nError generating stack: " + x.message + "\n" + x.stack; } } - function checkPropStringCoercion(value, propName) { + + var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; + var current = null; + var isRendering = false; + function getCurrentFiberOwnerNameInDevOrNull() { { - if (willCoercionThrow(value)) { - error( - "The provided `%s` prop is an unsupported type %s." + - " This value must be coerced to a string before using it here.", - propName, - typeName(value) - ); + if (current === null) { + return null; + } - return testStringCoercion(value); // throw (to help callers find troubleshooting comments) + var owner = current._debugOwner; + + if (owner !== null && typeof owner !== "undefined") { + return getComponentNameFromFiber(owner); } } + + return null; } - var ReactCurrentActQueue$3 = ReactSharedInternals.ReactCurrentActQueue; // An error that is thrown (e.g. by `use`) to trigger Suspense. If we - // detect this is caught by userspace, we'll log a warning in development. + function getCurrentFiberStackInDev() { + { + if (current === null) { + return ""; + } // Safe because if current fiber exists, we are reconciling, + // and it is guaranteed to be the work-in-progress version. - var SuspenseException = new Error( - "Suspense Exception: This is not a real error! It's an implementation " + - "detail of `use` to interrupt the current render. You must either " + - "rethrow it immediately, or move the `use` call outside of the " + - "`try/catch` block. Capturing without rethrowing will lead to " + - "unexpected behavior.\n\n" + - "To handle async errors, wrap your component in an error boundary, or " + - "call the promise's `.catch` method and pass the result to `use`" - ); - var SuspenseyCommitException = new Error( - "Suspense Exception: This is not a real error, and should not leak into " + - "userspace. If you're seeing this, it's likely a bug in React." - ); // This is a noop thenable that we use to trigger a fallback in throwException. - // TODO: It would be better to refactor throwException into multiple functions - // so we can trigger a fallback directly without having to check the type. But - // for now this will do. + return getStackByFiberInDevAndProd(current); + } + } - var noopSuspenseyCommitThenable = { - then: function () { - { - error( - "Internal React error: A listener was unexpectedly attached to a " + - '"noop" thenable. This is a bug in React. Please file an issue.' - ); - } + function resetCurrentFiber() { + { + ReactDebugCurrentFrame.getCurrentStack = null; + current = null; + isRendering = false; } - }; - function createThenableState() { - // The ThenableState is created the first time a component suspends. If it - // suspends again, we'll reuse the same state. - return []; } - function isThenableResolved(thenable) { - var status = thenable.status; - return status === "fulfilled" || status === "rejected"; + function setCurrentFiber(fiber) { + { + ReactDebugCurrentFrame.getCurrentStack = + fiber === null ? null : getCurrentFiberStackInDev; + current = fiber; + isRendering = false; + } + } + function getCurrentFiber() { + { + return current; + } + } + function setIsRendering(rendering) { + { + isRendering = rendering; + } } - function noop() {} + var ReactStrictModeWarnings = { + recordUnsafeLifecycleWarnings: function (fiber, instance) {}, + flushPendingUnsafeLifecycleWarnings: function () {}, + recordLegacyContextWarning: function (fiber, instance) {}, + flushLegacyContextWarning: function () {}, + discardPendingWarnings: function () {} + }; - function trackUsedThenable(thenableState, thenable, index) { - if (ReactCurrentActQueue$3.current !== null) { - ReactCurrentActQueue$3.didUsePromise = true; - } + { + var findStrictRoot = function (fiber) { + var maybeStrictRoot = null; + var node = fiber; - var previous = thenableState[index]; + while (node !== null) { + if (node.mode & StrictLegacyMode) { + maybeStrictRoot = node; + } - if (previous === undefined) { - thenableState.push(thenable); - } else { - if (previous !== thenable) { - // Reuse the previous thenable, and drop the new one. We can assume - // they represent the same value, because components are idempotent. - // Avoid an unhandled rejection errors for the Promises that we'll - // intentionally ignore. - thenable.then(noop, noop); - thenable = previous; + node = node.return; } - } // We use an expando to track the status and result of a thenable so that we - // can synchronously unwrap the value. Think of this as an extension of the - // Promise API, or a custom interface that is a superset of Thenable. - // - // If the thenable doesn't have a status, set it to "pending" and attach - // a listener that will update its status and result when it resolves. - switch (thenable.status) { - case "fulfilled": { - var fulfilledValue = thenable.value; - return fulfilledValue; + return maybeStrictRoot; + }; + + var setToSortedString = function (set) { + var array = []; + set.forEach(function (value) { + array.push(value); + }); + return array.sort().join(", "); + }; + + var pendingComponentWillMountWarnings = []; + var pendingUNSAFE_ComponentWillMountWarnings = []; + var pendingComponentWillReceivePropsWarnings = []; + var pendingUNSAFE_ComponentWillReceivePropsWarnings = []; + var pendingComponentWillUpdateWarnings = []; + var pendingUNSAFE_ComponentWillUpdateWarnings = []; // Tracks components we have already warned about. + + var didWarnAboutUnsafeLifecycles = new Set(); + + ReactStrictModeWarnings.recordUnsafeLifecycleWarnings = function ( + fiber, + instance + ) { + // Dedupe strategy: Warn once per component. + if (didWarnAboutUnsafeLifecycles.has(fiber.type)) { + return; } - case "rejected": { - var rejectedError = thenable.reason; - checkIfUseWrappedInAsyncCatch(rejectedError); - throw rejectedError; + if ( + typeof instance.componentWillMount === "function" && // Don't warn about react-lifecycles-compat polyfilled components. + instance.componentWillMount.__suppressDeprecationWarning !== true + ) { + pendingComponentWillMountWarnings.push(fiber); } - default: { - if (typeof thenable.status === "string") { - // Only instrument the thenable if the status if not defined. If - // it's defined, but an unknown value, assume it's been instrumented by - // some custom userspace implementation. We treat it as "pending". - // Attach a dummy listener, to ensure that any lazy initialization can - // happen. Flight lazily parses JSON when the value is actually awaited. - thenable.then(noop, noop); - } else { - // This is an uncached thenable that we haven't seen before. - // Detect infinite ping loops caused by uncached promises. - var root = getWorkInProgressRoot(); - - if (root !== null && root.shellSuspendCounter > 100) { - // This root has suspended repeatedly in the shell without making any - // progress (i.e. committing something). This is highly suggestive of - // an infinite ping loop, often caused by an accidental Async Client - // Component. - // - // During a transition, we can suspend the work loop until the promise - // to resolve, but this is a sync render, so that's not an option. We - // also can't show a fallback, because none was provided. So our last - // resort is to throw an error. - // - // TODO: Remove this error in a future release. Other ways of handling - // this case include forcing a concurrent render, or putting the whole - // root into offscreen mode. - throw new Error( - "async/await is not yet supported in Client Components, only " + - "Server Components. This error is often caused by accidentally " + - "adding `'use client'` to a module that was originally written " + - "for the server." - ); - } - - var pendingThenable = thenable; - pendingThenable.status = "pending"; - pendingThenable.then( - function (fulfilledValue) { - if (thenable.status === "pending") { - var fulfilledThenable = thenable; - fulfilledThenable.status = "fulfilled"; - fulfilledThenable.value = fulfilledValue; - } - }, - function (error) { - if (thenable.status === "pending") { - var rejectedThenable = thenable; - rejectedThenable.status = "rejected"; - rejectedThenable.reason = error; - } - } - ); // Check one more time in case the thenable resolved synchronously. - - switch (thenable.status) { - case "fulfilled": { - var fulfilledThenable = thenable; - return fulfilledThenable.value; - } - - case "rejected": { - var rejectedThenable = thenable; - var _rejectedError = rejectedThenable.reason; - checkIfUseWrappedInAsyncCatch(_rejectedError); - throw _rejectedError; - } - } - } // Suspend. - // - // Throwing here is an implementation detail that allows us to unwind the - // call stack. But we shouldn't allow it to leak into userspace. Throw an - // opaque placeholder value instead of the actual thenable. If it doesn't - // get captured by the work loop, log a warning, because that means - // something in userspace must have caught it. - - suspendedThenable = thenable; - - { - needsToResetSuspendedThenableDEV = true; - } - - throw SuspenseException; + if ( + fiber.mode & StrictLegacyMode && + typeof instance.UNSAFE_componentWillMount === "function" + ) { + pendingUNSAFE_ComponentWillMountWarnings.push(fiber); } - } - } - // passed to the rest of the Suspense implementation — which, for historical - // reasons, expects to receive a thenable. - - var suspendedThenable = null; - var needsToResetSuspendedThenableDEV = false; - function getSuspendedThenable() { - // This is called right after `use` suspends by throwing an exception. `use` - // throws an opaque value instead of the thenable itself so that it can't be - // caught in userspace. Then the work loop accesses the actual thenable using - // this function. - if (suspendedThenable === null) { - throw new Error( - "Expected a suspended thenable. This is a bug in React. Please file " + - "an issue." - ); - } - - var thenable = suspendedThenable; - suspendedThenable = null; - - { - needsToResetSuspendedThenableDEV = false; - } - return thenable; - } - function checkIfUseWrappedInTryCatch() { - { - // This was set right before SuspenseException was thrown, and it should - // have been cleared when the exception was handled. If it wasn't, - // it must have been caught by userspace. - if (needsToResetSuspendedThenableDEV) { - needsToResetSuspendedThenableDEV = false; - return true; + if ( + typeof instance.componentWillReceiveProps === "function" && + instance.componentWillReceiveProps.__suppressDeprecationWarning !== + true + ) { + pendingComponentWillReceivePropsWarnings.push(fiber); } - } - - return false; - } - function checkIfUseWrappedInAsyncCatch(rejectedReason) { - // This check runs in prod, too, because it prevents a more confusing - // downstream error, where SuspenseException is caught by a promise and - // thrown asynchronously. - // TODO: Another way to prevent SuspenseException from leaking into an async - // execution context is to check the dispatcher every time `use` is called, - // or some equivalent. That might be preferable for other reasons, too, since - // it matches how we prevent similar mistakes for other hooks. - if (rejectedReason === SuspenseException) { - throw new Error( - "Hooks are not supported inside an async component. This " + - "error is often caused by accidentally adding `'use client'` " + - "to a module that was originally written for the server." - ); - } - } - - var thenableState$1 = null; - var thenableIndexCounter$1 = 0; - var didWarnAboutMaps; - var didWarnAboutGenerators; - var didWarnAboutStringRefs; - var ownerHasKeyUseWarning; - var ownerHasFunctionTypeWarning; - - var warnForMissingKey = function (child, returnFiber) {}; - { - didWarnAboutMaps = false; - didWarnAboutGenerators = false; - didWarnAboutStringRefs = {}; - /** - * Warn if there's no key explicitly set on dynamic arrays of children or - * object keys are not valid. This allows us to keep track of children between - * updates. - */ - - ownerHasKeyUseWarning = {}; - ownerHasFunctionTypeWarning = {}; - - warnForMissingKey = function (child, returnFiber) { - if (child === null || typeof child !== "object") { - return; + if ( + fiber.mode & StrictLegacyMode && + typeof instance.UNSAFE_componentWillReceiveProps === "function" + ) { + pendingUNSAFE_ComponentWillReceivePropsWarnings.push(fiber); } - if (!child._store || child._store.validated || child.key != null) { - return; + if ( + typeof instance.componentWillUpdate === "function" && + instance.componentWillUpdate.__suppressDeprecationWarning !== true + ) { + pendingComponentWillUpdateWarnings.push(fiber); } - if (typeof child._store !== "object") { - throw new Error( - "React Component in warnForMissingKey should have a _store. " + - "This error is likely caused by a bug in React. Please file an issue." - ); - } // $FlowFixMe[cannot-write] unable to narrow type from mixed to writable object - - child._store.validated = true; - var componentName = - getComponentNameFromFiber(returnFiber) || "Component"; - - if (ownerHasKeyUseWarning[componentName]) { - return; + if ( + fiber.mode & StrictLegacyMode && + typeof instance.UNSAFE_componentWillUpdate === "function" + ) { + pendingUNSAFE_ComponentWillUpdateWarnings.push(fiber); } - - ownerHasKeyUseWarning[componentName] = true; - - error( - "Each child in a list should have a unique " + - '"key" prop. See https://reactjs.org/link/warning-keys for ' + - "more information." - ); }; - } - function isReactClass(type) { - return type.prototype && type.prototype.isReactComponent; - } - - function unwrapThenable(thenable) { - var index = thenableIndexCounter$1; - thenableIndexCounter$1 += 1; + ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings = + function () { + // We do an initial pass to gather component names + var componentWillMountUniqueNames = new Set(); - if (thenableState$1 === null) { - thenableState$1 = createThenableState(); - } + if (pendingComponentWillMountWarnings.length > 0) { + pendingComponentWillMountWarnings.forEach(function (fiber) { + componentWillMountUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingComponentWillMountWarnings = []; + } - return trackUsedThenable(thenableState$1, thenable, index); - } + var UNSAFE_componentWillMountUniqueNames = new Set(); - function coerceRef(returnFiber, current, element) { - var mixedRef = element.ref; + if (pendingUNSAFE_ComponentWillMountWarnings.length > 0) { + pendingUNSAFE_ComponentWillMountWarnings.forEach(function (fiber) { + UNSAFE_componentWillMountUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingUNSAFE_ComponentWillMountWarnings = []; + } - if ( - mixedRef !== null && - typeof mixedRef !== "function" && - typeof mixedRef !== "object" - ) { - { - if ( - // We warn in ReactElement.js if owner and self are equal for string refs - // because these cannot be automatically converted to an arrow function - // using a codemod. Therefore, we don't have to warn about string refs again. - !( - element._owner && - element._self && - element._owner.stateNode !== element._self - ) && // Will already throw with "Function components cannot have string refs" - !(element._owner && element._owner.tag !== ClassComponent) && // Will already warn with "Function components cannot be given refs" - !( - typeof element.type === "function" && !isReactClass(element.type) - ) && // Will already throw with "Element ref was specified as a string (someStringRef) but no owner was set" - element._owner - ) { - var componentName = - getComponentNameFromFiber(returnFiber) || "Component"; + var componentWillReceivePropsUniqueNames = new Set(); - if (!didWarnAboutStringRefs[componentName]) { - error( - 'Component "%s" contains the string ref "%s". Support for string refs ' + - "will be removed in a future major release. We recommend using " + - "useRef() or createRef() instead. " + - "Learn more about using refs safely here: " + - "https://reactjs.org/link/strict-mode-string-ref", - componentName, - mixedRef + if (pendingComponentWillReceivePropsWarnings.length > 0) { + pendingComponentWillReceivePropsWarnings.forEach(function (fiber) { + componentWillReceivePropsUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingComponentWillReceivePropsWarnings = []; + } - didWarnAboutStringRefs[componentName] = true; - } + var UNSAFE_componentWillReceivePropsUniqueNames = new Set(); + + if (pendingUNSAFE_ComponentWillReceivePropsWarnings.length > 0) { + pendingUNSAFE_ComponentWillReceivePropsWarnings.forEach( + function (fiber) { + UNSAFE_componentWillReceivePropsUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + } + ); + pendingUNSAFE_ComponentWillReceivePropsWarnings = []; } - } - if (element._owner) { - var owner = element._owner; - var inst; + var componentWillUpdateUniqueNames = new Set(); - if (owner) { - var ownerFiber = owner; + if (pendingComponentWillUpdateWarnings.length > 0) { + pendingComponentWillUpdateWarnings.forEach(function (fiber) { + componentWillUpdateUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingComponentWillUpdateWarnings = []; + } - if (ownerFiber.tag !== ClassComponent) { - throw new Error( - "Function components cannot have string refs. " + - "We recommend using useRef() instead. " + - "Learn more about using refs safely here: " + - "https://reactjs.org/link/strict-mode-string-ref" + var UNSAFE_componentWillUpdateUniqueNames = new Set(); + + if (pendingUNSAFE_ComponentWillUpdateWarnings.length > 0) { + pendingUNSAFE_ComponentWillUpdateWarnings.forEach(function (fiber) { + UNSAFE_componentWillUpdateUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" ); - } + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingUNSAFE_ComponentWillUpdateWarnings = []; + } // Finally, we flush all the warnings + // UNSAFE_ ones before the deprecated ones, since they'll be 'louder' - inst = ownerFiber.stateNode; - } + if (UNSAFE_componentWillMountUniqueNames.size > 0) { + var sortedNames = setToSortedString( + UNSAFE_componentWillMountUniqueNames + ); - if (!inst) { - throw new Error( - "Missing owner for string ref " + - mixedRef + - ". This error is likely caused by a " + - "bug in React. Please file an issue." + error( + "Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code. " + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + + "* Move code with side effects to componentDidMount, and set initial state in the constructor.\n" + + "\nPlease update the following components: %s", + sortedNames ); - } // Assigning this to a const so Flow knows it won't change in the closure + } - var resolvedInst = inst; + if (UNSAFE_componentWillReceivePropsUniqueNames.size > 0) { + var _sortedNames = setToSortedString( + UNSAFE_componentWillReceivePropsUniqueNames + ); - { - checkPropStringCoercion(mixedRef, "ref"); + error( + "Using UNSAFE_componentWillReceiveProps in strict mode is not recommended " + + "and may indicate bugs in your code. " + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + + "* Move data fetching code or side effects to componentDidUpdate.\n" + + "* If you're updating state whenever props change, " + + "refactor your code to use memoization techniques or move it to " + + "static getDerivedStateFromProps. Learn more at: https://reactjs.org/link/derived-state\n" + + "\nPlease update the following components: %s", + _sortedNames + ); } - var stringRef = "" + mixedRef; // Check if previous string ref matches new string ref + if (UNSAFE_componentWillUpdateUniqueNames.size > 0) { + var _sortedNames2 = setToSortedString( + UNSAFE_componentWillUpdateUniqueNames + ); - if ( - current !== null && - current.ref !== null && - typeof current.ref === "function" && - current.ref._stringRef === stringRef - ) { - return current.ref; + error( + "Using UNSAFE_componentWillUpdate in strict mode is not recommended " + + "and may indicate bugs in your code. " + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + + "* Move data fetching code or side effects to componentDidUpdate.\n" + + "\nPlease update the following components: %s", + _sortedNames2 + ); } - var ref = function (value) { - var refs = resolvedInst.refs; - - if (value === null) { - delete refs[stringRef]; - } else { - refs[stringRef] = value; - } - }; + if (componentWillMountUniqueNames.size > 0) { + var _sortedNames3 = setToSortedString( + componentWillMountUniqueNames + ); - ref._stringRef = stringRef; - return ref; - } else { - if (typeof mixedRef !== "string") { - throw new Error( - "Expected ref to be a function, a string, an object returned by React.createRef(), or null." + warn( + "componentWillMount has been renamed, and is not recommended for use. " + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + + "* Move code with side effects to componentDidMount, and set initial state in the constructor.\n" + + "* Rename componentWillMount to UNSAFE_componentWillMount to suppress " + + "this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. " + + "To rename all deprecated lifecycles to their new names, you can run " + + "`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n" + + "\nPlease update the following components: %s", + _sortedNames3 ); } - if (!element._owner) { - throw new Error( - "Element ref was specified as a string (" + - mixedRef + - ") but no owner was set. This could happen for one of" + - " the following reasons:\n" + - "1. You may be adding a ref to a function component\n" + - "2. You may be adding a ref to a component that was not created inside a component's render method\n" + - "3. You have multiple copies of React loaded\n" + - "See https://reactjs.org/link/refs-must-have-owner for more information." + if (componentWillReceivePropsUniqueNames.size > 0) { + var _sortedNames4 = setToSortedString( + componentWillReceivePropsUniqueNames ); - } - } - } - return mixedRef; - } + warn( + "componentWillReceiveProps has been renamed, and is not recommended for use. " + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + + "* Move data fetching code or side effects to componentDidUpdate.\n" + + "* If you're updating state whenever props change, refactor your " + + "code to use memoization techniques or move it to " + + "static getDerivedStateFromProps. Learn more at: https://reactjs.org/link/derived-state\n" + + "* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress " + + "this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. " + + "To rename all deprecated lifecycles to their new names, you can run " + + "`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n" + + "\nPlease update the following components: %s", + _sortedNames4 + ); + } - function throwOnInvalidObjectType(returnFiber, newChild) { - // $FlowFixMe[method-unbinding] - var childString = Object.prototype.toString.call(newChild); - throw new Error( - "Objects are not valid as a React child (found: " + - (childString === "[object Object]" - ? "object with keys {" + Object.keys(newChild).join(", ") + "}" - : childString) + - "). " + - "If you meant to render a collection of children, use an array " + - "instead." - ); - } + if (componentWillUpdateUniqueNames.size > 0) { + var _sortedNames5 = setToSortedString( + componentWillUpdateUniqueNames + ); - function warnOnFunctionType(returnFiber) { - { - var componentName = - getComponentNameFromFiber(returnFiber) || "Component"; + warn( + "componentWillUpdate has been renamed, and is not recommended for use. " + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + + "* Move data fetching code or side effects to componentDidUpdate.\n" + + "* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress " + + "this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. " + + "To rename all deprecated lifecycles to their new names, you can run " + + "`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n" + + "\nPlease update the following components: %s", + _sortedNames5 + ); + } + }; - if (ownerHasFunctionTypeWarning[componentName]) { - return; - } + var pendingLegacyContextWarning = new Map(); // Tracks components we have already warned about. - ownerHasFunctionTypeWarning[componentName] = true; + var didWarnAboutLegacyContext = new Set(); - error( - "Functions are not valid as a React child. This may happen if " + - "you return a Component instead of from render. " + - "Or maybe you meant to call this function rather than return it." - ); - } - } + ReactStrictModeWarnings.recordLegacyContextWarning = function ( + fiber, + instance + ) { + var strictRoot = findStrictRoot(fiber); - function resolveLazy(lazyType) { - var payload = lazyType._payload; - var init = lazyType._init; - return init(payload); - } // This wrapper function exists because I expect to clone the code in each path - // to be able to optimize each path individually by branching early. This needs - // a compiler or we can do it manually. Helpers that don't need this branching - // live outside of this function. + if (strictRoot === null) { + error( + "Expected to find a StrictMode component in a strict mode tree. " + + "This error is likely caused by a bug in React. Please file an issue." + ); - function createChildReconciler(shouldTrackSideEffects) { - function deleteChild(returnFiber, childToDelete) { - if (!shouldTrackSideEffects) { - // Noop. return; - } - - var deletions = returnFiber.deletions; + } // Dedup strategy: Warn once per component. - if (deletions === null) { - returnFiber.deletions = [childToDelete]; - returnFiber.flags |= ChildDeletion; - } else { - deletions.push(childToDelete); + if (didWarnAboutLegacyContext.has(fiber.type)) { + return; } - } - function deleteRemainingChildren(returnFiber, currentFirstChild) { - if (!shouldTrackSideEffects) { - // Noop. - return null; - } // TODO: For the shouldClone case, this could be micro-optimized a bit by - // assuming that after the first child we've already added everything. + var warningsForRoot = pendingLegacyContextWarning.get(strictRoot); - var childToDelete = currentFirstChild; + if ( + fiber.type.contextTypes != null || + fiber.type.childContextTypes != null || + (instance !== null && typeof instance.getChildContext === "function") + ) { + if (warningsForRoot === undefined) { + warningsForRoot = []; + pendingLegacyContextWarning.set(strictRoot, warningsForRoot); + } - while (childToDelete !== null) { - deleteChild(returnFiber, childToDelete); - childToDelete = childToDelete.sibling; + warningsForRoot.push(fiber); } + }; - return null; - } + ReactStrictModeWarnings.flushLegacyContextWarning = function () { + pendingLegacyContextWarning.forEach(function (fiberArray, strictRoot) { + if (fiberArray.length === 0) { + return; + } - function mapRemainingChildren(returnFiber, currentFirstChild) { - // Add the remaining children to a temporary map so that we can find them by - // keys quickly. Implicit (null) keys get added to this set with their index - // instead. - var existingChildren = new Map(); - var existingChild = currentFirstChild; + var firstFiber = fiberArray[0]; + var uniqueNames = new Set(); + fiberArray.forEach(function (fiber) { + uniqueNames.add(getComponentNameFromFiber(fiber) || "Component"); + didWarnAboutLegacyContext.add(fiber.type); + }); + var sortedNames = setToSortedString(uniqueNames); - while (existingChild !== null) { - if (existingChild.key !== null) { - existingChildren.set(existingChild.key, existingChild); - } else { - existingChildren.set(existingChild.index, existingChild); + try { + setCurrentFiber(firstFiber); + + error( + "Legacy context API has been detected within a strict-mode tree." + + "\n\nThe old API will be supported in all 16.x releases, but applications " + + "using it should migrate to the new version." + + "\n\nPlease update the following components: %s" + + "\n\nLearn more about this warning here: https://reactjs.org/link/legacy-context", + sortedNames + ); + } finally { + resetCurrentFiber(); } + }); + }; - existingChild = existingChild.sibling; - } + ReactStrictModeWarnings.discardPendingWarnings = function () { + pendingComponentWillMountWarnings = []; + pendingUNSAFE_ComponentWillMountWarnings = []; + pendingComponentWillReceivePropsWarnings = []; + pendingUNSAFE_ComponentWillReceivePropsWarnings = []; + pendingComponentWillUpdateWarnings = []; + pendingUNSAFE_ComponentWillUpdateWarnings = []; + pendingLegacyContextWarning = new Map(); + }; + } - return existingChildren; - } + /* + * The `'' + value` pattern (used in perf-sensitive code) throws for Symbol + * and Temporal.* types. See https://github.com/facebook/react/pull/22064. + * + * The functions in this module will throw an easier-to-understand, + * easier-to-debug exception with a clear errors message message explaining the + * problem. (Instead of a confusing exception thrown inside the implementation + * of the `value` object). + */ + // $FlowFixMe[incompatible-return] only called in DEV, so void return is not possible. + function typeName(value) { + { + // toStringTag is needed for namespaced types like Temporal.Instant + var hasToStringTag = typeof Symbol === "function" && Symbol.toStringTag; + var type = + (hasToStringTag && value[Symbol.toStringTag]) || + value.constructor.name || + "Object"; // $FlowFixMe[incompatible-return] - function useFiber(fiber, pendingProps) { - // We currently set sibling to null and index to 0 here because it is easy - // to forget to do before returning it. E.g. for the single child case. - var clone = createWorkInProgress(fiber, pendingProps); - clone.index = 0; - clone.sibling = null; - return clone; + return type; } + } // $FlowFixMe[incompatible-return] only called in DEV, so void return is not possible. - function placeChild(newFiber, lastPlacedIndex, newIndex) { - newFiber.index = newIndex; - - if (!shouldTrackSideEffects) { - // During hydration, the useId algorithm needs to know which fibers are - // part of a list of children (arrays, iterators). - newFiber.flags |= Forked; - return lastPlacedIndex; + function willCoercionThrow(value) { + { + try { + testStringCoercion(value); + return false; + } catch (e) { + return true; } + } + } - var current = newFiber.alternate; - - if (current !== null) { - var oldIndex = current.index; + function testStringCoercion(value) { + // If you ended up here by following an exception call stack, here's what's + // happened: you supplied an object or symbol value to React (as a prop, key, + // DOM attribute, CSS property, string ref, etc.) and when React tried to + // coerce it to a string using `'' + value`, an exception was thrown. + // + // The most common types that will cause this exception are `Symbol` instances + // and Temporal objects like `Temporal.Instant`. But any object that has a + // `valueOf` or `[Symbol.toPrimitive]` method that throws will also cause this + // exception. (Library authors do this to prevent users from using built-in + // numeric operators like `+` or comparison operators like `>=` because custom + // methods are needed to perform accurate arithmetic or comparison.) + // + // To fix the problem, coerce this object or symbol value to a string before + // passing it to React. The most reliable way is usually `String(value)`. + // + // To find which value is throwing, check the browser or debugger console. + // Before this exception was thrown, there should be `console.error` output + // that shows the type (Symbol, Temporal.PlainDate, etc.) that caused the + // problem and how that type was used: key, atrribute, input value prop, etc. + // In most cases, this console output also shows the component and its + // ancestor components where the exception happened. + // + // eslint-disable-next-line react-internal/safe-string-coercion + return "" + value; + } + function checkKeyStringCoercion(value) { + { + if (willCoercionThrow(value)) { + error( + "The provided key is an unsupported type %s." + + " This value must be coerced to a string before using it here.", + typeName(value) + ); - if (oldIndex < lastPlacedIndex) { - // This is a move. - newFiber.flags |= Placement | PlacementDEV; - return lastPlacedIndex; - } else { - // This item can stay in place. - return oldIndex; - } - } else { - // This is an insertion. - newFiber.flags |= Placement | PlacementDEV; - return lastPlacedIndex; + return testStringCoercion(value); // throw (to help callers find troubleshooting comments) } } + } + function checkPropStringCoercion(value, propName) { + { + if (willCoercionThrow(value)) { + error( + "The provided `%s` prop is an unsupported type %s." + + " This value must be coerced to a string before using it here.", + propName, + typeName(value) + ); - function placeSingleChild(newFiber) { - // This is simpler for the single child case. We only need to do a - // placement for inserting new children. - if (shouldTrackSideEffects && newFiber.alternate === null) { - newFiber.flags |= Placement | PlacementDEV; + return testStringCoercion(value); // throw (to help callers find troubleshooting comments) } - - return newFiber; } + } - function updateTextNode(returnFiber, current, textContent, lanes) { - if (current === null || current.tag !== HostText) { - // Insert - var created = createFiberFromText( - textContent, - returnFiber.mode, - lanes - ); - created.return = returnFiber; - return created; - } else { - // Update - var existing = useFiber(current, textContent); - existing.return = returnFiber; - return existing; - } - } + var ReactCurrentActQueue$2 = ReactSharedInternals.ReactCurrentActQueue; // An error that is thrown (e.g. by `use`) to trigger Suspense. If we + // detect this is caught by userspace, we'll log a warning in development. - function updateElement(returnFiber, current, element, lanes) { - var elementType = element.type; + var SuspenseException = new Error( + "Suspense Exception: This is not a real error! It's an implementation " + + "detail of `use` to interrupt the current render. You must either " + + "rethrow it immediately, or move the `use` call outside of the " + + "`try/catch` block. Capturing without rethrowing will lead to " + + "unexpected behavior.\n\n" + + "To handle async errors, wrap your component in an error boundary, or " + + "call the promise's `.catch` method and pass the result to `use`" + ); + var SuspenseyCommitException = new Error( + "Suspense Exception: This is not a real error, and should not leak into " + + "userspace. If you're seeing this, it's likely a bug in React." + ); // This is a noop thenable that we use to trigger a fallback in throwException. + // TODO: It would be better to refactor throwException into multiple functions + // so we can trigger a fallback directly without having to check the type. But + // for now this will do. - if (elementType === REACT_FRAGMENT_TYPE) { - return updateFragment( - returnFiber, - current, - element.props.children, - lanes, - element.key + var noopSuspenseyCommitThenable = { + then: function () { + { + error( + "Internal React error: A listener was unexpectedly attached to a " + + '"noop" thenable. This is a bug in React. Please file an issue.' ); } + } + }; + function createThenableState() { + // The ThenableState is created the first time a component suspends. If it + // suspends again, we'll reuse the same state. + return []; + } + function isThenableResolved(thenable) { + var status = thenable.status; + return status === "fulfilled" || status === "rejected"; + } - if (current !== null) { - if ( - current.elementType === elementType || // Keep this check inline so it only runs on the false path: - isCompatibleFamilyForHotReloading(current, element) || // Lazy types should reconcile their resolved type. - // We need to do this after the Hot Reloading check above, - // because hot reloading has different semantics than prod because - // it doesn't resuspend. So we can't let the call below suspend. - (typeof elementType === "object" && - elementType !== null && - elementType.$$typeof === REACT_LAZY_TYPE && - resolveLazy(elementType) === current.type) - ) { - // Move based on index - var existing = useFiber(current, element.props); - existing.ref = coerceRef(returnFiber, current, element); - existing.return = returnFiber; - - { - existing._debugSource = element._source; - existing._debugOwner = element._owner; - } - - return existing; - } - } // Insert + function noop() {} - var created = createFiberFromElement(element, returnFiber.mode, lanes); - created.ref = coerceRef(returnFiber, current, element); - created.return = returnFiber; - return created; + function trackUsedThenable(thenableState, thenable, index) { + if (ReactCurrentActQueue$2.current !== null) { + ReactCurrentActQueue$2.didUsePromise = true; } - function updatePortal(returnFiber, current, portal, lanes) { - if ( - current === null || - current.tag !== HostPortal || - current.stateNode.containerInfo !== portal.containerInfo || - current.stateNode.implementation !== portal.implementation - ) { - // Insert - var created = createFiberFromPortal(portal, returnFiber.mode, lanes); - created.return = returnFiber; - return created; - } else { - // Update - var existing = useFiber(current, portal.children || []); - existing.return = returnFiber; - return existing; - } - } + var previous = thenableState[index]; - function updateFragment(returnFiber, current, fragment, lanes, key) { - if (current === null || current.tag !== Fragment) { - // Insert - var created = createFiberFromFragment( - fragment, - returnFiber.mode, - lanes, - key - ); - created.return = returnFiber; - return created; - } else { - // Update - var existing = useFiber(current, fragment); - existing.return = returnFiber; - return existing; + if (previous === undefined) { + thenableState.push(thenable); + } else { + if (previous !== thenable) { + // Reuse the previous thenable, and drop the new one. We can assume + // they represent the same value, because components are idempotent. + // Avoid an unhandled rejection errors for the Promises that we'll + // intentionally ignore. + thenable.then(noop, noop); + thenable = previous; } - } - - function createChild(returnFiber, newChild, lanes) { - if ( - (typeof newChild === "string" && newChild !== "") || - typeof newChild === "number" - ) { - // Text nodes don't have keys. If the previous node is implicitly keyed - // we can continue to replace it without aborting even if it is not a text - // node. - var created = createFiberFromText( - "" + newChild, - returnFiber.mode, - lanes - ); - created.return = returnFiber; - return created; + } // We use an expando to track the status and result of a thenable so that we + // can synchronously unwrap the value. Think of this as an extension of the + // Promise API, or a custom interface that is a superset of Thenable. + // + // If the thenable doesn't have a status, set it to "pending" and attach + // a listener that will update its status and result when it resolves. + + switch (thenable.status) { + case "fulfilled": { + var fulfilledValue = thenable.value; + return fulfilledValue; } - if (typeof newChild === "object" && newChild !== null) { - switch (newChild.$$typeof) { - case REACT_ELEMENT_TYPE: { - var _created = createFiberFromElement( - newChild, - returnFiber.mode, - lanes - ); + case "rejected": { + var rejectedError = thenable.reason; + checkIfUseWrappedInAsyncCatch(rejectedError); + throw rejectedError; + } - _created.ref = coerceRef(returnFiber, null, newChild); - _created.return = returnFiber; - return _created; - } + default: { + if (typeof thenable.status === "string") { + // Only instrument the thenable if the status if not defined. If + // it's defined, but an unknown value, assume it's been instrumented by + // some custom userspace implementation. We treat it as "pending". + // Attach a dummy listener, to ensure that any lazy initialization can + // happen. Flight lazily parses JSON when the value is actually awaited. + thenable.then(noop, noop); + } else { + // This is an uncached thenable that we haven't seen before. + // Detect infinite ping loops caused by uncached promises. + var root = getWorkInProgressRoot(); - case REACT_PORTAL_TYPE: { - var _created2 = createFiberFromPortal( - newChild, - returnFiber.mode, - lanes + if (root !== null && root.shellSuspendCounter > 100) { + // This root has suspended repeatedly in the shell without making any + // progress (i.e. committing something). This is highly suggestive of + // an infinite ping loop, often caused by an accidental Async Client + // Component. + // + // During a transition, we can suspend the work loop until the promise + // to resolve, but this is a sync render, so that's not an option. We + // also can't show a fallback, because none was provided. So our last + // resort is to throw an error. + // + // TODO: Remove this error in a future release. Other ways of handling + // this case include forcing a concurrent render, or putting the whole + // root into offscreen mode. + throw new Error( + "async/await is not yet supported in Client Components, only " + + "Server Components. This error is often caused by accidentally " + + "adding `'use client'` to a module that was originally written " + + "for the server." ); - - _created2.return = returnFiber; - return _created2; } - case REACT_LAZY_TYPE: { - var payload = newChild._payload; - var init = newChild._init; - return createChild(returnFiber, init(payload), lanes); - } - } + var pendingThenable = thenable; + pendingThenable.status = "pending"; + pendingThenable.then( + function (fulfilledValue) { + if (thenable.status === "pending") { + var fulfilledThenable = thenable; + fulfilledThenable.status = "fulfilled"; + fulfilledThenable.value = fulfilledValue; + } + }, + function (error) { + if (thenable.status === "pending") { + var rejectedThenable = thenable; + rejectedThenable.status = "rejected"; + rejectedThenable.reason = error; + } + } + ); // Check one more time in case the thenable resolved synchronously. - if (isArray(newChild) || getIteratorFn(newChild)) { - var _created3 = createFiberFromFragment( - newChild, - returnFiber.mode, - lanes, - null - ); + switch (thenable.status) { + case "fulfilled": { + var fulfilledThenable = thenable; + return fulfilledThenable.value; + } - _created3.return = returnFiber; - return _created3; - } // Usable node types + case "rejected": { + var rejectedThenable = thenable; + var _rejectedError = rejectedThenable.reason; + checkIfUseWrappedInAsyncCatch(_rejectedError); + throw _rejectedError; + } + } + } // Suspend. // - // Unwrap the inner value and recursively call this function again. + // Throwing here is an implementation detail that allows us to unwind the + // call stack. But we shouldn't allow it to leak into userspace. Throw an + // opaque placeholder value instead of the actual thenable. If it doesn't + // get captured by the work loop, log a warning, because that means + // something in userspace must have caught it. - if (typeof newChild.then === "function") { - var thenable = newChild; - return createChild(returnFiber, unwrapThenable(thenable), lanes); - } + suspendedThenable = thenable; - if ( - newChild.$$typeof === REACT_CONTEXT_TYPE || - newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE - ) { - var context = newChild; - return createChild( - returnFiber, - readContextDuringReconcilation(returnFiber, context, lanes), - lanes - ); + { + needsToResetSuspendedThenableDEV = true; } - throwOnInvalidObjectType(returnFiber, newChild); - } - - { - if (typeof newChild === "function") { - warnOnFunctionType(returnFiber); - } + throw SuspenseException; } + } + } + // passed to the rest of the Suspense implementation — which, for historical + // reasons, expects to receive a thenable. - return null; + var suspendedThenable = null; + var needsToResetSuspendedThenableDEV = false; + function getSuspendedThenable() { + // This is called right after `use` suspends by throwing an exception. `use` + // throws an opaque value instead of the thenable itself so that it can't be + // caught in userspace. Then the work loop accesses the actual thenable using + // this function. + if (suspendedThenable === null) { + throw new Error( + "Expected a suspended thenable. This is a bug in React. Please file " + + "an issue." + ); } - function updateSlot(returnFiber, oldFiber, newChild, lanes) { - // Update the fiber if the keys match, otherwise return null. - var key = oldFiber !== null ? oldFiber.key : null; + var thenable = suspendedThenable; + suspendedThenable = null; - if ( - (typeof newChild === "string" && newChild !== "") || - typeof newChild === "number" - ) { - // Text nodes don't have keys. If the previous node is implicitly keyed - // we can continue to replace it without aborting even if it is not a text - // node. - if (key !== null) { - return null; - } + { + needsToResetSuspendedThenableDEV = false; + } - return updateTextNode(returnFiber, oldFiber, "" + newChild, lanes); + return thenable; + } + function checkIfUseWrappedInTryCatch() { + { + // This was set right before SuspenseException was thrown, and it should + // have been cleared when the exception was handled. If it wasn't, + // it must have been caught by userspace. + if (needsToResetSuspendedThenableDEV) { + needsToResetSuspendedThenableDEV = false; + return true; } + } - if (typeof newChild === "object" && newChild !== null) { - switch (newChild.$$typeof) { - case REACT_ELEMENT_TYPE: { - if (newChild.key === key) { - return updateElement(returnFiber, oldFiber, newChild, lanes); - } else { - return null; - } - } - - case REACT_PORTAL_TYPE: { - if (newChild.key === key) { - return updatePortal(returnFiber, oldFiber, newChild, lanes); - } else { - return null; - } - } - - case REACT_LAZY_TYPE: { - var payload = newChild._payload; - var init = newChild._init; - return updateSlot(returnFiber, oldFiber, init(payload), lanes); - } - } + return false; + } + function checkIfUseWrappedInAsyncCatch(rejectedReason) { + // This check runs in prod, too, because it prevents a more confusing + // downstream error, where SuspenseException is caught by a promise and + // thrown asynchronously. + // TODO: Another way to prevent SuspenseException from leaking into an async + // execution context is to check the dispatcher every time `use` is called, + // or some equivalent. That might be preferable for other reasons, too, since + // it matches how we prevent similar mistakes for other hooks. + if (rejectedReason === SuspenseException) { + throw new Error( + "Hooks are not supported inside an async component. This " + + "error is often caused by accidentally adding `'use client'` " + + "to a module that was originally written for the server." + ); + } + } - if (isArray(newChild) || getIteratorFn(newChild)) { - if (key !== null) { - return null; - } + var thenableState$1 = null; + var thenableIndexCounter$1 = 0; + var didWarnAboutMaps; + var didWarnAboutGenerators; + var didWarnAboutStringRefs; + var ownerHasKeyUseWarning; + var ownerHasFunctionTypeWarning; - return updateFragment(returnFiber, oldFiber, newChild, lanes, null); - } // Usable node types - // - // Unwrap the inner value and recursively call this function again. + var warnForMissingKey = function (child, returnFiber) {}; - if (typeof newChild.then === "function") { - var thenable = newChild; - return updateSlot( - returnFiber, - oldFiber, - unwrapThenable(thenable), - lanes - ); - } + { + didWarnAboutMaps = false; + didWarnAboutGenerators = false; + didWarnAboutStringRefs = {}; + /** + * Warn if there's no key explicitly set on dynamic arrays of children or + * object keys are not valid. This allows us to keep track of children between + * updates. + */ - if ( - newChild.$$typeof === REACT_CONTEXT_TYPE || - newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE - ) { - var context = newChild; - return updateSlot( - returnFiber, - oldFiber, - readContextDuringReconcilation(returnFiber, context, lanes), - lanes - ); - } + ownerHasKeyUseWarning = {}; + ownerHasFunctionTypeWarning = {}; - throwOnInvalidObjectType(returnFiber, newChild); + warnForMissingKey = function (child, returnFiber) { + if (child === null || typeof child !== "object") { + return; } - { - if (typeof newChild === "function") { - warnOnFunctionType(returnFiber); - } + if (!child._store || child._store.validated || child.key != null) { + return; } - return null; - } - - function updateFromMap( - existingChildren, - returnFiber, - newIdx, - newChild, - lanes - ) { - if ( - (typeof newChild === "string" && newChild !== "") || - typeof newChild === "number" - ) { - // Text nodes don't have keys, so we neither have to check the old nor - // new node for the key. If both are text nodes, they match. - var matchedFiber = existingChildren.get(newIdx) || null; - return updateTextNode( - returnFiber, - matchedFiber, - "" + newChild, - lanes + if (typeof child._store !== "object") { + throw new Error( + "React Component in warnForMissingKey should have a _store. " + + "This error is likely caused by a bug in React. Please file an issue." ); + } // $FlowFixMe[cannot-write] unable to narrow type from mixed to writable object + + child._store.validated = true; + var componentName = + getComponentNameFromFiber(returnFiber) || "Component"; + + if (ownerHasKeyUseWarning[componentName]) { + return; } - if (typeof newChild === "object" && newChild !== null) { - switch (newChild.$$typeof) { - case REACT_ELEMENT_TYPE: { - var _matchedFiber = - existingChildren.get( - newChild.key === null ? newIdx : newChild.key - ) || null; + ownerHasKeyUseWarning[componentName] = true; - return updateElement(returnFiber, _matchedFiber, newChild, lanes); - } + error( + "Each child in a list should have a unique " + + '"key" prop. See https://reactjs.org/link/warning-keys for ' + + "more information." + ); + }; + } - case REACT_PORTAL_TYPE: { - var _matchedFiber2 = - existingChildren.get( - newChild.key === null ? newIdx : newChild.key - ) || null; + function isReactClass(type) { + return type.prototype && type.prototype.isReactComponent; + } - return updatePortal(returnFiber, _matchedFiber2, newChild, lanes); - } + function unwrapThenable(thenable) { + var index = thenableIndexCounter$1; + thenableIndexCounter$1 += 1; - case REACT_LAZY_TYPE: - var payload = newChild._payload; - var init = newChild._init; - return updateFromMap( - existingChildren, - returnFiber, - newIdx, - init(payload), - lanes + if (thenableState$1 === null) { + thenableState$1 = createThenableState(); + } + + return trackUsedThenable(thenableState$1, thenable, index); + } + + function coerceRef(returnFiber, current, element) { + var mixedRef = element.ref; + + if ( + mixedRef !== null && + typeof mixedRef !== "function" && + typeof mixedRef !== "object" + ) { + { + if ( + // We warn in ReactElement.js if owner and self are equal for string refs + // because these cannot be automatically converted to an arrow function + // using a codemod. Therefore, we don't have to warn about string refs again. + !( + element._owner && + element._self && + element._owner.stateNode !== element._self + ) && // Will already throw with "Function components cannot have string refs" + !(element._owner && element._owner.tag !== ClassComponent) && // Will already warn with "Function components cannot be given refs" + !( + typeof element.type === "function" && !isReactClass(element.type) + ) && // Will already throw with "Element ref was specified as a string (someStringRef) but no owner was set" + element._owner + ) { + var componentName = + getComponentNameFromFiber(returnFiber) || "Component"; + + if (!didWarnAboutStringRefs[componentName]) { + error( + 'Component "%s" contains the string ref "%s". Support for string refs ' + + "will be removed in a future major release. We recommend using " + + "useRef() or createRef() instead. " + + "Learn more about using refs safely here: " + + "https://reactjs.org/link/strict-mode-string-ref", + componentName, + mixedRef ); + + didWarnAboutStringRefs[componentName] = true; + } } + } - if (isArray(newChild) || getIteratorFn(newChild)) { - var _matchedFiber3 = existingChildren.get(newIdx) || null; + if (element._owner) { + var owner = element._owner; + var inst; - return updateFragment( - returnFiber, - _matchedFiber3, - newChild, - lanes, - null - ); - } // Usable node types - // - // Unwrap the inner value and recursively call this function again. + if (owner) { + var ownerFiber = owner; - if (typeof newChild.then === "function") { - var thenable = newChild; - return updateFromMap( - existingChildren, - returnFiber, - newIdx, - unwrapThenable(thenable), - lanes - ); + if (ownerFiber.tag !== ClassComponent) { + throw new Error( + "Function components cannot have string refs. " + + "We recommend using useRef() instead. " + + "Learn more about using refs safely here: " + + "https://reactjs.org/link/strict-mode-string-ref" + ); + } + + inst = ownerFiber.stateNode; } - if ( - newChild.$$typeof === REACT_CONTEXT_TYPE || - newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE - ) { - var context = newChild; - return updateFromMap( - existingChildren, - returnFiber, - newIdx, - readContextDuringReconcilation(returnFiber, context, lanes), - lanes + if (!inst) { + throw new Error( + "Missing owner for string ref " + + mixedRef + + ". This error is likely caused by a " + + "bug in React. Please file an issue." ); - } + } // Assigning this to a const so Flow knows it won't change in the closure - throwOnInvalidObjectType(returnFiber, newChild); - } + var resolvedInst = inst; - { - if (typeof newChild === "function") { - warnOnFunctionType(returnFiber); + { + checkPropStringCoercion(mixedRef, "ref"); } - } - return null; - } - /** - * Warns if there is a duplicate or missing key - */ + var stringRef = "" + mixedRef; // Check if previous string ref matches new string ref - function warnOnInvalidKey(child, knownKeys, returnFiber) { - { - if (typeof child !== "object" || child === null) { - return knownKeys; + if ( + current !== null && + current.ref !== null && + typeof current.ref === "function" && + current.ref._stringRef === stringRef + ) { + return current.ref; } - switch (child.$$typeof) { - case REACT_ELEMENT_TYPE: - case REACT_PORTAL_TYPE: - warnForMissingKey(child, returnFiber); - var key = child.key; + var ref = function (value) { + var refs = resolvedInst.refs; - if (typeof key !== "string") { - break; - } + if (value === null) { + delete refs[stringRef]; + } else { + refs[stringRef] = value; + } + }; + + ref._stringRef = stringRef; + return ref; + } else { + if (typeof mixedRef !== "string") { + throw new Error( + "Expected ref to be a function, a string, an object returned by React.createRef(), or null." + ); + } - if (knownKeys === null) { - knownKeys = new Set(); - knownKeys.add(key); - break; - } + if (!element._owner) { + throw new Error( + "Element ref was specified as a string (" + + mixedRef + + ") but no owner was set. This could happen for one of" + + " the following reasons:\n" + + "1. You may be adding a ref to a function component\n" + + "2. You may be adding a ref to a component that was not created inside a component's render method\n" + + "3. You have multiple copies of React loaded\n" + + "See https://reactjs.org/link/refs-must-have-owner for more information." + ); + } + } + } - if (!knownKeys.has(key)) { - knownKeys.add(key); - break; - } + return mixedRef; + } - error( - "Encountered two children with the same key, `%s`. " + - "Keys should be unique so that components maintain their identity " + - "across updates. Non-unique keys may cause children to be " + - "duplicated and/or omitted — the behavior is unsupported and " + - "could change in a future version.", - key - ); + function throwOnInvalidObjectType(returnFiber, newChild) { + // $FlowFixMe[method-unbinding] + var childString = Object.prototype.toString.call(newChild); + throw new Error( + "Objects are not valid as a React child (found: " + + (childString === "[object Object]" + ? "object with keys {" + Object.keys(newChild).join(", ") + "}" + : childString) + + "). " + + "If you meant to render a collection of children, use an array " + + "instead." + ); + } - break; + function warnOnFunctionType(returnFiber) { + { + var componentName = + getComponentNameFromFiber(returnFiber) || "Component"; - case REACT_LAZY_TYPE: - var payload = child._payload; - var init = child._init; - warnOnInvalidKey(init(payload), knownKeys, returnFiber); - break; - } + if (ownerHasFunctionTypeWarning[componentName]) { + return; } - return knownKeys; + ownerHasFunctionTypeWarning[componentName] = true; + + error( + "Functions are not valid as a React child. This may happen if " + + "you return a Component instead of from render. " + + "Or maybe you meant to call this function rather than return it." + ); } + } - function reconcileChildrenArray( - returnFiber, - currentFirstChild, - newChildren, - lanes - ) { - // This algorithm can't optimize by searching from both ends since we - // don't have backpointers on fibers. I'm trying to see how far we can get - // with that model. If it ends up not being worth the tradeoffs, we can - // add it later. - // Even with a two ended optimization, we'd want to optimize for the case - // where there are few changes and brute force the comparison instead of - // going for the Map. It'd like to explore hitting that path first in - // forward-only mode and only go for the Map once we notice that we need - // lots of look ahead. This doesn't handle reversal as well as two ended - // search but that's unusual. Besides, for the two ended optimization to - // work on Iterables, we'd need to copy the whole set. - // In this first iteration, we'll just live with hitting the bad case - // (adding everything to a Map) in for every insert/move. - // If you change this code, also update reconcileChildrenIterator() which - // uses the same algorithm. - { - // First, validate keys. - var knownKeys = null; + function resolveLazy(lazyType) { + var payload = lazyType._payload; + var init = lazyType._init; + return init(payload); + } // This wrapper function exists because I expect to clone the code in each path + // to be able to optimize each path individually by branching early. This needs + // a compiler or we can do it manually. Helpers that don't need this branching + // live outside of this function. - for (var i = 0; i < newChildren.length; i++) { - var child = newChildren[i]; - knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); - } + function createChildReconciler(shouldTrackSideEffects) { + function deleteChild(returnFiber, childToDelete) { + if (!shouldTrackSideEffects) { + // Noop. + return; } - var resultingFirstChild = null; - var previousNewFiber = null; - var oldFiber = currentFirstChild; - var lastPlacedIndex = 0; - var newIdx = 0; - var nextOldFiber = null; + var deletions = returnFiber.deletions; - for (; oldFiber !== null && newIdx < newChildren.length; newIdx++) { - if (oldFiber.index > newIdx) { - nextOldFiber = oldFiber; - oldFiber = null; - } else { - nextOldFiber = oldFiber.sibling; - } + if (deletions === null) { + returnFiber.deletions = [childToDelete]; + returnFiber.flags |= ChildDeletion; + } else { + deletions.push(childToDelete); + } + } - var newFiber = updateSlot( - returnFiber, - oldFiber, - newChildren[newIdx], - lanes - ); + function deleteRemainingChildren(returnFiber, currentFirstChild) { + if (!shouldTrackSideEffects) { + // Noop. + return null; + } // TODO: For the shouldClone case, this could be micro-optimized a bit by + // assuming that after the first child we've already added everything. - if (newFiber === null) { - // TODO: This breaks on empty slots like null children. That's - // unfortunate because it triggers the slow path all the time. We need - // a better way to communicate whether this was a miss or null, - // boolean, undefined, etc. - if (oldFiber === null) { - oldFiber = nextOldFiber; - } + var childToDelete = currentFirstChild; - break; - } + while (childToDelete !== null) { + deleteChild(returnFiber, childToDelete); + childToDelete = childToDelete.sibling; + } - if (shouldTrackSideEffects) { - if (oldFiber && newFiber.alternate === null) { - // We matched the slot, but we didn't reuse the existing fiber, so we - // need to delete the existing child. - deleteChild(returnFiber, oldFiber); - } - } + return null; + } - lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx); + function mapRemainingChildren(returnFiber, currentFirstChild) { + // Add the remaining children to a temporary map so that we can find them by + // keys quickly. Implicit (null) keys get added to this set with their index + // instead. + var existingChildren = new Map(); + var existingChild = currentFirstChild; - if (previousNewFiber === null) { - // TODO: Move out of the loop. This only happens for the first run. - resultingFirstChild = newFiber; + while (existingChild !== null) { + if (existingChild.key !== null) { + existingChildren.set(existingChild.key, existingChild); } else { - // TODO: Defer siblings if we're not at the right index for this slot. - // I.e. if we had null values before, then we want to defer this - // for each null value. However, we also don't want to call updateSlot - // with the previous one. - previousNewFiber.sibling = newFiber; + existingChildren.set(existingChild.index, existingChild); } - previousNewFiber = newFiber; - oldFiber = nextOldFiber; + existingChild = existingChild.sibling; } - if (newIdx === newChildren.length) { - // We've reached the end of the new children. We can delete the rest. - deleteRemainingChildren(returnFiber, oldFiber); + return existingChildren; + } - return resultingFirstChild; - } + function useFiber(fiber, pendingProps) { + // We currently set sibling to null and index to 0 here because it is easy + // to forget to do before returning it. E.g. for the single child case. + var clone = createWorkInProgress(fiber, pendingProps); + clone.index = 0; + clone.sibling = null; + return clone; + } - if (oldFiber === null) { - // If we don't have any more existing children we can choose a fast path - // since the rest will all be insertions. - for (; newIdx < newChildren.length; newIdx++) { - var _newFiber = createChild( - returnFiber, - newChildren[newIdx], - lanes - ); + function placeChild(newFiber, lastPlacedIndex, newIndex) { + newFiber.index = newIndex; - if (_newFiber === null) { - continue; - } + if (!shouldTrackSideEffects) { + // During hydration, the useId algorithm needs to know which fibers are + // part of a list of children (arrays, iterators). + newFiber.flags |= Forked; + return lastPlacedIndex; + } - lastPlacedIndex = placeChild(_newFiber, lastPlacedIndex, newIdx); + var current = newFiber.alternate; - if (previousNewFiber === null) { - // TODO: Move out of the loop. This only happens for the first run. - resultingFirstChild = _newFiber; - } else { - previousNewFiber.sibling = _newFiber; - } + if (current !== null) { + var oldIndex = current.index; - previousNewFiber = _newFiber; + if (oldIndex < lastPlacedIndex) { + // This is a move. + newFiber.flags |= Placement | PlacementDEV; + return lastPlacedIndex; + } else { + // This item can stay in place. + return oldIndex; } + } else { + // This is an insertion. + newFiber.flags |= Placement | PlacementDEV; + return lastPlacedIndex; + } + } - return resultingFirstChild; - } // Add all children to a key map for quick lookups. + function placeSingleChild(newFiber) { + // This is simpler for the single child case. We only need to do a + // placement for inserting new children. + if (shouldTrackSideEffects && newFiber.alternate === null) { + newFiber.flags |= Placement | PlacementDEV; + } - var existingChildren = mapRemainingChildren(returnFiber, oldFiber); // Keep scanning and use the map to restore deleted items as moves. + return newFiber; + } - for (; newIdx < newChildren.length; newIdx++) { - var _newFiber2 = updateFromMap( - existingChildren, - returnFiber, - newIdx, - newChildren[newIdx], + function updateTextNode(returnFiber, current, textContent, lanes) { + if (current === null || current.tag !== HostText) { + // Insert + var created = createFiberFromText( + textContent, + returnFiber.mode, lanes ); + created.return = returnFiber; + return created; + } else { + // Update + var existing = useFiber(current, textContent); + existing.return = returnFiber; + return existing; + } + } - if (_newFiber2 !== null) { - if (shouldTrackSideEffects) { - if (_newFiber2.alternate !== null) { - // The new fiber is a work in progress, but if there exists a - // current, that means that we reused the fiber. We need to delete - // it from the child list so that we don't add it to the deletion - // list. - existingChildren.delete( - _newFiber2.key === null ? newIdx : _newFiber2.key - ); - } - } + function updateElement(returnFiber, current, element, lanes) { + var elementType = element.type; - lastPlacedIndex = placeChild(_newFiber2, lastPlacedIndex, newIdx); + if (elementType === REACT_FRAGMENT_TYPE) { + return updateFragment( + returnFiber, + current, + element.props.children, + lanes, + element.key + ); + } - if (previousNewFiber === null) { - resultingFirstChild = _newFiber2; - } else { - previousNewFiber.sibling = _newFiber2; + if (current !== null) { + if ( + current.elementType === elementType || // Keep this check inline so it only runs on the false path: + isCompatibleFamilyForHotReloading(current, element) || // Lazy types should reconcile their resolved type. + // We need to do this after the Hot Reloading check above, + // because hot reloading has different semantics than prod because + // it doesn't resuspend. So we can't let the call below suspend. + (typeof elementType === "object" && + elementType !== null && + elementType.$$typeof === REACT_LAZY_TYPE && + resolveLazy(elementType) === current.type) + ) { + // Move based on index + var existing = useFiber(current, element.props); + existing.ref = coerceRef(returnFiber, current, element); + existing.return = returnFiber; + + { + existing._debugSource = element._source; + existing._debugOwner = element._owner; } - previousNewFiber = _newFiber2; + return existing; } - } + } // Insert - if (shouldTrackSideEffects) { - // Any existing children that weren't consumed above were deleted. We need - // to add them to the deletion list. - existingChildren.forEach(function (child) { - return deleteChild(returnFiber, child); - }); - } + var created = createFiberFromElement(element, returnFiber.mode, lanes); + created.ref = coerceRef(returnFiber, current, element); + created.return = returnFiber; + return created; + } - return resultingFirstChild; + function updatePortal(returnFiber, current, portal, lanes) { + if ( + current === null || + current.tag !== HostPortal || + current.stateNode.containerInfo !== portal.containerInfo || + current.stateNode.implementation !== portal.implementation + ) { + // Insert + var created = createFiberFromPortal(portal, returnFiber.mode, lanes); + created.return = returnFiber; + return created; + } else { + // Update + var existing = useFiber(current, portal.children || []); + existing.return = returnFiber; + return existing; + } } - function reconcileChildrenIterator( - returnFiber, - currentFirstChild, - newChildrenIterable, - lanes - ) { - // This is the same implementation as reconcileChildrenArray(), - // but using the iterator instead. - var iteratorFn = getIteratorFn(newChildrenIterable); + function updateFragment(returnFiber, current, fragment, lanes, key) { + if (current === null || current.tag !== Fragment) { + // Insert + var created = createFiberFromFragment( + fragment, + returnFiber.mode, + lanes, + key + ); + created.return = returnFiber; + return created; + } else { + // Update + var existing = useFiber(current, fragment); + existing.return = returnFiber; + return existing; + } + } - if (typeof iteratorFn !== "function") { - throw new Error( - "An object is not an iterable. This error is likely caused by a bug in " + - "React. Please file an issue." + function createChild(returnFiber, newChild, lanes) { + if ( + (typeof newChild === "string" && newChild !== "") || + typeof newChild === "number" + ) { + // Text nodes don't have keys. If the previous node is implicitly keyed + // we can continue to replace it without aborting even if it is not a text + // node. + var created = createFiberFromText( + "" + newChild, + returnFiber.mode, + lanes ); + created.return = returnFiber; + return created; } - { - // We don't support rendering Generators because it's a mutation. - // See https://github.com/facebook/react/issues/12995 - if ( - typeof Symbol === "function" && // $FlowFixMe[prop-missing] Flow doesn't know about toStringTag - newChildrenIterable[Symbol.toStringTag] === "Generator" - ) { - if (!didWarnAboutGenerators) { - error( - "Using Generators as children is unsupported and will likely yield " + - "unexpected results because enumerating a generator mutates it. " + - "You may convert it to an array with `Array.from()` or the " + - "`[...spread]` operator before rendering. Keep in mind " + - "you might need to polyfill these features for older browsers." + if (typeof newChild === "object" && newChild !== null) { + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE: { + var _created = createFiberFromElement( + newChild, + returnFiber.mode, + lanes ); - } - - didWarnAboutGenerators = true; - } // Warn about using Maps as children - if (newChildrenIterable.entries === iteratorFn) { - if (!didWarnAboutMaps) { - error( - "Using Maps as children is not supported. " + - "Use an array of keyed ReactElements instead." - ); + _created.ref = coerceRef(returnFiber, null, newChild); + _created.return = returnFiber; + return _created; } - didWarnAboutMaps = true; - } // First, validate keys. - // We'll get a different iterator later for the main pass. - - var _newChildren = iteratorFn.call(newChildrenIterable); - - if (_newChildren) { - var knownKeys = null; + case REACT_PORTAL_TYPE: { + var _created2 = createFiberFromPortal( + newChild, + returnFiber.mode, + lanes + ); - var _step = _newChildren.next(); + _created2.return = returnFiber; + return _created2; + } - for (; !_step.done; _step = _newChildren.next()) { - var child = _step.value; - knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); + case REACT_LAZY_TYPE: { + var payload = newChild._payload; + var init = newChild._init; + return createChild(returnFiber, init(payload), lanes); } } - } - var newChildren = iteratorFn.call(newChildrenIterable); + if (isArray(newChild) || getIteratorFn(newChild)) { + var _created3 = createFiberFromFragment( + newChild, + returnFiber.mode, + lanes, + null + ); - if (newChildren == null) { - throw new Error("An iterable object provided no iterator."); - } + _created3.return = returnFiber; + return _created3; + } // Usable node types + // + // Unwrap the inner value and recursively call this function again. - var resultingFirstChild = null; - var previousNewFiber = null; - var oldFiber = currentFirstChild; - var lastPlacedIndex = 0; - var newIdx = 0; - var nextOldFiber = null; - var step = newChildren.next(); + if (typeof newChild.then === "function") { + var thenable = newChild; + return createChild(returnFiber, unwrapThenable(thenable), lanes); + } - for ( - ; - oldFiber !== null && !step.done; - newIdx++, step = newChildren.next() - ) { - if (oldFiber.index > newIdx) { - nextOldFiber = oldFiber; - oldFiber = null; - } else { - nextOldFiber = oldFiber.sibling; + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) { + var context = newChild; + return createChild( + returnFiber, + readContextDuringReconcilation(returnFiber, context, lanes), + lanes + ); } - var newFiber = updateSlot(returnFiber, oldFiber, step.value, lanes); - - if (newFiber === null) { - // TODO: This breaks on empty slots like null children. That's - // unfortunate because it triggers the slow path all the time. We need - // a better way to communicate whether this was a miss or null, - // boolean, undefined, etc. - if (oldFiber === null) { - oldFiber = nextOldFiber; - } + throwOnInvalidObjectType(returnFiber, newChild); + } - break; + { + if (typeof newChild === "function") { + warnOnFunctionType(returnFiber); } + } - if (shouldTrackSideEffects) { - if (oldFiber && newFiber.alternate === null) { - // We matched the slot, but we didn't reuse the existing fiber, so we - // need to delete the existing child. - deleteChild(returnFiber, oldFiber); - } - } + return null; + } - lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx); + function updateSlot(returnFiber, oldFiber, newChild, lanes) { + // Update the fiber if the keys match, otherwise return null. + var key = oldFiber !== null ? oldFiber.key : null; - if (previousNewFiber === null) { - // TODO: Move out of the loop. This only happens for the first run. - resultingFirstChild = newFiber; - } else { - // TODO: Defer siblings if we're not at the right index for this slot. - // I.e. if we had null values before, then we want to defer this - // for each null value. However, we also don't want to call updateSlot - // with the previous one. - previousNewFiber.sibling = newFiber; + if ( + (typeof newChild === "string" && newChild !== "") || + typeof newChild === "number" + ) { + // Text nodes don't have keys. If the previous node is implicitly keyed + // we can continue to replace it without aborting even if it is not a text + // node. + if (key !== null) { + return null; } - previousNewFiber = newFiber; - oldFiber = nextOldFiber; + return updateTextNode(returnFiber, oldFiber, "" + newChild, lanes); } - if (step.done) { - // We've reached the end of the new children. We can delete the rest. - deleteRemainingChildren(returnFiber, oldFiber); + if (typeof newChild === "object" && newChild !== null) { + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE: { + if (newChild.key === key) { + return updateElement(returnFiber, oldFiber, newChild, lanes); + } else { + return null; + } + } - return resultingFirstChild; - } + case REACT_PORTAL_TYPE: { + if (newChild.key === key) { + return updatePortal(returnFiber, oldFiber, newChild, lanes); + } else { + return null; + } + } - if (oldFiber === null) { - // If we don't have any more existing children we can choose a fast path - // since the rest will all be insertions. - for (; !step.done; newIdx++, step = newChildren.next()) { - var _newFiber3 = createChild(returnFiber, step.value, lanes); + case REACT_LAZY_TYPE: { + var payload = newChild._payload; + var init = newChild._init; + return updateSlot(returnFiber, oldFiber, init(payload), lanes); + } + } - if (_newFiber3 === null) { - continue; + if (isArray(newChild) || getIteratorFn(newChild)) { + if (key !== null) { + return null; } - lastPlacedIndex = placeChild(_newFiber3, lastPlacedIndex, newIdx); + return updateFragment(returnFiber, oldFiber, newChild, lanes, null); + } // Usable node types + // + // Unwrap the inner value and recursively call this function again. - if (previousNewFiber === null) { - // TODO: Move out of the loop. This only happens for the first run. - resultingFirstChild = _newFiber3; - } else { - previousNewFiber.sibling = _newFiber3; - } + if (typeof newChild.then === "function") { + var thenable = newChild; + return updateSlot( + returnFiber, + oldFiber, + unwrapThenable(thenable), + lanes + ); + } - previousNewFiber = _newFiber3; + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) { + var context = newChild; + return updateSlot( + returnFiber, + oldFiber, + readContextDuringReconcilation(returnFiber, context, lanes), + lanes + ); } - return resultingFirstChild; - } // Add all children to a key map for quick lookups. + throwOnInvalidObjectType(returnFiber, newChild); + } - var existingChildren = mapRemainingChildren(returnFiber, oldFiber); // Keep scanning and use the map to restore deleted items as moves. + { + if (typeof newChild === "function") { + warnOnFunctionType(returnFiber); + } + } - for (; !step.done; newIdx++, step = newChildren.next()) { - var _newFiber4 = updateFromMap( - existingChildren, + return null; + } + + function updateFromMap( + existingChildren, + returnFiber, + newIdx, + newChild, + lanes + ) { + if ( + (typeof newChild === "string" && newChild !== "") || + typeof newChild === "number" + ) { + // Text nodes don't have keys, so we neither have to check the old nor + // new node for the key. If both are text nodes, they match. + var matchedFiber = existingChildren.get(newIdx) || null; + return updateTextNode( returnFiber, - newIdx, - step.value, + matchedFiber, + "" + newChild, lanes ); + } - if (_newFiber4 !== null) { - if (shouldTrackSideEffects) { - if (_newFiber4.alternate !== null) { - // The new fiber is a work in progress, but if there exists a - // current, that means that we reused the fiber. We need to delete - // it from the child list so that we don't add it to the deletion - // list. - existingChildren.delete( - _newFiber4.key === null ? newIdx : _newFiber4.key - ); - } + if (typeof newChild === "object" && newChild !== null) { + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE: { + var _matchedFiber = + existingChildren.get( + newChild.key === null ? newIdx : newChild.key + ) || null; + + return updateElement(returnFiber, _matchedFiber, newChild, lanes); } - lastPlacedIndex = placeChild(_newFiber4, lastPlacedIndex, newIdx); + case REACT_PORTAL_TYPE: { + var _matchedFiber2 = + existingChildren.get( + newChild.key === null ? newIdx : newChild.key + ) || null; - if (previousNewFiber === null) { - resultingFirstChild = _newFiber4; - } else { - previousNewFiber.sibling = _newFiber4; + return updatePortal(returnFiber, _matchedFiber2, newChild, lanes); } - previousNewFiber = _newFiber4; + case REACT_LAZY_TYPE: + var payload = newChild._payload; + var init = newChild._init; + return updateFromMap( + existingChildren, + returnFiber, + newIdx, + init(payload), + lanes + ); } - } - - if (shouldTrackSideEffects) { - // Any existing children that weren't consumed above were deleted. We need - // to add them to the deletion list. - existingChildren.forEach(function (child) { - return deleteChild(returnFiber, child); - }); - } - - return resultingFirstChild; - } - - function reconcileSingleTextNode( - returnFiber, - currentFirstChild, - textContent, - lanes - ) { - // There's no need to check for keys on text nodes since we don't have a - // way to define them. - if (currentFirstChild !== null && currentFirstChild.tag === HostText) { - // We already have an existing node so let's just update it and delete - // the rest. - deleteRemainingChildren(returnFiber, currentFirstChild.sibling); - var existing = useFiber(currentFirstChild, textContent); - existing.return = returnFiber; - return existing; - } // The existing first child is not a text node so we need to create one - // and delete the existing ones. - deleteRemainingChildren(returnFiber, currentFirstChild); - var created = createFiberFromText(textContent, returnFiber.mode, lanes); - created.return = returnFiber; - return created; - } + if (isArray(newChild) || getIteratorFn(newChild)) { + var _matchedFiber3 = existingChildren.get(newIdx) || null; - function reconcileSingleElement( - returnFiber, - currentFirstChild, - element, - lanes - ) { - var key = element.key; - var child = currentFirstChild; + return updateFragment( + returnFiber, + _matchedFiber3, + newChild, + lanes, + null + ); + } // Usable node types + // + // Unwrap the inner value and recursively call this function again. - while (child !== null) { - // TODO: If key === null and child.key === null, then this only applies to - // the first item in the list. - if (child.key === key) { - var elementType = element.type; + if (typeof newChild.then === "function") { + var thenable = newChild; + return updateFromMap( + existingChildren, + returnFiber, + newIdx, + unwrapThenable(thenable), + lanes + ); + } - if (elementType === REACT_FRAGMENT_TYPE) { - if (child.tag === Fragment) { - deleteRemainingChildren(returnFiber, child.sibling); - var existing = useFiber(child, element.props.children); - existing.return = returnFiber; + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) { + var context = newChild; + return updateFromMap( + existingChildren, + returnFiber, + newIdx, + readContextDuringReconcilation(returnFiber, context, lanes), + lanes + ); + } - { - existing._debugSource = element._source; - existing._debugOwner = element._owner; - } + throwOnInvalidObjectType(returnFiber, newChild); + } - return existing; - } - } else { - if ( - child.elementType === elementType || // Keep this check inline so it only runs on the false path: - isCompatibleFamilyForHotReloading(child, element) || // Lazy types should reconcile their resolved type. - // We need to do this after the Hot Reloading check above, - // because hot reloading has different semantics than prod because - // it doesn't resuspend. So we can't let the call below suspend. - (typeof elementType === "object" && - elementType !== null && - elementType.$$typeof === REACT_LAZY_TYPE && - resolveLazy(elementType) === child.type) - ) { - deleteRemainingChildren(returnFiber, child.sibling); + { + if (typeof newChild === "function") { + warnOnFunctionType(returnFiber); + } + } - var _existing = useFiber(child, element.props); + return null; + } + /** + * Warns if there is a duplicate or missing key + */ - _existing.ref = coerceRef(returnFiber, child, element); - _existing.return = returnFiber; + function warnOnInvalidKey(child, knownKeys, returnFiber) { + { + if (typeof child !== "object" || child === null) { + return knownKeys; + } - { - _existing._debugSource = element._source; - _existing._debugOwner = element._owner; - } + switch (child.$$typeof) { + case REACT_ELEMENT_TYPE: + case REACT_PORTAL_TYPE: + warnForMissingKey(child, returnFiber); + var key = child.key; - return _existing; + if (typeof key !== "string") { + break; } - } // Didn't match. - - deleteRemainingChildren(returnFiber, child); - break; - } else { - deleteChild(returnFiber, child); - } - child = child.sibling; - } + if (knownKeys === null) { + knownKeys = new Set(); + knownKeys.add(key); + break; + } - if (element.type === REACT_FRAGMENT_TYPE) { - var created = createFiberFromFragment( - element.props.children, - returnFiber.mode, - lanes, - element.key - ); - created.return = returnFiber; - return created; - } else { - var _created4 = createFiberFromElement( - element, - returnFiber.mode, - lanes - ); + if (!knownKeys.has(key)) { + knownKeys.add(key); + break; + } - _created4.ref = coerceRef(returnFiber, currentFirstChild, element); - _created4.return = returnFiber; - return _created4; - } - } + error( + "Encountered two children with the same key, `%s`. " + + "Keys should be unique so that components maintain their identity " + + "across updates. Non-unique keys may cause children to be " + + "duplicated and/or omitted — the behavior is unsupported and " + + "could change in a future version.", + key + ); - function reconcileSinglePortal( - returnFiber, - currentFirstChild, - portal, - lanes - ) { - var key = portal.key; - var child = currentFirstChild; + break; - while (child !== null) { - // TODO: If key === null and child.key === null, then this only applies to - // the first item in the list. - if (child.key === key) { - if ( - child.tag === HostPortal && - child.stateNode.containerInfo === portal.containerInfo && - child.stateNode.implementation === portal.implementation - ) { - deleteRemainingChildren(returnFiber, child.sibling); - var existing = useFiber(child, portal.children || []); - existing.return = returnFiber; - return existing; - } else { - deleteRemainingChildren(returnFiber, child); + case REACT_LAZY_TYPE: + var payload = child._payload; + var init = child._init; + warnOnInvalidKey(init(payload), knownKeys, returnFiber); break; - } - } else { - deleteChild(returnFiber, child); } - - child = child.sibling; } - var created = createFiberFromPortal(portal, returnFiber.mode, lanes); - created.return = returnFiber; - return created; - } // This API will tag the children with the side-effect of the reconciliation - // itself. They will be added to the side-effect list as we pass through the - // children and the parent. + return knownKeys; + } - function reconcileChildFibersImpl( + function reconcileChildrenArray( returnFiber, currentFirstChild, - newChild, + newChildren, lanes ) { - // This function is not recursive. - // If the top level item is an array, we treat it as a set of children, - // not as a fragment. Nested arrays on the other hand will be treated as - // fragment nodes. Recursion happens at the normal flow. - // Handle top level unkeyed fragments as if they were arrays. - // This leads to an ambiguity between <>{[...]} and <>.... - // We treat the ambiguous cases above the same. - // TODO: Let's use recursion like we do for Usable nodes? - var isUnkeyedTopLevelFragment = - typeof newChild === "object" && - newChild !== null && - newChild.type === REACT_FRAGMENT_TYPE && - newChild.key === null; + // This algorithm can't optimize by searching from both ends since we + // don't have backpointers on fibers. I'm trying to see how far we can get + // with that model. If it ends up not being worth the tradeoffs, we can + // add it later. + // Even with a two ended optimization, we'd want to optimize for the case + // where there are few changes and brute force the comparison instead of + // going for the Map. It'd like to explore hitting that path first in + // forward-only mode and only go for the Map once we notice that we need + // lots of look ahead. This doesn't handle reversal as well as two ended + // search but that's unusual. Besides, for the two ended optimization to + // work on Iterables, we'd need to copy the whole set. + // In this first iteration, we'll just live with hitting the bad case + // (adding everything to a Map) in for every insert/move. + // If you change this code, also update reconcileChildrenIterator() which + // uses the same algorithm. + { + // First, validate keys. + var knownKeys = null; - if (isUnkeyedTopLevelFragment) { - newChild = newChild.props.children; - } // Handle object types + for (var i = 0; i < newChildren.length; i++) { + var child = newChildren[i]; + knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); + } + } - if (typeof newChild === "object" && newChild !== null) { - switch (newChild.$$typeof) { - case REACT_ELEMENT_TYPE: - return placeSingleChild( - reconcileSingleElement( - returnFiber, - currentFirstChild, - newChild, - lanes - ) - ); + var resultingFirstChild = null; + var previousNewFiber = null; + var oldFiber = currentFirstChild; + var lastPlacedIndex = 0; + var newIdx = 0; + var nextOldFiber = null; - case REACT_PORTAL_TYPE: - return placeSingleChild( - reconcileSinglePortal( - returnFiber, - currentFirstChild, - newChild, - lanes - ) - ); + for (; oldFiber !== null && newIdx < newChildren.length; newIdx++) { + if (oldFiber.index > newIdx) { + nextOldFiber = oldFiber; + oldFiber = null; + } else { + nextOldFiber = oldFiber.sibling; + } - case REACT_LAZY_TYPE: - var payload = newChild._payload; - var init = newChild._init; // TODO: This function is supposed to be non-recursive. + var newFiber = updateSlot( + returnFiber, + oldFiber, + newChildren[newIdx], + lanes + ); - return reconcileChildFibers( - returnFiber, - currentFirstChild, - init(payload), - lanes - ); + if (newFiber === null) { + // TODO: This breaks on empty slots like null children. That's + // unfortunate because it triggers the slow path all the time. We need + // a better way to communicate whether this was a miss or null, + // boolean, undefined, etc. + if (oldFiber === null) { + oldFiber = nextOldFiber; + } + + break; } - if (isArray(newChild)) { - return reconcileChildrenArray( - returnFiber, - currentFirstChild, - newChild, - lanes - ); + if (shouldTrackSideEffects) { + if (oldFiber && newFiber.alternate === null) { + // We matched the slot, but we didn't reuse the existing fiber, so we + // need to delete the existing child. + deleteChild(returnFiber, oldFiber); + } } - if (getIteratorFn(newChild)) { - return reconcileChildrenIterator( - returnFiber, - currentFirstChild, - newChild, - lanes - ); - } // Usables are a valid React node type. When React encounters a Usable in - // a child position, it unwraps it using the same algorithm as `use`. For - // example, for promises, React will throw an exception to unwind the - // stack, then replay the component once the promise resolves. - // - // A difference from `use` is that React will keep unwrapping the value - // until it reaches a non-Usable type. - // - // e.g. Usable>> should resolve to T - // - // The structure is a bit unfortunate. Ideally, we shouldn't need to - // replay the entire begin phase of the parent fiber in order to reconcile - // the children again. This would require a somewhat significant refactor, - // because reconcilation happens deep within the begin phase, and - // depending on the type of work, not always at the end. We should - // consider as an future improvement. + lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx); - if (typeof newChild.then === "function") { - var thenable = newChild; - return reconcileChildFibersImpl( - returnFiber, - currentFirstChild, - unwrapThenable(thenable), - lanes - ); + if (previousNewFiber === null) { + // TODO: Move out of the loop. This only happens for the first run. + resultingFirstChild = newFiber; + } else { + // TODO: Defer siblings if we're not at the right index for this slot. + // I.e. if we had null values before, then we want to defer this + // for each null value. However, we also don't want to call updateSlot + // with the previous one. + previousNewFiber.sibling = newFiber; } - if ( - newChild.$$typeof === REACT_CONTEXT_TYPE || - newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE - ) { - var context = newChild; - return reconcileChildFibersImpl( + previousNewFiber = newFiber; + oldFiber = nextOldFiber; + } + + if (newIdx === newChildren.length) { + // We've reached the end of the new children. We can delete the rest. + deleteRemainingChildren(returnFiber, oldFiber); + + return resultingFirstChild; + } + + if (oldFiber === null) { + // If we don't have any more existing children we can choose a fast path + // since the rest will all be insertions. + for (; newIdx < newChildren.length; newIdx++) { + var _newFiber = createChild( returnFiber, - currentFirstChild, - readContextDuringReconcilation(returnFiber, context, lanes), + newChildren[newIdx], lanes ); + + if (_newFiber === null) { + continue; + } + + lastPlacedIndex = placeChild(_newFiber, lastPlacedIndex, newIdx); + + if (previousNewFiber === null) { + // TODO: Move out of the loop. This only happens for the first run. + resultingFirstChild = _newFiber; + } else { + previousNewFiber.sibling = _newFiber; + } + + previousNewFiber = _newFiber; } - throwOnInvalidObjectType(returnFiber, newChild); - } + return resultingFirstChild; + } // Add all children to a key map for quick lookups. - if ( - (typeof newChild === "string" && newChild !== "") || - typeof newChild === "number" - ) { - return placeSingleChild( - reconcileSingleTextNode( - returnFiber, - currentFirstChild, - "" + newChild, - lanes - ) + var existingChildren = mapRemainingChildren(returnFiber, oldFiber); // Keep scanning and use the map to restore deleted items as moves. + + for (; newIdx < newChildren.length; newIdx++) { + var _newFiber2 = updateFromMap( + existingChildren, + returnFiber, + newIdx, + newChildren[newIdx], + lanes ); - } - { - if (typeof newChild === "function") { - warnOnFunctionType(returnFiber); + if (_newFiber2 !== null) { + if (shouldTrackSideEffects) { + if (_newFiber2.alternate !== null) { + // The new fiber is a work in progress, but if there exists a + // current, that means that we reused the fiber. We need to delete + // it from the child list so that we don't add it to the deletion + // list. + existingChildren.delete( + _newFiber2.key === null ? newIdx : _newFiber2.key + ); + } + } + + lastPlacedIndex = placeChild(_newFiber2, lastPlacedIndex, newIdx); + + if (previousNewFiber === null) { + resultingFirstChild = _newFiber2; + } else { + previousNewFiber.sibling = _newFiber2; + } + + previousNewFiber = _newFiber2; } - } // Remaining cases are all treated as empty. + } - return deleteRemainingChildren(returnFiber, currentFirstChild); + if (shouldTrackSideEffects) { + // Any existing children that weren't consumed above were deleted. We need + // to add them to the deletion list. + existingChildren.forEach(function (child) { + return deleteChild(returnFiber, child); + }); + } + + return resultingFirstChild; } - function reconcileChildFibers( + function reconcileChildrenIterator( returnFiber, currentFirstChild, - newChild, + newChildrenIterable, lanes ) { - // This indirection only exists so we can reset `thenableState` at the end. - // It should get inlined by Closure. - thenableIndexCounter$1 = 0; - var firstChildFiber = reconcileChildFibersImpl( - returnFiber, - currentFirstChild, - newChild, - lanes - ); - thenableState$1 = null; // Don't bother to reset `thenableIndexCounter` to 0 because it always gets - // set at the beginning. - - return firstChildFiber; - } + // This is the same implementation as reconcileChildrenArray(), + // but using the iterator instead. + var iteratorFn = getIteratorFn(newChildrenIterable); - return reconcileChildFibers; - } + if (typeof iteratorFn !== "function") { + throw new Error( + "An object is not an iterable. This error is likely caused by a bug in " + + "React. Please file an issue." + ); + } - var reconcileChildFibers = createChildReconciler(true); - var mountChildFibers = createChildReconciler(false); - function resetChildReconcilerOnUnwind() { - // On unwind, clear any pending thenables that were used. - thenableState$1 = null; - thenableIndexCounter$1 = 0; - } - function cloneChildFibers(current, workInProgress) { - if (current !== null && workInProgress.child !== current.child) { - throw new Error("Resuming work not yet implemented."); - } + { + // We don't support rendering Generators because it's a mutation. + // See https://github.com/facebook/react/issues/12995 + if ( + typeof Symbol === "function" && // $FlowFixMe[prop-missing] Flow doesn't know about toStringTag + newChildrenIterable[Symbol.toStringTag] === "Generator" + ) { + if (!didWarnAboutGenerators) { + error( + "Using Generators as children is unsupported and will likely yield " + + "unexpected results because enumerating a generator mutates it. " + + "You may convert it to an array with `Array.from()` or the " + + "`[...spread]` operator before rendering. Keep in mind " + + "you might need to polyfill these features for older browsers." + ); + } - if (workInProgress.child === null) { - return; - } + didWarnAboutGenerators = true; + } // Warn about using Maps as children - var currentChild = workInProgress.child; - var newChild = createWorkInProgress( - currentChild, - currentChild.pendingProps - ); - workInProgress.child = newChild; - newChild.return = workInProgress; + if (newChildrenIterable.entries === iteratorFn) { + if (!didWarnAboutMaps) { + error( + "Using Maps as children is not supported. " + + "Use an array of keyed ReactElements instead." + ); + } - while (currentChild.sibling !== null) { - currentChild = currentChild.sibling; - newChild = newChild.sibling = createWorkInProgress( - currentChild, - currentChild.pendingProps - ); - newChild.return = workInProgress; - } + didWarnAboutMaps = true; + } // First, validate keys. + // We'll get a different iterator later for the main pass. - newChild.sibling = null; - } // Reset a workInProgress child set to prepare it for a second pass. + var _newChildren = iteratorFn.call(newChildrenIterable); - function resetChildFibers(workInProgress, lanes) { - var child = workInProgress.child; + if (_newChildren) { + var knownKeys = null; - while (child !== null) { - resetWorkInProgress(child, lanes); - child = child.sibling; - } - } + var _step = _newChildren.next(); - // TODO: This isn't being used yet, but it's intended to replace the - // InvisibleParentContext that is currently managed by SuspenseContext. + for (; !_step.done; _step = _newChildren.next()) { + var child = _step.value; + knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); + } + } + } - var currentTreeHiddenStackCursor = createCursor(null); - var prevEntangledRenderLanesCursor = createCursor(NoLanes); - function pushHiddenContext(fiber, context) { - var prevEntangledRenderLanes = getEntangledRenderLanes(); - push(prevEntangledRenderLanesCursor, prevEntangledRenderLanes, fiber); - push(currentTreeHiddenStackCursor, context, fiber); // When rendering a subtree that's currently hidden, we must include all - // lanes that would have rendered if the hidden subtree hadn't been deferred. - // That is, in order to reveal content from hidden -> visible, we must commit - // all the updates that we skipped when we originally hid the tree. + var newChildren = iteratorFn.call(newChildrenIterable); - setEntangledRenderLanes( - mergeLanes(prevEntangledRenderLanes, context.baseLanes) - ); - } - function reuseHiddenContextOnStack(fiber) { - // This subtree is not currently hidden, so we don't need to add any lanes - // to the render lanes. But we still need to push something to avoid a - // context mismatch. Reuse the existing context on the stack. - push(prevEntangledRenderLanesCursor, getEntangledRenderLanes(), fiber); - push( - currentTreeHiddenStackCursor, - currentTreeHiddenStackCursor.current, - fiber - ); - } - function popHiddenContext(fiber) { - // Restore the previous render lanes from the stack - setEntangledRenderLanes(prevEntangledRenderLanesCursor.current); - pop(currentTreeHiddenStackCursor, fiber); - pop(prevEntangledRenderLanesCursor, fiber); - } - function isCurrentTreeHidden() { - return currentTreeHiddenStackCursor.current !== null; - } + if (newChildren == null) { + throw new Error("An iterable object provided no iterator."); + } - // suspends, i.e. it's the nearest `catch` block on the stack. + var resultingFirstChild = null; + var previousNewFiber = null; + var oldFiber = currentFirstChild; + var lastPlacedIndex = 0; + var newIdx = 0; + var nextOldFiber = null; + var step = newChildren.next(); - var suspenseHandlerStackCursor = createCursor(null); // Represents the outermost boundary that is not visible in the current tree. - // Everything above this is the "shell". When this is null, it means we're - // rendering in the shell of the app. If it's non-null, it means we're rendering - // deeper than the shell, inside a new tree that wasn't already visible. - // - // The main way we use this concept is to determine whether showing a fallback - // would result in a desirable or undesirable loading state. Activing a fallback - // in the shell is considered an undersirable loading state, because it would - // mean hiding visible (albeit stale) content in the current tree — we prefer to - // show the stale content, rather than switch to a fallback. But showing a - // fallback in a new tree is fine, because there's no stale content to - // prefer instead. + for ( + ; + oldFiber !== null && !step.done; + newIdx++, step = newChildren.next() + ) { + if (oldFiber.index > newIdx) { + nextOldFiber = oldFiber; + oldFiber = null; + } else { + nextOldFiber = oldFiber.sibling; + } - var shellBoundary = null; - function getShellBoundary() { - return shellBoundary; - } - function pushPrimaryTreeSuspenseHandler(handler) { - // TODO: Pass as argument - var current = handler.alternate; - // propagated a single level. For example, when ForceSuspenseFallback is set, - // it should only force the nearest Suspense boundary into fallback mode. + var newFiber = updateSlot(returnFiber, oldFiber, step.value, lanes); - pushSuspenseListContext( - handler, - setDefaultShallowSuspenseListContext(suspenseStackCursor.current) - ); // Experimental feature: Some Suspense boundaries are marked as having an - // to push a nested Suspense handler, because it will get replaced by the - // outer fallback, anyway. Consider this as a future optimization. + if (newFiber === null) { + // TODO: This breaks on empty slots like null children. That's + // unfortunate because it triggers the slow path all the time. We need + // a better way to communicate whether this was a miss or null, + // boolean, undefined, etc. + if (oldFiber === null) { + oldFiber = nextOldFiber; + } - push(suspenseHandlerStackCursor, handler, handler); + break; + } - if (shellBoundary === null) { - if (current === null || isCurrentTreeHidden()) { - // This boundary is not visible in the current UI. - shellBoundary = handler; - } else { - var prevState = current.memoizedState; + if (shouldTrackSideEffects) { + if (oldFiber && newFiber.alternate === null) { + // We matched the slot, but we didn't reuse the existing fiber, so we + // need to delete the existing child. + deleteChild(returnFiber, oldFiber); + } + } - if (prevState !== null) { - // This boundary is showing a fallback in the current UI. - shellBoundary = handler; + lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx); + + if (previousNewFiber === null) { + // TODO: Move out of the loop. This only happens for the first run. + resultingFirstChild = newFiber; + } else { + // TODO: Defer siblings if we're not at the right index for this slot. + // I.e. if we had null values before, then we want to defer this + // for each null value. However, we also don't want to call updateSlot + // with the previous one. + previousNewFiber.sibling = newFiber; } + + previousNewFiber = newFiber; + oldFiber = nextOldFiber; } - } - } - function pushFallbackTreeSuspenseHandler(fiber) { - // We're about to render the fallback. If something in the fallback suspends, - // it's akin to throwing inside of a `catch` block. This boundary should not - // capture. Reuse the existing handler on the stack. - reuseSuspenseHandlerOnStack(fiber); - } - function pushOffscreenSuspenseHandler(fiber) { - if (fiber.tag === OffscreenComponent) { - // A SuspenseList context is only pushed here to avoid a push/pop mismatch. - // Reuse the current value on the stack. - // TODO: We can avoid needing to push here by by forking popSuspenseHandler - // into separate functions for Suspense and Offscreen. - pushSuspenseListContext(fiber, suspenseStackCursor.current); - push(suspenseHandlerStackCursor, fiber, fiber); - if (shellBoundary !== null); - else { - var current = fiber.alternate; + if (step.done) { + // We've reached the end of the new children. We can delete the rest. + deleteRemainingChildren(returnFiber, oldFiber); - if (current !== null) { - var prevState = current.memoizedState; + return resultingFirstChild; + } - if (prevState !== null) { - // This is the first boundary in the stack that's already showing - // a fallback. So everything outside is considered the shell. - shellBoundary = fiber; + if (oldFiber === null) { + // If we don't have any more existing children we can choose a fast path + // since the rest will all be insertions. + for (; !step.done; newIdx++, step = newChildren.next()) { + var _newFiber3 = createChild(returnFiber, step.value, lanes); + + if (_newFiber3 === null) { + continue; } - } - } - } else { - // This is a LegacyHidden component. - reuseSuspenseHandlerOnStack(fiber); - } - } - function reuseSuspenseHandlerOnStack(fiber) { - pushSuspenseListContext(fiber, suspenseStackCursor.current); - push(suspenseHandlerStackCursor, getSuspenseHandler(), fiber); - } - function getSuspenseHandler() { - return suspenseHandlerStackCursor.current; - } - function popSuspenseHandler(fiber) { - pop(suspenseHandlerStackCursor, fiber); - if (shellBoundary === fiber) { - // Popping back into the shell. - shellBoundary = null; - } + lastPlacedIndex = placeChild(_newFiber3, lastPlacedIndex, newIdx); - popSuspenseListContext(fiber); - } // SuspenseList context - // TODO: Move to a separate module? We may change the SuspenseList - // implementation to hide/show in the commit phase, anyway. + if (previousNewFiber === null) { + // TODO: Move out of the loop. This only happens for the first run. + resultingFirstChild = _newFiber3; + } else { + previousNewFiber.sibling = _newFiber3; + } - var DefaultSuspenseContext = 0; - var SubtreeSuspenseContextMask = 1; // ForceSuspenseFallback can be used by SuspenseList to force newly added - // items into their fallback state during one of the render passes. + previousNewFiber = _newFiber3; + } - var ForceSuspenseFallback = 2; - var suspenseStackCursor = createCursor(DefaultSuspenseContext); - function hasSuspenseListContext(parentContext, flag) { - return (parentContext & flag) !== 0; - } - function setDefaultShallowSuspenseListContext(parentContext) { - return parentContext & SubtreeSuspenseContextMask; - } - function setShallowSuspenseListContext(parentContext, shallowContext) { - return (parentContext & SubtreeSuspenseContextMask) | shallowContext; - } - function pushSuspenseListContext(fiber, newContext) { - push(suspenseStackCursor, newContext, fiber); - } - function popSuspenseListContext(fiber) { - pop(suspenseStackCursor, fiber); - } + return resultingFirstChild; + } // Add all children to a key map for quick lookups. - // A non-null SuspenseState means that it is blocked for one reason or another. - // - A non-null dehydrated field means it's blocked pending hydration. - // - A non-null dehydrated field can use isSuspenseInstancePending or - // isSuspenseInstanceFallback to query the reason for being dehydrated. - // - A null dehydrated field means it's blocked by something suspending and - // we're currently showing a fallback instead. + var existingChildren = mapRemainingChildren(returnFiber, oldFiber); // Keep scanning and use the map to restore deleted items as moves. - function findFirstSuspended(row) { - var node = row; + for (; !step.done; newIdx++, step = newChildren.next()) { + var _newFiber4 = updateFromMap( + existingChildren, + returnFiber, + newIdx, + step.value, + lanes + ); - while (node !== null) { - if (node.tag === SuspenseComponent) { - var state = node.memoizedState; + if (_newFiber4 !== null) { + if (shouldTrackSideEffects) { + if (_newFiber4.alternate !== null) { + // The new fiber is a work in progress, but if there exists a + // current, that means that we reused the fiber. We need to delete + // it from the child list so that we don't add it to the deletion + // list. + existingChildren.delete( + _newFiber4.key === null ? newIdx : _newFiber4.key + ); + } + } - if (state !== null) { - var dehydrated = state.dehydrated; + lastPlacedIndex = placeChild(_newFiber4, lastPlacedIndex, newIdx); - if ( - dehydrated === null || - isSuspenseInstancePending() || - isSuspenseInstanceFallback() - ) { - return node; + if (previousNewFiber === null) { + resultingFirstChild = _newFiber4; + } else { + previousNewFiber.sibling = _newFiber4; } - } - } else if ( - node.tag === SuspenseListComponent && // revealOrder undefined can't be trusted because it don't - // keep track of whether it suspended or not. - node.memoizedProps.revealOrder !== undefined - ) { - var didSuspend = (node.flags & DidCapture) !== NoFlags$1; - if (didSuspend) { - return node; + previousNewFiber = _newFiber4; } - } else if (node.child !== null) { - node.child.return = node; - node = node.child; - continue; } - if (node === row) { - return null; + if (shouldTrackSideEffects) { + // Any existing children that weren't consumed above were deleted. We need + // to add them to the deletion list. + existingChildren.forEach(function (child) { + return deleteChild(returnFiber, child); + }); } - while (node.sibling === null) { - if (node.return === null || node.return === row) { - return null; - } + return resultingFirstChild; + } - node = node.return; - } + function reconcileSingleTextNode( + returnFiber, + currentFirstChild, + textContent, + lanes + ) { + // There's no need to check for keys on text nodes since we don't have a + // way to define them. + if (currentFirstChild !== null && currentFirstChild.tag === HostText) { + // We already have an existing node so let's just update it and delete + // the rest. + deleteRemainingChildren(returnFiber, currentFirstChild.sibling); + var existing = useFiber(currentFirstChild, textContent); + existing.return = returnFiber; + return existing; + } // The existing first child is not a text node so we need to create one + // and delete the existing ones. - node.sibling.return = node.return; - node = node.sibling; + deleteRemainingChildren(returnFiber, currentFirstChild); + var created = createFiberFromText(textContent, returnFiber.mode, lanes); + created.return = returnFiber; + return created; } - return null; - } + function reconcileSingleElement( + returnFiber, + currentFirstChild, + element, + lanes + ) { + var key = element.key; + var child = currentFirstChild; - var NoFlags = - /* */ - 0; // Represents whether effect should fire. + while (child !== null) { + // TODO: If key === null and child.key === null, then this only applies to + // the first item in the list. + if (child.key === key) { + var elementType = element.type; - var HasEffect = - /* */ - 1; // Represents the phase in which the effect (not the clean-up) fires. + if (elementType === REACT_FRAGMENT_TYPE) { + if (child.tag === Fragment) { + deleteRemainingChildren(returnFiber, child.sibling); + var existing = useFiber(child, element.props.children); + existing.return = returnFiber; - var Insertion = - /* */ - 2; - var Layout = - /* */ - 4; - var Passive = - /* */ - 8; + { + existing._debugSource = element._source; + existing._debugOwner = element._owner; + } - 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. + return existing; + } + } else { + if ( + child.elementType === elementType || // Keep this check inline so it only runs on the false path: + isCompatibleFamilyForHotReloading(child, element) || // Lazy types should reconcile their resolved type. + // We need to do this after the Hot Reloading check above, + // because hot reloading has different semantics than prod because + // it doesn't resuspend. So we can't let the call below suspend. + (typeof elementType === "object" && + elementType !== null && + elementType.$$typeof === REACT_LAZY_TYPE && + resolveLazy(elementType) === child.type) + ) { + deleteRemainingChildren(returnFiber, child.sibling); - var firstScheduledRoot = null; - var lastScheduledRoot = null; // Used to prevent redundant mircotasks from being scheduled. + var _existing = useFiber(child, element.props); - 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. + _existing.ref = coerceRef(returnFiber, child, element); + _existing.return = returnFiber; - var didScheduleMicrotask_act = false; // Used to quickly bail out of flushSync if there's no sync work to do. + { + _existing._debugSource = element._source; + _existing._debugOwner = element._owner; + } - 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. + return _existing; + } + } // Didn't match. - 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. + deleteRemainingChildren(returnFiber, child); + break; + } else { + deleteChild(returnFiber, child); + } - 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); + child = child.sibling; } - } - - 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; - } // There may or may not be synchronous work scheduled. Let's check. - var didPerformSomeWork; - var errors = null; - isFlushingWork = true; + if (element.type === REACT_FRAGMENT_TYPE) { + var created = createFiberFromFragment( + element.props.children, + returnFiber.mode, + lanes, + element.key + ); + created.return = returnFiber; + return created; + } else { + var _created4 = createFiberFromElement( + element, + returnFiber.mode, + lanes + ); - do { - didPerformSomeWork = false; - var root = firstScheduledRoot; + _created4.ref = coerceRef(returnFiber, currentFirstChild, element); + _created4.return = returnFiber; + return _created4; + } + } - while (root !== null) { - if (onlyLegacy && root.tag !== LegacyRoot); - else { - var workInProgressRoot = getWorkInProgressRoot(); - var workInProgressRootRenderLanes = - getWorkInProgressRootRenderLanes(); - var nextLanes = getNextLanes( - root, - root === workInProgressRoot - ? workInProgressRootRenderLanes - : NoLanes - ); + function reconcileSinglePortal( + returnFiber, + currentFirstChild, + portal, + lanes + ) { + var key = portal.key; + var child = currentFirstChild; - if (includesSyncLane(nextLanes)) { - // This root has pending sync work. Flush it now. - try { - didPerformSomeWork = true; - performSyncWorkOnRoot(root, nextLanes); - } catch (error) { - // Collect errors so we can rethrow them at the end - if (errors === null) { - errors = [error]; - } else { - errors.push(error); - } - } + while (child !== null) { + // TODO: If key === null and child.key === null, then this only applies to + // the first item in the list. + if (child.key === key) { + if ( + child.tag === HostPortal && + child.stateNode.containerInfo === portal.containerInfo && + child.stateNode.implementation === portal.implementation + ) { + deleteRemainingChildren(returnFiber, child.sibling); + var existing = useFiber(child, portal.children || []); + existing.return = returnFiber; + return existing; + } else { + deleteRemainingChildren(returnFiber, child); + break; } + } else { + deleteChild(returnFiber, child); } - root = root.next; + child = child.sibling; } - } 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. + var created = createFiberFromPortal(portal, returnFiber.mode, lanes); + created.return = returnFiber; + return created; + } // This API will tag the children with the side-effect of the reconciliation + // itself. They will be added to the side-effect list as we pass through the + // children and the parent. - 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])); - } + function reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + newChild, + lanes + ) { + // This function is not recursive. + // If the top level item is an array, we treat it as a set of children, + // not as a fragment. Nested arrays on the other hand will be treated as + // fragment nodes. Recursion happens at the normal flow. + // Handle top level unkeyed fragments as if they were arrays. + // This leads to an ambiguity between <>{[...]} and <>.... + // We treat the ambiguous cases above the same. + // TODO: Let's use recursion like we do for Usable nodes? + var isUnkeyedTopLevelFragment = + typeof newChild === "object" && + newChild !== null && + newChild.type === REACT_FRAGMENT_TYPE && + newChild.key === null; - var firstError = errors[0]; - throw firstError; + if (isUnkeyedTopLevelFragment) { + newChild = newChild.props.children; + } // Handle object types + + if (typeof newChild === "object" && newChild !== null) { + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE: + return placeSingleChild( + reconcileSingleElement( + returnFiber, + currentFirstChild, + newChild, + lanes + ) + ); + + case REACT_PORTAL_TYPE: + return placeSingleChild( + reconcileSinglePortal( + returnFiber, + currentFirstChild, + newChild, + lanes + ) + ); + + case REACT_LAZY_TYPE: + var payload = newChild._payload; + var init = newChild._init; // TODO: This function is supposed to be non-recursive. + + return reconcileChildFibers( + returnFiber, + currentFirstChild, + init(payload), + lanes + ); } - } else { - var error = errors[0]; - throw error; - } - } - } - function throwError(error) { - throw error; - } + if (isArray(newChild)) { + return reconcileChildrenArray( + returnFiber, + currentFirstChild, + newChild, + lanes + ); + } - function processRootScheduleInMicrotask() { - // This function is always called inside a microtask. It should never be - // called synchronously. - didScheduleMicrotask = false; + if (getIteratorFn(newChild)) { + return reconcileChildrenIterator( + returnFiber, + currentFirstChild, + newChild, + lanes + ); + } // Usables are a valid React node type. When React encounters a Usable in + // a child position, it unwraps it using the same algorithm as `use`. For + // example, for promises, React will throw an exception to unwind the + // stack, then replay the component once the promise resolves. + // + // A difference from `use` is that React will keep unwrapping the value + // until it reaches a non-Usable type. + // + // e.g. Usable>> should resolve to T + // + // The structure is a bit unfortunate. Ideally, we shouldn't need to + // replay the entire begin phase of the parent fiber in order to reconcile + // the children again. This would require a somewhat significant refactor, + // because reconcilation happens deep within the begin phase, and + // depending on the type of work, not always at the end. We should + // consider as an future improvement. - { - didScheduleMicrotask_act = false; - } // We'll recompute this as we iterate through all the roots and schedule them. + if (typeof newChild.then === "function") { + var thenable = newChild; + return reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + unwrapThenable(thenable), + lanes + ); + } - mightHavePendingSyncWork = false; - var currentTime = now$1(); - var prev = null; - var root = firstScheduledRoot; + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) { + var context = newChild; + return reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + readContextDuringReconcilation(returnFiber, context, lanes), + lanes + ); + } - while (root !== null) { - var next = root.next; + throwOnInvalidObjectType(returnFiber, newChild); + } if ( - currentEventTransitionLane !== NoLane && - shouldAttemptEagerTransition() + (typeof newChild === "string" && newChild !== "") || + typeof newChild === "number" ) { - // A transition was scheduled during an event, but we're going to try to - // render it synchronously anyway. We do this during a popstate event to - // preserve the scroll position of the previous page. - upgradePendingLaneToSync(root, currentEventTransitionLane); + return placeSingleChild( + reconcileSingleTextNode( + returnFiber, + currentFirstChild, + "" + newChild, + lanes + ) + ); } - 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 (typeof newChild === "function") { + warnOnFunctionType(returnFiber); } + } // Remaining cases are all treated as empty. - 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; + return deleteRemainingChildren(returnFiber, currentFirstChild); + } - if (includesSyncLane(nextLanes)) { - mightHavePendingSyncWork = true; - } - } + function reconcileChildFibers( + returnFiber, + currentFirstChild, + newChild, + lanes + ) { + // This indirection only exists so we can reset `thenableState` at the end. + // It should get inlined by Closure. + thenableIndexCounter$1 = 0; + var firstChildFiber = reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + newChild, + lanes + ); + thenableState$1 = null; // Don't bother to reset `thenableIndexCounter` to 0 because it always gets + // set at the beginning. - root = next; + return firstChildFiber; } - 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. + return reconcileChildFibers; + } - flushSyncWorkOnAllRoots(); + var reconcileChildFibers = createChildReconciler(true); + var mountChildFibers = createChildReconciler(false); + function resetChildReconcilerOnUnwind() { + // On unwind, clear any pending thenables that were used. + thenableState$1 = null; + thenableIndexCounter$1 = 0; } + function cloneChildFibers(current, workInProgress) { + if (current !== null && workInProgress.child !== current.child) { + throw new Error("Resuming work not yet implemented."); + } - 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. + if (workInProgress.child === null) { + return; + } - var workInProgressRoot = getWorkInProgressRoot(); - var workInProgressRootRenderLanes = getWorkInProgressRootRenderLanes(); - var nextLanes = getNextLanes( - root, - root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes + var currentChild = workInProgress.child; + var newChild = createWorkInProgress( + currentChild, + currentChild.pendingProps ); - var existingCallbackNode = root.callbackNode; + workInProgress.child = newChild; + newChild.return = workInProgress; - 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); - } + while (currentChild.sibling !== null) { + currentChild = currentChild.sibling; + newChild = newChild.sibling = createWorkInProgress( + currentChild, + currentChild.pendingProps + ); + newChild.return = workInProgress; + } - root.callbackNode = null; - root.callbackPriority = NoLane; - return NoLane; - } // Schedule a new callback in the host environment. + newChild.sibling = null; + } // Reset a workInProgress child set to prepare it for a second pass. - 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); - } + function resetChildFibers(workInProgress, lanes) { + var child = workInProgress.child; - 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); + while (child !== null) { + resetWorkInProgress(child, lanes); + child = child.sibling; + } + } - 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); - } + // TODO: This isn't being used yet, but it's intended to replace the + // InvisibleParentContext that is currently managed by SuspenseContext. - var schedulerPriorityLevel; + var currentTreeHiddenStackCursor = createCursor(null); + var prevEntangledRenderLanesCursor = createCursor(NoLanes); + function pushHiddenContext(fiber, context) { + var prevEntangledRenderLanes = getEntangledRenderLanes(); + push(prevEntangledRenderLanesCursor, prevEntangledRenderLanes, fiber); + push(currentTreeHiddenStackCursor, context, fiber); // When rendering a subtree that's currently hidden, we must include all + // lanes that would have rendered if the hidden subtree hadn't been deferred. + // That is, in order to reveal content from hidden -> visible, we must commit + // all the updates that we skipped when we originally hid the tree. - switch (lanesToEventPriority(nextLanes)) { - case DiscreteEventPriority: - schedulerPriorityLevel = ImmediatePriority; - break; + setEntangledRenderLanes( + mergeLanes(prevEntangledRenderLanes, context.baseLanes) + ); + } + function reuseHiddenContextOnStack(fiber) { + // This subtree is not currently hidden, so we don't need to add any lanes + // to the render lanes. But we still need to push something to avoid a + // context mismatch. Reuse the existing context on the stack. + push(prevEntangledRenderLanesCursor, getEntangledRenderLanes(), fiber); + push( + currentTreeHiddenStackCursor, + currentTreeHiddenStackCursor.current, + fiber + ); + } + function popHiddenContext(fiber) { + // Restore the previous render lanes from the stack + setEntangledRenderLanes(prevEntangledRenderLanesCursor.current); + pop(currentTreeHiddenStackCursor, fiber); + pop(prevEntangledRenderLanesCursor, fiber); + } + function isCurrentTreeHidden() { + return currentTreeHiddenStackCursor.current !== null; + } - case ContinuousEventPriority: - schedulerPriorityLevel = UserBlockingPriority; - break; + // suspends, i.e. it's the nearest `catch` block on the stack. - case DefaultEventPriority: - schedulerPriorityLevel = NormalPriority; - break; + var suspenseHandlerStackCursor = createCursor(null); // Represents the outermost boundary that is not visible in the current tree. + // Everything above this is the "shell". When this is null, it means we're + // rendering in the shell of the app. If it's non-null, it means we're rendering + // deeper than the shell, inside a new tree that wasn't already visible. + // + // The main way we use this concept is to determine whether showing a fallback + // would result in a desirable or undesirable loading state. Activing a fallback + // in the shell is considered an undersirable loading state, because it would + // mean hiding visible (albeit stale) content in the current tree — we prefer to + // show the stale content, rather than switch to a fallback. But showing a + // fallback in a new tree is fine, because there's no stale content to + // prefer instead. - case IdleEventPriority: - schedulerPriorityLevel = IdlePriority; - break; + var shellBoundary = null; + function getShellBoundary() { + return shellBoundary; + } + function pushPrimaryTreeSuspenseHandler(handler) { + // TODO: Pass as argument + var current = handler.alternate; + // propagated a single level. For example, when ForceSuspenseFallback is set, + // it should only force the nearest Suspense boundary into fallback mode. - default: - schedulerPriorityLevel = NormalPriority; - break; - } + pushSuspenseListContext( + handler, + setDefaultShallowSuspenseListContext(suspenseStackCursor.current) + ); // Experimental feature: Some Suspense boundaries are marked as having an + // to push a nested Suspense handler, because it will get replaced by the + // outer fallback, anyway. Consider this as a future optimization. - var newCallbackNode = scheduleCallback$1( - schedulerPriorityLevel, - performConcurrentWorkOnRoot.bind(null, root) - ); - root.callbackPriority = newCallbackPriority; - root.callbackNode = newCallbackNode; - return newCallbackPriority; - } - } + push(suspenseHandlerStackCursor, handler, handler); - 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 (shellBoundary === null) { + if (current === null || isCurrentTreeHidden()) { + // This boundary is not visible in the current UI. + shellBoundary = handler; + } else { + var prevState = current.memoizedState; - 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); + if (prevState !== null) { + // This boundary is showing a fallback in the current UI. + shellBoundary = handler; + } + } } + } + function pushFallbackTreeSuspenseHandler(fiber) { + // We're about to render the fallback. If something in the fallback suspends, + // it's akin to throwing inside of a `catch` block. This boundary should not + // capture. Reuse the existing handler on the stack. + reuseSuspenseHandlerOnStack(fiber); + } + function pushOffscreenSuspenseHandler(fiber) { + if (fiber.tag === OffscreenComponent) { + // A SuspenseList context is only pushed here to avoid a push/pop mismatch. + // Reuse the current value on the stack. + // TODO: We can avoid needing to push here by by forking popSuspenseHandler + // into separate functions for Suspense and Offscreen. + pushSuspenseListContext(fiber, suspenseStackCursor.current); + push(suspenseHandlerStackCursor, fiber, fiber); + + if (shellBoundary !== null); + else { + var current = fiber.alternate; - return null; - } - var fakeActCallbackNode$1 = {}; + if (current !== null) { + var prevState = current.memoizedState; - function scheduleCallback$1(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; + if (prevState !== null) { + // This is the first boundary in the stack that's already showing + // a fallback. So everything outside is considered the shell. + shellBoundary = fiber; + } + } + } } else { - return scheduleCallback$2(priorityLevel, callback); + // This is a LegacyHidden component. + reuseSuspenseHandlerOnStack(fiber); } } - - function cancelCallback(callbackNode) { - if (callbackNode === fakeActCallbackNode$1); - else if (callbackNode !== null) { - cancelCallback$1(callbackNode); - } + function reuseSuspenseHandlerOnStack(fiber) { + pushSuspenseListContext(fiber, suspenseStackCursor.current); + push(suspenseHandlerStackCursor, getSuspenseHandler(), fiber); } - - 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$2(ImmediatePriority, cb); - } + function getSuspenseHandler() { + return suspenseHandlerStackCursor.current; } + function popSuspenseHandler(fiber) { + pop(suspenseHandlerStackCursor, fiber); - 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(); + if (shellBoundary === fiber) { + // Popping back into the shell. + shellBoundary = null; } - return currentEventTransitionLane; - } + popSuspenseListContext(fiber); + } // SuspenseList context + // TODO: Move to a separate module? We may change the SuspenseList + // implementation to hide/show in the commit phase, anyway. - // transition updates that occur while the async action is still in progress - // are treated as part of the action. - // - // The ideal behavior would be to treat each async function as an independent - // action. However, without a mechanism like AsyncContext, we can't tell which - // action an update corresponds to. So instead, we entangle them all into one. - // The listeners to notify once the entangled scope completes. + var DefaultSuspenseContext = 0; + var SubtreeSuspenseContextMask = 1; // ForceSuspenseFallback can be used by SuspenseList to force newly added + // items into their fallback state during one of the render passes. - var currentEntangledListeners = null; // The number of pending async actions in the entangled scope. + var ForceSuspenseFallback = 2; + var suspenseStackCursor = createCursor(DefaultSuspenseContext); + function hasSuspenseListContext(parentContext, flag) { + return (parentContext & flag) !== 0; + } + function setDefaultShallowSuspenseListContext(parentContext) { + return parentContext & SubtreeSuspenseContextMask; + } + function setShallowSuspenseListContext(parentContext, shallowContext) { + return (parentContext & SubtreeSuspenseContextMask) | shallowContext; + } + function pushSuspenseListContext(fiber, newContext) { + push(suspenseStackCursor, newContext, fiber); + } + function popSuspenseListContext(fiber) { + pop(suspenseStackCursor, fiber); + } - var currentEntangledPendingCount = 0; // The transition lane shared by all updates in the entangled scope. + // A non-null SuspenseState means that it is blocked for one reason or another. + // - A non-null dehydrated field means it's blocked pending hydration. + // - A non-null dehydrated field can use isSuspenseInstancePending or + // isSuspenseInstanceFallback to query the reason for being dehydrated. + // - A null dehydrated field means it's blocked by something suspending and + // we're currently showing a fallback instead. - var currentEntangledLane = NoLane; - function requestAsyncActionContext( - actionReturnValue, // If this is provided, this resulting thenable resolves to this value instead - // of the return value of the action. This is a perf trick to avoid composing - // an extra async function. - overrideReturnValue - ) { - // 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. - var thenable = actionReturnValue; - var entangledListeners; + function findFirstSuspended(row) { + var node = row; - if (currentEntangledListeners === null) { - // There's no outer async action scope. Create a new one. - entangledListeners = currentEntangledListeners = []; - currentEntangledPendingCount = 0; - currentEntangledLane = requestTransitionLane(); - } else { - entangledListeners = currentEntangledListeners; - } + while (node !== null) { + if (node.tag === SuspenseComponent) { + var state = node.memoizedState; - currentEntangledPendingCount++; // Create a thenable that represents the result of this action, but doesn't - // resolve until the entire entangled scope has finished. - // - // Expressed using promises: - // const [thisResult] = await Promise.all([thisAction, entangledAction]); - // return thisResult; - - var resultThenable = createResultThenable(entangledListeners); - var resultStatus = "pending"; - var resultValue; - var rejectedReason; - thenable.then( - function (value) { - resultStatus = "fulfilled"; - resultValue = - overrideReturnValue !== null ? overrideReturnValue : value; - pingEngtangledActionScope(); - }, - function (error) { - resultStatus = "rejected"; - rejectedReason = error; - pingEngtangledActionScope(); - } - ); // Attach a listener to fill in the result. - - entangledListeners.push(function () { - switch (resultStatus) { - case "fulfilled": { - var fulfilledThenable = resultThenable; - fulfilledThenable.status = "fulfilled"; - fulfilledThenable.value = resultValue; - break; - } + if (state !== null) { + var dehydrated = state.dehydrated; - case "rejected": { - var rejectedThenable = resultThenable; - rejectedThenable.status = "rejected"; - rejectedThenable.reason = rejectedReason; - break; + if ( + dehydrated === null || + isSuspenseInstancePending() || + isSuspenseInstanceFallback() + ) { + return node; + } } + } else if ( + node.tag === SuspenseListComponent && // revealOrder undefined can't be trusted because it don't + // keep track of whether it suspended or not. + node.memoizedProps.revealOrder !== undefined + ) { + var didSuspend = (node.flags & DidCapture) !== NoFlags$1; - case "pending": - default: { - // The listener above should have been called first, so `resultStatus` - // should already be set to the correct value. - throw new Error( - "Thenable should have already resolved. This " + - "is a bug in React." - ); + if (didSuspend) { + return node; } + } else if (node.child !== null) { + node.child.return = node; + node = node.child; + continue; } - }); - return resultThenable; - } - function requestSyncActionContext( - actionReturnValue, // If this is provided, this resulting thenable resolves to this value instead - // of the return value of the action. This is a perf trick to avoid composing - // an extra async function. - overrideReturnValue - ) { - var resultValue = - overrideReturnValue !== null ? overrideReturnValue : actionReturnValue; // This is not an async action, but it may be part of an outer async action. - if (currentEntangledListeners === null) { - return resultValue; - } else { - // Return a thenable that does not resolve until the entangled actions - // have finished. - var entangledListeners = currentEntangledListeners; - var resultThenable = createResultThenable(entangledListeners); - entangledListeners.push(function () { - var fulfilledThenable = resultThenable; - fulfilledThenable.status = "fulfilled"; - fulfilledThenable.value = resultValue; - }); - return resultThenable; - } - } + if (node === row) { + return null; + } - function pingEngtangledActionScope() { - if ( - currentEntangledListeners !== null && - --currentEntangledPendingCount === 0 - ) { - // All the actions have finished. Close the entangled async action scope - // and notify all the listeners. - var listeners = currentEntangledListeners; - currentEntangledListeners = null; - currentEntangledLane = NoLane; + while (node.sibling === null) { + if (node.return === null || node.return === row) { + return null; + } - for (var i = 0; i < listeners.length; i++) { - var listener = listeners[i]; - listener(); + node = node.return; } + + node.sibling.return = node.return; + node = node.sibling; } - } - function createResultThenable(entangledListeners) { - // Waits for the entangled async action to complete, then resolves to the - // result of an individual action. - var resultThenable = { - status: "pending", - value: null, - reason: null, - then: function (resolve) { - // This is a bit of a cheat. `resolve` expects a value of type `S` to be - // passed, but because we're instrumenting the `status` field ourselves, - // and we know this thenable will only be used by React, we also know - // the value isn't actually needed. So we add the resolve function - // directly to the entangled listeners. - // - // This is also why we don't need to check if the thenable is still - // pending; the Suspense implementation already performs that check. - var ping = resolve; - entangledListeners.push(ping); - } - }; - return resultThenable; + return null; } - function peekEntangledActionLane() { - return currentEntangledLane; - } + var NoFlags = + /* */ + 0; // Represents whether effect should fire. + + var HasEffect = + /* */ + 1; // Represents the phase in which the effect (not the clean-up) fires. + + var Insertion = + /* */ + 2; + var Layout = + /* */ + 4; + var Passive = + /* */ + 8; var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, ReactCurrentBatchConfig$2 = ReactSharedInternals.ReactCurrentBatchConfig; @@ -11787,6 +11779,7 @@ to return true:wantsResponderID| | var newBaseQueueFirst = null; var newBaseQueueLast = null; var update = first; + var didReadFromEntangledAsyncAction = false; do { // An extra OffscreenLane bit is added to updates that were made to @@ -11829,6 +11822,17 @@ to return true:wantsResponderID| | ); markSkippedUpdateLanes(updateLane); } else { + // This update does have sufficient priority. + // Check if this update is part of a pending async action. If so, + // we'll need to suspend until the action has finished, so that it's + // batched together with future updates in the same action. + if ( + updateLane !== NoLane && + updateLane === peekEntangledActionLane() + ) { + didReadFromEntangledAsyncAction = true; + } // Check if this is an optimistic update. + { // This is not an optimistic update, and we're going to apply it now. // But, if there were earlier updates that were skipped, we need to @@ -11875,7 +11879,23 @@ to return true:wantsResponderID| | // different from the current state. if (!objectIs(newState, hook.memoizedState)) { - markWorkInProgressReceivedUpdate(); + markWorkInProgressReceivedUpdate(); // Check if this update is part of a pending async action. If so, we'll + // need to suspend until the action has finished, so that it's batched + // together with future updates in the same action. + // TODO: Once we support hooks inside useMemo (or an equivalent + // memoization boundary like Forget), hoist this logic so that it only + // suspends if the memo boundary produces a new value. + + if (didReadFromEntangledAsyncAction) { + var entangledActionThenable = peekEntangledActionThenable(); + + if (entangledActionThenable !== null) { + // TODO: Instead of the throwing the thenable directly, throw a + // special object like `use` does so we can detect if it's captured + // by userspace. + throw entangledActionThenable; + } + } } hook.memoizedState = newState; @@ -12694,7 +12714,7 @@ to return true:wantsResponderID| | } try { - var returnValue, thenable, entangledResult, _entangledResult2; + var returnValue, thenable, thenableForFinishedState; if (enableAsyncActions); else { // Async actions are not enabled. @@ -14906,6 +14926,7 @@ to return true:wantsResponderID| | // process them now. processUpdateQueue(workInProgress, newProps, instance, renderLanes); + suspendIfUpdateReadFromEntangledAsyncAction(); instance.state = workInProgress.memoizedState; } @@ -14973,6 +14994,7 @@ to return true:wantsResponderID| | var oldState = workInProgress.memoizedState; var newState = (instance.state = oldState); processUpdateQueue(workInProgress, newProps, instance, renderLanes); + suspendIfUpdateReadFromEntangledAsyncAction(); newState = workInProgress.memoizedState; if ( @@ -15125,6 +15147,7 @@ to return true:wantsResponderID| | var oldState = workInProgress.memoizedState; var newState = (instance.state = oldState); processUpdateQueue(workInProgress, newProps, instance, renderLanes); + suspendIfUpdateReadFromEntangledAsyncAction(); newState = workInProgress.memoizedState; if ( @@ -15698,7 +15721,7 @@ to return true:wantsResponderID| | } } - return; + return false; } case OffscreenComponent: { @@ -15733,7 +15756,7 @@ to return true:wantsResponderID| | attachPingListener(root, wakeable, rootRenderLanes); } - return; + return false; } } } @@ -15756,7 +15779,7 @@ to return true:wantsResponderID| | // and potentially log a warning. Revisit this for a future release. attachPingListener(root, wakeable, rootRenderLanes); renderDidSuspendDelayIfPossible(); - return; + return false; } else { // In a legacy root, suspending without a boundary is always an error. var uncaughtSuspenseError = new Error( @@ -15776,6 +15799,12 @@ to return true:wantsResponderID| | // over and traverse parent path again, this time treating the exception // as an error. + if (returnFiber === null) { + // There's no return fiber, which means the root errored. This should never + // happen. Return `true` to trigger a fatal error (panic). + return true; + } + var workInProgress = returnFiber; do { @@ -15791,7 +15820,7 @@ to return true:wantsResponderID| | lane ); enqueueCapturedUpdate(workInProgress, update); - return; + return false; } case ClassComponent: @@ -15820,7 +15849,7 @@ to return true:wantsResponderID| | ); enqueueCapturedUpdate(workInProgress, _update); - return; + return false; } break; @@ -15828,6 +15857,8 @@ to return true:wantsResponderID| | workInProgress = workInProgress.return; } while (workInProgress !== null); + + return false; } var ReactCurrentOwner$2 = ReactSharedInternals.ReactCurrentOwner; // A special exception that's used to unwind the stack when an update flows @@ -16802,6 +16833,10 @@ to return true:wantsResponderID| | cloneUpdateQueue(current, workInProgress); processUpdateQueue(workInProgress, nextProps, null, renderLanes); var nextState = workInProgress.memoizedState; + // it needs to happen after the `pushCacheProvider` call above to avoid a + // context stack mismatch. A bit unfortunate. + + suspendIfUpdateReadFromEntangledAsyncAction(); // Caution: React DevTools currently depends on this property // being called "element". var nextChildren = nextState.element; @@ -25242,7 +25277,7 @@ to return true:wantsResponderID| | // Unwind then continue with the normal work loop. workInProgressSuspendedReason = NotSuspended; workInProgressThrownValue = null; - throwAndUnwindWorkLoop(unitOfWork, thrownValue); + throwAndUnwindWorkLoop(root, unitOfWork, thrownValue); break; } } @@ -25347,7 +25382,7 @@ to return true:wantsResponderID| | // Unwind then continue with the normal work loop. workInProgressSuspendedReason = NotSuspended; workInProgressThrownValue = null; - throwAndUnwindWorkLoop(unitOfWork, thrownValue); + throwAndUnwindWorkLoop(root, unitOfWork, thrownValue); break; } @@ -25412,7 +25447,7 @@ to return true:wantsResponderID| | // Otherwise, unwind then continue with the normal work loop. workInProgressSuspendedReason = NotSuspended; workInProgressThrownValue = null; - throwAndUnwindWorkLoop(unitOfWork, thrownValue); + throwAndUnwindWorkLoop(root, unitOfWork, thrownValue); } break; @@ -25477,7 +25512,7 @@ to return true:wantsResponderID| | workInProgressSuspendedReason = NotSuspended; workInProgressThrownValue = null; - throwAndUnwindWorkLoop(unitOfWork, thrownValue); + throwAndUnwindWorkLoop(root, unitOfWork, thrownValue); break; } @@ -25488,7 +25523,7 @@ to return true:wantsResponderID| | // always unwind. workInProgressSuspendedReason = NotSuspended; workInProgressThrownValue = null; - throwAndUnwindWorkLoop(unitOfWork, thrownValue); + throwAndUnwindWorkLoop(root, unitOfWork, thrownValue); break; } @@ -25716,7 +25751,7 @@ to return true:wantsResponderID| | ReactCurrentOwner$1.current = null; } - function throwAndUnwindWorkLoop(unitOfWork, thrownValue) { + function throwAndUnwindWorkLoop(root, unitOfWork, thrownValue) { // This is a fork of performUnitOfWork specifcally for unwinding a fiber // that threw an exception. // @@ -25725,40 +25760,33 @@ to return true:wantsResponderID| | resetSuspendedWorkLoopOnUnwind(unitOfWork); var returnFiber = unitOfWork.return; - if (returnFiber === null || workInProgressRoot === null) { - // Expected to be working on a non-root fiber. This is a fatal error - // because there's no ancestor that can handle it; the root is - // supposed to capture all errors that weren't caught by an error - // boundary. - workInProgressRootExitStatus = RootFatalErrored; - workInProgressRootFatalError = thrownValue; // Set `workInProgress` to null. This represents advancing to the next - // sibling, or the parent if there are no siblings. But since the root - // has no siblings nor a parent, we set it to null. Usually this is - // handled by `completeUnitOfWork` or `unwindWork`, but since we're - // intentionally not calling those, we need set it here. - // TODO: Consider calling `unwindWork` to pop the contexts. - - workInProgress = null; - return; - } - try { // Find and mark the nearest Suspense or error boundary that can handle // this "exception". - throwException( - workInProgressRoot, + var didFatal = throwException( + root, returnFiber, unitOfWork, thrownValue, workInProgressRootRenderLanes ); + + if (didFatal) { + panicOnRootError(thrownValue); + return; + } } catch (error) { // We had trouble processing the error. An example of this happening is // when accessing the `componentDidCatch` property of an error boundary // throws an error. A weird edge case. There's a regression test for this. // To prevent an infinite loop, bubble the error up to the next parent. - workInProgress = returnFiber; - throw error; + if (returnFiber !== null) { + workInProgress = returnFiber; + throw error; + } else { + panicOnRootError(thrownValue); + return; + } } if (unitOfWork.flags & Incomplete) { @@ -25778,6 +25806,22 @@ to return true:wantsResponderID| | } } + function panicOnRootError(error) { + // There's no ancestor that can handle this exception. This should never + // happen because the root is supposed to capture all errors that weren't + // caught by an error boundary. This is a fatal error, or panic condition, + // because we've run out of ways to recover. + workInProgressRootExitStatus = RootFatalErrored; + workInProgressRootFatalError = error; // Set `workInProgress` to null. This represents advancing to the next + // sibling, or the parent if there are no siblings. But since the root + // has no siblings nor a parent, we set it to null. Usually this is + // handled by `completeUnitOfWork` or `unwindWork`, but since we're + // intentionally not calling those, we need set it here. + // TODO: Consider calling `unwindWork` to pop the contexts. + + workInProgress = null; + } + function completeUnitOfWork(unitOfWork) { // Attempt to complete the current unit of work, then move to the next // sibling. If there are no more siblings, return to the parent fiber. @@ -28279,7 +28323,7 @@ to return true:wantsResponderID| | return root; } - var ReactVersion = "18.3.0-canary-e2b49fad"; + var ReactVersion = "18.3.0-canary-08bfc409"; function createPortal$1( children, diff --git a/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactNativeRenderer-prod.fb.js b/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactNativeRenderer-prod.fb.js index d271b2ec3bfcf..ed72c5c2358e1 100644 --- a/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactNativeRenderer-prod.fb.js +++ b/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactNativeRenderer-prod.fb.js @@ -7,7 +7,7 @@ * @noflow * @nolint * @preventMunge - * @generated SignedSource<> + * @generated SignedSource<<08089ec617b423b74bdd6b2f946a0fd5>> */ "use strict"; @@ -940,7 +940,7 @@ eventPluginOrder = Array.prototype.slice.call([ "ReactNativeBridgeEventPlugin" ]); recomputePluginOrdering(); -var injectedNamesToPlugins$jscomp$inline_241 = { +var injectedNamesToPlugins$jscomp$inline_242 = { ResponderEventPlugin: ResponderEventPlugin, ReactNativeBridgeEventPlugin: { eventTypes: {}, @@ -986,32 +986,32 @@ var injectedNamesToPlugins$jscomp$inline_241 = { } } }, - isOrderingDirty$jscomp$inline_242 = !1, - pluginName$jscomp$inline_243; -for (pluginName$jscomp$inline_243 in injectedNamesToPlugins$jscomp$inline_241) + isOrderingDirty$jscomp$inline_243 = !1, + pluginName$jscomp$inline_244; +for (pluginName$jscomp$inline_244 in injectedNamesToPlugins$jscomp$inline_242) if ( - injectedNamesToPlugins$jscomp$inline_241.hasOwnProperty( - pluginName$jscomp$inline_243 + injectedNamesToPlugins$jscomp$inline_242.hasOwnProperty( + pluginName$jscomp$inline_244 ) ) { - var pluginModule$jscomp$inline_244 = - injectedNamesToPlugins$jscomp$inline_241[pluginName$jscomp$inline_243]; + var pluginModule$jscomp$inline_245 = + injectedNamesToPlugins$jscomp$inline_242[pluginName$jscomp$inline_244]; if ( - !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_243) || - namesToPlugins[pluginName$jscomp$inline_243] !== - pluginModule$jscomp$inline_244 + !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_244) || + namesToPlugins[pluginName$jscomp$inline_244] !== + pluginModule$jscomp$inline_245 ) { - if (namesToPlugins[pluginName$jscomp$inline_243]) + if (namesToPlugins[pluginName$jscomp$inline_244]) throw Error( "EventPluginRegistry: Cannot inject two different event plugins using the same name, `" + - (pluginName$jscomp$inline_243 + "`.") + (pluginName$jscomp$inline_244 + "`.") ); - namesToPlugins[pluginName$jscomp$inline_243] = - pluginModule$jscomp$inline_244; - isOrderingDirty$jscomp$inline_242 = !0; + namesToPlugins[pluginName$jscomp$inline_244] = + pluginModule$jscomp$inline_245; + isOrderingDirty$jscomp$inline_243 = !0; } } -isOrderingDirty$jscomp$inline_242 && recomputePluginOrdering(); +isOrderingDirty$jscomp$inline_243 && recomputePluginOrdering(); var instanceCache = new Map(), instanceProps = new Map(); function getInstanceFromTag(tag) { @@ -2216,6 +2216,219 @@ function getRootForUpdatedFiber(sourceFiber) { (sourceFiber = parent), (parent = sourceFiber.return); return 3 === sourceFiber.tag ? sourceFiber.stateNode : null; } +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$2(ImmediatePriority, processRootScheduleInMicrotask)); + enableDeferRootSchedulingToMicrotask || + scheduleTaskForRootDuringMicrotask(root, now()); +} +function flushSyncWorkAcrossRoots_impl(onlyLegacy) { + if (!isFlushingWork && mightHavePendingSyncWork) { + var errors = null; + isFlushingWork = !0; + do { + var didPerformSomeWork = !1; + for (var root = firstScheduledRoot; null !== root; ) { + if (!onlyLegacy || 0 === root.tag) { + var workInProgressRootRenderLanes$11 = workInProgressRootRenderLanes, + nextLanes = getNextLanes( + root, + root === workInProgressRoot ? workInProgressRootRenderLanes$11 : 0 + ); + if (0 !== (nextLanes & 3)) + try { + didPerformSomeWork = !0; + workInProgressRootRenderLanes$11 = root; + if (0 !== (executionContext & 6)) + throw Error("Should not already be working."); + if (!flushPassiveEffects()) { + var exitStatus = renderRootSync( + workInProgressRootRenderLanes$11, + nextLanes + ); + if ( + 0 !== workInProgressRootRenderLanes$11.tag && + 2 === exitStatus + ) { + var originallyAttemptedLanes = nextLanes, + errorRetryLanes = getLanesToRetrySynchronouslyOnError( + workInProgressRootRenderLanes$11, + originallyAttemptedLanes + ); + 0 !== errorRetryLanes && + ((nextLanes = errorRetryLanes), + (exitStatus = recoverFromConcurrentError( + workInProgressRootRenderLanes$11, + originallyAttemptedLanes, + errorRetryLanes + ))); + } + if (1 === exitStatus) + throw ( + ((originallyAttemptedLanes = workInProgressRootFatalError), + prepareFreshStack(workInProgressRootRenderLanes$11, 0), + markRootSuspended( + workInProgressRootRenderLanes$11, + nextLanes, + 0 + ), + ensureRootIsScheduled(workInProgressRootRenderLanes$11), + originallyAttemptedLanes) + ); + 6 === exitStatus + ? markRootSuspended( + workInProgressRootRenderLanes$11, + nextLanes, + workInProgressDeferredLane + ) + : ((workInProgressRootRenderLanes$11.finishedWork = + workInProgressRootRenderLanes$11.current.alternate), + (workInProgressRootRenderLanes$11.finishedLanes = + nextLanes), + commitRoot( + workInProgressRootRenderLanes$11, + workInProgressRootRecoverableErrors, + workInProgressTransitions, + workInProgressDeferredLane + )); + } + ensureRootIsScheduled(workInProgressRootRenderLanes$11); + } 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++) + (didPerformSomeWork = throwError.bind(null, errors[onlyLegacy])), + scheduleCallback$2(ImmediatePriority, didPerformSomeWork); + } + 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 & -62914561; + 0 < lanes; + + ) { + var index$5 = 31 - clz32(lanes), + lane = 1 << index$5, + expirationTime = expirationTimes[index$5]; + if (-1 === expirationTime) { + if (0 === (lane & suspendedLanes) || 0 !== (lane & pingedLanes)) + expirationTimes[index$5] = 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; + break; + case 268435456: + suspendedLanes = IdlePriority; + break; + default: + suspendedLanes = NormalPriority; + } + pingedLanes = performConcurrentWorkOnRoot.bind(null, root); + suspendedLanes = scheduleCallback$2(suspendedLanes, pingedLanes); + root.callbackPriority = currentTime; + root.callbackNode = suspendedLanes; + return currentTime; +} +function requestTransitionLane() { + if (0 === currentEventTransitionLane) { + var lane = nextTransitionLane; + nextTransitionLane <<= 1; + 0 === (nextTransitionLane & 4194176) && (nextTransitionLane = 128); + currentEventTransitionLane = lane; + } + return currentEventTransitionLane; +} var hasForceUpdate = !1; function initializeUpdateQueue(fiber) { fiber.updateQueue = { @@ -3435,219 +3648,6 @@ function findFirstSuspended(row) { } return null; } -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$2(ImmediatePriority, processRootScheduleInMicrotask)); - enableDeferRootSchedulingToMicrotask || - scheduleTaskForRootDuringMicrotask(root, now()); -} -function flushSyncWorkAcrossRoots_impl(onlyLegacy) { - if (!isFlushingWork && mightHavePendingSyncWork) { - var errors = null; - isFlushingWork = !0; - do { - var didPerformSomeWork = !1; - for (var root = firstScheduledRoot; null !== root; ) { - if (!onlyLegacy || 0 === root.tag) { - var workInProgressRootRenderLanes$28 = workInProgressRootRenderLanes, - nextLanes = getNextLanes( - root, - root === workInProgressRoot ? workInProgressRootRenderLanes$28 : 0 - ); - if (0 !== (nextLanes & 3)) - try { - didPerformSomeWork = !0; - workInProgressRootRenderLanes$28 = root; - if (0 !== (executionContext & 6)) - throw Error("Should not already be working."); - if (!flushPassiveEffects()) { - var exitStatus = renderRootSync( - workInProgressRootRenderLanes$28, - nextLanes - ); - if ( - 0 !== workInProgressRootRenderLanes$28.tag && - 2 === exitStatus - ) { - var originallyAttemptedLanes = nextLanes, - errorRetryLanes = getLanesToRetrySynchronouslyOnError( - workInProgressRootRenderLanes$28, - originallyAttemptedLanes - ); - 0 !== errorRetryLanes && - ((nextLanes = errorRetryLanes), - (exitStatus = recoverFromConcurrentError( - workInProgressRootRenderLanes$28, - originallyAttemptedLanes, - errorRetryLanes - ))); - } - if (1 === exitStatus) - throw ( - ((originallyAttemptedLanes = workInProgressRootFatalError), - prepareFreshStack(workInProgressRootRenderLanes$28, 0), - markRootSuspended( - workInProgressRootRenderLanes$28, - nextLanes, - 0 - ), - ensureRootIsScheduled(workInProgressRootRenderLanes$28), - originallyAttemptedLanes) - ); - 6 === exitStatus - ? markRootSuspended( - workInProgressRootRenderLanes$28, - nextLanes, - workInProgressDeferredLane - ) - : ((workInProgressRootRenderLanes$28.finishedWork = - workInProgressRootRenderLanes$28.current.alternate), - (workInProgressRootRenderLanes$28.finishedLanes = - nextLanes), - commitRoot( - workInProgressRootRenderLanes$28, - workInProgressRootRecoverableErrors, - workInProgressTransitions, - workInProgressDeferredLane - )); - } - ensureRootIsScheduled(workInProgressRootRenderLanes$28); - } 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++) - (didPerformSomeWork = throwError.bind(null, errors[onlyLegacy])), - scheduleCallback$2(ImmediatePriority, didPerformSomeWork); - } - 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 & -62914561; - 0 < lanes; - - ) { - var index$5 = 31 - clz32(lanes), - lane = 1 << index$5, - expirationTime = expirationTimes[index$5]; - if (-1 === expirationTime) { - if (0 === (lane & suspendedLanes) || 0 !== (lane & pingedLanes)) - expirationTimes[index$5] = 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; - break; - case 268435456: - suspendedLanes = IdlePriority; - break; - default: - suspendedLanes = NormalPriority; - } - pingedLanes = performConcurrentWorkOnRoot.bind(null, root); - suspendedLanes = scheduleCallback$2(suspendedLanes, pingedLanes); - root.callbackPriority = currentTime; - root.callbackNode = suspendedLanes; - return currentTime; -} -function requestTransitionLane() { - if (0 === currentEventTransitionLane) { - var lane = nextTransitionLane; - nextTransitionLane <<= 1; - 0 === (nextTransitionLane & 4194176) && (nextTransitionLane = 128); - currentEventTransitionLane = lane; - } - return currentEventTransitionLane; -} var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, ReactCurrentBatchConfig$2 = ReactSharedInternals.ReactCurrentBatchConfig, renderLanes = 0, @@ -4732,6 +4732,153 @@ function createClassErrorUpdate(fiber, errorInfo, lane) { }); return lane; } +function throwException( + root, + returnFiber, + sourceFiber, + value, + rootRenderLanes +) { + sourceFiber.flags |= 32768; + if ( + null !== value && + "object" === typeof value && + "function" === typeof value.then + ) { + var tag = sourceFiber.tag; + 0 !== (sourceFiber.mode & 1) || + (0 !== tag && 11 !== tag && 15 !== tag) || + ((tag = sourceFiber.alternate) + ? ((sourceFiber.updateQueue = tag.updateQueue), + (sourceFiber.memoizedState = tag.memoizedState), + (sourceFiber.lanes = tag.lanes)) + : ((sourceFiber.updateQueue = null), + (sourceFiber.memoizedState = null))); + tag = suspenseHandlerStackCursor.current; + if (null !== tag) { + switch (tag.tag) { + case 13: + return ( + sourceFiber.mode & 1 && + (null === shellBoundary + ? renderDidSuspendDelayIfPossible() + : null === tag.alternate && + 0 === workInProgressRootExitStatus && + (workInProgressRootExitStatus = 3)), + (tag.flags &= -257), + 0 === (tag.mode & 1) + ? tag === returnFiber + ? (tag.flags |= 65536) + : ((tag.flags |= 128), + (sourceFiber.flags |= 131072), + (sourceFiber.flags &= -52805), + 1 === sourceFiber.tag && + (null === sourceFiber.alternate + ? (sourceFiber.tag = 17) + : ((returnFiber = createUpdate(2)), + (returnFiber.tag = 2), + enqueueUpdate(sourceFiber, returnFiber, 2))), + (sourceFiber.lanes |= 2)) + : ((tag.flags |= 65536), (tag.lanes = rootRenderLanes)), + value === noopSuspenseyCommitThenable + ? (tag.flags |= 16384) + : ((returnFiber = tag.updateQueue), + null === returnFiber + ? (tag.updateQueue = new Set([value])) + : returnFiber.add(value), + tag.mode & 1 && + attachPingListener(root, value, rootRenderLanes)), + !1 + ); + case 22: + if (tag.mode & 1) + return ( + (tag.flags |= 65536), + value === noopSuspenseyCommitThenable + ? (tag.flags |= 16384) + : ((returnFiber = tag.updateQueue), + null === returnFiber + ? ((returnFiber = { + transitions: null, + markerInstances: null, + retryQueue: new Set([value]) + }), + (tag.updateQueue = returnFiber)) + : ((sourceFiber = returnFiber.retryQueue), + null === sourceFiber + ? (returnFiber.retryQueue = new Set([value])) + : sourceFiber.add(value)), + attachPingListener(root, value, rootRenderLanes)), + !1 + ); + } + throw Error( + "Unexpected Suspense handler tag (" + + tag.tag + + "). This is a bug in React." + ); + } + if (1 === root.tag) + return ( + attachPingListener(root, value, rootRenderLanes), + renderDidSuspendDelayIfPossible(), + !1 + ); + value = Error( + "A component suspended while responding to synchronous input. This will cause the UI to be replaced with a loading indicator. To fix, updates that suspend should be wrapped with startTransition." + ); + } + root = value = createCapturedValueAtFiber(value, sourceFiber); + 4 !== workInProgressRootExitStatus && (workInProgressRootExitStatus = 2); + null === workInProgressRootConcurrentErrors + ? (workInProgressRootConcurrentErrors = [root]) + : workInProgressRootConcurrentErrors.push(root); + if (null === returnFiber) return !0; + root = returnFiber; + do { + switch (root.tag) { + case 3: + return ( + (root.flags |= 65536), + (rootRenderLanes &= -rootRenderLanes), + (root.lanes |= rootRenderLanes), + (rootRenderLanes = createRootErrorUpdate( + root, + value, + rootRenderLanes + )), + enqueueCapturedUpdate(root, rootRenderLanes), + !1 + ); + case 1: + if ( + ((returnFiber = value), + (sourceFiber = root.type), + (tag = root.stateNode), + 0 === (root.flags & 128) && + ("function" === typeof sourceFiber.getDerivedStateFromError || + (null !== tag && + "function" === typeof tag.componentDidCatch && + (null === legacyErrorBoundariesThatAlreadyFailed || + !legacyErrorBoundariesThatAlreadyFailed.has(tag))))) + ) + return ( + (root.flags |= 65536), + (rootRenderLanes &= -rootRenderLanes), + (root.lanes |= rootRenderLanes), + (rootRenderLanes = createClassErrorUpdate( + root, + returnFiber, + rootRenderLanes + )), + enqueueCapturedUpdate(root, rootRenderLanes), + !1 + ); + } + root = root.return; + } while (null !== root); + return !1; +} var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner, SelectiveHydrationException = Error( "This is not a real error. It's an implementation detail of React's selective hydration feature. If this leaks into userspace, it's a bug in React. Please file an issue." @@ -5924,14 +6071,14 @@ function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { break; case "collapsed": lastTailNode = renderState.tail; - for (var lastTailNode$64 = null; null !== lastTailNode; ) - null !== lastTailNode.alternate && (lastTailNode$64 = lastTailNode), + for (var lastTailNode$65 = null; null !== lastTailNode; ) + null !== lastTailNode.alternate && (lastTailNode$65 = lastTailNode), (lastTailNode = lastTailNode.sibling); - null === lastTailNode$64 + null === lastTailNode$65 ? hasRenderedATailFallback || null === renderState.tail ? (renderState.tail = null) : (renderState.tail.sibling = null) - : (lastTailNode$64.sibling = null); + : (lastTailNode$65.sibling = null); } } function bubbleProperties(completedWork) { @@ -5941,19 +6088,19 @@ function bubbleProperties(completedWork) { newChildLanes = 0, subtreeFlags = 0; if (didBailout) - for (var child$65 = completedWork.child; null !== child$65; ) - (newChildLanes |= child$65.lanes | child$65.childLanes), - (subtreeFlags |= child$65.subtreeFlags & 31457280), - (subtreeFlags |= child$65.flags & 31457280), - (child$65.return = completedWork), - (child$65 = child$65.sibling); + for (var child$66 = completedWork.child; null !== child$66; ) + (newChildLanes |= child$66.lanes | child$66.childLanes), + (subtreeFlags |= child$66.subtreeFlags & 31457280), + (subtreeFlags |= child$66.flags & 31457280), + (child$66.return = completedWork), + (child$66 = child$66.sibling); else - for (child$65 = completedWork.child; null !== child$65; ) - (newChildLanes |= child$65.lanes | child$65.childLanes), - (subtreeFlags |= child$65.subtreeFlags), - (subtreeFlags |= child$65.flags), - (child$65.return = completedWork), - (child$65 = child$65.sibling); + for (child$66 = completedWork.child; null !== child$66; ) + (newChildLanes |= child$66.lanes | child$66.childLanes), + (subtreeFlags |= child$66.subtreeFlags), + (subtreeFlags |= child$66.flags), + (child$66.return = completedWork), + (child$66 = child$66.sibling); completedWork.subtreeFlags |= subtreeFlags; completedWork.childLanes = newChildLanes; return didBailout; @@ -6405,8 +6552,8 @@ function safelyDetachRef(current, nearestMountedAncestor) { else if ("function" === typeof ref) try { ref(null); - } catch (error$80) { - captureCommitPhaseError(current, nearestMountedAncestor, error$80); + } catch (error$81) { + captureCommitPhaseError(current, nearestMountedAncestor, error$81); } else ref.current = null; } @@ -6510,10 +6657,10 @@ function commitHookEffectListMount(flags, finishedWork) { var effect = (finishedWork = finishedWork.next); do { if ((effect.tag & flags) === flags) { - var create$81 = effect.create, + var create$82 = effect.create, inst = effect.inst; - create$81 = create$81(); - inst.destroy = create$81; + create$82 = create$82(); + inst.destroy = create$82; } effect = effect.next; } while (effect !== finishedWork); @@ -6567,11 +6714,11 @@ function commitLayoutEffectOnFiber(finishedRoot, current, finishedWork) { current, finishedRoot.__reactInternalSnapshotBeforeUpdate ); - } catch (error$82) { + } catch (error$83) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$82 + error$83 ); } } @@ -7060,8 +7207,8 @@ function commitMutationEffectsOnFiber(finishedWork, root) { } try { commitHookEffectListUnmount(5, finishedWork, finishedWork.return); - } catch (error$90) { - captureCommitPhaseError(finishedWork, finishedWork.return, error$90); + } catch (error$91) { + captureCommitPhaseError(finishedWork, finishedWork.return, error$91); } } break; @@ -7108,8 +7255,8 @@ function commitMutationEffectsOnFiber(finishedWork, root) { viewConfig.uiViewClassName, updatePayload ); - } catch (error$93) { - captureCommitPhaseError(finishedWork, finishedWork.return, error$93); + } catch (error$94) { + captureCommitPhaseError(finishedWork, finishedWork.return, error$94); } } break; @@ -7129,8 +7276,8 @@ function commitMutationEffectsOnFiber(finishedWork, root) { "RCTRawText", { text: current } ); - } catch (error$94) { - captureCommitPhaseError(finishedWork, finishedWork.return, error$94); + } catch (error$95) { + captureCommitPhaseError(finishedWork, finishedWork.return, error$95); } } break; @@ -7242,11 +7389,11 @@ function commitMutationEffectsOnFiber(finishedWork, root) { if (null === current) try { throw Error("Not yet implemented."); - } catch (error$84) { + } catch (error$85) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$84 + error$85 ); } } else if ( @@ -7320,12 +7467,12 @@ function commitReconciliationEffects(finishedWork) { break; case 3: case 4: - var parent$85 = JSCompiler_inline_result.stateNode.containerInfo, - before$86 = getHostSibling(finishedWork); + var parent$86 = JSCompiler_inline_result.stateNode.containerInfo, + before$87 = getHostSibling(finishedWork); insertOrAppendPlacementNodeIntoContainer( finishedWork, - before$86, - parent$85 + before$87, + parent$86 ); break; default: @@ -8177,13 +8324,13 @@ function renderRootSync(root, lanes) { default: (workInProgressSuspendedReason = 0), (workInProgressThrownValue = null), - throwAndUnwindWorkLoop(unitOfWork, thrownValue); + throwAndUnwindWorkLoop(root, unitOfWork, thrownValue); } } workLoopSync(); break; - } catch (thrownValue$98) { - handleThrow(root, thrownValue$98); + } catch (thrownValue$99) { + handleThrow(root, thrownValue$99); } while (1); lanes && root.shellSuspendCounter++; @@ -8219,7 +8366,7 @@ function renderRootConcurrent(root, lanes) { case 1: workInProgressSuspendedReason = 0; workInProgressThrownValue = null; - throwAndUnwindWorkLoop(lanes, thrownValue); + throwAndUnwindWorkLoop(root, lanes, thrownValue); break; case 2: if (isThenableResolved(thrownValue)) { @@ -8249,7 +8396,7 @@ function renderRootConcurrent(root, lanes) { replaySuspendedUnitOfWork(lanes)) : ((workInProgressSuspendedReason = 0), (workInProgressThrownValue = null), - throwAndUnwindWorkLoop(lanes, thrownValue)); + throwAndUnwindWorkLoop(root, lanes, thrownValue)); break; case 5: switch (workInProgress.tag) { @@ -8272,12 +8419,12 @@ function renderRootConcurrent(root, lanes) { } workInProgressSuspendedReason = 0; workInProgressThrownValue = null; - throwAndUnwindWorkLoop(lanes, thrownValue); + throwAndUnwindWorkLoop(root, lanes, thrownValue); break; case 6: workInProgressSuspendedReason = 0; workInProgressThrownValue = null; - throwAndUnwindWorkLoop(lanes, thrownValue); + throwAndUnwindWorkLoop(root, lanes, thrownValue); break; case 8: resetWorkInProgressStack(); @@ -8289,8 +8436,8 @@ function renderRootConcurrent(root, lanes) { } workLoopConcurrent(); break; - } catch (thrownValue$100) { - handleThrow(root, thrownValue$100); + } catch (thrownValue$101) { + handleThrow(root, thrownValue$101); } while (1); resetContextDependencies(); @@ -8368,191 +8515,55 @@ function replaySuspendedUnitOfWork(unitOfWork) { : (workInProgress = current); ReactCurrentOwner.current = null; } -function throwAndUnwindWorkLoop(unitOfWork, thrownValue) { +function throwAndUnwindWorkLoop(root, unitOfWork, thrownValue) { resetContextDependencies(); resetHooksOnUnwind(unitOfWork); thenableState$1 = null; thenableIndexCounter$1 = 0; var returnFiber = unitOfWork.return; - if (null === returnFiber || null === workInProgressRoot) - (workInProgressRootExitStatus = 1), - (workInProgressRootFatalError = thrownValue), - (workInProgress = null); - else { - try { - a: { - var root = workInProgressRoot, - value = thrownValue; - thrownValue = workInProgressRootRenderLanes; - unitOfWork.flags |= 32768; - if ( - null !== value && - "object" === typeof value && - "function" === typeof value.then - ) { - var wakeable = value, - tag = unitOfWork.tag; - if ( - 0 === (unitOfWork.mode & 1) && - (0 === tag || 11 === tag || 15 === tag) - ) { - var currentSource = unitOfWork.alternate; - currentSource - ? ((unitOfWork.updateQueue = currentSource.updateQueue), - (unitOfWork.memoizedState = currentSource.memoizedState), - (unitOfWork.lanes = currentSource.lanes)) - : ((unitOfWork.updateQueue = null), - (unitOfWork.memoizedState = null)); - } - var suspenseBoundary = suspenseHandlerStackCursor.current; - if (null !== suspenseBoundary) { - switch (suspenseBoundary.tag) { - case 13: - unitOfWork.mode & 1 && - (null === shellBoundary - ? renderDidSuspendDelayIfPossible() - : null === suspenseBoundary.alternate && - 0 === workInProgressRootExitStatus && - (workInProgressRootExitStatus = 3)); - suspenseBoundary.flags &= -257; - if (0 === (suspenseBoundary.mode & 1)) - if (suspenseBoundary === returnFiber) - suspenseBoundary.flags |= 65536; - else { - suspenseBoundary.flags |= 128; - unitOfWork.flags |= 131072; - unitOfWork.flags &= -52805; - if (1 === unitOfWork.tag) - if (null === unitOfWork.alternate) unitOfWork.tag = 17; - else { - var update = createUpdate(2); - update.tag = 2; - enqueueUpdate(unitOfWork, update, 2); - } - unitOfWork.lanes |= 2; - } - else - (suspenseBoundary.flags |= 65536), - (suspenseBoundary.lanes = thrownValue); - if (wakeable === noopSuspenseyCommitThenable) - suspenseBoundary.flags |= 16384; - else { - var retryQueue = suspenseBoundary.updateQueue; - null === retryQueue - ? (suspenseBoundary.updateQueue = new Set([wakeable])) - : retryQueue.add(wakeable); - suspenseBoundary.mode & 1 && - attachPingListener(root, wakeable, thrownValue); - } - break a; - case 22: - if (suspenseBoundary.mode & 1) { - suspenseBoundary.flags |= 65536; - if (wakeable === noopSuspenseyCommitThenable) - suspenseBoundary.flags |= 16384; - else { - var offscreenQueue = suspenseBoundary.updateQueue; - if (null === offscreenQueue) { - var newOffscreenQueue = { - transitions: null, - markerInstances: null, - retryQueue: new Set([wakeable]) - }; - suspenseBoundary.updateQueue = newOffscreenQueue; - } else { - var retryQueue$34 = offscreenQueue.retryQueue; - null === retryQueue$34 - ? (offscreenQueue.retryQueue = new Set([wakeable])) - : retryQueue$34.add(wakeable); - } - attachPingListener(root, wakeable, thrownValue); - } - break a; - } - } - throw Error( - "Unexpected Suspense handler tag (" + - suspenseBoundary.tag + - "). This is a bug in React." - ); - } - if (1 === root.tag) { - attachPingListener(root, wakeable, thrownValue); - renderDidSuspendDelayIfPossible(); - break a; - } else - value = Error( - "A component suspended while responding to synchronous input. This will cause the UI to be replaced with a loading indicator. To fix, updates that suspend should be wrapped with startTransition." - ); - } - root = value = createCapturedValueAtFiber(value, unitOfWork); - 4 !== workInProgressRootExitStatus && - (workInProgressRootExitStatus = 2); - null === workInProgressRootConcurrentErrors - ? (workInProgressRootConcurrentErrors = [root]) - : workInProgressRootConcurrentErrors.push(root); - root = returnFiber; - do { - switch (root.tag) { - case 3: - var errorInfo = value; - root.flags |= 65536; - thrownValue &= -thrownValue; - root.lanes |= thrownValue; - var update$jscomp$0 = createRootErrorUpdate( - root, - errorInfo, - thrownValue - ); - enqueueCapturedUpdate(root, update$jscomp$0); - break a; - case 1: - tag = value; - var ctor = root.type, - instance = root.stateNode; - if ( - 0 === (root.flags & 128) && - ("function" === typeof ctor.getDerivedStateFromError || - (null !== instance && - "function" === typeof instance.componentDidCatch && - (null === legacyErrorBoundariesThatAlreadyFailed || - !legacyErrorBoundariesThatAlreadyFailed.has(instance)))) - ) { - root.flags |= 65536; - update$jscomp$0 = thrownValue & -thrownValue; - root.lanes |= update$jscomp$0; - errorInfo = createClassErrorUpdate(root, tag, update$jscomp$0); - enqueueCapturedUpdate(root, errorInfo); - break a; - } - } - root = root.return; - } while (null !== root); - } - } catch (error) { - throw ((workInProgress = returnFiber), error); + try { + if ( + throwException( + root, + returnFiber, + unitOfWork, + thrownValue, + workInProgressRootRenderLanes + ) + ) { + workInProgressRootExitStatus = 1; + workInProgressRootFatalError = thrownValue; + workInProgress = null; + return; } - 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); + } catch (error) { + if (null !== returnFiber) throw ((workInProgress = returnFiber), error); + workInProgressRootExitStatus = 1; + workInProgressRootFatalError = thrownValue; + workInProgress = null; + return; } + if (unitOfWork.flags & 32768) + a: { + root = unitOfWork; + do { + unitOfWork = unwindWork(root.alternate, root); + if (null !== unitOfWork) { + unitOfWork.flags &= 32767; + workInProgress = unitOfWork; + break a; + } + root = root.return; + null !== root && + ((root.flags |= 32768), + (root.subtreeFlags = 0), + (root.deletions = null)); + workInProgress = root; + } while (null !== root); + workInProgressRootExitStatus = 6; + workInProgress = null; + } + else completeUnitOfWork(unitOfWork); } function completeUnitOfWork(unitOfWork) { var completedWork = unitOfWork; @@ -9772,10 +9783,10 @@ batchedUpdatesImpl = function (fn, a) { } }; var roots = new Map(), - devToolsConfig$jscomp$inline_1117 = { + devToolsConfig$jscomp$inline_1115 = { findFiberByHostInstance: getInstanceFromTag, bundleType: 0, - version: "18.3.0-canary-d76fd1b4", + version: "18.3.0-canary-eebf2655", rendererPackageName: "react-native-renderer", rendererConfig: { getInspectorDataForInstance: getInspectorDataForInstance, @@ -9791,11 +9802,11 @@ var roots = new Map(), }.bind(null, findNodeHandle) } }; -var internals$jscomp$inline_1370 = { - bundleType: devToolsConfig$jscomp$inline_1117.bundleType, - version: devToolsConfig$jscomp$inline_1117.version, - rendererPackageName: devToolsConfig$jscomp$inline_1117.rendererPackageName, - rendererConfig: devToolsConfig$jscomp$inline_1117.rendererConfig, +var internals$jscomp$inline_1350 = { + bundleType: devToolsConfig$jscomp$inline_1115.bundleType, + version: devToolsConfig$jscomp$inline_1115.version, + rendererPackageName: devToolsConfig$jscomp$inline_1115.rendererPackageName, + rendererConfig: devToolsConfig$jscomp$inline_1115.rendererConfig, overrideHookState: null, overrideHookStateDeletePath: null, overrideHookStateRenamePath: null, @@ -9811,26 +9822,26 @@ var internals$jscomp$inline_1370 = { return null === fiber ? null : fiber.stateNode; }, findFiberByHostInstance: - devToolsConfig$jscomp$inline_1117.findFiberByHostInstance || + devToolsConfig$jscomp$inline_1115.findFiberByHostInstance || emptyFindFiberByHostInstance, findHostInstancesForRefresh: null, scheduleRefresh: null, scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "18.3.0-canary-d76fd1b4" + reconcilerVersion: "18.3.0-canary-eebf2655" }; if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { - var hook$jscomp$inline_1371 = __REACT_DEVTOOLS_GLOBAL_HOOK__; + var hook$jscomp$inline_1351 = __REACT_DEVTOOLS_GLOBAL_HOOK__; if ( - !hook$jscomp$inline_1371.isDisabled && - hook$jscomp$inline_1371.supportsFiber + !hook$jscomp$inline_1351.isDisabled && + hook$jscomp$inline_1351.supportsFiber ) try { - (rendererID = hook$jscomp$inline_1371.inject( - internals$jscomp$inline_1370 + (rendererID = hook$jscomp$inline_1351.inject( + internals$jscomp$inline_1350 )), - (injectedHook = hook$jscomp$inline_1371); + (injectedHook = hook$jscomp$inline_1351); } catch (err) {} } exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = { diff --git a/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.fb.js b/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.fb.js index 429a1515957ac..193b40a250a76 100644 --- a/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.fb.js +++ b/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.fb.js @@ -7,7 +7,7 @@ * @noflow * @nolint * @preventMunge - * @generated SignedSource<<1ec259d95fb167ed4c8dd8c6c54e4cee>> + * @generated SignedSource<<375996f69ad5d47deb3462f97f5dbef9>> */ "use strict"; @@ -944,7 +944,7 @@ eventPluginOrder = Array.prototype.slice.call([ "ReactNativeBridgeEventPlugin" ]); recomputePluginOrdering(); -var injectedNamesToPlugins$jscomp$inline_257 = { +var injectedNamesToPlugins$jscomp$inline_258 = { ResponderEventPlugin: ResponderEventPlugin, ReactNativeBridgeEventPlugin: { eventTypes: {}, @@ -990,32 +990,32 @@ var injectedNamesToPlugins$jscomp$inline_257 = { } } }, - isOrderingDirty$jscomp$inline_258 = !1, - pluginName$jscomp$inline_259; -for (pluginName$jscomp$inline_259 in injectedNamesToPlugins$jscomp$inline_257) + isOrderingDirty$jscomp$inline_259 = !1, + pluginName$jscomp$inline_260; +for (pluginName$jscomp$inline_260 in injectedNamesToPlugins$jscomp$inline_258) if ( - injectedNamesToPlugins$jscomp$inline_257.hasOwnProperty( - pluginName$jscomp$inline_259 + injectedNamesToPlugins$jscomp$inline_258.hasOwnProperty( + pluginName$jscomp$inline_260 ) ) { - var pluginModule$jscomp$inline_260 = - injectedNamesToPlugins$jscomp$inline_257[pluginName$jscomp$inline_259]; + var pluginModule$jscomp$inline_261 = + injectedNamesToPlugins$jscomp$inline_258[pluginName$jscomp$inline_260]; if ( - !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_259) || - namesToPlugins[pluginName$jscomp$inline_259] !== - pluginModule$jscomp$inline_260 + !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_260) || + namesToPlugins[pluginName$jscomp$inline_260] !== + pluginModule$jscomp$inline_261 ) { - if (namesToPlugins[pluginName$jscomp$inline_259]) + if (namesToPlugins[pluginName$jscomp$inline_260]) throw Error( "EventPluginRegistry: Cannot inject two different event plugins using the same name, `" + - (pluginName$jscomp$inline_259 + "`.") + (pluginName$jscomp$inline_260 + "`.") ); - namesToPlugins[pluginName$jscomp$inline_259] = - pluginModule$jscomp$inline_260; - isOrderingDirty$jscomp$inline_258 = !0; + namesToPlugins[pluginName$jscomp$inline_260] = + pluginModule$jscomp$inline_261; + isOrderingDirty$jscomp$inline_259 = !0; } } -isOrderingDirty$jscomp$inline_258 && recomputePluginOrdering(); +isOrderingDirty$jscomp$inline_259 && recomputePluginOrdering(); var instanceCache = new Map(), instanceProps = new Map(); function getInstanceFromTag(tag) { @@ -2338,6 +2338,221 @@ function getRootForUpdatedFiber(sourceFiber) { (sourceFiber = parent), (parent = sourceFiber.return); return 3 === sourceFiber.tag ? sourceFiber.stateNode : null; } +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$2(ImmediatePriority, processRootScheduleInMicrotask)); + enableDeferRootSchedulingToMicrotask || + scheduleTaskForRootDuringMicrotask(root, now$1()); +} +function flushSyncWorkAcrossRoots_impl(onlyLegacy) { + if (!isFlushingWork && mightHavePendingSyncWork) { + var errors = null; + isFlushingWork = !0; + do { + var didPerformSomeWork = !1; + for (var root = firstScheduledRoot; null !== root; ) { + if (!onlyLegacy || 0 === root.tag) { + var workInProgressRootRenderLanes$14 = workInProgressRootRenderLanes, + nextLanes = getNextLanes( + root, + root === workInProgressRoot ? workInProgressRootRenderLanes$14 : 0 + ); + if (0 !== (nextLanes & 3)) + try { + didPerformSomeWork = !0; + workInProgressRootRenderLanes$14 = root; + if (0 !== (executionContext & 6)) + throw Error("Should not already be working."); + if (!flushPassiveEffects()) { + currentUpdateIsNested = nestedUpdateScheduled; + nestedUpdateScheduled = !1; + var exitStatus = renderRootSync( + workInProgressRootRenderLanes$14, + nextLanes + ); + if ( + 0 !== workInProgressRootRenderLanes$14.tag && + 2 === exitStatus + ) { + var originallyAttemptedLanes = nextLanes, + errorRetryLanes = getLanesToRetrySynchronouslyOnError( + workInProgressRootRenderLanes$14, + originallyAttemptedLanes + ); + 0 !== errorRetryLanes && + ((nextLanes = errorRetryLanes), + (exitStatus = recoverFromConcurrentError( + workInProgressRootRenderLanes$14, + originallyAttemptedLanes, + errorRetryLanes + ))); + } + if (1 === exitStatus) + throw ( + ((originallyAttemptedLanes = workInProgressRootFatalError), + prepareFreshStack(workInProgressRootRenderLanes$14, 0), + markRootSuspended( + workInProgressRootRenderLanes$14, + nextLanes, + 0 + ), + ensureRootIsScheduled(workInProgressRootRenderLanes$14), + originallyAttemptedLanes) + ); + 6 === exitStatus + ? markRootSuspended( + workInProgressRootRenderLanes$14, + nextLanes, + workInProgressDeferredLane + ) + : ((workInProgressRootRenderLanes$14.finishedWork = + workInProgressRootRenderLanes$14.current.alternate), + (workInProgressRootRenderLanes$14.finishedLanes = + nextLanes), + commitRoot( + workInProgressRootRenderLanes$14, + workInProgressRootRecoverableErrors, + workInProgressTransitions, + workInProgressDeferredLane + )); + } + ensureRootIsScheduled(workInProgressRootRenderLanes$14); + } 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++) + (didPerformSomeWork = throwError.bind(null, errors[onlyLegacy])), + scheduleCallback$2(ImmediatePriority, didPerformSomeWork); + } + throw errors[0]; + } + } +} +function throwError(error) { + throw error; +} +function processRootScheduleInMicrotask() { + mightHavePendingSyncWork = didScheduleMicrotask = !1; + for ( + var currentTime = now$1(), 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 & -62914561; + 0 < lanes; + + ) { + var index$6 = 31 - clz32(lanes), + lane = 1 << index$6, + expirationTime = expirationTimes[index$6]; + if (-1 === expirationTime) { + if (0 === (lane & suspendedLanes) || 0 !== (lane & pingedLanes)) + expirationTimes[index$6] = 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; + break; + case 268435456: + suspendedLanes = IdlePriority; + break; + default: + suspendedLanes = NormalPriority; + } + pingedLanes = performConcurrentWorkOnRoot.bind(null, root); + suspendedLanes = scheduleCallback$2(suspendedLanes, pingedLanes); + root.callbackPriority = currentTime; + root.callbackNode = suspendedLanes; + return currentTime; +} +function requestTransitionLane() { + if (0 === currentEventTransitionLane) { + var lane = nextTransitionLane; + nextTransitionLane <<= 1; + 0 === (nextTransitionLane & 4194176) && (nextTransitionLane = 128); + currentEventTransitionLane = lane; + } + return currentEventTransitionLane; +} var hasForceUpdate = !1; function initializeUpdateQueue(fiber) { fiber.updateQueue = { @@ -3513,264 +3728,49 @@ function pushPrimaryTreeSuspenseHandler(handler) { function pushOffscreenSuspenseHandler(fiber) { if (22 === fiber.tag) { if ( - (push(suspenseStackCursor, suspenseStackCursor.current), - push(suspenseHandlerStackCursor, fiber), - null === shellBoundary) - ) { - var current = fiber.alternate; - null !== current && - null !== current.memoizedState && - (shellBoundary = fiber); - } - } else reuseSuspenseHandlerOnStack(fiber); -} -function reuseSuspenseHandlerOnStack() { - push(suspenseStackCursor, suspenseStackCursor.current); - push(suspenseHandlerStackCursor, suspenseHandlerStackCursor.current); -} -function popSuspenseHandler(fiber) { - pop(suspenseHandlerStackCursor); - shellBoundary === fiber && (shellBoundary = null); - pop(suspenseStackCursor); -} -var suspenseStackCursor = createCursor(0); -function findFirstSuspended(row) { - for (var node = row; null !== node; ) { - if (13 === node.tag) { - var state = node.memoizedState; - if (null !== state && (null === state.dehydrated || shim$1() || shim$1())) - return node; - } else if (19 === node.tag && void 0 !== node.memoizedProps.revealOrder) { - if (0 !== (node.flags & 128)) return node; - } else if (null !== node.child) { - node.child.return = node; - node = node.child; - continue; - } - if (node === row) break; - for (; null === node.sibling; ) { - if (null === node.return || node.return === row) return null; - node = node.return; - } - node.sibling.return = node.return; - node = node.sibling; - } - return null; -} -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$2(ImmediatePriority, processRootScheduleInMicrotask)); - enableDeferRootSchedulingToMicrotask || - scheduleTaskForRootDuringMicrotask(root, now$1()); -} -function flushSyncWorkAcrossRoots_impl(onlyLegacy) { - if (!isFlushingWork && mightHavePendingSyncWork) { - var errors = null; - isFlushingWork = !0; - do { - var didPerformSomeWork = !1; - for (var root = firstScheduledRoot; null !== root; ) { - if (!onlyLegacy || 0 === root.tag) { - var workInProgressRootRenderLanes$31 = workInProgressRootRenderLanes, - nextLanes = getNextLanes( - root, - root === workInProgressRoot ? workInProgressRootRenderLanes$31 : 0 - ); - if (0 !== (nextLanes & 3)) - try { - didPerformSomeWork = !0; - workInProgressRootRenderLanes$31 = root; - if (0 !== (executionContext & 6)) - throw Error("Should not already be working."); - if (!flushPassiveEffects()) { - currentUpdateIsNested = nestedUpdateScheduled; - nestedUpdateScheduled = !1; - var exitStatus = renderRootSync( - workInProgressRootRenderLanes$31, - nextLanes - ); - if ( - 0 !== workInProgressRootRenderLanes$31.tag && - 2 === exitStatus - ) { - var originallyAttemptedLanes = nextLanes, - errorRetryLanes = getLanesToRetrySynchronouslyOnError( - workInProgressRootRenderLanes$31, - originallyAttemptedLanes - ); - 0 !== errorRetryLanes && - ((nextLanes = errorRetryLanes), - (exitStatus = recoverFromConcurrentError( - workInProgressRootRenderLanes$31, - originallyAttemptedLanes, - errorRetryLanes - ))); - } - if (1 === exitStatus) - throw ( - ((originallyAttemptedLanes = workInProgressRootFatalError), - prepareFreshStack(workInProgressRootRenderLanes$31, 0), - markRootSuspended( - workInProgressRootRenderLanes$31, - nextLanes, - 0 - ), - ensureRootIsScheduled(workInProgressRootRenderLanes$31), - originallyAttemptedLanes) - ); - 6 === exitStatus - ? markRootSuspended( - workInProgressRootRenderLanes$31, - nextLanes, - workInProgressDeferredLane - ) - : ((workInProgressRootRenderLanes$31.finishedWork = - workInProgressRootRenderLanes$31.current.alternate), - (workInProgressRootRenderLanes$31.finishedLanes = - nextLanes), - commitRoot( - workInProgressRootRenderLanes$31, - workInProgressRootRecoverableErrors, - workInProgressTransitions, - workInProgressDeferredLane - )); - } - ensureRootIsScheduled(workInProgressRootRenderLanes$31); - } 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++) - (didPerformSomeWork = throwError.bind(null, errors[onlyLegacy])), - scheduleCallback$2(ImmediatePriority, didPerformSomeWork); - } - throw errors[0]; + (push(suspenseStackCursor, suspenseStackCursor.current), + push(suspenseHandlerStackCursor, fiber), + null === shellBoundary) + ) { + var current = fiber.alternate; + null !== current && + null !== current.memoizedState && + (shellBoundary = fiber); } - } -} -function throwError(error) { - throw error; + } else reuseSuspenseHandlerOnStack(fiber); } -function processRootScheduleInMicrotask() { - mightHavePendingSyncWork = didScheduleMicrotask = !1; - for ( - var currentTime = now$1(), 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 reuseSuspenseHandlerOnStack() { + push(suspenseStackCursor, suspenseStackCursor.current); + push(suspenseHandlerStackCursor, suspenseHandlerStackCursor.current); } -function scheduleTaskForRootDuringMicrotask(root, currentTime) { - for ( - var suspendedLanes = root.suspendedLanes, - pingedLanes = root.pingedLanes, - expirationTimes = root.expirationTimes, - lanes = root.pendingLanes & -62914561; - 0 < lanes; - - ) { - var index$6 = 31 - clz32(lanes), - lane = 1 << index$6, - expirationTime = expirationTimes[index$6]; - if (-1 === expirationTime) { - if (0 === (lane & suspendedLanes) || 0 !== (lane & pingedLanes)) - expirationTimes[index$6] = 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; - break; - case 268435456: - suspendedLanes = IdlePriority; - break; - default: - suspendedLanes = NormalPriority; - } - pingedLanes = performConcurrentWorkOnRoot.bind(null, root); - suspendedLanes = scheduleCallback$2(suspendedLanes, pingedLanes); - root.callbackPriority = currentTime; - root.callbackNode = suspendedLanes; - return currentTime; +function popSuspenseHandler(fiber) { + pop(suspenseHandlerStackCursor); + shellBoundary === fiber && (shellBoundary = null); + pop(suspenseStackCursor); } -function requestTransitionLane() { - if (0 === currentEventTransitionLane) { - var lane = nextTransitionLane; - nextTransitionLane <<= 1; - 0 === (nextTransitionLane & 4194176) && (nextTransitionLane = 128); - currentEventTransitionLane = lane; +var suspenseStackCursor = createCursor(0); +function findFirstSuspended(row) { + for (var node = row; null !== node; ) { + if (13 === node.tag) { + var state = node.memoizedState; + if (null !== state && (null === state.dehydrated || shim$1() || shim$1())) + return node; + } else if (19 === node.tag && void 0 !== node.memoizedProps.revealOrder) { + if (0 !== (node.flags & 128)) return node; + } else if (null !== node.child) { + node.child.return = node; + node = node.child; + continue; + } + if (node === row) break; + for (; null === node.sibling; ) { + if (null === node.return || node.return === row) return null; + node = node.return; + } + node.sibling.return = node.return; + node = node.sibling; } - return currentEventTransitionLane; + return null; } var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, ReactCurrentBatchConfig$2 = ReactSharedInternals.ReactCurrentBatchConfig, @@ -4925,6 +4925,154 @@ function createClassErrorUpdate(fiber, errorInfo, lane) { }); return lane; } +function throwException( + root, + returnFiber, + sourceFiber, + value, + rootRenderLanes +) { + sourceFiber.flags |= 32768; + isDevToolsPresent && restorePendingUpdaters(root, rootRenderLanes); + if ( + null !== value && + "object" === typeof value && + "function" === typeof value.then + ) { + var tag = sourceFiber.tag; + 0 !== (sourceFiber.mode & 1) || + (0 !== tag && 11 !== tag && 15 !== tag) || + ((tag = sourceFiber.alternate) + ? ((sourceFiber.updateQueue = tag.updateQueue), + (sourceFiber.memoizedState = tag.memoizedState), + (sourceFiber.lanes = tag.lanes)) + : ((sourceFiber.updateQueue = null), + (sourceFiber.memoizedState = null))); + tag = suspenseHandlerStackCursor.current; + if (null !== tag) { + switch (tag.tag) { + case 13: + return ( + sourceFiber.mode & 1 && + (null === shellBoundary + ? renderDidSuspendDelayIfPossible() + : null === tag.alternate && + 0 === workInProgressRootExitStatus && + (workInProgressRootExitStatus = 3)), + (tag.flags &= -257), + 0 === (tag.mode & 1) + ? tag === returnFiber + ? (tag.flags |= 65536) + : ((tag.flags |= 128), + (sourceFiber.flags |= 131072), + (sourceFiber.flags &= -52805), + 1 === sourceFiber.tag && + (null === sourceFiber.alternate + ? (sourceFiber.tag = 17) + : ((returnFiber = createUpdate(2)), + (returnFiber.tag = 2), + enqueueUpdate(sourceFiber, returnFiber, 2))), + (sourceFiber.lanes |= 2)) + : ((tag.flags |= 65536), (tag.lanes = rootRenderLanes)), + value === noopSuspenseyCommitThenable + ? (tag.flags |= 16384) + : ((returnFiber = tag.updateQueue), + null === returnFiber + ? (tag.updateQueue = new Set([value])) + : returnFiber.add(value), + tag.mode & 1 && + attachPingListener(root, value, rootRenderLanes)), + !1 + ); + case 22: + if (tag.mode & 1) + return ( + (tag.flags |= 65536), + value === noopSuspenseyCommitThenable + ? (tag.flags |= 16384) + : ((returnFiber = tag.updateQueue), + null === returnFiber + ? ((returnFiber = { + transitions: null, + markerInstances: null, + retryQueue: new Set([value]) + }), + (tag.updateQueue = returnFiber)) + : ((sourceFiber = returnFiber.retryQueue), + null === sourceFiber + ? (returnFiber.retryQueue = new Set([value])) + : sourceFiber.add(value)), + attachPingListener(root, value, rootRenderLanes)), + !1 + ); + } + throw Error( + "Unexpected Suspense handler tag (" + + tag.tag + + "). This is a bug in React." + ); + } + if (1 === root.tag) + return ( + attachPingListener(root, value, rootRenderLanes), + renderDidSuspendDelayIfPossible(), + !1 + ); + value = Error( + "A component suspended while responding to synchronous input. This will cause the UI to be replaced with a loading indicator. To fix, updates that suspend should be wrapped with startTransition." + ); + } + root = value = createCapturedValueAtFiber(value, sourceFiber); + 4 !== workInProgressRootExitStatus && (workInProgressRootExitStatus = 2); + null === workInProgressRootConcurrentErrors + ? (workInProgressRootConcurrentErrors = [root]) + : workInProgressRootConcurrentErrors.push(root); + if (null === returnFiber) return !0; + root = returnFiber; + do { + switch (root.tag) { + case 3: + return ( + (root.flags |= 65536), + (rootRenderLanes &= -rootRenderLanes), + (root.lanes |= rootRenderLanes), + (rootRenderLanes = createRootErrorUpdate( + root, + value, + rootRenderLanes + )), + enqueueCapturedUpdate(root, rootRenderLanes), + !1 + ); + case 1: + if ( + ((returnFiber = value), + (sourceFiber = root.type), + (tag = root.stateNode), + 0 === (root.flags & 128) && + ("function" === typeof sourceFiber.getDerivedStateFromError || + (null !== tag && + "function" === typeof tag.componentDidCatch && + (null === legacyErrorBoundariesThatAlreadyFailed || + !legacyErrorBoundariesThatAlreadyFailed.has(tag))))) + ) + return ( + (root.flags |= 65536), + (rootRenderLanes &= -rootRenderLanes), + (root.lanes |= rootRenderLanes), + (rootRenderLanes = createClassErrorUpdate( + root, + returnFiber, + rootRenderLanes + )), + enqueueCapturedUpdate(root, rootRenderLanes), + !1 + ); + } + root = root.return; + } while (null !== root); + return !1; +} var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner, SelectiveHydrationException = Error( "This is not a real error. It's an implementation detail of React's selective hydration feature. If this leaks into userspace, it's a bug in React. Please file an issue." @@ -6148,14 +6296,14 @@ function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { break; case "collapsed": lastTailNode = renderState.tail; - for (var lastTailNode$68 = null; null !== lastTailNode; ) - null !== lastTailNode.alternate && (lastTailNode$68 = lastTailNode), + for (var lastTailNode$69 = null; null !== lastTailNode; ) + null !== lastTailNode.alternate && (lastTailNode$69 = lastTailNode), (lastTailNode = lastTailNode.sibling); - null === lastTailNode$68 + null === lastTailNode$69 ? hasRenderedATailFallback || null === renderState.tail ? (renderState.tail = null) : (renderState.tail.sibling = null) - : (lastTailNode$68.sibling = null); + : (lastTailNode$69.sibling = null); } } function bubbleProperties(completedWork) { @@ -6167,53 +6315,53 @@ function bubbleProperties(completedWork) { if (didBailout) if (0 !== (completedWork.mode & 2)) { for ( - var treeBaseDuration$70 = completedWork.selfBaseDuration, - child$71 = completedWork.child; - null !== child$71; + var treeBaseDuration$71 = completedWork.selfBaseDuration, + child$72 = completedWork.child; + null !== child$72; ) - (newChildLanes |= child$71.lanes | child$71.childLanes), - (subtreeFlags |= child$71.subtreeFlags & 31457280), - (subtreeFlags |= child$71.flags & 31457280), - (treeBaseDuration$70 += child$71.treeBaseDuration), - (child$71 = child$71.sibling); - completedWork.treeBaseDuration = treeBaseDuration$70; + (newChildLanes |= child$72.lanes | child$72.childLanes), + (subtreeFlags |= child$72.subtreeFlags & 31457280), + (subtreeFlags |= child$72.flags & 31457280), + (treeBaseDuration$71 += child$72.treeBaseDuration), + (child$72 = child$72.sibling); + completedWork.treeBaseDuration = treeBaseDuration$71; } else for ( - treeBaseDuration$70 = completedWork.child; - null !== treeBaseDuration$70; + treeBaseDuration$71 = completedWork.child; + null !== treeBaseDuration$71; ) (newChildLanes |= - treeBaseDuration$70.lanes | treeBaseDuration$70.childLanes), - (subtreeFlags |= treeBaseDuration$70.subtreeFlags & 31457280), - (subtreeFlags |= treeBaseDuration$70.flags & 31457280), - (treeBaseDuration$70.return = completedWork), - (treeBaseDuration$70 = treeBaseDuration$70.sibling); + treeBaseDuration$71.lanes | treeBaseDuration$71.childLanes), + (subtreeFlags |= treeBaseDuration$71.subtreeFlags & 31457280), + (subtreeFlags |= treeBaseDuration$71.flags & 31457280), + (treeBaseDuration$71.return = completedWork), + (treeBaseDuration$71 = treeBaseDuration$71.sibling); else if (0 !== (completedWork.mode & 2)) { - treeBaseDuration$70 = completedWork.actualDuration; - child$71 = completedWork.selfBaseDuration; + treeBaseDuration$71 = completedWork.actualDuration; + child$72 = completedWork.selfBaseDuration; for (var child = completedWork.child; null !== child; ) (newChildLanes |= child.lanes | child.childLanes), (subtreeFlags |= child.subtreeFlags), (subtreeFlags |= child.flags), - (treeBaseDuration$70 += child.actualDuration), - (child$71 += child.treeBaseDuration), + (treeBaseDuration$71 += child.actualDuration), + (child$72 += child.treeBaseDuration), (child = child.sibling); - completedWork.actualDuration = treeBaseDuration$70; - completedWork.treeBaseDuration = child$71; + completedWork.actualDuration = treeBaseDuration$71; + completedWork.treeBaseDuration = child$72; } else for ( - treeBaseDuration$70 = completedWork.child; - null !== treeBaseDuration$70; + treeBaseDuration$71 = completedWork.child; + null !== treeBaseDuration$71; ) (newChildLanes |= - treeBaseDuration$70.lanes | treeBaseDuration$70.childLanes), - (subtreeFlags |= treeBaseDuration$70.subtreeFlags), - (subtreeFlags |= treeBaseDuration$70.flags), - (treeBaseDuration$70.return = completedWork), - (treeBaseDuration$70 = treeBaseDuration$70.sibling); + treeBaseDuration$71.lanes | treeBaseDuration$71.childLanes), + (subtreeFlags |= treeBaseDuration$71.subtreeFlags), + (subtreeFlags |= treeBaseDuration$71.flags), + (treeBaseDuration$71.return = completedWork), + (treeBaseDuration$71 = treeBaseDuration$71.sibling); completedWork.subtreeFlags |= subtreeFlags; completedWork.childLanes = newChildLanes; return didBailout; @@ -6723,8 +6871,8 @@ function safelyDetachRef(current, nearestMountedAncestor) { recordLayoutEffectDuration(current); } else ref(null); - } catch (error$89) { - captureCommitPhaseError(current, nearestMountedAncestor, error$89); + } catch (error$90) { + captureCommitPhaseError(current, nearestMountedAncestor, error$90); } else ref.current = null; } @@ -6857,10 +7005,10 @@ function commitHookEffectListMount(flags, finishedWork) { injectedProfilingHooks.markComponentLayoutEffectMountStarted( finishedWork ); - var create$90 = effect.create, + var create$91 = effect.create, inst = effect.inst; - create$90 = create$90(); - inst.destroy = create$90; + create$91 = create$91(); + inst.destroy = create$91; 0 !== (flags & 8) ? null !== injectedProfilingHooks && "function" === @@ -6888,8 +7036,8 @@ function commitHookLayoutEffects(finishedWork, hookFlags) { } else try { commitHookEffectListMount(hookFlags, finishedWork); - } catch (error$92) { - captureCommitPhaseError(finishedWork, finishedWork.return, error$92); + } catch (error$93) { + captureCommitPhaseError(finishedWork, finishedWork.return, error$93); } } function commitClassCallbacks(finishedWork) { @@ -6969,11 +7117,11 @@ function commitLayoutEffectOnFiber(finishedRoot, current, finishedWork) { } else try { finishedRoot.componentDidMount(); - } catch (error$93) { + } catch (error$94) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$93 + error$94 ); } else { @@ -6990,11 +7138,11 @@ function commitLayoutEffectOnFiber(finishedRoot, current, finishedWork) { current, finishedRoot.__reactInternalSnapshotBeforeUpdate ); - } catch (error$94) { + } catch (error$95) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$94 + error$95 ); } recordLayoutEffectDuration(finishedWork); @@ -7005,11 +7153,11 @@ function commitLayoutEffectOnFiber(finishedRoot, current, finishedWork) { current, finishedRoot.__reactInternalSnapshotBeforeUpdate ); - } catch (error$95) { + } catch (error$96) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$95 + error$96 ); } } @@ -7525,22 +7673,22 @@ function commitMutationEffectsOnFiber(finishedWork, root) { try { startLayoutEffectTimer(), commitHookEffectListUnmount(5, finishedWork, finishedWork.return); - } catch (error$104) { + } catch (error$105) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$104 + error$105 ); } recordLayoutEffectDuration(finishedWork); } else try { commitHookEffectListUnmount(5, finishedWork, finishedWork.return); - } catch (error$105) { + } catch (error$106) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$105 + error$106 ); } } @@ -7588,8 +7736,8 @@ function commitMutationEffectsOnFiber(finishedWork, root) { viewConfig.uiViewClassName, updatePayload ); - } catch (error$108) { - captureCommitPhaseError(finishedWork, finishedWork.return, error$108); + } catch (error$109) { + captureCommitPhaseError(finishedWork, finishedWork.return, error$109); } } break; @@ -7609,8 +7757,8 @@ function commitMutationEffectsOnFiber(finishedWork, root) { "RCTRawText", { text: current } ); - } catch (error$109) { - captureCommitPhaseError(finishedWork, finishedWork.return, error$109); + } catch (error$110) { + captureCommitPhaseError(finishedWork, finishedWork.return, error$110); } } break; @@ -7722,11 +7870,11 @@ function commitMutationEffectsOnFiber(finishedWork, root) { if (null === current) try { throw Error("Not yet implemented."); - } catch (error$98) { + } catch (error$99) { captureCommitPhaseError( finishedWork, finishedWork.return, - error$98 + error$99 ); } } else if ( @@ -7800,12 +7948,12 @@ function commitReconciliationEffects(finishedWork) { break; case 3: case 4: - var parent$99 = JSCompiler_inline_result.stateNode.containerInfo, - before$100 = getHostSibling(finishedWork); + var parent$100 = JSCompiler_inline_result.stateNode.containerInfo, + before$101 = getHostSibling(finishedWork); insertOrAppendPlacementNodeIntoContainer( finishedWork, - before$100, - parent$99 + before$101, + parent$100 ); break; default: @@ -7991,8 +8139,8 @@ function commitHookPassiveMountEffects(finishedWork, hookFlags) { } else try { commitHookEffectListMount(hookFlags, finishedWork); - } catch (error$113) { - captureCommitPhaseError(finishedWork, finishedWork.return, error$113); + } catch (error$114) { + captureCommitPhaseError(finishedWork, finishedWork.return, error$114); } } function recursivelyTraversePassiveMountEffects(root, parentFiber) { @@ -8740,13 +8888,13 @@ function renderRootSync(root, lanes) { default: (workInProgressSuspendedReason = 0), (workInProgressThrownValue = null), - throwAndUnwindWorkLoop(memoizedUpdaters, thrownValue); + throwAndUnwindWorkLoop(root, memoizedUpdaters, thrownValue); } } workLoopSync(); break; - } catch (thrownValue$114) { - handleThrow(root, thrownValue$114); + } catch (thrownValue$115) { + handleThrow(root, thrownValue$115); } while (1); lanes && root.shellSuspendCounter++; @@ -8794,7 +8942,7 @@ function renderRootConcurrent(root, lanes) { case 1: workInProgressSuspendedReason = 0; workInProgressThrownValue = null; - throwAndUnwindWorkLoop(lanes, memoizedUpdaters); + throwAndUnwindWorkLoop(root, lanes, memoizedUpdaters); break; case 2: if (isThenableResolved(memoizedUpdaters)) { @@ -8824,7 +8972,7 @@ function renderRootConcurrent(root, lanes) { replaySuspendedUnitOfWork(lanes)) : ((workInProgressSuspendedReason = 0), (workInProgressThrownValue = null), - throwAndUnwindWorkLoop(lanes, memoizedUpdaters)); + throwAndUnwindWorkLoop(root, lanes, memoizedUpdaters)); break; case 5: switch (workInProgress.tag) { @@ -8847,12 +8995,12 @@ function renderRootConcurrent(root, lanes) { } workInProgressSuspendedReason = 0; workInProgressThrownValue = null; - throwAndUnwindWorkLoop(lanes, memoizedUpdaters); + throwAndUnwindWorkLoop(root, lanes, memoizedUpdaters); break; case 6: workInProgressSuspendedReason = 0; workInProgressThrownValue = null; - throwAndUnwindWorkLoop(lanes, memoizedUpdaters); + throwAndUnwindWorkLoop(root, lanes, memoizedUpdaters); break; case 8: resetWorkInProgressStack(); @@ -8863,8 +9011,8 @@ function renderRootConcurrent(root, lanes) { } workLoopConcurrent(); break; - } catch (thrownValue$116) { - handleThrow(root, thrownValue$116); + } catch (thrownValue$117) { + handleThrow(root, thrownValue$117); } while (1); resetContextDependencies(); @@ -8959,200 +9107,63 @@ function replaySuspendedUnitOfWork(unitOfWork) { : (workInProgress = current); ReactCurrentOwner.current = null; } -function throwAndUnwindWorkLoop(unitOfWork, thrownValue) { +function throwAndUnwindWorkLoop(root, unitOfWork, thrownValue) { resetContextDependencies(); resetHooksOnUnwind(unitOfWork); thenableState$1 = null; thenableIndexCounter$1 = 0; var returnFiber = unitOfWork.return; - if (null === returnFiber || null === workInProgressRoot) - (workInProgressRootExitStatus = 1), - (workInProgressRootFatalError = thrownValue), - (workInProgress = null); - else { - try { - a: { - var root = workInProgressRoot, - value = thrownValue; - thrownValue = workInProgressRootRenderLanes; - unitOfWork.flags |= 32768; - isDevToolsPresent && restorePendingUpdaters(root, thrownValue); - if ( - null !== value && - "object" === typeof value && - "function" === typeof value.then - ) { - var wakeable = value, - tag = unitOfWork.tag; - if ( - 0 === (unitOfWork.mode & 1) && - (0 === tag || 11 === tag || 15 === tag) - ) { - var currentSource = unitOfWork.alternate; - currentSource - ? ((unitOfWork.updateQueue = currentSource.updateQueue), - (unitOfWork.memoizedState = currentSource.memoizedState), - (unitOfWork.lanes = currentSource.lanes)) - : ((unitOfWork.updateQueue = null), - (unitOfWork.memoizedState = null)); - } - var suspenseBoundary = suspenseHandlerStackCursor.current; - if (null !== suspenseBoundary) { - switch (suspenseBoundary.tag) { - case 13: - unitOfWork.mode & 1 && - (null === shellBoundary - ? renderDidSuspendDelayIfPossible() - : null === suspenseBoundary.alternate && - 0 === workInProgressRootExitStatus && - (workInProgressRootExitStatus = 3)); - suspenseBoundary.flags &= -257; - if (0 === (suspenseBoundary.mode & 1)) - if (suspenseBoundary === returnFiber) - suspenseBoundary.flags |= 65536; - else { - suspenseBoundary.flags |= 128; - unitOfWork.flags |= 131072; - unitOfWork.flags &= -52805; - if (1 === unitOfWork.tag) - if (null === unitOfWork.alternate) unitOfWork.tag = 17; - else { - var update = createUpdate(2); - update.tag = 2; - enqueueUpdate(unitOfWork, update, 2); - } - unitOfWork.lanes |= 2; - } - else - (suspenseBoundary.flags |= 65536), - (suspenseBoundary.lanes = thrownValue); - if (wakeable === noopSuspenseyCommitThenable) - suspenseBoundary.flags |= 16384; - else { - var retryQueue = suspenseBoundary.updateQueue; - null === retryQueue - ? (suspenseBoundary.updateQueue = new Set([wakeable])) - : retryQueue.add(wakeable); - suspenseBoundary.mode & 1 && - attachPingListener(root, wakeable, thrownValue); - } - break a; - case 22: - if (suspenseBoundary.mode & 1) { - suspenseBoundary.flags |= 65536; - if (wakeable === noopSuspenseyCommitThenable) - suspenseBoundary.flags |= 16384; - else { - var offscreenQueue = suspenseBoundary.updateQueue; - if (null === offscreenQueue) { - var newOffscreenQueue = { - transitions: null, - markerInstances: null, - retryQueue: new Set([wakeable]) - }; - suspenseBoundary.updateQueue = newOffscreenQueue; - } else { - var retryQueue$37 = offscreenQueue.retryQueue; - null === retryQueue$37 - ? (offscreenQueue.retryQueue = new Set([wakeable])) - : retryQueue$37.add(wakeable); - } - attachPingListener(root, wakeable, thrownValue); - } - break a; - } - } - throw Error( - "Unexpected Suspense handler tag (" + - suspenseBoundary.tag + - "). This is a bug in React." - ); - } - if (1 === root.tag) { - attachPingListener(root, wakeable, thrownValue); - renderDidSuspendDelayIfPossible(); - break a; - } else - value = Error( - "A component suspended while responding to synchronous input. This will cause the UI to be replaced with a loading indicator. To fix, updates that suspend should be wrapped with startTransition." - ); - } - root = value = createCapturedValueAtFiber(value, unitOfWork); - 4 !== workInProgressRootExitStatus && - (workInProgressRootExitStatus = 2); - null === workInProgressRootConcurrentErrors - ? (workInProgressRootConcurrentErrors = [root]) - : workInProgressRootConcurrentErrors.push(root); - root = returnFiber; - do { - switch (root.tag) { - case 3: - var errorInfo = value; - root.flags |= 65536; - thrownValue &= -thrownValue; - root.lanes |= thrownValue; - var update$jscomp$0 = createRootErrorUpdate( - root, - errorInfo, - thrownValue - ); - enqueueCapturedUpdate(root, update$jscomp$0); - break a; - case 1: - tag = value; - var ctor = root.type, - instance = root.stateNode; - if ( - 0 === (root.flags & 128) && - ("function" === typeof ctor.getDerivedStateFromError || - (null !== instance && - "function" === typeof instance.componentDidCatch && - (null === legacyErrorBoundariesThatAlreadyFailed || - !legacyErrorBoundariesThatAlreadyFailed.has(instance)))) - ) { - root.flags |= 65536; - update$jscomp$0 = thrownValue & -thrownValue; - root.lanes |= update$jscomp$0; - errorInfo = createClassErrorUpdate(root, tag, update$jscomp$0); - enqueueCapturedUpdate(root, errorInfo); - break a; - } - } - root = root.return; - } while (null !== root); - } - } catch (error) { - throw ((workInProgress = returnFiber), error); + try { + if ( + throwException( + root, + returnFiber, + unitOfWork, + thrownValue, + workInProgressRootRenderLanes + ) + ) { + workInProgressRootExitStatus = 1; + workInProgressRootFatalError = thrownValue; + workInProgress = null; + return; } - if (unitOfWork.flags & 32768) - a: { - do { - returnFiber = unwindWork(unitOfWork.alternate, unitOfWork); - if (null !== returnFiber) { - returnFiber.flags &= 32767; - workInProgress = returnFiber; - break a; - } - if (0 !== (unitOfWork.mode & 2)) { - stopProfilerTimerIfRunningAndRecordDelta(unitOfWork, !1); - returnFiber = unitOfWork.actualDuration; - for (update$jscomp$0 = unitOfWork.child; null !== update$jscomp$0; ) - (returnFiber += update$jscomp$0.actualDuration), - (update$jscomp$0 = update$jscomp$0.sibling); - unitOfWork.actualDuration = returnFiber; - } - 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); + } catch (error) { + if (null !== returnFiber) throw ((workInProgress = returnFiber), error); + workInProgressRootExitStatus = 1; + workInProgressRootFatalError = thrownValue; + workInProgress = null; + return; } + if (unitOfWork.flags & 32768) + a: { + root = unitOfWork; + do { + unitOfWork = unwindWork(root.alternate, root); + if (null !== unitOfWork) { + unitOfWork.flags &= 32767; + workInProgress = unitOfWork; + break a; + } + if (0 !== (root.mode & 2)) { + stopProfilerTimerIfRunningAndRecordDelta(root, !1); + unitOfWork = root.actualDuration; + for (thrownValue = root.child; null !== thrownValue; ) + (unitOfWork += thrownValue.actualDuration), + (thrownValue = thrownValue.sibling); + root.actualDuration = unitOfWork; + } + root = root.return; + null !== root && + ((root.flags |= 32768), + (root.subtreeFlags = 0), + (root.deletions = null)); + workInProgress = root; + } while (null !== root); + workInProgressRootExitStatus = 6; + workInProgress = null; + } + else completeUnitOfWork(unitOfWork); } function completeUnitOfWork(unitOfWork) { var completedWork = unitOfWork; @@ -9340,11 +9351,11 @@ function flushPassiveEffects() { _finishedWork$memoize = finishedWork.memoizedProps, id = _finishedWork$memoize.id, onPostCommit = _finishedWork$memoize.onPostCommit, - commitTime$91 = commitTime, + commitTime$92 = commitTime, phase = null === finishedWork.alternate ? "mount" : "update"; currentUpdateIsNested && (phase = "nested-update"); "function" === typeof onPostCommit && - onPostCommit(id, phase, passiveEffectDuration, commitTime$91); + onPostCommit(id, phase, passiveEffectDuration, commitTime$92); var parentFiber = finishedWork.return; b: for (; null !== parentFiber; ) { switch (parentFiber.tag) { @@ -10474,10 +10485,10 @@ batchedUpdatesImpl = function (fn, a) { } }; var roots = new Map(), - devToolsConfig$jscomp$inline_1195 = { + devToolsConfig$jscomp$inline_1193 = { findFiberByHostInstance: getInstanceFromTag, bundleType: 0, - version: "18.3.0-canary-f4e963ab", + version: "18.3.0-canary-aa92563e", rendererPackageName: "react-native-renderer", rendererConfig: { getInspectorDataForInstance: getInspectorDataForInstance, @@ -10507,10 +10518,10 @@ var roots = new Map(), } catch (err) {} return hook.checkDCE ? !0 : !1; })({ - bundleType: devToolsConfig$jscomp$inline_1195.bundleType, - version: devToolsConfig$jscomp$inline_1195.version, - rendererPackageName: devToolsConfig$jscomp$inline_1195.rendererPackageName, - rendererConfig: devToolsConfig$jscomp$inline_1195.rendererConfig, + bundleType: devToolsConfig$jscomp$inline_1193.bundleType, + version: devToolsConfig$jscomp$inline_1193.version, + rendererPackageName: devToolsConfig$jscomp$inline_1193.rendererPackageName, + rendererConfig: devToolsConfig$jscomp$inline_1193.rendererConfig, overrideHookState: null, overrideHookStateDeletePath: null, overrideHookStateRenamePath: null, @@ -10526,14 +10537,14 @@ var roots = new Map(), return null === fiber ? null : fiber.stateNode; }, findFiberByHostInstance: - devToolsConfig$jscomp$inline_1195.findFiberByHostInstance || + devToolsConfig$jscomp$inline_1193.findFiberByHostInstance || emptyFindFiberByHostInstance, findHostInstancesForRefresh: null, scheduleRefresh: null, scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "18.3.0-canary-f4e963ab" + reconcilerVersion: "18.3.0-canary-aa92563e" }); exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = { computeComponentStackForErrorReporting: function (reactTag) {