From 2fe5b572bc79c51785bcd17dd16e85427c1d2548 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Markb=C3=A5ge?= Date: Thu, 30 Jan 2025 11:46:43 -0500 Subject: [PATCH 01/72] [Fiber] Read the class name from props.layout (#32273) Copypasta typo. --- packages/react-reconciler/src/ReactFiberCommitWork.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-reconciler/src/ReactFiberCommitWork.js b/packages/react-reconciler/src/ReactFiberCommitWork.js index b3f28d909469f..b465558ddb3fd 100644 --- a/packages/react-reconciler/src/ReactFiberCommitWork.js +++ b/packages/react-reconciler/src/ReactFiberCommitWork.js @@ -1212,7 +1212,7 @@ function measureUpdateViewTransition( ); const layoutClassName: ?string = getViewTransitionClassName( props.className, - props.update, + props.layout, ); let className: ?string; if (updateClassName === 'none') { From 14f7c072719564ee4269c5fdadb6b8a737546422 Mon Sep 17 00:00:00 2001 From: lauren Date: Thu, 30 Jan 2025 11:49:04 -0500 Subject: [PATCH 02/72] [ci] Try to parallelize devtools builds (#32266) Building DevTools is currently the long pole for the runtime CI job. Let's see if we can get the overall runtime for runtime build and test down by speeding this one step up. --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/react/pull/32266). * #32267 * __->__ #32266 --- .github/workflows/runtime_build_and_test.yml | 18 ++++++++---------- .../ci/pack_and_store_devtools_artifacts.sh | 14 ++++++++++---- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/.github/workflows/runtime_build_and_test.yml b/.github/workflows/runtime_build_and_test.yml index 78cbac7fb536d..77c54a4167178 100644 --- a/.github/workflows/runtime_build_and_test.yml +++ b/.github/workflows/runtime_build_and_test.yml @@ -501,6 +501,9 @@ jobs: name: Build DevTools and process artifacts needs: build_and_lint runs-on: ubuntu-latest + strategy: + matrix: + browser: [chrome, firefox, edge] steps: - uses: actions/checkout@v4 with: @@ -525,7 +528,7 @@ jobs: pattern: _build_* path: build merge-multiple: true - - run: ./scripts/ci/pack_and_store_devtools_artifacts.sh + - run: ./scripts/ci/pack_and_store_devtools_artifacts.sh ${{ matrix.browser }} env: RELEASE_CHANNEL: experimental - name: Display structure of build @@ -533,19 +536,14 @@ jobs: - name: Archive devtools build uses: actions/upload-artifact@v4 with: - name: react-devtools + name: react-devtools-${{ matrix.browser }} path: build/devtools.tgz # Simplifies getting the extension for local testing - - name: Archive chrome extension - uses: actions/upload-artifact@v4 - with: - name: react-devtools-chrome-extension - path: build/devtools/chrome-extension.zip - - name: Archive firefox extension + - name: Archive ${{ matrix.browser }} extension uses: actions/upload-artifact@v4 with: - name: react-devtools-firefox-extension - path: build/devtools/firefox-extension.zip + name: react-devtools-${{ matrix.browser }}-extension + path: build/devtools/${{ matrix.browser }}-extension.zip run_devtools_e2e_tests: name: Run DevTools e2e tests diff --git a/scripts/ci/pack_and_store_devtools_artifacts.sh b/scripts/ci/pack_and_store_devtools_artifacts.sh index 664440fd834f5..5118b42624732 100755 --- a/scripts/ci/pack_and_store_devtools_artifacts.sh +++ b/scripts/ci/pack_and_store_devtools_artifacts.sh @@ -17,10 +17,16 @@ npm pack mv ./react-devtools-inline*.tgz ../../build/devtools/ cd ../react-devtools-extensions -yarn build -mv ./chrome/build/ReactDevTools.zip ../../build/devtools/chrome-extension.zip -mv ./firefox/build/ReactDevTools.zip ../../build/devtools/firefox-extension.zip +if [[ -n "$1" ]]; then + yarn build:$1 + mv ./$1/build/ReactDevTools.zip ../../build/devtools/$1-extension.zip +else + yarn build + for browser in chrome firefox edge; do + mv ./$browser/build/ReactDevTools.zip ../../build/devtools/$browser-extension.zip + done +fi # Compress all DevTools artifacts into a single tarball for easy download cd ../../build/devtools -tar -zcvf ../devtools.tgz . \ No newline at end of file +tar -zcvf ../devtools.tgz . From f02ba2fcc5de5c280d5c79f52302b04daaaf1e23 Mon Sep 17 00:00:00 2001 From: lauren Date: Thu, 30 Jan 2025 11:55:28 -0500 Subject: [PATCH 03/72] [ci] Remove build_devtools_and_process_artifacts as a dependency to run_devtools_e2e_tests (#32267) I just noticed that we don't actually need to let the devtools build finish first because the e2e tests don't use those built files. We can decouple them to allow them to run in paralllel. --- .github/workflows/runtime_build_and_test.yml | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/.github/workflows/runtime_build_and_test.yml b/.github/workflows/runtime_build_and_test.yml index 77c54a4167178..99b6bb4a272e2 100644 --- a/.github/workflows/runtime_build_and_test.yml +++ b/.github/workflows/runtime_build_and_test.yml @@ -533,11 +533,6 @@ jobs: RELEASE_CHANNEL: experimental - name: Display structure of build run: ls -R build - - name: Archive devtools build - uses: actions/upload-artifact@v4 - with: - name: react-devtools-${{ matrix.browser }} - path: build/devtools.tgz # Simplifies getting the extension for local testing - name: Archive ${{ matrix.browser }} extension uses: actions/upload-artifact@v4 @@ -545,9 +540,20 @@ jobs: name: react-devtools-${{ matrix.browser }}-extension path: build/devtools/${{ matrix.browser }}-extension.zip + merge_devtools_artifacts: + name: Merge DevTools artifacts + needs: build_devtools_and_process_artifacts + runs-on: ubuntu-latest + steps: + - name: Merge artifacts + uses: actions/upload-artifact/merge@v4 + with: + name: react-devtools + pattern: react-devtools-*-extension + run_devtools_e2e_tests: name: Run DevTools e2e tests - needs: build_devtools_and_process_artifacts + needs: build_and_lint runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 From 4b3728f05efbab9624e981339d8a0992a58f9a41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Markb=C3=A5ge?= Date: Thu, 30 Jan 2025 12:13:36 -0500 Subject: [PATCH 04/72] [Fiber] Track Appearing Named ViewTransition in the accumulateSuspenseyCommit Phase (#32254) When a named ViewTransition component unmounts in one place and mounts in a different place we need to match these up so we know a pair has been created. Since the unmounts are tracked in the snapshot phase we need some way to track the mounts before that. Originally the way I did that is by reusing the render phase since there was no other phase in the commit before that. However, that's not quite correct. Just because something is visited in render doesn't mean it'll commit. E.g. if that tree ends up suspending or erroring. Which would lead to a false positive on match. The unmount shouldn't animate in that case. (Un)fortunately we have already added a traversal before the snapshot phase for tracking suspensey CSS. The `accumulateSuspenseyCommit` phase. This needs to find new mounts of Suspensey CSS or if there was a reappearing Offscreen boundary it needs to find any Suspensey CSS already inside that tree. This is exactly the same traversal we need to find newly appearing View Transition components. So we can just reuse that. --- .../src/ReactFiberBeginWork.js | 12 ++- .../src/ReactFiberCommitWork.js | 81 ++++++++++++------- .../src/ReactFiberCompleteWork.js | 42 ---------- .../react-reconciler/src/ReactFiberFlags.js | 7 +- .../src/ReactFiberWorkLoop.js | 46 +---------- 5 files changed, 66 insertions(+), 122 deletions(-) diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.js b/packages/react-reconciler/src/ReactFiberBeginWork.js index 28cdd0e1ed54c..6f4acf97cf455 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.js @@ -97,6 +97,7 @@ import { Passive, DidDefer, ViewTransitionNamedStatic, + ViewTransitionNamedMount, LayoutStatic, } from './ReactFiberFlags'; import { @@ -266,7 +267,6 @@ import { markSkippedUpdateLanes, getWorkInProgressRoot, peekDeferredLane, - trackAppearingViewTransition, } from './ReactFiberWorkLoop'; import {enqueueConcurrentRenderForLane} from './ReactFiberConcurrentUpdates'; import {pushCacheProvider, CacheContext} from './ReactFiberCacheComponent'; @@ -3243,12 +3243,10 @@ function updateViewTransition( if (pendingProps.name != null && pendingProps.name !== 'auto') { // Explicitly named boundary. We track it so that we can pair it up with another explicit // boundary if we get deleted. - workInProgress.flags |= ViewTransitionNamedStatic; - if (current === null) { - // This is a new mount. We track it in case we end up having a deletion with the same name. - // TODO: A problem with this strategy is that this subtree might not actually end up mounted. - trackAppearingViewTransition(instance, pendingProps.name); - } + workInProgress.flags |= + current === null + ? ViewTransitionNamedMount | ViewTransitionNamedStatic + : ViewTransitionNamedStatic; } else { // Assign an auto generated name using the useId algorthim if an explicit one is not provided. // We don't need the name yet but we do it here to allow hydration state to be used. diff --git a/packages/react-reconciler/src/ReactFiberCommitWork.js b/packages/react-reconciler/src/ReactFiberCommitWork.js index b465558ddb3fd..1cfe38cc209fa 100644 --- a/packages/react-reconciler/src/ReactFiberCommitWork.js +++ b/packages/react-reconciler/src/ReactFiberCommitWork.js @@ -276,6 +276,10 @@ export let shouldFireAfterActiveInstanceBlur: boolean = false; export let shouldStartViewTransition: boolean = false; +// This tracks named ViewTransition components found in the accumulateSuspenseyCommit +// phase that might need to find deleted pairs in the beforeMutation phase. +let appearingViewTransitions: Map | null = null; + // Used during the commit phase to track whether a parent ViewTransition component // might have been affected by any mutations / relayouts below. let viewTransitionContextChanged: boolean = false; @@ -288,7 +292,6 @@ export function commitBeforeMutationEffects( root: FiberRoot, firstChild: Fiber, committedLanes: Lanes, - appearingViewTransitions: Map | null, ): void { focusedInstanceHandle = prepareForCommit(root.containerInfo); shouldFireAfterActiveInstanceBlur = false; @@ -299,19 +302,15 @@ export function commitBeforeMutationEffects( includesOnlyViewTransitionEligibleLanes(committedLanes); nextEffect = firstChild; - commitBeforeMutationEffects_begin( - isViewTransitionEligible, - appearingViewTransitions, - ); + commitBeforeMutationEffects_begin(isViewTransitionEligible); // We no longer need to track the active instance fiber focusedInstanceHandle = null; + // We've found any matched pairs and can now reset. + appearingViewTransitions = null; } -function commitBeforeMutationEffects_begin( - isViewTransitionEligible: boolean, - appearingViewTransitions: Map | null, -) { +function commitBeforeMutationEffects_begin(isViewTransitionEligible: boolean) { // If this commit is eligible for a View Transition we look into all mutated subtrees. // TODO: We could optimize this by marking these with the Snapshot subtree flag in the render phase. const subtreeMask = isViewTransitionEligible @@ -331,7 +330,6 @@ function commitBeforeMutationEffects_begin( commitBeforeMutationEffectsDeletion( deletion, isViewTransitionEligible, - appearingViewTransitions, ); } } @@ -364,7 +362,7 @@ function commitBeforeMutationEffects_begin( isViewTransitionEligible ) { // Was previously mounted as visible but is now hidden. - commitExitViewTransitions(current, appearingViewTransitions); + commitExitViewTransitions(current); } // Skip before mutation effects of the children because they're hidden. commitBeforeMutationEffects_complete(isViewTransitionEligible); @@ -528,7 +526,6 @@ function commitBeforeMutationEffectsOnFiber( function commitBeforeMutationEffectsDeletion( deletion: Fiber, isViewTransitionEligible: boolean, - appearingViewTransitions: Map | null, ) { if (enableCreateEventHandleAPI) { // TODO (effects) It would be nice to avoid calling doesFiberContain() @@ -541,7 +538,7 @@ function commitBeforeMutationEffectsDeletion( } } if (isViewTransitionEligible) { - commitExitViewTransitions(deletion, appearingViewTransitions); + commitExitViewTransitions(deletion); } } @@ -745,14 +742,15 @@ function commitEnterViewTransitions(placement: Fiber): void { } } -function commitDeletedPairViewTransitions( - deletion: Fiber, - appearingViewTransitions: Map, -): void { - if (appearingViewTransitions.size === 0) { +function commitDeletedPairViewTransitions(deletion: Fiber): void { + if ( + appearingViewTransitions === null || + appearingViewTransitions.size === 0 + ) { // We've found all. return; } + const pairs = appearingViewTransitions; if ((deletion.subtreeFlags & ViewTransitionNamedStatic) === NoFlags) { // This has no named view transitions in its subtree. return; @@ -769,7 +767,7 @@ function commitDeletedPairViewTransitions( const props: ViewTransitionProps = child.memoizedProps; const name = props.name; if (name != null && name !== 'auto') { - const pair = appearingViewTransitions.get(name); + const pair = pairs.get(name); if (pair !== undefined) { const className: ?string = getViewTransitionClassName( props.className, @@ -802,23 +800,20 @@ function commitDeletedPairViewTransitions( } // Delete the entry so that we know when we've found all of them // and can stop searching (size reaches zero). - appearingViewTransitions.delete(name); - if (appearingViewTransitions.size === 0) { + pairs.delete(name); + if (pairs.size === 0) { break; } } } } - commitDeletedPairViewTransitions(child, appearingViewTransitions); + commitDeletedPairViewTransitions(child); } child = child.sibling; } } -function commitExitViewTransitions( - deletion: Fiber, - appearingViewTransitions: Map | null, -): void { +function commitExitViewTransitions(deletion: Fiber): void { if (deletion.tag === ViewTransitionComponent) { const props: ViewTransitionProps = deletion.memoizedProps; const name = getViewTransitionName(props, deletion.stateNode); @@ -863,17 +858,17 @@ function commitExitViewTransitions( } if (appearingViewTransitions !== null) { // Look for more pairs deeper in the tree. - commitDeletedPairViewTransitions(deletion, appearingViewTransitions); + commitDeletedPairViewTransitions(deletion); } } else if ((deletion.subtreeFlags & ViewTransitionStatic) !== NoFlags) { let child = deletion.child; while (child !== null) { - commitExitViewTransitions(child, appearingViewTransitions); + commitExitViewTransitions(child); child = child.sibling; } } else { if (appearingViewTransitions !== null) { - commitDeletedPairViewTransitions(deletion, appearingViewTransitions); + commitDeletedPairViewTransitions(deletion); } } } @@ -4813,8 +4808,13 @@ export function commitPassiveUnmountEffects(finishedWork: Fiber): void { // already in the "current" tree. Because their visibility has changed, the // browser may not have prerendered them yet. So we check the MaySuspendCommit // flag instead. +// +// Note that MaySuspendCommit and ShouldSuspendCommit also includes named +// ViewTransitions so that we know to also visit those to collect appearing +// pairs. let suspenseyCommitFlag = ShouldSuspendCommit; export function accumulateSuspenseyCommit(finishedWork: Fiber): void { + appearingViewTransitions = null; accumulateSuspenseyCommitOnFiber(finishedWork); } @@ -4893,6 +4893,29 @@ function accumulateSuspenseyCommitOnFiber(fiber: Fiber) { } break; } + case ViewTransitionComponent: { + if (enableViewTransition) { + if ((fiber.flags & suspenseyCommitFlag) !== NoFlags) { + const props: ViewTransitionProps = fiber.memoizedProps; + const name: ?string | 'auto' = props.name; + if (name != null && name !== 'auto') { + // This is a named ViewTransition being mounted or reappearing. Let's add it to + // the map so we can match it with deletions later. + if (appearingViewTransitions === null) { + appearingViewTransitions = new Map(); + } + // Reset the pair in case we didn't end up restoring the instance in previous commits. + // This shouldn't really happen anymore but just in case. We could maybe add an invariant. + const instance: ViewTransitionState = fiber.stateNode; + instance.paired = null; + appearingViewTransitions.set(name, instance); + } + } + recursivelyAccumulateSuspenseyCommit(fiber); + break; + } + // Fallthrough + } default: { recursivelyAccumulateSuspenseyCommit(fiber); } diff --git a/packages/react-reconciler/src/ReactFiberCompleteWork.js b/packages/react-reconciler/src/ReactFiberCompleteWork.js index ca6462d7e7d5a..89012e78cf652 100644 --- a/packages/react-reconciler/src/ReactFiberCompleteWork.js +++ b/packages/react-reconciler/src/ReactFiberCompleteWork.js @@ -28,10 +28,6 @@ import type { OffscreenState, OffscreenQueue, } from './ReactFiberActivityComponent'; -import type { - ViewTransitionProps, - ViewTransitionState, -} from './ReactFiberViewTransitionComponent'; import {isOffscreenManual} from './ReactFiberActivityComponent'; import type {TracingMarkerInstance} from './ReactFiberTracingMarkerComponent'; import type {Cache} from './ReactFiberCacheComponent'; @@ -99,7 +95,6 @@ import { ShouldSuspendCommit, Cloned, ViewTransitionStatic, - ViewTransitionNamedStatic, } from './ReactFiberFlags'; import { @@ -164,7 +159,6 @@ import { getWorkInProgressTransitions, shouldRemainOnPreviousScreen, markSpawnedRetryLane, - trackAppearingViewTransition, } from './ReactFiberWorkLoop'; import { OffscreenLane, @@ -947,34 +941,6 @@ function completeDehydratedSuspenseBoundary( } } -function trackReappearingViewTransitions(workInProgress: Fiber): void { - if ((workInProgress.subtreeFlags & ViewTransitionNamedStatic) === NoFlags) { - // This has no named view transitions in its subtree. - return; - } - // This needs to search for any explicitly named reappearing View Transitions, - // whether they were updated in this transition or unchanged from before. - let child = workInProgress.child; - while (child !== null) { - if (child.tag === OffscreenComponent && child.memoizedState === null) { - // This tree is currently hidden so we skip it. - } else { - if ( - child.tag === ViewTransitionComponent && - (child.flags & ViewTransitionNamedStatic) !== NoFlags - ) { - const props: ViewTransitionProps = child.memoizedProps; - if (props.name != null && props.name !== 'auto') { - const instance: ViewTransitionState = child.stateNode; - trackAppearingViewTransition(instance, props.name); - } - } - trackReappearingViewTransitions(child); - } - child = child.sibling; - } -} - function completeWork( current: Fiber | null, workInProgress: Fiber, @@ -1796,14 +1762,6 @@ function completeWork( const prevIsHidden = prevState !== null; if (prevIsHidden !== nextIsHidden) { workInProgress.flags |= Visibility; - if (enableViewTransition && !nextIsHidden) { - // If we're revealing a new tree, we need to find any named - // ViewTransitions inside it that might have a deleted pair. - // We do this in the complete phase in case the tree has - // changed during the reveal but we have to do it before we - // find the first deleted pair in the before mutation phase. - trackReappearingViewTransitions(workInProgress); - } } } else { // On initial mount, we only need a Visibility effect if the tree diff --git a/packages/react-reconciler/src/ReactFiberFlags.js b/packages/react-reconciler/src/ReactFiberFlags.js index d5dcc3ab7c9c0..b6b2efd1996a8 100644 --- a/packages/react-reconciler/src/ReactFiberFlags.js +++ b/packages/react-reconciler/src/ReactFiberFlags.js @@ -44,6 +44,7 @@ export const StoreConsistency = /* */ 0b0000000000000000100000000000 // possible, because we're about to run out of bits. export const ScheduleRetry = StoreConsistency; export const ShouldSuspendCommit = Visibility; +export const ViewTransitionNamedMount = ShouldSuspendCommit; export const DidDefer = ContentReset; export const FormReset = Snapshot; export const AffectedParentLayout = ContentReset; @@ -74,8 +75,10 @@ export const PassiveStatic = /* */ 0b0000000100000000000000000000 export const MaySuspendCommit = /* */ 0b0000001000000000000000000000000; // ViewTransitionNamedStatic tracks explicitly name ViewTransition components deeply // that might need to be visited during clean up. This is similar to SnapshotStatic -// if there was any other use for it. -export const ViewTransitionNamedStatic = /* */ SnapshotStatic; +// if there was any other use for it. It also needs to run in the same phase as +// MaySuspendCommit tracking. +export const ViewTransitionNamedStatic = + /* */ SnapshotStatic | MaySuspendCommit; // ViewTransitionStatic tracks whether there are an ViewTransition components from // the nearest HostComponent down. It resets at every HostComponent level. export const ViewTransitionStatic = /* */ 0b0000010000000000000000000000000; diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.js b/packages/react-reconciler/src/ReactFiberWorkLoop.js index 03f09c1dbaa5f..5f17ca31b3693 100644 --- a/packages/react-reconciler/src/ReactFiberWorkLoop.js +++ b/packages/react-reconciler/src/ReactFiberWorkLoop.js @@ -432,12 +432,6 @@ let workInProgressRootConcurrentErrors: Array> | null = // We will log them once the tree commits. let workInProgressRootRecoverableErrors: Array> | null = null; -// This tracks named ViewTransition components that might need to find deleted -// pairs in the snapshot phase. -let workInProgressAppearingViewTransitions: Map< - string, - ViewTransitionState, -> | null = null; // Tracks when an update occurs during the render phase. let workInProgressRootDidIncludeRecursiveRenderUpdate: boolean = false; @@ -1318,7 +1312,6 @@ function finishConcurrentRender( lanes, workInProgressRootRecoverableErrors, workInProgressTransitions, - workInProgressAppearingViewTransitions, workInProgressRootDidIncludeRecursiveRenderUpdate, workInProgressDeferredLane, workInProgressRootInterleavedUpdatedLanes, @@ -1368,7 +1361,6 @@ function finishConcurrentRender( finishedWork, workInProgressRootRecoverableErrors, workInProgressTransitions, - workInProgressAppearingViewTransitions, workInProgressRootDidIncludeRecursiveRenderUpdate, lanes, workInProgressDeferredLane, @@ -1390,7 +1382,6 @@ function finishConcurrentRender( finishedWork, workInProgressRootRecoverableErrors, workInProgressTransitions, - workInProgressAppearingViewTransitions, workInProgressRootDidIncludeRecursiveRenderUpdate, lanes, workInProgressDeferredLane, @@ -1410,7 +1401,6 @@ function commitRootWhenReady( finishedWork: Fiber, recoverableErrors: Array> | null, transitions: Array | null, - appearingViewTransitions: Map | null, didIncludeRenderPhaseUpdate: boolean, lanes: Lanes, spawnedLane: Lane, @@ -1442,9 +1432,9 @@ function commitRootWhenReady( // the suspensey resources. The renderer is responsible for accumulating // all the load events. This all happens in a single synchronous // transaction, so it track state in its own module scope. - if (maySuspendCommit) { - accumulateSuspenseyCommit(finishedWork); - } + // This will also track any newly added or appearing ViewTransition + // components for the purposes of forming pairs. + accumulateSuspenseyCommit(finishedWork); if (isViewTransitionEligible) { suspendOnActiveViewTransition(root.containerInfo); } @@ -1468,7 +1458,6 @@ function commitRootWhenReady( lanes, recoverableErrors, transitions, - appearingViewTransitions, didIncludeRenderPhaseUpdate, spawnedLane, updatedLanes, @@ -1492,7 +1481,6 @@ function commitRootWhenReady( lanes, recoverableErrors, transitions, - appearingViewTransitions, didIncludeRenderPhaseUpdate, spawnedLane, updatedLanes, @@ -1962,7 +1950,6 @@ function prepareFreshStack(root: FiberRoot, lanes: Lanes): Fiber { workInProgressRootConcurrentErrors = null; workInProgressRootRecoverableErrors = null; workInProgressRootDidIncludeRecursiveRenderUpdate = false; - workInProgressAppearingViewTransitions = null; // Get the lanes that are entangled with whatever we're about to render. We // track these separately so we can distinguish the priority of the render @@ -2302,25 +2289,6 @@ export function renderHasNotSuspendedYet(): boolean { return workInProgressRootExitStatus === RootInProgress; } -export function trackAppearingViewTransition( - instance: ViewTransitionState, - name: string, -): void { - if (workInProgressAppearingViewTransitions === null) { - if ( - !includesOnlyViewTransitionEligibleLanes(workInProgressRootRenderLanes) - ) { - return; - } - workInProgressAppearingViewTransitions = new Map(); - } - // Reset the pair in case we didn't end up restoring the instance in previous commits. - // This could happen since we don't actually commit all tracked instances if they end - // up in a non-committed subtree. - instance.paired = null; - workInProgressAppearingViewTransitions.set(name, instance); -} - // TODO: Over time, this function and renderRootConcurrent have become more // and more similar. Not sure it makes sense to maintain forked paths. Consider // unifying them again. @@ -3230,7 +3198,6 @@ function commitRoot( lanes: Lanes, recoverableErrors: null | Array>, transitions: Array | null, - appearingViewTransitions: Map | null, didIncludeRenderPhaseUpdate: boolean, spawnedLane: Lane, updatedLanes: Lanes, @@ -3460,12 +3427,7 @@ function commitRoot( // The first phase a "before mutation" phase. We use this phase to read the // state of the host tree right before we mutate it. This is where // getSnapshotBeforeUpdate is called. - commitBeforeMutationEffects( - root, - finishedWork, - lanes, - appearingViewTransitions, - ); + commitBeforeMutationEffects(root, finishedWork, lanes); } finally { // Reset the priority to the previous non-sync value. executionContext = prevExecutionContext; From 55b54b0d638a6ae5c7a5ab6dd4fee732cfbc47ad Mon Sep 17 00:00:00 2001 From: lauren Date: Thu, 30 Jan 2025 14:13:45 -0500 Subject: [PATCH 05/72] [ci] Only install chromium for flight fixtures (#32275) I noticed we only use chromium in fixtures/flight, so let's specifically only install that browser in ci. --- .github/workflows/runtime_build_and_test.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/runtime_build_and_test.yml b/.github/workflows/runtime_build_and_test.yml index 99b6bb4a272e2..9a592780b17c4 100644 --- a/.github/workflows/runtime_build_and_test.yml +++ b/.github/workflows/runtime_build_and_test.yml @@ -476,9 +476,7 @@ jobs: fi - name: Playwright install deps working-directory: fixtures/flight - run: | - npx playwright install - sudo npx playwright install-deps + run: npx playwright install --with-deps chromium - name: Run tests working-directory: fixtures/flight run: yarn test From 221f3002caa2314cba0a62950da6fb92b453d1d0 Mon Sep 17 00:00:00 2001 From: Ruslan Lesiutin Date: Thu, 30 Jan 2025 20:08:17 +0000 Subject: [PATCH 06/72] chore[DevTools]: make clipboardWrite optional for chromium (#32262) Addresses https://github.com/facebook/react/issues/32244. ### Chromium We will use [chrome.permissions](https://developer.chrome.com/docs/extensions/reference/api/permissions) for checking / requesting `clipboardWrite` permission before copying something to the clipboard. ### Firefox We will keep `clipboardWrite` as a required permission, because there is no reliable and working API for requesting optional permissions for extensions that are extending browser DevTools: - `chrome.permissions` is unavailable for devtools pages - https://bugzilla.mozilla.org/show_bug.cgi?id=1796933 - You can't call `chrome.permissions.request` from background, because this instruction has to be executed inside user-event callback, basically only initiated by user. I don't really want to come up with solutions like opening a new tab with a button that user has to click. --- .eslintrc.js | 2 ++ .../chrome/manifest.json | 4 ++- .../edge/manifest.json | 4 ++- .../src/devtools/ContextMenu/types.js | 2 +- .../src/devtools/store.js | 3 +- .../Components/InspectedElementContextTree.js | 15 +++++--- .../Components/InspectedElementPropsTree.js | 15 ++++---- .../Components/InspectedElementSourcePanel.js | 11 ++++-- .../Components/InspectedElementStateTree.js | 20 ++++++----- .../NativeStyleEditor/StyleEditor.js | 6 +++- .../views/Profiler/SidebarEventInfo.js | 6 +++- .../views/UnsupportedBridgeProtocolDialog.js | 11 ++++-- .../src/errors/PermissionNotGrantedError.js | 21 +++++++++++ .../frontend/utils/withPermissionsCheck.js | 35 +++++++++++++++++++ .../src/CanvasPageContextMenu.js | 12 +++++-- scripts/flow/react-devtools.js | 2 ++ 16 files changed, 136 insertions(+), 33 deletions(-) create mode 100644 packages/react-devtools-shared/src/errors/PermissionNotGrantedError.js create mode 100644 packages/react-devtools-shared/src/frontend/utils/withPermissionsCheck.js diff --git a/.eslintrc.js b/.eslintrc.js index f5b98c6b4887f..7fe08f4cdf36e 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -500,6 +500,7 @@ module.exports = { 'packages/react-devtools-shared/src/hook.js', 'packages/react-devtools-shared/src/backend/console.js', 'packages/react-devtools-shared/src/backend/shared/DevToolsComponentStackFrame.js', + 'packages/react-devtools-shared/src/frontend/utils/withPermissionsCheck.js', ], globals: { __IS_CHROME__: 'readonly', @@ -507,6 +508,7 @@ module.exports = { __IS_EDGE__: 'readonly', __IS_NATIVE__: 'readonly', __IS_INTERNAL_VERSION__: 'readonly', + chrome: 'readonly', }, }, { diff --git a/packages/react-devtools-extensions/chrome/manifest.json b/packages/react-devtools-extensions/chrome/manifest.json index 5d4c4f35e7227..4b2d810f60411 100644 --- a/packages/react-devtools-extensions/chrome/manifest.json +++ b/packages/react-devtools-extensions/chrome/manifest.json @@ -43,7 +43,9 @@ "permissions": [ "scripting", "storage", - "tabs", + "tabs" + ], + "optional_permissions": [ "clipboardWrite" ], "host_permissions": [ diff --git a/packages/react-devtools-extensions/edge/manifest.json b/packages/react-devtools-extensions/edge/manifest.json index 9a3b99cf17aa0..37a76be2f24bc 100644 --- a/packages/react-devtools-extensions/edge/manifest.json +++ b/packages/react-devtools-extensions/edge/manifest.json @@ -43,7 +43,9 @@ "permissions": [ "scripting", "storage", - "tabs", + "tabs" + ], + "optional_permissions": [ "clipboardWrite" ], "host_permissions": [ diff --git a/packages/react-devtools-shared/src/devtools/ContextMenu/types.js b/packages/react-devtools-shared/src/devtools/ContextMenu/types.js index e2e8cecae33ac..c2f296db10fe5 100644 --- a/packages/react-devtools-shared/src/devtools/ContextMenu/types.js +++ b/packages/react-devtools-shared/src/devtools/ContextMenu/types.js @@ -10,7 +10,7 @@ import type {Node as ReactNode} from 'react'; export type ContextMenuItem = { - onClick: () => void, + onClick: () => mixed, content: ReactNode, }; diff --git a/packages/react-devtools-shared/src/devtools/store.js b/packages/react-devtools-shared/src/devtools/store.js index 0a3fbe82bb6a0..3895217053df1 100644 --- a/packages/react-devtools-shared/src/devtools/store.js +++ b/packages/react-devtools-shared/src/devtools/store.js @@ -38,6 +38,7 @@ import { currentBridgeProtocol, } from 'react-devtools-shared/src/bridge'; import {StrictMode} from 'react-devtools-shared/src/frontend/types'; +import {withPermissionsCheck} from 'react-devtools-shared/src/frontend/utils/withPermissionsCheck'; import type { Element, @@ -1494,7 +1495,7 @@ export default class Store extends EventEmitter<{ }; onSaveToClipboard: (text: string) => void = text => { - copy(text); + withPermissionsCheck({permissions: ['clipboardWrite']}, () => copy(text))(); }; onBackendInitialized: () => void = () => { diff --git a/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementContextTree.js b/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementContextTree.js index 044a6d9b48d11..941fa5fe01ddb 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementContextTree.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementContextTree.js @@ -19,6 +19,7 @@ import { ElementTypeClass, ElementTypeFunction, } from 'react-devtools-shared/src/frontend/types'; +import {withPermissionsCheck} from 'react-devtools-shared/src/frontend/utils/withPermissionsCheck'; import type {InspectedElement} from 'react-devtools-shared/src/frontend/types'; import type {FrontendBridge} from 'react-devtools-shared/src/bridge'; @@ -41,14 +42,18 @@ export default function InspectedElementContextTree({ const isReadOnly = type !== ElementTypeClass && type !== ElementTypeFunction; - const entries = context != null ? Object.entries(context) : null; - if (entries !== null) { - entries.sort(alphaSortEntries); + if (context == null) { + return null; } - const isEmpty = entries === null || entries.length === 0; + const entries = Object.entries(context); + entries.sort(alphaSortEntries); + const isEmpty = entries.length === 0; - const handleCopy = () => copy(serializeDataForCopy(((context: any): Object))); + const handleCopy = withPermissionsCheck( + {permissions: ['clipboardWrite']}, + () => copy(serializeDataForCopy(context)), + ); // We add an object with a "value" key as a wrapper around Context data // so that we can use the shared component to display it. diff --git a/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementPropsTree.js b/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementPropsTree.js index 942d2a2490b46..729b517b46f98 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementPropsTree.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementPropsTree.js @@ -18,6 +18,7 @@ import {alphaSortEntries, serializeDataForCopy} from '../utils'; import Store from '../../store'; import styles from './InspectedElementSharedStyles.css'; import {ElementTypeClass} from 'react-devtools-shared/src/frontend/types'; +import {withPermissionsCheck} from 'react-devtools-shared/src/frontend/utils/withPermissionsCheck'; import type {InspectedElement} from 'react-devtools-shared/src/frontend/types'; import type {FrontendBridge} from 'react-devtools-shared/src/bridge'; @@ -53,17 +54,19 @@ export default function InspectedElementPropsTree({ const canRenamePaths = type === ElementTypeClass || canEditFunctionPropsRenamePaths; - const entries = props != null ? Object.entries(props) : null; - if (entries === null) { - // Skip the section for null props. + // Skip the section for null props. + if (props == null) { return null; } + const entries = Object.entries(props); entries.sort(alphaSortEntries); - const isEmpty = entries.length === 0; - const handleCopy = () => copy(serializeDataForCopy(((props: any): Object))); + const handleCopy = withPermissionsCheck( + {permissions: ['clipboardWrite']}, + () => copy(serializeDataForCopy(props)), + ); return (
@@ -76,7 +79,7 @@ export default function InspectedElementPropsTree({ )}
{!isEmpty && - (entries: any).map(([name, value]) => ( + entries.map(([name, value]) => ( copy(`${sourceURL}:${line}:${column}`); + const handleCopy = withPermissionsCheck( + {permissions: ['clipboardWrite']}, + () => copy(`${sourceURL}:${line}:${column}`), + ); return ( diff --git a/packages/react-devtools-shared/src/devtools/views/UnsupportedBridgeProtocolDialog.js b/packages/react-devtools-shared/src/devtools/views/UnsupportedBridgeProtocolDialog.js index 425dfe1d08c13..7bfd86fb9c19d 100644 --- a/packages/react-devtools-shared/src/devtools/views/UnsupportedBridgeProtocolDialog.js +++ b/packages/react-devtools-shared/src/devtools/views/UnsupportedBridgeProtocolDialog.js @@ -16,6 +16,7 @@ import Button from './Button'; import ButtonIcon from './ButtonIcon'; import {copy} from 'clipboard-js'; import styles from './UnsupportedBridgeProtocolDialog.css'; +import {withPermissionsCheck} from 'react-devtools-shared/src/frontend/utils/withPermissionsCheck'; import type {BridgeProtocol} from 'react-devtools-shared/src/bridge'; @@ -82,7 +83,10 @@ function DialogContent({
           {upgradeInstructions}
           
@@ -99,7 +103,10 @@ function DialogContent({
         
           {downgradeInstructions}
           
diff --git a/packages/react-devtools-shared/src/errors/PermissionNotGrantedError.js b/packages/react-devtools-shared/src/errors/PermissionNotGrantedError.js
new file mode 100644
index 0000000000000..dc9e4ad734e74
--- /dev/null
+++ b/packages/react-devtools-shared/src/errors/PermissionNotGrantedError.js
@@ -0,0 +1,21 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ * @flow
+ */
+
+export class PermissionNotGrantedError extends Error {
+  constructor() {
+    super("User didn't grant the required permission to perform an action");
+
+    // Maintains proper stack trace for where our error was thrown (only available on V8)
+    if (Error.captureStackTrace) {
+      Error.captureStackTrace(this, PermissionNotGrantedError);
+    }
+
+    this.name = 'PermissionNotGrantedError';
+  }
+}
diff --git a/packages/react-devtools-shared/src/frontend/utils/withPermissionsCheck.js b/packages/react-devtools-shared/src/frontend/utils/withPermissionsCheck.js
new file mode 100644
index 0000000000000..d87db82546484
--- /dev/null
+++ b/packages/react-devtools-shared/src/frontend/utils/withPermissionsCheck.js
@@ -0,0 +1,35 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ * @flow
+ */
+
+import {PermissionNotGrantedError} from 'react-devtools-shared/src/errors/PermissionNotGrantedError';
+
+type SupportedPermission = 'clipboardWrite';
+type Permissions = Array;
+type PermissionsOptions = {permissions: Permissions};
+
+// browser.permissions is not available for DevTools pages in Firefox
+// https://bugzilla.mozilla.org/show_bug.cgi?id=1796933
+// We are going to assume that requested permissions are not optional.
+export function withPermissionsCheck) => mixed>(
+  options: PermissionsOptions,
+  callback: T,
+): T | (() => Promise>) {
+  if (!__IS_CHROME__ && !__IS_EDGE__) {
+    return callback;
+  } else {
+    return async () => {
+      const granted = await chrome.permissions.request(options);
+      if (granted) {
+        return callback();
+      }
+
+      return Promise.reject(new PermissionNotGrantedError());
+    };
+  }
+}
diff --git a/packages/react-devtools-timeline/src/CanvasPageContextMenu.js b/packages/react-devtools-timeline/src/CanvasPageContextMenu.js
index 2af32a68aa4e5..5bd4da3141b79 100644
--- a/packages/react-devtools-timeline/src/CanvasPageContextMenu.js
+++ b/packages/react-devtools-timeline/src/CanvasPageContextMenu.js
@@ -13,6 +13,7 @@ import {copy} from 'clipboard-js';
 import prettyMilliseconds from 'pretty-ms';
 
 import ContextMenuContainer from 'react-devtools-shared/src/devtools/ContextMenu/ContextMenuContainer';
+import {withPermissionsCheck} from 'react-devtools-shared/src/frontend/utils/withPermissionsCheck';
 
 import {getBatchRange} from './utils/getBatchRange';
 import {moveStateToRange} from './view-base/utils/scrollState';
@@ -138,7 +139,9 @@ export default function CanvasPageContextMenu({
           content: 'Zoom to batch',
         },
         {
-          onClick: () => copySummary(timelineData, measure),
+          onClick: withPermissionsCheck({permissions: ['clipboardWrite']}, () =>
+            copySummary(timelineData, measure),
+          ),
           content: 'Copy summary',
         },
       );
@@ -147,16 +150,19 @@ export default function CanvasPageContextMenu({
     if (flamechartStackFrame != null) {
       items.push(
         {
-          onClick: () => copy(flamechartStackFrame.scriptUrl),
+          onClick: withPermissionsCheck({permissions: ['clipboardWrite']}, () =>
+            copy(flamechartStackFrame.scriptUrl),
+          ),
           content: 'Copy file path',
         },
         {
-          onClick: () =>
+          onClick: withPermissionsCheck({permissions: ['clipboardWrite']}, () =>
             copy(
               `line ${flamechartStackFrame.locationLine ?? ''}, column ${
                 flamechartStackFrame.locationColumn ?? ''
               }`,
             ),
+          ),
           content: 'Copy location',
         },
       );
diff --git a/scripts/flow/react-devtools.js b/scripts/flow/react-devtools.js
index 4e5fe0db1c625..4e0f2a915ede6 100644
--- a/scripts/flow/react-devtools.js
+++ b/scripts/flow/react-devtools.js
@@ -16,3 +16,5 @@ declare const __IS_FIREFOX__: boolean;
 declare const __IS_CHROME__: boolean;
 declare const __IS_EDGE__: boolean;
 declare const __IS_NATIVE__: boolean;
+
+declare const chrome: any;

From 87c03a0a134b19ffbda6bbef4b12202f4f5a4347 Mon Sep 17 00:00:00 2001
From: David Michael Gregg 
Date: Fri, 31 Jan 2025 01:44:02 -0500
Subject: [PATCH 07/72] =?UTF-8?q?Fix=20typo=20in=20dangerfile.js=20which?=
 =?UTF-8?q?=20results=20in=20an=20unreachable=20code=20path=E2=80=A6=20(#3?=
 =?UTF-8?q?2277)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

## Summary

Fix typo in dangerfile.js which results in an unreachable code path
which ought to be hit when there is no matching base artifact during
DangerCI automated code review.

See:
https://github.com/facebook/react/blob/221f3002caa2314cba0a62950da6fb92b453d1d0/dangerfile.js#L73
Compare:
https://github.com/facebook/react/blob/221f3002caa2314cba0a62950da6fb92b453d1d0/dangerfile.js#L171
And the case which should hit this code path:
https://github.com/facebook/react/blob/221f3002caa2314cba0a62950da6fb92b453d1d0/dangerfile.js#L160

Given the above context, the condition `Number === Infinity` is clearly
meant to be `decimal === Infinity`, which it will be if the `catch`
statement triggers when there is no matching base artifact. Without this
fix, the primitive value `Infinity` is passed to
`percentFormatter.format(decimal)`, resulting in the string `'+∞%'`.
With this fix, the resulting string will be the intended `'New file'`.

## [Resolves issue
32278](https://github.com/facebook/react/issues/32278)
---
 dangerfile.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/dangerfile.js b/dangerfile.js
index bfc41312e4429..d60da35b586f5 100644
--- a/dangerfile.js
+++ b/dangerfile.js
@@ -70,7 +70,7 @@ const percentFormatter = new Intl.NumberFormat('en', {
 });
 
 function change(decimal) {
-  if (Number === Infinity) {
+  if (decimal === Infinity) {
     return 'New file';
   }
   if (decimal === -1) {

From 9ff42a8798863c995523e284142b47e3cdfaee80 Mon Sep 17 00:00:00 2001
From: Timothy Yung 
Date: Thu, 30 Jan 2025 22:59:45 -0800
Subject: [PATCH 08/72] Permit non-`DEV` Elements in `React.Children` w/ `DEV`
 (#32117)

---
 .../react/src/__tests__/ReactChildren-test.js | 25 +++++++++++++++++++
 packages/react/src/jsx/ReactJSXElement.js     |  4 ++-
 2 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/packages/react/src/__tests__/ReactChildren-test.js b/packages/react/src/__tests__/ReactChildren-test.js
index 5cce6b24873f0..7843d203b0a15 100644
--- a/packages/react/src/__tests__/ReactChildren-test.js
+++ b/packages/react/src/__tests__/ReactChildren-test.js
@@ -1039,6 +1039,31 @@ describe('ReactChildren', () => {
     });
   });
 
+  it('does not throw on children without `_store`', async () => {
+    function ComponentRenderingFlattenedChildren({children}) {
+      return 
{React.Children.toArray(children)}
; + } + + const source =
; + const productionElement = {}; + Object.entries(source).forEach(([key, value]) => { + if (key !== '_owner' && key !== '_store') { + productionElement[key] = value; + } + }); + Object.freeze(productionElement); + + const container = document.createElement('div'); + const root = ReactDOMClient.createRoot(container); + await act(() => { + root.render( + + {productionElement} + , + ); + }); + }); + it('should escape keys', () => { const zero =
; const one =
; diff --git a/packages/react/src/jsx/ReactJSXElement.js b/packages/react/src/jsx/ReactJSXElement.js index e0a689ec2404f..5edcb333ea571 100644 --- a/packages/react/src/jsx/ReactJSXElement.js +++ b/packages/react/src/jsx/ReactJSXElement.js @@ -813,7 +813,9 @@ export function cloneAndReplaceKey(oldElement, newKey) { ); if (__DEV__) { // The cloned element should inherit the original element's key validation. - clonedElement._store.validated = oldElement._store.validated; + if (oldElement._store) { + clonedElement._store.validated = oldElement._store.validated; + } } return clonedElement; } From a657bc5dee29da313d2a03e7864b0665859bc7a8 Mon Sep 17 00:00:00 2001 From: michael faith Date: Fri, 31 Jan 2025 13:32:23 -0600 Subject: [PATCH 09/72] build(eslint-plugin-react-hooks): add dev dependencies for typescript migration (#32279) ## Summary Contributing to https://github.com/facebook/react/pull/32240, this change adds the dev dependencies needed to support the migration of the plugin to typescript. --- .../eslint-plugin-react-compiler/package.json | 2 +- .../eslint-plugin-react-hooks/package.json | 10 +- yarn.lock | 514 +++++++++++++++++- 3 files changed, 520 insertions(+), 6 deletions(-) diff --git a/compiler/packages/eslint-plugin-react-compiler/package.json b/compiler/packages/eslint-plugin-react-compiler/package.json index d325b3f3d1c67..1bf80ce963c27 100644 --- a/compiler/packages/eslint-plugin-react-compiler/package.json +++ b/compiler/packages/eslint-plugin-react-compiler/package.json @@ -23,7 +23,7 @@ "@babel/preset-env": "^7.22.4", "@babel/preset-typescript": "^7.18.6", "@babel/types": "^7.19.0", - "@types/eslint": "^8.56.6", + "@types/eslint": "^8.56.12", "@types/node": "^20.2.5", "babel-jest": "^29.0.3", "eslint": "8.57.0", diff --git a/packages/eslint-plugin-react-hooks/package.json b/packages/eslint-plugin-react-hooks/package.json index 94cdf12ec765f..b45609362faac 100644 --- a/packages/eslint-plugin-react-hooks/package.json +++ b/packages/eslint-plugin-react-hooks/package.json @@ -32,12 +32,20 @@ }, "devDependencies": { "@babel/eslint-parser": "^7.11.4", + "@tsconfig/strictest": "^2.0.5", "@typescript-eslint/parser-v2": "npm:@typescript-eslint/parser@^2.26.0", "@typescript-eslint/parser-v3": "npm:@typescript-eslint/parser@^3.10.0", "@typescript-eslint/parser-v4": "npm:@typescript-eslint/parser@^4.1.0", "@typescript-eslint/parser-v5": "npm:@typescript-eslint/parser@^5.62.0", + "@types/eslint": "^8.56.12", + "@types/estree": "^1.0.6", + "@types/estree-jsx": "^1.0.5", + "@types/node": "^20.2.5", "babel-eslint": "^10.0.3", "eslint-v7": "npm:eslint@^7.7.0", - "eslint-v9": "npm:eslint@^9.0.0" + "eslint-v9": "npm:eslint@^9.0.0", + "jest": "^29.5.0", + "tsup": "^8.3.5", + "typescript": "^5.4.3" } } diff --git a/yarn.lock b/yarn.lock index 48eca75afbba8..4922028dafc3b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2213,6 +2213,131 @@ opn "5.3.0" react "^16.13.1" +"@esbuild/aix-ppc64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz#38848d3e25afe842a7943643cbcd387cc6e13461" + integrity sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA== + +"@esbuild/android-arm64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz#f592957ae8b5643129fa889c79e69cd8669bb894" + integrity sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg== + +"@esbuild/android-arm@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.24.2.tgz#72d8a2063aa630308af486a7e5cbcd1e134335b3" + integrity sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q== + +"@esbuild/android-x64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.24.2.tgz#9a7713504d5f04792f33be9c197a882b2d88febb" + integrity sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw== + +"@esbuild/darwin-arm64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz#02ae04ad8ebffd6e2ea096181b3366816b2b5936" + integrity sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA== + +"@esbuild/darwin-x64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz#9ec312bc29c60e1b6cecadc82bd504d8adaa19e9" + integrity sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA== + +"@esbuild/freebsd-arm64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz#5e82f44cb4906d6aebf24497d6a068cfc152fa00" + integrity sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg== + +"@esbuild/freebsd-x64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz#3fb1ce92f276168b75074b4e51aa0d8141ecce7f" + integrity sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q== + +"@esbuild/linux-arm64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz#856b632d79eb80aec0864381efd29de8fd0b1f43" + integrity sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg== + +"@esbuild/linux-arm@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz#c846b4694dc5a75d1444f52257ccc5659021b736" + integrity sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA== + +"@esbuild/linux-ia32@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz#f8a16615a78826ccbb6566fab9a9606cfd4a37d5" + integrity sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw== + +"@esbuild/linux-loong64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz#1c451538c765bf14913512c76ed8a351e18b09fc" + integrity sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ== + +"@esbuild/linux-mips64el@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz#0846edeefbc3d8d50645c51869cc64401d9239cb" + integrity sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw== + +"@esbuild/linux-ppc64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz#8e3fc54505671d193337a36dfd4c1a23b8a41412" + integrity sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw== + +"@esbuild/linux-riscv64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz#6a1e92096d5e68f7bb10a0d64bb5b6d1daf9a694" + integrity sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q== + +"@esbuild/linux-s390x@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz#ab18e56e66f7a3c49cb97d337cd0a6fea28a8577" + integrity sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw== + +"@esbuild/linux-x64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz#8140c9b40da634d380b0b29c837a0b4267aff38f" + integrity sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q== + +"@esbuild/netbsd-arm64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.24.2.tgz#65f19161432bafb3981f5f20a7ff45abb2e708e6" + integrity sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw== + +"@esbuild/netbsd-x64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz#7a3a97d77abfd11765a72f1c6f9b18f5396bcc40" + integrity sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw== + +"@esbuild/openbsd-arm64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz#58b00238dd8f123bfff68d3acc53a6ee369af89f" + integrity sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A== + +"@esbuild/openbsd-x64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz#0ac843fda0feb85a93e288842936c21a00a8a205" + integrity sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA== + +"@esbuild/sunos-x64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz#8b7aa895e07828d36c422a4404cc2ecf27fb15c6" + integrity sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig== + +"@esbuild/win32-arm64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz#c023afb647cabf0c3ed13f0eddfc4f1d61c66a85" + integrity sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ== + +"@esbuild/win32-ia32@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz#96c356132d2dda990098c8b8b951209c3cd743c2" + integrity sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA== + +"@esbuild/win32-x64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz#34aa0b52d0fbb1a654b596acfa595f0c7b77a77b" + integrity sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg== + "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" @@ -2609,6 +2734,15 @@ "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping" "^0.3.9" +"@jridgewell/gen-mapping@^0.3.2": + version "0.3.8" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz#4f0e06362e01362f823d348f1872b08f666d8142" + integrity sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA== + dependencies: + "@jridgewell/set-array" "^1.2.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.24" + "@jridgewell/gen-mapping@^0.3.5": version "0.3.5" resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" @@ -3050,6 +3184,101 @@ estree-walker "^2.0.2" picomatch "^2.3.1" +"@rollup/rollup-android-arm-eabi@4.32.1": + version "4.32.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.32.1.tgz#c18bad635ba24220a6c8cc427ab2cab12e1531a3" + integrity sha512-/pqA4DmqyCm8u5YIDzIdlLcEmuvxb0v8fZdFhVMszSpDTgbQKdw3/mB3eMUHIbubtJ6F9j+LtmyCnHTEqIHyzA== + +"@rollup/rollup-android-arm64@4.32.1": + version "4.32.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.32.1.tgz#b5c00344b80f20889b72bfe65d3c209cef247362" + integrity sha512-If3PDskT77q7zgqVqYuj7WG3WC08G1kwXGVFi9Jr8nY6eHucREHkfpX79c0ACAjLj3QIWKPJR7w4i+f5EdLH5Q== + +"@rollup/rollup-darwin-arm64@4.32.1": + version "4.32.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.32.1.tgz#78e5358d4a2a08c090f75dd87fa2eada42eca1e5" + integrity sha512-zCpKHioQ9KgZToFp5Wvz6zaWbMzYQ2LJHQ+QixDKq52KKrF65ueu6Af4hLlLWHjX1Wf/0G5kSJM9PySW9IrvHA== + +"@rollup/rollup-darwin-x64@4.32.1": + version "4.32.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.32.1.tgz#c04c9e173244d44de50278f3f893fb68d987fcc6" + integrity sha512-sFvF+t2+TyUo/ZQqUcifrJIgznx58oFZbdHS9TvHq3xhPVL9nOp+yZ6LKrO9GWTP+6DbFtoyLDbjTpR62Mbr3Q== + +"@rollup/rollup-freebsd-arm64@4.32.1": + version "4.32.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.32.1.tgz#3bdf18d4ef32dcfe9b20bba18d7a53a101ed79d9" + integrity sha512-NbOa+7InvMWRcY9RG+B6kKIMD/FsnQPH0MWUvDlQB1iXnF/UcKSudCXZtv4lW+C276g3w5AxPbfry5rSYvyeYA== + +"@rollup/rollup-freebsd-x64@4.32.1": + version "4.32.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.32.1.tgz#35867b15c276f4b4ca8eb226f7dd6df8c64640db" + integrity sha512-JRBRmwvHPXR881j2xjry8HZ86wIPK2CcDw0EXchE1UgU0ubWp9nvlT7cZYKc6bkypBt745b4bglf3+xJ7hXWWw== + +"@rollup/rollup-linux-arm-gnueabihf@4.32.1": + version "4.32.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.32.1.tgz#92c212d1b38c105bd1eb101254722d27d869b1ac" + integrity sha512-PKvszb+9o/vVdUzCCjL0sKHukEQV39tD3fepXxYrHE3sTKrRdCydI7uldRLbjLmDA3TFDmh418XH19NOsDRH8g== + +"@rollup/rollup-linux-arm-musleabihf@4.32.1": + version "4.32.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.32.1.tgz#ebb94d8cd438f23e38caa4a87ca80d4cf5b50fa1" + integrity sha512-9WHEMV6Y89eL606ReYowXuGF1Yb2vwfKWKdD1A5h+OYnPZSJvxbEjxTRKPgi7tkP2DSnW0YLab1ooy+i/FQp/Q== + +"@rollup/rollup-linux-arm64-gnu@4.32.1": + version "4.32.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.32.1.tgz#ce6a5eacbd5fd4bdf7bf27bd818980230bdb9fab" + integrity sha512-tZWc9iEt5fGJ1CL2LRPw8OttkCBDs+D8D3oEM8mH8S1ICZCtFJhD7DZ3XMGM8kpqHvhGUTvNUYVDnmkj4BDXnw== + +"@rollup/rollup-linux-arm64-musl@4.32.1": + version "4.32.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.32.1.tgz#31b4e0a543607e6eb4f982ffb45830919a952a83" + integrity sha512-FTYc2YoTWUsBz5GTTgGkRYYJ5NGJIi/rCY4oK/I8aKowx1ToXeoVVbIE4LGAjsauvlhjfl0MYacxClLld1VrOw== + +"@rollup/rollup-linux-loongarch64-gnu@4.32.1": + version "4.32.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.32.1.tgz#ad7b35f193f1d2e0dc37eba733069b4af5f6498d" + integrity sha512-F51qLdOtpS6P1zJVRzYM0v6MrBNypyPEN1GfMiz0gPu9jN8ScGaEFIZQwteSsGKg799oR5EaP7+B2jHgL+d+Kw== + +"@rollup/rollup-linux-powerpc64le-gnu@4.32.1": + version "4.32.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.32.1.tgz#b713a55d7eac4d2c8a0109c3daca6ea85fc178b3" + integrity sha512-wO0WkfSppfX4YFm5KhdCCpnpGbtgQNj/tgvYzrVYFKDpven8w2N6Gg5nB6w+wAMO3AIfSTWeTjfVe+uZ23zAlg== + +"@rollup/rollup-linux-riscv64-gnu@4.32.1": + version "4.32.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.32.1.tgz#bea4fd8ad190e9bc1d11efafa2efc9d121f50b96" + integrity sha512-iWswS9cIXfJO1MFYtI/4jjlrGb/V58oMu4dYJIKnR5UIwbkzR0PJ09O0PDZT0oJ3LYWXBSWahNf/Mjo6i1E5/g== + +"@rollup/rollup-linux-s390x-gnu@4.32.1": + version "4.32.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.32.1.tgz#cc98c32733ca472635759c78a79b5f8d887b2a6a" + integrity sha512-RKt8NI9tebzmEthMnfVgG3i/XeECkMPS+ibVZjZ6mNekpbbUmkNWuIN2yHsb/mBPyZke4nlI4YqIdFPgKuoyQQ== + +"@rollup/rollup-linux-x64-gnu@4.32.1": + version "4.32.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.32.1.tgz#5c009c264a7ce0e19b40890ca9945440bb420691" + integrity sha512-WQFLZ9c42ECqEjwg/GHHsouij3pzLXkFdz0UxHa/0OM12LzvX7DzedlY0SIEly2v18YZLRhCRoHZDxbBSWoGYg== + +"@rollup/rollup-linux-x64-musl@4.32.1": + version "4.32.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.32.1.tgz#73d2f44070c23e031262b601927fdb4eec253bc1" + integrity sha512-BLoiyHDOWoS3uccNSADMza6V6vCNiphi94tQlVIL5de+r6r/CCQuNnerf+1g2mnk2b6edp5dk0nhdZ7aEjOBsA== + +"@rollup/rollup-win32-arm64-msvc@4.32.1": + version "4.32.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.32.1.tgz#fa106304818078f9d3fc9005642ad99f596eed2d" + integrity sha512-w2l3UnlgYTNNU+Z6wOR8YdaioqfEnwPjIsJ66KxKAf0p+AuL2FHeTX6qvM+p/Ue3XPBVNyVSfCrfZiQh7vZHLQ== + +"@rollup/rollup-win32-ia32-msvc@4.32.1": + version "4.32.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.32.1.tgz#a1a394c705a0d2a974a124c4b471fc1cf851a56f" + integrity sha512-Am9H+TGLomPGkBnaPWie4F3x+yQ2rr4Bk2jpwy+iV+Gel9jLAu/KqT8k3X4jxFPW6Zf8OMnehyutsd+eHoq1WQ== + +"@rollup/rollup-win32-x64-msvc@4.32.1": + version "4.32.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.32.1.tgz#512db088df67afee8f07183cdf8c9eecd64f6ef8" + integrity sha512-ar80GhdZb4DgmW3myIS9nRFYcpJRSME8iqWgzH2i44u+IdrzmiXVxeFnExQ5v4JYUSpg94bWjevMG8JHf1Da5Q== + "@sinclair/typebox@^0.25.16": version "0.25.24" resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.25.24.tgz#8c7688559979f7079aacaf31aa881c3aa410b718" @@ -3125,6 +3354,11 @@ resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf" integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A== +"@tsconfig/strictest@^2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@tsconfig/strictest/-/strictest-2.0.5.tgz#2cbc67f207ba87fdec2a84ad79b1708cf4edd93b" + integrity sha512-ec4tjL2Rr0pkZ5hww65c+EEPYwxOi4Ryv+0MtjeaSQRJyq322Q27eOQiFbuNgw2hpL4hB1/W/HBGk3VKS43osg== + "@types/babel__core@^7.1.14": version "7.20.5" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" @@ -3219,11 +3453,31 @@ "@types/estree" "*" "@types/json-schema" "*" +"@types/eslint@^8.56.12": + version "8.56.12" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.56.12.tgz#1657c814ffeba4d2f84c0d4ba0f44ca7ea1ca53a" + integrity sha512-03ruubjWyOHlmljCVoxSuNDdmfZDzsrrz0P2LeJsOXr+ZwFQ+0yQIwNCwt/GYhV7Z31fgtXJTAEs+FYlEL851g== + dependencies: + "@types/estree" "*" + "@types/json-schema" "*" + +"@types/estree-jsx@^1.0.5": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@types/estree-jsx/-/estree-jsx-1.0.5.tgz#858a88ea20f34fe65111f005a689fa1ebf70dc18" + integrity sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg== + dependencies: + "@types/estree" "*" + "@types/estree@*": version "0.0.42" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.42.tgz#8d0c1f480339efedb3e46070e22dd63e0430dd11" integrity sha512-K1DPVvnBCPxzD+G51/cxVIoc2X8uUVl1zpJeE6iKcgHMj4+tbat5Xu4TjV7v2QSDbIeAfLi2hIk+u2+s0MlpUQ== +"@types/estree@1.0.6", "@types/estree@^1.0.6": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50" + integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw== + "@types/estree@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2" @@ -3360,6 +3614,13 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-16.18.14.tgz#5465ce598486a703caddbefe8603f8a2cffa3461" integrity sha512-wvzClDGQXOCVNU4APPopC2KtMYukaF1MN/W3xAmslx22Z4/IF1/izDMekuyoUlwfnDHYCIZGaj7jMwnJKBTxKw== +"@types/node@^20.2.5": + version "20.17.16" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.17.16.tgz#b33b0edc1bf925b27349e494b871ca4451fabab4" + integrity sha512-vOTpLduLkZXePLxHiHsBLp98mHGnl8RptV4YAO3HfKO5UHjDvySGbxKtpYfy8Sx5+WKcgc45qNreJJRVM3L6mw== + dependencies: + undici-types "~6.19.2" + "@types/prettier@^1.0.0 || ^2.0.0 || ^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-3.0.0.tgz#e9bc8160230d3a461dab5c5b41cceef1ef723057" @@ -5297,6 +5558,13 @@ bundle-name@^3.0.0: dependencies: run-applescript "^5.0.0" +bundle-require@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/bundle-require/-/bundle-require-5.1.0.tgz#8db66f41950da3d77af1ef3322f4c3e04009faee" + integrity sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA== + dependencies: + load-tsconfig "^0.2.3" + bunyan@1.8.15: version "1.8.15" resolved "https://registry.yarnpkg.com/bunyan/-/bunyan-1.8.15.tgz#8ce34ca908a17d0776576ca1b2f6cbd916e93b46" @@ -5317,6 +5585,11 @@ bytes@3.1.2: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== +cac@^6.7.14: + version "6.7.14" + resolved "https://registry.yarnpkg.com/cac/-/cac-6.7.14.tgz#804e1e6f506ee363cb0e3ccbb09cad5dd9870959" + integrity sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ== + cache-base@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" @@ -5618,6 +5891,13 @@ chokidar@^3.5.3: optionalDependencies: fsevents "~2.3.2" +chokidar@^4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-4.0.3.tgz#7be37a4c03c9aee1ecfe862a4a23b2c70c205d30" + integrity sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA== + dependencies: + readdirp "^4.0.1" + chownr@^1.0.1: version "1.1.4" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" @@ -5886,7 +6166,7 @@ commander@^2.18.0, commander@^2.20.0, commander@^2.6.0, commander@^2.8.1: resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== -commander@^4.0.1: +commander@^4.0.0, commander@^4.0.1: version "4.1.1" resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== @@ -6029,6 +6309,11 @@ connect-history-api-fallback@^2.0.0: resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz#647264845251a0daf25b97ce87834cace0f5f1c8" integrity sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA== +consola@^3.2.3: + version "3.4.0" + resolved "https://registry.yarnpkg.com/consola/-/consola-3.4.0.tgz#4cfc9348fd85ed16a17940b3032765e31061ab88" + integrity sha512-EiPU8G6dQG0GFHNR8ljnZFki/8a+cQwEQ+7wpxdChl02Q8HXlwEZWD5lqAF8vC2sEC3Tehr8hy7vErz88LHyUA== + console-browserify@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" @@ -6552,6 +6837,13 @@ debug@^4.3.4, debug@~4.3.1: dependencies: ms "2.1.2" +debug@^4.3.7: + version "4.4.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" + integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== + dependencies: + ms "^2.1.3" + decamelize@6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-6.0.0.tgz#8cad4d916fde5c41a264a43d0ecc56fe3d31749e" @@ -7250,6 +7542,37 @@ es6-error@4.1.1, es6-error@^4.1.1: resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d" integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg== +esbuild@^0.24.0: + version "0.24.2" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.24.2.tgz#b5b55bee7de017bff5fb8a4e3e44f2ebe2c3567d" + integrity sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA== + optionalDependencies: + "@esbuild/aix-ppc64" "0.24.2" + "@esbuild/android-arm" "0.24.2" + "@esbuild/android-arm64" "0.24.2" + "@esbuild/android-x64" "0.24.2" + "@esbuild/darwin-arm64" "0.24.2" + "@esbuild/darwin-x64" "0.24.2" + "@esbuild/freebsd-arm64" "0.24.2" + "@esbuild/freebsd-x64" "0.24.2" + "@esbuild/linux-arm" "0.24.2" + "@esbuild/linux-arm64" "0.24.2" + "@esbuild/linux-ia32" "0.24.2" + "@esbuild/linux-loong64" "0.24.2" + "@esbuild/linux-mips64el" "0.24.2" + "@esbuild/linux-ppc64" "0.24.2" + "@esbuild/linux-riscv64" "0.24.2" + "@esbuild/linux-s390x" "0.24.2" + "@esbuild/linux-x64" "0.24.2" + "@esbuild/netbsd-arm64" "0.24.2" + "@esbuild/netbsd-x64" "0.24.2" + "@esbuild/openbsd-arm64" "0.24.2" + "@esbuild/openbsd-x64" "0.24.2" + "@esbuild/sunos-x64" "0.24.2" + "@esbuild/win32-arm64" "0.24.2" + "@esbuild/win32-ia32" "0.24.2" + "@esbuild/win32-x64" "0.24.2" + escalade@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.0.2.tgz#6a580d70edb87880f22b4c91d0d56078df6962c4" @@ -8124,6 +8447,11 @@ fd-slicer@~1.1.0: dependencies: pend "~1.2.0" +fdir@^6.4.2: + version "6.4.3" + resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.4.3.tgz#011cdacf837eca9b811c89dbb902df714273db72" + integrity sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw== + fetch-blob@^3.1.2, fetch-blob@^3.1.4: version "3.2.0" resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-3.2.0.tgz#f09b8d4bbd45adc6f0c20b7e787e793e309dcce9" @@ -8762,6 +9090,18 @@ glob@^10.2.5: minipass "^5.0.0 || ^6.0.2" path-scurry "^1.7.0" +glob@^10.3.10: + version "10.4.5" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956" + integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg== + dependencies: + foreground-child "^3.1.0" + jackspeak "^3.1.2" + minimatch "^9.0.4" + minipass "^7.1.2" + package-json-from-dist "^1.0.0" + path-scurry "^1.11.1" + glob@^6.0.1: version "6.0.4" resolved "https://registry.yarnpkg.com/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22" @@ -10927,7 +11267,7 @@ jest-worker@^29.7.0: merge-stream "^2.0.0" supports-color "^8.0.0" -jest@^29.4.2: +jest@^29.4.2, jest@^29.5.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest/-/jest-29.7.0.tgz#994676fc24177f088f1c5e3737f5697204ff2613" integrity sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw== @@ -10947,6 +11287,11 @@ jose@5.4.1: resolved "https://registry.yarnpkg.com/jose/-/jose-5.4.1.tgz#b471ee3963920ba5452fd1b1398c8ba72a7b2fcf" integrity sha512-U6QajmpV/nhL9SyfAewo000fkiRQ+Yd2H0lBxJJ9apjpOgkOcBQJWOrMo917lxLptdS/n/o/xPzMkXhF46K8hQ== +joycon@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/joycon/-/joycon-3.1.1.tgz#bce8596d6ae808f8b68168f5fc69280996894f03" + integrity sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw== + jpeg-js@^0.4.2: version "0.4.4" resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.4.4.tgz#a9f1c6f1f9f0fa80cdb3484ed9635054d28936aa" @@ -11328,6 +11673,11 @@ lighthouse-logger@^1.0.0: debug "^2.6.8" marky "^1.2.0" +lilconfig@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.1.3.tgz#a1bcfd6257f9585bf5ae14ceeebb7b559025e4c4" + integrity sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw== + lines-and-columns@^1.1.6: version "1.2.4" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" @@ -11349,6 +11699,11 @@ load-json-file@^1.0.0: pinkie-promise "^2.0.0" strip-bom "^2.0.0" +load-tsconfig@^0.2.3: + version "0.2.5" + resolved "https://registry.yarnpkg.com/load-tsconfig/-/load-tsconfig-0.2.5.tgz#453b8cd8961bfb912dea77eb6c168fe8cca3d3a1" + integrity sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg== + loader-runner@^4.2.0: version "4.3.0" resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" @@ -11485,6 +11840,11 @@ lodash.omitby@4.6.0: resolved "https://registry.yarnpkg.com/lodash.omitby/-/lodash.omitby-4.6.0.tgz#5c15ff4754ad555016b53c041311e8f079204791" integrity sha1-XBX/R1StVVAWtTwEExHo8HkgR5E= +lodash.sortby@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" + integrity sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA== + lodash.truncate@^4.4.2: version "4.4.2" resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" @@ -11998,7 +12358,7 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@2.1.3, ms@^2.1.1, ms@^2.1.2: +ms@2.1.3, ms@^2.1.1, ms@^2.1.2, ms@^2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== @@ -12030,7 +12390,7 @@ mv@~2: ncp "~2.0.0" rimraf "~2.4.0" -mz@2.7.0: +mz@2.7.0, mz@^2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== @@ -13072,6 +13432,11 @@ picocolors@^1.0.0: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== +picocolors@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== + picomatch@^2.0.4, picomatch@^2.2.3, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" @@ -13087,6 +13452,11 @@ picomatch@^2.2.1: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== +picomatch@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.2.tgz#77c742931e8f3b8820946c76cd0c1f13730d1dab" + integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg== + pify@^2.0.0, pify@^2.2.0, pify@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" @@ -13237,6 +13607,13 @@ posix-character-classes@^0.1.0: resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= +postcss-load-config@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-6.0.1.tgz#6fd7dcd8ae89badcf1b2d644489cbabf83aa8096" + integrity sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g== + dependencies: + lilconfig "^3.1.1" + postcss-modules-extract-imports@^1.2.0: version "1.2.1" resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.1.tgz#dc87e34148ec7eab5f791f7cd5849833375b741a" @@ -13965,6 +14342,11 @@ readdirp@^2.2.1: micromatch "^3.1.10" readable-stream "^2.0.2" +readdirp@^4.0.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-4.1.1.tgz#bd115327129672dc47f87408f05df9bd9ca3ef55" + integrity sha512-h80JrZu/MHUZCyHu5ciuoI0+WxsCxzxJTILn6Fs8rxSnFPh+UVHYfeIxK1nVGugMqkfC4vJcBOYbkfkwYK0+gw== + readdirp@~3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" @@ -14398,6 +14780,34 @@ rollup@^3.29.5: optionalDependencies: fsevents "~2.3.2" +rollup@^4.24.0: + version "4.32.1" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.32.1.tgz#95309604d92c3d21cbf06c3ee46a098209ce13a4" + integrity sha512-z+aeEsOeEa3mEbS1Tjl6sAZ8NE3+AalQz1RJGj81M+fizusbdDMoEJwdJNHfaB40Scr4qNu+welOfes7maKonA== + dependencies: + "@types/estree" "1.0.6" + optionalDependencies: + "@rollup/rollup-android-arm-eabi" "4.32.1" + "@rollup/rollup-android-arm64" "4.32.1" + "@rollup/rollup-darwin-arm64" "4.32.1" + "@rollup/rollup-darwin-x64" "4.32.1" + "@rollup/rollup-freebsd-arm64" "4.32.1" + "@rollup/rollup-freebsd-x64" "4.32.1" + "@rollup/rollup-linux-arm-gnueabihf" "4.32.1" + "@rollup/rollup-linux-arm-musleabihf" "4.32.1" + "@rollup/rollup-linux-arm64-gnu" "4.32.1" + "@rollup/rollup-linux-arm64-musl" "4.32.1" + "@rollup/rollup-linux-loongarch64-gnu" "4.32.1" + "@rollup/rollup-linux-powerpc64le-gnu" "4.32.1" + "@rollup/rollup-linux-riscv64-gnu" "4.32.1" + "@rollup/rollup-linux-s390x-gnu" "4.32.1" + "@rollup/rollup-linux-x64-gnu" "4.32.1" + "@rollup/rollup-linux-x64-musl" "4.32.1" + "@rollup/rollup-win32-arm64-msvc" "4.32.1" + "@rollup/rollup-win32-ia32-msvc" "4.32.1" + "@rollup/rollup-win32-x64-msvc" "4.32.1" + fsevents "~2.3.2" + rrweb-cssom@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz#ed298055b97cbddcdeb278f904857629dec5e0e1" @@ -15038,6 +15448,13 @@ source-map-url@^0.4.0: resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= +source-map@0.8.0-beta.0: + version "0.8.0-beta.0" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.8.0-beta.0.tgz#d4c1bb42c3f7ee925f005927ba10709e0d1d1f11" + integrity sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA== + dependencies: + whatwg-url "^7.0.0" + source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.6: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" @@ -15496,6 +15913,19 @@ style-loader@^1.2.1: loader-utils "^2.0.0" schema-utils "^2.6.6" +sucrase@^3.35.0: + version "3.35.0" + resolved "https://registry.yarnpkg.com/sucrase/-/sucrase-3.35.0.tgz#57f17a3d7e19b36d8995f06679d121be914ae263" + integrity sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA== + dependencies: + "@jridgewell/gen-mapping" "^0.3.2" + commander "^4.0.0" + glob "^10.3.10" + lines-and-columns "^1.1.6" + mz "^2.7.0" + pirates "^4.0.1" + ts-interface-checker "^0.1.9" + sumchecker@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/sumchecker/-/sumchecker-3.0.1.tgz#6377e996795abb0b6d348e9b3e1dfb24345a8e42" @@ -15784,6 +16214,19 @@ tiny-warning@^1.0.3: resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== +tinyexec@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/tinyexec/-/tinyexec-0.3.2.tgz#941794e657a85e496577995c6eef66f53f42b3d2" + integrity sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA== + +tinyglobby@^0.2.9: + version "0.2.10" + resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.10.tgz#e712cf2dc9b95a1f5c5bbd159720e15833977a0f" + integrity sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew== + dependencies: + fdir "^6.4.2" + picomatch "^4.0.2" + titleize@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/titleize/-/titleize-3.0.0.tgz#71c12eb7fdd2558aa8a44b0be83b8a76694acd53" @@ -15890,6 +16333,13 @@ tough-cookie@^4.1.2: universalify "^0.2.0" url-parse "^1.5.3" +tr46@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09" + integrity sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA== + dependencies: + punycode "^2.1.0" + tr46@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/tr46/-/tr46-4.1.1.tgz#281a758dcc82aeb4fe38c7dfe4d11a395aac8469" @@ -15907,6 +16357,11 @@ traverse-chain@~0.1.0: resolved "https://registry.yarnpkg.com/traverse-chain/-/traverse-chain-0.1.0.tgz#61dbc2d53b69ff6091a12a168fd7d433107e40f1" integrity sha1-YdvC1Ttp/2CRoSoWj9fUMxB+QPE= +tree-kill@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" + integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== + trim-newlines@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" @@ -15924,6 +16379,11 @@ ts-api-utils@^1.0.1: resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1" integrity sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ== +ts-interface-checker@^0.1.9: + version "0.1.13" + resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699" + integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA== + ts-node@8.9.1: version "8.9.1" resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.9.1.tgz#2f857f46c47e91dcd28a14e052482eb14cfd65a5" @@ -15950,6 +16410,28 @@ tslib@^2.3.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.0.tgz#803b8cdab3e12ba581a4ca41c8839bbb0dacb09e" integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg== +tsup@^8.3.5: + version "8.3.6" + resolved "https://registry.yarnpkg.com/tsup/-/tsup-8.3.6.tgz#a10eb2dc27f84b510a0f00341ab75cad03d13a88" + integrity sha512-XkVtlDV/58S9Ye0JxUUTcrQk4S+EqlOHKzg6Roa62rdjL1nGWNUstG0xgI4vanHdfIpjP448J8vlN0oK6XOJ5g== + dependencies: + bundle-require "^5.0.0" + cac "^6.7.14" + chokidar "^4.0.1" + consola "^3.2.3" + debug "^4.3.7" + esbuild "^0.24.0" + joycon "^3.1.1" + picocolors "^1.1.1" + postcss-load-config "^6.0.1" + resolve-from "^5.0.0" + rollup "^4.24.0" + source-map "0.8.0-beta.0" + sucrase "^3.35.0" + tinyexec "^0.3.1" + tinyglobby "^0.2.9" + tree-kill "^1.2.2" + tsutils@^3.17.1: version "3.17.1" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759" @@ -16053,6 +16535,11 @@ typescript@^3.7.5: resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.5.tgz#0692e21f65fd4108b9330238aac11dd2e177a1ae" integrity sha512-/P5lkRXkWHNAbcJIiHPfRoKqyd7bsyCma1hZNUGfn20qm64T6ZBlrzprymeu918H+mB/0rIg2gGK/BXkhhYgBw== +typescript@^5.4.3: + version "5.7.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.7.3.tgz#919b44a7dbb8583a9b856d162be24a54bf80073e" + integrity sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw== + ua-parser-js@^0.7.18, ua-parser-js@^0.7.9: version "0.7.20" resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.20.tgz#7527178b82f6a62a0f243d1f94fd30e3e3c21098" @@ -16086,6 +16573,11 @@ undici-types@~5.26.4: resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== +undici-types@~6.19.2: + version "6.19.8" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" + integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== + undici@^5.28.4: version "5.28.4" resolved "https://registry.yarnpkg.com/undici/-/undici-5.28.4.tgz#6b280408edb6a1a604a9b20340f45b422e373068" @@ -16577,6 +17069,11 @@ webidl-conversions@^3.0.0: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== +webidl-conversions@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" + integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== + webidl-conversions@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a" @@ -16747,6 +17244,15 @@ whatwg-url@^5.0.0: tr46 "~0.0.3" webidl-conversions "^3.0.0" +whatwg-url@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06" + integrity sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg== + dependencies: + lodash.sortby "^4.7.0" + tr46 "^1.0.1" + webidl-conversions "^4.0.2" + when@3.7.7: version "3.7.7" resolved "https://registry.yarnpkg.com/when/-/when-3.7.7.tgz#aba03fc3bb736d6c88b091d013d8a8e590d84718" From 19ca800caa01eec2f5e65e547c67b11592bec8b0 Mon Sep 17 00:00:00 2001 From: Wick Date: Sat, 1 Feb 2025 06:35:48 +0800 Subject: [PATCH 10/72] Reconciler: Combine identical cases in findParent (#32210) ## Summary When lookup `Parent`, `HostRoot` and `HostPortal` should be merged, because when creating a `Portal`, it will also include `containerInfo`(So we can directly use this `containerInfo` to delete the real DOM nodes.), so there is no need to handle them separately. ## How did you test this change? No behavior changes, all existing tests pass. --- packages/react-reconciler/src/ReactFiberCommitWork.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/react-reconciler/src/ReactFiberCommitWork.js b/packages/react-reconciler/src/ReactFiberCommitWork.js index 1cfe38cc209fa..850f3c67067ff 100644 --- a/packages/react-reconciler/src/ReactFiberCommitWork.js +++ b/packages/react-reconciler/src/ReactFiberCommitWork.js @@ -2007,11 +2007,7 @@ function commitDeletionEffects( hostParentIsContainer = false; break findParent; } - case HostRoot: { - hostParent = parent.stateNode.containerInfo; - hostParentIsContainer = true; - break findParent; - } + case HostRoot: case HostPortal: { hostParent = parent.stateNode.containerInfo; hostParentIsContainer = true; From 152bfe3769f87e29c8d68cb87fdb608d2483b7f1 Mon Sep 17 00:00:00 2001 From: mofeiZ <34200447+mofeiZ@users.noreply.github.com> Date: Fri, 31 Jan 2025 15:57:26 -0800 Subject: [PATCH 11/72] [compiler][rfc] Hacky retry pipeline for fire (#32164) Hacky retry pipeline for when transforming `fire(...)` calls encounters validation, todo, or memoization invariant bailouts. Would love feedback on how we implement this to be extensible to other compiler non-memoization features (e.g. inlineJSX) Some observations: - Compiler "front-end" passes (e.g. lower, type, effect, and mutability inferences) should be shared for all compiler features -- memo and otherwise - Many passes (anything dealing with reactive scope ranges, scope blocks / dependencies, and optimizations such as ReactiveIR #31974) can be left out of the retry pipeline. This PR hackily skips memoization features by removing reactive scope creation, but we probably should restructure the pipeline to skip these entirely on a retry - We should maintain a canonical set of "validation flags" Note the newly added fixtures are prefixed with `bailout-...` when the retry fire pipeline is used. These fixture outputs contain correctly inserted `useFire` calls and no memoization. --- .../src/Entrypoint/Pipeline.ts | 9 +- .../src/Entrypoint/Program.ts | 123 +++++++++++------- .../src/HIR/Environment.ts | 13 ++ .../src/Inference/InferReferenceEffects.ts | 2 +- .../bailout-capitalized-fn-call.expect.md | 50 +++++++ .../bailout-capitalized-fn-call.js | 16 +++ .../bailout-eslint-suppressions.expect.md | 55 ++++++++ .../bailout-eslint-suppressions.js | 18 +++ .../bailout-validate-preserve-memo.expect.md | 50 +++++++ .../bailout-validate-preserve-memo.js | 16 +++ .../bailout-validate-prop-write.expect.md | 42 ++++++ .../bailout-validate-prop-write.js | 12 ++ ...lout-validate-ref-current-access.expect.md | 51 ++++++++ .../bailout-validate-ref-current-access.js | 17 +++ .../bailout-retry/error.todo-syntax.expect.md | 49 +++++++ .../bailout-retry/error.todo-syntax.js | 20 +++ .../bailout-retry/todo-use-no-memo.expect.md | 47 +++++++ .../bailout-retry/todo-use-no-memo.js | 16 +++ ...ailout-validate-conditional-hook.expect.md | 57 ++++++++ ...s => bailout-validate-conditional-hook.js} | 7 +- ...r.invalid-conditional-use-effect.expect.md | 37 ------ 21 files changed, 617 insertions(+), 90 deletions(-) create mode 100644 compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/bailout-retry/bailout-capitalized-fn-call.expect.md create mode 100644 compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/bailout-retry/bailout-capitalized-fn-call.js create mode 100644 compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/bailout-retry/bailout-eslint-suppressions.expect.md create mode 100644 compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/bailout-retry/bailout-eslint-suppressions.js create mode 100644 compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/bailout-retry/bailout-validate-preserve-memo.expect.md create mode 100644 compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/bailout-retry/bailout-validate-preserve-memo.js create mode 100644 compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/bailout-retry/bailout-validate-prop-write.expect.md create mode 100644 compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/bailout-retry/bailout-validate-prop-write.js create mode 100644 compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/bailout-retry/bailout-validate-ref-current-access.expect.md create mode 100644 compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/bailout-retry/bailout-validate-ref-current-access.js create mode 100644 compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/bailout-retry/error.todo-syntax.expect.md create mode 100644 compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/bailout-retry/error.todo-syntax.js create mode 100644 compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/bailout-retry/todo-use-no-memo.expect.md create mode 100644 compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/bailout-retry/todo-use-no-memo.js create mode 100644 compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/bailout-validate-conditional-hook.expect.md rename compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/{error.invalid-conditional-use-effect.js => bailout-validate-conditional-hook.js} (55%) delete mode 100644 compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/error.invalid-conditional-use-effect.expect.md diff --git a/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Pipeline.ts b/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Pipeline.ts index a354acf69274e..0953289c1950e 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Pipeline.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Pipeline.ts @@ -162,7 +162,8 @@ function runWithEnvironment( if ( !env.config.enablePreserveExistingManualUseMemo && !env.config.disableMemoizationForDebugging && - !env.config.enableChangeDetectionForDebugging + !env.config.enableChangeDetectionForDebugging && + !env.config.enableMinimalTransformsForRetry ) { dropManualMemoization(hir); log({kind: 'hir', name: 'DropManualMemoization', value: hir}); @@ -279,8 +280,10 @@ function runWithEnvironment( value: hir, }); - inferReactiveScopeVariables(hir); - log({kind: 'hir', name: 'InferReactiveScopeVariables', value: hir}); + if (!env.config.enableMinimalTransformsForRetry) { + inferReactiveScopeVariables(hir); + log({kind: 'hir', name: 'InferReactiveScopeVariables', value: hir}); + } const fbtOperands = memoizeFbtAndMacroOperandsInSameScope(hir); log({ diff --git a/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Program.ts b/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Program.ts index 6ab9ee79c7412..787d9e7047efe 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Program.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Program.ts @@ -16,6 +16,7 @@ import { EnvironmentConfig, ExternalFunction, ReactFunctionType, + MINIMAL_RETRY_CONFIG, tryParseExternalFunction, } from '../HIR/Environment'; import {CodegenFunction} from '../ReactiveScopes'; @@ -382,66 +383,92 @@ export function compileProgram( ); } - let compiledFn: CodegenFunction; - try { - /** - * Note that Babel does not attach comment nodes to nodes; they are dangling off of the - * Program node itself. We need to figure out whether an eslint suppression range - * applies to this function first. - */ - const suppressionsInFunction = filterSuppressionsThatAffectFunction( - suppressions, - fn, - ); - if (suppressionsInFunction.length > 0) { - const lintError = suppressionsToCompilerError(suppressionsInFunction); - if (optOutDirectives.length > 0) { - logError(lintError, pass, fn.node.loc ?? null); - } else { - handleError(lintError, pass, fn.node.loc ?? null); - } - return null; + /** + * Note that Babel does not attach comment nodes to nodes; they are dangling off of the + * Program node itself. We need to figure out whether an eslint suppression range + * applies to this function first. + */ + const suppressionsInFunction = filterSuppressionsThatAffectFunction( + suppressions, + fn, + ); + let compileResult: + | {kind: 'compile'; compiledFn: CodegenFunction} + | {kind: 'error'; error: unknown}; + if (suppressionsInFunction.length > 0) { + compileResult = { + kind: 'error', + error: suppressionsToCompilerError(suppressionsInFunction), + }; + } else { + try { + compileResult = { + kind: 'compile', + compiledFn: compileFn( + fn, + environment, + fnType, + useMemoCacheIdentifier.name, + pass.opts.logger, + pass.filename, + pass.code, + ), + }; + } catch (err) { + compileResult = {kind: 'error', error: err}; } - - compiledFn = compileFn( - fn, - environment, - fnType, - useMemoCacheIdentifier.name, - pass.opts.logger, - pass.filename, - pass.code, - ); - pass.opts.logger?.logEvent(pass.filename, { - kind: 'CompileSuccess', - fnLoc: fn.node.loc ?? null, - fnName: compiledFn.id?.name ?? null, - memoSlots: compiledFn.memoSlotsUsed, - memoBlocks: compiledFn.memoBlocks, - memoValues: compiledFn.memoValues, - prunedMemoBlocks: compiledFn.prunedMemoBlocks, - prunedMemoValues: compiledFn.prunedMemoValues, - }); - } catch (err) { + } + // If non-memoization features are enabled, retry regardless of error kind + if (compileResult.kind === 'error' && environment.enableFire) { + try { + compileResult = { + kind: 'compile', + compiledFn: compileFn( + fn, + { + ...environment, + ...MINIMAL_RETRY_CONFIG, + }, + fnType, + useMemoCacheIdentifier.name, + pass.opts.logger, + pass.filename, + pass.code, + ), + }; + } catch (err) { + compileResult = {kind: 'error', error: err}; + } + } + if (compileResult.kind === 'error') { /** * If an opt out directive is present, log only instead of throwing and don't mark as * containing a critical error. */ - if (fn.node.body.type === 'BlockStatement') { - if (optOutDirectives.length > 0) { - logError(err, pass, fn.node.loc ?? null); - return null; - } + if (optOutDirectives.length > 0) { + logError(compileResult.error, pass, fn.node.loc ?? null); + } else { + handleError(compileResult.error, pass, fn.node.loc ?? null); } - handleError(err, pass, fn.node.loc ?? null); return null; } + pass.opts.logger?.logEvent(pass.filename, { + kind: 'CompileSuccess', + fnLoc: fn.node.loc ?? null, + fnName: compileResult.compiledFn.id?.name ?? null, + memoSlots: compileResult.compiledFn.memoSlotsUsed, + memoBlocks: compileResult.compiledFn.memoBlocks, + memoValues: compileResult.compiledFn.memoValues, + prunedMemoBlocks: compileResult.compiledFn.prunedMemoBlocks, + prunedMemoValues: compileResult.compiledFn.prunedMemoValues, + }); + /** * Always compile functions with opt in directives. */ if (optInDirectives.length > 0) { - return compiledFn; + return compileResult.compiledFn; } else if (pass.opts.compilationMode === 'annotation') { /** * No opt-in directive in annotation mode, so don't insert the compiled function. @@ -467,7 +494,7 @@ export function compileProgram( } if (!pass.opts.noEmit) { - return compiledFn; + return compileResult.compiledFn; } return null; }; diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/Environment.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/Environment.ts index 9df34242ec089..113af2025dd2b 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/Environment.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/Environment.ts @@ -552,6 +552,8 @@ const EnvironmentConfigSchema = z.object({ */ disableMemoizationForDebugging: z.boolean().default(false), + enableMinimalTransformsForRetry: z.boolean().default(false), + /** * When true, rather using memoized values, the compiler will always re-compute * values, and then use a heuristic to compare the memoized value to the newly @@ -626,6 +628,17 @@ const EnvironmentConfigSchema = z.object({ export type EnvironmentConfig = z.infer; +export const MINIMAL_RETRY_CONFIG: PartialEnvironmentConfig = { + validateHooksUsage: false, + validateRefAccessDuringRender: false, + validateNoSetStateInRender: false, + validateNoSetStateInPassiveEffects: false, + validateNoJSXInTryStatements: false, + validateMemoizedEffectDependencies: false, + validateNoCapitalizedCalls: null, + validateBlocklistedImports: null, + enableMinimalTransformsForRetry: true, +}; /** * For test fixtures and playground only. * diff --git a/compiler/packages/babel-plugin-react-compiler/src/Inference/InferReferenceEffects.ts b/compiler/packages/babel-plugin-react-compiler/src/Inference/InferReferenceEffects.ts index 70395e58d930e..0afe479df08dd 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Inference/InferReferenceEffects.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Inference/InferReferenceEffects.ts @@ -241,7 +241,7 @@ export default function inferReferenceEffects( if (options.isFunctionExpression) { fn.effects = functionEffects; - } else { + } else if (!fn.env.config.enableMinimalTransformsForRetry) { raiseFunctionEffectErrors(functionEffects); } } diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/bailout-retry/bailout-capitalized-fn-call.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/bailout-retry/bailout-capitalized-fn-call.expect.md new file mode 100644 index 0000000000000..f7f413dedf906 --- /dev/null +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/bailout-retry/bailout-capitalized-fn-call.expect.md @@ -0,0 +1,50 @@ + +## Input + +```javascript +// @validateNoCapitalizedCalls @enableFire +import {fire} from 'react'; +const CapitalizedCall = require('shared-runtime').sum; + +function Component({prop1, bar}) { + const foo = () => { + console.log(prop1); + }; + useEffect(() => { + fire(foo(prop1)); + fire(foo()); + fire(bar()); + }); + + return CapitalizedCall(); +} + +``` + +## Code + +```javascript +import { useFire } from "react/compiler-runtime"; // @validateNoCapitalizedCalls @enableFire +import { fire } from "react"; +const CapitalizedCall = require("shared-runtime").sum; + +function Component(t0) { + const { prop1, bar } = t0; + const foo = () => { + console.log(prop1); + }; + const t1 = useFire(foo); + const t2 = useFire(bar); + + useEffect(() => { + t1(prop1); + t1(); + t2(); + }); + return CapitalizedCall(); +} + +``` + +### Eval output +(kind: exception) Fixture not implemented \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/bailout-retry/bailout-capitalized-fn-call.js b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/bailout-retry/bailout-capitalized-fn-call.js new file mode 100644 index 0000000000000..b872fd8670e8e --- /dev/null +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/bailout-retry/bailout-capitalized-fn-call.js @@ -0,0 +1,16 @@ +// @validateNoCapitalizedCalls @enableFire +import {fire} from 'react'; +const CapitalizedCall = require('shared-runtime').sum; + +function Component({prop1, bar}) { + const foo = () => { + console.log(prop1); + }; + useEffect(() => { + fire(foo(prop1)); + fire(foo()); + fire(bar()); + }); + + return CapitalizedCall(); +} diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/bailout-retry/bailout-eslint-suppressions.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/bailout-retry/bailout-eslint-suppressions.expect.md new file mode 100644 index 0000000000000..ad7f0ab467b00 --- /dev/null +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/bailout-retry/bailout-eslint-suppressions.expect.md @@ -0,0 +1,55 @@ + +## Input + +```javascript +// @enableFire +import {useRef} from 'react'; + +function Component({props, bar}) { + const foo = () => { + console.log(props); + }; + useEffect(() => { + fire(foo(props)); + fire(foo()); + fire(bar()); + }); + + const ref = useRef(null); + // eslint-disable-next-line react-hooks/rules-of-hooks + ref.current = 'bad'; + return