diff --git a/.config/ast-grep/rule-tests/__snapshots__/no-map-async-cell-snapshot.yml b/.config/ast-grep/rule-tests/__snapshots__/no-map-async-cell-snapshot.yml new file mode 100644 index 000000000000..f287ad3e1e69 --- /dev/null +++ b/.config/ast-grep/rule-tests/__snapshots__/no-map-async-cell-snapshot.yml @@ -0,0 +1,282 @@ +id: no-map-async-cell +snapshots: + ? | + items.into_iter() + .map(async |item| Ok(item.process().await?.cell())) + .try_join() + .await + : labels: + - source: item.process().await?.cell() + style: primary + start: 43 + end: 71 + - source: |- + items.into_iter() + .map(async |item| Ok(item.process().await?.cell())) + style: secondary + start: 0 + end: 73 + - source: async |item| Ok(item.process().await?.cell()) + style: secondary + start: 27 + end: 72 + ? | + items.into_iter() + .map(async |item| item.process().await.cell()) + .try_join() + .await + : labels: + - source: |- + items.into_iter() + .map(async |item| item.process().await.cell()) + style: primary + start: 0 + end: 68 + - source: item.process().await.cell() + style: secondary + start: 40 + end: 67 + ? | + items.into_iter() + .map(async |item| { + Ok(item.process().await?.cell()) + }) + .try_join() + .await + : labels: + - source: item.process().await?.cell() + style: primary + start: 53 + end: 81 + - source: |- + items.into_iter() + .map(async |item| { + Ok(item.process().await?.cell()) + }) + style: secondary + start: 0 + end: 89 + - source: |- + async |item| { + Ok(item.process().await?.cell()) + } + style: secondary + start: 27 + end: 88 + ? | + items.into_iter() + .map(async |item| { + item.process().await.cell() + }) + .try_join() + .await + : labels: + - source: |- + items.into_iter() + .map(async |item| { + item.process().await.cell() + }) + style: primary + start: 0 + end: 84 + - source: item.process().await.cell() + style: secondary + start: 50 + end: 77 + ? | + items.into_iter() + .map(|item| async move { + Ok(item.process().await?.cell()) + }) + .try_join() + .await + : labels: + - source: item.process().await?.cell() + style: primary + start: 58 + end: 86 + - source: |- + items.into_iter() + .map(|item| async move { + Ok(item.process().await?.cell()) + }) + style: secondary + start: 0 + end: 94 + - source: |- + |item| async move { + Ok(item.process().await?.cell()) + } + style: secondary + start: 27 + end: 93 + ? | + items.into_iter() + .map(|item| async { + Ok(item.process().await?.cell()) + }) + .try_join() + .await + : labels: + - source: item.process().await?.cell() + style: primary + start: 53 + end: 81 + - source: |- + items.into_iter() + .map(|item| async { + Ok(item.process().await?.cell()) + }) + style: secondary + start: 0 + end: 89 + - source: |- + |item| async { + Ok(item.process().await?.cell()) + } + style: secondary + start: 27 + end: 88 + ? | + map.into_iter() + .map(|(ty, items)| { + ( + ty, + ChunkItemBatchGroup { + items, + chunk_groups: this.chunk_groups.clone(), + }, + ) + }) + .map(async |(ty, batch_group)| Ok((ty, batch_group.resolved_cell()))) + .try_join() + : labels: + - source: batch_group.resolved_cell() + style: primary + start: 256 + end: 283 + - source: |- + map.into_iter() + .map(|(ty, items)| { + ( + ty, + ChunkItemBatchGroup { + items, + chunk_groups: this.chunk_groups.clone(), + }, + ) + }) + .map(async |(ty, batch_group)| Ok((ty, batch_group.resolved_cell()))) + style: secondary + start: 0 + end: 286 + - source: async |(ty, batch_group)| Ok((ty, batch_group.resolved_cell())) + style: secondary + start: 222 + end: 285 + ? | + modules + .map(async |module| { + let result = module.compute().await?; + result.into_value().cell() + }) + : labels: + - source: result.into_value().cell() + style: primary + start: 88 + end: 114 + - source: |- + modules + .map(async |module| { + let result = module.compute().await?; + result.into_value().cell() + }) + style: secondary + start: 0 + end: 121 + - source: |- + async |module| { + let result = module.compute().await?; + result.into_value().cell() + } + style: secondary + start: 17 + end: 120 + ? | + modules + .map(async |module| { + let result = module.compute().await?; + result.into_value().cell() + }) + .try_join() + : labels: + - source: |- + modules + .map(async |module| { + let result = module.compute().await?; + result.into_value().cell() + }) + style: primary + start: 0 + end: 121 + - source: result.into_value().cell() + style: secondary + start: 88 + end: 114 + ? | + paths.map(async |(path, asset)| { + AssetBinding { + name: wasm_edge_var_name(Vc::upcast(*asset)).owned().await?, + }.cell() + }) + : labels: + - source: |- + paths.map(async |(path, asset)| { + AssetBinding { + name: wasm_edge_var_name(Vc::upcast(*asset)).owned().await?, + }.cell() + }) + style: primary + start: 0 + end: 137 + - source: |- + AssetBinding { + name: wasm_edge_var_name(Vc::upcast(*asset)).owned().await?, + }.cell() + style: secondary + start: 38 + end: 134 + ? | + paths.map(async |(path, asset)| { + Ok(AssetBinding { + name: wasm_edge_var_name(Vc::upcast(*asset)).owned().await?, + }.cell()) + }) + .try_join() + .await + : labels: + - source: |- + AssetBinding { + name: wasm_edge_var_name(Vc::upcast(*asset)).owned().await?, + }.cell() + style: primary + start: 41 + end: 137 + - source: |- + paths.map(async |(path, asset)| { + Ok(AssetBinding { + name: wasm_edge_var_name(Vc::upcast(*asset)).owned().await?, + }.cell()) + }) + style: secondary + start: 0 + end: 141 + - source: |- + async |(path, asset)| { + Ok(AssetBinding { + name: wasm_edge_var_name(Vc::upcast(*asset)).owned().await?, + }.cell()) + } + style: secondary + start: 10 + end: 140 diff --git a/.config/ast-grep/rule-tests/no-map-async-cell-test.yml b/.config/ast-grep/rule-tests/no-map-async-cell-test.yml new file mode 100644 index 000000000000..743a22265ac6 --- /dev/null +++ b/.config/ast-grep/rule-tests/no-map-async-cell-test.yml @@ -0,0 +1,70 @@ +id: no-map-async-cell +valid: + - | + items.into_iter() + .map(|item| item.process()) + .collect() + - | + items.into_iter() + .map(|item| { + SomeStruct { field: item }.cell() + }) + .collect() + - | + call_once(|| async { + X{}.cell() + }) +invalid: + - | + items.into_iter() + .map(|item| async move { + Ok(item.process().await?.cell()) + }) + .try_join() + .await + - | + items.into_iter() + .map(|item| async { + Ok(item.process().await?.cell()) + }) + .try_join() + .await + - | + items.into_iter() + .map(async |item| { + Ok(item.process().await?.cell()) + }) + .try_join() + .await + - | + items.into_iter() + .map(async |item| Ok(item.process().await?.cell())) + .try_join() + .await + - | + paths.map(async |(path, asset)| { + Ok(AssetBinding { + name: wasm_edge_var_name(Vc::upcast(*asset)).owned().await?, + }.cell()) + }) + .try_join() + .await + - | + modules + .map(async |module| { + let result = module.compute().await?; + result.into_value().cell() + }) + - | + map.into_iter() + .map(|(ty, items)| { + ( + ty, + ChunkItemBatchGroup { + items, + chunk_groups: this.chunk_groups.clone(), + }, + ) + }) + .map(async |(ty, batch_group)| Ok((ty, batch_group.resolved_cell()))) + .try_join() diff --git a/.config/ast-grep/rules/no-map-async-cell.yml b/.config/ast-grep/rules/no-map-async-cell.yml new file mode 100644 index 000000000000..5b5f0a25a2d1 --- /dev/null +++ b/.config/ast-grep/rules/no-map-async-cell.yml @@ -0,0 +1,26 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/ast-grep/ast-grep/main/schemas/rule.json + +id: no-map-async-cell +message: Using `.map(async |...| { ...cell() })` causes non-deterministic cell order +note: You probably want to first `try_join()` the async computations before wrapping them in a cell. +severity: error +language: Rust +rule: + all: + - any: + - pattern: $_X.cell() + - pattern: $_X.resolved_cell() + - pattern: ResolvedVc::cell($_X) + - pattern: Vc::cell($_X) + - inside: + stopBy: end + all: + - any: + - pattern: 'async |$$$ARGS| $BODY' + - pattern: 'async move |$$$ARGS| $BODY' + - pattern: '|$$$ARGS| async { $$$BODY }' + - pattern: '|$$$ARGS| async move { $$$BODY }' + - inside: + stopBy: end + field: arguments + pattern: $EXPR.map($$$CLOSURE) diff --git a/.github/labeler.json b/.github/labeler.json index 5dd8b60030b6..c77e0307516a 100644 --- a/.github/labeler.json +++ b/.github/labeler.json @@ -80,6 +80,7 @@ { "type": "user", "pattern": "bgw" }, { "type": "user", "pattern": "lukesandberg" }, { "type": "user", "pattern": "mischnic" }, + { "type": "user", "pattern": "mmastrac" }, { "type": "user", "pattern": "sokra" }, { "type": "user", "pattern": "timneutkens" }, { "type": "user", "pattern": "wbinnssmith" } diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index c03725aa3ae2..2d0d10b33d27 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -6,6 +6,12 @@ on: pull_request: types: [opened, synchronize] +concurrency: + # Limit concurrent runs to 1 per PR, + # but allow concurrent runs on push if they potentially use different source code + group: ${{ github.event_name == 'pull_request' && format('{0}-pr-{1}', github.workflow, github.ref_name) || format('{0}-sha-{1}', github.workflow, github.sha) }} + cancel-in-progress: true + # NOTE: anything in `afterBuild` inherits environment variables defined in # `build_reusable.yml` (not these!) because that job executes within the context # of that workflow. Environment variables are not automatically passed to diff --git a/.github/workflows/cancel.yml b/.github/workflows/cancel.yml deleted file mode 100644 index 9f5871a5ab8c..000000000000 --- a/.github/workflows/cancel.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: Cancel -on: - pull_request_target: - types: - - edited - - synchronize - -jobs: - cancel: - name: 'Cancel Previous Runs' - runs-on: ubuntu-latest - timeout-minutes: 2 - steps: - - uses: styfle/cancel-workflow-action@0.12.1 - with: - workflow_id: 57419851 - access_token: ${{ github.token }} diff --git a/.github/workflows/integration_tests_reusable.yml b/.github/workflows/integration_tests_reusable.yml index 596b8e2c41e7..a83f13f472f1 100644 --- a/.github/workflows/integration_tests_reusable.yml +++ b/.github/workflows/integration_tests_reusable.yml @@ -91,7 +91,6 @@ jobs: afterBuild: | # e2e and ${{ inputs.test_type }} tests with `node run-tests.js` - export NEXT_TEST_CONTINUE_ON_ERROR=true export NEXT_TEST_MODE=${{ inputs.test_type == 'development' && 'dev' || 'start' }} @@ -123,8 +122,6 @@ jobs: afterBuild: | # legacy integration tests with `node run-tests.js` - export NEXT_TEST_CONTINUE_ON_ERROR=true - # HACK: Despite the name, these environment variables are just used to # gate tests, so they're applicable to both turbopack and rspack tests export ${{ diff --git a/.github/workflows/nextjs.yml b/.github/workflows/nextjs.yml new file mode 100644 index 000000000000..2fd3b933336e --- /dev/null +++ b/.github/workflows/nextjs.yml @@ -0,0 +1,98 @@ +# Sample workflow for building and deploying a Next.js site to GitHub Pages +# +# To get started with Next.js see: https://nextjs.org/docs/getting-started +# +name: Deploy Next.js site to Pages + +on: + # Runs on pushes targeting the default branch + push: + branches: ["canary"] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +permissions: + contents: read + pages: write + id-token: write + +# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. +# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. +concurrency: + group: "pages" + cancel-in-progress: false + +jobs: + # Build job + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Detect package manager + id: detect-package-manager + run: | + if [ -f "${{ github.workspace }}/pnpm-lock.yaml" ]; then + echo "manager=pnpm" >> $GITHUB_OUTPUT + echo "command=install" >> $GITHUB_OUTPUT + echo "runner=pnpm" >> $GITHUB_OUTPUT + exit 0 + elif [ -f "${{ github.workspace }}/yarn.lock" ]; then + echo "manager=yarn" >> $GITHUB_OUTPUT + echo "command=install" >> $GITHUB_OUTPUT + echo "runner=yarn" >> $GITHUB_OUTPUT + exit 0 + elif [ -f "${{ github.workspace }}/package.json" ]; then + echo "manager=npm" >> $GITHUB_OUTPUT + echo "command=ci" >> $GITHUB_OUTPUT + echo "runner=npx --no-install" >> $GITHUB_OUTPUT + exit 0 + else + echo "Unable to determine package manager" + exit 1 + fi + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: "18,20,22,24" + cache: ${{ steps.detect-package-manager.outputs.manager }} + - name: Setup Pages + uses: actions/configure-pages@v5 + with: + # Automatically inject basePath in your Next.js configuration file and disable + # server side image optimization (https://nextjs.org/docs/api-reference/next/image#unoptimized). + # + # You may remove this line if you want to manage the configuration yourself. + static_site_generator: next + - name: Restore cache + uses: actions/cache@v4 + with: + path: | + .next/cache + # Generate a new cache whenever packages or source files change. + key: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json', '**/yarn.lock') }}-${{ hashFiles('**.[jt]s', '**.[jt]sx') }} + # If source files changed but packages didn't, rebuild from a prior cache. + restore-keys: | + ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json', '**/yarn.lock') }}- + - name: Install dependencies + run: ${{ steps.detect-package-manager.outputs.manager }} ${{ steps.detect-package-manager.outputs.command }} + - name: Build with Next.js + run: ${{ steps.detect-package-manager.outputs.runner }} next build + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + path: ./out + + # Deployment job + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + needs: build + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/.github/workflows/retry_deploy_test.yml b/.github/workflows/retry_deploy_test.yml index 08225ac31728..5ebff4000869 100644 --- a/.github/workflows/retry_deploy_test.yml +++ b/.github/workflows/retry_deploy_test.yml @@ -18,7 +18,10 @@ jobs: # Retry the test-e2e-deploy-release workflow once if: >- ${{ - startsWith(github.event.workflow_run.display_title, 'test-e2e-deploy') && + ( + github.event.workflow_run.event == 'release' || + github.event.workflow_run.display_title == 'test-e2e-deploy canary' + ) && github.event.workflow_run.conclusion == 'failure' && github.repository == 'vercel/next.js' && github.event.workflow_run.run_attempt < 2 @@ -40,7 +43,10 @@ jobs: # Report the failure to Slack if the test-e2e-deploy-release workflow has failed 2 times if: >- ${{ - startsWith(github.event.workflow_run.display_title, 'test-e2e-deploy') && + ( + github.event.workflow_run.event == 'release' || + github.event.workflow_run.display_title == 'test-e2e-deploy canary' + ) && github.event.workflow_run.conclusion == 'failure' && github.event.workflow_run.run_attempt >= 2 && !github.event.workflow_run.head_repository.fork diff --git a/.github/workflows/test_e2e_deploy_release.yml b/.github/workflows/test_e2e_deploy_release.yml index 3ad1f12e29ca..a40c90d49074 100644 --- a/.github/workflows/test_e2e_deploy_release.yml +++ b/.github/workflows/test_e2e_deploy_release.yml @@ -19,10 +19,6 @@ on: description: Override the proxy address to use for the test default: '' type: string - continueOnError: - description: whether the tests should continue on failure - default: false - type: boolean env: TURBO_TEAM: 'vercel' @@ -85,7 +81,6 @@ jobs: NEXT_E2E_TEST_TIMEOUT=240000 \ NEXT_TEST_MODE=deploy \ IS_WEBPACK_TEST=1 \ - NEXT_TEST_CONTINUE_ON_ERROR="${{ github.event.inputs.continueOnError || false }}" \ NEXT_EXTERNAL_TESTS_FILTERS="test/deploy-tests-manifest.json" \ NEXT_TEST_VERSION="${{ github.event.inputs.nextVersion || needs.setup.outputs.next-version || 'canary' }}" \ VERCEL_CLI_VERSION="${{ github.event.inputs.vercelCliVersion || 'vercel@latest' }}" \ diff --git a/.gitignore b/.gitignore index ad9c1fd2ecd6..43102aa0c41e 100644 --- a/.gitignore +++ b/.gitignore @@ -73,3 +73,5 @@ CLAUDE.local.md # Conductor (worktrees created by Conductor app, but keep scripts/) .conductor/*/ !.conductor/scripts/ + +index.scip diff --git a/.rustfmt.toml b/.rustfmt.toml index 75b28121a6d2..5a9400028019 100644 --- a/.rustfmt.toml +++ b/.rustfmt.toml @@ -1,3 +1,4 @@ +edition = "2024" max_width = 100 comment_width = 100 diff --git a/AGENTS.md b/AGENTS.md index 1213a85062f5..0a9d8c690f49 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -301,6 +301,7 @@ See [Codebase structure](#codebase-structure) above for detailed explanations. - Do NOT add "Generated with Claude Code" or co-author footers to commits or PRs - Keep commit messages concise and descriptive - PR descriptions should focus on what changed and why +- Do NOT mark PRs as "ready for review" (`gh pr ready`) - leave PRs in draft mode and let the user decide when to mark them ready ## Rebuilding Before Running Tests diff --git a/Cargo.lock b/Cargo.lock index 90759d9882fd..cdb13edd140b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -443,6 +443,29 @@ dependencies = [ "arrayvec 0.7.6", ] +[[package]] +name = "aws-lc-rs" +version = "1.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c953fe1ba023e6b7730c0d4b031d06f267f23a46167dcbd40316644b10a17ba" +dependencies = [ + "aws-lc-sys", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbfd150b5dbdb988bcc8fb1fe787eb6b7ee6180ca24da683b61ea5405f3d43ff" +dependencies = [ + "bindgen 0.69.5", + "cc", + "cmake", + "dunce", + "fs_extra", +] + [[package]] name = "axum" version = "0.7.5" @@ -578,6 +601,29 @@ dependencies = [ "virtue", ] +[[package]] +name = "bindgen" +version = "0.69.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" +dependencies = [ + "bitflags 2.9.1", + "cexpr", + "clang-sys", + "itertools 0.10.5", + "lazy_static", + "lazycell", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash 1.1.0", + "shlex", + "syn 2.0.104", + "which", +] + [[package]] name = "bindgen" version = "0.70.1" @@ -2899,12 +2945,10 @@ dependencies = [ "hyper 1.7.0", "hyper-util", "rustls", - "rustls-native-certs", "rustls-pki-types", "tokio", "tokio-rustls", "tower-service", - "webpki-roots", ] [[package]] @@ -3520,6 +3564,12 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + [[package]] name = "leb128" version = "0.2.5" @@ -4229,18 +4279,17 @@ dependencies = [ [[package]] name = "native-tls" -version = "0.2.11" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" dependencies = [ - "lazy_static", "libc", "log", "openssl", - "openssl-probe", + "openssl-probe 0.1.6", "openssl-sys", "schannel", - "security-framework 2.8.2", + "security-framework 2.11.1", "security-framework-sys", "tempfile", ] @@ -4768,11 +4817,11 @@ checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" [[package]] name = "openssl" -version = "0.10.47" +version = "0.10.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b277f87dacc05a6b709965d1cbafac4649d6ce9f3ce9ceb88508b5666dfec9" +checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.9.1", "cfg-if", "foreign-types", "libc", @@ -4783,13 +4832,13 @@ dependencies = [ [[package]] name = "openssl-macros" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.104", ] [[package]] @@ -4798,13 +4847,18 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" +[[package]] +name = "openssl-probe" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f50d9b3dabb09ecd771ad0aa242ca6894994c130308ca3d7684634df8037391" + [[package]] name = "openssl-sys" -version = "0.9.82" +version = "0.9.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a95792af3c4e0153c3914df2261bedd30a98476f94dc892b67dfe1d89d433a04" +checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" dependencies = [ - "autocfg", "cc", "libc", "pkg-config", @@ -5536,9 +5590,9 @@ dependencies = [ [[package]] name = "quinn" -version = "0.11.8" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "626214629cda6781b6dc1d316ba307189c85ba657213ce642d9c77670f8202c8" +checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" dependencies = [ "bytes", "cfg_aliases", @@ -5556,10 +5610,11 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.12" +version = "0.11.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49df843a9161c85bb8aae55f101bc0bac8bcafd637a620d9122fd7e0b2f7422e" +checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" dependencies = [ + "aws-lc-rs", "bytes", "getrandom 0.3.3", "lru-slab", @@ -5577,16 +5632,16 @@ dependencies = [ [[package]] name = "quinn-udp" -version = "0.5.12" +version = "0.5.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee4e529991f949c5e25755532370b8af5d114acae52326361d68d47af64aa842" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" dependencies = [ "cfg_aliases", "libc", "once_cell", "socket2 0.5.10", "tracing", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -5907,9 +5962,9 @@ checksum = "e3a8614ee435691de62bcffcf4a66d91b3594bf1428a5722e79103249a095690" [[package]] name = "reqwest" -version = "0.12.24" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d0946410b9f7b082a427e4ef5c8ff541a88b357bc6c637c40db3a68ac70a36f" +checksum = "04e9018c9d814e5f30cc16a0f03271aeab3571e609612d9fe78c1aa8d11c2f62" dependencies = [ "base64 0.22.1", "bytes", @@ -5930,11 +5985,8 @@ dependencies = [ "pin-project-lite", "quinn", "rustls", - "rustls-native-certs", "rustls-pki-types", - "serde", - "serde_json", - "serde_urlencoded", + "rustls-platform-verifier", "sync_wrapper", "tokio", "tokio-native-tls", @@ -5946,7 +5998,6 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots", ] [[package]] @@ -5957,15 +6008,14 @@ checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a" [[package]] name = "ring" -version = "0.17.8" +version = "0.17.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", "getrandom 0.2.15", "libc", - "spin", "untrusted", "windows-sys 0.52.0", ] @@ -6144,10 +6194,11 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.33" +version = "0.23.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "751e04a496ca00bb97a5e043158d23d66b5aabf2e1d5aa2a0aaebb1aafe6f82c" +checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc" dependencies = [ + "aws-lc-rs", "once_cell", "ring", "rustls-pki-types", @@ -6158,11 +6209,11 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9980d917ebb0c0536119ba501e90834767bffc3d60641457fd84a1f3fd337923" +checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" dependencies = [ - "openssl-probe", + "openssl-probe 0.2.0", "rustls-pki-types", "schannel", "security-framework 3.5.1", @@ -6170,20 +6221,48 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.12.0" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +checksum = "21e6f2ab2928ca4291b86736a8bd920a277a399bba1589409d72154ff87c1282" dependencies = [ "web-time", "zeroize", ] +[[package]] +name = "rustls-platform-verifier" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784" +dependencies = [ + "core-foundation 0.10.1", + "core-foundation-sys", + "jni", + "log", + "once_cell", + "rustls", + "rustls-native-certs", + "rustls-platform-verifier-android", + "rustls-webpki", + "security-framework 3.5.1", + "security-framework-sys", + "webpki-root-certs", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustls-platform-verifier-android" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" + [[package]] name = "rustls-webpki" -version = "0.103.7" +version = "0.103.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e10b3f4191e8a80e6b43eebabfac91e5dcecebb27a71f04e820c47ec41d314bf" +checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc" dependencies = [ + "aws-lc-rs", "ring", "rustls-pki-types", "untrusted", @@ -6252,11 +6331,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.21" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" +checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" dependencies = [ - "windows-sys 0.42.0", + "windows-sys 0.61.2", ] [[package]] @@ -6329,11 +6408,11 @@ checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" [[package]] name = "security-framework" -version = "2.8.2" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.9.1", "core-foundation 0.9.4", "core-foundation-sys", "libc", @@ -6974,9 +7053,9 @@ dependencies = [ [[package]] name = "subtle" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "supports-hyperlinks" @@ -8771,9 +8850,9 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.26.1" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ "rustls", "tokio", @@ -8965,9 +9044,9 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.6.6" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" +checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" dependencies = [ "bitflags 2.9.1", "bytes", @@ -9541,6 +9620,7 @@ dependencies = [ "anyhow", "futures", "rustc-hash 2.1.1", + "smallvec", "tokio", "turbo-tasks", ] @@ -10085,6 +10165,7 @@ name = "turbopack-resolve" version = "0.1.0" dependencies = [ "anyhow", + "bincode 2.0.1", "next-taskless", "regex", "serde", @@ -10852,7 +10933,7 @@ version = "6.1.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e588d83a5ac7eb5e6af54ac4d34183442e4dd2a7358d2a11793b17c03b7df0b" dependencies = [ - "bindgen", + "bindgen 0.70.1", "bytes", "cfg-if", "cmake", @@ -11280,10 +11361,10 @@ dependencies = [ ] [[package]] -name = "webpki-roots" -version = "1.0.2" +name = "webpki-root-certs" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8983c3ab33d6fb807cfcdad2491c4ea8cbc8ed839181c7dfd9c67c83e261b2" +checksum = "36a29fc0408b113f68cf32637857ab740edfafdf460c326cd2afaa2d84cc05dc" dependencies = [ "rustls-pki-types", ] @@ -11402,21 +11483,6 @@ dependencies = [ "windows-link 0.2.1", ] -[[package]] -name = "windows-sys" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - [[package]] name = "windows-sys" version = "0.45.0" @@ -11462,6 +11528,15 @@ dependencies = [ "windows-targets 0.53.5", ] +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link 0.2.1", +] + [[package]] name = "windows-targets" version = "0.42.2" @@ -11886,9 +11961,9 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.8.1" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" [[package]] name = "zerovec" diff --git a/Cargo.toml b/Cargo.toml index ef160d051f4e..8a0b66a10a2d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -176,9 +176,6 @@ opt-level = 3 [profile.release.package.turbopack-wasm] opt-level = 3 -[profile.release.package.rustls] -opt-level = "s" - [profile.release.package.turbopack-ecmascript-plugins] opt-level = 3 @@ -441,7 +438,7 @@ rand = "0.9.0" rayon = "1.10.0" regex = "1.10.6" regress = "0.10.4" -reqwest = { version = "0.12.24", default-features = false } +reqwest = { version = "0.13.1", default-features = false } ringmap = "0.1.3" roaring = "0.10.10" rstest = "0.16.0" diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000000..6f6bfb032759 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,21 @@ +# Security Policy + +## Supported Versions + +Use this section to tell people about which versions of your project are +currently being supported with security updates. + +| Version | Supported | +| ------- | ------------------ | +| 5.1.x | :white_check_mark: | +| 5.0.x | :x: | +| 4.0.x | :white_check_mark: | +| < 4.0 | :x: | + +## Reporting a Vulnerability + +The Next.js team and community take all security vulnerabilities seriously. + +To report a security vulnerability, please use the [GitHub private vulnerability reporting feature](https://github.com/vercel/next.js/security/advisories/new). + +You can expect a response within 48 hours. We appreciate your efforts to responsibly disclose your findings, and will make every effort to acknowledge your contributions. diff --git a/crates/napi/src/next_api/project.rs b/crates/napi/src/next_api/project.rs index bc052b877554..d435d52ad61d 100644 --- a/crates/napi/src/next_api/project.rs +++ b/crates/napi/src/next_api/project.rs @@ -50,7 +50,7 @@ use turbopack_core::{ PROJECT_FILESYSTEM_NAME, SOURCE_URL_PROTOCOL, diagnostics::PlainDiagnostic, error::PrettyPrintError, - issue::PlainIssue, + issue::{IssueFilter, PlainIssue}, output::{OutputAsset, OutputAssets}, source_map::{SourceMap, Token}, version::{PartialUpdate, TotalUpdate, Update, VersionState}, @@ -87,6 +87,10 @@ static SOURCE_MAP_PREFIX: Lazy = Lazy::new(|| format!("{SOURCE_URL_PROTO static SOURCE_MAP_PREFIX_PROJECT: Lazy = Lazy::new(|| format!("{SOURCE_URL_PROTOCOL}///[{PROJECT_FILESYSTEM_NAME}]/")); +/// Next doesn't display warnings from node_modules, so configure turbopack to not report them +/// either. This matches logic in `packages/next/src/server/dev/turbopack-utils.ts` +pub const NEXT_ISSUE_FILTER: IssueFilter = IssueFilter::warnings_and_foreign_errors(); + #[napi(object)] #[derive(Clone, Debug)] pub struct NapiEnvVar { @@ -1190,7 +1194,7 @@ async fn hmr_update_with_issues_operation( ) -> Result> { let update_op = project_hmr_update_operation(project, identifier, state); let update = update_op.read_strongly_consistent().await?; - let issues = get_issues(update_op).await?; + let issues = get_issues(update_op, NEXT_ISSUE_FILTER).await?; let diagnostics = get_diagnostics(update_op).await?; let effects = Arc::new(get_effects(update_op).await?); Ok(HmrUpdateWithIssues { @@ -1315,7 +1319,7 @@ async fn get_hmr_identifiers_with_issues_operation( ) -> Result> { let hmr_identifiers_op = project_container_hmr_identifiers_operation(container); let hmr_identifiers = hmr_identifiers_op.read_strongly_consistent().await?; - let issues = get_issues(hmr_identifiers_op).await?; + let issues = get_issues(hmr_identifiers_op, NEXT_ISSUE_FILTER).await?; let diagnostics = get_diagnostics(hmr_identifiers_op).await?; let effects = Arc::new(get_effects(hmr_identifiers_op).await?); Ok(HmrIdentifiersWithIssues { diff --git a/crates/napi/src/next_api/turbopack_ctx.rs b/crates/napi/src/next_api/turbopack_ctx.rs index 21e550f0bc1c..3b018273c77a 100644 --- a/crates/napi/src/next_api/turbopack_ctx.rs +++ b/crates/napi/src/next_api/turbopack_ctx.rs @@ -359,20 +359,15 @@ pub fn log_internal_error_and_inform(internal_error: &anyhow::Error) { env!("VERGEN_GIT_DESCRIBE"), env!("NEXTJS_VERSION") ); - let new_discussion_url = if supports_hyperlinks::supports_hyperlinks() { - "clicking here.".hyperlink( - format!( - "https://github.com/vercel/next.js/discussions/new?category=turbopack-error-report&title={}&body={}&labels=Turbopack,Turbopack%20Panic%20Backtrace", - &urlencoding::encode(&title), - &urlencoding::encode(&format!("{}\n\nError message:\n```\n{}\n```", &version_str, &internal_error_str)) - ) - ) + let bug_report_url = format!( + "https://bugs.nextjs.org/search?category=turbopack-error-report&title={}&body={}&labels=Turbopack,Turbopack%20Panic%20Backtrace", + &urlencoding::encode(&title), + &urlencoding::encode(&format!("{}\n\nError message:\n```\n{}\n```", &version_str, &internal_error_str)) + ); + let bug_report_message = if supports_hyperlinks::supports_hyperlinks() { + "clicking here.".hyperlink(&bug_report_url) } else { - format!( - "clicking here: https://github.com/vercel/next.js/discussions/new?category=turbopack-error-report&title={}&body={}&labels=Turbopack,Turbopack%20Panic%20Backtrace", - &urlencoding::encode(&title), - &urlencoding::encode(&format!("{}\n\nError message:\n```\n{}\n```", &version_str, &title)) - ) + format!("clicking here: {}", bug_report_url) }; eprintln!( @@ -380,6 +375,6 @@ pub fn log_internal_error_and_inform(internal_error: &anyhow::Error) { {}.\n\nTo help make Turbopack better, report this error by {}\n-----\n", "FATAL".red().bold(), PANIC_LOG.to_string_lossy(), - &new_discussion_url + &bug_report_message ); } diff --git a/crates/napi/src/next_api/utils.rs b/crates/napi/src/next_api/utils.rs index 49d9846e80b6..3ff6bb8a62c3 100644 --- a/crates/napi/src/next_api/utils.rs +++ b/crates/napi/src/next_api/utils.rs @@ -17,13 +17,13 @@ use turbo_tasks_fs::FileContent; use turbopack_core::{ diagnostics::{Diagnostic, DiagnosticContextExt, PlainDiagnostic}, issue::{ - CollectibleIssuesExt, IssueSeverity, PlainIssue, PlainIssueSource, PlainSource, - StyledString, + CollectibleIssuesExt, IssueFilter, IssueSeverity, PlainIssue, PlainIssueSource, + PlainSource, StyledString, }, source_pos::SourcePos, }; -use crate::next_api::turbopack_ctx::NextTurbopackContext; +use crate::next_api::{project::NEXT_ISSUE_FILTER, turbopack_ctx::NextTurbopackContext}; /// An [`OperationVc`] that can be passed back and forth to JS across the [`napi`][mod@napi] /// boundary via [`External`]. @@ -61,13 +61,6 @@ impl Deref for DetachedVc { } } -pub fn serde_enum_to_string(value: &T) -> Result { - Ok(serde_json::to_value(value)? - .as_str() - .context("value must serialize to a string")? - .to_string()) -} - /// An opaque handle to the root of a turbo-tasks computation created by /// [`turbo_tasks::TurboTasks::spawn_root_task`] that can be passed back and forth to JS across the /// [`napi`][mod@napi] boundary via [`External`]. @@ -102,8 +95,13 @@ pub fn root_task_dispose( Ok(()) } -pub async fn get_issues(source: OperationVc) -> Result>>> { - Ok(Arc::new(source.peek_issues().get_plain_issues().await?)) +pub async fn get_issues( + source: OperationVc, + filter: IssueFilter, +) -> Result>>> { + Ok(Arc::new( + source.peek_issues().get_plain_issues(filter).await?, + )) } /// Reads the [turbopack_core::diagnostics::Diagnostic] held @@ -369,7 +367,7 @@ pub async fn strongly_consistent_catch_collectables( Arc, )> { let result = source_op.read_strongly_consistent().await; - let issues = get_issues(source_op).await?; + let issues = get_issues(source_op, NEXT_ISSUE_FILTER).await?; let diagnostics = get_diagnostics(source_op).await?; let effects = Arc::new(get_effects(source_op).await?); diff --git a/crates/next-api/src/analyze.rs b/crates/next-api/src/analyze.rs index fd617edb1cfc..1609eeaf91a2 100644 --- a/crates/next-api/src/analyze.rs +++ b/crates/next-api/src/analyze.rs @@ -425,7 +425,7 @@ pub async fn analyze_module_graphs(module_graphs: Vc) -> Result>, ClientMani #[turbo_tasks::function] pub async fn map_client_references( - graph: Vc, + graph: ResolvedVc, ) -> Result> { let graph = graph.await?; let manifest = graph diff --git a/crates/next-api/src/dynamic_imports.rs b/crates/next-api/src/dynamic_imports.rs index de4e53480d4a..dad3bfdc4ad1 100644 --- a/crates/next-api/src/dynamic_imports.rs +++ b/crates/next-api/src/dynamic_imports.rs @@ -30,12 +30,9 @@ use turbo_tasks::{ debug::ValueDebugFormat, trace::TraceRawVcs, }; use turbopack_core::{ - chunk::{ - ChunkableModule, ChunkingContext, ModuleChunkItemIdExt, ModuleId, - availability_info::AvailabilityInfo, - }, + chunk::{ChunkableModule, ChunkingContext, availability_info::AvailabilityInfo}, module::Module, - module_graph::{ModuleGraph, SingleModuleGraph}, + module_graph::{ModuleGraph, ModuleGraphLayer}, output::{OutputAssetsReference, OutputAssetsWithReferenced}, }; @@ -84,12 +81,7 @@ pub(crate) async fn collect_next_dynamic_chunks( chunking_context.async_loader_chunk_item(*module, module_graph, availability_info); let async_chunk_group = async_loader.references().to_resolved().await?; - let module_id = dynamic_entry - .chunk_item_id(chunking_context) - .to_resolved() - .await?; - - Ok((*dynamic_entry, (module_id, async_chunk_group))) + Ok((*dynamic_entry, (*dynamic_entry, async_chunk_group))) }) .try_join() .await?; @@ -105,7 +97,10 @@ pub struct DynamicImportedChunks( #[bincode(with = "turbo_bincode::indexmap")] pub FxIndexMap< ResolvedVc, - (ResolvedVc, ResolvedVc), + ( + ResolvedVc, + ResolvedVc, + ), >, ); @@ -122,7 +117,9 @@ pub struct DynamicImportEntries( ); #[turbo_tasks::function] -pub async fn map_next_dynamic(graph: Vc) -> Result> { +pub async fn map_next_dynamic( + graph: ResolvedVc, +) -> Result> { let actions = graph .await? .iter_nodes() diff --git a/crates/next-api/src/loadable_manifest.rs b/crates/next-api/src/loadable_manifest.rs index 3f5fff4a4a87..9560430414f7 100644 --- a/crates/next-api/src/loadable_manifest.rs +++ b/crates/next-api/src/loadable_manifest.rs @@ -1,9 +1,10 @@ use anyhow::Result; use next_core::{next_manifests::LoadableManifest, util::NextRuntime}; -use turbo_tasks::{FxIndexMap, ResolvedVc, TryFlatJoinIterExt, Vc}; +use turbo_tasks::{FxIndexMap, ResolvedVc, TryFlatJoinIterExt, TryJoinIterExt, Vc}; use turbo_tasks_fs::{File, FileContent, FileSystemPath}; use turbopack_core::{ asset::AssetContent, + chunk::{ChunkingContext, ModuleChunkItemIdExt}, output::{OutputAsset, OutputAssets}, virtual_output::VirtualOutputAsset, }; @@ -14,6 +15,7 @@ use crate::dynamic_imports::DynamicImportedChunks; #[turbo_tasks::function] pub async fn create_react_loadable_manifest( dynamic_import_entries: Vc, + chunking_context: Vc>, client_relative_path: FileSystemPath, output_path: FileSystemPath, runtime: NextRuntime, @@ -22,31 +24,41 @@ pub async fn create_react_loadable_manifest( let mut loadable_manifest: FxIndexMap = FxIndexMap::default(); - for (_, (module_id, chunk_output)) in dynamic_import_entries.into_iter() { - let chunk_output = chunk_output.primary_assets().await?; + let entries = dynamic_import_entries + .iter() + .map(|(_, (dynamic_entry, chunk_output))| { + let client_relative_path = client_relative_path.clone(); + async move { + let module_id = dynamic_entry.chunk_item_id(chunking_context).await?; + let chunk_output = chunk_output.primary_assets().await?; - let id = &*module_id.await?; + let client_relative_path_value = client_relative_path.clone(); + let files = chunk_output + .iter() + .map(move |&file| { + let client_relative_path_value = client_relative_path_value.clone(); + async move { + Ok(client_relative_path_value + .get_path_to(&*file.path().await?) + .map(|path| path.into())) + } + }) + .try_flat_join() + .await?; - let client_relative_path_value = client_relative_path.clone(); - let files = chunk_output - .iter() - .map(move |&file| { - let client_relative_path_value = client_relative_path_value.clone(); - async move { - Ok(client_relative_path_value - .get_path_to(&*file.path().await?) - .map(|path| path.into())) - } - }) - .try_flat_join() - .await?; + Ok((module_id, files)) + } + }) + .try_join() + .await?; + for (module_id, files) in entries { let manifest_item = LoadableManifest { - id: id.into(), + id: (&module_id).into(), files, }; - loadable_manifest.insert(id.to_string(), manifest_item); + loadable_manifest.insert(module_id.to_string(), manifest_item); } let manifest_json = serde_json::to_string_pretty(&loadable_manifest)?; diff --git a/crates/next-api/src/middleware.rs b/crates/next-api/src/middleware.rs index 2b87d3709c3a..168f917daf90 100644 --- a/crates/next-api/src/middleware.rs +++ b/crates/next-api/src/middleware.rs @@ -14,10 +14,7 @@ use turbo_tasks::{Completion, ResolvedVc, Vc}; use turbo_tasks_fs::{self, File, FileContent, FileSystemPath}; use turbopack_core::{ asset::AssetContent, - chunk::{ - ChunkingContext, ChunkingContextExt, EntryChunkGroupResult, - availability_info::AvailabilityInfo, - }, + chunk::{ChunkingContextExt, EntryChunkGroupResult, availability_info::AvailabilityInfo}, context::AssetContext, module::Module, module_graph::{ @@ -138,7 +135,7 @@ impl MiddlewareEndpoint { }; let EntryChunkGroupResult { asset: chunk, .. } = *chunking_context - .entry_chunk_group( + .root_entry_chunk_group( this.project .node_root() .await? @@ -147,7 +144,6 @@ impl MiddlewareEndpoint { module_graph, OutputAssets::empty(), OutputAssets::empty(), - AvailabilityInfo::root(), ) .await?; Ok(*chunk) diff --git a/crates/next-api/src/module_graph.rs b/crates/next-api/src/module_graph.rs index b7124c18a7e2..7e02d7ed29a5 100644 --- a/crates/next-api/src/module_graph.rs +++ b/crates/next-api/src/module_graph.rs @@ -23,19 +23,21 @@ use turbopack_core::{ context::AssetContext, issue::{Issue, IssueExt, IssueSeverity, IssueStage, OptionStyledString, StyledString}, module::Module, - module_graph::{GraphTraversalAction, ModuleGraph, SingleModuleGraphWithBindingUsage}, + module_graph::{GraphTraversalAction, ModuleGraph, ModuleGraphLayer}, }; use turbopack_css::{CssModuleAsset, ModuleCssAsset}; use crate::{ client_references::{ClientManifestEntryType, ClientReferenceData, map_client_references}, dynamic_imports::{DynamicImportEntries, DynamicImportEntriesMapType, map_next_dynamic}, - server_actions::{AllActions, AllModuleActions, map_server_actions, to_rsc_context}, + server_actions::{ + ActionMeta, AllActions, AllModuleActions, map_server_actions, to_rsc_context, + }, }; #[turbo_tasks::value] pub struct NextDynamicGraph { - graph: SingleModuleGraphWithBindingUsage, + graph: ResolvedVc, is_single_page: bool, /// list of NextDynamicEntryModules @@ -52,12 +54,13 @@ impl NextDynamicGraphs { graphs: ResolvedVc, is_single_page: bool, ) -> Result> { - let graphs_ref = &graphs.await?; + let graphs_ref = &graphs.iter_graphs().await?; let next_dynamic = async { graphs_ref - .iter_graphs() + .iter() .map(|graph| { - NextDynamicGraph::new_with_entries(graph, is_single_page).to_resolved() + NextDynamicGraph::new_with_entries(graph.connect(), is_single_page) + .to_resolved() }) .try_join() .await @@ -130,10 +133,10 @@ pub struct DynamicImportEntriesWithImporter( impl NextDynamicGraph { #[turbo_tasks::function] pub async fn new_with_entries( - graph: SingleModuleGraphWithBindingUsage, + graph: ResolvedVc, is_single_page: bool, ) -> Result> { - let mapped = map_next_dynamic(*graph.graph); + let mapped = map_next_dynamic(*graph); Ok(NextDynamicGraph { is_single_page, @@ -151,7 +154,7 @@ impl NextDynamicGraph { let span = tracing::info_span!("collect next/dynamic imports for endpoint"); async move { let data = &*self.data.await?; - let graph = self.graph.read().await?; + let graph = self.graph.await?; #[derive(Clone, PartialEq, Eq)] enum VisitState { @@ -232,7 +235,7 @@ impl NextDynamicGraph { #[turbo_tasks::value] pub struct ServerActionsGraph { - graph: SingleModuleGraphWithBindingUsage, + graph: ResolvedVc, is_single_page: bool, /// (Layer, RSC or Browser module) -> list of actions @@ -249,12 +252,13 @@ impl ServerActionsGraphs { graphs: ResolvedVc, is_single_page: bool, ) -> Result> { - let graphs_ref = &graphs.await?; + let graphs_ref = &graphs.iter_graphs().await?; let server_actions = async { graphs_ref - .iter_graphs() + .iter() .map(|graph| { - ServerActionsGraph::new_with_entries(graph, is_single_page).to_resolved() + ServerActionsGraph::new_with_entries(graph.connect(), is_single_page) + .to_resolved() }) .try_join() .await @@ -316,10 +320,10 @@ impl ServerActionsGraphs { impl ServerActionsGraph { #[turbo_tasks::function] pub async fn new_with_entries( - graph: SingleModuleGraphWithBindingUsage, + graph: ResolvedVc, is_single_page: bool, ) -> Result> { - let mapped = map_server_actions(*graph.graph); + let mapped = map_server_actions(*graph); Ok(ServerActionsGraph { is_single_page, @@ -343,7 +347,7 @@ impl ServerActionsGraph { Cow::Borrowed(data) } else { // The graph contains the whole app, traverse and collect all reachable imports. - let graph = self.graph.read().await?; + let graph = self.graph.await?; if !graph.graphs.first().unwrap().has_entry_module(entry) { // the graph doesn't contain the entry, e.g. for the additional module graph @@ -372,12 +376,15 @@ impl ServerActionsGraph { actions .actions .iter() - .map(async |(hash, name)| { + .map(async |(hash, entry)| { Ok(( hash.to_string(), ( *layer, - name.to_string(), + ActionMeta { + name: entry.name.clone(), + source_path: actions.entry_path.clone(), + }, if *layer == ActionLayer::Rsc { *module } else { @@ -407,7 +414,7 @@ impl ServerActionsGraph { #[turbo_tasks::value] pub struct ClientReferencesGraph { is_single_page: bool, - graph: SingleModuleGraphWithBindingUsage, + graph: ResolvedVc, /// List of client references (modules that entries into the client graph) data: ResolvedVc, @@ -423,12 +430,13 @@ impl ClientReferencesGraphs { graphs: ResolvedVc, is_single_page: bool, ) -> Result> { - let graphs_ref = &graphs.await?; + let graphs_ref = graphs.iter_graphs().await?; let client_references = async { graphs_ref - .iter_graphs() + .iter() .map(|graph| { - ClientReferencesGraph::new_with_entries(graph, is_single_page).to_resolved() + ClientReferencesGraph::new_with_entries(graph.connect(), is_single_page) + .to_resolved() }) .try_join() .await @@ -518,10 +526,10 @@ impl ClientReferencesGraphs { impl ClientReferencesGraph { #[turbo_tasks::function] pub async fn new_with_entries( - graph: SingleModuleGraphWithBindingUsage, + graph: ResolvedVc, is_single_page: bool, ) -> Result> { - let mapped = map_client_references(*graph.graph); + let mapped = map_client_references(*graph); Ok(Self { is_single_page, @@ -539,7 +547,7 @@ impl ClientReferencesGraph { let span = tracing::info_span!("collect client references for endpoint"); async move { let data = &*self.data.await?; - let graph = self.graph.read().await?; + let graph = self.graph.await?; let entries = if !self.is_single_page { if !graph.graphs.first().unwrap().has_entry_module(entry) { @@ -766,12 +774,12 @@ struct ModuleNameMap(#[bincode(with = "turbo_bincode::indexmap")] pub FxModuleNa #[tracing::instrument(level = "info", name = "validate pages css imports", skip_all)] #[turbo_tasks::function] async fn validate_pages_css_imports_individual( - graph: SingleModuleGraphWithBindingUsage, + graph: ResolvedVc, is_single_page: bool, entry: Vc>, app_module: ResolvedVc>, ) -> Result<()> { - let graph = graph.read().await?; + let graph = graph.await?; let entry = entry.to_resolved().await?; let entries = if !is_single_page { @@ -869,12 +877,17 @@ pub async fn validate_pages_css_imports( entry: Vc>, app_module: Vc>, ) -> Result<()> { - let graphs = &graph.await?; + let graphs = graph.iter_graphs().await?; graphs - .iter_graphs() + .iter() .map(|graph| { - validate_pages_css_imports_individual(graph, is_single_page, entry, app_module) - .as_side_effect() + validate_pages_css_imports_individual( + graph.connect(), + is_single_page, + entry, + app_module, + ) + .as_side_effect() }) .try_join() .await?; diff --git a/crates/next-api/src/nft_json.rs b/crates/next-api/src/nft_json.rs index 95eb96cca73e..6e72dbd3a6da 100644 --- a/crates/next-api/src/nft_json.rs +++ b/crates/next-api/src/nft_json.rs @@ -76,30 +76,27 @@ impl OutputAsset for NftJsonAsset { } } -#[turbo_tasks::value(transparent)] -pub struct OutputSpecifier(Option); - fn get_output_specifier( - path_ref: &FileSystemPath, + chunk_path: &FileSystemPath, ident_folder: &FileSystemPath, ident_folder_in_project_fs: &FileSystemPath, output_root: &FileSystemPath, project_root: &FileSystemPath, -) -> Result { +) -> Option { // include assets in the outputs such as referenced chunks - if path_ref.is_inside_ref(output_root) { - return Ok(ident_folder.get_relative_path_to(path_ref).unwrap()); + if chunk_path.is_inside_ref(output_root) { + return Some(ident_folder.get_relative_path_to(chunk_path).unwrap()); } // include assets in the project root such as images and traced references (externals) - if path_ref.is_inside_ref(project_root) { - return Ok(ident_folder_in_project_fs - .get_relative_path_to(path_ref) - .unwrap()); + if chunk_path.is_inside_ref(project_root) { + return Some( + ident_folder_in_project_fs + .get_relative_path_to(chunk_path) + .unwrap(), + ); } - - // This should effectively be unreachable - bail!("NftJsonAsset: cannot handle filepath {path_ref}"); + None } /// Apply outputFileTracingIncludes patterns to find additional files @@ -285,13 +282,21 @@ impl Asset for NftJsonAsset { } } - let specifier = get_output_specifier( + let Some(specifier) = get_output_specifier( &referenced_chunk_path, &ident_folder, &ident_folder_in_project_fs, &output_root_ref, &project_root_ref, - )?; + ) else { + // This should effectively be unreachable + bail!( + "NftJsonAsset: cannot handle filepath '{chunk_path}' for \ + {referenced_chunk:?} it is not under the output_root: \ + '{output_root_ref}' or the project_root: '{project_root_ref}'", + chunk_path = referenced_chunk_path.value_to_string().await? + ); + }; result.insert(specifier); } diff --git a/crates/next-api/src/pages.rs b/crates/next-api/src/pages.rs index 3b057ba0f66d..ecfa167d27a3 100644 --- a/crates/next-api/src/pages.rs +++ b/crates/next-api/src/pages.rs @@ -736,7 +736,7 @@ impl PageEndpoint { should_read_binding_usage, ); graphs.push(graph); - visited_modules = visited_modules.concatenate(graph); + visited_modules = VisitedModules::concatenate(visited_modules, graph); } let graph = SingleModuleGraph::new_with_entries_visited_intern( @@ -747,21 +747,20 @@ impl PageEndpoint { ); graphs.push(graph); - let mut graph = ModuleGraph::from_graphs(graphs); - - if *project + let remove_unused_imports = *project .next_config() .turbopack_remove_unused_imports(next_mode) - .await? - { - graph = graph.without_unused_references( - *compute_binding_usage_info(graph.to_resolved().await?, true) - .resolve_strongly_consistent() - .await?, - ); - } + .await?; - Ok(graph) + let graph = if remove_unused_imports { + let graph = ModuleGraph::from_graphs(graphs.clone()); + let binding_usage_info = compute_binding_usage_info(graph, true); + ModuleGraph::from_graphs_without_unused_references(graphs, binding_usage_info) + } else { + ModuleGraph::from_graphs(graphs) + }; + + Ok(graph.connect()) } else { Ok(*project.whole_app_module_graphs().await?.full) } @@ -1069,11 +1068,15 @@ impl PageEndpoint { .is_production() { let additional_assets = if emit_manifests == EmitManifests::Full { - self.react_loadable_manifest(*dynamic_import_entries, NextRuntime::NodeJs) - .await? - .iter() - .map(|m| **m) - .collect() + self.react_loadable_manifest( + *dynamic_import_entries, + project.client_chunking_context(), + NextRuntime::NodeJs, + ) + .await? + .iter() + .map(|m| **m) + .collect() } else { vec![] }; @@ -1197,6 +1200,7 @@ impl PageEndpoint { async fn react_loadable_manifest( &self, dynamic_import_entries: Vc, + chunking_context: Vc>, runtime: NextRuntime, ) -> Result> { let node_root = self.pages_project.project().node_root().owned().await?; @@ -1209,6 +1213,7 @@ impl PageEndpoint { let loadable_path_prefix = get_asset_prefix_from_pathname(&self.pathname); Ok(create_react_loadable_manifest( dynamic_import_entries, + chunking_context, client_relative_path, node_root.join(&format!( "server/pages{loadable_path_prefix}/react-loadable-manifest", @@ -1389,8 +1394,11 @@ impl PageEndpoint { server_assets.push(pages_manifest); } if emit_manifests == EmitManifests::Full { - let loadable_manifest_output = - self.react_loadable_manifest(*dynamic_import_entries, NextRuntime::NodeJs); + let loadable_manifest_output = self.react_loadable_manifest( + *dynamic_import_entries, + this.pages_project.project().client_chunking_context(), + NextRuntime::NodeJs, + ); server_assets.extend(loadable_manifest_output.await?.iter().copied()); } @@ -1454,7 +1462,11 @@ impl PageEndpoint { if emit_manifests == EmitManifests::Full { let loadable_manifest_output = self - .react_loadable_manifest(*dynamic_import_entries, NextRuntime::Edge) + .react_loadable_manifest( + *dynamic_import_entries, + this.pages_project.project().client_chunking_context(), + NextRuntime::Edge, + ) .await?; if pages_structure.should_create_pages_entries { server_assets.extend(loadable_manifest_output.iter().copied()); diff --git a/crates/next-api/src/project.rs b/crates/next-api/src/project.rs index 103540167314..e3aab7adde92 100644 --- a/crates/next-api/src/project.rs +++ b/crates/next-api/src/project.rs @@ -47,8 +47,8 @@ use turbopack_core::{ PROJECT_FILESYSTEM_NAME, changed::content_changed, chunk::{ - ChunkingContext, EvaluatableAssets, - module_id_strategies::{DevModuleIdStrategy, ModuleIdStrategy}, + ChunkingContext, EvaluatableAssets, UnusedReferences, + chunk_id_strategy::{ModuleIdFallback, ModuleIdStrategy}, }, compile_time_info::CompileTimeInfo, context::AssetContext, @@ -1163,7 +1163,12 @@ impl Project { ) -> Result> { Ok(if *self.per_page_module_graph().await? { let is_production = self.next_mode().await?.is_production(); - ModuleGraph::from_entry_module(*entry, is_production, is_production) + ModuleGraph::from_single_graph(SingleModuleGraph::new_with_entry( + ChunkGroupEntry::Entry(vec![entry]), + is_production, + is_production, + )) + .connect() } else { *self.whole_app_module_graphs().await?.full }) @@ -1182,11 +1187,12 @@ impl Project { .copied() .map(ResolvedVc::upcast) .collect(); - ModuleGraph::from_modules( - Vc::cell(vec![ChunkGroupEntry::Entry(entries)]), + ModuleGraph::from_single_graph(SingleModuleGraph::new_with_entries( + ResolvedVc::cell(vec![ChunkGroupEntry::Entry(entries)]), is_production, is_production, - ) + )) + .connect() } else { *self.whole_app_module_graphs().await?.full }) @@ -2018,15 +2024,17 @@ impl Project { /// Gets the module id strategy for the project. #[turbo_tasks::function] - pub async fn module_ids(self: Vc) -> Result>> { + pub async fn module_ids(self: Vc) -> Result> { let module_id_strategy = *self.next_config().module_ids(self.next_mode()).await?; match module_id_strategy { - ModuleIdStrategyConfig::Named => Ok(Vc::upcast(DevModuleIdStrategy::new())), + ModuleIdStrategyConfig::Named => Ok(ModuleIdStrategy { + module_id_map: None, + fallback: ModuleIdFallback::Ident, + } + .cell()), ModuleIdStrategyConfig::Deterministic => { let module_graphs = self.whole_app_module_graphs().await?; - Ok(Vc::upcast(get_global_module_id_strategy( - *module_graphs.full, - ))) + Ok(get_global_module_id_strategy(*module_graphs.full)) } } } @@ -2034,19 +2042,11 @@ impl Project { /// Compute the used exports and unused imports for each module. #[turbo_tasks::function] async fn binding_usage_info(self: Vc) -> Result> { - let remove_unused_imports = *self - .next_config() - .turbopack_remove_unused_imports(self.next_mode()) - .await?; - let module_graphs = self.whole_app_module_graphs().await?; - Ok(*compute_binding_usage_info( - module_graphs.full_with_unused_references, - remove_unused_imports, - ) - // As a performance optimization, we resolve strongly consistently - .resolve_strongly_consistent() - .await?) + Ok(module_graphs + .binding_usage_info + .context("No binding usage info")? + .connect()) } /// Compute the used exports for each module. @@ -2067,17 +2067,15 @@ impl Project { /// Compute the unused references that were removed (inner graph tree shaking). #[turbo_tasks::function] - pub async fn unused_references(self: Vc) -> Result> { + pub async fn unused_references(self: Vc) -> Result> { if *self .next_config() .turbopack_remove_unused_imports(self.next_mode()) .await? { - Ok(Vc::cell(Some( - self.binding_usage_info().to_resolved().await?, - ))) + Ok(self.binding_usage_info().unused_references()) } else { - Ok(Vc::cell(None)) + Ok(Vc::cell(Default::default())) } } @@ -2104,7 +2102,7 @@ async fn whole_app_module_graph_operation( let should_trace = next_mode_ref.is_production(); let should_read_binding_usage = next_mode_ref.is_production(); let base_single_module_graph = SingleModuleGraph::new_with_entries( - project.get_all_entries(), + project.get_all_entries().to_resolved().await?, should_trace, should_read_binding_usage, ); @@ -2120,16 +2118,19 @@ async fn whole_app_module_graph_operation( let base = if turbopack_remove_unused_imports { // TODO suboptimal that we do compute_binding_usage_info twice (once for the base graph // and later for the full graph) - base.without_unused_references( - *compute_binding_usage_info(base.to_resolved().await?, true) - .resolve_strongly_consistent() - .await?, + let binding_usage_info = compute_binding_usage_info(base, true); + ModuleGraph::from_single_graph_without_unused_references( + base_single_module_graph, + binding_usage_info, ) } else { base }; - let additional_entries = project.get_all_additional_entries(base); + let additional_entries = project + .get_all_additional_entries(base.connect()) + .to_resolved() + .await?; let additional_module_graph = SingleModuleGraph::new_with_entries_visited( additional_entries, @@ -2138,28 +2139,23 @@ async fn whole_app_module_graph_operation( should_read_binding_usage, ); - let full_with_unused_references = - ModuleGraph::from_graphs(vec![base_single_module_graph, additional_module_graph]) - .to_resolved() - .await?; + let graphs = vec![base_single_module_graph, additional_module_graph]; - let full = if turbopack_remove_unused_imports { - full_with_unused_references - .without_unused_references( - *compute_binding_usage_info(full_with_unused_references, true) - .resolve_strongly_consistent() - .await?, - ) - .to_resolved() - .await? + let (full, binding_usage_info) = if turbopack_remove_unused_imports { + let full_with_unused_references = ModuleGraph::from_graphs(graphs.clone()); + let binding_usage_info = compute_binding_usage_info(full_with_unused_references, true); + ( + ModuleGraph::from_graphs_without_unused_references(graphs, binding_usage_info), + Some(binding_usage_info), + ) } else { - full_with_unused_references + (ModuleGraph::from_graphs(graphs), None) }; Ok(BaseAndFullModuleGraph { - base: base.to_resolved().await?, - full_with_unused_references, - full, + base: base.connect().to_resolved().await?, + full: full.connect().to_resolved().await?, + binding_usage_info, } .cell()) } @@ -2168,11 +2164,10 @@ async fn whole_app_module_graph_operation( pub struct BaseAndFullModuleGraph { /// The base module graph generated from the entry points. pub base: ResolvedVc, - /// The base graph plus any modules that were generated from additional entries (for which the - /// base graph is needed). - pub full_with_unused_references: ResolvedVc, /// `full_with_unused_references` but with unused references removed. pub full: ResolvedVc, + /// Information about binding usage in the module graph. + pub binding_usage_info: Option>, } #[turbo_tasks::function] @@ -2223,8 +2218,3 @@ fn all_assets_from_entries_operation( let assets = operation.connect(); Ok(all_assets_from_entries(assets)) } - -#[turbo_tasks::function] -fn stable_endpoint(endpoint: Vc>) -> Vc> { - endpoint -} diff --git a/crates/next-api/src/routes_hashes_manifest.rs b/crates/next-api/src/routes_hashes_manifest.rs index 87597db9a742..95f28f7b01b5 100644 --- a/crates/next-api/src/routes_hashes_manifest.rs +++ b/crates/next-api/src/routes_hashes_manifest.rs @@ -62,7 +62,7 @@ pub async fn endpoint_hashes( let mut all_modules = FxIndexSet::default(); - let module_graph = module_graph.read_graphs().await?; + let module_graph = module_graph.await?; module_graph.traverse_nodes_dfs( modules, diff --git a/crates/next-api/src/server_actions.rs b/crates/next-api/src/server_actions.rs index 189c8a2fd05c..60a9e50f84ed 100644 --- a/crates/next-api/src/server_actions.rs +++ b/crates/next-api/src/server_actions.rs @@ -1,6 +1,7 @@ use std::{collections::BTreeMap, io::Write}; use anyhow::{Context, Result, bail}; +use bincode::{Decode, Encode}; use next_core::{ next_manifests::{ ActionLayer, ActionManifestModuleId, ActionManifestWorkerEntry, ServerReferenceManifest, @@ -19,7 +20,9 @@ use swc_core::{ }, }; use turbo_rcstr::{RcStr, rcstr}; -use turbo_tasks::{FxIndexMap, ResolvedVc, TryFlatJoinIterExt, Vc}; +use turbo_tasks::{ + FxIndexMap, NonLocalValue, ResolvedVc, TryFlatJoinIterExt, Vc, trace::TraceRawVcs, +}; use turbo_tasks_fs::{self, File, FileContent, FileSystemPath, rope::RopeBuilder}; use turbopack_core::{ asset::AssetContent, @@ -30,7 +33,7 @@ use turbopack_core::{ file_source::FileSource, ident::AssetIdent, module::Module, - module_graph::{ModuleGraph, SingleModuleGraph, async_module_info::AsyncModulesInfo}, + module_graph::{ModuleGraph, ModuleGraphLayer, async_module_info::AsyncModulesInfo}, output::OutputAsset, reference_type::{EcmaScriptModulesReferenceSubType, ReferenceType}, resolve::ModulePart, @@ -42,6 +45,9 @@ use turbopack_ecmascript::{ tree_shake::asset::EcmascriptModulePartAsset, }; +/// Metadata for a server action: (layer, exported_name, filename) +type ActionMetadata = (ActionLayer, String, String); + #[turbo_tasks::value] pub(crate) struct ServerActionsManifest { pub loader: ResolvedVc>, @@ -112,11 +118,12 @@ pub(crate) async fn build_server_actions_loader( // hashed ID as export name. let mut contents = RopeBuilder::from(""); let mut import_map = FxIndexMap::default(); - for (hash_id, (_layer, name, module)) in actions.iter() { + for (hash_id, (_layer, meta, module)) in actions.iter() { let index = import_map.len(); let module_name = import_map .entry(*module) .or_insert_with(|| format!("ACTIONS_MODULE{index}").into()); + let name = &meta.name; writeln!( contents, "export {{{name} as '{hash_id}'}} from '{module_name}'" @@ -168,7 +175,7 @@ async fn build_manifest( let actions_value = actions.await?; let loader_id = chunk_item.id().await?; - let loader_id = match &*loader_id { + let loader_id = match &loader_id { ModuleId::Number(id) => ActionManifestModuleId::Number(*id), ModuleId::String(id) => ActionManifestModuleId::String(id), }; @@ -177,14 +184,19 @@ async fn build_manifest( NextRuntime::NodeJs => &mut manifest.node, }; - // Collect all the action metadata including filenames - let mut action_metadata: Vec<(String, (ActionLayer, String, String))> = Vec::new(); - for (hash_id, (layer, name, module)) in actions_value.iter() { - // Get the module path and use the full path - let module_path = module.ident().path().await?; - let full_path = module_path.to_string(); + // Collect all the action metadata including filenames and location + let mut action_metadata: Vec<(String, ActionMetadata)> = Vec::new(); + for (hash_id, (layer, meta, module)) in actions_value.iter() { + // Use source_path from the action comment if available (contains original .ts/.tsx path), + // otherwise fall back to module.ident().path() (may be compiled .js path) + let filename = if !meta.source_path.is_empty() { + meta.source_path.clone() + } else { + let module_path = module.ident().path().await?; + module_path.to_string() + }; - action_metadata.push((hash_id.clone(), (*layer, name.clone(), full_path))); + action_metadata.push((hash_id.clone(), (*layer, meta.name.clone(), filename))); } // Now create the manifest entries @@ -250,6 +262,31 @@ pub async fn to_rsc_context( Ok(module) } +/// Server action info for JSON parsing +#[derive(Clone, Debug, serde::Deserialize)] +#[serde(untagged)] +enum ServerActionInfoRaw { + /// Old format: just the export name as a string + Name(String), + /// New format: object with name + WithName { name: String }, +} + +impl ServerActionInfoRaw { + fn into_action_entry(self) -> ActionEntry { + match self { + ServerActionInfoRaw::Name(name) => ActionEntry { name }, + ServerActionInfoRaw::WithName { name } => ActionEntry { name }, + } + } +} + +/// Simplified action entry for storage in turbo_tasks values +#[derive(Clone, Debug, PartialEq, Eq, TraceRawVcs, NonLocalValue, Encode, Decode)] +pub struct ActionEntry { + pub name: String, +} + /// Parses the Server Actions comment for all exported action function names. /// /// Action names are stored in a leading BlockComment prefixed by @@ -257,7 +294,7 @@ pub async fn to_rsc_context( pub fn parse_server_actions( program: &Program, comments: &dyn Comments, -) -> Option<(BTreeMap, String, String)> { +) -> Option<(BTreeMap, String, String)> { let byte_pos = match program { Program::Module(m) => m.span.lo, Program::Script(s) => s.span.lo, @@ -266,7 +303,29 @@ pub fn parse_server_actions( comments.iter().find_map(|c| { c.text .split_once("__next_internal_action_entry_do_not_use__") - .and_then(|(_, actions)| serde_json::from_str(actions).ok()) + .and_then(|(_, actions)| { + // Try to parse as tuple format: (actions_map, entry_path, entry_query) + if let Ok((raw, entry_path, entry_query)) = serde_json::from_str::<( + BTreeMap, + String, + String, + )>(actions) + { + let converted: BTreeMap = raw + .into_iter() + .map(|(k, v)| (k, v.into_action_entry())) + .collect(); + return Some((converted, entry_path, entry_query)); + } + // Fall back to just actions map (old format without entry path/query) + let raw: BTreeMap = + serde_json::from_str(actions).ok()?; + let converted: BTreeMap = raw + .into_iter() + .map(|(k, v)| (k, v.into_action_entry())) + .collect(); + Some((converted, String::new(), String::new())) + }) }) }) } @@ -318,7 +377,7 @@ async fn parse_actions(module: ResolvedVc>) -> Result>) -> bool { .unwrap_or(false) } -type HashToLayerNameModule = Vec<(String, (ActionLayer, String, ResolvedVc>))>; +/// Action metadata including name and source path +#[derive(Clone, Debug, PartialEq, Eq, TraceRawVcs, NonLocalValue, Encode, Decode)] +pub struct ActionMeta { + pub name: String, + /// The original source file path (from entry_path in the action comment) + pub source_path: String, +} + +type HashToLayerNameModule = Vec<( + String, + (ActionLayer, ActionMeta, ResolvedVc>), +)>; /// A mapping of every module which exports a Server Action, with the hashed id /// and exported name of each found action. @@ -430,12 +500,12 @@ impl AllActions { } } -/// Maps the hashed action id to the action's exported function name. +/// Maps the hashed action id to the action's exported function name and location. #[turbo_tasks::value] #[derive(Debug)] pub struct ActionMap { #[bincode(with = "turbo_bincode::indexmap")] - pub actions: FxIndexMap, + pub actions: FxIndexMap, pub entry_path: String, pub entry_query: String, } @@ -453,7 +523,9 @@ pub struct AllModuleActions( ); #[turbo_tasks::function] -pub async fn map_server_actions(graph: Vc) -> Result> { +pub async fn map_server_actions( + graph: ResolvedVc, +) -> Result> { let actions = graph .await? .iter_nodes() diff --git a/crates/next-api/src/webpack_stats.rs b/crates/next-api/src/webpack_stats.rs index bed5c32e4ad9..b6dfbeca0f90 100644 --- a/crates/next-api/src/webpack_stats.rs +++ b/crates/next-api/src/webpack_stats.rs @@ -56,7 +56,7 @@ where }; let asset_reasons = { - let module_graph = module_graph.read_graphs().await?; + let module_graph = module_graph.await?; let mut edges = vec![]; module_graph.traverse_edges_unordered(|parent, current| { if let Some((parent_node, r)) = parent { @@ -155,7 +155,7 @@ where .await?; Ok(WebpackStatsModule { name: chunk_item.asset_ident().path().await?.path.clone(), - id: chunk_item.id().owned().await?, + id: chunk_item.id().await?, identifier: chunk_item.asset_ident().to_string().owned().await?, chunks: chunks.into_iter().collect(), size, diff --git a/crates/next-core/src/app_page_loader_tree.rs b/crates/next-core/src/app_page_loader_tree.rs index 0a58e9f0da32..8d608d32c073 100644 --- a/crates/next-core/src/app_page_loader_tree.rs +++ b/crates/next-core/src/app_page_loader_tree.rs @@ -184,9 +184,12 @@ impl AppPageLoaderTreeBuilder { let identifier = magic_identifier::mangle(&format!("{name} #{i}")); let inner_module_id = format!("METADATA_{i}"); + // This should use the same importing mechanism as create_module_tuple_code, so that + // the relative order of items is retained (which isn't the case + // when mixing ESM imports and requires). self.base .imports - .push(format!("import {identifier} from \"{inner_module_id}\";").into()); + .push(format!("const {identifier} = require(\"{inner_module_id}\");").into()); let source = dynamic_image_metadata_source( *ResolvedVc::upcast(self.base.module_asset_context), @@ -201,7 +204,7 @@ impl AppPageLoaderTreeBuilder { .insert(inner_module_id.into(), module); let s = " "; - writeln!(self.loader_tree_code, "{s}{identifier},")?; + writeln!(self.loader_tree_code, "{s}{identifier}.default,")?; } } Ok(()) @@ -228,9 +231,12 @@ impl AppPageLoaderTreeBuilder { self.base.imports.push(helper_import); } + // This should use the same importing mechanism as create_module_tuple_code, so that the + // relative order of items is retained (which isn't the case when mixing ESM imports and + // requires). self.base .imports - .push(format!("import {identifier} from \"{inner_module_id}\";").into()); + .push(format!("const {identifier} = require(\"{inner_module_id}\");").into()); let module = StructuredImageModuleType::create_module( Vc::upcast(FileSource::new(path.clone())), BlurPlaceholderMode::None, @@ -252,15 +258,21 @@ impl AppPageLoaderTreeBuilder { writeln!( self.loader_tree_code, "{s} url: fillMetadataSegment({}, await props.params, {}, true) + \ - `?${{{identifier}.src.split(\"/\").splice(-1)[0]}}`,", + `?${{{identifier}.default.src.split(\"/\").splice(-1)[0]}}`,", StringifyJs(&pathname_prefix), StringifyJs(metadata_route), )?; let numeric_sizes = name == "twitter" || name == "openGraph"; if numeric_sizes { - writeln!(self.loader_tree_code, "{s} width: {identifier}.width,")?; - writeln!(self.loader_tree_code, "{s} height: {identifier}.height,")?; + writeln!( + self.loader_tree_code, + "{s} width: {identifier}.default.width," + )?; + writeln!( + self.loader_tree_code, + "{s} height: {identifier}.default.height," + )?; } else { // For SVGs, skip sizes and use "any" to let it scale automatically based on viewport, // For the images doesn't provide the size properly, use "any" as well. @@ -268,7 +280,7 @@ impl AppPageLoaderTreeBuilder { let sizes = if path.has_extension(".svg") { "any".to_string() } else { - format!("${{{identifier}.width}}x${{{identifier}.height}}") + format!("${{{identifier}.default.width}}x${{{identifier}.default.height}}") }; writeln!(self.loader_tree_code, "{s} sizes: `{sizes}`,")?; } @@ -280,9 +292,12 @@ impl AppPageLoaderTreeBuilder { let identifier = magic_identifier::mangle(&format!("{name} alt text #{i}")); let inner_module_id = format!("METADATA_ALT_{i}"); + // This should use the same importing mechanism as create_module_tuple_code, so that the + // relative order of items is retained (which isn't the case when mixing ESM imports and + // requires). self.base .imports - .push(format!("import {identifier} from \"{inner_module_id}\";").into()); + .push(format!("const {identifier} = require(\"{inner_module_id}\");").into()); let module = self .base @@ -296,7 +311,7 @@ impl AppPageLoaderTreeBuilder { .inner_assets .insert(inner_module_id.into(), module); - writeln!(self.loader_tree_code, "{s} alt: {identifier},")?; + writeln!(self.loader_tree_code, "{s} alt: {identifier}.default,")?; } writeln!(self.loader_tree_code, "{s}}}]),")?; diff --git a/crates/next-core/src/bootstrap.rs b/crates/next-core/src/bootstrap.rs index b5f04dae8db0..1569f55a317e 100644 --- a/crates/next-core/src/bootstrap.rs +++ b/crates/next-core/src/bootstrap.rs @@ -13,24 +13,6 @@ use turbopack_core::{ }; use turbopack_ecmascript::utils::StringifyJs; -#[turbo_tasks::function] -pub fn route_bootstrap( - asset: Vc>, - asset_context: Vc>, - base_path: FileSystemPath, - bootstrap_asset: Vc>, - config: Vc, -) -> Vc> { - bootstrap( - asset, - asset_context, - base_path, - bootstrap_asset, - Vc::cell(FxIndexMap::default()), - config, - ) -} - #[turbo_tasks::value(transparent)] pub struct BootstrapConfig(#[bincode(with = "turbo_bincode::indexmap")] FxIndexMap); diff --git a/crates/next-core/src/embed_js.rs b/crates/next-core/src/embed_js.rs index 2ea821a6d1c6..26b1e08a64f1 100644 --- a/crates/next-core/src/embed_js.rs +++ b/crates/next-core/src/embed_js.rs @@ -2,7 +2,6 @@ use anyhow::Result; use turbo_rcstr::RcStr; use turbo_tasks::Vc; use turbo_tasks_fs::{FileContent, FileSystem, FileSystemPath}; -use turbopack_core::{file_source::FileSource, source::Source}; pub const VIRTUAL_PACKAGE_NAME: &str = "@vercel/turbopack-next"; @@ -21,10 +20,3 @@ pub(crate) async fn next_js_file(path: RcStr) -> Result> { pub(crate) async fn next_js_file_path(path: RcStr) -> Result> { Ok(next_js_fs().root().await?.join(&path)?.cell()) } - -#[turbo_tasks::function] -pub(crate) async fn next_asset(path: RcStr) -> Result>> { - Ok(Vc::upcast(FileSource::new( - next_js_file_path(path).owned().await?, - ))) -} diff --git a/crates/next-core/src/hmr_entry.rs b/crates/next-core/src/hmr_entry.rs index abbed4209dab..0f6e3e9512be 100644 --- a/crates/next-core/src/hmr_entry.rs +++ b/crates/next-core/src/hmr_entry.rs @@ -193,7 +193,12 @@ impl EcmascriptChunkItem for HmrEntryChunkItem { let this = self.module.await?; let module = this.module; let chunk_item = module.as_chunk_item(*self.module_graph, *self.chunking_context); - let id = self.chunking_context.chunk_item_id(chunk_item).await?; + let id = self + .chunking_context + .chunk_item_id_strategy() + .await? + .get_id(chunk_item) + .await?; let mut code = RopeBuilder::default(); writeln!(code, "{TURBOPACK_REQUIRE}({});", StringifyJs(&id))?; diff --git a/crates/next-core/src/next_app/metadata/mod.rs b/crates/next-core/src/next_app/metadata/mod.rs index 6274a7d9d5aa..140daaaf7970 100644 --- a/crates/next-core/src/next_app/metadata/mod.rs +++ b/crates/next-core/src/next_app/metadata/mod.rs @@ -226,10 +226,6 @@ pub fn is_metadata_route_file( false } -pub fn is_static_metadata_route_file(app_dir_relative_path: &str) -> bool { - is_metadata_route_file(app_dir_relative_path, &[], true) -} - /// Remove the 'app' prefix or '/route' suffix, only check the route name since /// they're only allowed in root app directory /// diff --git a/crates/next-core/src/next_build.rs b/crates/next-core/src/next_build.rs index 2bbe822463cd..a51ffbe8035d 100644 --- a/crates/next-core/src/next_build.rs +++ b/crates/next-core/src/next_build.rs @@ -1,8 +1,8 @@ use anyhow::Result; -use turbo_rcstr::{RcStr, rcstr}; +use turbo_rcstr::rcstr; use turbo_tasks::Vc; use turbo_tasks_fs::FileSystemPath; -use turbopack_core::resolve::{ExternalTraced, ExternalType, options::ImportMapping}; +use turbopack_core::resolve::options::ImportMapping; use crate::next_import_map::get_next_package; @@ -22,18 +22,3 @@ pub async fn get_postcss_package_mapping( ]) .cell()) } - -#[turbo_tasks::function] -pub async fn get_external_next_compiled_package_mapping( - package_name: Vc, -) -> Result> { - Ok(ImportMapping::Alternatives(vec![ - ImportMapping::External( - Some(format!("next/dist/compiled/{}", &*package_name.await?).into()), - ExternalType::CommonJs, - ExternalTraced::Traced, - ) - .resolved_cell(), - ]) - .cell()) -} diff --git a/crates/next-core/src/next_client/context.rs b/crates/next-core/src/next_client/context.rs index 2374540ff37b..b4b13eb57f90 100644 --- a/crates/next-core/src/next_client/context.rs +++ b/crates/next-core/src/next_client/context.rs @@ -17,7 +17,7 @@ use turbopack_browser::{ use turbopack_core::{ chunk::{ ChunkingConfig, ChunkingContext, MangleType, MinifyType, SourceMapSourceType, - SourceMapsType, module_id_strategies::ModuleIdStrategy, + SourceMapsType, UnusedReferences, chunk_id_strategy::ModuleIdStrategy, }, compile_time_info::{CompileTimeDefines, CompileTimeInfo, FreeVarReference, FreeVarReferences}, environment::{BrowserEnvironment, Environment, ExecutionEnvironment}, @@ -31,7 +31,7 @@ use turbopack_node::{ execution_context::ExecutionContext, transforms::postcss::{PostCssConfigLocation, PostCssTransformOptions}, }; -use turbopack_resolve::resolve_options_context::ResolveOptionsContext; +use turbopack_resolve::resolve_options_context::{ResolveOptionsContext, TsConfigHandling}; use crate::{ mode::NextMode, @@ -190,22 +190,21 @@ pub async fn get_client_resolve_options_context( ..Default::default() }; - let tsconfig_path = next_config - .typescript_tsconfig_path() - .await? - .as_ref() - // Fall back to tsconfig only for resolving. This is because we don't want Turbopack to - // resolve tsconfig.json relative to the file being compiled. - .or(Some(&RcStr::from("tsconfig.json"))) - .map(|p| project_path.join(p)) - .transpose()?; + let tsconfig_path = next_config.typescript_tsconfig_path().await?; + let tsconfig_path = project_path.join( + tsconfig_path + .as_ref() + // Fall back to tsconfig only for resolving. This is because we don't want Turbopack to + // resolve tsconfig.json relative to the file being compiled. + .unwrap_or(&rcstr!("tsconfig.json")), + )?; Ok(ResolveOptionsContext { enable_typescript: true, enable_react: true, enable_mjs_extension: true, custom_extensions: next_config.resolve_extension().owned().await?, - tsconfig_path, + tsconfig_path: TsConfigHandling::Fixed(tsconfig_path), rules: vec![( foreign_code_context_condition(next_config, project_path).await?, resolve_options_context.clone().resolved_cell(), @@ -421,9 +420,9 @@ pub struct ClientChunkingContextOptions { pub client_root_to_root_path: RcStr, pub asset_prefix: Vc, pub environment: Vc, - pub module_id_strategy: Vc>, + pub module_id_strategy: Vc, pub export_usage: Vc, - pub unused_references: Vc, + pub unused_references: Vc, pub minify: Vc, pub source_maps: Vc, pub no_mangling: Vc, @@ -481,7 +480,7 @@ pub async fn get_client_chunking_context( .asset_base_path(Some(asset_prefix)) .current_chunk_method(CurrentChunkMethod::DocumentCurrentScript) .export_usage(*export_usage.await?) - .unused_references(*unused_references.await?) + .unused_references(unused_references.to_resolved().await?) .module_id_strategy(module_id_strategy.to_resolved().await?) .debug_ids(*debug_ids.await?) .should_use_absolute_url_references(*should_use_absolute_url_references.await?) diff --git a/crates/next-core/src/next_config.rs b/crates/next-core/src/next_config.rs index e7ca235b642b..900b58e72b15 100644 --- a/crates/next-core/src/next_config.rs +++ b/crates/next-core/src/next_config.rs @@ -10,11 +10,11 @@ use turbo_tasks::{ FxIndexMap, NonLocalValue, OperationValue, ResolvedVc, TaskInput, Vc, debug::ValueDebugFormat, trace::TraceRawVcs, }; -use turbo_tasks_env::{EnvMap, ProcessEnv}; +use turbo_tasks_env::EnvMap; use turbo_tasks_fetch::FetchClientConfig; use turbo_tasks_fs::FileSystemPath; use turbopack::module_options::{ - ConditionItem, ConditionPath, LoaderRuleItem, WebpackRules, + ConditionItem, ConditionPath, ConditionQuery, LoaderRuleItem, WebpackRules, module_options_context::MdxTransformOptions, }; use turbopack_core::{ @@ -673,6 +673,42 @@ impl TryFrom for EsRegex { } } +#[derive( + Clone, + PartialEq, + Eq, + Debug, + Deserialize, + TraceRawVcs, + NonLocalValue, + OperationValue, + Encode, + Decode, +)] +#[serde( + tag = "type", + content = "value", + rename_all = "camelCase", + deny_unknown_fields +)] +pub enum ConfigConditionQuery { + Constant(RcStr), + Regex(RegexComponents), +} + +impl TryFrom for ConditionQuery { + type Error = anyhow::Error; + + fn try_from(config: ConfigConditionQuery) -> Result { + Ok(match config { + ConfigConditionQuery::Constant(value) => ConditionQuery::Constant(value), + ConfigConditionQuery::Regex(regex) => { + ConditionQuery::Regex(EsRegex::try_from(regex)?.resolved_cell()) + } + }) + } +} + #[derive( Deserialize, Clone, @@ -703,6 +739,8 @@ pub enum ConfigConditionItem { path: Option, #[serde(default)] content: Option, + #[serde(default)] + query: Option, }, } @@ -723,12 +761,17 @@ impl TryFrom for ConditionItem { ConfigConditionItem::Builtin(cond) => { ConditionItem::Builtin(RcStr::from(cond.as_str())) } - ConfigConditionItem::Base { path, content } => ConditionItem::Base { + ConfigConditionItem::Base { + path, + content, + query, + } => ConditionItem::Base { path: path.map(ConditionPath::try_from).transpose()?, content: content .map(EsRegex::try_from) .transpose()? .map(EsRegex::resolved_cell), + query: query.map(ConditionQuery::try_from).transpose()?, }, }) } @@ -989,7 +1032,6 @@ pub struct ExperimentalConfig { turbopack_client_side_nested_async_chunking: Option, turbopack_server_side_nested_async_chunking: Option, turbopack_import_type_bytes: Option, - turbopack_use_system_tls_certs: Option, /// Disable automatic configuration of the sass loader. #[serde(default)] turbopack_use_builtin_sass: Option, @@ -1651,21 +1693,11 @@ impl NextConfig { Vc::cell(self.experimental.swc_plugins.clone().unwrap_or_default()) } - #[turbo_tasks::function] - pub fn experimental_sri(&self) -> Vc { - Vc::cell(self.experimental.sri.clone()) - } - - #[turbo_tasks::function] - pub fn experimental_server_actions(&self) -> Vc { - Vc::cell(match self.experimental.server_actions.as_ref() { - Some(ServerActionsOrLegacyBool::ServerActionsConfig(server_actions)) => { - Some(server_actions.clone()) - } - Some(ServerActionsOrLegacyBool::LegacyBool(true)) => Some(ServerActions::default()), - _ => None, - }) - } + // TODO not implemented yet + // #[turbo_tasks::function] + // pub fn experimental_sri(&self) -> Vc { + // Vc::cell(self.experimental.sri.clone()) + // } #[turbo_tasks::function] pub fn experimental_turbopack_use_builtin_babel(&self) -> Vc> { @@ -2008,28 +2040,8 @@ impl NextConfig { } #[turbo_tasks::function] - pub async fn fetch_client( - &self, - env: Vc>, - ) -> Result> { - // Support both an env var and the experimental flag to provide more flexibility to - // developers on locked down systems, depending on if they want to configure this on a - // per-system or per-project basis. - let use_system_tls_certs = env - .read(rcstr!("NEXT_TURBOPACK_EXPERIMENTAL_USE_SYSTEM_TLS_CERTS")) - .await? - .as_ref() - .and_then(|env_value| { - // treat empty value same as an unset value - (!env_value.is_empty()).then(|| env_value == "1" || env_value == "true") - }) - .or(self.experimental.turbopack_use_system_tls_certs) - .unwrap_or(false); - Ok(FetchClientConfig { - tls_built_in_webpki_certs: !use_system_tls_certs, - tls_built_in_native_certs: use_system_tls_certs, - } - .cell()) + pub fn fetch_client(&self) -> Vc { + FetchClientConfig::default().cell() } } @@ -2111,6 +2123,7 @@ mod tests { source: rcstr!("@someTag"), flags: rcstr!(""), }), + query: None, }, ] .into(), diff --git a/crates/next-core/src/next_edge/context.rs b/crates/next-core/src/next_edge/context.rs index 4f2fe709003e..a934773fe07e 100644 --- a/crates/next-core/src/next_edge/context.rs +++ b/crates/next-core/src/next_edge/context.rs @@ -6,8 +6,8 @@ use turbo_tasks_fs::FileSystemPath; use turbopack_browser::BrowserChunkingContext; use turbopack_core::{ chunk::{ - ChunkingConfig, ChunkingContext, MangleType, MinifyType, SourceMapsType, - module_id_strategies::ModuleIdStrategy, + ChunkingConfig, ChunkingContext, MangleType, MinifyType, SourceMapsType, UnusedReferences, + chunk_id_strategy::ModuleIdStrategy, }, compile_time_info::{CompileTimeDefines, CompileTimeInfo, FreeVarReference, FreeVarReferences}, environment::{EdgeWorkerEnvironment, Environment, ExecutionEnvironment, NodeJsVersion}, @@ -17,7 +17,7 @@ use turbopack_core::{ use turbopack_css::chunk::CssChunkType; use turbopack_ecmascript::chunk::EcmascriptChunkType; use turbopack_node::execution_context::ExecutionContext; -use turbopack_resolve::resolve_options_context::ResolveOptionsContext; +use turbopack_resolve::resolve_options_context::{ResolveOptionsContext, TsConfigHandling}; use crate::{ app_structure::CollectedRootParams, @@ -172,21 +172,22 @@ pub async fn get_edge_resolve_options_context( ..Default::default() }; + let tsconfig_path = next_config.typescript_tsconfig_path().await?; + let tsconfig_path = project_path.join( + tsconfig_path + .as_ref() + // Fall back to tsconfig only for resolving. This is because we don't want Turbopack to + // resolve tsconfig.json relative to the file being compiled. + .unwrap_or(&rcstr!("tsconfig.json")), + )?; + Ok(ResolveOptionsContext { enable_typescript: true, enable_react: true, enable_mjs_extension: true, enable_edge_node_externals: true, custom_extensions: next_config.resolve_extension().owned().await?, - tsconfig_path: next_config - .typescript_tsconfig_path() - .await? - .as_ref() - // Fall back to tsconfig only for resolving. This is because we don't want Turbopack to - // resolve tsconfig.json relative to the file being compiled. - .or(Some(&RcStr::from("tsconfig.json"))) - .map(|p| project_path.join(p)) - .transpose()?, + tsconfig_path: TsConfigHandling::Fixed(tsconfig_path), rules: vec![( foreign_code_context_condition(next_config, project_path).await?, resolve_options_context.clone().resolved_cell(), @@ -203,9 +204,9 @@ pub struct EdgeChunkingContextOptions { pub node_root: FileSystemPath, pub output_root_to_root_path: Vc, pub environment: Vc, - pub module_id_strategy: Vc>, + pub module_id_strategy: Vc, pub export_usage: Vc, - pub unused_references: Vc, + pub unused_references: Vc, pub turbo_minify: Vc, pub turbo_source_maps: Vc, pub no_mangling: Vc, @@ -261,7 +262,7 @@ pub async fn get_edge_chunking_context_with_client_assets( .source_maps(*turbo_source_maps.await?) .module_id_strategy(module_id_strategy.to_resolved().await?) .export_usage(*export_usage.await?) - .unused_references(*unused_references.await?) + .unused_references(unused_references.to_resolved().await?) .nested_async_availability(*nested_async_chunking.await?); if !next_mode.is_development() { @@ -338,7 +339,7 @@ pub async fn get_edge_chunking_context( .source_maps(*turbo_source_maps.await?) .module_id_strategy(module_id_strategy.to_resolved().await?) .export_usage(*export_usage.await?) - .unused_references(*unused_references.await?) + .unused_references(unused_references.to_resolved().await?) .nested_async_availability(*nested_async_chunking.await?); if !next_mode.is_development() { diff --git a/crates/next-core/src/next_edge/route_regex.rs b/crates/next-core/src/next_edge/route_regex.rs index 0e847f3409bb..9e28105ed7bc 100644 --- a/crates/next-core/src/next_edge/route_regex.rs +++ b/crates/next-core/src/next_edge/route_regex.rs @@ -248,23 +248,6 @@ fn get_named_parametrized_route( (parameterized_route, route_keys) } -/// This function extends `getRouteRegex` generating also a named regexp where -/// each group is named along with a routeKeys object that indexes the assigned -/// named group with its corresponding key. -/// -/// When the routeKeys need to be prefixed to uniquely identify internally the -/// "prefixRouteKey" arg should be "true" currently this is only the case when -/// creating the routes-manifest during the build -pub fn get_named_route_regex(normalized_route: &str) -> NamedRouteRegex { - let (parameterized_route, route_keys) = get_named_parametrized_route(normalized_route, false); - let regex = get_route_regex(normalized_route); - NamedRouteRegex { - regex, - named_regex: format!("^{parameterized_route}(?:/)?$"), - route_keys, - } -} - /// Generates a named regexp. /// This is intended to be using for build time only. pub fn get_named_middleware_regex(normalized_route: &str) -> String { diff --git a/crates/next-core/src/next_font/google/mod.rs b/crates/next-core/src/next_font/google/mod.rs index 4b4a16e7ae72..9061a73acc28 100644 --- a/crates/next-core/src/next_font/google/mod.rs +++ b/crates/next-core/src/next_font/google/mod.rs @@ -21,7 +21,7 @@ use turbopack_core::{ context::AssetContext, ident::Layer, issue::{IssueExt, IssueSeverity, StyledString}, - module_graph::ModuleGraph, + module_graph::{ModuleGraph, SingleModuleGraph}, reference_type::{InnerAssets, ReferenceType}, resolve::{ ResolveResult, @@ -760,7 +760,12 @@ async fn get_mock_stylesheet( .module(); let entries = get_evaluate_entries(mocked_response_asset, asset_context, None); - let module_graph = ModuleGraph::from_modules(entries.graph_entries(), false, false); + let module_graph = ModuleGraph::from_single_graph(SingleModuleGraph::new_with_entries( + entries.graph_entries().to_resolved().await?, + false, + false, + )); + let module_graph = module_graph.connect(); let root = mock_fs.root().owned().await?; let val = evaluate( diff --git a/crates/next-core/src/next_import_map.rs b/crates/next-core/src/next_import_map.rs index 1dfff0b01b34..82c5a99d46c2 100644 --- a/crates/next-core/src/next_import_map.rs +++ b/crates/next-core/src/next_import_map.rs @@ -1109,7 +1109,7 @@ async fn insert_next_shared_aliases( next_font_google_replacer_mapping, ); - let fetch_client = next_config.fetch_client(execution_context.env()); + let fetch_client = next_config.fetch_client(); import_map.insert_alias( AliasPattern::exact(rcstr!( "@vercel/turbopack-next/internal/font/google/cssmodule.module.css" diff --git a/crates/next-core/src/next_manifests/client_reference_manifest.rs b/crates/next-core/src/next_manifests/client_reference_manifest.rs index 58d40c1a65f0..788107743b08 100644 --- a/crates/next-core/src/next_manifests/client_reference_manifest.rs +++ b/crates/next-core/src/next_manifests/client_reference_manifest.rs @@ -346,7 +346,7 @@ async fn build_manifest( get_client_reference_module_key(&server_path, "*"), ManifestNodeEntry { name: rcstr!("*"), - id: (&*client_chunk_item_id).into(), + id: (&client_chunk_item_id).into(), chunks: client_chunks_paths, // This should of course be client_is_async, but SSR can become // async due to ESM externals, and @@ -361,7 +361,7 @@ async fn build_manifest( rcstr!("*"), ManifestNodeEntry { name: rcstr!("*"), - id: (&*ssr_chunk_item_id).into(), + id: (&ssr_chunk_item_id).into(), chunks: ssr_chunks_paths, // See above r#async: client_is_async || ssr_is_async, @@ -373,7 +373,7 @@ async fn build_manifest( rcstr!("*"), ManifestNodeEntry { name: rcstr!("*"), - id: (&*rsc_chunk_item_id).into(), + id: (&rsc_chunk_item_id).into(), chunks: vec![], r#async: rsc_is_async, }, @@ -383,18 +383,18 @@ async fn build_manifest( NextRuntime::NodeJs => { entry_manifest .ssr_module_mapping - .insert((&*client_chunk_item_id).into(), ssr_manifest_node); + .insert((&client_chunk_item_id).into(), ssr_manifest_node); entry_manifest .rsc_module_mapping - .insert((&*client_chunk_item_id).into(), rsc_manifest_node); + .insert((&client_chunk_item_id).into(), rsc_manifest_node); } NextRuntime::Edge => { entry_manifest .edge_ssr_module_mapping - .insert((&*client_chunk_item_id).into(), ssr_manifest_node); + .insert((&client_chunk_item_id).into(), ssr_manifest_node); entry_manifest .edge_rsc_module_mapping - .insert((&*client_chunk_item_id).into(), rsc_manifest_node); + .insert((&client_chunk_item_id).into(), rsc_manifest_node); } } } diff --git a/crates/next-core/src/next_manifests/mod.rs b/crates/next-core/src/next_manifests/mod.rs index 03a839a1ed40..4c5381083fb0 100644 --- a/crates/next-core/src/next_manifests/mod.rs +++ b/crates/next-core/src/next_manifests/mod.rs @@ -390,6 +390,14 @@ pub struct ActionManifestEntry<'a> { pub exported_name: &'a str, pub filename: &'a str, + + /// Source location line number (1-indexed), if available + #[serde(skip_serializing_if = "Option::is_none")] + pub line: Option, + + /// Source location column number (1-indexed), if available + #[serde(skip_serializing_if = "Option::is_none")] + pub col: Option, } #[derive(Serialize, Debug)] diff --git a/crates/next-core/src/next_server/context.rs b/crates/next-core/src/next_server/context.rs index df8f24c28d55..c8ad79a763c9 100644 --- a/crates/next-core/src/next_server/context.rs +++ b/crates/next-core/src/next_server/context.rs @@ -16,7 +16,7 @@ use turbopack::{ use turbopack_core::{ chunk::{ ChunkingConfig, MangleType, MinifyType, SourceMapSourceType, SourceMapsType, - module_id_strategies::ModuleIdStrategy, + UnusedReferences, chunk_id_strategy::ModuleIdStrategy, }, compile_time_defines, compile_time_info::{CompileTimeDefines, CompileTimeInfo, FreeVarReferences}, @@ -37,7 +37,7 @@ use turbopack_node::{ transforms::postcss::{PostCssConfigLocation, PostCssTransformOptions}, }; use turbopack_nodejs::NodeJsChunkingContext; -use turbopack_resolve::resolve_options_context::ResolveOptionsContext; +use turbopack_resolve::resolve_options_context::{ResolveOptionsContext, TsConfigHandling}; use crate::{ app_structure::CollectedRootParams, @@ -326,22 +326,21 @@ pub async fn get_server_resolve_options_context( ..Default::default() }; - let tsconfig_path = next_config - .typescript_tsconfig_path() - .await? - .as_ref() - // Fall back to tsconfig only for resolving. This is because we don't want Turbopack to - // resolve tsconfig.json relative to the file being compiled. - .or(Some(&RcStr::from("tsconfig.json"))) - .map(|p| project_path.join(p)) - .transpose()?; + let tsconfig_path = next_config.typescript_tsconfig_path().await?; + let tsconfig_path = project_path.join( + tsconfig_path + .as_ref() + // Fall back to tsconfig only for resolving. This is because we don't want Turbopack to + // resolve tsconfig.json relative to the file being compiled. + .unwrap_or(&rcstr!("tsconfig.json")), + )?; Ok(ResolveOptionsContext { enable_typescript: true, enable_react: true, enable_mjs_extension: true, custom_extensions: next_config.resolve_extension().owned().await?, - tsconfig_path, + tsconfig_path: TsConfigHandling::Fixed(tsconfig_path), rules: vec![( foreign_code_context_condition, resolve_options_context.clone().resolved_cell(), @@ -993,9 +992,9 @@ pub struct ServerChunkingContextOptions { pub node_root: FileSystemPath, pub node_root_to_root_path: RcStr, pub environment: Vc, - pub module_id_strategy: Vc>, + pub module_id_strategy: Vc, pub export_usage: Vc, - pub unused_references: Vc, + pub unused_references: Vc, pub minify: Vc, pub source_maps: Vc, pub no_mangling: Vc, @@ -1056,7 +1055,7 @@ pub async fn get_server_chunking_context_with_client_assets( .source_maps(*source_maps.await?) .module_id_strategy(module_id_strategy.to_resolved().await?) .export_usage(*export_usage.await?) - .unused_references(*unused_references.await?) + .unused_references(unused_references.to_resolved().await?) .file_tracing(next_mode.is_production()) .debug_ids(*debug_ids.await?) .nested_async_availability(*nested_async_chunking.await?); @@ -1140,7 +1139,7 @@ pub async fn get_server_chunking_context( .source_maps(*source_maps.await?) .module_id_strategy(module_id_strategy.to_resolved().await?) .export_usage(*export_usage.await?) - .unused_references(*unused_references.await?) + .unused_references(unused_references.to_resolved().await?) .file_tracing(next_mode.is_production()) .debug_ids(*debug_ids.await?) .nested_async_availability(*nested_async_chunking.await?); diff --git a/crates/next-core/src/next_shared/webpack_rules/babel.rs b/crates/next-core/src/next_shared/webpack_rules/babel.rs index cb795fae2335..7d7d912a8ce8 100644 --- a/crates/next-core/src/next_shared/webpack_rules/babel.rs +++ b/crates/next-core/src/next_shared/webpack_rules/babel.rs @@ -198,6 +198,7 @@ pub async fn get_babel_loader_rules( .expect("valid const regex") .resolved_cell(), ), + query: None, }); } ReactCompilerCompilationMode::Infer => { @@ -210,6 +211,7 @@ pub async fn get_babel_loader_rules( .expect("valid const regex") .resolved_cell(), ), + query: None, }); } ReactCompilerCompilationMode::All => {} diff --git a/crates/next-core/src/raw_ecmascript_module.rs b/crates/next-core/src/raw_ecmascript_module.rs index 3d67d9fea854..72eeaf284257 100644 --- a/crates/next-core/src/raw_ecmascript_module.rs +++ b/crates/next-core/src/raw_ecmascript_module.rs @@ -1,7 +1,6 @@ use std::io::Write; use anyhow::{Result, bail}; -use either::Either; use once_cell::sync::Lazy; use regex::Regex; use tracing::Instrument; @@ -31,7 +30,7 @@ use turbopack_ecmascript::{ EcmascriptChunkItem, EcmascriptChunkItemContent, EcmascriptChunkItemOptions, EcmascriptChunkPlaceable, EcmascriptChunkType, EcmascriptExports, }, - source_map::parse_source_map_comment, + source_map::{extract_source_mapping_url_from_content, parse_source_map_comment}, utils::StringifyJs, }; @@ -263,9 +262,10 @@ impl EcmascriptChunkItem for RawEcmascriptChunkItem { } code += "(function(){\n"; + let source_mapping_url = extract_source_mapping_url_from_content(&content_str); let source_map = if let Some((source_map, _)) = parse_source_map_comment( source, - Either::Right(&content_str), + source_mapping_url, &*self.module.ident().path().await?, ) .await? diff --git a/crates/next-core/src/util.rs b/crates/next-core/src/util.rs index 14eefb80f797..3688fd1daa8e 100644 --- a/crates/next-core/src/util.rs +++ b/crates/next-core/src/util.rs @@ -146,7 +146,7 @@ pub async fn foreign_code_context_condition( )); let result = ContextCondition::all(vec![ - ContextCondition::InDirectory("node_modules".to_string()), + ContextCondition::InNodeModules, not_next_template_dir, ContextCondition::not(ContextCondition::any( transpiled_packages diff --git a/crates/next-custom-transforms/src/transforms/import_analyzer.rs b/crates/next-custom-transforms/src/transforms/import_analyzer.rs index aca0a1631729..e47cf7170d78 100644 --- a/crates/next-custom-transforms/src/transforms/import_analyzer.rs +++ b/crates/next-custom-transforms/src/transforms/import_analyzer.rs @@ -22,10 +22,6 @@ pub(crate) struct ImportMap { #[allow(unused)] impl ImportMap { - pub fn is_module_imported(&mut self, module: &Wtf8Atom) -> bool { - self.imported_modules.contains(module) - } - /// Returns true if `e` is an import of `orig_name` from `module`. pub fn is_import(&self, e: &Expr, module: &str, orig_name: &str) -> bool { match e { diff --git a/crates/next-custom-transforms/src/transforms/server_actions.rs b/crates/next-custom-transforms/src/transforms/server_actions.rs index e9ff6ebcf1c2..a36e1a84a37d 100644 --- a/crates/next-custom-transforms/src/transforms/server_actions.rs +++ b/crates/next-custom-transforms/src/transforms/server_actions.rs @@ -78,6 +78,12 @@ struct ServerReferenceExport { needs_cache_runtime_wrapper: bool, } +/// Export info for serialization +#[derive(Clone, Debug, serde::Serialize)] +struct ServerReferenceExportInfo { + name: Atom, +} + #[derive(Clone, Debug)] enum ServerActionsErrorKind { ExportedSyncFunction { @@ -199,21 +205,19 @@ pub fn server_actions( /// Serializes the Server References into a magic comment prefixed by /// `__next_internal_action_entry_do_not_use__`. fn generate_server_references_comment( - export_names_ordered_by_reference_id: &BTreeMap<&Atom, &ModuleExportName>, + export_infos_ordered_by_reference_id: &BTreeMap<&Atom, ServerReferenceExportInfo>, entry_path_query: Option<(&str, &str)>, ) -> String { - // Convert ModuleExportName to string for serialization - let export_map: BTreeMap<_, _> = export_names_ordered_by_reference_id - .iter() - .map(|(ref_id, export_name)| (*ref_id, export_name.atom())) - .collect(); - format!( " __next_internal_action_entry_do_not_use__ {} ", if let Some(entry_path_query) = entry_path_query { - serde_json::to_string(&(&export_map, entry_path_query.0, entry_path_query.1)) + serde_json::to_string(&( + &export_infos_ordered_by_reference_id, + entry_path_query.0, + entry_path_query.1, + )) } else { - serde_json::to_string(&export_map) + serde_json::to_string(&export_infos_ordered_by_reference_id) } .unwrap() ) @@ -2252,6 +2256,7 @@ impl VisitMut for ServerActions { export_name, reference_id: ref_id, needs_cache_runtime_wrapper, + .. } in &server_reference_exports { if !self.config.is_react_server_layer { @@ -2684,12 +2689,14 @@ impl VisitMut for ServerActions { } if self.has_action || self.has_cache { - // Flip the map and convert it to a BTreeMap for deterministic - // ordering in the server references comment. - let export_names_ordered_by_reference_id = self + // Build a map of reference_id -> export info + let export_infos_ordered_by_reference_id = self .reference_ids_by_export_name .iter() - .map(|(export_name, reference_id)| (reference_id, export_name)) + .map(|(export_name, reference_id)| { + let name_atom = export_name.atom().into_owned(); + (reference_id, ServerReferenceExportInfo { name: name_atom }) + }) .collect::>(); if self.config.is_react_server_layer { @@ -2700,10 +2707,13 @@ impl VisitMut for ServerActions { span: DUMMY_SP, kind: CommentKind::Block, text: generate_server_references_comment( - &export_names_ordered_by_reference_id, + &export_infos_ordered_by_reference_id, match self.mode { ServerActionsMode::Webpack => None, - ServerActionsMode::Turbopack => Some(("", "")), + ServerActionsMode::Turbopack => Some(( + &self.file_name, + self.file_query.as_ref().map_or("", |v| v), + )), }, ) .into(), @@ -2718,7 +2728,7 @@ impl VisitMut for ServerActions { span: DUMMY_SP, kind: CommentKind::Block, text: generate_server_references_comment( - &export_names_ordered_by_reference_id, + &export_infos_ordered_by_reference_id, None, ) .into(), @@ -2756,6 +2766,9 @@ impl VisitMut for ServerActions { // re-exports since the actual source maps are in the data URLs. let stripped_export_name = strip_export_name_span(&export_name); + let name_atom = export_name.atom().into_owned(); + let export_info = ServerReferenceExportInfo { name: name_atom }; + new.push(ModuleItem::ModuleDecl(ModuleDecl::ExportNamed( NamedExport { specifiers: vec![ExportSpecifier::Named( @@ -2775,7 +2788,7 @@ impl VisitMut for ServerActions { span: DUMMY_SP, kind: CommentKind::Block, text: generate_server_references_comment( - &std::iter::once((&ref_id, &export_name)) + &std::iter::once((&ref_id, export_info)) .collect(), Some(( &self.file_name, diff --git a/crates/next-custom-transforms/tests/errors/server-actions/server-graph/8/output.js b/crates/next-custom-transforms/tests/errors/server-actions/server-graph/8/output.js index bcc7f53d8e07..5b812840694b 100644 --- a/crates/next-custom-transforms/tests/errors/server-actions/server-graph/8/output.js +++ b/crates/next-custom-transforms/tests/errors/server-actions/server-graph/8/output.js @@ -3,7 +3,7 @@ export const $$RSC_SERVER_ACTION_0 = async function foo() { 'use strict'; }; registerServerReference($$RSC_SERVER_ACTION_0, "006a88810ecce4a4e8b59d53b8327d7e98bbf251d7", null); -/* __next_internal_action_entry_do_not_use__ {"006a88810ecce4a4e8b59d53b8327d7e98bbf251d7":"$$RSC_SERVER_ACTION_0"} */ const foo = $$RSC_SERVER_ACTION_0; +/* __next_internal_action_entry_do_not_use__ {"006a88810ecce4a4e8b59d53b8327d7e98bbf251d7":{"name":"$$RSC_SERVER_ACTION_0"}} */ const foo = $$RSC_SERVER_ACTION_0; const bar = async ()=>{ const x = 1; // prettier-ignore diff --git a/crates/next-custom-transforms/tests/fixture/next-font-with-directive/use-cache/output.js b/crates/next-custom-transforms/tests/fixture/next-font-with-directive/use-cache/output.js index 952d56bc3405..1bb53198b1f3 100644 --- a/crates/next-custom-transforms/tests/fixture/next-font-with-directive/use-cache/output.js +++ b/crates/next-custom-transforms/tests/fixture/next-font-with-directive/use-cache/output.js @@ -1,4 +1,4 @@ -/* __next_internal_action_entry_do_not_use__ {"c0dd5bb6fef67f5ab84327f5164ac2c3111a159337":"$$RSC_SERVER_CACHE_0"} */ import { registerServerReference } from "private-next-rsc-server-reference"; +/* __next_internal_action_entry_do_not_use__ {"c0dd5bb6fef67f5ab84327f5164ac2c3111a159337":{"name":"$$RSC_SERVER_CACHE_0"}} */ import { registerServerReference } from "private-next-rsc-server-reference"; import { cache as $$cache__ } from "private-next-rsc-cache-wrapper"; import { cache as $$reactCache__ } from "react"; import React from 'react'; diff --git a/crates/next-custom-transforms/tests/fixture/next-font-with-directive/use-server/output.js b/crates/next-custom-transforms/tests/fixture/next-font-with-directive/use-server/output.js index 83241ae20a6c..c758612c0f58 100644 --- a/crates/next-custom-transforms/tests/fixture/next-font-with-directive/use-server/output.js +++ b/crates/next-custom-transforms/tests/fixture/next-font-with-directive/use-server/output.js @@ -1,4 +1,4 @@ -/* __next_internal_action_entry_do_not_use__ {"00f8b140eeaaaa6c987593016c19b3fe41bc812c62":"myCoolServerAction"} */ import { registerServerReference } from "private-next-rsc-server-reference"; +/* __next_internal_action_entry_do_not_use__ {"00f8b140eeaaaa6c987593016c19b3fe41bc812c62":{"name":"myCoolServerAction"}} */ import { registerServerReference } from "private-next-rsc-server-reference"; import React from 'react'; import inter from '@next/font/google/target.css?{"path":"app/test.tsx","import":"Inter","arguments":[],"variableName":"inter"}'; export async function myCoolServerAction() { diff --git a/crates/next-custom-transforms/tests/fixture/react-server-components/client-graph/actions/output.js b/crates/next-custom-transforms/tests/fixture/react-server-components/client-graph/actions/output.js index fbbcbb8495b5..d8ce1043d8c2 100644 --- a/crates/next-custom-transforms/tests/fixture/react-server-components/client-graph/actions/output.js +++ b/crates/next-custom-transforms/tests/fixture/react-server-components/client-graph/actions/output.js @@ -1,3 +1,3 @@ -/* __next_internal_action_entry_do_not_use__ {"00a275d5b08d0553a04df65d28075d3cad57073dca":"test"} */ import { createServerReference, callServer, findSourceMapURL } from "private-next-rsc-action-client-wrapper"; +/* __next_internal_action_entry_do_not_use__ {"00a275d5b08d0553a04df65d28075d3cad57073dca":{"name":"test"}} */ import { createServerReference, callServer, findSourceMapURL } from "private-next-rsc-action-client-wrapper"; const $$RSC_SERVER_ACTION_0 = /*#__PURE__*/ createServerReference("00a275d5b08d0553a04df65d28075d3cad57073dca", callServer, void 0, findSourceMapURL, "test"); export { $$RSC_SERVER_ACTION_0 as test }; diff --git a/crates/next-custom-transforms/tests/fixture/react-server-components/client-graph/cache-life/output.js b/crates/next-custom-transforms/tests/fixture/react-server-components/client-graph/cache-life/output.js index fb43fae9a950..df6f53964bf1 100644 --- a/crates/next-custom-transforms/tests/fixture/react-server-components/client-graph/cache-life/output.js +++ b/crates/next-custom-transforms/tests/fixture/react-server-components/client-graph/cache-life/output.js @@ -1,3 +1,3 @@ -/* __next_internal_action_entry_do_not_use__ {"80a275d5b08d0553a04df65d28075d3cad57073dca":"test"} */ import { createServerReference, callServer, findSourceMapURL } from "private-next-rsc-action-client-wrapper"; +/* __next_internal_action_entry_do_not_use__ {"80a275d5b08d0553a04df65d28075d3cad57073dca":{"name":"test"}} */ import { createServerReference, callServer, findSourceMapURL } from "private-next-rsc-action-client-wrapper"; const $$RSC_SERVER_CACHE_0 = /*#__PURE__*/ createServerReference("80a275d5b08d0553a04df65d28075d3cad57073dca", callServer, void 0, findSourceMapURL, "test"); export { $$RSC_SERVER_CACHE_0 as test }; diff --git a/crates/next-custom-transforms/tests/fixture/react-server-components/client-graph/cache-tag/output.js b/crates/next-custom-transforms/tests/fixture/react-server-components/client-graph/cache-tag/output.js index fb43fae9a950..df6f53964bf1 100644 --- a/crates/next-custom-transforms/tests/fixture/react-server-components/client-graph/cache-tag/output.js +++ b/crates/next-custom-transforms/tests/fixture/react-server-components/client-graph/cache-tag/output.js @@ -1,3 +1,3 @@ -/* __next_internal_action_entry_do_not_use__ {"80a275d5b08d0553a04df65d28075d3cad57073dca":"test"} */ import { createServerReference, callServer, findSourceMapURL } from "private-next-rsc-action-client-wrapper"; +/* __next_internal_action_entry_do_not_use__ {"80a275d5b08d0553a04df65d28075d3cad57073dca":{"name":"test"}} */ import { createServerReference, callServer, findSourceMapURL } from "private-next-rsc-action-client-wrapper"; const $$RSC_SERVER_CACHE_0 = /*#__PURE__*/ createServerReference("80a275d5b08d0553a04df65d28075d3cad57073dca", callServer, void 0, findSourceMapURL, "test"); export { $$RSC_SERVER_CACHE_0 as test }; diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/1/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/1/output.js index 66a8c38073c7..121ad9b629d5 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/1/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/1/output.js @@ -1,5 +1,5 @@ // app/send.ts -/* __next_internal_action_entry_do_not_use__ {"00c18c215a6b7cdc64bf709f3a714ffdef1bf9651d":"default","70e10665baac148856374b2789aceb970f66fec33e":"myAction"} */ import { createServerReference, callServer, findSourceMapURL } from "private-next-rsc-action-client-wrapper"; +/* __next_internal_action_entry_do_not_use__ {"00c18c215a6b7cdc64bf709f3a714ffdef1bf9651d":{"name":"default"},"70e10665baac148856374b2789aceb970f66fec33e":{"name":"myAction"}} */ import { createServerReference, callServer, findSourceMapURL } from "private-next-rsc-action-client-wrapper"; const $$RSC_SERVER_ACTION_1 = /*#__PURE__*/ createServerReference("70e10665baac148856374b2789aceb970f66fec33e", callServer, void 0, findSourceMapURL, "myAction"); export { $$RSC_SERVER_ACTION_1 as myAction }; export default /*#__PURE__*/ createServerReference("00c18c215a6b7cdc64bf709f3a714ffdef1bf9651d", callServer, void 0, findSourceMapURL, "default"); diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/10/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/10/output.js index 76100be9694b..6ec9c186c375 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/10/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/10/output.js @@ -1,2 +1,2 @@ -/* __next_internal_action_entry_do_not_use__ {"80c18c215a6b7cdc64bf709f3a714ffdef1bf9651d":"default"} */ import { createServerReference, callServer, findSourceMapURL } from "private-next-rsc-action-client-wrapper"; +/* __next_internal_action_entry_do_not_use__ {"80c18c215a6b7cdc64bf709f3a714ffdef1bf9651d":{"name":"default"}} */ import { createServerReference, callServer, findSourceMapURL } from "private-next-rsc-action-client-wrapper"; export default /*#__PURE__*/ createServerReference("80c18c215a6b7cdc64bf709f3a714ffdef1bf9651d", callServer, void 0, findSourceMapURL, "default"); diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/11/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/11/output.js index 76100be9694b..6ec9c186c375 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/11/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/11/output.js @@ -1,2 +1,2 @@ -/* __next_internal_action_entry_do_not_use__ {"80c18c215a6b7cdc64bf709f3a714ffdef1bf9651d":"default"} */ import { createServerReference, callServer, findSourceMapURL } from "private-next-rsc-action-client-wrapper"; +/* __next_internal_action_entry_do_not_use__ {"80c18c215a6b7cdc64bf709f3a714ffdef1bf9651d":{"name":"default"}} */ import { createServerReference, callServer, findSourceMapURL } from "private-next-rsc-action-client-wrapper"; export default /*#__PURE__*/ createServerReference("80c18c215a6b7cdc64bf709f3a714ffdef1bf9651d", callServer, void 0, findSourceMapURL, "default"); diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/12/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/12/output.js index 76100be9694b..6ec9c186c375 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/12/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/12/output.js @@ -1,2 +1,2 @@ -/* __next_internal_action_entry_do_not_use__ {"80c18c215a6b7cdc64bf709f3a714ffdef1bf9651d":"default"} */ import { createServerReference, callServer, findSourceMapURL } from "private-next-rsc-action-client-wrapper"; +/* __next_internal_action_entry_do_not_use__ {"80c18c215a6b7cdc64bf709f3a714ffdef1bf9651d":{"name":"default"}} */ import { createServerReference, callServer, findSourceMapURL } from "private-next-rsc-action-client-wrapper"; export default /*#__PURE__*/ createServerReference("80c18c215a6b7cdc64bf709f3a714ffdef1bf9651d", callServer, void 0, findSourceMapURL, "default"); diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/13/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/13/output.js index fba80c8ff503..e8d18f0a1257 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/13/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/13/output.js @@ -1,4 +1,4 @@ -/* __next_internal_action_entry_do_not_use__ {"802af4786baeeb4011d0d5e5ff1cb669d517c9b125":"staticallyKnownFunction","807f03edbc83b6cc7e5ccc12da8fecf25146585bb7":"getCachedData","ff1acff246876a467753785a92d1f95ac6fe32c9b9":"Other","ff27fadf3eeb97c777cea9f14a407b5c0b42ac65bb":"aliased","ff438bb59117ff1af890c80ca3e39d9e888fc93033":"wrapped","ff84effee663e5ce4e0948b55df129a8df904c67aa":"Sync","ff8fa22f08e492db15701f58a1458cc4ebf782f855":"getData","ff980f8c891ae27674b86a4804d306bdb3065c2e4f":"getStuff","ffc18c215a6b7cdc64bf709f3a714ffdef1bf9651d":"default"} */ import { createServerReference, callServer, findSourceMapURL } from "private-next-rsc-action-client-wrapper"; +/* __next_internal_action_entry_do_not_use__ {"802af4786baeeb4011d0d5e5ff1cb669d517c9b125":{"name":"staticallyKnownFunction"},"807f03edbc83b6cc7e5ccc12da8fecf25146585bb7":{"name":"getCachedData"},"ff1acff246876a467753785a92d1f95ac6fe32c9b9":{"name":"Other"},"ff27fadf3eeb97c777cea9f14a407b5c0b42ac65bb":{"name":"aliased"},"ff438bb59117ff1af890c80ca3e39d9e888fc93033":{"name":"wrapped"},"ff84effee663e5ce4e0948b55df129a8df904c67aa":{"name":"Sync"},"ff8fa22f08e492db15701f58a1458cc4ebf782f855":{"name":"getData"},"ff980f8c891ae27674b86a4804d306bdb3065c2e4f":{"name":"getStuff"},"ffc18c215a6b7cdc64bf709f3a714ffdef1bf9651d":{"name":"default"}} */ import { createServerReference, callServer, findSourceMapURL } from "private-next-rsc-action-client-wrapper"; const $$RSC_SERVER_CACHE_0 = /*#__PURE__*/ createServerReference("807f03edbc83b6cc7e5ccc12da8fecf25146585bb7", callServer, void 0, findSourceMapURL, "getCachedData"); export { $$RSC_SERVER_CACHE_0 as getCachedData }; const $$RSC_SERVER_CACHE_1 = /*#__PURE__*/ createServerReference("802af4786baeeb4011d0d5e5ff1cb669d517c9b125", callServer, void 0, findSourceMapURL, "staticallyKnownFunction"); diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/14/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/14/output.js index 0fe3fb9ce2a8..ed95f9fdf84e 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/14/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/14/output.js @@ -1,3 +1,3 @@ -/* __next_internal_action_entry_do_not_use__ {"ffaa88e24cee8047d167e47f4f374dbddc187e2899":"fooCached"} */ import { createServerReference, callServer, findSourceMapURL } from "private-next-rsc-action-client-wrapper"; +/* __next_internal_action_entry_do_not_use__ {"ffaa88e24cee8047d167e47f4f374dbddc187e2899":{"name":"fooCached"}} */ import { createServerReference, callServer, findSourceMapURL } from "private-next-rsc-action-client-wrapper"; const $$RSC_SERVER_CACHE_0 = /*#__PURE__*/ createServerReference("ffaa88e24cee8047d167e47f4f374dbddc187e2899", callServer, void 0, findSourceMapURL, "fooCached"); export { $$RSC_SERVER_CACHE_0 as fooCached }; diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/15/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/15/output.js index 437d6e2f378e..1e2e5bceec72 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/15/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/15/output.js @@ -1,3 +1,3 @@ -/* __next_internal_action_entry_do_not_use__ {"0073f2cbccffb158eb2704761fc88fdbd0aaa102d0":"📙"} */ import { createServerReference, callServer, findSourceMapURL } from "private-next-rsc-action-client-wrapper"; +/* __next_internal_action_entry_do_not_use__ {"0073f2cbccffb158eb2704761fc88fdbd0aaa102d0":{"name":"📙"}} */ import { createServerReference, callServer, findSourceMapURL } from "private-next-rsc-action-client-wrapper"; const $$RSC_SERVER_ACTION_0 = /*#__PURE__*/ createServerReference("0073f2cbccffb158eb2704761fc88fdbd0aaa102d0", callServer, void 0, findSourceMapURL, "📙"); export { $$RSC_SERVER_ACTION_0 as "📙" }; diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/16/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/16/output.js index 6ec02ee4cf87..f744fc5053eb 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/16/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/16/output.js @@ -1,3 +1,3 @@ -/* __next_internal_action_entry_do_not_use__ {"8073f2cbccffb158eb2704761fc88fdbd0aaa102d0":"📙"} */ import { createServerReference, callServer, findSourceMapURL } from "private-next-rsc-action-client-wrapper"; +/* __next_internal_action_entry_do_not_use__ {"8073f2cbccffb158eb2704761fc88fdbd0aaa102d0":{"name":"📙"}} */ import { createServerReference, callServer, findSourceMapURL } from "private-next-rsc-action-client-wrapper"; const $$RSC_SERVER_CACHE_0 = /*#__PURE__*/ createServerReference("8073f2cbccffb158eb2704761fc88fdbd0aaa102d0", callServer, void 0, findSourceMapURL, "📙"); export { $$RSC_SERVER_CACHE_0 as "📙" }; diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/2/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/2/output.js index b0b9796ce3ab..09dc9cc72f88 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/2/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/2/output.js @@ -1,4 +1,4 @@ // app/send.ts -/* __next_internal_action_entry_do_not_use__ {"00ab21efdafbe611287bc25c0462b1e0510d13e48b":"foo"} */ import { createServerReference, callServer, findSourceMapURL } from "private-next-rsc-action-client-wrapper"; +/* __next_internal_action_entry_do_not_use__ {"00ab21efdafbe611287bc25c0462b1e0510d13e48b":{"name":"foo"}} */ import { createServerReference, callServer, findSourceMapURL } from "private-next-rsc-action-client-wrapper"; const $$RSC_SERVER_ACTION_0 = /*#__PURE__*/ createServerReference("00ab21efdafbe611287bc25c0462b1e0510d13e48b", callServer, void 0, findSourceMapURL, "foo"); export { $$RSC_SERVER_ACTION_0 as foo }; diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/3/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/3/output.js index c5a96e7cab43..a4627260f6ce 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/3/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/3/output.js @@ -1,4 +1,4 @@ -/* __next_internal_action_entry_do_not_use__ {"7fa0c73dd6f5af839e3335c6b19262ecb86cca6af4":"sampleFunction2","7fbd336abe00c3c59da66acb696fc8e151d8e54ea4":"sampleFunction","7fd4f2e95bc745b6500b439c0847003511748c8ece":"sampleFunction3","7ff03b256ee88a51700367acee3082894e25e6e7d9":"sampleFunction4"} */ import { createServerReference, callServer, findSourceMapURL } from "private-next-rsc-action-client-wrapper"; +/* __next_internal_action_entry_do_not_use__ {"7fa0c73dd6f5af839e3335c6b19262ecb86cca6af4":{"name":"sampleFunction2"},"7fbd336abe00c3c59da66acb696fc8e151d8e54ea4":{"name":"sampleFunction"},"7fd4f2e95bc745b6500b439c0847003511748c8ece":{"name":"sampleFunction3"},"7ff03b256ee88a51700367acee3082894e25e6e7d9":{"name":"sampleFunction4"}} */ import { createServerReference, callServer, findSourceMapURL } from "private-next-rsc-action-client-wrapper"; const $$RSC_SERVER_ACTION_0 = /*#__PURE__*/ createServerReference("7fbd336abe00c3c59da66acb696fc8e151d8e54ea4", callServer, void 0, findSourceMapURL, "sampleFunction"); export { $$RSC_SERVER_ACTION_0 as sampleFunction }; const $$RSC_SERVER_ACTION_1 = /*#__PURE__*/ createServerReference("7fa0c73dd6f5af839e3335c6b19262ecb86cca6af4", callServer, void 0, findSourceMapURL, "sampleFunction2"); diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/4/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/4/output.js index ce5a3d969ea5..8bcfb2361adf 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/4/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/4/output.js @@ -1,3 +1,3 @@ -/* __next_internal_action_entry_do_not_use__ {"00ac840dcaf5e8197cb02b7f3a43c119b7a770b272":"bar"} */ import { createServerReference, callServer, findSourceMapURL } from "private-next-rsc-action-client-wrapper"; +/* __next_internal_action_entry_do_not_use__ {"00ac840dcaf5e8197cb02b7f3a43c119b7a770b272":{"name":"bar"}} */ import { createServerReference, callServer, findSourceMapURL } from "private-next-rsc-action-client-wrapper"; const $$RSC_SERVER_ACTION_0 = /*#__PURE__*/ createServerReference("00ac840dcaf5e8197cb02b7f3a43c119b7a770b272", callServer, void 0, findSourceMapURL, "bar"); export { $$RSC_SERVER_ACTION_0 as bar }; diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/5/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/5/output.js index a91d80b54f0a..2a10eace4548 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/5/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/5/output.js @@ -1,3 +1,3 @@ -/* __next_internal_action_entry_do_not_use__ {"7f0090eaf4e1f08a2d94f6be401e54a2ded399b87c":"action0"} */ import { createServerReference, callServer, findSourceMapURL } from "private-next-rsc-action-client-wrapper"; +/* __next_internal_action_entry_do_not_use__ {"7f0090eaf4e1f08a2d94f6be401e54a2ded399b87c":{"name":"action0"}} */ import { createServerReference, callServer, findSourceMapURL } from "private-next-rsc-action-client-wrapper"; const $$RSC_SERVER_ACTION_0 = /*#__PURE__*/ createServerReference("7f0090eaf4e1f08a2d94f6be401e54a2ded399b87c", callServer, void 0, findSourceMapURL, "action0"); export { $$RSC_SERVER_ACTION_0 as action0 }; diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/6/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/6/output.js index e0ee0c5001b4..61bd9181344d 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/6/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/6/output.js @@ -1,4 +1,4 @@ -/* __next_internal_action_entry_do_not_use__ {"80ab21efdafbe611287bc25c0462b1e0510d13e48b":"foo","80ac840dcaf5e8197cb02b7f3a43c119b7a770b272":"bar"} */ import { createServerReference, callServer, findSourceMapURL } from "private-next-rsc-action-client-wrapper"; +/* __next_internal_action_entry_do_not_use__ {"80ab21efdafbe611287bc25c0462b1e0510d13e48b":{"name":"foo"},"80ac840dcaf5e8197cb02b7f3a43c119b7a770b272":{"name":"bar"}} */ import { createServerReference, callServer, findSourceMapURL } from "private-next-rsc-action-client-wrapper"; const $$RSC_SERVER_CACHE_0 = /*#__PURE__*/ createServerReference("80ab21efdafbe611287bc25c0462b1e0510d13e48b", callServer, void 0, findSourceMapURL, "foo"); export { $$RSC_SERVER_CACHE_0 as foo }; const $$RSC_SERVER_CACHE_1 = /*#__PURE__*/ createServerReference("80ac840dcaf5e8197cb02b7f3a43c119b7a770b272", callServer, void 0, findSourceMapURL, "bar"); diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/7/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/7/output.js index 30647bb277b1..89181e847e4a 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/7/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/7/output.js @@ -1,2 +1,2 @@ -/* __next_internal_action_entry_do_not_use__ {"00c18c215a6b7cdc64bf709f3a714ffdef1bf9651d":"default"} */ import { createServerReference, callServer, findSourceMapURL } from "private-next-rsc-action-client-wrapper"; +/* __next_internal_action_entry_do_not_use__ {"00c18c215a6b7cdc64bf709f3a714ffdef1bf9651d":{"name":"default"}} */ import { createServerReference, callServer, findSourceMapURL } from "private-next-rsc-action-client-wrapper"; export default /*#__PURE__*/ createServerReference("00c18c215a6b7cdc64bf709f3a714ffdef1bf9651d", callServer, void 0, findSourceMapURL, "default"); diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/8/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/8/output.js index 9f1897f9fed6..76a581321986 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/8/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/8/output.js @@ -1,3 +1,3 @@ -/* __next_internal_action_entry_do_not_use__ {"80ac840dcaf5e8197cb02b7f3a43c119b7a770b272":"bar"} */ import { createServerReference, callServer, findSourceMapURL } from "private-next-rsc-action-client-wrapper"; +/* __next_internal_action_entry_do_not_use__ {"80ac840dcaf5e8197cb02b7f3a43c119b7a770b272":{"name":"bar"}} */ import { createServerReference, callServer, findSourceMapURL } from "private-next-rsc-action-client-wrapper"; const $$RSC_SERVER_ACTION_0 = /*#__PURE__*/ createServerReference("80ac840dcaf5e8197cb02b7f3a43c119b7a770b272", callServer, void 0, findSourceMapURL, "bar"); export { $$RSC_SERVER_ACTION_0 as bar }; diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/9/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/9/output.js index 76100be9694b..6ec9c186c375 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/9/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/9/output.js @@ -1,2 +1,2 @@ -/* __next_internal_action_entry_do_not_use__ {"80c18c215a6b7cdc64bf709f3a714ffdef1bf9651d":"default"} */ import { createServerReference, callServer, findSourceMapURL } from "private-next-rsc-action-client-wrapper"; +/* __next_internal_action_entry_do_not_use__ {"80c18c215a6b7cdc64bf709f3a714ffdef1bf9651d":{"name":"default"}} */ import { createServerReference, callServer, findSourceMapURL } from "private-next-rsc-action-client-wrapper"; export default /*#__PURE__*/ createServerReference("80c18c215a6b7cdc64bf709f3a714ffdef1bf9651d", callServer, void 0, findSourceMapURL, "default"); diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/turbopack/1/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/turbopack/1/output.js index 82b90aca0d6f..2400f34ccf12 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/turbopack/1/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/client-graph/turbopack/1/output.js @@ -1,3 +1,3 @@ "use turbopack no side effects"; -export { foo } from "data:text/javascript,%2F%2A%20__next_internal_action_entry_do_not_use__%20%5B%7B%2200ab21efdafbe611287bc25c0462b1e0510d13e48b%22%3A%22foo%22%7D%2C%22%2Fapp%2Fitem.js%22%2C%22%22%5D%20%2A%2F%22use%20turbopack%20no%20side%20effects%22%3Bimport%7BcreateServerReference%2CcallServer%2CfindSourceMapURL%7Dfrom%22private-next-rsc-action-client-wrapper%22%3Bconst%20%24%24RSC_SERVER_ACTION_0%3D%2F%2A%23__PURE__%2A%2FcreateServerReference%28%2200ab21efdafbe611287bc25c0462b1e0510d13e48b%22%2CcallServer%2Cvoid%200%2CfindSourceMapURL%2C%22foo%22%29%3Bexport%7B%24%24RSC_SERVER_ACTION_0%20as%20foo%7D%3B"; -export { bar } from "data:text/javascript,%2F%2A%20__next_internal_action_entry_do_not_use__%20%5B%7B%2200ac840dcaf5e8197cb02b7f3a43c119b7a770b272%22%3A%22bar%22%7D%2C%22%2Fapp%2Fitem.js%22%2C%22%22%5D%20%2A%2F%22use%20turbopack%20no%20side%20effects%22%3Bimport%7BcreateServerReference%2CcallServer%2CfindSourceMapURL%7Dfrom%22private-next-rsc-action-client-wrapper%22%3Bconst%20%24%24RSC_SERVER_ACTION_1%3D%2F%2A%23__PURE__%2A%2FcreateServerReference%28%2200ac840dcaf5e8197cb02b7f3a43c119b7a770b272%22%2CcallServer%2Cvoid%200%2CfindSourceMapURL%2C%22bar%22%29%3Bexport%7B%24%24RSC_SERVER_ACTION_1%20as%20bar%7D%3B"; +export { foo } from "data:text/javascript,%2F%2A%20__next_internal_action_entry_do_not_use__%20%5B%7B%2200ab21efdafbe611287bc25c0462b1e0510d13e48b%22%3A%7B%22name%22%3A%22foo%22%7D%7D%2C%22%2Fapp%2Fitem.js%22%2C%22%22%5D%20%2A%2F%22use%20turbopack%20no%20side%20effects%22%3Bimport%7BcreateServerReference%2CcallServer%2CfindSourceMapURL%7Dfrom%22private-next-rsc-action-client-wrapper%22%3Bconst%20%24%24RSC_SERVER_ACTION_0%3D%2F%2A%23__PURE__%2A%2FcreateServerReference%28%2200ab21efdafbe611287bc25c0462b1e0510d13e48b%22%2CcallServer%2Cvoid%200%2CfindSourceMapURL%2C%22foo%22%29%3Bexport%7B%24%24RSC_SERVER_ACTION_0%20as%20foo%7D%3B"; +export { bar } from "data:text/javascript,%2F%2A%20__next_internal_action_entry_do_not_use__%20%5B%7B%2200ac840dcaf5e8197cb02b7f3a43c119b7a770b272%22%3A%7B%22name%22%3A%22bar%22%7D%7D%2C%22%2Fapp%2Fitem.js%22%2C%22%22%5D%20%2A%2F%22use%20turbopack%20no%20side%20effects%22%3Bimport%7BcreateServerReference%2CcallServer%2CfindSourceMapURL%7Dfrom%22private-next-rsc-action-client-wrapper%22%3Bconst%20%24%24RSC_SERVER_ACTION_1%3D%2F%2A%23__PURE__%2A%2FcreateServerReference%28%2200ac840dcaf5e8197cb02b7f3a43c119b7a770b272%22%2CcallServer%2Cvoid%200%2CfindSourceMapURL%2C%22bar%22%29%3Bexport%7B%24%24RSC_SERVER_ACTION_1%20as%20bar%7D%3B"; diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/1/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/1/output.js index 4a775c839c17..2bb43dda3434 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/1/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/1/output.js @@ -1,6 +1,6 @@ import { registerServerReference } from "private-next-rsc-server-reference"; import { encryptActionBoundArgs, decryptActionBoundArgs } from "private-next-rsc-action-encryption"; -/* __next_internal_action_entry_do_not_use__ {"406a88810ecce4a4e8b59d53b8327d7e98bbf251d7":"$$RSC_SERVER_ACTION_0","4090b5db271335765a4b0eab01f044b381b5ebd5cd":"$$RSC_SERVER_ACTION_1"} */ import { Button } from 'components'; +/* __next_internal_action_entry_do_not_use__ {"406a88810ecce4a4e8b59d53b8327d7e98bbf251d7":{"name":"$$RSC_SERVER_ACTION_0"},"4090b5db271335765a4b0eab01f044b381b5ebd5cd":{"name":"$$RSC_SERVER_ACTION_1"}} */ import { Button } from 'components'; import deleteFromDb from 'db'; export const $$RSC_SERVER_ACTION_0 = async function deleteItem($$ACTION_CLOSURE_BOUND) { var [$$ACTION_ARG_0, $$ACTION_ARG_1] = await decryptActionBoundArgs("406a88810ecce4a4e8b59d53b8327d7e98bbf251d7", $$ACTION_CLOSURE_BOUND); diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/10/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/10/output.js index 9055b582d1b6..4c9d52a1bc93 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/10/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/10/output.js @@ -1,4 +1,4 @@ -/* __next_internal_action_entry_do_not_use__ {"00c18c215a6b7cdc64bf709f3a714ffdef1bf9651d":"default"} */ import { registerServerReference } from "private-next-rsc-server-reference"; +/* __next_internal_action_entry_do_not_use__ {"00c18c215a6b7cdc64bf709f3a714ffdef1bf9651d":{"name":"default"}} */ import { registerServerReference } from "private-next-rsc-server-reference"; export default async function foo() {} import { ensureServerEntryExports } from "private-next-rsc-action-validate"; ensureServerEntryExports([ diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/11/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/11/output.js index 5caa85facf2f..5903159fff55 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/11/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/11/output.js @@ -1,4 +1,4 @@ -/* __next_internal_action_entry_do_not_use__ {"00c18c215a6b7cdc64bf709f3a714ffdef1bf9651d":"default"} */ import { registerServerReference } from "private-next-rsc-server-reference"; +/* __next_internal_action_entry_do_not_use__ {"00c18c215a6b7cdc64bf709f3a714ffdef1bf9651d":{"name":"default"}} */ import { registerServerReference } from "private-next-rsc-server-reference"; const $$RSC_SERVER_ACTION_0 = async function() {}; Object["defineProperty"]($$RSC_SERVER_ACTION_0, "name", { value: "default" diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/12/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/12/output.js index e36ccf0e96ca..a10ea7b79c5c 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/12/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/12/output.js @@ -1,4 +1,4 @@ -/* __next_internal_action_entry_do_not_use__ {"00c18c215a6b7cdc64bf709f3a714ffdef1bf9651d":"default"} */ import { registerServerReference } from "private-next-rsc-server-reference"; +/* __next_internal_action_entry_do_not_use__ {"00c18c215a6b7cdc64bf709f3a714ffdef1bf9651d":{"name":"default"}} */ import { registerServerReference } from "private-next-rsc-server-reference"; async function foo() {} export default foo; import { ensureServerEntryExports } from "private-next-rsc-action-validate"; diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/13/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/13/output.js index 83937a114865..a646c36efd6a 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/13/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/13/output.js @@ -1,4 +1,4 @@ -/* __next_internal_action_entry_do_not_use__ {"00ac840dcaf5e8197cb02b7f3a43c119b7a770b272":"bar","00c18c215a6b7cdc64bf709f3a714ffdef1bf9651d":"default"} */ import { registerServerReference } from "private-next-rsc-server-reference"; +/* __next_internal_action_entry_do_not_use__ {"00ac840dcaf5e8197cb02b7f3a43c119b7a770b272":{"name":"bar"},"00c18c215a6b7cdc64bf709f3a714ffdef1bf9651d":{"name":"default"}} */ import { registerServerReference } from "private-next-rsc-server-reference"; const foo = async function() {}; export default foo; const bar = async function() {}; diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/14/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/14/output.js index 579d4b4e0ef1..a305395e9254 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/14/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/14/output.js @@ -1,4 +1,4 @@ -/* __next_internal_action_entry_do_not_use__ {"00ab21efdafbe611287bc25c0462b1e0510d13e48b":"foo"} */ import { registerServerReference } from "private-next-rsc-server-reference"; +/* __next_internal_action_entry_do_not_use__ {"00ab21efdafbe611287bc25c0462b1e0510d13e48b":{"name":"foo"}} */ import { registerServerReference } from "private-next-rsc-server-reference"; export async function foo() { async function bar() {} } diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/15/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/15/output.js index f97b426881d2..0f3f1e96e437 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/15/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/15/output.js @@ -1,4 +1,4 @@ -/* __next_internal_action_entry_do_not_use__ {"60c18c215a6b7cdc64bf709f3a714ffdef1bf9651d":"default"} */ import { registerServerReference } from "private-next-rsc-server-reference"; +/* __next_internal_action_entry_do_not_use__ {"60c18c215a6b7cdc64bf709f3a714ffdef1bf9651d":{"name":"default"}} */ import { registerServerReference } from "private-next-rsc-server-reference"; const $$RSC_SERVER_ACTION_0 = async (a, b)=>{ console.log(a, b); }; diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/16/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/16/output.js index 1052758792d5..77ce08cac561 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/16/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/16/output.js @@ -1,6 +1,6 @@ import { registerServerReference } from "private-next-rsc-server-reference"; import { encryptActionBoundArgs, decryptActionBoundArgs } from "private-next-rsc-action-encryption"; -/* __next_internal_action_entry_do_not_use__ {"406a88810ecce4a4e8b59d53b8327d7e98bbf251d7":"$$RSC_SERVER_ACTION_0","7f1c36b06e398c97abe5d5d7ae8c672bfddf4e1b91":"$$RSC_SERVER_ACTION_2","7f90b5db271335765a4b0eab01f044b381b5ebd5cd":"$$RSC_SERVER_ACTION_1"} */ import { Button } from 'components'; +/* __next_internal_action_entry_do_not_use__ {"406a88810ecce4a4e8b59d53b8327d7e98bbf251d7":{"name":"$$RSC_SERVER_ACTION_0"},"7f1c36b06e398c97abe5d5d7ae8c672bfddf4e1b91":{"name":"$$RSC_SERVER_ACTION_2"},"7f90b5db271335765a4b0eab01f044b381b5ebd5cd":{"name":"$$RSC_SERVER_ACTION_1"}} */ import { Button } from 'components'; import deleteFromDb from 'db'; const v1 = 'v1'; export const $$RSC_SERVER_ACTION_0 = async function deleteItem($$ACTION_CLOSURE_BOUND) { diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/17/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/17/output.js index be2c6969eb1e..764511376b7c 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/17/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/17/output.js @@ -1,4 +1,4 @@ -/* __next_internal_action_entry_do_not_use__ {"00ab21efdafbe611287bc25c0462b1e0510d13e48b":"foo","00ac840dcaf5e8197cb02b7f3a43c119b7a770b272":"bar"} */ import { registerServerReference } from "private-next-rsc-server-reference"; +/* __next_internal_action_entry_do_not_use__ {"00ab21efdafbe611287bc25c0462b1e0510d13e48b":{"name":"foo"},"00ac840dcaf5e8197cb02b7f3a43c119b7a770b272":{"name":"bar"}} */ import { registerServerReference } from "private-next-rsc-server-reference"; export const foo = async ()=>{}; const bar = async ()=>{}; export { bar }; diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/18/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/18/output.js index e16a9e247fe4..d685fa60fda9 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/18/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/18/output.js @@ -1,6 +1,6 @@ import { registerServerReference } from "private-next-rsc-server-reference"; import { encryptActionBoundArgs, decryptActionBoundArgs } from "private-next-rsc-action-encryption"; -/* __next_internal_action_entry_do_not_use__ {"406a88810ecce4a4e8b59d53b8327d7e98bbf251d7":"$$RSC_SERVER_ACTION_0","4090b5db271335765a4b0eab01f044b381b5ebd5cd":"$$RSC_SERVER_ACTION_1"} */ import { Button } from 'components'; +/* __next_internal_action_entry_do_not_use__ {"406a88810ecce4a4e8b59d53b8327d7e98bbf251d7":{"name":"$$RSC_SERVER_ACTION_0"},"4090b5db271335765a4b0eab01f044b381b5ebd5cd":{"name":"$$RSC_SERVER_ACTION_1"}} */ import { Button } from 'components'; import deleteFromDb from 'db'; const v1 = 'v1'; export const $$RSC_SERVER_ACTION_0 = async function action($$ACTION_CLOSURE_BOUND) { diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/19/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/19/output.js index 4518b36fd0be..4b1f887b36bd 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/19/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/19/output.js @@ -1,6 +1,6 @@ import { registerServerReference } from "private-next-rsc-server-reference"; import { encryptActionBoundArgs, decryptActionBoundArgs } from "private-next-rsc-action-encryption"; -/* __next_internal_action_entry_do_not_use__ {"606a88810ecce4a4e8b59d53b8327d7e98bbf251d7":"$$RSC_SERVER_ACTION_0"} */ import { Button } from 'components'; +/* __next_internal_action_entry_do_not_use__ {"606a88810ecce4a4e8b59d53b8327d7e98bbf251d7":{"name":"$$RSC_SERVER_ACTION_0"}} */ import { Button } from 'components'; export const $$RSC_SERVER_ACTION_0 = async function action($$ACTION_CLOSURE_BOUND, value2) { var [$$ACTION_ARG_0] = await decryptActionBoundArgs("606a88810ecce4a4e8b59d53b8327d7e98bbf251d7", $$ACTION_CLOSURE_BOUND); return $$ACTION_ARG_0 * value2; diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/2/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/2/output.js index fbd319454732..ad7420b09f6a 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/2/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/2/output.js @@ -1,5 +1,5 @@ import { registerServerReference } from "private-next-rsc-server-reference"; -/* __next_internal_action_entry_do_not_use__ {"0090b5db271335765a4b0eab01f044b381b5ebd5cd":"$$RSC_SERVER_ACTION_1","706a88810ecce4a4e8b59d53b8327d7e98bbf251d7":"$$RSC_SERVER_ACTION_0"} */ import { validator } from 'auth'; +/* __next_internal_action_entry_do_not_use__ {"0090b5db271335765a4b0eab01f044b381b5ebd5cd":{"name":"$$RSC_SERVER_ACTION_1"},"706a88810ecce4a4e8b59d53b8327d7e98bbf251d7":{"name":"$$RSC_SERVER_ACTION_0"}} */ import { validator } from 'auth'; import { Button } from 'components'; export const $$RSC_SERVER_ACTION_0 = async function myAction(a, b, c) { console.log('a'); diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/20/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/20/output.js index 31b512d528d6..64fe75a0fb01 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/20/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/20/output.js @@ -1,4 +1,4 @@ -/* __next_internal_action_entry_do_not_use__ {"7fc18c215a6b7cdc64bf709f3a714ffdef1bf9651d":"default"} */ import { registerServerReference } from "private-next-rsc-server-reference"; +/* __next_internal_action_entry_do_not_use__ {"7fc18c215a6b7cdc64bf709f3a714ffdef1bf9651d":{"name":"default"}} */ import { registerServerReference } from "private-next-rsc-server-reference"; /** @type {[any]} */ const [foo] = [ null ]; diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/21/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/21/output.js index 478418280dfd..4b14389eb6f6 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/21/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/21/output.js @@ -1,6 +1,6 @@ import { registerServerReference } from "private-next-rsc-server-reference"; import { encryptActionBoundArgs, decryptActionBoundArgs } from "private-next-rsc-action-encryption"; -/* __next_internal_action_entry_do_not_use__ {"001c36b06e398c97abe5d5d7ae8c672bfddf4e1b91":"$$RSC_SERVER_ACTION_2","0090b5db271335765a4b0eab01f044b381b5ebd5cd":"$$RSC_SERVER_ACTION_1","606a88810ecce4a4e8b59d53b8327d7e98bbf251d7":"$$RSC_SERVER_ACTION_0"} */ import { validator, another } from 'auth'; +/* __next_internal_action_entry_do_not_use__ {"001c36b06e398c97abe5d5d7ae8c672bfddf4e1b91":{"name":"$$RSC_SERVER_ACTION_2"},"0090b5db271335765a4b0eab01f044b381b5ebd5cd":{"name":"$$RSC_SERVER_ACTION_1"},"606a88810ecce4a4e8b59d53b8327d7e98bbf251d7":{"name":"$$RSC_SERVER_ACTION_0"}} */ import { validator, another } from 'auth'; import { Button } from 'components'; const x = 1; export const $$RSC_SERVER_ACTION_0 = async function($$ACTION_CLOSURE_BOUND, z) { diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/22/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/22/output.js index 4ad31671faf9..fa2df3979aff 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/22/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/22/output.js @@ -1,4 +1,4 @@ -/* __next_internal_action_entry_do_not_use__ {"7fc18c215a6b7cdc64bf709f3a714ffdef1bf9651d":"default","7ff14702b5a021dd117f7ec7a3c838f397c2046d3b":"action"} */ import { registerServerReference } from "private-next-rsc-server-reference"; +/* __next_internal_action_entry_do_not_use__ {"7fc18c215a6b7cdc64bf709f3a714ffdef1bf9651d":{"name":"default"},"7ff14702b5a021dd117f7ec7a3c838f397c2046d3b":{"name":"action"}} */ import { registerServerReference } from "private-next-rsc-server-reference"; import { validator } from 'auth'; export const action = validator(async ()=>{}); const $$RSC_SERVER_ACTION_0 = validator(async ()=>{}); diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/23/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/23/output.js index 4ffbe64bec6e..00494e7f17d6 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/23/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/23/output.js @@ -10,7 +10,7 @@ export const $$RSC_SERVER_ACTION_1 = async function action2($$ACTION_CLOSURE_BOU console.log(a, b, $$ACTION_ARG_0, c, d); }; registerServerReference($$RSC_SERVER_ACTION_1, "7c90b5db271335765a4b0eab01f044b381b5ebd5cd", null); -/* __next_internal_action_entry_do_not_use__ {"7c6a88810ecce4a4e8b59d53b8327d7e98bbf251d7":"$$RSC_SERVER_ACTION_0","7c90b5db271335765a4b0eab01f044b381b5ebd5cd":"$$RSC_SERVER_ACTION_1"} */ export default function Page({ foo, x, y }) { +/* __next_internal_action_entry_do_not_use__ {"7c6a88810ecce4a4e8b59d53b8327d7e98bbf251d7":{"name":"$$RSC_SERVER_ACTION_0"},"7c90b5db271335765a4b0eab01f044b381b5ebd5cd":{"name":"$$RSC_SERVER_ACTION_1"}} */ export default function Page({ foo, x, y }) { var action = $$RSC_SERVER_ACTION_0.bind(null, encryptActionBoundArgs("7c6a88810ecce4a4e8b59d53b8327d7e98bbf251d7", x)); action.bind(null, foo[0], foo[1], foo.x, foo[y]); const action2 = $$RSC_SERVER_ACTION_1.bind(null, encryptActionBoundArgs("7c90b5db271335765a4b0eab01f044b381b5ebd5cd", x)); diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/24/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/24/output.js index 5828184b282b..2547acc7a274 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/24/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/24/output.js @@ -5,6 +5,6 @@ export const $$RSC_SERVER_ACTION_0 = async function action($$ACTION_CLOSURE_BOUN console.log(a, b, $$ACTION_ARG_0, d); }; registerServerReference($$RSC_SERVER_ACTION_0, "7c6a88810ecce4a4e8b59d53b8327d7e98bbf251d7", null); -/* __next_internal_action_entry_do_not_use__ {"7c6a88810ecce4a4e8b59d53b8327d7e98bbf251d7":"$$RSC_SERVER_ACTION_0"} */ export default function Page({ foo, x, y }) { +/* __next_internal_action_entry_do_not_use__ {"7c6a88810ecce4a4e8b59d53b8327d7e98bbf251d7":{"name":"$$RSC_SERVER_ACTION_0"}} */ export default function Page({ foo, x, y }) { var action = $$RSC_SERVER_ACTION_0.bind(null, encryptActionBoundArgs("7c6a88810ecce4a4e8b59d53b8327d7e98bbf251d7", foo)); } diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/25/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/25/output.js index 810ae69cfd9c..ce94eb1205d1 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/25/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/25/output.js @@ -1,6 +1,6 @@ import { registerServerReference } from "private-next-rsc-server-reference"; import { encryptActionBoundArgs, decryptActionBoundArgs } from "private-next-rsc-action-encryption"; -/* __next_internal_action_entry_do_not_use__ {"406a88810ecce4a4e8b59d53b8327d7e98bbf251d7":"$$RSC_SERVER_ACTION_0","4090b5db271335765a4b0eab01f044b381b5ebd5cd":"$$RSC_SERVER_ACTION_1"} */ import { Button } from 'components'; +/* __next_internal_action_entry_do_not_use__ {"406a88810ecce4a4e8b59d53b8327d7e98bbf251d7":{"name":"$$RSC_SERVER_ACTION_0"},"4090b5db271335765a4b0eab01f044b381b5ebd5cd":{"name":"$$RSC_SERVER_ACTION_1"}} */ import { Button } from 'components'; import deleteFromDb from 'db'; export const $$RSC_SERVER_ACTION_0 = async function deleteItem($$ACTION_CLOSURE_BOUND) { var [$$ACTION_ARG_0, $$ACTION_ARG_1] = await decryptActionBoundArgs("406a88810ecce4a4e8b59d53b8327d7e98bbf251d7", $$ACTION_CLOSURE_BOUND); diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/26/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/26/output.js index 3d279d6b057d..dcdd12e43070 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/26/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/26/output.js @@ -1,5 +1,5 @@ import { registerServerReference } from "private-next-rsc-server-reference"; -/* __next_internal_action_entry_do_not_use__ {"406a88810ecce4a4e8b59d53b8327d7e98bbf251d7":"$$RSC_SERVER_ACTION_0"} */ const noop = (action)=>action; +/* __next_internal_action_entry_do_not_use__ {"406a88810ecce4a4e8b59d53b8327d7e98bbf251d7":{"name":"$$RSC_SERVER_ACTION_0"}} */ const noop = (action)=>action; export const $$RSC_SERVER_ACTION_0 = async function(data) { console.log(data); }; diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/27/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/27/output.js index ee38e802379e..756d990c72bb 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/27/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/27/output.js @@ -1,7 +1,7 @@ // Rules here: // 1. Each exported function should still be exported, but as a reference `registerServerReference(...)`. // 2. Actual action functions should be renamed to `$$ACTION_...` and got exported. -/* __next_internal_action_entry_do_not_use__ {"001c36b06e398c97abe5d5d7ae8c672bfddf4e1b91":"$$RSC_SERVER_ACTION_2","006a88810ecce4a4e8b59d53b8327d7e98bbf251d7":"$$RSC_SERVER_ACTION_0","0090b5db271335765a4b0eab01f044b381b5ebd5cd":"$$RSC_SERVER_ACTION_1","009ed0cc47abc4e1c64320cf42b74ae60b58c40f00":"$$RSC_SERVER_ACTION_3","00a9b2939c1f39073a6bed227fd20233064c8b7869":"$$RSC_SERVER_ACTION_4"} */ import { registerServerReference } from "private-next-rsc-server-reference"; +/* __next_internal_action_entry_do_not_use__ {"001c36b06e398c97abe5d5d7ae8c672bfddf4e1b91":{"name":"$$RSC_SERVER_ACTION_2"},"006a88810ecce4a4e8b59d53b8327d7e98bbf251d7":{"name":"$$RSC_SERVER_ACTION_0"},"0090b5db271335765a4b0eab01f044b381b5ebd5cd":{"name":"$$RSC_SERVER_ACTION_1"},"009ed0cc47abc4e1c64320cf42b74ae60b58c40f00":{"name":"$$RSC_SERVER_ACTION_3"},"00a9b2939c1f39073a6bed227fd20233064c8b7869":{"name":"$$RSC_SERVER_ACTION_4"}} */ import { registerServerReference } from "private-next-rsc-server-reference"; export const $$RSC_SERVER_ACTION_0 = async function foo() { console.log(1); }; diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/28/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/28/output.js index 43431c00cb7e..f934f73af3a4 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/28/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/28/output.js @@ -1,6 +1,6 @@ import { registerServerReference } from "private-next-rsc-server-reference"; import { encryptActionBoundArgs, decryptActionBoundArgs } from "private-next-rsc-action-encryption"; -/* __next_internal_action_entry_do_not_use__ {"601c36b06e398c97abe5d5d7ae8c672bfddf4e1b91":"$$RSC_SERVER_ACTION_2","606a88810ecce4a4e8b59d53b8327d7e98bbf251d7":"$$RSC_SERVER_ACTION_0","6090b5db271335765a4b0eab01f044b381b5ebd5cd":"$$RSC_SERVER_ACTION_1"} */ let a, f; +/* __next_internal_action_entry_do_not_use__ {"601c36b06e398c97abe5d5d7ae8c672bfddf4e1b91":{"name":"$$RSC_SERVER_ACTION_2"},"606a88810ecce4a4e8b59d53b8327d7e98bbf251d7":{"name":"$$RSC_SERVER_ACTION_0"},"6090b5db271335765a4b0eab01f044b381b5ebd5cd":{"name":"$$RSC_SERVER_ACTION_1"}} */ let a, f; export const // FIXME: invalid transformation of hoisted functions (https://github.com/vercel/next.js/issues/57392) // (remove output.js from `tsconfig.json#exclude` to see the error) $$RSC_SERVER_ACTION_0 = async function action2($$ACTION_CLOSURE_BOUND, e) { diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/29/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/29/output.js index 0bbf69944693..e0a2a1ddc087 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/29/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/29/output.js @@ -1,4 +1,4 @@ -/* __next_internal_action_entry_do_not_use__ {"40c18c215a6b7cdc64bf709f3a714ffdef1bf9651d":"default"} */ import { registerServerReference } from "private-next-rsc-server-reference"; +/* __next_internal_action_entry_do_not_use__ {"40c18c215a6b7cdc64bf709f3a714ffdef1bf9651d":{"name":"default"}} */ import { registerServerReference } from "private-next-rsc-server-reference"; export const dec = async (value)=>{ return value - 1; }; diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/3/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/3/output.js index 8f6423eb8c6c..8f5b24f7a2be 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/3/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/3/output.js @@ -1,5 +1,5 @@ // app/send.ts -/* __next_internal_action_entry_do_not_use__ {"70e10665baac148856374b2789aceb970f66fec33e":"myAction"} */ import { registerServerReference } from "private-next-rsc-server-reference"; +/* __next_internal_action_entry_do_not_use__ {"70e10665baac148856374b2789aceb970f66fec33e":{"name":"myAction"}} */ import { registerServerReference } from "private-next-rsc-server-reference"; export async function myAction(a, b, c) { console.log('a'); } diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/30/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/30/output.js index 1b77b56e114e..0d4a9b2792da 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/30/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/30/output.js @@ -1,4 +1,4 @@ -/* __next_internal_action_entry_do_not_use__ {"601c36b06e398c97abe5d5d7ae8c672bfddf4e1b91":"$$RSC_SERVER_ACTION_2","606a88810ecce4a4e8b59d53b8327d7e98bbf251d7":"$$RSC_SERVER_ACTION_0","6090b5db271335765a4b0eab01f044b381b5ebd5cd":"$$RSC_SERVER_ACTION_1","7f0090eaf4e1f08a2d94f6be401e54a2ded399b87c":"action0"} */ import { registerServerReference } from "private-next-rsc-server-reference"; +/* __next_internal_action_entry_do_not_use__ {"601c36b06e398c97abe5d5d7ae8c672bfddf4e1b91":{"name":"$$RSC_SERVER_ACTION_2"},"606a88810ecce4a4e8b59d53b8327d7e98bbf251d7":{"name":"$$RSC_SERVER_ACTION_0"},"6090b5db271335765a4b0eab01f044b381b5ebd5cd":{"name":"$$RSC_SERVER_ACTION_1"},"7f0090eaf4e1f08a2d94f6be401e54a2ded399b87c":{"name":"action0"}} */ import { registerServerReference } from "private-next-rsc-server-reference"; import { encryptActionBoundArgs, decryptActionBoundArgs } from "private-next-rsc-action-encryption"; let a, f; export const // FIXME: invalid transformation of hoisted functions (https://github.com/vercel/next.js/issues/57392) diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/31/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/31/output.js index c478b0519f7a..3e001619ed0c 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/31/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/31/output.js @@ -1,4 +1,4 @@ -/* __next_internal_action_entry_do_not_use__ {"7fabf760c735ba66c4c26a2913864dd7e28fb88a91":"action2","7ff14702b5a021dd117f7ec7a3c838f397c2046d3b":"action"} */ import { registerServerReference } from "private-next-rsc-server-reference"; +/* __next_internal_action_entry_do_not_use__ {"7fabf760c735ba66c4c26a2913864dd7e28fb88a91":{"name":"action2"},"7ff14702b5a021dd117f7ec7a3c838f397c2046d3b":{"name":"action"}} */ import { registerServerReference } from "private-next-rsc-server-reference"; export const action = { async f (x) { ; diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/32/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/32/output.js index 12af2b3c4cb6..8deced32a406 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/32/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/32/output.js @@ -6,7 +6,7 @@ export const $$RSC_SERVER_ACTION_0 = async function action($$ACTION_CLOSURE_BOUN console.log($$ACTION_ARG_2.push.call($$ACTION_ARG_2, 5)); }; registerServerReference($$RSC_SERVER_ACTION_0, "406a88810ecce4a4e8b59d53b8327d7e98bbf251d7", null); -/* __next_internal_action_entry_do_not_use__ {"406a88810ecce4a4e8b59d53b8327d7e98bbf251d7":"$$RSC_SERVER_ACTION_0"} */ export function Component() { +/* __next_internal_action_entry_do_not_use__ {"406a88810ecce4a4e8b59d53b8327d7e98bbf251d7":{"name":"$$RSC_SERVER_ACTION_0"}} */ export function Component() { const data = [ 1, 2, diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/33/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/33/output.js index 22903960a780..2cf58d1d9adf 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/33/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/33/output.js @@ -1,7 +1,7 @@ import { registerServerReference } from "private-next-rsc-server-reference"; import { cache as $$cache__ } from "private-next-rsc-cache-wrapper"; import { cache as $$reactCache__ } from "react"; -/* __next_internal_action_entry_do_not_use__ {"803128060c414d59f8552e4788b846c0d2b7f74743":"$$RSC_SERVER_CACHE_0"} */ const v = 'world'; +/* __next_internal_action_entry_do_not_use__ {"803128060c414d59f8552e4788b846c0d2b7f74743":{"name":"$$RSC_SERVER_CACHE_0"}} */ const v = 'world'; const $$RSC_SERVER_CACHE_0_INNER = async function fn() { return 'hello, ' + v; }; diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/34/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/34/output.js index bee49e18ca03..a54e3295e87f 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/34/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/34/output.js @@ -1,4 +1,4 @@ -/* __next_internal_action_entry_do_not_use__ {"8012a8d21b6362b4cc8f5b15560525095bc48dba80":"$$RSC_SERVER_CACHE_3","803128060c414d59f8552e4788b846c0d2b7f74743":"$$RSC_SERVER_CACHE_0","8069348c79fce073bae2f70f139565a2fda1c74c74":"$$RSC_SERVER_CACHE_2","80951c375b4a6a6e89d67b743ec5808127cfde405d":"$$RSC_SERVER_CACHE_1"} */ import { registerServerReference } from "private-next-rsc-server-reference"; +/* __next_internal_action_entry_do_not_use__ {"8012a8d21b6362b4cc8f5b15560525095bc48dba80":{"name":"$$RSC_SERVER_CACHE_3"},"803128060c414d59f8552e4788b846c0d2b7f74743":{"name":"$$RSC_SERVER_CACHE_0"},"8069348c79fce073bae2f70f139565a2fda1c74c74":{"name":"$$RSC_SERVER_CACHE_2"},"80951c375b4a6a6e89d67b743ec5808127cfde405d":{"name":"$$RSC_SERVER_CACHE_1"}} */ import { registerServerReference } from "private-next-rsc-server-reference"; import { cache as $$cache__ } from "private-next-rsc-cache-wrapper"; import { cache as $$reactCache__ } from "react"; const $$RSC_SERVER_CACHE_0_INNER = async function foo() { diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/35/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/35/output.js index 4616042e3973..17664b12996a 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/35/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/35/output.js @@ -1,4 +1,4 @@ -/* __next_internal_action_entry_do_not_use__ {"803128060c414d59f8552e4788b846c0d2b7f74743":"$$RSC_SERVER_CACHE_0"} */ import { registerServerReference } from "private-next-rsc-server-reference"; +/* __next_internal_action_entry_do_not_use__ {"803128060c414d59f8552e4788b846c0d2b7f74743":{"name":"$$RSC_SERVER_CACHE_0"}} */ import { registerServerReference } from "private-next-rsc-server-reference"; import { cache as $$cache__ } from "private-next-rsc-cache-wrapper"; import { cache as $$reactCache__ } from "react"; const $$RSC_SERVER_CACHE_0_INNER = async function my_fn() { diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/36/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/36/output.js index ac5ea18b16c1..1679cff8b3ef 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/36/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/36/output.js @@ -1,4 +1,4 @@ -/* __next_internal_action_entry_do_not_use__ {"8012a8d21b6362b4cc8f5b15560525095bc48dba80":"$$RSC_SERVER_CACHE_3","803128060c414d59f8552e4788b846c0d2b7f74743":"$$RSC_SERVER_CACHE_0","80951c375b4a6a6e89d67b743ec5808127cfde405d":"$$RSC_SERVER_CACHE_1","c069348c79fce073bae2f70f139565a2fda1c74c74":"$$RSC_SERVER_CACHE_2"} */ import { registerServerReference } from "private-next-rsc-server-reference"; +/* __next_internal_action_entry_do_not_use__ {"8012a8d21b6362b4cc8f5b15560525095bc48dba80":{"name":"$$RSC_SERVER_CACHE_3"},"803128060c414d59f8552e4788b846c0d2b7f74743":{"name":"$$RSC_SERVER_CACHE_0"},"80951c375b4a6a6e89d67b743ec5808127cfde405d":{"name":"$$RSC_SERVER_CACHE_1"},"c069348c79fce073bae2f70f139565a2fda1c74c74":{"name":"$$RSC_SERVER_CACHE_2"}} */ import { registerServerReference } from "private-next-rsc-server-reference"; import { cache as $$cache__ } from "private-next-rsc-cache-wrapper"; import { cache as $$reactCache__ } from "react"; const $$RSC_SERVER_CACHE_0_INNER = async function foo() { diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/37/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/37/output.js index 17ebd931104e..7386acaf98b6 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/37/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/37/output.js @@ -1,4 +1,4 @@ -/* __next_internal_action_entry_do_not_use__ {"803128060c414d59f8552e4788b846c0d2b7f74743":"$$RSC_SERVER_CACHE_0"} */ import { registerServerReference } from "private-next-rsc-server-reference"; +/* __next_internal_action_entry_do_not_use__ {"803128060c414d59f8552e4788b846c0d2b7f74743":{"name":"$$RSC_SERVER_CACHE_0"}} */ import { registerServerReference } from "private-next-rsc-server-reference"; import { cache as $$cache__ } from "private-next-rsc-cache-wrapper"; import { cache as $$reactCache__ } from "react"; const $$RSC_SERVER_CACHE_0_INNER = async function fn() { diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/38/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/38/output.js index 17ac1a0cc279..5ab8bf20489d 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/38/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/38/output.js @@ -1,4 +1,4 @@ -/* __next_internal_action_entry_do_not_use__ {"803128060c414d59f8552e4788b846c0d2b7f74743":"$$RSC_SERVER_CACHE_0"} */ import { registerServerReference } from "private-next-rsc-server-reference"; +/* __next_internal_action_entry_do_not_use__ {"803128060c414d59f8552e4788b846c0d2b7f74743":{"name":"$$RSC_SERVER_CACHE_0"}} */ import { registerServerReference } from "private-next-rsc-server-reference"; import { cache as $$cache__ } from "private-next-rsc-cache-wrapper"; import { cache as $$reactCache__ } from "react"; const $$RSC_SERVER_CACHE_0_INNER = async function foo() { diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/39/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/39/output.js index 0ed25c2852de..f84f3080ef5c 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/39/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/39/output.js @@ -1,4 +1,4 @@ -/* __next_internal_action_entry_do_not_use__ {"c03128060c414d59f8552e4788b846c0d2b7f74743":"$$RSC_SERVER_CACHE_0"} */ import { registerServerReference } from "private-next-rsc-server-reference"; +/* __next_internal_action_entry_do_not_use__ {"c03128060c414d59f8552e4788b846c0d2b7f74743":{"name":"$$RSC_SERVER_CACHE_0"}} */ import { registerServerReference } from "private-next-rsc-server-reference"; import { encryptActionBoundArgs, decryptActionBoundArgs } from "private-next-rsc-action-encryption"; import { cache as $$cache__ } from "private-next-rsc-cache-wrapper"; import { cache as $$reactCache__ } from "react"; diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/4/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/4/output.js index 83c692dd8527..bb78c6fb2e0e 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/4/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/4/output.js @@ -1,4 +1,4 @@ -/* __next_internal_action_entry_do_not_use__ {"001ab723c80dcca470e0410b4b2a2fc2bf21f41476":"c","006a88810ecce4a4e8b59d53b8327d7e98bbf251d7":"$$RSC_SERVER_ACTION_0","006e7bc104e4d6e7fda190c4a51be969cfd0be6d6d":"a","00d1f7eb64271d7c601dfef7d4d7053de1c2ca4338":"b"} */ import { registerServerReference } from "private-next-rsc-server-reference"; +/* __next_internal_action_entry_do_not_use__ {"001ab723c80dcca470e0410b4b2a2fc2bf21f41476":{"name":"c"},"006a88810ecce4a4e8b59d53b8327d7e98bbf251d7":{"name":"$$RSC_SERVER_ACTION_0"},"006e7bc104e4d6e7fda190c4a51be969cfd0be6d6d":{"name":"a"},"00d1f7eb64271d7c601dfef7d4d7053de1c2ca4338":{"name":"b"}} */ import { registerServerReference } from "private-next-rsc-server-reference"; export async function a() {} export async function b() {} export async function c() {} diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/40/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/40/output.js index 089e497da1d5..7c50160ba337 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/40/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/40/output.js @@ -2,7 +2,7 @@ import { registerServerReference } from "private-next-rsc-server-reference"; import { encryptActionBoundArgs, decryptActionBoundArgs } from "private-next-rsc-action-encryption"; import { cache as $$cache__ } from "private-next-rsc-cache-wrapper"; import { cache as $$reactCache__ } from "react"; -/* __next_internal_action_entry_do_not_use__ {"6090b5db271335765a4b0eab01f044b381b5ebd5cd":"$$RSC_SERVER_ACTION_1","e03128060c414d59f8552e4788b846c0d2b7f74743":"$$RSC_SERVER_CACHE_0"} */ import { Form } from 'components'; +/* __next_internal_action_entry_do_not_use__ {"6090b5db271335765a4b0eab01f044b381b5ebd5cd":{"name":"$$RSC_SERVER_ACTION_1"},"e03128060c414d59f8552e4788b846c0d2b7f74743":{"name":"$$RSC_SERVER_CACHE_0"}} */ import { Form } from 'components'; const $$RSC_SERVER_CACHE_0_INNER = async function cache([$$ACTION_ARG_0, $$ACTION_ARG_1], e) { const f = $$ACTION_ARG_0 + e; return [ diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/41/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/41/output.js index 348610ba1df3..6eb6cbb44734 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/41/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/41/output.js @@ -1,4 +1,4 @@ -/* __next_internal_action_entry_do_not_use__ {"406a88810ecce4a4e8b59d53b8327d7e98bbf251d7":"$$RSC_SERVER_ACTION_0","c0951c375b4a6a6e89d67b743ec5808127cfde405d":"$$RSC_SERVER_CACHE_1"} */ import { registerServerReference } from "private-next-rsc-server-reference"; +/* __next_internal_action_entry_do_not_use__ {"406a88810ecce4a4e8b59d53b8327d7e98bbf251d7":{"name":"$$RSC_SERVER_ACTION_0"},"c0951c375b4a6a6e89d67b743ec5808127cfde405d":{"name":"$$RSC_SERVER_CACHE_1"}} */ import { registerServerReference } from "private-next-rsc-server-reference"; import { encryptActionBoundArgs, decryptActionBoundArgs } from "private-next-rsc-action-encryption"; import { cache as $$cache__ } from "private-next-rsc-cache-wrapper"; import { cache as $$reactCache__ } from "react"; diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/42/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/42/output.js index 12afdcfab24e..8271bf654854 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/42/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/42/output.js @@ -1,4 +1,4 @@ -/* __next_internal_action_entry_do_not_use__ {"c03128060c414d59f8552e4788b846c0d2b7f74743":"$$RSC_SERVER_CACHE_0"} */ import { registerServerReference } from "private-next-rsc-server-reference"; +/* __next_internal_action_entry_do_not_use__ {"c03128060c414d59f8552e4788b846c0d2b7f74743":{"name":"$$RSC_SERVER_CACHE_0"}} */ import { registerServerReference } from "private-next-rsc-server-reference"; import { encryptActionBoundArgs, decryptActionBoundArgs } from "private-next-rsc-action-encryption"; import { cache as $$cache__ } from "private-next-rsc-cache-wrapper"; import { cache as $$reactCache__ } from "react"; diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/43/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/43/output.js index 5a37a30fa57f..d52f20e2cf6d 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/43/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/43/output.js @@ -2,7 +2,7 @@ import { registerServerReference } from "private-next-rsc-server-reference"; import { encryptActionBoundArgs, decryptActionBoundArgs } from "private-next-rsc-action-encryption"; import { cache as $$cache__ } from "private-next-rsc-cache-wrapper"; import { cache as $$reactCache__ } from "react"; -/* __next_internal_action_entry_do_not_use__ {"406a88810ecce4a4e8b59d53b8327d7e98bbf251d7":"$$RSC_SERVER_ACTION_0","e0951c375b4a6a6e89d67b743ec5808127cfde405d":"$$RSC_SERVER_CACHE_1"} */ import { Button } from 'components'; +/* __next_internal_action_entry_do_not_use__ {"406a88810ecce4a4e8b59d53b8327d7e98bbf251d7":{"name":"$$RSC_SERVER_ACTION_0"},"e0951c375b4a6a6e89d67b743ec5808127cfde405d":{"name":"$$RSC_SERVER_CACHE_1"}} */ import { Button } from 'components'; const secret = 'my password is qwerty123'; export const $$RSC_SERVER_ACTION_0 = async function action($$ACTION_CLOSURE_BOUND) { var [$$ACTION_ARG_0] = await decryptActionBoundArgs("406a88810ecce4a4e8b59d53b8327d7e98bbf251d7", $$ACTION_CLOSURE_BOUND); diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/44/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/44/output.js index a232a80a55a3..77c392a0f8b1 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/44/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/44/output.js @@ -1,5 +1,5 @@ import { registerServerReference } from "private-next-rsc-server-reference"; -/* __next_internal_action_entry_do_not_use__ {"001c36b06e398c97abe5d5d7ae8c672bfddf4e1b91":"$$RSC_SERVER_ACTION_2","006a88810ecce4a4e8b59d53b8327d7e98bbf251d7":"$$RSC_SERVER_ACTION_0","0090b5db271335765a4b0eab01f044b381b5ebd5cd":"$$RSC_SERVER_ACTION_1","009ed0cc47abc4e1c64320cf42b74ae60b58c40f00":"$$RSC_SERVER_ACTION_3","00a9b2939c1f39073a6bed227fd20233064c8b7869":"$$RSC_SERVER_ACTION_4"} */ import { Form } from 'components'; +/* __next_internal_action_entry_do_not_use__ {"001c36b06e398c97abe5d5d7ae8c672bfddf4e1b91":{"name":"$$RSC_SERVER_ACTION_2"},"006a88810ecce4a4e8b59d53b8327d7e98bbf251d7":{"name":"$$RSC_SERVER_ACTION_0"},"0090b5db271335765a4b0eab01f044b381b5ebd5cd":{"name":"$$RSC_SERVER_ACTION_1"},"009ed0cc47abc4e1c64320cf42b74ae60b58c40f00":{"name":"$$RSC_SERVER_ACTION_3"},"00a9b2939c1f39073a6bed227fd20233064c8b7869":{"name":"$$RSC_SERVER_ACTION_4"}} */ import { Form } from 'components'; export const $$RSC_SERVER_ACTION_0 = async function foo() { return 'declarator arrow function expression'; }; diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/45/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/45/output.js index 454f5eb127fb..36eae803c0b6 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/45/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/45/output.js @@ -1,4 +1,4 @@ -/* __next_internal_action_entry_do_not_use__ {"803128060c414d59f8552e4788b846c0d2b7f74743":"$$RSC_SERVER_CACHE_0"} */ import { registerServerReference } from "private-next-rsc-server-reference"; +/* __next_internal_action_entry_do_not_use__ {"803128060c414d59f8552e4788b846c0d2b7f74743":{"name":"$$RSC_SERVER_CACHE_0"}} */ import { registerServerReference } from "private-next-rsc-server-reference"; import { cache as $$cache__ } from "private-next-rsc-cache-wrapper"; import { cache as $$reactCache__ } from "react"; // Expect no error here, this is allowed to be sync because it's not exported. diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/46/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/46/output.js index 3990994bc846..eadf5480bc17 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/46/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/46/output.js @@ -3,7 +3,7 @@ import { cache as $$cache__ } from "private-next-rsc-cache-wrapper"; import { cache as $$reactCache__ } from "react"; // This is for testing the "information byte" of Server Action / Cache IDs. // Should be 1 110000 0, which is "e0" in hex. -/* __next_internal_action_entry_do_not_use__ {"6090b5db271335765a4b0eab01f044b381b5ebd5cd":"$$RSC_SERVER_ACTION_1","7c9ed0cc47abc4e1c64320cf42b74ae60b58c40f00":"$$RSC_SERVER_ACTION_3","7ea9b2939c1f39073a6bed227fd20233064c8b7869":"$$RSC_SERVER_ACTION_4","e03128060c414d59f8552e4788b846c0d2b7f74743":"$$RSC_SERVER_CACHE_0","ff471a5eb0be1c31686dd4ba938a80328b80b1615d":"$$RSC_SERVER_CACHE_5","ff69348c79fce073bae2f70f139565a2fda1c74c74":"$$RSC_SERVER_CACHE_2"} */ const $$RSC_SERVER_CACHE_0_INNER = async function f1(a, b) { +/* __next_internal_action_entry_do_not_use__ {"6090b5db271335765a4b0eab01f044b381b5ebd5cd":{"name":"$$RSC_SERVER_ACTION_1"},"7c9ed0cc47abc4e1c64320cf42b74ae60b58c40f00":{"name":"$$RSC_SERVER_ACTION_3"},"7ea9b2939c1f39073a6bed227fd20233064c8b7869":{"name":"$$RSC_SERVER_ACTION_4"},"e03128060c414d59f8552e4788b846c0d2b7f74743":{"name":"$$RSC_SERVER_CACHE_0"},"ff471a5eb0be1c31686dd4ba938a80328b80b1615d":{"name":"$$RSC_SERVER_CACHE_5"},"ff69348c79fce073bae2f70f139565a2fda1c74c74":{"name":"$$RSC_SERVER_CACHE_2"}} */ const $$RSC_SERVER_CACHE_0_INNER = async function f1(a, b) { return [ a, b diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/47/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/47/output.js index d8b9e22612d0..c7ff0b5000dc 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/47/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/47/output.js @@ -1,5 +1,5 @@ import { registerServerReference } from "private-next-rsc-server-reference"; -/* __next_internal_action_entry_do_not_use__ {"406a88810ecce4a4e8b59d53b8327d7e98bbf251d7":"$$RSC_SERVER_ACTION_0"} */ import { redirect } from 'navigation'; +/* __next_internal_action_entry_do_not_use__ {"406a88810ecce4a4e8b59d53b8327d7e98bbf251d7":{"name":"$$RSC_SERVER_ACTION_0"}} */ import { redirect } from 'navigation'; export const $$RSC_SERVER_ACTION_0 = async function action(formData) { redirect('/header?name=' + formData.get('name') + '&hidden-info=' + formData.get('hidden-info')); }; diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/48/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/48/output.js index 3774de65006d..d39c40d21ec9 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/48/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/48/output.js @@ -1,4 +1,4 @@ -/* __next_internal_action_entry_do_not_use__ {"60079087479e4c103d815f273878c7d1b8e902cc39":"action3","70f14702b5a021dd117f7ec7a3c838f397c2046d3b":"action","7fc18c215a6b7cdc64bf709f3a714ffdef1bf9651d":"default","e03128060c414d59f8552e4788b846c0d2b7f74743":"$$RSC_SERVER_CACHE_0"} */ import { registerServerReference } from "private-next-rsc-server-reference"; +/* __next_internal_action_entry_do_not_use__ {"60079087479e4c103d815f273878c7d1b8e902cc39":{"name":"action3"},"70f14702b5a021dd117f7ec7a3c838f397c2046d3b":{"name":"action"},"7fc18c215a6b7cdc64bf709f3a714ffdef1bf9651d":{"name":"default"},"e03128060c414d59f8552e4788b846c0d2b7f74743":{"name":"$$RSC_SERVER_CACHE_0"}} */ import { registerServerReference } from "private-next-rsc-server-reference"; import { cache as $$cache__ } from "private-next-rsc-cache-wrapper"; import { cache as $$reactCache__ } from "react"; // Should be 0 111000 0, which is "70" in hex. diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/49/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/49/output.js index 2343457b43d5..dec3debe1033 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/49/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/49/output.js @@ -1,4 +1,4 @@ -/* __next_internal_action_entry_do_not_use__ {"f03128060c414d59f8552e4788b846c0d2b7f74743":"$$RSC_SERVER_CACHE_0"} */ import { registerServerReference } from "private-next-rsc-server-reference"; +/* __next_internal_action_entry_do_not_use__ {"f03128060c414d59f8552e4788b846c0d2b7f74743":{"name":"$$RSC_SERVER_CACHE_0"}} */ import { registerServerReference } from "private-next-rsc-server-reference"; import { cache as $$cache__ } from "private-next-rsc-cache-wrapper"; import { cache as $$reactCache__ } from "react"; const $$RSC_SERVER_CACHE_0_INNER = async function(a, b, c) { diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/5/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/5/output.js index d7a86d577e02..25ce764085f7 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/5/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/5/output.js @@ -1,6 +1,6 @@ import { registerServerReference } from "private-next-rsc-server-reference"; import { encryptActionBoundArgs, decryptActionBoundArgs } from "private-next-rsc-action-encryption"; -/* __next_internal_action_entry_do_not_use__ {"406a88810ecce4a4e8b59d53b8327d7e98bbf251d7":"$$RSC_SERVER_ACTION_0"} */ import { Button } from 'components'; +/* __next_internal_action_entry_do_not_use__ {"406a88810ecce4a4e8b59d53b8327d7e98bbf251d7":{"name":"$$RSC_SERVER_ACTION_0"}} */ import { Button } from 'components'; import deleteFromDb from 'db'; const v1 = 'v1'; export const $$RSC_SERVER_ACTION_0 = async function deleteItem($$ACTION_CLOSURE_BOUND) { diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/50/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/50/output.js index 7d8f9c071544..d1578c0be651 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/50/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/50/output.js @@ -1,4 +1,4 @@ -/* __next_internal_action_entry_do_not_use__ {"f03128060c414d59f8552e4788b846c0d2b7f74743":"$$RSC_SERVER_CACHE_0"} */ import { registerServerReference } from "private-next-rsc-server-reference"; +/* __next_internal_action_entry_do_not_use__ {"f03128060c414d59f8552e4788b846c0d2b7f74743":{"name":"$$RSC_SERVER_CACHE_0"}} */ import { registerServerReference } from "private-next-rsc-server-reference"; import { cache as $$cache__ } from "private-next-rsc-cache-wrapper"; import { cache as $$reactCache__ } from "react"; const $$RSC_SERVER_CACHE_0_INNER = async function(a, b, c) { diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/51/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/51/output.js index 5aab76b20884..6a32fb5f4c5b 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/51/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/51/output.js @@ -1,4 +1,4 @@ -/* __next_internal_action_entry_do_not_use__ {"601c36b06e398c97abe5d5d7ae8c672bfddf4e1b91":"$$RSC_SERVER_ACTION_2","6090b5db271335765a4b0eab01f044b381b5ebd5cd":"$$RSC_SERVER_ACTION_1","706a88810ecce4a4e8b59d53b8327d7e98bbf251d7":"$$RSC_SERVER_ACTION_0"} */ import { registerServerReference } from "private-next-rsc-server-reference"; +/* __next_internal_action_entry_do_not_use__ {"601c36b06e398c97abe5d5d7ae8c672bfddf4e1b91":{"name":"$$RSC_SERVER_ACTION_2"},"6090b5db271335765a4b0eab01f044b381b5ebd5cd":{"name":"$$RSC_SERVER_ACTION_1"},"706a88810ecce4a4e8b59d53b8327d7e98bbf251d7":{"name":"$$RSC_SERVER_ACTION_0"}} */ import { registerServerReference } from "private-next-rsc-server-reference"; export const $$RSC_SERVER_ACTION_0 = async function(a, b, c) { return
{a} diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/52/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/52/output.js index a0d130d7de35..23cd75a06185 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/52/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/52/output.js @@ -2,7 +2,7 @@ import { registerServerReference } from "private-next-rsc-server-reference"; import { encryptActionBoundArgs, decryptActionBoundArgs } from "private-next-rsc-action-encryption"; import { cache as $$cache__ } from "private-next-rsc-cache-wrapper"; import { cache as $$reactCache__ } from "react"; -/* __next_internal_action_entry_do_not_use__ {"409ed0cc47abc4e1c64320cf42b74ae60b58c40f00":"$$RSC_SERVER_ACTION_3","601c36b06e398c97abe5d5d7ae8c672bfddf4e1b91":"$$RSC_SERVER_ACTION_2","c0951c375b4a6a6e89d67b743ec5808127cfde405d":"$$RSC_SERVER_CACHE_1","e03128060c414d59f8552e4788b846c0d2b7f74743":"$$RSC_SERVER_CACHE_0"} */ import { Client } from 'components'; +/* __next_internal_action_entry_do_not_use__ {"409ed0cc47abc4e1c64320cf42b74ae60b58c40f00":{"name":"$$RSC_SERVER_ACTION_3"},"601c36b06e398c97abe5d5d7ae8c672bfddf4e1b91":{"name":"$$RSC_SERVER_ACTION_2"},"c0951c375b4a6a6e89d67b743ec5808127cfde405d":{"name":"$$RSC_SERVER_CACHE_1"},"e03128060c414d59f8552e4788b846c0d2b7f74743":{"name":"$$RSC_SERVER_CACHE_0"}} */ import { Client } from 'components'; const $$RSC_SERVER_CACHE_0_INNER = async function // Should be 1 110000 0, which is "e0" in hex (counts as two params, // because of the encrypted bound args param) fn1([$$ACTION_ARG_0, $$ACTION_ARG_1], c) { diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/53/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/53/output.js index 7d74be38d005..c0f3a49bf85d 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/53/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/53/output.js @@ -11,7 +11,7 @@ Object["defineProperty"]($$RSC_SERVER_CACHE_0, "name", { }); export const $$RSC_SERVER_ACTION_1 = async function bar() {}; registerServerReference($$RSC_SERVER_ACTION_1, "0090b5db271335765a4b0eab01f044b381b5ebd5cd", null); -/* __next_internal_action_entry_do_not_use__ {"0090b5db271335765a4b0eab01f044b381b5ebd5cd":"$$RSC_SERVER_ACTION_1","803128060c414d59f8552e4788b846c0d2b7f74743":"$$RSC_SERVER_CACHE_0"} */ export const obj = { +/* __next_internal_action_entry_do_not_use__ {"0090b5db271335765a4b0eab01f044b381b5ebd5cd":{"name":"$$RSC_SERVER_ACTION_1"},"803128060c414d59f8552e4788b846c0d2b7f74743":{"name":"$$RSC_SERVER_CACHE_0"}} */ export const obj = { foo: $$RSC_SERVER_CACHE_0, bar: $$RSC_SERVER_ACTION_1 }; diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/54/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/54/output.js index 6609bac1c1e1..96cf318be666 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/54/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/54/output.js @@ -17,7 +17,7 @@ export const $$RSC_SERVER_ACTION_1 = async function bar($$ACTION_CLOSURE_BOUND) console.log($$ACTION_ARG_0); }; registerServerReference($$RSC_SERVER_ACTION_1, "4090b5db271335765a4b0eab01f044b381b5ebd5cd", null); -/* __next_internal_action_entry_do_not_use__ {"4090b5db271335765a4b0eab01f044b381b5ebd5cd":"$$RSC_SERVER_ACTION_1","c03128060c414d59f8552e4788b846c0d2b7f74743":"$$RSC_SERVER_CACHE_0"} */ function createObj(n) { +/* __next_internal_action_entry_do_not_use__ {"4090b5db271335765a4b0eab01f044b381b5ebd5cd":{"name":"$$RSC_SERVER_ACTION_1"},"c03128060c414d59f8552e4788b846c0d2b7f74743":{"name":"$$RSC_SERVER_CACHE_0"}} */ function createObj(n) { const m = n + 1; return { foo: $$RSC_SERVER_CACHE_0.bind(null, encryptActionBoundArgs("c03128060c414d59f8552e4788b846c0d2b7f74743", n, m)), diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/55/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/55/output.js index 0dc082f1f92b..27f0d660fcd8 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/55/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/55/output.js @@ -11,7 +11,7 @@ registerServerReference($$RSC_SERVER_CACHE_0, "803128060c414d59f8552e4788b846c0d Object["defineProperty"]($$RSC_SERVER_CACHE_0, "name", { value: "fetch" }); -/* __next_internal_action_entry_do_not_use__ {"803128060c414d59f8552e4788b846c0d2b7f74743":"$$RSC_SERVER_CACHE_0"} */ export const api = { +/* __next_internal_action_entry_do_not_use__ {"803128060c414d59f8552e4788b846c0d2b7f74743":{"name":"$$RSC_SERVER_CACHE_0"}} */ export const api = { product: { fetch: $$RSC_SERVER_CACHE_0 } diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/56/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/56/output.js index 06693936654e..d98987985e73 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/56/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/56/output.js @@ -1,4 +1,4 @@ -/* __next_internal_action_entry_do_not_use__ {"ffaa88e24cee8047d167e47f4f374dbddc187e2899":"fooCached"} */ import { registerServerReference } from "private-next-rsc-server-reference"; +/* __next_internal_action_entry_do_not_use__ {"ffaa88e24cee8047d167e47f4f374dbddc187e2899":{"name":"fooCached"}} */ import { registerServerReference } from "private-next-rsc-server-reference"; import { cache as $$cache__ } from "private-next-rsc-cache-wrapper"; import { cache as $$reactCache__ } from "react"; const { foo: fooCached } = { diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/57/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/57/output.js index 14b7c7e2147c..22ae9d8c8a47 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/57/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/57/output.js @@ -15,7 +15,7 @@ export const $$RSC_SERVER_ACTION_1 = async function bar() { console.log(42); }; registerServerReference($$RSC_SERVER_ACTION_1, "0090b5db271335765a4b0eab01f044b381b5ebd5cd", null); -/* __next_internal_action_entry_do_not_use__ {"0090b5db271335765a4b0eab01f044b381b5ebd5cd":"$$RSC_SERVER_ACTION_1","803128060c414d59f8552e4788b846c0d2b7f74743":"$$RSC_SERVER_CACHE_0"} */ export class MyClass { +/* __next_internal_action_entry_do_not_use__ {"0090b5db271335765a4b0eab01f044b381b5ebd5cd":{"name":"$$RSC_SERVER_ACTION_1"},"803128060c414d59f8552e4788b846c0d2b7f74743":{"name":"$$RSC_SERVER_CACHE_0"}} */ export class MyClass { static foo = $$RSC_SERVER_CACHE_0; static bar = $$RSC_SERVER_ACTION_1; } diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/58/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/58/output.js index 82d505a460f2..bb26227f6c19 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/58/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/58/output.js @@ -12,7 +12,7 @@ export var $$RSC_SERVER_CACHE_0 = $$reactCache__(function() { return $$cache__("default", "c03128060c414d59f8552e4788b846c0d2b7f74743", 1, $$RSC_SERVER_CACHE_0_INNER, Array.prototype.slice.call(arguments, 0, 1)); }); registerServerReference($$RSC_SERVER_CACHE_0, "c03128060c414d59f8552e4788b846c0d2b7f74743", null); -/* __next_internal_action_entry_do_not_use__ {"4090b5db271335765a4b0eab01f044b381b5ebd5cd":"$$RSC_SERVER_ACTION_1","c03128060c414d59f8552e4788b846c0d2b7f74743":"$$RSC_SERVER_CACHE_0"} */ function createCachedFn(start) { +/* __next_internal_action_entry_do_not_use__ {"4090b5db271335765a4b0eab01f044b381b5ebd5cd":{"name":"$$RSC_SERVER_ACTION_1"},"c03128060c414d59f8552e4788b846c0d2b7f74743":{"name":"$$RSC_SERVER_CACHE_0"}} */ function createCachedFn(start) { function fn() { return start + Math.random(); } diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/59/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/59/output.js index 1af76197aa34..e7d9b33b0177 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/59/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/59/output.js @@ -1,4 +1,4 @@ -/* __next_internal_action_entry_do_not_use__ {"00b98e10c56c1bee7af6ff753c91a4c70ab0419f0a":"test","407a40999f9833d2bb66a82d6a20a7f2a7810315f8":"createItem"} */ import { registerServerReference } from "private-next-rsc-server-reference"; +/* __next_internal_action_entry_do_not_use__ {"00b98e10c56c1bee7af6ff753c91a4c70ab0419f0a":{"name":"test"},"407a40999f9833d2bb66a82d6a20a7f2a7810315f8":{"name":"createItem"}} */ import { registerServerReference } from "private-next-rsc-server-reference"; import { db } from 'database'; export const createItem = async (title)=>{ return new Promise((resolve, reject)=>{ diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/6/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/6/output.js index 0f59a3f895c9..ab10a1612c00 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/6/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/6/output.js @@ -1,6 +1,6 @@ import { registerServerReference } from "private-next-rsc-server-reference"; import { encryptActionBoundArgs, decryptActionBoundArgs } from "private-next-rsc-action-encryption"; -/* __next_internal_action_entry_do_not_use__ {"406a88810ecce4a4e8b59d53b8327d7e98bbf251d7":"$$RSC_SERVER_ACTION_0"} */ import ANYTHING from 'anything'; +/* __next_internal_action_entry_do_not_use__ {"406a88810ecce4a4e8b59d53b8327d7e98bbf251d7":{"name":"$$RSC_SERVER_ACTION_0"}} */ import ANYTHING from 'anything'; import f, { f1, f2 } from 'foo'; import { Button } from 'components'; const f3 = 1; diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/60/output.ts b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/60/output.ts index 028d03ae3c13..fc1fe3264ab6 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/60/output.ts +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/60/output.ts @@ -1,4 +1,4 @@ -/* __next_internal_action_entry_do_not_use__ {"803128060c414d59f8552e4788b846c0d2b7f74743":"$$RSC_SERVER_CACHE_0"} */ import { registerServerReference } from "private-next-rsc-server-reference"; +/* __next_internal_action_entry_do_not_use__ {"803128060c414d59f8552e4788b846c0d2b7f74743":{"name":"$$RSC_SERVER_CACHE_0"}} */ import { registerServerReference } from "private-next-rsc-server-reference"; import { cache as $$cache__ } from "private-next-rsc-cache-wrapper"; import { cache as $$reactCache__ } from "react"; // Exported TypeScript nodes should be ignored when validating that all module diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/61/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/61/output.js index d2ad593adffa..d9d1ff2d71d8 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/61/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/61/output.js @@ -5,7 +5,7 @@ export const $$RSC_SERVER_ACTION_0 = async function action($$ACTION_CLOSURE_BOUN console.log($$ACTION_ARG_0.find((x)=>x === $$ACTION_ARG_1)); }; registerServerReference($$RSC_SERVER_ACTION_0, "406a88810ecce4a4e8b59d53b8327d7e98bbf251d7", null); -/* __next_internal_action_entry_do_not_use__ {"406a88810ecce4a4e8b59d53b8327d7e98bbf251d7":"$$RSC_SERVER_ACTION_0","4090b5db271335765a4b0eab01f044b381b5ebd5cd":"$$RSC_SERVER_ACTION_1"} */ export function ComponentA({ list, y }) { +/* __next_internal_action_entry_do_not_use__ {"406a88810ecce4a4e8b59d53b8327d7e98bbf251d7":{"name":"$$RSC_SERVER_ACTION_0"},"4090b5db271335765a4b0eab01f044b381b5ebd5cd":{"name":"$$RSC_SERVER_ACTION_1"}} */ export function ComponentA({ list, y }) { return
; diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/62/output.ts b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/62/output.ts index 63f04788b17d..4f3247041f1e 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/62/output.ts +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/62/output.ts @@ -1,4 +1,4 @@ -/* __next_internal_action_entry_do_not_use__ {"0095ef8ede0a8a4c822fcbdb018cb264731cb15281":"actionA"} */ import { registerServerReference } from "private-next-rsc-server-reference"; +/* __next_internal_action_entry_do_not_use__ {"0095ef8ede0a8a4c822fcbdb018cb264731cb15281":{"name":"actionA"}} */ import { registerServerReference } from "private-next-rsc-server-reference"; export type X = string; // @ts-ignore -- that file does not exist export { type A } from './a'; diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/63/output.tsx b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/63/output.tsx index 96fa7b35c031..e17223ed7fea 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/63/output.tsx +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/63/output.tsx @@ -1,4 +1,4 @@ -/* __next_internal_action_entry_do_not_use__ {"803128060c414d59f8552e4788b846c0d2b7f74743":"$$RSC_SERVER_CACHE_0","80951c375b4a6a6e89d67b743ec5808127cfde405d":"$$RSC_SERVER_CACHE_1","ff1acff246876a467753785a92d1f95ac6fe32c9b9":"Other","ff27fadf3eeb97c777cea9f14a407b5c0b42ac65bb":"aliased","ff438bb59117ff1af890c80ca3e39d9e888fc93033":"wrapped","ff84effee663e5ce4e0948b55df129a8df904c67aa":"Sync","ff8fa22f08e492db15701f58a1458cc4ebf782f855":"getData","ff980f8c891ae27674b86a4804d306bdb3065c2e4f":"getStuff","ffc18c215a6b7cdc64bf709f3a714ffdef1bf9651d":"default"} */ import { registerServerReference } from "private-next-rsc-server-reference"; +/* __next_internal_action_entry_do_not_use__ {"803128060c414d59f8552e4788b846c0d2b7f74743":{"name":"$$RSC_SERVER_CACHE_0"},"80951c375b4a6a6e89d67b743ec5808127cfde405d":{"name":"$$RSC_SERVER_CACHE_1"},"ff1acff246876a467753785a92d1f95ac6fe32c9b9":{"name":"Other"},"ff27fadf3eeb97c777cea9f14a407b5c0b42ac65bb":{"name":"aliased"},"ff438bb59117ff1af890c80ca3e39d9e888fc93033":{"name":"wrapped"},"ff84effee663e5ce4e0948b55df129a8df904c67aa":{"name":"Sync"},"ff8fa22f08e492db15701f58a1458cc4ebf782f855":{"name":"getData"},"ff980f8c891ae27674b86a4804d306bdb3065c2e4f":{"name":"getStuff"},"ffc18c215a6b7cdc64bf709f3a714ffdef1bf9651d":{"name":"default"}} */ import { registerServerReference } from "private-next-rsc-server-reference"; import { cache as $$cache__ } from "private-next-rsc-cache-wrapper"; import { cache as $$reactCache__ } from "react"; // @ts-ignore diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/64/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/64/output.js index 6daa39b79b97..ff0615547e7d 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/64/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/64/output.js @@ -1,4 +1,4 @@ -/* __next_internal_action_entry_do_not_use__ {"ffc18c215a6b7cdc64bf709f3a714ffdef1bf9651d":"default"} */ import { registerServerReference } from "private-next-rsc-server-reference"; +/* __next_internal_action_entry_do_not_use__ {"ffc18c215a6b7cdc64bf709f3a714ffdef1bf9651d":{"name":"default"}} */ import { registerServerReference } from "private-next-rsc-server-reference"; import { cache as $$cache__ } from "private-next-rsc-cache-wrapper"; import { cache as $$reactCache__ } from "react"; // @ts-ignore diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/65/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/65/output.js index b22e2f8e10e1..169f4aec9e1b 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/65/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/65/output.js @@ -1,4 +1,4 @@ -/* __next_internal_action_entry_do_not_use__ {"006a88810ecce4a4e8b59d53b8327d7e98bbf251d7":"$$RSC_SERVER_ACTION_0","ffc18c215a6b7cdc64bf709f3a714ffdef1bf9651d":"default"} */ import { registerServerReference } from "private-next-rsc-server-reference"; +/* __next_internal_action_entry_do_not_use__ {"006a88810ecce4a4e8b59d53b8327d7e98bbf251d7":{"name":"$$RSC_SERVER_ACTION_0"},"ffc18c215a6b7cdc64bf709f3a714ffdef1bf9651d":{"name":"default"}} */ import { registerServerReference } from "private-next-rsc-server-reference"; import { cache as $$cache__ } from "private-next-rsc-cache-wrapper"; import { cache as $$reactCache__ } from "react"; // @ts-ignore diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/66/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/66/output.js index 2437d0e338ef..9c32e7bd2161 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/66/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/66/output.js @@ -1,4 +1,4 @@ -/* __next_internal_action_entry_do_not_use__ {"0073f2cbccffb158eb2704761fc88fdbd0aaa102d0":"📙"} */ import { registerServerReference } from "private-next-rsc-server-reference"; +/* __next_internal_action_entry_do_not_use__ {"0073f2cbccffb158eb2704761fc88fdbd0aaa102d0":{"name":"📙"}} */ import { registerServerReference } from "private-next-rsc-server-reference"; async function foo() {} export { foo as '📙' }; import { ensureServerEntryExports } from "private-next-rsc-action-validate"; diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/67/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/67/output.js index 66280b823067..6a1697a78ccb 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/67/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/67/output.js @@ -1,4 +1,4 @@ -/* __next_internal_action_entry_do_not_use__ {"803128060c414d59f8552e4788b846c0d2b7f74743":"$$RSC_SERVER_CACHE_0"} */ import { registerServerReference } from "private-next-rsc-server-reference"; +/* __next_internal_action_entry_do_not_use__ {"803128060c414d59f8552e4788b846c0d2b7f74743":{"name":"$$RSC_SERVER_CACHE_0"}} */ import { registerServerReference } from "private-next-rsc-server-reference"; import { cache as $$cache__ } from "private-next-rsc-cache-wrapper"; import { cache as $$reactCache__ } from "react"; const $$RSC_SERVER_CACHE_0_INNER = async function foo() {}; diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/68/output.tsx b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/68/output.tsx index 415c968d6da1..960539a9e924 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/68/output.tsx +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/68/output.tsx @@ -1,4 +1,4 @@ -/* __next_internal_action_entry_do_not_use__ {"ffab21efdafbe611287bc25c0462b1e0510d13e48b":"foo","ffac840dcaf5e8197cb02b7f3a43c119b7a770b272":"bar"} */ import { registerServerReference } from "private-next-rsc-server-reference"; +/* __next_internal_action_entry_do_not_use__ {"ffab21efdafbe611287bc25c0462b1e0510d13e48b":{"name":"foo"},"ffac840dcaf5e8197cb02b7f3a43c119b7a770b272":{"name":"bar"}} */ import { registerServerReference } from "private-next-rsc-server-reference"; import { cache as $$cache__ } from "private-next-rsc-cache-wrapper"; import { cache as $$reactCache__ } from "react"; // @ts-ignore diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/7/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/7/output.js index 6e16e58f9a4c..e713923b0f9e 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/7/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/7/output.js @@ -1,6 +1,6 @@ import { registerServerReference } from "private-next-rsc-server-reference"; import { encryptActionBoundArgs, decryptActionBoundArgs } from "private-next-rsc-action-encryption"; -/* __next_internal_action_entry_do_not_use__ {"401c36b06e398c97abe5d5d7ae8c672bfddf4e1b91":"$$RSC_SERVER_ACTION_2","406a88810ecce4a4e8b59d53b8327d7e98bbf251d7":"$$RSC_SERVER_ACTION_0","4090b5db271335765a4b0eab01f044b381b5ebd5cd":"$$RSC_SERVER_ACTION_1","409ed0cc47abc4e1c64320cf42b74ae60b58c40f00":"$$RSC_SERVER_ACTION_3"} */ import { Button } from 'components'; +/* __next_internal_action_entry_do_not_use__ {"401c36b06e398c97abe5d5d7ae8c672bfddf4e1b91":{"name":"$$RSC_SERVER_ACTION_2"},"406a88810ecce4a4e8b59d53b8327d7e98bbf251d7":{"name":"$$RSC_SERVER_ACTION_0"},"4090b5db271335765a4b0eab01f044b381b5ebd5cd":{"name":"$$RSC_SERVER_ACTION_1"},"409ed0cc47abc4e1c64320cf42b74ae60b58c40f00":{"name":"$$RSC_SERVER_ACTION_3"}} */ import { Button } from 'components'; import deleteFromDb from 'db'; export const $$RSC_SERVER_ACTION_0 = async function deleteItem1($$ACTION_CLOSURE_BOUND) { var [$$ACTION_ARG_0, $$ACTION_ARG_1, $$ACTION_ARG_2] = await decryptActionBoundArgs("406a88810ecce4a4e8b59d53b8327d7e98bbf251d7", $$ACTION_CLOSURE_BOUND); diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/70/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/70/output.js index 3259c45b3c6d..be15d9bdd495 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/70/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/70/output.js @@ -2,7 +2,7 @@ import { registerServerReference } from "private-next-rsc-server-reference"; import { cache as $$cache__ } from "private-next-rsc-cache-wrapper"; import { cache as $$reactCache__ } from "react"; // shadow the builtin Array global (used in the transform output) -/* __next_internal_action_entry_do_not_use__ {"c03128060c414d59f8552e4788b846c0d2b7f74743":"$$RSC_SERVER_CACHE_0"} */ const Array1 = {}; +/* __next_internal_action_entry_do_not_use__ {"c03128060c414d59f8552e4788b846c0d2b7f74743":{"name":"$$RSC_SERVER_CACHE_0"}} */ const Array1 = {}; const $$RSC_SERVER_CACHE_0_INNER = async function action(x) { return x; }; diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/71/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/71/output.js index dc92360c361e..bed80ec5f5cd 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/71/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/71/output.js @@ -2,7 +2,7 @@ import { registerServerReference } from "private-next-rsc-server-reference"; import { cache as $$cache__ } from "private-next-rsc-cache-wrapper"; import { cache as $$reactCache__ } from "react"; // shadow the builtin Object global (used in transform output) -/* __next_internal_action_entry_do_not_use__ {"803128060c414d59f8552e4788b846c0d2b7f74743":"$$RSC_SERVER_CACHE_0"} */ const Object1 = {}; +/* __next_internal_action_entry_do_not_use__ {"803128060c414d59f8552e4788b846c0d2b7f74743":{"name":"$$RSC_SERVER_CACHE_0"}} */ const Object1 = {}; const $$RSC_SERVER_CACHE_0_INNER = async function foo() { return 1; }; diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/8/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/8/output.js index d0e535c0eb2c..35819c0982c3 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/8/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/8/output.js @@ -1,5 +1,5 @@ import { registerServerReference } from "private-next-rsc-server-reference"; -/* __next_internal_action_entry_do_not_use__ {"706a88810ecce4a4e8b59d53b8327d7e98bbf251d7":"$$RSC_SERVER_ACTION_0"} */ import { Button } from 'components'; +/* __next_internal_action_entry_do_not_use__ {"706a88810ecce4a4e8b59d53b8327d7e98bbf251d7":{"name":"$$RSC_SERVER_ACTION_0"}} */ import { Button } from 'components'; export const $$RSC_SERVER_ACTION_0 = async function myAction(a, b, c) { // comment 'use strict'; diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/9/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/9/output.js index dd2f527efecb..3fb992bfa7d1 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/9/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server-graph/9/output.js @@ -1,5 +1,5 @@ // app/send.ts -/* __next_internal_action_entry_do_not_use__ {"00050e3854b72b19e3c7e3966a67535543a90bf7e0":"baz","00ab21efdafbe611287bc25c0462b1e0510d13e48b":"foo","00c18c215a6b7cdc64bf709f3a714ffdef1bf9651d":"default"} */ import { registerServerReference } from "private-next-rsc-server-reference"; +/* __next_internal_action_entry_do_not_use__ {"00050e3854b72b19e3c7e3966a67535543a90bf7e0":{"name":"baz"},"00ab21efdafbe611287bc25c0462b1e0510d13e48b":{"name":"foo"},"00c18c215a6b7cdc64bf709f3a714ffdef1bf9651d":{"name":"default"}} */ import { registerServerReference } from "private-next-rsc-server-reference"; async function foo() {} export { foo }; async function bar() {} diff --git a/crates/next-custom-transforms/tests/fixture/source-maps/client-graph/development/server-actions/1/output.js b/crates/next-custom-transforms/tests/fixture/source-maps/client-graph/development/server-actions/1/output.js index d4a256595813..679768b535b1 100644 --- a/crates/next-custom-transforms/tests/fixture/source-maps/client-graph/development/server-actions/1/output.js +++ b/crates/next-custom-transforms/tests/fixture/source-maps/client-graph/development/server-actions/1/output.js @@ -1,4 +1,4 @@ -/* __next_internal_action_entry_do_not_use__ {"001e1a741f85a589443b50c4863618893572cfb178":"renamed","006c24672f968b0713dae406536f7dd6fe7d9a7fa0":"getHeaders","0073f2cbccffb158eb2704761fc88fdbd0aaa102d0":"📙","4028baf972d345b86b747ad0df73d75a0088a42214":"dec","403724e93433a7e950ef2f8479f31225e4b0dd0cc5":"redirectAction","40c18c215a6b7cdc64bf709f3a714ffdef1bf9651d":"default","40e44b877cc9d02556f56639c94229621ab0af0f5f":"inc","40f4ad91903d1bf66bfd4e0788888852badc924261":"slowInc"} */ import { createServerReference, callServer, findSourceMapURL } from "private-next-rsc-action-client-wrapper"; +/* __next_internal_action_entry_do_not_use__ {"001e1a741f85a589443b50c4863618893572cfb178":{"name":"renamed"},"006c24672f968b0713dae406536f7dd6fe7d9a7fa0":{"name":"getHeaders"},"0073f2cbccffb158eb2704761fc88fdbd0aaa102d0":{"name":"📙"},"4028baf972d345b86b747ad0df73d75a0088a42214":{"name":"dec"},"403724e93433a7e950ef2f8479f31225e4b0dd0cc5":{"name":"redirectAction"},"40c18c215a6b7cdc64bf709f3a714ffdef1bf9651d":{"name":"default"},"40e44b877cc9d02556f56639c94229621ab0af0f5f":{"name":"inc"},"40f4ad91903d1bf66bfd4e0788888852badc924261":{"name":"slowInc"}} */ import { createServerReference, callServer, findSourceMapURL } from "private-next-rsc-action-client-wrapper"; const $$RSC_SERVER_ACTION_1 = /*#__PURE__*/ createServerReference("006c24672f968b0713dae406536f7dd6fe7d9a7fa0", callServer, void 0, findSourceMapURL, "getHeaders"); export { $$RSC_SERVER_ACTION_1 as getHeaders }; const $$RSC_SERVER_ACTION_2 = /*#__PURE__*/ createServerReference("40e44b877cc9d02556f56639c94229621ab0af0f5f", callServer, void 0, findSourceMapURL, "inc"); diff --git a/crates/next-custom-transforms/tests/fixture/source-maps/client-graph/production/server-actions/1/output.js b/crates/next-custom-transforms/tests/fixture/source-maps/client-graph/production/server-actions/1/output.js index 4f47af397c6d..ea47011d8541 100644 --- a/crates/next-custom-transforms/tests/fixture/source-maps/client-graph/production/server-actions/1/output.js +++ b/crates/next-custom-transforms/tests/fixture/source-maps/client-graph/production/server-actions/1/output.js @@ -1,4 +1,4 @@ -/* __next_internal_action_entry_do_not_use__ {"001e1a741f85a589443b50c4863618893572cfb178":"renamed","006c24672f968b0713dae406536f7dd6fe7d9a7fa0":"getHeaders","0073f2cbccffb158eb2704761fc88fdbd0aaa102d0":"📙","4028baf972d345b86b747ad0df73d75a0088a42214":"dec","403724e93433a7e950ef2f8479f31225e4b0dd0cc5":"redirectAction","40c18c215a6b7cdc64bf709f3a714ffdef1bf9651d":"default","40e44b877cc9d02556f56639c94229621ab0af0f5f":"inc","40f4ad91903d1bf66bfd4e0788888852badc924261":"slowInc"} */ import { createServerReference, callServer, findSourceMapURL } from "private-next-rsc-action-client-wrapper"; +/* __next_internal_action_entry_do_not_use__ {"001e1a741f85a589443b50c4863618893572cfb178":{"name":"renamed"},"006c24672f968b0713dae406536f7dd6fe7d9a7fa0":{"name":"getHeaders"},"0073f2cbccffb158eb2704761fc88fdbd0aaa102d0":{"name":"📙"},"4028baf972d345b86b747ad0df73d75a0088a42214":{"name":"dec"},"403724e93433a7e950ef2f8479f31225e4b0dd0cc5":{"name":"redirectAction"},"40c18c215a6b7cdc64bf709f3a714ffdef1bf9651d":{"name":"default"},"40e44b877cc9d02556f56639c94229621ab0af0f5f":{"name":"inc"},"40f4ad91903d1bf66bfd4e0788888852badc924261":{"name":"slowInc"}} */ import { createServerReference, callServer, findSourceMapURL } from "private-next-rsc-action-client-wrapper"; const $$RSC_SERVER_ACTION_1 = /*#__PURE__*/ createServerReference("006c24672f968b0713dae406536f7dd6fe7d9a7fa0", callServer, void 0, findSourceMapURL, "getHeaders"); export { $$RSC_SERVER_ACTION_1 as getHeaders }; const $$RSC_SERVER_ACTION_2 = /*#__PURE__*/ createServerReference("40e44b877cc9d02556f56639c94229621ab0af0f5f", callServer, void 0, findSourceMapURL, "inc"); diff --git a/crates/next-custom-transforms/tests/fixture/source-maps/server-graph/use-cache/1/output.js b/crates/next-custom-transforms/tests/fixture/source-maps/server-graph/use-cache/1/output.js index 648b7b05b102..ad03cfa8146e 100644 --- a/crates/next-custom-transforms/tests/fixture/source-maps/server-graph/use-cache/1/output.js +++ b/crates/next-custom-transforms/tests/fixture/source-maps/server-graph/use-cache/1/output.js @@ -1,4 +1,4 @@ -/* __next_internal_action_entry_do_not_use__ {"803128060c414d59f8552e4788b846c0d2b7f74743":"$$RSC_SERVER_CACHE_0","80951c375b4a6a6e89d67b743ec5808127cfde405d":"$$RSC_SERVER_CACHE_1"} */ import { registerServerReference } from "private-next-rsc-server-reference"; +/* __next_internal_action_entry_do_not_use__ {"803128060c414d59f8552e4788b846c0d2b7f74743":{"name":"$$RSC_SERVER_CACHE_0"},"80951c375b4a6a6e89d67b743ec5808127cfde405d":{"name":"$$RSC_SERVER_CACHE_1"}} */ import { registerServerReference } from "private-next-rsc-server-reference"; import { cache as $$cache__ } from "private-next-rsc-cache-wrapper"; import { cache as $$reactCache__ } from "react"; const $$RSC_SERVER_CACHE_0_INNER = async function foo() {}; diff --git a/crates/next-custom-transforms/tests/fixture/source-maps/turbopack/client-graph/development/server-actions/1/output.js b/crates/next-custom-transforms/tests/fixture/source-maps/turbopack/client-graph/development/server-actions/1/output.js index b7c59d3ce8a8..ff4deaf40091 100644 --- a/crates/next-custom-transforms/tests/fixture/source-maps/turbopack/client-graph/development/server-actions/1/output.js +++ b/crates/next-custom-transforms/tests/fixture/source-maps/turbopack/client-graph/development/server-actions/1/output.js @@ -1,9 +1,9 @@ "use turbopack no side effects"; -export { getHeaders } from "data:text/javascript,%2F%2A%20__next_internal_action_entry_do_not_use__%20%5B%7B%22006c24672f968b0713dae406536f7dd6fe7d9a7fa0%22%3A%22getHeaders%22%7D%2C%22%2Fapp%2Fitem.js%22%2C%22%22%5D%20%2A%2F%22use%20turbopack%20no%20side%20effects%22%3Bimport%7BcreateServerReference%2CcallServer%2CfindSourceMapURL%7Dfrom%22private-next-rsc-action-client-wrapper%22%3Bconst%20%24%24RSC_SERVER_ACTION_1%3D%2F%2A%23__PURE__%2A%2FcreateServerReference%28%22006c24672f968b0713dae406536f7dd6fe7d9a7fa0%22%2CcallServer%2Cvoid%200%2CfindSourceMapURL%2C%22getHeaders%22%29%3Bexport%7B%24%24RSC_SERVER_ACTION_1%20as%20getHeaders%7D%3B%0A%2F%2F%23%20sourceMappingURL%3Ddata%3Aapplication%2Fjson%3Bbase64%2CeyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImlucHV0LmpzIl0sInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc2VydmVyJ1xuXG5pbXBvcnQgJ3NlcnZlci1vbmx5J1xuXG5pbXBvcnQgeyByZWRpcmVjdCB9IGZyb20gJ25leHQvbmF2aWdhdGlvbidcbmltcG9ydCB7IGhlYWRlcnMsIGNvb2tpZXMgfSBmcm9tICduZXh0L2hlYWRlcnMnXG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRIZWFkZXJzKCkge1xuICBjb25zb2xlLmxvZygnYWNjZXB0IGhlYWRlcjonLCAoYXdhaXQgaGVhZGVycygpKS5nZXQoJ2FjY2VwdCcpKVxuICA7KGF3YWl0IGNvb2tpZXMoKSkuc2V0KCd0ZXN0LWNvb2tpZScsIERhdGUubm93KCkpXG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBpbmModmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlICsgMVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2xvd0luYyh2YWx1ZSkge1xuICBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4gc2V0VGltZW91dChyZXNvbHZlLCAxMDAwMCkpXG4gIHJldHVybiB2YWx1ZSArIDFcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRlYyh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgLSAxXG59XG5cbmV4cG9ydCBkZWZhdWx0IGFzeW5jIGZ1bmN0aW9uICh2YWx1ZSkge1xuICBjb25zb2xlLmxvZygndGhpc19pc19zZW5zaXRpdmVfaW5mbycpXG4gIHJldHVybiB2YWx1ZSAqIDJcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlZGlyZWN0QWN0aW9uKHBhdGgpIHtcbiAgcmVkaXJlY3QocGF0aClcbn1cblxuY29uc3Qgb3JpZ2luYWwgPSBhc3luYyAoKSA9PiB7XG4gIGNvbnNvbGUubG9nKCdhY3Rpb24nKVxufVxuZXhwb3J0IHsgb3JpZ2luYWwgYXMgcmVuYW1lZCB9XG5cbmV4cG9ydCB7IGZvbyBhcyAn8J%2BTmScgfVxuYXN5bmMgZnVuY3Rpb24gZm9vKCkge31cbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiMlFBT3NCLHVMQUFBIn0%3D"; -export { inc } from "data:text/javascript,%2F%2A%20__next_internal_action_entry_do_not_use__%20%5B%7B%2240e44b877cc9d02556f56639c94229621ab0af0f5f%22%3A%22inc%22%7D%2C%22%2Fapp%2Fitem.js%22%2C%22%22%5D%20%2A%2F%22use%20turbopack%20no%20side%20effects%22%3Bimport%7BcreateServerReference%2CcallServer%2CfindSourceMapURL%7Dfrom%22private-next-rsc-action-client-wrapper%22%3Bconst%20%24%24RSC_SERVER_ACTION_2%3D%2F%2A%23__PURE__%2A%2FcreateServerReference%28%2240e44b877cc9d02556f56639c94229621ab0af0f5f%22%2CcallServer%2Cvoid%200%2CfindSourceMapURL%2C%22inc%22%29%3Bexport%7B%24%24RSC_SERVER_ACTION_2%20as%20inc%7D%3B%0A%2F%2F%23%20sourceMappingURL%3Ddata%3Aapplication%2Fjson%3Bbase64%2CeyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImlucHV0LmpzIl0sInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc2VydmVyJ1xuXG5pbXBvcnQgJ3NlcnZlci1vbmx5J1xuXG5pbXBvcnQgeyByZWRpcmVjdCB9IGZyb20gJ25leHQvbmF2aWdhdGlvbidcbmltcG9ydCB7IGhlYWRlcnMsIGNvb2tpZXMgfSBmcm9tICduZXh0L2hlYWRlcnMnXG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRIZWFkZXJzKCkge1xuICBjb25zb2xlLmxvZygnYWNjZXB0IGhlYWRlcjonLCAoYXdhaXQgaGVhZGVycygpKS5nZXQoJ2FjY2VwdCcpKVxuICA7KGF3YWl0IGNvb2tpZXMoKSkuc2V0KCd0ZXN0LWNvb2tpZScsIERhdGUubm93KCkpXG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBpbmModmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlICsgMVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2xvd0luYyh2YWx1ZSkge1xuICBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4gc2V0VGltZW91dChyZXNvbHZlLCAxMDAwMCkpXG4gIHJldHVybiB2YWx1ZSArIDFcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRlYyh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgLSAxXG59XG5cbmV4cG9ydCBkZWZhdWx0IGFzeW5jIGZ1bmN0aW9uICh2YWx1ZSkge1xuICBjb25zb2xlLmxvZygndGhpc19pc19zZW5zaXRpdmVfaW5mbycpXG4gIHJldHVybiB2YWx1ZSAqIDJcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlZGlyZWN0QWN0aW9uKHBhdGgpIHtcbiAgcmVkaXJlY3QocGF0aClcbn1cblxuY29uc3Qgb3JpZ2luYWwgPSBhc3luYyAoKSA9PiB7XG4gIGNvbnNvbGUubG9nKCdhY3Rpb24nKVxufVxuZXhwb3J0IHsgb3JpZ2luYWwgYXMgcmVuYW1lZCB9XG5cbmV4cG9ydCB7IGZvbyBhcyAn8J%2BTmScgfVxuYXN5bmMgZnVuY3Rpb24gZm9vKCkge31cbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoib1FBWXNCLGdMQUFBIn0%3D"; -export { slowInc } from "data:text/javascript,%2F%2A%20__next_internal_action_entry_do_not_use__%20%5B%7B%2240f4ad91903d1bf66bfd4e0788888852badc924261%22%3A%22slowInc%22%7D%2C%22%2Fapp%2Fitem.js%22%2C%22%22%5D%20%2A%2F%22use%20turbopack%20no%20side%20effects%22%3Bimport%7BcreateServerReference%2CcallServer%2CfindSourceMapURL%7Dfrom%22private-next-rsc-action-client-wrapper%22%3Bconst%20%24%24RSC_SERVER_ACTION_3%3D%2F%2A%23__PURE__%2A%2FcreateServerReference%28%2240f4ad91903d1bf66bfd4e0788888852badc924261%22%2CcallServer%2Cvoid%200%2CfindSourceMapURL%2C%22slowInc%22%29%3Bexport%7B%24%24RSC_SERVER_ACTION_3%20as%20slowInc%7D%3B%0A%2F%2F%23%20sourceMappingURL%3Ddata%3Aapplication%2Fjson%3Bbase64%2CeyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImlucHV0LmpzIl0sInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc2VydmVyJ1xuXG5pbXBvcnQgJ3NlcnZlci1vbmx5J1xuXG5pbXBvcnQgeyByZWRpcmVjdCB9IGZyb20gJ25leHQvbmF2aWdhdGlvbidcbmltcG9ydCB7IGhlYWRlcnMsIGNvb2tpZXMgfSBmcm9tICduZXh0L2hlYWRlcnMnXG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRIZWFkZXJzKCkge1xuICBjb25zb2xlLmxvZygnYWNjZXB0IGhlYWRlcjonLCAoYXdhaXQgaGVhZGVycygpKS5nZXQoJ2FjY2VwdCcpKVxuICA7KGF3YWl0IGNvb2tpZXMoKSkuc2V0KCd0ZXN0LWNvb2tpZScsIERhdGUubm93KCkpXG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBpbmModmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlICsgMVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2xvd0luYyh2YWx1ZSkge1xuICBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4gc2V0VGltZW91dChyZXNvbHZlLCAxMDAwMCkpXG4gIHJldHVybiB2YWx1ZSArIDFcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRlYyh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgLSAxXG59XG5cbmV4cG9ydCBkZWZhdWx0IGFzeW5jIGZ1bmN0aW9uICh2YWx1ZSkge1xuICBjb25zb2xlLmxvZygndGhpc19pc19zZW5zaXRpdmVfaW5mbycpXG4gIHJldHVybiB2YWx1ZSAqIDJcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlZGlyZWN0QWN0aW9uKHBhdGgpIHtcbiAgcmVkaXJlY3QocGF0aClcbn1cblxuY29uc3Qgb3JpZ2luYWwgPSBhc3luYyAoKSA9PiB7XG4gIGNvbnNvbGUubG9nKCdhY3Rpb24nKVxufVxuZXhwb3J0IHsgb3JpZ2luYWwgYXMgcmVuYW1lZCB9XG5cbmV4cG9ydCB7IGZvbyBhcyAn8J%2BTmScgfVxuYXN5bmMgZnVuY3Rpb24gZm9vKCkge31cbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoid1FBZ0JzQixvTEFBQSJ9"; -export { dec } from "data:text/javascript,%2F%2A%20__next_internal_action_entry_do_not_use__%20%5B%7B%224028baf972d345b86b747ad0df73d75a0088a42214%22%3A%22dec%22%7D%2C%22%2Fapp%2Fitem.js%22%2C%22%22%5D%20%2A%2F%22use%20turbopack%20no%20side%20effects%22%3Bimport%7BcreateServerReference%2CcallServer%2CfindSourceMapURL%7Dfrom%22private-next-rsc-action-client-wrapper%22%3Bconst%20%24%24RSC_SERVER_ACTION_4%3D%2F%2A%23__PURE__%2A%2FcreateServerReference%28%224028baf972d345b86b747ad0df73d75a0088a42214%22%2CcallServer%2Cvoid%200%2CfindSourceMapURL%2C%22dec%22%29%3Bexport%7B%24%24RSC_SERVER_ACTION_4%20as%20dec%7D%3B%0A%2F%2F%23%20sourceMappingURL%3Ddata%3Aapplication%2Fjson%3Bbase64%2CeyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImlucHV0LmpzIl0sInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc2VydmVyJ1xuXG5pbXBvcnQgJ3NlcnZlci1vbmx5J1xuXG5pbXBvcnQgeyByZWRpcmVjdCB9IGZyb20gJ25leHQvbmF2aWdhdGlvbidcbmltcG9ydCB7IGhlYWRlcnMsIGNvb2tpZXMgfSBmcm9tICduZXh0L2hlYWRlcnMnXG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRIZWFkZXJzKCkge1xuICBjb25zb2xlLmxvZygnYWNjZXB0IGhlYWRlcjonLCAoYXdhaXQgaGVhZGVycygpKS5nZXQoJ2FjY2VwdCcpKVxuICA7KGF3YWl0IGNvb2tpZXMoKSkuc2V0KCd0ZXN0LWNvb2tpZScsIERhdGUubm93KCkpXG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBpbmModmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlICsgMVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2xvd0luYyh2YWx1ZSkge1xuICBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4gc2V0VGltZW91dChyZXNvbHZlLCAxMDAwMCkpXG4gIHJldHVybiB2YWx1ZSArIDFcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRlYyh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgLSAxXG59XG5cbmV4cG9ydCBkZWZhdWx0IGFzeW5jIGZ1bmN0aW9uICh2YWx1ZSkge1xuICBjb25zb2xlLmxvZygndGhpc19pc19zZW5zaXRpdmVfaW5mbycpXG4gIHJldHVybiB2YWx1ZSAqIDJcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlZGlyZWN0QWN0aW9uKHBhdGgpIHtcbiAgcmVkaXJlY3QocGF0aClcbn1cblxuY29uc3Qgb3JpZ2luYWwgPSBhc3luYyAoKSA9PiB7XG4gIGNvbnNvbGUubG9nKCdhY3Rpb24nKVxufVxuZXhwb3J0IHsgb3JpZ2luYWwgYXMgcmVuYW1lZCB9XG5cbmV4cG9ydCB7IGZvbyBhcyAn8J%2BTmScgfVxuYXN5bmMgZnVuY3Rpb24gZm9vKCkge31cbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoib1FBcUJzQixnTEFBQSJ9"; -export { default } from "data:text/javascript,%2F%2A%20__next_internal_action_entry_do_not_use__%20%5B%7B%2240c18c215a6b7cdc64bf709f3a714ffdef1bf9651d%22%3A%22default%22%7D%2C%22%2Fapp%2Fitem.js%22%2C%22%22%5D%20%2A%2F%22use%20turbopack%20no%20side%20effects%22%3Bimport%7BcreateServerReference%2CcallServer%2CfindSourceMapURL%7Dfrom%22private-next-rsc-action-client-wrapper%22%3Bexport%20default%20createServerReference%28%2240c18c215a6b7cdc64bf709f3a714ffdef1bf9651d%22%2CcallServer%2Cvoid%200%2CfindSourceMapURL%2C%22default%22%29%3B%0A%2F%2F%23%20sourceMappingURL%3Ddata%3Aapplication%2Fjson%3Bbase64%2CeyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImlucHV0LmpzIl0sInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc2VydmVyJ1xuXG5pbXBvcnQgJ3NlcnZlci1vbmx5J1xuXG5pbXBvcnQgeyByZWRpcmVjdCB9IGZyb20gJ25leHQvbmF2aWdhdGlvbidcbmltcG9ydCB7IGhlYWRlcnMsIGNvb2tpZXMgfSBmcm9tICduZXh0L2hlYWRlcnMnXG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRIZWFkZXJzKCkge1xuICBjb25zb2xlLmxvZygnYWNjZXB0IGhlYWRlcjonLCAoYXdhaXQgaGVhZGVycygpKS5nZXQoJ2FjY2VwdCcpKVxuICA7KGF3YWl0IGNvb2tpZXMoKSkuc2V0KCd0ZXN0LWNvb2tpZScsIERhdGUubm93KCkpXG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBpbmModmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlICsgMVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2xvd0luYyh2YWx1ZSkge1xuICBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4gc2V0VGltZW91dChyZXNvbHZlLCAxMDAwMCkpXG4gIHJldHVybiB2YWx1ZSArIDFcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRlYyh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgLSAxXG59XG5cbmV4cG9ydCBkZWZhdWx0IGFzeW5jIGZ1bmN0aW9uICh2YWx1ZSkge1xuICBjb25zb2xlLmxvZygndGhpc19pc19zZW5zaXRpdmVfaW5mbycpXG4gIHJldHVybiB2YWx1ZSAqIDJcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlZGlyZWN0QWN0aW9uKHBhdGgpIHtcbiAgcmVkaXJlY3QocGF0aClcbn1cblxuY29uc3Qgb3JpZ2luYWwgPSBhc3luYyAoKSA9PiB7XG4gIGNvbnNvbGUubG9nKCdhY3Rpb24nKVxufVxuZXhwb3J0IHsgb3JpZ2luYWwgYXMgcmVuYW1lZCB9XG5cbmV4cG9ydCB7IGZvbyBhcyAn8J%2BTmScgfVxuYXN5bmMgZnVuY3Rpb24gZm9vKCkge31cbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiaVJBeUJlIn0%3D"; -export { redirectAction } from "data:text/javascript,%2F%2A%20__next_internal_action_entry_do_not_use__%20%5B%7B%22403724e93433a7e950ef2f8479f31225e4b0dd0cc5%22%3A%22redirectAction%22%7D%2C%22%2Fapp%2Fitem.js%22%2C%22%22%5D%20%2A%2F%22use%20turbopack%20no%20side%20effects%22%3Bimport%7BcreateServerReference%2CcallServer%2CfindSourceMapURL%7Dfrom%22private-next-rsc-action-client-wrapper%22%3Bconst%20%24%24RSC_SERVER_ACTION_5%3D%2F%2A%23__PURE__%2A%2FcreateServerReference%28%22403724e93433a7e950ef2f8479f31225e4b0dd0cc5%22%2CcallServer%2Cvoid%200%2CfindSourceMapURL%2C%22redirectAction%22%29%3Bexport%7B%24%24RSC_SERVER_ACTION_5%20as%20redirectAction%7D%3B%0A%2F%2F%23%20sourceMappingURL%3Ddata%3Aapplication%2Fjson%3Bbase64%2CeyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImlucHV0LmpzIl0sInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc2VydmVyJ1xuXG5pbXBvcnQgJ3NlcnZlci1vbmx5J1xuXG5pbXBvcnQgeyByZWRpcmVjdCB9IGZyb20gJ25leHQvbmF2aWdhdGlvbidcbmltcG9ydCB7IGhlYWRlcnMsIGNvb2tpZXMgfSBmcm9tICduZXh0L2hlYWRlcnMnXG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRIZWFkZXJzKCkge1xuICBjb25zb2xlLmxvZygnYWNjZXB0IGhlYWRlcjonLCAoYXdhaXQgaGVhZGVycygpKS5nZXQoJ2FjY2VwdCcpKVxuICA7KGF3YWl0IGNvb2tpZXMoKSkuc2V0KCd0ZXN0LWNvb2tpZScsIERhdGUubm93KCkpXG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBpbmModmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlICsgMVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2xvd0luYyh2YWx1ZSkge1xuICBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4gc2V0VGltZW91dChyZXNvbHZlLCAxMDAwMCkpXG4gIHJldHVybiB2YWx1ZSArIDFcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRlYyh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgLSAxXG59XG5cbmV4cG9ydCBkZWZhdWx0IGFzeW5jIGZ1bmN0aW9uICh2YWx1ZSkge1xuICBjb25zb2xlLmxvZygndGhpc19pc19zZW5zaXRpdmVfaW5mbycpXG4gIHJldHVybiB2YWx1ZSAqIDJcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlZGlyZWN0QWN0aW9uKHBhdGgpIHtcbiAgcmVkaXJlY3QocGF0aClcbn1cblxuY29uc3Qgb3JpZ2luYWwgPSBhc3luYyAoKSA9PiB7XG4gIGNvbnNvbGUubG9nKCdhY3Rpb24nKVxufVxuZXhwb3J0IHsgb3JpZ2luYWwgYXMgcmVuYW1lZCB9XG5cbmV4cG9ydCB7IGZvbyBhcyAn8J%2BTmScgfVxuYXN5bmMgZnVuY3Rpb24gZm9vKCkge31cbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiK1FBOEJzQiwyTEFBQSJ9"; -export { renamed } from "data:text/javascript,%2F%2A%20__next_internal_action_entry_do_not_use__%20%5B%7B%22001e1a741f85a589443b50c4863618893572cfb178%22%3A%22renamed%22%7D%2C%22%2Fapp%2Fitem.js%22%2C%22%22%5D%20%2A%2F%22use%20turbopack%20no%20side%20effects%22%3Bimport%7BcreateServerReference%2CcallServer%2CfindSourceMapURL%7Dfrom%22private-next-rsc-action-client-wrapper%22%3Bconst%20%24%24RSC_SERVER_ACTION_6%3D%2F%2A%23__PURE__%2A%2FcreateServerReference%28%22001e1a741f85a589443b50c4863618893572cfb178%22%2CcallServer%2Cvoid%200%2CfindSourceMapURL%2C%22renamed%22%29%3Bexport%7B%24%24RSC_SERVER_ACTION_6%20as%20renamed%7D%3B%0A%2F%2F%23%20sourceMappingURL%3Ddata%3Aapplication%2Fjson%3Bbase64%2CeyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImlucHV0LmpzIl0sInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc2VydmVyJ1xuXG5pbXBvcnQgJ3NlcnZlci1vbmx5J1xuXG5pbXBvcnQgeyByZWRpcmVjdCB9IGZyb20gJ25leHQvbmF2aWdhdGlvbidcbmltcG9ydCB7IGhlYWRlcnMsIGNvb2tpZXMgfSBmcm9tICduZXh0L2hlYWRlcnMnXG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRIZWFkZXJzKCkge1xuICBjb25zb2xlLmxvZygnYWNjZXB0IGhlYWRlcjonLCAoYXdhaXQgaGVhZGVycygpKS5nZXQoJ2FjY2VwdCcpKVxuICA7KGF3YWl0IGNvb2tpZXMoKSkuc2V0KCd0ZXN0LWNvb2tpZScsIERhdGUubm93KCkpXG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBpbmModmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlICsgMVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2xvd0luYyh2YWx1ZSkge1xuICBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4gc2V0VGltZW91dChyZXNvbHZlLCAxMDAwMCkpXG4gIHJldHVybiB2YWx1ZSArIDFcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRlYyh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgLSAxXG59XG5cbmV4cG9ydCBkZWZhdWx0IGFzeW5jIGZ1bmN0aW9uICh2YWx1ZSkge1xuICBjb25zb2xlLmxvZygndGhpc19pc19zZW5zaXRpdmVfaW5mbycpXG4gIHJldHVybiB2YWx1ZSAqIDJcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlZGlyZWN0QWN0aW9uKHBhdGgpIHtcbiAgcmVkaXJlY3QocGF0aClcbn1cblxuY29uc3Qgb3JpZ2luYWwgPSBhc3luYyAoKSA9PiB7XG4gIGNvbnNvbGUubG9nKCdhY3Rpb24nKVxufVxuZXhwb3J0IHsgb3JpZ2luYWwgYXMgcmVuYW1lZCB9XG5cbmV4cG9ydCB7IGZvbyBhcyAn8J%2BTmScgfVxuYXN5bmMgZnVuY3Rpb24gZm9vKCkge31cbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoid1FBa0NNLG9MQUdlIn0%3D"; -export { "📙" } from "data:text/javascript,%2F%2A%20__next_internal_action_entry_do_not_use__%20%5B%7B%220073f2cbccffb158eb2704761fc88fdbd0aaa102d0%22%3A%22%F0%9F%93%99%22%7D%2C%22%2Fapp%2Fitem.js%22%2C%22%22%5D%20%2A%2F%22use%20turbopack%20no%20side%20effects%22%3Bimport%7BcreateServerReference%2CcallServer%2CfindSourceMapURL%7Dfrom%22private-next-rsc-action-client-wrapper%22%3Bconst%20%24%24RSC_SERVER_ACTION_7%3D%2F%2A%23__PURE__%2A%2FcreateServerReference%28%220073f2cbccffb158eb2704761fc88fdbd0aaa102d0%22%2CcallServer%2Cvoid%200%2CfindSourceMapURL%2C%22%F0%9F%93%99%22%29%3Bexport%7B%24%24RSC_SERVER_ACTION_7%20as%20%22%F0%9F%93%99%22%7D%3B%0A%2F%2F%23%20sourceMappingURL%3Ddata%3Aapplication%2Fjson%3Bbase64%2CeyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImlucHV0LmpzIl0sInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc2VydmVyJ1xuXG5pbXBvcnQgJ3NlcnZlci1vbmx5J1xuXG5pbXBvcnQgeyByZWRpcmVjdCB9IGZyb20gJ25leHQvbmF2aWdhdGlvbidcbmltcG9ydCB7IGhlYWRlcnMsIGNvb2tpZXMgfSBmcm9tICduZXh0L2hlYWRlcnMnXG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRIZWFkZXJzKCkge1xuICBjb25zb2xlLmxvZygnYWNjZXB0IGhlYWRlcjonLCAoYXdhaXQgaGVhZGVycygpKS5nZXQoJ2FjY2VwdCcpKVxuICA7KGF3YWl0IGNvb2tpZXMoKSkuc2V0KCd0ZXN0LWNvb2tpZScsIERhdGUubm93KCkpXG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBpbmModmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlICsgMVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2xvd0luYyh2YWx1ZSkge1xuICBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4gc2V0VGltZW91dChyZXNvbHZlLCAxMDAwMCkpXG4gIHJldHVybiB2YWx1ZSArIDFcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRlYyh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgLSAxXG59XG5cbmV4cG9ydCBkZWZhdWx0IGFzeW5jIGZ1bmN0aW9uICh2YWx1ZSkge1xuICBjb25zb2xlLmxvZygndGhpc19pc19zZW5zaXRpdmVfaW5mbycpXG4gIHJldHVybiB2YWx1ZSAqIDJcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlZGlyZWN0QWN0aW9uKHBhdGgpIHtcbiAgcmVkaXJlY3QocGF0aClcbn1cblxuY29uc3Qgb3JpZ2luYWwgPSBhc3luYyAoKSA9PiB7XG4gIGNvbnNvbGUubG9nKCdhY3Rpb24nKVxufVxuZXhwb3J0IHsgb3JpZ2luYWwgYXMgcmVuYW1lZCB9XG5cbmV4cG9ydCB7IGZvbyBhcyAn8J%2BTmScgfVxuYXN5bmMgZnVuY3Rpb24gZm9vKCkge31cbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoibVFBd0NlLCtLQURDIn0%3D"; +export { getHeaders } from "data:text/javascript,%2F%2A%20__next_internal_action_entry_do_not_use__%20%5B%7B%22006c24672f968b0713dae406536f7dd6fe7d9a7fa0%22%3A%7B%22name%22%3A%22getHeaders%22%7D%7D%2C%22%2Fapp%2Fitem.js%22%2C%22%22%5D%20%2A%2F%22use%20turbopack%20no%20side%20effects%22%3Bimport%7BcreateServerReference%2CcallServer%2CfindSourceMapURL%7Dfrom%22private-next-rsc-action-client-wrapper%22%3Bconst%20%24%24RSC_SERVER_ACTION_1%3D%2F%2A%23__PURE__%2A%2FcreateServerReference%28%22006c24672f968b0713dae406536f7dd6fe7d9a7fa0%22%2CcallServer%2Cvoid%200%2CfindSourceMapURL%2C%22getHeaders%22%29%3Bexport%7B%24%24RSC_SERVER_ACTION_1%20as%20getHeaders%7D%3B%0A%2F%2F%23%20sourceMappingURL%3Ddata%3Aapplication%2Fjson%3Bbase64%2CeyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImlucHV0LmpzIl0sInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc2VydmVyJ1xuXG5pbXBvcnQgJ3NlcnZlci1vbmx5J1xuXG5pbXBvcnQgeyByZWRpcmVjdCB9IGZyb20gJ25leHQvbmF2aWdhdGlvbidcbmltcG9ydCB7IGhlYWRlcnMsIGNvb2tpZXMgfSBmcm9tICduZXh0L2hlYWRlcnMnXG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRIZWFkZXJzKCkge1xuICBjb25zb2xlLmxvZygnYWNjZXB0IGhlYWRlcjonLCAoYXdhaXQgaGVhZGVycygpKS5nZXQoJ2FjY2VwdCcpKVxuICA7KGF3YWl0IGNvb2tpZXMoKSkuc2V0KCd0ZXN0LWNvb2tpZScsIERhdGUubm93KCkpXG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBpbmModmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlICsgMVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2xvd0luYyh2YWx1ZSkge1xuICBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4gc2V0VGltZW91dChyZXNvbHZlLCAxMDAwMCkpXG4gIHJldHVybiB2YWx1ZSArIDFcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRlYyh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgLSAxXG59XG5cbmV4cG9ydCBkZWZhdWx0IGFzeW5jIGZ1bmN0aW9uICh2YWx1ZSkge1xuICBjb25zb2xlLmxvZygndGhpc19pc19zZW5zaXRpdmVfaW5mbycpXG4gIHJldHVybiB2YWx1ZSAqIDJcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlZGlyZWN0QWN0aW9uKHBhdGgpIHtcbiAgcmVkaXJlY3QocGF0aClcbn1cblxuY29uc3Qgb3JpZ2luYWwgPSBhc3luYyAoKSA9PiB7XG4gIGNvbnNvbGUubG9nKCdhY3Rpb24nKVxufVxuZXhwb3J0IHsgb3JpZ2luYWwgYXMgcmVuYW1lZCB9XG5cbmV4cG9ydCB7IGZvbyBhcyAn8J%2BTmScgfVxuYXN5bmMgZnVuY3Rpb24gZm9vKCkge31cbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoib1JBT3NCLHVMQUFBIn0%3D"; +export { inc } from "data:text/javascript,%2F%2A%20__next_internal_action_entry_do_not_use__%20%5B%7B%2240e44b877cc9d02556f56639c94229621ab0af0f5f%22%3A%7B%22name%22%3A%22inc%22%7D%7D%2C%22%2Fapp%2Fitem.js%22%2C%22%22%5D%20%2A%2F%22use%20turbopack%20no%20side%20effects%22%3Bimport%7BcreateServerReference%2CcallServer%2CfindSourceMapURL%7Dfrom%22private-next-rsc-action-client-wrapper%22%3Bconst%20%24%24RSC_SERVER_ACTION_2%3D%2F%2A%23__PURE__%2A%2FcreateServerReference%28%2240e44b877cc9d02556f56639c94229621ab0af0f5f%22%2CcallServer%2Cvoid%200%2CfindSourceMapURL%2C%22inc%22%29%3Bexport%7B%24%24RSC_SERVER_ACTION_2%20as%20inc%7D%3B%0A%2F%2F%23%20sourceMappingURL%3Ddata%3Aapplication%2Fjson%3Bbase64%2CeyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImlucHV0LmpzIl0sInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc2VydmVyJ1xuXG5pbXBvcnQgJ3NlcnZlci1vbmx5J1xuXG5pbXBvcnQgeyByZWRpcmVjdCB9IGZyb20gJ25leHQvbmF2aWdhdGlvbidcbmltcG9ydCB7IGhlYWRlcnMsIGNvb2tpZXMgfSBmcm9tICduZXh0L2hlYWRlcnMnXG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRIZWFkZXJzKCkge1xuICBjb25zb2xlLmxvZygnYWNjZXB0IGhlYWRlcjonLCAoYXdhaXQgaGVhZGVycygpKS5nZXQoJ2FjY2VwdCcpKVxuICA7KGF3YWl0IGNvb2tpZXMoKSkuc2V0KCd0ZXN0LWNvb2tpZScsIERhdGUubm93KCkpXG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBpbmModmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlICsgMVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2xvd0luYyh2YWx1ZSkge1xuICBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4gc2V0VGltZW91dChyZXNvbHZlLCAxMDAwMCkpXG4gIHJldHVybiB2YWx1ZSArIDFcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRlYyh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgLSAxXG59XG5cbmV4cG9ydCBkZWZhdWx0IGFzeW5jIGZ1bmN0aW9uICh2YWx1ZSkge1xuICBjb25zb2xlLmxvZygndGhpc19pc19zZW5zaXRpdmVfaW5mbycpXG4gIHJldHVybiB2YWx1ZSAqIDJcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlZGlyZWN0QWN0aW9uKHBhdGgpIHtcbiAgcmVkaXJlY3QocGF0aClcbn1cblxuY29uc3Qgb3JpZ2luYWwgPSBhc3luYyAoKSA9PiB7XG4gIGNvbnNvbGUubG9nKCdhY3Rpb24nKVxufVxuZXhwb3J0IHsgb3JpZ2luYWwgYXMgcmVuYW1lZCB9XG5cbmV4cG9ydCB7IGZvbyBhcyAn8J%2BTmScgfVxuYXN5bmMgZnVuY3Rpb24gZm9vKCkge31cbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiNlFBWXNCLGdMQUFBIn0%3D"; +export { slowInc } from "data:text/javascript,%2F%2A%20__next_internal_action_entry_do_not_use__%20%5B%7B%2240f4ad91903d1bf66bfd4e0788888852badc924261%22%3A%7B%22name%22%3A%22slowInc%22%7D%7D%2C%22%2Fapp%2Fitem.js%22%2C%22%22%5D%20%2A%2F%22use%20turbopack%20no%20side%20effects%22%3Bimport%7BcreateServerReference%2CcallServer%2CfindSourceMapURL%7Dfrom%22private-next-rsc-action-client-wrapper%22%3Bconst%20%24%24RSC_SERVER_ACTION_3%3D%2F%2A%23__PURE__%2A%2FcreateServerReference%28%2240f4ad91903d1bf66bfd4e0788888852badc924261%22%2CcallServer%2Cvoid%200%2CfindSourceMapURL%2C%22slowInc%22%29%3Bexport%7B%24%24RSC_SERVER_ACTION_3%20as%20slowInc%7D%3B%0A%2F%2F%23%20sourceMappingURL%3Ddata%3Aapplication%2Fjson%3Bbase64%2CeyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImlucHV0LmpzIl0sInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc2VydmVyJ1xuXG5pbXBvcnQgJ3NlcnZlci1vbmx5J1xuXG5pbXBvcnQgeyByZWRpcmVjdCB9IGZyb20gJ25leHQvbmF2aWdhdGlvbidcbmltcG9ydCB7IGhlYWRlcnMsIGNvb2tpZXMgfSBmcm9tICduZXh0L2hlYWRlcnMnXG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRIZWFkZXJzKCkge1xuICBjb25zb2xlLmxvZygnYWNjZXB0IGhlYWRlcjonLCAoYXdhaXQgaGVhZGVycygpKS5nZXQoJ2FjY2VwdCcpKVxuICA7KGF3YWl0IGNvb2tpZXMoKSkuc2V0KCd0ZXN0LWNvb2tpZScsIERhdGUubm93KCkpXG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBpbmModmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlICsgMVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2xvd0luYyh2YWx1ZSkge1xuICBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4gc2V0VGltZW91dChyZXNvbHZlLCAxMDAwMCkpXG4gIHJldHVybiB2YWx1ZSArIDFcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRlYyh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgLSAxXG59XG5cbmV4cG9ydCBkZWZhdWx0IGFzeW5jIGZ1bmN0aW9uICh2YWx1ZSkge1xuICBjb25zb2xlLmxvZygndGhpc19pc19zZW5zaXRpdmVfaW5mbycpXG4gIHJldHVybiB2YWx1ZSAqIDJcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlZGlyZWN0QWN0aW9uKHBhdGgpIHtcbiAgcmVkaXJlY3QocGF0aClcbn1cblxuY29uc3Qgb3JpZ2luYWwgPSBhc3luYyAoKSA9PiB7XG4gIGNvbnNvbGUubG9nKCdhY3Rpb24nKVxufVxuZXhwb3J0IHsgb3JpZ2luYWwgYXMgcmVuYW1lZCB9XG5cbmV4cG9ydCB7IGZvbyBhcyAn8J%2BTmScgfVxuYXN5bmMgZnVuY3Rpb24gZm9vKCkge31cbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiaVJBZ0JzQixvTEFBQSJ9"; +export { dec } from "data:text/javascript,%2F%2A%20__next_internal_action_entry_do_not_use__%20%5B%7B%224028baf972d345b86b747ad0df73d75a0088a42214%22%3A%7B%22name%22%3A%22dec%22%7D%7D%2C%22%2Fapp%2Fitem.js%22%2C%22%22%5D%20%2A%2F%22use%20turbopack%20no%20side%20effects%22%3Bimport%7BcreateServerReference%2CcallServer%2CfindSourceMapURL%7Dfrom%22private-next-rsc-action-client-wrapper%22%3Bconst%20%24%24RSC_SERVER_ACTION_4%3D%2F%2A%23__PURE__%2A%2FcreateServerReference%28%224028baf972d345b86b747ad0df73d75a0088a42214%22%2CcallServer%2Cvoid%200%2CfindSourceMapURL%2C%22dec%22%29%3Bexport%7B%24%24RSC_SERVER_ACTION_4%20as%20dec%7D%3B%0A%2F%2F%23%20sourceMappingURL%3Ddata%3Aapplication%2Fjson%3Bbase64%2CeyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImlucHV0LmpzIl0sInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc2VydmVyJ1xuXG5pbXBvcnQgJ3NlcnZlci1vbmx5J1xuXG5pbXBvcnQgeyByZWRpcmVjdCB9IGZyb20gJ25leHQvbmF2aWdhdGlvbidcbmltcG9ydCB7IGhlYWRlcnMsIGNvb2tpZXMgfSBmcm9tICduZXh0L2hlYWRlcnMnXG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRIZWFkZXJzKCkge1xuICBjb25zb2xlLmxvZygnYWNjZXB0IGhlYWRlcjonLCAoYXdhaXQgaGVhZGVycygpKS5nZXQoJ2FjY2VwdCcpKVxuICA7KGF3YWl0IGNvb2tpZXMoKSkuc2V0KCd0ZXN0LWNvb2tpZScsIERhdGUubm93KCkpXG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBpbmModmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlICsgMVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2xvd0luYyh2YWx1ZSkge1xuICBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4gc2V0VGltZW91dChyZXNvbHZlLCAxMDAwMCkpXG4gIHJldHVybiB2YWx1ZSArIDFcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRlYyh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgLSAxXG59XG5cbmV4cG9ydCBkZWZhdWx0IGFzeW5jIGZ1bmN0aW9uICh2YWx1ZSkge1xuICBjb25zb2xlLmxvZygndGhpc19pc19zZW5zaXRpdmVfaW5mbycpXG4gIHJldHVybiB2YWx1ZSAqIDJcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlZGlyZWN0QWN0aW9uKHBhdGgpIHtcbiAgcmVkaXJlY3QocGF0aClcbn1cblxuY29uc3Qgb3JpZ2luYWwgPSBhc3luYyAoKSA9PiB7XG4gIGNvbnNvbGUubG9nKCdhY3Rpb24nKVxufVxuZXhwb3J0IHsgb3JpZ2luYWwgYXMgcmVuYW1lZCB9XG5cbmV4cG9ydCB7IGZvbyBhcyAn8J%2BTmScgfVxuYXN5bmMgZnVuY3Rpb24gZm9vKCkge31cbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiNlFBcUJzQixnTEFBQSJ9"; +export { default } from "data:text/javascript,%2F%2A%20__next_internal_action_entry_do_not_use__%20%5B%7B%2240c18c215a6b7cdc64bf709f3a714ffdef1bf9651d%22%3A%7B%22name%22%3A%22default%22%7D%7D%2C%22%2Fapp%2Fitem.js%22%2C%22%22%5D%20%2A%2F%22use%20turbopack%20no%20side%20effects%22%3Bimport%7BcreateServerReference%2CcallServer%2CfindSourceMapURL%7Dfrom%22private-next-rsc-action-client-wrapper%22%3Bexport%20default%20createServerReference%28%2240c18c215a6b7cdc64bf709f3a714ffdef1bf9651d%22%2CcallServer%2Cvoid%200%2CfindSourceMapURL%2C%22default%22%29%3B%0A%2F%2F%23%20sourceMappingURL%3Ddata%3Aapplication%2Fjson%3Bbase64%2CeyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImlucHV0LmpzIl0sInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc2VydmVyJ1xuXG5pbXBvcnQgJ3NlcnZlci1vbmx5J1xuXG5pbXBvcnQgeyByZWRpcmVjdCB9IGZyb20gJ25leHQvbmF2aWdhdGlvbidcbmltcG9ydCB7IGhlYWRlcnMsIGNvb2tpZXMgfSBmcm9tICduZXh0L2hlYWRlcnMnXG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRIZWFkZXJzKCkge1xuICBjb25zb2xlLmxvZygnYWNjZXB0IGhlYWRlcjonLCAoYXdhaXQgaGVhZGVycygpKS5nZXQoJ2FjY2VwdCcpKVxuICA7KGF3YWl0IGNvb2tpZXMoKSkuc2V0KCd0ZXN0LWNvb2tpZScsIERhdGUubm93KCkpXG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBpbmModmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlICsgMVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2xvd0luYyh2YWx1ZSkge1xuICBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4gc2V0VGltZW91dChyZXNvbHZlLCAxMDAwMCkpXG4gIHJldHVybiB2YWx1ZSArIDFcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRlYyh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgLSAxXG59XG5cbmV4cG9ydCBkZWZhdWx0IGFzeW5jIGZ1bmN0aW9uICh2YWx1ZSkge1xuICBjb25zb2xlLmxvZygndGhpc19pc19zZW5zaXRpdmVfaW5mbycpXG4gIHJldHVybiB2YWx1ZSAqIDJcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlZGlyZWN0QWN0aW9uKHBhdGgpIHtcbiAgcmVkaXJlY3QocGF0aClcbn1cblxuY29uc3Qgb3JpZ2luYWwgPSBhc3luYyAoKSA9PiB7XG4gIGNvbnNvbGUubG9nKCdhY3Rpb24nKVxufVxuZXhwb3J0IHsgb3JpZ2luYWwgYXMgcmVuYW1lZCB9XG5cbmV4cG9ydCB7IGZvbyBhcyAn8J%2BTmScgfVxuYXN5bmMgZnVuY3Rpb24gZm9vKCkge31cbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiMFJBeUJlIn0%3D"; +export { redirectAction } from "data:text/javascript,%2F%2A%20__next_internal_action_entry_do_not_use__%20%5B%7B%22403724e93433a7e950ef2f8479f31225e4b0dd0cc5%22%3A%7B%22name%22%3A%22redirectAction%22%7D%7D%2C%22%2Fapp%2Fitem.js%22%2C%22%22%5D%20%2A%2F%22use%20turbopack%20no%20side%20effects%22%3Bimport%7BcreateServerReference%2CcallServer%2CfindSourceMapURL%7Dfrom%22private-next-rsc-action-client-wrapper%22%3Bconst%20%24%24RSC_SERVER_ACTION_5%3D%2F%2A%23__PURE__%2A%2FcreateServerReference%28%22403724e93433a7e950ef2f8479f31225e4b0dd0cc5%22%2CcallServer%2Cvoid%200%2CfindSourceMapURL%2C%22redirectAction%22%29%3Bexport%7B%24%24RSC_SERVER_ACTION_5%20as%20redirectAction%7D%3B%0A%2F%2F%23%20sourceMappingURL%3Ddata%3Aapplication%2Fjson%3Bbase64%2CeyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImlucHV0LmpzIl0sInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc2VydmVyJ1xuXG5pbXBvcnQgJ3NlcnZlci1vbmx5J1xuXG5pbXBvcnQgeyByZWRpcmVjdCB9IGZyb20gJ25leHQvbmF2aWdhdGlvbidcbmltcG9ydCB7IGhlYWRlcnMsIGNvb2tpZXMgfSBmcm9tICduZXh0L2hlYWRlcnMnXG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRIZWFkZXJzKCkge1xuICBjb25zb2xlLmxvZygnYWNjZXB0IGhlYWRlcjonLCAoYXdhaXQgaGVhZGVycygpKS5nZXQoJ2FjY2VwdCcpKVxuICA7KGF3YWl0IGNvb2tpZXMoKSkuc2V0KCd0ZXN0LWNvb2tpZScsIERhdGUubm93KCkpXG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBpbmModmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlICsgMVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2xvd0luYyh2YWx1ZSkge1xuICBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4gc2V0VGltZW91dChyZXNvbHZlLCAxMDAwMCkpXG4gIHJldHVybiB2YWx1ZSArIDFcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRlYyh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgLSAxXG59XG5cbmV4cG9ydCBkZWZhdWx0IGFzeW5jIGZ1bmN0aW9uICh2YWx1ZSkge1xuICBjb25zb2xlLmxvZygndGhpc19pc19zZW5zaXRpdmVfaW5mbycpXG4gIHJldHVybiB2YWx1ZSAqIDJcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlZGlyZWN0QWN0aW9uKHBhdGgpIHtcbiAgcmVkaXJlY3QocGF0aClcbn1cblxuY29uc3Qgb3JpZ2luYWwgPSBhc3luYyAoKSA9PiB7XG4gIGNvbnNvbGUubG9nKCdhY3Rpb24nKVxufVxuZXhwb3J0IHsgb3JpZ2luYWwgYXMgcmVuYW1lZCB9XG5cbmV4cG9ydCB7IGZvbyBhcyAn8J%2BTmScgfVxuYXN5bmMgZnVuY3Rpb24gZm9vKCkge31cbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoid1JBOEJzQiwyTEFBQSJ9"; +export { renamed } from "data:text/javascript,%2F%2A%20__next_internal_action_entry_do_not_use__%20%5B%7B%22001e1a741f85a589443b50c4863618893572cfb178%22%3A%7B%22name%22%3A%22renamed%22%7D%7D%2C%22%2Fapp%2Fitem.js%22%2C%22%22%5D%20%2A%2F%22use%20turbopack%20no%20side%20effects%22%3Bimport%7BcreateServerReference%2CcallServer%2CfindSourceMapURL%7Dfrom%22private-next-rsc-action-client-wrapper%22%3Bconst%20%24%24RSC_SERVER_ACTION_6%3D%2F%2A%23__PURE__%2A%2FcreateServerReference%28%22001e1a741f85a589443b50c4863618893572cfb178%22%2CcallServer%2Cvoid%200%2CfindSourceMapURL%2C%22renamed%22%29%3Bexport%7B%24%24RSC_SERVER_ACTION_6%20as%20renamed%7D%3B%0A%2F%2F%23%20sourceMappingURL%3Ddata%3Aapplication%2Fjson%3Bbase64%2CeyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImlucHV0LmpzIl0sInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc2VydmVyJ1xuXG5pbXBvcnQgJ3NlcnZlci1vbmx5J1xuXG5pbXBvcnQgeyByZWRpcmVjdCB9IGZyb20gJ25leHQvbmF2aWdhdGlvbidcbmltcG9ydCB7IGhlYWRlcnMsIGNvb2tpZXMgfSBmcm9tICduZXh0L2hlYWRlcnMnXG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRIZWFkZXJzKCkge1xuICBjb25zb2xlLmxvZygnYWNjZXB0IGhlYWRlcjonLCAoYXdhaXQgaGVhZGVycygpKS5nZXQoJ2FjY2VwdCcpKVxuICA7KGF3YWl0IGNvb2tpZXMoKSkuc2V0KCd0ZXN0LWNvb2tpZScsIERhdGUubm93KCkpXG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBpbmModmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlICsgMVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2xvd0luYyh2YWx1ZSkge1xuICBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4gc2V0VGltZW91dChyZXNvbHZlLCAxMDAwMCkpXG4gIHJldHVybiB2YWx1ZSArIDFcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRlYyh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgLSAxXG59XG5cbmV4cG9ydCBkZWZhdWx0IGFzeW5jIGZ1bmN0aW9uICh2YWx1ZSkge1xuICBjb25zb2xlLmxvZygndGhpc19pc19zZW5zaXRpdmVfaW5mbycpXG4gIHJldHVybiB2YWx1ZSAqIDJcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlZGlyZWN0QWN0aW9uKHBhdGgpIHtcbiAgcmVkaXJlY3QocGF0aClcbn1cblxuY29uc3Qgb3JpZ2luYWwgPSBhc3luYyAoKSA9PiB7XG4gIGNvbnNvbGUubG9nKCdhY3Rpb24nKVxufVxuZXhwb3J0IHsgb3JpZ2luYWwgYXMgcmVuYW1lZCB9XG5cbmV4cG9ydCB7IGZvbyBhcyAn8J%2BTmScgfVxuYXN5bmMgZnVuY3Rpb24gZm9vKCkge31cbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiaVJBa0NNLG9MQUdlIn0%3D"; +export { "📙" } from "data:text/javascript,%2F%2A%20__next_internal_action_entry_do_not_use__%20%5B%7B%220073f2cbccffb158eb2704761fc88fdbd0aaa102d0%22%3A%7B%22name%22%3A%22%F0%9F%93%99%22%7D%7D%2C%22%2Fapp%2Fitem.js%22%2C%22%22%5D%20%2A%2F%22use%20turbopack%20no%20side%20effects%22%3Bimport%7BcreateServerReference%2CcallServer%2CfindSourceMapURL%7Dfrom%22private-next-rsc-action-client-wrapper%22%3Bconst%20%24%24RSC_SERVER_ACTION_7%3D%2F%2A%23__PURE__%2A%2FcreateServerReference%28%220073f2cbccffb158eb2704761fc88fdbd0aaa102d0%22%2CcallServer%2Cvoid%200%2CfindSourceMapURL%2C%22%F0%9F%93%99%22%29%3Bexport%7B%24%24RSC_SERVER_ACTION_7%20as%20%22%F0%9F%93%99%22%7D%3B%0A%2F%2F%23%20sourceMappingURL%3Ddata%3Aapplication%2Fjson%3Bbase64%2CeyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImlucHV0LmpzIl0sInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc2VydmVyJ1xuXG5pbXBvcnQgJ3NlcnZlci1vbmx5J1xuXG5pbXBvcnQgeyByZWRpcmVjdCB9IGZyb20gJ25leHQvbmF2aWdhdGlvbidcbmltcG9ydCB7IGhlYWRlcnMsIGNvb2tpZXMgfSBmcm9tICduZXh0L2hlYWRlcnMnXG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRIZWFkZXJzKCkge1xuICBjb25zb2xlLmxvZygnYWNjZXB0IGhlYWRlcjonLCAoYXdhaXQgaGVhZGVycygpKS5nZXQoJ2FjY2VwdCcpKVxuICA7KGF3YWl0IGNvb2tpZXMoKSkuc2V0KCd0ZXN0LWNvb2tpZScsIERhdGUubm93KCkpXG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBpbmModmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlICsgMVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2xvd0luYyh2YWx1ZSkge1xuICBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4gc2V0VGltZW91dChyZXNvbHZlLCAxMDAwMCkpXG4gIHJldHVybiB2YWx1ZSArIDFcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRlYyh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgLSAxXG59XG5cbmV4cG9ydCBkZWZhdWx0IGFzeW5jIGZ1bmN0aW9uICh2YWx1ZSkge1xuICBjb25zb2xlLmxvZygndGhpc19pc19zZW5zaXRpdmVfaW5mbycpXG4gIHJldHVybiB2YWx1ZSAqIDJcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlZGlyZWN0QWN0aW9uKHBhdGgpIHtcbiAgcmVkaXJlY3QocGF0aClcbn1cblxuY29uc3Qgb3JpZ2luYWwgPSBhc3luYyAoKSA9PiB7XG4gIGNvbnNvbGUubG9nKCdhY3Rpb24nKVxufVxuZXhwb3J0IHsgb3JpZ2luYWwgYXMgcmVuYW1lZCB9XG5cbmV4cG9ydCB7IGZvbyBhcyAn8J%2BTmScgfVxuYXN5bmMgZnVuY3Rpb24gZm9vKCkge31cbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiNFFBd0NlLCtLQURDIn0%3D"; diff --git a/crates/next-custom-transforms/tests/fixture/source-maps/turbopack/client-graph/production/server-actions/1/output.js b/crates/next-custom-transforms/tests/fixture/source-maps/turbopack/client-graph/production/server-actions/1/output.js index 215f42144fd1..4976779eb229 100644 --- a/crates/next-custom-transforms/tests/fixture/source-maps/turbopack/client-graph/production/server-actions/1/output.js +++ b/crates/next-custom-transforms/tests/fixture/source-maps/turbopack/client-graph/production/server-actions/1/output.js @@ -1,9 +1,9 @@ "use turbopack no side effects"; -export { getHeaders } from "data:text/javascript,%2F%2A%20__next_internal_action_entry_do_not_use__%20%5B%7B%22006c24672f968b0713dae406536f7dd6fe7d9a7fa0%22%3A%22getHeaders%22%7D%2C%22%2Fapp%2Fitem.js%22%2C%22%22%5D%20%2A%2F%22use%20turbopack%20no%20side%20effects%22%3Bimport%7BcreateServerReference%2CcallServer%2CfindSourceMapURL%7Dfrom%22private-next-rsc-action-client-wrapper%22%3Bconst%20%24%24RSC_SERVER_ACTION_1%3D%2F%2A%23__PURE__%2A%2FcreateServerReference%28%22006c24672f968b0713dae406536f7dd6fe7d9a7fa0%22%2CcallServer%2Cvoid%200%2CfindSourceMapURL%2C%22getHeaders%22%29%3Bexport%7B%24%24RSC_SERVER_ACTION_1%20as%20getHeaders%7D%3B"; -export { inc } from "data:text/javascript,%2F%2A%20__next_internal_action_entry_do_not_use__%20%5B%7B%2240e44b877cc9d02556f56639c94229621ab0af0f5f%22%3A%22inc%22%7D%2C%22%2Fapp%2Fitem.js%22%2C%22%22%5D%20%2A%2F%22use%20turbopack%20no%20side%20effects%22%3Bimport%7BcreateServerReference%2CcallServer%2CfindSourceMapURL%7Dfrom%22private-next-rsc-action-client-wrapper%22%3Bconst%20%24%24RSC_SERVER_ACTION_2%3D%2F%2A%23__PURE__%2A%2FcreateServerReference%28%2240e44b877cc9d02556f56639c94229621ab0af0f5f%22%2CcallServer%2Cvoid%200%2CfindSourceMapURL%2C%22inc%22%29%3Bexport%7B%24%24RSC_SERVER_ACTION_2%20as%20inc%7D%3B"; -export { slowInc } from "data:text/javascript,%2F%2A%20__next_internal_action_entry_do_not_use__%20%5B%7B%2240f4ad91903d1bf66bfd4e0788888852badc924261%22%3A%22slowInc%22%7D%2C%22%2Fapp%2Fitem.js%22%2C%22%22%5D%20%2A%2F%22use%20turbopack%20no%20side%20effects%22%3Bimport%7BcreateServerReference%2CcallServer%2CfindSourceMapURL%7Dfrom%22private-next-rsc-action-client-wrapper%22%3Bconst%20%24%24RSC_SERVER_ACTION_3%3D%2F%2A%23__PURE__%2A%2FcreateServerReference%28%2240f4ad91903d1bf66bfd4e0788888852badc924261%22%2CcallServer%2Cvoid%200%2CfindSourceMapURL%2C%22slowInc%22%29%3Bexport%7B%24%24RSC_SERVER_ACTION_3%20as%20slowInc%7D%3B"; -export { dec } from "data:text/javascript,%2F%2A%20__next_internal_action_entry_do_not_use__%20%5B%7B%224028baf972d345b86b747ad0df73d75a0088a42214%22%3A%22dec%22%7D%2C%22%2Fapp%2Fitem.js%22%2C%22%22%5D%20%2A%2F%22use%20turbopack%20no%20side%20effects%22%3Bimport%7BcreateServerReference%2CcallServer%2CfindSourceMapURL%7Dfrom%22private-next-rsc-action-client-wrapper%22%3Bconst%20%24%24RSC_SERVER_ACTION_4%3D%2F%2A%23__PURE__%2A%2FcreateServerReference%28%224028baf972d345b86b747ad0df73d75a0088a42214%22%2CcallServer%2Cvoid%200%2CfindSourceMapURL%2C%22dec%22%29%3Bexport%7B%24%24RSC_SERVER_ACTION_4%20as%20dec%7D%3B"; -export { default } from "data:text/javascript,%2F%2A%20__next_internal_action_entry_do_not_use__%20%5B%7B%2240c18c215a6b7cdc64bf709f3a714ffdef1bf9651d%22%3A%22default%22%7D%2C%22%2Fapp%2Fitem.js%22%2C%22%22%5D%20%2A%2F%22use%20turbopack%20no%20side%20effects%22%3Bimport%7BcreateServerReference%2CcallServer%2CfindSourceMapURL%7Dfrom%22private-next-rsc-action-client-wrapper%22%3Bexport%20default%20%2F%2A%23__PURE__%2A%2FcreateServerReference%28%2240c18c215a6b7cdc64bf709f3a714ffdef1bf9651d%22%2CcallServer%2Cvoid%200%2CfindSourceMapURL%2C%22default%22%29%3B"; -export { redirectAction } from "data:text/javascript,%2F%2A%20__next_internal_action_entry_do_not_use__%20%5B%7B%22403724e93433a7e950ef2f8479f31225e4b0dd0cc5%22%3A%22redirectAction%22%7D%2C%22%2Fapp%2Fitem.js%22%2C%22%22%5D%20%2A%2F%22use%20turbopack%20no%20side%20effects%22%3Bimport%7BcreateServerReference%2CcallServer%2CfindSourceMapURL%7Dfrom%22private-next-rsc-action-client-wrapper%22%3Bconst%20%24%24RSC_SERVER_ACTION_5%3D%2F%2A%23__PURE__%2A%2FcreateServerReference%28%22403724e93433a7e950ef2f8479f31225e4b0dd0cc5%22%2CcallServer%2Cvoid%200%2CfindSourceMapURL%2C%22redirectAction%22%29%3Bexport%7B%24%24RSC_SERVER_ACTION_5%20as%20redirectAction%7D%3B"; -export { renamed } from "data:text/javascript,%2F%2A%20__next_internal_action_entry_do_not_use__%20%5B%7B%22001e1a741f85a589443b50c4863618893572cfb178%22%3A%22renamed%22%7D%2C%22%2Fapp%2Fitem.js%22%2C%22%22%5D%20%2A%2F%22use%20turbopack%20no%20side%20effects%22%3Bimport%7BcreateServerReference%2CcallServer%2CfindSourceMapURL%7Dfrom%22private-next-rsc-action-client-wrapper%22%3Bconst%20%24%24RSC_SERVER_ACTION_6%3D%2F%2A%23__PURE__%2A%2FcreateServerReference%28%22001e1a741f85a589443b50c4863618893572cfb178%22%2CcallServer%2Cvoid%200%2CfindSourceMapURL%2C%22renamed%22%29%3Bexport%7B%24%24RSC_SERVER_ACTION_6%20as%20renamed%7D%3B"; -export { "📙" } from "data:text/javascript,%2F%2A%20__next_internal_action_entry_do_not_use__%20%5B%7B%220073f2cbccffb158eb2704761fc88fdbd0aaa102d0%22%3A%22%F0%9F%93%99%22%7D%2C%22%2Fapp%2Fitem.js%22%2C%22%22%5D%20%2A%2F%22use%20turbopack%20no%20side%20effects%22%3Bimport%7BcreateServerReference%2CcallServer%2CfindSourceMapURL%7Dfrom%22private-next-rsc-action-client-wrapper%22%3Bconst%20%24%24RSC_SERVER_ACTION_7%3D%2F%2A%23__PURE__%2A%2FcreateServerReference%28%220073f2cbccffb158eb2704761fc88fdbd0aaa102d0%22%2CcallServer%2Cvoid%200%2CfindSourceMapURL%2C%22%F0%9F%93%99%22%29%3Bexport%7B%24%24RSC_SERVER_ACTION_7%20as%20%22%F0%9F%93%99%22%7D%3B"; +export { getHeaders } from "data:text/javascript,%2F%2A%20__next_internal_action_entry_do_not_use__%20%5B%7B%22006c24672f968b0713dae406536f7dd6fe7d9a7fa0%22%3A%7B%22name%22%3A%22getHeaders%22%7D%7D%2C%22%2Fapp%2Fitem.js%22%2C%22%22%5D%20%2A%2F%22use%20turbopack%20no%20side%20effects%22%3Bimport%7BcreateServerReference%2CcallServer%2CfindSourceMapURL%7Dfrom%22private-next-rsc-action-client-wrapper%22%3Bconst%20%24%24RSC_SERVER_ACTION_1%3D%2F%2A%23__PURE__%2A%2FcreateServerReference%28%22006c24672f968b0713dae406536f7dd6fe7d9a7fa0%22%2CcallServer%2Cvoid%200%2CfindSourceMapURL%2C%22getHeaders%22%29%3Bexport%7B%24%24RSC_SERVER_ACTION_1%20as%20getHeaders%7D%3B"; +export { inc } from "data:text/javascript,%2F%2A%20__next_internal_action_entry_do_not_use__%20%5B%7B%2240e44b877cc9d02556f56639c94229621ab0af0f5f%22%3A%7B%22name%22%3A%22inc%22%7D%7D%2C%22%2Fapp%2Fitem.js%22%2C%22%22%5D%20%2A%2F%22use%20turbopack%20no%20side%20effects%22%3Bimport%7BcreateServerReference%2CcallServer%2CfindSourceMapURL%7Dfrom%22private-next-rsc-action-client-wrapper%22%3Bconst%20%24%24RSC_SERVER_ACTION_2%3D%2F%2A%23__PURE__%2A%2FcreateServerReference%28%2240e44b877cc9d02556f56639c94229621ab0af0f5f%22%2CcallServer%2Cvoid%200%2CfindSourceMapURL%2C%22inc%22%29%3Bexport%7B%24%24RSC_SERVER_ACTION_2%20as%20inc%7D%3B"; +export { slowInc } from "data:text/javascript,%2F%2A%20__next_internal_action_entry_do_not_use__%20%5B%7B%2240f4ad91903d1bf66bfd4e0788888852badc924261%22%3A%7B%22name%22%3A%22slowInc%22%7D%7D%2C%22%2Fapp%2Fitem.js%22%2C%22%22%5D%20%2A%2F%22use%20turbopack%20no%20side%20effects%22%3Bimport%7BcreateServerReference%2CcallServer%2CfindSourceMapURL%7Dfrom%22private-next-rsc-action-client-wrapper%22%3Bconst%20%24%24RSC_SERVER_ACTION_3%3D%2F%2A%23__PURE__%2A%2FcreateServerReference%28%2240f4ad91903d1bf66bfd4e0788888852badc924261%22%2CcallServer%2Cvoid%200%2CfindSourceMapURL%2C%22slowInc%22%29%3Bexport%7B%24%24RSC_SERVER_ACTION_3%20as%20slowInc%7D%3B"; +export { dec } from "data:text/javascript,%2F%2A%20__next_internal_action_entry_do_not_use__%20%5B%7B%224028baf972d345b86b747ad0df73d75a0088a42214%22%3A%7B%22name%22%3A%22dec%22%7D%7D%2C%22%2Fapp%2Fitem.js%22%2C%22%22%5D%20%2A%2F%22use%20turbopack%20no%20side%20effects%22%3Bimport%7BcreateServerReference%2CcallServer%2CfindSourceMapURL%7Dfrom%22private-next-rsc-action-client-wrapper%22%3Bconst%20%24%24RSC_SERVER_ACTION_4%3D%2F%2A%23__PURE__%2A%2FcreateServerReference%28%224028baf972d345b86b747ad0df73d75a0088a42214%22%2CcallServer%2Cvoid%200%2CfindSourceMapURL%2C%22dec%22%29%3Bexport%7B%24%24RSC_SERVER_ACTION_4%20as%20dec%7D%3B"; +export { default } from "data:text/javascript,%2F%2A%20__next_internal_action_entry_do_not_use__%20%5B%7B%2240c18c215a6b7cdc64bf709f3a714ffdef1bf9651d%22%3A%7B%22name%22%3A%22default%22%7D%7D%2C%22%2Fapp%2Fitem.js%22%2C%22%22%5D%20%2A%2F%22use%20turbopack%20no%20side%20effects%22%3Bimport%7BcreateServerReference%2CcallServer%2CfindSourceMapURL%7Dfrom%22private-next-rsc-action-client-wrapper%22%3Bexport%20default%20%2F%2A%23__PURE__%2A%2FcreateServerReference%28%2240c18c215a6b7cdc64bf709f3a714ffdef1bf9651d%22%2CcallServer%2Cvoid%200%2CfindSourceMapURL%2C%22default%22%29%3B"; +export { redirectAction } from "data:text/javascript,%2F%2A%20__next_internal_action_entry_do_not_use__%20%5B%7B%22403724e93433a7e950ef2f8479f31225e4b0dd0cc5%22%3A%7B%22name%22%3A%22redirectAction%22%7D%7D%2C%22%2Fapp%2Fitem.js%22%2C%22%22%5D%20%2A%2F%22use%20turbopack%20no%20side%20effects%22%3Bimport%7BcreateServerReference%2CcallServer%2CfindSourceMapURL%7Dfrom%22private-next-rsc-action-client-wrapper%22%3Bconst%20%24%24RSC_SERVER_ACTION_5%3D%2F%2A%23__PURE__%2A%2FcreateServerReference%28%22403724e93433a7e950ef2f8479f31225e4b0dd0cc5%22%2CcallServer%2Cvoid%200%2CfindSourceMapURL%2C%22redirectAction%22%29%3Bexport%7B%24%24RSC_SERVER_ACTION_5%20as%20redirectAction%7D%3B"; +export { renamed } from "data:text/javascript,%2F%2A%20__next_internal_action_entry_do_not_use__%20%5B%7B%22001e1a741f85a589443b50c4863618893572cfb178%22%3A%7B%22name%22%3A%22renamed%22%7D%7D%2C%22%2Fapp%2Fitem.js%22%2C%22%22%5D%20%2A%2F%22use%20turbopack%20no%20side%20effects%22%3Bimport%7BcreateServerReference%2CcallServer%2CfindSourceMapURL%7Dfrom%22private-next-rsc-action-client-wrapper%22%3Bconst%20%24%24RSC_SERVER_ACTION_6%3D%2F%2A%23__PURE__%2A%2FcreateServerReference%28%22001e1a741f85a589443b50c4863618893572cfb178%22%2CcallServer%2Cvoid%200%2CfindSourceMapURL%2C%22renamed%22%29%3Bexport%7B%24%24RSC_SERVER_ACTION_6%20as%20renamed%7D%3B"; +export { "📙" } from "data:text/javascript,%2F%2A%20__next_internal_action_entry_do_not_use__%20%5B%7B%220073f2cbccffb158eb2704761fc88fdbd0aaa102d0%22%3A%7B%22name%22%3A%22%F0%9F%93%99%22%7D%7D%2C%22%2Fapp%2Fitem.js%22%2C%22%22%5D%20%2A%2F%22use%20turbopack%20no%20side%20effects%22%3Bimport%7BcreateServerReference%2CcallServer%2CfindSourceMapURL%7Dfrom%22private-next-rsc-action-client-wrapper%22%3Bconst%20%24%24RSC_SERVER_ACTION_7%3D%2F%2A%23__PURE__%2A%2FcreateServerReference%28%220073f2cbccffb158eb2704761fc88fdbd0aaa102d0%22%2CcallServer%2Cvoid%200%2CfindSourceMapURL%2C%22%F0%9F%93%99%22%29%3Bexport%7B%24%24RSC_SERVER_ACTION_7%20as%20%22%F0%9F%93%99%22%7D%3B"; diff --git a/docs/01-app/01-getting-started/13-fonts.mdx b/docs/01-app/01-getting-started/13-fonts.mdx index dedc5e345157..41bb572701f9 100644 --- a/docs/01-app/01-getting-started/13-fonts.mdx +++ b/docs/01-app/01-getting-started/13-fonts.mdx @@ -12,6 +12,8 @@ The [`next/font`](/docs/app/api-reference/components/font) module automatically It includes **built-in self-hosting** for any font file. This means you can optimally load web fonts with no layout shift. + + To start using `next/font`, import it from [`next/font/local`](#local-fonts) or [`next/font/google`](#google-fonts), call it as a function with the appropriate options, and set the `className` of the element you want to apply the font to. For example: ```tsx filename="app/layout.tsx" highlight={1,3-5,9} switcher @@ -48,12 +50,99 @@ export default function Layout({ children }) { Fonts are scoped to the component they're used in. To apply a font to your entire application, add it to the [Root Layout](/docs/app/api-reference/file-conventions/layout#root-layout). + + + + +To start using `next/font`, import it from [`next/font/local`](#local-fonts) or [`next/font/google`](#google-fonts), call it as a function with the appropriate options, and set the `className` of the element you want to apply the font to. For example, you can apply fonts globally in your [Custom App](/docs/pages/building-your-application/routing/custom-app) (`pages/_app`): + +```tsx filename="pages/_app.tsx" highlight={1,4-6,10} switcher +import { Geist } from 'next/font/google' +import type { AppProps } from 'next/app' + +const geist = Geist({ + subsets: ['latin'], +}) + +export default function MyApp({ Component, pageProps }: AppProps) { + return ( +
+ +
+ ) +} +``` + +```jsx filename="pages/_app.js" highlight={1,3-5,9} switcher +import { Geist } from 'next/font/google' + +const geist = Geist({ + subsets: ['latin'], +}) + +export default function MyApp({ Component, pageProps }) { + return ( +
+ +
+ ) +} +``` + +If you want to apply the font to the `` element, you can use a [Custom Document](/docs/pages/building-your-application/routing/custom-document) (`pages/_document`): + +```tsx filename="pages/_document.tsx" highlight={2,4-6,10} switcher +import { Html, Head, Main, NextScript } from 'next/document' +import { Geist } from 'next/font/google' + +const geist = Geist({ + subsets: ['latin'], +}) + +export default function Document() { + return ( + + + +
+ + + + ) +} +``` + +```jsx filename="pages/_document.js" highlight={2,4-6,10} switcher +import { Html, Head, Main, NextScript } from 'next/document' +import { Geist } from 'next/font/google' + +const geist = Geist({ + subsets: ['latin'], +}) + +export default function Document() { + return ( + + + +
+ + + + ) +} +``` + + + ## Google fonts You can automatically self-host any Google Font. Fonts are included stored as static assets and served from the same domain as your deployment, meaning no requests are sent to Google by the browser when the user visits your site. To start using a Google Font, import your chosen font from `next/font/google`: + + ```tsx filename="app/layout.tsx" switcher import { Geist } from 'next/font/google' @@ -90,8 +179,49 @@ export default function RootLayout({ children }) { } ``` + + + + +```tsx filename="pages/_app.tsx" switcher +import { Geist } from 'next/font/google' +import type { AppProps } from 'next/app' + +const geist = Geist({ + subsets: ['latin'], +}) + +export default function MyApp({ Component, pageProps }: AppProps) { + return ( +
+ +
+ ) +} +``` + +```jsx filename="pages/_app.js" switcher +import { Geist } from 'next/font/google' + +const geist = Geist({ + subsets: ['latin'], +}) + +export default function MyApp({ Component, pageProps }) { + return ( +
+ +
+ ) +} +``` + +
+ We recommend using [variable fonts](https://fonts.google.com/variablefonts) for the best performance and flexibility. But if you can't use a variable font, you will need to specify a weight: + + ```tsx filename="app/layout.tsx" highlight={4} switcher import { Roboto } from 'next/font/google' @@ -130,8 +260,51 @@ export default function RootLayout({ children }) { } ``` + + + + +```tsx filename="pages/_app.tsx" highlight={5} switcher +import { Roboto } from 'next/font/google' +import type { AppProps } from 'next/app' + +const roboto = Roboto({ + weight: '400', + subsets: ['latin'], +}) + +export default function MyApp({ Component, pageProps }: AppProps) { + return ( +
+ +
+ ) +} +``` + +```jsx filename="pages/_app.js" highlight={4} switcher +import { Roboto } from 'next/font/google' + +const roboto = Roboto({ + weight: '400', + subsets: ['latin'], +}) + +export default function MyApp({ Component, pageProps }) { + return ( +
+ +
+ ) +} +``` + +
+ ## Local fonts + + To use a local font, import your font from `next/font/local` and specify the [`src`](/docs/app/api-reference/components/font#src) of your local font file. Fonts can be stored in the [`public`](/docs/app/api-reference/file-conventions/public-folder) folder or co-located inside the `app` folder. For example: ```tsx filename="app/layout.tsx" switcher @@ -170,6 +343,47 @@ export default function RootLayout({ children }) { } ``` + + + + +To use a local font, import your font from `next/font/local` and specify the [`src`](/docs/pages/api-reference/components/font#src) of your local font file. Fonts can be stored in the [`public`](/docs/pages/api-reference/file-conventions/public-folder) folder or inside the `pages` folder. For example: + +```tsx filename="pages/_app.tsx" switcher +import localFont from 'next/font/local' +import type { AppProps } from 'next/app' + +const myFont = localFont({ + src: './my-font.woff2', +}) + +export default function MyApp({ Component, pageProps }: AppProps) { + return ( +
+ +
+ ) +} +``` + +```jsx filename="pages/_app.js" switcher +import localFont from 'next/font/local' + +const myFont = localFont({ + src: './my-font.woff2', +}) + +export default function MyApp({ Component, pageProps }) { + return ( +
+ +
+ ) +} +``` + +
+ If you want to use multiple files for a single font family, `src` can be an array: ```js diff --git a/docs/01-app/02-guides/upgrading/version-16.mdx b/docs/01-app/02-guides/upgrading/version-16.mdx index b8d0c29862e5..f6715e6213c6 100644 --- a/docs/01-app/02-guides/upgrading/version-16.mdx +++ b/docs/01-app/02-guides/upgrading/version-16.mdx @@ -14,9 +14,11 @@ If you're using an AI coding assistant that supports the [Model Context Protocol #### Setup -Add the following configuration to your MCP client, example: +Add the following configuration to your MCP client, for each coding agent you can read [this section](https://github.com/vercel/next-devtools-mcp#mcp-client-configuration) for configuration details. -```json +**example:** + +```json filename=".mcp.json" { "mcpServers": { "next-devtools": { @@ -27,7 +29,7 @@ Add the following configuration to your MCP client, example: } ``` -For more information, visit the [`next-devtools-mcp`](https://www.npmjs.com/package/next-devtools-mcp) package on npm to configure with your MCP client. +For more information, visit the [`next-devtools-mcp`](https://github.com/vercel/next-devtools-mcp) documentation to configure with your MCP client. > **Note:** Using `next-devtools-mcp@latest` ensures that your MCP client will always use the latest version of the Next.js DevTools MCP server. diff --git a/docs/01-app/03-api-reference/02-components/image.mdx b/docs/01-app/03-api-reference/02-components/image.mdx index 2c9fe992f4fd..d18811c8d285 100644 --- a/docs/01-app/03-api-reference/02-components/image.mdx +++ b/docs/01-app/03-api-reference/02-components/image.mdx @@ -839,22 +839,22 @@ module.exports = { #### `maximumResponseBody` -The default image optimization loader will fetch source images up to 300 MB in size. +The default image optimization loader will fetch source images up to 50 MB in size. ```js filename="next.config.js" module.exports = { images: { - maximumResponseBody: 300_000_000, + maximumResponseBody: 50_000_000, }, } ``` -If you know all your source images are small, you can protect memory constrained servers by reducing this to a smaller value such as 50 MB. +If you know all your source images are small, you can protect memory constrained servers by reducing this to a smaller value such as 5 MB. ```js filename="next.config.js" module.exports = { images: { - maximumResponseBody: 50_000_000, + maximumResponseBody: 5_000_000, }, } ``` diff --git a/docs/01-app/03-api-reference/05-config/01-next-config-js/turbopack.mdx b/docs/01-app/03-api-reference/05-config/01-next-config-js/turbopack.mdx index a260fc2aa8ce..91caa3d0902e 100644 --- a/docs/01-app/03-api-reference/05-config/01-next-config-js/turbopack.mdx +++ b/docs/01-app/03-api-reference/05-config/01-next-config-js/turbopack.mdx @@ -213,7 +213,10 @@ module.exports = { ``` - Supported boolean operators are `{all: [...]}`, `{any: [...]}` and `{not: ...}`. -- Supported customizable operators are `{path: string | RegExp}` and `{content: RegExp}`. If `path` and `content` are specified in the same object, it acts as an implicit `and`. +- Supported customizable operators are `{path: string | RegExp}`, `{content: RegExp}`, and `{query: string | RegExp}`. If multiple operators are specified in the same object, it acts as an implicit `and`. + - `path` matches against the project-relative file path. A string is treated as a glob pattern, while a RegExp matches anywhere in the path. + - `content` matches anywhere in the file content. + - `query` matches the import's query string (e.g., `?foo` in `import './file?foo'`). A string must match exactly, while a RegExp can match partially. In addition, a number of built-in conditions are supported: @@ -308,6 +311,7 @@ The option automatically adds a polyfill for debug IDs to the JavaScript bundle | Version | Changes | | -------- | ----------------------------------------------- | +| `16.2.0` | `turbopack.rules.*.condition.query` was added. | | `16.0.0` | `turbopack.debugIds` was added. | | `16.0.0` | `turbopack.rules.*.condition` was added. | | `15.3.0` | `experimental.turbo` is changed to `turbopack`. | diff --git a/docs/02-pages/04-api-reference/03-functions/use-params.mdx b/docs/02-pages/04-api-reference/03-functions/use-params.mdx new file mode 100644 index 000000000000..15ce3211236b --- /dev/null +++ b/docs/02-pages/04-api-reference/03-functions/use-params.mdx @@ -0,0 +1,242 @@ +--- +title: useParams +description: API Reference for the useParams hook in the Pages Router. +--- + +`useParams` is a hook that lets you read a route's [dynamic params](/docs/pages/building-your-application/routing/dynamic-routes) filled in by the current URL. + +```tsx filename="pages/shop/[slug].tsx" switcher +import { useParams } from 'next/navigation' + +export default function ShopPage() { + const params = useParams<{ slug: string }>() + + if (!params) { + // Render fallback UI while params are not yet available + return null + } + + // Route -> /shop/[slug] + // URL -> /shop/shoes + // `params` -> { slug: 'shoes' } + return <>Shop: {params.slug} +} +``` + +```jsx filename="pages/shop/[slug].js" switcher +import { useParams } from 'next/navigation' + +export default function ShopPage() { + const params = useParams() + + if (!params) { + // Render fallback UI while params are not yet available + return null + } + + // Route -> /shop/[slug] + // URL -> /shop/shoes + // `params` -> { slug: 'shoes' } + return <>Shop: {params.slug} +} +``` + +## Parameters + +```tsx +const params = useParams() +``` + +`useParams` does not take any parameters. + +## Returns + +`useParams` returns an object containing the current route's filled in [dynamic parameters](/docs/pages/building-your-application/routing/dynamic-routes), or `null` during [pre-rendering](#behavior-during-pre-rendering). + +- Each property in the object is an active dynamic segment. +- The property name is the segment's name, and the property value is what the segment is filled in with. +- The property value will either be a `string` or array of `string`s depending on the [type of dynamic segment](/docs/pages/building-your-application/routing/dynamic-routes). +- If the route contains no dynamic parameters, `useParams` returns an empty object. + +For example: + +| Route | URL | `useParams()` | +| ---------------------------- | ----------- | ------------------------- | +| `pages/shop/page.js` | `/shop` | `{}` | +| `pages/shop/[slug].js` | `/shop/1` | `{ slug: '1' }` | +| `pages/shop/[tag]/[item].js` | `/shop/1/2` | `{ tag: '1', item: '2' }` | +| `pages/shop/[...slug].js` | `/shop/1/2` | `{ slug: ['1', '2'] }` | + +> **Good to know**: `useParams` is a [React Hook](https://react.dev/learn#using-hooks) and cannot be used with classes. + +## Behavior + +### Behavior during pre-rendering + +For pages that are [statically optimized](/docs/pages/building-your-application/rendering/automatic-static-optimization), `useParams` will return `null` on the initial render. After hydration, the value will be updated to the actual params once the router is ready. + +This is because params cannot be known during static generation for dynamic routes. + +```tsx filename="pages/shop/[slug].tsx" switcher +import { useParams } from 'next/navigation' + +export default function ShopPage() { + const params = useParams<{ slug: string }>() + + if (!params) { + // Return a fallback UI while params are loading + // This prevents hydration mismatches + return + } + + return <>Shop: {params.slug} +} +``` + +```jsx filename="pages/shop/[slug].js" switcher +import { useParams } from 'next/navigation' + +export default function ShopPage() { + const params = useParams() + + if (!params) { + // Return a fallback UI while params are loading + // This prevents hydration mismatches + return + } + + return <>Shop: {params.slug} +} +``` + +### Using with `getServerSideProps` + +When using [`getServerSideProps`](/docs/pages/building-your-application/data-fetching/get-server-side-props), the page is server-rendered on each request and `useParams` will return the actual params immediately: + +```tsx filename="pages/shop/[slug].tsx" switcher +import { useParams } from 'next/navigation' + +export default function ShopPage() { + const params = useParams<{ slug: string }>() + + // With getServerSideProps, this fallback is never rendered because + // params is always available on the server. However, keeping + // the fallback allows this component to be reused on other pages + // that may not use getServerSideProps. + if (!params) { + return null + } + + return <>Shop: {params.slug} +} + +export async function getServerSideProps() { + return { props: {} } +} +``` + +```jsx filename="pages/shop/[slug].js" switcher +import { useParams } from 'next/navigation' + +export default function ShopPage() { + const params = useParams() + + // With getServerSideProps, this fallback is never rendered because + // params is always available on the server. However, keeping + // the fallback allows this component to be reused on other pages + // that may not use getServerSideProps. + if (!params) { + return null + } + + return <>Shop: {params.slug} +} + +export async function getServerSideProps() { + return { props: {} } +} +``` + +### Comparison with `router.query` + +`useParams` only returns the dynamic route parameters, whereas [`router.query`](/docs/pages/api-reference/functions/use-router#router-object) from `useRouter` includes both dynamic parameters and query string parameters. + +```tsx filename="pages/shop/[slug].tsx" switcher +import { useRouter } from 'next/router' +import { useParams } from 'next/navigation' + +export default function ShopPage() { + const router = useRouter() + const params = useParams() + + // URL -> /shop/shoes?color=red + + // router.query -> { slug: 'shoes', color: 'red' } + // params -> { slug: 'shoes' } + + // ... +} +``` + +```jsx filename="pages/shop/[slug].js" switcher +import { useRouter } from 'next/router' +import { useParams } from 'next/navigation' + +export default function ShopPage() { + const router = useRouter() + const params = useParams() + + // URL -> /shop/shoes?color=red + + // router.query -> { slug: 'shoes', color: 'red' } + // params -> { slug: 'shoes' } + + // ... +} +``` + +## Examples + +### Sharing components with App Router + +`useParams` from `next/navigation` works in both the Pages Router and App Router. This allows you to create shared components that work in either context: + +```tsx filename="components/breadcrumb.tsx" switcher +import { useParams } from 'next/navigation' + +// This component works in both pages/ and app/ +export function Breadcrumb() { + const params = useParams<{ slug: string }>() + + if (!params) { + // Fallback for Pages Router during pre-rendering + return + } + + return +} +``` + +```jsx filename="components/breadcrumb.js" switcher +import { useParams } from 'next/navigation' + +// This component works in both pages/ and app/ +export function Breadcrumb() { + const params = useParams() + + if (!params) { + // Fallback for Pages Router during pre-rendering + return + } + + return +} +``` + +> **Good to know**: When using this component in the App Router, `useParams` never returns `null`, so the fallback branch will not be rendered. + +## Version History + +| Version | Changes | +| --------- | ----------------------- | +| `v13.3.0` | `useParams` introduced. | diff --git a/docs/02-pages/04-api-reference/03-functions/use-search-params.mdx b/docs/02-pages/04-api-reference/03-functions/use-search-params.mdx new file mode 100644 index 000000000000..1f68d36a4836 --- /dev/null +++ b/docs/02-pages/04-api-reference/03-functions/use-search-params.mdx @@ -0,0 +1,318 @@ +--- +title: useSearchParams +description: API Reference for the useSearchParams hook in the Pages Router. +--- + +`useSearchParams` is a hook that lets you read the current URL's **query string**. + +`useSearchParams` returns a **read-only** version of the [`URLSearchParams`](https://developer.mozilla.org/docs/Web/API/URLSearchParams) interface. + +```tsx filename="pages/dashboard.tsx" switcher +import { useSearchParams } from 'next/navigation' + +export default function Dashboard() { + const searchParams = useSearchParams() + + if (!searchParams) { + // Render fallback UI while search params are not yet available + return null + } + + const search = searchParams.get('search') + + // URL -> `/dashboard?search=my-project` + // `search` -> 'my-project' + return <>Search: {search} +} +``` + +```jsx filename="pages/dashboard.js" switcher +import { useSearchParams } from 'next/navigation' + +export default function Dashboard() { + const searchParams = useSearchParams() + + if (!searchParams) { + // Render fallback UI while search params are not yet available + return null + } + + const search = searchParams.get('search') + + // URL -> `/dashboard?search=my-project` + // `search` -> 'my-project' + return <>Search: {search} +} +``` + +## Parameters + +```tsx +const searchParams = useSearchParams() +``` + +`useSearchParams` does not take any parameters. + +## Returns + +`useSearchParams` returns a **read-only** version of the [`URLSearchParams`](https://developer.mozilla.org/docs/Web/API/URLSearchParams) interface, or `null` during [pre-rendering](#behavior-during-pre-rendering). + +The interface includes utility methods for reading the URL's query string: + +- [`URLSearchParams.get()`](https://developer.mozilla.org/docs/Web/API/URLSearchParams/get): Returns the first value associated with the search parameter. For example: + + | URL | `searchParams.get("a")` | + | -------------------- | --------------------------------------------------------------------------------------------------------------- | + | `/dashboard?a=1` | `'1'` | + | `/dashboard?a=` | `''` | + | `/dashboard?b=3` | `null` | + | `/dashboard?a=1&a=2` | `'1'` _- use [`getAll()`](https://developer.mozilla.org/docs/Web/API/URLSearchParams/getAll) to get all values_ | + +- [`URLSearchParams.has()`](https://developer.mozilla.org/docs/Web/API/URLSearchParams/has): Returns a boolean value indicating if the given parameter exists. For example: + + | URL | `searchParams.has("a")` | + | ---------------- | ----------------------- | + | `/dashboard?a=1` | `true` | + | `/dashboard?b=3` | `false` | + +- Learn more about other **read-only** methods of [`URLSearchParams`](https://developer.mozilla.org/docs/Web/API/URLSearchParams), including the [`getAll()`](https://developer.mozilla.org/docs/Web/API/URLSearchParams/getAll), [`keys()`](https://developer.mozilla.org/docs/Web/API/URLSearchParams/keys), [`values()`](https://developer.mozilla.org/docs/Web/API/URLSearchParams/values), [`entries()`](https://developer.mozilla.org/docs/Web/API/URLSearchParams/entries), [`forEach()`](https://developer.mozilla.org/docs/Web/API/URLSearchParams/forEach), and [`toString()`](https://developer.mozilla.org/docs/Web/API/URLSearchParams/toString). + +> **Good to know**: `useSearchParams` is a [React Hook](https://react.dev/learn#using-hooks) and cannot be used with classes. + +## Behavior + +### Behavior during pre-rendering + +For pages that are [statically optimized](/docs/pages/building-your-application/rendering/automatic-static-optimization) (not using `getServerSideProps`), `useSearchParams` will return `null` during pre-rendering. After hydration, the value will be updated to the actual search params. + +This is because search params cannot be known during static generation as they depend on the request. + +```tsx filename="pages/dashboard.tsx" switcher +import { useSearchParams } from 'next/navigation' + +export default function Dashboard() { + const searchParams = useSearchParams() + + if (!searchParams) { + // Return a fallback UI while search params are loading + // This prevents hydration mismatches + return + } + + const search = searchParams.get('search') + + return <>Search: {search} +} +``` + +```jsx filename="pages/dashboard.js" switcher +import { useSearchParams } from 'next/navigation' + +export default function Dashboard() { + const searchParams = useSearchParams() + + if (!searchParams) { + // Return a fallback UI while search params are loading + // This prevents hydration mismatches + return + } + + const search = searchParams.get('search') + + return <>Search: {search} +} +``` + +### Using with `getServerSideProps` + +When using [`getServerSideProps`](/docs/pages/building-your-application/data-fetching/get-server-side-props), the page is server-rendered on each request and `useSearchParams` will return the actual search params immediately: + +```tsx filename="pages/dashboard.tsx" switcher +import { useSearchParams } from 'next/navigation' + +export default function Dashboard() { + const searchParams = useSearchParams() + + // With getServerSideProps, this fallback is never rendered because + // searchParams is always available on the server. However, keeping + // the fallback allows this component to be reused on other pages + // that may not use getServerSideProps. + if (!searchParams) { + return null + } + + const search = searchParams.get('search') + + return <>Search: {search} +} + +export async function getServerSideProps() { + return { props: {} } +} +``` + +```jsx filename="pages/dashboard.js" switcher +import { useSearchParams } from 'next/navigation' + +export default function Dashboard() { + const searchParams = useSearchParams() + + // With getServerSideProps, this fallback is never rendered because + // searchParams is always available on the server. However, keeping + // the fallback allows this component to be reused on other pages + // that may not use getServerSideProps. + if (!searchParams) { + return null + } + + const search = searchParams.get('search') + + return <>Search: {search} +} + +export async function getServerSideProps() { + return { props: {} } +} +``` + +## Examples + +### Updating search params + +You can use the [`useRouter`](/docs/pages/api-reference/functions/use-router) hook to update search params: + +```tsx filename="pages/dashboard.tsx" switcher +import { useRouter } from 'next/router' +import { useSearchParams } from 'next/navigation' +import { useCallback } from 'react' + +export default function Dashboard() { + const router = useRouter() + const searchParams = useSearchParams() + + const createQueryString = useCallback( + (name: string, value: string) => { + const params = new URLSearchParams(searchParams?.toString()) + params.set(name, value) + return params.toString() + }, + [searchParams] + ) + + if (!searchParams) { + return null + } + + return ( + <> +

Sort By

+ + + + ) +} +``` + +```jsx filename="pages/dashboard.js" switcher +import { useRouter } from 'next/router' +import { useSearchParams } from 'next/navigation' +import { useCallback } from 'react' + +export default function Dashboard() { + const router = useRouter() + const searchParams = useSearchParams() + + const createQueryString = useCallback( + (name, value) => { + const params = new URLSearchParams(searchParams?.toString()) + params.set(name, value) + return params.toString() + }, + [searchParams] + ) + + if (!searchParams) { + return null + } + + return ( + <> +

Sort By

+ + + + ) +} +``` + +### Sharing components with App Router + +`useSearchParams` from `next/navigation` works in both the Pages Router and App Router. This allows you to create shared components that work in either context: + +```tsx filename="components/search-bar.tsx" switcher +import { useSearchParams } from 'next/navigation' + +// This component works in both pages/ and app/ +export function SearchBar() { + const searchParams = useSearchParams() + + if (!searchParams) { + // Fallback for Pages Router during pre-rendering + return + } + + const search = searchParams.get('search') ?? '' + + return +} +``` + +```jsx filename="components/search-bar.js" switcher +import { useSearchParams } from 'next/navigation' + +// This component works in both pages/ and app/ +export function SearchBar() { + const searchParams = useSearchParams() + + if (!searchParams) { + // Fallback for Pages Router during pre-rendering + return + } + + const search = searchParams.get('search') ?? '' + + return +} +``` + +> **Good to know**: When using this component in the App Router, wrap it in a `` boundary for [static rendering](/docs/app/api-reference/functions/use-search-params#static-rendering) support. + +## Version History + +| Version | Changes | +| --------- | ----------------------------- | +| `v13.0.0` | `useSearchParams` introduced. | diff --git a/lerna.json b/lerna.json index 91aa4b780c74..ad2a3b9c8590 100644 --- a/lerna.json +++ b/lerna.json @@ -15,5 +15,5 @@ "registry": "https://registry.npmjs.org/" } }, - "version": "16.1.1-canary.22" + "version": "16.1.1-canary.31" } \ No newline at end of file diff --git a/package.json b/package.json index 82906f2dec50..cc9859ba039a 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "scripts": { "new-error": "turbo gen error", "new-test": "turbo gen test", - "clean": "lerna clean -y && lerna bootstrap && lerna run clean && lerna exec 'node ../../scripts/rm.mjs dist'", + "clean": "lerna clean -y && lerna run clean && lerna exec 'node ../../scripts/rm.mjs dist'", "build": "turbo run build --remote-cache-timeout 60 --summarize true", "lerna": "lerna", "dev": "turbo run dev --parallel --filter=\"!@next/bundle-analyzer-ui\"", @@ -198,7 +198,7 @@ "eslint-plugin-jsdoc": "48.0.4", "eslint-plugin-mdx": "3.1.5", "eslint-plugin-react": "7.37.0", - "eslint-plugin-react-hooks": "0.0.0-experimental-65eec428-20251218", + "eslint-plugin-react-hooks": "0.0.0-experimental-bef88f7c-20260116", "event-stream": "4.0.1", "execa": "2.0.3", "expect": "29.7.0", @@ -258,16 +258,16 @@ "pretty-ms": "7.0.0", "random-seed": "0.3.0", "react": "19.0.0", - "react-builtin": "npm:react@19.3.0-canary-65eec428-20251218", + "react-builtin": "npm:react@19.3.0-canary-bef88f7c-20260116", "react-dom": "19.0.0", - "react-dom-builtin": "npm:react-dom@19.3.0-canary-65eec428-20251218", - "react-dom-experimental-builtin": "npm:react-dom@0.0.0-experimental-65eec428-20251218", - "react-experimental-builtin": "npm:react@0.0.0-experimental-65eec428-20251218", - "react-is-builtin": "npm:react-is@19.3.0-canary-65eec428-20251218", - "react-server-dom-turbopack": "19.3.0-canary-65eec428-20251218", - "react-server-dom-turbopack-experimental": "npm:react-server-dom-turbopack@0.0.0-experimental-65eec428-20251218", - "react-server-dom-webpack": "19.3.0-canary-65eec428-20251218", - "react-server-dom-webpack-experimental": "npm:react-server-dom-webpack@0.0.0-experimental-65eec428-20251218", + "react-dom-builtin": "npm:react-dom@19.3.0-canary-bef88f7c-20260116", + "react-dom-experimental-builtin": "npm:react-dom@0.0.0-experimental-bef88f7c-20260116", + "react-experimental-builtin": "npm:react@0.0.0-experimental-bef88f7c-20260116", + "react-is-builtin": "npm:react-is@19.3.0-canary-bef88f7c-20260116", + "react-server-dom-turbopack": "19.3.0-canary-bef88f7c-20260116", + "react-server-dom-turbopack-experimental": "npm:react-server-dom-turbopack@0.0.0-experimental-bef88f7c-20260116", + "react-server-dom-webpack": "19.3.0-canary-bef88f7c-20260116", + "react-server-dom-webpack-experimental": "npm:react-server-dom-webpack@0.0.0-experimental-bef88f7c-20260116", "react-ssr-prepass": "1.0.8", "react-virtualized": "9.22.3", "relay-compiler": "13.0.2", @@ -277,8 +277,8 @@ "resolve-from": "5.0.0", "sass": "1.54.0", "satori": "0.15.2", - "scheduler-builtin": "npm:scheduler@0.28.0-canary-65eec428-20251218", - "scheduler-experimental-builtin": "npm:scheduler@0.0.0-experimental-65eec428-20251218", + "scheduler-builtin": "npm:scheduler@0.28.0-canary-bef88f7c-20260116", + "scheduler-experimental-builtin": "npm:scheduler@0.0.0-experimental-bef88f7c-20260116", "seedrandom": "3.0.5", "semver": "7.3.7", "serve-handler": "6.1.6", @@ -323,10 +323,10 @@ "@types/react-dom": "19.2.1", "@types/retry": "0.12.0", "jest-snapshot": "30.0.0-alpha.6", - "react": "19.3.0-canary-65eec428-20251218", - "react-dom": "19.3.0-canary-65eec428-20251218", - "react-is": "19.3.0-canary-65eec428-20251218", - "scheduler": "0.28.0-canary-65eec428-20251218" + "react": "19.3.0-canary-bef88f7c-20260116", + "react-dom": "19.3.0-canary-bef88f7c-20260116", + "react-is": "19.3.0-canary-bef88f7c-20260116", + "scheduler": "0.28.0-canary-bef88f7c-20260116" }, "packageExtensions": { "eslint-plugin-react-hooks@0.0.0-experimental-6de32a5a-20250822": { diff --git a/packages/create-next-app/helpers/get-pkg-manager.ts b/packages/create-next-app/helpers/get-pkg-manager.ts index 20900ebcb9ed..2d9f850949de 100644 --- a/packages/create-next-app/helpers/get-pkg-manager.ts +++ b/packages/create-next-app/helpers/get-pkg-manager.ts @@ -1,3 +1,5 @@ +import { execSync } from 'child_process' + export type PackageManager = 'npm' | 'pnpm' | 'yarn' | 'bun' export function getPkgManager(): PackageManager { @@ -17,3 +19,35 @@ export function getPkgManager(): PackageManager { return 'npm' } + +/** + * Get the major version of pnpm being used. + * Returns null if unable to determine the version. + * + * First tries to parse from npm_config_user_agent (e.g., "pnpm/9.13.2 npm/? ..."), + * then falls back to spawning `pnpm --version --silent`. + */ +export function getPnpmMajorVersion(): number | null { + // Try to get version from user agent first (e.g., "pnpm/9.13.2 npm/? node/v20.x linux x64") + const userAgent = process.env.npm_config_user_agent || '' + const pnpmVersionMatch = userAgent.match(/pnpm\/(\d+)/) + if (pnpmVersionMatch) { + return parseInt(pnpmVersionMatch[1], 10) + } + + // Fall back to spawning pnpm --version + try { + const version = execSync('pnpm --version --silent', { + encoding: 'utf8', + stdio: ['pipe', 'pipe', 'ignore'], + }).trim() + const majorVersion = parseInt(version.split('.')[0], 10) + if (!Number.isNaN(majorVersion)) { + return majorVersion + } + } catch { + // pnpm not available or failed to run + } + + return null +} diff --git a/packages/create-next-app/package.json b/packages/create-next-app/package.json index ec85e7c66a31..f9d35096643e 100644 --- a/packages/create-next-app/package.json +++ b/packages/create-next-app/package.json @@ -1,6 +1,6 @@ { "name": "create-next-app", - "version": "16.1.1-canary.22", + "version": "16.1.1-canary.31", "keywords": [ "react", "next", diff --git a/packages/create-next-app/templates/index.ts b/packages/create-next-app/templates/index.ts index 5fbd1dc6ccf1..bca5bf716666 100644 --- a/packages/create-next-app/templates/index.ts +++ b/packages/create-next-app/templates/index.ts @@ -1,6 +1,7 @@ import { install } from "../helpers/install"; import { runTypegen } from "../helpers/typegen"; import { copy } from "../helpers/copy"; +import { getPnpmMajorVersion } from "../helpers/get-pkg-manager"; import { async as glob } from "fast-glob"; import os from "os"; @@ -320,24 +321,29 @@ export const installTemplate = async ({ } if (packageManager === "pnpm") { - const pnpmWorkspaceYaml = [ - // required for v9, v10 doesn't need it anymore - "packages:", - " - .", - // v10 setting without counterpart in v9 - "ignoredBuiltDependencies:", - // Sharp has prebuilt binaries for the platforms next-swc has binaries. - // If it needs to build binaries from source, next-swc wouldn't work either. - // See https://sharp.pixelplumbing.com/install/#:~:text=When%20using%20pnpm%2C%20add%20sharp%20to%20ignoredBuiltDependencies%20to%20silence%20warnings - " - sharp", - // Not needed for pnpm: https://github.com/unrs/unrs-resolver/issues/193#issuecomment-3295510146 - " - unrs-resolver", - "", - ].join(os.EOL); - await fs.writeFile( - path.join(root, "pnpm-workspace.yaml"), - pnpmWorkspaceYaml, - ); + // Only create pnpm-workspace.yaml for pnpm v10+. + // In v9, having a pnpm-workspace.yaml (even with packages: []) causes + // ERR_PNPM_ADDING_TO_ROOT errors when running `pnpm add`. + // In v10, the packages field can be omitted entirely. + // If we can't determine the version, assume latest (v10+) since we already + // know pnpm is being used at this point. + const pnpmMajorVersion = getPnpmMajorVersion(); + if (pnpmMajorVersion === null || pnpmMajorVersion >= 10) { + const pnpmWorkspaceYaml = [ + "ignoredBuiltDependencies:", + // Sharp has prebuilt binaries for the platforms next-swc has binaries. + // If it needs to build binaries from source, next-swc wouldn't work either. + // See https://sharp.pixelplumbing.com/install/#:~:text=When%20using%20pnpm%2C%20add%20sharp%20to%20ignoredBuiltDependencies%20to%20silence%20warnings + " - sharp", + // Not needed for pnpm: https://github.com/unrs/unrs-resolver/issues/193#issuecomment-3295510146 + " - unrs-resolver", + "", + ].join(os.EOL); + await fs.writeFile( + path.join(root, "pnpm-workspace.yaml"), + pnpmWorkspaceYaml, + ); + } } if (packageManager === "bun") { diff --git a/packages/eslint-config-next/package.json b/packages/eslint-config-next/package.json index 98107f6d2f69..f08dd3c3941d 100644 --- a/packages/eslint-config-next/package.json +++ b/packages/eslint-config-next/package.json @@ -1,6 +1,6 @@ { "name": "eslint-config-next", - "version": "16.1.1-canary.22", + "version": "16.1.1-canary.31", "description": "ESLint configuration used by Next.js.", "license": "MIT", "repository": { @@ -12,7 +12,7 @@ "dist" ], "dependencies": { - "@next/eslint-plugin-next": "16.1.1-canary.22", + "@next/eslint-plugin-next": "16.1.1-canary.31", "eslint-import-resolver-node": "^0.3.6", "eslint-import-resolver-typescript": "^3.5.2", "eslint-plugin-import": "^2.32.0", diff --git a/packages/eslint-plugin-internal/package.json b/packages/eslint-plugin-internal/package.json index e5f7caac490c..ec3a8f34cea6 100644 --- a/packages/eslint-plugin-internal/package.json +++ b/packages/eslint-plugin-internal/package.json @@ -1,7 +1,7 @@ { "name": "@next/eslint-plugin-internal", "private": true, - "version": "16.1.1-canary.22", + "version": "16.1.1-canary.31", "description": "ESLint plugin for working on Next.js.", "exports": { ".": "./src/eslint-plugin-internal.js" diff --git a/packages/eslint-plugin-next/package.json b/packages/eslint-plugin-next/package.json index 68e18f642e68..397fec410540 100644 --- a/packages/eslint-plugin-next/package.json +++ b/packages/eslint-plugin-next/package.json @@ -1,6 +1,6 @@ { "name": "@next/eslint-plugin-next", - "version": "16.1.1-canary.22", + "version": "16.1.1-canary.31", "description": "ESLint plugin for Next.js.", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/font/package.json b/packages/font/package.json index 0432314b052b..528519e0842a 100644 --- a/packages/font/package.json +++ b/packages/font/package.json @@ -1,7 +1,7 @@ { "name": "@next/font", "private": true, - "version": "16.1.1-canary.22", + "version": "16.1.1-canary.31", "repository": { "url": "vercel/next.js", "directory": "packages/font" diff --git a/packages/next-bundle-analyzer/package.json b/packages/next-bundle-analyzer/package.json index eb45f9d4ddf0..bf6d24ecfc6d 100644 --- a/packages/next-bundle-analyzer/package.json +++ b/packages/next-bundle-analyzer/package.json @@ -1,6 +1,6 @@ { "name": "@next/bundle-analyzer", - "version": "16.1.1-canary.22", + "version": "16.1.1-canary.31", "main": "index.js", "types": "index.d.ts", "license": "MIT", diff --git a/packages/next-codemod/package.json b/packages/next-codemod/package.json index 1481475a6ca6..bec6c45f6c96 100644 --- a/packages/next-codemod/package.json +++ b/packages/next-codemod/package.json @@ -1,6 +1,6 @@ { "name": "@next/codemod", - "version": "16.1.1-canary.22", + "version": "16.1.1-canary.31", "license": "MIT", "repository": { "type": "git", diff --git a/packages/next-env/package.json b/packages/next-env/package.json index 4365779134a6..e3dada2db389 100644 --- a/packages/next-env/package.json +++ b/packages/next-env/package.json @@ -1,6 +1,6 @@ { "name": "@next/env", - "version": "16.1.1-canary.22", + "version": "16.1.1-canary.31", "keywords": [ "react", "next", diff --git a/packages/next-mdx/package.json b/packages/next-mdx/package.json index d294cc54e440..960ebd407901 100644 --- a/packages/next-mdx/package.json +++ b/packages/next-mdx/package.json @@ -1,6 +1,6 @@ { "name": "@next/mdx", - "version": "16.1.1-canary.22", + "version": "16.1.1-canary.31", "main": "index.js", "license": "MIT", "repository": { diff --git a/packages/next-plugin-storybook/package.json b/packages/next-plugin-storybook/package.json index 37281f000c5e..de52efa35a3e 100644 --- a/packages/next-plugin-storybook/package.json +++ b/packages/next-plugin-storybook/package.json @@ -1,6 +1,6 @@ { "name": "@next/plugin-storybook", - "version": "16.1.1-canary.22", + "version": "16.1.1-canary.31", "repository": { "url": "vercel/next.js", "directory": "packages/next-plugin-storybook" diff --git a/packages/next-polyfill-module/package.json b/packages/next-polyfill-module/package.json index 2644c11ea1b0..82b240420e27 100644 --- a/packages/next-polyfill-module/package.json +++ b/packages/next-polyfill-module/package.json @@ -1,6 +1,6 @@ { "name": "@next/polyfill-module", - "version": "16.1.1-canary.22", + "version": "16.1.1-canary.31", "description": "A standard library polyfill for ES Modules supporting browsers (Edge 16+, Firefox 60+, Chrome 61+, Safari 10.1+)", "main": "dist/polyfill-module.js", "license": "MIT", diff --git a/packages/next-polyfill-nomodule/package.json b/packages/next-polyfill-nomodule/package.json index 5c336781e318..98255ab1207e 100644 --- a/packages/next-polyfill-nomodule/package.json +++ b/packages/next-polyfill-nomodule/package.json @@ -1,6 +1,6 @@ { "name": "@next/polyfill-nomodule", - "version": "16.1.1-canary.22", + "version": "16.1.1-canary.31", "description": "A polyfill for non-dead, nomodule browsers.", "main": "dist/polyfill-nomodule.js", "license": "MIT", diff --git a/packages/next-routing/package.json b/packages/next-routing/package.json index f3db9afac95d..3196c283a2f1 100644 --- a/packages/next-routing/package.json +++ b/packages/next-routing/package.json @@ -1,6 +1,6 @@ { "name": "@next/routing", - "version": "16.1.1-canary.22", + "version": "16.1.1-canary.31", "keywords": [ "react", "next", diff --git a/packages/next-rspack/package.json b/packages/next-rspack/package.json index 4c047fc1875e..1363e1796201 100644 --- a/packages/next-rspack/package.json +++ b/packages/next-rspack/package.json @@ -1,6 +1,6 @@ { "name": "next-rspack", - "version": "16.1.1-canary.22", + "version": "16.1.1-canary.31", "repository": { "url": "vercel/next.js", "directory": "packages/next-rspack" diff --git a/packages/next-swc/package.json b/packages/next-swc/package.json index a3c3121d683b..d4881f3c24b5 100644 --- a/packages/next-swc/package.json +++ b/packages/next-swc/package.json @@ -1,6 +1,6 @@ { "name": "@next/swc", - "version": "16.1.1-canary.22", + "version": "16.1.1-canary.31", "private": true, "files": [ "native/" diff --git a/packages/next/package.json b/packages/next/package.json index cc8ce43067e5..dc55e9f3362f 100644 --- a/packages/next/package.json +++ b/packages/next/package.json @@ -1,6 +1,6 @@ { "name": "next", - "version": "16.1.1-canary.22", + "version": "16.1.1-canary.31", "description": "The React Framework", "main": "./dist/server/next.js", "license": "MIT", @@ -97,7 +97,7 @@ ] }, "dependencies": { - "@next/env": "16.1.1-canary.22", + "@next/env": "16.1.1-canary.31", "@swc/helpers": "0.5.15", "baseline-browser-mapping": "^2.8.3", "caniuse-lite": "^1.0.30001579", @@ -162,11 +162,11 @@ "@modelcontextprotocol/sdk": "1.18.1", "@mswjs/interceptors": "0.23.0", "@napi-rs/triples": "1.2.0", - "@next/font": "16.1.1-canary.22", - "@next/polyfill-module": "16.1.1-canary.22", - "@next/polyfill-nomodule": "16.1.1-canary.22", - "@next/react-refresh-utils": "16.1.1-canary.22", - "@next/swc": "16.1.1-canary.22", + "@next/font": "16.1.1-canary.31", + "@next/polyfill-module": "16.1.1-canary.31", + "@next/polyfill-nomodule": "16.1.1-canary.31", + "@next/react-refresh-utils": "16.1.1-canary.31", + "@next/swc": "16.1.1-canary.31", "@opentelemetry/api": "1.6.0", "@playwright/test": "1.51.1", "@rspack/core": "1.6.7", diff --git a/packages/next/src/build/analysis/get-page-static-info.ts b/packages/next/src/build/analysis/get-page-static-info.ts index afafdda505cf..e391f3bc48c7 100644 --- a/packages/next/src/build/analysis/get-page-static-info.ts +++ b/packages/next/src/build/analysis/get-page-static-info.ts @@ -113,8 +113,10 @@ export type PageStaticInfo = AppPageStaticInfo | PagesPageStaticInfo const CLIENT_MODULE_LABEL = /\/\* __next_internal_client_entry_do_not_use__ ([^ ]*) (cjs|auto) \*\// +// Match JSON object that may contain nested objects (for loc info) +// The JSON ends right before the closing " */" const ACTION_MODULE_LABEL = - /\/\* __next_internal_action_entry_do_not_use__ (\{[^}]+\}) \*\// + /\/\* __next_internal_action_entry_do_not_use__ (\{.*\}) \*\// const CLIENT_DIRECTIVE = 'use client' const SERVER_ACTION_DIRECTIVE = 'use server' @@ -125,8 +127,9 @@ export function getRSCModuleInformation( isReactServerLayer: boolean ): RSCMeta { const actionsJson = source.match(ACTION_MODULE_LABEL) + // Parse action metadata - supports both old format (string) and new format (object with loc) const parsedActionsMeta = actionsJson - ? (JSON.parse(actionsJson[1]) as Record) + ? (JSON.parse(actionsJson[1]) as RSCMeta['actionIds']) : undefined const clientInfoMatch = source.match(CLIENT_MODULE_LABEL) const isClientRef = !!clientInfoMatch diff --git a/packages/next/src/build/index.ts b/packages/next/src/build/index.ts index 61223ab7b992..f948dfd4568d 100644 --- a/packages/next/src/build/index.ts +++ b/packages/next/src/build/index.ts @@ -229,6 +229,7 @@ import { createRouteTypesManifest, writeRouteTypesManifest, writeValidatorFile, + writeRouteTypesEntryFile, } from '../server/lib/router-utils/route-types-utils' import { Lockfile } from './lockfile' import { @@ -1421,7 +1422,13 @@ export default async function build( await nextBuildSpan .traceChild('generate-route-types') .traceAsyncFn(async () => { - const routeTypesFilePath = path.join(distDir, 'types', 'routes.d.ts') + // Actual type files go to route-types.d.ts (not routes.d.ts) + // routes.d.ts is reserved for the entry file + const routeTypesFilePath = path.join( + distDir, + 'types', + 'route-types.d.ts' + ) const validatorFilePath = path.join(distDir, 'types', 'validator.ts') await mkdir(path.dirname(routeTypesFilePath), { recursive: true }) @@ -1506,6 +1513,20 @@ export default async function build( validatorFilePath, Boolean(config.experimental.strictRouteTypes) ) + + // Write the entry file at {distDirRoot}/types/routes.d.ts + // This ensures next-env.d.ts has a consistent import path + const entryFilePath = path.join( + dir, + config.distDirRoot, + 'types', + 'routes.d.ts' + ) + const actualTypesDir = path.join(distDir, 'types') + await writeRouteTypesEntryFile(entryFilePath, actualTypesDir, { + strictRouteTypes: Boolean(config.experimental.strictRouteTypes), + typedRoutes: Boolean(config.typedRoutes), + }) }) // Turbopack already handles conflicting app and page routes. diff --git a/packages/next/src/build/swc/index.ts b/packages/next/src/build/swc/index.ts index 18b8ef1d2520..257314bcb04a 100644 --- a/packages/next/src/build/swc/index.ts +++ b/packages/next/src/build/swc/index.ts @@ -950,6 +950,9 @@ function bindingToApi( | { type: 'regex'; value: { source: string; flags: string } } | { type: 'glob'; value: string } content?: { source: string; flags: string } + query?: + | { type: 'regex'; value: { source: string; flags: string } } + | { type: 'constant'; value: string } } // converts regexes to a `RegexComponents` object so that it can be JSON-serialized when passed to @@ -985,6 +988,15 @@ function bindingToApi( } : { type: 'glob', value: cond.path }, content: cond.content && regexComponents(cond.content), + query: + cond.query == null + ? undefined + : cond.query instanceof RegExp + ? { + type: 'regex', + value: regexComponents(cond.query), + } + : { type: 'constant', value: cond.query }, } } } diff --git a/packages/next/src/build/templates/app-page.ts b/packages/next/src/build/templates/app-page.ts index b7964efe7a3a..701d9ee902ba 100644 --- a/packages/next/src/build/templates/app-page.ts +++ b/packages/next/src/build/templates/app-page.ts @@ -75,18 +75,18 @@ import { */ declare const tree: LoaderTree -// We inject the tree and pages here so that we can use them in the route -// module. -// INJECT:tree - -import GlobalError from 'VAR_MODULE_GLOBAL_ERROR' with { 'turbopack-transition': 'next-server-utility' } - +// TODO this should ideally be read from the loader tree instead, where it's always inserted already anyway. +import GlobalError from 'VAR_MODULE_GLOBAL_ERROR' with { 'turbopack-transition': 'next-server-component' } export { GlobalError } // These are injected by the loader afterwards. declare const __next_app_require__: (id: string | number) => unknown declare const __next_app_load_chunk__: (id: string | number) => Promise +// We inject the tree and pages here so that we can use them in the route +// module. +// INJECT:tree + // INJECT:__next_app_require__ // INJECT:__next_app_load_chunk__ @@ -1246,8 +1246,6 @@ export async function handler( RSC_CONTENT_TYPE_HEADER ), cacheControl: cacheEntry.cacheControl, - cdnCacheControlHeader: - nextConfig.experimental.cdnCacheControlHeader, }) } @@ -1265,7 +1263,6 @@ export async function handler( poweredByHeader: nextConfig.poweredByHeader, result: RenderResult.EMPTY, cacheControl: cacheEntry.cacheControl, - cdnCacheControlHeader: nextConfig.experimental.cdnCacheControlHeader, }) } @@ -1355,8 +1352,6 @@ export async function handler( poweredByHeader: nextConfig.poweredByHeader, result: RenderResult.EMPTY, cacheControl: cacheEntry.cacheControl, - cdnCacheControlHeader: - nextConfig.experimental.cdnCacheControlHeader, }) } else { // Otherwise this case is not expected. @@ -1373,8 +1368,6 @@ export async function handler( poweredByHeader: nextConfig.poweredByHeader, result: cachedData.html, cacheControl: cacheEntry.cacheControl, - cdnCacheControlHeader: - nextConfig.experimental.cdnCacheControlHeader, }) } @@ -1390,7 +1383,6 @@ export async function handler( RSC_CONTENT_TYPE_HEADER ), cacheControl: cacheEntry.cacheControl, - cdnCacheControlHeader: nextConfig.experimental.cdnCacheControlHeader, }) } @@ -1423,7 +1415,6 @@ export async function handler( poweredByHeader: nextConfig.poweredByHeader, result: body, cacheControl: cacheEntry.cacheControl, - cdnCacheControlHeader: nextConfig.experimental.cdnCacheControlHeader, }) } @@ -1450,7 +1441,6 @@ export async function handler( poweredByHeader: nextConfig.poweredByHeader, result: body, cacheControl: { revalidate: 0, expire: undefined }, - cdnCacheControlHeader: nextConfig.experimental.cdnCacheControlHeader, }) } @@ -1510,7 +1500,6 @@ export async function handler( // the response being sent to the client it's dynamic parts are streamed // to the client on the same request. cacheControl: { revalidate: 0, expire: undefined }, - cdnCacheControlHeader: nextConfig.experimental.cdnCacheControlHeader, }) } diff --git a/packages/next/src/build/templates/app-route.ts b/packages/next/src/build/templates/app-route.ts index 2c5348dd7be2..c07c51affff9 100644 --- a/packages/next/src/build/templates/app-route.ts +++ b/packages/next/src/build/templates/app-route.ts @@ -27,7 +27,7 @@ import { fromNodeOutgoingHttpHeaders, toNodeOutgoingHttpHeaders, } from '../../server/web/utils' -import { setCacheControlHeaders } from '../../server/lib/cache-control' +import { getCacheControlHeader } from '../../server/lib/cache-control' import { INFINITE_CACHE, NEXT_CACHE_TAGS_HEADER } from '../../lib/constants' import { NoFallbackError } from '../../shared/lib/no-fallback-error.external' import { @@ -459,10 +459,9 @@ export async function handler( !res.getHeader('Cache-Control') && !headers.get('Cache-Control') ) { - setCacheControlHeaders( - headers, - cacheEntry.cacheControl, - nextConfig.experimental.cdnCacheControlHeader + headers.set( + 'Cache-Control', + getCacheControlHeader(cacheEntry.cacheControl) ) } diff --git a/packages/next/src/build/type-check.ts b/packages/next/src/build/type-check.ts index d674b370e7aa..cff4f47ce471 100644 --- a/packages/next/src/build/type-check.ts +++ b/packages/next/src/build/type-check.ts @@ -20,10 +20,10 @@ import { hrtimeDurationToString } from './duration-to-string' function verifyTypeScriptSetup( dir: string, distDir: string, + distDirRoot: string, strictRouteTypes: boolean, typeCheckPreflight: boolean, tsconfigPath: string | undefined, - typedRoutes: boolean, disableStaticImages: boolean, cacheDir: string | undefined, enableWorkerThreads: boolean | undefined, @@ -52,10 +52,10 @@ function verifyTypeScriptSetup( .verifyTypeScriptSetup({ dir, distDir, + distDirRoot, strictRouteTypes, typeCheckPreflight, tsconfigPath, - typedRoutes, disableStaticImages, cacheDir, hasAppDir, @@ -121,10 +121,10 @@ export async function startTypeChecking({ verifyTypeScriptSetup( dir, config.distDir, + config.distDirRoot, Boolean(config.experimental.strictRouteTypes), !ignoreTypeScriptErrors, config.typescript.tsconfigPath, - Boolean(config.typedRoutes), config.images.disableStaticImages, cacheDir, config.experimental.workerThreads, diff --git a/packages/next/src/build/webpack/loaders/get-module-build-info.ts b/packages/next/src/build/webpack/loaders/get-module-build-info.ts index c15052f7cb93..f677d988d685 100644 --- a/packages/next/src/build/webpack/loaders/get-module-build-info.ts +++ b/packages/next/src/build/webpack/loaders/get-module-build-info.ts @@ -26,9 +26,26 @@ export function getModuleBuildInfo(webpackModule: webpack.Module) { return webpackModule.buildInfo as ModuleBuildInfo } +/** + * Location info for a server action (1-indexed line and column) + */ +export interface ServerActionLocation { + line: number + col: number +} + +/** + * Server action info including name and optional source location + */ +export interface ServerActionInfo { + name: string + loc?: ServerActionLocation +} + export interface RSCMeta { type: RSCModuleType - actionIds?: Record + /** Map of action ID to export name (old format) or action info (new format with location) */ + actionIds?: Record clientRefs?: string[] clientEntryType?: 'cjs' | 'auto' isClientRef?: boolean diff --git a/packages/next/src/build/webpack/loaders/next-flight-client-module-loader.ts b/packages/next/src/build/webpack/loaders/next-flight-client-module-loader.ts index 186c68d6ed5a..9f4c9f82f59a 100644 --- a/packages/next/src/build/webpack/loaders/next-flight-client-module-loader.ts +++ b/packages/next/src/build/webpack/loaders/next-flight-client-module-loader.ts @@ -32,7 +32,10 @@ const flightClientModuleLoader: webpack.LoaderDefinitionFunction = return ( prefix + Object.entries(buildInfo.rsc.actionIds) - .map(([id, name]) => { + .map(([id, exportInfo]) => { + // exportInfo can be a string (legacy) or object with name + const name = + typeof exportInfo === 'string' ? exportInfo : exportInfo.name return `export { ${name} } from 'next-flight-server-reference-proxy-loader?id=${id}&name=${name}!'` }) .join('\n') diff --git a/packages/next/src/build/webpack/plugins/flight-client-entry-plugin.ts b/packages/next/src/build/webpack/plugins/flight-client-entry-plugin.ts index b01dce4bcd7d..45757716b517 100644 --- a/packages/next/src/build/webpack/plugins/flight-client-entry-plugin.ts +++ b/packages/next/src/build/webpack/plugins/flight-client-entry-plugin.ts @@ -81,7 +81,11 @@ type Actions = { } } -type ActionIdNamePair = { id: string; exportedName?: string; filename?: string } +type ActionIdNamePair = { + id: string + exportedName?: string + filename?: string +} export type ActionManifest = { // Assign a unique encryption key during production build. @@ -658,11 +662,18 @@ export class FlightClientEntryPlugin { if (actionIds) { collectedActions.set( modResource, - Object.entries(actionIds).map(([id, exportedName]) => ({ - id, - exportedName, - filename: path.posix.relative(this.projectDir, modResource), - })) + Object.entries(actionIds).map(([id, actionInfo]) => { + // Handle both old format (string) and new format (object with name) + const exportedName = + typeof actionInfo === 'object' && actionInfo !== null + ? actionInfo.name + : actionInfo + return { + id, + exportedName, + filename: path.posix.relative(this.projectDir, modResource), + } + }) ) } @@ -759,11 +770,18 @@ export class FlightClientEntryPlugin { if (actionIds) { actionImports.push([ modResource, - Object.entries(actionIds).map(([id, exportedName]) => ({ - id, - exportedName, - filename: path.posix.relative(this.projectDir, modResource), - })), + Object.entries(actionIds).map(([id, actionInfo]) => { + // Handle both old format (string) and new format (object with name) + const exportedName = + typeof actionInfo === 'object' && actionInfo !== null + ? actionInfo.name + : actionInfo + return { + id, + exportedName, + filename: path.posix.relative(this.projectDir, modResource), + } + }), ]) } diff --git a/packages/next/src/build/webpack/plugins/flight-manifest-plugin.ts b/packages/next/src/build/webpack/plugins/flight-manifest-plugin.ts index 2786b0d8f122..3dee6cccc8ce 100644 --- a/packages/next/src/build/webpack/plugins/flight-manifest-plugin.ts +++ b/packages/next/src/build/webpack/plugins/flight-manifest-plugin.ts @@ -578,13 +578,27 @@ export class ClientReferenceManifestPlugin { edgeRscModuleMapping: {}, } - const segments = [...entryNameToGroupName(pageName).split('/'), 'page'] - let group = '' - for (const segment of segments) { - for (const manifest of manifestsPerGroup.get(group) || []) { + // Route handlers don't render React components and don't need + // client component references from parent layouts/pages. + // They only need their own entry's manifest (for 'use cache' support). + const isRouteHandler = /\/route$/.test(pageName) + + if (isRouteHandler) { + // Route handlers only get their own manifest, not parent manifests + const groupName = entryNameToGroupName(pageName) + for (const manifest of manifestsPerGroup.get(groupName) || []) { mergeManifest(mergedManifest, manifest) } - group += (group ? '/' : '') + segment + } else { + // Pages need manifests merged from parent layouts + const segments = [...entryNameToGroupName(pageName).split('/'), 'page'] + let group = '' + for (const segment of segments) { + for (const manifest of manifestsPerGroup.get(group) || []) { + mergeManifest(mergedManifest, manifest) + } + group += (group ? '/' : '') + segment + } } const json = JSON.stringify(mergedManifest) diff --git a/packages/next/src/cli/next-start.ts b/packages/next/src/cli/next-start.ts index 4fbb70f78043..356ac7e406f2 100755 --- a/packages/next/src/cli/next-start.ts +++ b/packages/next/src/cli/next-start.ts @@ -1,5 +1,12 @@ #!/usr/bin/env node +// Ensure NEXT_PRIVATE_START_TIME is set for accurate "Ready in" timing. +// This should already be set by bin/next.ts, but we set it here as a fallback +// in case the module is loaded through a different code path. +if (!process.env.NEXT_PRIVATE_START_TIME) { + process.env.NEXT_PRIVATE_START_TIME = Date.now().toString() +} + import '../server/lib/cpu-profile' import { saveCpuProfile } from '../server/lib/cpu-profile' import { startServer } from '../server/lib/start-server' diff --git a/packages/next/src/cli/next-test.ts b/packages/next/src/cli/next-test.ts index 065a7ae9dfeb..736ff34a91ed 100644 --- a/packages/next/src/cli/next-test.ts +++ b/packages/next/src/cli/next-test.ts @@ -140,10 +140,10 @@ async function runPlaywright( const { version: typeScriptVersion } = await verifyTypeScriptSetup({ dir: baseDir, distDir: nextConfig.distDir, + distDirRoot: nextConfig.distDirRoot, strictRouteTypes: Boolean(nextConfig.experimental.strictRouteTypes), typeCheckPreflight: false, tsconfigPath: nextConfig.typescript.tsconfigPath, - typedRoutes: Boolean(nextConfig.typedRoutes), disableStaticImages: nextConfig.images.disableStaticImages, hasAppDir: !!appDir, hasPagesDir: !!pagesDir, diff --git a/packages/next/src/cli/next-typegen.ts b/packages/next/src/cli/next-typegen.ts index 185bfe03905a..6bdde6f37253 100644 --- a/packages/next/src/cli/next-typegen.ts +++ b/packages/next/src/cli/next-typegen.ts @@ -29,6 +29,7 @@ import { createRouteTypesManifest, writeRouteTypesManifest, writeValidatorFile, + writeRouteTypesEntryFile, } from '../server/lib/router-utils/route-types-utils' import { writeCacheLifeTypes } from '../server/lib/router-utils/cache-life-type-utils' import { createValidFileMatcher } from '../server/lib/find-page-file' @@ -59,10 +60,10 @@ const nextTypegen = async ( await verifyTypeScriptSetup({ dir: baseDir, distDir: nextConfig.distDir, + distDirRoot: nextConfig.distDirRoot, strictRouteTypes, typeCheckPreflight: false, tsconfigPath: nextConfig.typescript.tsconfigPath, - typedRoutes: Boolean(nextConfig.typedRoutes), disableStaticImages: nextConfig.images.disableStaticImages, hasAppDir: !!appDir, hasPagesDir: !!pagesDir, @@ -73,7 +74,9 @@ const nextTypegen = async ( console.log('Generating route types...') - const routeTypesFilePath = join(distDir, 'types', 'routes.d.ts') + // Actual type files go to route-types.d.ts (not routes.d.ts) + // routes.d.ts is reserved for the entry file + const routeTypesFilePath = join(distDir, 'types', 'route-types.d.ts') const validatorFilePath = join(distDir, 'types', 'validator.ts') await mkdir(join(distDir, 'types'), { recursive: true }) @@ -183,6 +186,20 @@ const nextTypegen = async ( const cacheLifeFilePath = join(distDir, 'types', 'cache-life.d.ts') writeCacheLifeTypes(nextConfig.cacheLife, cacheLifeFilePath) + // Write the entry file at {distDirRoot}/types/routes.d.ts + // This ensures next-env.d.ts has a consistent import path + const entryFilePath = join( + baseDir, + nextConfig.distDirRoot, + 'types', + 'routes.d.ts' + ) + const actualTypesDir = join(distDir, 'types') + await writeRouteTypesEntryFile(entryFilePath, actualTypesDir, { + strictRouteTypes, + typedRoutes: Boolean(nextConfig.typedRoutes), + }) + console.log('✓ Types generated successfully') } diff --git a/packages/next/src/client/components/app-router.tsx b/packages/next/src/client/components/app-router.tsx index 137a76ca81d8..2dc635cda5f0 100644 --- a/packages/next/src/client/components/app-router.tsx +++ b/packages/next/src/client/components/app-router.tsx @@ -40,7 +40,7 @@ import { type GlobalErrorState, } from './app-router-instance' import { getRedirectTypeFromError, getURLFromRedirectError } from './redirect' -import { isRedirectError, RedirectType } from './redirect-error' +import { isRedirectError } from './redirect-error' import { pingVisibleLinks } from './links' import RootErrorBoundary from './errors/root-error-boundary' import DefaultGlobalError from './builtin/global-error' @@ -236,7 +236,7 @@ function Router({ const redirectType = getRedirectTypeFromError(error) // TODO: This should access the router methods directly, rather than // go through the public interface. - if (redirectType === RedirectType.push) { + if (redirectType === 'push') { publicAppRouterInstance.push(url, {}) } else { publicAppRouterInstance.replace(url, {}) diff --git a/packages/next/src/client/components/bfcache.ts b/packages/next/src/client/components/bfcache-state-manager.ts similarity index 94% rename from packages/next/src/client/components/bfcache.ts rename to packages/next/src/client/components/bfcache-state-manager.ts index 97acb4e0ada6..f2198d07e96c 100644 --- a/packages/next/src/client/components/bfcache.ts +++ b/packages/next/src/client/components/bfcache-state-manager.ts @@ -1,4 +1,7 @@ -import type { FlightRouterState } from '../../shared/lib/app-router-types' +import type { + CacheNode, + FlightRouterState, +} from '../../shared/lib/app-router-types' import { useState } from 'react' // When the flag is disabled, only track the currently active tree @@ -6,6 +9,7 @@ const MAX_BF_CACHE_ENTRIES = process.env.__NEXT_CACHE_COMPONENTS ? 3 : 1 export type RouterBFCacheEntry = { tree: FlightRouterState + cacheNode: CacheNode stateKey: string // The entries form a linked list, sorted in order of most recently active. next: RouterBFCacheEntry | null @@ -33,6 +37,7 @@ export type RouterBFCacheEntry = { */ export function useRouterBFCache( activeTree: FlightRouterState, + activeCacheNode: CacheNode, activeStateKey: string ): RouterBFCacheEntry { // The currently active entry. The entries form a linked list, sorted in @@ -48,6 +53,7 @@ export function useRouterBFCache( () => { const initialEntry: RouterBFCacheEntry = { tree: activeTree, + cacheNode: activeCacheNode, stateKey: activeStateKey, next: null, } @@ -72,6 +78,7 @@ export function useRouterBFCache( // linked list. const newActiveEntry: RouterBFCacheEntry = { tree: activeTree, + cacheNode: activeCacheNode, stateKey: activeStateKey, next: null, } @@ -98,6 +105,7 @@ export function useRouterBFCache( n++ const entry: RouterBFCacheEntry = { tree: oldEntry.tree, + cacheNode: oldEntry.cacheNode, stateKey: oldEntry.stateKey, next: null, } diff --git a/packages/next/src/client/components/layout-router.tsx b/packages/next/src/client/components/layout-router.tsx index af075d71b936..f88fd59d67e8 100644 --- a/packages/next/src/client/components/layout-router.tsx +++ b/packages/next/src/client/components/layout-router.tsx @@ -32,7 +32,10 @@ import { disableSmoothScrollDuringRouteTransition } from '../../shared/lib/route import { RedirectBoundary } from './redirect-boundary' import { HTTPAccessFallbackBoundary } from './http-access-fallback/error-boundary' import { createRouterCacheKey } from './router-reducer/create-router-cache-key' -import { useRouterBFCache, type RouterBFCacheEntry } from './bfcache' +import { + useRouterBFCache, + type RouterBFCacheEntry, +} from './bfcache-state-manager' import { normalizeAppPath } from '../../shared/lib/router/utils/app-paths' import { NavigationPromisesContext, @@ -529,14 +532,6 @@ export default function OuterLayoutRouter({ // Get the CacheNode for this segment by reading it from the parent segment's // child map. - const parentParallelRoutes = parentCacheNode.parallelRoutes - let segmentMap = parentParallelRoutes.get(parallelRouterKey) - // If the parallel router cache node does not exist yet, create it. - // This writes to the cache when there is no item in the cache yet. It never *overwrites* existing cache items which is why it's safe in concurrent mode. - if (!segmentMap) { - segmentMap = new Map() - parentParallelRoutes.set(parallelRouterKey, segmentMap) - } const parentTreeSegment = parentTree[0] const segmentPath = parentSegmentPath === null @@ -557,7 +552,8 @@ export default function OuterLayoutRouter({ // (This only applies to page segments; layout segments cannot access search // params on the server.) const activeTree = parentTree[1][parallelRouterKey] - if (activeTree === undefined) { + const maybeParentSlots = parentCacheNode.slots + if (activeTree === undefined || maybeParentSlots === null) { // Could not find a matching segment. The client tree is inconsistent with // the server tree. Suspend indefinitely; the router will have already // detected the inconsistency when handling the server response, and @@ -566,6 +562,7 @@ export default function OuterLayoutRouter({ } const activeSegment = activeTree[0] + const activeCacheNode = maybeParentSlots![parallelRouterKey] ?? null const activeStateKey = createRouterCacheKey(activeSegment, true) // no search params // At each level of the route tree, not only do we render the currently @@ -576,17 +573,15 @@ export default function OuterLayoutRouter({ // bfcacheEntry is a linked list of FlightRouterStates. let bfcacheEntry: RouterBFCacheEntry | null = useRouterBFCache( activeTree, + activeCacheNode, activeStateKey ) let children: Array = [] do { const tree = bfcacheEntry.tree + const cacheNode = bfcacheEntry.cacheNode const stateKey = bfcacheEntry.stateKey const segment = tree[0] - const cacheKey = createRouterCacheKey(segment) - - // Read segment path from the parallel router cache node. - const cacheNode = segmentMap.get(cacheKey) ?? null /* - Error boundary diff --git a/packages/next/src/client/components/navigation.react-server.ts b/packages/next/src/client/components/navigation.react-server.ts index bb6aacd01388..73acad861673 100644 --- a/packages/next/src/client/components/navigation.react-server.ts +++ b/packages/next/src/client/components/navigation.react-server.ts @@ -7,9 +7,13 @@ export function unstable_isUnrecognizedActionError(): boolean { } export { redirect, permanentRedirect } from './redirect' -export { RedirectType } from './redirect-error' export { notFound } from './not-found' export { forbidden } from './forbidden' export { unauthorized } from './unauthorized' export { unstable_rethrow } from './unstable-rethrow' export { ReadonlyURLSearchParams } + +export const RedirectType = { + push: 'push', + replace: 'replace', +} as const diff --git a/packages/next/src/client/components/redirect-boundary.tsx b/packages/next/src/client/components/redirect-boundary.tsx index 470acc9ee1ce..32f68f284e2c 100644 --- a/packages/next/src/client/components/redirect-boundary.tsx +++ b/packages/next/src/client/components/redirect-boundary.tsx @@ -3,7 +3,7 @@ import React, { useEffect } from 'react' import type { AppRouterInstance } from '../../shared/lib/app-router-context.shared-runtime' import { useRouter } from './navigation' import { getRedirectTypeFromError, getURLFromRedirectError } from './redirect' -import { RedirectType, isRedirectError } from './redirect-error' +import { type RedirectType, isRedirectError } from './redirect-error' interface RedirectBoundaryProps { router: AppRouterInstance @@ -23,7 +23,7 @@ function HandleRedirect({ useEffect(() => { React.startTransition(() => { - if (redirectType === RedirectType.push) { + if (redirectType === 'push') { router.push(redirect, {}) } else { router.replace(redirect, {}) diff --git a/packages/next/src/client/components/redirect-error.ts b/packages/next/src/client/components/redirect-error.ts index 35589bdaa531..e7c4d83d9d90 100644 --- a/packages/next/src/client/components/redirect-error.ts +++ b/packages/next/src/client/components/redirect-error.ts @@ -2,10 +2,7 @@ import { RedirectStatusCode } from './redirect-status-code' export const REDIRECT_ERROR_CODE = 'NEXT_REDIRECT' -export enum RedirectType { - push = 'push', - replace = 'replace', -} +export type RedirectType = 'push' | 'replace' export type RedirectError = Error & { digest: `${typeof REDIRECT_ERROR_CODE};${RedirectType};${string};${RedirectStatusCode};` diff --git a/packages/next/src/client/components/redirect.ts b/packages/next/src/client/components/redirect.ts index d5db39935f73..8bf2b774e0cd 100644 --- a/packages/next/src/client/components/redirect.ts +++ b/packages/next/src/client/components/redirect.ts @@ -1,6 +1,6 @@ import { RedirectStatusCode } from './redirect-status-code' import { - RedirectType, + type RedirectType, type RedirectError, isRedirectError, REDIRECT_ERROR_CODE, @@ -40,9 +40,7 @@ export function redirect( url: string, type?: RedirectType ): never { - type ??= actionAsyncStorage?.getStore()?.isAction - ? RedirectType.push - : RedirectType.replace + type ??= actionAsyncStorage?.getStore()?.isAction ? 'push' : 'replace' throw getRedirectError(url, type, RedirectStatusCode.TemporaryRedirect) } @@ -61,7 +59,7 @@ export function redirect( export function permanentRedirect( /** The URL to redirect to */ url: string, - type: RedirectType = RedirectType.replace + type: RedirectType = 'replace' ): never { throw getRedirectError(url, type, RedirectStatusCode.PermanentRedirect) } diff --git a/packages/next/src/client/components/router-reducer/handle-mutable.ts b/packages/next/src/client/components/router-reducer/handle-mutable.ts deleted file mode 100644 index b47f7b7a13ac..000000000000 --- a/packages/next/src/client/components/router-reducer/handle-mutable.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { computeChangedPath } from './compute-changed-path' -import type { - Mutable, - ReadonlyReducerState, - ReducerState, -} from './router-reducer-types' - -function isNotUndefined(value: T): value is Exclude { - return typeof value !== 'undefined' -} - -export function handleMutable( - state: ReadonlyReducerState, - mutable: Mutable -): ReducerState { - // shouldScroll is true by default, can override to false. - const shouldScroll = mutable.shouldScroll ?? true - - let previousNextUrl = state.previousNextUrl - let nextUrl = state.nextUrl - - if (isNotUndefined(mutable.patchedTree)) { - // If we received a patched tree, we need to compute the changed path. - const changedPath = computeChangedPath(state.tree, mutable.patchedTree) - if (changedPath) { - // If the tree changed, we need to update the nextUrl - previousNextUrl = nextUrl - nextUrl = changedPath - } else if (!nextUrl) { - // if the tree ends up being the same (ie, no changed path), and we don't have a nextUrl, then we should use the canonicalUrl - nextUrl = state.canonicalUrl - } - // otherwise this will be a no-op and continue to use the existing nextUrl - } - - return { - // Set href. - canonicalUrl: mutable.canonicalUrl ?? state.canonicalUrl, - renderedSearch: mutable.renderedSearch ?? state.renderedSearch, - pushRef: { - pendingPush: isNotUndefined(mutable.pendingPush) - ? mutable.pendingPush - : state.pushRef.pendingPush, - mpaNavigation: isNotUndefined(mutable.mpaNavigation) - ? mutable.mpaNavigation - : state.pushRef.mpaNavigation, - preserveCustomHistoryState: isNotUndefined( - mutable.preserveCustomHistoryState - ) - ? mutable.preserveCustomHistoryState - : state.pushRef.preserveCustomHistoryState, - }, - // All navigation requires scroll and focus management to trigger. - focusAndScrollRef: { - apply: shouldScroll - ? isNotUndefined(mutable?.scrollableSegments) - ? true - : state.focusAndScrollRef.apply - : // If shouldScroll is false then we should not apply scroll and focus management. - false, - onlyHashChange: mutable.onlyHashChange || false, - hashFragment: shouldScroll - ? // Empty hash should trigger default behavior of scrolling layout into view. - // #top is handled in layout-router. - mutable.hashFragment && mutable.hashFragment !== '' - ? // Remove leading # and decode hash to make non-latin hashes work. - decodeURIComponent(mutable.hashFragment.slice(1)) - : state.focusAndScrollRef.hashFragment - : // If shouldScroll is false then we should not apply scroll and focus management. - null, - segmentPaths: shouldScroll - ? (mutable?.scrollableSegments ?? state.focusAndScrollRef.segmentPaths) - : // If shouldScroll is false then we should not apply scroll and focus management. - [], - }, - // Apply cache. - cache: mutable.cache ? mutable.cache : state.cache, - // Apply patched router state. - tree: isNotUndefined(mutable.patchedTree) - ? mutable.patchedTree - : state.tree, - nextUrl, - previousNextUrl: previousNextUrl, - debugInfo: mutable.collectedDebugInfo ?? null, - } -} diff --git a/packages/next/src/client/components/router-reducer/ppr-navigations.ts b/packages/next/src/client/components/router-reducer/ppr-navigations.ts index 519c184af2bf..b436c4740a49 100644 --- a/packages/next/src/client/components/router-reducer/ppr-navigations.ts +++ b/packages/next/src/client/components/router-reducer/ppr-navigations.ts @@ -4,10 +4,7 @@ import type { FlightSegmentPath, Segment, } from '../../../shared/lib/app-router-types' -import type { - ChildSegmentMap, - CacheNode, -} from '../../../shared/lib/app-router-types' +import type { CacheNode } from '../../../shared/lib/app-router-types' import type { HeadData } from '../../../shared/lib/app-router-types' import { PAGE_SEGMENT_KEY, @@ -16,7 +13,6 @@ import { } from '../../../shared/lib/segment' import { matchSegment } from '../match-segments' import { createHrefFromUrl } from './create-href-from-url' -import { createRouterCacheKey } from './create-router-cache-key' import { fetchServerResponse } from './fetch-server-response' import { dispatchAppRouterAction } from '../use-action-queue' import { @@ -24,7 +20,6 @@ import { type ServerPatchAction, } from './router-reducer-types' import { isNavigatingToNewRootLayout } from './is-navigating-to-new-root-layout' -import { DYNAMIC_STALETIME_MS } from './reducers/navigate-reducer' import { convertServerPatchToFullTree, type NavigationSeed, @@ -42,6 +37,11 @@ import { getRenderedSearchFromVaryPath, type PageVaryPath, } from '../segment-cache/vary-path' +import { + readFromBFCache, + readFromBFCacheDuringRegularNavigation, + writeToBFCache, +} from '../segment-cache/bfcache' // This is yet another tree type that is used to track pending promises that // need to be fulfilled once the dynamic data is received. The terminal nodes of @@ -125,7 +125,6 @@ export function createInitialCacheNodeForHydration( navigatedAt, initialTree, null, - undefined, FreshnessPolicy.Hydration, seedData, seedHead, @@ -281,7 +280,6 @@ function updateCacheNodeOnNavigation( navigatedAt, newRouteTree, newMetadataVaryPath, - oldCacheNode, freshness, seedData, seedHead, @@ -312,21 +310,6 @@ function updateCacheNodeOnNavigation( // trigger an MPA navigation. const childDidFindRootLayout = didFindRootLayout || newRouteTree.isRootLayout - const oldParallelRoutes = - oldCacheNode !== undefined ? oldCacheNode.parallelRoutes : undefined - - // Clone the current set of segment children, even if they aren't active in - // the new tree. - // TODO: We currently retain all the inactive segments indefinitely, until - // there's an explicit refresh, or a parent layout is lazily refreshed. We - // rely on this for popstate navigations, which update the Router State Tree - // but do not eagerly perform a data fetch, because they expect the segment - // data to already be in the Cache Node tree. For highly static sites that - // are mostly read-only, this may happen only rarely, causing memory to - // leak. We should figure out a better model for the lifetime of inactive - // segments, so we can maintain instant back/forward navigations without - // leaking memory indefinitely. - let shouldDropSiblingCaches: boolean = false let shouldRefreshDynamicData: boolean = false switch (freshness) { case FreshnessPolicy.Default: @@ -334,21 +317,16 @@ function updateCacheNodeOnNavigation( case FreshnessPolicy.Hydration: // <- shouldn't happen during client nav // We should never drop dynamic data in shared layouts, except during // a refresh. - shouldDropSiblingCaches = false shouldRefreshDynamicData = false break case FreshnessPolicy.RefreshAll: case FreshnessPolicy.HMRRefresh: - shouldDropSiblingCaches = true shouldRefreshDynamicData = true break default: freshness satisfies never break } - const newParallelRoutes = new Map( - shouldDropSiblingCaches ? undefined : oldParallelRoutes - ) // TODO: We're not consistent about how we do this check. Some places // check if the segment starts with PAGE_SEGMENT_KEY, but most seem to @@ -371,13 +349,11 @@ function updateCacheNodeOnNavigation( ) { // Reuse the existing CacheNode const dropPrefetchRsc = false - newCacheNode = reuseDynamicCacheNode( - dropPrefetchRsc, - oldCacheNode, - newParallelRoutes - ) + newCacheNode = reuseSharedCacheNode(dropPrefetchRsc, oldCacheNode) needsDynamicRequest = false } else { + // If this is part of a refresh, ignore the existing CacheNode and create a + // new one. const seedRsc = seedData !== null ? seedData[0] : null const result = createCacheNodeForSegment( navigatedAt, @@ -385,7 +361,6 @@ function updateCacheNodeOnNavigation( seedRsc, newMetadataVaryPath, seedHead, - newParallelRoutes, freshness ) newCacheNode = result.cacheNode @@ -444,7 +419,13 @@ function updateCacheNodeOnNavigation( [parallelRouteKey: string]: FlightRouterState } = {} + let newCacheNodeSlots: Record | null = null if (newSlots !== null) { + const oldCacheNodeSlots = + oldCacheNode !== undefined ? oldCacheNode.slots : null + + newCacheNode.slots = newCacheNodeSlots = {} + taskChildren = new Map() for (let parallelRouteKey in newSlots) { let newRouteTreeChild: RouteTree = newSlots[parallelRouteKey] const oldRouterStateChild: FlightRouterState | void = @@ -454,10 +435,6 @@ function updateCacheNodeOnNavigation( // server response. Trigger a full-page navigation. return null } - const oldSegmentMapChild = - oldParallelRoutes !== undefined - ? oldParallelRoutes.get(parallelRouteKey) - : undefined let seedDataChild: CacheNodeSeedData | void | null = seedDataChildren !== null ? seedDataChildren[parallelRouteKey] : null @@ -489,10 +466,9 @@ function updateCacheNodeOnNavigation( seedHeadChild = null } - const newSegmentKeyChild = createRouterCacheKey(newSegmentChild) const oldCacheNodeChild = - oldSegmentMapChild !== undefined - ? oldSegmentMapChild.get(newSegmentKeyChild) + oldCacheNodeSlots !== null + ? oldCacheNodeSlots[parallelRouteKey] : undefined const taskChild = updateCacheNodeOnNavigation( @@ -523,18 +499,8 @@ function updateCacheNodeOnNavigation( } // Recursively propagate up the child tasks. - if (taskChildren === null) { - taskChildren = new Map() - } taskChildren.set(parallelRouteKey, taskChild) - const newCacheNodeChild = taskChild.node - if (newCacheNodeChild !== null) { - const newSegmentMapChild: ChildSegmentMap = new Map( - shouldDropSiblingCaches ? undefined : oldSegmentMapChild - ) - newSegmentMapChild.set(newSegmentKeyChild, newCacheNodeChild) - newParallelRoutes.set(parallelRouteKey, newSegmentMapChild) - } + newCacheNodeSlots[parallelRouteKey] = taskChild.node // The child tree's route state may be different from the prefetched // route sent by the server. We need to clone it as we traverse back up @@ -585,7 +551,6 @@ function createCacheNodeOnNavigation( navigatedAt: number, newRouteTree: RouteTree, newMetadataVaryPath: PageVaryPath | null, - oldCacheNode: CacheNode | void, freshness: FreshnessPolicy, seedData: CacheNodeSeedData | null, seedHead: HeadData | null, @@ -613,77 +578,7 @@ function createCacheNodeOnNavigation( const newSlots = newRouteTree.slots const seedDataChildren = seedData !== null ? seedData[1] : null - const oldParallelRoutes = - oldCacheNode !== undefined ? oldCacheNode.parallelRoutes : undefined - - let shouldDropSiblingCaches: boolean = false - let shouldRefreshDynamicData: boolean = false - let dropPrefetchRsc: boolean = false - switch (freshness) { - case FreshnessPolicy.Default: - // We should never drop dynamic data in sibling caches except during - // a refresh. - shouldDropSiblingCaches = false - - // Only reuse the dynamic data if experimental.staleTimes.dynamic config - // is set, and the data is not stale. (This is not a recommended API with - // Cache Components, but it's supported for backwards compatibility. Use - // cacheLife instead.) - // - // DYNAMIC_STALETIME_MS defaults to 0, but it can be increased. - shouldRefreshDynamicData = - oldCacheNode === undefined || - navigatedAt - oldCacheNode.navigatedAt >= DYNAMIC_STALETIME_MS - - dropPrefetchRsc = false - break - case FreshnessPolicy.Hydration: - // During hydration, we assume the data sent by the server is both - // consistent and complete. - shouldRefreshDynamicData = false - shouldDropSiblingCaches = false - dropPrefetchRsc = false - break - case FreshnessPolicy.HistoryTraversal: - // During back/forward navigations, we reuse the dynamic data regardless - // of how stale it may be. - shouldRefreshDynamicData = false - shouldRefreshDynamicData = false - - // Only show prefetched data if the dynamic data is still pending. This - // avoids a flash back to the prefetch state in a case where it's highly - // likely to have already streamed in. - // - // Tehnically, what we're actually checking is whether the dynamic network - // response was received. But since it's a streaming response, this does - // not mean that all the dynamic data has fully streamed in. It just means - // that _some_ of the dynamic data was received. But as a heuristic, we - // assume that the rest dynamic data will stream in quickly, so it's still - // better to skip the prefetch state. - if (oldCacheNode !== undefined) { - const oldRsc = oldCacheNode.rsc - const oldRscDidResolve = - !isDeferredRsc(oldRsc) || oldRsc.status !== 'pending' - dropPrefetchRsc = oldRscDidResolve - } else { - dropPrefetchRsc = false - } - break - case FreshnessPolicy.RefreshAll: - case FreshnessPolicy.HMRRefresh: - // Drop all dynamic data. - shouldRefreshDynamicData = true - shouldDropSiblingCaches = true - dropPrefetchRsc = false - break - default: - freshness satisfies never - break - } - const newParallelRoutes = new Map( - shouldDropSiblingCaches ? undefined : oldParallelRoutes - ) const isLeafSegment = newSlots === null if (isLeafSegment) { @@ -702,30 +597,17 @@ function createCacheNodeOnNavigation( accumulation.scrollableSegments.push(segmentPath) } - let newCacheNode: CacheNode - let needsDynamicRequest: boolean - if (!shouldRefreshDynamicData && oldCacheNode !== undefined) { - // Reuse the existing CacheNode - newCacheNode = reuseDynamicCacheNode( - dropPrefetchRsc, - oldCacheNode, - newParallelRoutes - ) - needsDynamicRequest = false - } else { - const seedRsc = seedData !== null ? seedData[0] : null - const result = createCacheNodeForSegment( - navigatedAt, - newRouteTree, - seedRsc, - newMetadataVaryPath, - seedHead, - newParallelRoutes, - freshness - ) - newCacheNode = result.cacheNode - needsDynamicRequest = result.needsDynamicRequest - } + const seedRsc = seedData !== null ? seedData[0] : null + const result = createCacheNodeForSegment( + navigatedAt, + newRouteTree, + seedRsc, + newMetadataVaryPath, + seedHead, + freshness + ) + const newCacheNode = result.cacheNode + const needsDynamicRequest = result.needsDynamicRequest let patchedRouterStateChildren: { [parallelRouteKey: string]: FlightRouterState @@ -737,29 +619,19 @@ function createCacheNodeOnNavigation( [parallelRouteKey: string]: FlightRouterState } = {} + let newCacheNodeSlots: Record | null = null if (newSlots !== null) { + newCacheNode.slots = newCacheNodeSlots = {} + taskChildren = new Map() for (let parallelRouteKey in newSlots) { const newRouteTreeChild: RouteTree = newSlots[parallelRouteKey] - const oldSegmentMapChild = - oldParallelRoutes !== undefined - ? oldParallelRoutes.get(parallelRouteKey) - : undefined const seedDataChild: CacheNodeSeedData | void | null = seedDataChildren !== null ? seedDataChildren[parallelRouteKey] : null - const newSegmentChild = createSegmentFromRouteTree(newRouteTreeChild) - const newSegmentKeyChild = createRouterCacheKey(newSegmentChild) - - const oldCacheNodeChild = - oldSegmentMapChild !== undefined - ? oldSegmentMapChild.get(newSegmentKeyChild) - : undefined - const taskChild = createCacheNodeOnNavigation( navigatedAt, newRouteTreeChild, newMetadataVaryPath, - oldCacheNodeChild, freshness, seedDataChild ?? null, seedHead, @@ -769,18 +641,8 @@ function createCacheNodeOnNavigation( accumulation ) - if (taskChildren === null) { - taskChildren = new Map() - } taskChildren.set(parallelRouteKey, taskChild) - const newCacheNodeChild = taskChild.node - if (newCacheNodeChild !== null) { - const newSegmentMapChild: ChildSegmentMap = new Map( - shouldDropSiblingCaches ? undefined : oldSegmentMapChild - ) - newSegmentMapChild.set(newSegmentKeyChild, newCacheNodeChild) - newParallelRoutes.set(parallelRouteKey, newSegmentMapChild) - } + newCacheNodeSlots[parallelRouteKey] = taskChild.node const taskChildRoute = taskChild.route patchedRouterStateChildren[parallelRouteKey] = taskChildRoute @@ -974,19 +836,16 @@ function reuseActiveSegmentInDefaultSlot( return reusedRouteTree } -function reuseDynamicCacheNode( +function reuseSharedCacheNode( dropPrefetchRsc: boolean, - existingCacheNode: CacheNode, - parallelRoutes: Map + existingCacheNode: CacheNode ): CacheNode { - // Clone an existing CacheNode's data, with (possibly) new children. + // Clone the CacheNode that was already present in the previous tree return createCacheNode( existingCacheNode.rsc, dropPrefetchRsc ? null : existingCacheNode.prefetchRsc, existingCacheNode.head, - dropPrefetchRsc ? null : existingCacheNode.prefetchHead, - parallelRoutes, - existingCacheNode.navigatedAt + dropPrefetchRsc ? null : existingCacheNode.prefetchHead ) } @@ -996,10 +855,10 @@ function createCacheNodeForSegment( seedRsc: React.ReactNode | null, metadataVaryPath: PageVaryPath | null, seedHead: HeadData | null, - newParallelRoutes: Map, freshness: FreshnessPolicy ): { cacheNode: CacheNode; needsDynamicRequest: boolean } { - // Construct a new CacheNode using data from the Segment Cache. + // Construct a new CacheNode using data from the BFCache, the client's + // Segment Cache, or seeded from a server response. // // If there's a cache miss, or if we only have a partial hit, we'll render // the partial state immediately, and spawn a request to the server to fill @@ -1014,32 +873,92 @@ function createCacheNodeForSegment( // referred to as the "seed" data.) const isPage = tree.isPage - if (freshness === FreshnessPolicy.Hydration) { - // We should never spawn network requests during hydration. We must treat - // the initial payload as authoritative, because the initial page load is - // used as a last-ditch mechanism for recovering the app. - // - // This is also an important safety check because if this leaks into the - // server rendering path (which theoretically it never should because the - // server payload should be consistent), the server would hang because these - // promises would never resolve. - // - // TODO: There is an existing case where the global "not found" boundary - // triggers this path. But it does render correctly despite that. That's an - // unusual render path so it's not surprising, but we should look into - // modeling it in a more consistent way. See also the /_notFound special - // case in updateCacheNodeOnNavigation. - return { - cacheNode: createCacheNode( - seedRsc, - null, - isPage ? seedHead : null, - null, - newParallelRoutes, - now - ), - needsDynamicRequest: false, + + // During certain kinds of navigations, we may be able to render from + // the BFCache. + switch (freshness) { + case FreshnessPolicy.Default: { + // When experimental.staleTimes.dynamic config is set, we read from the + // BFCache even during regular navigations. + const bfcacheEntry = readFromBFCacheDuringRegularNavigation( + now, + tree.varyPath + ) + if (bfcacheEntry !== null) { + return { + cacheNode: createCacheNode( + bfcacheEntry.rsc, + bfcacheEntry.prefetchRsc, + bfcacheEntry.head, + bfcacheEntry.prefetchHead + ), + needsDynamicRequest: false, + } + } + break } + case FreshnessPolicy.Hydration: { + // This is not related to the BFCache but it is a special case. + // + // We should never spawn network requests during hydration. We must treat + // the initial payload as authoritative, because the initial page load is + // used as a last-ditch mechanism for recovering the app. + // + // This is also an important safety check because if this leaks into the + // server rendering path (which theoretically it never should because the + // server payload should be consistent), the server would hang because these + // promises would never resolve. + // + // TODO: There is an existing case where the global "not found" boundary + // triggers this path. But it does render correctly despite that. That's an + // unusual render path so it's not surprising, but we should look into + // modeling it in a more consistent way. See also the /_notFound special + // case in updateCacheNodeOnNavigation. + const rsc = seedRsc + const prefetchRsc = null + const head = isPage ? seedHead : null + const prefetchHead = null + writeToBFCache(now, tree.varyPath, rsc, prefetchRsc, head, prefetchHead) + return { + cacheNode: createCacheNode(rsc, prefetchRsc, head, prefetchHead), + needsDynamicRequest: false, + } + } + case FreshnessPolicy.HistoryTraversal: + const bfcacheEntry = readFromBFCache(tree.varyPath) + if (bfcacheEntry !== null) { + // Only show prefetched data if the dynamic data is still pending. This + // avoids a flash back to the prefetch state in a case where it's highly + // likely to have already streamed in. + // + // Tehnically, what we're actually checking is whether the dynamic + // network response was received. But since it's a streaming response, + // this does not mean that all the dynamic data has fully streamed in. + // It just means that _some_ of the dynamic data was received. But as a + // heuristic, we assume that the rest dynamic data will stream in + // quickly, so it's still better to skip the prefetch state. + const oldRsc = bfcacheEntry.rsc + const oldRscDidResolve = + !isDeferredRsc(oldRsc) || oldRsc.status !== 'pending' + const dropPrefetchRsc = oldRscDidResolve + return { + cacheNode: createCacheNode( + bfcacheEntry.rsc, + dropPrefetchRsc ? null : bfcacheEntry.prefetchRsc, + bfcacheEntry.head, + dropPrefetchRsc ? null : bfcacheEntry.prefetchHead + ), + needsDynamicRequest: false, + } + } + break + case FreshnessPolicy.RefreshAll: + case FreshnessPolicy.HMRRefresh: + // Don't consult the BFCache. + break + default: + freshness satisfies never + break } let cachedRsc: React.ReactNode | null = null @@ -1196,15 +1115,13 @@ function createCacheNodeForSegment( } } + // Now that we're creating a new segment, write its data to the BFCache. A + // subsequent back/forward navigation will reuse this same data, until or + // unless it's cleared by a refresh/revalidation. + writeToBFCache(now, tree.varyPath, rsc, prefetchRsc, head, prefetchHead) + return { - cacheNode: createCacheNode( - rsc, - prefetchRsc, - head, - prefetchHead, - newParallelRoutes, - now - ), + cacheNode: createCacheNode(rsc, prefetchRsc, head, prefetchHead), // TODO: We should store this field on the CacheNode itself. I think we can // probably unify NavigationTask, CacheNode, and DeferredRsc into a // single type. Or at least CacheNode and DeferredRsc. @@ -1217,17 +1134,14 @@ function createCacheNode( rsc: React.ReactNode | null, prefetchRsc: React.ReactNode | null, head: React.ReactNode | null, - prefetchHead: HeadData | null, - parallelRoutes: Map, - navigatedAt: number + prefetchHead: HeadData | null ): CacheNode { return { rsc, prefetchRsc, head, prefetchHead, - parallelRoutes, - navigatedAt, + slots: null, } } diff --git a/packages/next/src/client/components/router-reducer/reducers/find-head-in-cache.test.tsx b/packages/next/src/client/components/router-reducer/reducers/find-head-in-cache.test.tsx deleted file mode 100644 index 760f364ebf13..000000000000 --- a/packages/next/src/client/components/router-reducer/reducers/find-head-in-cache.test.tsx +++ /dev/null @@ -1,107 +0,0 @@ -import type { - FlightRouterState, - CacheNode, -} from '../../../../shared/lib/app-router-types' -import { findHeadInCache } from './find-head-in-cache' - -const navigatedAt = -1 - -describe('findHeadInCache', () => { - it('should find the head', () => { - const routerTree: FlightRouterState = [ - '', - { - children: [ - 'linking', - { - children: [ - 'about', - { - children: ['', {}], - }, - ], - }, - ], - }, - undefined, - undefined, - true, - ] - - const cache: CacheNode = { - navigatedAt, - rsc: null, - prefetchRsc: null, - head: null, - prefetchHead: null, - parallelRoutes: new Map([ - [ - 'children', - new Map([ - [ - 'linking', - { - navigatedAt, - rsc: null, - prefetchRsc: null, - head: null, - prefetchHead: null, - parallelRoutes: new Map([ - [ - 'children', - new Map([ - [ - 'about', - { - navigatedAt, - head: null, - prefetchHead: null, - parallelRoutes: new Map([ - [ - 'children', - new Map([ - [ - '', - { - navigatedAt, - rsc: null, - prefetchRsc: null, - prefetchHead: null, - parallelRoutes: new Map(), - head: null, - }, - ], - ]), - ], - ]), - rsc: null, - prefetchRsc: null, - }, - ], - // TODO-APP: this segment should be preserved when creating the new cache - // [ - // '', - // { - // rsc: <>Page, - // prefetchRsc: null, - // parallelRoutes: new Map(), - // }, - // ], - ]), - ], - ]), - }, - ], - ]), - ], - ]), - } - - const result = findHeadInCache(cache, routerTree[1]) - expect(result).not.toBeNull() - - const [cacheNode, key] = result! - expect(cacheNode.head).toBe(null) - expect(key).toBe('/linking/about/') - }) -}) diff --git a/packages/next/src/client/components/router-reducer/reducers/find-head-in-cache.ts b/packages/next/src/client/components/router-reducer/reducers/find-head-in-cache.ts index 415b35628a13..296aea9fbb5a 100644 --- a/packages/next/src/client/components/router-reducer/reducers/find-head-in-cache.ts +++ b/packages/next/src/client/components/router-reducer/reducers/find-head-in-cache.ts @@ -35,35 +35,34 @@ function findHeadInCacheImpl( parallelRoutesKeys.unshift('children') } - for (const key of parallelRoutesKeys) { - const [segment, childParallelRoutes] = parallelRoutes[key] - // If the parallel is not matched and using the default segment, - // skip searching the head from it. - if (segment === DEFAULT_SEGMENT_KEY) { - continue - } - const childSegmentMap = cache.parallelRoutes.get(key) - if (!childSegmentMap) { - continue - } + const slots = cache.slots + if (slots !== null) { + for (const key of parallelRoutesKeys) { + const [segment, childParallelRoutes] = parallelRoutes[key] + // If the parallel is not matched and using the default segment, + // skip searching the head from it. + if (segment === DEFAULT_SEGMENT_KEY) { + continue + } - const cacheKey = createRouterCacheKey(segment) - const cacheKeyWithoutSearchParams = createRouterCacheKey(segment, true) + const childCacheNode = slots[key] + if (!childCacheNode) { + continue + } - const cacheNode = childSegmentMap.get(cacheKey) - if (!cacheNode) { - continue - } + const cacheKey = createRouterCacheKey(segment) + const cacheKeyWithoutSearchParams = createRouterCacheKey(segment, true) - const item = findHeadInCacheImpl( - cacheNode, - childParallelRoutes, - keyPrefix + '/' + cacheKey, - keyPrefix + '/' + cacheKeyWithoutSearchParams - ) + const item = findHeadInCacheImpl( + childCacheNode, + childParallelRoutes, + keyPrefix + '/' + cacheKey, + keyPrefix + '/' + cacheKeyWithoutSearchParams + ) - if (item) { - return item + if (item) { + return item + } } } diff --git a/packages/next/src/client/components/router-reducer/reducers/navigate-reducer.ts b/packages/next/src/client/components/router-reducer/reducers/navigate-reducer.ts index 9a2e11f19ee5..eb4184248fa2 100644 --- a/packages/next/src/client/components/router-reducer/reducers/navigate-reducer.ts +++ b/packages/next/src/client/components/router-reducer/reducers/navigate-reducer.ts @@ -1,24 +1,15 @@ import type { - FlightRouterState, - FlightSegmentPath, -} from '../../../../shared/lib/app-router-types' -import { createHrefFromUrl } from '../create-href-from-url' -import type { - Mutable, NavigateAction, ReadonlyReducerState, ReducerState, } from '../router-reducer-types' -import { handleMutable } from '../handle-mutable' import { + completeHardNavigation, navigate as navigateUsingSegmentCache, - type NavigationResult, } from '../../segment-cache/navigation' -import { NavigationResultTag } from '../../segment-cache/types' import { getStaleTimeMs } from '../../segment-cache/cache' import { FreshnessPolicy } from '../ppr-navigations' -import { isJavaScriptURLString } from '../../../lib/javascript-url' // These values are set by `define-env-plugin` (based on `nextConfig.experimental.staleTimes`) // and default to 5 minutes (static) / 0 seconds (dynamic) @@ -29,141 +20,20 @@ export const STATIC_STALETIME_MS = getStaleTimeMs( Number(process.env.__NEXT_CLIENT_ROUTER_STATIC_STALETIME) ) -export function handleExternalUrl( - state: ReadonlyReducerState, - mutable: Mutable, - url: string, - pendingPush: boolean -) { - if (isJavaScriptURLString(url)) { - console.error( - 'Next.js has blocked a javascript: URL as a security precaution.' - ) - return handleMutable(state, mutable) - } - - mutable.mpaNavigation = true - mutable.canonicalUrl = url - mutable.pendingPush = pendingPush - mutable.scrollableSegments = undefined - - return handleMutable(state, mutable) -} - -export function generateSegmentsFromPatch( - flightRouterPatch: FlightRouterState -): FlightSegmentPath[] { - const segments: FlightSegmentPath[] = [] - const [segment, parallelRoutes] = flightRouterPatch - - if (Object.keys(parallelRoutes).length === 0) { - return [[segment]] - } - - for (const [parallelRouteKey, parallelRoute] of Object.entries( - parallelRoutes - )) { - for (const childSegment of generateSegmentsFromPatch(parallelRoute)) { - // If the segment is empty, it means we are at the root of the tree - if (segment === '') { - segments.push([parallelRouteKey, ...childSegment]) - } else { - segments.push([segment, parallelRouteKey, ...childSegment]) - } - } - } - - return segments -} - -export function handleNavigationResult( - url: URL, - state: ReadonlyReducerState, - mutable: Mutable, - pendingPush: boolean, - result: NavigationResult -): ReducerState { - switch (result.tag) { - case NavigationResultTag.MPA: { - // Perform an MPA navigation. - const newUrl = result.data - return handleExternalUrl(state, mutable, newUrl, pendingPush) - } - case NavigationResultTag.Success: { - // Received a new result. - mutable.cache = result.data.cacheNode - mutable.patchedTree = result.data.flightRouterState - mutable.renderedSearch = result.data.renderedSearch - mutable.canonicalUrl = result.data.canonicalUrl - // TODO: During a refresh, we don't set the `scrollableSegments`. There's - // some confusing and subtle logic in `handleMutable` that decides what - // to do when `shouldScroll` is set but `scrollableSegments` is not. I'm - // not convinced it's totally coherent but the tests assert on this - // particular behavior so I've ported the logic as-is from the previous - // router implementation, for now. - mutable.scrollableSegments = result.data.scrollableSegments ?? undefined - mutable.shouldScroll = result.data.shouldScroll - mutable.hashFragment = result.data.hash - - // Check if the only thing that changed was the hash fragment. - const oldUrl = new URL(state.canonicalUrl, url) - const onlyHashChange = - // We don't need to compare the origins, because client-driven - // navigations are always same-origin. - url.pathname === oldUrl.pathname && - url.search === oldUrl.search && - url.hash !== oldUrl.hash - if (onlyHashChange) { - // The only updated part of the URL is the hash. - mutable.onlyHashChange = true - mutable.shouldScroll = result.data.shouldScroll - mutable.hashFragment = url.hash - // Setting this to an empty array triggers a scroll for all new and - // updated segments. See `ScrollAndFocusHandler` for more details. - mutable.scrollableSegments = [] - } - - return handleMutable(state, mutable) - } - case NavigationResultTag.Async: { - return result.data.then( - (asyncResult) => - handleNavigationResult(url, state, mutable, pendingPush, asyncResult), - // If the navigation failed, return the current state. - // TODO: This matches the current behavior but we need to do something - // better here if the network fails. - () => { - return state - } - ) - } - default: { - result satisfies never - return state - } - } -} - export function navigateReducer( state: ReadonlyReducerState, action: NavigateAction ): ReducerState { const { url, isExternalUrl, navigateType, shouldScroll } = action - const mutable: Mutable = {} - const href = createHrefFromUrl(url) - const pendingPush = navigateType === 'push' - - mutable.preserveCustomHistoryState = false - mutable.pendingPush = pendingPush if (isExternalUrl) { - return handleExternalUrl(state, mutable, url.toString(), pendingPush) + return completeHardNavigation(state, url, navigateType) } // Handles case where `` tag is present, // which will trigger an MPA navigation. if (document.getElementById('__next-page-redirect')) { - return handleExternalUrl(state, mutable, href, pendingPush) + return completeHardNavigation(state, url, navigateType) } // Temporary glue code between the router reducer and the new navigation @@ -171,7 +41,8 @@ export function navigateReducer( // state machine. const currentUrl = new URL(state.canonicalUrl, location.origin) const currentRenderedSearch = state.renderedSearch - const result = navigateUsingSegmentCache( + return navigateUsingSegmentCache( + state, url, currentUrl, currentRenderedSearch, @@ -180,7 +51,6 @@ export function navigateReducer( state.nextUrl, FreshnessPolicy.Default, shouldScroll, - mutable + navigateType ) - return handleNavigationResult(url, state, mutable, pendingPush, result) } diff --git a/packages/next/src/client/components/router-reducer/reducers/refresh-reducer.ts b/packages/next/src/client/components/router-reducer/reducers/refresh-reducer.ts index 9b68e015d92a..700513e4ed00 100644 --- a/packages/next/src/client/components/router-reducer/reducers/refresh-reducer.ts +++ b/packages/next/src/client/components/router-reducer/reducers/refresh-reducer.ts @@ -1,9 +1,7 @@ import type { - Mutable, ReadonlyReducerState, ReducerState, } from '../router-reducer-types' -import { handleNavigationResult } from './navigate-reducer' import { convertServerPatchToFullTree, navigateToKnownRoute, @@ -11,6 +9,7 @@ import { import { revalidateEntireCache } from '../../segment-cache/cache' import { hasInterceptionRouteInCurrentTree } from './has-interception-route-in-current-tree' import { FreshnessPolicy } from '../ppr-navigations' +import { invalidateBfCache } from '../../segment-cache/bfcache' export function refreshReducer(state: ReadonlyReducerState): ReducerState { // TODO: Currently, all refreshes purge the prefetch cache. In the future, @@ -26,6 +25,9 @@ export function refreshDynamicData( state: ReadonlyReducerState, freshnessPolicy: FreshnessPolicy.RefreshAll | FreshnessPolicy.HMRRefresh ): ReducerState { + // During a refresh, invalidate the BFCache, which may contain dynamic data. + invalidateBfCache() + const currentNextUrl = state.nextUrl // We always send the last next-url, not the current when performing a dynamic @@ -41,7 +43,7 @@ export function refreshDynamicData( const currentUrl = new URL(currentCanonicalUrl, location.origin) const currentRenderedSearch = state.renderedSearch const currentFlightRouterState = state.tree - const shouldScroll = true + const shouldScroll = false // Create a NavigationSeed from the current FlightRouterState. // TODO: Eventually we will store this type directly on the state object @@ -54,8 +56,10 @@ export function refreshDynamicData( ) const now = Date.now() - const result = navigateToKnownRoute( + const navigateType = 'replace' + return navigateToKnownRoute( now, + state, currentUrl, currentCanonicalUrl, refreshSeed, @@ -65,11 +69,8 @@ export function refreshDynamicData( currentFlightRouterState, freshnessPolicy, nextUrlForRefresh, - shouldScroll + shouldScroll, + navigateType, + null ) - - const mutable: Mutable = {} - mutable.preserveCustomHistoryState = false - - return handleNavigationResult(currentUrl, state, mutable, false, result) } diff --git a/packages/next/src/client/components/router-reducer/reducers/restore-reducer.ts b/packages/next/src/client/components/router-reducer/reducers/restore-reducer.ts index 6aecd319874b..5c20992125ed 100644 --- a/packages/next/src/client/components/router-reducer/reducers/restore-reducer.ts +++ b/packages/next/src/client/components/router-reducer/reducers/restore-reducer.ts @@ -1,4 +1,3 @@ -import { createHrefFromUrl } from '../create-href-from-url' import type { ReadonlyReducerState, ReducerState, @@ -12,9 +11,11 @@ import { type NavigationRequestAccumulation, } from '../ppr-navigations' import type { FlightRouterState } from '../../../../shared/lib/app-router-types' -import { handleExternalUrl } from './navigate-reducer' -import type { Mutable } from '../router-reducer-types' -import { convertServerPatchToFullTree } from '../../segment-cache/navigation' +import { + completeHardNavigation, + completeTraverseNavigation, + convertServerPatchToFullTree, +} from '../../segment-cache/navigation' export function restoreReducer( state: ReadonlyReducerState, @@ -39,7 +40,6 @@ export function restoreReducer( const currentUrl = new URL(state.canonicalUrl, location.origin) const restoredUrl = action.url - const restoredCanonicalUrl = createHrefFromUrl(restoredUrl) const restoredNextUrl = extractPathFromFlightRouterState(treeToRestore) ?? restoredUrl.pathname @@ -69,12 +69,8 @@ export function restoreReducer( ) if (task === null) { - const mutable: Mutable = { - preserveCustomHistoryState: true, - } - return handleExternalUrl(state, mutable, restoredCanonicalUrl, false) + return completeHardNavigation(state, restoredUrl, 'replace') } - spawnDynamicRequests( task, restoredUrl, @@ -82,27 +78,12 @@ export function restoreReducer( FreshnessPolicy.HistoryTraversal, accumulation ) - - return { - // Set canonical url - canonicalUrl: restoredCanonicalUrl, + return completeTraverseNavigation( + state, + restoredUrl, renderedSearch, - pushRef: { - pendingPush: false, - mpaNavigation: false, - // Ensures that the custom history state that was set is preserved when applying this update. - preserveCustomHistoryState: true, - }, - focusAndScrollRef: state.focusAndScrollRef, - cache: task.node, - // Restore provided tree - tree: task.route, - - nextUrl: restoredNextUrl, - // TODO: We need to restore previousNextUrl, too, which represents the - // Next-Url that was used to fetch the data. Anywhere we fetch using the - // canonical URL, there should be a corresponding Next-Url. - previousNextUrl: null, - debugInfo: null, - } + task.node, + task.route, + restoredNextUrl + ) } diff --git a/packages/next/src/client/components/router-reducer/reducers/server-action-reducer.ts b/packages/next/src/client/components/router-reducer/reducers/server-action-reducer.ts index cae187dff361..b2bcc01acd08 100644 --- a/packages/next/src/client/components/router-reducer/reducers/server-action-reducer.ts +++ b/packages/next/src/client/components/router-reducer/reducers/server-action-reducer.ts @@ -28,11 +28,9 @@ import type { ReadonlyReducerState, ReducerState, ServerActionAction, - ServerActionMutable, } from '../router-reducer-types' import { assignLocation } from '../../../assign-location' import { createHrefFromUrl } from '../create-href-from-url' -import { handleExternalUrl, handleNavigationResult } from './navigate-reducer' import { hasInterceptionRouteInCurrentTree } from './has-interception-route-in-current-tree' import { normalizeFlightData, @@ -40,7 +38,7 @@ import { type NormalizedFlightData, } from '../../../flight-data-helpers' import { getRedirectError } from '../../redirect' -import { RedirectType } from '../../redirect-error' +import type { RedirectType } from '../../redirect-error' import { removeBasePath } from '../../../remove-base-path' import { hasBasePath } from '../../../has-base-path' import { @@ -50,9 +48,10 @@ import { import { revalidateEntireCache } from '../../segment-cache/cache' import { getDeploymentId } from '../../../../shared/lib/deployment-id' import { + completeHardNavigation, convertServerPatchToFullTree, navigateToKnownRoute, - navigate as navigateUsingSegmentCache, + navigate, } from '../../segment-cache/navigation' import type { NormalizedSearch } from '../../segment-cache/cache-key' import { @@ -63,6 +62,7 @@ import { } from '../../../../shared/lib/action-revalidation-kind' import { isExternalURL } from '../../app-router-utils' import { FreshnessPolicy } from '../ppr-navigations' +import { invalidateBfCache } from '../../segment-cache/bfcache' const createFromFetch = createFromFetchBrowser as (typeof import('react-server-dom-webpack/client.browser'))['createFromFetch'] @@ -154,10 +154,10 @@ async function fetchServerAction( let redirectType: RedirectType | undefined switch (_redirectType) { case 'push': - redirectType = RedirectType.push + redirectType = 'push' break case 'replace': - redirectType = RedirectType.replace + redirectType = 'replace' break default: redirectType = undefined @@ -254,9 +254,6 @@ export function serverActionReducer( action: ServerActionAction ): ReducerState { const { resolve, reject } = action - const mutable: ServerActionMutable = {} - - mutable.preserveCustomHistoryState = false // only pass along the `nextUrl` param (used for interception routes) if the current route was intercepted. // If the route has been intercepted, the action should be as well. @@ -283,6 +280,11 @@ export function serverActionReducer( redirectType, }) => { if (revalidationKind !== ActionDidNotRevalidate) { + // There was either a revalidation or a refresh, or maybe both. + + // Evict the BFCache, which may contain dynamic data. + invalidateBfCache() + // Store whether this action triggered any revalidation // The action queue will use this information to potentially // trigger a refresh action if the action was discarded @@ -296,9 +298,7 @@ export function serverActionReducer( } } - const pendingPush = redirectType !== RedirectType.replace - state.pushRef.pendingPush = pendingPush - mutable.pendingPush = pendingPush + const navigateType = redirectType || 'push' if (redirectLocation !== undefined) { // If the action triggered a redirect, the action promise will be rejected with @@ -307,17 +307,16 @@ export function serverActionReducer( // the component that called the action as the error boundary will remount the tree. // The status code doesn't matter here as the action handler will have already sent // a response with the correct status code. - const resolvedRedirectType = redirectType || RedirectType.push if (isExternalURL(redirectLocation)) { // External redirect. Triggers an MPA navigation. const redirectHref = redirectLocation.href const redirectError = createRedirectErrorForAction( redirectHref, - resolvedRedirectType + navigateType ) reject(redirectError) - return handleExternalUrl(state, mutable, redirectHref, pendingPush) + return completeHardNavigation(state, redirectLocation, navigateType) } else { // Internal redirect. Triggers an SPA navigation. const redirectWithBasepath = createHrefFromUrl( @@ -329,7 +328,7 @@ export function serverActionReducer( : redirectWithBasepath const redirectError = createRedirectErrorForAction( redirectHref, - resolvedRedirectType + navigateType ) reject(redirectError) } @@ -357,18 +356,17 @@ export function serverActionReducer( // an external redirect. // TODO: We should refactor the action response type to be more explicit // about the various response types. - return handleExternalUrl( - state, - mutable, - redirectLocation.href, - pendingPush - ) + return completeHardNavigation(state, redirectLocation, navigateType) } if (typeof flightData === 'string') { // If the flight data is just a string, something earlier in the // response handling triggered an external redirect. - return handleExternalUrl(state, mutable, flightData, pendingPush) + return completeHardNavigation( + state, + new URL(flightData, location.origin), + navigateType + ) } // The action triggered a navigation — either a redirect, a revalidation, @@ -407,8 +405,9 @@ export function serverActionReducer( flightDataRenderedSearch ) const now = Date.now() - const result = navigateToKnownRoute( + return navigateToKnownRoute( now, + state, redirectUrl, redirectCanonicalUrl, redirectSeed, @@ -418,20 +417,16 @@ export function serverActionReducer( currentFlightRouterState, freshnessPolicy, nextUrl, - shouldScroll - ) - return handleNavigationResult( - redirectUrl, - state, - mutable, - pendingPush, - result + shouldScroll, + navigateType, + null ) } // The server did not send back new data. We'll perform a regular, non- // seeded navigation — effectively the same as or router.push(). - const result = navigateUsingSegmentCache( + return navigate( + state, redirectUrl, currentUrl, currentRenderedSearch, @@ -440,14 +435,7 @@ export function serverActionReducer( nextUrl, freshnessPolicy, shouldScroll, - mutable - ) - return handleNavigationResult( - redirectUrl, - state, - mutable, - pendingPush, - result + navigateType ) }, (e: any) => { diff --git a/packages/next/src/client/components/router-reducer/reducers/server-patch-reducer.ts b/packages/next/src/client/components/router-reducer/reducers/server-patch-reducer.ts index 78d00412c45e..c877d69b8048 100644 --- a/packages/next/src/client/components/router-reducer/reducers/server-patch-reducer.ts +++ b/packages/next/src/client/components/router-reducer/reducers/server-patch-reducer.ts @@ -3,10 +3,11 @@ import type { ServerPatchAction, ReducerState, ReadonlyReducerState, - Mutable, } from '../router-reducer-types' -import { handleExternalUrl, handleNavigationResult } from './navigate-reducer' -import { navigateToKnownRoute } from '../../segment-cache/navigation' +import { + completeHardNavigation, + navigateToKnownRoute, +} from '../../segment-cache/navigation' import { refreshReducer } from './refresh-reducer' import { FreshnessPolicy } from '../ppr-navigations' @@ -14,9 +15,6 @@ export function serverPatchReducer( state: ReadonlyReducerState, action: ServerPatchAction ): ReducerState { - const mutable: Mutable = {} - mutable.preserveCustomHistoryState = false - // A "retry" is a navigation that happens due to a route mismatch. It's // similar to a refresh, because we will omit any existing dynamic data on // the page. But we seed the retry navigation with the exact tree that the @@ -24,10 +22,12 @@ export function serverPatchReducer( const retryMpa = action.mpa const retryUrl = new URL(action.url, location.origin) const retrySeed = action.seed + // A retry should not create a new history entry. + const navigateType = 'replace' if (retryMpa || retrySeed === null) { // If the server did not send back data during the mismatch, fall back to // an MPA navigation. - return handleExternalUrl(state, mutable, retryUrl.href, false) + return completeHardNavigation(state, retryUrl, navigateType) } const currentUrl = new URL(state.canonicalUrl, location.origin) const currentRenderedSearch = state.renderedSearch @@ -41,12 +41,11 @@ export function serverPatchReducer( // using the tree we just received from the server. const retryCanonicalUrl = createHrefFromUrl(retryUrl) const retryNextUrl = action.nextUrl - // A retry should not create a new history entry. - const pendingPush = false const shouldScroll = true const now = Date.now() - const result = navigateToKnownRoute( + return navigateToKnownRoute( now, + state, retryUrl, retryCanonicalUrl, retrySeed, @@ -56,7 +55,8 @@ export function serverPatchReducer( state.tree, FreshnessPolicy.RefreshAll, retryNextUrl, - shouldScroll + shouldScroll, + navigateType, + null ) - return handleNavigationResult(retryUrl, state, mutable, pendingPush, result) } diff --git a/packages/next/src/client/components/router-reducer/router-reducer-types.ts b/packages/next/src/client/components/router-reducer/router-reducer-types.ts index 2d579ca0e1ea..23d262d13de8 100644 --- a/packages/next/src/client/components/router-reducer/router-reducer-types.ts +++ b/packages/next/src/client/components/router-reducer/router-reducer-types.ts @@ -23,25 +23,6 @@ export type RouterChangeByServerResponse = ({ serverResponse: FetchServerResponseResult }) => void -export interface Mutable { - mpaNavigation?: boolean - patchedTree?: FlightRouterState - renderedSearch?: string - canonicalUrl?: string - scrollableSegments?: FlightSegmentPath[] - pendingPush?: boolean - cache?: CacheNode - hashFragment?: string - shouldScroll?: boolean - preserveCustomHistoryState?: boolean - onlyHashChange?: boolean - collectedDebugInfo?: Array -} - -export interface ServerActionMutable extends Mutable { - inFlightServerAction?: Promise | null -} - /** * Refresh triggers a refresh of the full page data. * - fetches the Flight data and fills rsc at the root of the cache. diff --git a/packages/next/src/client/components/segment-cache/bfcache.ts b/packages/next/src/client/components/segment-cache/bfcache.ts new file mode 100644 index 000000000000..36859c3028d4 --- /dev/null +++ b/packages/next/src/client/components/segment-cache/bfcache.ts @@ -0,0 +1,97 @@ +import type { SegmentVaryPath } from './vary-path' +import { + setInCacheMap, + getFromCacheMap, + type UnknownMapEntry, + type CacheMap, + createCacheMap, +} from './cache-map' +import { DYNAMIC_STALETIME_MS } from '../router-reducer/reducers/navigate-reducer' + +export type BFCacheEntry = { + rsc: React.ReactNode | null + prefetchRsc: React.ReactNode | null + head: React.ReactNode | null + prefetchHead: React.ReactNode | null + + ref: UnknownMapEntry | null + size: number + staleAt: number + version: number +} + +const bfcacheMap: CacheMap = createCacheMap() + +let currentBfCacheVersion = 0 + +export function invalidateBfCache(): void { + currentBfCacheVersion++ +} + +export function writeToBFCache( + now: number, + varyPath: SegmentVaryPath, + rsc: React.ReactNode, + prefetchRsc: React.ReactNode, + head: React.ReactNode, + prefetchHead: React.ReactNode +): void { + const entry: BFCacheEntry = { + rsc, + prefetchRsc, + head, + prefetchHead, + + ref: null, + // TODO: This is just a heuristic. Getting the actual size of the segment + // isn't feasible because it's part of a larger streaming response. The + // LRU will still evict it, we just won't have a fully accurate total + // LRU size. However, we'll probably remove the size tracking from the LRU + // entirely and use memory pressure events instead. + size: 100, + + // A back/forward navigation will disregard the stale time. This field is + // only relevant when staleTimes.dynamic is enabled. + staleAt: now + DYNAMIC_STALETIME_MS, + version: currentBfCacheVersion, + } + const isRevalidation = false + setInCacheMap(bfcacheMap, varyPath, entry, isRevalidation) +} + +export function readFromBFCache( + varyPath: SegmentVaryPath +): BFCacheEntry | null { + const isRevalidation = false + return getFromCacheMap( + // During a back/forward navigation, it doesn't matter how stale the data + // might be. Pass -1 instead of the actual current time to bypass + // staleness checks. + -1, + currentBfCacheVersion, + bfcacheMap, + varyPath, + isRevalidation + ) +} + +export function readFromBFCacheDuringRegularNavigation( + now: number, + varyPath: SegmentVaryPath +): BFCacheEntry | null { + if (DYNAMIC_STALETIME_MS <= 0) { + // Only reuse the dynamic data if experimental.staleTimes.dynamic config + // is set, and the data is not stale. (This is not a recommended API with + // Cache Components, but it's supported for backwards compatibility. Use + // cacheLife instead.) + return null + } + const isRevalidation = false + return getFromCacheMap( + now, + currentBfCacheVersion, + bfcacheMap, + varyPath, + isRevalidation + ) +} diff --git a/packages/next/src/client/components/segment-cache/lru.ts b/packages/next/src/client/components/segment-cache/lru.ts index f5f8dc01a437..490e7f7b9c39 100644 --- a/packages/next/src/client/components/segment-cache/lru.ts +++ b/packages/next/src/client/components/segment-cache/lru.ts @@ -83,6 +83,8 @@ export function deleteFromLru(deleted: UnknownMapEntry) { head = null } else { head = next + prev.next = next + next.prev = prev } } else { prev.next = next diff --git a/packages/next/src/client/components/segment-cache/navigation.ts b/packages/next/src/client/components/segment-cache/navigation.ts index a52bbe410ad4..3a4face7f91e 100644 --- a/packages/next/src/client/components/segment-cache/navigation.ts +++ b/packages/next/src/client/components/segment-cache/navigation.ts @@ -11,7 +11,6 @@ import { startPPRNavigation, spawnDynamicRequests, FreshnessPolicy, - type NavigationTask, type NavigationRequestAccumulation, } from '../router-reducer/ppr-navigations' import { createHrefFromUrl } from '../router-reducer/create-href-from-url' @@ -24,36 +23,10 @@ import { type FulfilledRouteCacheEntry, } from './cache' import { createCacheKey, type NormalizedSearch } from './cache-key' -import { NavigationResultTag } from './types' import type { PageVaryPath } from './vary-path' - -type MPANavigationResult = { - tag: NavigationResultTag.MPA - data: string -} - -type SuccessfulNavigationResult = { - tag: NavigationResultTag.Success - data: { - flightRouterState: FlightRouterState - cacheNode: CacheNode - canonicalUrl: string - renderedSearch: string - scrollableSegments: Array | null - shouldScroll: boolean - hash: string - } -} - -type AsyncNavigationResult = { - tag: NavigationResultTag.Async - data: Promise -} - -export type NavigationResult = - | MPANavigationResult - | SuccessfulNavigationResult - | AsyncNavigationResult +import type { AppRouterState } from '../router-reducer/router-reducer-types' +import { computeChangedPath } from '../router-reducer/compute-changed-path' +import { isJavaScriptURLString } from '../../lib/javascript-url' /** * Navigate to a new URL, using the Segment Cache to construct a response. @@ -64,6 +37,7 @@ export type NavigationResult = * stream in any missing data. */ export function navigate( + state: AppRouterState, url: URL, currentUrl: URL, currentRenderedSearch: string, @@ -72,8 +46,8 @@ export function navigate( nextUrl: string | null, freshnessPolicy: FreshnessPolicy, shouldScroll: boolean, - accumulation: { collectedDebugInfo?: Array } -): NavigationResult { + navigateType: 'push' | 'replace' +): AppRouterState | Promise { const now = Date.now() const href = url.href @@ -83,6 +57,7 @@ export function navigate( // We have a matching prefetch. return navigateUsingPrefetchedRouteTree( now, + state, url, currentUrl, currentRenderedSearch, @@ -91,6 +66,7 @@ export function navigate( currentFlightRouterState, freshnessPolicy, shouldScroll, + navigateType, route ) } @@ -110,6 +86,7 @@ export function navigate( // We have an optimistic route tree. Proceed with the normal flow. return navigateUsingPrefetchedRouteTree( now, + state, url, currentUrl, currentRenderedSearch, @@ -118,35 +95,34 @@ export function navigate( currentFlightRouterState, freshnessPolicy, shouldScroll, + navigateType, optimisticRoute ) } } // There's no matching prefetch for this route in the cache. - let collectedDebugInfo = accumulation.collectedDebugInfo ?? [] - if (accumulation.collectedDebugInfo === undefined) { - collectedDebugInfo = accumulation.collectedDebugInfo = [] - } - return { - tag: NavigationResultTag.Async, - data: navigateToUnknownRoute( - now, - url, - currentUrl, - currentRenderedSearch, - nextUrl, - currentCacheNode, - currentFlightRouterState, - freshnessPolicy, - shouldScroll, - collectedDebugInfo - ), - } + return navigateToUnknownRoute( + now, + state, + url, + currentUrl, + currentRenderedSearch, + nextUrl, + currentCacheNode, + currentFlightRouterState, + freshnessPolicy, + shouldScroll, + navigateType + ).catch(() => { + // If the navigation fails, return the current state + return state + }) } export function navigateToKnownRoute( now: number, + state: AppRouterState, url: URL, canonicalUrl: string, navigationSeed: NavigationSeed, @@ -156,8 +132,10 @@ export function navigateToKnownRoute( currentFlightRouterState: FlightRouterState, freshnessPolicy: FreshnessPolicy, nextUrl: string | null, - shouldScroll: boolean -): SuccessfulNavigationResult | MPANavigationResult { + shouldScroll: boolean, + navigateType: 'push' | 'replace', + debugInfo: Array | null +): AppRouterState { // A version of navigate() that accepts the target route tree as an argument // rather than reading it from the prefetch cache. const accumulation: NavigationRequestAccumulation = { @@ -199,24 +177,27 @@ export function navigateToKnownRoute( ) if (task !== null) { spawnDynamicRequests(task, url, nextUrl, freshnessPolicy, accumulation) - return navigationTaskToResult( - task, - canonicalUrl, + return completeSoftNavigation( + state, + url, + nextUrl, + task.route, + task.node, navigationSeed.renderedSearch, - accumulation.scrollableSegments, + canonicalUrl, + navigateType, shouldScroll, - url.hash + accumulation.scrollableSegments, + debugInfo ) } // Could not perform a SPA navigation. Revert to a full-page (MPA) navigation. - return { - tag: NavigationResultTag.MPA, - data: canonicalUrl, - } + return completeHardNavigation(state, url, navigateType) } function navigateUsingPrefetchedRouteTree( now: number, + state: AppRouterState, url: URL, currentUrl: URL, currentRenderedSearch: string, @@ -225,8 +206,9 @@ function navigateUsingPrefetchedRouteTree( currentFlightRouterState: FlightRouterState, freshnessPolicy: FreshnessPolicy, shouldScroll: boolean, + navigateType: 'push' | 'replace', route: FulfilledRouteCacheEntry -): SuccessfulNavigationResult | MPANavigationResult { +): AppRouterState { const routeTree = route.tree const canonicalUrl = route.canonicalUrl + url.hash const renderedSearch = route.renderedSearch @@ -239,6 +221,7 @@ function navigateUsingPrefetchedRouteTree( } return navigateToKnownRoute( now, + state, url, canonicalUrl, prefetchSeed, @@ -248,32 +231,12 @@ function navigateUsingPrefetchedRouteTree( currentFlightRouterState, freshnessPolicy, nextUrl, - shouldScroll + shouldScroll, + navigateType, + null ) } -function navigationTaskToResult( - task: NavigationTask, - canonicalUrl: string, - renderedSearch: string, - scrollableSegments: Array | null, - shouldScroll: boolean, - hash: string -): SuccessfulNavigationResult | MPANavigationResult { - return { - tag: NavigationResultTag.Success, - data: { - flightRouterState: task.route, - cacheNode: task.node, - canonicalUrl, - renderedSearch, - scrollableSegments, - shouldScroll, - hash, - }, - } -} - // Used to request all the dynamic data for a route, rather than just a subset, // e.g. during a refresh or a revalidation. Typically this gets constructed // during the normal flow when diffing the route tree, but for an unprefetched @@ -288,6 +251,7 @@ const DynamicRequestTreeForEntireRoute: FlightRouterState = [ async function navigateToUnknownRoute( now: number, + state: AppRouterState, url: URL, currentUrl: URL, currentRenderedSearch: string, @@ -296,8 +260,8 @@ async function navigateToUnknownRoute( currentFlightRouterState: FlightRouterState, freshnessPolicy: FreshnessPolicy, shouldScroll: boolean, - collectedDebugInfo: Array -): Promise { + navigateType: 'push' | 'replace' +): Promise { // Runs when a navigation happens but there's no cached prefetch we can use. // Don't bother to wait for a prefetch response; go straight to a full // navigation that contains both static and dynamic data in a single stream. @@ -334,22 +298,11 @@ async function navigateToUnknownRoute( const result = await promiseForDynamicServerResponse if (typeof result === 'string') { // This is an MPA navigation. - const newUrl = result - return { - tag: NavigationResultTag.MPA, - data: newUrl, - } + const redirectUrl = new URL(result, location.origin) + return completeHardNavigation(state, redirectUrl, navigateType) } - const { - flightData, - canonicalUrl, - renderedSearch, - debugInfo: debugInfoFromResponse, - } = result - if (debugInfoFromResponse !== null) { - collectedDebugInfo.push(...debugInfoFromResponse) - } + const { flightData, canonicalUrl, renderedSearch, debugInfo } = result // Since the response format of dynamic requests and prefetches is slightly // different, we'll need to massage the data a bit. Create FlightRouterState @@ -362,6 +315,7 @@ async function navigateToUnknownRoute( return navigateToKnownRoute( now, + state, url, createHrefFromUrl(canonicalUrl), navigationSeed, @@ -371,10 +325,174 @@ async function navigateToUnknownRoute( currentFlightRouterState, freshnessPolicy, nextUrl, - shouldScroll + shouldScroll, + navigateType, + debugInfo ) } +export function completeHardNavigation( + state: AppRouterState, + url: URL, + navigateType: 'push' | 'replace' +): AppRouterState { + if (isJavaScriptURLString(url.href)) { + console.error( + 'Next.js has blocked a javascript: URL as a security precaution.' + ) + return state + } + const newState: AppRouterState = { + canonicalUrl: + url.origin === location.origin ? createHrefFromUrl(url) : url.href, + pushRef: { + pendingPush: navigateType === 'push', + mpaNavigation: true, + preserveCustomHistoryState: false, + }, + // TODO: None of the rest of these values are consistent with the incoming + // navigation. We rely on the fact that AppRouter will suspend and trigger + // a hard navigation before it accesses any of these values. But instead + // we should trigger the hard navigation and blocking any subsequent + // router updates without updating React. + renderedSearch: state.renderedSearch, + focusAndScrollRef: state.focusAndScrollRef, + cache: state.cache, + tree: state.tree, + nextUrl: state.nextUrl, + previousNextUrl: state.previousNextUrl, + debugInfo: null, + } + return newState +} + +export function completeSoftNavigation( + oldState: AppRouterState, + url: URL, + referringNextUrl: string | null, + tree: FlightRouterState, + cache: CacheNode, + renderedSearch: string, + canonicalUrl: string, + navigateType: 'push' | 'replace', + shouldScroll: boolean, + scrollableSegments: Array | null, + collectedDebugInfo: Array | null +) { + // The "Next-Url" is a special representation of the URL that Next.js + // uses to implement interception routes. + // TODO: Get rid of this extra traversal by computing this during the + // same traversal that computes the tree itself. We should also figure out + // what is the minimum information needed for the server to correctly + // intercept the route. + const changedPath = computeChangedPath(oldState.tree, tree) + const nextUrlForNewRoute = changedPath ? changedPath : oldState.nextUrl + + // This value is stored on the state as `previousNextUrl`; the naming is + // confusing. What it represents is the "Next-Url" header that was used to + // fetch the incoming route. It's essentially the refererer URL, but in a + // Next.js specific format. During refreshes, this is sent back to the server + // instead of the current route's "Next-Url" so that the same interception + // logic is applied as during the original navigation. + const previousNextUrl = referringNextUrl + + // Check if the only thing that changed was the hash fragment. + const oldUrl = new URL(oldState.canonicalUrl, url) + const onlyHashChange = + // We don't need to compare the origins, because client-driven + // navigations are always same-origin. + url.pathname === oldUrl.pathname && + url.search === oldUrl.search && + url.hash !== oldUrl.hash + + // During a hash-only change, setting scrollableSegments to an empty + // array triggers a scroll for all new and updated segments. See + // `ScrollAndFocusHandler` for more details. + // + // TODO: Given the previous comment, I don't know why shouldScroll = + // false sets this to an empty array. Seems like an accident. I'm just + // preserving the logic that was already here. Clean this up when we + // move the per-segment scroll state to the CacheNode. + const segmentPathsToScrollTo = + onlyHashChange || !shouldScroll + ? [] + : scrollableSegments !== null + ? scrollableSegments + : oldState.focusAndScrollRef.segmentPaths + + const newState: AppRouterState = { + canonicalUrl, + renderedSearch, + pushRef: { + pendingPush: navigateType === 'push', + mpaNavigation: false, + preserveCustomHistoryState: false, + }, + focusAndScrollRef: { + // TODO: We should track all the per-segment scroll state on the CacheNode + // instead of using the paths. + apply: shouldScroll + ? segmentPathsToScrollTo !== null + ? true + : oldState.focusAndScrollRef.apply + : oldState.focusAndScrollRef.apply, + onlyHashChange, + hashFragment: + // Remove leading # and decode hash to make non-latin hashes work. + // + // Empty hash should trigger default behavior of scrolling layout into + // view. #top is handled in layout-router. + // + // Refer to `ScrollAndFocusHandler` for details on how this is used. + shouldScroll && url.hash !== '' + ? decodeURIComponent(url.hash.slice(1)) + : oldState.focusAndScrollRef.hashFragment, + segmentPaths: segmentPathsToScrollTo, + }, + cache, + tree, + nextUrl: nextUrlForNewRoute, + previousNextUrl, + debugInfo: collectedDebugInfo, + } + return newState +} + +export function completeTraverseNavigation( + state: AppRouterState, + url: URL, + renderedSearch: string, + cache: CacheNode, + tree: FlightRouterState, + nextUrl: string | null +) { + return { + // Set canonical url + canonicalUrl: createHrefFromUrl(url), + renderedSearch, + pushRef: { + pendingPush: false, + mpaNavigation: false, + // Ensures that the custom history state that was set is preserved when applying this update. + preserveCustomHistoryState: true, + }, + focusAndScrollRef: state.focusAndScrollRef, + cache, + // Restore provided tree + tree, + nextUrl, + // TODO: We need to restore previousNextUrl, too, which represents the + // Next-Url that was used to fetch the data. Anywhere we fetch using the + // canonical URL, there should be a corresponding Next-Url. + previousNextUrl: null, + debugInfo: null, + } +} + +// TODO: The rest of this file is related to converting the server response into +// the data structures used by the client. Probably should move to a +// separate module. + export type NavigationSeed = { renderedSearch: string routeTree: RouteTree diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-client.development.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-client.development.js index a311152465b0..ac9f4af54a7c 100644 --- a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-client.development.js +++ b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-client.development.js @@ -1273,6 +1273,10 @@ (root.pingedLanes = 0), (root.warmLanes = 0)); } + function markRootPinged$1(root, pingedLanes) { + root.pingedLanes |= root.suspendedLanes & pingedLanes; + root.warmLanes &= ~pingedLanes; + } function markRootFinished( root, finishedLanes, @@ -4508,38 +4512,6 @@ errors )); } - function logRenderPhase(startTime, endTime, lanes, debugTask) { - if (supportsUserTiming && !(endTime <= startTime)) { - var color = - (lanes & 738197653) === lanes ? "tertiary-dark" : "primary-dark"; - lanes = - (lanes & 536870912) === lanes - ? "Prepared" - : (lanes & 201326741) === lanes - ? "Hydrated" - : "Render"; - debugTask - ? debugTask.run( - console.timeStamp.bind( - console, - lanes, - startTime, - endTime, - currentTrack, - LANES_TRACK_GROUP, - color - ) - ) - : console.timeStamp( - lanes, - startTime, - endTime, - currentTrack, - LANES_TRACK_GROUP, - color - ); - } - } function logSuspendedRenderPhase(startTime, endTime, lanes, debugTask) { !supportsUserTiming || endTime <= startTime || @@ -4592,50 +4564,6 @@ lanes )); } - function logRecoveredRenderPhase( - startTime, - endTime, - lanes, - recoverableErrors, - hydrationFailed, - debugTask - ) { - if (supportsUserTiming && !(endTime <= startTime)) { - lanes = []; - for (var i = 0; i < recoverableErrors.length; i++) { - var error = recoverableErrors[i].value; - lanes.push([ - "Recoverable Error", - "object" === typeof error && - null !== error && - "string" === typeof error.message - ? String(error.message) - : String(error) - ]); - } - startTime = { - start: startTime, - end: endTime, - detail: { - devtools: { - color: "primary-dark", - track: currentTrack, - trackGroup: LANES_TRACK_GROUP, - tooltipText: hydrationFailed - ? "Hydration Failed" - : "Recovered after Error", - properties: lanes - } - } - }; - debugTask - ? debugTask.run( - performance.measure.bind(performance, "Recovered", startTime) - ) - : performance.measure("Recovered", startTime); - performance.clearMeasures("Recovered"); - } - } function logErroredRenderPhase(startTime, endTime, lanes, debugTask) { !supportsUserTiming || endTime <= startTime || @@ -5098,7 +5026,7 @@ (workInProgress.key = current.key), (workInProgress.actualDuration = -0), (workInProgress.actualStartTime = -1.1)); - workInProgress.flags = current.flags & 132120576; + workInProgress.flags = current.flags & 133169152; workInProgress.childLanes = current.childLanes; workInProgress.lanes = current.lanes; workInProgress.child = current.child; @@ -5136,7 +5064,7 @@ return workInProgress; } function resetWorkInProgress(workInProgress, renderLanes) { - workInProgress.flags &= 132120578; + workInProgress.flags &= 133169154; var current = workInProgress.alternate; null === current ? ((workInProgress.childLanes = 0), @@ -6224,39 +6152,30 @@ gestureOptions, transitionTypes ) { - if (gestureOptions && null != gestureOptions.rangeStart) - var JSCompiler_temp = gestureOptions.rangeStart; - else { - JSCompiler_temp = gestureTimeline.currentTime; - if (null === JSCompiler_temp) - throw Error( - "Cannot start a gesture with a disconnected AnimationTimeline." - ); - JSCompiler_temp = - "number" === typeof JSCompiler_temp - ? JSCompiler_temp - : JSCompiler_temp.value; - } + var rangeStart = + gestureOptions && null != gestureOptions.rangeStart + ? gestureOptions.rangeStart + : getCurrentGestureOffset(gestureTimeline); gestureOptions = gestureOptions && null != gestureOptions.rangeEnd ? gestureOptions.rangeEnd - : 50 > JSCompiler_temp + : 50 > rangeStart ? 100 : 0; for (root = root.pendingGestures; null !== root; ) { if (root.provider === gestureTimeline) { root.count++; - root.rangeStart = JSCompiler_temp; + root.rangeStart = rangeStart; root.rangeEnd = gestureOptions; if (null !== transitionTypes) for ( gestureTimeline = root.types, null === gestureTimeline && (gestureTimeline = root.types = []), - JSCompiler_temp = 0; - JSCompiler_temp < transitionTypes.length; - JSCompiler_temp++ + rangeStart = 0; + rangeStart < transitionTypes.length; + rangeStart++ ) - (gestureOptions = transitionTypes[JSCompiler_temp]), + (gestureOptions = transitionTypes[rangeStart]), -1 === gestureTimeline.indexOf(gestureOptions) && gestureTimeline.push(gestureOptions); return root; @@ -6266,47 +6185,78 @@ } return null; } - function deleteScheduledGesture(root, gesture) { - null === gesture.prev - ? (root.pendingGestures === gesture && - ((root.pendingGestures = gesture.next), - null === root.pendingGestures && (root.pendingLanes &= -65)), - root.stoppingGestures === gesture && - (root.stoppingGestures = gesture.next)) - : ((gesture.prev.next = gesture.next), - null !== gesture.next && (gesture.next.prev = gesture.prev), - (gesture.prev = null), - (gesture.next = null)); - } - function stopCompletedGestures(root) { - var gesture = root.stoppingGestures; - for (root.stoppingGestures = null; null !== gesture; ) - null !== gesture.running && - (gesture.running.skipTransition(), (gesture.running = null)), - (root = gesture.next), - (gesture.next = null), - (gesture.prev = null), - (gesture = root); + function stopCommittedGesture(root) { + var committedGesture = root.pendingGestures; + if (null !== committedGesture) { + committedGesture.committing = !1; + var nextGesture = committedGesture.next; + null === nextGesture + ? (root.pendingLanes &= -65) + : (nextGesture.prev = null); + root.pendingGestures = nextGesture; + root = committedGesture.running; + null !== root && + ((committedGesture.running = null), root.skipTransition()); + } + } + function scheduleGestureCommit(gesture, callback) { + gesture.commit = callback; + return function () { + gesture.commit = null; + }; } function chainGestureCancellation(root, scheduledGesture, prevCancel) { return function () { - if ( - null !== scheduledGesture && - (scheduledGesture.count--, 0 === scheduledGesture.count) - ) { - deleteScheduledGesture(root, scheduledGesture); - var runningTransition = scheduledGesture.running; - if (null !== runningTransition) { - var pendingLanesExcludingGestureLane = root.pendingLanes & -65; - 0 !== (pendingLanesExcludingGestureLane & 127) || - 0 !== (pendingLanesExcludingGestureLane & 4194048) - ? ((runningTransition = root.stoppingGestures), - null !== runningTransition && - ((scheduledGesture.next = runningTransition), - (runningTransition.prev = scheduledGesture)), - (root.stoppingGestures = scheduledGesture)) - : ((scheduledGesture.running = null), - runningTransition.skipTransition()); + if (null !== scheduledGesture) { + if (0 !== scheduledGesture.revertLane) { + var entangledLanes = + scheduledGesture.revertLane | requestTransitionLane(); + markRootEntangled(root, entangledLanes); + } + scheduledGesture.count--; + if (0 === scheduledGesture.count) { + var finalOffset = getCurrentGestureOffset( + scheduledGesture.provider + ), + rangeStart = scheduledGesture.rangeStart, + rangeEnd = scheduledGesture.rangeEnd; + entangledLanes = scheduledGesture.running; + null !== entangledLanes && + (rangeStart < rangeEnd + ? finalOffset > rangeStart + (rangeEnd - rangeStart) / 2 + : finalOffset < rangeEnd + (rangeStart - rangeEnd) / 2) + ? ((scheduledGesture.committing = !0), + root.pendingGestures === scheduledGesture && + ((entangledLanes = scheduledGesture.commit), + null !== entangledLanes + ? ((scheduledGesture.commit = null), entangledLanes()) + : null !== root.pendingGestures && + (markRootPinged$1(root, 64), + ensureRootIsScheduled(root)))) + : null === scheduledGesture.prev + ? (root.pendingGestures === scheduledGesture && + ((root.pendingGestures = scheduledGesture.next), + (finalOffset = root.pendingLanes), + null === root.pendingGestures && (finalOffset &= -65), + markRootFinished(root, 64, finalOffset, 0, 0, 0), + workInProgressRoot === root && + 64 === workInProgressRootRenderLanes + ? (executionContext & RenderContext) === NoContext && + prepareFreshStack(root, 0) + : null !== root.cancelPendingCommit && + 64 === pendingEffectsLanes && + ((finalOffset = root.cancelPendingCommit), + null !== finalOffset && + ((root.cancelPendingCommit = null), finalOffset())), + null !== root.pendingGestures && markRootPinged$1(root, 64), + ensureRootIsScheduled(root)), + (scheduledGesture.running = null), + null !== entangledLanes && entangledLanes.skipTransition()) + : ((scheduledGesture.prev.next = scheduledGesture.next), + null !== scheduledGesture.next && + (scheduledGesture.next.prev = scheduledGesture.prev), + (scheduledGesture.prev = null), + (scheduledGesture.next = null)); } } null !== prevCancel && prevCancel(); @@ -8224,7 +8174,7 @@ null; hookTypesUpdateIndexDev = -1; null !== current && - (current.flags & 132120576) !== (workInProgress.flags & 132120576) && + (current.flags & 133169152) !== (workInProgress.flags & 133169152) && console.error( "Internal React error: Expected static flag was missing. Please notify the React team." ); @@ -8524,18 +8474,20 @@ if (64 === updateLane) { var scheduledGesture = update.gesture; if (null !== scheduledGesture) - if (0 === scheduledGesture.count) { + if (0 !== scheduledGesture.count || scheduledGesture.committing) + if (64 === renderLanes) { + shouldSkipUpdate = workInProgressRoot; + if (null === shouldSkipUpdate) + throw Error( + "Expected a work-in-progress root. This is a bug in React. Please file an issue." + ); + shouldSkipUpdate = + shouldSkipUpdate.pendingGestures !== scheduledGesture; + } else shouldSkipUpdate = !0; + else { update = update.next; continue; - } else if (64 === renderLanes) { - shouldSkipUpdate = workInProgressRoot; - if (null === shouldSkipUpdate) - throw Error( - "Expected a work-in-progress root. This is a bug in React. Please file an issue." - ); - shouldSkipUpdate = - shouldSkipUpdate.pendingGestures !== scheduledGesture; - } else shouldSkipUpdate = !0; + } } if (shouldSkipUpdate) (scheduledGesture = { @@ -9388,7 +9340,7 @@ hook ); if ( - 0 === (renderLanes & 42) || + 0 === (renderLanes & 106) || (0 !== (renderLanes & 1073741824) && 0 === (workInProgressRootRenderLanes & 261930)) ) @@ -9774,6 +9726,9 @@ rangeEnd: 100, types: null, running: null, + commit: null, + committing: !1, + revertLane: 0, prev: fiber, next: null }; @@ -9783,7 +9738,10 @@ ensureRootIsScheduled(throwIfDuringRender); throwIfDuringRender = transition; } - action.gesture = throwIfDuringRender; + throwIfDuringRender = action.gesture = throwIfDuringRender; + 0 === throwIfDuringRender.revertLane + ? (throwIfDuringRender.revertLane = action.revertLane) + : (action.revertLane = throwIfDuringRender.revertLane); } } function isRenderPhaseUpdate(fiber) { @@ -11396,24 +11354,24 @@ return current; } function updateSuspenseComponent(current, workInProgress, renderLanes) { - var JSCompiler_object_inline_digest_3226; - var JSCompiler_object_inline_stack_3227 = workInProgress.pendingProps; + var JSCompiler_object_inline_digest_3284; + var JSCompiler_object_inline_stack_3285 = workInProgress.pendingProps; shouldSuspendImpl(workInProgress) && (workInProgress.flags |= 128); - var JSCompiler_object_inline_message_3225 = !1; + var JSCompiler_object_inline_message_3283 = !1; var didSuspend = 0 !== (workInProgress.flags & 128); - (JSCompiler_object_inline_digest_3226 = didSuspend) || - (JSCompiler_object_inline_digest_3226 = + (JSCompiler_object_inline_digest_3284 = didSuspend) || + (JSCompiler_object_inline_digest_3284 = null !== current && null === current.memoizedState ? !1 : 0 !== (suspenseStackCursor.current & ForceSuspenseFallback)); - JSCompiler_object_inline_digest_3226 && - ((JSCompiler_object_inline_message_3225 = !0), + JSCompiler_object_inline_digest_3284 && + ((JSCompiler_object_inline_message_3283 = !0), (workInProgress.flags &= -129)); - JSCompiler_object_inline_digest_3226 = 0 !== (workInProgress.flags & 32); + JSCompiler_object_inline_digest_3284 = 0 !== (workInProgress.flags & 32); workInProgress.flags &= -33; if (null === current) { if (isHydrating) { - JSCompiler_object_inline_message_3225 + JSCompiler_object_inline_message_3283 ? pushPrimaryTreeSuspenseHandler(workInProgress) : reuseSuspenseHandlerOnStack(workInProgress); (current = nextHydratableInstance) @@ -11426,18 +11384,18 @@ ? renderLanes : null), null !== renderLanes && - ((JSCompiler_object_inline_digest_3226 = { + ((JSCompiler_object_inline_digest_3284 = { dehydrated: renderLanes, treeContext: getSuspendedTreeContext(), retryLane: 536870912, hydrationErrors: null }), (workInProgress.memoizedState = - JSCompiler_object_inline_digest_3226), - (JSCompiler_object_inline_digest_3226 = + JSCompiler_object_inline_digest_3284), + (JSCompiler_object_inline_digest_3284 = createFiberFromDehydratedFragment(renderLanes)), - (JSCompiler_object_inline_digest_3226.return = workInProgress), - (workInProgress.child = JSCompiler_object_inline_digest_3226), + (JSCompiler_object_inline_digest_3284.return = workInProgress), + (workInProgress.child = JSCompiler_object_inline_digest_3284), (hydrationParentFiber = workInProgress), (nextHydratableInstance = null))) : (renderLanes = null); @@ -11451,9 +11409,9 @@ : (workInProgress.lanes = 536870912); return null; } - var nextPrimaryChildren = JSCompiler_object_inline_stack_3227.children, - nextFallbackChildren = JSCompiler_object_inline_stack_3227.fallback; - if (JSCompiler_object_inline_message_3225) + var nextPrimaryChildren = JSCompiler_object_inline_stack_3285.children, + nextFallbackChildren = JSCompiler_object_inline_stack_3285.fallback; + if (JSCompiler_object_inline_message_3283) return ( reuseSuspenseHandlerOnStack(workInProgress), mountSuspenseFallbackChildren( @@ -11462,19 +11420,19 @@ nextFallbackChildren, renderLanes ), - (JSCompiler_object_inline_stack_3227 = workInProgress.child), - (JSCompiler_object_inline_stack_3227.memoizedState = + (JSCompiler_object_inline_stack_3285 = workInProgress.child), + (JSCompiler_object_inline_stack_3285.memoizedState = mountSuspenseOffscreenState(renderLanes)), - (JSCompiler_object_inline_stack_3227.childLanes = + (JSCompiler_object_inline_stack_3285.childLanes = getRemainingWorkInPrimaryTree( current, - JSCompiler_object_inline_digest_3226, + JSCompiler_object_inline_digest_3284, renderLanes )), (workInProgress.memoizedState = SUSPENDED_MARKER), - bailoutOffscreenComponent(null, JSCompiler_object_inline_stack_3227) + bailoutOffscreenComponent(null, JSCompiler_object_inline_stack_3285) ); - if (!0 === JSCompiler_object_inline_stack_3227.defer) + if (!0 === JSCompiler_object_inline_stack_3285.defer) return ( reuseSuspenseHandlerOnStack(workInProgress), mountSuspenseFallbackChildren( @@ -11483,18 +11441,18 @@ nextFallbackChildren, renderLanes ), - (JSCompiler_object_inline_stack_3227 = workInProgress.child), - (JSCompiler_object_inline_stack_3227.memoizedState = + (JSCompiler_object_inline_stack_3285 = workInProgress.child), + (JSCompiler_object_inline_stack_3285.memoizedState = mountSuspenseOffscreenState(renderLanes)), - (JSCompiler_object_inline_stack_3227.childLanes = + (JSCompiler_object_inline_stack_3285.childLanes = getRemainingWorkInPrimaryTree( current, - JSCompiler_object_inline_digest_3226, + JSCompiler_object_inline_digest_3284, renderLanes )), (workInProgress.memoizedState = SUSPENDED_MARKER), (workInProgress.lanes = 4194304), - bailoutOffscreenComponent(null, JSCompiler_object_inline_stack_3227) + bailoutOffscreenComponent(null, JSCompiler_object_inline_stack_3285) ); pushPrimaryTreeSuspenseHandler(workInProgress); return mountSuspensePrimaryChildren( @@ -11504,8 +11462,8 @@ } var prevState = current.memoizedState; if (null !== prevState) { - var JSCompiler_object_inline_componentStack_3228 = prevState.dehydrated; - if (null !== JSCompiler_object_inline_componentStack_3228) { + var JSCompiler_object_inline_componentStack_3286 = prevState.dehydrated; + if (null !== JSCompiler_object_inline_componentStack_3286) { if (didSuspend) workInProgress.flags & 256 ? (pushPrimaryTreeSuspenseHandler(workInProgress), @@ -11522,13 +11480,13 @@ (workInProgress = null)) : (reuseSuspenseHandlerOnStack(workInProgress), (nextPrimaryChildren = - JSCompiler_object_inline_stack_3227.fallback), + JSCompiler_object_inline_stack_3285.fallback), (nextFallbackChildren = workInProgress.mode), - (JSCompiler_object_inline_stack_3227 = + (JSCompiler_object_inline_stack_3285 = mountWorkInProgressOffscreenFiber( { mode: "visible", - children: JSCompiler_object_inline_stack_3227.children + children: JSCompiler_object_inline_stack_3285.children }, nextFallbackChildren )), @@ -11539,30 +11497,30 @@ null )), (nextPrimaryChildren.flags |= 2), - (JSCompiler_object_inline_stack_3227.return = workInProgress), + (JSCompiler_object_inline_stack_3285.return = workInProgress), (nextPrimaryChildren.return = workInProgress), - (JSCompiler_object_inline_stack_3227.sibling = + (JSCompiler_object_inline_stack_3285.sibling = nextPrimaryChildren), - (workInProgress.child = JSCompiler_object_inline_stack_3227), + (workInProgress.child = JSCompiler_object_inline_stack_3285), reconcileChildFibers( workInProgress, current.child, null, renderLanes ), - (JSCompiler_object_inline_stack_3227 = workInProgress.child), - (JSCompiler_object_inline_stack_3227.memoizedState = + (JSCompiler_object_inline_stack_3285 = workInProgress.child), + (JSCompiler_object_inline_stack_3285.memoizedState = mountSuspenseOffscreenState(renderLanes)), - (JSCompiler_object_inline_stack_3227.childLanes = + (JSCompiler_object_inline_stack_3285.childLanes = getRemainingWorkInPrimaryTree( current, - JSCompiler_object_inline_digest_3226, + JSCompiler_object_inline_digest_3284, renderLanes )), (workInProgress.memoizedState = SUSPENDED_MARKER), (workInProgress = bailoutOffscreenComponent( null, - JSCompiler_object_inline_stack_3227 + JSCompiler_object_inline_stack_3285 ))); else if ( (pushPrimaryTreeSuspenseHandler(workInProgress), @@ -11570,45 +11528,45 @@ 0 !== (renderLanes & 536870912) && markRenderDerivedCause(workInProgress), isSuspenseInstanceFallback( - JSCompiler_object_inline_componentStack_3228 + JSCompiler_object_inline_componentStack_3286 )) ) { - JSCompiler_object_inline_digest_3226 = - JSCompiler_object_inline_componentStack_3228.nextSibling && - JSCompiler_object_inline_componentStack_3228.nextSibling.dataset; - if (JSCompiler_object_inline_digest_3226) { - nextPrimaryChildren = JSCompiler_object_inline_digest_3226.dgst; - var message = JSCompiler_object_inline_digest_3226.msg; - nextFallbackChildren = JSCompiler_object_inline_digest_3226.stck; - var componentStack = JSCompiler_object_inline_digest_3226.cstck; + JSCompiler_object_inline_digest_3284 = + JSCompiler_object_inline_componentStack_3286.nextSibling && + JSCompiler_object_inline_componentStack_3286.nextSibling.dataset; + if (JSCompiler_object_inline_digest_3284) { + nextPrimaryChildren = JSCompiler_object_inline_digest_3284.dgst; + var message = JSCompiler_object_inline_digest_3284.msg; + nextFallbackChildren = JSCompiler_object_inline_digest_3284.stck; + var componentStack = JSCompiler_object_inline_digest_3284.cstck; } - JSCompiler_object_inline_message_3225 = message; - JSCompiler_object_inline_digest_3226 = nextPrimaryChildren; - JSCompiler_object_inline_stack_3227 = nextFallbackChildren; - JSCompiler_object_inline_componentStack_3228 = componentStack; - nextPrimaryChildren = JSCompiler_object_inline_message_3225; - nextFallbackChildren = JSCompiler_object_inline_componentStack_3228; + JSCompiler_object_inline_message_3283 = message; + JSCompiler_object_inline_digest_3284 = nextPrimaryChildren; + JSCompiler_object_inline_stack_3285 = nextFallbackChildren; + JSCompiler_object_inline_componentStack_3286 = componentStack; + nextPrimaryChildren = JSCompiler_object_inline_message_3283; + nextFallbackChildren = JSCompiler_object_inline_componentStack_3286; nextPrimaryChildren = nextPrimaryChildren ? Error(nextPrimaryChildren) : Error( "The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering." ); nextPrimaryChildren.stack = - JSCompiler_object_inline_stack_3227 || ""; - nextPrimaryChildren.digest = JSCompiler_object_inline_digest_3226; - JSCompiler_object_inline_digest_3226 = + JSCompiler_object_inline_stack_3285 || ""; + nextPrimaryChildren.digest = JSCompiler_object_inline_digest_3284; + JSCompiler_object_inline_digest_3284 = void 0 === nextFallbackChildren ? null : nextFallbackChildren; - JSCompiler_object_inline_stack_3227 = { + JSCompiler_object_inline_stack_3285 = { value: nextPrimaryChildren, source: null, - stack: JSCompiler_object_inline_digest_3226 + stack: JSCompiler_object_inline_digest_3284 }; - "string" === typeof JSCompiler_object_inline_digest_3226 && + "string" === typeof JSCompiler_object_inline_digest_3284 && CapturedStacks.set( nextPrimaryChildren, - JSCompiler_object_inline_stack_3227 + JSCompiler_object_inline_stack_3285 ); - queueHydrationError(JSCompiler_object_inline_stack_3227); + queueHydrationError(JSCompiler_object_inline_stack_3285); workInProgress = retrySuspenseComponentWithoutHydrating( current, workInProgress, @@ -11622,35 +11580,35 @@ renderLanes, !1 ), - (JSCompiler_object_inline_digest_3226 = + (JSCompiler_object_inline_digest_3284 = 0 !== (renderLanes & current.childLanes)), - didReceiveUpdate || JSCompiler_object_inline_digest_3226) + didReceiveUpdate || JSCompiler_object_inline_digest_3284) ) { - JSCompiler_object_inline_digest_3226 = workInProgressRoot; + JSCompiler_object_inline_digest_3284 = workInProgressRoot; if ( - null !== JSCompiler_object_inline_digest_3226 && - ((JSCompiler_object_inline_stack_3227 = getBumpedLaneForHydration( - JSCompiler_object_inline_digest_3226, + null !== JSCompiler_object_inline_digest_3284 && + ((JSCompiler_object_inline_stack_3285 = getBumpedLaneForHydration( + JSCompiler_object_inline_digest_3284, renderLanes )), - 0 !== JSCompiler_object_inline_stack_3227 && - JSCompiler_object_inline_stack_3227 !== prevState.retryLane) + 0 !== JSCompiler_object_inline_stack_3285 && + JSCompiler_object_inline_stack_3285 !== prevState.retryLane) ) throw ( - ((prevState.retryLane = JSCompiler_object_inline_stack_3227), + ((prevState.retryLane = JSCompiler_object_inline_stack_3285), enqueueConcurrentRenderForLane( current, - JSCompiler_object_inline_stack_3227 + JSCompiler_object_inline_stack_3285 ), scheduleUpdateOnFiber( - JSCompiler_object_inline_digest_3226, + JSCompiler_object_inline_digest_3284, current, - JSCompiler_object_inline_stack_3227 + JSCompiler_object_inline_stack_3285 ), SelectiveHydrationException) ); isSuspenseInstancePending( - JSCompiler_object_inline_componentStack_3228 + JSCompiler_object_inline_componentStack_3286 ) || renderDidSuspendDelayIfPossible(); workInProgress = retrySuspenseComponentWithoutHydrating( current, @@ -11659,14 +11617,14 @@ ); } else isSuspenseInstancePending( - JSCompiler_object_inline_componentStack_3228 + JSCompiler_object_inline_componentStack_3286 ) ? ((workInProgress.flags |= 192), (workInProgress.child = current.child), (workInProgress = null)) : ((current = prevState.treeContext), (nextHydratableInstance = getNextHydratable( - JSCompiler_object_inline_componentStack_3228.nextSibling + JSCompiler_object_inline_componentStack_3286.nextSibling )), (hydrationParentFiber = workInProgress), (isHydrating = !0), @@ -11678,32 +11636,32 @@ restoreSuspendedTreeContext(workInProgress, current), (workInProgress = mountSuspensePrimaryChildren( workInProgress, - JSCompiler_object_inline_stack_3227.children + JSCompiler_object_inline_stack_3285.children )), (workInProgress.flags |= 4096)); return workInProgress; } } - if (JSCompiler_object_inline_message_3225) + if (JSCompiler_object_inline_message_3283) return ( reuseSuspenseHandlerOnStack(workInProgress), - (nextPrimaryChildren = JSCompiler_object_inline_stack_3227.fallback), + (nextPrimaryChildren = JSCompiler_object_inline_stack_3285.fallback), (nextFallbackChildren = workInProgress.mode), (componentStack = current.child), - (JSCompiler_object_inline_componentStack_3228 = + (JSCompiler_object_inline_componentStack_3286 = componentStack.sibling), - (JSCompiler_object_inline_stack_3227 = createWorkInProgress( + (JSCompiler_object_inline_stack_3285 = createWorkInProgress( componentStack, { mode: "hidden", - children: JSCompiler_object_inline_stack_3227.children + children: JSCompiler_object_inline_stack_3285.children } )), - (JSCompiler_object_inline_stack_3227.subtreeFlags = - componentStack.subtreeFlags & 132120576), - null !== JSCompiler_object_inline_componentStack_3228 + (JSCompiler_object_inline_stack_3285.subtreeFlags = + componentStack.subtreeFlags & 133169152), + null !== JSCompiler_object_inline_componentStack_3286 ? (nextPrimaryChildren = createWorkInProgress( - JSCompiler_object_inline_componentStack_3228, + JSCompiler_object_inline_componentStack_3286, nextPrimaryChildren )) : ((nextPrimaryChildren = createFiberFromFragment( @@ -11714,11 +11672,11 @@ )), (nextPrimaryChildren.flags |= 2)), (nextPrimaryChildren.return = workInProgress), - (JSCompiler_object_inline_stack_3227.return = workInProgress), - (JSCompiler_object_inline_stack_3227.sibling = nextPrimaryChildren), - (workInProgress.child = JSCompiler_object_inline_stack_3227), - bailoutOffscreenComponent(null, JSCompiler_object_inline_stack_3227), - (JSCompiler_object_inline_stack_3227 = workInProgress.child), + (JSCompiler_object_inline_stack_3285.return = workInProgress), + (JSCompiler_object_inline_stack_3285.sibling = nextPrimaryChildren), + (workInProgress.child = JSCompiler_object_inline_stack_3285), + bailoutOffscreenComponent(null, JSCompiler_object_inline_stack_3285), + (JSCompiler_object_inline_stack_3285 = workInProgress.child), (nextPrimaryChildren = current.child.memoizedState), null === nextPrimaryChildren ? (nextPrimaryChildren = mountSuspenseOffscreenState(renderLanes)) @@ -11734,18 +11692,18 @@ baseLanes: nextPrimaryChildren.baseLanes | renderLanes, cachePool: nextFallbackChildren })), - (JSCompiler_object_inline_stack_3227.memoizedState = + (JSCompiler_object_inline_stack_3285.memoizedState = nextPrimaryChildren), - (JSCompiler_object_inline_stack_3227.childLanes = + (JSCompiler_object_inline_stack_3285.childLanes = getRemainingWorkInPrimaryTree( current, - JSCompiler_object_inline_digest_3226, + JSCompiler_object_inline_digest_3284, renderLanes )), (workInProgress.memoizedState = SUSPENDED_MARKER), bailoutOffscreenComponent( current.child, - JSCompiler_object_inline_stack_3227 + JSCompiler_object_inline_stack_3285 ) ); null !== prevState && @@ -11757,16 +11715,16 @@ current = renderLanes.sibling; renderLanes = createWorkInProgress(renderLanes, { mode: "visible", - children: JSCompiler_object_inline_stack_3227.children + children: JSCompiler_object_inline_stack_3285.children }); renderLanes.return = workInProgress; renderLanes.sibling = null; null !== current && - ((JSCompiler_object_inline_digest_3226 = workInProgress.deletions), - null === JSCompiler_object_inline_digest_3226 + ((JSCompiler_object_inline_digest_3284 = workInProgress.deletions), + null === JSCompiler_object_inline_digest_3284 ? ((workInProgress.deletions = [current]), (workInProgress.flags |= 16)) - : JSCompiler_object_inline_digest_3226.push(current)); + : JSCompiler_object_inline_digest_3284.push(current)); workInProgress.child = renderLanes; workInProgress.memoizedState = null; return renderLanes; @@ -13080,8 +13038,8 @@ ) (newChildLanes |= _child2.lanes | _child2.childLanes), - (subtreeFlags |= _child2.subtreeFlags & 132120576), - (subtreeFlags |= _child2.flags & 132120576), + (subtreeFlags |= _child2.subtreeFlags & 133169152), + (subtreeFlags |= _child2.flags & 133169152), (_treeBaseDuration += _child2.treeBaseDuration), (_child2 = _child2.sibling); completedWork.treeBaseDuration = _treeBaseDuration; @@ -13093,8 +13051,8 @@ ) (newChildLanes |= _treeBaseDuration.lanes | _treeBaseDuration.childLanes), - (subtreeFlags |= _treeBaseDuration.subtreeFlags & 132120576), - (subtreeFlags |= _treeBaseDuration.flags & 132120576), + (subtreeFlags |= _treeBaseDuration.subtreeFlags & 133169152), + (subtreeFlags |= _treeBaseDuration.flags & 133169152), (_treeBaseDuration.return = completedWork), (_treeBaseDuration = _treeBaseDuration.sibling); else if ((completedWork.mode & ProfileMode) !== NoMode) { @@ -14947,7 +14905,9 @@ (viewTransitionCancelableChildren = []), viewTransitionCancelableChildren.push( instance, - oldName, + 0 === viewTransitionHostInstanceIdx + ? oldName + : oldName + "_" + viewTransitionHostInstanceIdx, child.memoizedProps )); viewTransitionHostInstanceIdx++; @@ -18912,7 +18872,7 @@ throw Error("Unknown root exit status."); } if (null !== ReactSharedInternals.actQueue) - commitRoot( + completeRoot( forceSync, yieldEndTime, lanes, @@ -18922,6 +18882,7 @@ workInProgressDeferredLane, workInProgressRootInterleavedUpdatedLanes, workInProgressSuspendedRetryLanes, + workInProgressRootDidSkipSuspendedSiblings, startTime, null, null, @@ -18946,7 +18907,7 @@ if (0 !== getNextLanes(forceSync, 0, !0)) break a; pendingEffectsLanes = lanes; forceSync.timeoutHandle = scheduleTimeout( - commitRootWhenReady.bind( + completeRootWhenReady.bind( null, forceSync, yieldEndTime, @@ -18967,7 +18928,7 @@ ); break a; } - commitRootWhenReady( + completeRootWhenReady( forceSync, yieldEndTime, workInProgressRootRecoverableErrors, @@ -18990,7 +18951,7 @@ } while (1); ensureRootIsScheduled(root); } - function commitRootWhenReady( + function completeRootWhenReady( root, finishedWork, recoverableErrors, @@ -19016,23 +18977,26 @@ subtreeFlags & 8192 || 16785408 === (subtreeFlags & 16785408) || isGestureTransition - ) + ) { + suspendedState = { + stylesheets: null, + count: 0, + imgCount: 0, + imgBytes: 0, + suspenseyImages: [], + waitingForImages: !0, + waitingForViewTransition: !1, + unsuspend: noop$1 + }; + appearingViewTransitions = null; + accumulateSuspenseyCommitOnFiber(finishedWork, lanes, suspendedState); if ( - ((suspendedState = { - stylesheets: null, - count: 0, - imgCount: 0, - imgBytes: 0, - suspenseyImages: [], - waitingForImages: !0, - waitingForViewTransition: !1, - unsuspend: noop$1 - }), - (appearingViewTransitions = null), - accumulateSuspenseyCommitOnFiber(finishedWork, lanes, suspendedState), - (isViewTransitionEligible || isGestureTransition) && - null === root.stoppingGestures && - ((subtreeFlags = suspendedState), + isViewTransitionEligible || + (isGestureTransition && + null !== root.pendingGestures && + null === root.pendingGestures.running) + ) + (subtreeFlags = suspendedState), (isViewTransitionEligible = root.containerInfo), (isViewTransitionEligible = ( 9 === isViewTransitionEligible.nodeType @@ -19046,19 +19010,18 @@ isViewTransitionEligible.finished.then( subtreeFlags, subtreeFlags - ))), - (subtreeFlags = - (lanes & 62914560) === lanes - ? globalMostRecentFallbackTime - now$1() - : (lanes & 4194048) === lanes - ? globalMostRecentTransitionTime - now$1() - : 0), - (subtreeFlags = waitForCommitToBeReady(suspendedState, subtreeFlags)), - null !== subtreeFlags) - ) { + )); + subtreeFlags = + (lanes & 62914560) === lanes + ? globalMostRecentFallbackTime - now$1() + : (lanes & 4194048) === lanes + ? globalMostRecentTransitionTime - now$1() + : 0; + subtreeFlags = waitForCommitToBeReady(suspendedState, subtreeFlags); + if (null !== subtreeFlags) { pendingEffectsLanes = lanes; root.cancelPendingCommit = subtreeFlags( - commitRoot.bind( + completeRoot.bind( null, root, finishedWork, @@ -19069,6 +19032,7 @@ spawnedLane, updatedLanes, suspendedRetryLanes, + didSkipSuspendedSiblings, exitStatus, suspendedState, suspendedState.waitingForViewTransition @@ -19094,7 +19058,8 @@ ); return; } - commitRoot( + } + completeRoot( root, finishedWork, lanes, @@ -19104,6 +19069,7 @@ spawnedLane, updatedLanes, suspendedRetryLanes, + didSkipSuspendedSiblings, exitStatus, suspendedState, suspendedCommitReason, @@ -20085,6 +20051,14 @@ break; case 5: resetHooksOnUnwind(unitOfWork); + var fiber = unitOfWork; + fiber === hydrationParentFiber && + (isHydrating + ? (popToNextHostParent(fiber), + 5 === fiber.tag && + null != fiber.stateNode && + (nextHydratableInstance = fiber.stateNode)) + : (popToNextHostParent(fiber), (isHydrating = !0))); default: unwindInterruptedWork(current, unitOfWork), (unitOfWork = workInProgress = @@ -20223,7 +20197,7 @@ workInProgressRootExitStatus = RootSuspendedAtTheShell; workInProgress = null; } - function commitRoot( + function completeRoot( root, finishedWork, lanes, @@ -20233,6 +20207,7 @@ spawnedLane, updatedLanes, suspendedRetryLanes, + didSkipSuspendedSiblings, exitStatus, suspendedState, suspendedCommitReason, @@ -20247,33 +20222,96 @@ if ((executionContext & (RenderContext | CommitContext)) !== NoContext) throw Error("Should not already be working."); setCurrentTrackFromLanes(lanes); - exitStatus === RootErrored - ? logErroredRenderPhase( - completedRenderStartTime, - completedRenderEndTime, - lanes, - workInProgressUpdateTask - ) - : null !== recoverableErrors - ? logRecoveredRenderPhase( - completedRenderStartTime, - completedRenderEndTime, - lanes, - recoverableErrors, - null !== finishedWork && - null !== finishedWork.alternate && - finishedWork.alternate.memoizedState.isDehydrated && - 0 !== (finishedWork.flags & 256), - workInProgressUpdateTask - ) - : logRenderPhase( - completedRenderStartTime, - completedRenderEndTime, - lanes, - workInProgressUpdateTask - ); - if (null === finishedWork) - null !== root.stoppingGestures && stopCompletedGestures(root); + 64 === lanes && + (completedRenderStartTime < gestureClampTime && + (completedRenderStartTime = gestureClampTime), + completedRenderEndTime < gestureClampTime && + (completedRenderEndTime = gestureClampTime)); + if (exitStatus === RootErrored) + logErroredRenderPhase( + completedRenderStartTime, + completedRenderEndTime, + lanes, + workInProgressUpdateTask + ); + else if (null !== recoverableErrors) { + var startTime = completedRenderStartTime, + endTime = completedRenderEndTime, + hydrationFailed = + null !== finishedWork && + null !== finishedWork.alternate && + finishedWork.alternate.memoizedState.isDehydrated && + 0 !== (finishedWork.flags & 256), + debugTask = workInProgressUpdateTask; + if (supportsUserTiming && !(endTime <= startTime)) { + for (var properties = [], i = 0; i < recoverableErrors.length; i++) { + var error = recoverableErrors[i].value; + properties.push([ + "Recoverable Error", + "object" === typeof error && + null !== error && + "string" === typeof error.message + ? String(error.message) + : String(error) + ]); + } + startTime = { + start: startTime, + end: endTime, + detail: { + devtools: { + color: "primary-dark", + track: currentTrack, + trackGroup: LANES_TRACK_GROUP, + tooltipText: hydrationFailed + ? "Hydration Failed" + : "Recovered after Error", + properties: properties + } + } + }; + debugTask + ? debugTask.run( + performance.measure.bind(performance, "Recovered", startTime) + ) + : performance.measure("Recovered", startTime); + performance.clearMeasures("Recovered"); + } + } else + (debugTask = completedRenderStartTime), + (startTime = completedRenderEndTime), + (endTime = workInProgressUpdateTask), + !supportsUserTiming || + startTime <= debugTask || + ((hydrationFailed = + (lanes & 738197653) === lanes ? "tertiary-dark" : "primary-dark"), + (properties = + (lanes & 536870912) === lanes + ? "Prepared" + : (lanes & 201326741) === lanes + ? "Hydrated" + : "Render"), + endTime + ? endTime.run( + console.timeStamp.bind( + console, + properties, + debugTask, + startTime, + currentTrack, + LANES_TRACK_GROUP, + hydrationFailed + ) + ) + : console.timeStamp( + properties, + debugTask, + startTime, + currentTrack, + LANES_TRACK_GROUP, + hydrationFailed + )); + if (null === finishedWork) 64 === lanes && stopCommittedGesture(root); else { 0 === lanes && console.error( @@ -20283,119 +20321,330 @@ throw Error( "Cannot commit the same tree as before. This error is likely caused by a bug in React. Please file an issue." ); - didIncludeRenderPhaseUpdate = - finishedWork.lanes | finishedWork.childLanes; - didIncludeRenderPhaseUpdate |= concurrentlyUpdatedLanes; - null === root.pendingGestures && - (0 !== (didIncludeRenderPhaseUpdate & 64) && - ((gestureUpdateTime = -1.1), - (gestureUpdateType = 0), - (gestureSuspendedTime = -1.1), - (gestureEventRepeatTime = gestureEventTime), - (gestureEventTime = -1.1)), - (didIncludeRenderPhaseUpdate &= -65)); - markRootFinished( - root, - lanes, - didIncludeRenderPhaseUpdate, - spawnedLane, - updatedLanes, - suspendedRetryLanes - ); root === workInProgressRoot && ((workInProgress = workInProgressRoot = null), (workInProgressRootRenderLanes = 0)); pendingFinishedWork = finishedWork; pendingEffectsRoot = root; pendingEffectsLanes = lanes; - pendingEffectsRemainingLanes = didIncludeRenderPhaseUpdate; pendingPassiveTransitions = transitions; pendingRecoverableErrors = recoverableErrors; pendingEffectsRenderEndTime = completedRenderEndTime; pendingSuspendedCommitReason = suspendedCommitReason; pendingDelayedCommitReason = IMMEDIATE_COMMIT; pendingSuspendedViewTransitionReason = null; - if (64 === lanes) - commitGestureOnRoot( + if ( + 64 === lanes && + ((debugTask = root.pendingGestures), + null !== debugTask && !debugTask.committing) + ) { + markRootSuspended( root, - finishedWork, - recoverableErrors, - suspendedState + lanes, + spawnedLane, + !didSkipSuspendedSiblings ); - else { - pendingViewTransitionEvents = null; - (lanes & 335544064) === lanes - ? ((pendingTransitionTypes = claimQueuedTransitionTypes(root)), - (recoverableErrors = 10262)) - : ((pendingTransitionTypes = null), (recoverableErrors = 10256)); - 0 !== finishedWork.actualDuration || - 0 !== (finishedWork.subtreeFlags & recoverableErrors) || - 0 !== (finishedWork.flags & recoverableErrors) - ? ((root.callbackNode = null), - (root.callbackPriority = 0), - scheduleCallback$1(NormalPriority$1, function () { - schedulerEvent = window.event; - pendingDelayedCommitReason === IMMEDIATE_COMMIT && - (pendingDelayedCommitReason = DELAYED_PASSIVE_COMMIT); - flushPassiveEffects(); - return null; - })) - : ((root.callbackNode = null), (root.callbackPriority = 0)); - commitErrors = null; - commitStartTime = now(); - null !== suspendedCommitReason && - logSuspendedCommitPhase( - completedRenderEndTime, - commitStartTime, - suspendedCommitReason, - workInProgressUpdateTask - ); - shouldStartViewTransition = !1; - suspendedCommitReason = 0 !== (finishedWork.flags & 13878); - if ( - 0 !== (finishedWork.subtreeFlags & 13878) || - suspendedCommitReason - ) { - suspendedCommitReason = ReactSharedInternals.T; - ReactSharedInternals.T = null; - completedRenderEndTime = ReactDOMSharedInternals.p; - ReactDOMSharedInternals.p = DiscreteEventPriority; - recoverableErrors = executionContext; - executionContext |= CommitContext; - try { - commitBeforeMutationEffects(root, finishedWork, lanes); - } finally { - (executionContext = recoverableErrors), - (ReactDOMSharedInternals.p = completedRenderEndTime), - (ReactSharedInternals.T = suspendedCommitReason); + if (null === debugTask.running) + if ( + ((suspendedCommitReason = root.pendingGestures), + null === suspendedCommitReason) + ) + ensureRootIsScheduled(root); + else { + animatingLanes |= pendingEffectsLanes; + animatingTask = null; + startTime = ReactSharedInternals.T; + ReactSharedInternals.T = null; + endTime = ReactDOMSharedInternals.p; + ReactDOMSharedInternals.p = DiscreteEventPriority; + hydrationFailed = executionContext; + executionContext |= CommitContext; + try { + didWarnForRootClone || + ((didWarnForRootClone = !0), + console.warn( + "startGestureTransition() caused something to mutate or relayout the root. This currently requires a clone of the whole document. Make sure to add a directly around an absolutely positioned DOM node to minimize the impact of any changes caused by the Gesture Transition." + )); + var rootContainer = root.containerInfo, + documentElement = + 9 === rootContainer.nodeType + ? rootContainer.documentElement + : rootContainer.ownerDocument.documentElement; + null !== documentElement && + "" === documentElement.style.viewTransitionName && + (documentElement.style.viewTransitionName = "none"); + var containerInstance = + 9 === rootContainer.nodeType + ? rootContainer.body + : "HTML" === rootContainer.nodeName + ? rootContainer.ownerDocument.body + : rootContainer; + var containerParent = containerInstance.parentNode; + if (null === containerParent) + throw Error( + "Cannot use a startGestureTransition() on a detached root." + ); + var clone = containerInstance.cloneNode(!1), + computedStyle = getComputedStyle(containerInstance); + if ( + "absolute" !== computedStyle.position && + "fixed" !== computedStyle.position + ) { + for ( + rootContainer = containerParent; + null != rootContainer.parentNode && + 9 !== rootContainer.parentNode.nodeType && + "static" === getComputedStyle(rootContainer).position; + + ) + rootContainer = rootContainer.parentNode; + var positionedAncestorStyle = rootContainer.style, + containerInstanceStyle = containerInstance.style, + prevAncestorTranslate = positionedAncestorStyle.translate, + prevAncestorScale = positionedAncestorStyle.scale, + prevAncestorRotate = positionedAncestorStyle.rotate, + prevAncestorTransform = positionedAncestorStyle.transform, + prevTranslate = containerInstanceStyle.translate, + prevScale = containerInstanceStyle.scale, + prevRotate = containerInstanceStyle.rotate, + prevTransform = containerInstanceStyle.transform; + positionedAncestorStyle.translate = "none"; + positionedAncestorStyle.scale = "none"; + positionedAncestorStyle.rotate = "none"; + positionedAncestorStyle.transform = "none"; + containerInstanceStyle.translate = "none"; + containerInstanceStyle.scale = "none"; + containerInstanceStyle.rotate = "none"; + containerInstanceStyle.transform = "none"; + var ancestorRect = rootContainer.getBoundingClientRect(), + rect = containerInstance.getBoundingClientRect(), + cloneStyle = clone.style; + cloneStyle.position = "absolute"; + cloneStyle.top = rect.top - ancestorRect.top + "px"; + cloneStyle.left = rect.left - ancestorRect.left + "px"; + cloneStyle.width = rect.width + "px"; + cloneStyle.height = rect.height + "px"; + cloneStyle.margin = "0px"; + cloneStyle.boxSizing = "border-box"; + positionedAncestorStyle.translate = prevAncestorTranslate; + positionedAncestorStyle.scale = prevAncestorScale; + positionedAncestorStyle.rotate = prevAncestorRotate; + positionedAncestorStyle.transform = prevAncestorTransform; + containerInstanceStyle.translate = prevTranslate; + containerInstanceStyle.scale = prevScale; + containerInstanceStyle.rotate = prevRotate; + containerInstanceStyle.transform = prevTransform; + } + clone.style.viewTransitionName = "root"; + var transform = computedStyle.transform; + "none" === transform && (transform = ""); + var scale = computedStyle.scale; + if ("none" !== scale && "" !== scale) { + var parts = scale.split(" "); + transform = + (3 === parts.length ? "scale3d" : "scale") + + "(" + + parts.join(", ") + + ") " + + transform; + } + var rotate = computedStyle.rotate; + if ("none" !== rotate && "" !== rotate) { + var _parts = rotate.split(" "); + transform = + 1 === _parts.length + ? "rotate(" + _parts[0] + ") " + transform + : 2 === _parts.length + ? "rotate" + + _parts[0].toUpperCase() + + "(" + + _parts[1] + + ") " + + transform + : "rotate3d(" + _parts.join(", ") + ") " + transform; + } + var translate = computedStyle.translate; + if ("none" !== translate && "" !== translate) { + var _parts2 = translate.split(" "); + transform = + (3 === _parts2.length ? "translate3d" : "translate") + + "(" + + _parts2.join(", ") + + ") " + + transform; + } + var transform$jscomp$0 = transform; + clone.style.translate = "none"; + clone.style.scale = "none"; + clone.style.rotate = "none"; + clone.style.transform = + "translate(-20000px, -20000px) " + transform$jscomp$0; + containerInstance.parentNode.insertBefore( + clone, + containerInstance.nextSibling + ); + root.gestureClone = clone; + recursivelyInsertClones( + finishedWork, + clone, + null, + CLONE_UPDATE + ); + } finally { + (executionContext = hydrationFailed), + (ReactDOMSharedInternals.p = endTime), + (ReactSharedInternals.T = startTime); + } + pendingTransitionTypes = suspendedCommitReason.types; + pendingEffectsStatus = PENDING_GESTURE_MUTATION_PHASE; + pendingViewTransition = suspendedCommitReason.running = + startGestureTransition( + suspendedState, + root.containerInfo, + suspendedCommitReason.provider, + suspendedCommitReason.rangeStart, + suspendedCommitReason.rangeEnd, + pendingTransitionTypes, + flushGestureMutations, + flushGestureAnimations, + reportViewTransitionError, + finishedViewTransition.bind(null, pendingEffectsLanes) + ); } - } - finishedWork = shouldStartViewTransition; - null !== root.stoppingGestures && - (stopCompletedGestures(root), (finishedWork = !1)); - pendingEffectsStatus = PENDING_MUTATION_PHASE; - finishedWork - ? ((animatingLanes |= lanes), - (animatingTask = null), - (pendingViewTransition = startViewTransition( - suspendedState, - root.containerInfo, - pendingTransitionTypes, - flushMutationEffects, - flushLayoutEffects, - flushAfterMutationEffects, - flushSpawnedWork, - flushPassiveEffects, - reportViewTransitionError, - suspendedViewTransition, - finishedViewTransition.bind(null, lanes) - ))) - : (flushMutationEffects(), - flushLayoutEffects(), - flushSpawnedWork()); + else + finalizeRender(lanes, completedRenderEndTime), + (pendingFinishedWork = pendingEffectsRoot = null), + (pendingEffectsLanes = 0); + root.cancelPendingCommit = scheduleGestureCommit( + debugTask, + completeRoot.bind( + null, + root, + finishedWork, + lanes, + recoverableErrors, + transitions, + didIncludeRenderPhaseUpdate, + spawnedLane, + updatedLanes, + suspendedRetryLanes, + didSkipSuspendedSiblings, + exitStatus, + suspendedState, + "Waiting for the Gesture to finish", + completedRenderStartTime, + completedRenderEndTime + ) + ); + return; } + commitRoot( + root, + finishedWork, + lanes, + spawnedLane, + updatedLanes, + suspendedRetryLanes, + suspendedState, + suspendedCommitReason, + completedRenderEndTime + ); } } + function commitRoot( + root, + finishedWork, + lanes, + spawnedLane, + updatedLanes, + suspendedRetryLanes, + suspendedState, + suspendedCommitReason, + completedRenderEndTime + ) { + var remainingLanes = finishedWork.lanes | finishedWork.childLanes; + pendingEffectsRemainingLanes = remainingLanes; + remainingLanes |= concurrentlyUpdatedLanes; + null === root.pendingGestures && + (0 !== (remainingLanes & 64) && + ((gestureUpdateTime = -1.1), + (gestureUpdateType = 0), + (gestureSuspendedTime = -1.1), + (gestureEventRepeatTime = gestureEventTime), + (gestureEventTime = -1.1)), + (remainingLanes &= -65)); + markRootFinished( + root, + lanes, + remainingLanes, + spawnedLane, + updatedLanes, + suspendedRetryLanes + ); + pendingViewTransitionEvents = null; + (lanes & 335544064) === lanes + ? ((pendingTransitionTypes = claimQueuedTransitionTypes(root)), + (spawnedLane = 10262)) + : ((pendingTransitionTypes = null), (spawnedLane = 10256)); + 0 !== finishedWork.actualDuration || + 0 !== (finishedWork.subtreeFlags & spawnedLane) || + 0 !== (finishedWork.flags & spawnedLane) + ? ((root.callbackNode = null), + (root.callbackPriority = 0), + scheduleCallback$1(NormalPriority$1, function () { + schedulerEvent = window.event; + pendingDelayedCommitReason === IMMEDIATE_COMMIT && + (pendingDelayedCommitReason = DELAYED_PASSIVE_COMMIT); + flushPassiveEffects(); + return null; + })) + : ((root.callbackNode = null), (root.callbackPriority = 0)); + commitErrors = null; + commitStartTime = now(); + null !== suspendedCommitReason && + logSuspendedCommitPhase( + completedRenderEndTime, + commitStartTime, + suspendedCommitReason, + workInProgressUpdateTask + ); + shouldStartViewTransition = !1; + suspendedCommitReason = 0 !== (finishedWork.flags & 13878); + if (0 !== (finishedWork.subtreeFlags & 13878) || suspendedCommitReason) { + suspendedCommitReason = ReactSharedInternals.T; + ReactSharedInternals.T = null; + completedRenderEndTime = ReactDOMSharedInternals.p; + ReactDOMSharedInternals.p = DiscreteEventPriority; + spawnedLane = executionContext; + executionContext |= CommitContext; + try { + commitBeforeMutationEffects(root, finishedWork, lanes); + } finally { + (executionContext = spawnedLane), + (ReactDOMSharedInternals.p = completedRenderEndTime), + (ReactSharedInternals.T = suspendedCommitReason); + } + } + 64 === lanes && stopCommittedGesture(root); + pendingEffectsStatus = PENDING_MUTATION_PHASE; + shouldStartViewTransition + ? ((animatingLanes |= lanes), + (animatingTask = null), + (pendingViewTransition = startViewTransition( + suspendedState, + root.containerInfo, + pendingTransitionTypes, + flushMutationEffects, + flushLayoutEffects, + flushAfterMutationEffects, + flushSpawnedWork, + flushPassiveEffects, + reportViewTransitionError, + suspendedViewTransition, + finishedViewTransition.bind(null, lanes) + ))) + : (flushMutationEffects(), flushLayoutEffects(), flushSpawnedWork()); + } function reportViewTransitionError(error) { if (pendingEffectsStatus !== NO_PENDING_EFFECTS) { var onRecoverableError = pendingEffectsRoot.onRecoverableError; @@ -20855,172 +21104,6 @@ flushSyncWorkAcrossRoots_impl(0, !1); } } - function commitGestureOnRoot( - root, - finishedWork, - recoverableErrors, - suspendedState - ) { - recoverableErrors = root.pendingGestures; - if (null === recoverableErrors) ensureRootIsScheduled(root); - else { - deleteScheduledGesture(root, recoverableErrors); - animatingLanes |= pendingEffectsLanes; - animatingTask = null; - var prevTransition = ReactSharedInternals.T; - ReactSharedInternals.T = null; - var previousPriority = ReactDOMSharedInternals.p; - ReactDOMSharedInternals.p = DiscreteEventPriority; - var prevExecutionContext = executionContext; - executionContext |= CommitContext; - try { - didWarnForRootClone || - ((didWarnForRootClone = !0), - console.warn( - "startGestureTransition() caused something to mutate or relayout the root. This currently requires a clone of the whole document. Make sure to add a directly around an absolutely positioned DOM node to minimize the impact of any changes caused by the Gesture Transition." - )); - var rootContainer = root.containerInfo, - documentElement = - 9 === rootContainer.nodeType - ? rootContainer.documentElement - : rootContainer.ownerDocument.documentElement; - null !== documentElement && - "" === documentElement.style.viewTransitionName && - (documentElement.style.viewTransitionName = "none"); - var containerInstance = - 9 === rootContainer.nodeType - ? rootContainer.body - : "HTML" === rootContainer.nodeName - ? rootContainer.ownerDocument.body - : rootContainer; - var containerParent = containerInstance.parentNode; - if (null === containerParent) - throw Error( - "Cannot use a startGestureTransition() on a detached root." - ); - var clone = containerInstance.cloneNode(!1), - computedStyle = getComputedStyle(containerInstance); - if ( - "absolute" !== computedStyle.position && - "fixed" !== computedStyle.position - ) { - for ( - rootContainer = containerParent; - null != rootContainer.parentNode && - 9 !== rootContainer.parentNode.nodeType && - "static" === getComputedStyle(rootContainer).position; - - ) - rootContainer = rootContainer.parentNode; - var positionedAncestorStyle = rootContainer.style, - containerInstanceStyle = containerInstance.style, - prevAncestorTranslate = positionedAncestorStyle.translate, - prevAncestorScale = positionedAncestorStyle.scale, - prevAncestorRotate = positionedAncestorStyle.rotate, - prevAncestorTransform = positionedAncestorStyle.transform, - prevTranslate = containerInstanceStyle.translate, - prevScale = containerInstanceStyle.scale, - prevRotate = containerInstanceStyle.rotate, - prevTransform = containerInstanceStyle.transform; - positionedAncestorStyle.translate = "none"; - positionedAncestorStyle.scale = "none"; - positionedAncestorStyle.rotate = "none"; - positionedAncestorStyle.transform = "none"; - containerInstanceStyle.translate = "none"; - containerInstanceStyle.scale = "none"; - containerInstanceStyle.rotate = "none"; - containerInstanceStyle.transform = "none"; - var ancestorRect = rootContainer.getBoundingClientRect(), - rect = containerInstance.getBoundingClientRect(), - cloneStyle = clone.style; - cloneStyle.position = "absolute"; - cloneStyle.top = rect.top - ancestorRect.top + "px"; - cloneStyle.left = rect.left - ancestorRect.left + "px"; - cloneStyle.width = rect.width + "px"; - cloneStyle.height = rect.height + "px"; - cloneStyle.margin = "0px"; - cloneStyle.boxSizing = "border-box"; - positionedAncestorStyle.translate = prevAncestorTranslate; - positionedAncestorStyle.scale = prevAncestorScale; - positionedAncestorStyle.rotate = prevAncestorRotate; - positionedAncestorStyle.transform = prevAncestorTransform; - containerInstanceStyle.translate = prevTranslate; - containerInstanceStyle.scale = prevScale; - containerInstanceStyle.rotate = prevRotate; - containerInstanceStyle.transform = prevTransform; - } - clone.style.viewTransitionName = "root"; - var transform = computedStyle.transform; - "none" === transform && (transform = ""); - var scale = computedStyle.scale; - if ("none" !== scale && "" !== scale) { - var parts = scale.split(" "); - transform = - (3 === parts.length ? "scale3d" : "scale") + - "(" + - parts.join(", ") + - ") " + - transform; - } - var rotate = computedStyle.rotate; - if ("none" !== rotate && "" !== rotate) { - var _parts = rotate.split(" "); - transform = - 1 === _parts.length - ? "rotate(" + _parts[0] + ") " + transform - : 2 === _parts.length - ? "rotate" + - _parts[0].toUpperCase() + - "(" + - _parts[1] + - ") " + - transform - : "rotate3d(" + _parts.join(", ") + ") " + transform; - } - var translate = computedStyle.translate; - if ("none" !== translate && "" !== translate) { - var _parts2 = translate.split(" "); - transform = - (3 === _parts2.length ? "translate3d" : "translate") + - "(" + - _parts2.join(", ") + - ") " + - transform; - } - var transform$jscomp$0 = transform; - clone.style.translate = "none"; - clone.style.scale = "none"; - clone.style.rotate = "none"; - clone.style.transform = - "translate(-20000px, -20000px) " + transform$jscomp$0; - containerInstance.parentNode.insertBefore( - clone, - containerInstance.nextSibling - ); - root.gestureClone = clone; - recursivelyInsertClones(finishedWork, clone, null, CLONE_UPDATE); - } finally { - (executionContext = prevExecutionContext), - (ReactDOMSharedInternals.p = previousPriority), - (ReactSharedInternals.T = prevTransition); - } - pendingTransitionTypes = recoverableErrors.types; - pendingEffectsStatus = PENDING_GESTURE_MUTATION_PHASE; - pendingViewTransition = recoverableErrors.running = - startGestureTransition( - suspendedState, - root.containerInfo, - recoverableErrors.provider, - recoverableErrors.rangeStart, - recoverableErrors.rangeEnd, - pendingTransitionTypes, - flushGestureMutations, - flushGestureAnimations, - reportViewTransitionError, - finishedViewTransition.bind(null, pendingEffectsLanes) - ); - } - } function flushGestureMutations() { if (pendingEffectsStatus === PENDING_GESTURE_MUTATION_PHASE) { pendingEffectsStatus = NO_PENDING_EFFECTS; @@ -21076,16 +21159,42 @@ (ReactDOMSharedInternals.p = previousPriority), (ReactSharedInternals.T = prevTransition); } + commitEndTime = now(); + root = pendingEffectsRenderEndTime; + prevTransition = commitEndTime; + !supportsUserTiming || + prevTransition <= root || + (animatingTask + ? animatingTask.run( + console.timeStamp.bind( + console, + "Create Ghost Tree", + root, + prevTransition, + currentTrack, + LANES_TRACK_GROUP, + "secondary-dark" + ) + ) + : console.timeStamp( + "Create Ghost Tree", + root, + prevTransition, + currentTrack, + LANES_TRACK_GROUP, + "secondary-dark" + )); pendingEffectsStatus = PENDING_GESTURE_ANIMATION_PHASE; } } function flushGestureAnimations() { flushGestureMutations(); if (pendingEffectsStatus === PENDING_GESTURE_ANIMATION_PHASE) { - var lanes = pendingEffectsLanes; + var lanes = pendingEffectsLanes, + startViewTransitionStartTime = commitEndTime; commitEndTime = now(); logStartViewTransitionYieldPhase( - pendingEffectsRenderEndTime, + startViewTransitionStartTime, commitEndTime, pendingDelayedCommitReason === ABORTED_VIEW_TRANSITION_COMMIT, animatingTask @@ -21093,8 +21202,8 @@ pendingDelayedCommitReason !== ABORTED_VIEW_TRANSITION_COMMIT && (pendingDelayedCommitReason = ANIMATION_STARTED_COMMIT); pendingEffectsStatus = NO_PENDING_EFFECTS; - var root = pendingEffectsRoot, - finishedWork = pendingFinishedWork; + startViewTransitionStartTime = pendingEffectsRoot; + var finishedWork = pendingFinishedWork; pendingFinishedWork = pendingEffectsRoot = null; pendingEffectsLanes = 0; pendingViewTransition = null; @@ -21106,14 +21215,16 @@ executionContext |= CommitContext; try { restoreViewTransitionsOnFiber(finishedWork), - restoreRootViewTransitionName(root.containerInfo); + restoreRootViewTransitionName( + startViewTransitionStartTime.containerInfo + ); } finally { (executionContext = prevExecutionContext), (ReactDOMSharedInternals.p = previousPriority), (ReactSharedInternals.T = prevTransition); } finalizeRender(lanes, commitEndTime); - ensureRootIsScheduled(root); + ensureRootIsScheduled(startViewTransitionStartTime); } } function makeErrorInfo(componentStack) { @@ -21376,8 +21487,7 @@ function pingSuspendedRoot(root, wakeable, pingedLanes) { var pingCache = root.pingCache; null !== pingCache && pingCache.delete(wakeable); - root.pingedLanes |= root.suspendedLanes & pingedLanes; - root.warmLanes &= ~pingedLanes; + markRootPinged$1(root, pingedLanes); 64 === pingedLanes ? 0 > gestureUpdateTime && ((gestureClampTime = gestureUpdateTime = now()), @@ -26151,6 +26261,14 @@ new: new ViewTransitionPseudoElement("new", name) }; } + function getCurrentGestureOffset(timeline) { + timeline = timeline.currentTime; + if (null === timeline) + throw Error( + "Cannot start a gesture with a disconnected AnimationTimeline." + ); + return "number" === typeof timeline ? timeline : timeline.value; + } function FragmentInstance(fragmentFiber) { this._fragmentFiber = fragmentFiber; this._observers = this._eventListeners = null; @@ -27492,11 +27610,7 @@ this.pooledCache = this.pendingIndicator = null; this.pooledCacheLanes = 0; this.formState = formState; - this.gestureClone = - this.stoppingGestures = - this.pendingGestures = - this.transitionTypes = - null; + this.gestureClone = this.pendingGestures = this.transitionTypes = null; this.incompleteTransitions = new Map(); this.passiveEffectDuration = this.effectDuration = -0; this.memoizedUpdaters = new Set(); @@ -32448,11 +32562,11 @@ }; (function () { var isomorphicReactPackageVersion = React.version; - if ("19.3.0-experimental-65eec428-20251218" !== isomorphicReactPackageVersion) + if ("19.3.0-experimental-bef88f7c-20260116" !== isomorphicReactPackageVersion) throw Error( 'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' + (isomorphicReactPackageVersion + - "\n - react-dom: 19.3.0-experimental-65eec428-20251218\nLearn more: https://react.dev/warnings/version-mismatch") + "\n - react-dom: 19.3.0-experimental-bef88f7c-20260116\nLearn more: https://react.dev/warnings/version-mismatch") ); })(); ("function" === typeof Map && @@ -32489,10 +32603,10 @@ !(function () { var internals = { bundleType: 1, - version: "19.3.0-experimental-65eec428-20251218", + version: "19.3.0-experimental-bef88f7c-20260116", rendererPackageName: "react-dom", currentDispatcherRef: ReactSharedInternals, - reconcilerVersion: "19.3.0-experimental-65eec428-20251218" + reconcilerVersion: "19.3.0-experimental-bef88f7c-20260116" }; internals.overrideHookState = overrideHookState; internals.overrideHookStateDeletePath = overrideHookStateDeletePath; @@ -32640,7 +32754,7 @@ listenToAllSupportedEvents(container); return new ReactDOMHydrationRoot(initialChildren); }; - exports.version = "19.3.0-experimental-65eec428-20251218"; + exports.version = "19.3.0-experimental-bef88f7c-20260116"; "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-client.production.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-client.production.js index 62641e69260b..9dbfbde6039b 100644 --- a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-client.production.js +++ b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-client.production.js @@ -822,6 +822,10 @@ function markRootUpdated$1(root, updateLane) { 268435456 !== updateLane && ((root.suspendedLanes = 0), (root.pingedLanes = 0), (root.warmLanes = 0)); } +function markRootPinged$1(root, pingedLanes) { + root.pingedLanes |= root.suspendedLanes & pingedLanes; + root.warmLanes &= ~pingedLanes; +} function markRootFinished( root, finishedLanes, @@ -2582,7 +2586,7 @@ function createWorkInProgress(current, pendingProps) { (workInProgress.subtreeFlags = 0), (workInProgress.deletions = null), (workInProgress.key = current.key)); - workInProgress.flags = current.flags & 132120576; + workInProgress.flags = current.flags & 133169152; workInProgress.childLanes = current.childLanes; workInProgress.lanes = current.lanes; workInProgress.child = current.child; @@ -2601,7 +2605,7 @@ function createWorkInProgress(current, pendingProps) { return workInProgress; } function resetWorkInProgress(workInProgress, renderLanes) { - workInProgress.flags &= 132120578; + workInProgress.flags &= 133169154; var current = workInProgress.alternate; null === current ? ((workInProgress.childLanes = 0), @@ -3331,36 +3335,30 @@ function startScheduledGesture( gestureOptions, transitionTypes ) { - if (gestureOptions && null != gestureOptions.rangeStart) - var JSCompiler_temp = gestureOptions.rangeStart; - else { - JSCompiler_temp = gestureTimeline.currentTime; - if (null === JSCompiler_temp) throw Error(formatProdErrorMessage(549)); - JSCompiler_temp = - "number" === typeof JSCompiler_temp - ? JSCompiler_temp - : JSCompiler_temp.value; - } + var rangeStart = + gestureOptions && null != gestureOptions.rangeStart + ? gestureOptions.rangeStart + : getCurrentGestureOffset(gestureTimeline); gestureOptions = gestureOptions && null != gestureOptions.rangeEnd ? gestureOptions.rangeEnd - : 50 > JSCompiler_temp + : 50 > rangeStart ? 100 : 0; for (root = root.pendingGestures; null !== root; ) { if (root.provider === gestureTimeline) { root.count++; - root.rangeStart = JSCompiler_temp; + root.rangeStart = rangeStart; root.rangeEnd = gestureOptions; if (null !== transitionTypes) for ( gestureTimeline = root.types, null === gestureTimeline && (gestureTimeline = root.types = []), - JSCompiler_temp = 0; - JSCompiler_temp < transitionTypes.length; - JSCompiler_temp++ + rangeStart = 0; + rangeStart < transitionTypes.length; + rangeStart++ ) - (gestureOptions = transitionTypes[JSCompiler_temp]), + (gestureOptions = transitionTypes[rangeStart]), -1 === gestureTimeline.indexOf(gestureOptions) && gestureTimeline.push(gestureOptions); return root; @@ -3370,27 +3368,24 @@ function startScheduledGesture( } return null; } -function deleteScheduledGesture(root, gesture) { - null === gesture.prev - ? (root.pendingGestures === gesture && - ((root.pendingGestures = gesture.next), - null === root.pendingGestures && (root.pendingLanes &= -65)), - root.stoppingGestures === gesture && - (root.stoppingGestures = gesture.next)) - : ((gesture.prev.next = gesture.next), - null !== gesture.next && (gesture.next.prev = gesture.prev), - (gesture.prev = null), - (gesture.next = null)); -} -function stopCompletedGestures(root) { - var gesture = root.stoppingGestures; - for (root.stoppingGestures = null; null !== gesture; ) - null !== gesture.running && - (gesture.running.skipTransition(), (gesture.running = null)), - (root = gesture.next), - (gesture.next = null), - (gesture.prev = null), - (gesture = root); +function stopCommittedGesture(root) { + var committedGesture = root.pendingGestures; + if (null !== committedGesture) { + committedGesture.committing = !1; + var nextGesture = committedGesture.next; + null === nextGesture + ? (root.pendingLanes &= -65) + : (nextGesture.prev = null); + root.pendingGestures = nextGesture; + root = committedGesture.running; + null !== root && ((committedGesture.running = null), root.skipTransition()); + } +} +function scheduleGestureCommit(gesture, callback) { + gesture.commit = callback; + return function () { + gesture.commit = null; + }; } var prevOnStartTransitionFinish = ReactSharedInternals.S; ReactSharedInternals.S = function (transition, returnValue) { @@ -3421,23 +3416,52 @@ ReactSharedInternals.S = function (transition, returnValue) { }; function chainGestureCancellation(root, scheduledGesture, prevCancel) { return function () { - if ( - null !== scheduledGesture && - (scheduledGesture.count--, 0 === scheduledGesture.count) - ) { - deleteScheduledGesture(root, scheduledGesture); - var runningTransition = scheduledGesture.running; - if (null !== runningTransition) { - var pendingLanesExcludingGestureLane = root.pendingLanes & -65; - 0 !== (pendingLanesExcludingGestureLane & 127) || - 0 !== (pendingLanesExcludingGestureLane & 4194048) - ? ((runningTransition = root.stoppingGestures), - null !== runningTransition && - ((scheduledGesture.next = runningTransition), - (runningTransition.prev = scheduledGesture)), - (root.stoppingGestures = scheduledGesture)) - : ((scheduledGesture.running = null), - runningTransition.skipTransition()); + if (null !== scheduledGesture) { + if (0 !== scheduledGesture.revertLane) { + var entangledLanes = + scheduledGesture.revertLane | requestTransitionLane(); + markRootEntangled(root, entangledLanes); + } + scheduledGesture.count--; + if (0 === scheduledGesture.count) { + var finalOffset = getCurrentGestureOffset(scheduledGesture.provider), + rangeStart = scheduledGesture.rangeStart, + rangeEnd = scheduledGesture.rangeEnd; + entangledLanes = scheduledGesture.running; + null !== entangledLanes && + (rangeStart < rangeEnd + ? finalOffset > rangeStart + (rangeEnd - rangeStart) / 2 + : finalOffset < rangeEnd + (rangeStart - rangeEnd) / 2) + ? ((scheduledGesture.committing = !0), + root.pendingGestures === scheduledGesture && + ((entangledLanes = scheduledGesture.commit), + null !== entangledLanes + ? ((scheduledGesture.commit = null), entangledLanes()) + : null !== root.pendingGestures && + (markRootPinged$1(root, 64), ensureRootIsScheduled(root)))) + : null === scheduledGesture.prev + ? (root.pendingGestures === scheduledGesture && + ((root.pendingGestures = scheduledGesture.next), + (finalOffset = root.pendingLanes), + null === root.pendingGestures && (finalOffset &= -65), + markRootFinished(root, 64, finalOffset, 0, 0, 0), + workInProgressRoot === root && + 64 === workInProgressRootRenderLanes + ? 0 === (executionContext & 2) && prepareFreshStack(root, 0) + : null !== root.cancelPendingCommit && + 64 === pendingEffectsLanes && + ((finalOffset = root.cancelPendingCommit), + null !== finalOffset && + ((root.cancelPendingCommit = null), finalOffset())), + null !== root.pendingGestures && markRootPinged$1(root, 64), + ensureRootIsScheduled(root)), + (scheduledGesture.running = null), + null !== entangledLanes && entangledLanes.skipTransition()) + : ((scheduledGesture.prev.next = scheduledGesture.next), + null !== scheduledGesture.next && + (scheduledGesture.next.prev = scheduledGesture.prev), + (scheduledGesture.prev = null), + (scheduledGesture.next = null)); } } null !== prevCancel && prevCancel(); @@ -4954,16 +4978,18 @@ function updateReducerImpl(hook, current, reducer) { if (64 === updateLane) { var scheduledGesture = update.gesture; if (null !== scheduledGesture) - if (0 === scheduledGesture.count) { + if (0 !== scheduledGesture.count || scheduledGesture.committing) + if (64 !== renderLanes) shouldSkipUpdate = !0; + else { + shouldSkipUpdate = workInProgressRoot; + if (null === shouldSkipUpdate) + throw Error(formatProdErrorMessage(349)); + shouldSkipUpdate = + shouldSkipUpdate.pendingGestures !== scheduledGesture; + } + else { update = update.next; continue; - } else if (64 !== renderLanes) shouldSkipUpdate = !0; - else { - shouldSkipUpdate = workInProgressRoot; - if (null === shouldSkipUpdate) - throw Error(formatProdErrorMessage(349)); - shouldSkipUpdate = - shouldSkipUpdate.pendingGestures !== scheduledGesture; } } if (shouldSkipUpdate) @@ -5586,7 +5612,7 @@ function updateDeferredValueImpl(hook, prevValue, value, initialValue) { hook ); if ( - 0 === (renderLanes & 42) || + 0 === (renderLanes & 106) || (0 !== (renderLanes & 1073741824) && 0 === (workInProgressRootRenderLanes & 261930)) ) @@ -5852,6 +5878,9 @@ function dispatchOptimisticSetState(fiber, throwIfDuringRender, queue, action) { rangeEnd: 100, types: null, running: null, + commit: null, + committing: !1, + revertLane: 0, prev: fiber, next: null }; @@ -5861,7 +5890,10 @@ function dispatchOptimisticSetState(fiber, throwIfDuringRender, queue, action) { ensureRootIsScheduled(throwIfDuringRender); throwIfDuringRender = transition; } - action.gesture = throwIfDuringRender; + throwIfDuringRender = action.gesture = throwIfDuringRender; + 0 === throwIfDuringRender.revertLane + ? (throwIfDuringRender.revertLane = action.revertLane) + : (action.revertLane = throwIfDuringRender.revertLane); } } function isRenderPhaseUpdate(fiber) { @@ -7486,7 +7518,7 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { mode: "hidden", children: nextProps.children })), - (nextProps.subtreeFlags = nextFallbackChildren.subtreeFlags & 132120576), + (nextProps.subtreeFlags = nextFallbackChildren.subtreeFlags & 133169152), null !== digest ? (nextPrimaryChildren = createWorkInProgress( digest, @@ -8468,8 +8500,8 @@ function bubbleProperties(completedWork) { if (didBailout) for (var child$118 = completedWork.child; null !== child$118; ) (newChildLanes |= child$118.lanes | child$118.childLanes), - (subtreeFlags |= child$118.subtreeFlags & 132120576), - (subtreeFlags |= child$118.flags & 132120576), + (subtreeFlags |= child$118.subtreeFlags & 133169152), + (subtreeFlags |= child$118.flags & 133169152), (child$118.return = completedWork), (child$118 = child$118.sibling); else @@ -9815,7 +9847,9 @@ function measureViewTransitionHostInstancesRecursive( (viewTransitionCancelableChildren = []), viewTransitionCancelableChildren.push( instance, - oldName, + 0 === viewTransitionHostInstanceIdx + ? oldName + : oldName + "_" + viewTransitionHostInstanceIdx, child.memoizedProps )); viewTransitionHostInstanceIdx++; @@ -12809,7 +12843,7 @@ function performWorkOnRoot(root$jscomp$0, lanes, forceSync) { if (0 !== getNextLanes(shouldTimeSlice, 0, !0)) break a; pendingEffectsLanes = lanes; shouldTimeSlice.timeoutHandle = scheduleTimeout( - commitRootWhenReady.bind( + completeRootWhenReady.bind( null, shouldTimeSlice, forceSync, @@ -12830,7 +12864,7 @@ function performWorkOnRoot(root$jscomp$0, lanes, forceSync) { ); break a; } - commitRootWhenReady( + completeRootWhenReady( shouldTimeSlice, forceSync, workInProgressRootRecoverableErrors, @@ -12852,7 +12886,7 @@ function performWorkOnRoot(root$jscomp$0, lanes, forceSync) { } while (1); ensureRootIsScheduled(root$jscomp$0); } -function commitRootWhenReady( +function completeRootWhenReady( root, finishedWork, recoverableErrors, @@ -12871,34 +12905,33 @@ function commitRootWhenReady( root.timeoutHandle = -1; var subtreeFlags = finishedWork.subtreeFlags, isViewTransitionEligible = (lanes & 335544064) === lanes, - isGestureTransition = 64 === lanes; - suspendedCommitReason = null; + isGestureTransition = 64 === lanes, + suspendedState = null; if ( isViewTransitionEligible || subtreeFlags & 8192 || 16785408 === (subtreeFlags & 16785408) || isGestureTransition - ) + ) { + suspendedState = { + stylesheets: null, + count: 0, + imgCount: 0, + imgBytes: 0, + suspenseyImages: [], + waitingForImages: !0, + waitingForViewTransition: !1, + unsuspend: noop$1 + }; + appearingViewTransitions = null; + accumulateSuspenseyCommitOnFiber(finishedWork, lanes, suspendedState); if ( - ((suspendedCommitReason = { - stylesheets: null, - count: 0, - imgCount: 0, - imgBytes: 0, - suspenseyImages: [], - waitingForImages: !0, - waitingForViewTransition: !1, - unsuspend: noop$1 - }), - (appearingViewTransitions = null), - accumulateSuspenseyCommitOnFiber( - finishedWork, - lanes, - suspendedCommitReason - ), - (isViewTransitionEligible || isGestureTransition) && - null === root.stoppingGestures && - ((subtreeFlags = suspendedCommitReason), + isViewTransitionEligible || + (isGestureTransition && + null !== root.pendingGestures && + null === root.pendingGestures.running) + ) + (subtreeFlags = suspendedState), (isViewTransitionEligible = root.containerInfo), (isViewTransitionEligible = ( 9 === isViewTransitionEligible.nodeType @@ -12909,22 +12942,18 @@ function commitRootWhenReady( (subtreeFlags.count++, (subtreeFlags.waitingForViewTransition = !0), (subtreeFlags = onUnsuspend.bind(subtreeFlags)), - isViewTransitionEligible.finished.then(subtreeFlags, subtreeFlags))), - (subtreeFlags = - (lanes & 62914560) === lanes - ? globalMostRecentFallbackTime - now() - : (lanes & 4194048) === lanes - ? globalMostRecentTransitionTime - now() - : 0), - (subtreeFlags = waitForCommitToBeReady( - suspendedCommitReason, - subtreeFlags - )), - null !== subtreeFlags) - ) { + isViewTransitionEligible.finished.then(subtreeFlags, subtreeFlags)); + subtreeFlags = + (lanes & 62914560) === lanes + ? globalMostRecentFallbackTime - now() + : (lanes & 4194048) === lanes + ? globalMostRecentTransitionTime - now() + : 0; + subtreeFlags = waitForCommitToBeReady(suspendedState, subtreeFlags); + if (null !== subtreeFlags) { pendingEffectsLanes = lanes; root.cancelPendingCommit = subtreeFlags( - commitRoot.bind( + completeRoot.bind( null, root, finishedWork, @@ -12935,8 +12964,9 @@ function commitRootWhenReady( spawnedLane, updatedLanes, suspendedRetryLanes, + didSkipSuspendedSiblings, exitStatus, - suspendedCommitReason, + suspendedState, null, completedRenderStartTime, completedRenderEndTime @@ -12945,7 +12975,8 @@ function commitRootWhenReady( markRootSuspended(root, lanes, spawnedLane, !didSkipSuspendedSiblings); return; } - commitRoot( + } + completeRoot( root, finishedWork, lanes, @@ -12955,8 +12986,12 @@ function commitRootWhenReady( spawnedLane, updatedLanes, suspendedRetryLanes, + didSkipSuspendedSiblings, exitStatus, - suspendedCommitReason + suspendedState, + suspendedCommitReason, + completedRenderStartTime, + completedRenderEndTime ); } function isRenderConsistentWithExternalStores(finishedWork) { @@ -13363,6 +13398,14 @@ function replaySuspendedUnitOfWork(unitOfWork) { break; case 5: resetHooksOnUnwind(next); + var fiber = next; + fiber === hydrationParentFiber && + (isHydrating + ? (popToNextHostParent(fiber), + 5 === fiber.tag && + null != fiber.stateNode && + (nextHydratableInstance = fiber.stateNode)) + : (popToNextHostParent(fiber), (isHydrating = !0))); default: unwindInterruptedWork(current, next), (next = workInProgress = @@ -13484,7 +13527,7 @@ function unwindUnitOfWork(unitOfWork, skipSiblings) { workInProgressRootExitStatus = 6; workInProgress = null; } -function commitRoot( +function completeRoot( root, finishedWork, lanes, @@ -13494,97 +13537,290 @@ function commitRoot( spawnedLane, updatedLanes, suspendedRetryLanes, + didSkipSuspendedSiblings, exitStatus, - suspendedState + suspendedState, + suspendedCommitReason, + completedRenderStartTime, + completedRenderEndTime ) { root.cancelPendingCommit = null; do flushPendingEffects(); while (0 !== pendingEffectsStatus); if (0 !== (executionContext & 6)) throw Error(formatProdErrorMessage(327)); - if (null === finishedWork) - null !== root.stoppingGestures && stopCompletedGestures(root); + if (null === finishedWork) 64 === lanes && stopCommittedGesture(root); else { if (finishedWork === root.current) throw Error(formatProdErrorMessage(177)); - didIncludeRenderPhaseUpdate = finishedWork.lanes | finishedWork.childLanes; - didIncludeRenderPhaseUpdate |= concurrentlyUpdatedLanes; - null === root.pendingGestures && (didIncludeRenderPhaseUpdate &= -65); - markRootFinished( - root, - lanes, - didIncludeRenderPhaseUpdate, - spawnedLane, - updatedLanes, - suspendedRetryLanes - ); root === workInProgressRoot && ((workInProgress = workInProgressRoot = null), (workInProgressRootRenderLanes = 0)); pendingFinishedWork = finishedWork; pendingEffectsRoot = root; pendingEffectsLanes = lanes; - pendingEffectsRemainingLanes = didIncludeRenderPhaseUpdate; pendingPassiveTransitions = transitions; pendingRecoverableErrors = recoverableErrors; - if (64 === lanes) - commitGestureOnRoot( - root, - finishedWork, - recoverableErrors, - suspendedState - ); - else { - pendingViewTransitionEvents = null; - (lanes & 335544064) === lanes - ? ((pendingTransitionTypes = claimQueuedTransitionTypes(root)), - (recoverableErrors = 10262)) - : ((pendingTransitionTypes = null), (recoverableErrors = 10256)); - 0 !== (finishedWork.subtreeFlags & recoverableErrors) || - 0 !== (finishedWork.flags & recoverableErrors) - ? ((root.callbackNode = null), - (root.callbackPriority = 0), - scheduleCallback$1(NormalPriority$1, function () { - flushPassiveEffects(); - return null; - })) - : ((root.callbackNode = null), (root.callbackPriority = 0)); - shouldStartViewTransition = !1; - recoverableErrors = 0 !== (finishedWork.flags & 13878); - if (0 !== (finishedWork.subtreeFlags & 13878) || recoverableErrors) { - recoverableErrors = ReactSharedInternals.T; - ReactSharedInternals.T = null; - transitions = ReactDOMSharedInternals.p; - ReactDOMSharedInternals.p = 2; - spawnedLane = executionContext; - executionContext |= 4; - try { - commitBeforeMutationEffects(root, finishedWork, lanes); - } finally { - (executionContext = spawnedLane), - (ReactDOMSharedInternals.p = transitions), - (ReactSharedInternals.T = recoverableErrors); + if ( + 64 === lanes && + ((suspendedCommitReason = root.pendingGestures), + null !== suspendedCommitReason && !suspendedCommitReason.committing) + ) { + markRootSuspended(root, lanes, spawnedLane, !didSkipSuspendedSiblings); + if (null === suspendedCommitReason.running) { + var finishedGesture = root.pendingGestures; + if (null === finishedGesture) ensureRootIsScheduled(root); + else { + var prevTransition = ReactSharedInternals.T; + ReactSharedInternals.T = null; + var previousPriority = ReactDOMSharedInternals.p; + ReactDOMSharedInternals.p = 2; + var prevExecutionContext = executionContext; + executionContext |= 4; + try { + var rootContainer = root.containerInfo, + documentElement = + 9 === rootContainer.nodeType + ? rootContainer.documentElement + : rootContainer.ownerDocument.documentElement; + null !== documentElement && + "" === documentElement.style.viewTransitionName && + (documentElement.style.viewTransitionName = "none"); + var containerInstance = + 9 === rootContainer.nodeType + ? rootContainer.body + : "HTML" === rootContainer.nodeName + ? rootContainer.ownerDocument.body + : rootContainer; + var containerParent = containerInstance.parentNode; + if (null === containerParent) + throw Error(formatProdErrorMessage(552)); + var clone = containerInstance.cloneNode(!1), + computedStyle = getComputedStyle(containerInstance); + if ( + "absolute" !== computedStyle.position && + "fixed" !== computedStyle.position + ) { + for ( + rootContainer = containerParent; + null != rootContainer.parentNode && + 9 !== rootContainer.parentNode.nodeType && + "static" === getComputedStyle(rootContainer).position; + + ) + rootContainer = rootContainer.parentNode; + var positionedAncestorStyle = rootContainer.style, + containerInstanceStyle = containerInstance.style, + prevAncestorTranslate = positionedAncestorStyle.translate, + prevAncestorScale = positionedAncestorStyle.scale, + prevAncestorRotate = positionedAncestorStyle.rotate, + prevAncestorTransform = positionedAncestorStyle.transform, + prevTranslate = containerInstanceStyle.translate, + prevScale = containerInstanceStyle.scale, + prevRotate = containerInstanceStyle.rotate, + prevTransform = containerInstanceStyle.transform; + positionedAncestorStyle.translate = "none"; + positionedAncestorStyle.scale = "none"; + positionedAncestorStyle.rotate = "none"; + positionedAncestorStyle.transform = "none"; + containerInstanceStyle.translate = "none"; + containerInstanceStyle.scale = "none"; + containerInstanceStyle.rotate = "none"; + containerInstanceStyle.transform = "none"; + var ancestorRect = rootContainer.getBoundingClientRect(), + rect = containerInstance.getBoundingClientRect(), + cloneStyle = clone.style; + cloneStyle.position = "absolute"; + cloneStyle.top = rect.top - ancestorRect.top + "px"; + cloneStyle.left = rect.left - ancestorRect.left + "px"; + cloneStyle.width = rect.width + "px"; + cloneStyle.height = rect.height + "px"; + cloneStyle.margin = "0px"; + cloneStyle.boxSizing = "border-box"; + positionedAncestorStyle.translate = prevAncestorTranslate; + positionedAncestorStyle.scale = prevAncestorScale; + positionedAncestorStyle.rotate = prevAncestorRotate; + positionedAncestorStyle.transform = prevAncestorTransform; + containerInstanceStyle.translate = prevTranslate; + containerInstanceStyle.scale = prevScale; + containerInstanceStyle.rotate = prevRotate; + containerInstanceStyle.transform = prevTransform; + } + clone.style.viewTransitionName = "root"; + var transform = computedStyle.transform; + "none" === transform && (transform = ""); + var scale = computedStyle.scale; + if ("none" !== scale && "" !== scale) { + var parts = scale.split(" "); + transform = + (3 === parts.length ? "scale3d" : "scale") + + "(" + + parts.join(", ") + + ") " + + transform; + } + var rotate = computedStyle.rotate; + if ("none" !== rotate && "" !== rotate) { + var parts$269 = rotate.split(" "); + transform = + 1 === parts$269.length + ? "rotate(" + parts$269[0] + ") " + transform + : 2 === parts$269.length + ? "rotate" + + parts$269[0].toUpperCase() + + "(" + + parts$269[1] + + ") " + + transform + : "rotate3d(" + parts$269.join(", ") + ") " + transform; + } + var translate = computedStyle.translate; + if ("none" !== translate && "" !== translate) { + var parts$270 = translate.split(" "); + transform = + (3 === parts$270.length ? "translate3d" : "translate") + + "(" + + parts$270.join(", ") + + ") " + + transform; + } + var JSCompiler_inline_result = transform; + clone.style.translate = "none"; + clone.style.scale = "none"; + clone.style.rotate = "none"; + clone.style.transform = + "translate(-20000px, -20000px) " + JSCompiler_inline_result; + containerInstance.parentNode.insertBefore( + clone, + containerInstance.nextSibling + ); + root.gestureClone = clone; + recursivelyInsertClones(finishedWork, clone, null, 0); + } finally { + (executionContext = prevExecutionContext), + (ReactDOMSharedInternals.p = previousPriority), + (ReactSharedInternals.T = prevTransition); + } + pendingTransitionTypes = finishedGesture.types; + pendingEffectsStatus = 6; + pendingViewTransition = finishedGesture.running = + startGestureTransition( + suspendedState, + root.containerInfo, + finishedGesture.provider, + finishedGesture.rangeStart, + finishedGesture.rangeEnd, + pendingTransitionTypes, + flushGestureMutations, + flushGestureAnimations, + reportViewTransitionError, + null + ); } - } - finishedWork = shouldStartViewTransition; - null !== root.stoppingGestures && - (stopCompletedGestures(root), (finishedWork = !1)); - pendingEffectsStatus = 1; - finishedWork - ? (pendingViewTransition = startViewTransition( - suspendedState, - root.containerInfo, - pendingTransitionTypes, - flushMutationEffects, - flushLayoutEffects, - flushAfterMutationEffects, - flushSpawnedWork, - flushPassiveEffects, - reportViewTransitionError, - null, - null - )) - : (flushMutationEffects(), flushLayoutEffects(), flushSpawnedWork()); + } else + (pendingFinishedWork = pendingEffectsRoot = null), + (pendingEffectsLanes = 0); + root.cancelPendingCommit = scheduleGestureCommit( + suspendedCommitReason, + completeRoot.bind( + null, + root, + finishedWork, + lanes, + recoverableErrors, + transitions, + didIncludeRenderPhaseUpdate, + spawnedLane, + updatedLanes, + suspendedRetryLanes, + didSkipSuspendedSiblings, + exitStatus, + suspendedState, + "Waiting for the Gesture to finish", + completedRenderStartTime, + completedRenderEndTime + ) + ); + return; + } + commitRoot( + root, + finishedWork, + lanes, + spawnedLane, + updatedLanes, + suspendedRetryLanes, + suspendedState + ); + } +} +function commitRoot( + root, + finishedWork, + lanes, + spawnedLane, + updatedLanes, + suspendedRetryLanes, + suspendedState +) { + var remainingLanes = finishedWork.lanes | finishedWork.childLanes; + pendingEffectsRemainingLanes = remainingLanes; + remainingLanes |= concurrentlyUpdatedLanes; + null === root.pendingGestures && (remainingLanes &= -65); + markRootFinished( + root, + lanes, + remainingLanes, + spawnedLane, + updatedLanes, + suspendedRetryLanes + ); + pendingViewTransitionEvents = null; + (lanes & 335544064) === lanes + ? ((pendingTransitionTypes = claimQueuedTransitionTypes(root)), + (spawnedLane = 10262)) + : ((pendingTransitionTypes = null), (spawnedLane = 10256)); + 0 !== (finishedWork.subtreeFlags & spawnedLane) || + 0 !== (finishedWork.flags & spawnedLane) + ? ((root.callbackNode = null), + (root.callbackPriority = 0), + scheduleCallback$1(NormalPriority$1, function () { + flushPassiveEffects(); + return null; + })) + : ((root.callbackNode = null), (root.callbackPriority = 0)); + shouldStartViewTransition = !1; + spawnedLane = 0 !== (finishedWork.flags & 13878); + if (0 !== (finishedWork.subtreeFlags & 13878) || spawnedLane) { + spawnedLane = ReactSharedInternals.T; + ReactSharedInternals.T = null; + updatedLanes = ReactDOMSharedInternals.p; + ReactDOMSharedInternals.p = 2; + suspendedRetryLanes = executionContext; + executionContext |= 4; + try { + commitBeforeMutationEffects(root, finishedWork, lanes); + } finally { + (executionContext = suspendedRetryLanes), + (ReactDOMSharedInternals.p = updatedLanes), + (ReactSharedInternals.T = spawnedLane); } } + 64 === lanes && stopCommittedGesture(root); + pendingEffectsStatus = 1; + shouldStartViewTransition + ? (pendingViewTransition = startViewTransition( + suspendedState, + root.containerInfo, + pendingTransitionTypes, + flushMutationEffects, + flushLayoutEffects, + flushAfterMutationEffects, + flushSpawnedWork, + flushPassiveEffects, + reportViewTransitionError, + null, + null + )) + : (flushMutationEffects(), flushLayoutEffects(), flushSpawnedWork()); } function reportViewTransitionError(error) { if (0 !== pendingEffectsStatus) { @@ -13869,161 +14105,6 @@ function flushSpawnedWork() { flushSyncWorkAcrossRoots_impl(0, !1); } } -function commitGestureOnRoot( - root, - finishedWork, - recoverableErrors, - suspendedState -) { - recoverableErrors = root.pendingGestures; - if (null === recoverableErrors) ensureRootIsScheduled(root); - else { - deleteScheduledGesture(root, recoverableErrors); - var prevTransition = ReactSharedInternals.T; - ReactSharedInternals.T = null; - var previousPriority = ReactDOMSharedInternals.p; - ReactDOMSharedInternals.p = 2; - var prevExecutionContext = executionContext; - executionContext |= 4; - try { - var rootContainer = root.containerInfo, - documentElement = - 9 === rootContainer.nodeType - ? rootContainer.documentElement - : rootContainer.ownerDocument.documentElement; - null !== documentElement && - "" === documentElement.style.viewTransitionName && - (documentElement.style.viewTransitionName = "none"); - var containerInstance = - 9 === rootContainer.nodeType - ? rootContainer.body - : "HTML" === rootContainer.nodeName - ? rootContainer.ownerDocument.body - : rootContainer; - var containerParent = containerInstance.parentNode; - if (null === containerParent) throw Error(formatProdErrorMessage(552)); - var clone = containerInstance.cloneNode(!1), - computedStyle = getComputedStyle(containerInstance); - if ( - "absolute" !== computedStyle.position && - "fixed" !== computedStyle.position - ) { - for ( - rootContainer = containerParent; - null != rootContainer.parentNode && - 9 !== rootContainer.parentNode.nodeType && - "static" === getComputedStyle(rootContainer).position; - - ) - rootContainer = rootContainer.parentNode; - var positionedAncestorStyle = rootContainer.style, - containerInstanceStyle = containerInstance.style, - prevAncestorTranslate = positionedAncestorStyle.translate, - prevAncestorScale = positionedAncestorStyle.scale, - prevAncestorRotate = positionedAncestorStyle.rotate, - prevAncestorTransform = positionedAncestorStyle.transform, - prevTranslate = containerInstanceStyle.translate, - prevScale = containerInstanceStyle.scale, - prevRotate = containerInstanceStyle.rotate, - prevTransform = containerInstanceStyle.transform; - positionedAncestorStyle.translate = "none"; - positionedAncestorStyle.scale = "none"; - positionedAncestorStyle.rotate = "none"; - positionedAncestorStyle.transform = "none"; - containerInstanceStyle.translate = "none"; - containerInstanceStyle.scale = "none"; - containerInstanceStyle.rotate = "none"; - containerInstanceStyle.transform = "none"; - var ancestorRect = rootContainer.getBoundingClientRect(), - rect = containerInstance.getBoundingClientRect(), - cloneStyle = clone.style; - cloneStyle.position = "absolute"; - cloneStyle.top = rect.top - ancestorRect.top + "px"; - cloneStyle.left = rect.left - ancestorRect.left + "px"; - cloneStyle.width = rect.width + "px"; - cloneStyle.height = rect.height + "px"; - cloneStyle.margin = "0px"; - cloneStyle.boxSizing = "border-box"; - positionedAncestorStyle.translate = prevAncestorTranslate; - positionedAncestorStyle.scale = prevAncestorScale; - positionedAncestorStyle.rotate = prevAncestorRotate; - positionedAncestorStyle.transform = prevAncestorTransform; - containerInstanceStyle.translate = prevTranslate; - containerInstanceStyle.scale = prevScale; - containerInstanceStyle.rotate = prevRotate; - containerInstanceStyle.transform = prevTransform; - } - clone.style.viewTransitionName = "root"; - var transform = computedStyle.transform; - "none" === transform && (transform = ""); - var scale = computedStyle.scale; - if ("none" !== scale && "" !== scale) { - var parts = scale.split(" "); - transform = - (3 === parts.length ? "scale3d" : "scale") + - "(" + - parts.join(", ") + - ") " + - transform; - } - var rotate = computedStyle.rotate; - if ("none" !== rotate && "" !== rotate) { - var parts$269 = rotate.split(" "); - transform = - 1 === parts$269.length - ? "rotate(" + parts$269[0] + ") " + transform - : 2 === parts$269.length - ? "rotate" + - parts$269[0].toUpperCase() + - "(" + - parts$269[1] + - ") " + - transform - : "rotate3d(" + parts$269.join(", ") + ") " + transform; - } - var translate = computedStyle.translate; - if ("none" !== translate && "" !== translate) { - var parts$270 = translate.split(" "); - transform = - (3 === parts$270.length ? "translate3d" : "translate") + - "(" + - parts$270.join(", ") + - ") " + - transform; - } - var JSCompiler_inline_result = transform; - clone.style.translate = "none"; - clone.style.scale = "none"; - clone.style.rotate = "none"; - clone.style.transform = - "translate(-20000px, -20000px) " + JSCompiler_inline_result; - containerInstance.parentNode.insertBefore( - clone, - containerInstance.nextSibling - ); - root.gestureClone = clone; - recursivelyInsertClones(finishedWork, clone, null, 0); - } finally { - (executionContext = prevExecutionContext), - (ReactDOMSharedInternals.p = previousPriority), - (ReactSharedInternals.T = prevTransition); - } - pendingTransitionTypes = recoverableErrors.types; - pendingEffectsStatus = 6; - pendingViewTransition = recoverableErrors.running = startGestureTransition( - suspendedState, - root.containerInfo, - recoverableErrors.provider, - recoverableErrors.rangeStart, - recoverableErrors.rangeEnd, - pendingTransitionTypes, - flushGestureMutations, - flushGestureAnimations, - reportViewTransitionError, - null - ); - } -} function flushGestureMutations() { if (6 === pendingEffectsStatus) { pendingEffectsStatus = 0; @@ -14226,8 +14307,7 @@ function attachPingListener(root, wakeable, lanes) { function pingSuspendedRoot(root, wakeable, pingedLanes) { var pingCache = root.pingCache; null !== pingCache && pingCache.delete(wakeable); - root.pingedLanes |= root.suspendedLanes & pingedLanes; - root.warmLanes &= ~pingedLanes; + markRootPinged$1(root, pingedLanes); workInProgressRoot === root && (workInProgressRootRenderLanes & pingedLanes) === pingedLanes && (4 === workInProgressRootExitStatus || @@ -14643,20 +14723,20 @@ function debounceScrollEnd(targetInst, nativeEvent, nativeEventTarget) { (nativeEventTarget[internalScrollTimer] = targetInst)); } for ( - var i$jscomp$inline_1796 = 0; - i$jscomp$inline_1796 < simpleEventPluginEvents.length; - i$jscomp$inline_1796++ + var i$jscomp$inline_1809 = 0; + i$jscomp$inline_1809 < simpleEventPluginEvents.length; + i$jscomp$inline_1809++ ) { - var eventName$jscomp$inline_1797 = - simpleEventPluginEvents[i$jscomp$inline_1796], - domEventName$jscomp$inline_1798 = - eventName$jscomp$inline_1797.toLowerCase(), - capitalizedEvent$jscomp$inline_1799 = - eventName$jscomp$inline_1797[0].toUpperCase() + - eventName$jscomp$inline_1797.slice(1); + var eventName$jscomp$inline_1810 = + simpleEventPluginEvents[i$jscomp$inline_1809], + domEventName$jscomp$inline_1811 = + eventName$jscomp$inline_1810.toLowerCase(), + capitalizedEvent$jscomp$inline_1812 = + eventName$jscomp$inline_1810[0].toUpperCase() + + eventName$jscomp$inline_1810.slice(1); registerSimpleEvent( - domEventName$jscomp$inline_1798, - "on" + capitalizedEvent$jscomp$inline_1799 + domEventName$jscomp$inline_1811, + "on" + capitalizedEvent$jscomp$inline_1812 ); } registerSimpleEvent(ANIMATION_END, "onAnimationEnd"); @@ -17314,6 +17394,11 @@ function createViewTransitionInstance(name) { new: new ViewTransitionPseudoElement("new", name) }; } +function getCurrentGestureOffset(timeline) { + timeline = timeline.currentTime; + if (null === timeline) throw Error(formatProdErrorMessage(549)); + return "number" === typeof timeline ? timeline : timeline.value; +} function FragmentInstance(fragmentFiber) { this._fragmentFiber = fragmentFiber; this._observers = this._eventListeners = null; @@ -18898,11 +18983,7 @@ function FiberRootNode( this.pooledCache = this.pendingIndicator = null; this.pooledCacheLanes = 0; this.formState = formState; - this.gestureClone = - this.stoppingGestures = - this.pendingGestures = - this.transitionTypes = - null; + this.gestureClone = this.pendingGestures = this.transitionTypes = null; this.incompleteTransitions = new Map(); } function createFiberRoot( @@ -19641,16 +19722,16 @@ ReactDOMHydrationRoot.prototype.unstable_scheduleHydration = function (target) { 0 === i && attemptExplicitHydrationTarget(target); } }; -var isomorphicReactPackageVersion$jscomp$inline_2214 = React.version; +var isomorphicReactPackageVersion$jscomp$inline_2227 = React.version; if ( - "19.3.0-experimental-65eec428-20251218" !== - isomorphicReactPackageVersion$jscomp$inline_2214 + "19.3.0-experimental-bef88f7c-20260116" !== + isomorphicReactPackageVersion$jscomp$inline_2227 ) throw Error( formatProdErrorMessage( 527, - isomorphicReactPackageVersion$jscomp$inline_2214, - "19.3.0-experimental-65eec428-20251218" + isomorphicReactPackageVersion$jscomp$inline_2227, + "19.3.0-experimental-bef88f7c-20260116" ) ); ReactDOMSharedInternals.findDOMNode = function (componentOrElement) { @@ -19670,24 +19751,24 @@ ReactDOMSharedInternals.findDOMNode = function (componentOrElement) { null === componentOrElement ? null : componentOrElement.stateNode; return componentOrElement; }; -var internals$jscomp$inline_2917 = { +var internals$jscomp$inline_2930 = { bundleType: 0, - version: "19.3.0-experimental-65eec428-20251218", + version: "19.3.0-experimental-bef88f7c-20260116", rendererPackageName: "react-dom", currentDispatcherRef: ReactSharedInternals, - reconcilerVersion: "19.3.0-experimental-65eec428-20251218" + reconcilerVersion: "19.3.0-experimental-bef88f7c-20260116" }; if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { - var hook$jscomp$inline_2918 = __REACT_DEVTOOLS_GLOBAL_HOOK__; + var hook$jscomp$inline_2931 = __REACT_DEVTOOLS_GLOBAL_HOOK__; if ( - !hook$jscomp$inline_2918.isDisabled && - hook$jscomp$inline_2918.supportsFiber + !hook$jscomp$inline_2931.isDisabled && + hook$jscomp$inline_2931.supportsFiber ) try { - (rendererID = hook$jscomp$inline_2918.inject( - internals$jscomp$inline_2917 + (rendererID = hook$jscomp$inline_2931.inject( + internals$jscomp$inline_2930 )), - (injectedHook = hook$jscomp$inline_2918); + (injectedHook = hook$jscomp$inline_2931); } catch (err) {} } exports.createRoot = function (container, options) { @@ -19782,4 +19863,4 @@ exports.hydrateRoot = function (container, initialChildren, options) { listenToAllSupportedEvents(container); return new ReactDOMHydrationRoot(initialChildren); }; -exports.version = "19.3.0-experimental-65eec428-20251218"; +exports.version = "19.3.0-experimental-bef88f7c-20260116"; diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-profiling.development.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-profiling.development.js index 1cdf8dfda4ab..de52b64df0b4 100644 --- a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-profiling.development.js +++ b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-profiling.development.js @@ -1281,6 +1281,10 @@ (root.pingedLanes = 0), (root.warmLanes = 0)); } + function markRootPinged$1(root, pingedLanes) { + root.pingedLanes |= root.suspendedLanes & pingedLanes; + root.warmLanes &= ~pingedLanes; + } function markRootFinished( root, finishedLanes, @@ -4516,38 +4520,6 @@ errors )); } - function logRenderPhase(startTime, endTime, lanes, debugTask) { - if (supportsUserTiming && !(endTime <= startTime)) { - var color = - (lanes & 738197653) === lanes ? "tertiary-dark" : "primary-dark"; - lanes = - (lanes & 536870912) === lanes - ? "Prepared" - : (lanes & 201326741) === lanes - ? "Hydrated" - : "Render"; - debugTask - ? debugTask.run( - console.timeStamp.bind( - console, - lanes, - startTime, - endTime, - currentTrack, - LANES_TRACK_GROUP, - color - ) - ) - : console.timeStamp( - lanes, - startTime, - endTime, - currentTrack, - LANES_TRACK_GROUP, - color - ); - } - } function logSuspendedRenderPhase(startTime, endTime, lanes, debugTask) { !supportsUserTiming || endTime <= startTime || @@ -4600,50 +4572,6 @@ lanes )); } - function logRecoveredRenderPhase( - startTime, - endTime, - lanes, - recoverableErrors, - hydrationFailed, - debugTask - ) { - if (supportsUserTiming && !(endTime <= startTime)) { - lanes = []; - for (var i = 0; i < recoverableErrors.length; i++) { - var error = recoverableErrors[i].value; - lanes.push([ - "Recoverable Error", - "object" === typeof error && - null !== error && - "string" === typeof error.message - ? String(error.message) - : String(error) - ]); - } - startTime = { - start: startTime, - end: endTime, - detail: { - devtools: { - color: "primary-dark", - track: currentTrack, - trackGroup: LANES_TRACK_GROUP, - tooltipText: hydrationFailed - ? "Hydration Failed" - : "Recovered after Error", - properties: lanes - } - } - }; - debugTask - ? debugTask.run( - performance.measure.bind(performance, "Recovered", startTime) - ) - : performance.measure("Recovered", startTime); - performance.clearMeasures("Recovered"); - } - } function logErroredRenderPhase(startTime, endTime, lanes, debugTask) { !supportsUserTiming || endTime <= startTime || @@ -5106,7 +5034,7 @@ (workInProgress.key = current.key), (workInProgress.actualDuration = -0), (workInProgress.actualStartTime = -1.1)); - workInProgress.flags = current.flags & 132120576; + workInProgress.flags = current.flags & 133169152; workInProgress.childLanes = current.childLanes; workInProgress.lanes = current.lanes; workInProgress.child = current.child; @@ -5144,7 +5072,7 @@ return workInProgress; } function resetWorkInProgress(workInProgress, renderLanes) { - workInProgress.flags &= 132120578; + workInProgress.flags &= 133169154; var current = workInProgress.alternate; null === current ? ((workInProgress.childLanes = 0), @@ -6232,39 +6160,30 @@ gestureOptions, transitionTypes ) { - if (gestureOptions && null != gestureOptions.rangeStart) - var JSCompiler_temp = gestureOptions.rangeStart; - else { - JSCompiler_temp = gestureTimeline.currentTime; - if (null === JSCompiler_temp) - throw Error( - "Cannot start a gesture with a disconnected AnimationTimeline." - ); - JSCompiler_temp = - "number" === typeof JSCompiler_temp - ? JSCompiler_temp - : JSCompiler_temp.value; - } + var rangeStart = + gestureOptions && null != gestureOptions.rangeStart + ? gestureOptions.rangeStart + : getCurrentGestureOffset(gestureTimeline); gestureOptions = gestureOptions && null != gestureOptions.rangeEnd ? gestureOptions.rangeEnd - : 50 > JSCompiler_temp + : 50 > rangeStart ? 100 : 0; for (root = root.pendingGestures; null !== root; ) { if (root.provider === gestureTimeline) { root.count++; - root.rangeStart = JSCompiler_temp; + root.rangeStart = rangeStart; root.rangeEnd = gestureOptions; if (null !== transitionTypes) for ( gestureTimeline = root.types, null === gestureTimeline && (gestureTimeline = root.types = []), - JSCompiler_temp = 0; - JSCompiler_temp < transitionTypes.length; - JSCompiler_temp++ + rangeStart = 0; + rangeStart < transitionTypes.length; + rangeStart++ ) - (gestureOptions = transitionTypes[JSCompiler_temp]), + (gestureOptions = transitionTypes[rangeStart]), -1 === gestureTimeline.indexOf(gestureOptions) && gestureTimeline.push(gestureOptions); return root; @@ -6274,47 +6193,78 @@ } return null; } - function deleteScheduledGesture(root, gesture) { - null === gesture.prev - ? (root.pendingGestures === gesture && - ((root.pendingGestures = gesture.next), - null === root.pendingGestures && (root.pendingLanes &= -65)), - root.stoppingGestures === gesture && - (root.stoppingGestures = gesture.next)) - : ((gesture.prev.next = gesture.next), - null !== gesture.next && (gesture.next.prev = gesture.prev), - (gesture.prev = null), - (gesture.next = null)); - } - function stopCompletedGestures(root) { - var gesture = root.stoppingGestures; - for (root.stoppingGestures = null; null !== gesture; ) - null !== gesture.running && - (gesture.running.skipTransition(), (gesture.running = null)), - (root = gesture.next), - (gesture.next = null), - (gesture.prev = null), - (gesture = root); + function stopCommittedGesture(root) { + var committedGesture = root.pendingGestures; + if (null !== committedGesture) { + committedGesture.committing = !1; + var nextGesture = committedGesture.next; + null === nextGesture + ? (root.pendingLanes &= -65) + : (nextGesture.prev = null); + root.pendingGestures = nextGesture; + root = committedGesture.running; + null !== root && + ((committedGesture.running = null), root.skipTransition()); + } + } + function scheduleGestureCommit(gesture, callback) { + gesture.commit = callback; + return function () { + gesture.commit = null; + }; } function chainGestureCancellation(root, scheduledGesture, prevCancel) { return function () { - if ( - null !== scheduledGesture && - (scheduledGesture.count--, 0 === scheduledGesture.count) - ) { - deleteScheduledGesture(root, scheduledGesture); - var runningTransition = scheduledGesture.running; - if (null !== runningTransition) { - var pendingLanesExcludingGestureLane = root.pendingLanes & -65; - 0 !== (pendingLanesExcludingGestureLane & 127) || - 0 !== (pendingLanesExcludingGestureLane & 4194048) - ? ((runningTransition = root.stoppingGestures), - null !== runningTransition && - ((scheduledGesture.next = runningTransition), - (runningTransition.prev = scheduledGesture)), - (root.stoppingGestures = scheduledGesture)) - : ((scheduledGesture.running = null), - runningTransition.skipTransition()); + if (null !== scheduledGesture) { + if (0 !== scheduledGesture.revertLane) { + var entangledLanes = + scheduledGesture.revertLane | requestTransitionLane(); + markRootEntangled(root, entangledLanes); + } + scheduledGesture.count--; + if (0 === scheduledGesture.count) { + var finalOffset = getCurrentGestureOffset( + scheduledGesture.provider + ), + rangeStart = scheduledGesture.rangeStart, + rangeEnd = scheduledGesture.rangeEnd; + entangledLanes = scheduledGesture.running; + null !== entangledLanes && + (rangeStart < rangeEnd + ? finalOffset > rangeStart + (rangeEnd - rangeStart) / 2 + : finalOffset < rangeEnd + (rangeStart - rangeEnd) / 2) + ? ((scheduledGesture.committing = !0), + root.pendingGestures === scheduledGesture && + ((entangledLanes = scheduledGesture.commit), + null !== entangledLanes + ? ((scheduledGesture.commit = null), entangledLanes()) + : null !== root.pendingGestures && + (markRootPinged$1(root, 64), + ensureRootIsScheduled(root)))) + : null === scheduledGesture.prev + ? (root.pendingGestures === scheduledGesture && + ((root.pendingGestures = scheduledGesture.next), + (finalOffset = root.pendingLanes), + null === root.pendingGestures && (finalOffset &= -65), + markRootFinished(root, 64, finalOffset, 0, 0, 0), + workInProgressRoot === root && + 64 === workInProgressRootRenderLanes + ? (executionContext & RenderContext) === NoContext && + prepareFreshStack(root, 0) + : null !== root.cancelPendingCommit && + 64 === pendingEffectsLanes && + ((finalOffset = root.cancelPendingCommit), + null !== finalOffset && + ((root.cancelPendingCommit = null), finalOffset())), + null !== root.pendingGestures && markRootPinged$1(root, 64), + ensureRootIsScheduled(root)), + (scheduledGesture.running = null), + null !== entangledLanes && entangledLanes.skipTransition()) + : ((scheduledGesture.prev.next = scheduledGesture.next), + null !== scheduledGesture.next && + (scheduledGesture.next.prev = scheduledGesture.prev), + (scheduledGesture.prev = null), + (scheduledGesture.next = null)); } } null !== prevCancel && prevCancel(); @@ -8232,7 +8182,7 @@ null; hookTypesUpdateIndexDev = -1; null !== current && - (current.flags & 132120576) !== (workInProgress.flags & 132120576) && + (current.flags & 133169152) !== (workInProgress.flags & 133169152) && console.error( "Internal React error: Expected static flag was missing. Please notify the React team." ); @@ -8532,18 +8482,20 @@ if (64 === updateLane) { var scheduledGesture = update.gesture; if (null !== scheduledGesture) - if (0 === scheduledGesture.count) { + if (0 !== scheduledGesture.count || scheduledGesture.committing) + if (64 === renderLanes) { + shouldSkipUpdate = workInProgressRoot; + if (null === shouldSkipUpdate) + throw Error( + "Expected a work-in-progress root. This is a bug in React. Please file an issue." + ); + shouldSkipUpdate = + shouldSkipUpdate.pendingGestures !== scheduledGesture; + } else shouldSkipUpdate = !0; + else { update = update.next; continue; - } else if (64 === renderLanes) { - shouldSkipUpdate = workInProgressRoot; - if (null === shouldSkipUpdate) - throw Error( - "Expected a work-in-progress root. This is a bug in React. Please file an issue." - ); - shouldSkipUpdate = - shouldSkipUpdate.pendingGestures !== scheduledGesture; - } else shouldSkipUpdate = !0; + } } if (shouldSkipUpdate) (scheduledGesture = { @@ -9396,7 +9348,7 @@ hook ); if ( - 0 === (renderLanes & 42) || + 0 === (renderLanes & 106) || (0 !== (renderLanes & 1073741824) && 0 === (workInProgressRootRenderLanes & 261930)) ) @@ -9782,6 +9734,9 @@ rangeEnd: 100, types: null, running: null, + commit: null, + committing: !1, + revertLane: 0, prev: fiber, next: null }; @@ -9791,7 +9746,10 @@ ensureRootIsScheduled(throwIfDuringRender); throwIfDuringRender = transition; } - action.gesture = throwIfDuringRender; + throwIfDuringRender = action.gesture = throwIfDuringRender; + 0 === throwIfDuringRender.revertLane + ? (throwIfDuringRender.revertLane = action.revertLane) + : (action.revertLane = throwIfDuringRender.revertLane); } } function isRenderPhaseUpdate(fiber) { @@ -11404,24 +11362,24 @@ return current; } function updateSuspenseComponent(current, workInProgress, renderLanes) { - var JSCompiler_object_inline_digest_3231; - var JSCompiler_object_inline_stack_3232 = workInProgress.pendingProps; + var JSCompiler_object_inline_digest_3289; + var JSCompiler_object_inline_stack_3290 = workInProgress.pendingProps; shouldSuspendImpl(workInProgress) && (workInProgress.flags |= 128); - var JSCompiler_object_inline_message_3230 = !1; + var JSCompiler_object_inline_message_3288 = !1; var didSuspend = 0 !== (workInProgress.flags & 128); - (JSCompiler_object_inline_digest_3231 = didSuspend) || - (JSCompiler_object_inline_digest_3231 = + (JSCompiler_object_inline_digest_3289 = didSuspend) || + (JSCompiler_object_inline_digest_3289 = null !== current && null === current.memoizedState ? !1 : 0 !== (suspenseStackCursor.current & ForceSuspenseFallback)); - JSCompiler_object_inline_digest_3231 && - ((JSCompiler_object_inline_message_3230 = !0), + JSCompiler_object_inline_digest_3289 && + ((JSCompiler_object_inline_message_3288 = !0), (workInProgress.flags &= -129)); - JSCompiler_object_inline_digest_3231 = 0 !== (workInProgress.flags & 32); + JSCompiler_object_inline_digest_3289 = 0 !== (workInProgress.flags & 32); workInProgress.flags &= -33; if (null === current) { if (isHydrating) { - JSCompiler_object_inline_message_3230 + JSCompiler_object_inline_message_3288 ? pushPrimaryTreeSuspenseHandler(workInProgress) : reuseSuspenseHandlerOnStack(workInProgress); (current = nextHydratableInstance) @@ -11434,18 +11392,18 @@ ? renderLanes : null), null !== renderLanes && - ((JSCompiler_object_inline_digest_3231 = { + ((JSCompiler_object_inline_digest_3289 = { dehydrated: renderLanes, treeContext: getSuspendedTreeContext(), retryLane: 536870912, hydrationErrors: null }), (workInProgress.memoizedState = - JSCompiler_object_inline_digest_3231), - (JSCompiler_object_inline_digest_3231 = + JSCompiler_object_inline_digest_3289), + (JSCompiler_object_inline_digest_3289 = createFiberFromDehydratedFragment(renderLanes)), - (JSCompiler_object_inline_digest_3231.return = workInProgress), - (workInProgress.child = JSCompiler_object_inline_digest_3231), + (JSCompiler_object_inline_digest_3289.return = workInProgress), + (workInProgress.child = JSCompiler_object_inline_digest_3289), (hydrationParentFiber = workInProgress), (nextHydratableInstance = null))) : (renderLanes = null); @@ -11459,9 +11417,9 @@ : (workInProgress.lanes = 536870912); return null; } - var nextPrimaryChildren = JSCompiler_object_inline_stack_3232.children, - nextFallbackChildren = JSCompiler_object_inline_stack_3232.fallback; - if (JSCompiler_object_inline_message_3230) + var nextPrimaryChildren = JSCompiler_object_inline_stack_3290.children, + nextFallbackChildren = JSCompiler_object_inline_stack_3290.fallback; + if (JSCompiler_object_inline_message_3288) return ( reuseSuspenseHandlerOnStack(workInProgress), mountSuspenseFallbackChildren( @@ -11470,19 +11428,19 @@ nextFallbackChildren, renderLanes ), - (JSCompiler_object_inline_stack_3232 = workInProgress.child), - (JSCompiler_object_inline_stack_3232.memoizedState = + (JSCompiler_object_inline_stack_3290 = workInProgress.child), + (JSCompiler_object_inline_stack_3290.memoizedState = mountSuspenseOffscreenState(renderLanes)), - (JSCompiler_object_inline_stack_3232.childLanes = + (JSCompiler_object_inline_stack_3290.childLanes = getRemainingWorkInPrimaryTree( current, - JSCompiler_object_inline_digest_3231, + JSCompiler_object_inline_digest_3289, renderLanes )), (workInProgress.memoizedState = SUSPENDED_MARKER), - bailoutOffscreenComponent(null, JSCompiler_object_inline_stack_3232) + bailoutOffscreenComponent(null, JSCompiler_object_inline_stack_3290) ); - if (!0 === JSCompiler_object_inline_stack_3232.defer) + if (!0 === JSCompiler_object_inline_stack_3290.defer) return ( reuseSuspenseHandlerOnStack(workInProgress), mountSuspenseFallbackChildren( @@ -11491,18 +11449,18 @@ nextFallbackChildren, renderLanes ), - (JSCompiler_object_inline_stack_3232 = workInProgress.child), - (JSCompiler_object_inline_stack_3232.memoizedState = + (JSCompiler_object_inline_stack_3290 = workInProgress.child), + (JSCompiler_object_inline_stack_3290.memoizedState = mountSuspenseOffscreenState(renderLanes)), - (JSCompiler_object_inline_stack_3232.childLanes = + (JSCompiler_object_inline_stack_3290.childLanes = getRemainingWorkInPrimaryTree( current, - JSCompiler_object_inline_digest_3231, + JSCompiler_object_inline_digest_3289, renderLanes )), (workInProgress.memoizedState = SUSPENDED_MARKER), (workInProgress.lanes = 4194304), - bailoutOffscreenComponent(null, JSCompiler_object_inline_stack_3232) + bailoutOffscreenComponent(null, JSCompiler_object_inline_stack_3290) ); pushPrimaryTreeSuspenseHandler(workInProgress); return mountSuspensePrimaryChildren( @@ -11512,8 +11470,8 @@ } var prevState = current.memoizedState; if (null !== prevState) { - var JSCompiler_object_inline_componentStack_3233 = prevState.dehydrated; - if (null !== JSCompiler_object_inline_componentStack_3233) { + var JSCompiler_object_inline_componentStack_3291 = prevState.dehydrated; + if (null !== JSCompiler_object_inline_componentStack_3291) { if (didSuspend) workInProgress.flags & 256 ? (pushPrimaryTreeSuspenseHandler(workInProgress), @@ -11530,13 +11488,13 @@ (workInProgress = null)) : (reuseSuspenseHandlerOnStack(workInProgress), (nextPrimaryChildren = - JSCompiler_object_inline_stack_3232.fallback), + JSCompiler_object_inline_stack_3290.fallback), (nextFallbackChildren = workInProgress.mode), - (JSCompiler_object_inline_stack_3232 = + (JSCompiler_object_inline_stack_3290 = mountWorkInProgressOffscreenFiber( { mode: "visible", - children: JSCompiler_object_inline_stack_3232.children + children: JSCompiler_object_inline_stack_3290.children }, nextFallbackChildren )), @@ -11547,30 +11505,30 @@ null )), (nextPrimaryChildren.flags |= 2), - (JSCompiler_object_inline_stack_3232.return = workInProgress), + (JSCompiler_object_inline_stack_3290.return = workInProgress), (nextPrimaryChildren.return = workInProgress), - (JSCompiler_object_inline_stack_3232.sibling = + (JSCompiler_object_inline_stack_3290.sibling = nextPrimaryChildren), - (workInProgress.child = JSCompiler_object_inline_stack_3232), + (workInProgress.child = JSCompiler_object_inline_stack_3290), reconcileChildFibers( workInProgress, current.child, null, renderLanes ), - (JSCompiler_object_inline_stack_3232 = workInProgress.child), - (JSCompiler_object_inline_stack_3232.memoizedState = + (JSCompiler_object_inline_stack_3290 = workInProgress.child), + (JSCompiler_object_inline_stack_3290.memoizedState = mountSuspenseOffscreenState(renderLanes)), - (JSCompiler_object_inline_stack_3232.childLanes = + (JSCompiler_object_inline_stack_3290.childLanes = getRemainingWorkInPrimaryTree( current, - JSCompiler_object_inline_digest_3231, + JSCompiler_object_inline_digest_3289, renderLanes )), (workInProgress.memoizedState = SUSPENDED_MARKER), (workInProgress = bailoutOffscreenComponent( null, - JSCompiler_object_inline_stack_3232 + JSCompiler_object_inline_stack_3290 ))); else if ( (pushPrimaryTreeSuspenseHandler(workInProgress), @@ -11578,45 +11536,45 @@ 0 !== (renderLanes & 536870912) && markRenderDerivedCause(workInProgress), isSuspenseInstanceFallback( - JSCompiler_object_inline_componentStack_3233 + JSCompiler_object_inline_componentStack_3291 )) ) { - JSCompiler_object_inline_digest_3231 = - JSCompiler_object_inline_componentStack_3233.nextSibling && - JSCompiler_object_inline_componentStack_3233.nextSibling.dataset; - if (JSCompiler_object_inline_digest_3231) { - nextPrimaryChildren = JSCompiler_object_inline_digest_3231.dgst; - var message = JSCompiler_object_inline_digest_3231.msg; - nextFallbackChildren = JSCompiler_object_inline_digest_3231.stck; - var componentStack = JSCompiler_object_inline_digest_3231.cstck; + JSCompiler_object_inline_digest_3289 = + JSCompiler_object_inline_componentStack_3291.nextSibling && + JSCompiler_object_inline_componentStack_3291.nextSibling.dataset; + if (JSCompiler_object_inline_digest_3289) { + nextPrimaryChildren = JSCompiler_object_inline_digest_3289.dgst; + var message = JSCompiler_object_inline_digest_3289.msg; + nextFallbackChildren = JSCompiler_object_inline_digest_3289.stck; + var componentStack = JSCompiler_object_inline_digest_3289.cstck; } - JSCompiler_object_inline_message_3230 = message; - JSCompiler_object_inline_digest_3231 = nextPrimaryChildren; - JSCompiler_object_inline_stack_3232 = nextFallbackChildren; - JSCompiler_object_inline_componentStack_3233 = componentStack; - nextPrimaryChildren = JSCompiler_object_inline_message_3230; - nextFallbackChildren = JSCompiler_object_inline_componentStack_3233; + JSCompiler_object_inline_message_3288 = message; + JSCompiler_object_inline_digest_3289 = nextPrimaryChildren; + JSCompiler_object_inline_stack_3290 = nextFallbackChildren; + JSCompiler_object_inline_componentStack_3291 = componentStack; + nextPrimaryChildren = JSCompiler_object_inline_message_3288; + nextFallbackChildren = JSCompiler_object_inline_componentStack_3291; nextPrimaryChildren = nextPrimaryChildren ? Error(nextPrimaryChildren) : Error( "The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering." ); nextPrimaryChildren.stack = - JSCompiler_object_inline_stack_3232 || ""; - nextPrimaryChildren.digest = JSCompiler_object_inline_digest_3231; - JSCompiler_object_inline_digest_3231 = + JSCompiler_object_inline_stack_3290 || ""; + nextPrimaryChildren.digest = JSCompiler_object_inline_digest_3289; + JSCompiler_object_inline_digest_3289 = void 0 === nextFallbackChildren ? null : nextFallbackChildren; - JSCompiler_object_inline_stack_3232 = { + JSCompiler_object_inline_stack_3290 = { value: nextPrimaryChildren, source: null, - stack: JSCompiler_object_inline_digest_3231 + stack: JSCompiler_object_inline_digest_3289 }; - "string" === typeof JSCompiler_object_inline_digest_3231 && + "string" === typeof JSCompiler_object_inline_digest_3289 && CapturedStacks.set( nextPrimaryChildren, - JSCompiler_object_inline_stack_3232 + JSCompiler_object_inline_stack_3290 ); - queueHydrationError(JSCompiler_object_inline_stack_3232); + queueHydrationError(JSCompiler_object_inline_stack_3290); workInProgress = retrySuspenseComponentWithoutHydrating( current, workInProgress, @@ -11630,35 +11588,35 @@ renderLanes, !1 ), - (JSCompiler_object_inline_digest_3231 = + (JSCompiler_object_inline_digest_3289 = 0 !== (renderLanes & current.childLanes)), - didReceiveUpdate || JSCompiler_object_inline_digest_3231) + didReceiveUpdate || JSCompiler_object_inline_digest_3289) ) { - JSCompiler_object_inline_digest_3231 = workInProgressRoot; + JSCompiler_object_inline_digest_3289 = workInProgressRoot; if ( - null !== JSCompiler_object_inline_digest_3231 && - ((JSCompiler_object_inline_stack_3232 = getBumpedLaneForHydration( - JSCompiler_object_inline_digest_3231, + null !== JSCompiler_object_inline_digest_3289 && + ((JSCompiler_object_inline_stack_3290 = getBumpedLaneForHydration( + JSCompiler_object_inline_digest_3289, renderLanes )), - 0 !== JSCompiler_object_inline_stack_3232 && - JSCompiler_object_inline_stack_3232 !== prevState.retryLane) + 0 !== JSCompiler_object_inline_stack_3290 && + JSCompiler_object_inline_stack_3290 !== prevState.retryLane) ) throw ( - ((prevState.retryLane = JSCompiler_object_inline_stack_3232), + ((prevState.retryLane = JSCompiler_object_inline_stack_3290), enqueueConcurrentRenderForLane( current, - JSCompiler_object_inline_stack_3232 + JSCompiler_object_inline_stack_3290 ), scheduleUpdateOnFiber( - JSCompiler_object_inline_digest_3231, + JSCompiler_object_inline_digest_3289, current, - JSCompiler_object_inline_stack_3232 + JSCompiler_object_inline_stack_3290 ), SelectiveHydrationException) ); isSuspenseInstancePending( - JSCompiler_object_inline_componentStack_3233 + JSCompiler_object_inline_componentStack_3291 ) || renderDidSuspendDelayIfPossible(); workInProgress = retrySuspenseComponentWithoutHydrating( current, @@ -11667,14 +11625,14 @@ ); } else isSuspenseInstancePending( - JSCompiler_object_inline_componentStack_3233 + JSCompiler_object_inline_componentStack_3291 ) ? ((workInProgress.flags |= 192), (workInProgress.child = current.child), (workInProgress = null)) : ((current = prevState.treeContext), (nextHydratableInstance = getNextHydratable( - JSCompiler_object_inline_componentStack_3233.nextSibling + JSCompiler_object_inline_componentStack_3291.nextSibling )), (hydrationParentFiber = workInProgress), (isHydrating = !0), @@ -11686,32 +11644,32 @@ restoreSuspendedTreeContext(workInProgress, current), (workInProgress = mountSuspensePrimaryChildren( workInProgress, - JSCompiler_object_inline_stack_3232.children + JSCompiler_object_inline_stack_3290.children )), (workInProgress.flags |= 4096)); return workInProgress; } } - if (JSCompiler_object_inline_message_3230) + if (JSCompiler_object_inline_message_3288) return ( reuseSuspenseHandlerOnStack(workInProgress), - (nextPrimaryChildren = JSCompiler_object_inline_stack_3232.fallback), + (nextPrimaryChildren = JSCompiler_object_inline_stack_3290.fallback), (nextFallbackChildren = workInProgress.mode), (componentStack = current.child), - (JSCompiler_object_inline_componentStack_3233 = + (JSCompiler_object_inline_componentStack_3291 = componentStack.sibling), - (JSCompiler_object_inline_stack_3232 = createWorkInProgress( + (JSCompiler_object_inline_stack_3290 = createWorkInProgress( componentStack, { mode: "hidden", - children: JSCompiler_object_inline_stack_3232.children + children: JSCompiler_object_inline_stack_3290.children } )), - (JSCompiler_object_inline_stack_3232.subtreeFlags = - componentStack.subtreeFlags & 132120576), - null !== JSCompiler_object_inline_componentStack_3233 + (JSCompiler_object_inline_stack_3290.subtreeFlags = + componentStack.subtreeFlags & 133169152), + null !== JSCompiler_object_inline_componentStack_3291 ? (nextPrimaryChildren = createWorkInProgress( - JSCompiler_object_inline_componentStack_3233, + JSCompiler_object_inline_componentStack_3291, nextPrimaryChildren )) : ((nextPrimaryChildren = createFiberFromFragment( @@ -11722,11 +11680,11 @@ )), (nextPrimaryChildren.flags |= 2)), (nextPrimaryChildren.return = workInProgress), - (JSCompiler_object_inline_stack_3232.return = workInProgress), - (JSCompiler_object_inline_stack_3232.sibling = nextPrimaryChildren), - (workInProgress.child = JSCompiler_object_inline_stack_3232), - bailoutOffscreenComponent(null, JSCompiler_object_inline_stack_3232), - (JSCompiler_object_inline_stack_3232 = workInProgress.child), + (JSCompiler_object_inline_stack_3290.return = workInProgress), + (JSCompiler_object_inline_stack_3290.sibling = nextPrimaryChildren), + (workInProgress.child = JSCompiler_object_inline_stack_3290), + bailoutOffscreenComponent(null, JSCompiler_object_inline_stack_3290), + (JSCompiler_object_inline_stack_3290 = workInProgress.child), (nextPrimaryChildren = current.child.memoizedState), null === nextPrimaryChildren ? (nextPrimaryChildren = mountSuspenseOffscreenState(renderLanes)) @@ -11742,18 +11700,18 @@ baseLanes: nextPrimaryChildren.baseLanes | renderLanes, cachePool: nextFallbackChildren })), - (JSCompiler_object_inline_stack_3232.memoizedState = + (JSCompiler_object_inline_stack_3290.memoizedState = nextPrimaryChildren), - (JSCompiler_object_inline_stack_3232.childLanes = + (JSCompiler_object_inline_stack_3290.childLanes = getRemainingWorkInPrimaryTree( current, - JSCompiler_object_inline_digest_3231, + JSCompiler_object_inline_digest_3289, renderLanes )), (workInProgress.memoizedState = SUSPENDED_MARKER), bailoutOffscreenComponent( current.child, - JSCompiler_object_inline_stack_3232 + JSCompiler_object_inline_stack_3290 ) ); null !== prevState && @@ -11765,16 +11723,16 @@ current = renderLanes.sibling; renderLanes = createWorkInProgress(renderLanes, { mode: "visible", - children: JSCompiler_object_inline_stack_3232.children + children: JSCompiler_object_inline_stack_3290.children }); renderLanes.return = workInProgress; renderLanes.sibling = null; null !== current && - ((JSCompiler_object_inline_digest_3231 = workInProgress.deletions), - null === JSCompiler_object_inline_digest_3231 + ((JSCompiler_object_inline_digest_3289 = workInProgress.deletions), + null === JSCompiler_object_inline_digest_3289 ? ((workInProgress.deletions = [current]), (workInProgress.flags |= 16)) - : JSCompiler_object_inline_digest_3231.push(current)); + : JSCompiler_object_inline_digest_3289.push(current)); workInProgress.child = renderLanes; workInProgress.memoizedState = null; return renderLanes; @@ -13088,8 +13046,8 @@ ) (newChildLanes |= _child2.lanes | _child2.childLanes), - (subtreeFlags |= _child2.subtreeFlags & 132120576), - (subtreeFlags |= _child2.flags & 132120576), + (subtreeFlags |= _child2.subtreeFlags & 133169152), + (subtreeFlags |= _child2.flags & 133169152), (_treeBaseDuration += _child2.treeBaseDuration), (_child2 = _child2.sibling); completedWork.treeBaseDuration = _treeBaseDuration; @@ -13101,8 +13059,8 @@ ) (newChildLanes |= _treeBaseDuration.lanes | _treeBaseDuration.childLanes), - (subtreeFlags |= _treeBaseDuration.subtreeFlags & 132120576), - (subtreeFlags |= _treeBaseDuration.flags & 132120576), + (subtreeFlags |= _treeBaseDuration.subtreeFlags & 133169152), + (subtreeFlags |= _treeBaseDuration.flags & 133169152), (_treeBaseDuration.return = completedWork), (_treeBaseDuration = _treeBaseDuration.sibling); else if ((completedWork.mode & ProfileMode) !== NoMode) { @@ -14955,7 +14913,9 @@ (viewTransitionCancelableChildren = []), viewTransitionCancelableChildren.push( instance, - oldName, + 0 === viewTransitionHostInstanceIdx + ? oldName + : oldName + "_" + viewTransitionHostInstanceIdx, child.memoizedProps )); viewTransitionHostInstanceIdx++; @@ -18920,7 +18880,7 @@ throw Error("Unknown root exit status."); } if (null !== ReactSharedInternals.actQueue) - commitRoot( + completeRoot( forceSync, yieldEndTime, lanes, @@ -18930,6 +18890,7 @@ workInProgressDeferredLane, workInProgressRootInterleavedUpdatedLanes, workInProgressSuspendedRetryLanes, + workInProgressRootDidSkipSuspendedSiblings, startTime, null, null, @@ -18954,7 +18915,7 @@ if (0 !== getNextLanes(forceSync, 0, !0)) break a; pendingEffectsLanes = lanes; forceSync.timeoutHandle = scheduleTimeout( - commitRootWhenReady.bind( + completeRootWhenReady.bind( null, forceSync, yieldEndTime, @@ -18975,7 +18936,7 @@ ); break a; } - commitRootWhenReady( + completeRootWhenReady( forceSync, yieldEndTime, workInProgressRootRecoverableErrors, @@ -18998,7 +18959,7 @@ } while (1); ensureRootIsScheduled(root); } - function commitRootWhenReady( + function completeRootWhenReady( root, finishedWork, recoverableErrors, @@ -19024,23 +18985,26 @@ subtreeFlags & 8192 || 16785408 === (subtreeFlags & 16785408) || isGestureTransition - ) + ) { + suspendedState = { + stylesheets: null, + count: 0, + imgCount: 0, + imgBytes: 0, + suspenseyImages: [], + waitingForImages: !0, + waitingForViewTransition: !1, + unsuspend: noop$1 + }; + appearingViewTransitions = null; + accumulateSuspenseyCommitOnFiber(finishedWork, lanes, suspendedState); if ( - ((suspendedState = { - stylesheets: null, - count: 0, - imgCount: 0, - imgBytes: 0, - suspenseyImages: [], - waitingForImages: !0, - waitingForViewTransition: !1, - unsuspend: noop$1 - }), - (appearingViewTransitions = null), - accumulateSuspenseyCommitOnFiber(finishedWork, lanes, suspendedState), - (isViewTransitionEligible || isGestureTransition) && - null === root.stoppingGestures && - ((subtreeFlags = suspendedState), + isViewTransitionEligible || + (isGestureTransition && + null !== root.pendingGestures && + null === root.pendingGestures.running) + ) + (subtreeFlags = suspendedState), (isViewTransitionEligible = root.containerInfo), (isViewTransitionEligible = ( 9 === isViewTransitionEligible.nodeType @@ -19054,19 +19018,18 @@ isViewTransitionEligible.finished.then( subtreeFlags, subtreeFlags - ))), - (subtreeFlags = - (lanes & 62914560) === lanes - ? globalMostRecentFallbackTime - now$1() - : (lanes & 4194048) === lanes - ? globalMostRecentTransitionTime - now$1() - : 0), - (subtreeFlags = waitForCommitToBeReady(suspendedState, subtreeFlags)), - null !== subtreeFlags) - ) { + )); + subtreeFlags = + (lanes & 62914560) === lanes + ? globalMostRecentFallbackTime - now$1() + : (lanes & 4194048) === lanes + ? globalMostRecentTransitionTime - now$1() + : 0; + subtreeFlags = waitForCommitToBeReady(suspendedState, subtreeFlags); + if (null !== subtreeFlags) { pendingEffectsLanes = lanes; root.cancelPendingCommit = subtreeFlags( - commitRoot.bind( + completeRoot.bind( null, root, finishedWork, @@ -19077,6 +19040,7 @@ spawnedLane, updatedLanes, suspendedRetryLanes, + didSkipSuspendedSiblings, exitStatus, suspendedState, suspendedState.waitingForViewTransition @@ -19102,7 +19066,8 @@ ); return; } - commitRoot( + } + completeRoot( root, finishedWork, lanes, @@ -19112,6 +19077,7 @@ spawnedLane, updatedLanes, suspendedRetryLanes, + didSkipSuspendedSiblings, exitStatus, suspendedState, suspendedCommitReason, @@ -20093,6 +20059,14 @@ break; case 5: resetHooksOnUnwind(unitOfWork); + var fiber = unitOfWork; + fiber === hydrationParentFiber && + (isHydrating + ? (popToNextHostParent(fiber), + 5 === fiber.tag && + null != fiber.stateNode && + (nextHydratableInstance = fiber.stateNode)) + : (popToNextHostParent(fiber), (isHydrating = !0))); default: unwindInterruptedWork(current, unitOfWork), (unitOfWork = workInProgress = @@ -20231,7 +20205,7 @@ workInProgressRootExitStatus = RootSuspendedAtTheShell; workInProgress = null; } - function commitRoot( + function completeRoot( root, finishedWork, lanes, @@ -20241,6 +20215,7 @@ spawnedLane, updatedLanes, suspendedRetryLanes, + didSkipSuspendedSiblings, exitStatus, suspendedState, suspendedCommitReason, @@ -20255,33 +20230,96 @@ if ((executionContext & (RenderContext | CommitContext)) !== NoContext) throw Error("Should not already be working."); setCurrentTrackFromLanes(lanes); - exitStatus === RootErrored - ? logErroredRenderPhase( - completedRenderStartTime, - completedRenderEndTime, - lanes, - workInProgressUpdateTask - ) - : null !== recoverableErrors - ? logRecoveredRenderPhase( - completedRenderStartTime, - completedRenderEndTime, - lanes, - recoverableErrors, - null !== finishedWork && - null !== finishedWork.alternate && - finishedWork.alternate.memoizedState.isDehydrated && - 0 !== (finishedWork.flags & 256), - workInProgressUpdateTask - ) - : logRenderPhase( - completedRenderStartTime, - completedRenderEndTime, - lanes, - workInProgressUpdateTask - ); - if (null === finishedWork) - null !== root.stoppingGestures && stopCompletedGestures(root); + 64 === lanes && + (completedRenderStartTime < gestureClampTime && + (completedRenderStartTime = gestureClampTime), + completedRenderEndTime < gestureClampTime && + (completedRenderEndTime = gestureClampTime)); + if (exitStatus === RootErrored) + logErroredRenderPhase( + completedRenderStartTime, + completedRenderEndTime, + lanes, + workInProgressUpdateTask + ); + else if (null !== recoverableErrors) { + var startTime = completedRenderStartTime, + endTime = completedRenderEndTime, + hydrationFailed = + null !== finishedWork && + null !== finishedWork.alternate && + finishedWork.alternate.memoizedState.isDehydrated && + 0 !== (finishedWork.flags & 256), + debugTask = workInProgressUpdateTask; + if (supportsUserTiming && !(endTime <= startTime)) { + for (var properties = [], i = 0; i < recoverableErrors.length; i++) { + var error = recoverableErrors[i].value; + properties.push([ + "Recoverable Error", + "object" === typeof error && + null !== error && + "string" === typeof error.message + ? String(error.message) + : String(error) + ]); + } + startTime = { + start: startTime, + end: endTime, + detail: { + devtools: { + color: "primary-dark", + track: currentTrack, + trackGroup: LANES_TRACK_GROUP, + tooltipText: hydrationFailed + ? "Hydration Failed" + : "Recovered after Error", + properties: properties + } + } + }; + debugTask + ? debugTask.run( + performance.measure.bind(performance, "Recovered", startTime) + ) + : performance.measure("Recovered", startTime); + performance.clearMeasures("Recovered"); + } + } else + (debugTask = completedRenderStartTime), + (startTime = completedRenderEndTime), + (endTime = workInProgressUpdateTask), + !supportsUserTiming || + startTime <= debugTask || + ((hydrationFailed = + (lanes & 738197653) === lanes ? "tertiary-dark" : "primary-dark"), + (properties = + (lanes & 536870912) === lanes + ? "Prepared" + : (lanes & 201326741) === lanes + ? "Hydrated" + : "Render"), + endTime + ? endTime.run( + console.timeStamp.bind( + console, + properties, + debugTask, + startTime, + currentTrack, + LANES_TRACK_GROUP, + hydrationFailed + ) + ) + : console.timeStamp( + properties, + debugTask, + startTime, + currentTrack, + LANES_TRACK_GROUP, + hydrationFailed + )); + if (null === finishedWork) 64 === lanes && stopCommittedGesture(root); else { 0 === lanes && console.error( @@ -20291,119 +20329,330 @@ throw Error( "Cannot commit the same tree as before. This error is likely caused by a bug in React. Please file an issue." ); - didIncludeRenderPhaseUpdate = - finishedWork.lanes | finishedWork.childLanes; - didIncludeRenderPhaseUpdate |= concurrentlyUpdatedLanes; - null === root.pendingGestures && - (0 !== (didIncludeRenderPhaseUpdate & 64) && - ((gestureUpdateTime = -1.1), - (gestureUpdateType = 0), - (gestureSuspendedTime = -1.1), - (gestureEventRepeatTime = gestureEventTime), - (gestureEventTime = -1.1)), - (didIncludeRenderPhaseUpdate &= -65)); - markRootFinished( - root, - lanes, - didIncludeRenderPhaseUpdate, - spawnedLane, - updatedLanes, - suspendedRetryLanes - ); root === workInProgressRoot && ((workInProgress = workInProgressRoot = null), (workInProgressRootRenderLanes = 0)); pendingFinishedWork = finishedWork; pendingEffectsRoot = root; pendingEffectsLanes = lanes; - pendingEffectsRemainingLanes = didIncludeRenderPhaseUpdate; pendingPassiveTransitions = transitions; pendingRecoverableErrors = recoverableErrors; pendingEffectsRenderEndTime = completedRenderEndTime; pendingSuspendedCommitReason = suspendedCommitReason; pendingDelayedCommitReason = IMMEDIATE_COMMIT; pendingSuspendedViewTransitionReason = null; - if (64 === lanes) - commitGestureOnRoot( + if ( + 64 === lanes && + ((debugTask = root.pendingGestures), + null !== debugTask && !debugTask.committing) + ) { + markRootSuspended( root, - finishedWork, - recoverableErrors, - suspendedState + lanes, + spawnedLane, + !didSkipSuspendedSiblings ); - else { - pendingViewTransitionEvents = null; - (lanes & 335544064) === lanes - ? ((pendingTransitionTypes = claimQueuedTransitionTypes(root)), - (recoverableErrors = 10262)) - : ((pendingTransitionTypes = null), (recoverableErrors = 10256)); - 0 !== finishedWork.actualDuration || - 0 !== (finishedWork.subtreeFlags & recoverableErrors) || - 0 !== (finishedWork.flags & recoverableErrors) - ? ((root.callbackNode = null), - (root.callbackPriority = 0), - scheduleCallback$1(NormalPriority$1, function () { - schedulerEvent = window.event; - pendingDelayedCommitReason === IMMEDIATE_COMMIT && - (pendingDelayedCommitReason = DELAYED_PASSIVE_COMMIT); - flushPassiveEffects(); - return null; - })) - : ((root.callbackNode = null), (root.callbackPriority = 0)); - commitErrors = null; - commitStartTime = now(); - null !== suspendedCommitReason && - logSuspendedCommitPhase( - completedRenderEndTime, - commitStartTime, - suspendedCommitReason, - workInProgressUpdateTask - ); - shouldStartViewTransition = !1; - suspendedCommitReason = 0 !== (finishedWork.flags & 13878); - if ( - 0 !== (finishedWork.subtreeFlags & 13878) || - suspendedCommitReason - ) { - suspendedCommitReason = ReactSharedInternals.T; - ReactSharedInternals.T = null; - completedRenderEndTime = ReactDOMSharedInternals.p; - ReactDOMSharedInternals.p = DiscreteEventPriority; - recoverableErrors = executionContext; - executionContext |= CommitContext; - try { - commitBeforeMutationEffects(root, finishedWork, lanes); - } finally { - (executionContext = recoverableErrors), - (ReactDOMSharedInternals.p = completedRenderEndTime), - (ReactSharedInternals.T = suspendedCommitReason); + if (null === debugTask.running) + if ( + ((suspendedCommitReason = root.pendingGestures), + null === suspendedCommitReason) + ) + ensureRootIsScheduled(root); + else { + animatingLanes |= pendingEffectsLanes; + animatingTask = null; + startTime = ReactSharedInternals.T; + ReactSharedInternals.T = null; + endTime = ReactDOMSharedInternals.p; + ReactDOMSharedInternals.p = DiscreteEventPriority; + hydrationFailed = executionContext; + executionContext |= CommitContext; + try { + didWarnForRootClone || + ((didWarnForRootClone = !0), + console.warn( + "startGestureTransition() caused something to mutate or relayout the root. This currently requires a clone of the whole document. Make sure to add a directly around an absolutely positioned DOM node to minimize the impact of any changes caused by the Gesture Transition." + )); + var rootContainer = root.containerInfo, + documentElement = + 9 === rootContainer.nodeType + ? rootContainer.documentElement + : rootContainer.ownerDocument.documentElement; + null !== documentElement && + "" === documentElement.style.viewTransitionName && + (documentElement.style.viewTransitionName = "none"); + var containerInstance = + 9 === rootContainer.nodeType + ? rootContainer.body + : "HTML" === rootContainer.nodeName + ? rootContainer.ownerDocument.body + : rootContainer; + var containerParent = containerInstance.parentNode; + if (null === containerParent) + throw Error( + "Cannot use a startGestureTransition() on a detached root." + ); + var clone = containerInstance.cloneNode(!1), + computedStyle = getComputedStyle(containerInstance); + if ( + "absolute" !== computedStyle.position && + "fixed" !== computedStyle.position + ) { + for ( + rootContainer = containerParent; + null != rootContainer.parentNode && + 9 !== rootContainer.parentNode.nodeType && + "static" === getComputedStyle(rootContainer).position; + + ) + rootContainer = rootContainer.parentNode; + var positionedAncestorStyle = rootContainer.style, + containerInstanceStyle = containerInstance.style, + prevAncestorTranslate = positionedAncestorStyle.translate, + prevAncestorScale = positionedAncestorStyle.scale, + prevAncestorRotate = positionedAncestorStyle.rotate, + prevAncestorTransform = positionedAncestorStyle.transform, + prevTranslate = containerInstanceStyle.translate, + prevScale = containerInstanceStyle.scale, + prevRotate = containerInstanceStyle.rotate, + prevTransform = containerInstanceStyle.transform; + positionedAncestorStyle.translate = "none"; + positionedAncestorStyle.scale = "none"; + positionedAncestorStyle.rotate = "none"; + positionedAncestorStyle.transform = "none"; + containerInstanceStyle.translate = "none"; + containerInstanceStyle.scale = "none"; + containerInstanceStyle.rotate = "none"; + containerInstanceStyle.transform = "none"; + var ancestorRect = rootContainer.getBoundingClientRect(), + rect = containerInstance.getBoundingClientRect(), + cloneStyle = clone.style; + cloneStyle.position = "absolute"; + cloneStyle.top = rect.top - ancestorRect.top + "px"; + cloneStyle.left = rect.left - ancestorRect.left + "px"; + cloneStyle.width = rect.width + "px"; + cloneStyle.height = rect.height + "px"; + cloneStyle.margin = "0px"; + cloneStyle.boxSizing = "border-box"; + positionedAncestorStyle.translate = prevAncestorTranslate; + positionedAncestorStyle.scale = prevAncestorScale; + positionedAncestorStyle.rotate = prevAncestorRotate; + positionedAncestorStyle.transform = prevAncestorTransform; + containerInstanceStyle.translate = prevTranslate; + containerInstanceStyle.scale = prevScale; + containerInstanceStyle.rotate = prevRotate; + containerInstanceStyle.transform = prevTransform; + } + clone.style.viewTransitionName = "root"; + var transform = computedStyle.transform; + "none" === transform && (transform = ""); + var scale = computedStyle.scale; + if ("none" !== scale && "" !== scale) { + var parts = scale.split(" "); + transform = + (3 === parts.length ? "scale3d" : "scale") + + "(" + + parts.join(", ") + + ") " + + transform; + } + var rotate = computedStyle.rotate; + if ("none" !== rotate && "" !== rotate) { + var _parts = rotate.split(" "); + transform = + 1 === _parts.length + ? "rotate(" + _parts[0] + ") " + transform + : 2 === _parts.length + ? "rotate" + + _parts[0].toUpperCase() + + "(" + + _parts[1] + + ") " + + transform + : "rotate3d(" + _parts.join(", ") + ") " + transform; + } + var translate = computedStyle.translate; + if ("none" !== translate && "" !== translate) { + var _parts2 = translate.split(" "); + transform = + (3 === _parts2.length ? "translate3d" : "translate") + + "(" + + _parts2.join(", ") + + ") " + + transform; + } + var transform$jscomp$0 = transform; + clone.style.translate = "none"; + clone.style.scale = "none"; + clone.style.rotate = "none"; + clone.style.transform = + "translate(-20000px, -20000px) " + transform$jscomp$0; + containerInstance.parentNode.insertBefore( + clone, + containerInstance.nextSibling + ); + root.gestureClone = clone; + recursivelyInsertClones( + finishedWork, + clone, + null, + CLONE_UPDATE + ); + } finally { + (executionContext = hydrationFailed), + (ReactDOMSharedInternals.p = endTime), + (ReactSharedInternals.T = startTime); + } + pendingTransitionTypes = suspendedCommitReason.types; + pendingEffectsStatus = PENDING_GESTURE_MUTATION_PHASE; + pendingViewTransition = suspendedCommitReason.running = + startGestureTransition( + suspendedState, + root.containerInfo, + suspendedCommitReason.provider, + suspendedCommitReason.rangeStart, + suspendedCommitReason.rangeEnd, + pendingTransitionTypes, + flushGestureMutations, + flushGestureAnimations, + reportViewTransitionError, + finishedViewTransition.bind(null, pendingEffectsLanes) + ); } - } - finishedWork = shouldStartViewTransition; - null !== root.stoppingGestures && - (stopCompletedGestures(root), (finishedWork = !1)); - pendingEffectsStatus = PENDING_MUTATION_PHASE; - finishedWork - ? ((animatingLanes |= lanes), - (animatingTask = null), - (pendingViewTransition = startViewTransition( - suspendedState, - root.containerInfo, - pendingTransitionTypes, - flushMutationEffects, - flushLayoutEffects, - flushAfterMutationEffects, - flushSpawnedWork, - flushPassiveEffects, - reportViewTransitionError, - suspendedViewTransition, - finishedViewTransition.bind(null, lanes) - ))) - : (flushMutationEffects(), - flushLayoutEffects(), - flushSpawnedWork()); + else + finalizeRender(lanes, completedRenderEndTime), + (pendingFinishedWork = pendingEffectsRoot = null), + (pendingEffectsLanes = 0); + root.cancelPendingCommit = scheduleGestureCommit( + debugTask, + completeRoot.bind( + null, + root, + finishedWork, + lanes, + recoverableErrors, + transitions, + didIncludeRenderPhaseUpdate, + spawnedLane, + updatedLanes, + suspendedRetryLanes, + didSkipSuspendedSiblings, + exitStatus, + suspendedState, + "Waiting for the Gesture to finish", + completedRenderStartTime, + completedRenderEndTime + ) + ); + return; } + commitRoot( + root, + finishedWork, + lanes, + spawnedLane, + updatedLanes, + suspendedRetryLanes, + suspendedState, + suspendedCommitReason, + completedRenderEndTime + ); } } + function commitRoot( + root, + finishedWork, + lanes, + spawnedLane, + updatedLanes, + suspendedRetryLanes, + suspendedState, + suspendedCommitReason, + completedRenderEndTime + ) { + var remainingLanes = finishedWork.lanes | finishedWork.childLanes; + pendingEffectsRemainingLanes = remainingLanes; + remainingLanes |= concurrentlyUpdatedLanes; + null === root.pendingGestures && + (0 !== (remainingLanes & 64) && + ((gestureUpdateTime = -1.1), + (gestureUpdateType = 0), + (gestureSuspendedTime = -1.1), + (gestureEventRepeatTime = gestureEventTime), + (gestureEventTime = -1.1)), + (remainingLanes &= -65)); + markRootFinished( + root, + lanes, + remainingLanes, + spawnedLane, + updatedLanes, + suspendedRetryLanes + ); + pendingViewTransitionEvents = null; + (lanes & 335544064) === lanes + ? ((pendingTransitionTypes = claimQueuedTransitionTypes(root)), + (spawnedLane = 10262)) + : ((pendingTransitionTypes = null), (spawnedLane = 10256)); + 0 !== finishedWork.actualDuration || + 0 !== (finishedWork.subtreeFlags & spawnedLane) || + 0 !== (finishedWork.flags & spawnedLane) + ? ((root.callbackNode = null), + (root.callbackPriority = 0), + scheduleCallback$1(NormalPriority$1, function () { + schedulerEvent = window.event; + pendingDelayedCommitReason === IMMEDIATE_COMMIT && + (pendingDelayedCommitReason = DELAYED_PASSIVE_COMMIT); + flushPassiveEffects(); + return null; + })) + : ((root.callbackNode = null), (root.callbackPriority = 0)); + commitErrors = null; + commitStartTime = now(); + null !== suspendedCommitReason && + logSuspendedCommitPhase( + completedRenderEndTime, + commitStartTime, + suspendedCommitReason, + workInProgressUpdateTask + ); + shouldStartViewTransition = !1; + suspendedCommitReason = 0 !== (finishedWork.flags & 13878); + if (0 !== (finishedWork.subtreeFlags & 13878) || suspendedCommitReason) { + suspendedCommitReason = ReactSharedInternals.T; + ReactSharedInternals.T = null; + completedRenderEndTime = ReactDOMSharedInternals.p; + ReactDOMSharedInternals.p = DiscreteEventPriority; + spawnedLane = executionContext; + executionContext |= CommitContext; + try { + commitBeforeMutationEffects(root, finishedWork, lanes); + } finally { + (executionContext = spawnedLane), + (ReactDOMSharedInternals.p = completedRenderEndTime), + (ReactSharedInternals.T = suspendedCommitReason); + } + } + 64 === lanes && stopCommittedGesture(root); + pendingEffectsStatus = PENDING_MUTATION_PHASE; + shouldStartViewTransition + ? ((animatingLanes |= lanes), + (animatingTask = null), + (pendingViewTransition = startViewTransition( + suspendedState, + root.containerInfo, + pendingTransitionTypes, + flushMutationEffects, + flushLayoutEffects, + flushAfterMutationEffects, + flushSpawnedWork, + flushPassiveEffects, + reportViewTransitionError, + suspendedViewTransition, + finishedViewTransition.bind(null, lanes) + ))) + : (flushMutationEffects(), flushLayoutEffects(), flushSpawnedWork()); + } function reportViewTransitionError(error) { if (pendingEffectsStatus !== NO_PENDING_EFFECTS) { var onRecoverableError = pendingEffectsRoot.onRecoverableError; @@ -20863,172 +21112,6 @@ flushSyncWorkAcrossRoots_impl(0, !1); } } - function commitGestureOnRoot( - root, - finishedWork, - recoverableErrors, - suspendedState - ) { - recoverableErrors = root.pendingGestures; - if (null === recoverableErrors) ensureRootIsScheduled(root); - else { - deleteScheduledGesture(root, recoverableErrors); - animatingLanes |= pendingEffectsLanes; - animatingTask = null; - var prevTransition = ReactSharedInternals.T; - ReactSharedInternals.T = null; - var previousPriority = ReactDOMSharedInternals.p; - ReactDOMSharedInternals.p = DiscreteEventPriority; - var prevExecutionContext = executionContext; - executionContext |= CommitContext; - try { - didWarnForRootClone || - ((didWarnForRootClone = !0), - console.warn( - "startGestureTransition() caused something to mutate or relayout the root. This currently requires a clone of the whole document. Make sure to add a directly around an absolutely positioned DOM node to minimize the impact of any changes caused by the Gesture Transition." - )); - var rootContainer = root.containerInfo, - documentElement = - 9 === rootContainer.nodeType - ? rootContainer.documentElement - : rootContainer.ownerDocument.documentElement; - null !== documentElement && - "" === documentElement.style.viewTransitionName && - (documentElement.style.viewTransitionName = "none"); - var containerInstance = - 9 === rootContainer.nodeType - ? rootContainer.body - : "HTML" === rootContainer.nodeName - ? rootContainer.ownerDocument.body - : rootContainer; - var containerParent = containerInstance.parentNode; - if (null === containerParent) - throw Error( - "Cannot use a startGestureTransition() on a detached root." - ); - var clone = containerInstance.cloneNode(!1), - computedStyle = getComputedStyle(containerInstance); - if ( - "absolute" !== computedStyle.position && - "fixed" !== computedStyle.position - ) { - for ( - rootContainer = containerParent; - null != rootContainer.parentNode && - 9 !== rootContainer.parentNode.nodeType && - "static" === getComputedStyle(rootContainer).position; - - ) - rootContainer = rootContainer.parentNode; - var positionedAncestorStyle = rootContainer.style, - containerInstanceStyle = containerInstance.style, - prevAncestorTranslate = positionedAncestorStyle.translate, - prevAncestorScale = positionedAncestorStyle.scale, - prevAncestorRotate = positionedAncestorStyle.rotate, - prevAncestorTransform = positionedAncestorStyle.transform, - prevTranslate = containerInstanceStyle.translate, - prevScale = containerInstanceStyle.scale, - prevRotate = containerInstanceStyle.rotate, - prevTransform = containerInstanceStyle.transform; - positionedAncestorStyle.translate = "none"; - positionedAncestorStyle.scale = "none"; - positionedAncestorStyle.rotate = "none"; - positionedAncestorStyle.transform = "none"; - containerInstanceStyle.translate = "none"; - containerInstanceStyle.scale = "none"; - containerInstanceStyle.rotate = "none"; - containerInstanceStyle.transform = "none"; - var ancestorRect = rootContainer.getBoundingClientRect(), - rect = containerInstance.getBoundingClientRect(), - cloneStyle = clone.style; - cloneStyle.position = "absolute"; - cloneStyle.top = rect.top - ancestorRect.top + "px"; - cloneStyle.left = rect.left - ancestorRect.left + "px"; - cloneStyle.width = rect.width + "px"; - cloneStyle.height = rect.height + "px"; - cloneStyle.margin = "0px"; - cloneStyle.boxSizing = "border-box"; - positionedAncestorStyle.translate = prevAncestorTranslate; - positionedAncestorStyle.scale = prevAncestorScale; - positionedAncestorStyle.rotate = prevAncestorRotate; - positionedAncestorStyle.transform = prevAncestorTransform; - containerInstanceStyle.translate = prevTranslate; - containerInstanceStyle.scale = prevScale; - containerInstanceStyle.rotate = prevRotate; - containerInstanceStyle.transform = prevTransform; - } - clone.style.viewTransitionName = "root"; - var transform = computedStyle.transform; - "none" === transform && (transform = ""); - var scale = computedStyle.scale; - if ("none" !== scale && "" !== scale) { - var parts = scale.split(" "); - transform = - (3 === parts.length ? "scale3d" : "scale") + - "(" + - parts.join(", ") + - ") " + - transform; - } - var rotate = computedStyle.rotate; - if ("none" !== rotate && "" !== rotate) { - var _parts = rotate.split(" "); - transform = - 1 === _parts.length - ? "rotate(" + _parts[0] + ") " + transform - : 2 === _parts.length - ? "rotate" + - _parts[0].toUpperCase() + - "(" + - _parts[1] + - ") " + - transform - : "rotate3d(" + _parts.join(", ") + ") " + transform; - } - var translate = computedStyle.translate; - if ("none" !== translate && "" !== translate) { - var _parts2 = translate.split(" "); - transform = - (3 === _parts2.length ? "translate3d" : "translate") + - "(" + - _parts2.join(", ") + - ") " + - transform; - } - var transform$jscomp$0 = transform; - clone.style.translate = "none"; - clone.style.scale = "none"; - clone.style.rotate = "none"; - clone.style.transform = - "translate(-20000px, -20000px) " + transform$jscomp$0; - containerInstance.parentNode.insertBefore( - clone, - containerInstance.nextSibling - ); - root.gestureClone = clone; - recursivelyInsertClones(finishedWork, clone, null, CLONE_UPDATE); - } finally { - (executionContext = prevExecutionContext), - (ReactDOMSharedInternals.p = previousPriority), - (ReactSharedInternals.T = prevTransition); - } - pendingTransitionTypes = recoverableErrors.types; - pendingEffectsStatus = PENDING_GESTURE_MUTATION_PHASE; - pendingViewTransition = recoverableErrors.running = - startGestureTransition( - suspendedState, - root.containerInfo, - recoverableErrors.provider, - recoverableErrors.rangeStart, - recoverableErrors.rangeEnd, - pendingTransitionTypes, - flushGestureMutations, - flushGestureAnimations, - reportViewTransitionError, - finishedViewTransition.bind(null, pendingEffectsLanes) - ); - } - } function flushGestureMutations() { if (pendingEffectsStatus === PENDING_GESTURE_MUTATION_PHASE) { pendingEffectsStatus = NO_PENDING_EFFECTS; @@ -21084,16 +21167,42 @@ (ReactDOMSharedInternals.p = previousPriority), (ReactSharedInternals.T = prevTransition); } + commitEndTime = now(); + root = pendingEffectsRenderEndTime; + prevTransition = commitEndTime; + !supportsUserTiming || + prevTransition <= root || + (animatingTask + ? animatingTask.run( + console.timeStamp.bind( + console, + "Create Ghost Tree", + root, + prevTransition, + currentTrack, + LANES_TRACK_GROUP, + "secondary-dark" + ) + ) + : console.timeStamp( + "Create Ghost Tree", + root, + prevTransition, + currentTrack, + LANES_TRACK_GROUP, + "secondary-dark" + )); pendingEffectsStatus = PENDING_GESTURE_ANIMATION_PHASE; } } function flushGestureAnimations() { flushGestureMutations(); if (pendingEffectsStatus === PENDING_GESTURE_ANIMATION_PHASE) { - var lanes = pendingEffectsLanes; + var lanes = pendingEffectsLanes, + startViewTransitionStartTime = commitEndTime; commitEndTime = now(); logStartViewTransitionYieldPhase( - pendingEffectsRenderEndTime, + startViewTransitionStartTime, commitEndTime, pendingDelayedCommitReason === ABORTED_VIEW_TRANSITION_COMMIT, animatingTask @@ -21101,8 +21210,8 @@ pendingDelayedCommitReason !== ABORTED_VIEW_TRANSITION_COMMIT && (pendingDelayedCommitReason = ANIMATION_STARTED_COMMIT); pendingEffectsStatus = NO_PENDING_EFFECTS; - var root = pendingEffectsRoot, - finishedWork = pendingFinishedWork; + startViewTransitionStartTime = pendingEffectsRoot; + var finishedWork = pendingFinishedWork; pendingFinishedWork = pendingEffectsRoot = null; pendingEffectsLanes = 0; pendingViewTransition = null; @@ -21114,14 +21223,16 @@ executionContext |= CommitContext; try { restoreViewTransitionsOnFiber(finishedWork), - restoreRootViewTransitionName(root.containerInfo); + restoreRootViewTransitionName( + startViewTransitionStartTime.containerInfo + ); } finally { (executionContext = prevExecutionContext), (ReactDOMSharedInternals.p = previousPriority), (ReactSharedInternals.T = prevTransition); } finalizeRender(lanes, commitEndTime); - ensureRootIsScheduled(root); + ensureRootIsScheduled(startViewTransitionStartTime); } } function makeErrorInfo(componentStack) { @@ -21384,8 +21495,7 @@ function pingSuspendedRoot(root, wakeable, pingedLanes) { var pingCache = root.pingCache; null !== pingCache && pingCache.delete(wakeable); - root.pingedLanes |= root.suspendedLanes & pingedLanes; - root.warmLanes &= ~pingedLanes; + markRootPinged$1(root, pingedLanes); 64 === pingedLanes ? 0 > gestureUpdateTime && ((gestureClampTime = gestureUpdateTime = now()), @@ -26159,6 +26269,14 @@ new: new ViewTransitionPseudoElement("new", name) }; } + function getCurrentGestureOffset(timeline) { + timeline = timeline.currentTime; + if (null === timeline) + throw Error( + "Cannot start a gesture with a disconnected AnimationTimeline." + ); + return "number" === typeof timeline ? timeline : timeline.value; + } function FragmentInstance(fragmentFiber) { this._fragmentFiber = fragmentFiber; this._observers = this._eventListeners = null; @@ -27500,11 +27618,7 @@ this.pooledCache = this.pendingIndicator = null; this.pooledCacheLanes = 0; this.formState = formState; - this.gestureClone = - this.stoppingGestures = - this.pendingGestures = - this.transitionTypes = - null; + this.gestureClone = this.pendingGestures = this.transitionTypes = null; this.incompleteTransitions = new Map(); this.passiveEffectDuration = this.effectDuration = -0; this.memoizedUpdaters = new Set(); @@ -32505,11 +32619,11 @@ }; (function () { var isomorphicReactPackageVersion = React.version; - if ("19.3.0-experimental-65eec428-20251218" !== isomorphicReactPackageVersion) + if ("19.3.0-experimental-bef88f7c-20260116" !== isomorphicReactPackageVersion) throw Error( 'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' + (isomorphicReactPackageVersion + - "\n - react-dom: 19.3.0-experimental-65eec428-20251218\nLearn more: https://react.dev/warnings/version-mismatch") + "\n - react-dom: 19.3.0-experimental-bef88f7c-20260116\nLearn more: https://react.dev/warnings/version-mismatch") ); })(); ("function" === typeof Map && @@ -32546,10 +32660,10 @@ !(function () { var internals = { bundleType: 1, - version: "19.3.0-experimental-65eec428-20251218", + version: "19.3.0-experimental-bef88f7c-20260116", rendererPackageName: "react-dom", currentDispatcherRef: ReactSharedInternals, - reconcilerVersion: "19.3.0-experimental-65eec428-20251218" + reconcilerVersion: "19.3.0-experimental-bef88f7c-20260116" }; internals.overrideHookState = overrideHookState; internals.overrideHookStateDeletePath = overrideHookStateDeletePath; @@ -33027,7 +33141,7 @@ exports.useFormStatus = function () { return resolveDispatcher().useHostTransitionStatus(); }; - exports.version = "19.3.0-experimental-65eec428-20251218"; + exports.version = "19.3.0-experimental-bef88f7c-20260116"; "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-profiling.profiling.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-profiling.profiling.js index 668d994059a1..234632dc3279 100644 --- a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-profiling.profiling.js +++ b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-profiling.profiling.js @@ -887,6 +887,10 @@ function markRootUpdated$1(root, updateLane) { 268435456 !== updateLane && ((root.suspendedLanes = 0), (root.pingedLanes = 0), (root.warmLanes = 0)); } +function markRootPinged$1(root, pingedLanes) { + root.pingedLanes |= root.suspendedLanes & pingedLanes; + root.warmLanes &= ~pingedLanes; +} function markRootFinished( root, finishedLanes, @@ -2891,7 +2895,7 @@ function createWorkInProgress(current, pendingProps) { (workInProgress.key = current.key), (workInProgress.actualDuration = -0), (workInProgress.actualStartTime = -1.1)); - workInProgress.flags = current.flags & 132120576; + workInProgress.flags = current.flags & 133169152; workInProgress.childLanes = current.childLanes; workInProgress.lanes = current.lanes; workInProgress.child = current.child; @@ -2912,7 +2916,7 @@ function createWorkInProgress(current, pendingProps) { return workInProgress; } function resetWorkInProgress(workInProgress, renderLanes) { - workInProgress.flags &= 132120578; + workInProgress.flags &= 133169154; var current = workInProgress.alternate; null === current ? ((workInProgress.childLanes = 0), @@ -3844,36 +3848,30 @@ function startScheduledGesture( gestureOptions, transitionTypes ) { - if (gestureOptions && null != gestureOptions.rangeStart) - var JSCompiler_temp = gestureOptions.rangeStart; - else { - JSCompiler_temp = gestureTimeline.currentTime; - if (null === JSCompiler_temp) throw Error(formatProdErrorMessage(549)); - JSCompiler_temp = - "number" === typeof JSCompiler_temp - ? JSCompiler_temp - : JSCompiler_temp.value; - } + var rangeStart = + gestureOptions && null != gestureOptions.rangeStart + ? gestureOptions.rangeStart + : getCurrentGestureOffset(gestureTimeline); gestureOptions = gestureOptions && null != gestureOptions.rangeEnd ? gestureOptions.rangeEnd - : 50 > JSCompiler_temp + : 50 > rangeStart ? 100 : 0; for (root = root.pendingGestures; null !== root; ) { if (root.provider === gestureTimeline) { root.count++; - root.rangeStart = JSCompiler_temp; + root.rangeStart = rangeStart; root.rangeEnd = gestureOptions; if (null !== transitionTypes) for ( gestureTimeline = root.types, null === gestureTimeline && (gestureTimeline = root.types = []), - JSCompiler_temp = 0; - JSCompiler_temp < transitionTypes.length; - JSCompiler_temp++ + rangeStart = 0; + rangeStart < transitionTypes.length; + rangeStart++ ) - (gestureOptions = transitionTypes[JSCompiler_temp]), + (gestureOptions = transitionTypes[rangeStart]), -1 === gestureTimeline.indexOf(gestureOptions) && gestureTimeline.push(gestureOptions); return root; @@ -3883,27 +3881,24 @@ function startScheduledGesture( } return null; } -function deleteScheduledGesture(root, gesture) { - null === gesture.prev - ? (root.pendingGestures === gesture && - ((root.pendingGestures = gesture.next), - null === root.pendingGestures && (root.pendingLanes &= -65)), - root.stoppingGestures === gesture && - (root.stoppingGestures = gesture.next)) - : ((gesture.prev.next = gesture.next), - null !== gesture.next && (gesture.next.prev = gesture.prev), - (gesture.prev = null), - (gesture.next = null)); -} -function stopCompletedGestures(root) { - var gesture = root.stoppingGestures; - for (root.stoppingGestures = null; null !== gesture; ) - null !== gesture.running && - (gesture.running.skipTransition(), (gesture.running = null)), - (root = gesture.next), - (gesture.next = null), - (gesture.prev = null), - (gesture = root); +function stopCommittedGesture(root) { + var committedGesture = root.pendingGestures; + if (null !== committedGesture) { + committedGesture.committing = !1; + var nextGesture = committedGesture.next; + null === nextGesture + ? (root.pendingLanes &= -65) + : (nextGesture.prev = null); + root.pendingGestures = nextGesture; + root = committedGesture.running; + null !== root && ((committedGesture.running = null), root.skipTransition()); + } +} +function scheduleGestureCommit(gesture, callback) { + gesture.commit = callback; + return function () { + gesture.commit = null; + }; } var prevOnStartTransitionFinish = ReactSharedInternals.S; ReactSharedInternals.S = function (transition, returnValue) { @@ -3951,23 +3946,52 @@ ReactSharedInternals.S = function (transition, returnValue) { }; function chainGestureCancellation(root, scheduledGesture, prevCancel) { return function () { - if ( - null !== scheduledGesture && - (scheduledGesture.count--, 0 === scheduledGesture.count) - ) { - deleteScheduledGesture(root, scheduledGesture); - var runningTransition = scheduledGesture.running; - if (null !== runningTransition) { - var pendingLanesExcludingGestureLane = root.pendingLanes & -65; - 0 !== (pendingLanesExcludingGestureLane & 127) || - 0 !== (pendingLanesExcludingGestureLane & 4194048) - ? ((runningTransition = root.stoppingGestures), - null !== runningTransition && - ((scheduledGesture.next = runningTransition), - (runningTransition.prev = scheduledGesture)), - (root.stoppingGestures = scheduledGesture)) - : ((scheduledGesture.running = null), - runningTransition.skipTransition()); + if (null !== scheduledGesture) { + if (0 !== scheduledGesture.revertLane) { + var entangledLanes = + scheduledGesture.revertLane | requestTransitionLane(); + markRootEntangled(root, entangledLanes); + } + scheduledGesture.count--; + if (0 === scheduledGesture.count) { + var finalOffset = getCurrentGestureOffset(scheduledGesture.provider), + rangeStart = scheduledGesture.rangeStart, + rangeEnd = scheduledGesture.rangeEnd; + entangledLanes = scheduledGesture.running; + null !== entangledLanes && + (rangeStart < rangeEnd + ? finalOffset > rangeStart + (rangeEnd - rangeStart) / 2 + : finalOffset < rangeEnd + (rangeStart - rangeEnd) / 2) + ? ((scheduledGesture.committing = !0), + root.pendingGestures === scheduledGesture && + ((entangledLanes = scheduledGesture.commit), + null !== entangledLanes + ? ((scheduledGesture.commit = null), entangledLanes()) + : null !== root.pendingGestures && + (markRootPinged$1(root, 64), ensureRootIsScheduled(root)))) + : null === scheduledGesture.prev + ? (root.pendingGestures === scheduledGesture && + ((root.pendingGestures = scheduledGesture.next), + (finalOffset = root.pendingLanes), + null === root.pendingGestures && (finalOffset &= -65), + markRootFinished(root, 64, finalOffset, 0, 0, 0), + workInProgressRoot === root && + 64 === workInProgressRootRenderLanes + ? 0 === (executionContext & 2) && prepareFreshStack(root, 0) + : null !== root.cancelPendingCommit && + 64 === pendingEffectsLanes && + ((finalOffset = root.cancelPendingCommit), + null !== finalOffset && + ((root.cancelPendingCommit = null), finalOffset())), + null !== root.pendingGestures && markRootPinged$1(root, 64), + ensureRootIsScheduled(root)), + (scheduledGesture.running = null), + null !== entangledLanes && entangledLanes.skipTransition()) + : ((scheduledGesture.prev.next = scheduledGesture.next), + null !== scheduledGesture.next && + (scheduledGesture.next.prev = scheduledGesture.prev), + (scheduledGesture.prev = null), + (scheduledGesture.next = null)); } } null !== prevCancel && prevCancel(); @@ -5484,16 +5508,18 @@ function updateReducerImpl(hook, current, reducer) { if (64 === updateLane) { var scheduledGesture = update.gesture; if (null !== scheduledGesture) - if (0 === scheduledGesture.count) { + if (0 !== scheduledGesture.count || scheduledGesture.committing) + if (64 === renderLanes) { + shouldSkipUpdate = workInProgressRoot; + if (null === shouldSkipUpdate) + throw Error(formatProdErrorMessage(349)); + shouldSkipUpdate = + shouldSkipUpdate.pendingGestures !== scheduledGesture; + } else shouldSkipUpdate = !0; + else { update = update.next; continue; - } else if (64 === renderLanes) { - shouldSkipUpdate = workInProgressRoot; - if (null === shouldSkipUpdate) - throw Error(formatProdErrorMessage(349)); - shouldSkipUpdate = - shouldSkipUpdate.pendingGestures !== scheduledGesture; - } else shouldSkipUpdate = !0; + } } if (shouldSkipUpdate) (scheduledGesture = { @@ -6116,7 +6142,7 @@ function updateDeferredValueImpl(hook, prevValue, value, initialValue) { hook ); if ( - 0 === (renderLanes & 42) || + 0 === (renderLanes & 106) || (0 !== (renderLanes & 1073741824) && 0 === (workInProgressRootRenderLanes & 261930)) ) @@ -6387,6 +6413,9 @@ function dispatchOptimisticSetState(fiber, throwIfDuringRender, queue, action) { rangeEnd: 100, types: null, running: null, + commit: null, + committing: !1, + revertLane: 0, prev: fiber, next: null }; @@ -6396,7 +6425,10 @@ function dispatchOptimisticSetState(fiber, throwIfDuringRender, queue, action) { ensureRootIsScheduled(throwIfDuringRender); throwIfDuringRender = transition; } - action.gesture = throwIfDuringRender; + throwIfDuringRender = action.gesture = throwIfDuringRender; + 0 === throwIfDuringRender.revertLane + ? (throwIfDuringRender.revertLane = action.revertLane) + : (action.revertLane = throwIfDuringRender.revertLane); } } function isRenderPhaseUpdate(fiber) { @@ -8024,7 +8056,7 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { mode: "hidden", children: nextProps.children })), - (nextProps.subtreeFlags = nextFallbackChildren.subtreeFlags & 132120576), + (nextProps.subtreeFlags = nextFallbackChildren.subtreeFlags & 133169152), null !== digest ? (nextPrimaryChildren = createWorkInProgress( digest, @@ -9026,8 +9058,8 @@ function bubbleProperties(completedWork) { ) (newChildLanes |= child$130.lanes | child$130.childLanes), - (subtreeFlags |= child$130.subtreeFlags & 132120576), - (subtreeFlags |= child$130.flags & 132120576), + (subtreeFlags |= child$130.subtreeFlags & 133169152), + (subtreeFlags |= child$130.flags & 133169152), (treeBaseDuration$129 += child$130.treeBaseDuration), (child$130 = child$130.sibling); completedWork.treeBaseDuration = treeBaseDuration$129; @@ -9039,8 +9071,8 @@ function bubbleProperties(completedWork) { ) (newChildLanes |= treeBaseDuration$129.lanes | treeBaseDuration$129.childLanes), - (subtreeFlags |= treeBaseDuration$129.subtreeFlags & 132120576), - (subtreeFlags |= treeBaseDuration$129.flags & 132120576), + (subtreeFlags |= treeBaseDuration$129.subtreeFlags & 133169152), + (subtreeFlags |= treeBaseDuration$129.flags & 133169152), (treeBaseDuration$129.return = completedWork), (treeBaseDuration$129 = treeBaseDuration$129.sibling); else if (0 !== (completedWork.mode & 2)) { @@ -10560,7 +10592,9 @@ function measureViewTransitionHostInstancesRecursive( (viewTransitionCancelableChildren = []), viewTransitionCancelableChildren.push( instance, - oldName, + 0 === viewTransitionHostInstanceIdx + ? oldName + : oldName + "_" + viewTransitionHostInstanceIdx, child.memoizedProps )); viewTransitionHostInstanceIdx++; @@ -14208,7 +14242,7 @@ function performWorkOnRoot(root$jscomp$0, lanes, forceSync) { if (0 !== getNextLanes(yieldEndTime, 0, !0)) break a; pendingEffectsLanes = lanes; yieldEndTime.timeoutHandle = scheduleTimeout( - commitRootWhenReady.bind( + completeRootWhenReady.bind( null, yieldEndTime, forceSync, @@ -14229,7 +14263,7 @@ function performWorkOnRoot(root$jscomp$0, lanes, forceSync) { ); break a; } - commitRootWhenReady( + completeRootWhenReady( yieldEndTime, forceSync, workInProgressRootRecoverableErrors, @@ -14251,7 +14285,7 @@ function performWorkOnRoot(root$jscomp$0, lanes, forceSync) { } while (1); ensureRootIsScheduled(root$jscomp$0); } -function commitRootWhenReady( +function completeRootWhenReady( root, finishedWork, recoverableErrors, @@ -14277,23 +14311,26 @@ function commitRootWhenReady( subtreeFlags & 8192 || 16785408 === (subtreeFlags & 16785408) || isGestureTransition - ) + ) { + suspendedState = { + stylesheets: null, + count: 0, + imgCount: 0, + imgBytes: 0, + suspenseyImages: [], + waitingForImages: !0, + waitingForViewTransition: !1, + unsuspend: noop$1 + }; + appearingViewTransitions = null; + accumulateSuspenseyCommitOnFiber(finishedWork, lanes, suspendedState); if ( - ((suspendedState = { - stylesheets: null, - count: 0, - imgCount: 0, - imgBytes: 0, - suspenseyImages: [], - waitingForImages: !0, - waitingForViewTransition: !1, - unsuspend: noop$1 - }), - (appearingViewTransitions = null), - accumulateSuspenseyCommitOnFiber(finishedWork, lanes, suspendedState), - (isViewTransitionEligible || isGestureTransition) && - null === root.stoppingGestures && - ((subtreeFlags = suspendedState), + isViewTransitionEligible || + (isGestureTransition && + null !== root.pendingGestures && + null === root.pendingGestures.running) + ) + (subtreeFlags = suspendedState), (isViewTransitionEligible = root.containerInfo), (isViewTransitionEligible = ( 9 === isViewTransitionEligible.nodeType @@ -14304,19 +14341,18 @@ function commitRootWhenReady( (subtreeFlags.count++, (subtreeFlags.waitingForViewTransition = !0), (subtreeFlags = onUnsuspend.bind(subtreeFlags)), - isViewTransitionEligible.finished.then(subtreeFlags, subtreeFlags))), - (subtreeFlags = - (lanes & 62914560) === lanes - ? globalMostRecentFallbackTime - now$1() - : (lanes & 4194048) === lanes - ? globalMostRecentTransitionTime - now$1() - : 0), - (subtreeFlags = waitForCommitToBeReady(suspendedState, subtreeFlags)), - null !== subtreeFlags) - ) { + isViewTransitionEligible.finished.then(subtreeFlags, subtreeFlags)); + subtreeFlags = + (lanes & 62914560) === lanes + ? globalMostRecentFallbackTime - now$1() + : (lanes & 4194048) === lanes + ? globalMostRecentTransitionTime - now$1() + : 0; + subtreeFlags = waitForCommitToBeReady(suspendedState, subtreeFlags); + if (null !== subtreeFlags) { pendingEffectsLanes = lanes; root.cancelPendingCommit = subtreeFlags( - commitRoot.bind( + completeRoot.bind( null, root, finishedWork, @@ -14327,6 +14363,7 @@ function commitRootWhenReady( spawnedLane, updatedLanes, suspendedRetryLanes, + didSkipSuspendedSiblings, exitStatus, suspendedState, suspendedState.waitingForViewTransition @@ -14347,7 +14384,8 @@ function commitRootWhenReady( markRootSuspended(root, lanes, spawnedLane, !didSkipSuspendedSiblings); return; } - commitRoot( + } + completeRoot( root, finishedWork, lanes, @@ -14357,6 +14395,7 @@ function commitRootWhenReady( spawnedLane, updatedLanes, suspendedRetryLanes, + didSkipSuspendedSiblings, exitStatus, suspendedState, suspendedCommitReason, @@ -15108,6 +15147,14 @@ function replaySuspendedUnitOfWork(unitOfWork) { break; case 5: resetHooksOnUnwind(next); + var fiber = next; + fiber === hydrationParentFiber && + (isHydrating + ? (popToNextHostParent(fiber), + 5 === fiber.tag && + null != fiber.stateNode && + (nextHydratableInstance = fiber.stateNode)) + : (popToNextHostParent(fiber), (isHydrating = !0))); default: unwindInterruptedWork(current, next), (next = workInProgress = @@ -15238,7 +15285,7 @@ function unwindUnitOfWork(unitOfWork, skipSiblings) { workInProgressRootExitStatus = 6; workInProgress = null; } -function commitRoot( +function completeRoot( root, finishedWork, lanes, @@ -15248,6 +15295,7 @@ function commitRoot( spawnedLane, updatedLanes, suspendedRetryLanes, + didSkipSuspendedSiblings, exitStatus, suspendedState, suspendedCommitReason, @@ -15259,146 +15307,352 @@ function commitRoot( while (0 !== pendingEffectsStatus); if (0 !== (executionContext & 6)) throw Error(formatProdErrorMessage(327)); setCurrentTrackFromLanes(lanes); - 2 === exitStatus - ? logErroredRenderPhase(completedRenderStartTime, completedRenderEndTime) - : null !== recoverableErrors - ? !supportsUserTiming || - completedRenderEndTime <= completedRenderStartTime || - console.timeStamp( - "Recovered", - completedRenderStartTime, - completedRenderEndTime, - currentTrack, - "Scheduler \u269b", - "error" - ) - : !supportsUserTiming || - completedRenderEndTime <= completedRenderStartTime || - console.timeStamp( - (lanes & 536870912) === lanes - ? "Prepared" - : (lanes & 201326741) === lanes - ? "Hydrated" - : "Render", - completedRenderStartTime, - completedRenderEndTime, - currentTrack, - "Scheduler \u269b", - (lanes & 738197653) === lanes ? "tertiary-dark" : "primary-dark" - ); - if (null === finishedWork) - null !== root.stoppingGestures && stopCompletedGestures(root); + 64 === lanes && + (completedRenderStartTime < gestureClampTime && + (completedRenderStartTime = gestureClampTime), + completedRenderEndTime < gestureClampTime && + (completedRenderEndTime = gestureClampTime)); + if (2 === exitStatus) + logErroredRenderPhase(completedRenderStartTime, completedRenderEndTime); + else if (null !== recoverableErrors) + !supportsUserTiming || + completedRenderEndTime <= completedRenderStartTime || + console.timeStamp( + "Recovered", + completedRenderStartTime, + completedRenderEndTime, + currentTrack, + "Scheduler \u269b", + "error" + ); + else { + var startTime = completedRenderStartTime, + endTime = completedRenderEndTime; + !supportsUserTiming || + endTime <= startTime || + console.timeStamp( + (lanes & 536870912) === lanes + ? "Prepared" + : (lanes & 201326741) === lanes + ? "Hydrated" + : "Render", + startTime, + endTime, + currentTrack, + "Scheduler \u269b", + (lanes & 738197653) === lanes ? "tertiary-dark" : "primary-dark" + ); + } + if (null === finishedWork) 64 === lanes && stopCommittedGesture(root); else { if (finishedWork === root.current) throw Error(formatProdErrorMessage(177)); - didIncludeRenderPhaseUpdate = finishedWork.lanes | finishedWork.childLanes; - didIncludeRenderPhaseUpdate |= concurrentlyUpdatedLanes; - null === root.pendingGestures && - (0 !== (didIncludeRenderPhaseUpdate & 64) && - ((gestureUpdateTime = -1.1), - (gestureUpdateType = 0), - (gestureSuspendedTime = -1.1), - (gestureEventRepeatTime = gestureEventTime), - (gestureEventTime = -1.1)), - (didIncludeRenderPhaseUpdate &= -65)); - markRootFinished( - root, - lanes, - didIncludeRenderPhaseUpdate, - spawnedLane, - updatedLanes, - suspendedRetryLanes - ); root === workInProgressRoot && ((workInProgress = workInProgressRoot = null), (workInProgressRootRenderLanes = 0)); pendingFinishedWork = finishedWork; pendingEffectsRoot = root; pendingEffectsLanes = lanes; - pendingEffectsRemainingLanes = didIncludeRenderPhaseUpdate; pendingPassiveTransitions = transitions; pendingRecoverableErrors = recoverableErrors; pendingEffectsRenderEndTime = completedRenderEndTime; pendingSuspendedCommitReason = suspendedCommitReason; pendingDelayedCommitReason = 0; pendingSuspendedViewTransitionReason = null; - if (64 === lanes) - commitGestureOnRoot( - root, - finishedWork, - recoverableErrors, - suspendedState - ); - else { - pendingViewTransitionEvents = null; - (lanes & 335544064) === lanes - ? ((pendingTransitionTypes = claimQueuedTransitionTypes(root)), - (recoverableErrors = 10262)) - : ((pendingTransitionTypes = null), (recoverableErrors = 10256)); - 0 !== finishedWork.actualDuration || - 0 !== (finishedWork.subtreeFlags & recoverableErrors) || - 0 !== (finishedWork.flags & recoverableErrors) - ? ((root.callbackNode = null), - (root.callbackPriority = 0), - scheduleCallback$1(NormalPriority$1, function () { - schedulerEvent = window.event; - 0 === pendingDelayedCommitReason && - (pendingDelayedCommitReason = 2); - flushPassiveEffects(); - return null; - })) - : ((root.callbackNode = null), (root.callbackPriority = 0)); - commitErrors = null; - commitStartTime = now(); - null !== suspendedCommitReason && - (!supportsUserTiming || - commitStartTime <= completedRenderEndTime || - console.timeStamp( - suspendedCommitReason, - completedRenderEndTime, - commitStartTime, - currentTrack, - "Scheduler \u269b", - "secondary-light" - )); - shouldStartViewTransition = !1; - suspendedCommitReason = 0 !== (finishedWork.flags & 13878); - if (0 !== (finishedWork.subtreeFlags & 13878) || suspendedCommitReason) { - suspendedCommitReason = ReactSharedInternals.T; - ReactSharedInternals.T = null; - completedRenderEndTime = ReactDOMSharedInternals.p; - ReactDOMSharedInternals.p = 2; - recoverableErrors = executionContext; - executionContext |= 4; - try { - commitBeforeMutationEffects(root, finishedWork, lanes); - } finally { - (executionContext = recoverableErrors), - (ReactDOMSharedInternals.p = completedRenderEndTime), - (ReactSharedInternals.T = suspendedCommitReason); + if ( + 64 === lanes && + ((startTime = root.pendingGestures), + null !== startTime && !startTime.committing) + ) { + markRootSuspended(root, lanes, spawnedLane, !didSkipSuspendedSiblings); + if (null === startTime.running) + if ( + ((suspendedCommitReason = root.pendingGestures), + null === suspendedCommitReason) + ) + ensureRootIsScheduled(root); + else { + animatingLanes |= pendingEffectsLanes; + endTime = ReactSharedInternals.T; + ReactSharedInternals.T = null; + var previousPriority = ReactDOMSharedInternals.p; + ReactDOMSharedInternals.p = 2; + var prevExecutionContext = executionContext; + executionContext |= 4; + try { + var rootContainer = root.containerInfo, + documentElement = + 9 === rootContainer.nodeType + ? rootContainer.documentElement + : rootContainer.ownerDocument.documentElement; + null !== documentElement && + "" === documentElement.style.viewTransitionName && + (documentElement.style.viewTransitionName = "none"); + var containerInstance = + 9 === rootContainer.nodeType + ? rootContainer.body + : "HTML" === rootContainer.nodeName + ? rootContainer.ownerDocument.body + : rootContainer; + var containerParent = containerInstance.parentNode; + if (null === containerParent) + throw Error(formatProdErrorMessage(552)); + var clone = containerInstance.cloneNode(!1), + computedStyle = getComputedStyle(containerInstance); + if ( + "absolute" !== computedStyle.position && + "fixed" !== computedStyle.position + ) { + for ( + rootContainer = containerParent; + null != rootContainer.parentNode && + 9 !== rootContainer.parentNode.nodeType && + "static" === getComputedStyle(rootContainer).position; + + ) + rootContainer = rootContainer.parentNode; + var positionedAncestorStyle = rootContainer.style, + containerInstanceStyle = containerInstance.style, + prevAncestorTranslate = positionedAncestorStyle.translate, + prevAncestorScale = positionedAncestorStyle.scale, + prevAncestorRotate = positionedAncestorStyle.rotate, + prevAncestorTransform = positionedAncestorStyle.transform, + prevTranslate = containerInstanceStyle.translate, + prevScale = containerInstanceStyle.scale, + prevRotate = containerInstanceStyle.rotate, + prevTransform = containerInstanceStyle.transform; + positionedAncestorStyle.translate = "none"; + positionedAncestorStyle.scale = "none"; + positionedAncestorStyle.rotate = "none"; + positionedAncestorStyle.transform = "none"; + containerInstanceStyle.translate = "none"; + containerInstanceStyle.scale = "none"; + containerInstanceStyle.rotate = "none"; + containerInstanceStyle.transform = "none"; + var ancestorRect = rootContainer.getBoundingClientRect(), + rect = containerInstance.getBoundingClientRect(), + cloneStyle = clone.style; + cloneStyle.position = "absolute"; + cloneStyle.top = rect.top - ancestorRect.top + "px"; + cloneStyle.left = rect.left - ancestorRect.left + "px"; + cloneStyle.width = rect.width + "px"; + cloneStyle.height = rect.height + "px"; + cloneStyle.margin = "0px"; + cloneStyle.boxSizing = "border-box"; + positionedAncestorStyle.translate = prevAncestorTranslate; + positionedAncestorStyle.scale = prevAncestorScale; + positionedAncestorStyle.rotate = prevAncestorRotate; + positionedAncestorStyle.transform = prevAncestorTransform; + containerInstanceStyle.translate = prevTranslate; + containerInstanceStyle.scale = prevScale; + containerInstanceStyle.rotate = prevRotate; + containerInstanceStyle.transform = prevTransform; + } + clone.style.viewTransitionName = "root"; + var transform = computedStyle.transform; + "none" === transform && (transform = ""); + var scale = computedStyle.scale; + if ("none" !== scale && "" !== scale) { + var parts = scale.split(" "); + transform = + (3 === parts.length ? "scale3d" : "scale") + + "(" + + parts.join(", ") + + ") " + + transform; + } + var rotate = computedStyle.rotate; + if ("none" !== rotate && "" !== rotate) { + var parts$312 = rotate.split(" "); + transform = + 1 === parts$312.length + ? "rotate(" + parts$312[0] + ") " + transform + : 2 === parts$312.length + ? "rotate" + + parts$312[0].toUpperCase() + + "(" + + parts$312[1] + + ") " + + transform + : "rotate3d(" + parts$312.join(", ") + ") " + transform; + } + var translate = computedStyle.translate; + if ("none" !== translate && "" !== translate) { + var parts$313 = translate.split(" "); + transform = + (3 === parts$313.length ? "translate3d" : "translate") + + "(" + + parts$313.join(", ") + + ") " + + transform; + } + var JSCompiler_inline_result = transform; + clone.style.translate = "none"; + clone.style.scale = "none"; + clone.style.rotate = "none"; + clone.style.transform = + "translate(-20000px, -20000px) " + JSCompiler_inline_result; + containerInstance.parentNode.insertBefore( + clone, + containerInstance.nextSibling + ); + root.gestureClone = clone; + recursivelyInsertClones(finishedWork, clone, null, 0); + } finally { + (executionContext = prevExecutionContext), + (ReactDOMSharedInternals.p = previousPriority), + (ReactSharedInternals.T = endTime); + } + pendingTransitionTypes = suspendedCommitReason.types; + pendingEffectsStatus = 6; + pendingViewTransition = suspendedCommitReason.running = + startGestureTransition( + suspendedState, + root.containerInfo, + suspendedCommitReason.provider, + suspendedCommitReason.rangeStart, + suspendedCommitReason.rangeEnd, + pendingTransitionTypes, + flushGestureMutations, + flushGestureAnimations, + reportViewTransitionError, + finishedViewTransition.bind(null, pendingEffectsLanes) + ); } - } - finishedWork = shouldStartViewTransition; - null !== root.stoppingGestures && - (stopCompletedGestures(root), (finishedWork = !1)); - pendingEffectsStatus = 1; - finishedWork - ? ((animatingLanes |= lanes), - (pendingViewTransition = startViewTransition( - suspendedState, - root.containerInfo, - pendingTransitionTypes, - flushMutationEffects, - flushLayoutEffects, - flushAfterMutationEffects, - flushSpawnedWork, - flushPassiveEffects, - reportViewTransitionError, - suspendedViewTransition, - finishedViewTransition.bind(null, lanes) - ))) - : (flushMutationEffects(), flushLayoutEffects(), flushSpawnedWork()); + else + finalizeRender(lanes, completedRenderEndTime), + (pendingFinishedWork = pendingEffectsRoot = null), + (pendingEffectsLanes = 0); + root.cancelPendingCommit = scheduleGestureCommit( + startTime, + completeRoot.bind( + null, + root, + finishedWork, + lanes, + recoverableErrors, + transitions, + didIncludeRenderPhaseUpdate, + spawnedLane, + updatedLanes, + suspendedRetryLanes, + didSkipSuspendedSiblings, + exitStatus, + suspendedState, + "Waiting for the Gesture to finish", + completedRenderStartTime, + completedRenderEndTime + ) + ); + return; + } + commitRoot( + root, + finishedWork, + lanes, + spawnedLane, + updatedLanes, + suspendedRetryLanes, + suspendedState, + suspendedCommitReason, + completedRenderEndTime + ); + } +} +function commitRoot( + root, + finishedWork, + lanes, + spawnedLane, + updatedLanes, + suspendedRetryLanes, + suspendedState, + suspendedCommitReason, + completedRenderEndTime +) { + var remainingLanes = finishedWork.lanes | finishedWork.childLanes; + pendingEffectsRemainingLanes = remainingLanes; + remainingLanes |= concurrentlyUpdatedLanes; + null === root.pendingGestures && + (0 !== (remainingLanes & 64) && + ((gestureUpdateTime = -1.1), + (gestureUpdateType = 0), + (gestureSuspendedTime = -1.1), + (gestureEventRepeatTime = gestureEventTime), + (gestureEventTime = -1.1)), + (remainingLanes &= -65)); + markRootFinished( + root, + lanes, + remainingLanes, + spawnedLane, + updatedLanes, + suspendedRetryLanes + ); + pendingViewTransitionEvents = null; + (lanes & 335544064) === lanes + ? ((pendingTransitionTypes = claimQueuedTransitionTypes(root)), + (spawnedLane = 10262)) + : ((pendingTransitionTypes = null), (spawnedLane = 10256)); + 0 !== finishedWork.actualDuration || + 0 !== (finishedWork.subtreeFlags & spawnedLane) || + 0 !== (finishedWork.flags & spawnedLane) + ? ((root.callbackNode = null), + (root.callbackPriority = 0), + scheduleCallback$1(NormalPriority$1, function () { + schedulerEvent = window.event; + 0 === pendingDelayedCommitReason && (pendingDelayedCommitReason = 2); + flushPassiveEffects(); + return null; + })) + : ((root.callbackNode = null), (root.callbackPriority = 0)); + commitErrors = null; + commitStartTime = now(); + null !== suspendedCommitReason && + (!supportsUserTiming || + commitStartTime <= completedRenderEndTime || + console.timeStamp( + suspendedCommitReason, + completedRenderEndTime, + commitStartTime, + currentTrack, + "Scheduler \u269b", + "secondary-light" + )); + shouldStartViewTransition = !1; + suspendedCommitReason = 0 !== (finishedWork.flags & 13878); + if (0 !== (finishedWork.subtreeFlags & 13878) || suspendedCommitReason) { + suspendedCommitReason = ReactSharedInternals.T; + ReactSharedInternals.T = null; + completedRenderEndTime = ReactDOMSharedInternals.p; + ReactDOMSharedInternals.p = 2; + spawnedLane = executionContext; + executionContext |= 4; + try { + commitBeforeMutationEffects(root, finishedWork, lanes); + } finally { + (executionContext = spawnedLane), + (ReactDOMSharedInternals.p = completedRenderEndTime), + (ReactSharedInternals.T = suspendedCommitReason); } } + 64 === lanes && stopCommittedGesture(root); + pendingEffectsStatus = 1; + shouldStartViewTransition + ? ((animatingLanes |= lanes), + (pendingViewTransition = startViewTransition( + suspendedState, + root.containerInfo, + pendingTransitionTypes, + flushMutationEffects, + flushLayoutEffects, + flushAfterMutationEffects, + flushSpawnedWork, + flushPassiveEffects, + reportViewTransitionError, + suspendedViewTransition, + finishedViewTransition.bind(null, lanes) + ))) + : (flushMutationEffects(), flushLayoutEffects(), flushSpawnedWork()); } function reportViewTransitionError(error) { if (0 !== pendingEffectsStatus) { @@ -15799,162 +16053,6 @@ function flushSpawnedWork() { flushSyncWorkAcrossRoots_impl(0, !1); } } -function commitGestureOnRoot( - root, - finishedWork, - recoverableErrors, - suspendedState -) { - recoverableErrors = root.pendingGestures; - if (null === recoverableErrors) ensureRootIsScheduled(root); - else { - deleteScheduledGesture(root, recoverableErrors); - animatingLanes |= pendingEffectsLanes; - var prevTransition = ReactSharedInternals.T; - ReactSharedInternals.T = null; - var previousPriority = ReactDOMSharedInternals.p; - ReactDOMSharedInternals.p = 2; - var prevExecutionContext = executionContext; - executionContext |= 4; - try { - var rootContainer = root.containerInfo, - documentElement = - 9 === rootContainer.nodeType - ? rootContainer.documentElement - : rootContainer.ownerDocument.documentElement; - null !== documentElement && - "" === documentElement.style.viewTransitionName && - (documentElement.style.viewTransitionName = "none"); - var containerInstance = - 9 === rootContainer.nodeType - ? rootContainer.body - : "HTML" === rootContainer.nodeName - ? rootContainer.ownerDocument.body - : rootContainer; - var containerParent = containerInstance.parentNode; - if (null === containerParent) throw Error(formatProdErrorMessage(552)); - var clone = containerInstance.cloneNode(!1), - computedStyle = getComputedStyle(containerInstance); - if ( - "absolute" !== computedStyle.position && - "fixed" !== computedStyle.position - ) { - for ( - rootContainer = containerParent; - null != rootContainer.parentNode && - 9 !== rootContainer.parentNode.nodeType && - "static" === getComputedStyle(rootContainer).position; - - ) - rootContainer = rootContainer.parentNode; - var positionedAncestorStyle = rootContainer.style, - containerInstanceStyle = containerInstance.style, - prevAncestorTranslate = positionedAncestorStyle.translate, - prevAncestorScale = positionedAncestorStyle.scale, - prevAncestorRotate = positionedAncestorStyle.rotate, - prevAncestorTransform = positionedAncestorStyle.transform, - prevTranslate = containerInstanceStyle.translate, - prevScale = containerInstanceStyle.scale, - prevRotate = containerInstanceStyle.rotate, - prevTransform = containerInstanceStyle.transform; - positionedAncestorStyle.translate = "none"; - positionedAncestorStyle.scale = "none"; - positionedAncestorStyle.rotate = "none"; - positionedAncestorStyle.transform = "none"; - containerInstanceStyle.translate = "none"; - containerInstanceStyle.scale = "none"; - containerInstanceStyle.rotate = "none"; - containerInstanceStyle.transform = "none"; - var ancestorRect = rootContainer.getBoundingClientRect(), - rect = containerInstance.getBoundingClientRect(), - cloneStyle = clone.style; - cloneStyle.position = "absolute"; - cloneStyle.top = rect.top - ancestorRect.top + "px"; - cloneStyle.left = rect.left - ancestorRect.left + "px"; - cloneStyle.width = rect.width + "px"; - cloneStyle.height = rect.height + "px"; - cloneStyle.margin = "0px"; - cloneStyle.boxSizing = "border-box"; - positionedAncestorStyle.translate = prevAncestorTranslate; - positionedAncestorStyle.scale = prevAncestorScale; - positionedAncestorStyle.rotate = prevAncestorRotate; - positionedAncestorStyle.transform = prevAncestorTransform; - containerInstanceStyle.translate = prevTranslate; - containerInstanceStyle.scale = prevScale; - containerInstanceStyle.rotate = prevRotate; - containerInstanceStyle.transform = prevTransform; - } - clone.style.viewTransitionName = "root"; - var transform = computedStyle.transform; - "none" === transform && (transform = ""); - var scale = computedStyle.scale; - if ("none" !== scale && "" !== scale) { - var parts = scale.split(" "); - transform = - (3 === parts.length ? "scale3d" : "scale") + - "(" + - parts.join(", ") + - ") " + - transform; - } - var rotate = computedStyle.rotate; - if ("none" !== rotate && "" !== rotate) { - var parts$312 = rotate.split(" "); - transform = - 1 === parts$312.length - ? "rotate(" + parts$312[0] + ") " + transform - : 2 === parts$312.length - ? "rotate" + - parts$312[0].toUpperCase() + - "(" + - parts$312[1] + - ") " + - transform - : "rotate3d(" + parts$312.join(", ") + ") " + transform; - } - var translate = computedStyle.translate; - if ("none" !== translate && "" !== translate) { - var parts$313 = translate.split(" "); - transform = - (3 === parts$313.length ? "translate3d" : "translate") + - "(" + - parts$313.join(", ") + - ") " + - transform; - } - var JSCompiler_inline_result = transform; - clone.style.translate = "none"; - clone.style.scale = "none"; - clone.style.rotate = "none"; - clone.style.transform = - "translate(-20000px, -20000px) " + JSCompiler_inline_result; - containerInstance.parentNode.insertBefore( - clone, - containerInstance.nextSibling - ); - root.gestureClone = clone; - recursivelyInsertClones(finishedWork, clone, null, 0); - } finally { - (executionContext = prevExecutionContext), - (ReactDOMSharedInternals.p = previousPriority), - (ReactSharedInternals.T = prevTransition); - } - pendingTransitionTypes = recoverableErrors.types; - pendingEffectsStatus = 6; - pendingViewTransition = recoverableErrors.running = startGestureTransition( - suspendedState, - root.containerInfo, - recoverableErrors.provider, - recoverableErrors.rangeStart, - recoverableErrors.rangeEnd, - pendingTransitionTypes, - flushGestureMutations, - flushGestureAnimations, - reportViewTransitionError, - finishedViewTransition.bind(null, pendingEffectsLanes) - ); - } -} function flushGestureMutations() { if (6 === pendingEffectsStatus) { pendingEffectsStatus = 0; @@ -16003,23 +16101,35 @@ function flushGestureMutations() { (ReactDOMSharedInternals.p = previousPriority), (ReactSharedInternals.T = prevTransition); } + commitEndTime = now(); + !supportsUserTiming || + commitEndTime <= pendingEffectsRenderEndTime || + console.timeStamp( + "Create Ghost Tree", + pendingEffectsRenderEndTime, + commitEndTime, + currentTrack, + "Scheduler \u269b", + "secondary-dark" + ); pendingEffectsStatus = 7; } } function flushGestureAnimations() { flushGestureMutations(); if (7 === pendingEffectsStatus) { - var lanes = pendingEffectsLanes; + var lanes = pendingEffectsLanes, + startViewTransitionStartTime = commitEndTime; commitEndTime = now(); logStartViewTransitionYieldPhase( - pendingEffectsRenderEndTime, + startViewTransitionStartTime, commitEndTime, 1 === pendingDelayedCommitReason ); 1 !== pendingDelayedCommitReason && (pendingDelayedCommitReason = 3); pendingEffectsStatus = 0; - var root = pendingEffectsRoot, - finishedWork = pendingFinishedWork; + startViewTransitionStartTime = pendingEffectsRoot; + var finishedWork = pendingFinishedWork; pendingFinishedWork = pendingEffectsRoot = null; pendingEffectsLanes = 0; pendingViewTransition = null; @@ -16031,14 +16141,16 @@ function flushGestureAnimations() { executionContext |= 4; try { restoreViewTransitionsOnFiber(finishedWork), - restoreRootViewTransitionName(root.containerInfo); + restoreRootViewTransitionName( + startViewTransitionStartTime.containerInfo + ); } finally { (executionContext = prevExecutionContext), (ReactDOMSharedInternals.p = previousPriority), (ReactSharedInternals.T = prevTransition); } finalizeRender(lanes, commitEndTime); - ensureRootIsScheduled(root); + ensureRootIsScheduled(startViewTransitionStartTime); } } function releaseRootPooledCache(root, remainingLanes) { @@ -16211,8 +16323,7 @@ function attachPingListener(root, wakeable, lanes) { function pingSuspendedRoot(root, wakeable, pingedLanes) { var pingCache = root.pingCache; null !== pingCache && pingCache.delete(wakeable); - root.pingedLanes |= root.suspendedLanes & pingedLanes; - root.warmLanes &= ~pingedLanes; + markRootPinged$1(root, pingedLanes); 64 === pingedLanes ? 0 > gestureUpdateTime && ((gestureClampTime = gestureUpdateTime = now()), (gestureUpdateType = 2)) @@ -16651,20 +16762,20 @@ function debounceScrollEnd(targetInst, nativeEvent, nativeEventTarget) { (nativeEventTarget[internalScrollTimer] = targetInst)); } for ( - var i$jscomp$inline_2092 = 0; - i$jscomp$inline_2092 < simpleEventPluginEvents.length; - i$jscomp$inline_2092++ + var i$jscomp$inline_2113 = 0; + i$jscomp$inline_2113 < simpleEventPluginEvents.length; + i$jscomp$inline_2113++ ) { - var eventName$jscomp$inline_2093 = - simpleEventPluginEvents[i$jscomp$inline_2092], - domEventName$jscomp$inline_2094 = - eventName$jscomp$inline_2093.toLowerCase(), - capitalizedEvent$jscomp$inline_2095 = - eventName$jscomp$inline_2093[0].toUpperCase() + - eventName$jscomp$inline_2093.slice(1); + var eventName$jscomp$inline_2114 = + simpleEventPluginEvents[i$jscomp$inline_2113], + domEventName$jscomp$inline_2115 = + eventName$jscomp$inline_2114.toLowerCase(), + capitalizedEvent$jscomp$inline_2116 = + eventName$jscomp$inline_2114[0].toUpperCase() + + eventName$jscomp$inline_2114.slice(1); registerSimpleEvent( - domEventName$jscomp$inline_2094, - "on" + capitalizedEvent$jscomp$inline_2095 + domEventName$jscomp$inline_2115, + "on" + capitalizedEvent$jscomp$inline_2116 ); } registerSimpleEvent(ANIMATION_END, "onAnimationEnd"); @@ -19352,6 +19463,11 @@ function createViewTransitionInstance(name) { new: new ViewTransitionPseudoElement("new", name) }; } +function getCurrentGestureOffset(timeline) { + timeline = timeline.currentTime; + if (null === timeline) throw Error(formatProdErrorMessage(549)); + return "number" === typeof timeline ? timeline : timeline.value; +} function FragmentInstance(fragmentFiber) { this._fragmentFiber = fragmentFiber; this._observers = this._eventListeners = null; @@ -20936,11 +21052,7 @@ function FiberRootNode( this.pooledCache = this.pendingIndicator = null; this.pooledCacheLanes = 0; this.formState = formState; - this.gestureClone = - this.stoppingGestures = - this.pendingGestures = - this.transitionTypes = - null; + this.gestureClone = this.pendingGestures = this.transitionTypes = null; this.incompleteTransitions = new Map(); this.passiveEffectDuration = this.effectDuration = -0; this.memoizedUpdaters = new Set(); @@ -21701,16 +21813,16 @@ ReactDOMHydrationRoot.prototype.unstable_scheduleHydration = function (target) { 0 === i && attemptExplicitHydrationTarget(target); } }; -var isomorphicReactPackageVersion$jscomp$inline_2510 = React.version; +var isomorphicReactPackageVersion$jscomp$inline_2531 = React.version; if ( - "19.3.0-experimental-65eec428-20251218" !== - isomorphicReactPackageVersion$jscomp$inline_2510 + "19.3.0-experimental-bef88f7c-20260116" !== + isomorphicReactPackageVersion$jscomp$inline_2531 ) throw Error( formatProdErrorMessage( 527, - isomorphicReactPackageVersion$jscomp$inline_2510, - "19.3.0-experimental-65eec428-20251218" + isomorphicReactPackageVersion$jscomp$inline_2531, + "19.3.0-experimental-bef88f7c-20260116" ) ); ReactDOMSharedInternals.findDOMNode = function (componentOrElement) { @@ -21730,24 +21842,24 @@ ReactDOMSharedInternals.findDOMNode = function (componentOrElement) { null === componentOrElement ? null : componentOrElement.stateNode; return componentOrElement; }; -var internals$jscomp$inline_3226 = { +var internals$jscomp$inline_3251 = { bundleType: 0, - version: "19.3.0-experimental-65eec428-20251218", + version: "19.3.0-experimental-bef88f7c-20260116", rendererPackageName: "react-dom", currentDispatcherRef: ReactSharedInternals, - reconcilerVersion: "19.3.0-experimental-65eec428-20251218" + reconcilerVersion: "19.3.0-experimental-bef88f7c-20260116" }; if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { - var hook$jscomp$inline_3227 = __REACT_DEVTOOLS_GLOBAL_HOOK__; + var hook$jscomp$inline_3252 = __REACT_DEVTOOLS_GLOBAL_HOOK__; if ( - !hook$jscomp$inline_3227.isDisabled && - hook$jscomp$inline_3227.supportsFiber + !hook$jscomp$inline_3252.isDisabled && + hook$jscomp$inline_3252.supportsFiber ) try { - (rendererID = hook$jscomp$inline_3227.inject( - internals$jscomp$inline_3226 + (rendererID = hook$jscomp$inline_3252.inject( + internals$jscomp$inline_3251 )), - (injectedHook = hook$jscomp$inline_3227); + (injectedHook = hook$jscomp$inline_3252); } catch (err) {} } function getCrossOriginStringAs(as, input) { @@ -22003,7 +22115,7 @@ exports.useFormState = function (action, initialState, permalink) { exports.useFormStatus = function () { return ReactSharedInternals.H.useHostTransitionStatus(); }; -exports.version = "19.3.0-experimental-65eec428-20251218"; +exports.version = "19.3.0-experimental-bef88f7c-20260116"; "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server-legacy.browser.development.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server-legacy.browser.development.js index 591fffe2b50d..1a9aa7284f45 100644 --- a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server-legacy.browser.development.js +++ b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server-legacy.browser.development.js @@ -10411,5 +10411,5 @@ 'The server used "renderToString" which does not support Suspense. If you intended for this Suspense boundary to render the fallback content on the server consider throwing an Error somewhere within the Suspense boundary. If you intended to have the server wait for the suspended component please switch to "renderToReadableStream" which supports Suspense on the server' ); }; - exports.version = "19.3.0-experimental-65eec428-20251218"; + exports.version = "19.3.0-experimental-bef88f7c-20260116"; })(); diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server-legacy.browser.production.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server-legacy.browser.production.js index de70d056c489..350cfe8ad488 100644 --- a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server-legacy.browser.production.js +++ b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server-legacy.browser.production.js @@ -7035,4 +7035,4 @@ exports.renderToString = function (children, options) { 'The server used "renderToString" which does not support Suspense. If you intended for this Suspense boundary to render the fallback content on the server consider throwing an Error somewhere within the Suspense boundary. If you intended to have the server wait for the suspended component please switch to "renderToReadableStream" which supports Suspense on the server' ); }; -exports.version = "19.3.0-experimental-65eec428-20251218"; +exports.version = "19.3.0-experimental-bef88f7c-20260116"; diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server-legacy.node.development.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server-legacy.node.development.js index 88da68fa1626..6b1dcfa83604 100644 --- a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server-legacy.node.development.js +++ b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server-legacy.node.development.js @@ -10411,5 +10411,5 @@ 'The server used "renderToString" which does not support Suspense. If you intended for this Suspense boundary to render the fallback content on the server consider throwing an Error somewhere within the Suspense boundary. If you intended to have the server wait for the suspended component please switch to "renderToPipeableStream" which supports Suspense on the server' ); }; - exports.version = "19.3.0-experimental-65eec428-20251218"; + exports.version = "19.3.0-experimental-bef88f7c-20260116"; })(); diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server-legacy.node.production.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server-legacy.node.production.js index 335527ef82c5..a6522f8dd786 100644 --- a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server-legacy.node.production.js +++ b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server-legacy.node.production.js @@ -7138,4 +7138,4 @@ exports.renderToString = function (children, options) { 'The server used "renderToString" which does not support Suspense. If you intended for this Suspense boundary to render the fallback content on the server consider throwing an Error somewhere within the Suspense boundary. If you intended to have the server wait for the suspended component please switch to "renderToPipeableStream" which supports Suspense on the server' ); }; -exports.version = "19.3.0-experimental-65eec428-20251218"; +exports.version = "19.3.0-experimental-bef88f7c-20260116"; diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.browser.development.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.browser.development.js index 01cc58c5acd6..598e93086c17 100644 --- a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.browser.development.js +++ b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.browser.development.js @@ -9390,11 +9390,11 @@ } function ensureCorrectIsomorphicReactVersion() { var isomorphicReactPackageVersion = React.version; - if ("19.3.0-experimental-65eec428-20251218" !== isomorphicReactPackageVersion) + if ("19.3.0-experimental-bef88f7c-20260116" !== isomorphicReactPackageVersion) throw Error( 'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' + (isomorphicReactPackageVersion + - "\n - react-dom: 19.3.0-experimental-65eec428-20251218\nLearn more: https://react.dev/warnings/version-mismatch") + "\n - react-dom: 19.3.0-experimental-bef88f7c-20260116\nLearn more: https://react.dev/warnings/version-mismatch") ); } var React = require("next/dist/compiled/react-experimental"), @@ -11214,5 +11214,5 @@ startWork(request); }); }; - exports.version = "19.3.0-experimental-65eec428-20251218"; + exports.version = "19.3.0-experimental-bef88f7c-20260116"; })(); diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.browser.production.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.browser.production.js index 8f4449c4c44d..651733d44b0f 100644 --- a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.browser.production.js +++ b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.browser.production.js @@ -7688,12 +7688,12 @@ function getPostponedState(request) { } function ensureCorrectIsomorphicReactVersion() { var isomorphicReactPackageVersion = React.version; - if ("19.3.0-experimental-65eec428-20251218" !== isomorphicReactPackageVersion) + if ("19.3.0-experimental-bef88f7c-20260116" !== isomorphicReactPackageVersion) throw Error( formatProdErrorMessage( 527, isomorphicReactPackageVersion, - "19.3.0-experimental-65eec428-20251218" + "19.3.0-experimental-bef88f7c-20260116" ) ); } @@ -7944,4 +7944,4 @@ exports.resumeAndPrerender = function (children, postponedState, options) { startWork(request); }); }; -exports.version = "19.3.0-experimental-65eec428-20251218"; +exports.version = "19.3.0-experimental-bef88f7c-20260116"; diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.bun.production.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.bun.production.js index 7635d2f693e6..ecc7783c248c 100644 --- a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.bun.production.js +++ b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.bun.production.js @@ -7383,11 +7383,11 @@ function getPostponedState(request) { } function ensureCorrectIsomorphicReactVersion() { var isomorphicReactPackageVersion = React.version; - if ("19.3.0-experimental-65eec428-20251218" !== isomorphicReactPackageVersion) + if ("19.3.0-experimental-bef88f7c-20260116" !== isomorphicReactPackageVersion) throw Error( 'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' + (isomorphicReactPackageVersion + - "\n - react-dom: 19.3.0-experimental-65eec428-20251218\nLearn more: https://react.dev/warnings/version-mismatch") + "\n - react-dom: 19.3.0-experimental-bef88f7c-20260116\nLearn more: https://react.dev/warnings/version-mismatch") ); } ensureCorrectIsomorphicReactVersion(); @@ -7932,4 +7932,4 @@ exports.resumeToPipeableStream = function (children, postponedState, options) { } }; }; -exports.version = "19.3.0-experimental-65eec428-20251218"; +exports.version = "19.3.0-experimental-bef88f7c-20260116"; diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.edge.development.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.edge.development.js index 7fa9b95d0f85..729b03ff8742 100644 --- a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.edge.development.js +++ b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.edge.development.js @@ -9419,11 +9419,11 @@ } function ensureCorrectIsomorphicReactVersion() { var isomorphicReactPackageVersion = React.version; - if ("19.3.0-experimental-65eec428-20251218" !== isomorphicReactPackageVersion) + if ("19.3.0-experimental-bef88f7c-20260116" !== isomorphicReactPackageVersion) throw Error( 'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' + (isomorphicReactPackageVersion + - "\n - react-dom: 19.3.0-experimental-65eec428-20251218\nLearn more: https://react.dev/warnings/version-mismatch") + "\n - react-dom: 19.3.0-experimental-bef88f7c-20260116\nLearn more: https://react.dev/warnings/version-mismatch") ); } var React = require("next/dist/compiled/react-experimental"), @@ -11239,5 +11239,5 @@ startWork(request); }); }; - exports.version = "19.3.0-experimental-65eec428-20251218"; + exports.version = "19.3.0-experimental-bef88f7c-20260116"; })(); diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.edge.production.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.edge.production.js index 82bf9b86857e..80a27827e748 100644 --- a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.edge.production.js +++ b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.edge.production.js @@ -7806,11 +7806,11 @@ function getPostponedState(request) { } function ensureCorrectIsomorphicReactVersion() { var isomorphicReactPackageVersion = React.version; - if ("19.3.0-experimental-65eec428-20251218" !== isomorphicReactPackageVersion) + if ("19.3.0-experimental-bef88f7c-20260116" !== isomorphicReactPackageVersion) throw Error( 'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' + (isomorphicReactPackageVersion + - "\n - react-dom: 19.3.0-experimental-65eec428-20251218\nLearn more: https://react.dev/warnings/version-mismatch") + "\n - react-dom: 19.3.0-experimental-bef88f7c-20260116\nLearn more: https://react.dev/warnings/version-mismatch") ); } ensureCorrectIsomorphicReactVersion(); @@ -8060,4 +8060,4 @@ exports.resumeAndPrerender = function (children, postponedState, options) { startWork(request); }); }; -exports.version = "19.3.0-experimental-65eec428-20251218"; +exports.version = "19.3.0-experimental-bef88f7c-20260116"; diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.node.development.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.node.development.js index 0e32c41b5702..5740ef5a3a92 100644 --- a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.node.development.js +++ b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.node.development.js @@ -9279,11 +9279,11 @@ } function ensureCorrectIsomorphicReactVersion() { var isomorphicReactPackageVersion = React.version; - if ("19.3.0-experimental-65eec428-20251218" !== isomorphicReactPackageVersion) + if ("19.3.0-experimental-bef88f7c-20260116" !== isomorphicReactPackageVersion) throw Error( 'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' + (isomorphicReactPackageVersion + - "\n - react-dom: 19.3.0-experimental-65eec428-20251218\nLearn more: https://react.dev/warnings/version-mismatch") + "\n - react-dom: 19.3.0-experimental-bef88f7c-20260116\nLearn more: https://react.dev/warnings/version-mismatch") ); } function createDrainHandler(destination, request) { @@ -11405,5 +11405,5 @@ } }; }; - exports.version = "19.3.0-experimental-65eec428-20251218"; + exports.version = "19.3.0-experimental-bef88f7c-20260116"; })(); diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.node.production.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.node.production.js index f42926ccda49..509840b9172f 100644 --- a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.node.production.js +++ b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.node.production.js @@ -7685,11 +7685,11 @@ function getPostponedState(request) { } function ensureCorrectIsomorphicReactVersion() { var isomorphicReactPackageVersion = React.version; - if ("19.3.0-experimental-65eec428-20251218" !== isomorphicReactPackageVersion) + if ("19.3.0-experimental-bef88f7c-20260116" !== isomorphicReactPackageVersion) throw Error( 'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' + (isomorphicReactPackageVersion + - "\n - react-dom: 19.3.0-experimental-65eec428-20251218\nLearn more: https://react.dev/warnings/version-mismatch") + "\n - react-dom: 19.3.0-experimental-bef88f7c-20260116\nLearn more: https://react.dev/warnings/version-mismatch") ); } ensureCorrectIsomorphicReactVersion(); @@ -8239,4 +8239,4 @@ exports.resumeToPipeableStream = function (children, postponedState, options) { } }; }; -exports.version = "19.3.0-experimental-65eec428-20251218"; +exports.version = "19.3.0-experimental-bef88f7c-20260116"; diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-unstable_testing.development.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-unstable_testing.development.js index 106c90f76f33..367d368748bf 100644 --- a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-unstable_testing.development.js +++ b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-unstable_testing.development.js @@ -1273,6 +1273,10 @@ (root.pingedLanes = 0), (root.warmLanes = 0)); } + function markRootPinged$1(root, pingedLanes) { + root.pingedLanes |= root.suspendedLanes & pingedLanes; + root.warmLanes &= ~pingedLanes; + } function markRootFinished( root, finishedLanes, @@ -4549,38 +4553,6 @@ errors )); } - function logRenderPhase(startTime, endTime, lanes, debugTask) { - if (supportsUserTiming && !(endTime <= startTime)) { - var color = - (lanes & 738197653) === lanes ? "tertiary-dark" : "primary-dark"; - lanes = - (lanes & 536870912) === lanes - ? "Prepared" - : (lanes & 201326741) === lanes - ? "Hydrated" - : "Render"; - debugTask - ? debugTask.run( - console.timeStamp.bind( - console, - lanes, - startTime, - endTime, - currentTrack, - LANES_TRACK_GROUP, - color - ) - ) - : console.timeStamp( - lanes, - startTime, - endTime, - currentTrack, - LANES_TRACK_GROUP, - color - ); - } - } function logSuspendedRenderPhase(startTime, endTime, lanes, debugTask) { !supportsUserTiming || endTime <= startTime || @@ -4633,50 +4605,6 @@ lanes )); } - function logRecoveredRenderPhase( - startTime, - endTime, - lanes, - recoverableErrors, - hydrationFailed, - debugTask - ) { - if (supportsUserTiming && !(endTime <= startTime)) { - lanes = []; - for (var i = 0; i < recoverableErrors.length; i++) { - var error = recoverableErrors[i].value; - lanes.push([ - "Recoverable Error", - "object" === typeof error && - null !== error && - "string" === typeof error.message - ? String(error.message) - : String(error) - ]); - } - startTime = { - start: startTime, - end: endTime, - detail: { - devtools: { - color: "primary-dark", - track: currentTrack, - trackGroup: LANES_TRACK_GROUP, - tooltipText: hydrationFailed - ? "Hydration Failed" - : "Recovered after Error", - properties: lanes - } - } - }; - debugTask - ? debugTask.run( - performance.measure.bind(performance, "Recovered", startTime) - ) - : performance.measure("Recovered", startTime); - performance.clearMeasures("Recovered"); - } - } function logErroredRenderPhase(startTime, endTime, lanes, debugTask) { !supportsUserTiming || endTime <= startTime || @@ -5139,7 +5067,7 @@ (workInProgress.key = current.key), (workInProgress.actualDuration = -0), (workInProgress.actualStartTime = -1.1)); - workInProgress.flags = current.flags & 132120576; + workInProgress.flags = current.flags & 133169152; workInProgress.childLanes = current.childLanes; workInProgress.lanes = current.lanes; workInProgress.child = current.child; @@ -5177,7 +5105,7 @@ return workInProgress; } function resetWorkInProgress(workInProgress, renderLanes) { - workInProgress.flags &= 132120578; + workInProgress.flags &= 133169154; var current = workInProgress.alternate; null === current ? ((workInProgress.childLanes = 0), @@ -6265,39 +6193,30 @@ gestureOptions, transitionTypes ) { - if (gestureOptions && null != gestureOptions.rangeStart) - var JSCompiler_temp = gestureOptions.rangeStart; - else { - JSCompiler_temp = gestureTimeline.currentTime; - if (null === JSCompiler_temp) - throw Error( - "Cannot start a gesture with a disconnected AnimationTimeline." - ); - JSCompiler_temp = - "number" === typeof JSCompiler_temp - ? JSCompiler_temp - : JSCompiler_temp.value; - } + var rangeStart = + gestureOptions && null != gestureOptions.rangeStart + ? gestureOptions.rangeStart + : getCurrentGestureOffset(gestureTimeline); gestureOptions = gestureOptions && null != gestureOptions.rangeEnd ? gestureOptions.rangeEnd - : 50 > JSCompiler_temp + : 50 > rangeStart ? 100 : 0; for (root = root.pendingGestures; null !== root; ) { if (root.provider === gestureTimeline) { root.count++; - root.rangeStart = JSCompiler_temp; + root.rangeStart = rangeStart; root.rangeEnd = gestureOptions; if (null !== transitionTypes) for ( gestureTimeline = root.types, null === gestureTimeline && (gestureTimeline = root.types = []), - JSCompiler_temp = 0; - JSCompiler_temp < transitionTypes.length; - JSCompiler_temp++ + rangeStart = 0; + rangeStart < transitionTypes.length; + rangeStart++ ) - (gestureOptions = transitionTypes[JSCompiler_temp]), + (gestureOptions = transitionTypes[rangeStart]), -1 === gestureTimeline.indexOf(gestureOptions) && gestureTimeline.push(gestureOptions); return root; @@ -6307,47 +6226,78 @@ } return null; } - function deleteScheduledGesture(root, gesture) { - null === gesture.prev - ? (root.pendingGestures === gesture && - ((root.pendingGestures = gesture.next), - null === root.pendingGestures && (root.pendingLanes &= -65)), - root.stoppingGestures === gesture && - (root.stoppingGestures = gesture.next)) - : ((gesture.prev.next = gesture.next), - null !== gesture.next && (gesture.next.prev = gesture.prev), - (gesture.prev = null), - (gesture.next = null)); - } - function stopCompletedGestures(root) { - var gesture = root.stoppingGestures; - for (root.stoppingGestures = null; null !== gesture; ) - null !== gesture.running && - (gesture.running.skipTransition(), (gesture.running = null)), - (root = gesture.next), - (gesture.next = null), - (gesture.prev = null), - (gesture = root); + function stopCommittedGesture(root) { + var committedGesture = root.pendingGestures; + if (null !== committedGesture) { + committedGesture.committing = !1; + var nextGesture = committedGesture.next; + null === nextGesture + ? (root.pendingLanes &= -65) + : (nextGesture.prev = null); + root.pendingGestures = nextGesture; + root = committedGesture.running; + null !== root && + ((committedGesture.running = null), root.skipTransition()); + } + } + function scheduleGestureCommit(gesture, callback) { + gesture.commit = callback; + return function () { + gesture.commit = null; + }; } function chainGestureCancellation(root, scheduledGesture, prevCancel) { return function () { - if ( - null !== scheduledGesture && - (scheduledGesture.count--, 0 === scheduledGesture.count) - ) { - deleteScheduledGesture(root, scheduledGesture); - var runningTransition = scheduledGesture.running; - if (null !== runningTransition) { - var pendingLanesExcludingGestureLane = root.pendingLanes & -65; - 0 !== (pendingLanesExcludingGestureLane & 127) || - 0 !== (pendingLanesExcludingGestureLane & 4194048) - ? ((runningTransition = root.stoppingGestures), - null !== runningTransition && - ((scheduledGesture.next = runningTransition), - (runningTransition.prev = scheduledGesture)), - (root.stoppingGestures = scheduledGesture)) - : ((scheduledGesture.running = null), - runningTransition.skipTransition()); + if (null !== scheduledGesture) { + if (0 !== scheduledGesture.revertLane) { + var entangledLanes = + scheduledGesture.revertLane | requestTransitionLane(); + markRootEntangled(root, entangledLanes); + } + scheduledGesture.count--; + if (0 === scheduledGesture.count) { + var finalOffset = getCurrentGestureOffset( + scheduledGesture.provider + ), + rangeStart = scheduledGesture.rangeStart, + rangeEnd = scheduledGesture.rangeEnd; + entangledLanes = scheduledGesture.running; + null !== entangledLanes && + (rangeStart < rangeEnd + ? finalOffset > rangeStart + (rangeEnd - rangeStart) / 2 + : finalOffset < rangeEnd + (rangeStart - rangeEnd) / 2) + ? ((scheduledGesture.committing = !0), + root.pendingGestures === scheduledGesture && + ((entangledLanes = scheduledGesture.commit), + null !== entangledLanes + ? ((scheduledGesture.commit = null), entangledLanes()) + : null !== root.pendingGestures && + (markRootPinged$1(root, 64), + ensureRootIsScheduled(root)))) + : null === scheduledGesture.prev + ? (root.pendingGestures === scheduledGesture && + ((root.pendingGestures = scheduledGesture.next), + (finalOffset = root.pendingLanes), + null === root.pendingGestures && (finalOffset &= -65), + markRootFinished(root, 64, finalOffset, 0, 0, 0), + workInProgressRoot === root && + 64 === workInProgressRootRenderLanes + ? (executionContext & RenderContext) === NoContext && + prepareFreshStack(root, 0) + : null !== root.cancelPendingCommit && + 64 === pendingEffectsLanes && + ((finalOffset = root.cancelPendingCommit), + null !== finalOffset && + ((root.cancelPendingCommit = null), finalOffset())), + null !== root.pendingGestures && markRootPinged$1(root, 64), + ensureRootIsScheduled(root)), + (scheduledGesture.running = null), + null !== entangledLanes && entangledLanes.skipTransition()) + : ((scheduledGesture.prev.next = scheduledGesture.next), + null !== scheduledGesture.next && + (scheduledGesture.next.prev = scheduledGesture.prev), + (scheduledGesture.prev = null), + (scheduledGesture.next = null)); } } null !== prevCancel && prevCancel(); @@ -8265,7 +8215,7 @@ null; hookTypesUpdateIndexDev = -1; null !== current && - (current.flags & 132120576) !== (workInProgress.flags & 132120576) && + (current.flags & 133169152) !== (workInProgress.flags & 133169152) && console.error( "Internal React error: Expected static flag was missing. Please notify the React team." ); @@ -8565,18 +8515,20 @@ if (64 === updateLane) { var scheduledGesture = update.gesture; if (null !== scheduledGesture) - if (0 === scheduledGesture.count) { + if (0 !== scheduledGesture.count || scheduledGesture.committing) + if (64 === renderLanes) { + shouldSkipUpdate = workInProgressRoot; + if (null === shouldSkipUpdate) + throw Error( + "Expected a work-in-progress root. This is a bug in React. Please file an issue." + ); + shouldSkipUpdate = + shouldSkipUpdate.pendingGestures !== scheduledGesture; + } else shouldSkipUpdate = !0; + else { update = update.next; continue; - } else if (64 === renderLanes) { - shouldSkipUpdate = workInProgressRoot; - if (null === shouldSkipUpdate) - throw Error( - "Expected a work-in-progress root. This is a bug in React. Please file an issue." - ); - shouldSkipUpdate = - shouldSkipUpdate.pendingGestures !== scheduledGesture; - } else shouldSkipUpdate = !0; + } } if (shouldSkipUpdate) (scheduledGesture = { @@ -9429,7 +9381,7 @@ hook ); if ( - 0 === (renderLanes & 42) || + 0 === (renderLanes & 106) || (0 !== (renderLanes & 1073741824) && 0 === (workInProgressRootRenderLanes & 261930)) ) @@ -9815,6 +9767,9 @@ rangeEnd: 100, types: null, running: null, + commit: null, + committing: !1, + revertLane: 0, prev: fiber, next: null }; @@ -9824,7 +9779,10 @@ ensureRootIsScheduled(throwIfDuringRender); throwIfDuringRender = transition; } - action.gesture = throwIfDuringRender; + throwIfDuringRender = action.gesture = throwIfDuringRender; + 0 === throwIfDuringRender.revertLane + ? (throwIfDuringRender.revertLane = action.revertLane) + : (action.revertLane = throwIfDuringRender.revertLane); } } function isRenderPhaseUpdate(fiber) { @@ -11437,24 +11395,24 @@ return current; } function updateSuspenseComponent(current, workInProgress, renderLanes) { - var JSCompiler_object_inline_digest_3260; - var JSCompiler_object_inline_stack_3261 = workInProgress.pendingProps; + var JSCompiler_object_inline_digest_3318; + var JSCompiler_object_inline_stack_3319 = workInProgress.pendingProps; shouldSuspendImpl(workInProgress) && (workInProgress.flags |= 128); - var JSCompiler_object_inline_message_3259 = !1; + var JSCompiler_object_inline_message_3317 = !1; var didSuspend = 0 !== (workInProgress.flags & 128); - (JSCompiler_object_inline_digest_3260 = didSuspend) || - (JSCompiler_object_inline_digest_3260 = + (JSCompiler_object_inline_digest_3318 = didSuspend) || + (JSCompiler_object_inline_digest_3318 = null !== current && null === current.memoizedState ? !1 : 0 !== (suspenseStackCursor.current & ForceSuspenseFallback)); - JSCompiler_object_inline_digest_3260 && - ((JSCompiler_object_inline_message_3259 = !0), + JSCompiler_object_inline_digest_3318 && + ((JSCompiler_object_inline_message_3317 = !0), (workInProgress.flags &= -129)); - JSCompiler_object_inline_digest_3260 = 0 !== (workInProgress.flags & 32); + JSCompiler_object_inline_digest_3318 = 0 !== (workInProgress.flags & 32); workInProgress.flags &= -33; if (null === current) { if (isHydrating) { - JSCompiler_object_inline_message_3259 + JSCompiler_object_inline_message_3317 ? pushPrimaryTreeSuspenseHandler(workInProgress) : reuseSuspenseHandlerOnStack(workInProgress); (current = nextHydratableInstance) @@ -11467,18 +11425,18 @@ ? renderLanes : null), null !== renderLanes && - ((JSCompiler_object_inline_digest_3260 = { + ((JSCompiler_object_inline_digest_3318 = { dehydrated: renderLanes, treeContext: getSuspendedTreeContext(), retryLane: 536870912, hydrationErrors: null }), (workInProgress.memoizedState = - JSCompiler_object_inline_digest_3260), - (JSCompiler_object_inline_digest_3260 = + JSCompiler_object_inline_digest_3318), + (JSCompiler_object_inline_digest_3318 = createFiberFromDehydratedFragment(renderLanes)), - (JSCompiler_object_inline_digest_3260.return = workInProgress), - (workInProgress.child = JSCompiler_object_inline_digest_3260), + (JSCompiler_object_inline_digest_3318.return = workInProgress), + (workInProgress.child = JSCompiler_object_inline_digest_3318), (hydrationParentFiber = workInProgress), (nextHydratableInstance = null))) : (renderLanes = null); @@ -11492,9 +11450,9 @@ : (workInProgress.lanes = 536870912); return null; } - var nextPrimaryChildren = JSCompiler_object_inline_stack_3261.children, - nextFallbackChildren = JSCompiler_object_inline_stack_3261.fallback; - if (JSCompiler_object_inline_message_3259) + var nextPrimaryChildren = JSCompiler_object_inline_stack_3319.children, + nextFallbackChildren = JSCompiler_object_inline_stack_3319.fallback; + if (JSCompiler_object_inline_message_3317) return ( reuseSuspenseHandlerOnStack(workInProgress), mountSuspenseFallbackChildren( @@ -11503,19 +11461,19 @@ nextFallbackChildren, renderLanes ), - (JSCompiler_object_inline_stack_3261 = workInProgress.child), - (JSCompiler_object_inline_stack_3261.memoizedState = + (JSCompiler_object_inline_stack_3319 = workInProgress.child), + (JSCompiler_object_inline_stack_3319.memoizedState = mountSuspenseOffscreenState(renderLanes)), - (JSCompiler_object_inline_stack_3261.childLanes = + (JSCompiler_object_inline_stack_3319.childLanes = getRemainingWorkInPrimaryTree( current, - JSCompiler_object_inline_digest_3260, + JSCompiler_object_inline_digest_3318, renderLanes )), (workInProgress.memoizedState = SUSPENDED_MARKER), - bailoutOffscreenComponent(null, JSCompiler_object_inline_stack_3261) + bailoutOffscreenComponent(null, JSCompiler_object_inline_stack_3319) ); - if (!0 === JSCompiler_object_inline_stack_3261.defer) + if (!0 === JSCompiler_object_inline_stack_3319.defer) return ( reuseSuspenseHandlerOnStack(workInProgress), mountSuspenseFallbackChildren( @@ -11524,18 +11482,18 @@ nextFallbackChildren, renderLanes ), - (JSCompiler_object_inline_stack_3261 = workInProgress.child), - (JSCompiler_object_inline_stack_3261.memoizedState = + (JSCompiler_object_inline_stack_3319 = workInProgress.child), + (JSCompiler_object_inline_stack_3319.memoizedState = mountSuspenseOffscreenState(renderLanes)), - (JSCompiler_object_inline_stack_3261.childLanes = + (JSCompiler_object_inline_stack_3319.childLanes = getRemainingWorkInPrimaryTree( current, - JSCompiler_object_inline_digest_3260, + JSCompiler_object_inline_digest_3318, renderLanes )), (workInProgress.memoizedState = SUSPENDED_MARKER), (workInProgress.lanes = 4194304), - bailoutOffscreenComponent(null, JSCompiler_object_inline_stack_3261) + bailoutOffscreenComponent(null, JSCompiler_object_inline_stack_3319) ); pushPrimaryTreeSuspenseHandler(workInProgress); return mountSuspensePrimaryChildren( @@ -11545,8 +11503,8 @@ } var prevState = current.memoizedState; if (null !== prevState) { - var JSCompiler_object_inline_componentStack_3262 = prevState.dehydrated; - if (null !== JSCompiler_object_inline_componentStack_3262) { + var JSCompiler_object_inline_componentStack_3320 = prevState.dehydrated; + if (null !== JSCompiler_object_inline_componentStack_3320) { if (didSuspend) workInProgress.flags & 256 ? (pushPrimaryTreeSuspenseHandler(workInProgress), @@ -11563,13 +11521,13 @@ (workInProgress = null)) : (reuseSuspenseHandlerOnStack(workInProgress), (nextPrimaryChildren = - JSCompiler_object_inline_stack_3261.fallback), + JSCompiler_object_inline_stack_3319.fallback), (nextFallbackChildren = workInProgress.mode), - (JSCompiler_object_inline_stack_3261 = + (JSCompiler_object_inline_stack_3319 = mountWorkInProgressOffscreenFiber( { mode: "visible", - children: JSCompiler_object_inline_stack_3261.children + children: JSCompiler_object_inline_stack_3319.children }, nextFallbackChildren )), @@ -11580,30 +11538,30 @@ null )), (nextPrimaryChildren.flags |= 2), - (JSCompiler_object_inline_stack_3261.return = workInProgress), + (JSCompiler_object_inline_stack_3319.return = workInProgress), (nextPrimaryChildren.return = workInProgress), - (JSCompiler_object_inline_stack_3261.sibling = + (JSCompiler_object_inline_stack_3319.sibling = nextPrimaryChildren), - (workInProgress.child = JSCompiler_object_inline_stack_3261), + (workInProgress.child = JSCompiler_object_inline_stack_3319), reconcileChildFibers( workInProgress, current.child, null, renderLanes ), - (JSCompiler_object_inline_stack_3261 = workInProgress.child), - (JSCompiler_object_inline_stack_3261.memoizedState = + (JSCompiler_object_inline_stack_3319 = workInProgress.child), + (JSCompiler_object_inline_stack_3319.memoizedState = mountSuspenseOffscreenState(renderLanes)), - (JSCompiler_object_inline_stack_3261.childLanes = + (JSCompiler_object_inline_stack_3319.childLanes = getRemainingWorkInPrimaryTree( current, - JSCompiler_object_inline_digest_3260, + JSCompiler_object_inline_digest_3318, renderLanes )), (workInProgress.memoizedState = SUSPENDED_MARKER), (workInProgress = bailoutOffscreenComponent( null, - JSCompiler_object_inline_stack_3261 + JSCompiler_object_inline_stack_3319 ))); else if ( (pushPrimaryTreeSuspenseHandler(workInProgress), @@ -11611,45 +11569,45 @@ 0 !== (renderLanes & 536870912) && markRenderDerivedCause(workInProgress), isSuspenseInstanceFallback( - JSCompiler_object_inline_componentStack_3262 + JSCompiler_object_inline_componentStack_3320 )) ) { - JSCompiler_object_inline_digest_3260 = - JSCompiler_object_inline_componentStack_3262.nextSibling && - JSCompiler_object_inline_componentStack_3262.nextSibling.dataset; - if (JSCompiler_object_inline_digest_3260) { - nextPrimaryChildren = JSCompiler_object_inline_digest_3260.dgst; - var message = JSCompiler_object_inline_digest_3260.msg; - nextFallbackChildren = JSCompiler_object_inline_digest_3260.stck; - var componentStack = JSCompiler_object_inline_digest_3260.cstck; + JSCompiler_object_inline_digest_3318 = + JSCompiler_object_inline_componentStack_3320.nextSibling && + JSCompiler_object_inline_componentStack_3320.nextSibling.dataset; + if (JSCompiler_object_inline_digest_3318) { + nextPrimaryChildren = JSCompiler_object_inline_digest_3318.dgst; + var message = JSCompiler_object_inline_digest_3318.msg; + nextFallbackChildren = JSCompiler_object_inline_digest_3318.stck; + var componentStack = JSCompiler_object_inline_digest_3318.cstck; } - JSCompiler_object_inline_message_3259 = message; - JSCompiler_object_inline_digest_3260 = nextPrimaryChildren; - JSCompiler_object_inline_stack_3261 = nextFallbackChildren; - JSCompiler_object_inline_componentStack_3262 = componentStack; - nextPrimaryChildren = JSCompiler_object_inline_message_3259; - nextFallbackChildren = JSCompiler_object_inline_componentStack_3262; + JSCompiler_object_inline_message_3317 = message; + JSCompiler_object_inline_digest_3318 = nextPrimaryChildren; + JSCompiler_object_inline_stack_3319 = nextFallbackChildren; + JSCompiler_object_inline_componentStack_3320 = componentStack; + nextPrimaryChildren = JSCompiler_object_inline_message_3317; + nextFallbackChildren = JSCompiler_object_inline_componentStack_3320; nextPrimaryChildren = nextPrimaryChildren ? Error(nextPrimaryChildren) : Error( "The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering." ); nextPrimaryChildren.stack = - JSCompiler_object_inline_stack_3261 || ""; - nextPrimaryChildren.digest = JSCompiler_object_inline_digest_3260; - JSCompiler_object_inline_digest_3260 = + JSCompiler_object_inline_stack_3319 || ""; + nextPrimaryChildren.digest = JSCompiler_object_inline_digest_3318; + JSCompiler_object_inline_digest_3318 = void 0 === nextFallbackChildren ? null : nextFallbackChildren; - JSCompiler_object_inline_stack_3261 = { + JSCompiler_object_inline_stack_3319 = { value: nextPrimaryChildren, source: null, - stack: JSCompiler_object_inline_digest_3260 + stack: JSCompiler_object_inline_digest_3318 }; - "string" === typeof JSCompiler_object_inline_digest_3260 && + "string" === typeof JSCompiler_object_inline_digest_3318 && CapturedStacks.set( nextPrimaryChildren, - JSCompiler_object_inline_stack_3261 + JSCompiler_object_inline_stack_3319 ); - queueHydrationError(JSCompiler_object_inline_stack_3261); + queueHydrationError(JSCompiler_object_inline_stack_3319); workInProgress = retrySuspenseComponentWithoutHydrating( current, workInProgress, @@ -11663,35 +11621,35 @@ renderLanes, !1 ), - (JSCompiler_object_inline_digest_3260 = + (JSCompiler_object_inline_digest_3318 = 0 !== (renderLanes & current.childLanes)), - didReceiveUpdate || JSCompiler_object_inline_digest_3260) + didReceiveUpdate || JSCompiler_object_inline_digest_3318) ) { - JSCompiler_object_inline_digest_3260 = workInProgressRoot; + JSCompiler_object_inline_digest_3318 = workInProgressRoot; if ( - null !== JSCompiler_object_inline_digest_3260 && - ((JSCompiler_object_inline_stack_3261 = getBumpedLaneForHydration( - JSCompiler_object_inline_digest_3260, + null !== JSCompiler_object_inline_digest_3318 && + ((JSCompiler_object_inline_stack_3319 = getBumpedLaneForHydration( + JSCompiler_object_inline_digest_3318, renderLanes )), - 0 !== JSCompiler_object_inline_stack_3261 && - JSCompiler_object_inline_stack_3261 !== prevState.retryLane) + 0 !== JSCompiler_object_inline_stack_3319 && + JSCompiler_object_inline_stack_3319 !== prevState.retryLane) ) throw ( - ((prevState.retryLane = JSCompiler_object_inline_stack_3261), + ((prevState.retryLane = JSCompiler_object_inline_stack_3319), enqueueConcurrentRenderForLane( current, - JSCompiler_object_inline_stack_3261 + JSCompiler_object_inline_stack_3319 ), scheduleUpdateOnFiber( - JSCompiler_object_inline_digest_3260, + JSCompiler_object_inline_digest_3318, current, - JSCompiler_object_inline_stack_3261 + JSCompiler_object_inline_stack_3319 ), SelectiveHydrationException) ); isSuspenseInstancePending( - JSCompiler_object_inline_componentStack_3262 + JSCompiler_object_inline_componentStack_3320 ) || renderDidSuspendDelayIfPossible(); workInProgress = retrySuspenseComponentWithoutHydrating( current, @@ -11700,14 +11658,14 @@ ); } else isSuspenseInstancePending( - JSCompiler_object_inline_componentStack_3262 + JSCompiler_object_inline_componentStack_3320 ) ? ((workInProgress.flags |= 192), (workInProgress.child = current.child), (workInProgress = null)) : ((current = prevState.treeContext), (nextHydratableInstance = getNextHydratable( - JSCompiler_object_inline_componentStack_3262.nextSibling + JSCompiler_object_inline_componentStack_3320.nextSibling )), (hydrationParentFiber = workInProgress), (isHydrating = !0), @@ -11719,32 +11677,32 @@ restoreSuspendedTreeContext(workInProgress, current), (workInProgress = mountSuspensePrimaryChildren( workInProgress, - JSCompiler_object_inline_stack_3261.children + JSCompiler_object_inline_stack_3319.children )), (workInProgress.flags |= 4096)); return workInProgress; } } - if (JSCompiler_object_inline_message_3259) + if (JSCompiler_object_inline_message_3317) return ( reuseSuspenseHandlerOnStack(workInProgress), - (nextPrimaryChildren = JSCompiler_object_inline_stack_3261.fallback), + (nextPrimaryChildren = JSCompiler_object_inline_stack_3319.fallback), (nextFallbackChildren = workInProgress.mode), (componentStack = current.child), - (JSCompiler_object_inline_componentStack_3262 = + (JSCompiler_object_inline_componentStack_3320 = componentStack.sibling), - (JSCompiler_object_inline_stack_3261 = createWorkInProgress( + (JSCompiler_object_inline_stack_3319 = createWorkInProgress( componentStack, { mode: "hidden", - children: JSCompiler_object_inline_stack_3261.children + children: JSCompiler_object_inline_stack_3319.children } )), - (JSCompiler_object_inline_stack_3261.subtreeFlags = - componentStack.subtreeFlags & 132120576), - null !== JSCompiler_object_inline_componentStack_3262 + (JSCompiler_object_inline_stack_3319.subtreeFlags = + componentStack.subtreeFlags & 133169152), + null !== JSCompiler_object_inline_componentStack_3320 ? (nextPrimaryChildren = createWorkInProgress( - JSCompiler_object_inline_componentStack_3262, + JSCompiler_object_inline_componentStack_3320, nextPrimaryChildren )) : ((nextPrimaryChildren = createFiberFromFragment( @@ -11755,11 +11713,11 @@ )), (nextPrimaryChildren.flags |= 2)), (nextPrimaryChildren.return = workInProgress), - (JSCompiler_object_inline_stack_3261.return = workInProgress), - (JSCompiler_object_inline_stack_3261.sibling = nextPrimaryChildren), - (workInProgress.child = JSCompiler_object_inline_stack_3261), - bailoutOffscreenComponent(null, JSCompiler_object_inline_stack_3261), - (JSCompiler_object_inline_stack_3261 = workInProgress.child), + (JSCompiler_object_inline_stack_3319.return = workInProgress), + (JSCompiler_object_inline_stack_3319.sibling = nextPrimaryChildren), + (workInProgress.child = JSCompiler_object_inline_stack_3319), + bailoutOffscreenComponent(null, JSCompiler_object_inline_stack_3319), + (JSCompiler_object_inline_stack_3319 = workInProgress.child), (nextPrimaryChildren = current.child.memoizedState), null === nextPrimaryChildren ? (nextPrimaryChildren = mountSuspenseOffscreenState(renderLanes)) @@ -11775,18 +11733,18 @@ baseLanes: nextPrimaryChildren.baseLanes | renderLanes, cachePool: nextFallbackChildren })), - (JSCompiler_object_inline_stack_3261.memoizedState = + (JSCompiler_object_inline_stack_3319.memoizedState = nextPrimaryChildren), - (JSCompiler_object_inline_stack_3261.childLanes = + (JSCompiler_object_inline_stack_3319.childLanes = getRemainingWorkInPrimaryTree( current, - JSCompiler_object_inline_digest_3260, + JSCompiler_object_inline_digest_3318, renderLanes )), (workInProgress.memoizedState = SUSPENDED_MARKER), bailoutOffscreenComponent( current.child, - JSCompiler_object_inline_stack_3261 + JSCompiler_object_inline_stack_3319 ) ); null !== prevState && @@ -11798,16 +11756,16 @@ current = renderLanes.sibling; renderLanes = createWorkInProgress(renderLanes, { mode: "visible", - children: JSCompiler_object_inline_stack_3261.children + children: JSCompiler_object_inline_stack_3319.children }); renderLanes.return = workInProgress; renderLanes.sibling = null; null !== current && - ((JSCompiler_object_inline_digest_3260 = workInProgress.deletions), - null === JSCompiler_object_inline_digest_3260 + ((JSCompiler_object_inline_digest_3318 = workInProgress.deletions), + null === JSCompiler_object_inline_digest_3318 ? ((workInProgress.deletions = [current]), (workInProgress.flags |= 16)) - : JSCompiler_object_inline_digest_3260.push(current)); + : JSCompiler_object_inline_digest_3318.push(current)); workInProgress.child = renderLanes; workInProgress.memoizedState = null; return renderLanes; @@ -13121,8 +13079,8 @@ ) (newChildLanes |= _child2.lanes | _child2.childLanes), - (subtreeFlags |= _child2.subtreeFlags & 132120576), - (subtreeFlags |= _child2.flags & 132120576), + (subtreeFlags |= _child2.subtreeFlags & 133169152), + (subtreeFlags |= _child2.flags & 133169152), (_treeBaseDuration += _child2.treeBaseDuration), (_child2 = _child2.sibling); completedWork.treeBaseDuration = _treeBaseDuration; @@ -13134,8 +13092,8 @@ ) (newChildLanes |= _treeBaseDuration.lanes | _treeBaseDuration.childLanes), - (subtreeFlags |= _treeBaseDuration.subtreeFlags & 132120576), - (subtreeFlags |= _treeBaseDuration.flags & 132120576), + (subtreeFlags |= _treeBaseDuration.subtreeFlags & 133169152), + (subtreeFlags |= _treeBaseDuration.flags & 133169152), (_treeBaseDuration.return = completedWork), (_treeBaseDuration = _treeBaseDuration.sibling); else if ((completedWork.mode & ProfileMode) !== NoMode) { @@ -14988,7 +14946,9 @@ (viewTransitionCancelableChildren = []), viewTransitionCancelableChildren.push( instance, - oldName, + 0 === viewTransitionHostInstanceIdx + ? oldName + : oldName + "_" + viewTransitionHostInstanceIdx, child.memoizedProps )); viewTransitionHostInstanceIdx++; @@ -19135,7 +19095,7 @@ throw Error("Unknown root exit status."); } if (null !== ReactSharedInternals.actQueue) - commitRoot( + completeRoot( forceSync, yieldEndTime, lanes, @@ -19145,6 +19105,7 @@ workInProgressDeferredLane, workInProgressRootInterleavedUpdatedLanes, workInProgressSuspendedRetryLanes, + workInProgressRootDidSkipSuspendedSiblings, startTime, null, null, @@ -19169,7 +19130,7 @@ if (0 !== getNextLanes(forceSync, 0, !0)) break a; pendingEffectsLanes = lanes; forceSync.timeoutHandle = scheduleTimeout( - commitRootWhenReady.bind( + completeRootWhenReady.bind( null, forceSync, yieldEndTime, @@ -19190,7 +19151,7 @@ ); break a; } - commitRootWhenReady( + completeRootWhenReady( forceSync, yieldEndTime, workInProgressRootRecoverableErrors, @@ -19213,7 +19174,7 @@ } while (1); ensureRootIsScheduled(root); } - function commitRootWhenReady( + function completeRootWhenReady( root, finishedWork, recoverableErrors, @@ -19239,23 +19200,26 @@ subtreeFlags & 8192 || 16785408 === (subtreeFlags & 16785408) || isGestureTransition - ) + ) { + suspendedState = { + stylesheets: null, + count: 0, + imgCount: 0, + imgBytes: 0, + suspenseyImages: [], + waitingForImages: !0, + waitingForViewTransition: !1, + unsuspend: noop$1 + }; + appearingViewTransitions = null; + accumulateSuspenseyCommitOnFiber(finishedWork, lanes, suspendedState); if ( - ((suspendedState = { - stylesheets: null, - count: 0, - imgCount: 0, - imgBytes: 0, - suspenseyImages: [], - waitingForImages: !0, - waitingForViewTransition: !1, - unsuspend: noop$1 - }), - (appearingViewTransitions = null), - accumulateSuspenseyCommitOnFiber(finishedWork, lanes, suspendedState), - (isViewTransitionEligible || isGestureTransition) && - null === root.stoppingGestures && - ((subtreeFlags = suspendedState), + isViewTransitionEligible || + (isGestureTransition && + null !== root.pendingGestures && + null === root.pendingGestures.running) + ) + (subtreeFlags = suspendedState), (isViewTransitionEligible = root.containerInfo), (isViewTransitionEligible = ( 9 === isViewTransitionEligible.nodeType @@ -19269,19 +19233,18 @@ isViewTransitionEligible.finished.then( subtreeFlags, subtreeFlags - ))), - (subtreeFlags = - (lanes & 62914560) === lanes - ? globalMostRecentFallbackTime - now$1() - : (lanes & 4194048) === lanes - ? globalMostRecentTransitionTime - now$1() - : 0), - (subtreeFlags = waitForCommitToBeReady(suspendedState, subtreeFlags)), - null !== subtreeFlags) - ) { + )); + subtreeFlags = + (lanes & 62914560) === lanes + ? globalMostRecentFallbackTime - now$1() + : (lanes & 4194048) === lanes + ? globalMostRecentTransitionTime - now$1() + : 0; + subtreeFlags = waitForCommitToBeReady(suspendedState, subtreeFlags); + if (null !== subtreeFlags) { pendingEffectsLanes = lanes; root.cancelPendingCommit = subtreeFlags( - commitRoot.bind( + completeRoot.bind( null, root, finishedWork, @@ -19292,6 +19255,7 @@ spawnedLane, updatedLanes, suspendedRetryLanes, + didSkipSuspendedSiblings, exitStatus, suspendedState, suspendedState.waitingForViewTransition @@ -19317,7 +19281,8 @@ ); return; } - commitRoot( + } + completeRoot( root, finishedWork, lanes, @@ -19327,6 +19292,7 @@ spawnedLane, updatedLanes, suspendedRetryLanes, + didSkipSuspendedSiblings, exitStatus, suspendedState, suspendedCommitReason, @@ -20308,6 +20274,14 @@ break; case 5: resetHooksOnUnwind(unitOfWork); + var fiber = unitOfWork; + fiber === hydrationParentFiber && + (isHydrating + ? (popToNextHostParent(fiber), + 5 === fiber.tag && + null != fiber.stateNode && + (nextHydratableInstance = fiber.stateNode)) + : (popToNextHostParent(fiber), (isHydrating = !0))); default: unwindInterruptedWork(current, unitOfWork), (unitOfWork = workInProgress = @@ -20446,7 +20420,7 @@ workInProgressRootExitStatus = RootSuspendedAtTheShell; workInProgress = null; } - function commitRoot( + function completeRoot( root, finishedWork, lanes, @@ -20456,6 +20430,7 @@ spawnedLane, updatedLanes, suspendedRetryLanes, + didSkipSuspendedSiblings, exitStatus, suspendedState, suspendedCommitReason, @@ -20470,33 +20445,96 @@ if ((executionContext & (RenderContext | CommitContext)) !== NoContext) throw Error("Should not already be working."); setCurrentTrackFromLanes(lanes); - exitStatus === RootErrored - ? logErroredRenderPhase( - completedRenderStartTime, - completedRenderEndTime, - lanes, - workInProgressUpdateTask - ) - : null !== recoverableErrors - ? logRecoveredRenderPhase( - completedRenderStartTime, - completedRenderEndTime, - lanes, - recoverableErrors, - null !== finishedWork && - null !== finishedWork.alternate && - finishedWork.alternate.memoizedState.isDehydrated && - 0 !== (finishedWork.flags & 256), - workInProgressUpdateTask - ) - : logRenderPhase( - completedRenderStartTime, - completedRenderEndTime, - lanes, - workInProgressUpdateTask - ); - if (null === finishedWork) - null !== root.stoppingGestures && stopCompletedGestures(root); + 64 === lanes && + (completedRenderStartTime < gestureClampTime && + (completedRenderStartTime = gestureClampTime), + completedRenderEndTime < gestureClampTime && + (completedRenderEndTime = gestureClampTime)); + if (exitStatus === RootErrored) + logErroredRenderPhase( + completedRenderStartTime, + completedRenderEndTime, + lanes, + workInProgressUpdateTask + ); + else if (null !== recoverableErrors) { + var startTime = completedRenderStartTime, + endTime = completedRenderEndTime, + hydrationFailed = + null !== finishedWork && + null !== finishedWork.alternate && + finishedWork.alternate.memoizedState.isDehydrated && + 0 !== (finishedWork.flags & 256), + debugTask = workInProgressUpdateTask; + if (supportsUserTiming && !(endTime <= startTime)) { + for (var properties = [], i = 0; i < recoverableErrors.length; i++) { + var error = recoverableErrors[i].value; + properties.push([ + "Recoverable Error", + "object" === typeof error && + null !== error && + "string" === typeof error.message + ? String(error.message) + : String(error) + ]); + } + startTime = { + start: startTime, + end: endTime, + detail: { + devtools: { + color: "primary-dark", + track: currentTrack, + trackGroup: LANES_TRACK_GROUP, + tooltipText: hydrationFailed + ? "Hydration Failed" + : "Recovered after Error", + properties: properties + } + } + }; + debugTask + ? debugTask.run( + performance.measure.bind(performance, "Recovered", startTime) + ) + : performance.measure("Recovered", startTime); + performance.clearMeasures("Recovered"); + } + } else + (debugTask = completedRenderStartTime), + (startTime = completedRenderEndTime), + (endTime = workInProgressUpdateTask), + !supportsUserTiming || + startTime <= debugTask || + ((hydrationFailed = + (lanes & 738197653) === lanes ? "tertiary-dark" : "primary-dark"), + (properties = + (lanes & 536870912) === lanes + ? "Prepared" + : (lanes & 201326741) === lanes + ? "Hydrated" + : "Render"), + endTime + ? endTime.run( + console.timeStamp.bind( + console, + properties, + debugTask, + startTime, + currentTrack, + LANES_TRACK_GROUP, + hydrationFailed + ) + ) + : console.timeStamp( + properties, + debugTask, + startTime, + currentTrack, + LANES_TRACK_GROUP, + hydrationFailed + )); + if (null === finishedWork) 64 === lanes && stopCommittedGesture(root); else { 0 === lanes && console.error( @@ -20506,119 +20544,330 @@ throw Error( "Cannot commit the same tree as before. This error is likely caused by a bug in React. Please file an issue." ); - didIncludeRenderPhaseUpdate = - finishedWork.lanes | finishedWork.childLanes; - didIncludeRenderPhaseUpdate |= concurrentlyUpdatedLanes; - null === root.pendingGestures && - (0 !== (didIncludeRenderPhaseUpdate & 64) && - ((gestureUpdateTime = -1.1), - (gestureUpdateType = 0), - (gestureSuspendedTime = -1.1), - (gestureEventRepeatTime = gestureEventTime), - (gestureEventTime = -1.1)), - (didIncludeRenderPhaseUpdate &= -65)); - markRootFinished( - root, - lanes, - didIncludeRenderPhaseUpdate, - spawnedLane, - updatedLanes, - suspendedRetryLanes - ); root === workInProgressRoot && ((workInProgress = workInProgressRoot = null), (workInProgressRootRenderLanes = 0)); pendingFinishedWork = finishedWork; pendingEffectsRoot = root; pendingEffectsLanes = lanes; - pendingEffectsRemainingLanes = didIncludeRenderPhaseUpdate; pendingPassiveTransitions = transitions; pendingRecoverableErrors = recoverableErrors; pendingEffectsRenderEndTime = completedRenderEndTime; pendingSuspendedCommitReason = suspendedCommitReason; pendingDelayedCommitReason = IMMEDIATE_COMMIT; pendingSuspendedViewTransitionReason = null; - if (64 === lanes) - commitGestureOnRoot( + if ( + 64 === lanes && + ((debugTask = root.pendingGestures), + null !== debugTask && !debugTask.committing) + ) { + markRootSuspended( root, - finishedWork, - recoverableErrors, - suspendedState + lanes, + spawnedLane, + !didSkipSuspendedSiblings ); - else { - pendingViewTransitionEvents = null; - (lanes & 335544064) === lanes - ? ((pendingTransitionTypes = claimQueuedTransitionTypes(root)), - (recoverableErrors = 10262)) - : ((pendingTransitionTypes = null), (recoverableErrors = 10256)); - 0 !== finishedWork.actualDuration || - 0 !== (finishedWork.subtreeFlags & recoverableErrors) || - 0 !== (finishedWork.flags & recoverableErrors) - ? ((root.callbackNode = null), - (root.callbackPriority = 0), - scheduleCallback$1(NormalPriority$1, function () { - schedulerEvent = window.event; - pendingDelayedCommitReason === IMMEDIATE_COMMIT && - (pendingDelayedCommitReason = DELAYED_PASSIVE_COMMIT); - flushPassiveEffects(); - return null; - })) - : ((root.callbackNode = null), (root.callbackPriority = 0)); - commitErrors = null; - commitStartTime = now(); - null !== suspendedCommitReason && - logSuspendedCommitPhase( - completedRenderEndTime, - commitStartTime, - suspendedCommitReason, - workInProgressUpdateTask - ); - shouldStartViewTransition = !1; - suspendedCommitReason = 0 !== (finishedWork.flags & 13878); - if ( - 0 !== (finishedWork.subtreeFlags & 13878) || - suspendedCommitReason - ) { - suspendedCommitReason = ReactSharedInternals.T; - ReactSharedInternals.T = null; - completedRenderEndTime = ReactDOMSharedInternals.p; - ReactDOMSharedInternals.p = DiscreteEventPriority; - recoverableErrors = executionContext; - executionContext |= CommitContext; - try { - commitBeforeMutationEffects(root, finishedWork, lanes); - } finally { - (executionContext = recoverableErrors), - (ReactDOMSharedInternals.p = completedRenderEndTime), - (ReactSharedInternals.T = suspendedCommitReason); + if (null === debugTask.running) + if ( + ((suspendedCommitReason = root.pendingGestures), + null === suspendedCommitReason) + ) + ensureRootIsScheduled(root); + else { + animatingLanes |= pendingEffectsLanes; + animatingTask = null; + startTime = ReactSharedInternals.T; + ReactSharedInternals.T = null; + endTime = ReactDOMSharedInternals.p; + ReactDOMSharedInternals.p = DiscreteEventPriority; + hydrationFailed = executionContext; + executionContext |= CommitContext; + try { + didWarnForRootClone || + ((didWarnForRootClone = !0), + console.warn( + "startGestureTransition() caused something to mutate or relayout the root. This currently requires a clone of the whole document. Make sure to add a directly around an absolutely positioned DOM node to minimize the impact of any changes caused by the Gesture Transition." + )); + var rootContainer = root.containerInfo, + documentElement = + 9 === rootContainer.nodeType + ? rootContainer.documentElement + : rootContainer.ownerDocument.documentElement; + null !== documentElement && + "" === documentElement.style.viewTransitionName && + (documentElement.style.viewTransitionName = "none"); + var containerInstance = + 9 === rootContainer.nodeType + ? rootContainer.body + : "HTML" === rootContainer.nodeName + ? rootContainer.ownerDocument.body + : rootContainer; + var containerParent = containerInstance.parentNode; + if (null === containerParent) + throw Error( + "Cannot use a startGestureTransition() on a detached root." + ); + var clone = containerInstance.cloneNode(!1), + computedStyle = getComputedStyle(containerInstance); + if ( + "absolute" !== computedStyle.position && + "fixed" !== computedStyle.position + ) { + for ( + rootContainer = containerParent; + null != rootContainer.parentNode && + 9 !== rootContainer.parentNode.nodeType && + "static" === getComputedStyle(rootContainer).position; + + ) + rootContainer = rootContainer.parentNode; + var positionedAncestorStyle = rootContainer.style, + containerInstanceStyle = containerInstance.style, + prevAncestorTranslate = positionedAncestorStyle.translate, + prevAncestorScale = positionedAncestorStyle.scale, + prevAncestorRotate = positionedAncestorStyle.rotate, + prevAncestorTransform = positionedAncestorStyle.transform, + prevTranslate = containerInstanceStyle.translate, + prevScale = containerInstanceStyle.scale, + prevRotate = containerInstanceStyle.rotate, + prevTransform = containerInstanceStyle.transform; + positionedAncestorStyle.translate = "none"; + positionedAncestorStyle.scale = "none"; + positionedAncestorStyle.rotate = "none"; + positionedAncestorStyle.transform = "none"; + containerInstanceStyle.translate = "none"; + containerInstanceStyle.scale = "none"; + containerInstanceStyle.rotate = "none"; + containerInstanceStyle.transform = "none"; + var ancestorRect = rootContainer.getBoundingClientRect(), + rect = containerInstance.getBoundingClientRect(), + cloneStyle = clone.style; + cloneStyle.position = "absolute"; + cloneStyle.top = rect.top - ancestorRect.top + "px"; + cloneStyle.left = rect.left - ancestorRect.left + "px"; + cloneStyle.width = rect.width + "px"; + cloneStyle.height = rect.height + "px"; + cloneStyle.margin = "0px"; + cloneStyle.boxSizing = "border-box"; + positionedAncestorStyle.translate = prevAncestorTranslate; + positionedAncestorStyle.scale = prevAncestorScale; + positionedAncestorStyle.rotate = prevAncestorRotate; + positionedAncestorStyle.transform = prevAncestorTransform; + containerInstanceStyle.translate = prevTranslate; + containerInstanceStyle.scale = prevScale; + containerInstanceStyle.rotate = prevRotate; + containerInstanceStyle.transform = prevTransform; + } + clone.style.viewTransitionName = "root"; + var transform = computedStyle.transform; + "none" === transform && (transform = ""); + var scale = computedStyle.scale; + if ("none" !== scale && "" !== scale) { + var parts = scale.split(" "); + transform = + (3 === parts.length ? "scale3d" : "scale") + + "(" + + parts.join(", ") + + ") " + + transform; + } + var rotate = computedStyle.rotate; + if ("none" !== rotate && "" !== rotate) { + var _parts = rotate.split(" "); + transform = + 1 === _parts.length + ? "rotate(" + _parts[0] + ") " + transform + : 2 === _parts.length + ? "rotate" + + _parts[0].toUpperCase() + + "(" + + _parts[1] + + ") " + + transform + : "rotate3d(" + _parts.join(", ") + ") " + transform; + } + var translate = computedStyle.translate; + if ("none" !== translate && "" !== translate) { + var _parts2 = translate.split(" "); + transform = + (3 === _parts2.length ? "translate3d" : "translate") + + "(" + + _parts2.join(", ") + + ") " + + transform; + } + var transform$jscomp$0 = transform; + clone.style.translate = "none"; + clone.style.scale = "none"; + clone.style.rotate = "none"; + clone.style.transform = + "translate(-20000px, -20000px) " + transform$jscomp$0; + containerInstance.parentNode.insertBefore( + clone, + containerInstance.nextSibling + ); + root.gestureClone = clone; + recursivelyInsertClones( + finishedWork, + clone, + null, + CLONE_UPDATE + ); + } finally { + (executionContext = hydrationFailed), + (ReactDOMSharedInternals.p = endTime), + (ReactSharedInternals.T = startTime); + } + pendingTransitionTypes = suspendedCommitReason.types; + pendingEffectsStatus = PENDING_GESTURE_MUTATION_PHASE; + pendingViewTransition = suspendedCommitReason.running = + startGestureTransition( + suspendedState, + root.containerInfo, + suspendedCommitReason.provider, + suspendedCommitReason.rangeStart, + suspendedCommitReason.rangeEnd, + pendingTransitionTypes, + flushGestureMutations, + flushGestureAnimations, + reportViewTransitionError, + finishedViewTransition.bind(null, pendingEffectsLanes) + ); } - } - finishedWork = shouldStartViewTransition; - null !== root.stoppingGestures && - (stopCompletedGestures(root), (finishedWork = !1)); - pendingEffectsStatus = PENDING_MUTATION_PHASE; - finishedWork - ? ((animatingLanes |= lanes), - (animatingTask = null), - (pendingViewTransition = startViewTransition( - suspendedState, - root.containerInfo, - pendingTransitionTypes, - flushMutationEffects, - flushLayoutEffects, - flushAfterMutationEffects, - flushSpawnedWork, - flushPassiveEffects, - reportViewTransitionError, - suspendedViewTransition, - finishedViewTransition.bind(null, lanes) - ))) - : (flushMutationEffects(), - flushLayoutEffects(), - flushSpawnedWork()); + else + finalizeRender(lanes, completedRenderEndTime), + (pendingFinishedWork = pendingEffectsRoot = null), + (pendingEffectsLanes = 0); + root.cancelPendingCommit = scheduleGestureCommit( + debugTask, + completeRoot.bind( + null, + root, + finishedWork, + lanes, + recoverableErrors, + transitions, + didIncludeRenderPhaseUpdate, + spawnedLane, + updatedLanes, + suspendedRetryLanes, + didSkipSuspendedSiblings, + exitStatus, + suspendedState, + "Waiting for the Gesture to finish", + completedRenderStartTime, + completedRenderEndTime + ) + ); + return; } + commitRoot( + root, + finishedWork, + lanes, + spawnedLane, + updatedLanes, + suspendedRetryLanes, + suspendedState, + suspendedCommitReason, + completedRenderEndTime + ); } } + function commitRoot( + root, + finishedWork, + lanes, + spawnedLane, + updatedLanes, + suspendedRetryLanes, + suspendedState, + suspendedCommitReason, + completedRenderEndTime + ) { + var remainingLanes = finishedWork.lanes | finishedWork.childLanes; + pendingEffectsRemainingLanes = remainingLanes; + remainingLanes |= concurrentlyUpdatedLanes; + null === root.pendingGestures && + (0 !== (remainingLanes & 64) && + ((gestureUpdateTime = -1.1), + (gestureUpdateType = 0), + (gestureSuspendedTime = -1.1), + (gestureEventRepeatTime = gestureEventTime), + (gestureEventTime = -1.1)), + (remainingLanes &= -65)); + markRootFinished( + root, + lanes, + remainingLanes, + spawnedLane, + updatedLanes, + suspendedRetryLanes + ); + pendingViewTransitionEvents = null; + (lanes & 335544064) === lanes + ? ((pendingTransitionTypes = claimQueuedTransitionTypes(root)), + (spawnedLane = 10262)) + : ((pendingTransitionTypes = null), (spawnedLane = 10256)); + 0 !== finishedWork.actualDuration || + 0 !== (finishedWork.subtreeFlags & spawnedLane) || + 0 !== (finishedWork.flags & spawnedLane) + ? ((root.callbackNode = null), + (root.callbackPriority = 0), + scheduleCallback$1(NormalPriority$1, function () { + schedulerEvent = window.event; + pendingDelayedCommitReason === IMMEDIATE_COMMIT && + (pendingDelayedCommitReason = DELAYED_PASSIVE_COMMIT); + flushPassiveEffects(); + return null; + })) + : ((root.callbackNode = null), (root.callbackPriority = 0)); + commitErrors = null; + commitStartTime = now(); + null !== suspendedCommitReason && + logSuspendedCommitPhase( + completedRenderEndTime, + commitStartTime, + suspendedCommitReason, + workInProgressUpdateTask + ); + shouldStartViewTransition = !1; + suspendedCommitReason = 0 !== (finishedWork.flags & 13878); + if (0 !== (finishedWork.subtreeFlags & 13878) || suspendedCommitReason) { + suspendedCommitReason = ReactSharedInternals.T; + ReactSharedInternals.T = null; + completedRenderEndTime = ReactDOMSharedInternals.p; + ReactDOMSharedInternals.p = DiscreteEventPriority; + spawnedLane = executionContext; + executionContext |= CommitContext; + try { + commitBeforeMutationEffects(root, finishedWork, lanes); + } finally { + (executionContext = spawnedLane), + (ReactDOMSharedInternals.p = completedRenderEndTime), + (ReactSharedInternals.T = suspendedCommitReason); + } + } + 64 === lanes && stopCommittedGesture(root); + pendingEffectsStatus = PENDING_MUTATION_PHASE; + shouldStartViewTransition + ? ((animatingLanes |= lanes), + (animatingTask = null), + (pendingViewTransition = startViewTransition( + suspendedState, + root.containerInfo, + pendingTransitionTypes, + flushMutationEffects, + flushLayoutEffects, + flushAfterMutationEffects, + flushSpawnedWork, + flushPassiveEffects, + reportViewTransitionError, + suspendedViewTransition, + finishedViewTransition.bind(null, lanes) + ))) + : (flushMutationEffects(), flushLayoutEffects(), flushSpawnedWork()); + } function reportViewTransitionError(error) { if (pendingEffectsStatus !== NO_PENDING_EFFECTS) { var onRecoverableError = pendingEffectsRoot.onRecoverableError; @@ -21078,172 +21327,6 @@ flushSyncWorkAcrossRoots_impl(0, !1); } } - function commitGestureOnRoot( - root, - finishedWork, - recoverableErrors, - suspendedState - ) { - recoverableErrors = root.pendingGestures; - if (null === recoverableErrors) ensureRootIsScheduled(root); - else { - deleteScheduledGesture(root, recoverableErrors); - animatingLanes |= pendingEffectsLanes; - animatingTask = null; - var prevTransition = ReactSharedInternals.T; - ReactSharedInternals.T = null; - var previousPriority = ReactDOMSharedInternals.p; - ReactDOMSharedInternals.p = DiscreteEventPriority; - var prevExecutionContext = executionContext; - executionContext |= CommitContext; - try { - didWarnForRootClone || - ((didWarnForRootClone = !0), - console.warn( - "startGestureTransition() caused something to mutate or relayout the root. This currently requires a clone of the whole document. Make sure to add a directly around an absolutely positioned DOM node to minimize the impact of any changes caused by the Gesture Transition." - )); - var rootContainer = root.containerInfo, - documentElement = - 9 === rootContainer.nodeType - ? rootContainer.documentElement - : rootContainer.ownerDocument.documentElement; - null !== documentElement && - "" === documentElement.style.viewTransitionName && - (documentElement.style.viewTransitionName = "none"); - var containerInstance = - 9 === rootContainer.nodeType - ? rootContainer.body - : "HTML" === rootContainer.nodeName - ? rootContainer.ownerDocument.body - : rootContainer; - var containerParent = containerInstance.parentNode; - if (null === containerParent) - throw Error( - "Cannot use a startGestureTransition() on a detached root." - ); - var clone = containerInstance.cloneNode(!1), - computedStyle = getComputedStyle(containerInstance); - if ( - "absolute" !== computedStyle.position && - "fixed" !== computedStyle.position - ) { - for ( - rootContainer = containerParent; - null != rootContainer.parentNode && - 9 !== rootContainer.parentNode.nodeType && - "static" === getComputedStyle(rootContainer).position; - - ) - rootContainer = rootContainer.parentNode; - var positionedAncestorStyle = rootContainer.style, - containerInstanceStyle = containerInstance.style, - prevAncestorTranslate = positionedAncestorStyle.translate, - prevAncestorScale = positionedAncestorStyle.scale, - prevAncestorRotate = positionedAncestorStyle.rotate, - prevAncestorTransform = positionedAncestorStyle.transform, - prevTranslate = containerInstanceStyle.translate, - prevScale = containerInstanceStyle.scale, - prevRotate = containerInstanceStyle.rotate, - prevTransform = containerInstanceStyle.transform; - positionedAncestorStyle.translate = "none"; - positionedAncestorStyle.scale = "none"; - positionedAncestorStyle.rotate = "none"; - positionedAncestorStyle.transform = "none"; - containerInstanceStyle.translate = "none"; - containerInstanceStyle.scale = "none"; - containerInstanceStyle.rotate = "none"; - containerInstanceStyle.transform = "none"; - var ancestorRect = rootContainer.getBoundingClientRect(), - rect = containerInstance.getBoundingClientRect(), - cloneStyle = clone.style; - cloneStyle.position = "absolute"; - cloneStyle.top = rect.top - ancestorRect.top + "px"; - cloneStyle.left = rect.left - ancestorRect.left + "px"; - cloneStyle.width = rect.width + "px"; - cloneStyle.height = rect.height + "px"; - cloneStyle.margin = "0px"; - cloneStyle.boxSizing = "border-box"; - positionedAncestorStyle.translate = prevAncestorTranslate; - positionedAncestorStyle.scale = prevAncestorScale; - positionedAncestorStyle.rotate = prevAncestorRotate; - positionedAncestorStyle.transform = prevAncestorTransform; - containerInstanceStyle.translate = prevTranslate; - containerInstanceStyle.scale = prevScale; - containerInstanceStyle.rotate = prevRotate; - containerInstanceStyle.transform = prevTransform; - } - clone.style.viewTransitionName = "root"; - var transform = computedStyle.transform; - "none" === transform && (transform = ""); - var scale = computedStyle.scale; - if ("none" !== scale && "" !== scale) { - var parts = scale.split(" "); - transform = - (3 === parts.length ? "scale3d" : "scale") + - "(" + - parts.join(", ") + - ") " + - transform; - } - var rotate = computedStyle.rotate; - if ("none" !== rotate && "" !== rotate) { - var _parts = rotate.split(" "); - transform = - 1 === _parts.length - ? "rotate(" + _parts[0] + ") " + transform - : 2 === _parts.length - ? "rotate" + - _parts[0].toUpperCase() + - "(" + - _parts[1] + - ") " + - transform - : "rotate3d(" + _parts.join(", ") + ") " + transform; - } - var translate = computedStyle.translate; - if ("none" !== translate && "" !== translate) { - var _parts2 = translate.split(" "); - transform = - (3 === _parts2.length ? "translate3d" : "translate") + - "(" + - _parts2.join(", ") + - ") " + - transform; - } - var transform$jscomp$0 = transform; - clone.style.translate = "none"; - clone.style.scale = "none"; - clone.style.rotate = "none"; - clone.style.transform = - "translate(-20000px, -20000px) " + transform$jscomp$0; - containerInstance.parentNode.insertBefore( - clone, - containerInstance.nextSibling - ); - root.gestureClone = clone; - recursivelyInsertClones(finishedWork, clone, null, CLONE_UPDATE); - } finally { - (executionContext = prevExecutionContext), - (ReactDOMSharedInternals.p = previousPriority), - (ReactSharedInternals.T = prevTransition); - } - pendingTransitionTypes = recoverableErrors.types; - pendingEffectsStatus = PENDING_GESTURE_MUTATION_PHASE; - pendingViewTransition = recoverableErrors.running = - startGestureTransition( - suspendedState, - root.containerInfo, - recoverableErrors.provider, - recoverableErrors.rangeStart, - recoverableErrors.rangeEnd, - pendingTransitionTypes, - flushGestureMutations, - flushGestureAnimations, - reportViewTransitionError, - finishedViewTransition.bind(null, pendingEffectsLanes) - ); - } - } function flushGestureMutations() { if (pendingEffectsStatus === PENDING_GESTURE_MUTATION_PHASE) { pendingEffectsStatus = NO_PENDING_EFFECTS; @@ -21299,16 +21382,42 @@ (ReactDOMSharedInternals.p = previousPriority), (ReactSharedInternals.T = prevTransition); } + commitEndTime = now(); + root = pendingEffectsRenderEndTime; + prevTransition = commitEndTime; + !supportsUserTiming || + prevTransition <= root || + (animatingTask + ? animatingTask.run( + console.timeStamp.bind( + console, + "Create Ghost Tree", + root, + prevTransition, + currentTrack, + LANES_TRACK_GROUP, + "secondary-dark" + ) + ) + : console.timeStamp( + "Create Ghost Tree", + root, + prevTransition, + currentTrack, + LANES_TRACK_GROUP, + "secondary-dark" + )); pendingEffectsStatus = PENDING_GESTURE_ANIMATION_PHASE; } } function flushGestureAnimations() { flushGestureMutations(); if (pendingEffectsStatus === PENDING_GESTURE_ANIMATION_PHASE) { - var lanes = pendingEffectsLanes; + var lanes = pendingEffectsLanes, + startViewTransitionStartTime = commitEndTime; commitEndTime = now(); logStartViewTransitionYieldPhase( - pendingEffectsRenderEndTime, + startViewTransitionStartTime, commitEndTime, pendingDelayedCommitReason === ABORTED_VIEW_TRANSITION_COMMIT, animatingTask @@ -21316,8 +21425,8 @@ pendingDelayedCommitReason !== ABORTED_VIEW_TRANSITION_COMMIT && (pendingDelayedCommitReason = ANIMATION_STARTED_COMMIT); pendingEffectsStatus = NO_PENDING_EFFECTS; - var root = pendingEffectsRoot, - finishedWork = pendingFinishedWork; + startViewTransitionStartTime = pendingEffectsRoot; + var finishedWork = pendingFinishedWork; pendingFinishedWork = pendingEffectsRoot = null; pendingEffectsLanes = 0; pendingViewTransition = null; @@ -21329,14 +21438,16 @@ executionContext |= CommitContext; try { restoreViewTransitionsOnFiber(finishedWork), - restoreRootViewTransitionName(root.containerInfo); + restoreRootViewTransitionName( + startViewTransitionStartTime.containerInfo + ); } finally { (executionContext = prevExecutionContext), (ReactDOMSharedInternals.p = previousPriority), (ReactSharedInternals.T = prevTransition); } finalizeRender(lanes, commitEndTime); - ensureRootIsScheduled(root); + ensureRootIsScheduled(startViewTransitionStartTime); } } function makeErrorInfo(componentStack) { @@ -21599,8 +21710,7 @@ function pingSuspendedRoot(root, wakeable, pingedLanes) { var pingCache = root.pingCache; null !== pingCache && pingCache.delete(wakeable); - root.pingedLanes |= root.suspendedLanes & pingedLanes; - root.warmLanes &= ~pingedLanes; + markRootPinged$1(root, pingedLanes); 64 === pingedLanes ? 0 > gestureUpdateTime && ((gestureClampTime = gestureUpdateTime = now()), @@ -26374,6 +26484,14 @@ new: new ViewTransitionPseudoElement("new", name) }; } + function getCurrentGestureOffset(timeline) { + timeline = timeline.currentTime; + if (null === timeline) + throw Error( + "Cannot start a gesture with a disconnected AnimationTimeline." + ); + return "number" === typeof timeline ? timeline : timeline.value; + } function FragmentInstance(fragmentFiber) { this._fragmentFiber = fragmentFiber; this._observers = this._eventListeners = null; @@ -27767,11 +27885,7 @@ this.pooledCache = this.pendingIndicator = null; this.pooledCacheLanes = 0; this.formState = formState; - this.gestureClone = - this.stoppingGestures = - this.pendingGestures = - this.transitionTypes = - null; + this.gestureClone = this.pendingGestures = this.transitionTypes = null; this.incompleteTransitions = new Map(); this.passiveEffectDuration = this.effectDuration = -0; this.memoizedUpdaters = new Set(); @@ -32769,11 +32883,11 @@ }; (function () { var isomorphicReactPackageVersion = React.version; - if ("19.3.0-experimental-65eec428-20251218" !== isomorphicReactPackageVersion) + if ("19.3.0-experimental-bef88f7c-20260116" !== isomorphicReactPackageVersion) throw Error( 'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' + (isomorphicReactPackageVersion + - "\n - react-dom: 19.3.0-experimental-65eec428-20251218\nLearn more: https://react.dev/warnings/version-mismatch") + "\n - react-dom: 19.3.0-experimental-bef88f7c-20260116\nLearn more: https://react.dev/warnings/version-mismatch") ); })(); ("function" === typeof Map && @@ -32810,10 +32924,10 @@ !(function () { var internals = { bundleType: 1, - version: "19.3.0-experimental-65eec428-20251218", + version: "19.3.0-experimental-bef88f7c-20260116", rendererPackageName: "react-dom", currentDispatcherRef: ReactSharedInternals, - reconcilerVersion: "19.3.0-experimental-65eec428-20251218" + reconcilerVersion: "19.3.0-experimental-bef88f7c-20260116" }; internals.overrideHookState = overrideHookState; internals.overrideHookStateDeletePath = overrideHookStateDeletePath; @@ -33127,5 +33241,5 @@ } }; }; - exports.version = "19.3.0-experimental-65eec428-20251218"; + exports.version = "19.3.0-experimental-bef88f7c-20260116"; })(); diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-unstable_testing.production.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-unstable_testing.production.js index 1760d70eec7e..62deac03650d 100644 --- a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-unstable_testing.production.js +++ b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-unstable_testing.production.js @@ -822,6 +822,10 @@ function markRootUpdated$1(root, updateLane) { 268435456 !== updateLane && ((root.suspendedLanes = 0), (root.pingedLanes = 0), (root.warmLanes = 0)); } +function markRootPinged$1(root, pingedLanes) { + root.pingedLanes |= root.suspendedLanes & pingedLanes; + root.warmLanes &= ~pingedLanes; +} function markRootFinished( root, finishedLanes, @@ -2668,7 +2672,7 @@ function createWorkInProgress(current, pendingProps) { (workInProgress.subtreeFlags = 0), (workInProgress.deletions = null), (workInProgress.key = current.key)); - workInProgress.flags = current.flags & 132120576; + workInProgress.flags = current.flags & 133169152; workInProgress.childLanes = current.childLanes; workInProgress.lanes = current.lanes; workInProgress.child = current.child; @@ -2687,7 +2691,7 @@ function createWorkInProgress(current, pendingProps) { return workInProgress; } function resetWorkInProgress(workInProgress, renderLanes) { - workInProgress.flags &= 132120578; + workInProgress.flags &= 133169154; var current = workInProgress.alternate; null === current ? ((workInProgress.childLanes = 0), @@ -3417,36 +3421,30 @@ function startScheduledGesture( gestureOptions, transitionTypes ) { - if (gestureOptions && null != gestureOptions.rangeStart) - var JSCompiler_temp = gestureOptions.rangeStart; - else { - JSCompiler_temp = gestureTimeline.currentTime; - if (null === JSCompiler_temp) throw Error(formatProdErrorMessage(549)); - JSCompiler_temp = - "number" === typeof JSCompiler_temp - ? JSCompiler_temp - : JSCompiler_temp.value; - } + var rangeStart = + gestureOptions && null != gestureOptions.rangeStart + ? gestureOptions.rangeStart + : getCurrentGestureOffset(gestureTimeline); gestureOptions = gestureOptions && null != gestureOptions.rangeEnd ? gestureOptions.rangeEnd - : 50 > JSCompiler_temp + : 50 > rangeStart ? 100 : 0; for (root = root.pendingGestures; null !== root; ) { if (root.provider === gestureTimeline) { root.count++; - root.rangeStart = JSCompiler_temp; + root.rangeStart = rangeStart; root.rangeEnd = gestureOptions; if (null !== transitionTypes) for ( gestureTimeline = root.types, null === gestureTimeline && (gestureTimeline = root.types = []), - JSCompiler_temp = 0; - JSCompiler_temp < transitionTypes.length; - JSCompiler_temp++ + rangeStart = 0; + rangeStart < transitionTypes.length; + rangeStart++ ) - (gestureOptions = transitionTypes[JSCompiler_temp]), + (gestureOptions = transitionTypes[rangeStart]), -1 === gestureTimeline.indexOf(gestureOptions) && gestureTimeline.push(gestureOptions); return root; @@ -3456,27 +3454,24 @@ function startScheduledGesture( } return null; } -function deleteScheduledGesture(root, gesture) { - null === gesture.prev - ? (root.pendingGestures === gesture && - ((root.pendingGestures = gesture.next), - null === root.pendingGestures && (root.pendingLanes &= -65)), - root.stoppingGestures === gesture && - (root.stoppingGestures = gesture.next)) - : ((gesture.prev.next = gesture.next), - null !== gesture.next && (gesture.next.prev = gesture.prev), - (gesture.prev = null), - (gesture.next = null)); -} -function stopCompletedGestures(root) { - var gesture = root.stoppingGestures; - for (root.stoppingGestures = null; null !== gesture; ) - null !== gesture.running && - (gesture.running.skipTransition(), (gesture.running = null)), - (root = gesture.next), - (gesture.next = null), - (gesture.prev = null), - (gesture = root); +function stopCommittedGesture(root) { + var committedGesture = root.pendingGestures; + if (null !== committedGesture) { + committedGesture.committing = !1; + var nextGesture = committedGesture.next; + null === nextGesture + ? (root.pendingLanes &= -65) + : (nextGesture.prev = null); + root.pendingGestures = nextGesture; + root = committedGesture.running; + null !== root && ((committedGesture.running = null), root.skipTransition()); + } +} +function scheduleGestureCommit(gesture, callback) { + gesture.commit = callback; + return function () { + gesture.commit = null; + }; } var prevOnStartTransitionFinish = ReactSharedInternals.S; ReactSharedInternals.S = function (transition, returnValue) { @@ -3507,23 +3502,52 @@ ReactSharedInternals.S = function (transition, returnValue) { }; function chainGestureCancellation(root, scheduledGesture, prevCancel) { return function () { - if ( - null !== scheduledGesture && - (scheduledGesture.count--, 0 === scheduledGesture.count) - ) { - deleteScheduledGesture(root, scheduledGesture); - var runningTransition = scheduledGesture.running; - if (null !== runningTransition) { - var pendingLanesExcludingGestureLane = root.pendingLanes & -65; - 0 !== (pendingLanesExcludingGestureLane & 127) || - 0 !== (pendingLanesExcludingGestureLane & 4194048) - ? ((runningTransition = root.stoppingGestures), - null !== runningTransition && - ((scheduledGesture.next = runningTransition), - (runningTransition.prev = scheduledGesture)), - (root.stoppingGestures = scheduledGesture)) - : ((scheduledGesture.running = null), - runningTransition.skipTransition()); + if (null !== scheduledGesture) { + if (0 !== scheduledGesture.revertLane) { + var entangledLanes = + scheduledGesture.revertLane | requestTransitionLane(); + markRootEntangled(root, entangledLanes); + } + scheduledGesture.count--; + if (0 === scheduledGesture.count) { + var finalOffset = getCurrentGestureOffset(scheduledGesture.provider), + rangeStart = scheduledGesture.rangeStart, + rangeEnd = scheduledGesture.rangeEnd; + entangledLanes = scheduledGesture.running; + null !== entangledLanes && + (rangeStart < rangeEnd + ? finalOffset > rangeStart + (rangeEnd - rangeStart) / 2 + : finalOffset < rangeEnd + (rangeStart - rangeEnd) / 2) + ? ((scheduledGesture.committing = !0), + root.pendingGestures === scheduledGesture && + ((entangledLanes = scheduledGesture.commit), + null !== entangledLanes + ? ((scheduledGesture.commit = null), entangledLanes()) + : null !== root.pendingGestures && + (markRootPinged$1(root, 64), ensureRootIsScheduled(root)))) + : null === scheduledGesture.prev + ? (root.pendingGestures === scheduledGesture && + ((root.pendingGestures = scheduledGesture.next), + (finalOffset = root.pendingLanes), + null === root.pendingGestures && (finalOffset &= -65), + markRootFinished(root, 64, finalOffset, 0, 0, 0), + workInProgressRoot === root && + 64 === workInProgressRootRenderLanes + ? 0 === (executionContext & 2) && prepareFreshStack(root, 0) + : null !== root.cancelPendingCommit && + 64 === pendingEffectsLanes && + ((finalOffset = root.cancelPendingCommit), + null !== finalOffset && + ((root.cancelPendingCommit = null), finalOffset())), + null !== root.pendingGestures && markRootPinged$1(root, 64), + ensureRootIsScheduled(root)), + (scheduledGesture.running = null), + null !== entangledLanes && entangledLanes.skipTransition()) + : ((scheduledGesture.prev.next = scheduledGesture.next), + null !== scheduledGesture.next && + (scheduledGesture.next.prev = scheduledGesture.prev), + (scheduledGesture.prev = null), + (scheduledGesture.next = null)); } } null !== prevCancel && prevCancel(); @@ -5040,16 +5064,18 @@ function updateReducerImpl(hook, current, reducer) { if (64 === updateLane) { var scheduledGesture = update.gesture; if (null !== scheduledGesture) - if (0 === scheduledGesture.count) { + if (0 !== scheduledGesture.count || scheduledGesture.committing) + if (64 !== renderLanes) shouldSkipUpdate = !0; + else { + shouldSkipUpdate = workInProgressRoot; + if (null === shouldSkipUpdate) + throw Error(formatProdErrorMessage(349)); + shouldSkipUpdate = + shouldSkipUpdate.pendingGestures !== scheduledGesture; + } + else { update = update.next; continue; - } else if (64 !== renderLanes) shouldSkipUpdate = !0; - else { - shouldSkipUpdate = workInProgressRoot; - if (null === shouldSkipUpdate) - throw Error(formatProdErrorMessage(349)); - shouldSkipUpdate = - shouldSkipUpdate.pendingGestures !== scheduledGesture; } } if (shouldSkipUpdate) @@ -5672,7 +5698,7 @@ function updateDeferredValueImpl(hook, prevValue, value, initialValue) { hook ); if ( - 0 === (renderLanes & 42) || + 0 === (renderLanes & 106) || (0 !== (renderLanes & 1073741824) && 0 === (workInProgressRootRenderLanes & 261930)) ) @@ -5938,6 +5964,9 @@ function dispatchOptimisticSetState(fiber, throwIfDuringRender, queue, action) { rangeEnd: 100, types: null, running: null, + commit: null, + committing: !1, + revertLane: 0, prev: fiber, next: null }; @@ -5947,7 +5976,10 @@ function dispatchOptimisticSetState(fiber, throwIfDuringRender, queue, action) { ensureRootIsScheduled(throwIfDuringRender); throwIfDuringRender = transition; } - action.gesture = throwIfDuringRender; + throwIfDuringRender = action.gesture = throwIfDuringRender; + 0 === throwIfDuringRender.revertLane + ? (throwIfDuringRender.revertLane = action.revertLane) + : (action.revertLane = throwIfDuringRender.revertLane); } } function isRenderPhaseUpdate(fiber) { @@ -7572,7 +7604,7 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { mode: "hidden", children: nextProps.children })), - (nextProps.subtreeFlags = nextFallbackChildren.subtreeFlags & 132120576), + (nextProps.subtreeFlags = nextFallbackChildren.subtreeFlags & 133169152), null !== digest ? (nextPrimaryChildren = createWorkInProgress( digest, @@ -8554,8 +8586,8 @@ function bubbleProperties(completedWork) { if (didBailout) for (var child$118 = completedWork.child; null !== child$118; ) (newChildLanes |= child$118.lanes | child$118.childLanes), - (subtreeFlags |= child$118.subtreeFlags & 132120576), - (subtreeFlags |= child$118.flags & 132120576), + (subtreeFlags |= child$118.subtreeFlags & 133169152), + (subtreeFlags |= child$118.flags & 133169152), (child$118.return = completedWork), (child$118 = child$118.sibling); else @@ -9901,7 +9933,9 @@ function measureViewTransitionHostInstancesRecursive( (viewTransitionCancelableChildren = []), viewTransitionCancelableChildren.push( instance, - oldName, + 0 === viewTransitionHostInstanceIdx + ? oldName + : oldName + "_" + viewTransitionHostInstanceIdx, child.memoizedProps )); viewTransitionHostInstanceIdx++; @@ -13081,7 +13115,7 @@ function performWorkOnRoot(root$jscomp$0, lanes, forceSync) { if (0 !== getNextLanes(shouldTimeSlice, 0, !0)) break a; pendingEffectsLanes = lanes; shouldTimeSlice.timeoutHandle = scheduleTimeout( - commitRootWhenReady.bind( + completeRootWhenReady.bind( null, shouldTimeSlice, forceSync, @@ -13102,7 +13136,7 @@ function performWorkOnRoot(root$jscomp$0, lanes, forceSync) { ); break a; } - commitRootWhenReady( + completeRootWhenReady( shouldTimeSlice, forceSync, workInProgressRootRecoverableErrors, @@ -13124,7 +13158,7 @@ function performWorkOnRoot(root$jscomp$0, lanes, forceSync) { } while (1); ensureRootIsScheduled(root$jscomp$0); } -function commitRootWhenReady( +function completeRootWhenReady( root, finishedWork, recoverableErrors, @@ -13143,34 +13177,33 @@ function commitRootWhenReady( root.timeoutHandle = -1; var subtreeFlags = finishedWork.subtreeFlags, isViewTransitionEligible = (lanes & 335544064) === lanes, - isGestureTransition = 64 === lanes; - suspendedCommitReason = null; + isGestureTransition = 64 === lanes, + suspendedState = null; if ( isViewTransitionEligible || subtreeFlags & 8192 || 16785408 === (subtreeFlags & 16785408) || isGestureTransition - ) + ) { + suspendedState = { + stylesheets: null, + count: 0, + imgCount: 0, + imgBytes: 0, + suspenseyImages: [], + waitingForImages: !0, + waitingForViewTransition: !1, + unsuspend: noop$1 + }; + appearingViewTransitions = null; + accumulateSuspenseyCommitOnFiber(finishedWork, lanes, suspendedState); if ( - ((suspendedCommitReason = { - stylesheets: null, - count: 0, - imgCount: 0, - imgBytes: 0, - suspenseyImages: [], - waitingForImages: !0, - waitingForViewTransition: !1, - unsuspend: noop$1 - }), - (appearingViewTransitions = null), - accumulateSuspenseyCommitOnFiber( - finishedWork, - lanes, - suspendedCommitReason - ), - (isViewTransitionEligible || isGestureTransition) && - null === root.stoppingGestures && - ((subtreeFlags = suspendedCommitReason), + isViewTransitionEligible || + (isGestureTransition && + null !== root.pendingGestures && + null === root.pendingGestures.running) + ) + (subtreeFlags = suspendedState), (isViewTransitionEligible = root.containerInfo), (isViewTransitionEligible = ( 9 === isViewTransitionEligible.nodeType @@ -13181,22 +13214,18 @@ function commitRootWhenReady( (subtreeFlags.count++, (subtreeFlags.waitingForViewTransition = !0), (subtreeFlags = onUnsuspend.bind(subtreeFlags)), - isViewTransitionEligible.finished.then(subtreeFlags, subtreeFlags))), - (subtreeFlags = - (lanes & 62914560) === lanes - ? globalMostRecentFallbackTime - now() - : (lanes & 4194048) === lanes - ? globalMostRecentTransitionTime - now() - : 0), - (subtreeFlags = waitForCommitToBeReady( - suspendedCommitReason, - subtreeFlags - )), - null !== subtreeFlags) - ) { + isViewTransitionEligible.finished.then(subtreeFlags, subtreeFlags)); + subtreeFlags = + (lanes & 62914560) === lanes + ? globalMostRecentFallbackTime - now() + : (lanes & 4194048) === lanes + ? globalMostRecentTransitionTime - now() + : 0; + subtreeFlags = waitForCommitToBeReady(suspendedState, subtreeFlags); + if (null !== subtreeFlags) { pendingEffectsLanes = lanes; root.cancelPendingCommit = subtreeFlags( - commitRoot.bind( + completeRoot.bind( null, root, finishedWork, @@ -13207,8 +13236,9 @@ function commitRootWhenReady( spawnedLane, updatedLanes, suspendedRetryLanes, + didSkipSuspendedSiblings, exitStatus, - suspendedCommitReason, + suspendedState, null, completedRenderStartTime, completedRenderEndTime @@ -13217,7 +13247,8 @@ function commitRootWhenReady( markRootSuspended(root, lanes, spawnedLane, !didSkipSuspendedSiblings); return; } - commitRoot( + } + completeRoot( root, finishedWork, lanes, @@ -13227,8 +13258,12 @@ function commitRootWhenReady( spawnedLane, updatedLanes, suspendedRetryLanes, + didSkipSuspendedSiblings, exitStatus, - suspendedCommitReason + suspendedState, + suspendedCommitReason, + completedRenderStartTime, + completedRenderEndTime ); } function isRenderConsistentWithExternalStores(finishedWork) { @@ -13635,6 +13670,14 @@ function replaySuspendedUnitOfWork(unitOfWork) { break; case 5: resetHooksOnUnwind(next); + var fiber = next; + fiber === hydrationParentFiber && + (isHydrating + ? (popToNextHostParent(fiber), + 5 === fiber.tag && + null != fiber.stateNode && + (nextHydratableInstance = fiber.stateNode)) + : (popToNextHostParent(fiber), (isHydrating = !0))); default: unwindInterruptedWork(current, next), (next = workInProgress = @@ -13756,7 +13799,7 @@ function unwindUnitOfWork(unitOfWork, skipSiblings) { workInProgressRootExitStatus = 6; workInProgress = null; } -function commitRoot( +function completeRoot( root, finishedWork, lanes, @@ -13766,97 +13809,290 @@ function commitRoot( spawnedLane, updatedLanes, suspendedRetryLanes, + didSkipSuspendedSiblings, exitStatus, - suspendedState + suspendedState, + suspendedCommitReason, + completedRenderStartTime, + completedRenderEndTime ) { root.cancelPendingCommit = null; do flushPendingEffects(); while (0 !== pendingEffectsStatus); if (0 !== (executionContext & 6)) throw Error(formatProdErrorMessage(327)); - if (null === finishedWork) - null !== root.stoppingGestures && stopCompletedGestures(root); + if (null === finishedWork) 64 === lanes && stopCommittedGesture(root); else { if (finishedWork === root.current) throw Error(formatProdErrorMessage(177)); - didIncludeRenderPhaseUpdate = finishedWork.lanes | finishedWork.childLanes; - didIncludeRenderPhaseUpdate |= concurrentlyUpdatedLanes; - null === root.pendingGestures && (didIncludeRenderPhaseUpdate &= -65); - markRootFinished( - root, - lanes, - didIncludeRenderPhaseUpdate, - spawnedLane, - updatedLanes, - suspendedRetryLanes - ); root === workInProgressRoot && ((workInProgress = workInProgressRoot = null), (workInProgressRootRenderLanes = 0)); pendingFinishedWork = finishedWork; pendingEffectsRoot = root; pendingEffectsLanes = lanes; - pendingEffectsRemainingLanes = didIncludeRenderPhaseUpdate; pendingPassiveTransitions = transitions; pendingRecoverableErrors = recoverableErrors; - if (64 === lanes) - commitGestureOnRoot( - root, - finishedWork, - recoverableErrors, - suspendedState - ); - else { - pendingViewTransitionEvents = null; - (lanes & 335544064) === lanes - ? ((pendingTransitionTypes = claimQueuedTransitionTypes(root)), - (recoverableErrors = 10262)) - : ((pendingTransitionTypes = null), (recoverableErrors = 10256)); - 0 !== (finishedWork.subtreeFlags & recoverableErrors) || - 0 !== (finishedWork.flags & recoverableErrors) - ? ((root.callbackNode = null), - (root.callbackPriority = 0), - scheduleCallback$1(NormalPriority$1, function () { - flushPassiveEffects(); - return null; - })) - : ((root.callbackNode = null), (root.callbackPriority = 0)); - shouldStartViewTransition = !1; - recoverableErrors = 0 !== (finishedWork.flags & 13878); - if (0 !== (finishedWork.subtreeFlags & 13878) || recoverableErrors) { - recoverableErrors = ReactSharedInternals.T; - ReactSharedInternals.T = null; - transitions = ReactDOMSharedInternals.p; - ReactDOMSharedInternals.p = 2; - spawnedLane = executionContext; - executionContext |= 4; - try { - commitBeforeMutationEffects(root, finishedWork, lanes); - } finally { - (executionContext = spawnedLane), - (ReactDOMSharedInternals.p = transitions), - (ReactSharedInternals.T = recoverableErrors); + if ( + 64 === lanes && + ((suspendedCommitReason = root.pendingGestures), + null !== suspendedCommitReason && !suspendedCommitReason.committing) + ) { + markRootSuspended(root, lanes, spawnedLane, !didSkipSuspendedSiblings); + if (null === suspendedCommitReason.running) { + var finishedGesture = root.pendingGestures; + if (null === finishedGesture) ensureRootIsScheduled(root); + else { + var prevTransition = ReactSharedInternals.T; + ReactSharedInternals.T = null; + var previousPriority = ReactDOMSharedInternals.p; + ReactDOMSharedInternals.p = 2; + var prevExecutionContext = executionContext; + executionContext |= 4; + try { + var rootContainer = root.containerInfo, + documentElement = + 9 === rootContainer.nodeType + ? rootContainer.documentElement + : rootContainer.ownerDocument.documentElement; + null !== documentElement && + "" === documentElement.style.viewTransitionName && + (documentElement.style.viewTransitionName = "none"); + var containerInstance = + 9 === rootContainer.nodeType + ? rootContainer.body + : "HTML" === rootContainer.nodeName + ? rootContainer.ownerDocument.body + : rootContainer; + var containerParent = containerInstance.parentNode; + if (null === containerParent) + throw Error(formatProdErrorMessage(552)); + var clone = containerInstance.cloneNode(!1), + computedStyle = getComputedStyle(containerInstance); + if ( + "absolute" !== computedStyle.position && + "fixed" !== computedStyle.position + ) { + for ( + rootContainer = containerParent; + null != rootContainer.parentNode && + 9 !== rootContainer.parentNode.nodeType && + "static" === getComputedStyle(rootContainer).position; + + ) + rootContainer = rootContainer.parentNode; + var positionedAncestorStyle = rootContainer.style, + containerInstanceStyle = containerInstance.style, + prevAncestorTranslate = positionedAncestorStyle.translate, + prevAncestorScale = positionedAncestorStyle.scale, + prevAncestorRotate = positionedAncestorStyle.rotate, + prevAncestorTransform = positionedAncestorStyle.transform, + prevTranslate = containerInstanceStyle.translate, + prevScale = containerInstanceStyle.scale, + prevRotate = containerInstanceStyle.rotate, + prevTransform = containerInstanceStyle.transform; + positionedAncestorStyle.translate = "none"; + positionedAncestorStyle.scale = "none"; + positionedAncestorStyle.rotate = "none"; + positionedAncestorStyle.transform = "none"; + containerInstanceStyle.translate = "none"; + containerInstanceStyle.scale = "none"; + containerInstanceStyle.rotate = "none"; + containerInstanceStyle.transform = "none"; + var ancestorRect = rootContainer.getBoundingClientRect(), + rect = containerInstance.getBoundingClientRect(), + cloneStyle = clone.style; + cloneStyle.position = "absolute"; + cloneStyle.top = rect.top - ancestorRect.top + "px"; + cloneStyle.left = rect.left - ancestorRect.left + "px"; + cloneStyle.width = rect.width + "px"; + cloneStyle.height = rect.height + "px"; + cloneStyle.margin = "0px"; + cloneStyle.boxSizing = "border-box"; + positionedAncestorStyle.translate = prevAncestorTranslate; + positionedAncestorStyle.scale = prevAncestorScale; + positionedAncestorStyle.rotate = prevAncestorRotate; + positionedAncestorStyle.transform = prevAncestorTransform; + containerInstanceStyle.translate = prevTranslate; + containerInstanceStyle.scale = prevScale; + containerInstanceStyle.rotate = prevRotate; + containerInstanceStyle.transform = prevTransform; + } + clone.style.viewTransitionName = "root"; + var transform = computedStyle.transform; + "none" === transform && (transform = ""); + var scale = computedStyle.scale; + if ("none" !== scale && "" !== scale) { + var parts = scale.split(" "); + transform = + (3 === parts.length ? "scale3d" : "scale") + + "(" + + parts.join(", ") + + ") " + + transform; + } + var rotate = computedStyle.rotate; + if ("none" !== rotate && "" !== rotate) { + var parts$270 = rotate.split(" "); + transform = + 1 === parts$270.length + ? "rotate(" + parts$270[0] + ") " + transform + : 2 === parts$270.length + ? "rotate" + + parts$270[0].toUpperCase() + + "(" + + parts$270[1] + + ") " + + transform + : "rotate3d(" + parts$270.join(", ") + ") " + transform; + } + var translate = computedStyle.translate; + if ("none" !== translate && "" !== translate) { + var parts$271 = translate.split(" "); + transform = + (3 === parts$271.length ? "translate3d" : "translate") + + "(" + + parts$271.join(", ") + + ") " + + transform; + } + var JSCompiler_inline_result = transform; + clone.style.translate = "none"; + clone.style.scale = "none"; + clone.style.rotate = "none"; + clone.style.transform = + "translate(-20000px, -20000px) " + JSCompiler_inline_result; + containerInstance.parentNode.insertBefore( + clone, + containerInstance.nextSibling + ); + root.gestureClone = clone; + recursivelyInsertClones(finishedWork, clone, null, 0); + } finally { + (executionContext = prevExecutionContext), + (ReactDOMSharedInternals.p = previousPriority), + (ReactSharedInternals.T = prevTransition); + } + pendingTransitionTypes = finishedGesture.types; + pendingEffectsStatus = 6; + pendingViewTransition = finishedGesture.running = + startGestureTransition( + suspendedState, + root.containerInfo, + finishedGesture.provider, + finishedGesture.rangeStart, + finishedGesture.rangeEnd, + pendingTransitionTypes, + flushGestureMutations, + flushGestureAnimations, + reportViewTransitionError, + null + ); } - } - finishedWork = shouldStartViewTransition; - null !== root.stoppingGestures && - (stopCompletedGestures(root), (finishedWork = !1)); - pendingEffectsStatus = 1; - finishedWork - ? (pendingViewTransition = startViewTransition( - suspendedState, - root.containerInfo, - pendingTransitionTypes, - flushMutationEffects, - flushLayoutEffects, - flushAfterMutationEffects, - flushSpawnedWork, - flushPassiveEffects, - reportViewTransitionError, - null, - null - )) - : (flushMutationEffects(), flushLayoutEffects(), flushSpawnedWork()); + } else + (pendingFinishedWork = pendingEffectsRoot = null), + (pendingEffectsLanes = 0); + root.cancelPendingCommit = scheduleGestureCommit( + suspendedCommitReason, + completeRoot.bind( + null, + root, + finishedWork, + lanes, + recoverableErrors, + transitions, + didIncludeRenderPhaseUpdate, + spawnedLane, + updatedLanes, + suspendedRetryLanes, + didSkipSuspendedSiblings, + exitStatus, + suspendedState, + "Waiting for the Gesture to finish", + completedRenderStartTime, + completedRenderEndTime + ) + ); + return; + } + commitRoot( + root, + finishedWork, + lanes, + spawnedLane, + updatedLanes, + suspendedRetryLanes, + suspendedState + ); + } +} +function commitRoot( + root, + finishedWork, + lanes, + spawnedLane, + updatedLanes, + suspendedRetryLanes, + suspendedState +) { + var remainingLanes = finishedWork.lanes | finishedWork.childLanes; + pendingEffectsRemainingLanes = remainingLanes; + remainingLanes |= concurrentlyUpdatedLanes; + null === root.pendingGestures && (remainingLanes &= -65); + markRootFinished( + root, + lanes, + remainingLanes, + spawnedLane, + updatedLanes, + suspendedRetryLanes + ); + pendingViewTransitionEvents = null; + (lanes & 335544064) === lanes + ? ((pendingTransitionTypes = claimQueuedTransitionTypes(root)), + (spawnedLane = 10262)) + : ((pendingTransitionTypes = null), (spawnedLane = 10256)); + 0 !== (finishedWork.subtreeFlags & spawnedLane) || + 0 !== (finishedWork.flags & spawnedLane) + ? ((root.callbackNode = null), + (root.callbackPriority = 0), + scheduleCallback$1(NormalPriority$1, function () { + flushPassiveEffects(); + return null; + })) + : ((root.callbackNode = null), (root.callbackPriority = 0)); + shouldStartViewTransition = !1; + spawnedLane = 0 !== (finishedWork.flags & 13878); + if (0 !== (finishedWork.subtreeFlags & 13878) || spawnedLane) { + spawnedLane = ReactSharedInternals.T; + ReactSharedInternals.T = null; + updatedLanes = ReactDOMSharedInternals.p; + ReactDOMSharedInternals.p = 2; + suspendedRetryLanes = executionContext; + executionContext |= 4; + try { + commitBeforeMutationEffects(root, finishedWork, lanes); + } finally { + (executionContext = suspendedRetryLanes), + (ReactDOMSharedInternals.p = updatedLanes), + (ReactSharedInternals.T = spawnedLane); } } + 64 === lanes && stopCommittedGesture(root); + pendingEffectsStatus = 1; + shouldStartViewTransition + ? (pendingViewTransition = startViewTransition( + suspendedState, + root.containerInfo, + pendingTransitionTypes, + flushMutationEffects, + flushLayoutEffects, + flushAfterMutationEffects, + flushSpawnedWork, + flushPassiveEffects, + reportViewTransitionError, + null, + null + )) + : (flushMutationEffects(), flushLayoutEffects(), flushSpawnedWork()); } function reportViewTransitionError(error) { if (0 !== pendingEffectsStatus) { @@ -14141,161 +14377,6 @@ function flushSpawnedWork() { flushSyncWorkAcrossRoots_impl(0, !1); } } -function commitGestureOnRoot( - root, - finishedWork, - recoverableErrors, - suspendedState -) { - recoverableErrors = root.pendingGestures; - if (null === recoverableErrors) ensureRootIsScheduled(root); - else { - deleteScheduledGesture(root, recoverableErrors); - var prevTransition = ReactSharedInternals.T; - ReactSharedInternals.T = null; - var previousPriority = ReactDOMSharedInternals.p; - ReactDOMSharedInternals.p = 2; - var prevExecutionContext = executionContext; - executionContext |= 4; - try { - var rootContainer = root.containerInfo, - documentElement = - 9 === rootContainer.nodeType - ? rootContainer.documentElement - : rootContainer.ownerDocument.documentElement; - null !== documentElement && - "" === documentElement.style.viewTransitionName && - (documentElement.style.viewTransitionName = "none"); - var containerInstance = - 9 === rootContainer.nodeType - ? rootContainer.body - : "HTML" === rootContainer.nodeName - ? rootContainer.ownerDocument.body - : rootContainer; - var containerParent = containerInstance.parentNode; - if (null === containerParent) throw Error(formatProdErrorMessage(552)); - var clone = containerInstance.cloneNode(!1), - computedStyle = getComputedStyle(containerInstance); - if ( - "absolute" !== computedStyle.position && - "fixed" !== computedStyle.position - ) { - for ( - rootContainer = containerParent; - null != rootContainer.parentNode && - 9 !== rootContainer.parentNode.nodeType && - "static" === getComputedStyle(rootContainer).position; - - ) - rootContainer = rootContainer.parentNode; - var positionedAncestorStyle = rootContainer.style, - containerInstanceStyle = containerInstance.style, - prevAncestorTranslate = positionedAncestorStyle.translate, - prevAncestorScale = positionedAncestorStyle.scale, - prevAncestorRotate = positionedAncestorStyle.rotate, - prevAncestorTransform = positionedAncestorStyle.transform, - prevTranslate = containerInstanceStyle.translate, - prevScale = containerInstanceStyle.scale, - prevRotate = containerInstanceStyle.rotate, - prevTransform = containerInstanceStyle.transform; - positionedAncestorStyle.translate = "none"; - positionedAncestorStyle.scale = "none"; - positionedAncestorStyle.rotate = "none"; - positionedAncestorStyle.transform = "none"; - containerInstanceStyle.translate = "none"; - containerInstanceStyle.scale = "none"; - containerInstanceStyle.rotate = "none"; - containerInstanceStyle.transform = "none"; - var ancestorRect = rootContainer.getBoundingClientRect(), - rect = containerInstance.getBoundingClientRect(), - cloneStyle = clone.style; - cloneStyle.position = "absolute"; - cloneStyle.top = rect.top - ancestorRect.top + "px"; - cloneStyle.left = rect.left - ancestorRect.left + "px"; - cloneStyle.width = rect.width + "px"; - cloneStyle.height = rect.height + "px"; - cloneStyle.margin = "0px"; - cloneStyle.boxSizing = "border-box"; - positionedAncestorStyle.translate = prevAncestorTranslate; - positionedAncestorStyle.scale = prevAncestorScale; - positionedAncestorStyle.rotate = prevAncestorRotate; - positionedAncestorStyle.transform = prevAncestorTransform; - containerInstanceStyle.translate = prevTranslate; - containerInstanceStyle.scale = prevScale; - containerInstanceStyle.rotate = prevRotate; - containerInstanceStyle.transform = prevTransform; - } - clone.style.viewTransitionName = "root"; - var transform = computedStyle.transform; - "none" === transform && (transform = ""); - var scale = computedStyle.scale; - if ("none" !== scale && "" !== scale) { - var parts = scale.split(" "); - transform = - (3 === parts.length ? "scale3d" : "scale") + - "(" + - parts.join(", ") + - ") " + - transform; - } - var rotate = computedStyle.rotate; - if ("none" !== rotate && "" !== rotate) { - var parts$270 = rotate.split(" "); - transform = - 1 === parts$270.length - ? "rotate(" + parts$270[0] + ") " + transform - : 2 === parts$270.length - ? "rotate" + - parts$270[0].toUpperCase() + - "(" + - parts$270[1] + - ") " + - transform - : "rotate3d(" + parts$270.join(", ") + ") " + transform; - } - var translate = computedStyle.translate; - if ("none" !== translate && "" !== translate) { - var parts$271 = translate.split(" "); - transform = - (3 === parts$271.length ? "translate3d" : "translate") + - "(" + - parts$271.join(", ") + - ") " + - transform; - } - var JSCompiler_inline_result = transform; - clone.style.translate = "none"; - clone.style.scale = "none"; - clone.style.rotate = "none"; - clone.style.transform = - "translate(-20000px, -20000px) " + JSCompiler_inline_result; - containerInstance.parentNode.insertBefore( - clone, - containerInstance.nextSibling - ); - root.gestureClone = clone; - recursivelyInsertClones(finishedWork, clone, null, 0); - } finally { - (executionContext = prevExecutionContext), - (ReactDOMSharedInternals.p = previousPriority), - (ReactSharedInternals.T = prevTransition); - } - pendingTransitionTypes = recoverableErrors.types; - pendingEffectsStatus = 6; - pendingViewTransition = recoverableErrors.running = startGestureTransition( - suspendedState, - root.containerInfo, - recoverableErrors.provider, - recoverableErrors.rangeStart, - recoverableErrors.rangeEnd, - pendingTransitionTypes, - flushGestureMutations, - flushGestureAnimations, - reportViewTransitionError, - null - ); - } -} function flushGestureMutations() { if (6 === pendingEffectsStatus) { pendingEffectsStatus = 0; @@ -14498,8 +14579,7 @@ function attachPingListener(root, wakeable, lanes) { function pingSuspendedRoot(root, wakeable, pingedLanes) { var pingCache = root.pingCache; null !== pingCache && pingCache.delete(wakeable); - root.pingedLanes |= root.suspendedLanes & pingedLanes; - root.warmLanes &= ~pingedLanes; + markRootPinged$1(root, pingedLanes); workInProgressRoot === root && (workInProgressRootRenderLanes & pingedLanes) === pingedLanes && (4 === workInProgressRootExitStatus || @@ -14915,20 +14995,20 @@ function debounceScrollEnd(targetInst, nativeEvent, nativeEventTarget) { (nativeEventTarget[internalScrollTimer] = targetInst)); } for ( - var i$jscomp$inline_1825 = 0; - i$jscomp$inline_1825 < simpleEventPluginEvents.length; - i$jscomp$inline_1825++ + var i$jscomp$inline_1838 = 0; + i$jscomp$inline_1838 < simpleEventPluginEvents.length; + i$jscomp$inline_1838++ ) { - var eventName$jscomp$inline_1826 = - simpleEventPluginEvents[i$jscomp$inline_1825], - domEventName$jscomp$inline_1827 = - eventName$jscomp$inline_1826.toLowerCase(), - capitalizedEvent$jscomp$inline_1828 = - eventName$jscomp$inline_1826[0].toUpperCase() + - eventName$jscomp$inline_1826.slice(1); + var eventName$jscomp$inline_1839 = + simpleEventPluginEvents[i$jscomp$inline_1838], + domEventName$jscomp$inline_1840 = + eventName$jscomp$inline_1839.toLowerCase(), + capitalizedEvent$jscomp$inline_1841 = + eventName$jscomp$inline_1839[0].toUpperCase() + + eventName$jscomp$inline_1839.slice(1); registerSimpleEvent( - domEventName$jscomp$inline_1827, - "on" + capitalizedEvent$jscomp$inline_1828 + domEventName$jscomp$inline_1840, + "on" + capitalizedEvent$jscomp$inline_1841 ); } registerSimpleEvent(ANIMATION_END, "onAnimationEnd"); @@ -17586,6 +17666,11 @@ function createViewTransitionInstance(name) { new: new ViewTransitionPseudoElement("new", name) }; } +function getCurrentGestureOffset(timeline) { + timeline = timeline.currentTime; + if (null === timeline) throw Error(formatProdErrorMessage(549)); + return "number" === typeof timeline ? timeline : timeline.value; +} function FragmentInstance(fragmentFiber) { this._fragmentFiber = fragmentFiber; this._observers = this._eventListeners = null; @@ -19214,11 +19299,7 @@ function FiberRootNode( this.pooledCache = this.pendingIndicator = null; this.pooledCacheLanes = 0; this.formState = formState; - this.gestureClone = - this.stoppingGestures = - this.pendingGestures = - this.transitionTypes = - null; + this.gestureClone = this.pendingGestures = this.transitionTypes = null; this.incompleteTransitions = new Map(); } function createFiberRoot( @@ -19957,16 +20038,16 @@ ReactDOMHydrationRoot.prototype.unstable_scheduleHydration = function (target) { 0 === i && attemptExplicitHydrationTarget(target); } }; -var isomorphicReactPackageVersion$jscomp$inline_2243 = React.version; +var isomorphicReactPackageVersion$jscomp$inline_2256 = React.version; if ( - "19.3.0-experimental-65eec428-20251218" !== - isomorphicReactPackageVersion$jscomp$inline_2243 + "19.3.0-experimental-bef88f7c-20260116" !== + isomorphicReactPackageVersion$jscomp$inline_2256 ) throw Error( formatProdErrorMessage( 527, - isomorphicReactPackageVersion$jscomp$inline_2243, - "19.3.0-experimental-65eec428-20251218" + isomorphicReactPackageVersion$jscomp$inline_2256, + "19.3.0-experimental-bef88f7c-20260116" ) ); ReactDOMSharedInternals.findDOMNode = function (componentOrElement) { @@ -19986,24 +20067,24 @@ ReactDOMSharedInternals.findDOMNode = function (componentOrElement) { null === componentOrElement ? null : componentOrElement.stateNode; return componentOrElement; }; -var internals$jscomp$inline_2951 = { +var internals$jscomp$inline_2964 = { bundleType: 0, - version: "19.3.0-experimental-65eec428-20251218", + version: "19.3.0-experimental-bef88f7c-20260116", rendererPackageName: "react-dom", currentDispatcherRef: ReactSharedInternals, - reconcilerVersion: "19.3.0-experimental-65eec428-20251218" + reconcilerVersion: "19.3.0-experimental-bef88f7c-20260116" }; if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { - var hook$jscomp$inline_2952 = __REACT_DEVTOOLS_GLOBAL_HOOK__; + var hook$jscomp$inline_2965 = __REACT_DEVTOOLS_GLOBAL_HOOK__; if ( - !hook$jscomp$inline_2952.isDisabled && - hook$jscomp$inline_2952.supportsFiber + !hook$jscomp$inline_2965.isDisabled && + hook$jscomp$inline_2965.supportsFiber ) try { - (rendererID = hook$jscomp$inline_2952.inject( - internals$jscomp$inline_2951 + (rendererID = hook$jscomp$inline_2965.inject( + internals$jscomp$inline_2964 )), - (injectedHook = hook$jscomp$inline_2952); + (injectedHook = hook$jscomp$inline_2965); } catch (err) {} } exports.createComponentSelector = function (component) { @@ -20249,4 +20330,4 @@ exports.observeVisibleRects = function ( } }; }; -exports.version = "19.3.0-experimental-65eec428-20251218"; +exports.version = "19.3.0-experimental-bef88f7c-20260116"; diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom.development.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom.development.js index 5c37e9562dae..d87945124964 100644 --- a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom.development.js +++ b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom.development.js @@ -422,7 +422,7 @@ exports.useFormStatus = function () { return resolveDispatcher().useHostTransitionStatus(); }; - exports.version = "19.3.0-experimental-65eec428-20251218"; + exports.version = "19.3.0-experimental-bef88f7c-20260116"; "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom.production.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom.production.js index b729c0735432..7c942948f2c5 100644 --- a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom.production.js +++ b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom.production.js @@ -213,4 +213,4 @@ exports.useFormState = function (action, initialState, permalink) { exports.useFormStatus = function () { return ReactSharedInternals.H.useHostTransitionStatus(); }; -exports.version = "19.3.0-experimental-65eec428-20251218"; +exports.version = "19.3.0-experimental-bef88f7c-20260116"; diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom.react-server.development.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom.react-server.development.js index 44ff5c345f9a..b0caa467c92d 100644 --- a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom.react-server.development.js +++ b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom.react-server.development.js @@ -336,5 +336,5 @@ })) : Internals.d.m(href)); }; - exports.version = "19.3.0-experimental-65eec428-20251218"; + exports.version = "19.3.0-experimental-bef88f7c-20260116"; })(); diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom.react-server.production.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom.react-server.production.js index 05e912ee6f8f..e6090e805e6b 100644 --- a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom.react-server.production.js +++ b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom.react-server.production.js @@ -149,4 +149,4 @@ exports.preloadModule = function (href, options) { }); } else Internals.d.m(href); }; -exports.version = "19.3.0-experimental-65eec428-20251218"; +exports.version = "19.3.0-experimental-bef88f7c-20260116"; diff --git a/packages/next/src/compiled/react-dom-experimental/package.json b/packages/next/src/compiled/react-dom-experimental/package.json index f82e1113216d..831f1b97fff3 100644 --- a/packages/next/src/compiled/react-dom-experimental/package.json +++ b/packages/next/src/compiled/react-dom-experimental/package.json @@ -72,10 +72,10 @@ "./package.json": "./package.json" }, "dependencies": { - "scheduler": "0.0.0-experimental-65eec428-20251218" + "scheduler": "0.0.0-experimental-bef88f7c-20260116" }, "peerDependencies": { - "react": "0.0.0-experimental-65eec428-20251218" + "react": "0.0.0-experimental-bef88f7c-20260116" }, "browser": { "./server.js": "./server.browser.js", diff --git a/packages/next/src/compiled/react-dom/cjs/react-dom-client.development.js b/packages/next/src/compiled/react-dom/cjs/react-dom-client.development.js index 804852feed9b..c3647544ac47 100644 --- a/packages/next/src/compiled/react-dom/cjs/react-dom-client.development.js +++ b/packages/next/src/compiled/react-dom/cjs/react-dom-client.development.js @@ -4549,38 +4549,6 @@ errors )); } - function logRenderPhase(startTime, endTime, lanes, debugTask) { - if (supportsUserTiming && !(endTime <= startTime)) { - var color = - (lanes & 738197653) === lanes ? "tertiary-dark" : "primary-dark"; - lanes = - (lanes & 536870912) === lanes - ? "Prepared" - : (lanes & 201326741) === lanes - ? "Hydrated" - : "Render"; - debugTask - ? debugTask.run( - console.timeStamp.bind( - console, - lanes, - startTime, - endTime, - currentTrack, - LANES_TRACK_GROUP, - color - ) - ) - : console.timeStamp( - lanes, - startTime, - endTime, - currentTrack, - LANES_TRACK_GROUP, - color - ); - } - } function logSuspendedRenderPhase(startTime, endTime, lanes, debugTask) { !supportsUserTiming || endTime <= startTime || @@ -4633,50 +4601,6 @@ lanes )); } - function logRecoveredRenderPhase( - startTime, - endTime, - lanes, - recoverableErrors, - hydrationFailed, - debugTask - ) { - if (supportsUserTiming && !(endTime <= startTime)) { - lanes = []; - for (var i = 0; i < recoverableErrors.length; i++) { - var error = recoverableErrors[i].value; - lanes.push([ - "Recoverable Error", - "object" === typeof error && - null !== error && - "string" === typeof error.message - ? String(error.message) - : String(error) - ]); - } - startTime = { - start: startTime, - end: endTime, - detail: { - devtools: { - color: "primary-dark", - track: currentTrack, - trackGroup: LANES_TRACK_GROUP, - tooltipText: hydrationFailed - ? "Hydration Failed" - : "Recovered after Error", - properties: lanes - } - } - }; - debugTask - ? debugTask.run( - performance.measure.bind(performance, "Recovered", startTime) - ) - : performance.measure("Recovered", startTime); - performance.clearMeasures("Recovered"); - } - } function logErroredRenderPhase(startTime, endTime, lanes, debugTask) { !supportsUserTiming || endTime <= startTime || @@ -5105,7 +5029,7 @@ (workInProgress.deletions = null), (workInProgress.actualDuration = -0), (workInProgress.actualStartTime = -1.1)); - workInProgress.flags = current.flags & 132120576; + workInProgress.flags = current.flags & 133169152; workInProgress.childLanes = current.childLanes; workInProgress.lanes = current.lanes; workInProgress.child = current.child; @@ -5143,7 +5067,7 @@ return workInProgress; } function resetWorkInProgress(workInProgress, renderLanes) { - workInProgress.flags &= 132120578; + workInProgress.flags &= 133169154; var current = workInProgress.alternate; null === current ? ((workInProgress.childLanes = 0), @@ -8028,7 +7952,7 @@ null; hookTypesUpdateIndexDev = -1; null !== current && - (current.flags & 132120576) !== (workInProgress.flags & 132120576) && + (current.flags & 133169152) !== (workInProgress.flags & 133169152) && console.error( "Internal React error: Expected static flag was missing. Please notify the React team." ); @@ -9174,7 +9098,7 @@ hook ); if ( - 0 === (renderLanes & 42) || + 0 === (renderLanes & 106) || (0 !== (renderLanes & 1073741824) && 0 === (workInProgressRootRenderLanes & 261930)) ) @@ -11145,24 +11069,24 @@ return current; } function updateSuspenseComponent(current, workInProgress, renderLanes) { - var JSCompiler_object_inline_digest_2939; - var JSCompiler_object_inline_stack_2940 = workInProgress.pendingProps; + var JSCompiler_object_inline_digest_2961; + var JSCompiler_object_inline_stack_2962 = workInProgress.pendingProps; shouldSuspendImpl(workInProgress) && (workInProgress.flags |= 128); - var JSCompiler_object_inline_message_2938 = !1; + var JSCompiler_object_inline_message_2960 = !1; var didSuspend = 0 !== (workInProgress.flags & 128); - (JSCompiler_object_inline_digest_2939 = didSuspend) || - (JSCompiler_object_inline_digest_2939 = + (JSCompiler_object_inline_digest_2961 = didSuspend) || + (JSCompiler_object_inline_digest_2961 = null !== current && null === current.memoizedState ? !1 : 0 !== (suspenseStackCursor.current & ForceSuspenseFallback)); - JSCompiler_object_inline_digest_2939 && - ((JSCompiler_object_inline_message_2938 = !0), + JSCompiler_object_inline_digest_2961 && + ((JSCompiler_object_inline_message_2960 = !0), (workInProgress.flags &= -129)); - JSCompiler_object_inline_digest_2939 = 0 !== (workInProgress.flags & 32); + JSCompiler_object_inline_digest_2961 = 0 !== (workInProgress.flags & 32); workInProgress.flags &= -33; if (null === current) { if (isHydrating) { - JSCompiler_object_inline_message_2938 + JSCompiler_object_inline_message_2960 ? pushPrimaryTreeSuspenseHandler(workInProgress) : reuseSuspenseHandlerOnStack(workInProgress); (current = nextHydratableInstance) @@ -11175,18 +11099,18 @@ ? renderLanes : null), null !== renderLanes && - ((JSCompiler_object_inline_digest_2939 = { + ((JSCompiler_object_inline_digest_2961 = { dehydrated: renderLanes, treeContext: getSuspendedTreeContext(), retryLane: 536870912, hydrationErrors: null }), (workInProgress.memoizedState = - JSCompiler_object_inline_digest_2939), - (JSCompiler_object_inline_digest_2939 = + JSCompiler_object_inline_digest_2961), + (JSCompiler_object_inline_digest_2961 = createFiberFromDehydratedFragment(renderLanes)), - (JSCompiler_object_inline_digest_2939.return = workInProgress), - (workInProgress.child = JSCompiler_object_inline_digest_2939), + (JSCompiler_object_inline_digest_2961.return = workInProgress), + (workInProgress.child = JSCompiler_object_inline_digest_2961), (hydrationParentFiber = workInProgress), (nextHydratableInstance = null))) : (renderLanes = null); @@ -11200,39 +11124,39 @@ : (workInProgress.lanes = 536870912); return null; } - var nextPrimaryChildren = JSCompiler_object_inline_stack_2940.children; - JSCompiler_object_inline_stack_2940 = - JSCompiler_object_inline_stack_2940.fallback; - if (JSCompiler_object_inline_message_2938) { + var nextPrimaryChildren = JSCompiler_object_inline_stack_2962.children; + JSCompiler_object_inline_stack_2962 = + JSCompiler_object_inline_stack_2962.fallback; + if (JSCompiler_object_inline_message_2960) { reuseSuspenseHandlerOnStack(workInProgress); var mode = workInProgress.mode; nextPrimaryChildren = mountWorkInProgressOffscreenFiber( { mode: "hidden", children: nextPrimaryChildren }, mode ); - JSCompiler_object_inline_stack_2940 = createFiberFromFragment( - JSCompiler_object_inline_stack_2940, + JSCompiler_object_inline_stack_2962 = createFiberFromFragment( + JSCompiler_object_inline_stack_2962, mode, renderLanes, null ); nextPrimaryChildren.return = workInProgress; - JSCompiler_object_inline_stack_2940.return = workInProgress; - nextPrimaryChildren.sibling = JSCompiler_object_inline_stack_2940; + JSCompiler_object_inline_stack_2962.return = workInProgress; + nextPrimaryChildren.sibling = JSCompiler_object_inline_stack_2962; workInProgress.child = nextPrimaryChildren; - JSCompiler_object_inline_stack_2940 = workInProgress.child; - JSCompiler_object_inline_stack_2940.memoizedState = + JSCompiler_object_inline_stack_2962 = workInProgress.child; + JSCompiler_object_inline_stack_2962.memoizedState = mountSuspenseOffscreenState(renderLanes); - JSCompiler_object_inline_stack_2940.childLanes = + JSCompiler_object_inline_stack_2962.childLanes = getRemainingWorkInPrimaryTree( current, - JSCompiler_object_inline_digest_2939, + JSCompiler_object_inline_digest_2961, renderLanes ); workInProgress.memoizedState = SUSPENDED_MARKER; return bailoutOffscreenComponent( null, - JSCompiler_object_inline_stack_2940 + JSCompiler_object_inline_stack_2962 ); } pushPrimaryTreeSuspenseHandler(workInProgress); @@ -11243,8 +11167,8 @@ } var prevState = current.memoizedState; if (null !== prevState) { - var JSCompiler_object_inline_componentStack_2941 = prevState.dehydrated; - if (null !== JSCompiler_object_inline_componentStack_2941) { + var JSCompiler_object_inline_componentStack_2963 = prevState.dehydrated; + if (null !== JSCompiler_object_inline_componentStack_2963) { if (didSuspend) workInProgress.flags & 256 ? (pushPrimaryTreeSuspenseHandler(workInProgress), @@ -11261,13 +11185,13 @@ (workInProgress = null)) : (reuseSuspenseHandlerOnStack(workInProgress), (nextPrimaryChildren = - JSCompiler_object_inline_stack_2940.fallback), + JSCompiler_object_inline_stack_2962.fallback), (mode = workInProgress.mode), - (JSCompiler_object_inline_stack_2940 = + (JSCompiler_object_inline_stack_2962 = mountWorkInProgressOffscreenFiber( { mode: "visible", - children: JSCompiler_object_inline_stack_2940.children + children: JSCompiler_object_inline_stack_2962.children }, mode )), @@ -11278,30 +11202,30 @@ null )), (nextPrimaryChildren.flags |= 2), - (JSCompiler_object_inline_stack_2940.return = workInProgress), + (JSCompiler_object_inline_stack_2962.return = workInProgress), (nextPrimaryChildren.return = workInProgress), - (JSCompiler_object_inline_stack_2940.sibling = + (JSCompiler_object_inline_stack_2962.sibling = nextPrimaryChildren), - (workInProgress.child = JSCompiler_object_inline_stack_2940), + (workInProgress.child = JSCompiler_object_inline_stack_2962), reconcileChildFibers( workInProgress, current.child, null, renderLanes ), - (JSCompiler_object_inline_stack_2940 = workInProgress.child), - (JSCompiler_object_inline_stack_2940.memoizedState = + (JSCompiler_object_inline_stack_2962 = workInProgress.child), + (JSCompiler_object_inline_stack_2962.memoizedState = mountSuspenseOffscreenState(renderLanes)), - (JSCompiler_object_inline_stack_2940.childLanes = + (JSCompiler_object_inline_stack_2962.childLanes = getRemainingWorkInPrimaryTree( current, - JSCompiler_object_inline_digest_2939, + JSCompiler_object_inline_digest_2961, renderLanes )), (workInProgress.memoizedState = SUSPENDED_MARKER), (workInProgress = bailoutOffscreenComponent( null, - JSCompiler_object_inline_stack_2940 + JSCompiler_object_inline_stack_2962 ))); else if ( (pushPrimaryTreeSuspenseHandler(workInProgress), @@ -11309,45 +11233,45 @@ 0 !== (renderLanes & 536870912) && markRenderDerivedCause(workInProgress), isSuspenseInstanceFallback( - JSCompiler_object_inline_componentStack_2941 + JSCompiler_object_inline_componentStack_2963 )) ) { - JSCompiler_object_inline_digest_2939 = - JSCompiler_object_inline_componentStack_2941.nextSibling && - JSCompiler_object_inline_componentStack_2941.nextSibling.dataset; - if (JSCompiler_object_inline_digest_2939) { - nextPrimaryChildren = JSCompiler_object_inline_digest_2939.dgst; - var message = JSCompiler_object_inline_digest_2939.msg; - mode = JSCompiler_object_inline_digest_2939.stck; - var componentStack = JSCompiler_object_inline_digest_2939.cstck; + JSCompiler_object_inline_digest_2961 = + JSCompiler_object_inline_componentStack_2963.nextSibling && + JSCompiler_object_inline_componentStack_2963.nextSibling.dataset; + if (JSCompiler_object_inline_digest_2961) { + nextPrimaryChildren = JSCompiler_object_inline_digest_2961.dgst; + var message = JSCompiler_object_inline_digest_2961.msg; + mode = JSCompiler_object_inline_digest_2961.stck; + var componentStack = JSCompiler_object_inline_digest_2961.cstck; } - JSCompiler_object_inline_message_2938 = message; - JSCompiler_object_inline_digest_2939 = nextPrimaryChildren; - JSCompiler_object_inline_stack_2940 = mode; - JSCompiler_object_inline_componentStack_2941 = componentStack; - nextPrimaryChildren = JSCompiler_object_inline_message_2938; - mode = JSCompiler_object_inline_componentStack_2941; + JSCompiler_object_inline_message_2960 = message; + JSCompiler_object_inline_digest_2961 = nextPrimaryChildren; + JSCompiler_object_inline_stack_2962 = mode; + JSCompiler_object_inline_componentStack_2963 = componentStack; + nextPrimaryChildren = JSCompiler_object_inline_message_2960; + mode = JSCompiler_object_inline_componentStack_2963; nextPrimaryChildren = nextPrimaryChildren ? Error(nextPrimaryChildren) : Error( "The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering." ); nextPrimaryChildren.stack = - JSCompiler_object_inline_stack_2940 || ""; - nextPrimaryChildren.digest = JSCompiler_object_inline_digest_2939; - JSCompiler_object_inline_digest_2939 = + JSCompiler_object_inline_stack_2962 || ""; + nextPrimaryChildren.digest = JSCompiler_object_inline_digest_2961; + JSCompiler_object_inline_digest_2961 = void 0 === mode ? null : mode; - JSCompiler_object_inline_stack_2940 = { + JSCompiler_object_inline_stack_2962 = { value: nextPrimaryChildren, source: null, - stack: JSCompiler_object_inline_digest_2939 + stack: JSCompiler_object_inline_digest_2961 }; - "string" === typeof JSCompiler_object_inline_digest_2939 && + "string" === typeof JSCompiler_object_inline_digest_2961 && CapturedStacks.set( nextPrimaryChildren, - JSCompiler_object_inline_stack_2940 + JSCompiler_object_inline_stack_2962 ); - queueHydrationError(JSCompiler_object_inline_stack_2940); + queueHydrationError(JSCompiler_object_inline_stack_2962); workInProgress = retrySuspenseComponentWithoutHydrating( current, workInProgress, @@ -11361,35 +11285,35 @@ renderLanes, !1 ), - (JSCompiler_object_inline_digest_2939 = + (JSCompiler_object_inline_digest_2961 = 0 !== (renderLanes & current.childLanes)), - didReceiveUpdate || JSCompiler_object_inline_digest_2939) + didReceiveUpdate || JSCompiler_object_inline_digest_2961) ) { - JSCompiler_object_inline_digest_2939 = workInProgressRoot; + JSCompiler_object_inline_digest_2961 = workInProgressRoot; if ( - null !== JSCompiler_object_inline_digest_2939 && - ((JSCompiler_object_inline_stack_2940 = getBumpedLaneForHydration( - JSCompiler_object_inline_digest_2939, + null !== JSCompiler_object_inline_digest_2961 && + ((JSCompiler_object_inline_stack_2962 = getBumpedLaneForHydration( + JSCompiler_object_inline_digest_2961, renderLanes )), - 0 !== JSCompiler_object_inline_stack_2940 && - JSCompiler_object_inline_stack_2940 !== prevState.retryLane) + 0 !== JSCompiler_object_inline_stack_2962 && + JSCompiler_object_inline_stack_2962 !== prevState.retryLane) ) throw ( - ((prevState.retryLane = JSCompiler_object_inline_stack_2940), + ((prevState.retryLane = JSCompiler_object_inline_stack_2962), enqueueConcurrentRenderForLane( current, - JSCompiler_object_inline_stack_2940 + JSCompiler_object_inline_stack_2962 ), scheduleUpdateOnFiber( - JSCompiler_object_inline_digest_2939, + JSCompiler_object_inline_digest_2961, current, - JSCompiler_object_inline_stack_2940 + JSCompiler_object_inline_stack_2962 ), SelectiveHydrationException) ); isSuspenseInstancePending( - JSCompiler_object_inline_componentStack_2941 + JSCompiler_object_inline_componentStack_2963 ) || renderDidSuspendDelayIfPossible(); workInProgress = retrySuspenseComponentWithoutHydrating( current, @@ -11398,14 +11322,14 @@ ); } else isSuspenseInstancePending( - JSCompiler_object_inline_componentStack_2941 + JSCompiler_object_inline_componentStack_2963 ) ? ((workInProgress.flags |= 192), (workInProgress.child = current.child), (workInProgress = null)) : ((current = prevState.treeContext), (nextHydratableInstance = getNextHydratable( - JSCompiler_object_inline_componentStack_2941.nextSibling + JSCompiler_object_inline_componentStack_2963.nextSibling )), (hydrationParentFiber = workInProgress), (isHydrating = !0), @@ -11417,32 +11341,32 @@ restoreSuspendedTreeContext(workInProgress, current), (workInProgress = mountSuspensePrimaryChildren( workInProgress, - JSCompiler_object_inline_stack_2940.children + JSCompiler_object_inline_stack_2962.children )), (workInProgress.flags |= 4096)); return workInProgress; } } - if (JSCompiler_object_inline_message_2938) + if (JSCompiler_object_inline_message_2960) return ( reuseSuspenseHandlerOnStack(workInProgress), - (nextPrimaryChildren = JSCompiler_object_inline_stack_2940.fallback), + (nextPrimaryChildren = JSCompiler_object_inline_stack_2962.fallback), (mode = workInProgress.mode), (componentStack = current.child), - (JSCompiler_object_inline_componentStack_2941 = + (JSCompiler_object_inline_componentStack_2963 = componentStack.sibling), - (JSCompiler_object_inline_stack_2940 = createWorkInProgress( + (JSCompiler_object_inline_stack_2962 = createWorkInProgress( componentStack, { mode: "hidden", - children: JSCompiler_object_inline_stack_2940.children + children: JSCompiler_object_inline_stack_2962.children } )), - (JSCompiler_object_inline_stack_2940.subtreeFlags = - componentStack.subtreeFlags & 132120576), - null !== JSCompiler_object_inline_componentStack_2941 + (JSCompiler_object_inline_stack_2962.subtreeFlags = + componentStack.subtreeFlags & 133169152), + null !== JSCompiler_object_inline_componentStack_2963 ? (nextPrimaryChildren = createWorkInProgress( - JSCompiler_object_inline_componentStack_2941, + JSCompiler_object_inline_componentStack_2963, nextPrimaryChildren )) : ((nextPrimaryChildren = createFiberFromFragment( @@ -11453,11 +11377,11 @@ )), (nextPrimaryChildren.flags |= 2)), (nextPrimaryChildren.return = workInProgress), - (JSCompiler_object_inline_stack_2940.return = workInProgress), - (JSCompiler_object_inline_stack_2940.sibling = nextPrimaryChildren), - (workInProgress.child = JSCompiler_object_inline_stack_2940), - bailoutOffscreenComponent(null, JSCompiler_object_inline_stack_2940), - (JSCompiler_object_inline_stack_2940 = workInProgress.child), + (JSCompiler_object_inline_stack_2962.return = workInProgress), + (JSCompiler_object_inline_stack_2962.sibling = nextPrimaryChildren), + (workInProgress.child = JSCompiler_object_inline_stack_2962), + bailoutOffscreenComponent(null, JSCompiler_object_inline_stack_2962), + (JSCompiler_object_inline_stack_2962 = workInProgress.child), (nextPrimaryChildren = current.child.memoizedState), null === nextPrimaryChildren ? (nextPrimaryChildren = mountSuspenseOffscreenState(renderLanes)) @@ -11473,18 +11397,18 @@ baseLanes: nextPrimaryChildren.baseLanes | renderLanes, cachePool: mode })), - (JSCompiler_object_inline_stack_2940.memoizedState = + (JSCompiler_object_inline_stack_2962.memoizedState = nextPrimaryChildren), - (JSCompiler_object_inline_stack_2940.childLanes = + (JSCompiler_object_inline_stack_2962.childLanes = getRemainingWorkInPrimaryTree( current, - JSCompiler_object_inline_digest_2939, + JSCompiler_object_inline_digest_2961, renderLanes )), (workInProgress.memoizedState = SUSPENDED_MARKER), bailoutOffscreenComponent( current.child, - JSCompiler_object_inline_stack_2940 + JSCompiler_object_inline_stack_2962 ) ); null !== prevState && @@ -11496,16 +11420,16 @@ current = renderLanes.sibling; renderLanes = createWorkInProgress(renderLanes, { mode: "visible", - children: JSCompiler_object_inline_stack_2940.children + children: JSCompiler_object_inline_stack_2962.children }); renderLanes.return = workInProgress; renderLanes.sibling = null; null !== current && - ((JSCompiler_object_inline_digest_2939 = workInProgress.deletions), - null === JSCompiler_object_inline_digest_2939 + ((JSCompiler_object_inline_digest_2961 = workInProgress.deletions), + null === JSCompiler_object_inline_digest_2961 ? ((workInProgress.deletions = [current]), (workInProgress.flags |= 16)) - : JSCompiler_object_inline_digest_2939.push(current)); + : JSCompiler_object_inline_digest_2961.push(current)); workInProgress.child = renderLanes; workInProgress.memoizedState = null; return renderLanes; @@ -12785,8 +12709,8 @@ ) (newChildLanes |= _child2.lanes | _child2.childLanes), - (subtreeFlags |= _child2.subtreeFlags & 132120576), - (subtreeFlags |= _child2.flags & 132120576), + (subtreeFlags |= _child2.subtreeFlags & 133169152), + (subtreeFlags |= _child2.flags & 133169152), (_treeBaseDuration += _child2.treeBaseDuration), (_child2 = _child2.sibling); completedWork.treeBaseDuration = _treeBaseDuration; @@ -12798,8 +12722,8 @@ ) (newChildLanes |= _treeBaseDuration.lanes | _treeBaseDuration.childLanes), - (subtreeFlags |= _treeBaseDuration.subtreeFlags & 132120576), - (subtreeFlags |= _treeBaseDuration.flags & 132120576), + (subtreeFlags |= _treeBaseDuration.subtreeFlags & 133169152), + (subtreeFlags |= _treeBaseDuration.flags & 133169152), (_treeBaseDuration.return = completedWork), (_treeBaseDuration = _treeBaseDuration.sibling); else if ((completedWork.mode & ProfileMode) !== NoMode) { @@ -14641,7 +14565,9 @@ (viewTransitionCancelableChildren = []), viewTransitionCancelableChildren.push( instance, - oldName, + 0 === viewTransitionHostInstanceIdx + ? oldName + : oldName + "_" + viewTransitionHostInstanceIdx, child.memoizedProps )); viewTransitionHostInstanceIdx++; @@ -17996,7 +17922,7 @@ throw Error("Unknown root exit status."); } if (null !== ReactSharedInternals.actQueue) - commitRoot( + completeRoot( forceSync, yieldEndTime, lanes, @@ -18006,6 +17932,7 @@ workInProgressDeferredLane, workInProgressRootInterleavedUpdatedLanes, workInProgressSuspendedRetryLanes, + workInProgressRootDidSkipSuspendedSiblings, startTime, null, null, @@ -18030,7 +17957,7 @@ if (0 !== getNextLanes(forceSync, 0, !0)) break a; pendingEffectsLanes = lanes; forceSync.timeoutHandle = scheduleTimeout( - commitRootWhenReady.bind( + completeRootWhenReady.bind( null, forceSync, yieldEndTime, @@ -18051,7 +17978,7 @@ ); break a; } - commitRootWhenReady( + completeRootWhenReady( forceSync, yieldEndTime, workInProgressRootRecoverableErrors, @@ -18074,7 +18001,7 @@ } while (1); ensureRootIsScheduled(root); } - function commitRootWhenReady( + function completeRootWhenReady( root, finishedWork, recoverableErrors, @@ -18139,7 +18066,7 @@ ) { pendingEffectsLanes = lanes; root.cancelPendingCommit = subtreeFlags( - commitRoot.bind( + completeRoot.bind( null, root, finishedWork, @@ -18150,6 +18077,7 @@ spawnedLane, updatedLanes, suspendedRetryLanes, + didSkipSuspendedSiblings, exitStatus, suspendedState, suspendedState.waitingForViewTransition @@ -18175,7 +18103,7 @@ ); return; } - commitRoot( + completeRoot( root, finishedWork, lanes, @@ -18185,6 +18113,7 @@ spawnedLane, updatedLanes, suspendedRetryLanes, + didSkipSuspendedSiblings, exitStatus, suspendedState, suspendedCommitReason, @@ -19047,6 +18976,14 @@ break; case 5: resetHooksOnUnwind(unitOfWork); + var fiber = unitOfWork; + fiber === hydrationParentFiber && + (isHydrating + ? (popToNextHostParent(fiber), + 5 === fiber.tag && + null != fiber.stateNode && + (nextHydratableInstance = fiber.stateNode)) + : (popToNextHostParent(fiber), (isHydrating = !0))); default: unwindInterruptedWork(current, unitOfWork), (unitOfWork = workInProgress = @@ -19185,7 +19122,7 @@ workInProgressRootExitStatus = RootSuspendedAtTheShell; workInProgress = null; } - function commitRoot( + function completeRoot( root, finishedWork, lanes, @@ -19195,6 +19132,7 @@ spawnedLane, updatedLanes, suspendedRetryLanes, + didSkipSuspendedSiblings, exitStatus, suspendedState, suspendedCommitReason, @@ -19209,31 +19147,94 @@ if ((executionContext & (RenderContext | CommitContext)) !== NoContext) throw Error("Should not already be working."); setCurrentTrackFromLanes(lanes); - exitStatus === RootErrored - ? logErroredRenderPhase( - completedRenderStartTime, - completedRenderEndTime, - lanes, - workInProgressUpdateTask - ) - : null !== recoverableErrors - ? logRecoveredRenderPhase( - completedRenderStartTime, - completedRenderEndTime, - lanes, - recoverableErrors, - null !== finishedWork && - null !== finishedWork.alternate && - finishedWork.alternate.memoizedState.isDehydrated && - 0 !== (finishedWork.flags & 256), - workInProgressUpdateTask - ) - : logRenderPhase( - completedRenderStartTime, - completedRenderEndTime, - lanes, - workInProgressUpdateTask - ); + if (exitStatus === RootErrored) + logErroredRenderPhase( + completedRenderStartTime, + completedRenderEndTime, + lanes, + workInProgressUpdateTask + ); + else if (null !== recoverableErrors) { + if ( + ((didSkipSuspendedSiblings = + null !== finishedWork && + null !== finishedWork.alternate && + finishedWork.alternate.memoizedState.isDehydrated && + 0 !== (finishedWork.flags & 256)), + (didIncludeRenderPhaseUpdate = workInProgressUpdateTask), + supportsUserTiming && + !(completedRenderEndTime <= completedRenderStartTime)) + ) { + exitStatus = []; + for (var i = 0; i < recoverableErrors.length; i++) { + var error = recoverableErrors[i].value; + exitStatus.push([ + "Recoverable Error", + "object" === typeof error && + null !== error && + "string" === typeof error.message + ? String(error.message) + : String(error) + ]); + } + completedRenderStartTime = { + start: completedRenderStartTime, + end: completedRenderEndTime, + detail: { + devtools: { + color: "primary-dark", + track: currentTrack, + trackGroup: LANES_TRACK_GROUP, + tooltipText: didSkipSuspendedSiblings + ? "Hydration Failed" + : "Recovered after Error", + properties: exitStatus + } + } + }; + didIncludeRenderPhaseUpdate + ? didIncludeRenderPhaseUpdate.run( + performance.measure.bind( + performance, + "Recovered", + completedRenderStartTime + ) + ) + : performance.measure("Recovered", completedRenderStartTime); + performance.clearMeasures("Recovered"); + } + } else + (didIncludeRenderPhaseUpdate = workInProgressUpdateTask), + !supportsUserTiming || + completedRenderEndTime <= completedRenderStartTime || + ((didSkipSuspendedSiblings = + (lanes & 738197653) === lanes ? "tertiary-dark" : "primary-dark"), + (exitStatus = + (lanes & 536870912) === lanes + ? "Prepared" + : (lanes & 201326741) === lanes + ? "Hydrated" + : "Render"), + didIncludeRenderPhaseUpdate + ? didIncludeRenderPhaseUpdate.run( + console.timeStamp.bind( + console, + exitStatus, + completedRenderStartTime, + completedRenderEndTime, + currentTrack, + LANES_TRACK_GROUP, + didSkipSuspendedSiblings + ) + ) + : console.timeStamp( + exitStatus, + completedRenderStartTime, + completedRenderEndTime, + currentTrack, + LANES_TRACK_GROUP, + didSkipSuspendedSiblings + )); if (null !== finishedWork) { 0 === lanes && console.error( @@ -19243,97 +19244,115 @@ throw Error( "Cannot commit the same tree as before. This error is likely caused by a bug in React. Please file an issue." ); - didIncludeRenderPhaseUpdate = - finishedWork.lanes | finishedWork.childLanes; - didIncludeRenderPhaseUpdate |= concurrentlyUpdatedLanes; - markRootFinished( - root, - lanes, - didIncludeRenderPhaseUpdate, - spawnedLane, - updatedLanes, - suspendedRetryLanes - ); root === workInProgressRoot && ((workInProgress = workInProgressRoot = null), (workInProgressRootRenderLanes = 0)); pendingFinishedWork = finishedWork; pendingEffectsRoot = root; pendingEffectsLanes = lanes; - pendingEffectsRemainingLanes = didIncludeRenderPhaseUpdate; pendingPassiveTransitions = transitions; pendingRecoverableErrors = recoverableErrors; pendingEffectsRenderEndTime = completedRenderEndTime; pendingSuspendedCommitReason = suspendedCommitReason; pendingDelayedCommitReason = IMMEDIATE_COMMIT; - pendingViewTransitionEvents = pendingSuspendedViewTransitionReason = - null; - (lanes & 335544064) === lanes - ? ((pendingTransitionTypes = claimQueuedTransitionTypes(root)), - (recoverableErrors = 10262)) - : ((pendingTransitionTypes = null), (recoverableErrors = 10256)); - 0 !== finishedWork.actualDuration || - 0 !== (finishedWork.subtreeFlags & recoverableErrors) || - 0 !== (finishedWork.flags & recoverableErrors) - ? ((root.callbackNode = null), - (root.callbackPriority = 0), - scheduleCallback$1(NormalPriority$1, function () { - schedulerEvent = window.event; - pendingDelayedCommitReason === IMMEDIATE_COMMIT && - (pendingDelayedCommitReason = DELAYED_PASSIVE_COMMIT); - flushPassiveEffects(); - return null; - })) - : ((root.callbackNode = null), (root.callbackPriority = 0)); - commitErrors = null; - commitStartTime = now(); - null !== suspendedCommitReason && - logSuspendedCommitPhase( - completedRenderEndTime, - commitStartTime, - suspendedCommitReason, - workInProgressUpdateTask - ); - shouldStartViewTransition = !1; - suspendedCommitReason = 0 !== (finishedWork.flags & 13878); - if ( - 0 !== (finishedWork.subtreeFlags & 13878) || - suspendedCommitReason - ) { - suspendedCommitReason = ReactSharedInternals.T; - ReactSharedInternals.T = null; - completedRenderEndTime = ReactDOMSharedInternals.p; - ReactDOMSharedInternals.p = DiscreteEventPriority; - recoverableErrors = executionContext; - executionContext |= CommitContext; - try { - commitBeforeMutationEffects(root, finishedWork, lanes); - } finally { - (executionContext = recoverableErrors), - (ReactDOMSharedInternals.p = completedRenderEndTime), - (ReactSharedInternals.T = suspendedCommitReason); - } + pendingSuspendedViewTransitionReason = null; + commitRoot( + root, + finishedWork, + lanes, + spawnedLane, + updatedLanes, + suspendedRetryLanes, + suspendedState, + suspendedCommitReason, + completedRenderEndTime + ); + } + } + function commitRoot( + root, + finishedWork, + lanes, + spawnedLane, + updatedLanes, + suspendedRetryLanes, + suspendedState, + suspendedCommitReason, + completedRenderEndTime + ) { + var remainingLanes = finishedWork.lanes | finishedWork.childLanes; + pendingEffectsRemainingLanes = remainingLanes; + remainingLanes |= concurrentlyUpdatedLanes; + markRootFinished( + root, + lanes, + remainingLanes, + spawnedLane, + updatedLanes, + suspendedRetryLanes + ); + pendingViewTransitionEvents = null; + (lanes & 335544064) === lanes + ? ((pendingTransitionTypes = claimQueuedTransitionTypes(root)), + (spawnedLane = 10262)) + : ((pendingTransitionTypes = null), (spawnedLane = 10256)); + 0 !== finishedWork.actualDuration || + 0 !== (finishedWork.subtreeFlags & spawnedLane) || + 0 !== (finishedWork.flags & spawnedLane) + ? ((root.callbackNode = null), + (root.callbackPriority = 0), + scheduleCallback$1(NormalPriority$1, function () { + schedulerEvent = window.event; + pendingDelayedCommitReason === IMMEDIATE_COMMIT && + (pendingDelayedCommitReason = DELAYED_PASSIVE_COMMIT); + flushPassiveEffects(); + return null; + })) + : ((root.callbackNode = null), (root.callbackPriority = 0)); + commitErrors = null; + commitStartTime = now(); + null !== suspendedCommitReason && + logSuspendedCommitPhase( + completedRenderEndTime, + commitStartTime, + suspendedCommitReason, + workInProgressUpdateTask + ); + shouldStartViewTransition = !1; + suspendedCommitReason = 0 !== (finishedWork.flags & 13878); + if (0 !== (finishedWork.subtreeFlags & 13878) || suspendedCommitReason) { + suspendedCommitReason = ReactSharedInternals.T; + ReactSharedInternals.T = null; + completedRenderEndTime = ReactDOMSharedInternals.p; + ReactDOMSharedInternals.p = DiscreteEventPriority; + spawnedLane = executionContext; + executionContext |= CommitContext; + try { + commitBeforeMutationEffects(root, finishedWork, lanes); + } finally { + (executionContext = spawnedLane), + (ReactDOMSharedInternals.p = completedRenderEndTime), + (ReactSharedInternals.T = suspendedCommitReason); } - finishedWork = shouldStartViewTransition; - pendingEffectsStatus = PENDING_MUTATION_PHASE; - finishedWork - ? ((animatingLanes |= lanes), - (animatingTask = null), - (pendingViewTransition = startViewTransition( - suspendedState, - root.containerInfo, - pendingTransitionTypes, - flushMutationEffects, - flushLayoutEffects, - flushAfterMutationEffects, - flushSpawnedWork, - flushPassiveEffects, - reportViewTransitionError, - suspendedViewTransition, - finishedViewTransition.bind(null, lanes) - ))) - : (flushMutationEffects(), flushLayoutEffects(), flushSpawnedWork()); } + pendingEffectsStatus = PENDING_MUTATION_PHASE; + shouldStartViewTransition + ? ((animatingLanes |= lanes), + (animatingTask = null), + (pendingViewTransition = startViewTransition( + suspendedState, + root.containerInfo, + pendingTransitionTypes, + flushMutationEffects, + flushLayoutEffects, + flushAfterMutationEffects, + flushSpawnedWork, + flushPassiveEffects, + reportViewTransitionError, + suspendedViewTransition, + finishedViewTransition.bind(null, lanes) + ))) + : (flushMutationEffects(), flushLayoutEffects(), flushSpawnedWork()); } function reportViewTransitionError(error) { if (pendingEffectsStatus !== NO_PENDING_EFFECTS) { @@ -30396,11 +30415,11 @@ }; (function () { var isomorphicReactPackageVersion = React.version; - if ("19.3.0-canary-65eec428-20251218" !== isomorphicReactPackageVersion) + if ("19.3.0-canary-bef88f7c-20260116" !== isomorphicReactPackageVersion) throw Error( 'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' + (isomorphicReactPackageVersion + - "\n - react-dom: 19.3.0-canary-65eec428-20251218\nLearn more: https://react.dev/warnings/version-mismatch") + "\n - react-dom: 19.3.0-canary-bef88f7c-20260116\nLearn more: https://react.dev/warnings/version-mismatch") ); })(); ("function" === typeof Map && @@ -30437,10 +30456,10 @@ !(function () { var internals = { bundleType: 1, - version: "19.3.0-canary-65eec428-20251218", + version: "19.3.0-canary-bef88f7c-20260116", rendererPackageName: "react-dom", currentDispatcherRef: ReactSharedInternals, - reconcilerVersion: "19.3.0-canary-65eec428-20251218" + reconcilerVersion: "19.3.0-canary-bef88f7c-20260116" }; internals.overrideHookState = overrideHookState; internals.overrideHookStateDeletePath = overrideHookStateDeletePath; @@ -30578,7 +30597,7 @@ listenToAllSupportedEvents(container); return new ReactDOMHydrationRoot(initialChildren); }; - exports.version = "19.3.0-canary-65eec428-20251218"; + exports.version = "19.3.0-canary-bef88f7c-20260116"; "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && diff --git a/packages/next/src/compiled/react-dom/cjs/react-dom-client.production.js b/packages/next/src/compiled/react-dom/cjs/react-dom-client.production.js index d2d37f6a7d0e..94ff12c35f38 100644 --- a/packages/next/src/compiled/react-dom/cjs/react-dom-client.production.js +++ b/packages/next/src/compiled/react-dom/cjs/react-dom-client.production.js @@ -2617,7 +2617,7 @@ function createWorkInProgress(current, pendingProps) { (workInProgress.flags = 0), (workInProgress.subtreeFlags = 0), (workInProgress.deletions = null)); - workInProgress.flags = current.flags & 132120576; + workInProgress.flags = current.flags & 133169152; workInProgress.childLanes = current.childLanes; workInProgress.lanes = current.lanes; workInProgress.child = current.child; @@ -2636,7 +2636,7 @@ function createWorkInProgress(current, pendingProps) { return workInProgress; } function resetWorkInProgress(workInProgress, renderLanes) { - workInProgress.flags &= 132120578; + workInProgress.flags &= 133169154; var current = workInProgress.alternate; null === current ? ((workInProgress.childLanes = 0), @@ -5413,7 +5413,7 @@ function updateDeferredValueImpl(hook, prevValue, value, initialValue) { hook ); if ( - 0 === (renderLanes & 42) || + 0 === (renderLanes & 106) || (0 !== (renderLanes & 1073741824) && 0 === (workInProgressRootRenderLanes & 261930)) ) @@ -7260,7 +7260,7 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { mode: "hidden", children: nextProps.children })), - (nextProps.subtreeFlags = prevState.subtreeFlags & 132120576), + (nextProps.subtreeFlags = prevState.subtreeFlags & 133169152), null !== digest ? (nextPrimaryChildren = createWorkInProgress( digest, @@ -8219,8 +8219,8 @@ function bubbleProperties(completedWork) { if (didBailout) for (var child$111 = completedWork.child; null !== child$111; ) (newChildLanes |= child$111.lanes | child$111.childLanes), - (subtreeFlags |= child$111.subtreeFlags & 132120576), - (subtreeFlags |= child$111.flags & 132120576), + (subtreeFlags |= child$111.subtreeFlags & 133169152), + (subtreeFlags |= child$111.flags & 133169152), (child$111.return = completedWork), (child$111 = child$111.sibling); else @@ -9549,7 +9549,9 @@ function measureViewTransitionHostInstancesRecursive( (viewTransitionCancelableChildren = []), viewTransitionCancelableChildren.push( instance, - oldName, + 0 === viewTransitionHostInstanceIdx + ? oldName + : oldName + "_" + viewTransitionHostInstanceIdx, child.memoizedProps )); viewTransitionHostInstanceIdx++; @@ -11957,7 +11959,7 @@ function performWorkOnRoot(root$jscomp$0, lanes, forceSync) { if (0 !== getNextLanes(shouldTimeSlice, 0, !0)) break a; pendingEffectsLanes = lanes; shouldTimeSlice.timeoutHandle = scheduleTimeout( - commitRootWhenReady.bind( + completeRootWhenReady.bind( null, shouldTimeSlice, forceSync, @@ -11978,7 +11980,7 @@ function performWorkOnRoot(root$jscomp$0, lanes, forceSync) { ); break a; } - commitRootWhenReady( + completeRootWhenReady( shouldTimeSlice, forceSync, workInProgressRootRecoverableErrors, @@ -12000,7 +12002,7 @@ function performWorkOnRoot(root$jscomp$0, lanes, forceSync) { } while (1); ensureRootIsScheduled(root$jscomp$0); } -function commitRootWhenReady( +function completeRootWhenReady( root, finishedWork, recoverableErrors, @@ -12069,7 +12071,7 @@ function commitRootWhenReady( ) { pendingEffectsLanes = lanes; root.cancelPendingCommit = subtreeFlags( - commitRoot.bind( + completeRoot.bind( null, root, finishedWork, @@ -12080,6 +12082,7 @@ function commitRootWhenReady( spawnedLane, updatedLanes, suspendedRetryLanes, + didSkipSuspendedSiblings, exitStatus, suspendedCommitReason, null, @@ -12090,7 +12093,7 @@ function commitRootWhenReady( markRootSuspended(root, lanes, spawnedLane, !didSkipSuspendedSiblings); return; } - commitRoot( + completeRoot( root, finishedWork, lanes, @@ -12100,6 +12103,7 @@ function commitRootWhenReady( spawnedLane, updatedLanes, suspendedRetryLanes, + didSkipSuspendedSiblings, exitStatus, suspendedCommitReason ); @@ -12508,6 +12512,14 @@ function replaySuspendedUnitOfWork(unitOfWork) { break; case 5: resetHooksOnUnwind(next); + var fiber = next; + fiber === hydrationParentFiber && + (isHydrating + ? (popToNextHostParent(fiber), + 5 === fiber.tag && + null != fiber.stateNode && + (nextHydratableInstance = fiber.stateNode)) + : (popToNextHostParent(fiber), (isHydrating = !0))); default: unwindInterruptedWork(current, next), (next = workInProgress = @@ -12629,7 +12641,7 @@ function unwindUnitOfWork(unitOfWork, skipSiblings) { workInProgressRootExitStatus = 6; workInProgress = null; } -function commitRoot( +function completeRoot( root, finishedWork, lanes, @@ -12639,6 +12651,7 @@ function commitRoot( spawnedLane, updatedLanes, suspendedRetryLanes, + didSkipSuspendedSiblings, exitStatus, suspendedState ) { @@ -12648,74 +12661,92 @@ function commitRoot( if (0 !== (executionContext & 6)) throw Error(formatProdErrorMessage(327)); if (null !== finishedWork) { if (finishedWork === root.current) throw Error(formatProdErrorMessage(177)); - didIncludeRenderPhaseUpdate = finishedWork.lanes | finishedWork.childLanes; - didIncludeRenderPhaseUpdate |= concurrentlyUpdatedLanes; - markRootFinished( - root, - lanes, - didIncludeRenderPhaseUpdate, - spawnedLane, - updatedLanes, - suspendedRetryLanes - ); root === workInProgressRoot && ((workInProgress = workInProgressRoot = null), (workInProgressRootRenderLanes = 0)); pendingFinishedWork = finishedWork; pendingEffectsRoot = root; pendingEffectsLanes = lanes; - pendingEffectsRemainingLanes = didIncludeRenderPhaseUpdate; pendingPassiveTransitions = transitions; pendingRecoverableErrors = recoverableErrors; - pendingViewTransitionEvents = null; - (lanes & 335544064) === lanes - ? ((pendingTransitionTypes = claimQueuedTransitionTypes(root)), - (recoverableErrors = 10262)) - : ((pendingTransitionTypes = null), (recoverableErrors = 10256)); - 0 !== (finishedWork.subtreeFlags & recoverableErrors) || - 0 !== (finishedWork.flags & recoverableErrors) - ? ((root.callbackNode = null), - (root.callbackPriority = 0), - scheduleCallback$1(NormalPriority$1, function () { - flushPassiveEffects(); - return null; - })) - : ((root.callbackNode = null), (root.callbackPriority = 0)); - shouldStartViewTransition = !1; - recoverableErrors = 0 !== (finishedWork.flags & 13878); - if (0 !== (finishedWork.subtreeFlags & 13878) || recoverableErrors) { - recoverableErrors = ReactSharedInternals.T; - ReactSharedInternals.T = null; - transitions = ReactDOMSharedInternals.p; - ReactDOMSharedInternals.p = 2; - spawnedLane = executionContext; - executionContext |= 4; - try { - commitBeforeMutationEffects(root, finishedWork, lanes); - } finally { - (executionContext = spawnedLane), - (ReactDOMSharedInternals.p = transitions), - (ReactSharedInternals.T = recoverableErrors); - } + commitRoot( + root, + finishedWork, + lanes, + spawnedLane, + updatedLanes, + suspendedRetryLanes, + suspendedState + ); + } +} +function commitRoot( + root, + finishedWork, + lanes, + spawnedLane, + updatedLanes, + suspendedRetryLanes, + suspendedState +) { + var remainingLanes = finishedWork.lanes | finishedWork.childLanes; + pendingEffectsRemainingLanes = remainingLanes; + remainingLanes |= concurrentlyUpdatedLanes; + markRootFinished( + root, + lanes, + remainingLanes, + spawnedLane, + updatedLanes, + suspendedRetryLanes + ); + pendingViewTransitionEvents = null; + (lanes & 335544064) === lanes + ? ((pendingTransitionTypes = claimQueuedTransitionTypes(root)), + (spawnedLane = 10262)) + : ((pendingTransitionTypes = null), (spawnedLane = 10256)); + 0 !== (finishedWork.subtreeFlags & spawnedLane) || + 0 !== (finishedWork.flags & spawnedLane) + ? ((root.callbackNode = null), + (root.callbackPriority = 0), + scheduleCallback$1(NormalPriority$1, function () { + flushPassiveEffects(); + return null; + })) + : ((root.callbackNode = null), (root.callbackPriority = 0)); + shouldStartViewTransition = !1; + spawnedLane = 0 !== (finishedWork.flags & 13878); + if (0 !== (finishedWork.subtreeFlags & 13878) || spawnedLane) { + spawnedLane = ReactSharedInternals.T; + ReactSharedInternals.T = null; + updatedLanes = ReactDOMSharedInternals.p; + ReactDOMSharedInternals.p = 2; + suspendedRetryLanes = executionContext; + executionContext |= 4; + try { + commitBeforeMutationEffects(root, finishedWork, lanes); + } finally { + (executionContext = suspendedRetryLanes), + (ReactDOMSharedInternals.p = updatedLanes), + (ReactSharedInternals.T = spawnedLane); } - finishedWork = shouldStartViewTransition; - pendingEffectsStatus = 1; - finishedWork - ? (pendingViewTransition = startViewTransition( - suspendedState, - root.containerInfo, - pendingTransitionTypes, - flushMutationEffects, - flushLayoutEffects, - flushAfterMutationEffects, - flushSpawnedWork, - flushPassiveEffects, - reportViewTransitionError, - null, - null - )) - : (flushMutationEffects(), flushLayoutEffects(), flushSpawnedWork()); } + pendingEffectsStatus = 1; + shouldStartViewTransition + ? (pendingViewTransition = startViewTransition( + suspendedState, + root.containerInfo, + pendingTransitionTypes, + flushMutationEffects, + flushLayoutEffects, + flushAfterMutationEffects, + flushSpawnedWork, + flushPassiveEffects, + reportViewTransitionError, + null, + null + )) + : (flushMutationEffects(), flushLayoutEffects(), flushSpawnedWork()); } function reportViewTransitionError(error) { if (0 !== pendingEffectsStatus) { @@ -17988,14 +18019,14 @@ ReactDOMHydrationRoot.prototype.unstable_scheduleHydration = function (target) { }; var isomorphicReactPackageVersion$jscomp$inline_2040 = React.version; if ( - "19.3.0-canary-65eec428-20251218" !== + "19.3.0-canary-bef88f7c-20260116" !== isomorphicReactPackageVersion$jscomp$inline_2040 ) throw Error( formatProdErrorMessage( 527, isomorphicReactPackageVersion$jscomp$inline_2040, - "19.3.0-canary-65eec428-20251218" + "19.3.0-canary-bef88f7c-20260116" ) ); ReactDOMSharedInternals.findDOMNode = function (componentOrElement) { @@ -18015,24 +18046,24 @@ ReactDOMSharedInternals.findDOMNode = function (componentOrElement) { null === componentOrElement ? null : componentOrElement.stateNode; return componentOrElement; }; -var internals$jscomp$inline_2628 = { +var internals$jscomp$inline_2630 = { bundleType: 0, - version: "19.3.0-canary-65eec428-20251218", + version: "19.3.0-canary-bef88f7c-20260116", rendererPackageName: "react-dom", currentDispatcherRef: ReactSharedInternals, - reconcilerVersion: "19.3.0-canary-65eec428-20251218" + reconcilerVersion: "19.3.0-canary-bef88f7c-20260116" }; if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { - var hook$jscomp$inline_2629 = __REACT_DEVTOOLS_GLOBAL_HOOK__; + var hook$jscomp$inline_2631 = __REACT_DEVTOOLS_GLOBAL_HOOK__; if ( - !hook$jscomp$inline_2629.isDisabled && - hook$jscomp$inline_2629.supportsFiber + !hook$jscomp$inline_2631.isDisabled && + hook$jscomp$inline_2631.supportsFiber ) try { - (rendererID = hook$jscomp$inline_2629.inject( - internals$jscomp$inline_2628 + (rendererID = hook$jscomp$inline_2631.inject( + internals$jscomp$inline_2630 )), - (injectedHook = hook$jscomp$inline_2629); + (injectedHook = hook$jscomp$inline_2631); } catch (err) {} } exports.createRoot = function (container, options) { @@ -18118,4 +18149,4 @@ exports.hydrateRoot = function (container, initialChildren, options) { listenToAllSupportedEvents(container); return new ReactDOMHydrationRoot(initialChildren); }; -exports.version = "19.3.0-canary-65eec428-20251218"; +exports.version = "19.3.0-canary-bef88f7c-20260116"; diff --git a/packages/next/src/compiled/react-dom/cjs/react-dom-profiling.development.js b/packages/next/src/compiled/react-dom/cjs/react-dom-profiling.development.js index fc594b425b43..29991fb71db0 100644 --- a/packages/next/src/compiled/react-dom/cjs/react-dom-profiling.development.js +++ b/packages/next/src/compiled/react-dom/cjs/react-dom-profiling.development.js @@ -4557,38 +4557,6 @@ errors )); } - function logRenderPhase(startTime, endTime, lanes, debugTask) { - if (supportsUserTiming && !(endTime <= startTime)) { - var color = - (lanes & 738197653) === lanes ? "tertiary-dark" : "primary-dark"; - lanes = - (lanes & 536870912) === lanes - ? "Prepared" - : (lanes & 201326741) === lanes - ? "Hydrated" - : "Render"; - debugTask - ? debugTask.run( - console.timeStamp.bind( - console, - lanes, - startTime, - endTime, - currentTrack, - LANES_TRACK_GROUP, - color - ) - ) - : console.timeStamp( - lanes, - startTime, - endTime, - currentTrack, - LANES_TRACK_GROUP, - color - ); - } - } function logSuspendedRenderPhase(startTime, endTime, lanes, debugTask) { !supportsUserTiming || endTime <= startTime || @@ -4641,50 +4609,6 @@ lanes )); } - function logRecoveredRenderPhase( - startTime, - endTime, - lanes, - recoverableErrors, - hydrationFailed, - debugTask - ) { - if (supportsUserTiming && !(endTime <= startTime)) { - lanes = []; - for (var i = 0; i < recoverableErrors.length; i++) { - var error = recoverableErrors[i].value; - lanes.push([ - "Recoverable Error", - "object" === typeof error && - null !== error && - "string" === typeof error.message - ? String(error.message) - : String(error) - ]); - } - startTime = { - start: startTime, - end: endTime, - detail: { - devtools: { - color: "primary-dark", - track: currentTrack, - trackGroup: LANES_TRACK_GROUP, - tooltipText: hydrationFailed - ? "Hydration Failed" - : "Recovered after Error", - properties: lanes - } - } - }; - debugTask - ? debugTask.run( - performance.measure.bind(performance, "Recovered", startTime) - ) - : performance.measure("Recovered", startTime); - performance.clearMeasures("Recovered"); - } - } function logErroredRenderPhase(startTime, endTime, lanes, debugTask) { !supportsUserTiming || endTime <= startTime || @@ -5113,7 +5037,7 @@ (workInProgress.deletions = null), (workInProgress.actualDuration = -0), (workInProgress.actualStartTime = -1.1)); - workInProgress.flags = current.flags & 132120576; + workInProgress.flags = current.flags & 133169152; workInProgress.childLanes = current.childLanes; workInProgress.lanes = current.lanes; workInProgress.child = current.child; @@ -5151,7 +5075,7 @@ return workInProgress; } function resetWorkInProgress(workInProgress, renderLanes) { - workInProgress.flags &= 132120578; + workInProgress.flags &= 133169154; var current = workInProgress.alternate; null === current ? ((workInProgress.childLanes = 0), @@ -8036,7 +7960,7 @@ null; hookTypesUpdateIndexDev = -1; null !== current && - (current.flags & 132120576) !== (workInProgress.flags & 132120576) && + (current.flags & 133169152) !== (workInProgress.flags & 133169152) && console.error( "Internal React error: Expected static flag was missing. Please notify the React team." ); @@ -9182,7 +9106,7 @@ hook ); if ( - 0 === (renderLanes & 42) || + 0 === (renderLanes & 106) || (0 !== (renderLanes & 1073741824) && 0 === (workInProgressRootRenderLanes & 261930)) ) @@ -11153,24 +11077,24 @@ return current; } function updateSuspenseComponent(current, workInProgress, renderLanes) { - var JSCompiler_object_inline_digest_2944; - var JSCompiler_object_inline_stack_2945 = workInProgress.pendingProps; + var JSCompiler_object_inline_digest_2966; + var JSCompiler_object_inline_stack_2967 = workInProgress.pendingProps; shouldSuspendImpl(workInProgress) && (workInProgress.flags |= 128); - var JSCompiler_object_inline_message_2943 = !1; + var JSCompiler_object_inline_message_2965 = !1; var didSuspend = 0 !== (workInProgress.flags & 128); - (JSCompiler_object_inline_digest_2944 = didSuspend) || - (JSCompiler_object_inline_digest_2944 = + (JSCompiler_object_inline_digest_2966 = didSuspend) || + (JSCompiler_object_inline_digest_2966 = null !== current && null === current.memoizedState ? !1 : 0 !== (suspenseStackCursor.current & ForceSuspenseFallback)); - JSCompiler_object_inline_digest_2944 && - ((JSCompiler_object_inline_message_2943 = !0), + JSCompiler_object_inline_digest_2966 && + ((JSCompiler_object_inline_message_2965 = !0), (workInProgress.flags &= -129)); - JSCompiler_object_inline_digest_2944 = 0 !== (workInProgress.flags & 32); + JSCompiler_object_inline_digest_2966 = 0 !== (workInProgress.flags & 32); workInProgress.flags &= -33; if (null === current) { if (isHydrating) { - JSCompiler_object_inline_message_2943 + JSCompiler_object_inline_message_2965 ? pushPrimaryTreeSuspenseHandler(workInProgress) : reuseSuspenseHandlerOnStack(workInProgress); (current = nextHydratableInstance) @@ -11183,18 +11107,18 @@ ? renderLanes : null), null !== renderLanes && - ((JSCompiler_object_inline_digest_2944 = { + ((JSCompiler_object_inline_digest_2966 = { dehydrated: renderLanes, treeContext: getSuspendedTreeContext(), retryLane: 536870912, hydrationErrors: null }), (workInProgress.memoizedState = - JSCompiler_object_inline_digest_2944), - (JSCompiler_object_inline_digest_2944 = + JSCompiler_object_inline_digest_2966), + (JSCompiler_object_inline_digest_2966 = createFiberFromDehydratedFragment(renderLanes)), - (JSCompiler_object_inline_digest_2944.return = workInProgress), - (workInProgress.child = JSCompiler_object_inline_digest_2944), + (JSCompiler_object_inline_digest_2966.return = workInProgress), + (workInProgress.child = JSCompiler_object_inline_digest_2966), (hydrationParentFiber = workInProgress), (nextHydratableInstance = null))) : (renderLanes = null); @@ -11208,39 +11132,39 @@ : (workInProgress.lanes = 536870912); return null; } - var nextPrimaryChildren = JSCompiler_object_inline_stack_2945.children; - JSCompiler_object_inline_stack_2945 = - JSCompiler_object_inline_stack_2945.fallback; - if (JSCompiler_object_inline_message_2943) { + var nextPrimaryChildren = JSCompiler_object_inline_stack_2967.children; + JSCompiler_object_inline_stack_2967 = + JSCompiler_object_inline_stack_2967.fallback; + if (JSCompiler_object_inline_message_2965) { reuseSuspenseHandlerOnStack(workInProgress); var mode = workInProgress.mode; nextPrimaryChildren = mountWorkInProgressOffscreenFiber( { mode: "hidden", children: nextPrimaryChildren }, mode ); - JSCompiler_object_inline_stack_2945 = createFiberFromFragment( - JSCompiler_object_inline_stack_2945, + JSCompiler_object_inline_stack_2967 = createFiberFromFragment( + JSCompiler_object_inline_stack_2967, mode, renderLanes, null ); nextPrimaryChildren.return = workInProgress; - JSCompiler_object_inline_stack_2945.return = workInProgress; - nextPrimaryChildren.sibling = JSCompiler_object_inline_stack_2945; + JSCompiler_object_inline_stack_2967.return = workInProgress; + nextPrimaryChildren.sibling = JSCompiler_object_inline_stack_2967; workInProgress.child = nextPrimaryChildren; - JSCompiler_object_inline_stack_2945 = workInProgress.child; - JSCompiler_object_inline_stack_2945.memoizedState = + JSCompiler_object_inline_stack_2967 = workInProgress.child; + JSCompiler_object_inline_stack_2967.memoizedState = mountSuspenseOffscreenState(renderLanes); - JSCompiler_object_inline_stack_2945.childLanes = + JSCompiler_object_inline_stack_2967.childLanes = getRemainingWorkInPrimaryTree( current, - JSCompiler_object_inline_digest_2944, + JSCompiler_object_inline_digest_2966, renderLanes ); workInProgress.memoizedState = SUSPENDED_MARKER; return bailoutOffscreenComponent( null, - JSCompiler_object_inline_stack_2945 + JSCompiler_object_inline_stack_2967 ); } pushPrimaryTreeSuspenseHandler(workInProgress); @@ -11251,8 +11175,8 @@ } var prevState = current.memoizedState; if (null !== prevState) { - var JSCompiler_object_inline_componentStack_2946 = prevState.dehydrated; - if (null !== JSCompiler_object_inline_componentStack_2946) { + var JSCompiler_object_inline_componentStack_2968 = prevState.dehydrated; + if (null !== JSCompiler_object_inline_componentStack_2968) { if (didSuspend) workInProgress.flags & 256 ? (pushPrimaryTreeSuspenseHandler(workInProgress), @@ -11269,13 +11193,13 @@ (workInProgress = null)) : (reuseSuspenseHandlerOnStack(workInProgress), (nextPrimaryChildren = - JSCompiler_object_inline_stack_2945.fallback), + JSCompiler_object_inline_stack_2967.fallback), (mode = workInProgress.mode), - (JSCompiler_object_inline_stack_2945 = + (JSCompiler_object_inline_stack_2967 = mountWorkInProgressOffscreenFiber( { mode: "visible", - children: JSCompiler_object_inline_stack_2945.children + children: JSCompiler_object_inline_stack_2967.children }, mode )), @@ -11286,30 +11210,30 @@ null )), (nextPrimaryChildren.flags |= 2), - (JSCompiler_object_inline_stack_2945.return = workInProgress), + (JSCompiler_object_inline_stack_2967.return = workInProgress), (nextPrimaryChildren.return = workInProgress), - (JSCompiler_object_inline_stack_2945.sibling = + (JSCompiler_object_inline_stack_2967.sibling = nextPrimaryChildren), - (workInProgress.child = JSCompiler_object_inline_stack_2945), + (workInProgress.child = JSCompiler_object_inline_stack_2967), reconcileChildFibers( workInProgress, current.child, null, renderLanes ), - (JSCompiler_object_inline_stack_2945 = workInProgress.child), - (JSCompiler_object_inline_stack_2945.memoizedState = + (JSCompiler_object_inline_stack_2967 = workInProgress.child), + (JSCompiler_object_inline_stack_2967.memoizedState = mountSuspenseOffscreenState(renderLanes)), - (JSCompiler_object_inline_stack_2945.childLanes = + (JSCompiler_object_inline_stack_2967.childLanes = getRemainingWorkInPrimaryTree( current, - JSCompiler_object_inline_digest_2944, + JSCompiler_object_inline_digest_2966, renderLanes )), (workInProgress.memoizedState = SUSPENDED_MARKER), (workInProgress = bailoutOffscreenComponent( null, - JSCompiler_object_inline_stack_2945 + JSCompiler_object_inline_stack_2967 ))); else if ( (pushPrimaryTreeSuspenseHandler(workInProgress), @@ -11317,45 +11241,45 @@ 0 !== (renderLanes & 536870912) && markRenderDerivedCause(workInProgress), isSuspenseInstanceFallback( - JSCompiler_object_inline_componentStack_2946 + JSCompiler_object_inline_componentStack_2968 )) ) { - JSCompiler_object_inline_digest_2944 = - JSCompiler_object_inline_componentStack_2946.nextSibling && - JSCompiler_object_inline_componentStack_2946.nextSibling.dataset; - if (JSCompiler_object_inline_digest_2944) { - nextPrimaryChildren = JSCompiler_object_inline_digest_2944.dgst; - var message = JSCompiler_object_inline_digest_2944.msg; - mode = JSCompiler_object_inline_digest_2944.stck; - var componentStack = JSCompiler_object_inline_digest_2944.cstck; + JSCompiler_object_inline_digest_2966 = + JSCompiler_object_inline_componentStack_2968.nextSibling && + JSCompiler_object_inline_componentStack_2968.nextSibling.dataset; + if (JSCompiler_object_inline_digest_2966) { + nextPrimaryChildren = JSCompiler_object_inline_digest_2966.dgst; + var message = JSCompiler_object_inline_digest_2966.msg; + mode = JSCompiler_object_inline_digest_2966.stck; + var componentStack = JSCompiler_object_inline_digest_2966.cstck; } - JSCompiler_object_inline_message_2943 = message; - JSCompiler_object_inline_digest_2944 = nextPrimaryChildren; - JSCompiler_object_inline_stack_2945 = mode; - JSCompiler_object_inline_componentStack_2946 = componentStack; - nextPrimaryChildren = JSCompiler_object_inline_message_2943; - mode = JSCompiler_object_inline_componentStack_2946; + JSCompiler_object_inline_message_2965 = message; + JSCompiler_object_inline_digest_2966 = nextPrimaryChildren; + JSCompiler_object_inline_stack_2967 = mode; + JSCompiler_object_inline_componentStack_2968 = componentStack; + nextPrimaryChildren = JSCompiler_object_inline_message_2965; + mode = JSCompiler_object_inline_componentStack_2968; nextPrimaryChildren = nextPrimaryChildren ? Error(nextPrimaryChildren) : Error( "The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering." ); nextPrimaryChildren.stack = - JSCompiler_object_inline_stack_2945 || ""; - nextPrimaryChildren.digest = JSCompiler_object_inline_digest_2944; - JSCompiler_object_inline_digest_2944 = + JSCompiler_object_inline_stack_2967 || ""; + nextPrimaryChildren.digest = JSCompiler_object_inline_digest_2966; + JSCompiler_object_inline_digest_2966 = void 0 === mode ? null : mode; - JSCompiler_object_inline_stack_2945 = { + JSCompiler_object_inline_stack_2967 = { value: nextPrimaryChildren, source: null, - stack: JSCompiler_object_inline_digest_2944 + stack: JSCompiler_object_inline_digest_2966 }; - "string" === typeof JSCompiler_object_inline_digest_2944 && + "string" === typeof JSCompiler_object_inline_digest_2966 && CapturedStacks.set( nextPrimaryChildren, - JSCompiler_object_inline_stack_2945 + JSCompiler_object_inline_stack_2967 ); - queueHydrationError(JSCompiler_object_inline_stack_2945); + queueHydrationError(JSCompiler_object_inline_stack_2967); workInProgress = retrySuspenseComponentWithoutHydrating( current, workInProgress, @@ -11369,35 +11293,35 @@ renderLanes, !1 ), - (JSCompiler_object_inline_digest_2944 = + (JSCompiler_object_inline_digest_2966 = 0 !== (renderLanes & current.childLanes)), - didReceiveUpdate || JSCompiler_object_inline_digest_2944) + didReceiveUpdate || JSCompiler_object_inline_digest_2966) ) { - JSCompiler_object_inline_digest_2944 = workInProgressRoot; + JSCompiler_object_inline_digest_2966 = workInProgressRoot; if ( - null !== JSCompiler_object_inline_digest_2944 && - ((JSCompiler_object_inline_stack_2945 = getBumpedLaneForHydration( - JSCompiler_object_inline_digest_2944, + null !== JSCompiler_object_inline_digest_2966 && + ((JSCompiler_object_inline_stack_2967 = getBumpedLaneForHydration( + JSCompiler_object_inline_digest_2966, renderLanes )), - 0 !== JSCompiler_object_inline_stack_2945 && - JSCompiler_object_inline_stack_2945 !== prevState.retryLane) + 0 !== JSCompiler_object_inline_stack_2967 && + JSCompiler_object_inline_stack_2967 !== prevState.retryLane) ) throw ( - ((prevState.retryLane = JSCompiler_object_inline_stack_2945), + ((prevState.retryLane = JSCompiler_object_inline_stack_2967), enqueueConcurrentRenderForLane( current, - JSCompiler_object_inline_stack_2945 + JSCompiler_object_inline_stack_2967 ), scheduleUpdateOnFiber( - JSCompiler_object_inline_digest_2944, + JSCompiler_object_inline_digest_2966, current, - JSCompiler_object_inline_stack_2945 + JSCompiler_object_inline_stack_2967 ), SelectiveHydrationException) ); isSuspenseInstancePending( - JSCompiler_object_inline_componentStack_2946 + JSCompiler_object_inline_componentStack_2968 ) || renderDidSuspendDelayIfPossible(); workInProgress = retrySuspenseComponentWithoutHydrating( current, @@ -11406,14 +11330,14 @@ ); } else isSuspenseInstancePending( - JSCompiler_object_inline_componentStack_2946 + JSCompiler_object_inline_componentStack_2968 ) ? ((workInProgress.flags |= 192), (workInProgress.child = current.child), (workInProgress = null)) : ((current = prevState.treeContext), (nextHydratableInstance = getNextHydratable( - JSCompiler_object_inline_componentStack_2946.nextSibling + JSCompiler_object_inline_componentStack_2968.nextSibling )), (hydrationParentFiber = workInProgress), (isHydrating = !0), @@ -11425,32 +11349,32 @@ restoreSuspendedTreeContext(workInProgress, current), (workInProgress = mountSuspensePrimaryChildren( workInProgress, - JSCompiler_object_inline_stack_2945.children + JSCompiler_object_inline_stack_2967.children )), (workInProgress.flags |= 4096)); return workInProgress; } } - if (JSCompiler_object_inline_message_2943) + if (JSCompiler_object_inline_message_2965) return ( reuseSuspenseHandlerOnStack(workInProgress), - (nextPrimaryChildren = JSCompiler_object_inline_stack_2945.fallback), + (nextPrimaryChildren = JSCompiler_object_inline_stack_2967.fallback), (mode = workInProgress.mode), (componentStack = current.child), - (JSCompiler_object_inline_componentStack_2946 = + (JSCompiler_object_inline_componentStack_2968 = componentStack.sibling), - (JSCompiler_object_inline_stack_2945 = createWorkInProgress( + (JSCompiler_object_inline_stack_2967 = createWorkInProgress( componentStack, { mode: "hidden", - children: JSCompiler_object_inline_stack_2945.children + children: JSCompiler_object_inline_stack_2967.children } )), - (JSCompiler_object_inline_stack_2945.subtreeFlags = - componentStack.subtreeFlags & 132120576), - null !== JSCompiler_object_inline_componentStack_2946 + (JSCompiler_object_inline_stack_2967.subtreeFlags = + componentStack.subtreeFlags & 133169152), + null !== JSCompiler_object_inline_componentStack_2968 ? (nextPrimaryChildren = createWorkInProgress( - JSCompiler_object_inline_componentStack_2946, + JSCompiler_object_inline_componentStack_2968, nextPrimaryChildren )) : ((nextPrimaryChildren = createFiberFromFragment( @@ -11461,11 +11385,11 @@ )), (nextPrimaryChildren.flags |= 2)), (nextPrimaryChildren.return = workInProgress), - (JSCompiler_object_inline_stack_2945.return = workInProgress), - (JSCompiler_object_inline_stack_2945.sibling = nextPrimaryChildren), - (workInProgress.child = JSCompiler_object_inline_stack_2945), - bailoutOffscreenComponent(null, JSCompiler_object_inline_stack_2945), - (JSCompiler_object_inline_stack_2945 = workInProgress.child), + (JSCompiler_object_inline_stack_2967.return = workInProgress), + (JSCompiler_object_inline_stack_2967.sibling = nextPrimaryChildren), + (workInProgress.child = JSCompiler_object_inline_stack_2967), + bailoutOffscreenComponent(null, JSCompiler_object_inline_stack_2967), + (JSCompiler_object_inline_stack_2967 = workInProgress.child), (nextPrimaryChildren = current.child.memoizedState), null === nextPrimaryChildren ? (nextPrimaryChildren = mountSuspenseOffscreenState(renderLanes)) @@ -11481,18 +11405,18 @@ baseLanes: nextPrimaryChildren.baseLanes | renderLanes, cachePool: mode })), - (JSCompiler_object_inline_stack_2945.memoizedState = + (JSCompiler_object_inline_stack_2967.memoizedState = nextPrimaryChildren), - (JSCompiler_object_inline_stack_2945.childLanes = + (JSCompiler_object_inline_stack_2967.childLanes = getRemainingWorkInPrimaryTree( current, - JSCompiler_object_inline_digest_2944, + JSCompiler_object_inline_digest_2966, renderLanes )), (workInProgress.memoizedState = SUSPENDED_MARKER), bailoutOffscreenComponent( current.child, - JSCompiler_object_inline_stack_2945 + JSCompiler_object_inline_stack_2967 ) ); null !== prevState && @@ -11504,16 +11428,16 @@ current = renderLanes.sibling; renderLanes = createWorkInProgress(renderLanes, { mode: "visible", - children: JSCompiler_object_inline_stack_2945.children + children: JSCompiler_object_inline_stack_2967.children }); renderLanes.return = workInProgress; renderLanes.sibling = null; null !== current && - ((JSCompiler_object_inline_digest_2944 = workInProgress.deletions), - null === JSCompiler_object_inline_digest_2944 + ((JSCompiler_object_inline_digest_2966 = workInProgress.deletions), + null === JSCompiler_object_inline_digest_2966 ? ((workInProgress.deletions = [current]), (workInProgress.flags |= 16)) - : JSCompiler_object_inline_digest_2944.push(current)); + : JSCompiler_object_inline_digest_2966.push(current)); workInProgress.child = renderLanes; workInProgress.memoizedState = null; return renderLanes; @@ -12793,8 +12717,8 @@ ) (newChildLanes |= _child2.lanes | _child2.childLanes), - (subtreeFlags |= _child2.subtreeFlags & 132120576), - (subtreeFlags |= _child2.flags & 132120576), + (subtreeFlags |= _child2.subtreeFlags & 133169152), + (subtreeFlags |= _child2.flags & 133169152), (_treeBaseDuration += _child2.treeBaseDuration), (_child2 = _child2.sibling); completedWork.treeBaseDuration = _treeBaseDuration; @@ -12806,8 +12730,8 @@ ) (newChildLanes |= _treeBaseDuration.lanes | _treeBaseDuration.childLanes), - (subtreeFlags |= _treeBaseDuration.subtreeFlags & 132120576), - (subtreeFlags |= _treeBaseDuration.flags & 132120576), + (subtreeFlags |= _treeBaseDuration.subtreeFlags & 133169152), + (subtreeFlags |= _treeBaseDuration.flags & 133169152), (_treeBaseDuration.return = completedWork), (_treeBaseDuration = _treeBaseDuration.sibling); else if ((completedWork.mode & ProfileMode) !== NoMode) { @@ -14649,7 +14573,9 @@ (viewTransitionCancelableChildren = []), viewTransitionCancelableChildren.push( instance, - oldName, + 0 === viewTransitionHostInstanceIdx + ? oldName + : oldName + "_" + viewTransitionHostInstanceIdx, child.memoizedProps )); viewTransitionHostInstanceIdx++; @@ -18004,7 +17930,7 @@ throw Error("Unknown root exit status."); } if (null !== ReactSharedInternals.actQueue) - commitRoot( + completeRoot( forceSync, yieldEndTime, lanes, @@ -18014,6 +17940,7 @@ workInProgressDeferredLane, workInProgressRootInterleavedUpdatedLanes, workInProgressSuspendedRetryLanes, + workInProgressRootDidSkipSuspendedSiblings, startTime, null, null, @@ -18038,7 +17965,7 @@ if (0 !== getNextLanes(forceSync, 0, !0)) break a; pendingEffectsLanes = lanes; forceSync.timeoutHandle = scheduleTimeout( - commitRootWhenReady.bind( + completeRootWhenReady.bind( null, forceSync, yieldEndTime, @@ -18059,7 +17986,7 @@ ); break a; } - commitRootWhenReady( + completeRootWhenReady( forceSync, yieldEndTime, workInProgressRootRecoverableErrors, @@ -18082,7 +18009,7 @@ } while (1); ensureRootIsScheduled(root); } - function commitRootWhenReady( + function completeRootWhenReady( root, finishedWork, recoverableErrors, @@ -18147,7 +18074,7 @@ ) { pendingEffectsLanes = lanes; root.cancelPendingCommit = subtreeFlags( - commitRoot.bind( + completeRoot.bind( null, root, finishedWork, @@ -18158,6 +18085,7 @@ spawnedLane, updatedLanes, suspendedRetryLanes, + didSkipSuspendedSiblings, exitStatus, suspendedState, suspendedState.waitingForViewTransition @@ -18183,7 +18111,7 @@ ); return; } - commitRoot( + completeRoot( root, finishedWork, lanes, @@ -18193,6 +18121,7 @@ spawnedLane, updatedLanes, suspendedRetryLanes, + didSkipSuspendedSiblings, exitStatus, suspendedState, suspendedCommitReason, @@ -19055,6 +18984,14 @@ break; case 5: resetHooksOnUnwind(unitOfWork); + var fiber = unitOfWork; + fiber === hydrationParentFiber && + (isHydrating + ? (popToNextHostParent(fiber), + 5 === fiber.tag && + null != fiber.stateNode && + (nextHydratableInstance = fiber.stateNode)) + : (popToNextHostParent(fiber), (isHydrating = !0))); default: unwindInterruptedWork(current, unitOfWork), (unitOfWork = workInProgress = @@ -19193,7 +19130,7 @@ workInProgressRootExitStatus = RootSuspendedAtTheShell; workInProgress = null; } - function commitRoot( + function completeRoot( root, finishedWork, lanes, @@ -19203,6 +19140,7 @@ spawnedLane, updatedLanes, suspendedRetryLanes, + didSkipSuspendedSiblings, exitStatus, suspendedState, suspendedCommitReason, @@ -19217,31 +19155,94 @@ if ((executionContext & (RenderContext | CommitContext)) !== NoContext) throw Error("Should not already be working."); setCurrentTrackFromLanes(lanes); - exitStatus === RootErrored - ? logErroredRenderPhase( - completedRenderStartTime, - completedRenderEndTime, - lanes, - workInProgressUpdateTask - ) - : null !== recoverableErrors - ? logRecoveredRenderPhase( - completedRenderStartTime, - completedRenderEndTime, - lanes, - recoverableErrors, - null !== finishedWork && - null !== finishedWork.alternate && - finishedWork.alternate.memoizedState.isDehydrated && - 0 !== (finishedWork.flags & 256), - workInProgressUpdateTask - ) - : logRenderPhase( - completedRenderStartTime, - completedRenderEndTime, - lanes, - workInProgressUpdateTask - ); + if (exitStatus === RootErrored) + logErroredRenderPhase( + completedRenderStartTime, + completedRenderEndTime, + lanes, + workInProgressUpdateTask + ); + else if (null !== recoverableErrors) { + if ( + ((didSkipSuspendedSiblings = + null !== finishedWork && + null !== finishedWork.alternate && + finishedWork.alternate.memoizedState.isDehydrated && + 0 !== (finishedWork.flags & 256)), + (didIncludeRenderPhaseUpdate = workInProgressUpdateTask), + supportsUserTiming && + !(completedRenderEndTime <= completedRenderStartTime)) + ) { + exitStatus = []; + for (var i = 0; i < recoverableErrors.length; i++) { + var error = recoverableErrors[i].value; + exitStatus.push([ + "Recoverable Error", + "object" === typeof error && + null !== error && + "string" === typeof error.message + ? String(error.message) + : String(error) + ]); + } + completedRenderStartTime = { + start: completedRenderStartTime, + end: completedRenderEndTime, + detail: { + devtools: { + color: "primary-dark", + track: currentTrack, + trackGroup: LANES_TRACK_GROUP, + tooltipText: didSkipSuspendedSiblings + ? "Hydration Failed" + : "Recovered after Error", + properties: exitStatus + } + } + }; + didIncludeRenderPhaseUpdate + ? didIncludeRenderPhaseUpdate.run( + performance.measure.bind( + performance, + "Recovered", + completedRenderStartTime + ) + ) + : performance.measure("Recovered", completedRenderStartTime); + performance.clearMeasures("Recovered"); + } + } else + (didIncludeRenderPhaseUpdate = workInProgressUpdateTask), + !supportsUserTiming || + completedRenderEndTime <= completedRenderStartTime || + ((didSkipSuspendedSiblings = + (lanes & 738197653) === lanes ? "tertiary-dark" : "primary-dark"), + (exitStatus = + (lanes & 536870912) === lanes + ? "Prepared" + : (lanes & 201326741) === lanes + ? "Hydrated" + : "Render"), + didIncludeRenderPhaseUpdate + ? didIncludeRenderPhaseUpdate.run( + console.timeStamp.bind( + console, + exitStatus, + completedRenderStartTime, + completedRenderEndTime, + currentTrack, + LANES_TRACK_GROUP, + didSkipSuspendedSiblings + ) + ) + : console.timeStamp( + exitStatus, + completedRenderStartTime, + completedRenderEndTime, + currentTrack, + LANES_TRACK_GROUP, + didSkipSuspendedSiblings + )); if (null !== finishedWork) { 0 === lanes && console.error( @@ -19251,97 +19252,115 @@ throw Error( "Cannot commit the same tree as before. This error is likely caused by a bug in React. Please file an issue." ); - didIncludeRenderPhaseUpdate = - finishedWork.lanes | finishedWork.childLanes; - didIncludeRenderPhaseUpdate |= concurrentlyUpdatedLanes; - markRootFinished( - root, - lanes, - didIncludeRenderPhaseUpdate, - spawnedLane, - updatedLanes, - suspendedRetryLanes - ); root === workInProgressRoot && ((workInProgress = workInProgressRoot = null), (workInProgressRootRenderLanes = 0)); pendingFinishedWork = finishedWork; pendingEffectsRoot = root; pendingEffectsLanes = lanes; - pendingEffectsRemainingLanes = didIncludeRenderPhaseUpdate; pendingPassiveTransitions = transitions; pendingRecoverableErrors = recoverableErrors; pendingEffectsRenderEndTime = completedRenderEndTime; pendingSuspendedCommitReason = suspendedCommitReason; pendingDelayedCommitReason = IMMEDIATE_COMMIT; - pendingViewTransitionEvents = pendingSuspendedViewTransitionReason = - null; - (lanes & 335544064) === lanes - ? ((pendingTransitionTypes = claimQueuedTransitionTypes(root)), - (recoverableErrors = 10262)) - : ((pendingTransitionTypes = null), (recoverableErrors = 10256)); - 0 !== finishedWork.actualDuration || - 0 !== (finishedWork.subtreeFlags & recoverableErrors) || - 0 !== (finishedWork.flags & recoverableErrors) - ? ((root.callbackNode = null), - (root.callbackPriority = 0), - scheduleCallback$1(NormalPriority$1, function () { - schedulerEvent = window.event; - pendingDelayedCommitReason === IMMEDIATE_COMMIT && - (pendingDelayedCommitReason = DELAYED_PASSIVE_COMMIT); - flushPassiveEffects(); - return null; - })) - : ((root.callbackNode = null), (root.callbackPriority = 0)); - commitErrors = null; - commitStartTime = now(); - null !== suspendedCommitReason && - logSuspendedCommitPhase( - completedRenderEndTime, - commitStartTime, - suspendedCommitReason, - workInProgressUpdateTask - ); - shouldStartViewTransition = !1; - suspendedCommitReason = 0 !== (finishedWork.flags & 13878); - if ( - 0 !== (finishedWork.subtreeFlags & 13878) || - suspendedCommitReason - ) { - suspendedCommitReason = ReactSharedInternals.T; - ReactSharedInternals.T = null; - completedRenderEndTime = ReactDOMSharedInternals.p; - ReactDOMSharedInternals.p = DiscreteEventPriority; - recoverableErrors = executionContext; - executionContext |= CommitContext; - try { - commitBeforeMutationEffects(root, finishedWork, lanes); - } finally { - (executionContext = recoverableErrors), - (ReactDOMSharedInternals.p = completedRenderEndTime), - (ReactSharedInternals.T = suspendedCommitReason); - } + pendingSuspendedViewTransitionReason = null; + commitRoot( + root, + finishedWork, + lanes, + spawnedLane, + updatedLanes, + suspendedRetryLanes, + suspendedState, + suspendedCommitReason, + completedRenderEndTime + ); + } + } + function commitRoot( + root, + finishedWork, + lanes, + spawnedLane, + updatedLanes, + suspendedRetryLanes, + suspendedState, + suspendedCommitReason, + completedRenderEndTime + ) { + var remainingLanes = finishedWork.lanes | finishedWork.childLanes; + pendingEffectsRemainingLanes = remainingLanes; + remainingLanes |= concurrentlyUpdatedLanes; + markRootFinished( + root, + lanes, + remainingLanes, + spawnedLane, + updatedLanes, + suspendedRetryLanes + ); + pendingViewTransitionEvents = null; + (lanes & 335544064) === lanes + ? ((pendingTransitionTypes = claimQueuedTransitionTypes(root)), + (spawnedLane = 10262)) + : ((pendingTransitionTypes = null), (spawnedLane = 10256)); + 0 !== finishedWork.actualDuration || + 0 !== (finishedWork.subtreeFlags & spawnedLane) || + 0 !== (finishedWork.flags & spawnedLane) + ? ((root.callbackNode = null), + (root.callbackPriority = 0), + scheduleCallback$1(NormalPriority$1, function () { + schedulerEvent = window.event; + pendingDelayedCommitReason === IMMEDIATE_COMMIT && + (pendingDelayedCommitReason = DELAYED_PASSIVE_COMMIT); + flushPassiveEffects(); + return null; + })) + : ((root.callbackNode = null), (root.callbackPriority = 0)); + commitErrors = null; + commitStartTime = now(); + null !== suspendedCommitReason && + logSuspendedCommitPhase( + completedRenderEndTime, + commitStartTime, + suspendedCommitReason, + workInProgressUpdateTask + ); + shouldStartViewTransition = !1; + suspendedCommitReason = 0 !== (finishedWork.flags & 13878); + if (0 !== (finishedWork.subtreeFlags & 13878) || suspendedCommitReason) { + suspendedCommitReason = ReactSharedInternals.T; + ReactSharedInternals.T = null; + completedRenderEndTime = ReactDOMSharedInternals.p; + ReactDOMSharedInternals.p = DiscreteEventPriority; + spawnedLane = executionContext; + executionContext |= CommitContext; + try { + commitBeforeMutationEffects(root, finishedWork, lanes); + } finally { + (executionContext = spawnedLane), + (ReactDOMSharedInternals.p = completedRenderEndTime), + (ReactSharedInternals.T = suspendedCommitReason); } - finishedWork = shouldStartViewTransition; - pendingEffectsStatus = PENDING_MUTATION_PHASE; - finishedWork - ? ((animatingLanes |= lanes), - (animatingTask = null), - (pendingViewTransition = startViewTransition( - suspendedState, - root.containerInfo, - pendingTransitionTypes, - flushMutationEffects, - flushLayoutEffects, - flushAfterMutationEffects, - flushSpawnedWork, - flushPassiveEffects, - reportViewTransitionError, - suspendedViewTransition, - finishedViewTransition.bind(null, lanes) - ))) - : (flushMutationEffects(), flushLayoutEffects(), flushSpawnedWork()); } + pendingEffectsStatus = PENDING_MUTATION_PHASE; + shouldStartViewTransition + ? ((animatingLanes |= lanes), + (animatingTask = null), + (pendingViewTransition = startViewTransition( + suspendedState, + root.containerInfo, + pendingTransitionTypes, + flushMutationEffects, + flushLayoutEffects, + flushAfterMutationEffects, + flushSpawnedWork, + flushPassiveEffects, + reportViewTransitionError, + suspendedViewTransition, + finishedViewTransition.bind(null, lanes) + ))) + : (flushMutationEffects(), flushLayoutEffects(), flushSpawnedWork()); } function reportViewTransitionError(error) { if (pendingEffectsStatus !== NO_PENDING_EFFECTS) { @@ -30454,11 +30473,11 @@ }; (function () { var isomorphicReactPackageVersion = React.version; - if ("19.3.0-canary-65eec428-20251218" !== isomorphicReactPackageVersion) + if ("19.3.0-canary-bef88f7c-20260116" !== isomorphicReactPackageVersion) throw Error( 'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' + (isomorphicReactPackageVersion + - "\n - react-dom: 19.3.0-canary-65eec428-20251218\nLearn more: https://react.dev/warnings/version-mismatch") + "\n - react-dom: 19.3.0-canary-bef88f7c-20260116\nLearn more: https://react.dev/warnings/version-mismatch") ); })(); ("function" === typeof Map && @@ -30495,10 +30514,10 @@ !(function () { var internals = { bundleType: 1, - version: "19.3.0-canary-65eec428-20251218", + version: "19.3.0-canary-bef88f7c-20260116", rendererPackageName: "react-dom", currentDispatcherRef: ReactSharedInternals, - reconcilerVersion: "19.3.0-canary-65eec428-20251218" + reconcilerVersion: "19.3.0-canary-bef88f7c-20260116" }; internals.overrideHookState = overrideHookState; internals.overrideHookStateDeletePath = overrideHookStateDeletePath; @@ -30966,7 +30985,7 @@ exports.useFormStatus = function () { return resolveDispatcher().useHostTransitionStatus(); }; - exports.version = "19.3.0-canary-65eec428-20251218"; + exports.version = "19.3.0-canary-bef88f7c-20260116"; "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && diff --git a/packages/next/src/compiled/react-dom/cjs/react-dom-profiling.profiling.js b/packages/next/src/compiled/react-dom/cjs/react-dom-profiling.profiling.js index 93efa1aad368..8de7f06a5ab8 100644 --- a/packages/next/src/compiled/react-dom/cjs/react-dom-profiling.profiling.js +++ b/packages/next/src/compiled/react-dom/cjs/react-dom-profiling.profiling.js @@ -2909,7 +2909,7 @@ function createWorkInProgress(current, pendingProps) { (workInProgress.deletions = null), (workInProgress.actualDuration = -0), (workInProgress.actualStartTime = -1.1)); - workInProgress.flags = current.flags & 132120576; + workInProgress.flags = current.flags & 133169152; workInProgress.childLanes = current.childLanes; workInProgress.lanes = current.lanes; workInProgress.child = current.child; @@ -2930,7 +2930,7 @@ function createWorkInProgress(current, pendingProps) { return workInProgress; } function resetWorkInProgress(workInProgress, renderLanes) { - workInProgress.flags &= 132120578; + workInProgress.flags &= 133169154; var current = workInProgress.alternate; null === current ? ((workInProgress.childLanes = 0), @@ -5912,7 +5912,7 @@ function updateDeferredValueImpl(hook, prevValue, value, initialValue) { hook ); if ( - 0 === (renderLanes & 42) || + 0 === (renderLanes & 106) || (0 !== (renderLanes & 1073741824) && 0 === (workInProgressRootRenderLanes & 261930)) ) @@ -7767,7 +7767,7 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { mode: "hidden", children: nextProps.children })), - (nextProps.subtreeFlags = prevState.subtreeFlags & 132120576), + (nextProps.subtreeFlags = prevState.subtreeFlags & 133169152), null !== digest ? (nextPrimaryChildren = createWorkInProgress( digest, @@ -8746,8 +8746,8 @@ function bubbleProperties(completedWork) { ) (newChildLanes |= child$123.lanes | child$123.childLanes), - (subtreeFlags |= child$123.subtreeFlags & 132120576), - (subtreeFlags |= child$123.flags & 132120576), + (subtreeFlags |= child$123.subtreeFlags & 133169152), + (subtreeFlags |= child$123.flags & 133169152), (treeBaseDuration$122 += child$123.treeBaseDuration), (child$123 = child$123.sibling); completedWork.treeBaseDuration = treeBaseDuration$122; @@ -8759,8 +8759,8 @@ function bubbleProperties(completedWork) { ) (newChildLanes |= treeBaseDuration$122.lanes | treeBaseDuration$122.childLanes), - (subtreeFlags |= treeBaseDuration$122.subtreeFlags & 132120576), - (subtreeFlags |= treeBaseDuration$122.flags & 132120576), + (subtreeFlags |= treeBaseDuration$122.subtreeFlags & 133169152), + (subtreeFlags |= treeBaseDuration$122.flags & 133169152), (treeBaseDuration$122.return = completedWork), (treeBaseDuration$122 = treeBaseDuration$122.sibling); else if (0 !== (completedWork.mode & 2)) { @@ -10263,7 +10263,9 @@ function measureViewTransitionHostInstancesRecursive( (viewTransitionCancelableChildren = []), viewTransitionCancelableChildren.push( instance, - oldName, + 0 === viewTransitionHostInstanceIdx + ? oldName + : oldName + "_" + viewTransitionHostInstanceIdx, child.memoizedProps )); viewTransitionHostInstanceIdx++; @@ -13326,7 +13328,7 @@ function performWorkOnRoot(root$jscomp$0, lanes, forceSync) { if (0 !== getNextLanes(yieldEndTime, 0, !0)) break a; pendingEffectsLanes = lanes; yieldEndTime.timeoutHandle = scheduleTimeout( - commitRootWhenReady.bind( + completeRootWhenReady.bind( null, yieldEndTime, forceSync, @@ -13347,7 +13349,7 @@ function performWorkOnRoot(root$jscomp$0, lanes, forceSync) { ); break a; } - commitRootWhenReady( + completeRootWhenReady( yieldEndTime, forceSync, workInProgressRootRecoverableErrors, @@ -13369,7 +13371,7 @@ function performWorkOnRoot(root$jscomp$0, lanes, forceSync) { } while (1); ensureRootIsScheduled(root$jscomp$0); } -function commitRootWhenReady( +function completeRootWhenReady( root, finishedWork, recoverableErrors, @@ -13431,7 +13433,7 @@ function commitRootWhenReady( ) { pendingEffectsLanes = lanes; root.cancelPendingCommit = subtreeFlags( - commitRoot.bind( + completeRoot.bind( null, root, finishedWork, @@ -13442,6 +13444,7 @@ function commitRootWhenReady( spawnedLane, updatedLanes, suspendedRetryLanes, + didSkipSuspendedSiblings, exitStatus, suspendedState, suspendedState.waitingForViewTransition @@ -13462,7 +13465,7 @@ function commitRootWhenReady( markRootSuspended(root, lanes, spawnedLane, !didSkipSuspendedSiblings); return; } - commitRoot( + completeRoot( root, finishedWork, lanes, @@ -13472,6 +13475,7 @@ function commitRootWhenReady( spawnedLane, updatedLanes, suspendedRetryLanes, + didSkipSuspendedSiblings, exitStatus, suspendedState, suspendedCommitReason, @@ -14146,6 +14150,14 @@ function replaySuspendedUnitOfWork(unitOfWork) { break; case 5: resetHooksOnUnwind(next); + var fiber = next; + fiber === hydrationParentFiber && + (isHydrating + ? (popToNextHostParent(fiber), + 5 === fiber.tag && + null != fiber.stateNode && + (nextHydratableInstance = fiber.stateNode)) + : (popToNextHostParent(fiber), (isHydrating = !0))); default: unwindInterruptedWork(current, next), (next = workInProgress = @@ -14276,7 +14288,7 @@ function unwindUnitOfWork(unitOfWork, skipSiblings) { workInProgressRootExitStatus = 6; workInProgress = null; } -function commitRoot( +function completeRoot( root, finishedWork, lanes, @@ -14286,6 +14298,7 @@ function commitRoot( spawnedLane, updatedLanes, suspendedRetryLanes, + didSkipSuspendedSiblings, exitStatus, suspendedState, suspendedCommitReason, @@ -14326,94 +14339,117 @@ function commitRoot( ); if (null !== finishedWork) { if (finishedWork === root.current) throw Error(formatProdErrorMessage(177)); - didIncludeRenderPhaseUpdate = finishedWork.lanes | finishedWork.childLanes; - didIncludeRenderPhaseUpdate |= concurrentlyUpdatedLanes; - markRootFinished( - root, - lanes, - didIncludeRenderPhaseUpdate, - spawnedLane, - updatedLanes, - suspendedRetryLanes - ); root === workInProgressRoot && ((workInProgress = workInProgressRoot = null), (workInProgressRootRenderLanes = 0)); pendingFinishedWork = finishedWork; pendingEffectsRoot = root; pendingEffectsLanes = lanes; - pendingEffectsRemainingLanes = didIncludeRenderPhaseUpdate; pendingPassiveTransitions = transitions; pendingRecoverableErrors = recoverableErrors; pendingEffectsRenderEndTime = completedRenderEndTime; pendingSuspendedCommitReason = suspendedCommitReason; pendingDelayedCommitReason = 0; - pendingViewTransitionEvents = pendingSuspendedViewTransitionReason = null; - (lanes & 335544064) === lanes - ? ((pendingTransitionTypes = claimQueuedTransitionTypes(root)), - (recoverableErrors = 10262)) - : ((pendingTransitionTypes = null), (recoverableErrors = 10256)); - 0 !== finishedWork.actualDuration || - 0 !== (finishedWork.subtreeFlags & recoverableErrors) || - 0 !== (finishedWork.flags & recoverableErrors) - ? ((root.callbackNode = null), - (root.callbackPriority = 0), - scheduleCallback$1(NormalPriority$1, function () { - schedulerEvent = window.event; - 0 === pendingDelayedCommitReason && (pendingDelayedCommitReason = 2); - flushPassiveEffects(); - return null; - })) - : ((root.callbackNode = null), (root.callbackPriority = 0)); - commitErrors = null; - commitStartTime = now(); - null !== suspendedCommitReason && - (!supportsUserTiming || - commitStartTime <= completedRenderEndTime || - console.timeStamp( - suspendedCommitReason, - completedRenderEndTime, - commitStartTime, - currentTrack, - "Scheduler \u269b", - "secondary-light" - )); - shouldStartViewTransition = !1; - suspendedCommitReason = 0 !== (finishedWork.flags & 13878); - if (0 !== (finishedWork.subtreeFlags & 13878) || suspendedCommitReason) { - suspendedCommitReason = ReactSharedInternals.T; - ReactSharedInternals.T = null; - completedRenderEndTime = ReactDOMSharedInternals.p; - ReactDOMSharedInternals.p = 2; - recoverableErrors = executionContext; - executionContext |= 4; - try { - commitBeforeMutationEffects(root, finishedWork, lanes); - } finally { - (executionContext = recoverableErrors), - (ReactDOMSharedInternals.p = completedRenderEndTime), - (ReactSharedInternals.T = suspendedCommitReason); - } + pendingSuspendedViewTransitionReason = null; + commitRoot( + root, + finishedWork, + lanes, + spawnedLane, + updatedLanes, + suspendedRetryLanes, + suspendedState, + suspendedCommitReason, + completedRenderEndTime + ); + } +} +function commitRoot( + root, + finishedWork, + lanes, + spawnedLane, + updatedLanes, + suspendedRetryLanes, + suspendedState, + suspendedCommitReason, + completedRenderEndTime +) { + var remainingLanes = finishedWork.lanes | finishedWork.childLanes; + pendingEffectsRemainingLanes = remainingLanes; + remainingLanes |= concurrentlyUpdatedLanes; + markRootFinished( + root, + lanes, + remainingLanes, + spawnedLane, + updatedLanes, + suspendedRetryLanes + ); + pendingViewTransitionEvents = null; + (lanes & 335544064) === lanes + ? ((pendingTransitionTypes = claimQueuedTransitionTypes(root)), + (spawnedLane = 10262)) + : ((pendingTransitionTypes = null), (spawnedLane = 10256)); + 0 !== finishedWork.actualDuration || + 0 !== (finishedWork.subtreeFlags & spawnedLane) || + 0 !== (finishedWork.flags & spawnedLane) + ? ((root.callbackNode = null), + (root.callbackPriority = 0), + scheduleCallback$1(NormalPriority$1, function () { + schedulerEvent = window.event; + 0 === pendingDelayedCommitReason && (pendingDelayedCommitReason = 2); + flushPassiveEffects(); + return null; + })) + : ((root.callbackNode = null), (root.callbackPriority = 0)); + commitErrors = null; + commitStartTime = now(); + null !== suspendedCommitReason && + (!supportsUserTiming || + commitStartTime <= completedRenderEndTime || + console.timeStamp( + suspendedCommitReason, + completedRenderEndTime, + commitStartTime, + currentTrack, + "Scheduler \u269b", + "secondary-light" + )); + shouldStartViewTransition = !1; + suspendedCommitReason = 0 !== (finishedWork.flags & 13878); + if (0 !== (finishedWork.subtreeFlags & 13878) || suspendedCommitReason) { + suspendedCommitReason = ReactSharedInternals.T; + ReactSharedInternals.T = null; + completedRenderEndTime = ReactDOMSharedInternals.p; + ReactDOMSharedInternals.p = 2; + spawnedLane = executionContext; + executionContext |= 4; + try { + commitBeforeMutationEffects(root, finishedWork, lanes); + } finally { + (executionContext = spawnedLane), + (ReactDOMSharedInternals.p = completedRenderEndTime), + (ReactSharedInternals.T = suspendedCommitReason); } - finishedWork = shouldStartViewTransition; - pendingEffectsStatus = 1; - finishedWork - ? ((animatingLanes |= lanes), - (pendingViewTransition = startViewTransition( - suspendedState, - root.containerInfo, - pendingTransitionTypes, - flushMutationEffects, - flushLayoutEffects, - flushAfterMutationEffects, - flushSpawnedWork, - flushPassiveEffects, - reportViewTransitionError, - suspendedViewTransition, - finishedViewTransition.bind(null, lanes) - ))) - : (flushMutationEffects(), flushLayoutEffects(), flushSpawnedWork()); } + pendingEffectsStatus = 1; + shouldStartViewTransition + ? ((animatingLanes |= lanes), + (pendingViewTransition = startViewTransition( + suspendedState, + root.containerInfo, + pendingTransitionTypes, + flushMutationEffects, + flushLayoutEffects, + flushAfterMutationEffects, + flushSpawnedWork, + flushPassiveEffects, + reportViewTransitionError, + suspendedViewTransition, + finishedViewTransition.bind(null, lanes) + ))) + : (flushMutationEffects(), flushLayoutEffects(), flushSpawnedWork()); } function reportViewTransitionError(error) { if (0 !== pendingEffectsStatus) { @@ -15292,20 +15328,20 @@ function extractEvents$1( } } for ( - var i$jscomp$inline_1988 = 0; - i$jscomp$inline_1988 < simpleEventPluginEvents.length; - i$jscomp$inline_1988++ + var i$jscomp$inline_1995 = 0; + i$jscomp$inline_1995 < simpleEventPluginEvents.length; + i$jscomp$inline_1995++ ) { - var eventName$jscomp$inline_1989 = - simpleEventPluginEvents[i$jscomp$inline_1988], - domEventName$jscomp$inline_1990 = - eventName$jscomp$inline_1989.toLowerCase(), - capitalizedEvent$jscomp$inline_1991 = - eventName$jscomp$inline_1989[0].toUpperCase() + - eventName$jscomp$inline_1989.slice(1); + var eventName$jscomp$inline_1996 = + simpleEventPluginEvents[i$jscomp$inline_1995], + domEventName$jscomp$inline_1997 = + eventName$jscomp$inline_1996.toLowerCase(), + capitalizedEvent$jscomp$inline_1998 = + eventName$jscomp$inline_1996[0].toUpperCase() + + eventName$jscomp$inline_1996.slice(1); registerSimpleEvent( - domEventName$jscomp$inline_1990, - "on" + capitalizedEvent$jscomp$inline_1991 + domEventName$jscomp$inline_1997, + "on" + capitalizedEvent$jscomp$inline_1998 ); } registerSimpleEvent(ANIMATION_END, "onAnimationEnd"); @@ -19914,16 +19950,16 @@ ReactDOMHydrationRoot.prototype.unstable_scheduleHydration = function (target) { 0 === i && attemptExplicitHydrationTarget(target); } }; -var isomorphicReactPackageVersion$jscomp$inline_2337 = React.version; +var isomorphicReactPackageVersion$jscomp$inline_2344 = React.version; if ( - "19.3.0-canary-65eec428-20251218" !== - isomorphicReactPackageVersion$jscomp$inline_2337 + "19.3.0-canary-bef88f7c-20260116" !== + isomorphicReactPackageVersion$jscomp$inline_2344 ) throw Error( formatProdErrorMessage( 527, - isomorphicReactPackageVersion$jscomp$inline_2337, - "19.3.0-canary-65eec428-20251218" + isomorphicReactPackageVersion$jscomp$inline_2344, + "19.3.0-canary-bef88f7c-20260116" ) ); ReactDOMSharedInternals.findDOMNode = function (componentOrElement) { @@ -19943,24 +19979,24 @@ ReactDOMSharedInternals.findDOMNode = function (componentOrElement) { null === componentOrElement ? null : componentOrElement.stateNode; return componentOrElement; }; -var internals$jscomp$inline_2938 = { +var internals$jscomp$inline_2947 = { bundleType: 0, - version: "19.3.0-canary-65eec428-20251218", + version: "19.3.0-canary-bef88f7c-20260116", rendererPackageName: "react-dom", currentDispatcherRef: ReactSharedInternals, - reconcilerVersion: "19.3.0-canary-65eec428-20251218" + reconcilerVersion: "19.3.0-canary-bef88f7c-20260116" }; if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { - var hook$jscomp$inline_2939 = __REACT_DEVTOOLS_GLOBAL_HOOK__; + var hook$jscomp$inline_2948 = __REACT_DEVTOOLS_GLOBAL_HOOK__; if ( - !hook$jscomp$inline_2939.isDisabled && - hook$jscomp$inline_2939.supportsFiber + !hook$jscomp$inline_2948.isDisabled && + hook$jscomp$inline_2948.supportsFiber ) try { - (rendererID = hook$jscomp$inline_2939.inject( - internals$jscomp$inline_2938 + (rendererID = hook$jscomp$inline_2948.inject( + internals$jscomp$inline_2947 )), - (injectedHook = hook$jscomp$inline_2939); + (injectedHook = hook$jscomp$inline_2948); } catch (err) {} } function getCrossOriginStringAs(as, input) { @@ -20207,7 +20243,7 @@ exports.useFormState = function (action, initialState, permalink) { exports.useFormStatus = function () { return ReactSharedInternals.H.useHostTransitionStatus(); }; -exports.version = "19.3.0-canary-65eec428-20251218"; +exports.version = "19.3.0-canary-bef88f7c-20260116"; "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && diff --git a/packages/next/src/compiled/react-dom/cjs/react-dom-server-legacy.browser.development.js b/packages/next/src/compiled/react-dom/cjs/react-dom-server-legacy.browser.development.js index 3ac8b39470fb..b6bdae7fd436 100644 --- a/packages/next/src/compiled/react-dom/cjs/react-dom-server-legacy.browser.development.js +++ b/packages/next/src/compiled/react-dom/cjs/react-dom-server-legacy.browser.development.js @@ -10035,5 +10035,5 @@ 'The server used "renderToString" which does not support Suspense. If you intended for this Suspense boundary to render the fallback content on the server consider throwing an Error somewhere within the Suspense boundary. If you intended to have the server wait for the suspended component please switch to "renderToReadableStream" which supports Suspense on the server' ); }; - exports.version = "19.3.0-canary-65eec428-20251218"; + exports.version = "19.3.0-canary-bef88f7c-20260116"; })(); diff --git a/packages/next/src/compiled/react-dom/cjs/react-dom-server-legacy.browser.production.js b/packages/next/src/compiled/react-dom/cjs/react-dom-server-legacy.browser.production.js index 8b6011cb1e8d..ae7a304a4b56 100644 --- a/packages/next/src/compiled/react-dom/cjs/react-dom-server-legacy.browser.production.js +++ b/packages/next/src/compiled/react-dom/cjs/react-dom-server-legacy.browser.production.js @@ -6763,4 +6763,4 @@ exports.renderToString = function (children, options) { 'The server used "renderToString" which does not support Suspense. If you intended for this Suspense boundary to render the fallback content on the server consider throwing an Error somewhere within the Suspense boundary. If you intended to have the server wait for the suspended component please switch to "renderToReadableStream" which supports Suspense on the server' ); }; -exports.version = "19.3.0-canary-65eec428-20251218"; +exports.version = "19.3.0-canary-bef88f7c-20260116"; diff --git a/packages/next/src/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js b/packages/next/src/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js index 0568b57363b3..a9dc5281c3ca 100644 --- a/packages/next/src/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js +++ b/packages/next/src/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js @@ -10035,5 +10035,5 @@ 'The server used "renderToString" which does not support Suspense. If you intended for this Suspense boundary to render the fallback content on the server consider throwing an Error somewhere within the Suspense boundary. If you intended to have the server wait for the suspended component please switch to "renderToPipeableStream" which supports Suspense on the server' ); }; - exports.version = "19.3.0-canary-65eec428-20251218"; + exports.version = "19.3.0-canary-bef88f7c-20260116"; })(); diff --git a/packages/next/src/compiled/react-dom/cjs/react-dom-server-legacy.node.production.js b/packages/next/src/compiled/react-dom/cjs/react-dom-server-legacy.node.production.js index 7d1df836c822..5948bee4a5f4 100644 --- a/packages/next/src/compiled/react-dom/cjs/react-dom-server-legacy.node.production.js +++ b/packages/next/src/compiled/react-dom/cjs/react-dom-server-legacy.node.production.js @@ -6855,4 +6855,4 @@ exports.renderToString = function (children, options) { 'The server used "renderToString" which does not support Suspense. If you intended for this Suspense boundary to render the fallback content on the server consider throwing an Error somewhere within the Suspense boundary. If you intended to have the server wait for the suspended component please switch to "renderToPipeableStream" which supports Suspense on the server' ); }; -exports.version = "19.3.0-canary-65eec428-20251218"; +exports.version = "19.3.0-canary-bef88f7c-20260116"; diff --git a/packages/next/src/compiled/react-dom/cjs/react-dom-server.browser.development.js b/packages/next/src/compiled/react-dom/cjs/react-dom-server.browser.development.js index 6bc9629e189b..338c7c436fa5 100644 --- a/packages/next/src/compiled/react-dom/cjs/react-dom-server.browser.development.js +++ b/packages/next/src/compiled/react-dom/cjs/react-dom-server.browser.development.js @@ -9001,11 +9001,11 @@ } function ensureCorrectIsomorphicReactVersion() { var isomorphicReactPackageVersion = React.version; - if ("19.3.0-canary-65eec428-20251218" !== isomorphicReactPackageVersion) + if ("19.3.0-canary-bef88f7c-20260116" !== isomorphicReactPackageVersion) throw Error( 'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' + (isomorphicReactPackageVersion + - "\n - react-dom: 19.3.0-canary-65eec428-20251218\nLearn more: https://react.dev/warnings/version-mismatch") + "\n - react-dom: 19.3.0-canary-bef88f7c-20260116\nLearn more: https://react.dev/warnings/version-mismatch") ); } var React = require("next/dist/compiled/react"), @@ -10808,5 +10808,5 @@ startWork(request); }); }; - exports.version = "19.3.0-canary-65eec428-20251218"; + exports.version = "19.3.0-canary-bef88f7c-20260116"; })(); diff --git a/packages/next/src/compiled/react-dom/cjs/react-dom-server.browser.production.js b/packages/next/src/compiled/react-dom/cjs/react-dom-server.browser.production.js index f030fb2077d9..af97b004a0c1 100644 --- a/packages/next/src/compiled/react-dom/cjs/react-dom-server.browser.production.js +++ b/packages/next/src/compiled/react-dom/cjs/react-dom-server.browser.production.js @@ -7365,12 +7365,12 @@ function getPostponedState(request) { } function ensureCorrectIsomorphicReactVersion() { var isomorphicReactPackageVersion = React.version; - if ("19.3.0-canary-65eec428-20251218" !== isomorphicReactPackageVersion) + if ("19.3.0-canary-bef88f7c-20260116" !== isomorphicReactPackageVersion) throw Error( formatProdErrorMessage( 527, isomorphicReactPackageVersion, - "19.3.0-canary-65eec428-20251218" + "19.3.0-canary-bef88f7c-20260116" ) ); } @@ -7621,4 +7621,4 @@ exports.resumeAndPrerender = function (children, postponedState, options) { startWork(request); }); }; -exports.version = "19.3.0-canary-65eec428-20251218"; +exports.version = "19.3.0-canary-bef88f7c-20260116"; diff --git a/packages/next/src/compiled/react-dom/cjs/react-dom-server.bun.production.js b/packages/next/src/compiled/react-dom/cjs/react-dom-server.bun.production.js index ba6559fc8ae3..13b5d8a25f46 100644 --- a/packages/next/src/compiled/react-dom/cjs/react-dom-server.bun.production.js +++ b/packages/next/src/compiled/react-dom/cjs/react-dom-server.bun.production.js @@ -7073,11 +7073,11 @@ function getPostponedState(request) { } function ensureCorrectIsomorphicReactVersion() { var isomorphicReactPackageVersion = React.version; - if ("19.3.0-canary-65eec428-20251218" !== isomorphicReactPackageVersion) + if ("19.3.0-canary-bef88f7c-20260116" !== isomorphicReactPackageVersion) throw Error( 'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' + (isomorphicReactPackageVersion + - "\n - react-dom: 19.3.0-canary-65eec428-20251218\nLearn more: https://react.dev/warnings/version-mismatch") + "\n - react-dom: 19.3.0-canary-bef88f7c-20260116\nLearn more: https://react.dev/warnings/version-mismatch") ); } ensureCorrectIsomorphicReactVersion(); @@ -7622,4 +7622,4 @@ exports.resumeToPipeableStream = function (children, postponedState, options) { } }; }; -exports.version = "19.3.0-canary-65eec428-20251218"; +exports.version = "19.3.0-canary-bef88f7c-20260116"; diff --git a/packages/next/src/compiled/react-dom/cjs/react-dom-server.edge.development.js b/packages/next/src/compiled/react-dom/cjs/react-dom-server.edge.development.js index 529e1bb108ff..946c123163e3 100644 --- a/packages/next/src/compiled/react-dom/cjs/react-dom-server.edge.development.js +++ b/packages/next/src/compiled/react-dom/cjs/react-dom-server.edge.development.js @@ -9024,11 +9024,11 @@ } function ensureCorrectIsomorphicReactVersion() { var isomorphicReactPackageVersion = React.version; - if ("19.3.0-canary-65eec428-20251218" !== isomorphicReactPackageVersion) + if ("19.3.0-canary-bef88f7c-20260116" !== isomorphicReactPackageVersion) throw Error( 'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' + (isomorphicReactPackageVersion + - "\n - react-dom: 19.3.0-canary-65eec428-20251218\nLearn more: https://react.dev/warnings/version-mismatch") + "\n - react-dom: 19.3.0-canary-bef88f7c-20260116\nLearn more: https://react.dev/warnings/version-mismatch") ); } var React = require("next/dist/compiled/react"), @@ -10827,5 +10827,5 @@ startWork(request); }); }; - exports.version = "19.3.0-canary-65eec428-20251218"; + exports.version = "19.3.0-canary-bef88f7c-20260116"; })(); diff --git a/packages/next/src/compiled/react-dom/cjs/react-dom-server.edge.production.js b/packages/next/src/compiled/react-dom/cjs/react-dom-server.edge.production.js index 423b892e9523..9a8231a4924c 100644 --- a/packages/next/src/compiled/react-dom/cjs/react-dom-server.edge.production.js +++ b/packages/next/src/compiled/react-dom/cjs/react-dom-server.edge.production.js @@ -7472,11 +7472,11 @@ function getPostponedState(request) { } function ensureCorrectIsomorphicReactVersion() { var isomorphicReactPackageVersion = React.version; - if ("19.3.0-canary-65eec428-20251218" !== isomorphicReactPackageVersion) + if ("19.3.0-canary-bef88f7c-20260116" !== isomorphicReactPackageVersion) throw Error( 'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' + (isomorphicReactPackageVersion + - "\n - react-dom: 19.3.0-canary-65eec428-20251218\nLearn more: https://react.dev/warnings/version-mismatch") + "\n - react-dom: 19.3.0-canary-bef88f7c-20260116\nLearn more: https://react.dev/warnings/version-mismatch") ); } ensureCorrectIsomorphicReactVersion(); @@ -7726,4 +7726,4 @@ exports.resumeAndPrerender = function (children, postponedState, options) { startWork(request); }); }; -exports.version = "19.3.0-canary-65eec428-20251218"; +exports.version = "19.3.0-canary-bef88f7c-20260116"; diff --git a/packages/next/src/compiled/react-dom/cjs/react-dom-server.node.development.js b/packages/next/src/compiled/react-dom/cjs/react-dom-server.node.development.js index 265efc753e0e..18341bc167fa 100644 --- a/packages/next/src/compiled/react-dom/cjs/react-dom-server.node.development.js +++ b/packages/next/src/compiled/react-dom/cjs/react-dom-server.node.development.js @@ -8898,11 +8898,11 @@ } function ensureCorrectIsomorphicReactVersion() { var isomorphicReactPackageVersion = React.version; - if ("19.3.0-canary-65eec428-20251218" !== isomorphicReactPackageVersion) + if ("19.3.0-canary-bef88f7c-20260116" !== isomorphicReactPackageVersion) throw Error( 'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' + (isomorphicReactPackageVersion + - "\n - react-dom: 19.3.0-canary-65eec428-20251218\nLearn more: https://react.dev/warnings/version-mismatch") + "\n - react-dom: 19.3.0-canary-bef88f7c-20260116\nLearn more: https://react.dev/warnings/version-mismatch") ); } function createDrainHandler(destination, request) { @@ -11007,5 +11007,5 @@ } }; }; - exports.version = "19.3.0-canary-65eec428-20251218"; + exports.version = "19.3.0-canary-bef88f7c-20260116"; })(); diff --git a/packages/next/src/compiled/react-dom/cjs/react-dom-server.node.production.js b/packages/next/src/compiled/react-dom/cjs/react-dom-server.node.production.js index b71e391be8fc..c3fd755404f2 100644 --- a/packages/next/src/compiled/react-dom/cjs/react-dom-server.node.production.js +++ b/packages/next/src/compiled/react-dom/cjs/react-dom-server.node.production.js @@ -7363,11 +7363,11 @@ function getPostponedState(request) { } function ensureCorrectIsomorphicReactVersion() { var isomorphicReactPackageVersion = React.version; - if ("19.3.0-canary-65eec428-20251218" !== isomorphicReactPackageVersion) + if ("19.3.0-canary-bef88f7c-20260116" !== isomorphicReactPackageVersion) throw Error( 'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' + (isomorphicReactPackageVersion + - "\n - react-dom: 19.3.0-canary-65eec428-20251218\nLearn more: https://react.dev/warnings/version-mismatch") + "\n - react-dom: 19.3.0-canary-bef88f7c-20260116\nLearn more: https://react.dev/warnings/version-mismatch") ); } ensureCorrectIsomorphicReactVersion(); @@ -7917,4 +7917,4 @@ exports.resumeToPipeableStream = function (children, postponedState, options) { } }; }; -exports.version = "19.3.0-canary-65eec428-20251218"; +exports.version = "19.3.0-canary-bef88f7c-20260116"; diff --git a/packages/next/src/compiled/react-dom/cjs/react-dom.development.js b/packages/next/src/compiled/react-dom/cjs/react-dom.development.js index 9967a88bb3ce..283e8bc1597f 100644 --- a/packages/next/src/compiled/react-dom/cjs/react-dom.development.js +++ b/packages/next/src/compiled/react-dom/cjs/react-dom.development.js @@ -422,7 +422,7 @@ exports.useFormStatus = function () { return resolveDispatcher().useHostTransitionStatus(); }; - exports.version = "19.3.0-canary-65eec428-20251218"; + exports.version = "19.3.0-canary-bef88f7c-20260116"; "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && diff --git a/packages/next/src/compiled/react-dom/cjs/react-dom.production.js b/packages/next/src/compiled/react-dom/cjs/react-dom.production.js index cd2caa4cb44d..293945358c9e 100644 --- a/packages/next/src/compiled/react-dom/cjs/react-dom.production.js +++ b/packages/next/src/compiled/react-dom/cjs/react-dom.production.js @@ -213,4 +213,4 @@ exports.useFormState = function (action, initialState, permalink) { exports.useFormStatus = function () { return ReactSharedInternals.H.useHostTransitionStatus(); }; -exports.version = "19.3.0-canary-65eec428-20251218"; +exports.version = "19.3.0-canary-bef88f7c-20260116"; diff --git a/packages/next/src/compiled/react-dom/cjs/react-dom.react-server.development.js b/packages/next/src/compiled/react-dom/cjs/react-dom.react-server.development.js index 3e56ea220745..aee4067a1c20 100644 --- a/packages/next/src/compiled/react-dom/cjs/react-dom.react-server.development.js +++ b/packages/next/src/compiled/react-dom/cjs/react-dom.react-server.development.js @@ -336,5 +336,5 @@ })) : Internals.d.m(href)); }; - exports.version = "19.3.0-canary-65eec428-20251218"; + exports.version = "19.3.0-canary-bef88f7c-20260116"; })(); diff --git a/packages/next/src/compiled/react-dom/cjs/react-dom.react-server.production.js b/packages/next/src/compiled/react-dom/cjs/react-dom.react-server.production.js index b99ef09e8b17..61732c556be3 100644 --- a/packages/next/src/compiled/react-dom/cjs/react-dom.react-server.production.js +++ b/packages/next/src/compiled/react-dom/cjs/react-dom.react-server.production.js @@ -149,4 +149,4 @@ exports.preloadModule = function (href, options) { }); } else Internals.d.m(href); }; -exports.version = "19.3.0-canary-65eec428-20251218"; +exports.version = "19.3.0-canary-bef88f7c-20260116"; diff --git a/packages/next/src/compiled/react-dom/package.json b/packages/next/src/compiled/react-dom/package.json index f5d6b36f3549..2c438845c452 100644 --- a/packages/next/src/compiled/react-dom/package.json +++ b/packages/next/src/compiled/react-dom/package.json @@ -67,10 +67,10 @@ "./package.json": "./package.json" }, "dependencies": { - "scheduler": "0.28.0-canary-65eec428-20251218" + "scheduler": "0.28.0-canary-bef88f7c-20260116" }, "peerDependencies": { - "react": "19.3.0-canary-65eec428-20251218" + "react": "19.3.0-canary-bef88f7c-20260116" }, "browser": { "./server.js": "./server.browser.js", diff --git a/packages/next/src/compiled/react-experimental/cjs/react.development.js b/packages/next/src/compiled/react-experimental/cjs/react.development.js index 18643d7e5492..23d2dcb1fe6f 100644 --- a/packages/next/src/compiled/react-experimental/cjs/react.development.js +++ b/packages/next/src/compiled/react-experimental/cjs/react.development.js @@ -1391,7 +1391,7 @@ exports.useTransition = function () { return resolveDispatcher().useTransition(); }; - exports.version = "19.3.0-experimental-65eec428-20251218"; + exports.version = "19.3.0-experimental-bef88f7c-20260116"; "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && diff --git a/packages/next/src/compiled/react-experimental/cjs/react.production.js b/packages/next/src/compiled/react-experimental/cjs/react.production.js index 7694cd9716c4..c981eafe0658 100644 --- a/packages/next/src/compiled/react-experimental/cjs/react.production.js +++ b/packages/next/src/compiled/react-experimental/cjs/react.production.js @@ -268,19 +268,27 @@ function mapChildren(children, func, context) { } function lazyInitializer(payload) { if (-1 === payload._status) { - var ctor = payload._result; - ctor = ctor(); - ctor.then( + var ctor = payload._result, + thenable = ctor(); + thenable.then( function (moduleObject) { if (0 === payload._status || -1 === payload._status) - (payload._status = 1), (payload._result = moduleObject); + (payload._status = 1), + (payload._result = moduleObject), + void 0 === thenable.status && + ((thenable.status = "fulfilled"), + (thenable.value = moduleObject)); }, function (error) { if (0 === payload._status || -1 === payload._status) - (payload._status = 2), (payload._result = error); + (payload._status = 2), + (payload._result = error), + void 0 === thenable.status && + ((thenable.status = "rejected"), (thenable.reason = error)); } ); - -1 === payload._status && ((payload._status = 0), (payload._result = ctor)); + -1 === payload._status && + ((payload._status = 0), (payload._result = thenable)); } if (1 === payload._status) return payload._result.default; throw payload._result; @@ -605,4 +613,4 @@ exports.useSyncExternalStore = function ( exports.useTransition = function () { return ReactSharedInternals.H.useTransition(); }; -exports.version = "19.3.0-experimental-65eec428-20251218"; +exports.version = "19.3.0-experimental-bef88f7c-20260116"; diff --git a/packages/next/src/compiled/react-experimental/cjs/react.react-server.development.js b/packages/next/src/compiled/react-experimental/cjs/react.react-server.development.js index 23fefe304fca..480a8e8cc5c8 100644 --- a/packages/next/src/compiled/react-experimental/cjs/react.react-server.development.js +++ b/packages/next/src/compiled/react-experimental/cjs/react.react-server.development.js @@ -1061,5 +1061,5 @@ exports.useMemo = function (create, deps) { return resolveDispatcher().useMemo(create, deps); }; - exports.version = "19.3.0-experimental-65eec428-20251218"; + exports.version = "19.3.0-experimental-bef88f7c-20260116"; })(); diff --git a/packages/next/src/compiled/react-experimental/cjs/react.react-server.production.js b/packages/next/src/compiled/react-experimental/cjs/react.react-server.production.js index 2a0206eb8177..80e68ddb4668 100644 --- a/packages/next/src/compiled/react-experimental/cjs/react.react-server.production.js +++ b/packages/next/src/compiled/react-experimental/cjs/react.react-server.production.js @@ -251,19 +251,27 @@ function mapChildren(children, func, context) { } function lazyInitializer(payload) { if (-1 === payload._status) { - var ctor = payload._result; - ctor = ctor(); - ctor.then( + var ctor = payload._result, + thenable = ctor(); + thenable.then( function (moduleObject) { if (0 === payload._status || -1 === payload._status) - (payload._status = 1), (payload._result = moduleObject); + (payload._status = 1), + (payload._result = moduleObject), + void 0 === thenable.status && + ((thenable.status = "fulfilled"), + (thenable.value = moduleObject)); }, function (error) { if (0 === payload._status || -1 === payload._status) - (payload._status = 2), (payload._result = error); + (payload._status = 2), + (payload._result = error), + void 0 === thenable.status && + ((thenable.status = "rejected"), (thenable.reason = error)); } ); - -1 === payload._status && ((payload._status = 0), (payload._result = ctor)); + -1 === payload._status && + ((payload._status = 0), (payload._result = thenable)); } if (1 === payload._status) return payload._result.default; throw payload._result; @@ -571,4 +579,4 @@ exports.useId = function () { exports.useMemo = function (create, deps) { return ReactSharedInternals.H.useMemo(create, deps); }; -exports.version = "19.3.0-experimental-65eec428-20251218"; +exports.version = "19.3.0-experimental-bef88f7c-20260116"; diff --git a/packages/next/src/compiled/react-is/package.json b/packages/next/src/compiled/react-is/package.json index dfab51327778..7e77d0665c75 100644 --- a/packages/next/src/compiled/react-is/package.json +++ b/packages/next/src/compiled/react-is/package.json @@ -1,6 +1,6 @@ { "name": "react-is", - "version": "19.3.0-canary-65eec428-20251218", + "version": "19.3.0-canary-bef88f7c-20260116", "description": "Brand checking of React Elements.", "main": "index.js", "sideEffects": false, diff --git a/packages/next/src/compiled/react-server-dom-turbopack-experimental/cjs/react-server-dom-turbopack-client.browser.development.js b/packages/next/src/compiled/react-server-dom-turbopack-experimental/cjs/react-server-dom-turbopack-client.browser.development.js index ca74c9f4800d..75db6d6e3d53 100644 --- a/packages/next/src/compiled/react-server-dom-turbopack-experimental/cjs/react-server-dom-turbopack-client.browser.development.js +++ b/packages/next/src/compiled/react-server-dom-turbopack-experimental/cjs/react-server-dom-turbopack-client.browser.development.js @@ -5000,10 +5000,10 @@ return hook.checkDCE ? !0 : !1; })({ bundleType: 1, - version: "19.3.0-experimental-65eec428-20251218", + version: "19.3.0-experimental-bef88f7c-20260116", rendererPackageName: "react-server-dom-turbopack", currentDispatcherRef: ReactSharedInternals, - reconcilerVersion: "19.3.0-experimental-65eec428-20251218", + reconcilerVersion: "19.3.0-experimental-bef88f7c-20260116", getCurrentComponentInfo: function () { return currentOwnerInDEV; } diff --git a/packages/next/src/compiled/react-server-dom-turbopack-experimental/package.json b/packages/next/src/compiled/react-server-dom-turbopack-experimental/package.json index 80985b903abd..29a313de4aaa 100644 --- a/packages/next/src/compiled/react-server-dom-turbopack-experimental/package.json +++ b/packages/next/src/compiled/react-server-dom-turbopack-experimental/package.json @@ -48,7 +48,7 @@ "neo-async": "^2.6.1" }, "peerDependencies": { - "react": "0.0.0-experimental-65eec428-20251218", - "react-dom": "0.0.0-experimental-65eec428-20251218" + "react": "0.0.0-experimental-bef88f7c-20260116", + "react-dom": "0.0.0-experimental-bef88f7c-20260116" } } \ No newline at end of file diff --git a/packages/next/src/compiled/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js b/packages/next/src/compiled/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js index fd229ebbcc87..cfd236c03df5 100644 --- a/packages/next/src/compiled/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js +++ b/packages/next/src/compiled/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js @@ -5000,10 +5000,10 @@ return hook.checkDCE ? !0 : !1; })({ bundleType: 1, - version: "19.3.0-canary-65eec428-20251218", + version: "19.3.0-canary-bef88f7c-20260116", rendererPackageName: "react-server-dom-turbopack", currentDispatcherRef: ReactSharedInternals, - reconcilerVersion: "19.3.0-canary-65eec428-20251218", + reconcilerVersion: "19.3.0-canary-bef88f7c-20260116", getCurrentComponentInfo: function () { return currentOwnerInDEV; } diff --git a/packages/next/src/compiled/react-server-dom-turbopack/package.json b/packages/next/src/compiled/react-server-dom-turbopack/package.json index cfc220229025..60c6a9af4b03 100644 --- a/packages/next/src/compiled/react-server-dom-turbopack/package.json +++ b/packages/next/src/compiled/react-server-dom-turbopack/package.json @@ -48,7 +48,7 @@ "neo-async": "^2.6.1" }, "peerDependencies": { - "react": "19.3.0-canary-65eec428-20251218", - "react-dom": "19.3.0-canary-65eec428-20251218" + "react": "19.3.0-canary-bef88f7c-20260116", + "react-dom": "19.3.0-canary-bef88f7c-20260116" } } \ No newline at end of file diff --git a/packages/next/src/compiled/react-server-dom-webpack-experimental/cjs/react-server-dom-webpack-client.browser.development.js b/packages/next/src/compiled/react-server-dom-webpack-experimental/cjs/react-server-dom-webpack-client.browser.development.js index dc0b10925d67..12a86bf43be4 100644 --- a/packages/next/src/compiled/react-server-dom-webpack-experimental/cjs/react-server-dom-webpack-client.browser.development.js +++ b/packages/next/src/compiled/react-server-dom-webpack-experimental/cjs/react-server-dom-webpack-client.browser.development.js @@ -5016,10 +5016,10 @@ return hook.checkDCE ? !0 : !1; })({ bundleType: 1, - version: "19.3.0-experimental-65eec428-20251218", + version: "19.3.0-experimental-bef88f7c-20260116", rendererPackageName: "react-server-dom-webpack", currentDispatcherRef: ReactSharedInternals, - reconcilerVersion: "19.3.0-experimental-65eec428-20251218", + reconcilerVersion: "19.3.0-experimental-bef88f7c-20260116", getCurrentComponentInfo: function () { return currentOwnerInDEV; } diff --git a/packages/next/src/compiled/react-server-dom-webpack-experimental/package.json b/packages/next/src/compiled/react-server-dom-webpack-experimental/package.json index e9f4a82a7b41..63842d45f579 100644 --- a/packages/next/src/compiled/react-server-dom-webpack-experimental/package.json +++ b/packages/next/src/compiled/react-server-dom-webpack-experimental/package.json @@ -52,8 +52,8 @@ "webpack-sources": "^3.2.0" }, "peerDependencies": { - "react": "0.0.0-experimental-65eec428-20251218", - "react-dom": "0.0.0-experimental-65eec428-20251218", + "react": "0.0.0-experimental-bef88f7c-20260116", + "react-dom": "0.0.0-experimental-bef88f7c-20260116", "webpack": "^5.59.0" } } \ No newline at end of file diff --git a/packages/next/src/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js b/packages/next/src/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js index af8f5c2866ae..623f336a1cd2 100644 --- a/packages/next/src/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js +++ b/packages/next/src/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js @@ -5016,10 +5016,10 @@ return hook.checkDCE ? !0 : !1; })({ bundleType: 1, - version: "19.3.0-canary-65eec428-20251218", + version: "19.3.0-canary-bef88f7c-20260116", rendererPackageName: "react-server-dom-webpack", currentDispatcherRef: ReactSharedInternals, - reconcilerVersion: "19.3.0-canary-65eec428-20251218", + reconcilerVersion: "19.3.0-canary-bef88f7c-20260116", getCurrentComponentInfo: function () { return currentOwnerInDEV; } diff --git a/packages/next/src/compiled/react-server-dom-webpack/package.json b/packages/next/src/compiled/react-server-dom-webpack/package.json index bf8dc32f05ab..a38b0dc8d3d5 100644 --- a/packages/next/src/compiled/react-server-dom-webpack/package.json +++ b/packages/next/src/compiled/react-server-dom-webpack/package.json @@ -52,8 +52,8 @@ "webpack-sources": "^3.2.0" }, "peerDependencies": { - "react": "19.3.0-canary-65eec428-20251218", - "react-dom": "19.3.0-canary-65eec428-20251218", + "react": "19.3.0-canary-bef88f7c-20260116", + "react-dom": "19.3.0-canary-bef88f7c-20260116", "webpack": "^5.59.0" } } \ No newline at end of file diff --git a/packages/next/src/compiled/react/cjs/react.development.js b/packages/next/src/compiled/react/cjs/react.development.js index 3cea6ad65484..758c4d36476b 100644 --- a/packages/next/src/compiled/react/cjs/react.development.js +++ b/packages/next/src/compiled/react/cjs/react.development.js @@ -1322,7 +1322,7 @@ exports.useTransition = function () { return resolveDispatcher().useTransition(); }; - exports.version = "19.3.0-canary-65eec428-20251218"; + exports.version = "19.3.0-canary-bef88f7c-20260116"; "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && diff --git a/packages/next/src/compiled/react/cjs/react.production.js b/packages/next/src/compiled/react/cjs/react.production.js index 5095970f0808..32f05ddd7ff1 100644 --- a/packages/next/src/compiled/react/cjs/react.production.js +++ b/packages/next/src/compiled/react/cjs/react.production.js @@ -264,19 +264,27 @@ function mapChildren(children, func, context) { } function lazyInitializer(payload) { if (-1 === payload._status) { - var ctor = payload._result; - ctor = ctor(); - ctor.then( + var ctor = payload._result, + thenable = ctor(); + thenable.then( function (moduleObject) { if (0 === payload._status || -1 === payload._status) - (payload._status = 1), (payload._result = moduleObject); + (payload._status = 1), + (payload._result = moduleObject), + void 0 === thenable.status && + ((thenable.status = "fulfilled"), + (thenable.value = moduleObject)); }, function (error) { if (0 === payload._status || -1 === payload._status) - (payload._status = 2), (payload._result = error); + (payload._status = 2), + (payload._result = error), + void 0 === thenable.status && + ((thenable.status = "rejected"), (thenable.reason = error)); } ); - -1 === payload._status && ((payload._status = 0), (payload._result = ctor)); + -1 === payload._status && + ((payload._status = 0), (payload._result = thenable)); } if (1 === payload._status) return payload._result.default; throw payload._result; @@ -554,4 +562,4 @@ exports.useSyncExternalStore = function ( exports.useTransition = function () { return ReactSharedInternals.H.useTransition(); }; -exports.version = "19.3.0-canary-65eec428-20251218"; +exports.version = "19.3.0-canary-bef88f7c-20260116"; diff --git a/packages/next/src/compiled/react/cjs/react.react-server.development.js b/packages/next/src/compiled/react/cjs/react.react-server.development.js index 8decb0952f0f..13cd7fa3b63b 100644 --- a/packages/next/src/compiled/react/cjs/react.react-server.development.js +++ b/packages/next/src/compiled/react/cjs/react.react-server.development.js @@ -874,5 +874,5 @@ exports.useMemo = function (create, deps) { return resolveDispatcher().useMemo(create, deps); }; - exports.version = "19.3.0-canary-65eec428-20251218"; + exports.version = "19.3.0-canary-bef88f7c-20260116"; })(); diff --git a/packages/next/src/compiled/react/cjs/react.react-server.production.js b/packages/next/src/compiled/react/cjs/react.react-server.production.js index 0713eed1ee8c..8621bb108658 100644 --- a/packages/next/src/compiled/react/cjs/react.react-server.production.js +++ b/packages/next/src/compiled/react/cjs/react.react-server.production.js @@ -236,19 +236,27 @@ function mapChildren(children, func, context) { } function lazyInitializer(payload) { if (-1 === payload._status) { - var ctor = payload._result; - ctor = ctor(); - ctor.then( + var ctor = payload._result, + thenable = ctor(); + thenable.then( function (moduleObject) { if (0 === payload._status || -1 === payload._status) - (payload._status = 1), (payload._result = moduleObject); + (payload._status = 1), + (payload._result = moduleObject), + void 0 === thenable.status && + ((thenable.status = "fulfilled"), + (thenable.value = moduleObject)); }, function (error) { if (0 === payload._status || -1 === payload._status) - (payload._status = 2), (payload._result = error); + (payload._status = 2), + (payload._result = error), + void 0 === thenable.status && + ((thenable.status = "rejected"), (thenable.reason = error)); } ); - -1 === payload._status && ((payload._status = 0), (payload._result = ctor)); + -1 === payload._status && + ((payload._status = 0), (payload._result = thenable)); } if (1 === payload._status) return payload._result.default; throw payload._result; @@ -425,4 +433,4 @@ exports.useId = function () { exports.useMemo = function (create, deps) { return ReactSharedInternals.H.useMemo(create, deps); }; -exports.version = "19.3.0-canary-65eec428-20251218"; +exports.version = "19.3.0-canary-bef88f7c-20260116"; diff --git a/packages/next/src/compiled/unistore/unistore.js b/packages/next/src/compiled/unistore/unistore.js index 15608cd790fd..e8d288ecd34a 100644 --- a/packages/next/src/compiled/unistore/unistore.js +++ b/packages/next/src/compiled/unistore/unistore.js @@ -1 +1 @@ -(()=>{var t=[,t=>{function n(t,i){for(var _ in i)t[_]=i[_];return t}t.exports=function(t){var i=[];function u(t){for(var _=[],a=0;a{var t={251:t=>{function n(t,i){for(var _ in i)t[_]=i[_];return t}t.exports=function(t){var i=[];function u(t){for(var _=[],a=0;a(mod: { default: T } | T): T { + // @ts-ignore return mod.default || mod } diff --git a/packages/next/src/lib/metadata/resolve-metadata.ts b/packages/next/src/lib/metadata/resolve-metadata.ts index f64d76c24925..a644ffcef2dd 100644 --- a/packages/next/src/lib/metadata/resolve-metadata.ts +++ b/packages/next/src/lib/metadata/resolve-metadata.ts @@ -559,7 +559,7 @@ async function collectStaticImagesFiles( const iconPromises = metadata[type as 'icon' | 'apple'].map( async (imageModule: (p: any) => Promise) => - interopDefault(await imageModule(props)) + await interopDefault(imageModule)(props) ) return iconPromises?.length > 0 diff --git a/packages/next/src/lib/typescript/writeAppTypeDeclarations.ts b/packages/next/src/lib/typescript/writeAppTypeDeclarations.ts index 20727d2074b8..97fddf39a8aa 100644 --- a/packages/next/src/lib/typescript/writeAppTypeDeclarations.ts +++ b/packages/next/src/lib/typescript/writeAppTypeDeclarations.ts @@ -5,20 +5,21 @@ import { promises as fs } from 'fs' export async function writeAppTypeDeclarations({ baseDir, distDir, + distDirRoot, imageImportsEnabled, hasPagesDir, hasAppDir, - strictRouteTypes, - typedRoutes, }: { baseDir: string distDir: string + /** The root dist directory without /dev suffix, used for fixed type paths */ + distDirRoot?: string imageImportsEnabled: boolean hasPagesDir: boolean hasAppDir: boolean - strictRouteTypes: boolean - typedRoutes: boolean }): Promise { + // Use distDirRoot for fixed paths in next-env.d.ts, fallback to distDir + const typesDistDir = distDirRoot ?? distDir // Reference `next` types const appTypeDeclarations = path.join(baseDir, 'next-env.d.ts') @@ -61,36 +62,16 @@ export async function writeAppTypeDeclarations({ ) } + // Use fixed path for the entry type file (always at .next/types/routes.d.ts) + // This entry file re-exports from actual type files which may be at different paths const routeTypesPath = path.posix.join( - distDir.replaceAll(path.win32.sep, path.posix.sep), + typesDistDir.replaceAll(path.win32.sep, path.posix.sep), 'types/routes.d.ts' ) // Use ESM import instead of triple-slash reference for better ESLint compatibility lines.push(`import "./${routeTypesPath}";`) - if (strictRouteTypes) { - const cacheLifePath = path.posix.join( - distDir.replaceAll(path.win32.sep, path.posix.sep), - 'types/cache-life.d.ts' - ) - lines.push(`import "./${cacheLifePath}";`) - - const routeValidatorPath = path.posix.join( - distDir.replaceAll(path.win32.sep, path.posix.sep), - 'types/validator.ts' - ) - lines.push(`import "./${routeValidatorPath}";`) - - if (typedRoutes === true) { - const linkTypesPath = path.posix.join( - distDir.replaceAll(path.win32.sep, path.posix.sep), - 'types/link.d.ts' - ) - lines.push(`import "./${linkTypesPath}";`) - } - } - // Push the notice in. lines.push( '', diff --git a/packages/next/src/lib/verify-typescript-setup.ts b/packages/next/src/lib/verify-typescript-setup.ts index c80f35c4522e..4575bce9ebf1 100644 --- a/packages/next/src/lib/verify-typescript-setup.ts +++ b/packages/next/src/lib/verify-typescript-setup.ts @@ -36,11 +36,11 @@ const requiredPackages = [ export async function verifyTypeScriptSetup({ dir, distDir, + distDirRoot, cacheDir, strictRouteTypes, tsconfigPath, typeCheckPreflight, - typedRoutes, disableStaticImages, hasAppDir, hasPagesDir, @@ -51,11 +51,12 @@ export async function verifyTypeScriptSetup({ }: { dir: string distDir: string + /** The root dist directory without /dev suffix, used for fixed type paths */ + distDirRoot?: string cacheDir?: string strictRouteTypes: boolean tsconfigPath: string | undefined typeCheckPreflight: boolean - typedRoutes: boolean disableStaticImages: boolean hasAppDir: boolean hasPagesDir: boolean @@ -148,11 +149,10 @@ export async function verifyTypeScriptSetup({ await writeAppTypeDeclarations({ baseDir: dir, distDir, + distDirRoot, imageImportsEnabled: !disableStaticImages, hasPagesDir, hasAppDir, - strictRouteTypes, - typedRoutes, }) let result diff --git a/packages/next/src/next-devtools/userspace/app/errors/intercept-console-error.ts b/packages/next/src/next-devtools/userspace/app/errors/intercept-console-error.ts index 5d70332b87c9..a444369f628e 100644 --- a/packages/next/src/next-devtools/userspace/app/errors/intercept-console-error.ts +++ b/packages/next/src/next-devtools/userspace/app/errors/intercept-console-error.ts @@ -14,8 +14,11 @@ export function patchConsoleError() { } window.console.error = function error(...args: any[]) { let maybeError: unknown + let isReplayedLog = false if (process.env.NODE_ENV !== 'production') { - const { error: replayedError } = parseConsoleArgs(args) + const { error: replayedError, environmentName } = parseConsoleArgs(args) + // If environmentName is set, this is a server log replayed by React in the browser + isReplayedLog = !!environmentName if (replayedError) { maybeError = replayedError } else if (isError(args[0])) { @@ -37,7 +40,10 @@ export function patchConsoleError() { args ) } - forwardErrorLog(args) + // Don't forward replayed server logs to terminal - they were already logged on the server + if (!isReplayedLog) { + forwardErrorLog(args) + } originConsoleError.apply(window.console, args) } diff --git a/packages/next/src/next-devtools/userspace/app/forward-logs.ts b/packages/next/src/next-devtools/userspace/app/forward-logs.ts index c8fb51553c35..1904b9abc632 100644 --- a/packages/next/src/next-devtools/userspace/app/forward-logs.ts +++ b/packages/next/src/next-devtools/userspace/app/forward-logs.ts @@ -1,7 +1,3 @@ -import { - getOwnerStack, - setOwnerStackIfAvailable, -} from './errors/stitched-error' import { getErrorSource } from '../../../shared/lib/error-source' import { getIsTerminalLoggingEnabled } from './terminal-logging-config' import { @@ -328,7 +324,7 @@ const stringifyUserArg = ( } const createErrorArg = (error: Error) => { - const stack = stackWithOwners(error) + const stack = getErrorStack(error) return { kind: 'formatted-error-arg' as const, prefix: error.message ? `${error.name}: ${error.message}` : `${error.name}`, @@ -347,7 +343,7 @@ const createLogEntry = (level: LogMethod, args: any[]) => { // do not abstract this, it implicitly relies on which functions call it. forcing the inlined implementation makes you think about callers // error capture stack trace maybe - const stack = stackWithOwners(new Error()) + const stack = getErrorStack(new Error()) const stackLines = stack?.split('\n') const cleanStack = stackLines?.slice(3).join('\n') // this is probably ignored anyways const entry: ConsoleEntry = { @@ -369,6 +365,11 @@ const createLogEntry = (level: LogMethod, args: any[]) => { } export const forwardErrorLog = (args: any[]) => { + // Skip React server replayed logs - they were already logged on the server + if (isReactServerReplayedLog(args)) { + return + } + // Always log to client file logger with args (formatting done inside log method) clientFileLogger.log('error', args) // Only forward to terminal if enabled @@ -389,7 +390,7 @@ export const forwardErrorLog = (args: any[]) => { * * do not abstract this, it implicitly relies on which functions call it. forcing the inlined implementation makes you think about callers */ - const stack = stackWithOwners(new Error()) + const stack = getErrorStack(new Error()) const stackLines = stack?.split('\n') const cleanStack = stackLines?.slice(3).join('\n') @@ -426,12 +427,8 @@ const createUncaughtErrorEntry = ( logQueue.scheduleLogSend(entry) } -const stackWithOwners = (error: Error) => { - let ownerStack = '' - setOwnerStackIfAvailable(error) - ownerStack = getOwnerStack(error) || '' - const stack = (error.stack || '') + ownerStack - return stack +const getErrorStack = (error: Error) => { + return error.stack || '' } export function logUnhandledRejection(reason: unknown) { @@ -448,7 +445,7 @@ export function logUnhandledRejection(reason: unknown) { } if (reason instanceof Error) { - createUnhandledRejectionErrorEntry(reason, stackWithOwners(reason)) + createUnhandledRejectionErrorEntry(reason, getErrorStack(reason)) return } createUnhandledRejectionNonErrorEntry(reason) @@ -543,7 +540,7 @@ export function forwardUnhandledError(error: Error) { return } - createUncaughtErrorEntry(error.name, error.message, stackWithOwners(error)) + createUncaughtErrorEntry(error.name, error.message, getErrorStack(error)) } // TODO: this router check is brittle, we need to update based on the current router the user is using diff --git a/packages/next/src/server/app-render/action-handler.ts b/packages/next/src/server/app-render/action-handler.ts index e0ed28cf4599..7d0b4ff0626e 100644 --- a/packages/next/src/server/app-render/action-handler.ts +++ b/packages/next/src/server/app-render/action-handler.ts @@ -57,19 +57,23 @@ import { getServerModuleMap, } from './manifests-singleton' import { isNodeNextRequest, isWebNextRequest } from '../base-http/helpers' +import { normalizeFilePath } from './segment-explorer-path' +import type { ServerActionLogInfo } from '../dev/server-action-logger' import { RedirectStatusCode } from '../../client/components/redirect-status-code' import { synchronizeMutableCookies } from '../async-storage/request-store' import type { TemporaryReferenceSet } from 'react-server-dom-webpack/server' import { workUnitAsyncStorage } from '../app-render/work-unit-async-storage.external' import { InvariantError } from '../../shared/lib/invariant-error' import { executeRevalidates } from '../revalidation-utils' -import { getRequestMeta } from '../request-meta' +import { addRequestMeta, getRequestMeta } from '../request-meta' import { setCacheBustingSearchParam } from '../../client/components/router-reducer/set-cache-busting-search-param' import { ActionDidNotRevalidate, ActionDidRevalidateStaticAndDynamic, } from '../../shared/lib/action-revalidation-kind' +const INLINE_ACTION_PREFIX = '$$RSC_SERVER_ACTION_' + /** * Checks if the app has any server actions defined in any runtime. */ @@ -1080,6 +1084,37 @@ export async function handleAction({ actionId! ] + // Log server action call in development + let logInfo: ServerActionLogInfo | null = null + if (process.env.NODE_ENV === 'development') { + const serverActionsManifest = getServerActionsManifest() + const runtime = process.env.NEXT_RUNTIME === 'edge' ? 'edge' : 'node' + const actionInfo = serverActionsManifest[runtime]?.[actionId!] + + if (actionInfo) { + const isInlineAction = + actionInfo.exportedName?.startsWith(INLINE_ACTION_PREFIX) + + const projectDir = + ctx.renderOpts.dir || + (process.env.NEXT_RUNTIME === 'edge' ? '' : process.cwd()) + const location = normalizeFilePath(projectDir, actionInfo.filename) + + // Format function name for display + let functionName: string + if (isInlineAction) { + functionName = '' + } else if (actionInfo.exportedName === 'default') { + functionName = 'default' + } else { + functionName = actionInfo.exportedName || '' + } + + logInfo = { functionName, args: boundActionArguments, location } + } + } + + const startTime = performance.now() const { actionResult, skipPageRendering } = await executeActionAndPrepareForRender( actionHandler, @@ -1089,6 +1124,16 @@ export async function handleAction({ actionWasForwarded ).finally(() => { addRevalidationHeader(res, { workStore, requestStore }) + if (logInfo) { + // Store server action log info to be logged after the request log + const duration = Math.round(performance.now() - startTime) + addRequestMeta(req, 'devServerActionLog', { + functionName: logInfo.functionName, + args: logInfo.args, + location: logInfo.location, + duration, + }) + } }) // For form actions, we need to continue rendering the page. diff --git a/packages/next/src/server/app-render/encryption.ts b/packages/next/src/server/app-render/encryption.ts index 86852170c899..09b53ae2c0b1 100644 --- a/packages/next/src/server/app-render/encryption.ts +++ b/packages/next/src/server/app-render/encryption.ts @@ -153,11 +153,35 @@ export const encryptActionBoundArgs = React.cache( }) } + const prerenderResumeDataCache = workUnitStore + ? getPrerenderResumeDataCache(workUnitStore) + : null + const renderResumeDataCache = workUnitStore + ? getRenderResumeDataCache(workUnitStore) + : null + // Using Flight to serialize the args into a string. const serialized = await streamToString( renderToReadableStream(args, clientModules, { filterStackFrame, signal: hangingInputAbortSignal, + debugChannel: + // In Cache Components, we want to cache the encrypted result, + // and we use the unencrypted bound args as a cache key. + // In order to do that we need to strip debug info, because it + // contains timing information and thus changes each time we serialize the args. + // We can do this by piping debug info into a debug channel that throws it away. + // + // Note that this can result in dangling debug info references when we decode the bound args, + // but React ignores those as long as no debug channel is passed on the decode side, so it's fine: + // https://github.com/facebook/react/blob/bb8a76c6cc77ea2976d690ea09f5a1b3d9b1792a/packages/react-client/src/ReactFlightClient.js#L1711-L1729 + // https://github.com/facebook/react/blob/bb8a76c6cc77ea2976d690ea09f5a1b3d9b1792a/packages/react-client/src/ReactFlightClient.js#L4005-L4025 + process.env.NODE_ENV === 'development' && + (prerenderResumeDataCache || renderResumeDataCache) + ? { + writable: new WritableStream(), + } + : undefined, onError(err) { if (hangingInputAbortSignal?.aborted) { return @@ -201,8 +225,6 @@ export const encryptActionBoundArgs = React.cache( startReadOnce() - const prerenderResumeDataCache = getPrerenderResumeDataCache(workUnitStore) - const renderResumeDataCache = getRenderResumeDataCache(workUnitStore) const cacheKey = actionId + serialized const cachedEncrypted = @@ -291,6 +313,12 @@ export async function decryptActionBoundArgs( }), { findSourceMapURL, + // NOTE: When we serialized the bound args, we may have used a dummy debug channel to strip debug info. + // In that case, it's important that we also *don't* pass a debug channel here, because that will make + // the Flight Client ignore the dangling references: + // https://github.com/facebook/react/blob/bb8a76c6cc77ea2976d690ea09f5a1b3d9b1792a/packages/react-client/src/ReactFlightClient.js#L1711-L1729 + // https://github.com/facebook/react/blob/bb8a76c6cc77ea2976d690ea09f5a1b3d9b1792a/packages/react-client/src/ReactFlightClient.js#L4005-L4025 + debugChannel: undefined, serverConsumerManifest: { // moduleLoading must be null because we don't want to trigger preloads of ClientReferences // to be added to the current execution. Instead, we'll wait for any ClientReference diff --git a/packages/next/src/server/app-render/segment-explorer-path.ts b/packages/next/src/server/app-render/segment-explorer-path.ts index b0943316aa11..ab6cfe89569b 100644 --- a/packages/next/src/server/app-render/segment-explorer-path.ts +++ b/packages/next/src/server/app-render/segment-explorer-path.ts @@ -5,27 +5,62 @@ export const BUILTIN_PREFIX = '__next_builtin__' const nextInternalPrefixRegex = /^(.*[\\/])?next[\\/]dist[\\/]client[\\/]components[\\/]builtin[\\/]/ -export function normalizeConventionFilePath( +/** + * Normalize a file path to be relative to the project directory. + * Handles Turbopack [project] prefix and monorepo setups. + */ +export function normalizeFilePath( projectDir: string, - conventionPath: string | undefined -) { + filePath: string | undefined +): string { // Turbopack project path is formed as: "/". // When project root is not the working directory, we can extract the relative project root path. // This is mostly used for running Next.js inside a monorepo. const cwd = process.env.NEXT_RUNTIME === 'edge' ? '' : process.cwd() - const relativeProjectRoot = projectDir.replace(cwd, '') + const relativeProjectRoot = projectDir.replace(cwd, '').replace(/^[\\/]/, '') - let relativePath = (conventionPath || '') + let relativePath = (filePath || '') // remove turbopack [project] prefix - .replace(/^\[project\]/, '') - // remove turbopack relative project path, everything after [project] and before the working directory. - .replace(relativeProjectRoot, '') - // remove the project root from the path + .replace(/^\[project\][\\/]?/, '') + // remove the project root from the path (absolute) .replace(projectDir, '') - // remove cwd prefix + // remove cwd prefix (absolute) .replace(cwd, '') + // normalize path separators and remove leading slash + .replace(/\\/g, '/') + .replace(/^\//, '') + + // remove relative project path prefix (e.g., "test/e2e/app-dir/actions/") + if (relativeProjectRoot && relativePath.startsWith(relativeProjectRoot)) { + relativePath = relativePath + .slice(relativeProjectRoot.length) + .replace(/^\//, '') + } + + // Handle case where filename is relative to a parent of projectDir + // (e.g., in tests where filename is "test/tmp/next-test-XXX/app/page.js" + // but projectDir is the test temp directory) + if (relativePath.includes('/')) { + const projectDirName = projectDir.split(/[\\/]/).pop() || '' + if (projectDirName) { + const projectDirWithSlash = projectDirName + '/' + const idx = relativePath.indexOf(projectDirWithSlash) + if (idx >= 0) { + relativePath = relativePath.slice(idx + projectDirWithSlash.length) + } + } + } + + return relativePath +} + +export function normalizeConventionFilePath( + projectDir: string, + conventionPath: string | undefined +) { + let relativePath = normalizeFilePath(projectDir, conventionPath) // remove /(src/)?app/ dir prefix - .replace(/^([\\/])*(src[\\/])?app[\\/]/, '') + .replace(/^(src\/)?app\//, '') // If it's internal file only keep the filename, strip nextjs internal prefix if (nextInternalPrefixRegex.test(relativePath)) { @@ -34,7 +69,7 @@ export function normalizeConventionFilePath( relativePath = `${BUILTIN_PREFIX}${relativePath}` } - return relativePath.replace(/\\/g, '/') + return relativePath } // if a filepath is a builtin file. e.g. diff --git a/packages/next/src/server/base-server.ts b/packages/next/src/server/base-server.ts index 28bc5cd18455..a94d1f4401fb 100644 --- a/packages/next/src/server/base-server.ts +++ b/packages/next/src/server/base-server.ts @@ -376,7 +376,6 @@ export default abstract class Server< generateEtags: boolean poweredByHeader: boolean cacheControl: CacheControl | undefined - cdnCacheControlHeader?: string } ): Promise @@ -565,8 +564,6 @@ export default abstract class Server< dynamicOnHover: this.nextConfig.experimental.dynamicOnHover ?? false, inlineCss: this.nextConfig.experimental.inlineCss ?? false, authInterrupts: !!this.nextConfig.experimental.authInterrupts, - cdnCacheControlHeader: - this.nextConfig.experimental.cdnCacheControlHeader, maxPostponedStateSizeBytes: parseMaxPostponedStateSize( this.nextConfig.experimental.maxPostponedStateSize ), @@ -1800,8 +1797,6 @@ export default abstract class Server< generateEtags, poweredByHeader, cacheControl, - cdnCacheControlHeader: - this.nextConfig.experimental.cdnCacheControlHeader, }) res.statusCode = originalStatus } diff --git a/packages/next/src/server/config-schema.ts b/packages/next/src/server/config-schema.ts index 265a38199358..43d0eb7619f0 100644 --- a/packages/next/src/server/config-schema.ts +++ b/packages/next/src/server/config-schema.ts @@ -129,6 +129,7 @@ const zTurbopackCondition: zod.ZodType = z.union([ z.strictObject({ path: z.union([z.string(), z.instanceof(RegExp)]).optional(), content: z.instanceof(RegExp).optional(), + query: z.union([z.string(), z.instanceof(RegExp)]).optional(), }), ]) @@ -192,7 +193,6 @@ export const experimentalSchema = { memoryBasedWorkersCount: z.boolean().optional(), craCompat: z.boolean().optional(), caseSensitiveRoutes: z.boolean().optional(), - cdnCacheControlHeader: z.string().optional(), clientParamParsingOrigins: z.array(z.string()).optional(), dynamicOnHover: z.boolean().optional(), disableOptimizedLoading: z.boolean().optional(), @@ -308,7 +308,6 @@ export const experimentalSchema = { turbopackClientSideNestedAsyncChunking: z.boolean().optional(), turbopackServerSideNestedAsyncChunking: z.boolean().optional(), turbopackImportTypeBytes: z.boolean().optional(), - turbopackUseSystemTlsCerts: z.boolean().optional(), turbopackUseBuiltinBabel: z.boolean().optional(), turbopackUseBuiltinSass: z.boolean().optional(), turbopackModuleIds: z.enum(['named', 'deterministic']).optional(), @@ -342,7 +341,9 @@ export const experimentalSchema = { browserDebugInfoInTerminal: z .union([ z.boolean(), + z.enum(['error', 'warn', 'verbose']), z.object({ + level: z.enum(['error', 'warn', 'verbose']).optional(), depthLimit: z.number().int().positive().optional(), edgeLimit: z.number().int().positive().optional(), showSourceLocation: z.boolean().optional(), diff --git a/packages/next/src/server/config-shared.ts b/packages/next/src/server/config-shared.ts index dad1aeae61c5..5da5e5206dcd 100644 --- a/packages/next/src/server/config-shared.ts +++ b/packages/next/src/server/config-shared.ts @@ -118,6 +118,7 @@ export type TurbopackRuleCondition = | { path?: string | RegExp content?: RegExp + query?: string | RegExp } export type TurbopackRuleConfigItem = { @@ -279,12 +280,6 @@ export interface ExperimentalConfig { prerenderEarlyExit?: boolean linkNoTouchStart?: boolean caseSensitiveRoutes?: boolean - /** - * Custom header name to use for CDN cache control instead of the default - * 'CDN-Cache-Control'. This can be used to target specific CDN providers - * that do not support `CDN-Cache-Control` and have their own custom header. - */ - cdnCacheControlHeader?: string /** * The origins that are allowed to write the rewritten headers when * performing a non-relative rewrite. When undefined, no non-relative @@ -485,31 +480,6 @@ export interface ExperimentalConfig { */ turbopackInferModuleSideEffects?: boolean - /** - * Use the system-provided CA roots instead of bundled CA roots for external HTTPS requests - * made by Turbopack. Currently this is only used for fetching data from Google Fonts. - * - * This may be useful in cases where you or an employer are MITMing traffic. - * - * This option is experimental because: - * - This may cause small performance problems, as it uses [`rustls-native-certs`]( - * https://github.com/rustls/rustls-native-certs). - * - In the future, this may become the default, and this option may be eliminated, once - * is resolved. - * - * Users who need to configure this behavior system-wide can override the project - * configuration using the `NEXT_TURBOPACK_EXPERIMENTAL_USE_SYSTEM_TLS_CERTS=1` environment - * variable. - * - * This option is ignored on Windows on ARM, where the native TLS implementation is always - * used. - * - * If you need to set a proxy, Turbopack [respects the common `HTTP_PROXY` and `HTTPS_PROXY` - * environment variable convention](https://docs.rs/reqwest/latest/reqwest/#proxies). HTTP - * proxies are supported, SOCKS proxies are not currently supported. - */ - turbopackUseSystemTlsCerts?: boolean - /** * Set this to `false` to disable the automatic configuration of the babel loader when a Babel * configuration file is present. This option is enabled by default. @@ -788,11 +758,27 @@ export interface ExperimentalConfig { globalNotFound?: boolean /** - * Enable debug information to be forwarded from browser to dev server stdout/stderr + * Enable debug information to be forwarded from browser to dev server stdout/stderr. + * + * - `'warn'` (default): Forward warnings and errors to terminal + * - `'error'`: Forward only errors to terminal + * - `'verbose'`: Forward all browser console output to terminal + * - `true`: Same as 'verbose' - forward all browser console output to terminal + * - `false`: Disable browser log forwarding to terminal + * - Object: Enable with custom configuration */ browserDebugInfoInTerminal?: | boolean + | 'error' + | 'warn' + | 'verbose' | { + /** + * Minimum log level to show in terminal. + * @default 'verbose' (for object config, to preserve backward compatibility) + */ + level?: 'error' | 'warn' | 'verbose' + /** * Option to limit stringification at a specific nesting depth when logging circular objects. * @default 5 @@ -1533,7 +1519,6 @@ export const defaultConfig = Object.freeze({ serverMinification: true, linkNoTouchStart: false, caseSensitiveRoutes: false, - cdnCacheControlHeader: undefined, clientParamParsingOrigins: undefined, dynamicOnHover: false, preloadEntriesOnStart: true, @@ -1602,7 +1587,7 @@ export const defaultConfig = Object.freeze({ useCache: undefined, slowModuleDetection: undefined, globalNotFound: false, - browserDebugInfoInTerminal: false, + browserDebugInfoInTerminal: 'warn', lockDistDir: true, isolatedDevBuild: true, proxyClientMaxBodySize: 10_485_760, // 10MB @@ -1683,7 +1668,6 @@ export interface NextConfigRuntime { | 'clientParamParsingOrigins' | 'adapterPath' | 'allowedRevalidateHeaderKeys' - | 'cdnCacheControlHeader' | 'fetchCacheKeyPrefix' | 'isrFlushToDisk' | 'optimizeCss' @@ -1740,7 +1724,6 @@ export function getNextConfigRuntime( clientParamParsingOrigins: ex.clientParamParsingOrigins, adapterPath: ex.adapterPath, allowedRevalidateHeaderKeys: ex.allowedRevalidateHeaderKeys, - cdnCacheControlHeader: ex.cdnCacheControlHeader, fetchCacheKeyPrefix: ex.fetchCacheKeyPrefix, isrFlushToDisk: ex.isrFlushToDisk, optimizeCss: ex.optimizeCss, diff --git a/packages/next/src/server/dev/browser-logs/receive-logs.ts b/packages/next/src/server/dev/browser-logs/receive-logs.ts index 71e7d40c121a..2eebff31f89a 100644 --- a/packages/next/src/server/dev/browser-logs/receive-logs.ts +++ b/packages/next/src/server/dev/browser-logs/receive-logs.ts @@ -416,7 +416,7 @@ async function handleDefaultConsole( browserPrefix: string, ctx: MappingContext, distDir: string, - config: boolean | { logDepth?: number; showSourceLocation?: boolean }, + config: BrowserLogConfig, isServerLog: boolean ) { const consoleArgs = await prepareConsoleArgs(entry, ctx, distDir) @@ -445,11 +445,77 @@ async function handleDefaultConsole( } } +type LogLevel = 'error' | 'warn' | 'verbose' + +type BrowserLogConfig = + | boolean + | LogLevel + | { level?: LogLevel; showSourceLocation?: boolean } + +// Log levels from most severe to least severe +// Lower index = more severe +const LOG_LEVEL_PRIORITY: Record = { + error: 0, + warn: 1, + verbose: 2, +} + +// Map console methods to log levels +const METHOD_TO_LEVEL: Record = { + error: 'error', + warn: 'warn', + info: 'verbose', + log: 'verbose', + debug: 'verbose', + table: 'verbose', + trace: 'verbose', + dir: 'verbose', + dirxml: 'verbose', + assert: 'error', + group: 'verbose', + groupCollapsed: 'verbose', + groupEnd: 'verbose', +} + +function shouldShowEntry( + entry: ServerLogEntry, + config: BrowserLogConfig +): boolean { + // If config is false, don't show any entries + if (config === false) { + return false + } + + // Determine the effective minimum log level + const minLevel: LogLevel = + typeof config === 'string' + ? config + : config === true + ? 'verbose' // true means show everything + : typeof config === 'object' + ? (config.level ?? 'verbose') // object config defaults to verbose for backward compatibility + : 'warn' // default for new installations + + const minPriority = LOG_LEVEL_PRIORITY[minLevel] + + // formatted-error and any-logged-error are always treated as errors + if (entry.kind === 'formatted-error' || entry.kind === 'any-logged-error') { + return LOG_LEVEL_PRIORITY['error'] <= minPriority + } + + if (entry.kind === 'console') { + const entryLevel = METHOD_TO_LEVEL[entry.method] || 'log' + return LOG_LEVEL_PRIORITY[entryLevel] <= minPriority + } + + return false +} + export async function handleLog( entries: ServerLogEntry[], ctx: MappingContext, distDir: string, - config: boolean | { logDepth?: number; showSourceLocation?: boolean } + config: BrowserLogConfig ): Promise { // Determine the source based on the context const isServerLog = ctx.isServer || ctx.isEdgeServer @@ -457,6 +523,10 @@ export async function handleLog( const fileLogger = getFileLogger() for (const entry of entries) { + // Filter entries based on config mode + if (!shouldShowEntry(entry, config)) { + continue + } try { switch (entry.kind) { case 'console': { @@ -596,7 +666,7 @@ export async function receiveBrowserLogsWebpack(opts: { edgeServerStats: () => any rootDirectory: string distDir: string - config: boolean | { logDepth?: number; showSourceLocation?: boolean } + config: BrowserLogConfig }): Promise { const { entries, @@ -634,7 +704,7 @@ export async function receiveBrowserLogsTurbopack(opts: { project: Project projectPath: string distDir: string - config: boolean | { logDepth?: number; showSourceLocation?: boolean } + config: BrowserLogConfig }): Promise { const { entries, router, sourceType, project, projectPath, distDir } = opts diff --git a/packages/next/src/server/dev/browser-logs/source-map.ts b/packages/next/src/server/dev/browser-logs/source-map.ts index ea1f71352f29..6804600bf106 100644 --- a/packages/next/src/server/dev/browser-logs/source-map.ts +++ b/packages/next/src/server/dev/browser-logs/source-map.ts @@ -261,7 +261,12 @@ export const withLocation = async ( }, ctx: MappingContext, distDir: string, - config: boolean | { logDepth?: number; showSourceLocation?: boolean } + config: + | boolean + | 'error' + | 'warn' + | 'verbose' + | { level?: 'error' | 'warn' | 'verbose'; showSourceLocation?: boolean } ) => { if (typeof config === 'object' && config.showSourceLocation === false) { return original diff --git a/packages/next/src/server/dev/log-requests.ts b/packages/next/src/server/dev/log-requests.ts index 9aa318ae7de8..1761c2955e2e 100644 --- a/packages/next/src/server/dev/log-requests.ts +++ b/packages/next/src/server/dev/log-requests.ts @@ -13,7 +13,8 @@ import { stripNextRscUnionQuery } from '../../lib/url' import type { FetchMetric } from '../base-http' import type { NodeNextRequest, NodeNextResponse } from '../base-http/node' import type { LoggingConfig } from '../config-shared' -import { getRequestMeta } from '../request-meta' +import { getRequestMeta, removeRequestMeta } from '../request-meta' +import { formatArgs } from './server-action-logger' /** * Returns true if the incoming request should be ignored for logging. @@ -61,6 +62,16 @@ export function logRequests( devRequestTimingInternalsEnd, devGenerateStaticParamsDuration ) + + // Log server action after the request log + const serverActionLog = getRequestMeta(request, 'devServerActionLog') + if (serverActionLog) { + const argsStr = formatArgs(serverActionLog.args) + process.stdout.write( + ` └─ ƒ ${serverActionLog.functionName}(${argsStr}) in ${serverActionLog.duration}ms ${dim(serverActionLog.location)}\n` + ) + removeRequestMeta(request, 'devServerActionLog') + } } if (request.fetchMetrics) { diff --git a/packages/next/src/server/dev/server-action-logger.ts b/packages/next/src/server/dev/server-action-logger.ts new file mode 100644 index 000000000000..2f581e0f3bab --- /dev/null +++ b/packages/next/src/server/dev/server-action-logger.ts @@ -0,0 +1,38 @@ +import { configure } from 'next/dist/compiled/safe-stable-stringify' + +// Configure stringify with reasonable limits for action logging +const stringify = configure({ + maximumDepth: 2, + maximumBreadth: 3, +}) + +/** + * Format a single argument for display in server action logs. + */ +function formatArg(arg: unknown): string { + try { + return stringify(arg) ?? String(arg) + } catch { + // String(arg) can throw for temporary client references (e.g., class instances + // passed from client to server) because accessing .toString() on them throws + // "Cannot access toString on the server" + try { + return String(arg) + } catch { + return '[unserializable]' + } + } +} + +/** + * Format arguments array to a string for display + */ +export function formatArgs(args: unknown[]): string { + return args.map((a) => formatArg(a)).join(', ') +} + +export interface ServerActionLogInfo { + functionName: string + args: unknown[] + location: string +} diff --git a/packages/next/src/server/lib/cache-control.ts b/packages/next/src/server/lib/cache-control.ts index 61ca2cdfc443..93a8b0873690 100644 --- a/packages/next/src/server/lib/cache-control.ts +++ b/packages/next/src/server/lib/cache-control.ts @@ -1,4 +1,3 @@ -import type { ServerResponse } from 'http' import { CACHE_ONE_YEAR } from '../../lib/constants' /** @@ -15,15 +14,10 @@ export interface CacheControl { expire: number | undefined } -export interface CacheHeaders { - 'Cache-Control': string - cdnCacheControl?: string -} - export function getCacheControlHeader({ revalidate, expire, -}: CacheControl): CacheHeaders { +}: CacheControl): string { const swrHeader = typeof revalidate === 'number' && expire !== undefined && @@ -32,67 +26,10 @@ export function getCacheControlHeader({ : '' if (revalidate === 0) { - return { - 'Cache-Control': - 'private, no-cache, no-store, max-age=0, must-revalidate', - } - } - - // For non-zero revalidation, we want to leverage CDN stale-while-revalidate caching - // semantics without allowing the browser to cache the response. - const maxAge = typeof revalidate === 'number' ? revalidate : CACHE_ONE_YEAR - const cdnCacheControl = `max-age=${maxAge}${swrHeader}` - const cacheControl = `s-maxage=${maxAge}` - - return { - 'Cache-Control': cacheControl, - cdnCacheControl: cdnCacheControl, + return 'private, no-cache, no-store, max-age=0, must-revalidate' + } else if (typeof revalidate === 'number') { + return `s-maxage=${revalidate}${swrHeader}` } -} - -/** - * The default header name used for CDN cache control. - */ -export const DEFAULT_CDN_CACHE_CONTROL_HEADER = 'CDN-Cache-Control' -/** - * Sets cache control headers on a ServerResponse object. - * Use this helper to consistently set Cache-Control and CDN cache control headers. - * - * @param res - The ServerResponse object - * @param cacheControl - The cache control configuration - * @param cdnCacheControlHeader - Custom CDN cache control header name from config, falls back to 'CDN-Cache-Control' if undefined - */ -export function setResponseCacheControlHeaders( - res: ServerResponse, - cacheControl: CacheControl, - cdnCacheControlHeader: string | undefined -): void { - const cacheHeaders = getCacheControlHeader(cacheControl) - const headerName = cdnCacheControlHeader ?? DEFAULT_CDN_CACHE_CONTROL_HEADER - res.setHeader('Cache-Control', cacheHeaders['Cache-Control']) - if (cacheHeaders.cdnCacheControl) { - res.setHeader(headerName, cacheHeaders.cdnCacheControl) - } -} - -/** - * Sets cache control headers on a Headers object (for Web API responses). - * Use this helper to consistently set Cache-Control and CDN cache control headers. - * - * @param headers - The Headers object - * @param cacheControl - The cache control configuration - * @param cdnCacheControlHeader - Custom CDN cache control header name from config, falls back to 'CDN-Cache-Control' if undefined - */ -export function setCacheControlHeaders( - headers: Headers, - cacheControl: CacheControl, - cdnCacheControlHeader: string | undefined -): void { - const cacheHeaders = getCacheControlHeader(cacheControl) - const headerName = cdnCacheControlHeader ?? DEFAULT_CDN_CACHE_CONTROL_HEADER - headers.set('Cache-Control', cacheHeaders['Cache-Control']) - if (cacheHeaders.cdnCacheControl) { - headers.set(headerName, cacheHeaders.cdnCacheControl) - } + return `s-maxage=${CACHE_ONE_YEAR}${swrHeader}` } diff --git a/packages/next/src/server/lib/router-utils/route-types-utils.ts b/packages/next/src/server/lib/router-utils/route-types-utils.ts index 6eb0733b2e6c..c7f6978f40df 100644 --- a/packages/next/src/server/lib/router-utils/route-types-utils.ts +++ b/packages/next/src/server/lib/router-utils/route-types-utils.ts @@ -395,3 +395,51 @@ export async function writeValidatorFile( : generateValidatorFile(manifest) ) } + +/** + * Writes the entry file at {distDirRoot}/types/routes.d.ts that re-exports + * from the actual type files. This ensures next-env.d.ts has a consistent + * import path regardless of isolatedDevBuild setting. + * + * @param entryFilePath - Path to the entry file (e.g., .next/types/routes.d.ts) + * @param actualTypesDir - Path to the actual types directory (e.g., .next/types or .next/dev/types) + * @param options - Configuration options for what to include + */ +export async function writeRouteTypesEntryFile( + entryFilePath: string, + actualTypesDir: string, + options: { + strictRouteTypes: boolean + typedRoutes: boolean + } +) { + const entryDir = path.dirname(entryFilePath) + + if (!fs.existsSync(entryDir)) { + await fs.promises.mkdir(entryDir, { recursive: true }) + } + + // Calculate relative path from entry file to actual types directory + const relativePath = normalizePathSep(path.relative(entryDir, actualTypesDir)) + const prefix = relativePath === '' ? './' : `./${relativePath}/` + + const lines: string[] = [ + '// This is an auto-generated entry file that re-exports route types.', + '// Do not edit this file directly.', + '', + `export type * from "${prefix}route-types.d.ts";`, + ] + + if (options.strictRouteTypes) { + lines.push(`import "${prefix}cache-life.d.ts";`) + lines.push(`import "${prefix}validator.ts";`) + + if (options.typedRoutes) { + lines.push(`import "${prefix}link.d.ts";`) + } + } + + lines.push('') // trailing newline + + await fs.promises.writeFile(entryFilePath, lines.join('\n')) +} diff --git a/packages/next/src/server/lib/router-utils/setup-dev-bundler.ts b/packages/next/src/server/lib/router-utils/setup-dev-bundler.ts index e4b2ff330546..5ad4b198caca 100644 --- a/packages/next/src/server/lib/router-utils/setup-dev-bundler.ts +++ b/packages/next/src/server/lib/router-utils/setup-dev-bundler.ts @@ -88,6 +88,7 @@ import { createRouteTypesManifest, writeRouteTypesManifest, writeValidatorFile, + writeRouteTypesEntryFile, } from './route-types-utils' import { writeCacheLifeTypes } from './cache-life-type-utils' import { isParallelRouteSegment } from '../../../shared/lib/segment' @@ -146,10 +147,10 @@ async function verifyTypeScript(opts: SetupOpts) { const verifyResult = await verifyTypeScriptSetup({ dir: opts.dir, distDir: opts.nextConfig.distDir, + distDirRoot: opts.nextConfig.distDirRoot, strictRouteTypes: Boolean(opts.nextConfig.experimental.strictRouteTypes), typeCheckPreflight: false, tsconfigPath: opts.nextConfig.typescript.tsconfigPath, - typedRoutes: Boolean(opts.nextConfig.typedRoutes), disableStaticImages: opts.nextConfig.images.disableStaticImages, hasAppDir: !!opts.appDir, hasPagesDir: !!opts.pagesDir, @@ -267,10 +268,22 @@ async function startWatcher( pageApiRoutes: new Set(), filePathToRoute: new Map(), }, - path.join(distTypesDir, 'routes.d.ts'), + path.join(distTypesDir, 'route-types.d.ts'), opts.nextConfig ) + // Write the entry file at {distDirRoot}/types/routes.d.ts for initial state + const initialEntryFilePath = path.join( + opts.dir, + opts.nextConfig.distDirRoot, + 'types', + 'routes.d.ts' + ) + await writeRouteTypesEntryFile(initialEntryFilePath, distTypesDir, { + strictRouteTypes: Boolean(nextConfig.experimental.strictRouteTypes), + typedRoutes: Boolean(nextConfig.typedRoutes), + }) + const routesManifestPath = path.join(distDir, ROUTES_MANIFEST) const routesManifest: DevRoutesManifest = { version: 3, @@ -379,7 +392,9 @@ async function startWatcher( let previousClientRouterFilters: any let previousConflictingPagePaths: Set = new Set() - const routeTypesFilePath = path.join(distDir, 'types', 'routes.d.ts') + // Actual type files go to route-types.d.ts (not routes.d.ts) + // routes.d.ts is reserved for the entry file + const routeTypesFilePath = path.join(distDir, 'types', 'route-types.d.ts') const validatorFilePath = path.join(distDir, 'types', 'validator.ts') let initialWatchTime = performance.now() + performance.timeOrigin @@ -1202,6 +1217,19 @@ async function startWatcher( // Generate cache-life types if cacheLife config exists const cacheLifeFilePath = path.join(distTypesDir, 'cache-life.d.ts') writeCacheLifeTypes(opts.nextConfig.cacheLife, cacheLifeFilePath) + + // Write the entry file at {distDirRoot}/types/routes.d.ts + // This ensures next-env.d.ts has a consistent import path + const entryFilePath = path.join( + opts.dir, + opts.nextConfig.distDirRoot, + 'types', + 'routes.d.ts' + ) + await writeRouteTypesEntryFile(entryFilePath, distTypesDir, { + strictRouteTypes: Boolean(nextConfig.experimental.strictRouteTypes), + typedRoutes: Boolean(nextConfig.typedRoutes), + }) } if (!resolved) { diff --git a/packages/next/src/server/lib/start-server.ts b/packages/next/src/server/lib/start-server.ts index 00b18ff42980..47e971d4c71c 100644 --- a/packages/next/src/server/lib/start-server.ts +++ b/packages/next/src/server/lib/start-server.ts @@ -2,9 +2,6 @@ import './cpu-profile' import { getNetworkHost } from '../../lib/get-network-host' -if (performance.getEntriesByName('next-start').length === 0) { - performance.mark('next-start') -} import '../next' import '../require-hook' @@ -370,10 +367,11 @@ export async function startServer( }) // Calculate and log "Ready in X" before loading config - // so it reflects actual framework startup time + // so it reflects actual framework startup time. + // NEXT_PRIVATE_START_TIME is set by bin/next.ts or cli/next-start.ts. const startTime = parseInt(process.env.NEXT_PRIVATE_START_TIME || '0', 10) const endTime = Date.now() - const startServerProcessDurationMs = endTime - startTime + const startServerProcessDurationMs = startTime ? endTime - startTime : 0 const formattedStartDuration = durationToString( startServerProcessDurationMs / 1000 diff --git a/packages/next/src/server/load-components.ts b/packages/next/src/server/load-components.ts index b9ef663a461c..093c6d67eb11 100644 --- a/packages/next/src/server/load-components.ts +++ b/packages/next/src/server/load-components.ts @@ -308,7 +308,9 @@ async function loadComponentsImpl< ComponentMod return { + // @ts-expect-error this is indeed `{} || AppType` and not always `AppType` App, + // @ts-expect-error this is indeed `{} || DocumentType` and not always `DocumentType` Document, Component, buildManifest, diff --git a/packages/next/src/server/next-server.ts b/packages/next/src/server/next-server.ts index 1f48abccfb56..b5269e22a829 100644 --- a/packages/next/src/server/next-server.ts +++ b/packages/next/src/server/next-server.ts @@ -609,7 +609,6 @@ export default class NextNodeServer extends BaseServer< generateEtags: boolean poweredByHeader: boolean cacheControl: CacheControl | undefined - cdnCacheControlHeader?: string } ): Promise { return sendRenderResult({ @@ -619,7 +618,6 @@ export default class NextNodeServer extends BaseServer< generateEtags: options.generateEtags, poweredByHeader: options.poweredByHeader, cacheControl: options.cacheControl, - cdnCacheControlHeader: options.cdnCacheControlHeader, }) } diff --git a/packages/next/src/server/node-environment-extensions/fast-set-immediate.external.ts b/packages/next/src/server/node-environment-extensions/fast-set-immediate.external.ts index 2d906004638a..2e11d16e6f71 100644 --- a/packages/next/src/server/node-environment-extensions/fast-set-immediate.external.ts +++ b/packages/next/src/server/node-environment-extensions/fast-set-immediate.external.ts @@ -22,6 +22,9 @@ let currentExecution: Execution | null = null const originalSetImmediate = globalThis.setImmediate const originalClearImmediate = globalThis.clearImmediate const originalNextTick = process.nextTick +const originalSetImmediatePromisify: (typeof setImmediate)['__promisify__'] = + // @ts-expect-error: the types for `promisify.custom` are strange + originalSetImmediate[promisify.custom] export { originalSetImmediate as unpatchedSetImmediate } @@ -621,10 +624,7 @@ function patchedSetImmediatePromise( options?: import('node:timers').TimerOptions ): Promise { if (currentExecution === null) { - const originalPromisify: (typeof setImmediate)['__promisify__'] = - // @ts-expect-error: the types for `promisify.custom` are strange - originalSetImmediate[promisify.custom] - return originalPromisify(value, options) + return originalSetImmediatePromisify(value, options) } return new Promise((resolve, reject) => { diff --git a/packages/next/src/server/render.tsx b/packages/next/src/server/render.tsx index c7a484873fbd..f867c3dc63bb 100644 --- a/packages/next/src/server/render.tsx +++ b/packages/next/src/server/render.tsx @@ -101,7 +101,7 @@ import { import { getTracer } from './lib/trace/tracer' import { RenderSpan } from './lib/trace/constants' import { ReflectAdapter } from './web/spec-extension/adapters/reflect' -import { setResponseCacheControlHeaders } from './lib/cache-control' +import { getCacheControlHeader } from './lib/cache-control' import { getErrorSource } from '../shared/lib/error-source' import type { DeepReadonly } from '../shared/lib/deep-readonly' import type { PagesDevOverlayBridgeType } from '../next-devtools/userspace/pages/pages-dev-overlay-setup' @@ -287,7 +287,6 @@ export type RenderOptsPartial = { expireTime?: number experimental: { clientTraceMetadata?: string[] - cdnCacheControlHeader?: string } } @@ -556,10 +555,9 @@ export async function renderToHTMLImpl( // ensure we set cache header so it's not rendered on-demand // every request if (isAutoExport && !dev && isExperimentalCompile) { - setResponseCacheControlHeaders( - res, - { revalidate: false, expire: expireTime }, - renderOpts.experimental.cdnCacheControlHeader + res.setHeader( + 'Cache-Control', + getCacheControlHeader({ revalidate: false, expire: expireTime }) ) isAutoExport = false } diff --git a/packages/next/src/server/request-meta.ts b/packages/next/src/server/request-meta.ts index 72d2d883bcf7..c60b09c1068f 100644 --- a/packages/next/src/server/request-meta.ts +++ b/packages/next/src/server/request-meta.ts @@ -286,6 +286,16 @@ export interface RequestMeta { * DEV only: The duration of getStaticPaths/generateStaticParams in process.hrtime.bigint() */ devGenerateStaticParamsDuration?: bigint + + /** + * DEV only: Server action log info to be logged after the request log + */ + devServerActionLog?: { + functionName: string + args: unknown[] + location: string + duration: number + } } /** diff --git a/packages/next/src/server/route-modules/pages/pages-handler.ts b/packages/next/src/server/route-modules/pages/pages-handler.ts index f6a81000e386..0b69e2160bfb 100644 --- a/packages/next/src/server/route-modules/pages/pages-handler.ts +++ b/packages/next/src/server/route-modules/pages/pages-handler.ts @@ -22,7 +22,7 @@ import { } from '../../response-cache' import { - setResponseCacheControlHeaders, + getCacheControlHeader, type CacheControl, } from '../../lib/cache-control' import { normalizeRepeatedSlashes } from '../../../shared/lib/utils' @@ -616,11 +616,7 @@ export const getHandler = ({ // If cache control is already set on the response we don't // override it to allow users to customize it via next.config if (cacheControl && !res.getHeader('Cache-Control')) { - setResponseCacheControlHeaders( - res, - cacheControl, - nextConfig.experimental.cdnCacheControlHeader - ) + res.setHeader('Cache-Control', getCacheControlHeader(cacheControl)) } // notFound: true case @@ -736,7 +732,6 @@ export const getHandler = ({ generateEtags: nextConfig.generateEtags, poweredByHeader: nextConfig.poweredByHeader, cacheControl: routeModule.isDev ? undefined : cacheControl, - cdnCacheControlHeader: nextConfig.experimental.cdnCacheControlHeader, }) } diff --git a/packages/next/src/server/send-payload.ts b/packages/next/src/server/send-payload.ts index 9266bc110c94..731b69b21b66 100644 --- a/packages/next/src/server/send-payload.ts +++ b/packages/next/src/server/send-payload.ts @@ -5,7 +5,7 @@ import type { CacheControl } from './lib/cache-control' import { isResSent } from '../shared/lib/utils' import { generateETag } from './lib/etag' import fresh from 'next/dist/compiled/fresh' -import { setResponseCacheControlHeaders } from './lib/cache-control' +import { getCacheControlHeader } from './lib/cache-control' import { HTML_CONTENT_TYPE_HEADER } from '../lib/constants' export function sendEtagResponse( @@ -39,7 +39,6 @@ export async function sendRenderResult({ generateEtags, poweredByHeader, cacheControl, - cdnCacheControlHeader, }: { req: IncomingMessage res: ServerResponse @@ -47,7 +46,6 @@ export async function sendRenderResult({ generateEtags: boolean poweredByHeader: boolean cacheControl: CacheControl | undefined - cdnCacheControlHeader?: string }): Promise { if (isResSent(res)) { return @@ -60,7 +58,7 @@ export async function sendRenderResult({ // If cache control is already set on the response we don't // override it to allow users to customize it via next.config if (cacheControl && !res.getHeader('Cache-Control')) { - setResponseCacheControlHeaders(res, cacheControl, cdnCacheControlHeader) + res.setHeader('Cache-Control', getCacheControlHeader(cacheControl)) } const payload = result.isDynamic ? null : result.toUnchunkedString() diff --git a/packages/next/src/shared/lib/app-router-types.ts b/packages/next/src/shared/lib/app-router-types.ts index 9449c4f43829..dd46fbbfd0e9 100644 --- a/packages/next/src/shared/lib/app-router-types.ts +++ b/packages/next/src/shared/lib/app-router-types.ts @@ -14,8 +14,6 @@ export type LoadingModuleData = /** viewport metadata node */ export type HeadData = React.ReactNode -export type ChildSegmentMap = Map - /** * Cache node used in app-router / layout-router. */ @@ -48,14 +46,7 @@ export type CacheNode = { head: HeadData - parallelRoutes: Map - - /** - * The timestamp of the navigation that last updated the CacheNode's data. If - * a CacheNode is reused from a previous navigation, this value is not - * updated. Used to track the staleness of the data. - */ - navigatedAt: number + slots: Record | null } export type DynamicParamTypes = diff --git a/packages/next/src/shared/lib/image-config.ts b/packages/next/src/shared/lib/image-config.ts index 5bcd3f37b47b..32e86c2521f8 100644 --- a/packages/next/src/shared/lib/image-config.ts +++ b/packages/next/src/shared/lib/image-config.ts @@ -157,7 +157,7 @@ export const imageConfigDefault: ImageConfigComplete = { minimumCacheTTL: 14400, // 4 hours formats: ['image/webp'], maximumRedirects: 3, - maximumResponseBody: 300_000_000, // 300MB + maximumResponseBody: 50_000_000, // 50 MB dangerouslyAllowLocalIP: false, dangerouslyAllowSVG: false, contentSecurityPolicy: `script-src 'none'; frame-src 'none'; sandbox;`, diff --git a/packages/react-refresh-utils/package.json b/packages/react-refresh-utils/package.json index 5755597054dd..32e1bf95e224 100644 --- a/packages/react-refresh-utils/package.json +++ b/packages/react-refresh-utils/package.json @@ -1,6 +1,6 @@ { "name": "@next/react-refresh-utils", - "version": "16.1.1-canary.22", + "version": "16.1.1-canary.31", "description": "An experimental package providing utilities for React Refresh.", "repository": { "url": "vercel/next.js", diff --git a/packages/third-parties/package.json b/packages/third-parties/package.json index d931eafc5845..081091cf2349 100644 --- a/packages/third-parties/package.json +++ b/packages/third-parties/package.json @@ -1,6 +1,6 @@ { "name": "@next/third-parties", - "version": "16.1.1-canary.22", + "version": "16.1.1-canary.31", "repository": { "url": "vercel/next.js", "directory": "packages/third-parties" @@ -26,7 +26,7 @@ "third-party-capital": "1.0.20" }, "devDependencies": { - "next": "16.1.1-canary.22", + "next": "16.1.1-canary.31", "outdent": "0.8.0", "prettier": "2.5.1", "typescript": "5.9.2" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b71effca9563..92ec42935cd4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -17,10 +17,10 @@ overrides: '@types/react-dom': 19.2.1 '@types/retry': 0.12.0 jest-snapshot: 30.0.0-alpha.6 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 - react-is: 19.3.0-canary-65eec428-20251218 - scheduler: 0.28.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 + react-is: 19.3.0-canary-bef88f7c-20260116 + scheduler: 0.28.0-canary-bef88f7c-20260116 packageExtensionsChecksum: 2c0398c5f3e8ad5816061c5823d227e9 @@ -77,7 +77,7 @@ importers: version: 11.11.0 '@emotion/react': specifier: 11.11.1 - version: 11.11.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) + version: 11.11.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) '@eslint/compat': specifier: 1.4.0 version: 1.4.0(eslint@9.37.0(jiti@2.5.1)) @@ -98,7 +98,7 @@ importers: version: 2.2.1(webpack@5.98.0(@swc/core@1.11.24(@swc/helpers@0.5.15))) '@mdx-js/react': specifier: 2.2.1 - version: 2.2.1(react@19.3.0-canary-65eec428-20251218) + version: 2.2.1(react@19.3.0-canary-bef88f7c-20260116) '@next/bundle-analyzer': specifier: workspace:* version: link:packages/next-bundle-analyzer @@ -161,7 +161,7 @@ importers: version: 6.1.2(@jest/globals@29.7.0)(@types/jest@29.5.5)(jest@29.7.0(@types/node@20.17.6(patch_hash=rvl3vkomen3tospgr67bzubfyu))(babel-plugin-macros@3.1.0)) '@testing-library/react': specifier: ^15.0.5 - version: 15.0.7(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) + version: 15.0.7(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) '@types/busboy': specifier: 1.5.3 version: 1.5.3 @@ -304,8 +304,8 @@ importers: specifier: 7.37.0 version: 7.37.0(eslint@9.37.0(jiti@2.5.1)) eslint-plugin-react-hooks: - specifier: 0.0.0-experimental-65eec428-20251218 - version: 0.0.0-experimental-65eec428-20251218(eslint@9.37.0(jiti@2.5.1)) + specifier: 0.0.0-experimental-bef88f7c-20260116 + version: 0.0.0-experimental-bef88f7c-20260116(eslint@9.37.0(jiti@2.5.1)) event-stream: specifier: 4.0.1 version: 4.0.1 @@ -481,44 +481,44 @@ importers: specifier: 0.3.0 version: 0.3.0 react: - specifier: 19.3.0-canary-65eec428-20251218 - version: 19.3.0-canary-65eec428-20251218 + specifier: 19.3.0-canary-bef88f7c-20260116 + version: 19.3.0-canary-bef88f7c-20260116 react-builtin: - specifier: npm:react@19.3.0-canary-65eec428-20251218 - version: react@19.3.0-canary-65eec428-20251218 + specifier: npm:react@19.3.0-canary-bef88f7c-20260116 + version: react@19.3.0-canary-bef88f7c-20260116 react-dom: - specifier: 19.3.0-canary-65eec428-20251218 - version: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + specifier: 19.3.0-canary-bef88f7c-20260116 + version: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) react-dom-builtin: - specifier: npm:react-dom@19.3.0-canary-65eec428-20251218 - version: react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + specifier: npm:react-dom@19.3.0-canary-bef88f7c-20260116 + version: react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) react-dom-experimental-builtin: - specifier: npm:react-dom@0.0.0-experimental-65eec428-20251218 - version: react-dom@0.0.0-experimental-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + specifier: npm:react-dom@0.0.0-experimental-bef88f7c-20260116 + version: react-dom@0.0.0-experimental-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) react-experimental-builtin: - specifier: npm:react@0.0.0-experimental-65eec428-20251218 - version: react@0.0.0-experimental-65eec428-20251218 + specifier: npm:react@0.0.0-experimental-bef88f7c-20260116 + version: react@0.0.0-experimental-bef88f7c-20260116 react-is-builtin: - specifier: npm:react-is@19.3.0-canary-65eec428-20251218 - version: react-is@19.3.0-canary-65eec428-20251218 + specifier: npm:react-is@19.3.0-canary-bef88f7c-20260116 + version: react-is@19.3.0-canary-bef88f7c-20260116 react-server-dom-turbopack: - specifier: 19.3.0-canary-65eec428-20251218 - version: 19.3.0-canary-65eec428-20251218(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) + specifier: 19.3.0-canary-bef88f7c-20260116 + version: 19.3.0-canary-bef88f7c-20260116(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) react-server-dom-turbopack-experimental: - specifier: npm:react-server-dom-turbopack@0.0.0-experimental-65eec428-20251218 - version: react-server-dom-turbopack@0.0.0-experimental-65eec428-20251218(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) + specifier: npm:react-server-dom-turbopack@0.0.0-experimental-bef88f7c-20260116 + version: react-server-dom-turbopack@0.0.0-experimental-bef88f7c-20260116(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) react-server-dom-webpack: - specifier: 19.3.0-canary-65eec428-20251218 - version: 19.3.0-canary-65eec428-20251218(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)(webpack@5.98.0(@swc/core@1.11.24(@swc/helpers@0.5.15))) + specifier: 19.3.0-canary-bef88f7c-20260116 + version: 19.3.0-canary-bef88f7c-20260116(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)(webpack@5.98.0(@swc/core@1.11.24(@swc/helpers@0.5.15))) react-server-dom-webpack-experimental: - specifier: npm:react-server-dom-webpack@0.0.0-experimental-65eec428-20251218 - version: react-server-dom-webpack@0.0.0-experimental-65eec428-20251218(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)(webpack@5.98.0(@swc/core@1.11.24(@swc/helpers@0.5.15))) + specifier: npm:react-server-dom-webpack@0.0.0-experimental-bef88f7c-20260116 + version: react-server-dom-webpack@0.0.0-experimental-bef88f7c-20260116(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)(webpack@5.98.0(@swc/core@1.11.24(@swc/helpers@0.5.15))) react-ssr-prepass: specifier: 1.0.8 - version: 1.0.8(react-is@19.3.0-canary-fd524fe0-20251121)(react@19.3.0-canary-65eec428-20251218) + version: 1.0.8(react-is@19.3.0-canary-fd524fe0-20251121)(react@19.3.0-canary-bef88f7c-20260116) react-virtualized: specifier: 9.22.3 - version: 9.22.3(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) + version: 9.22.3(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) relay-compiler: specifier: 13.0.2 version: 13.0.2 @@ -541,11 +541,11 @@ importers: specifier: 0.15.2 version: 0.15.2 scheduler-builtin: - specifier: npm:scheduler@0.28.0-canary-65eec428-20251218 - version: scheduler@0.28.0-canary-65eec428-20251218 + specifier: npm:scheduler@0.28.0-canary-bef88f7c-20260116 + version: scheduler@0.28.0-canary-bef88f7c-20260116 scheduler-experimental-builtin: - specifier: npm:scheduler@0.0.0-experimental-65eec428-20251218 - version: scheduler@0.0.0-experimental-65eec428-20251218 + specifier: npm:scheduler@0.0.0-experimental-bef88f7c-20260116 + version: scheduler@0.0.0-experimental-bef88f7c-20260116 seedrandom: specifier: 3.0.5 version: 3.0.5 @@ -563,13 +563,13 @@ importers: version: 6.0.0 styled-jsx: specifier: 5.1.6 - version: 5.1.6(@babel/core@7.26.10)(babel-plugin-macros@3.1.0)(react@19.3.0-canary-65eec428-20251218) + version: 5.1.6(@babel/core@7.26.10)(babel-plugin-macros@3.1.0)(react@19.3.0-canary-bef88f7c-20260116) styled-jsx-plugin-postcss: specifier: 3.0.2 version: 3.0.2 swr: specifier: ^2.2.4 - version: 2.2.4(react@19.3.0-canary-65eec428-20251218) + version: 2.2.4(react@19.3.0-canary-bef88f7c-20260116) tailwindcss: specifier: 3.2.7 version: 3.2.7(postcss@8.4.31) @@ -623,22 +623,22 @@ importers: dependencies: '@radix-ui/react-dialog': specifier: 1.1.4 - version: 1.1.4(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) + version: 1.1.4(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) '@radix-ui/react-popover': specifier: 1.1.4 - version: 1.1.4(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) + version: 1.1.4(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) '@radix-ui/react-select': specifier: 2.2.6 - version: 2.2.6(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) + version: 2.2.6(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) '@radix-ui/react-slot': specifier: 1.1.1 - version: 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) + version: 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) '@radix-ui/react-toggle-group': specifier: 1.1.1 - version: 1.1.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) + version: 1.1.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) '@radix-ui/react-tooltip': specifier: 1.1.4 - version: 1.1.4(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) + version: 1.1.4(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) autoprefixer: specifier: ^10.4.20 version: 10.4.21(postcss@8.5.3) @@ -650,28 +650,28 @@ importers: version: 2.1.1 cmdk: specifier: 1.0.4 - version: 1.0.4(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) + version: 1.0.4(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) lucide-react: specifier: ^0.554.0 - version: 0.554.0(react@19.3.0-canary-65eec428-20251218) + version: 0.554.0(react@19.3.0-canary-bef88f7c-20260116) next: specifier: 16.0.8 - version: 16.0.8(@babel/core@7.26.10)(@opentelemetry/api@1.6.0)(@playwright/test@1.51.1)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-3fde738-20250918)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)(sass@1.77.8) + version: 16.0.8(@babel/core@7.26.10)(@opentelemetry/api@1.6.0)(@playwright/test@1.51.1)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-3fde738-20250918)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)(sass@1.77.8) next-themes: specifier: ^0.4.6 - version: 0.4.6(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) + version: 0.4.6(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) polished: specifier: ^4.3.1 version: 4.3.1 react: - specifier: 19.3.0-canary-65eec428-20251218 - version: 19.3.0-canary-65eec428-20251218 + specifier: 19.3.0-canary-bef88f7c-20260116 + version: 19.3.0-canary-bef88f7c-20260116 react-dom: - specifier: 19.3.0-canary-65eec428-20251218 - version: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + specifier: 19.3.0-canary-bef88f7c-20260116 + version: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) swr: specifier: ^2.2.4 - version: 2.2.4(react@19.3.0-canary-65eec428-20251218) + version: 2.2.4(react@19.3.0-canary-bef88f7c-20260116) tailwind-merge: specifier: ^2.5.5 version: 2.6.0 @@ -714,22 +714,22 @@ importers: dependencies: fumadocs-core: specifier: 15.7.12 - version: 15.7.12(@types/react@19.2.2)(next@15.5.8(@babel/core@7.26.10)(@opentelemetry/api@1.6.0)(@playwright/test@1.51.1)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-3fde738-20250918)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)(sass@1.77.8))(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) + version: 15.7.12(@types/react@19.2.2)(next@15.5.8(@babel/core@7.26.10)(@opentelemetry/api@1.6.0)(@playwright/test@1.51.1)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-3fde738-20250918)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)(sass@1.77.8))(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) fumadocs-mdx: specifier: 11.10.0 - version: 11.10.0(fumadocs-core@15.7.12(@types/react@19.2.2)(next@15.5.8(@babel/core@7.26.10)(@opentelemetry/api@1.6.0)(@playwright/test@1.51.1)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-3fde738-20250918)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)(sass@1.77.8))(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218))(next@15.5.8(@babel/core@7.26.10)(@opentelemetry/api@1.6.0)(@playwright/test@1.51.1)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-3fde738-20250918)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)(sass@1.77.8))(react@19.3.0-canary-65eec428-20251218) + version: 11.10.0(fumadocs-core@15.7.12(@types/react@19.2.2)(next@15.5.8(@babel/core@7.26.10)(@opentelemetry/api@1.6.0)(@playwright/test@1.51.1)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-3fde738-20250918)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)(sass@1.77.8))(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116))(next@15.5.8(@babel/core@7.26.10)(@opentelemetry/api@1.6.0)(@playwright/test@1.51.1)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-3fde738-20250918)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)(sass@1.77.8))(react@19.3.0-canary-bef88f7c-20260116) fumadocs-ui: specifier: 15.7.12 - version: 15.7.12(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(next@15.5.8(@babel/core@7.26.10)(@opentelemetry/api@1.6.0)(@playwright/test@1.51.1)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-3fde738-20250918)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)(sass@1.77.8))(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)(tailwindcss@4.1.13) + version: 15.7.12(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(next@15.5.8(@babel/core@7.26.10)(@opentelemetry/api@1.6.0)(@playwright/test@1.51.1)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-3fde738-20250918)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)(sass@1.77.8))(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)(tailwindcss@4.1.13) next: specifier: 15.5.8 - version: 15.5.8(@babel/core@7.26.10)(@opentelemetry/api@1.6.0)(@playwright/test@1.51.1)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-3fde738-20250918)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)(sass@1.77.8) + version: 15.5.8(@babel/core@7.26.10)(@opentelemetry/api@1.6.0)(@playwright/test@1.51.1)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-3fde738-20250918)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)(sass@1.77.8) react: - specifier: 19.3.0-canary-65eec428-20251218 - version: 19.3.0-canary-65eec428-20251218 + specifier: 19.3.0-canary-bef88f7c-20260116 + version: 19.3.0-canary-bef88f7c-20260116 react-dom: - specifier: 19.3.0-canary-65eec428-20251218 - version: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + specifier: 19.3.0-canary-bef88f7c-20260116 + version: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) devDependencies: '@eslint/eslintrc': specifier: ^3 @@ -1008,7 +1008,7 @@ importers: packages/eslint-config-next: dependencies: '@next/eslint-plugin-next': - specifier: 16.1.1-canary.22 + specifier: 16.1.1-canary.31 version: link:../eslint-plugin-next eslint: specifier: '>=9.0.0' @@ -1085,7 +1085,7 @@ importers: packages/next: dependencies: '@next/env': - specifier: 16.1.1-canary.22 + specifier: 16.1.1-canary.31 version: link:../next-env '@swc/helpers': specifier: 0.5.15 @@ -1100,17 +1100,17 @@ importers: specifier: 8.4.31 version: 8.4.31 react: - specifier: 19.3.0-canary-65eec428-20251218 - version: 19.3.0-canary-65eec428-20251218 + specifier: 19.3.0-canary-bef88f7c-20260116 + version: 19.3.0-canary-bef88f7c-20260116 react-dom: - specifier: 19.3.0-canary-65eec428-20251218 - version: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + specifier: 19.3.0-canary-bef88f7c-20260116 + version: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) sass: specifier: ^1.3.0 version: 1.77.8 styled-jsx: specifier: 5.1.6 - version: 5.1.6(@babel/core@7.26.10)(babel-plugin-macros@3.1.0)(react@19.3.0-canary-65eec428-20251218) + version: 5.1.6(@babel/core@7.26.10)(babel-plugin-macros@3.1.0)(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: sharp: specifier: ^0.34.5 @@ -1181,7 +1181,7 @@ importers: version: 7.27.0 '@base-ui-components/react': specifier: 1.0.0-beta.2 - version: 1.0.0-beta.2(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) + version: 1.0.0-beta.2(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) '@capsizecss/metrics': specifier: 3.4.0 version: 3.4.0 @@ -1213,19 +1213,19 @@ importers: specifier: 1.2.0 version: 1.2.0 '@next/font': - specifier: 16.1.1-canary.22 + specifier: 16.1.1-canary.31 version: link:../font '@next/polyfill-module': - specifier: 16.1.1-canary.22 + specifier: 16.1.1-canary.31 version: link:../next-polyfill-module '@next/polyfill-nomodule': - specifier: 16.1.1-canary.22 + specifier: 16.1.1-canary.31 version: link:../next-polyfill-nomodule '@next/react-refresh-utils': - specifier: 16.1.1-canary.22 + specifier: 16.1.1-canary.31 version: link:../react-refresh-utils '@next/swc': - specifier: 16.1.1-canary.22 + specifier: 16.1.1-canary.31 version: link:../next-swc '@opentelemetry/api': specifier: 1.6.0 @@ -1250,13 +1250,13 @@ importers: version: 3.0.0(@swc/helpers@0.5.15)(webpack@5.98.0(@swc/core@1.11.24(@swc/helpers@0.5.15))(esbuild@0.25.9)) '@storybook/blocks': specifier: 8.6.0 - version: 8.6.0(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)(storybook@8.6.0(prettier@3.6.2)) + version: 8.6.0(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)(storybook@8.6.0(prettier@3.6.2)) '@storybook/react': specifier: 8.6.0 - version: 8.6.0(@storybook/test@8.6.0(storybook@8.6.0(prettier@3.6.2)))(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)(storybook@8.6.0(prettier@3.6.2))(typescript@5.9.2) + version: 8.6.0(@storybook/test@8.6.0(storybook@8.6.0(prettier@3.6.2)))(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)(storybook@8.6.0(prettier@3.6.2))(typescript@5.9.2) '@storybook/react-webpack5': specifier: 8.6.0 - version: 8.6.0(@rspack/core@1.6.7(@swc/helpers@0.5.15))(@storybook/test@8.6.0(storybook@8.6.0(prettier@3.6.2)))(@swc/core@1.11.24(@swc/helpers@0.5.15))(esbuild@0.25.9)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)(storybook@8.6.0(prettier@3.6.2))(typescript@5.9.2) + version: 8.6.0(@rspack/core@1.6.7(@swc/helpers@0.5.15))(@storybook/test@8.6.0(storybook@8.6.0(prettier@3.6.2)))(@swc/core@1.11.24(@swc/helpers@0.5.15))(esbuild@0.25.9)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)(storybook@8.6.0(prettier@3.6.2))(typescript@5.9.2) '@storybook/test': specifier: 8.6.0 version: 8.6.0(storybook@8.6.0(prettier@3.6.2)) @@ -1754,7 +1754,7 @@ importers: version: 1.0.35 unistore: specifier: 3.4.1 - version: 3.4.1(react@19.3.0-canary-65eec428-20251218) + version: 3.4.1(react@19.3.0-canary-bef88f7c-20260116) util: specifier: 0.12.4 version: 0.12.4 @@ -1936,14 +1936,14 @@ importers: packages/third-parties: dependencies: react: - specifier: 19.3.0-canary-65eec428-20251218 - version: 19.3.0-canary-65eec428-20251218 + specifier: 19.3.0-canary-bef88f7c-20260116 + version: 19.3.0-canary-bef88f7c-20260116 third-party-capital: specifier: 1.0.20 version: 1.0.20 devDependencies: next: - specifier: 16.1.1-canary.22 + specifier: 16.1.1-canary.31 version: link:../next outdent: specifier: 0.8.0 @@ -2000,14 +2000,14 @@ importers: specifier: 29.5.0 version: 29.5.0 react: - specifier: 19.3.0-canary-65eec428-20251218 - version: 19.3.0-canary-65eec428-20251218 + specifier: 19.3.0-canary-bef88f7c-20260116 + version: 19.3.0-canary-bef88f7c-20260116 react-test-renderer: specifier: 18.2.0 - version: 18.2.0(react@19.3.0-canary-65eec428-20251218) + version: 18.2.0(react@19.3.0-canary-bef88f7c-20260116) styled-jsx: specifier: ^5.1.2 - version: 5.1.6(@babel/core@7.26.10)(babel-plugin-macros@3.1.0)(react@19.3.0-canary-65eec428-20251218) + version: 5.1.6(@babel/core@7.26.10)(babel-plugin-macros@3.1.0)(react@19.3.0-canary-bef88f7c-20260116) turbopack/packages/devlow-bench: dependencies: @@ -2895,8 +2895,8 @@ packages: engines: {node: '>=14.0.0'} peerDependencies: '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -2905,8 +2905,8 @@ packages: resolution: {integrity: sha512-9+uaWyF1o/PgXqHLJnC81IIG0HlV3o9eFCQ5hWZDMx5NHrFk0rrwqEFGQOB8lti/rnbxNPi+kYYw1D4e8xSn/Q==} peerDependencies: '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -3061,7 +3061,7 @@ packages: resolution: {integrity: sha512-5mlW1DquU5HaxjLkfkGN1GA/fvVGdyHURRiX/0FHl2cfIfRxSOfmxEH5YS43edp0OldZrZ+dkBKbngxcNCdZvA==} peerDependencies: '@types/react': '*' - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -3078,7 +3078,7 @@ packages: '@emotion/use-insertion-effect-with-fallbacks@1.0.1': resolution: {integrity: sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==} peerDependencies: - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 '@emotion/utils@1.2.1': resolution: {integrity: sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==} @@ -3583,20 +3583,20 @@ packages: '@floating-ui/react-dom@2.1.0': resolution: {integrity: sha512-lNzj5EQmEKn5FFKc04+zasr09h/uX8RtJRNj5gUXsSQIXHVWTVh+hVAg1vOMCexkX8EgvemMvIFpQfkosnVNyA==} peerDependencies: - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 '@floating-ui/react-dom@2.1.5': resolution: {integrity: sha512-HDO/1/1oH9fjj4eLgegrlH3dklZpHtUYYFiVwMUwfGvk9jWDRWqkklA2/NFScknrcNSspbV868WjXORvreDX+Q==} peerDependencies: - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 '@floating-ui/react@0.26.16': resolution: {integrity: sha512-HEf43zxZNAI/E781QIVpYSF3K2VH4TTYZpqecjdsFkjsaU1EbaWcM++kw0HXFffj7gDUcBFevX8s0rQGQpxkow==} peerDependencies: - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 '@floating-ui/utils@0.2.10': resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==} @@ -4313,13 +4313,13 @@ packages: resolution: {integrity: sha512-l9ypojKN3PjwO1CSLIsqxi7mA25+7w+xc71Q+JuCCREI0tuGwkZsKbIOpuTATIJOjPh8ycLiW7QxX1LYsRTq6w==} peerDependencies: '@mantine/hooks': 7.10.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 '@mantine/hooks@7.11.2': resolution: {integrity: sha512-jhyVe/sbDEG2U8rr2lMecUPgQxcfr5hh9HazqGfkS7ZRIMDO7uJ947yAcTMGGkp5Lxtt5TBFt1Cb6tiB2/1agg==} peerDependencies: - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 '@mapbox/node-pre-gyp@1.0.5': resolution: {integrity: sha512-4srsKPXWlIxp5Vbqz5uLfBN+du2fJChBoYn/f2h991WLdk7jUvcSk/McVLSv/X+xQIPI8eGD5GjrnygdyHnhPA==} @@ -4339,13 +4339,13 @@ packages: '@mdx-js/react@2.2.1': resolution: {integrity: sha512-YdXcMcEnqZhzql98RNrqYo9cEhTTesBiCclEtoiQUbJwx87q9453GTapYU6kJ8ZZ2ek1Vp25SiAXEFy5O/eAPw==} peerDependencies: - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 '@mdx-js/react@3.1.0': resolution: {integrity: sha512-QjHtSaoameoalGnKDT3FoIl4+9RwyTmo9ZJGBdLOks/YOiWHoRDI3PUwEzOE7kEmGcV3AFcp9K6dYu9rEuKLAQ==} peerDependencies: '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 '@modelcontextprotocol/sdk@1.18.1': resolution: {integrity: sha512-d//GE8/Yh7aC3e7p+kZG8JqqEAwwDUmAfvH1quogtbk+ksS6E0RR6toKKESPYYZVre0meqkJb27zb+dhqE9Sgw==} @@ -5016,8 +5016,8 @@ packages: peerDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5029,8 +5029,8 @@ packages: peerDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5042,8 +5042,8 @@ packages: peerDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5055,8 +5055,8 @@ packages: peerDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5068,8 +5068,8 @@ packages: peerDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5081,8 +5081,8 @@ packages: peerDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5094,8 +5094,8 @@ packages: peerDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5106,7 +5106,7 @@ packages: resolution: {integrity: sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==} peerDependencies: '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5115,7 +5115,7 @@ packages: resolution: {integrity: sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==} peerDependencies: '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5124,7 +5124,7 @@ packages: resolution: {integrity: sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==} peerDependencies: '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5133,7 +5133,7 @@ packages: resolution: {integrity: sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==} peerDependencies: '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5142,7 +5142,7 @@ packages: resolution: {integrity: sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==} peerDependencies: '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5151,7 +5151,7 @@ packages: resolution: {integrity: sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==} peerDependencies: '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5161,8 +5161,8 @@ packages: peerDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5174,8 +5174,8 @@ packages: peerDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5186,7 +5186,7 @@ packages: resolution: {integrity: sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg==} peerDependencies: '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5195,7 +5195,7 @@ packages: resolution: {integrity: sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==} peerDependencies: '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5205,8 +5205,8 @@ packages: peerDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5218,8 +5218,8 @@ packages: peerDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5231,8 +5231,8 @@ packages: peerDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5243,7 +5243,7 @@ packages: resolution: {integrity: sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg==} peerDependencies: '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5252,7 +5252,7 @@ packages: resolution: {integrity: sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==} peerDependencies: '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5262,8 +5262,8 @@ packages: peerDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5275,8 +5275,8 @@ packages: peerDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5287,7 +5287,7 @@ packages: resolution: {integrity: sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==} peerDependencies: '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5296,7 +5296,7 @@ packages: resolution: {integrity: sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==} peerDependencies: '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5306,8 +5306,8 @@ packages: peerDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5319,8 +5319,8 @@ packages: peerDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5332,8 +5332,8 @@ packages: peerDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5345,8 +5345,8 @@ packages: peerDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5358,8 +5358,8 @@ packages: peerDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5371,8 +5371,8 @@ packages: peerDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5384,8 +5384,8 @@ packages: peerDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5397,8 +5397,8 @@ packages: peerDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5410,8 +5410,8 @@ packages: peerDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5423,8 +5423,8 @@ packages: peerDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5436,8 +5436,8 @@ packages: peerDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5449,8 +5449,8 @@ packages: peerDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5462,8 +5462,8 @@ packages: peerDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5475,8 +5475,8 @@ packages: peerDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5488,8 +5488,8 @@ packages: peerDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5501,8 +5501,8 @@ packages: peerDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5514,8 +5514,8 @@ packages: peerDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5527,8 +5527,8 @@ packages: peerDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5540,8 +5540,8 @@ packages: peerDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5552,7 +5552,7 @@ packages: resolution: {integrity: sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==} peerDependencies: '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5561,7 +5561,7 @@ packages: resolution: {integrity: sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g==} peerDependencies: '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5570,7 +5570,7 @@ packages: resolution: {integrity: sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==} peerDependencies: '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5580,8 +5580,8 @@ packages: peerDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5593,8 +5593,8 @@ packages: peerDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5606,8 +5606,8 @@ packages: peerDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5619,8 +5619,8 @@ packages: peerDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5631,7 +5631,7 @@ packages: resolution: {integrity: sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==} peerDependencies: '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5640,7 +5640,7 @@ packages: resolution: {integrity: sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==} peerDependencies: '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5649,7 +5649,7 @@ packages: resolution: {integrity: sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==} peerDependencies: '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5658,7 +5658,7 @@ packages: resolution: {integrity: sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==} peerDependencies: '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5667,7 +5667,7 @@ packages: resolution: {integrity: sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==} peerDependencies: '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5676,7 +5676,7 @@ packages: resolution: {integrity: sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==} peerDependencies: '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5685,7 +5685,7 @@ packages: resolution: {integrity: sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==} peerDependencies: '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5694,7 +5694,7 @@ packages: resolution: {integrity: sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==} peerDependencies: '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5703,7 +5703,7 @@ packages: resolution: {integrity: sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==} peerDependencies: '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5712,7 +5712,7 @@ packages: resolution: {integrity: sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==} peerDependencies: '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5721,7 +5721,7 @@ packages: resolution: {integrity: sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ==} peerDependencies: '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5730,7 +5730,7 @@ packages: resolution: {integrity: sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==} peerDependencies: '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5739,7 +5739,7 @@ packages: resolution: {integrity: sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==} peerDependencies: '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5748,7 +5748,7 @@ packages: resolution: {integrity: sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==} peerDependencies: '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5758,8 +5758,8 @@ packages: peerDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -5771,8 +5771,8 @@ packages: peerDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -6076,8 +6076,8 @@ packages: '@storybook/blocks@8.6.0': resolution: {integrity: sha512-3PNxlB5Ooj8CIhttbDxeV6kW7ui+2GEdTngtqhnsUHVjzeTKpilsk2lviOeUzqlyq5FDK+rhpZ3L3DJ9pDvioA==} peerDependencies: - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 storybook: ^8.6.0 peerDependenciesMeta: react: @@ -6127,8 +6127,8 @@ packages: resolution: {integrity: sha512-Nz/UzeYQdUZUhacrPyfkiiysSjydyjgg/p0P9HxB4p/WaJUUjMAcaoaLgy3EXx61zZJ3iD36WPuDkZs5QYrA0A==} engines: {node: '>=14.0.0'} peerDependencies: - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 '@storybook/instrumenter@8.6.0': resolution: {integrity: sha512-eEY/Hfa3Vj5Nv4vHRHlSqjoyW6oAKNK3rKIXfL/eawQwb7rKhzijDLG5YBH44Hh7dEPIqUp0LEdgpyIY7GXezg==} @@ -6144,8 +6144,8 @@ packages: resolution: {integrity: sha512-04T86VG0UJtiozgZkTR5sY1qM3E0Rgwqwllvyy7kFFdkV+Sv/VsPjW9sC38s9C8FtCYRL8pJZz81ey3oylpIMA==} engines: {node: '>=18.0.0'} peerDependencies: - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 storybook: ^8.6.0 typescript: '*' peerDependenciesMeta: @@ -6166,16 +6166,16 @@ packages: '@storybook/react-dom-shim@8.6.0': resolution: {integrity: sha512-5Y+vMHhcx0xnaNsLQMbkmjc3zkDn/fGBNsiLH2e4POvW3ZQvOxjoyxAsEQaKwLtFgsdCFSd2tR89F6ItYrA2JQ==} peerDependencies: - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 storybook: ^8.6.0 '@storybook/react-webpack5@8.6.0': resolution: {integrity: sha512-2L9CYDPn1OL0B8K5EU/Wpo9Slg8f0vkYPaPioQnmcK3Q4SJR4JAuDVWHUtNdxhaPOkHIy887Tfrf6BEC/blMaQ==} engines: {node: '>=18.0.0'} peerDependencies: - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 storybook: ^8.6.0 typescript: '>= 4.2.x' peerDependenciesMeta: @@ -6187,8 +6187,8 @@ packages: engines: {node: '>=18.0.0'} peerDependencies: '@storybook/test': 8.6.0 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 storybook: ^8.6.0 typescript: '>= 4.2.x' peerDependenciesMeta: @@ -6456,8 +6456,8 @@ packages: engines: {node: '>=18'} peerDependencies: '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -8395,8 +8395,8 @@ packages: cmdk@1.0.4: resolution: {integrity: sha512-AnsjfHyHpQ/EFeAnG216WY7A5LiYCoZzCSygiLvfXC3H3LFGCprErteUcszaVluGOhuOTbJS3jWHrSDYPBBygg==} peerDependencies: - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 co@4.6.0: resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} @@ -10062,8 +10062,8 @@ packages: peerDependencies: eslint: '>=8.0.0' - eslint-plugin-react-hooks@0.0.0-experimental-65eec428-20251218: - resolution: {integrity: sha512-B87ITIaWtlbj+P+69CH+2RFOqvML6SMMwkNShO8YEwsw0p4ekm1cOW53LG36XuT6ImCjijr6bpUNuf7fpFeLJQ==} + eslint-plugin-react-hooks@0.0.0-experimental-bef88f7c-20260116: + resolution: {integrity: sha512-NlzhHRkUSYAwR6z8tgi1Hat/nUmqcUy2fOK6N4AcBpceSYWjp1yNj/IjghmXzHo1UI/Epy6a0RWzGBAHmsRBSw==} engines: {node: '>=18'} peerDependencies: eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 @@ -10712,8 +10712,8 @@ packages: '@types/react': 19.2.2 algoliasearch: 5.x.x next: 14.x.x || 15.x.x - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 react-router: 7.x.x waku: ^0.26.0 peerDependenciesMeta: @@ -10745,7 +10745,7 @@ packages: '@fumadocs/mdx-remote': ^1.4.0 fumadocs-core: ^14.0.0 || ^15.0.0 next: ^15.3.0 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 vite: 6.x.x || 7.x.x peerDependenciesMeta: '@fumadocs/mdx-remote': @@ -10762,8 +10762,8 @@ packages: peerDependencies: '@types/react': 19.2.2 next: 14.x.x || 15.x.x - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 tailwindcss: ^3.4.14 || ^4.0.0 peerDependenciesMeta: '@types/react': @@ -13092,12 +13092,12 @@ packages: lucide-react@0.383.0: resolution: {integrity: sha512-13xlG0CQCJtzjSQYwwJ3WRqMHtRj3EXmLlorrARt7y+IHnxUCp3XyFNL1DfaGySWxHObDvnu1u1dV+0VMKHUSg==} peerDependencies: - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 lucide-react@0.554.0: resolution: {integrity: sha512-St+z29uthEJVx0Is7ellNkgTEhaeSoA42I7JjOCBCrc5X6LYMGSv0P/2uS5HDLTExP5tpiqRD2PyUEOS6s9UXA==} peerDependencies: - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 lz-string@1.5.0: resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} @@ -13893,8 +13893,8 @@ packages: next-themes@0.4.6: resolution: {integrity: sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==} peerDependencies: - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 next-tick@1.0.0: resolution: {integrity: sha512-mc/caHeUcdjnC/boPWJefDr4KUIWQNv+tlnFnJd38QMou86QtxQzBJfxgGRzvx8jazYRqrVlaHarfO72uNxPOg==} @@ -13908,8 +13908,8 @@ packages: '@opentelemetry/api': ^1.1.0 '@playwright/test': ^1.51.1 babel-plugin-react-compiler: '*' - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 sass: ^1.3.0 peerDependenciesMeta: '@opentelemetry/api': @@ -13930,8 +13930,8 @@ packages: '@opentelemetry/api': ^1.1.0 '@playwright/test': ^1.51.1 babel-plugin-react-compiler: '*' - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 sass: ^1.3.0 peerDependenciesMeta: '@opentelemetry/api': @@ -15823,23 +15823,23 @@ packages: resolution: {integrity: sha512-APPU8HB2uZnpl6Vt/+0AFoVYgSRtfiP6FLrZgPPTDmqSb2R4qZRbgd0A3VzIFxDt5e+Fozjx79WjLWnF69DK8g==} engines: {node: '>=16.14.0'} - react-dom@0.0.0-experimental-65eec428-20251218: - resolution: {integrity: sha512-DsqleuSRJ+53FO0euO01GozbBaSn0JZivNx08rlWGMyFx6KJUULTXXog8GE3RM+Kn3qcHt1kQ5VG1oHwgAhiBQ==} + react-dom@0.0.0-experimental-bef88f7c-20260116: + resolution: {integrity: sha512-R7PJceI2mqPWe3qfLArvtp5FlCflKqVp4nwubqROYZ/qHCfZRhY6t5pW81e2eBzpZsafKtuF1yQbziJkVGv/TQ==} peerDependencies: - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 - react-dom@19.3.0-canary-65eec428-20251218: - resolution: {integrity: sha512-ipd0VQrwUN+LeUVD/vcQyEz2g1diog1/f0UcccS6bNzhL2H/MoYDY6ojzgzbOHLilu2rDlHE21KBpV6FqJ51uw==} + react-dom@19.3.0-canary-bef88f7c-20260116: + resolution: {integrity: sha512-mPS5FRdF5YvZDmMXeOxOwC7DsjqvYnx2b+NDHx6XSkJcoy3LNyw6uwoiajO1bR2eYbbnDOAycRN2V5ht5WHoLw==} peerDependencies: - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 react-dom@19.3.0-canary-fd524fe0-20251121: resolution: {integrity: sha512-+M3m+8ysDcPmt7ncitPOX5O71OOKF6lq6INFZFUMJjEGDxvl4CS2D41DJG5MnXcwiWTZLAp/uILZtt4sKTRSyQ==} peerDependencies: - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 - react-is@19.3.0-canary-65eec428-20251218: - resolution: {integrity: sha512-VFcWOOqyArxj5BEijnXuMlDAxwWgbusC+rj/Uv13uDiOKzIUYU2yZ2xy/GS2Wziy9qLGQFOtoCWfgq5cuXXtJQ==} + react-is@19.3.0-canary-bef88f7c-20260116: + resolution: {integrity: sha512-Ovxb95Ir6eyWpOwbGUvWNWrf+gOe41UtcsD4m6Ze+Kdmbqx/P0IhUFr5oHDd6/yY2Ii7Z13VGB/ZVtqrv76sCw==} react-is@19.3.0-canary-fd524fe0-20251121: resolution: {integrity: sha512-06VG41yCv5V7FPCLxo4hBaiLEoReJ35LK9VvEqveBJq5cbEhakZznJLnPU1oJ3CCrL4DyBsPXw9EiYlrOL8c3Q==} @@ -15850,14 +15850,14 @@ packages: react-medium-image-zoom@5.3.0: resolution: {integrity: sha512-RCIzVlsKqy3BYgGgYbolUfuvx0aSKC7YhX/IJGEp+WJxsqdIVYJHkBdj++FAj6VD7RiWj6VVmdCfa/9vJE9hZg==} peerDependencies: - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 react-number-format@5.4.0: resolution: {integrity: sha512-NWdICrqLhI7rAS8yUeLVd6Wr4cN7UjJ9IBTS0f/a9i7UB4x4Ti70kGnksBtZ7o4Z7YRbvCMMR/jQmkoOBa/4fg==} peerDependencies: - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 react-refresh@0.12.0: resolution: {integrity: sha512-suLIhrU2IHKL5JEKR/fAwJv7bbeq4kJ+pJopf77jHwuR+HmJS/HbrPIGsTBUVfw7tXPOmYv7UJ7PCaN49e8x4A==} @@ -15868,7 +15868,7 @@ packages: engines: {node: '>=10'} peerDependencies: '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -15878,7 +15878,7 @@ packages: engines: {node: '>=10'} peerDependencies: '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -15888,7 +15888,7 @@ packages: engines: {node: '>=10'} peerDependencies: '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -15898,58 +15898,58 @@ packages: engines: {node: '>=10'} peerDependencies: '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true - react-server-dom-turbopack@0.0.0-experimental-65eec428-20251218: - resolution: {integrity: sha512-t9sgX87Y5cZu0UDG5BF1JmyuvGTqGb2S53gFVBHZJO6azo/1RuTz5HKYpactDu+PQJwlYCE2V6SYSFYKXZoRmQ==} + react-server-dom-turbopack@0.0.0-experimental-bef88f7c-20260116: + resolution: {integrity: sha512-IEzXHa2zAjne2RO9PLMEZt5WcxBtcFrxYWY7q6H8JkIHkUV5vBrnVAoQX1BvoxlBDPuuYTLfuKj3yVvPHeGAOw==} engines: {node: '>=0.10.0'} peerDependencies: - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 - react-server-dom-turbopack@19.3.0-canary-65eec428-20251218: - resolution: {integrity: sha512-Mpxx7txjFaNBZaQ/4Jp2xdDKts4Qm7UfjB+VLoA1ghOKawr+qsCgzmZtgZkYFl0lfBUmndJjhdaFGydNAkK4tw==} + react-server-dom-turbopack@19.3.0-canary-bef88f7c-20260116: + resolution: {integrity: sha512-P1xxqdZUxAyUim7i6XDE7V7i/jIYCe8Q60FcUlSM4v+NLhr1NLqD+gZzfpHpd6YaxCuHIp0yRifATrwZHsEzMg==} engines: {node: '>=0.10.0'} peerDependencies: - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 - react-server-dom-webpack@0.0.0-experimental-65eec428-20251218: - resolution: {integrity: sha512-nKYwUA/Jn3k+2SXk7N2oiX9+utZhA5viikK51evMK5OB0nb+RzUYQ8CfUex+e/N5y7u9Vt0OSRIeLiyfNR/iiQ==} + react-server-dom-webpack@0.0.0-experimental-bef88f7c-20260116: + resolution: {integrity: sha512-JyHWeKy7bZg3drRyV6aU3qxmCfWlA1S/DBeyCFWge/ry+ktgaydhLct7ULnk9hUJvslxuD4NUdou+iw0NDEi6g==} engines: {node: '>=0.10.0'} peerDependencies: - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 webpack: 5.98.0 - react-server-dom-webpack@19.3.0-canary-65eec428-20251218: - resolution: {integrity: sha512-nsNeiDI8kb+UGy1Ne3/MOTh3RyRWS1JoT+Lfwr2duBnpyNAlw4+wMirvbksGQPpn5ZM59Qz2bDMu5bZY+nzAcA==} + react-server-dom-webpack@19.3.0-canary-bef88f7c-20260116: + resolution: {integrity: sha512-zi26SqNz+++I21+WmDMBgcZ6hqQnR5Bex0ksZfBIXS08tM0dEYLYfKARzdpPXYUHaXrlJIVdhMgaLvX13/UeRQ==} engines: {node: '>=0.10.0'} peerDependencies: - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 webpack: 5.98.0 react-shallow-renderer@16.15.0: resolution: {integrity: sha512-oScf2FqQ9LFVQgA73vr86xl2NaOIX73rh+YFqcOp68CWj56tSfgtGKrEbyhCj0rSijyG9M1CYprTh39fBi5hzA==} peerDependencies: - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 react-ssr-prepass@1.0.8: resolution: {integrity: sha512-O0gfRA1SaK+9ITKxqfnXsej2jF+OHGP/+GxD4unROQaM/0/UczGF9fuF+wTboxaQoKdIf4FvS3h/OigWh704VA==} peerDependencies: - react: 19.3.0-canary-65eec428-20251218 - react-is: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-is: 19.3.0-canary-bef88f7c-20260116 react-style-singleton@2.2.1: resolution: {integrity: sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==} engines: {node: '>=10'} peerDependencies: '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -15959,7 +15959,7 @@ packages: engines: {node: '>=10'} peerDependencies: '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -15967,26 +15967,26 @@ packages: react-test-renderer@18.2.0: resolution: {integrity: sha512-JWD+aQ0lh2gvh4NM3bBM42Kx+XybOxCpgYK7F8ugAlpaTSnWsX+39Z4XkOykGZAHrjwwTZT3x3KxswVWxHPUqA==} peerDependencies: - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 react-textarea-autosize@8.5.3: resolution: {integrity: sha512-XT1024o2pqCuZSuBt9FwHlaDeNtVrtCXu0Rnz88t1jUGheCLa3PhjE1GH8Ctm2axEtvdCl5SUHYschyQ0L5QHQ==} engines: {node: '>=10'} peerDependencies: - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 react-virtualized@9.22.3: resolution: {integrity: sha512-MKovKMxWTcwPSxE1kK1HcheQTWfuCxAuBoSTf2gwyMM21NdX/PXUhnoP8Uc5dRKd+nKm8v41R36OellhdCpkrw==} peerDependencies: - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116 - react@0.0.0-experimental-65eec428-20251218: - resolution: {integrity: sha512-gkKY+9ry8wCfHTl1PZv+41FIYBcM8KCH9FK2lBd1ZJKGfqPJBoXBwZlhJXFLIzkvQ+04uPE1vl7PkDKd2jr4eA==} + react@0.0.0-experimental-bef88f7c-20260116: + resolution: {integrity: sha512-Az/6X9UOT+Xb8e7om1Jk/IF7ubGc1+cX0+gpoH/DEcKQH4Yz0JckTSaOvLn/COvK0SFlar9wBP+5uGkmwOoBLA==} engines: {node: '>=0.10.0'} - react@19.3.0-canary-65eec428-20251218: - resolution: {integrity: sha512-14H0NuO8YvzFub5VVYEpbvgrjMzGJ6fz2rxYLWTpS5QpF5y/62AURjy9Welihvvx8uthhhx9LbZYfepUX6Ws6w==} + react@19.3.0-canary-bef88f7c-20260116: + resolution: {integrity: sha512-LR13FdiRCHmt7kAKbZyj45LGGoYbQoiULsEWgVjkaIWT6d4exh/6OCdCUxuu8asVbd2vo3kpvvzaBRCLQ7oE3w==} engines: {node: '>=0.10.0'} react@19.3.0-canary-fd524fe0-20251121: @@ -16593,11 +16593,11 @@ packages: resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} engines: {node: '>=v12.22.7'} - scheduler@0.0.0-experimental-65eec428-20251218: - resolution: {integrity: sha512-o/tHfvOwVwYEnYEyjaz0eGosKSwEI3TovZCMJn1lahoQZSct//0AxlCLQYyhp0bfjegsCqw/G0VozhkOhlfTeQ==} + scheduler@0.0.0-experimental-bef88f7c-20260116: + resolution: {integrity: sha512-63kuIj5jx/5tMMRHFBhLWy1InJsvv2rJa+nCKFrNyat5pji2fx5cWrxmZ/0buQAn1cKWs8GjqModGsOZwlweLQ==} - scheduler@0.28.0-canary-65eec428-20251218: - resolution: {integrity: sha512-vmWiNSe2l1jzT66MQ9VyyuPkm1PYmaoxAcHTXj04WO7/27krmqQ6uzCwlS0z1SVEd8BMoM/LkQ/C5x3rkv0WSA==} + scheduler@0.28.0-canary-bef88f7c-20260116: + resolution: {integrity: sha512-tUEFippF+5hnb3kQwTf6Dqj0uVRgtt50Zrd35odAz/QIhTHHwQCxrXUllM13W0Y4+UpPFtyH7Lf92mrErlftXw==} schema-utils@2.7.1: resolution: {integrity: sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==} @@ -17282,7 +17282,7 @@ packages: peerDependencies: '@babel/core': '*' babel-plugin-macros: '*' - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@babel/core': optional: true @@ -17369,7 +17369,7 @@ packages: swr@2.2.4: resolution: {integrity: sha512-njiZ/4RiIhoOlAaLYDqwz5qH/KZXVilRLvomrx83HjzCWTfa+InyfAjv05PSFxnmLzZkNO9ZfvgoqzAaEI4sGQ==} peerDependencies: - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 symbol-observable@1.0.1: resolution: {integrity: sha512-Kb3PrPYz4HanVF1LVGuAdW6LoVgIwjUYJGzFe7NDrBLCN4lsV/5J0MFurV+ygS4bRVwrCEt2c7MQ1R2a72oJDw==} @@ -18232,7 +18232,7 @@ packages: engines: {node: '>=10'} peerDependencies: '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -18242,7 +18242,7 @@ packages: engines: {node: '>=10'} peerDependencies: '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -18250,13 +18250,13 @@ packages: use-composed-ref@1.3.0: resolution: {integrity: sha512-GLMG0Jc/jiKov/3Ulid1wbv3r54K9HlMW29IWcDFPEqFkSO2nS0MuefWgMJpeHQ9YJeXDL3ZUF+P3jdXlZX/cQ==} peerDependencies: - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 use-isomorphic-layout-effect@1.1.2: resolution: {integrity: sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==} peerDependencies: '@types/react': '*' - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -18265,7 +18265,7 @@ packages: resolution: {integrity: sha512-xA+AVm/Wlg3e2P/JiItTziwS7FK92LWrDB0p+hgXloIMuVCeJJ8v6f0eeHyPZaJrM+usM1FkFfbNCrJGs8A/zw==} peerDependencies: '@types/react': '*' - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -18275,7 +18275,7 @@ packages: engines: {node: '>=10'} peerDependencies: '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -18285,7 +18285,7 @@ packages: engines: {node: '>=10'} peerDependencies: '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 peerDependenciesMeta: '@types/react': optional: true @@ -18293,7 +18293,7 @@ packages: use-sync-external-store@1.5.0: resolution: {integrity: sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==} peerDependencies: - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} @@ -19908,28 +19908,28 @@ snapshots: '@babel/helper-string-parser': 7.25.9 '@babel/helper-validator-identifier': 7.25.9 - '@base-ui-components/react@1.0.0-beta.2(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)': + '@base-ui-components/react@1.0.0-beta.2(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)': dependencies: '@babel/runtime': 7.27.6 - '@base-ui-components/utils': 0.1.0(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@floating-ui/react-dom': 2.1.5(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) + '@base-ui-components/utils': 0.1.0(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@floating-ui/react-dom': 2.1.5(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) '@floating-ui/utils': 0.2.10 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) reselect: 5.1.1 tabbable: 6.2.0 - use-sync-external-store: 1.5.0(react@19.3.0-canary-65eec428-20251218) + use-sync-external-store: 1.5.0(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@types/react': 19.2.2 - '@base-ui-components/utils@0.1.0(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)': + '@base-ui-components/utils@0.1.0(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)': dependencies: '@babel/runtime': 7.27.6 '@floating-ui/utils': 0.2.10 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) reselect: 5.1.1 - use-sync-external-store: 1.5.0(react@19.3.0-canary-65eec428-20251218) + use-sync-external-store: 1.5.0(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@types/react': 19.2.2 @@ -20102,17 +20102,17 @@ snapshots: '@emotion/memoize@0.8.1': {} - '@emotion/react@11.11.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218)': + '@emotion/react@11.11.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116)': dependencies: '@babel/runtime': 7.27.0 '@emotion/babel-plugin': 11.11.0 '@emotion/cache': 11.11.0 '@emotion/serialize': 1.1.2 - '@emotion/use-insertion-effect-with-fallbacks': 1.0.1(react@19.3.0-canary-65eec428-20251218) + '@emotion/use-insertion-effect-with-fallbacks': 1.0.1(react@19.3.0-canary-bef88f7c-20260116) '@emotion/utils': 1.2.1 '@emotion/weak-memoize': 0.3.1 hoist-non-react-statics: 3.3.2 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 optionalDependencies: '@types/react': 19.2.2 transitivePeerDependencies: @@ -20130,9 +20130,9 @@ snapshots: '@emotion/unitless@0.8.1': {} - '@emotion/use-insertion-effect-with-fallbacks@1.0.1(react@19.3.0-canary-65eec428-20251218)': + '@emotion/use-insertion-effect-with-fallbacks@1.0.1(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 '@emotion/utils@1.2.1': {} @@ -20555,11 +20555,11 @@ snapshots: react: 19.3.0-canary-fd524fe0-20251121 react-dom: 19.3.0-canary-fd524fe0-20251121(react@19.3.0-canary-fd524fe0-20251121) - '@floating-ui/react-dom@2.1.5(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)': + '@floating-ui/react-dom@2.1.5(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)': dependencies: '@floating-ui/dom': 1.7.3 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) '@floating-ui/react@0.26.16(react-dom@19.3.0-canary-fd524fe0-20251121(react@19.3.0-canary-fd524fe0-20251121))(react@19.3.0-canary-fd524fe0-20251121)': dependencies: @@ -21519,11 +21519,11 @@ snapshots: transitivePeerDependencies: - supports-color - '@mdx-js/react@2.2.1(react@19.3.0-canary-65eec428-20251218)': + '@mdx-js/react@2.2.1(react@19.3.0-canary-bef88f7c-20260116)': dependencies: '@types/mdx': 2.0.13 '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 '@mdx-js/react@2.2.1(react@19.3.0-canary-fd524fe0-20251121)': dependencies: @@ -21531,11 +21531,11 @@ snapshots: '@types/react': 19.2.2 react: 19.3.0-canary-fd524fe0-20251121 - '@mdx-js/react@3.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218)': + '@mdx-js/react@3.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116)': dependencies: '@types/mdx': 2.0.13 '@types/react': 19.2.2 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 '@modelcontextprotocol/sdk@1.18.1': dependencies: @@ -22305,749 +22305,749 @@ snapshots: '@radix-ui/primitive@1.1.3': {} - '@radix-ui/react-accordion@1.2.12(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-accordion@1.2.12(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)': dependencies: '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collapsible': 1.1.12(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + '@radix-ui/react-collapsible': 1.1.12(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1(@types/react@19.2.2) - '@radix-ui/react-arrow@1.1.0(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-arrow@1.1.0(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1(@types/react@19.2.2) - '@radix-ui/react-arrow@1.1.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-arrow@1.1.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1(@types/react@19.2.2) - '@radix-ui/react-arrow@1.1.7(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-arrow@1.1.7(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1(@types/react@19.2.2) - '@radix-ui/react-collapsible@1.1.12(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-collapsible@1.1.12(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)': dependencies: '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1(@types/react@19.2.2) - '@radix-ui/react-collection@1.1.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-collection@1.1.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-context': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-slot': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-context': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-slot': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1(@types/react@19.2.2) - '@radix-ui/react-collection@1.1.7(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-collection@1.1.7(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-slot': 1.2.3(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1(@types/react@19.2.2) - '@radix-ui/react-compose-refs@1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-compose-refs@1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 optionalDependencies: '@types/react': 19.2.2 - '@radix-ui/react-compose-refs@1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-compose-refs@1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 optionalDependencies: '@types/react': 19.2.2 - '@radix-ui/react-compose-refs@1.1.2(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-compose-refs@1.1.2(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 optionalDependencies: '@types/react': 19.2.2 - '@radix-ui/react-context@1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-context@1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 optionalDependencies: '@types/react': 19.2.2 - '@radix-ui/react-context@1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-context@1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 optionalDependencies: '@types/react': 19.2.2 - '@radix-ui/react-context@1.1.2(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-context@1.1.2(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 optionalDependencies: '@types/react': 19.2.2 - '@radix-ui/react-dialog@1.1.15(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-dialog@1.1.15(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)': dependencies: '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-slot': 1.2.3(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) aria-hidden: 1.2.6 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) - react-remove-scroll: 2.7.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) + react-remove-scroll: 2.7.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1(@types/react@19.2.2) - '@radix-ui/react-dialog@1.1.4(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-dialog@1.1.4(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)': dependencies: '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-context': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-dismissable-layer': 1.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-focus-guards': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-focus-scope': 1.1.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-id': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-portal': 1.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-presence': 1.1.2(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-slot': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-context': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-dismissable-layer': 1.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-focus-guards': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-focus-scope': 1.1.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-id': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-portal': 1.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-presence': 1.1.2(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-slot': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) aria-hidden: 1.2.6 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) - react-remove-scroll: 2.7.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) + react-remove-scroll: 2.7.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1(@types/react@19.2.2) - '@radix-ui/react-direction@1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-direction@1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 optionalDependencies: '@types/react': 19.2.2 - '@radix-ui/react-direction@1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-direction@1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 optionalDependencies: '@types/react': 19.2.2 - '@radix-ui/react-dismissable-layer@1.1.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-dismissable-layer@1.1.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)': dependencies: '@radix-ui/primitive': 1.1.0 - '@radix-ui/react-compose-refs': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-escape-keydown': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + '@radix-ui/react-compose-refs': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-escape-keydown': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1(@types/react@19.2.2) - '@radix-ui/react-dismissable-layer@1.1.11(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-dismissable-layer@1.1.11(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)': dependencies: '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-escape-keydown': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-escape-keydown': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1(@types/react@19.2.2) - '@radix-ui/react-dismissable-layer@1.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-dismissable-layer@1.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)': dependencies: '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-escape-keydown': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-escape-keydown': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1(@types/react@19.2.2) - '@radix-ui/react-focus-guards@1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-focus-guards@1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 optionalDependencies: '@types/react': 19.2.2 - '@radix-ui/react-focus-guards@1.1.3(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-focus-guards@1.1.3(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 optionalDependencies: '@types/react': 19.2.2 - '@radix-ui/react-focus-scope@1.1.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-focus-scope@1.1.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1(@types/react@19.2.2) - '@radix-ui/react-focus-scope@1.1.7(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-focus-scope@1.1.7(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1(@types/react@19.2.2) - '@radix-ui/react-id@1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-id@1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - react: 19.3.0-canary-65eec428-20251218 + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + react: 19.3.0-canary-bef88f7c-20260116 optionalDependencies: '@types/react': 19.2.2 - '@radix-ui/react-id@1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-id@1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - react: 19.3.0-canary-65eec428-20251218 + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + react: 19.3.0-canary-bef88f7c-20260116 optionalDependencies: '@types/react': 19.2.2 - '@radix-ui/react-navigation-menu@1.2.14(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-navigation-menu@1.2.14(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)': dependencies: '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1(@types/react@19.2.2) - '@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)': dependencies: '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-slot': 1.2.3(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) aria-hidden: 1.2.6 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) - react-remove-scroll: 2.7.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) + react-remove-scroll: 2.7.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1(@types/react@19.2.2) - '@radix-ui/react-popover@1.1.4(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-popover@1.1.4(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)': dependencies: '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-context': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-dismissable-layer': 1.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-focus-guards': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-focus-scope': 1.1.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-id': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-popper': 1.2.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-portal': 1.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-presence': 1.1.2(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-slot': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-context': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-dismissable-layer': 1.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-focus-guards': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-focus-scope': 1.1.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-id': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-popper': 1.2.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-portal': 1.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-presence': 1.1.2(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-slot': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) aria-hidden: 1.2.6 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) - react-remove-scroll: 2.7.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) + react-remove-scroll: 2.7.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1(@types/react@19.2.2) - '@radix-ui/react-popper@1.2.0(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)': - dependencies: - '@floating-ui/react-dom': 2.1.5(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-arrow': 1.1.0(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-compose-refs': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-context': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-rect': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-size': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) + '@radix-ui/react-popper@1.2.0(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)': + dependencies: + '@floating-ui/react-dom': 2.1.5(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-arrow': 1.1.0(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-compose-refs': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-context': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-rect': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-size': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) '@radix-ui/rect': 1.1.0 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1(@types/react@19.2.2) - '@radix-ui/react-popper@1.2.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)': - dependencies: - '@floating-ui/react-dom': 2.1.5(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-arrow': 1.1.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-context': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-rect': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-size': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) + '@radix-ui/react-popper@1.2.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)': + dependencies: + '@floating-ui/react-dom': 2.1.5(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-arrow': 1.1.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-context': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-rect': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-size': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) '@radix-ui/rect': 1.1.0 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1(@types/react@19.2.2) - '@radix-ui/react-popper@1.2.8(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)': - dependencies: - '@floating-ui/react-dom': 2.1.5(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-arrow': 1.1.7(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-rect': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) + '@radix-ui/react-popper@1.2.8(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)': + dependencies: + '@floating-ui/react-dom': 2.1.5(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-arrow': 1.1.7(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-rect': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) '@radix-ui/rect': 1.1.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1(@types/react@19.2.2) - '@radix-ui/react-portal@1.1.2(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-portal@1.1.2(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1(@types/react@19.2.2) - '@radix-ui/react-portal@1.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-portal@1.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1(@types/react@19.2.2) - '@radix-ui/react-portal@1.1.9(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-portal@1.1.9(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1(@types/react@19.2.2) - '@radix-ui/react-presence@1.1.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-presence@1.1.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - '@radix-ui/react-compose-refs': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + '@radix-ui/react-compose-refs': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1(@types/react@19.2.2) - '@radix-ui/react-presence@1.1.2(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-presence@1.1.2(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1(@types/react@19.2.2) - '@radix-ui/react-presence@1.1.5(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-presence@1.1.5(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1(@types/react@19.2.2) - '@radix-ui/react-primitive@2.0.0(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-primitive@2.0.0(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - '@radix-ui/react-slot': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + '@radix-ui/react-slot': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1(@types/react@19.2.2) - '@radix-ui/react-primitive@2.0.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-primitive@2.0.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - '@radix-ui/react-slot': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + '@radix-ui/react-slot': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1(@types/react@19.2.2) - '@radix-ui/react-primitive@2.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-primitive@2.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + '@radix-ui/react-slot': 1.2.3(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1(@types/react@19.2.2) - '@radix-ui/react-roving-focus@1.1.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-roving-focus@1.1.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)': dependencies: '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-collection': 1.1.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-context': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-direction': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-id': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + '@radix-ui/react-collection': 1.1.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-context': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-direction': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-id': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1(@types/react@19.2.2) - '@radix-ui/react-roving-focus@1.1.11(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-roving-focus@1.1.11(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)': dependencies: '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1(@types/react@19.2.2) - '@radix-ui/react-scroll-area@1.2.10(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-scroll-area@1.2.10(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)': dependencies: '@radix-ui/number': 1.1.1 '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1(@types/react@19.2.2) - '@radix-ui/react-select@2.2.6(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-select@2.2.6(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)': dependencies: '@radix-ui/number': 1.1.1 '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-slot': 1.2.3(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) aria-hidden: 1.2.6 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) - react-remove-scroll: 2.7.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) + react-remove-scroll: 2.7.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1(@types/react@19.2.2) - '@radix-ui/react-slot@1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-slot@1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - '@radix-ui/react-compose-refs': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - react: 19.3.0-canary-65eec428-20251218 + '@radix-ui/react-compose-refs': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + react: 19.3.0-canary-bef88f7c-20260116 optionalDependencies: '@types/react': 19.2.2 - '@radix-ui/react-slot@1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-slot@1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - react: 19.3.0-canary-65eec428-20251218 + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + react: 19.3.0-canary-bef88f7c-20260116 optionalDependencies: '@types/react': 19.2.2 - '@radix-ui/react-slot@1.2.3(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-slot@1.2.3(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - react: 19.3.0-canary-65eec428-20251218 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + react: 19.3.0-canary-bef88f7c-20260116 optionalDependencies: '@types/react': 19.2.2 - '@radix-ui/react-tabs@1.1.13(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-tabs@1.1.13(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)': dependencies: '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-context': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1(@types/react@19.2.2) - '@radix-ui/react-toggle-group@1.1.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-toggle-group@1.1.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)': dependencies: '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-context': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-direction': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-roving-focus': 1.1.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-toggle': 1.1.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + '@radix-ui/react-context': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-direction': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-roving-focus': 1.1.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-toggle': 1.1.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1(@types/react@19.2.2) - '@radix-ui/react-toggle@1.1.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-toggle@1.1.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)': dependencies: '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1(@types/react@19.2.2) - '@radix-ui/react-tooltip@1.1.4(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-tooltip@1.1.4(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)': dependencies: '@radix-ui/primitive': 1.1.0 - '@radix-ui/react-compose-refs': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-context': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-dismissable-layer': 1.1.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-id': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-popper': 1.2.0(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-portal': 1.1.2(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-presence': 1.1.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-slot': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-visually-hidden': 1.1.0(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + '@radix-ui/react-compose-refs': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-context': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-dismissable-layer': 1.1.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-id': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-popper': 1.2.0(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-portal': 1.1.2(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-presence': 1.1.1(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-slot': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-visually-hidden': 1.1.0(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1(@types/react@19.2.2) - '@radix-ui/react-use-callback-ref@1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-use-callback-ref@1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 optionalDependencies: '@types/react': 19.2.2 - '@radix-ui/react-use-callback-ref@1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-use-callback-ref@1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 optionalDependencies: '@types/react': 19.2.2 - '@radix-ui/react-use-controllable-state@1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-use-controllable-state@1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - react: 19.3.0-canary-65eec428-20251218 + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + react: 19.3.0-canary-bef88f7c-20260116 optionalDependencies: '@types/react': 19.2.2 - '@radix-ui/react-use-controllable-state@1.2.2(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-use-controllable-state@1.2.2(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - '@radix-ui/react-use-effect-event': 0.0.2(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - react: 19.3.0-canary-65eec428-20251218 + '@radix-ui/react-use-effect-event': 0.0.2(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + react: 19.3.0-canary-bef88f7c-20260116 optionalDependencies: '@types/react': 19.2.2 - '@radix-ui/react-use-effect-event@0.0.2(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-use-effect-event@0.0.2(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - react: 19.3.0-canary-65eec428-20251218 + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + react: 19.3.0-canary-bef88f7c-20260116 optionalDependencies: '@types/react': 19.2.2 - '@radix-ui/react-use-escape-keydown@1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-use-escape-keydown@1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - react: 19.3.0-canary-65eec428-20251218 + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + react: 19.3.0-canary-bef88f7c-20260116 optionalDependencies: '@types/react': 19.2.2 - '@radix-ui/react-use-escape-keydown@1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-use-escape-keydown@1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - react: 19.3.0-canary-65eec428-20251218 + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + react: 19.3.0-canary-bef88f7c-20260116 optionalDependencies: '@types/react': 19.2.2 - '@radix-ui/react-use-layout-effect@1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-use-layout-effect@1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 optionalDependencies: '@types/react': 19.2.2 - '@radix-ui/react-use-layout-effect@1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-use-layout-effect@1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 optionalDependencies: '@types/react': 19.2.2 - '@radix-ui/react-use-previous@1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-use-previous@1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 optionalDependencies: '@types/react': 19.2.2 - '@radix-ui/react-use-rect@1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-use-rect@1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116)': dependencies: '@radix-ui/rect': 1.1.0 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 optionalDependencies: '@types/react': 19.2.2 - '@radix-ui/react-use-rect@1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-use-rect@1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116)': dependencies: '@radix-ui/rect': 1.1.1 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 optionalDependencies: '@types/react': 19.2.2 - '@radix-ui/react-use-size@1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-use-size@1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - react: 19.3.0-canary-65eec428-20251218 + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + react: 19.3.0-canary-bef88f7c-20260116 optionalDependencies: '@types/react': 19.2.2 - '@radix-ui/react-use-size@1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-use-size@1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - react: 19.3.0-canary-65eec428-20251218 + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + react: 19.3.0-canary-bef88f7c-20260116 optionalDependencies: '@types/react': 19.2.2 - '@radix-ui/react-visually-hidden@1.1.0(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-visually-hidden@1.1.0(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1(@types/react@19.2.2) - '@radix-ui/react-visually-hidden@1.2.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)': + '@radix-ui/react-visually-hidden@1.2.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@types/react': 19.2.2 '@types/react-dom': 19.2.1(@types/react@19.2.2) @@ -23345,12 +23345,12 @@ snapshots: '@storybook/addon-docs@8.6.0(@types/react@19.2.2)(storybook@8.6.0(prettier@3.6.2))': dependencies: - '@mdx-js/react': 3.1.0(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@storybook/blocks': 8.6.0(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)(storybook@8.6.0(prettier@3.6.2)) + '@mdx-js/react': 3.1.0(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@storybook/blocks': 8.6.0(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)(storybook@8.6.0(prettier@3.6.2)) '@storybook/csf-plugin': 8.6.0(storybook@8.6.0(prettier@3.6.2)) - '@storybook/react-dom-shim': 8.6.0(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)(storybook@8.6.0(prettier@3.6.2)) - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + '@storybook/react-dom-shim': 8.6.0(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)(storybook@8.6.0(prettier@3.6.2)) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) storybook: 8.6.0(prettier@3.6.2) ts-dedent: 2.2.0 transitivePeerDependencies: @@ -23415,14 +23415,14 @@ snapshots: - '@swc/helpers' - webpack - '@storybook/blocks@8.6.0(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)(storybook@8.6.0(prettier@3.6.2))': + '@storybook/blocks@8.6.0(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)(storybook@8.6.0(prettier@3.6.2))': dependencies: - '@storybook/icons': 1.3.0(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) + '@storybook/icons': 1.3.0(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) storybook: 8.6.0(prettier@3.6.2) ts-dedent: 2.2.0 optionalDependencies: - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) '@storybook/builder-webpack5@8.6.0(@rspack/core@1.6.7(@swc/helpers@0.5.15))(@swc/core@1.11.24(@swc/helpers@0.5.15))(esbuild@0.25.9)(storybook@8.6.0(prettier@3.6.2))(typescript@5.9.2)': dependencies: @@ -23501,10 +23501,10 @@ snapshots: '@storybook/global@5.0.0': {} - '@storybook/icons@1.3.0(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)': + '@storybook/icons@1.3.0(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)': dependencies: - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) '@storybook/instrumenter@8.6.0(storybook@8.6.0(prettier@3.6.2))': dependencies: @@ -23516,17 +23516,17 @@ snapshots: dependencies: storybook: 8.6.0(prettier@3.6.2) - '@storybook/preset-react-webpack@8.6.0(@storybook/test@8.6.0(storybook@8.6.0(prettier@3.6.2)))(@swc/core@1.11.24(@swc/helpers@0.5.15))(esbuild@0.25.9)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)(storybook@8.6.0(prettier@3.6.2))(typescript@5.9.2)': + '@storybook/preset-react-webpack@8.6.0(@storybook/test@8.6.0(storybook@8.6.0(prettier@3.6.2)))(@swc/core@1.11.24(@swc/helpers@0.5.15))(esbuild@0.25.9)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)(storybook@8.6.0(prettier@3.6.2))(typescript@5.9.2)': dependencies: '@storybook/core-webpack': 8.6.0(storybook@8.6.0(prettier@3.6.2)) - '@storybook/react': 8.6.0(@storybook/test@8.6.0(storybook@8.6.0(prettier@3.6.2)))(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)(storybook@8.6.0(prettier@3.6.2))(typescript@5.9.2) + '@storybook/react': 8.6.0(@storybook/test@8.6.0(storybook@8.6.0(prettier@3.6.2)))(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)(storybook@8.6.0(prettier@3.6.2))(typescript@5.9.2) '@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0(typescript@5.9.2)(webpack@5.98.0(@swc/core@1.11.24(@swc/helpers@0.5.15))(esbuild@0.25.9)) '@types/semver': 7.5.6 find-up: 5.0.0 magic-string: 0.30.19 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 react-docgen: 7.1.0 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) resolve: 1.22.10 semver: 7.6.3 storybook: 8.6.0(prettier@3.6.2) @@ -23560,19 +23560,19 @@ snapshots: transitivePeerDependencies: - supports-color - '@storybook/react-dom-shim@8.6.0(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)(storybook@8.6.0(prettier@3.6.2))': + '@storybook/react-dom-shim@8.6.0(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)(storybook@8.6.0(prettier@3.6.2))': dependencies: - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) storybook: 8.6.0(prettier@3.6.2) - '@storybook/react-webpack5@8.6.0(@rspack/core@1.6.7(@swc/helpers@0.5.15))(@storybook/test@8.6.0(storybook@8.6.0(prettier@3.6.2)))(@swc/core@1.11.24(@swc/helpers@0.5.15))(esbuild@0.25.9)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)(storybook@8.6.0(prettier@3.6.2))(typescript@5.9.2)': + '@storybook/react-webpack5@8.6.0(@rspack/core@1.6.7(@swc/helpers@0.5.15))(@storybook/test@8.6.0(storybook@8.6.0(prettier@3.6.2)))(@swc/core@1.11.24(@swc/helpers@0.5.15))(esbuild@0.25.9)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)(storybook@8.6.0(prettier@3.6.2))(typescript@5.9.2)': dependencies: '@storybook/builder-webpack5': 8.6.0(@rspack/core@1.6.7(@swc/helpers@0.5.15))(@swc/core@1.11.24(@swc/helpers@0.5.15))(esbuild@0.25.9)(storybook@8.6.0(prettier@3.6.2))(typescript@5.9.2) - '@storybook/preset-react-webpack': 8.6.0(@storybook/test@8.6.0(storybook@8.6.0(prettier@3.6.2)))(@swc/core@1.11.24(@swc/helpers@0.5.15))(esbuild@0.25.9)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)(storybook@8.6.0(prettier@3.6.2))(typescript@5.9.2) - '@storybook/react': 8.6.0(@storybook/test@8.6.0(storybook@8.6.0(prettier@3.6.2)))(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)(storybook@8.6.0(prettier@3.6.2))(typescript@5.9.2) - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + '@storybook/preset-react-webpack': 8.6.0(@storybook/test@8.6.0(storybook@8.6.0(prettier@3.6.2)))(@swc/core@1.11.24(@swc/helpers@0.5.15))(esbuild@0.25.9)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)(storybook@8.6.0(prettier@3.6.2))(typescript@5.9.2) + '@storybook/react': 8.6.0(@storybook/test@8.6.0(storybook@8.6.0(prettier@3.6.2)))(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)(storybook@8.6.0(prettier@3.6.2))(typescript@5.9.2) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) storybook: 8.6.0(prettier@3.6.2) optionalDependencies: typescript: 5.9.2 @@ -23585,16 +23585,16 @@ snapshots: - uglify-js - webpack-cli - '@storybook/react@8.6.0(@storybook/test@8.6.0(storybook@8.6.0(prettier@3.6.2)))(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)(storybook@8.6.0(prettier@3.6.2))(typescript@5.9.2)': + '@storybook/react@8.6.0(@storybook/test@8.6.0(storybook@8.6.0(prettier@3.6.2)))(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)(storybook@8.6.0(prettier@3.6.2))(typescript@5.9.2)': dependencies: '@storybook/components': 8.6.0(storybook@8.6.0(prettier@3.6.2)) '@storybook/global': 5.0.0 '@storybook/manager-api': 8.6.0(storybook@8.6.0(prettier@3.6.2)) '@storybook/preview-api': 8.6.0(storybook@8.6.0(prettier@3.6.2)) - '@storybook/react-dom-shim': 8.6.0(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)(storybook@8.6.0(prettier@3.6.2)) + '@storybook/react-dom-shim': 8.6.0(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)(storybook@8.6.0(prettier@3.6.2)) '@storybook/theming': 8.6.0(storybook@8.6.0(prettier@3.6.2)) - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) storybook: 8.6.0(prettier@3.6.2) optionalDependencies: '@storybook/test': 8.6.0(storybook@8.6.0(prettier@3.6.2)) @@ -23872,13 +23872,13 @@ snapshots: lodash: 4.17.21 redent: 3.0.0 - '@testing-library/react@15.0.7(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)': + '@testing-library/react@15.0.7(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)': dependencies: '@babel/runtime': 7.27.0 '@testing-library/dom': 10.1.0 '@types/react-dom': 19.2.1(@types/react@19.2.2) - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@types/react': 19.2.2 @@ -26116,14 +26116,14 @@ snapshots: cmd-shim@7.0.0: {} - cmdk@1.0.4(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218): + cmdk@1.0.4(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116): dependencies: - '@radix-ui/react-dialog': 1.1.4(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) - use-sync-external-store: 1.5.0(react@19.3.0-canary-65eec428-20251218) + '@radix-ui/react-dialog': 1.1.4(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) + use-sync-external-store: 1.5.0(react@19.3.0-canary-bef88f7c-20260116) transitivePeerDependencies: - '@types/react' - '@types/react-dom' @@ -28157,7 +28157,7 @@ snapshots: - bluebird - supports-color - eslint-plugin-react-hooks@0.0.0-experimental-65eec428-20251218(eslint@9.37.0(jiti@2.5.1)): + eslint-plugin-react-hooks@0.0.0-experimental-bef88f7c-20260116(eslint@9.37.0(jiti@2.5.1)): dependencies: '@babel/core': 7.26.10 '@babel/parser': 7.27.0 @@ -29115,7 +29115,7 @@ snapshots: fsevents@2.3.3: optional: true - fumadocs-core@15.7.12(@types/react@19.2.2)(next@15.5.8(@babel/core@7.26.10)(@opentelemetry/api@1.6.0)(@playwright/test@1.51.1)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-3fde738-20250918)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)(sass@1.77.8))(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218): + fumadocs-core@15.7.12(@types/react@19.2.2)(next@15.5.8(@babel/core@7.26.10)(@opentelemetry/api@1.6.0)(@playwright/test@1.51.1)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-3fde738-20250918)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)(sass@1.77.8))(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116): dependencies: '@formatjs/intl-localematcher': 0.6.1 '@orama/orama': 3.1.13 @@ -29127,7 +29127,7 @@ snapshots: image-size: 2.0.2 negotiator: 1.0.0 npm-to-yarn: 3.0.1 - react-remove-scroll: 2.7.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) + react-remove-scroll: 2.7.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) remark: 15.0.1 remark-gfm: 4.0.1 remark-rehype: 11.1.2 @@ -29136,20 +29136,20 @@ snapshots: unist-util-visit: 5.0.0 optionalDependencies: '@types/react': 19.2.2 - next: 15.5.8(@babel/core@7.26.10)(@opentelemetry/api@1.6.0)(@playwright/test@1.51.1)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-3fde738-20250918)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)(sass@1.77.8) - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + next: 15.5.8(@babel/core@7.26.10)(@opentelemetry/api@1.6.0)(@playwright/test@1.51.1)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-3fde738-20250918)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)(sass@1.77.8) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) transitivePeerDependencies: - supports-color - fumadocs-mdx@11.10.0(fumadocs-core@15.7.12(@types/react@19.2.2)(next@15.5.8(@babel/core@7.26.10)(@opentelemetry/api@1.6.0)(@playwright/test@1.51.1)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-3fde738-20250918)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)(sass@1.77.8))(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218))(next@15.5.8(@babel/core@7.26.10)(@opentelemetry/api@1.6.0)(@playwright/test@1.51.1)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-3fde738-20250918)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)(sass@1.77.8))(react@19.3.0-canary-65eec428-20251218): + fumadocs-mdx@11.10.0(fumadocs-core@15.7.12(@types/react@19.2.2)(next@15.5.8(@babel/core@7.26.10)(@opentelemetry/api@1.6.0)(@playwright/test@1.51.1)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-3fde738-20250918)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)(sass@1.77.8))(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116))(next@15.5.8(@babel/core@7.26.10)(@opentelemetry/api@1.6.0)(@playwright/test@1.51.1)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-3fde738-20250918)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)(sass@1.77.8))(react@19.3.0-canary-bef88f7c-20260116): dependencies: '@mdx-js/mdx': 3.1.1 '@standard-schema/spec': 1.0.0 chokidar: 4.0.3 esbuild: 0.25.9 estree-util-value-to-estree: 3.5.0 - fumadocs-core: 15.7.12(@types/react@19.2.2)(next@15.5.8(@babel/core@7.26.10)(@opentelemetry/api@1.6.0)(@playwright/test@1.51.1)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-3fde738-20250918)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)(sass@1.77.8))(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) + fumadocs-core: 15.7.12(@types/react@19.2.2)(next@15.5.8(@babel/core@7.26.10)(@opentelemetry/api@1.6.0)(@playwright/test@1.51.1)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-3fde738-20250918)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)(sass@1.77.8))(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) js-yaml: 4.1.0 lru-cache: 11.2.1 picocolors: 1.1.1 @@ -29161,36 +29161,36 @@ snapshots: unist-util-visit: 5.0.0 zod: 4.1.13 optionalDependencies: - next: 15.5.8(@babel/core@7.26.10)(@opentelemetry/api@1.6.0)(@playwright/test@1.51.1)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-3fde738-20250918)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)(sass@1.77.8) - react: 19.3.0-canary-65eec428-20251218 + next: 15.5.8(@babel/core@7.26.10)(@opentelemetry/api@1.6.0)(@playwright/test@1.51.1)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-3fde738-20250918)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)(sass@1.77.8) + react: 19.3.0-canary-bef88f7c-20260116 transitivePeerDependencies: - supports-color - fumadocs-ui@15.7.12(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(next@15.5.8(@babel/core@7.26.10)(@opentelemetry/api@1.6.0)(@playwright/test@1.51.1)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-3fde738-20250918)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)(sass@1.77.8))(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)(tailwindcss@4.1.13): - dependencies: - '@radix-ui/react-accordion': 1.2.12(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-collapsible': 1.1.12(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-dialog': 1.1.15(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-navigation-menu': 1.2.14(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-popover': 1.1.15(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-scroll-area': 1.2.10(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - '@radix-ui/react-tabs': 1.1.13(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) + fumadocs-ui@15.7.12(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(next@15.5.8(@babel/core@7.26.10)(@opentelemetry/api@1.6.0)(@playwright/test@1.51.1)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-3fde738-20250918)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)(sass@1.77.8))(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)(tailwindcss@4.1.13): + dependencies: + '@radix-ui/react-accordion': 1.2.12(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-collapsible': 1.1.12(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-dialog': 1.1.15(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-navigation-menu': 1.2.14(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-popover': 1.1.15(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-scroll-area': 1.2.10(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-slot': 1.2.3(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + '@radix-ui/react-tabs': 1.1.13(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) class-variance-authority: 0.7.1 - fumadocs-core: 15.7.12(@types/react@19.2.2)(next@15.5.8(@babel/core@7.26.10)(@opentelemetry/api@1.6.0)(@playwright/test@1.51.1)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-3fde738-20250918)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)(sass@1.77.8))(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) + fumadocs-core: 15.7.12(@types/react@19.2.2)(next@15.5.8(@babel/core@7.26.10)(@opentelemetry/api@1.6.0)(@playwright/test@1.51.1)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-3fde738-20250918)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)(sass@1.77.8))(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) lodash.merge: 4.6.2 - next-themes: 0.4.6(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) + next-themes: 0.4.6(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) postcss-selector-parser: 7.1.0 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) - react-medium-image-zoom: 5.3.0(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) + react-medium-image-zoom: 5.3.0(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116) scroll-into-view-if-needed: 3.1.0 tailwind-merge: 3.3.1 optionalDependencies: '@types/react': 19.2.2 - next: 15.5.8(@babel/core@7.26.10)(@opentelemetry/api@1.6.0)(@playwright/test@1.51.1)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-3fde738-20250918)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)(sass@1.77.8) + next: 15.5.8(@babel/core@7.26.10)(@opentelemetry/api@1.6.0)(@playwright/test@1.51.1)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-3fde738-20250918)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)(sass@1.77.8) tailwindcss: 4.1.13 transitivePeerDependencies: - '@mixedbread/sdk' @@ -29862,7 +29862,7 @@ snapshots: hoist-non-react-statics@3.3.2: dependencies: - react-is: 19.3.0-canary-65eec428-20251218 + react-is: 19.3.0-canary-bef88f7c-20260116 homedir-polyfill@1.0.3: dependencies: @@ -32135,9 +32135,9 @@ snapshots: dependencies: react: 19.3.0-canary-fd524fe0-20251121 - lucide-react@0.554.0(react@19.3.0-canary-65eec428-20251218): + lucide-react@0.554.0(react@19.3.0-canary-bef88f7c-20260116): dependencies: - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 lz-string@1.5.0: {} @@ -33495,22 +33495,22 @@ snapshots: dependencies: inherits: 2.0.4 - next-themes@0.4.6(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218): + next-themes@0.4.6(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116): dependencies: - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) next-tick@1.0.0: {} - next@15.5.8(@babel/core@7.26.10)(@opentelemetry/api@1.6.0)(@playwright/test@1.51.1)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-3fde738-20250918)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)(sass@1.77.8): + next@15.5.8(@babel/core@7.26.10)(@opentelemetry/api@1.6.0)(@playwright/test@1.51.1)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-3fde738-20250918)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)(sass@1.77.8): dependencies: '@next/env': 15.5.8 '@swc/helpers': 0.5.15 caniuse-lite: 1.0.30001746 postcss: 8.4.31 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) - styled-jsx: 5.1.6(@babel/core@7.26.10)(babel-plugin-macros@3.1.0)(react@19.3.0-canary-65eec428-20251218) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) + styled-jsx: 5.1.6(@babel/core@7.26.10)(babel-plugin-macros@3.1.0)(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@next/swc-darwin-arm64': 15.5.7 '@next/swc-darwin-x64': 15.5.7 @@ -33529,15 +33529,15 @@ snapshots: - '@babel/core' - babel-plugin-macros - next@16.0.8(@babel/core@7.26.10)(@opentelemetry/api@1.6.0)(@playwright/test@1.51.1)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-3fde738-20250918)(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)(sass@1.77.8): + next@16.0.8(@babel/core@7.26.10)(@opentelemetry/api@1.6.0)(@playwright/test@1.51.1)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-3fde738-20250918)(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)(sass@1.77.8): dependencies: '@next/env': 16.0.8 '@swc/helpers': 0.5.15 caniuse-lite: 1.0.30001746 postcss: 8.4.31 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) - styled-jsx: 5.1.6(@babel/core@7.26.10)(babel-plugin-macros@3.1.0)(react@19.3.0-canary-65eec428-20251218) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) + styled-jsx: 5.1.6(@babel/core@7.26.10)(babel-plugin-macros@3.1.0)(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@next/swc-darwin-arm64': 16.0.8 '@next/swc-darwin-x64': 16.0.8 @@ -35373,31 +35373,31 @@ snapshots: dependencies: ansi-regex: 5.0.1 ansi-styles: 5.2.0 - react-is: 19.3.0-canary-65eec428-20251218 + react-is: 19.3.0-canary-bef88f7c-20260116 pretty-format@29.5.0: dependencies: '@jest/schemas': 29.4.3 ansi-styles: 5.2.0 - react-is: 19.3.0-canary-65eec428-20251218 + react-is: 19.3.0-canary-bef88f7c-20260116 pretty-format@29.7.0: dependencies: '@jest/schemas': 29.6.3 ansi-styles: 5.2.0 - react-is: 19.3.0-canary-65eec428-20251218 + react-is: 19.3.0-canary-bef88f7c-20260116 pretty-format@30.0.0-alpha.6: dependencies: '@jest/schemas': 30.0.0-alpha.6 ansi-styles: 5.2.0 - react-is: 19.3.0-canary-65eec428-20251218 + react-is: 19.3.0-canary-bef88f7c-20260116 pretty-format@30.2.0: dependencies: '@jest/schemas': 30.0.5 ansi-styles: 5.2.0 - react-is: 19.3.0-canary-65eec428-20251218 + react-is: 19.3.0-canary-bef88f7c-20260116 pretty-ms@7.0.0: dependencies: @@ -35461,7 +35461,7 @@ snapshots: dependencies: loose-envify: 1.4.0 object-assign: 4.1.1 - react-is: 19.3.0-canary-65eec428-20251218 + react-is: 19.3.0-canary-bef88f7c-20260116 property-information@5.6.0: dependencies: @@ -35673,31 +35673,31 @@ snapshots: transitivePeerDependencies: - supports-color - react-dom@0.0.0-experimental-65eec428-20251218(react@19.3.0-canary-65eec428-20251218): + react-dom@0.0.0-experimental-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116): dependencies: - react: 19.3.0-canary-65eec428-20251218 - scheduler: 0.28.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + scheduler: 0.28.0-canary-bef88f7c-20260116 - react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218): + react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116): dependencies: - react: 19.3.0-canary-65eec428-20251218 - scheduler: 0.28.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + scheduler: 0.28.0-canary-bef88f7c-20260116 react-dom@19.3.0-canary-fd524fe0-20251121(react@19.3.0-canary-fd524fe0-20251121): dependencies: react: 19.3.0-canary-fd524fe0-20251121 - scheduler: 0.28.0-canary-65eec428-20251218 + scheduler: 0.28.0-canary-bef88f7c-20260116 - react-is@19.3.0-canary-65eec428-20251218: {} + react-is@19.3.0-canary-bef88f7c-20260116: {} react-is@19.3.0-canary-fd524fe0-20251121: {} react-lifecycles-compat@3.0.4: {} - react-medium-image-zoom@5.3.0(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218): + react-medium-image-zoom@5.3.0(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116): dependencies: - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) react-number-format@5.4.0(react-dom@19.3.0-canary-fd524fe0-20251121(react@19.3.0-canary-fd524fe0-20251121))(react@19.3.0-canary-fd524fe0-20251121): dependencies: @@ -35715,10 +35715,10 @@ snapshots: optionalDependencies: '@types/react': 19.2.2 - react-remove-scroll-bar@2.3.8(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218): + react-remove-scroll-bar@2.3.8(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116): dependencies: - react: 19.3.0-canary-65eec428-20251218 - react-style-singleton: 2.2.3(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) + react: 19.3.0-canary-bef88f7c-20260116 + react-style-singleton: 2.2.3(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) tslib: 2.8.1 optionalDependencies: '@types/react': 19.2.2 @@ -35734,59 +35734,59 @@ snapshots: optionalDependencies: '@types/react': 19.2.2 - react-remove-scroll@2.7.1(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218): + react-remove-scroll@2.7.1(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116): dependencies: - react: 19.3.0-canary-65eec428-20251218 - react-remove-scroll-bar: 2.3.8(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - react-style-singleton: 2.2.3(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) + react: 19.3.0-canary-bef88f7c-20260116 + react-remove-scroll-bar: 2.3.8(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + react-style-singleton: 2.2.3(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) tslib: 2.8.1 - use-callback-ref: 1.3.3(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) - use-sidecar: 1.1.3(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218) + use-callback-ref: 1.3.3(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) + use-sidecar: 1.1.3(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116) optionalDependencies: '@types/react': 19.2.2 - react-server-dom-turbopack@0.0.0-experimental-65eec428-20251218(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218): + react-server-dom-turbopack@0.0.0-experimental-bef88f7c-20260116(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116): dependencies: acorn-loose: 8.3.0 neo-async: 2.6.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) - react-server-dom-turbopack@19.3.0-canary-65eec428-20251218(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218): + react-server-dom-turbopack@19.3.0-canary-bef88f7c-20260116(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116): dependencies: acorn-loose: 8.3.0 neo-async: 2.6.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) - react-server-dom-webpack@0.0.0-experimental-65eec428-20251218(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)(webpack@5.98.0(@swc/core@1.11.24(@swc/helpers@0.5.15))): + react-server-dom-webpack@0.0.0-experimental-bef88f7c-20260116(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)(webpack@5.98.0(@swc/core@1.11.24(@swc/helpers@0.5.15))): dependencies: acorn-loose: 8.3.0 neo-async: 2.6.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) webpack: 5.98.0(@swc/core@1.11.24(@swc/helpers@0.5.15)) webpack-sources: 3.2.3(patch_hash=jbynf5dc46ambamq3wuyho6hkq) - react-server-dom-webpack@19.3.0-canary-65eec428-20251218(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218)(webpack@5.98.0(@swc/core@1.11.24(@swc/helpers@0.5.15))): + react-server-dom-webpack@19.3.0-canary-bef88f7c-20260116(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116)(webpack@5.98.0(@swc/core@1.11.24(@swc/helpers@0.5.15))): dependencies: acorn-loose: 8.3.0 neo-async: 2.6.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) webpack: 5.98.0(@swc/core@1.11.24(@swc/helpers@0.5.15)) webpack-sources: 3.2.3(patch_hash=jbynf5dc46ambamq3wuyho6hkq) - react-shallow-renderer@16.15.0(react@19.3.0-canary-65eec428-20251218): + react-shallow-renderer@16.15.0(react@19.3.0-canary-bef88f7c-20260116): dependencies: object-assign: 4.1.1 - react: 19.3.0-canary-65eec428-20251218 - react-is: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-is: 19.3.0-canary-bef88f7c-20260116 - react-ssr-prepass@1.0.8(react-is@19.3.0-canary-fd524fe0-20251121)(react@19.3.0-canary-65eec428-20251218): + react-ssr-prepass@1.0.8(react-is@19.3.0-canary-fd524fe0-20251121)(react@19.3.0-canary-bef88f7c-20260116): dependencies: object-is: 1.0.2 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 react-is: 19.3.0-canary-fd524fe0-20251121 react-style-singleton@2.2.1(@types/react@19.2.2)(react@19.3.0-canary-fd524fe0-20251121): @@ -35798,10 +35798,10 @@ snapshots: optionalDependencies: '@types/react': 19.2.2 - react-style-singleton@2.2.3(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218): + react-style-singleton@2.2.3(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116): dependencies: get-nonce: 1.0.1 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 tslib: 2.8.1 optionalDependencies: '@types/react': 19.2.2 @@ -35814,12 +35814,12 @@ snapshots: optionalDependencies: '@types/react': 19.2.2 - react-test-renderer@18.2.0(react@19.3.0-canary-65eec428-20251218): + react-test-renderer@18.2.0(react@19.3.0-canary-bef88f7c-20260116): dependencies: - react: 19.3.0-canary-65eec428-20251218 - react-is: 19.3.0-canary-65eec428-20251218 - react-shallow-renderer: 16.15.0(react@19.3.0-canary-65eec428-20251218) - scheduler: 0.28.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 + react-is: 19.3.0-canary-bef88f7c-20260116 + react-shallow-renderer: 16.15.0(react@19.3.0-canary-bef88f7c-20260116) + scheduler: 0.28.0-canary-bef88f7c-20260116 react-textarea-autosize@8.5.3(@types/react@19.2.2)(react@19.3.0-canary-fd524fe0-20251121): dependencies: @@ -35830,20 +35830,20 @@ snapshots: transitivePeerDependencies: - '@types/react' - react-virtualized@9.22.3(react-dom@19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218))(react@19.3.0-canary-65eec428-20251218): + react-virtualized@9.22.3(react-dom@19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116))(react@19.3.0-canary-bef88f7c-20260116): dependencies: '@babel/runtime': 7.27.0 clsx: 1.1.1 dom-helpers: 5.2.1 loose-envify: 1.4.0 prop-types: 15.8.1 - react: 19.3.0-canary-65eec428-20251218 - react-dom: 19.3.0-canary-65eec428-20251218(react@19.3.0-canary-65eec428-20251218) + react: 19.3.0-canary-bef88f7c-20260116 + react-dom: 19.3.0-canary-bef88f7c-20260116(react@19.3.0-canary-bef88f7c-20260116) react-lifecycles-compat: 3.0.4 - react@0.0.0-experimental-65eec428-20251218: {} + react@0.0.0-experimental-bef88f7c-20260116: {} - react@19.3.0-canary-65eec428-20251218: {} + react@19.3.0-canary-bef88f7c-20260116: {} react@19.3.0-canary-fd524fe0-20251121: {} @@ -36671,9 +36671,9 @@ snapshots: dependencies: xmlchars: 2.2.0 - scheduler@0.0.0-experimental-65eec428-20251218: {} + scheduler@0.0.0-experimental-bef88f7c-20260116: {} - scheduler@0.28.0-canary-65eec428-20251218: {} + scheduler@0.28.0-canary-bef88f7c-20260116: {} schema-utils@2.7.1: dependencies: @@ -37566,10 +37566,10 @@ snapshots: postcss: 7.0.32 postcss-load-plugins: 2.3.0 - styled-jsx@5.1.6(@babel/core@7.26.10)(babel-plugin-macros@3.1.0)(react@19.3.0-canary-65eec428-20251218): + styled-jsx@5.1.6(@babel/core@7.26.10)(babel-plugin-macros@3.1.0)(react@19.3.0-canary-bef88f7c-20260116): dependencies: client-only: 0.0.1 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 optionalDependencies: '@babel/core': 7.26.10 babel-plugin-macros: 3.1.0 @@ -37673,11 +37673,11 @@ snapshots: '@swc/counter': 0.1.3 webpack: 5.98.0(@swc/core@1.11.24(@swc/helpers@0.5.15))(esbuild@0.25.9) - swr@2.2.4(react@19.3.0-canary-65eec428-20251218): + swr@2.2.4(react@19.3.0-canary-bef88f7c-20260116): dependencies: client-only: 0.0.1 - react: 19.3.0-canary-65eec428-20251218 - use-sync-external-store: 1.5.0(react@19.3.0-canary-65eec428-20251218) + react: 19.3.0-canary-bef88f7c-20260116 + use-sync-external-store: 1.5.0(react@19.3.0-canary-bef88f7c-20260116) symbol-observable@1.0.1: {} @@ -38533,9 +38533,9 @@ snapshots: unist-util-is: 6.0.0 unist-util-visit-parents: 6.0.1 - unistore@3.4.1(react@19.3.0-canary-65eec428-20251218): + unistore@3.4.1(react@19.3.0-canary-bef88f7c-20260116): optionalDependencies: - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 universal-github-app-jwt@1.1.1: dependencies: @@ -38670,9 +38670,9 @@ snapshots: optionalDependencies: '@types/react': 19.2.2 - use-callback-ref@1.3.3(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218): + use-callback-ref@1.3.3(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116): dependencies: - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 tslib: 2.8.1 optionalDependencies: '@types/react': 19.2.2 @@ -38702,17 +38702,17 @@ snapshots: optionalDependencies: '@types/react': 19.2.2 - use-sidecar@1.1.3(@types/react@19.2.2)(react@19.3.0-canary-65eec428-20251218): + use-sidecar@1.1.3(@types/react@19.2.2)(react@19.3.0-canary-bef88f7c-20260116): dependencies: detect-node-es: 1.1.0 - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 tslib: 2.8.1 optionalDependencies: '@types/react': 19.2.2 - use-sync-external-store@1.5.0(react@19.3.0-canary-65eec428-20251218): + use-sync-external-store@1.5.0(react@19.3.0-canary-bef88f7c-20260116): dependencies: - react: 19.3.0-canary-65eec428-20251218 + react: 19.3.0-canary-bef88f7c-20260116 util-deprecate@1.0.2: {} diff --git a/run-tests.js b/run-tests.js index 3b3591b060ce..8dccfe3b1b84 100644 --- a/run-tests.js +++ b/run-tests.js @@ -53,10 +53,6 @@ const DEFAULT_NUM_RETRIES = 2 const DEFAULT_CONCURRENCY = 2 const RESULTS_EXT = `.results.json` const isTestJob = !!process.env.NEXT_TEST_JOB -// Check env to see if test should continue even if some of test fails -const shouldContinueTestsOnError = - process.env.NEXT_TEST_CONTINUE_ON_ERROR === 'true' - const KV_TIMINGS_KEY = 'test-timings' const kvClient = @@ -482,8 +478,6 @@ ${ENDGROUP}`) `jest${process.platform === 'win32' ? '.CMD' : ''}` ) let firstError = true - const testController = new AbortController() - const testSignal = testController.signal let hadFailures = false const runTestOnce = (/** @type {TestFile} */ test, isFinalRun, isRetry) => @@ -597,13 +591,10 @@ ${ENDGROUP}`) if (isChildExitWithNonZero) { if (hideOutput) { await outputSema.acquire() - const isExpanded = - firstError && !testSignal.aborted && !shouldContinueTestsOnError + const isExpanded = firstError if (isExpanded) { firstError = false process.stdout.write(`❌ ${test.file} output:\n`) - } else if (testSignal.aborted) { - process.stdout.write(`${GROUP}${test.file} output (killed)\n`) } else { process.stdout.write(`${GROUP}❌ ${test.file} output\n`) } @@ -616,7 +607,7 @@ ${ENDGROUP}`) output += chunk.toString() } - if (process.env.CI && !testSignal.aborted) { + if (process.env.CI) { errorsPerTests.set(test.file, output) } @@ -700,24 +691,12 @@ ${ENDGROUP}`) if (!passed) { hadFailures = true - const error = new Error( - // "failed to pass within" is a keyword parsed by next-pr-webhook - `${test.file} failed to pass within ${numRetries} retries` - ) - console.error(error.message) - - if (!shouldContinueTestsOnError) { - testController.abort(error) - } else { - console.log( - `CONTINUE_ON_ERROR enabled, continuing tests after ${test.file} failed` - ) - } + // "failed to pass within" is a keyword parsed by next-pr-webhook + console.error(`${test.file} failed to pass within ${numRetries} retries`) } - // Emit test output if test failed or if we're continuing tests on error - // This is parsed by the commenter webhook to notify about failing tests - if ((!passed || shouldContinueTestsOnError) && isTestJob) { + // Emit test output, parsed by the commenter webhook to notify about failing tests + if (!passed && isTestJob) { try { const testsOutput = await fsp.readFile( `${test.file}${RESULTS_EXT}`, @@ -761,13 +740,6 @@ ${ENDGROUP}`) await sema.acquire() try { - if (testSignal.aborted) { - // We already logged the abort reason. No need to include it in cause. - const error = new Error(`Skipped due to abort.`) - error.name = test.file - throw error - } - await runTest(test) } finally { sema.release() @@ -783,11 +755,6 @@ ${ENDGROUP}`) } } - if (hadFailures && !shouldContinueTestsOnError) { - // TODO: Does it make sense to update timings if there were failures if without shouldContinueTestsOnError? - return hadFailures - } - if (options.timings) { const curTimings = {} // let junitData = `` diff --git a/test/development/acceptance/ReactRefreshLogBox.test.ts b/test/development/acceptance/ReactRefreshLogBox.test.ts index 3376c3e8908c..8355359bff8d 100644 --- a/test/development/acceptance/ReactRefreshLogBox.test.ts +++ b/test/development/acceptance/ReactRefreshLogBox.test.ts @@ -633,6 +633,20 @@ describe('ReactRefreshLogBox', () => { ], } `) + } else if (isTurbopack) { + await expect(browser).toDisplayRedbox(` + { + "description": "", + "environmentLabel": null, + "label": "Runtime Error", + "source": "Child.js (4:11) @ ClickCount.render + > 4 | throw new Error() + | ^", + "stack": [ + "ClickCount.render Child.js (4:11)", + ], + } + `) } else { await expect(browser).toDisplayRedbox(` { diff --git a/test/development/acceptance/error-recovery.test.ts b/test/development/acceptance/error-recovery.test.ts index 00915a3c930a..664fef247449 100644 --- a/test/development/acceptance/error-recovery.test.ts +++ b/test/development/acceptance/error-recovery.test.ts @@ -313,6 +313,20 @@ describe('pages/ error recovery', () => { ], } `) + } else if (isTurbopack) { + await expect(browser).toDisplayRedbox(` + { + "description": "oops", + "environmentLabel": null, + "label": "Runtime Error", + "source": "child.js (3:9) @ Child + > 3 | throw new Error('oops') + | ^", + "stack": [ + "Child child.js (3:9)", + ], + } + `) } else { await expect(browser).toDisplayRedbox(` { diff --git a/test/development/app-dir/browser-log-forwarding/fixtures/error-level/app/layout.tsx b/test/development/app-dir/browser-log-forwarding/fixtures/error-level/app/layout.tsx new file mode 100644 index 000000000000..08eaa94fdc88 --- /dev/null +++ b/test/development/app-dir/browser-log-forwarding/fixtures/error-level/app/layout.tsx @@ -0,0 +1,11 @@ +export default function RootLayout({ + children, +}: { + children: React.ReactNode +}) { + return ( + + {children} + + ) +} diff --git a/test/development/app-dir/browser-log-forwarding/fixtures/error-level/app/page.tsx b/test/development/app-dir/browser-log-forwarding/fixtures/error-level/app/page.tsx new file mode 100644 index 000000000000..fe6fba3965b3 --- /dev/null +++ b/test/development/app-dir/browser-log-forwarding/fixtures/error-level/app/page.tsx @@ -0,0 +1,15 @@ +'use client' + +import { useEffect } from 'react' + +export default function Page() { + useEffect(() => { + console.log('browser log: this is a log message') + console.info('browser info: this is an info message') + console.warn('browser warn: this is a warning message') + console.error('browser error: this is an error message') + console.debug('browser debug: this is a debug message') + }, []) + + return

Browser Log Forwarding Test

+} diff --git a/test/development/app-dir/browser-log-forwarding/fixtures/error-level/error-level.test.ts b/test/development/app-dir/browser-log-forwarding/fixtures/error-level/error-level.test.ts new file mode 100644 index 000000000000..f320803582e6 --- /dev/null +++ b/test/development/app-dir/browser-log-forwarding/fixtures/error-level/error-level.test.ts @@ -0,0 +1,35 @@ +import { nextTestSetup } from 'e2e-utils' +import { retry } from 'next-test-utils' + +describe('browser-log-forwarding error level', () => { + const { next } = nextTestSetup({ + files: __dirname, + }) + + it('should only forward error logs to terminal', async () => { + const outputIndex = next.cliOutput.length + await next.browser('/') + + await retry(() => { + const output = next.cliOutput.slice(outputIndex) + expect(output).toContain('browser error:') + }) + + // Get final output after logs are forwarded + const output = next.cliOutput.slice(outputIndex) + + // Filter to only browser forwarded logs, excluding hydration noise + const browserLogs = output + .split('\n') + .filter( + (line) => + line.includes('[browser]') && + !line.includes('Next.js hydrate callback fire') + ) + .join('\n') + + expect(browserLogs).toMatchInlineSnapshot( + `"[browser] browser error: this is an error message "` + ) + }) +}) diff --git a/test/e2e/app-dir/cdn-cache-control-header/next.config.js b/test/development/app-dir/browser-log-forwarding/fixtures/error-level/next.config.js similarity index 62% rename from test/e2e/app-dir/cdn-cache-control-header/next.config.js rename to test/development/app-dir/browser-log-forwarding/fixtures/error-level/next.config.js index 57ec2bcaa491..587191004a62 100644 --- a/test/e2e/app-dir/cdn-cache-control-header/next.config.js +++ b/test/development/app-dir/browser-log-forwarding/fixtures/error-level/next.config.js @@ -2,9 +2,8 @@ * @type {import('next').NextConfig} */ const nextConfig = { - cacheComponents: true, experimental: { - cdnCacheControlHeader: 'Surrogate-Control', + browserDebugInfoInTerminal: 'error', }, } diff --git a/test/development/app-dir/browser-log-forwarding/fixtures/verbose-level/app/layout.tsx b/test/development/app-dir/browser-log-forwarding/fixtures/verbose-level/app/layout.tsx new file mode 100644 index 000000000000..08eaa94fdc88 --- /dev/null +++ b/test/development/app-dir/browser-log-forwarding/fixtures/verbose-level/app/layout.tsx @@ -0,0 +1,11 @@ +export default function RootLayout({ + children, +}: { + children: React.ReactNode +}) { + return ( + + {children} + + ) +} diff --git a/test/development/app-dir/browser-log-forwarding/fixtures/verbose-level/app/page.tsx b/test/development/app-dir/browser-log-forwarding/fixtures/verbose-level/app/page.tsx new file mode 100644 index 000000000000..fe6fba3965b3 --- /dev/null +++ b/test/development/app-dir/browser-log-forwarding/fixtures/verbose-level/app/page.tsx @@ -0,0 +1,15 @@ +'use client' + +import { useEffect } from 'react' + +export default function Page() { + useEffect(() => { + console.log('browser log: this is a log message') + console.info('browser info: this is an info message') + console.warn('browser warn: this is a warning message') + console.error('browser error: this is an error message') + console.debug('browser debug: this is a debug message') + }, []) + + return

Browser Log Forwarding Test

+} diff --git a/test/development/app-dir/browser-log-forwarding/fixtures/verbose-level/next.config.js b/test/development/app-dir/browser-log-forwarding/fixtures/verbose-level/next.config.js new file mode 100644 index 000000000000..9372e26f4098 --- /dev/null +++ b/test/development/app-dir/browser-log-forwarding/fixtures/verbose-level/next.config.js @@ -0,0 +1,10 @@ +/** + * @type {import('next').NextConfig} + */ +const nextConfig = { + experimental: { + browserDebugInfoInTerminal: 'verbose', + }, +} + +module.exports = nextConfig diff --git a/test/development/app-dir/browser-log-forwarding/fixtures/verbose-level/verbose-level.test.ts b/test/development/app-dir/browser-log-forwarding/fixtures/verbose-level/verbose-level.test.ts new file mode 100644 index 000000000000..5d593d8144cc --- /dev/null +++ b/test/development/app-dir/browser-log-forwarding/fixtures/verbose-level/verbose-level.test.ts @@ -0,0 +1,45 @@ +import { nextTestSetup } from 'e2e-utils' +import { retry } from 'next-test-utils' + +describe('browser-log-forwarding verbose level', () => { + const { next } = nextTestSetup({ + files: __dirname, + }) + + it('should forward all logs to terminal', async () => { + const outputIndex = next.cliOutput.length + await next.browser('/') + + await retry(() => { + const output = next.cliOutput.slice(outputIndex) + expect(output).toContain('browser error:') + expect(output).toContain('browser warn:') + expect(output).toContain('browser log:') + }) + + // Get final output after logs are forwarded + const output = next.cliOutput.slice(outputIndex) + + // Filter to only browser forwarded logs, excluding noise + const browserLogs = output + .split('\n') + .filter( + (line) => + line.includes('[browser]') && + !line.includes('Next.js hydrate callback fire') && + !line.includes('connected to ws at') && + !line.includes('received ws message') && + !line.includes('Download the React DevTools') && + !line.includes('Next.js page already hydrated') + ) + .join('\n') + + expect(browserLogs).toMatchInlineSnapshot(` + "[browser] browser log: this is a log message (app/page.tsx:7:13) + [browser] browser info: this is an info message (app/page.tsx:8:13) + [browser] browser warn: this is a warning message (app/page.tsx:9:13) + [browser] browser error: this is an error message + [browser] browser debug: this is a debug message (app/page.tsx:11:13)" + `) + }) +}) diff --git a/test/development/app-dir/browser-log-forwarding/fixtures/warn-level/app/layout.tsx b/test/development/app-dir/browser-log-forwarding/fixtures/warn-level/app/layout.tsx new file mode 100644 index 000000000000..08eaa94fdc88 --- /dev/null +++ b/test/development/app-dir/browser-log-forwarding/fixtures/warn-level/app/layout.tsx @@ -0,0 +1,11 @@ +export default function RootLayout({ + children, +}: { + children: React.ReactNode +}) { + return ( + + {children} + + ) +} diff --git a/test/development/app-dir/browser-log-forwarding/fixtures/warn-level/app/page.tsx b/test/development/app-dir/browser-log-forwarding/fixtures/warn-level/app/page.tsx new file mode 100644 index 000000000000..fe6fba3965b3 --- /dev/null +++ b/test/development/app-dir/browser-log-forwarding/fixtures/warn-level/app/page.tsx @@ -0,0 +1,15 @@ +'use client' + +import { useEffect } from 'react' + +export default function Page() { + useEffect(() => { + console.log('browser log: this is a log message') + console.info('browser info: this is an info message') + console.warn('browser warn: this is a warning message') + console.error('browser error: this is an error message') + console.debug('browser debug: this is a debug message') + }, []) + + return

Browser Log Forwarding Test

+} diff --git a/test/development/app-dir/browser-log-forwarding/fixtures/warn-level/next.config.js b/test/development/app-dir/browser-log-forwarding/fixtures/warn-level/next.config.js new file mode 100644 index 000000000000..dfd06f543b91 --- /dev/null +++ b/test/development/app-dir/browser-log-forwarding/fixtures/warn-level/next.config.js @@ -0,0 +1,10 @@ +/** + * @type {import('next').NextConfig} + */ +const nextConfig = { + experimental: { + browserDebugInfoInTerminal: 'warn', + }, +} + +module.exports = nextConfig diff --git a/test/development/app-dir/browser-log-forwarding/fixtures/warn-level/warn-level.test.ts b/test/development/app-dir/browser-log-forwarding/fixtures/warn-level/warn-level.test.ts new file mode 100644 index 000000000000..70b42e824b81 --- /dev/null +++ b/test/development/app-dir/browser-log-forwarding/fixtures/warn-level/warn-level.test.ts @@ -0,0 +1,37 @@ +import { nextTestSetup } from 'e2e-utils' +import { retry } from 'next-test-utils' + +describe('browser-log-forwarding warn level', () => { + const { next } = nextTestSetup({ + files: __dirname, + }) + + it('should forward warn and error logs to terminal', async () => { + const outputIndex = next.cliOutput.length + await next.browser('/') + + await retry(() => { + const output = next.cliOutput.slice(outputIndex) + expect(output).toContain('browser error:') + expect(output).toContain('browser warn:') + }) + + // Get final output after logs are forwarded + const output = next.cliOutput.slice(outputIndex) + + // Filter to only browser forwarded logs, excluding hydration noise + const browserLogs = output + .split('\n') + .filter( + (line) => + line.includes('[browser]') && + !line.includes('Next.js hydrate callback fire') + ) + .join('\n') + + expect(browserLogs).toMatchInlineSnapshot(` + "[browser] browser warn: this is a warning message (app/page.tsx:9:13) + [browser] browser error: this is an error message " + `) + }) +}) diff --git a/test/development/app-dir/isolated-dev-build-strict-route-types/app/layout.tsx b/test/development/app-dir/isolated-dev-build-strict-route-types/app/layout.tsx new file mode 100644 index 000000000000..08eaa94fdc88 --- /dev/null +++ b/test/development/app-dir/isolated-dev-build-strict-route-types/app/layout.tsx @@ -0,0 +1,11 @@ +export default function RootLayout({ + children, +}: { + children: React.ReactNode +}) { + return ( + + {children} + + ) +} diff --git a/test/development/app-dir/isolated-dev-build-strict-route-types/app/page.tsx b/test/development/app-dir/isolated-dev-build-strict-route-types/app/page.tsx new file mode 100644 index 000000000000..ff7159d9149f --- /dev/null +++ b/test/development/app-dir/isolated-dev-build-strict-route-types/app/page.tsx @@ -0,0 +1,3 @@ +export default function Page() { + return

hello world

+} diff --git a/test/development/app-dir/isolated-dev-build-strict-route-types/isolated-dev-build-strict-route-types.test.ts b/test/development/app-dir/isolated-dev-build-strict-route-types/isolated-dev-build-strict-route-types.test.ts new file mode 100644 index 000000000000..74867182b022 --- /dev/null +++ b/test/development/app-dir/isolated-dev-build-strict-route-types/isolated-dev-build-strict-route-types.test.ts @@ -0,0 +1,52 @@ +import { nextTestSetup } from 'e2e-utils' +import { retry } from 'next-test-utils' + +describe('isolated-dev-build with strictRouteTypes', () => { + const { next } = nextTestSetup({ + files: __dirname, + }) + + it('should use fixed path in next-env.d.ts with strictRouteTypes enabled', async () => { + await retry(async () => { + // next-env.d.ts should use the fixed path .next/types/routes.d.ts + // not the dev-specific path .next/dev/types/routes.d.ts + // even with strictRouteTypes enabled + const nextEnvContent = await next.readFile('next-env.d.ts') + expect(nextEnvContent).toContain('import "./.next/types/routes.d.ts"') + expect(nextEnvContent).not.toContain('.next/dev/types') + + // With strictRouteTypes enabled, next-env.d.ts should NOT have + // additional imports for cache-life, validator, link + // These are now re-exported from the entry file + expect(nextEnvContent).not.toContain('cache-life') + expect(nextEnvContent).not.toContain('validator') + expect(nextEnvContent).not.toContain('link.d.ts') + }) + }) + + it('should create entry file that re-exports strict route type files', async () => { + await retry(async () => { + // The entry file should exist at the fixed path + expect(await next.hasFile('.next/types/routes.d.ts')).toBe(true) + + // The entry file should reference the actual types in .next/dev/types + const entryFileContent = await next.readFile('.next/types/routes.d.ts') + expect(entryFileContent).toContain('route-types.d.ts') + expect(entryFileContent).toContain('../dev/types/') + + // With strictRouteTypes enabled, entry file should also reference + // cache-life.d.ts and validator.ts + expect(entryFileContent).toContain('cache-life.d.ts') + expect(entryFileContent).toContain('validator.ts') + }) + }) + + it('should create strict route type files in .next/dev/types/', async () => { + await retry(async () => { + // Actual type files should be in .next/dev/types/ + expect(await next.hasFile('.next/dev/types/route-types.d.ts')).toBe(true) + expect(await next.hasFile('.next/dev/types/cache-life.d.ts')).toBe(true) + expect(await next.hasFile('.next/dev/types/validator.ts')).toBe(true) + }) + }) +}) diff --git a/test/development/app-dir/isolated-dev-build-strict-route-types/next.config.js b/test/development/app-dir/isolated-dev-build-strict-route-types/next.config.js new file mode 100644 index 000000000000..39e74f88eb0e --- /dev/null +++ b/test/development/app-dir/isolated-dev-build-strict-route-types/next.config.js @@ -0,0 +1,10 @@ +/** + * @type {import('next').NextConfig} + */ +const nextConfig = { + experimental: { + strictRouteTypes: true, + }, +} + +module.exports = nextConfig diff --git a/test/development/app-dir/isolated-dev-build/isolated-dev-build.test.ts b/test/development/app-dir/isolated-dev-build/isolated-dev-build.test.ts index 97533ad4c8c6..a9504e0c52e2 100644 --- a/test/development/app-dir/isolated-dev-build/isolated-dev-build.test.ts +++ b/test/development/app-dir/isolated-dev-build/isolated-dev-build.test.ts @@ -25,4 +25,33 @@ describe('isolated-dev-build', () => { expect(await browser.elementByCss('p').text()).toBe('hello updated world') }) }) + + it('should use fixed path in next-env.d.ts regardless of isolatedDevBuild', async () => { + await retry(async () => { + // next-env.d.ts should use the fixed path .next/types/routes.d.ts + // not the dev-specific path .next/dev/types/routes.d.ts + const nextEnvContent = await next.readFile('next-env.d.ts') + expect(nextEnvContent).toContain('import "./.next/types/routes.d.ts"') + expect(nextEnvContent).not.toContain('.next/dev/types') + }) + }) + + it('should create entry file at .next/types/routes.d.ts that references dev types', async () => { + await retry(async () => { + // The entry file should exist at the fixed path + expect(await next.hasFile('.next/types/routes.d.ts')).toBe(true) + + // The entry file should reference the actual types in .next/dev/types + const entryFileContent = await next.readFile('.next/types/routes.d.ts') + expect(entryFileContent).toContain('route-types.d.ts') + expect(entryFileContent).toContain('../dev/types/') + }) + }) + + it('should create actual type files in .next/dev/types/', async () => { + await retry(async () => { + // Actual type files should be in .next/dev/types/ + expect(await next.hasFile('.next/dev/types/route-types.d.ts')).toBe(true) + }) + }) }) diff --git a/test/e2e/app-dir/cache-components-segment-configs/cache-components-edge-deduplication.test.ts b/test/e2e/app-dir/cache-components-segment-configs/cache-components-edge-deduplication.test.ts index 893920ef4ed8..2dbfd8c9cf08 100644 --- a/test/e2e/app-dir/cache-components-segment-configs/cache-components-edge-deduplication.test.ts +++ b/test/e2e/app-dir/cache-components-segment-configs/cache-components-edge-deduplication.test.ts @@ -7,6 +7,14 @@ import { getRedboxDescription, getRedboxSource, } from 'next-test-utils' + +// Filter out browser log lines from CLI output to avoid counting forwarded browser errors +function filterBrowserLogs(output: string): string { + return output + .split('\n') + .filter((line) => !line.includes('[browser]')) + .join('\n') +} ;(process.env.IS_TURBOPACK_TEST ? describe : describe.skip)( 'cache-components-edge-deduplication', () => { @@ -49,7 +57,9 @@ import { Route segment config "runtime" is not compatible with \`nextConfig.cacheComponents\`. Please remove it." `) // Count occurrences of the layout error at the specific location - const layoutErrorMatches = next.cliOutput.match( + // Filter out browser logs to avoid counting forwarded browser errors + const filteredOutput = filterBrowserLogs(next.cliOutput) + const layoutErrorMatches = filteredOutput.match( /\.\/app\/edge-with-layout\/layout\.tsx:1:14/g ) // We don't show an error stack, just the individual error messages at each location diff --git a/test/e2e/app-dir/cache-components/app/server-action-inline/form.tsx b/test/e2e/app-dir/cache-components/app/server-action-inline/form.tsx index 4e3c8b9118e6..67b7e7d0931e 100644 --- a/test/e2e/app-dir/cache-components/app/server-action-inline/form.tsx +++ b/test/e2e/app-dir/cache-components/app/server-action-inline/form.tsx @@ -1,9 +1,9 @@ 'use client' -import { useActionState } from 'react' +import { ReactNode, useActionState } from 'react' import { getSentinelValue } from '../getSentinelValue' -export function Form({ action }) { +export function Form({ action }: { action: () => Promise }) { const [result, formAction] = useActionState(action, 'initial') return ( diff --git a/test/e2e/app-dir/cache-components/app/server-action-inline/page.tsx b/test/e2e/app-dir/cache-components/app/server-action-inline/page.tsx index 446341535b39..268bc5afef96 100644 --- a/test/e2e/app-dir/cache-components/app/server-action-inline/page.tsx +++ b/test/e2e/app-dir/cache-components/app/server-action-inline/page.tsx @@ -1,14 +1,26 @@ import { Form } from './form' export default function Page() { - const value = 'result' - + const simpleValue = 'result' + // JSX has debug info, which affects the serialized result + const jsxValue = and more + // Async components emit timing chunks + const timedValue = return (
{ 'use server' - return value + return ( + <> + {simpleValue} {jsxValue} {timedValue} + + ) }} /> ) } + +async function HasTimingInfo() { + await Promise.resolve() + return 'and even more' +} diff --git a/test/e2e/app-dir/cache-components/cache-components.server-action.test.ts b/test/e2e/app-dir/cache-components/cache-components.server-action.test.ts index c716dd1d1449..aadb054a2b14 100644 --- a/test/e2e/app-dir/cache-components/cache-components.server-action.test.ts +++ b/test/e2e/app-dir/cache-components/cache-components.server-action.test.ts @@ -19,21 +19,18 @@ describe('cache-components', () => { it('should not have cache components errors when encoding bound args for inline server actions', async () => { const browser = await next.browser('/server-action-inline') expect(await browser.elementByCss('p').text()).toBe('initial') - await browser.elementByCss('button').click() + if (isNextDev) { + await waitForNoRedbox(browser) + } + await browser.elementByCss('button').click() await retry(async () => { - expect(await browser.elementByCss('p').text()).toBe('result') + expect(await browser.elementByCss('p').text()).toBe( + 'result and more and even more' + ) }) - if (isNextDev) { - // TODO(react-time-info): For experimental React in dev mode, the - // inclusion of server timings in the RSC payload makes the serialized - // bound args not suitable to be used as a cache key. When this is fixed - // we expect this error not to be logged anymore. - expect(next.cliOutput).toMatch('Error: Route "/server-action-inline"') - - await waitForNoRedbox(browser) - } + expect(next.cliOutput).not.toInclude('Error: Route "/server-action-inline"') }) it('should prerender pages with inline server actions', async () => { diff --git a/test/e2e/app-dir/cdn-cache-control-header/app/layout.tsx b/test/e2e/app-dir/cdn-cache-control-header/app/layout.tsx deleted file mode 100644 index c7295294439d..000000000000 --- a/test/e2e/app-dir/cdn-cache-control-header/app/layout.tsx +++ /dev/null @@ -1,7 +0,0 @@ -export default function Layout({ children }: { children: React.ReactNode }) { - return ( - - {children} - - ) -} diff --git a/test/e2e/app-dir/cdn-cache-control-header/app/page.tsx b/test/e2e/app-dir/cdn-cache-control-header/app/page.tsx deleted file mode 100644 index 859eee56ca4d..000000000000 --- a/test/e2e/app-dir/cdn-cache-control-header/app/page.tsx +++ /dev/null @@ -1,8 +0,0 @@ -'use cache' - -import { cacheLife } from 'next/cache' - -export default async function Page() { - cacheLife('minutes') - return

Hello World

-} diff --git a/test/e2e/app-dir/cdn-cache-control-header/cdn-cache-control-header.test.ts b/test/e2e/app-dir/cdn-cache-control-header/cdn-cache-control-header.test.ts deleted file mode 100644 index faf41f82849f..000000000000 --- a/test/e2e/app-dir/cdn-cache-control-header/cdn-cache-control-header.test.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { nextTestSetup } from 'e2e-utils' - -describe('cdn-cache-control-header', () => { - const { next, isNextDev, isNextDeploy } = nextTestSetup({ - files: __dirname, - }) - - if (isNextDeploy) { - it('should skip for deploy', () => {}) - return - } - - it('should use custom CDN cache control header name from experimental config', async () => { - const res = await next.fetch('/') - - // In dev mode, no caching headers are set - if (isNextDev) { - expect(res.headers.get('cache-control')).toBe('no-store, must-revalidate') - expect(res.headers.get('surrogate-control')).toBeNull() - expect(res.headers.get('cdn-cache-control')).toBeNull() - return - } - - expect(res.headers.get('cache-control')).toBe('s-maxage=60') - expect(res.headers.get('surrogate-control')).toMatch(/^max-age=\d+/) - expect(res.headers.get('cdn-cache-control')).toBeNull() - }) -}) diff --git a/test/e2e/app-dir/client-reference-chunking/app/issue/layout.tsx b/test/e2e/app-dir/client-reference-chunking/app/issue/layout.tsx new file mode 100644 index 000000000000..76a2e95b824c --- /dev/null +++ b/test/e2e/app-dir/client-reference-chunking/app/issue/layout.tsx @@ -0,0 +1,7 @@ +export default function SubLayout({ + children, +}: Readonly<{ + children: React.ReactNode +}>) { + return
{children}
+} diff --git a/test/e2e/app-dir/client-reference-chunking/app/issue/opengraph-image.tsx b/test/e2e/app-dir/client-reference-chunking/app/issue/opengraph-image.tsx new file mode 100644 index 000000000000..5e967faa7e41 --- /dev/null +++ b/test/e2e/app-dir/client-reference-chunking/app/issue/opengraph-image.tsx @@ -0,0 +1,32 @@ +import { ImageResponse } from 'next/og' + +// Image metadata +export const size = { + width: 516, + height: 271, +} + +export const contentType = 'image/png' + +export default async function Image() { + return new ImageResponse( + ( +
+ Issue page opengraph image +
+ ), + { + ...size, + } + ) +} diff --git a/test/e2e/app-dir/client-reference-chunking/app/issue/page.tsx b/test/e2e/app-dir/client-reference-chunking/app/issue/page.tsx new file mode 100644 index 000000000000..84c026f5e4ce --- /dev/null +++ b/test/e2e/app-dir/client-reference-chunking/app/issue/page.tsx @@ -0,0 +1,8 @@ +/** Add your relevant code here for the issue to reproduce */ +export default function IssuePage() { + return ( +
+

Welcome to the Issue Page

+
+ ) +} diff --git a/test/e2e/app-dir/client-reference-chunking/app/layout.tsx b/test/e2e/app-dir/client-reference-chunking/app/layout.tsx new file mode 100644 index 000000000000..114750e34e49 --- /dev/null +++ b/test/e2e/app-dir/client-reference-chunking/app/layout.tsx @@ -0,0 +1,20 @@ +export default function RootLayout({ + children, +}: Readonly<{ + children: React.ReactNode +}>) { + return ( + + +
+ +
+
{children}
+ + + ) +} diff --git a/test/e2e/app-dir/client-reference-chunking/app/page.tsx b/test/e2e/app-dir/client-reference-chunking/app/page.tsx new file mode 100644 index 000000000000..367e646032d8 --- /dev/null +++ b/test/e2e/app-dir/client-reference-chunking/app/page.tsx @@ -0,0 +1,10 @@ +/** Add your relevant code here for the issue to reproduce */ +export default function Home() { + return ( + + ) +} diff --git a/test/e2e/app-dir/client-reference-chunking/client-reference-chunking.test.ts b/test/e2e/app-dir/client-reference-chunking/client-reference-chunking.test.ts new file mode 100644 index 000000000000..610810173b9d --- /dev/null +++ b/test/e2e/app-dir/client-reference-chunking/client-reference-chunking.test.ts @@ -0,0 +1,38 @@ +import { type NextInstance, nextTestSetup } from 'e2e-utils' +import { type ClientReferenceManifest } from 'next/dist/build/webpack/plugins/flight-manifest-plugin' + +async function loadClientReferenceManifest( + next: NextInstance, + page: string +): Promise { + return JSON.parse( + ( + await next.readFile( + `${next.distDir}/server/app${page}page_client-reference-manifest.js` + ) + ).match(/]\s*=\s*([\S\s]+)$/)[1] + ) +} + +describe('client-reference-chunking', () => { + const { next } = nextTestSetup({ + files: __dirname, + skipDeployment: true, + }) + + it('should use the same chunks for client references across routes', async () => { + const browser = await next.browser('/') + await browser.elementByCss('a[href="/issue"]').click() + + expect(await browser.elementByCss('body').text()).toContain( + 'Welcome to the Issue Page' + ) + + let rootManifest = await loadClientReferenceManifest(next, '/') + let issueManifest = await loadClientReferenceManifest(next, '/issue/') + + // These two routes have the same client component references, so these should be exactly the + // same (especially the `chunks` field) + expect(rootManifest.clientModules).toEqual(issueManifest.clientModules) + }) +}) diff --git a/test/e2e/app-dir/client-reference-chunking/next.config.js b/test/e2e/app-dir/client-reference-chunking/next.config.js new file mode 100644 index 000000000000..807126e4cf0b --- /dev/null +++ b/test/e2e/app-dir/client-reference-chunking/next.config.js @@ -0,0 +1,6 @@ +/** + * @type {import('next').NextConfig} + */ +const nextConfig = {} + +module.exports = nextConfig diff --git a/test/e2e/app-dir/custom-cache-control/custom-cache-control.test.ts b/test/e2e/app-dir/custom-cache-control/custom-cache-control.test.ts index ce10656eeddc..ffe2610ccd03 100644 --- a/test/e2e/app-dir/custom-cache-control/custom-cache-control.test.ts +++ b/test/e2e/app-dir/custom-cache-control/custom-cache-control.test.ts @@ -31,14 +31,10 @@ describe('custom-cache-control', () => { const res = await next.fetch('/app-ssg/another') // eslint-disable-next-line jest/no-standalone-expect expect(res.headers.get('cache-control')).toBe( - isNextDev ? 'no-store, must-revalidate' : 's-maxage=120' + isNextDev + ? 'no-store, must-revalidate' + : 's-maxage=120, stale-while-revalidate=31535880' ) - if (!isNextDev) { - // eslint-disable-next-line jest/no-standalone-expect - expect(res.headers.get('cdn-cache-control')).toBe( - 'max-age=120, stale-while-revalidate=31535880' - ) - } } ) @@ -73,13 +69,10 @@ describe('custom-cache-control', () => { it('should have default cache-control for pages-ssg another', async () => { const res = await next.fetch('/pages-ssg/another') expect(res.headers.get('cache-control')).toBe( - isNextDev ? 'no-store, must-revalidate' : 's-maxage=120' + isNextDev + ? 'no-store, must-revalidate' + : 's-maxage=120, stale-while-revalidate=31535880' ) - if (!isNextDev) { - expect(res.headers.get('cdn-cache-control')).toBe( - 'max-age=120, stale-while-revalidate=31535880' - ) - } }) it('should have default cache-control for pages-ssr', async () => { diff --git a/test/e2e/app-dir/log-file/log-file.test.ts b/test/e2e/app-dir/log-file/log-file.test.ts index 11f3d0a4e9f8..79f22b614188 100644 --- a/test/e2e/app-dir/log-file/log-file.test.ts +++ b/test/e2e/app-dir/log-file/log-file.test.ts @@ -82,6 +82,8 @@ describe('log-file', () => { if (isNextDev) { await retry(async () => { const newLogContent = getNewLogContent() + // The server logs will be replayed in the browser, but they'll not be forwarded to terminal, + // as terminal already has them in the first place. expect(newLogContent).toMatchInlineSnapshot(` "[xx:xx:xx.xxx] Server LOG RSC: This is a log message from server component [xx:xx:xx.xxx] Server ERROR RSC: This is an error message from server component @@ -119,10 +121,15 @@ describe('log-file', () => { if (isNextDev) { await retry(async () => { const newLogContent = getNewLogContent() + // Only browser only logs are being forwarded to terminal expect(newLogContent).toMatchInlineSnapshot(` "[xx:xx:xx.xxx] Browser LOG Client: Complex circular object: {"data":{"nested":{"items":[1,2,3],"value":42},"parent":"[Circular]"},"metadata":{"name":"safe stringify","version":"1.0.0"},"name":"test"} [xx:xx:xx.xxx] Browser ERROR Client: This is an error message from client component [xx:xx:xx.xxx] Browser WARN Client: This is a warning message from client component + [xx:xx:xx.xxx] Server ERROR [browser] "Client: This is an error message from client component" "\\n at ClientPage.useEffect (app/client/page.tsx:25:13)\\n 23 | circularObj.data.parent = circularObj\\n 24 | console.log('Client: Complex circular object:', circularObj)\\n> 25 | console.error('Client: This is an error message from client component')\\n | ^\\n 26 | console.warn('Client: This is a warning message from client component')\\n 27 | }, [])\\n 28 |" "(app/client/page.tsx:25:13)" + [xx:xx:xx.xxx] Browser ERROR Client: This is an error message from client component "\\n at ClientPage.useEffect (app/client/page.tsx:25:13)\\n 23 | circularObj.data.parent = circularObj\\n 24 | console.log('Client: Complex circular object:', circularObj)\\n> 25 | console.error('Client: This is an error message from client component')\\n | ^\\n 26 | console.warn('Client: This is a warning message from client component')\\n 27 | }, [])\\n 28 |" "(app/client/page.tsx:25:13)" + [xx:xx:xx.xxx] Server WARN [browser] "Client: This is a warning message from client component" "(app/client/page.tsx:26:13)" + [xx:xx:xx.xxx] Browser WARN Client: This is a warning message from client component " `) }) diff --git a/test/e2e/app-dir/node-worker-threads/app/api/simple-worker-test/route.ts b/test/e2e/app-dir/node-worker-threads/app/api/simple-worker-test/route.ts new file mode 100644 index 000000000000..424514a3e6c7 --- /dev/null +++ b/test/e2e/app-dir/node-worker-threads/app/api/simple-worker-test/route.ts @@ -0,0 +1,41 @@ +import { Worker } from 'node:worker_threads' +import { NextResponse } from 'next/server' + +export async function GET() { + try { + // Test with a relative path instead of __filename + const worker = new Worker('./app/worker-dir/simple-worker.ts') + + const message = await new Promise((resolve, reject) => { + const timeout = setTimeout(() => { + reject(new Error('Worker timeout')) + }, 5000) + + worker.on('message', (msg) => { + clearTimeout(timeout) + resolve(msg) + }) + worker.on('error', (err) => { + clearTimeout(timeout) + reject(err) + }) + worker.on('exit', (code) => { + if (code !== 0) { + clearTimeout(timeout) + reject(new Error(`Worker stopped with exit code ${code}`)) + } + }) + + worker.postMessage('ping') + }) + + await worker.terminate() + + return NextResponse.json({ success: true, message }) + } catch (error) { + return NextResponse.json( + { success: false, error: String(error) }, + { status: 500 } + ) + } +} diff --git a/test/e2e/app-dir/node-worker-threads/app/api/worker-test/route.ts b/test/e2e/app-dir/node-worker-threads/app/api/worker-test/route.ts new file mode 100644 index 000000000000..89038954af4a --- /dev/null +++ b/test/e2e/app-dir/node-worker-threads/app/api/worker-test/route.ts @@ -0,0 +1,62 @@ +import { Worker, isMainThread, parentPort } from 'node:worker_threads' +import { NextResponse } from 'next/server' + +// This file tests self-referencing worker threads using __filename +// This pattern is used by libraries like @duckdb/duckdb-wasm + +if (!isMainThread && parentPort) { + // Worker thread - handle messages + parentPort.on('message', (msg) => { + if (msg === 'ping') { + parentPort!.postMessage('pong') + } + }) +} + +export async function GET() { + if (!isMainThread) { + // If we're in a worker, don't try to create another worker + return NextResponse.json({ error: 'Already in worker' }, { status: 500 }) + } + + // Log __filename for debugging + console.log('__filename:', __filename) + console.log('typeof __filename:', typeof __filename) + + try { + // Create a worker using __filename - this is the pattern that triggers the cycle bug + const worker = new Worker(__filename) + + const message = await new Promise((resolve, reject) => { + const timeout = setTimeout(() => { + reject(new Error('Worker timeout')) + }, 5000) + + worker.on('message', (msg) => { + clearTimeout(timeout) + resolve(msg) + }) + worker.on('error', (err) => { + clearTimeout(timeout) + reject(err) + }) + worker.on('exit', (code) => { + if (code !== 0) { + clearTimeout(timeout) + reject(new Error(`Worker stopped with exit code ${code}`)) + } + }) + + worker.postMessage('ping') + }) + + await worker.terminate() + + return NextResponse.json({ success: true, message }) + } catch (error) { + return NextResponse.json( + { success: false, error: String(error) }, + { status: 500 } + ) + } +} diff --git a/test/e2e/app-dir/node-worker-threads/app/layout.tsx b/test/e2e/app-dir/node-worker-threads/app/layout.tsx new file mode 100644 index 000000000000..08eaa94fdc88 --- /dev/null +++ b/test/e2e/app-dir/node-worker-threads/app/layout.tsx @@ -0,0 +1,11 @@ +export default function RootLayout({ + children, +}: { + children: React.ReactNode +}) { + return ( + + {children} + + ) +} diff --git a/test/e2e/app-dir/node-worker-threads/app/worker-dir/simple-worker.ts b/test/e2e/app-dir/node-worker-threads/app/worker-dir/simple-worker.ts new file mode 100644 index 000000000000..0aeed237ef59 --- /dev/null +++ b/test/e2e/app-dir/node-worker-threads/app/worker-dir/simple-worker.ts @@ -0,0 +1,9 @@ +import { parentPort } from 'node:worker_threads' + +if (parentPort) { + parentPort.on('message', (msg) => { + if (msg === 'ping') { + parentPort!.postMessage('pong from simple worker') + } + }) +} diff --git a/test/e2e/app-dir/node-worker-threads/node-worker-threads.test.ts b/test/e2e/app-dir/node-worker-threads/node-worker-threads.test.ts new file mode 100644 index 000000000000..ec47e8a54382 --- /dev/null +++ b/test/e2e/app-dir/node-worker-threads/node-worker-threads.test.ts @@ -0,0 +1,36 @@ +import { nextTestSetup } from 'e2e-utils' + +describe('node-worker-threads', () => { + const { next, skipped, isTurbopack } = nextTestSetup({ + files: __dirname, + skipDeployment: true, + }) + + if (skipped) { + return + } + + // These tests are Turbopack-specific since they rely on Turbopack's worker bundling + if (!isTurbopack) { + it.skip('webpack doesnt support bundling worker-threads', () => {}) + return + } + + it('should handle simple worker with relative path', async () => { + const res = await next.fetch('/api/simple-worker-test') + const data = await res.json() + console.log('Simple worker response:', data) + expect(res.status).toBe(200) + expect(data.success).toBe(true) + expect(data.message).toBe('pong from simple worker') + }) + + it('should handle self-referencing worker with __filename', async () => { + const res = await next.fetch('/api/worker-test') + const data = await res.json() + console.log('Self-ref worker response:', data) + expect(res.status).toBe(200) + expect(data.success).toBe(true) + expect(data.message).toBe('pong') + }) +}) diff --git a/test/e2e/app-dir/server-action-logging/app/action-buttons.js b/test/e2e/app-dir/server-action-logging/app/action-buttons.js new file mode 100644 index 000000000000..cc86e9780058 --- /dev/null +++ b/test/e2e/app-dir/server-action-logging/app/action-buttons.js @@ -0,0 +1,116 @@ +'use client' + +import { useState } from 'react' + +export default function ActionButtons({ + successAction, + multiArgAction, + redirectAction, + notFoundAction, + errorAction, + objectArgAction, + arrayArgAction, + inlineAction, + promiseArgAction, +}) { + const [result, setResult] = useState(null) + const [error, setError] = useState(null) + + const handleSuccess = async () => { + setError(null) + const res = await successAction(5) + setResult(res) + } + + const handleMultiArg = async () => { + setError(null) + const res = await multiArgAction(1, 2, 3) + setResult(res) + } + + const handleRedirect = async () => { + setError(null) + await redirectAction('/redirect-target') + } + + const handleNotFound = async () => { + setError(null) + try { + await notFoundAction() + } catch (e) { + setError('notFound triggered') + } + } + + const handleError = async () => { + setError(null) + try { + await errorAction() + } catch (e) { + setError(e.message) + } + } + + const handleObjectArg = async () => { + setError(null) + const res = await objectArgAction({ name: 'test', value: 42 }) + setResult(res) + } + + const handleArrayArg = async () => { + setError(null) + const res = await arrayArgAction([1, 2, 3, 4, 5]) + setResult(res) + } + + const handleInline = async () => { + setError(null) + const res = await inlineAction(10) + setResult({ doubled: res }) + } + + const handlePromiseArg = async () => { + setError(null) + const res = await promiseArgAction(Promise.resolve('hello')) + setResult(res) + } + + return ( +
+

Server Action Logging Test

+ +
+ + + + + + + + + +
+ + {result &&
{JSON.stringify(result, null, 2)}
} + {error &&

{error}

} +
+ ) +} diff --git a/test/e2e/app-dir/server-action-logging/app/actions.js b/test/e2e/app-dir/server-action-logging/app/actions.js new file mode 100644 index 000000000000..0cf456b46b7d --- /dev/null +++ b/test/e2e/app-dir/server-action-logging/app/actions.js @@ -0,0 +1,50 @@ +'use server' + +import { redirect } from 'next/navigation' +import { notFound } from 'next/navigation' + +// Simple successful action +export async function successAction(value) { + return { result: value + 1 } +} + +// Action with multiple arguments +export async function multiArgAction(a, b, c) { + return { sum: a + b + c } +} + +// Action that redirects (should show 303 status) +export async function redirectAction(path) { + redirect(path) +} + +// Action that throws notFound (should show 404 status) +export async function notFoundAction() { + notFound() +} + +// Action that throws an error (should show 500 status) +export async function errorAction() { + throw new Error('Intentional error for testing') +} + +// Action with object argument +export async function objectArgAction(data) { + return { received: data } +} + +// Action with array argument +export async function arrayArgAction(items) { + return { count: items.length } +} + +// Inline action export for testing inline action display +export const inlineAction = async (value) => { + return value * 2 +} + +// Action with promise argument +export async function promiseArgAction(promiseValue) { + const resolved = await promiseValue + return { resolved } +} diff --git a/test/e2e/app-dir/server-action-logging/app/inline/button.js b/test/e2e/app-dir/server-action-logging/app/inline/button.js new file mode 100644 index 000000000000..731621c84553 --- /dev/null +++ b/test/e2e/app-dir/server-action-logging/app/inline/button.js @@ -0,0 +1,21 @@ +'use client' + +import { useState } from 'react' + +export function InlineActionButton({ action }) { + const [result, setResult] = useState(null) + + const handleClick = async () => { + const res = await action(10) + setResult(res) + } + + return ( +
+ + {result &&
{JSON.stringify(result, null, 2)}
} +
+ ) +} diff --git a/test/e2e/app-dir/server-action-logging/app/inline/page.js b/test/e2e/app-dir/server-action-logging/app/inline/page.js new file mode 100644 index 000000000000..fce42e3181f9 --- /dev/null +++ b/test/e2e/app-dir/server-action-logging/app/inline/page.js @@ -0,0 +1,15 @@ +import { InlineActionButton } from './button' + +export default function InlinePage() { + async function trueInlineAction(value) { + 'use server' + return { doubled: value * 2 } + } + + return ( +
+

Inline Action Test

+ +
+ ) +} diff --git a/test/e2e/app-dir/server-action-logging/app/layout.js b/test/e2e/app-dir/server-action-logging/app/layout.js new file mode 100644 index 000000000000..750eb927b198 --- /dev/null +++ b/test/e2e/app-dir/server-action-logging/app/layout.js @@ -0,0 +1,7 @@ +export default function Layout({ children }) { + return ( + + {children} + + ) +} diff --git a/test/e2e/app-dir/server-action-logging/app/not-found.js b/test/e2e/app-dir/server-action-logging/app/not-found.js new file mode 100644 index 000000000000..93bf1a6399cb --- /dev/null +++ b/test/e2e/app-dir/server-action-logging/app/not-found.js @@ -0,0 +1,3 @@ +export default function NotFound() { + return

Not Found

+} diff --git a/test/e2e/app-dir/server-action-logging/app/page.js b/test/e2e/app-dir/server-action-logging/app/page.js new file mode 100644 index 000000000000..7a9545952575 --- /dev/null +++ b/test/e2e/app-dir/server-action-logging/app/page.js @@ -0,0 +1,28 @@ +import ActionButtons from './action-buttons' +import { + successAction, + multiArgAction, + redirectAction, + notFoundAction, + errorAction, + objectArgAction, + arrayArgAction, + inlineAction, + promiseArgAction, +} from './actions' + +export default function Page() { + return ( + + ) +} diff --git a/test/e2e/app-dir/server-action-logging/app/redirect-target/page.js b/test/e2e/app-dir/server-action-logging/app/redirect-target/page.js new file mode 100644 index 000000000000..ca924ba9b12b --- /dev/null +++ b/test/e2e/app-dir/server-action-logging/app/redirect-target/page.js @@ -0,0 +1,3 @@ +export default function RedirectTarget() { + return

Redirect Target

+} diff --git a/test/e2e/app-dir/server-action-logging/server-action-logging.test.ts b/test/e2e/app-dir/server-action-logging/server-action-logging.test.ts new file mode 100644 index 000000000000..c4a5d0a380cc --- /dev/null +++ b/test/e2e/app-dir/server-action-logging/server-action-logging.test.ts @@ -0,0 +1,189 @@ +import stripAnsi from 'strip-ansi' +import { retry } from 'next-test-utils' +import { nextTestSetup } from 'e2e-utils' + +describe('server-action-logging', () => { + const { next, isNextStart, skipped } = nextTestSetup({ + skipDeployment: true, + files: __dirname, + }) + + if (skipped) return + + if (isNextStart) { + it('should not log server actions in production mode', async () => { + const browser = await next.browser('/') + const outputIndex = next.cliOutput.length + + await browser.elementByCss('#success-action').click() + await browser.waitForElementByCss('#result') + + // Wait a bit and verify no action logs appear + await retry(() => { + const logs = stripAnsi(next.cliOutput.slice(outputIndex)) + // Should not contain the server action log format + expect(logs).not.toContain('└─ ƒ successAction') + }) + }) + return + } + + it('should log successful server action', async () => { + const browser = await next.browser('/') + const outputIndex = next.cliOutput.length + + await browser.elementByCss('#success-action').click() + await browser.waitForElementByCss('#result') + + await retry(() => { + const logs = stripAnsi(next.cliOutput.slice(outputIndex)) + expect(logs).toContain('└─ ƒ successAction') + expect(logs).toMatch(/└─ ƒ successAction\(5\) in \d+ms/) + + // Validate order: POST request and server action log should be on consecutive lines + const lines = logs.split('\n') + const postLineIndex = lines.findIndex((line) => line.includes('POST /')) + const actionLineIndex = lines.findIndex((line) => + line.includes('└─ ƒ successAction') + ) + expect(postLineIndex).toBeGreaterThan(-1) + expect(actionLineIndex).toBe(postLineIndex + 1) + }) + }) + + it('should log server action with multiple arguments', async () => { + const browser = await next.browser('/') + const outputIndex = next.cliOutput.length + + await browser.elementByCss('#multi-arg-action').click() + await browser.waitForElementByCss('#result') + + await retry(() => { + const logs = stripAnsi(next.cliOutput.slice(outputIndex)) + expect(logs).toContain('└─ ƒ multiArgAction') + expect(logs).toMatch(/└─ ƒ multiArgAction\(1, 2, 3\) in \d+ms/) + }) + }) + + it('should log server action with object argument', async () => { + const browser = await next.browser('/') + const outputIndex = next.cliOutput.length + + await browser.elementByCss('#object-arg-action').click() + await browser.waitForElementByCss('#result') + + await retry(() => { + const logs = stripAnsi(next.cliOutput.slice(outputIndex)) + expect(logs).toContain('└─ ƒ objectArgAction') + // safe-stable-stringify outputs JSON format + expect(logs).toMatch( + /└─ ƒ objectArgAction\(\{"name":"test","value":42\}\) in \d+ms/ + ) + }) + }) + + it('should log server action with array argument (truncated)', async () => { + const browser = await next.browser('/') + const outputIndex = next.cliOutput.length + + await browser.elementByCss('#array-arg-action').click() + await browser.waitForElementByCss('#result') + + await retry(() => { + const logs = stripAnsi(next.cliOutput.slice(outputIndex)) + expect(logs).toContain('└─ ƒ arrayArgAction') + // Arrays are truncated by safe-stable-stringify + expect(logs).toMatch(/└─ ƒ arrayArgAction\(\[1,2,3,.*\]\) in \d+ms/) + }) + }) + + it('should log redirect action', async () => { + const browser = await next.browser('/') + const outputIndex = next.cliOutput.length + + await browser.elementByCss('#redirect-action').click() + await browser.waitForElementByCss('#redirect-target') + + await retry(() => { + const logs = stripAnsi(next.cliOutput.slice(outputIndex)) + expect(logs).toContain('└─ ƒ redirectAction') + expect(logs).toMatch( + /└─ ƒ redirectAction\("\/redirect-target"\) in \d+ms/ + ) + }) + }) + + it('should log notFound action', async () => { + const browser = await next.browser('/') + const outputIndex = next.cliOutput.length + + await browser.elementByCss('#not-found-action').click() + + await retry(() => { + const logs = stripAnsi(next.cliOutput.slice(outputIndex)) + expect(logs).toContain('└─ ƒ notFoundAction') + expect(logs).toMatch(/└─ ƒ notFoundAction\(\) in \d+ms/) + }) + }) + + it('should log error action', async () => { + const browser = await next.browser('/') + const outputIndex = next.cliOutput.length + + await browser.elementByCss('#error-action').click() + await browser.waitForElementByCss('#error') + + await retry(() => { + const logs = stripAnsi(next.cliOutput.slice(outputIndex)) + expect(logs).toContain('└─ ƒ errorAction') + expect(logs).toMatch(/└─ ƒ errorAction\(\) in \d+ms/) + }) + }) + + it('should log server action with promise argument', async () => { + const browser = await next.browser('/') + const outputIndex = next.cliOutput.length + + await browser.elementByCss('#promise-arg-action').click() + await browser.waitForElementByCss('#result') + + await retry(() => { + const logs = stripAnsi(next.cliOutput.slice(outputIndex)) + expect(logs).toContain('└─ ƒ promiseArgAction') + expect(logs).toMatch(/└─ ƒ promiseArgAction\(.*\) in \d+ms/) + }) + }) + + it('should log inline action', async () => { + const browser = await next.browser('/inline') + await browser.waitForElementByCss('#inline-page') + const outputIndex = next.cliOutput.length + + await browser.elementByCss('#true-inline-action').click() + await browser.waitForElementByCss('#result') + + await retry(() => { + const logs = stripAnsi(next.cliOutput.slice(outputIndex)) + // Inline actions show as with file location + expect(logs).toMatch( + /└─ ƒ \(10\) in \d+ms app\/inline\/page\.js/ + ) + }) + }) + + it('should show relative file path in log', async () => { + const browser = await next.browser('/') + const outputIndex = next.cliOutput.length + + await browser.elementByCss('#success-action').click() + await browser.waitForElementByCss('#result') + + await retry(() => { + const logs = stripAnsi(next.cliOutput.slice(outputIndex)) + // Should show relative path like app/actions.js, not full path + expect(logs).toMatch(/app\/actions\.js/) + // Should not contain the test directory prefix + expect(logs).not.toContain('test/e2e/app-dir/server-action-logging/') + }) + }) +}) diff --git a/test/e2e/app-dir/typed-routes/typed-routes.test.ts b/test/e2e/app-dir/typed-routes/typed-routes.test.ts index 1ea4e2f84691..75cb77df9289 100644 --- a/test/e2e/app-dir/typed-routes/typed-routes.test.ts +++ b/test/e2e/app-dir/typed-routes/typed-routes.test.ts @@ -23,14 +23,14 @@ describe('typed-routes', () => { it('should generate route types correctly', async () => { await retry(async () => { - const dts = await next.readFile(`${next.distDir}/types/routes.d.ts`) + const dts = await next.readFile(`${next.distDir}/types/route-types.d.ts`) expect(dts).toContain(expectedDts) }) }) it('should correctly convert custom route patterns from path-to-regexp to bracket syntax', async () => { await retry(async () => { - const dts = await next.readFile(`${next.distDir}/types/routes.d.ts`) + const dts = await next.readFile(`${next.distDir}/types/route-types.d.ts`) // Test standard dynamic segment: :slug -> [slug] expect(dts).toContain('"/project/[slug]"') @@ -58,7 +58,7 @@ describe('typed-routes', () => { await retry(async () => { const routeTypesContent = await next.readFile( - `${next.distDir}/types/routes.d.ts` + `${next.distDir}/types/route-types.d.ts` ) expect(routeTypesContent).toContain( @@ -70,7 +70,7 @@ describe('typed-routes', () => { it('should generate RouteContext type for route handlers', async () => { await retry(async () => { - const dts = await next.readFile(`${next.distDir}/types/routes.d.ts`) + const dts = await next.readFile(`${next.distDir}/types/route-types.d.ts`) expect(dts).toContain( 'interface RouteContext' ) diff --git a/test/e2e/app-dir/use-cache/use-cache.test.ts b/test/e2e/app-dir/use-cache/use-cache.test.ts index b6319a1e87cc..1cfde181a3d5 100644 --- a/test/e2e/app-dir/use-cache/use-cache.test.ts +++ b/test/e2e/app-dir/use-cache/use-cache.test.ts @@ -553,19 +553,17 @@ describe('use-cache', () => { it('should send an SWR cache-control header based on the revalidate and expire values', async () => { let response = await next.fetch('/cache-life') - expect(response.headers.get('cache-control')).toBe('s-maxage=100') - expect(response.headers.get('cdn-cache-control')).toBe( + expect(response.headers.get('cache-control')).toBe( // revalidate is set to 100, expire is set to 300 => SWR 200 - 'max-age=100, stale-while-revalidate=200' + 's-maxage=100, stale-while-revalidate=200' ) response = await next.fetch('/cache-fetch') - expect(response.headers.get('cache-control')).toBe('s-maxage=900') - expect(response.headers.get('cdn-cache-control')).toBe( + expect(response.headers.get('cache-control')).toBe( // revalidate is set to 900, expire is one year (31536000, default // expireTime) => SWR 31535100 - 'max-age=900, stale-while-revalidate=31535100' + 's-maxage=900, stale-while-revalidate=31535100' ) }) diff --git a/test/e2e/app-dir/webpack-loader-resource-query/app/data.txt b/test/e2e/app-dir/webpack-loader-resource-query/app/data.txt new file mode 100644 index 000000000000..5e1c309dae7f --- /dev/null +++ b/test/e2e/app-dir/webpack-loader-resource-query/app/data.txt @@ -0,0 +1 @@ +Hello World \ No newline at end of file diff --git a/test/e2e/app-dir/webpack-loader-resource-query/app/page.tsx b/test/e2e/app-dir/webpack-loader-resource-query/app/page.tsx index d4ca1cbf7a05..76c9949dbbcc 100644 --- a/test/e2e/app-dir/webpack-loader-resource-query/app/page.tsx +++ b/test/e2e/app-dir/webpack-loader-resource-query/app/page.tsx @@ -1,7 +1,17 @@ // @ts-expect-error -- ignore import { v } from './test.mdx?test=hi' +// @ts-expect-error -- ignore +import reversed from './data.txt?reverse' +// @ts-expect-error -- ignore +import upper from './data.txt?upper' export default function Page() { console.log(v) - return

hello world

+ return ( +
+

hello world

+

{reversed}

+

{upper}

+
+ ) } diff --git a/test/e2e/app-dir/webpack-loader-resource-query/next.config.js b/test/e2e/app-dir/webpack-loader-resource-query/next.config.js index 2b1af2ed85a3..f5539343b1c4 100644 --- a/test/e2e/app-dir/webpack-loader-resource-query/next.config.js +++ b/test/e2e/app-dir/webpack-loader-resource-query/next.config.js @@ -6,6 +6,18 @@ const nextConfig = { loaders: [require.resolve('./test-file-loader.js')], as: '*.js', }, + '*.txt': [ + { + condition: { query: '?reverse' }, + loaders: [require.resolve('./reverse-loader.js')], + as: '*.js', + }, + { + condition: { query: /\?upper/ }, + loaders: [require.resolve('./upper-loader.js')], + as: '*.js', + }, + ], }, }, webpack(config) { @@ -13,6 +25,14 @@ const nextConfig = { test: /\.mdx/, use: require.resolve('./test-file-loader.js'), }) + config.module.rules.push({ + resourceQuery: '?reverse', + use: require.resolve('./reverse-loader.js'), + }) + config.module.rules.push({ + resourceQuery: /\?upper/, + use: require.resolve('./upper-loader.js'), + }) return config }, } diff --git a/test/e2e/app-dir/webpack-loader-resource-query/reverse-loader.js b/test/e2e/app-dir/webpack-loader-resource-query/reverse-loader.js new file mode 100644 index 000000000000..8a53c4b6a8f8 --- /dev/null +++ b/test/e2e/app-dir/webpack-loader-resource-query/reverse-loader.js @@ -0,0 +1,4 @@ +module.exports = function reverseLoader(source) { + const reversed = source.split('').reverse().join('') + return `export default ${JSON.stringify(reversed)}` +} diff --git a/test/e2e/app-dir/webpack-loader-resource-query/turbopack-loader-resource-query.test.ts b/test/e2e/app-dir/webpack-loader-resource-query/turbopack-loader-resource-query.test.ts deleted file mode 100644 index 9a2ae523bdcf..000000000000 --- a/test/e2e/app-dir/webpack-loader-resource-query/turbopack-loader-resource-query.test.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { nextTestSetup } from 'e2e-utils' - -describe('webpack-loader-resource-query', () => { - const { next, skipped } = nextTestSetup({ - files: __dirname, - skipDeployment: true, - }) - - if (skipped) return - - it('should pass query to loader', async () => { - await next.render$('/') - - expect(next.cliOutput).toContain('resource query: ?test=hi') - }) -}) diff --git a/test/e2e/app-dir/webpack-loader-resource-query/upper-loader.js b/test/e2e/app-dir/webpack-loader-resource-query/upper-loader.js new file mode 100644 index 000000000000..bcdee94c419c --- /dev/null +++ b/test/e2e/app-dir/webpack-loader-resource-query/upper-loader.js @@ -0,0 +1,4 @@ +module.exports = function upperLoader(source) { + const upper = source.toUpperCase() + return `export default ${JSON.stringify(upper)}` +} diff --git a/test/e2e/app-dir/webpack-loader-resource-query/webpack-loader-resource-query.test.js b/test/e2e/app-dir/webpack-loader-resource-query/webpack-loader-resource-query.test.js new file mode 100644 index 000000000000..6a86fffdc412 --- /dev/null +++ b/test/e2e/app-dir/webpack-loader-resource-query/webpack-loader-resource-query.test.js @@ -0,0 +1,28 @@ +import { nextTestSetup } from 'e2e-utils' + +describe('webpack-loader-resource-query', () => { + const { next, skipped } = nextTestSetup({ + files: __dirname, + skipDeployment: true, + }) + + if (skipped) return + + it('should pass query to loader', async () => { + await next.render$('/') + + expect(next.cliOutput).toContain('resource query: ?test=hi') + }) + + it('should apply loader based on resourceQuery', async () => { + const $ = await next.render$('/') + const text = $('#reversed').text() + expect(text).toBe('dlroW olleH') + }) + + it('should apply loader based on resourceQuery regex', async () => { + const $ = await next.render$('/') + const text = $('#upper').text() + expect(text).toBe('HELLO WORLD') + }) +}) diff --git a/test/e2e/prerender.test.ts b/test/e2e/prerender.test.ts index d548f7604263..d4be9c3a4c0b 100644 --- a/test/e2e/prerender.test.ts +++ b/test/e2e/prerender.test.ts @@ -676,25 +676,21 @@ describe('Prerender', () => { if (!isDev) { it('should use correct caching headers for a revalidate page', async () => { const initialRes = await fetchViaHTTP(next.url, '/') - expect(initialRes.headers.get('cache-control')).toBe('s-maxage=2') - if (!isDeploy) { - expect(initialRes.headers.get('cdn-cache-control')).toBe( - 'max-age=2, stale-while-revalidate=31535998' - ) - } + expect(initialRes.headers.get('cache-control')).toBe( + isDeploy + ? 'public, max-age=0, must-revalidate' + : 's-maxage=2, stale-while-revalidate=31535998' + ) }) it('should use correct caching headers for a fallback-true page (prerendered)', async () => { const initialRes = await fetchViaHTTP(next.url, '/fallback-true/first') expect(initialRes.status).toBe(200) expect(initialRes.headers.get('cache-control')).toBe( - isDeploy ? 'public, max-age=0, must-revalidate' : 's-maxage=2' + isDeploy + ? 'public, max-age=0, must-revalidate' + : 's-maxage=2, stale-while-revalidate=31535998' ) - if (!isDeploy) { - expect(initialRes.headers.get('cdn-cache-control')).toBe( - 'max-age=2, stale-while-revalidate=31535998' - ) - } expect(await initialRes.text()).not.toContain('hi fallback') const dataRes = await fetchViaHTTP( @@ -703,23 +699,19 @@ describe('Prerender', () => { ) expect(dataRes.status).toBe(200) expect(dataRes.headers.get('cache-control')).toBe( - isDeploy ? 'public, max-age=0, must-revalidate' : 's-maxage=2' + isDeploy + ? 'public, max-age=0, must-revalidate' + : 's-maxage=2, stale-while-revalidate=31535998' ) - if (!isDeploy) { - expect(dataRes.headers.get('cdn-cache-control')).toBe( - 'max-age=2, stale-while-revalidate=31535998' - ) - } await retry(async () => { const finalRes = await fetchViaHTTP(next.url, `/fallback-true/first`) expect(finalRes.status).toBe(200) - expect(finalRes.headers.get('cache-control')).toBe('s-maxage=2') - if (!isDeploy) { - expect(finalRes.headers.get('cdn-cache-control')).toBe( - 'max-age=2, stale-while-revalidate=31535998' - ) - } + expect(finalRes.headers.get('cache-control')).toBe( + isDeploy + ? 'public, max-age=0, must-revalidate' + : 's-maxage=2, stale-while-revalidate=31535998' + ) expect(await finalRes.text()).not.toContain('hi fallback') }) }) @@ -739,22 +731,20 @@ describe('Prerender', () => { `/_next/data/${next.buildId}/fallback-true/second.json` ) expect(dataRes.status).toBe(200) - expect(dataRes.headers.get('cache-control')).toBe('s-maxage=2') - if (!isDeploy) { - expect(dataRes.headers.get('cdn-cache-control')).toBe( - 'max-age=2, stale-while-revalidate=31535998' - ) - } + expect(dataRes.headers.get('cache-control')).toBe( + isDeploy + ? 'public, max-age=0, must-revalidate' + : 's-maxage=2, stale-while-revalidate=31535998' + ) await retry(async () => { const finalRes = await fetchViaHTTP(next.url, `/fallback-true/second`) expect(finalRes.status).toBe(200) - expect(finalRes.headers.get('cache-control')).toBe('s-maxage=2') - if (!isDeploy) { - expect(finalRes.headers.get('cdn-cache-control')).toBe( - 'max-age=2, stale-while-revalidate=31535998' - ) - } + expect(finalRes.headers.get('cache-control')).toBe( + isDeploy + ? 'public, max-age=0, must-revalidate' + : 's-maxage=2, stale-while-revalidate=31535998' + ) expect(await finalRes.text()).not.toContain('hi fallback') }) }) @@ -1390,11 +1380,6 @@ describe('Prerender', () => { expect(initialRes.headers.get('cache-control')).toBe( isDeploy ? 'public, max-age=0, must-revalidate' : 's-maxage=31536000' ) - if (!isDeploy) { - expect(initialRes.headers.get('cdn-cache-control')).toBe( - 'max-age=31536000' - ) - } const initialHtml = await initialRes.text() expect(initialHtml).toMatch(/hello.*?world/) }) diff --git a/test/integration/app-types/src/app/type-checks/redirect/page.tsx b/test/integration/app-types/src/app/type-checks/redirect/page.tsx index 9b41f224e0ff..350b904c0b24 100644 --- a/test/integration/app-types/src/app/type-checks/redirect/page.tsx +++ b/test/integration/app-types/src/app/type-checks/redirect/page.tsx @@ -1,4 +1,4 @@ -import { redirect, permanentRedirect } from 'next/navigation' +import { redirect, permanentRedirect, RedirectType } from 'next/navigation' import type { Route } from 'next' export default function Page() { @@ -21,6 +21,11 @@ export default function Page() { permanentRedirect('/blog/a/b') permanentRedirect(`/dashboard/${'123'}`) permanentRedirect('/external' as Route) + + // RedirectType should be correctly typed as literal types: + redirect('/dashboard/another', RedirectType.replace) + redirect('/about', RedirectType.push) + permanentRedirect('/dashboard/user', RedirectType.replace) } return
diff --git a/test/integration/create-next-app/package-manager/pnpm.test.ts b/test/integration/create-next-app/package-manager/pnpm.test.ts index 7a0615a0e885..69eb214db524 100644 --- a/test/integration/create-next-app/package-manager/pnpm.test.ts +++ b/test/integration/create-next-app/package-manager/pnpm.test.ts @@ -2,6 +2,7 @@ import { DEFAULT_FILES, FULL_EXAMPLE_PATH, projectFilesShouldExist, + projectFilesShouldNotExist, run, useTempDir, } from '../utils' @@ -86,6 +87,74 @@ describe('create-next-app with package manager pnpm', () => { }) }) + // These tests use --skip-install because: + // 1. We only need to verify the workspace file is created/not created + // 2. The CI runs pnpm v9, but when testing v10 behavior, the workspace file + // created for v10 (without packages field) would fail with pnpm v9 + it('should create pnpm-workspace.yaml for pnpm v10+', async () => { + await useTempDir(async (cwd) => { + const projectName = 'pnpm-v10-workspace' + const res = await run( + [ + projectName, + '--ts', + '--app', + '--no-turbopack', + '--no-linter', + '--no-src-dir', + '--no-tailwind', + '--no-import-alias', + '--no-react-compiler', + '--skip-install', + ], + nextTgzFilename, + { + cwd, + env: { npm_config_user_agent: 'pnpm/10.0.0 npm/? node/v20.0.0' }, + } + ) + + expect(res.exitCode).toBe(0) + projectFilesShouldExist({ + cwd, + projectName, + files: ['package.json', 'pnpm-workspace.yaml'], + }) + }) + }) + + it('should NOT create pnpm-workspace.yaml for pnpm v9', async () => { + await useTempDir(async (cwd) => { + const projectName = 'pnpm-v9-no-workspace' + const res = await run( + [ + projectName, + '--ts', + '--app', + '--no-turbopack', + '--no-linter', + '--no-src-dir', + '--no-tailwind', + '--no-import-alias', + '--no-react-compiler', + '--skip-install', + ], + nextTgzFilename, + { + cwd, + env: { npm_config_user_agent: 'pnpm/9.13.2 npm/? node/v20.0.0' }, + } + ) + + expect(res.exitCode).toBe(0) + projectFilesShouldNotExist({ + cwd, + projectName, + files: ['pnpm-workspace.yaml'], + }) + }) + }) + it('should use pnpm for --use-pnpm flag with example', async () => { await useTempDir(async (cwd) => { const projectName = 'use-pnpm-with-example' diff --git a/test/integration/custom-server-types/next-env.d.ts b/test/integration/custom-server-types/next-env.d.ts index 83311bdfa264..1a1bf607fce1 100644 --- a/test/integration/custom-server-types/next-env.d.ts +++ b/test/integration/custom-server-types/next-env.d.ts @@ -1,6 +1,6 @@ /// /// -import './.next/dev/types/routes.d.ts' +import './.next/types/routes.d.ts' // NOTE: This file should not be edited // see https://nextjs.org/docs/pages/api-reference/config/typescript for more information. diff --git a/test/integration/next-image-new/app-dir-localpatterns/test/index.test.ts b/test/integration/next-image-new/app-dir-localpatterns/test/index.test.ts index 39721d880c94..82dbd0d0767c 100644 --- a/test/integration/next-image-new/app-dir-localpatterns/test/index.test.ts +++ b/test/integration/next-image-new/app-dir-localpatterns/test/index.test.ts @@ -98,7 +98,7 @@ function runTests(mode: 'dev' | 'server') { }, ], maximumRedirects: 3, - maximumResponseBody: 300000000, + maximumResponseBody: 50000000, minimumCacheTTL: 14400, path: '/_next/image', qualities: [75], diff --git a/test/integration/next-image-new/app-dir-qualities/test/index.test.ts b/test/integration/next-image-new/app-dir-qualities/test/index.test.ts index 18d4d6435c70..9989bef779dd 100644 --- a/test/integration/next-image-new/app-dir-qualities/test/index.test.ts +++ b/test/integration/next-image-new/app-dir-qualities/test/index.test.ts @@ -110,7 +110,7 @@ function runTests(mode: 'dev' | 'server') { }, ], maximumRedirects: 3, - maximumResponseBody: 300000000, + maximumResponseBody: 50000000, minimumCacheTTL: 14400, path: '/_next/image', qualities: [42, 69, 88], diff --git a/test/integration/next-image-new/app-dir/test/index.test.ts b/test/integration/next-image-new/app-dir/test/index.test.ts index 3dc4554aa7af..b4cacddceb32 100644 --- a/test/integration/next-image-new/app-dir/test/index.test.ts +++ b/test/integration/next-image-new/app-dir/test/index.test.ts @@ -1796,7 +1796,7 @@ function runTests(mode: 'dev' | 'server') { }, ], maximumRedirects: 3, - maximumResponseBody: 300000000, + maximumResponseBody: 50000000, minimumCacheTTL: 14400, path: '/_next/image', qualities: [75], diff --git a/test/integration/next-image-new/unicode/test/index.test.ts b/test/integration/next-image-new/unicode/test/index.test.ts index 953db9f27045..7963c4faf2d7 100644 --- a/test/integration/next-image-new/unicode/test/index.test.ts +++ b/test/integration/next-image-new/unicode/test/index.test.ts @@ -103,7 +103,7 @@ function runTests(mode: 'server' | 'dev') { }, ], maximumRedirects: 3, - maximumResponseBody: 300000000, + maximumResponseBody: 50000000, minimumCacheTTL: 14400, path: '/_next/image', qualities: [75], diff --git a/test/integration/next-image-new/unoptimized/test/index.test.ts b/test/integration/next-image-new/unoptimized/test/index.test.ts index 293e0b7d1c83..8e67882c46ab 100644 --- a/test/integration/next-image-new/unoptimized/test/index.test.ts +++ b/test/integration/next-image-new/unoptimized/test/index.test.ts @@ -118,7 +118,7 @@ function runTests(url: string, mode: 'dev' | 'server') { }, ], maximumRedirects: 3, - maximumResponseBody: 300000000, + maximumResponseBody: 50000000, minimumCacheTTL: 14400, path: '/_next/image', qualities: [75], diff --git a/test/integration/not-found-revalidate/test/index.test.ts b/test/integration/not-found-revalidate/test/index.test.ts index f6b5d4bd3f4e..57ddb31d205e 100644 --- a/test/integration/not-found-revalidate/test/index.test.ts +++ b/test/integration/not-found-revalidate/test/index.test.ts @@ -81,9 +81,8 @@ const runTests = () => { let res = await fetchViaHTTP(appPort, '/fallback-blocking/hello') let $ = cheerio.load(await res.text()) - expect(res.headers.get('cache-control')).toBe('s-maxage=1') - expect(res.headers.get('cdn-cache-control')).toBe( - `max-age=1, stale-while-revalidate=31535999` + expect(res.headers.get('cache-control')).toBe( + `s-maxage=1, stale-while-revalidate=31535999` ) expect(res.status).toBe(404) expect(JSON.parse($('#props').text()).notFound).toBe(true) @@ -92,9 +91,8 @@ const runTests = () => { res = await fetchViaHTTP(appPort, '/fallback-blocking/hello') $ = cheerio.load(await res.text()) - expect(res.headers.get('cache-control')).toBe('s-maxage=1') - expect(res.headers.get('cdn-cache-control')).toBe( - `max-age=1, stale-while-revalidate=31535999` + expect(res.headers.get('cache-control')).toBe( + `s-maxage=1, stale-while-revalidate=31535999` ) expect(res.status).toBe(404) expect(JSON.parse($('#props').text()).notFound).toBe(true) @@ -104,9 +102,8 @@ const runTests = () => { $ = cheerio.load(await res.text()) const props = JSON.parse($('#props').text()) - expect(res.headers.get('cache-control')).toBe('s-maxage=1') - expect(res.headers.get('cdn-cache-control')).toBe( - 'max-age=1, stale-while-revalidate=31535999' + expect(res.headers.get('cache-control')).toBe( + 's-maxage=1, stale-while-revalidate=31535999' ) expect(res.status).toBe(200) expect(props.found).toBe(true) @@ -118,9 +115,8 @@ const runTests = () => { $ = cheerio.load(await res.text()) const props2 = JSON.parse($('#props').text()) - expect(res.headers.get('cache-control')).toBe('s-maxage=1') - expect(res.headers.get('cdn-cache-control')).toBe( - 'max-age=1, stale-while-revalidate=31535999' + expect(res.headers.get('cache-control')).toBe( + 's-maxage=1, stale-while-revalidate=31535999' ) expect(res.status).toBe(200) expect(props2.found).toBe(true) @@ -132,9 +128,8 @@ const runTests = () => { $ = cheerio.load(await res.text()) const props3 = JSON.parse($('#props').text()) - expect(res.headers.get('cache-control')).toBe('s-maxage=1') - expect(res.headers.get('cdn-cache-control')).toBe( - 'max-age=1, stale-while-revalidate=31535999' + expect(res.headers.get('cache-control')).toBe( + 's-maxage=1, stale-while-revalidate=31535999' ) expect(res.status).toBe(200) expect(props3.found).toBe(true) @@ -152,9 +147,8 @@ const runTests = () => { let res = await fetchViaHTTP(appPort, '/fallback-true/world') let $ = cheerio.load(await res.text()) - expect(res.headers.get('cache-control')).toBe('s-maxage=1') - expect(res.headers.get('cdn-cache-control')).toBe( - `max-age=1, stale-while-revalidate=31535999` + expect(res.headers.get('cache-control')).toBe( + `s-maxage=1, stale-while-revalidate=31535999` ) expect(res.status).toBe(404) expect(JSON.parse($('#props').text()).notFound).toBe(true) @@ -164,9 +158,8 @@ const runTests = () => { $ = cheerio.load(await res.text()) const props = JSON.parse($('#props').text()) - expect(res.headers.get('cache-control')).toBe('s-maxage=1') - expect(res.headers.get('cdn-cache-control')).toBe( - 'max-age=1, stale-while-revalidate=31535999' + expect(res.headers.get('cache-control')).toBe( + 's-maxage=1, stale-while-revalidate=31535999' ) expect(res.status).toBe(200) expect(props.found).toBe(true) @@ -178,9 +171,8 @@ const runTests = () => { $ = cheerio.load(await res.text()) const props2 = JSON.parse($('#props').text()) - expect(res.headers.get('cache-control')).toBe('s-maxage=1') - expect(res.headers.get('cdn-cache-control')).toBe( - 'max-age=1, stale-while-revalidate=31535999' + expect(res.headers.get('cache-control')).toBe( + 's-maxage=1, stale-while-revalidate=31535999' ) expect(res.status).toBe(200) expect(props2.found).toBe(true) @@ -192,9 +184,8 @@ const runTests = () => { $ = cheerio.load(await res.text()) const props3 = JSON.parse($('#props').text()) - expect(res.headers.get('cache-control')).toBe('s-maxage=1') - expect(res.headers.get('cdn-cache-control')).toBe( - 'max-age=1, stale-while-revalidate=31535999' + expect(res.headers.get('cache-control')).toBe( + 's-maxage=1, stale-while-revalidate=31535999' ) expect(res.status).toBe(200) expect(props3.found).toBe(true) diff --git a/test/integration/typescript-app-type-declarations/next-env.d.ts b/test/integration/typescript-app-type-declarations/next-env.d.ts index 7996d352f43b..1a1bf607fce1 100644 --- a/test/integration/typescript-app-type-declarations/next-env.d.ts +++ b/test/integration/typescript-app-type-declarations/next-env.d.ts @@ -1,6 +1,6 @@ /// /// -import "./.next/dev/types/routes.d.ts"; +import './.next/types/routes.d.ts' // NOTE: This file should not be edited // see https://nextjs.org/docs/pages/api-reference/config/typescript for more information. diff --git a/test/integration/typescript-app-type-declarations/next-env.strictRouteTypes.d.ts b/test/integration/typescript-app-type-declarations/next-env.strictRouteTypes.d.ts index 1c2a6d8c33fc..19709046afd6 100644 --- a/test/integration/typescript-app-type-declarations/next-env.strictRouteTypes.d.ts +++ b/test/integration/typescript-app-type-declarations/next-env.strictRouteTypes.d.ts @@ -1,8 +1,6 @@ /// /// -import "./.next/dev/types/routes.d.ts"; -import "./.next/dev/types/cache-life.d.ts"; -import "./.next/dev/types/validator.ts"; +import "./.next/types/routes.d.ts"; // NOTE: This file should not be edited // see https://nextjs.org/docs/pages/api-reference/config/typescript for more information. diff --git a/test/production/app-dir/route-handler-manifest-size/app/api-with-client/client-utils.ts b/test/production/app-dir/route-handler-manifest-size/app/api-with-client/client-utils.ts new file mode 100644 index 000000000000..677abe7c44e8 --- /dev/null +++ b/test/production/app-dir/route-handler-manifest-size/app/api-with-client/client-utils.ts @@ -0,0 +1,6 @@ +'use client' + +// A client utility module directly imported by a route handler +export function formatData(data: { value: number }) { + return `Formatted: ${data.value}` +} diff --git a/test/production/app-dir/route-handler-manifest-size/app/api-with-client/route.ts b/test/production/app-dir/route-handler-manifest-size/app/api-with-client/route.ts new file mode 100644 index 000000000000..55a776a16a83 --- /dev/null +++ b/test/production/app-dir/route-handler-manifest-size/app/api-with-client/route.ts @@ -0,0 +1,14 @@ +import { NextResponse } from 'next/server' +// Direct import from a 'use client' module +// The import creates a client reference in the manifest +import { formatData } from './client-utils' + +export async function GET() { + // Note: formatData is a client reference here, not the actual function + // This tests that direct client imports appear in the route's manifest + return NextResponse.json({ + message: 'Hello from route handler with client import', + // We can't actually call formatData here since it's a client reference + hasClientImport: typeof formatData !== 'undefined', + }) +} diff --git a/test/production/app-dir/route-handler-manifest-size/app/api/hello/route.ts b/test/production/app-dir/route-handler-manifest-size/app/api/hello/route.ts new file mode 100644 index 000000000000..388e6c20ca06 --- /dev/null +++ b/test/production/app-dir/route-handler-manifest-size/app/api/hello/route.ts @@ -0,0 +1,6 @@ +import { NextResponse } from 'next/server' + +// Pure route handler with no client component imports +export async function GET() { + return NextResponse.json({ message: 'Hello from pure route handler' }) +} diff --git a/test/production/app-dir/route-handler-manifest-size/app/components/Button.tsx b/test/production/app-dir/route-handler-manifest-size/app/components/Button.tsx new file mode 100644 index 000000000000..008407d445ba --- /dev/null +++ b/test/production/app-dir/route-handler-manifest-size/app/components/Button.tsx @@ -0,0 +1,12 @@ +'use client' + +export function Button({ children }: { children: React.ReactNode }) { + return ( + + ) +} diff --git a/test/production/app-dir/route-handler-manifest-size/app/components/Dropdown.tsx b/test/production/app-dir/route-handler-manifest-size/app/components/Dropdown.tsx new file mode 100644 index 000000000000..1ee1fc9bd26d --- /dev/null +++ b/test/production/app-dir/route-handler-manifest-size/app/components/Dropdown.tsx @@ -0,0 +1,36 @@ +'use client' + +import { useState } from 'react' + +export function Dropdown({ + items, +}: { + items: { label: string; value: string }[] +}) { + const [isOpen, setIsOpen] = useState(false) + const [selected, setSelected] = useState(null) + + return ( +
+ + {isOpen && ( +
    + {items.map((item) => ( +
  • { + setSelected(item.label) + setIsOpen(false) + }} + className="px-4 py-2 hover:bg-gray-100 cursor-pointer" + > + {item.label} +
  • + ))} +
+ )} +
+ ) +} diff --git a/test/production/app-dir/route-handler-manifest-size/app/components/Modal.tsx b/test/production/app-dir/route-handler-manifest-size/app/components/Modal.tsx new file mode 100644 index 000000000000..0dd324f86748 --- /dev/null +++ b/test/production/app-dir/route-handler-manifest-size/app/components/Modal.tsx @@ -0,0 +1,21 @@ +'use client' + +import { useState } from 'react' + +export function Modal({ children }: { children: React.ReactNode }) { + const [isOpen, setIsOpen] = useState(false) + + return ( + <> + + {isOpen && ( +
+
+ {children} + +
+
+ )} + + ) +} diff --git a/test/production/app-dir/route-handler-manifest-size/app/layout.tsx b/test/production/app-dir/route-handler-manifest-size/app/layout.tsx new file mode 100644 index 000000000000..dbce4ea8e3ae --- /dev/null +++ b/test/production/app-dir/route-handler-manifest-size/app/layout.tsx @@ -0,0 +1,11 @@ +export default function RootLayout({ + children, +}: { + children: React.ReactNode +}) { + return ( + + {children} + + ) +} diff --git a/test/production/app-dir/route-handler-manifest-size/app/page.tsx b/test/production/app-dir/route-handler-manifest-size/app/page.tsx new file mode 100644 index 000000000000..4b54b9123eaf --- /dev/null +++ b/test/production/app-dir/route-handler-manifest-size/app/page.tsx @@ -0,0 +1,19 @@ +import { Button } from './components/Button' +import { Modal } from './components/Modal' +import { Dropdown } from './components/Dropdown' + +export default function Page() { + return ( +
+

Page with Client Components

+ + Modal content + +
+ ) +} diff --git a/test/production/app-dir/route-handler-manifest-size/route-handler-manifest-size.test.ts b/test/production/app-dir/route-handler-manifest-size/route-handler-manifest-size.test.ts new file mode 100644 index 000000000000..693aeb388388 --- /dev/null +++ b/test/production/app-dir/route-handler-manifest-size/route-handler-manifest-size.test.ts @@ -0,0 +1,123 @@ +import { join } from 'path' +import { nextTestSetup } from 'e2e-utils' +import type { ClientReferenceManifest } from 'next/dist/build/webpack/plugins/flight-manifest-plugin' + +describe('route-handler-manifest-size', () => { + const { next, isNextStart, skipped } = nextTestSetup({ + files: __dirname, + // This test is specifically for webpack behavior + skipDeployment: true, + }) + + if (skipped) return + + /** + * Loads and returns the client reference manifest for a given route + */ + function getClientReferenceManifest(route: string): ClientReferenceManifest { + const appDir = next.testDir + const manifestPath = join( + appDir, + `.next/server/app${route}_client-reference-manifest.js` + ) + const modulePath = require.resolve(manifestPath) + + // Clear any cached version + delete require.cache[modulePath] + + // Initialize global if needed + if (!(globalThis as any).__RSC_MANIFEST) { + ;(globalThis as any).__RSC_MANIFEST = {} + } + + // Load the manifest (it sets globalThis.__RSC_MANIFEST) + require(modulePath) + + const manifest = (globalThis as any).__RSC_MANIFEST[ + route + ] as ClientReferenceManifest + + // Clean up require cache but keep manifest for potential re-reads + delete require.cache[modulePath] + + return manifest + } + + /** + * Gets the module paths from clientModules + */ + function getClientModulePaths(manifest: ClientReferenceManifest): string[] { + return Object.keys(manifest.clientModules) + } + + if (isNextStart) { + it('should not include page client components in pure route handler manifest', () => { + const manifest = getClientReferenceManifest('/api/hello/route') + const modulePaths = getClientModulePaths(manifest) + + // The pure route handler should NOT contain client components from the page + const hasButton = modulePaths.some((p) => p.includes('Button')) + const hasModal = modulePaths.some((p) => p.includes('Modal')) + const hasDropdown = modulePaths.some((p) => p.includes('Dropdown')) + + expect(hasButton).toBe(false) + expect(hasModal).toBe(false) + expect(hasDropdown).toBe(false) + }) + + it('should include page client components in page manifest', () => { + const manifest = getClientReferenceManifest('/page') + const modulePaths = getClientModulePaths(manifest) + + // The page should contain its client components + const hasButton = modulePaths.some((p) => p.includes('Button')) + const hasModal = modulePaths.some((p) => p.includes('Modal')) + const hasDropdown = modulePaths.some((p) => p.includes('Dropdown')) + + expect(hasButton).toBe(true) + expect(hasModal).toBe(true) + expect(hasDropdown).toBe(true) + }) + + it('should have significantly smaller manifest for pure route handler compared to page', () => { + const routeManifest = getClientReferenceManifest('/api/hello/route') + const pageManifest = getClientReferenceManifest('/page') + + const routeModuleCount = Object.keys(routeManifest.clientModules).length + const pageModuleCount = Object.keys(pageManifest.clientModules).length + + // Route handler should have fewer client modules than the page + // (ideally 0 for a pure route handler, but allowing some for internal modules) + expect(routeModuleCount).toBeLessThan(pageModuleCount) + }) + + it('should not include page components in route handler that imports client module', () => { + const manifest = getClientReferenceManifest('/api-with-client/route') + const modulePaths = getClientModulePaths(manifest) + + // Route handler should NOT have unrelated client components from the page + // (even if it imports its own client module) + const hasButton = modulePaths.some((p) => p.includes('Button')) + const hasModal = modulePaths.some((p) => p.includes('Modal')) + const hasDropdown = modulePaths.some((p) => p.includes('Dropdown')) + + expect(hasButton).toBe(false) + expect(hasModal).toBe(false) + expect(hasDropdown).toBe(false) + }) + } + + // Functional tests that work in both dev and production + it('should respond correctly from pure route handler', async () => { + const res = await next.fetch('/api/hello') + expect(res.status).toBe(200) + const json = await res.json() + expect(json.message).toBe('Hello from pure route handler') + }) + + it('should render page with client components', async () => { + const browser = await next.browser('/') + const heading = await browser.elementByCss('h1').text() + expect(heading).toBe('Page with Client Components') + }) +}) diff --git a/test/production/app-dir/types-gen-nounuselocal/types-gen-nounuselocal.test.ts b/test/production/app-dir/types-gen-nounuselocal/types-gen-nounuselocal.test.ts index 83daae35eb2a..ee4387f9d965 100644 --- a/test/production/app-dir/types-gen-nounuselocal/types-gen-nounuselocal.test.ts +++ b/test/production/app-dir/types-gen-nounuselocal/types-gen-nounuselocal.test.ts @@ -22,7 +22,7 @@ describe('types-gen-nounuselocal', () => { it('should generate route types successfully', async () => { const routeTypes = await fsp.readFile( - path.join(next.testDir, '.next', 'types', 'routes.d.ts'), + path.join(next.testDir, '.next', 'types', 'route-types.d.ts'), 'utf-8' ) diff --git a/test/production/standalone-mode/required-server-files/required-server-files-app.test.ts b/test/production/standalone-mode/required-server-files/required-server-files-app.test.ts index 7694bd5b4171..19a0aad43a17 100644 --- a/test/production/standalone-mode/required-server-files/required-server-files-app.test.ts +++ b/test/production/standalone-mode/required-server-files/required-server-files-app.test.ts @@ -113,7 +113,6 @@ describe('required server files app router', () => { }) expect(res.status).toBe(200) expect(res.headers.get('cache-control')).toBe('s-maxage=31536000') - expect(res.headers.get('cdn-cache-control')).toBe('max-age=31536000') }) it('should handle optional catchall', async () => { @@ -172,9 +171,8 @@ describe('required server files app router', () => { }, }) expect(res.status).toBe(200) - expect(res.headers.get('cache-control')).toBe('s-maxage=3600') - expect(res.headers.get('cdn-cache-control')).toBe( - 'max-age=3600, stale-while-revalidate=31532400' + expect(res.headers.get('cache-control')).toBe( + 's-maxage=3600, stale-while-revalidate=31532400' ) }) diff --git a/test/production/standalone-mode/required-server-files/required-server-files-i18n.test.ts b/test/production/standalone-mode/required-server-files/required-server-files-i18n.test.ts index f1eb6abbc2db..b6ba636e8a76 100644 --- a/test/production/standalone-mode/required-server-files/required-server-files-i18n.test.ts +++ b/test/production/standalone-mode/required-server-files/required-server-files-i18n.test.ts @@ -174,9 +174,8 @@ describe('required server files i18n', () => { redirect: 'manual', }) expect(res.status).toBe(200) - expect(res.headers.get('cache-control')).toBe('s-maxage=1') - expect(res.headers.get('cdn-cache-control')).toBe( - 'max-age=1, stale-while-revalidate=31535999' + expect(res.headers.get('cache-control')).toBe( + 's-maxage=1, stale-while-revalidate=31535999' ) await waitFor(2000) @@ -186,9 +185,8 @@ describe('required server files i18n', () => { redirect: 'manual', }) expect(res2.status).toBe(404) - expect(res2.headers.get('cache-control')).toBe('s-maxage=1') - expect(res2.headers.get('cdn-cache-control')).toBe( - 'max-age=1, stale-while-revalidate=31535999' + expect(res2.headers.get('cache-control')).toBe( + 's-maxage=1, stale-while-revalidate=31535999' ) }) diff --git a/test/production/standalone-mode/required-server-files/required-server-files.test.ts b/test/production/standalone-mode/required-server-files/required-server-files.test.ts index 0bd27ad702a1..47f60363ebbc 100644 --- a/test/production/standalone-mode/required-server-files/required-server-files.test.ts +++ b/test/production/standalone-mode/required-server-files/required-server-files.test.ts @@ -220,18 +220,16 @@ describe('required server files', () => { path: '/optional-ssg/redirect-1', dest: '/somewhere', cacheControl: 's-maxage=31536000', - cdnCacheControl: 'max-age=31536000', }, { case: 'redirect with revalidate', path: '/optional-ssg/redirect-2', dest: '/somewhere-else', - cacheControl: 's-maxage=5', - cdnCacheControl: 'max-age=5, stale-while-revalidate=31535995', + cacheControl: 's-maxage=5, stale-while-revalidate=31535995', }, ])( `should have correct cache-control for $case`, - async ({ path, dest, cacheControl, cdnCacheControl }) => { + async ({ path, dest, cacheControl }) => { const res = await fetchViaHTTP(appPort, path, undefined, { redirect: 'manual', }) @@ -240,7 +238,6 @@ describe('required server files', () => { dest ) expect(res.headers.get('cache-control')).toBe(cacheControl) - expect(res.headers.get('cdn-cache-control')).toBe(cdnCacheControl) const dataRes = await fetchViaHTTP( appPort, @@ -250,8 +247,6 @@ describe('required server files', () => { redirect: 'manual', } ) - expect(dataRes.headers.get('cache-control')).toBe(cacheControl) - expect(dataRes.headers.get('cdn-cache-control')).toBe(cdnCacheControl) expect((await dataRes.json()).pageProps).toEqual({ __N_REDIRECT: dest, __N_REDIRECT_STATUS: 307, @@ -302,24 +297,21 @@ describe('required server files', () => { path: '/optional-ssg/not-found-1', dest: '/somewhere', cacheControl: 's-maxage=31536000', - cdnCacheControl: 'max-age=31536000', }, { case: 'notFound with revalidate', path: '/optional-ssg/not-found-2', dest: '/somewhere-else', - cacheControl: 's-maxage=5', - cdnCacheControl: 'max-age=5, stale-while-revalidate=31535995', + cacheControl: 's-maxage=5, stale-while-revalidate=31535995', }, ])( `should have correct cache-control for $case`, - async ({ path, dest, cacheControl, cdnCacheControl }) => { + async ({ path, dest, cacheControl }) => { const res = await fetchViaHTTP(appPort, path, undefined, { redirect: 'manual', }) expect(res.status).toBe(404) expect(res.headers.get('cache-control')).toBe(cacheControl) - expect(res.headers.get('cdn-cache-control')).toBe(cdnCacheControl) const dataRes = await fetchViaHTTP( appPort, @@ -330,7 +322,6 @@ describe('required server files', () => { } ) expect(dataRes.headers.get('cache-control')).toBe(cacheControl) - expect(dataRes.headers.get('cdn-cache-control')).toBe(cdnCacheControl) } ) @@ -338,7 +329,6 @@ describe('required server files', () => { const res = await fetchViaHTTP(appPort, '/optional-ssg/props-no-revalidate') expect(res.status).toBe(200) expect(res.headers.get('cache-control')).toBe('s-maxage=31536000') - expect(res.headers.get('cdn-cache-control')).toBe('max-age=31536000') const $ = cheerio.load(await res.text()) expect(JSON.parse($('#props').text()).params).toEqual({ rest: ['props-no-revalidate'], @@ -351,7 +341,6 @@ describe('required server files', () => { ) expect(dataRes.status).toBe(200) expect(res.headers.get('cache-control')).toBe('s-maxage=31536000') - expect(res.headers.get('cdn-cache-control')).toBe('max-age=31536000') expect((await dataRes.json()).pageProps.params).toEqual({ rest: ['props-no-revalidate'], }) @@ -544,9 +533,8 @@ describe('required server files', () => { redirect: 'manual', }) expect(res.status).toBe(200) - expect(res.headers.get('cache-control')).toBe('s-maxage=1') - expect(res.headers.get('cdn-cache-control')).toBe( - 'max-age=1, stale-while-revalidate=31535999' + expect(res.headers.get('cache-control')).toBe( + 's-maxage=1, stale-while-revalidate=31535999' ) await waitFor(2000) @@ -556,9 +544,8 @@ describe('required server files', () => { redirect: 'manual', }) expect(res2.status).toBe(404) - expect(res2.headers.get('cache-control')).toBe('s-maxage=1') - expect(res2.headers.get('cdn-cache-control')).toBe( - 'max-age=1, stale-while-revalidate=31535999' + expect(res2.headers.get('cache-control')).toBe( + 's-maxage=1, stale-while-revalidate=31535999' ) }) diff --git a/test/rspack-build-tests-manifest.json b/test/rspack-build-tests-manifest.json index 7a189fe084ba..95c118c6d519 100644 --- a/test/rspack-build-tests-manifest.json +++ b/test/rspack-build-tests-manifest.json @@ -2299,15 +2299,6 @@ "flakey": [], "runtimeError": false }, - "test/e2e/app-dir/cdn-cache-control-header/cdn-cache-control-header.test.ts": { - "passed": [ - "cdn-cache-control-header should use custom CDN cache control header name from experimental config" - ], - "failed": [], - "pending": [], - "flakey": [], - "runtimeError": false - }, "test/e2e/app-dir/client-module-with-package-type/index.test.ts": { "passed": [ "esm-client-module-without-exports \"type\": \"commonjs\" in package.json should render without errors: import cjs", @@ -6149,7 +6140,10 @@ "test/e2e/app-dir/resume-data-cache/resume-data-cache.test.ts": { "passed": [ "resume-data-cache should have consistent data between static and dynamic renders with fetch cache", - "resume-data-cache should have consistent data between static and dynamic renders with use cache" + "resume-data-cache should have consistent data between static and dynamic renders with use cache", + "resume-data-cache should see fresh data after updateTag in server action with fetch cache", + "resume-data-cache should see fresh data after updateTag in server action with use cache", + "resume-data-cache should use RDC for server action re-renders" ], "failed": [], "pending": [], @@ -10615,7 +10609,10 @@ "test/e2e/swc-plugins/index.test.ts": { "passed": ["swcPlugins supports swcPlugins basic case"], "failed": [], - "pending": ["swcPlugins invalid plugin name shows a redbox in dev"], + "pending": [ + "swcPlugins incompatible plugin version shows a redbox in dev", + "swcPlugins invalid plugin name shows a redbox in dev" + ], "flakey": [], "runtimeError": false }, @@ -21676,9 +21673,9 @@ "passed": [], "failed": [], "pending": [ - "next-server-nft should not include .next directory in traces despite dynamic fs operations", - "next-server-nft should not trace too many files in next-minimal-server.js.nft.json", - "next-server-nft should not trace too many files in next-server.js.nft.json" + "next-server-nft default mode should not include .next directory in traces despite dynamic fs operations", + "next-server-nft default mode should not trace too many files in next-minimal-server.js.nft.json", + "next-server-nft with output:standalone should not trace too many files in next-server.js.nft.json" ], "flakey": [], "runtimeError": false diff --git a/test/rspack-dev-tests-manifest.json b/test/rspack-dev-tests-manifest.json index c896ef23ecae..a6f20476b4d3 100644 --- a/test/rspack-dev-tests-manifest.json +++ b/test/rspack-dev-tests-manifest.json @@ -4612,15 +4612,6 @@ "flakey": [], "runtimeError": false }, - "test/e2e/app-dir/cdn-cache-control-header/cdn-cache-control-header.test.ts": { - "passed": [ - "cdn-cache-control-header should use custom CDN cache control header name from experimental config" - ], - "failed": [], - "pending": [], - "flakey": [], - "runtimeError": false - }, "test/e2e/app-dir/client-module-with-package-type/index.test.ts": { "passed": [ "esm-client-module-without-exports \"type\": \"commonjs\" in package.json should render without errors: import cjs", @@ -12630,6 +12621,7 @@ }, "test/e2e/swc-plugins/index.test.ts": { "passed": [ + "swcPlugins incompatible plugin version shows a redbox in dev", "swcPlugins invalid plugin name shows a redbox in dev", "swcPlugins supports swcPlugins basic case" ], diff --git a/test/unit/image-optimizer/fetch-external-image.test.ts b/test/unit/image-optimizer/fetch-external-image.test.ts index 4be31fda1e3b..d20fc916729a 100644 --- a/test/unit/image-optimizer/fetch-external-image.test.ts +++ b/test/unit/image-optimizer/fetch-external-image.test.ts @@ -19,7 +19,7 @@ describe('fetchExternalImage', () => { const error = await fetchExternalImage( 'http://example.com/no-body.jpg', false, - 300_000_000 + 50_000_000 ).catch((e) => e) expect(error).toBeInstanceOf(ImageError) diff --git a/test/unit/write-app-declarations.test.ts b/test/unit/write-app-declarations.test.ts index ddaa8dee4760..dd6e0cfd447d 100644 --- a/test/unit/write-app-declarations.test.ts +++ b/test/unit/write-app-declarations.test.ts @@ -3,12 +3,13 @@ import os from 'os' import fs from 'fs-extra' import { join } from 'path' import { writeAppTypeDeclarations } from 'next/dist/lib/typescript/writeAppTypeDeclarations' +import { writeRouteTypesEntryFile } from 'next/dist/server/lib/router-utils/route-types-utils' const fixtureDir = join(__dirname, 'fixtures/app-declarations') const declarationFile = join(fixtureDir, 'next-env.d.ts') const imageImportsEnabled = false -describe('find config', () => { +describe('writeAppTypeDeclarations', () => { beforeEach(async () => { await fs.ensureDir(fixtureDir) }) @@ -38,8 +39,6 @@ describe('find config', () => { imageImportsEnabled, hasPagesDir: false, hasAppDir: false, - strictRouteTypes: false, - typedRoutes: true, }) expect(await fs.readFile(declarationFile, 'utf8')).toBe(content) }) @@ -68,8 +67,6 @@ describe('find config', () => { imageImportsEnabled, hasPagesDir: false, hasAppDir: false, - strictRouteTypes: false, - typedRoutes: true, }) expect(await fs.readFile(declarationFile, 'utf8')).toBe(content) }) @@ -96,8 +93,6 @@ describe('find config', () => { imageImportsEnabled, hasPagesDir: false, hasAppDir: false, - strictRouteTypes: false, - typedRoutes: true, }) expect(await fs.readFile(declarationFile, 'utf8')).toBe(content) }) @@ -109,8 +104,6 @@ describe('find config', () => { imageImportsEnabled, hasPagesDir: false, hasAppDir: true, - strictRouteTypes: false, - typedRoutes: true, }) await expect(fs.readFile(declarationFile, 'utf8')).resolves.not.toContain( @@ -123,12 +116,147 @@ describe('find config', () => { imageImportsEnabled, hasPagesDir: true, hasAppDir: true, - strictRouteTypes: false, - typedRoutes: true, }) await expect(fs.readFile(declarationFile, 'utf8')).resolves.toContain( 'next/navigation-types/compat/navigation' ) }) + + describe('next-env.d.ts consistency between dev and build', () => { + it('should produce consistent content regardless of distDir', async () => { + // Simulate dev mode: distDir = '.next/dev', distDirRoot = '.next' + await writeAppTypeDeclarations({ + baseDir: fixtureDir, + distDir: '.next/dev', + distDirRoot: '.next', + imageImportsEnabled, + hasPagesDir: false, + hasAppDir: true, + }) + const devContent = await fs.readFile(declarationFile, 'utf8') + + // Simulate build mode: distDir = '.next', distDirRoot = '.next' + await writeAppTypeDeclarations({ + baseDir: fixtureDir, + distDir: '.next', + distDirRoot: '.next', + imageImportsEnabled, + hasPagesDir: false, + hasAppDir: true, + }) + const buildContent = await fs.readFile(declarationFile, 'utf8') + + // Both should be identical + expect(devContent).toBe(buildContent) + // Should use fixed path from distDirRoot + expect(devContent).toContain('import "./.next/types/routes.d.ts";') + expect(devContent).not.toContain('.next/dev') + }) + + it('should use distDir when distDirRoot is not provided', async () => { + await writeAppTypeDeclarations({ + baseDir: fixtureDir, + distDir: '.next', + imageImportsEnabled, + hasPagesDir: false, + hasAppDir: true, + }) + const content = await fs.readFile(declarationFile, 'utf8') + + expect(content).toContain('import "./.next/types/routes.d.ts";') + }) + }) +}) + +describe('writeRouteTypesEntryFile', () => { + const entryFileDir = join(fixtureDir, '.next', 'types') + const entryFilePath = join(entryFileDir, 'routes.d.ts') + + beforeEach(async () => { + await fs.ensureDir(entryFileDir) + }) + afterEach(() => fs.remove(join(fixtureDir, '.next'))) + + it('should write entry file with strictRouteTypes disabled', async () => { + const actualTypesDir = join(fixtureDir, '.next', 'types') + + await writeRouteTypesEntryFile(entryFilePath, actualTypesDir, { + strictRouteTypes: false, + typedRoutes: false, + }) + + const content = await fs.readFile(entryFilePath, 'utf8') + expect(content).toMatchInlineSnapshot(` +"// This is an auto-generated entry file that re-exports route types. +// Do not edit this file directly. + +export type * from "./route-types.d.ts"; +" +`) + }) + + it('should write entry file with strictRouteTypes enabled', async () => { + const actualTypesDir = join(fixtureDir, '.next', 'types') + + await writeRouteTypesEntryFile(entryFilePath, actualTypesDir, { + strictRouteTypes: true, + typedRoutes: false, + }) + + const content = await fs.readFile(entryFilePath, 'utf8') + expect(content).toMatchInlineSnapshot(` +"// This is an auto-generated entry file that re-exports route types. +// Do not edit this file directly. + +export type * from "./route-types.d.ts"; +import "./cache-life.d.ts"; +import "./validator.ts"; +" +`) + }) + + it('should write entry file with strictRouteTypes and typedRoutes enabled', async () => { + const actualTypesDir = join(fixtureDir, '.next', 'types') + + await writeRouteTypesEntryFile(entryFilePath, actualTypesDir, { + strictRouteTypes: true, + typedRoutes: true, + }) + + const content = await fs.readFile(entryFilePath, 'utf8') + expect(content).toMatchInlineSnapshot(` +"// This is an auto-generated entry file that re-exports route types. +// Do not edit this file directly. + +export type * from "./route-types.d.ts"; +import "./cache-life.d.ts"; +import "./validator.ts"; +import "./link.d.ts"; +" +`) + }) + + it('should use relative path when entry file and actual types are in different directories', async () => { + // Simulate dev mode: entry file at .next/types, actual types at .next/dev/types + const devTypesDir = join(fixtureDir, '.next', 'dev', 'types') + await fs.ensureDir(devTypesDir) + + await writeRouteTypesEntryFile(entryFilePath, devTypesDir, { + strictRouteTypes: true, + typedRoutes: true, + }) + + const content = await fs.readFile(entryFilePath, 'utf8') + expect(content).toMatchInlineSnapshot(` +"// This is an auto-generated entry file that re-exports route types. +// Do not edit this file directly. + +export type * from "./../dev/types/route-types.d.ts"; +import "./../dev/types/cache-life.d.ts"; +import "./../dev/types/validator.ts"; +import "./../dev/types/link.d.ts"; +" +`) + }) }) diff --git a/turbopack/crates/turbo-tasks-backend/Cargo.toml b/turbopack/crates/turbo-tasks-backend/Cargo.toml index 7404fcb2d9b8..4e198ef2df29 100644 --- a/turbopack/crates/turbo-tasks-backend/Cargo.toml +++ b/turbopack/crates/turbo-tasks-backend/Cargo.toml @@ -20,10 +20,12 @@ verify_serialization = [] verify_aggregation_graph = [] verify_immutable = [] verify_determinism = [] -trace_aggregation_update = [] -trace_find_and_schedule = [] +trace_aggregation_update_queue = [] +trace_aggregation_update = ["trace_aggregation_update_queue"] +trace_leaf_distance_update = [] +trace_find_and_schedule = ["trace_aggregation_update_queue"] trace_task_completion = [] -trace_task_dirty = [] +trace_task_dirty = ["trace_aggregation_update_queue"] trace_task_output_dependencies = [] trace_task_details = [] lmdb = ["dep:lmdb-rkv"] diff --git a/turbopack/crates/turbo-tasks-backend/src/backend/counter_map.rs b/turbopack/crates/turbo-tasks-backend/src/backend/counter_map.rs new file mode 100644 index 000000000000..28f748a651f7 --- /dev/null +++ b/turbopack/crates/turbo-tasks-backend/src/backend/counter_map.rs @@ -0,0 +1,438 @@ +// TODO(PR 2): Remove this once the storage schema is integrated with the rest of the codebase. +// This module is scaffolding for the TaskStorage macro and is not yet used. +#![allow(dead_code)] +use std::{ + hash::{BuildHasherDefault, Hash}, + ops::{Add, AddAssign, Sub}, +}; + +use auto_hash_map::{AutoMap, map::Entry}; +use bincode::{ + Decode, Encode, + de::Decoder, + enc::Encoder, + error::{DecodeError, EncodeError}, +}; +use rustc_hash::FxHasher; + +type InnerMap = AutoMap, 1>; + +/// A map optimized for reference counting, backed by AutoMap. +/// +/// Entries are automatically removed when their count reaches zero. +/// This provides memory-efficient storage for sparse counter data. +#[derive(Debug, Clone)] +pub struct CounterMap(InnerMap); + +impl Default for CounterMap { + fn default() -> Self { + Self(InnerMap::default()) + } +} + +impl PartialEq for CounterMap { + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 + } +} + +impl Encode for CounterMap { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + self.0.encode(encoder) + } +} + +impl Decode for CounterMap +where + K: Decode + Eq + Hash, + V: Decode, +{ + fn decode>(decoder: &mut D) -> Result { + Ok(Self(InnerMap::decode(decoder)?)) + } +} + +/// Trait for counter value types that support the required operations. +pub trait CounterValue: + Copy + Default + PartialEq + PartialOrd + Add + AddAssign + Sub +{ + /// Check if this value is zero. + fn is_zero(&self) -> bool; + + /// Check if this value is positive (> 0). + fn is_positive(&self) -> bool; +} + +impl CounterValue for u32 { + fn is_zero(&self) -> bool { + *self == 0 + } + + fn is_positive(&self) -> bool { + *self > 0 + } +} + +impl CounterValue for i32 { + fn is_zero(&self) -> bool { + *self == 0 + } + + fn is_positive(&self) -> bool { + *self > 0 + } +} + +impl CounterMap { + fn new() -> Self { + Self(AutoMap::default()) + } + + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } + + pub fn len(&self) -> usize { + self.0.len() + } + + pub fn get(&self, key: &K) -> Option<&V> + where + K: Eq + Hash, + { + self.0.get(key) + } + + pub fn iter(&self) -> impl Iterator { + self.0.iter() + } + + pub fn remove(&mut self, key: &K) -> Option + where + K: Eq + Hash, + { + self.0.remove(key) + } +} + +impl CounterMap { + /// Insert a key-value pair. Panics if value is zero (invariant: zero values are not stored). + #[cfg(test)] + pub fn insert(&mut self, key: K, value: V) -> Option { + debug_assert!( + !value.is_zero(), + "CounterMap invariant violated: cannot insert zero value" + ); + self.0.insert(key, value) + } + + /// Update a counter by the given delta, returning `true` if the count + /// crossed zero (became zero or became non-zero). + /// + /// This is useful for tracking state transitions where crossing zero + /// indicates a significant change (e.g., first reference added or last + /// reference removed). + pub fn update_count(&mut self, key: K, delta: V) -> bool { + match self.0.entry(key) { + Entry::Occupied(mut e) => { + let old = *e.get_mut(); + // Invariant: we never store zero values, so any existing entry must be non-zero + debug_assert!( + !old.is_zero(), + "CounterMap invariant violated: zero value stored" + ); + let new = old + delta; + if new.is_zero() { + e.remove(); + true // crossed from non-zero to zero + } else { + *e.get_mut() = new; + false // stayed non-zero + } + } + Entry::Vacant(e) => { + if !delta.is_zero() { + e.insert(delta); + true // crossed from zero to non-zero + } else { + false + } + } + } + } + + /// Update a counter by the given delta and return the new value. + pub fn update_and_get(&mut self, key: K, delta: V) -> V { + match self.0.entry(key) { + Entry::Occupied(mut e) => { + let old = *e.get_mut(); + // Invariant: we never store zero values, so any existing entry must be non-zero + debug_assert!( + !old.is_zero(), + "CounterMap invariant violated: zero value stored" + ); + let new_value = old + delta; + if new_value.is_zero() { + e.remove(); + } else { + *e.get_mut() = new_value; + } + new_value + } + Entry::Vacant(e) => { + if !delta.is_zero() { + e.insert(delta); + } + delta + } + } + } + + /// Update a counter using a closure that receives the current value + /// (or None if not present) and returns the new value (or None to remove). + pub fn update_with(&mut self, key: K, f: F) + where + F: FnOnce(Option) -> Option, + { + match self.0.entry(key) { + Entry::Occupied(mut e) => { + let old = *e.get_mut(); + // Invariant: we never store zero values, so any existing entry must be non-zero + debug_assert!( + !old.is_zero(), + "CounterMap invariant violated: zero value stored" + ); + match f(Some(old)) { + Some(new) => { + *e.get_mut() = new; + } + None => { + e.remove(); + } + } + } + Entry::Vacant(e) => { + if let Some(new) = f(None) { + e.insert(new); + } + } + } + } + + /// Add a new entry, panicking if the entry already exists. + pub fn add_entry(&mut self, key: K, value: V) { + let old = self.0.insert(key, value); + assert!(old.is_none(), "Entry already exists"); + } + + /// Update a signed counter by the given delta, returning `true` if the count + /// crossed the positive boundary (became positive or became non-positive). + /// + /// This is useful for tracking collectibles where positive counts indicate + /// presence and non-positive counts indicate absence. + pub fn update_positive_crossing(&mut self, key: K, delta: V) -> bool { + match self.0.entry(key) { + Entry::Occupied(mut e) => { + let old = *e.get_mut(); + // Invariant: we never store zero values, so any existing entry must be non-zero + debug_assert!( + !old.is_zero(), + "CounterMap invariant violated: zero value stored" + ); + let new = old + delta; + let state_change = old.is_positive() != new.is_positive(); + if new.is_zero() { + e.remove(); + } else { + *e.get_mut() = new; + } + state_change + } + Entry::Vacant(e) => { + if !delta.is_zero() { + e.insert(delta); + delta.is_positive() + } else { + false + } + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_update_count_new_entry() { + let mut map: CounterMap = CounterMap::new(); + // Adding new entry crosses zero (from nothing to something) + assert!(map.update_count(1, 5)); + assert_eq!(map.get(&1), Some(&5)); + } + + #[test] + fn test_update_count_increment() { + let mut map: CounterMap = CounterMap::new(); + map.update_count(1, 5); + // Incrementing existing entry doesn't cross zero + assert!(!map.update_count(1, 3)); + assert_eq!(map.get(&1), Some(&8)); + } + + #[test] + fn test_update_count_removal_on_zero() { + let mut map: CounterMap = CounterMap::new(); + map.update_count(1, 5); + // Subtracting to zero removes entry and crosses zero + assert!(map.update_count(1, -5)); + assert!(map.is_empty()); + assert_eq!(map.get(&1), None); + } + + #[test] + fn test_update_count_zero_delta_on_empty() { + let mut map: CounterMap = CounterMap::new(); + // Adding zero to non-existent entry doesn't create it + assert!(!map.update_count(1, 0)); + assert!(map.is_empty()); + } + + #[test] + fn test_update_and_get_new_entry() { + let mut map: CounterMap = CounterMap::new(); + assert_eq!(map.update_and_get(1, 5), 5); + assert_eq!(map.get(&1), Some(&5)); + } + + #[test] + fn test_update_and_get_increment() { + let mut map: CounterMap = CounterMap::new(); + map.update_and_get(1, 5); + assert_eq!(map.update_and_get(1, 3), 8); + assert_eq!(map.get(&1), Some(&8)); + } + + #[test] + fn test_update_and_get_removal() { + let mut map: CounterMap = CounterMap::new(); + map.update_and_get(1, 5); + assert_eq!(map.update_and_get(1, -5), 0); + assert!(map.is_empty()); + } + + #[test] + fn test_add_entry() { + let mut map: CounterMap = CounterMap::new(); + map.add_entry(1, 10); + assert_eq!(map.get(&1), Some(&10)); + } + + #[test] + #[should_panic(expected = "Entry already exists")] + fn test_add_entry_panics_on_duplicate() { + let mut map: CounterMap = CounterMap::new(); + map.add_entry(1, 10); + map.add_entry(1, 20); // Should panic + } + + #[test] + fn test_update_positive_crossing_new_positive() { + let mut map: CounterMap = CounterMap::new(); + // From nothing to positive - crosses positive boundary + assert!(map.update_positive_crossing(1, 5)); + assert_eq!(map.get(&1), Some(&5)); + } + + #[test] + fn test_update_positive_crossing_new_negative() { + let mut map: CounterMap = CounterMap::new(); + // From nothing to negative - doesn't cross positive boundary + assert!(!map.update_positive_crossing(1, -5)); + assert_eq!(map.get(&1), Some(&-5)); + } + + #[test] + fn test_update_positive_crossing_stay_positive() { + let mut map: CounterMap = CounterMap::new(); + map.update_positive_crossing(1, 5); + // Staying positive doesn't cross boundary + assert!(!map.update_positive_crossing(1, 3)); + assert_eq!(map.get(&1), Some(&8)); + } + + #[test] + fn test_update_positive_crossing_to_non_positive() { + let mut map: CounterMap = CounterMap::new(); + map.update_positive_crossing(1, 5); + // Crossing to non-positive + assert!(map.update_positive_crossing(1, -8)); + assert_eq!(map.get(&1), Some(&-3)); + } + + #[test] + fn test_update_positive_crossing_to_zero_removes() { + let mut map: CounterMap = CounterMap::new(); + map.update_positive_crossing(1, 5); + // Crossing to zero removes and crosses boundary + assert!(map.update_positive_crossing(1, -5)); + assert!(map.is_empty()); + } + + #[test] + fn test_update_with_create() { + let mut map: CounterMap = CounterMap::new(); + map.update_with(1, |_| Some(10)); + assert_eq!(map.get(&1), Some(&10)); + } + + #[test] + fn test_update_with_modify() { + let mut map: CounterMap = CounterMap::new(); + map.update_with(1, |_| Some(10)); + map.update_with(1, |v| v.map(|x| x + 5)); + assert_eq!(map.get(&1), Some(&15)); + } + + #[test] + fn test_update_with_remove() { + let mut map: CounterMap = CounterMap::new(); + map.update_with(1, |_| Some(10)); + map.update_with(1, |_| None); + assert!(map.is_empty()); + } + + #[test] + fn test_update_with_no_op() { + let mut map: CounterMap = CounterMap::new(); + map.update_with(1, |_| None); + assert!(map.is_empty()); + } + + #[test] + fn test_len_and_is_empty() { + let mut map: CounterMap = CounterMap::new(); + assert!(map.is_empty()); + assert_eq!(map.len(), 0); + + map.update_count(1, 5); + assert!(!map.is_empty()); + assert_eq!(map.len(), 1); + + map.update_count(2, 10); + assert_eq!(map.len(), 2); + } + + #[test] + fn test_iter() { + let mut map: CounterMap = CounterMap::new(); + map.update_count(1, 5); + map.update_count(2, 10); + + let entries: Vec<_> = map.iter().collect(); + assert_eq!(entries.len(), 2); + assert!(entries.contains(&(&1, &5))); + assert!(entries.contains(&(&2, &10))); + } +} diff --git a/turbopack/crates/turbo-tasks-backend/src/backend/mod.rs b/turbopack/crates/turbo-tasks-backend/src/backend/mod.rs index 06d35fca998e..6a83bbea783f 100644 --- a/turbopack/crates/turbo-tasks-backend/src/backend/mod.rs +++ b/turbopack/crates/turbo-tasks-backend/src/backend/mod.rs @@ -1,6 +1,8 @@ +mod counter_map; mod dynamic_storage; mod operation; mod storage; +mod storage_schema; use std::{ borrow::Cow, @@ -24,9 +26,9 @@ use smallvec::{SmallVec, smallvec}; use tokio::time::{Duration, Instant}; use tracing::{Span, trace_span}; use turbo_tasks::{ - CellId, FxDashMap, KeyValuePair, RawVc, ReadCellOptions, ReadConsistency, ReadOutputOptions, - ReadTracking, TRANSIENT_TASK_BIT, TaskExecutionReason, TaskId, TraitTypeId, - TurboTasksBackendApi, ValueTypeId, + CellId, FxDashMap, KeyValuePair, RawVc, ReadCellOptions, ReadCellTracking, ReadConsistency, + ReadOutputOptions, ReadTracking, TRANSIENT_TASK_BIT, TaskExecutionReason, TaskId, TaskPriority, + TraitTypeId, TurboTasksBackendApi, ValueTypeId, backend::{ Backend, CachedTaskType, CellContent, TaskExecutionSpec, TransientTaskRoot, TransientTaskType, TurboTasksExecutionError, TypedCellContent, VerificationMode, @@ -34,10 +36,11 @@ use turbo_tasks::{ event::{Event, EventListener}, message_queue::TimingEvent, registry::get_value_type, + scope::scope_and_block, task_statistics::TaskStatisticsApi, trace::TraceRawVcs, turbo_tasks, - util::IdFactoryWithReuse, + util::{IdFactoryWithReuse, good_chunk_size, into_chunks}, }; pub use self::{operation::AnyOperation, storage::TaskDataCategory}; @@ -46,10 +49,11 @@ use crate::backend::operation::TaskDirtyCause; use crate::{ backend::{ operation::{ - AggregationUpdateJob, AggregationUpdateQueue, CleanupOldEdgesOperation, - ComputeDirtyAndCleanUpdate, ConnectChildOperation, ExecuteContext, ExecuteContextImpl, - Operation, OutdatedEdge, TaskGuard, connect_children, get_aggregation_number, - get_uppers, is_root_node, make_task_dirty_internal, prepare_new_children, + AggregationUpdateJob, AggregationUpdateQueue, ChildExecuteContext, + CleanupOldEdgesOperation, ComputeDirtyAndCleanUpdate, ConnectChildOperation, + ExecuteContext, ExecuteContextImpl, LeafDistanceUpdateQueue, Operation, OutdatedEdge, + TaskGuard, connect_children, get_aggregation_number, get_uppers, is_root_node, + make_task_dirty_internal, prepare_new_children, }, storage::{ InnerStorageSnapshot, Storage, count, get, get_many, get_mut, get_mut_or_insert_with, @@ -68,6 +72,11 @@ use crate::{ }, }; +/// Threshold for parallelizing making dependent tasks dirty. +/// If the number of dependent tasks exceeds this threshold, +/// the operation will be parallelized. +const DEPENDENT_TASKS_DIRTY_PARALLIZATION_THRESHOLD: usize = 10000; + const SNAPSHOT_REQUESTED_BIT: usize = 1 << (usize::BITS - 1); /// Configurable idle timeout for snapshot persistence. @@ -418,7 +427,6 @@ impl Drop for OperationGuard<'_, B> { /// Intermediate result of step 1 of task execution completion. struct TaskExecutionCompletePrepareResult { pub new_children: FxHashSet, - pub removed_data: Vec, pub is_now_immutable: bool, #[cfg(feature = "verify_determinism")] pub no_output_set: bool, @@ -566,7 +574,7 @@ impl TurboTasksBackendInner { // Check the dirty count of the root node let has_dirty_containers = task.has_dirty_containers(); - if has_dirty_containers || is_dirty { + if has_dirty_containers || is_dirty.is_some() { let activeness = get_mut!(task, Activeness); let mut task_ids_to_schedule: Vec<_> = Vec::new(); // When there are dirty task, subscribe to the all_clean_event @@ -632,7 +640,11 @@ impl TurboTasksBackendInner { let has_dirty_containers = task.has_dirty_containers(); let task_description = ctx.get_task_description(task_id); - let is_dirty_label = if is_dirty { ", dirty" } else { "" }; + let is_dirty_label = if let Some(parent_priority) = is_dirty { + format!(", dirty({parent_priority})") + } else { + String::new() + }; let has_dirty_containers_label = if has_dirty_containers { ", dirty containers" } else { @@ -724,10 +736,25 @@ impl TurboTasksBackendInner { dependent_task = ?reader ) .entered(); - let _ = task.add(CachedDataItem::OutputDependent { - task: reader.unwrap(), + let mut queue = LeafDistanceUpdateQueue::new(); + let reader = reader.unwrap(); + if task.add(CachedDataItem::OutputDependent { + task: reader, value: (), - }); + }) { + // Ensure that dependent leaf distance is strictly monotonic increasing + let leaf_distance = get!(task, LeafDistance).copied().unwrap_or_default(); + let reader_leaf_distance = + get!(reader_task, LeafDistance).copied().unwrap_or_default(); + if reader_leaf_distance.distance <= leaf_distance.distance { + queue.push( + reader, + leaf_distance.distance, + leaf_distance.max_distance_in_buffer, + ); + } + } + drop(task); // Note: We use `task_pair` earlier to lock the task and its reader at the same @@ -744,6 +771,9 @@ impl TurboTasksBackendInner { value: (), }); } + drop(reader_task); + + queue.execute(&mut ctx); } return result; @@ -770,7 +800,7 @@ impl TurboTasksBackendInner { // It's not possible that the task is InProgress at this point. If it is InProgress { // done: true } it must have Output and would early return. task.add_new(item); - ctx.schedule_task(task); + ctx.schedule_task(task, TaskPriority::Initial); Ok(Err(listener)) } @@ -791,13 +821,16 @@ impl TurboTasksBackendInner { reader: Option, reader_task: Option, cell: CellId, + key: Option, ) { if let Some(mut reader_task) = reader_task && (!task.is_immutable() || cfg!(feature = "verify_immutable")) { + let reader = reader.unwrap(); let _ = task.add(CachedDataItem::CellDependent { cell, - task: reader.unwrap(), + key, + task: reader, value: (), }); drop(task); @@ -812,11 +845,16 @@ impl TurboTasksBackendInner { cell, }; if reader_task - .remove(&CachedDataItemKey::OutdatedCellDependency { target }) + .remove(&CachedDataItemKey::OutdatedCellDependency { target, key }) .is_none() { - let _ = reader_task.add(CachedDataItem::CellDependency { target, value: () }); + let _ = reader_task.add(CachedDataItem::CellDependency { + target, + key, + value: (), + }); } + drop(reader_task); } } @@ -828,7 +866,7 @@ impl TurboTasksBackendInner { let mut ctx = self.execute_context(turbo_tasks); let (mut task, reader_task) = if self.should_track_dependencies() - && !matches!(tracking, ReadTracking::Untracked) + && !matches!(tracking, ReadCellTracking::Untracked) && let Some(reader_id) = reader && reader_id != task_id { @@ -848,7 +886,7 @@ impl TurboTasksBackendInner { }; if let Some(content) = content { if tracking.should_track(false) { - add_cell_dependency(task_id, task, reader, reader_task, cell); + add_cell_dependency(task_id, task, reader, reader_task, cell, tracking.key()); } return Ok(Ok(TypedCellContent( cell.type_id, @@ -875,7 +913,7 @@ impl TurboTasksBackendInner { .copied(); let Some(max_id) = max_id else { if tracking.should_track(true) { - add_cell_dependency(task_id, task, reader, reader_task, cell); + add_cell_dependency(task_id, task, reader, reader_task, cell, tracking.key()); } bail!( "Cell {cell:?} no longer exists in task {} (no cell of this type exists)", @@ -884,7 +922,7 @@ impl TurboTasksBackendInner { }; if cell.index >= max_id { if tracking.should_track(true) { - add_cell_dependency(task_id, task, reader, reader_task, cell); + add_cell_dependency(task_id, task, reader, reader_task, cell, tracking.key()); } bail!( "Cell {cell:?} no longer exists in task {} (index out of bounds)", @@ -917,7 +955,7 @@ impl TurboTasksBackendInner { TaskExecutionReason::CellNotAvailable, || self.get_task_desc_fn(task_id), )); - ctx.schedule_task(task); + ctx.schedule_task(task, TaskPriority::Initial); Ok(Err(listener)) } @@ -1617,6 +1655,7 @@ impl TurboTasksBackendInner { fn try_start_task_execution( &self, task_id: TaskId, + priority: TaskPriority, turbo_tasks: &dyn TurboTasksBackendApi>, ) -> Option> { enum TaskType { @@ -1684,22 +1723,26 @@ impl TurboTasksBackendInner { if self.should_track_dependencies() { // Make all dependencies outdated let outdated_cell_dependencies_to_add = - iter_many!(task, CellDependency { target } => target) + iter_many!(task, CellDependency { target, key } => (target, key)) .collect::>(); let outdated_cell_dependencies_to_remove = - iter_many!(task, OutdatedCellDependency { target } => target) - .filter(|&target| { - !task.has_key(&CachedDataItemKey::CellDependency { target }) + iter_many!(task, OutdatedCellDependency { target, key } => (target, key)) + .filter(|&(target, key)| { + !task.has_key(&CachedDataItemKey::CellDependency { target, key }) }) .collect::>(); task.extend( CachedDataItemType::OutdatedCellDependency, outdated_cell_dependencies_to_add .into_iter() - .map(|target| CachedDataItem::OutdatedCellDependency { target, value: () }), + .map(|(target, key)| CachedDataItem::OutdatedCellDependency { + target, + key, + value: (), + }), ); - for target in outdated_cell_dependencies_to_remove { - task.remove(&CachedDataItemKey::OutdatedCellDependency { target }); + for (target, key) in outdated_cell_dependencies_to_remove { + task.remove(&CachedDataItemKey::OutdatedCellDependency { target, key }); } let outdated_output_dependencies_to_add = @@ -1734,7 +1777,7 @@ impl TurboTasksBackendInner { arg, } = &*task_type; ( - native_fn.span(task_id.persistence(), execution_reason), + native_fn.span(task_id.persistence(), execution_reason, priority), native_fn.execute(*this, &**arg), ) } @@ -1793,11 +1836,13 @@ impl TurboTasksBackendInner { stale = tracing::field::Empty, ) .entered(); + + let is_error = result.is_err(); + let mut ctx = self.execute_context(turbo_tasks); let Some(TaskExecutionCompletePrepareResult { new_children, - mut removed_data, is_now_immutable, #[cfg(feature = "verify_determinism")] no_output_set, @@ -1852,6 +1897,7 @@ impl TurboTasksBackendInner { return true; } + let mut removed_data = Vec::new(); if self.task_execution_completed_finish( &mut ctx, task_id, @@ -1867,9 +1913,15 @@ impl TurboTasksBackendInner { return true; } - drop(removed_data); + self.task_execution_completed_cleanup( + &mut ctx, + task_id, + cell_counters, + is_error, + &mut removed_data, + ); - self.task_execution_completed_cleanup(&mut ctx, task_id); + drop(removed_data); false } @@ -1890,7 +1942,6 @@ impl TurboTasksBackendInner { if matches!(in_progress, InProgressState::Canceled) { return Some(TaskExecutionCompletePrepareResult { new_children: Default::default(), - removed_data: Default::default(), is_now_immutable: false, #[cfg(feature = "verify_determinism")] no_output_set: false, @@ -1982,7 +2033,6 @@ impl TurboTasksBackendInner { let mut queue = AggregationUpdateQueue::new(); - let mut removed_data = Vec::new(); let mut old_edges = Vec::new(); let has_children = !new_children.is_empty(); @@ -2000,7 +2050,7 @@ impl TurboTasksBackendInner { Some( // Collect all dependencies on tasks to check if all dependencies are immutable iter_many!(task, OutputDependency { target } => target) - .chain(iter_many!(task, CellDependency { target } => target.task)) + .chain(iter_many!(task, CellDependency { target, key: _ } => target.task)) .collect::>(), ) } else { @@ -2021,27 +2071,6 @@ impl TurboTasksBackendInner { old_edges.extend(iter_many!(task, Child { task } => task).map(OutdatedEdge::Child)); } - // Remove no longer existing cells and - // find all outdated data items (removed cells, outdated edges) - // Note: For persistent tasks we only want to call extract_if when there are actual cells to - // remove to avoid tracking that as modification. - if task_id.is_transient() || iter_many!(task, CellData { cell } - if cell_counters.get(&cell.type_id).is_none_or(|start_index| cell.index >= *start_index) => cell - ).count() > 0 { - removed_data.extend(task.extract_if(CachedDataItemType::CellData, |key, _| { - matches!(key, CachedDataItemKey::CellData { cell } if cell_counters - .get(&cell.type_id).is_none_or(|start_index| cell.index >= *start_index)) - })); - } - if task_id.is_transient() || iter_many!(task, TransientCellData { cell } - if cell_counters.get(&cell.type_id).is_none_or(|start_index| cell.index >= *start_index) => cell - ).count() > 0 { - removed_data.extend(task.extract_if(CachedDataItemType::TransientCellData, |key, _| { - matches!(key, CachedDataItemKey::TransientCellData { cell } if cell_counters - .get(&cell.type_id).is_none_or(|start_index| cell.index >= *start_index)) - })); - } - old_edges.extend( task.iter(CachedDataItemType::OutdatedCollectible) .filter_map(|(key, value)| match (key, value) { @@ -2054,27 +2083,8 @@ impl TurboTasksBackendInner { ); if self.should_track_dependencies() { - old_edges.extend(iter_many!(task, OutdatedCellDependency { target } => OutdatedEdge::CellDependency(target))); + old_edges.extend(iter_many!(task, OutdatedCellDependency { target, key } => OutdatedEdge::CellDependency(target, key))); old_edges.extend(iter_many!(task, OutdatedOutputDependency { target } => OutdatedEdge::OutputDependency(target))); - old_edges.extend( - iter_many!(task, CellDependent { cell, task } => (cell, task)).filter_map( - |(cell, task)| { - if cell_counters - .get(&cell.type_id) - .is_none_or(|start_index| cell.index >= *start_index) - && let Some(old_counter) = old_counters.get(&cell.type_id) - && cell.index < *old_counter - { - return Some(OutdatedEdge::RemovedCellDependent { - task_id: task, - #[cfg(feature = "trace_task_dirty")] - value_type_id: cell.type_id, - }); - } - None - }, - ), - ); } // Check if output need to be updated @@ -2151,7 +2161,6 @@ impl TurboTasksBackendInner { Some(TaskExecutionCompletePrepareResult { new_children, - removed_data, is_now_immutable, #[cfg(feature = "verify_determinism")] no_output_set, @@ -2176,8 +2185,12 @@ impl TurboTasksBackendInner { ); } - let mut queue = AggregationUpdateQueue::new(); - for dependent_task_id in output_dependent_tasks { + fn process_output_dependents( + ctx: &mut impl ExecuteContext<'_>, + task_id: TaskId, + dependent_task_id: TaskId, + queue: &mut AggregationUpdateQueue, + ) { #[cfg(feature = "trace_task_output_dependencies")] let span = tracing::trace_span!( "invalidate output dependency", @@ -2190,7 +2203,7 @@ impl TurboTasksBackendInner { // once tasks are never invalidated #[cfg(feature = "trace_task_output_dependencies")] span.record("result", "once task"); - continue; + return; } let mut make_stale = true; let dependent = ctx.task(dependent_task_id, TaskDataCategory::All); @@ -2207,7 +2220,7 @@ impl TurboTasksBackendInner { // output anymore and doesn't need to be invalidated #[cfg(feature = "trace_task_output_dependencies")] span.record("result", "no backward dependency"); - continue; + return; } make_task_dirty_internal( dependent, @@ -2215,14 +2228,41 @@ impl TurboTasksBackendInner { make_stale, #[cfg(feature = "trace_task_dirty")] TaskDirtyCause::OutputChange { task_id }, - &mut queue, + queue, ctx, ); #[cfg(feature = "trace_task_output_dependencies")] span.record("result", "marked dirty"); } - queue.execute(ctx); + if output_dependent_tasks.len() > DEPENDENT_TASKS_DIRTY_PARALLIZATION_THRESHOLD { + let chunk_size = good_chunk_size(output_dependent_tasks.len()); + let chunks = into_chunks(output_dependent_tasks.to_vec(), chunk_size); + let _ = scope_and_block(chunks.len(), |scope| { + for chunk in chunks { + let child_ctx = ctx.child_context(); + scope.spawn(move || { + let mut ctx = child_ctx.create(); + let mut queue = AggregationUpdateQueue::new(); + for dependent_task_id in chunk { + process_output_dependents( + &mut ctx, + task_id, + dependent_task_id, + &mut queue, + ) + } + queue.execute(&mut ctx); + }); + } + }); + } else { + let mut queue = AggregationUpdateQueue::new(); + for dependent_task_id in output_dependent_tasks { + process_output_dependents(ctx, task_id, dependent_task_id, &mut queue); + } + queue.execute(ctx); + } } fn task_execution_completed_unfinished_children_dirty( @@ -2389,7 +2429,7 @@ impl TurboTasksBackendInner { let old_dirtyness = get!(task, Dirty).cloned(); let (old_self_dirty, old_current_session_self_clean) = match old_dirtyness { None => (false, false), - Some(Dirtyness::Dirty) => (true, false), + Some(Dirtyness::Dirty(_)) => (true, false), Some(Dirtyness::SessionDependent) => { let clean_in_current_session = get!(task, CurrentSessionClean).is_some(); (true, clean_in_current_session) @@ -2488,14 +2528,59 @@ impl TurboTasksBackendInner { reschedule } - fn task_execution_completed_cleanup(&self, ctx: &mut impl ExecuteContext<'_>, task_id: TaskId) { + fn task_execution_completed_cleanup( + &self, + ctx: &mut impl ExecuteContext<'_>, + task_id: TaskId, + cell_counters: &AutoMap, 8>, + is_error: bool, + removed_data: &mut Vec, + ) { let mut task = ctx.task(task_id, TaskDataCategory::All); + + // An error is potentially caused by a eventual consistency, so we avoid updating cells + // after an error as it is likely transient and we want to keep the dependent tasks + // clean to avoid re-executions. + if !is_error { + // Remove no longer existing cells and + // find all outdated data items (removed cells, outdated edges) + // Note: For persistent tasks we only want to call extract_if when there are actual + // cells to remove to avoid tracking that as modification. + // Note: We do not mark the tasks as dirty here, as these tasks are unused or stale + // anyway and we want to avoid needless re-executions. When the cells become + // used again, they are invalidated from the update cell operation. + let is_cell_unused = |cell: CellId| { + cell_counters + .get(&cell.type_id) + .is_none_or(|start_index| cell.index >= *start_index) + }; + if task_id.is_transient() + || iter_many!(task, CellData { cell } => cell).any(is_cell_unused) + { + removed_data.extend(task.extract_if(CachedDataItemType::CellData, |key, _| { + matches!(key, CachedDataItemKey::CellData { cell } if cell_counters.get(&cell.type_id).is_none_or(|start_index| cell.index >= *start_index)) + })); + } + if task_id.is_transient() + || iter_many!(task, TransientCellData { cell } => cell).any(is_cell_unused) + { + removed_data.extend(task.extract_if( + CachedDataItemType::TransientCellData, + |key, _| { + matches!(key, CachedDataItemKey::TransientCellData { cell } if cell_counters.get(&cell.type_id).is_none_or(|start_index| cell.index >= *start_index)) + }, + )); + } + } + + // Shrink memory usage task.shrink_to_fit(CachedDataItemType::CellData); task.shrink_to_fit(CachedDataItemType::TransientCellData); task.shrink_to_fit(CachedDataItemType::CellTypeMaxIndex); task.shrink_to_fit(CachedDataItemType::CellDependency); task.shrink_to_fit(CachedDataItemType::OutputDependency); task.shrink_to_fit(CachedDataItemType::CollectiblesDependency); + drop(task); } @@ -2742,6 +2827,7 @@ impl TurboTasksBackendInner { cell: CellId, is_serializable_cell_content: bool, content: CellContent, + updated_key_hashes: Option>, verification_mode: VerificationMode, turbo_tasks: &dyn TurboTasksBackendApi>, ) { @@ -2750,6 +2836,7 @@ impl TurboTasksBackendInner { cell, content, is_serializable_cell_content, + updated_key_hashes, verification_mode, self.execute_context(turbo_tasks), ); @@ -2892,7 +2979,7 @@ impl TurboTasksBackendInner { let mut task = ctx.task(task_id, TaskDataCategory::All); let is_dirty = task.is_dirty(); let has_dirty_containers = task.has_dirty_containers(); - if is_dirty || has_dirty_containers { + if is_dirty.is_some() || has_dirty_containers { if let Some(activeness_state) = get_mut!(task, Activeness) { // We will finish the task, but it would be removed after the task is done activeness_state.unset_root_type(); @@ -3231,9 +3318,11 @@ impl Backend for TurboTasksBackend { fn try_start_task_execution( &self, task_id: TaskId, + priority: TaskPriority, turbo_tasks: &dyn TurboTasksBackendApi, ) -> Option> { - self.0.try_start_task_execution(task_id, turbo_tasks) + self.0 + .try_start_task_execution(task_id, priority, turbo_tasks) } fn task_execution_completed( @@ -3337,6 +3426,7 @@ impl Backend for TurboTasksBackend { cell: CellId, is_serializable_cell_content: bool, content: CellContent, + updated_key_hashes: Option>, verification_mode: VerificationMode, turbo_tasks: &dyn TurboTasksBackendApi, ) { @@ -3345,6 +3435,7 @@ impl Backend for TurboTasksBackend { cell, is_serializable_cell_content, content, + updated_key_hashes, verification_mode, turbo_tasks, ); diff --git a/turbopack/crates/turbo-tasks-backend/src/backend/operation/aggregation_update.rs b/turbopack/crates/turbo-tasks-backend/src/backend/operation/aggregation_update.rs index 555668f022e3..57a95445cd49 100644 --- a/turbopack/crates/turbo-tasks-backend/src/backend/operation/aggregation_update.rs +++ b/turbopack/crates/turbo-tasks-backend/src/backend/operation/aggregation_update.rs @@ -15,6 +15,8 @@ use indexmap::map::Entry; use ringmap::RingSet; use rustc_hash::{FxBuildHasher, FxHashMap}; use smallvec::{SmallVec, smallvec}; +#[cfg(feature = "trace_aggregation_update_queue")] +use tracing::span::Span; #[cfg(any( feature = "trace_aggregation_update", feature = "trace_find_and_schedule" @@ -683,8 +685,8 @@ impl AggregatedDataUpdate { struct AggregationNumberUpdate { base_aggregation_number: u32, distance: Option, - #[cfg(feature = "trace_aggregation_update")] - #[bincode(skip, default)] + #[cfg(feature = "trace_aggregation_update_queue")] + #[bincode(skip)] span: Option, } @@ -692,8 +694,8 @@ struct AggregationNumberUpdate { #[derive(Encode, Decode, Clone)] struct AggregationUpdateJobItem { job: AggregationUpdateJob, - #[cfg(feature = "trace_aggregation_update")] - #[bincode(skip, default)] + #[cfg(feature = "trace_aggregation_update_queue")] + #[bincode(skip)] span: Option, } @@ -701,7 +703,7 @@ impl AggregationUpdateJobItem { fn new(job: AggregationUpdateJob) -> Self { Self { job, - #[cfg(feature = "trace_aggregation_update")] + #[cfg(feature = "trace_aggregation_update_queue")] span: Some(Span::current()), } } @@ -709,7 +711,7 @@ impl AggregationUpdateJobItem { fn entered(self) -> AggregationUpdateJobGuard { AggregationUpdateJobGuard { job: self.job, - #[cfg(feature = "trace_aggregation_update")] + #[cfg(feature = "trace_aggregation_update_queue")] _guard: self.span.map(|s| s.entered()), } } @@ -717,7 +719,7 @@ impl AggregationUpdateJobItem { struct AggregationUpdateJobGuard { job: AggregationUpdateJob, - #[cfg(feature = "trace_aggregation_update")] + #[cfg(feature = "trace_aggregation_update_queue")] _guard: Option, } @@ -726,8 +728,8 @@ struct AggregationUpdateJobGuard { struct BalanceJob { upper_id: TaskId, task_id: TaskId, - #[cfg(feature = "trace_aggregation_update")] - #[bincode(skip, default)] + #[cfg(feature = "trace_aggregation_update_queue")] + #[bincode(skip)] span: Option, } @@ -736,7 +738,7 @@ impl BalanceJob { Self { upper_id: upper, task_id: task, - #[cfg(feature = "trace_aggregation_update")] + #[cfg(feature = "trace_aggregation_update_queue")] span: Some(Span::current()), } } @@ -761,8 +763,8 @@ impl Eq for BalanceJob {} #[derive(Encode, Decode, Clone)] struct OptimizeJob { task_id: TaskId, - #[cfg(feature = "trace_aggregation_update")] - #[bincode(skip, default)] + #[cfg(feature = "trace_aggregation_update_queue")] + #[bincode(skip)] span: Option, } @@ -770,7 +772,7 @@ impl OptimizeJob { fn new(task: TaskId) -> Self { Self { task_id: task, - #[cfg(feature = "trace_aggregation_update")] + #[cfg(feature = "trace_aggregation_update_queue")] span: Some(Span::current()), } } @@ -795,7 +797,7 @@ impl Eq for OptimizeJob {} struct FindAndScheduleJob { task_id: TaskId, #[cfg(feature = "trace_find_and_schedule")] - #[bincode(skip, default)] + #[bincode(skip)] span: Option, } @@ -846,7 +848,7 @@ mod encode_jobs { | AggregationUpdateJob::DecreaseActiveCounts { .. } => { AggregationUpdateJobItem { job: AggregationUpdateJob::Noop, - #[cfg(feature = "trace_aggregation_update")] + #[cfg(feature = "trace_aggregation_update_queue")] span: None, } .encode(encoder)?; @@ -883,8 +885,8 @@ pub struct AggregationUpdateQueue { #[bincode(with = "encode_jobs")] jobs: VecDeque, #[bincode(with = "turbo_bincode::indexmap")] - number_updates: FxIndexMap, - done_number_updates: FxHashMap, + aggregation_number_updates: FxIndexMap, + done_aggregation_number_updates: FxHashMap, #[bincode(with = "turbo_bincode::ringset")] find_and_schedule: FxRingSet, #[bincode(with = "turbo_bincode::ringset")] @@ -898,8 +900,8 @@ impl AggregationUpdateQueue { pub fn new() -> Self { Self { jobs: VecDeque::with_capacity(0), - number_updates: FxIndexMap::default(), - done_number_updates: FxHashMap::default(), + aggregation_number_updates: FxIndexMap::default(), + done_aggregation_number_updates: FxHashMap::default(), find_and_schedule: FxRingSet::default(), balance_queue: FxRingSet::default(), optimize_queue: FxRingSet::default(), @@ -910,14 +912,14 @@ impl AggregationUpdateQueue { pub fn is_empty(&self) -> bool { let Self { jobs, - number_updates, + aggregation_number_updates, find_and_schedule, balance_queue, optimize_queue, - done_number_updates: _, + done_aggregation_number_updates: _, } = self; jobs.is_empty() - && number_updates.is_empty() + && aggregation_number_updates.is_empty() && find_and_schedule.is_empty() && balance_queue.is_empty() && optimize_queue.is_empty() @@ -931,7 +933,7 @@ impl AggregationUpdateQueue { base_aggregation_number, distance, } => { - match self.number_updates.entry(task_id) { + match self.aggregation_number_updates.entry(task_id) { Entry::Occupied(mut entry) => { let update = entry.get_mut(); update.base_aggregation_number = @@ -945,7 +947,7 @@ impl AggregationUpdateQueue { } } Entry::Vacant(entry) => { - match self.done_number_updates.entry(task_id) { + match self.done_aggregation_number_updates.entry(task_id) { HashMapEntry::Occupied(mut entry) => { let update = entry.get_mut(); let change = @@ -966,7 +968,7 @@ impl AggregationUpdateQueue { entry.insert(AggregationNumberUpdate { base_aggregation_number, distance, - #[cfg(feature = "trace_aggregation_update")] + #[cfg(feature = "trace_aggregation_update_queue")] span: Some(Span::current()), }); } @@ -1207,7 +1209,7 @@ impl AggregationUpdateQueue { } } false - } else if !self.number_updates.is_empty() { + } else if !self.aggregation_number_updates.is_empty() { let mut remaining = MAX_COUNT_BEFORE_YIELD; while remaining > 0 { if let Some(( @@ -1215,19 +1217,19 @@ impl AggregationUpdateQueue { AggregationNumberUpdate { base_aggregation_number, distance, - #[cfg(feature = "trace_aggregation_update")] + #[cfg(feature = "trace_aggregation_update_queue")] span, }, - )) = self.number_updates.pop() + )) = self.aggregation_number_updates.pop() { - #[cfg(feature = "trace_aggregation_update")] + #[cfg(feature = "trace_aggregation_update_queue")] let _guard = span.map(|s| s.entered()); - self.done_number_updates.insert( + self.done_aggregation_number_updates.insert( task_id, AggregationNumberUpdate { base_aggregation_number, distance, - #[cfg(feature = "trace_aggregation_update")] + #[cfg(feature = "trace_aggregation_update_queue")] span: None, }, ); @@ -1244,11 +1246,11 @@ impl AggregationUpdateQueue { if let Some(BalanceJob { upper_id: upper, task_id: task, - #[cfg(feature = "trace_aggregation_update")] + #[cfg(feature = "trace_aggregation_update_queue")] span, }) = self.balance_queue.pop_front() { - #[cfg(feature = "trace_aggregation_update")] + #[cfg(feature = "trace_aggregation_update_queue")] let _guard = span.map(|s| s.entered()); self.balance_edge(ctx, upper, task); remaining -= 1; @@ -1259,14 +1261,14 @@ impl AggregationUpdateQueue { false } else if let Some(OptimizeJob { task_id, - #[cfg(feature = "trace_aggregation_update")] + #[cfg(feature = "trace_aggregation_update_queue")] span, }) = self.optimize_queue.pop_front() { // Note: We must process one optimization completely before starting with the next one. // Otherwise this could lead to optimizing every node of a subgraph of inner nodes, as // all have the same upper count. Optimizing the root first - #[cfg(feature = "trace_aggregation_update")] + #[cfg(feature = "trace_aggregation_update_queue")] let _guard = span.map(|s| s.entered()); self.optimize_task(ctx, task_id); false @@ -1498,10 +1500,13 @@ impl AggregationUpdateQueue { ) { // Task need to be scheduled if it's dirty or doesn't have output let dirty = task.is_dirty(); - let should_schedule = if dirty { - Some(TaskExecutionReason::ActivateDirty) + let should_schedule = if let Some(parent_priority) = dirty { + Some((TaskExecutionReason::ActivateDirty, parent_priority)) } else if !task.has_key(&CachedDataItemKey::Output {}) { - Some(TaskExecutionReason::ActivateInitial) + Some(( + TaskExecutionReason::ActivateInitial, + ctx.get_current_task_priority(), + )) } else { None }; @@ -1512,7 +1517,7 @@ impl AggregationUpdateQueue { if !is_active_until_clean { let mut dirty_containers = task.dirty_containers().peekable(); let is_empty = dirty_containers.peek().is_none(); - if !is_empty || dirty { + if !is_empty || dirty.is_some() { self.extend_find_and_schedule_dirty(dirty_containers); let activeness_state = @@ -1520,11 +1525,11 @@ impl AggregationUpdateQueue { activeness_state.set_active_until_clean(); } } - if let Some(reason) = should_schedule { + if let Some((reason, parent_priority)) = should_schedule { let description = || ctx.get_task_desc_fn(task_id); if task.add(CachedDataItem::new_scheduled(reason, description)) { drop(task); - ctx.schedule(task_id); + ctx.schedule(task_id, parent_priority); } } } diff --git a/turbopack/crates/turbo-tasks-backend/src/backend/operation/cleanup_old_edges.rs b/turbopack/crates/turbo-tasks-backend/src/backend/operation/cleanup_old_edges.rs index e18873d38280..c24134816678 100644 --- a/turbopack/crates/turbo-tasks-backend/src/backend/operation/cleanup_old_edges.rs +++ b/turbopack/crates/turbo-tasks-backend/src/backend/operation/cleanup_old_edges.rs @@ -5,8 +5,6 @@ use rustc_hash::FxHashSet; use smallvec::SmallVec; use turbo_tasks::TaskId; -#[cfg(feature = "trace_task_dirty")] -use crate::backend::operation::invalidate::TaskDirtyCause; use crate::{ backend::{ TaskDataCategory, get, get_many, @@ -16,7 +14,6 @@ use crate::{ AggregationUpdateJob, AggregationUpdateQueue, InnerOfUppersLostFollowersJob, get_aggregation_number, get_uppers, is_aggregating_node, }, - invalidate::make_task_dirty, }, storage::update_count, }, @@ -42,14 +39,9 @@ pub enum CleanupOldEdgesOperation { pub enum OutdatedEdge { Child(TaskId), Collectible(CollectibleRef, i32), - CellDependency(CellRef), + CellDependency(CellRef, Option), OutputDependency(TaskId), CollectiblesDependency(CollectiblesRef), - RemovedCellDependent { - task_id: TaskId, - #[cfg(feature = "trace_task_dirty")] - value_type_id: turbo_tasks::ValueTypeId, - }, } impl CleanupOldEdgesOperation { @@ -160,14 +152,18 @@ impl Operation for CleanupOldEdgesOperation { AggregatedDataUpdate::new().collectibles_update(collectibles), )); } - OutdatedEdge::CellDependency(CellRef { - task: cell_task_id, - cell, - }) => { + OutdatedEdge::CellDependency( + CellRef { + task: cell_task_id, + cell, + }, + key, + ) => { { let mut task = ctx.task(cell_task_id, TaskDataCategory::Data); task.remove(&CachedDataItemKey::CellDependent { cell, + key, task: task_id, }); } @@ -178,6 +174,7 @@ impl Operation for CleanupOldEdgesOperation { task: cell_task_id, cell, }, + key, }); } } @@ -224,21 +221,6 @@ impl Operation for CleanupOldEdgesOperation { }); } } - OutdatedEdge::RemovedCellDependent { - task_id, - #[cfg(feature = "trace_task_dirty")] - value_type_id, - } => { - make_task_dirty( - task_id, - #[cfg(feature = "trace_task_dirty")] - TaskDirtyCause::CellRemoved { - value_type: value_type_id, - }, - queue, - ctx, - ); - } } } diff --git a/turbopack/crates/turbo-tasks-backend/src/backend/operation/connect_child.rs b/turbopack/crates/turbo-tasks-backend/src/backend/operation/connect_child.rs index cbfc93a6d5f6..9492f6bdce82 100644 --- a/turbopack/crates/turbo-tasks-backend/src/backend/operation/connect_child.rs +++ b/turbopack/crates/turbo-tasks-backend/src/backend/operation/connect_child.rs @@ -34,7 +34,7 @@ impl ConnectChildOperation { new_children, .. })) = get_mut!(parent_task, InProgress) else { - panic!("Task is not in progress while calling another task"); + panic!("Task is not in progress while calling another task: {parent_task:?}"); }; // Quick skip if the child was already connected before @@ -74,7 +74,7 @@ impl ConnectChildOperation { || ctx.get_task_desc_fn(child_task_id), )) { - ctx.schedule_task(child_task); + ctx.schedule_task(child_task, ctx.get_current_task_priority()); } } diff --git a/turbopack/crates/turbo-tasks-backend/src/backend/operation/connect_children.rs b/turbopack/crates/turbo-tasks-backend/src/backend/operation/connect_children.rs index 36ab4b042ecf..3009a06f29bd 100644 --- a/turbopack/crates/turbo-tasks-backend/src/backend/operation/connect_children.rs +++ b/turbopack/crates/turbo-tasks-backend/src/backend/operation/connect_children.rs @@ -125,10 +125,10 @@ pub fn connect_children( // This avoids long pauses of more than 30µs * 10k = 300ms. // We don't want to parallelize too eagerly as spawning tasks and the temporary allocations have // a cost as well. - const MIN_CHILDREN_FOR_PARALLEL: usize = 10000; + const CONNECT_CHILDREN_PARALLIZATION_THRESHOLD: usize = 10000; let len = new_follower_ids.len(); - if len >= MIN_CHILDREN_FOR_PARALLEL { + if len >= CONNECT_CHILDREN_PARALLIZATION_THRESHOLD { let new_follower_ids = new_follower_ids.into_vec(); let chunk_size = good_chunk_size(len); let _ = scope_and_block(len.div_ceil(chunk_size), |scope| { diff --git a/turbopack/crates/turbo-tasks-backend/src/backend/operation/invalidate.rs b/turbopack/crates/turbo-tasks-backend/src/backend/operation/invalidate.rs index 2383da6ee391..fd0be0958fd4 100644 --- a/turbopack/crates/turbo-tasks-backend/src/backend/operation/invalidate.rs +++ b/turbopack/crates/turbo-tasks-backend/src/backend/operation/invalidate.rs @@ -13,10 +13,7 @@ use crate::{ }, storage::{get, get_mut, remove}, }, - data::{ - CachedDataItem, CachedDataItemKey, CachedDataItemValue, Dirtyness, InProgressState, - InProgressStateInner, - }, + data::{CachedDataItem, CachedDataItemKey, Dirtyness, InProgressState, InProgressStateInner}, }; #[derive(Encode, Decode, Clone, Default)] @@ -64,7 +61,7 @@ impl Operation for InvalidateOperation { make_task_dirty( task_id, #[cfg(feature = "trace_task_dirty")] - cause, + cause.clone(), &mut queue, ctx, ); @@ -90,11 +87,12 @@ impl Operation for InvalidateOperation { } #[cfg(feature = "trace_task_dirty")] -#[derive(Serialize, Deserialize, Clone, Copy, Debug)] +#[derive(Encode, Decode, Clone, Debug)] pub enum TaskDirtyCause { InitialDirty, CellChange { value_type: turbo_tasks::ValueTypeId, + keys: SmallVec<[Option; 2]>, }, CellRemoved { value_type: turbo_tasks::ValueTypeId, @@ -132,12 +130,27 @@ impl<'e, E: ExecuteContext<'e>> std::fmt::Display for TaskDirtyCauseInContext<'_ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self.cause { TaskDirtyCause::InitialDirty => write!(f, "initial dirty"), - TaskDirtyCause::CellChange { value_type } => { - write!( - f, - "{} cell changed", - turbo_tasks::registry::get_value_type(*value_type).name - ) + TaskDirtyCause::CellChange { value_type, keys } => { + if keys.is_empty() { + write!( + f, + "{} cell changed", + turbo_tasks::registry::get_value_type(*value_type).name + ) + } else { + write!( + f, + "{} cell changed (keys: {})", + turbo_tasks::registry::get_value_type(*value_type).name, + keys.iter() + .map(|key| match key { + Some(k) => k.to_string(), + None => "*".to_string(), + }) + .collect::>() + .join(", ") + ) + } } TaskDirtyCause::CellRemoved { value_type } => { write!( @@ -231,13 +244,9 @@ pub fn make_task_dirty_internal( .entered(); *stale = true; } - let old = task.insert(CachedDataItem::Dirty { - value: Dirtyness::Dirty, - }); - let (old_self_dirty, old_current_session_self_clean) = match old { - Some(CachedDataItemValue::Dirty { - value: Dirtyness::Dirty, - }) => { + let current = get!(task, Dirty); + let (old_self_dirty, old_current_session_self_clean, parent_priority) = match current { + Some(Dirtyness::Dirty(current_priority)) => { #[cfg(feature = "trace_task_dirty")] let _span = tracing::trace_span!( "task already dirty", @@ -247,17 +256,26 @@ pub fn make_task_dirty_internal( ) .entered(); // already dirty + let parent_priority = ctx.get_current_task_priority(); + if current_priority >= &parent_priority { + // Update the priority to be the lower one + task.insert(CachedDataItem::Dirty { + value: Dirtyness::Dirty(parent_priority), + }); + } return; } - Some(CachedDataItemValue::Dirty { - value: Dirtyness::SessionDependent, - }) => { + Some(Dirtyness::SessionDependent) => { + let parent_priority = ctx.get_current_task_priority(); + task.insert(CachedDataItem::Dirty { + value: Dirtyness::Dirty(parent_priority), + }); // It was a session-dependent dirty before, so we need to remove that clean count let was_current_session_clean = remove!(task, CurrentSessionClean).is_some(); if was_current_session_clean { // There was a clean count for a session. If it was the current session, we need to // propagate that change. - (true, true) + (true, true, parent_priority) } else { #[cfg(feature = "trace_task_dirty")] let _span = tracing::trace_span!( @@ -271,10 +289,13 @@ pub fn make_task_dirty_internal( } } None => { + let parent_priority = ctx.get_current_task_priority(); + task.insert(CachedDataItem::Dirty { + value: Dirtyness::Dirty(parent_priority), + }); // It was clean before, so we need to increase the dirty count - (false, false) + (false, false, parent_priority) } - _ => unreachable!(), }; let new_self_dirty = true; @@ -327,7 +348,7 @@ pub fn make_task_dirty_internal( )) { drop(task); let task = ctx.task(task_id, TaskDataCategory::All); - ctx.schedule_task(task); + ctx.schedule_task(task, parent_priority); } } } diff --git a/turbopack/crates/turbo-tasks-backend/src/backend/operation/leaf_distance_update.rs b/turbopack/crates/turbo-tasks-backend/src/backend/operation/leaf_distance_update.rs new file mode 100644 index 000000000000..9fec97b41a61 --- /dev/null +++ b/turbopack/crates/turbo-tasks-backend/src/backend/operation/leaf_distance_update.rs @@ -0,0 +1,198 @@ +use std::{ + cmp::Reverse, + collections::{BinaryHeap, hash_map::Entry}, +}; + +use bincode::{Decode, Encode}; +use rustc_hash::FxHashMap; +#[cfg(feature = "trace_leaf_distance_update")] +use tracing::{span::Span, trace_span}; +use turbo_tasks::TaskId; + +use crate::{ + backend::{ + TaskDataCategory, + operation::{ExecuteContext, Operation, TaskGuard}, + storage::{get, iter_many}, + }, + data::CachedDataItem, +}; + +/// The maximum number of leaf distance updates to process before yielding back to the executor. +/// This prevents long blocking operations and allows to interrupt the processing for persistent +/// caching. +const MAX_COUNT_BEFORE_YIELD: usize = 1000; + +/// We avoid incrementing the leaf distance by 1 each time to avoid frequent updates. +/// Instead we use a buffer zone that shrinks as the leaf distance increases. +/// This constant defines the size of that buffer zone at leaf distance 0. +const BASE_LEAF_DISTANCE_BUFFER: u32 = 128; + +/// An leaf distance update job that is enqueued. +#[derive(Encode, Decode, Clone)] +struct LeafDistanceUpdate { + dependencies_distance: u32, + dependencies_max_distance_in_buffer: u32, + done: bool, + #[cfg(feature = "trace_leaf_distance_update")] + #[bincode(skip)] + span: Option, +} + +impl LeafDistanceUpdate { + fn add(&mut self, dependency_distance: u32, dependency_max_distance_in_buffer: u32) { + self.dependencies_distance = self.dependencies_distance.max(dependency_distance); + self.dependencies_max_distance_in_buffer = self + .dependencies_max_distance_in_buffer + .max(dependency_max_distance_in_buffer); + } +} + +/// A queue of leaf distance update jobs. +/// It will execute these jobs in order of their minimum dependency leaf distance. +/// This ensures that we never have to re-process a task. +#[derive(Default, Encode, Decode, Clone)] +pub struct LeafDistanceUpdateQueue { + queue: BinaryHeap<(Reverse, TaskId)>, + leaf_distance_updates: FxHashMap, +} + +impl LeafDistanceUpdateQueue { + pub fn new() -> Self { + Self::default() + } + + pub fn is_empty(&self) -> bool { + self.queue.is_empty() + } + + pub fn push( + &mut self, + task_id: TaskId, + dependency_distance: u32, + dependency_max_distance_in_buffer: u32, + ) { + match self.leaf_distance_updates.entry(task_id) { + Entry::Occupied(mut entry) => { + let update = entry.get_mut(); + if update.done && update.dependencies_distance < dependency_distance { + update.done = false; + self.queue.push((Reverse(dependency_distance), task_id)); + } + update.add(dependency_distance, dependency_max_distance_in_buffer); + } + Entry::Vacant(entry) => { + entry.insert(LeafDistanceUpdate { + dependencies_distance: dependency_distance, + dependencies_max_distance_in_buffer: dependency_max_distance_in_buffer, + done: false, + }); + self.queue.push((Reverse(dependency_distance), task_id)); + } + }; + } + + /// Executes a single step of the queue. Returns true, when the queue is empty. + pub fn process(&mut self, ctx: &mut impl ExecuteContext) -> bool { + let mut remaining = MAX_COUNT_BEFORE_YIELD; + while remaining > 0 { + if let Some((Reverse(queue_dependencies_distance), task_id)) = self.queue.pop() { + let &mut LeafDistanceUpdate { + dependencies_distance, + dependencies_max_distance_in_buffer, + ref mut done, + #[cfg(feature = "trace_leaf_distance_update")] + span, + } = self.leaf_distance_updates.get_mut(&task_id).unwrap(); + if queue_dependencies_distance != dependencies_distance { + // Stale entry in queue + // Re-enqueue to keep the ordering correct + self.queue.push((Reverse(dependencies_distance), task_id)); + continue; + } + #[cfg(feature = "trace_leaf_distance_update")] + let _guard = span.map(|s| s.entered()); + *done = true; + self.update_leaf_distance( + ctx, + task_id, + dependencies_distance, + dependencies_max_distance_in_buffer, + ); + remaining -= 1; + } else { + return true; + } + } + false + } + + fn update_leaf_distance( + &mut self, + ctx: &mut impl ExecuteContext, + task_id: TaskId, + dependencies_distance: u32, + dependencies_max_distance_in_buffer: u32, + ) { + #[cfg(feature = "trace_leaf_distance_update")] + let _span = trace_span!( + "update leaf distance", + dependencies_distance, + dependencies_max_distance_in_buffer + ) + .entered(); + let mut task = ctx.task( + task_id, + // For performance reasons this should stay `Data` and not `All` + TaskDataCategory::Data, + ); + debug_assert!(dependencies_max_distance_in_buffer < u32::MAX / 2); + let mut leaf_distance = get!(task, LeafDistance).copied().unwrap_or_default(); + if leaf_distance.distance > dependencies_distance { + // It is strictly monotonic. No need to update. + return; + } + // It's not strictly monotonic, we need to update + if leaf_distance.max_distance_in_buffer <= dependencies_distance { + // We overshoot the buffer zone. + let old_value = leaf_distance.distance; + leaf_distance.distance = dependencies_max_distance_in_buffer + 1; + let buffer_size = BASE_LEAF_DISTANCE_BUFFER + - BASE_LEAF_DISTANCE_BUFFER.saturating_mul(old_value) / leaf_distance.distance; + leaf_distance.max_distance_in_buffer = leaf_distance.distance + buffer_size; + } else { + // We are within the buffer zone, keep the max as is + leaf_distance.distance = dependencies_distance + 1; + } + let dependents = iter_many!(task, OutputDependent { task } => task) + // TODO Technically this is also needed, but there are cycles in the CellDependent graph + // So we need to handle that properly first + // When enabling this, make sure to also call the leaf update queue when adding CellDependents + // .chain(iter_many!(task, CellDependent { task, .. } => task)) + ; + for dependent_id in dependents { + self.push( + dependent_id, + leaf_distance.distance, + leaf_distance.max_distance_in_buffer, + ); + } + task.insert(CachedDataItem::LeafDistance { + value: leaf_distance, + }); + } +} + +impl Operation for LeafDistanceUpdateQueue { + fn execute(mut self, ctx: &mut impl ExecuteContext) { + if self.is_empty() { + return; + } + loop { + ctx.operation_suspend_point(&self); + if self.process(ctx) { + return; + } + } + } +} diff --git a/turbopack/crates/turbo-tasks-backend/src/backend/operation/mod.rs b/turbopack/crates/turbo-tasks-backend/src/backend/operation/mod.rs index 961fba638424..0a50e8f33e34 100644 --- a/turbopack/crates/turbo-tasks-backend/src/backend/operation/mod.rs +++ b/turbopack/crates/turbo-tasks-backend/src/backend/operation/mod.rs @@ -3,6 +3,7 @@ mod cleanup_old_edges; mod connect_child; mod connect_children; mod invalidate; +mod leaf_distance_update; mod prepare_new_children; mod update_cell; mod update_collectible; @@ -15,7 +16,8 @@ use std::{ use bincode::{Decode, Encode}; use turbo_tasks::{ - CellId, FxIndexMap, KeyValuePair, TaskId, TurboTasksBackendApi, TypedSharedReference, + CellId, FxIndexMap, KeyValuePair, TaskId, TaskPriority, TurboTasksBackendApi, + TypedSharedReference, }; use crate::{ @@ -77,8 +79,9 @@ pub trait ExecuteContext<'e>: Sized { task_id2: TaskId, category: TaskDataCategory, ) -> (Self::TaskGuardImpl, Self::TaskGuardImpl); - fn schedule(&mut self, task_id: TaskId); - fn schedule_task(&self, task: Self::TaskGuardImpl); + fn schedule(&mut self, task_id: TaskId, parent_priority: TaskPriority); + fn schedule_task(&self, task: Self::TaskGuardImpl, parent_priority: TaskPriority); + fn get_current_task_priority(&self) -> TaskPriority; fn operation_suspend_point(&mut self, op: &T) where T: Clone + Into; @@ -243,6 +246,8 @@ where if id.is_transient() { if call_prepared_task_callback_for_transient_tasks { let mut task = self.backend.storage.access_mut(id); + // TODO add is_restoring and avoid concurrent restores and duplicates tasks + // ids in `task_ids` if !task.state().is_restored(category) { task.state_mut().set_restored(TaskDataCategory::All); } @@ -555,13 +560,28 @@ where ) } - fn schedule(&mut self, task_id: TaskId) { + fn schedule(&mut self, task_id: TaskId, parent_priority: TaskPriority) { let task = self.task(task_id, TaskDataCategory::All); - self.schedule_task(task); + self.schedule_task(task, parent_priority); } - fn schedule_task(&self, task: Self::TaskGuardImpl) { - self.turbo_tasks.schedule(task.id()); + fn schedule_task(&self, task: Self::TaskGuardImpl, parent_priority: TaskPriority) { + let priority = if get!(task, Output).is_some() { + TaskPriority::invalidation( + get!(task, LeafDistance) + .copied() + .unwrap_or_default() + .distance, + ) + } else { + TaskPriority::initial() + }; + self.turbo_tasks + .schedule(task.id(), priority.in_parent(parent_priority)); + } + + fn get_current_task_priority(&self) -> TaskPriority { + self.turbo_tasks.get_current_task_priority() } fn operation_suspend_point>(&mut self, op: &T) { @@ -665,15 +685,21 @@ pub trait TaskGuard: Debug { fn is_immutable(&self) -> bool { self.has_key(&CachedDataItemKey::Immutable {}) } - fn is_dirty(&self) -> bool { - get!(self, Dirty).is_some_and(|dirtyness| match dirtyness { - Dirtyness::Dirty => true, - Dirtyness::SessionDependent => get!(self, CurrentSessionClean).is_none(), + fn is_dirty(&self) -> Option { + get!(self, Dirty).and_then(|dirtyness| match dirtyness { + Dirtyness::Dirty(priority) => Some(*priority), + Dirtyness::SessionDependent => { + if get!(self, CurrentSessionClean).is_none() { + Some(TaskPriority::leaf()) + } else { + None + } + } }) } fn dirtyness_and_session(&self) -> Option<(Dirtyness, bool)> { match get!(self, Dirty)? { - Dirtyness::Dirty => Some((Dirtyness::Dirty, false)), + Dirtyness::Dirty(priority) => Some((Dirtyness::Dirty(*priority), false)), Dirtyness::SessionDependent => Some(( Dirtyness::SessionDependent, get!(self, CurrentSessionClean).is_some(), @@ -684,7 +710,7 @@ pub trait TaskGuard: Debug { fn dirty(&self) -> (bool, bool) { match get!(self, Dirty) { None => (false, false), - Some(Dirtyness::Dirty) => (true, false), + Some(Dirtyness::Dirty(_)) => (true, false), Some(Dirtyness::SessionDependent) => (true, get!(self, CurrentSessionClean).is_some()), } } @@ -1003,7 +1029,7 @@ impl TaskGuard for TaskGuardImpl<'_, B> { } self.task.state_mut().set_prefetched(true); let map = iter_many!(self, OutputDependency { target } => (target, TaskDataCategory::Meta)) - .chain(iter_many!(self, CellDependency { target } => (target.task, TaskDataCategory::All))) + .chain(iter_many!(self, CellDependency { target, key: _ } => (target.task, TaskDataCategory::All))) .chain(iter_many!(self, CollectiblesDependency { target } => (target.task, TaskDataCategory::All))) .chain(iter_many!(self, Child { task } => (task, TaskDataCategory::All))) .collect::>(); @@ -1041,6 +1067,7 @@ pub enum AnyOperation { UpdateCell(update_cell::UpdateCellOperation), CleanupOldEdges(cleanup_old_edges::CleanupOldEdgesOperation), AggregationUpdate(aggregation_update::AggregationUpdateQueue), + LeafDistanceUpdate(leaf_distance_update::LeafDistanceUpdateQueue), Nested(Vec), } @@ -1052,6 +1079,7 @@ impl AnyOperation { AnyOperation::UpdateCell(op) => op.execute(ctx), AnyOperation::CleanupOldEdges(op) => op.execute(ctx), AnyOperation::AggregationUpdate(op) => op.execute(ctx), + AnyOperation::LeafDistanceUpdate(op) => op.execute(ctx), AnyOperation::Nested(ops) => { for op in ops { op.execute(ctx); @@ -1066,6 +1094,7 @@ impl_operation!(Invalidate invalidate::InvalidateOperation); impl_operation!(UpdateCell update_cell::UpdateCellOperation); impl_operation!(CleanupOldEdges cleanup_old_edges::CleanupOldEdgesOperation); impl_operation!(AggregationUpdate aggregation_update::AggregationUpdateQueue); +impl_operation!(LeafDistanceUpdate leaf_distance_update::LeafDistanceUpdateQueue); #[cfg(feature = "trace_task_dirty")] pub use self::invalidate::TaskDirtyCause; diff --git a/turbopack/crates/turbo-tasks-backend/src/backend/operation/update_cell.rs b/turbopack/crates/turbo-tasks-backend/src/backend/operation/update_cell.rs index e5408cb1f1c5..c76df6b0a594 100644 --- a/turbopack/crates/turbo-tasks-backend/src/backend/operation/update_cell.rs +++ b/turbopack/crates/turbo-tasks-backend/src/backend/operation/update_cell.rs @@ -1,10 +1,12 @@ use std::mem::take; use bincode::{Decode, Encode}; +use once_cell::unsync::Lazy; +use rustc_hash::FxHashSet; use smallvec::SmallVec; #[cfg(not(feature = "verify_determinism"))] use turbo_tasks::backend::VerificationMode; -use turbo_tasks::{CellId, TaskId, TypedSharedReference, backend::CellContent}; +use turbo_tasks::{CellId, FxIndexMap, TaskId, TypedSharedReference, backend::CellContent}; #[cfg(feature = "trace_task_dirty")] use crate::backend::operation::invalidate::TaskDirtyCause; @@ -26,7 +28,10 @@ pub enum UpdateCellOperation { InvalidateWhenCellDependency { is_serializable_cell_content: bool, cell_ref: CellRef, - dependent_tasks: SmallVec<[TaskId; 4]>, + #[bincode(with = "turbo_bincode::indexmap")] + dependent_tasks: FxIndexMap; 2]>>, + #[cfg(feature = "trace_task_dirty")] + has_updated_key_hashes: bool, content: Option, queue: AggregationUpdateQueue, }, @@ -49,6 +54,7 @@ impl UpdateCellOperation { cell: CellId, content: CellContent, is_serializable_cell_content: bool, + updated_key_hashes: Option>, #[cfg(feature = "verify_determinism")] verification_mode: VerificationMode, #[cfg(not(feature = "verify_determinism"))] _verification_mode: VerificationMode, mut ctx: impl ExecuteContext, @@ -96,17 +102,31 @@ impl UpdateCellOperation { // When not recomputing, we need to notify dependent tasks if the content actually // changes. - let dependent_tasks: SmallVec<[TaskId; 4]> = iter_many!( + #[cfg(feature = "trace_task_dirty")] + let has_updated_key_hashes = updated_key_hashes.is_some(); + let updated_key_hashes_set = updated_key_hashes.map(|updated_key_hashes| { + Lazy::new(|| updated_key_hashes.into_iter().collect::>()) + }); + + let tasks_with_keys = iter_many!( task, - CellDependent { cell: dependent_cell, task } - if dependent_cell == cell - => task + CellDependent { cell: dependent_cell, key, task } + if dependent_cell == cell && key.is_none_or(|key_hash| { + updated_key_hashes_set.as_ref().is_none_or(|set| { + set.contains(&key_hash) + }) + }) + => (task, key) ) - .filter(|&dependent_task_id| { + .filter(|&(dependent_task_id, _)| { // once tasks are never invalidated !ctx.is_once_task(dependent_task_id) - }) - .collect(); + }); + let mut dependent_tasks: FxIndexMap; 2]>> = + FxIndexMap::default(); + for (task, key) in tasks_with_keys { + dependent_tasks.entry(task).or_default().push(key); + } if !dependent_tasks.is_empty() { // Slow path: We need to invalidate tasks depending on this cell. @@ -132,7 +152,7 @@ impl UpdateCellOperation { ctx.prepare_tasks( dependent_tasks - .iter() + .keys() .map(|&id| (id, TaskDataCategory::All)), ); @@ -143,6 +163,8 @@ impl UpdateCellOperation { cell, }, dependent_tasks, + #[cfg(feature = "trace_task_dirty")] + has_updated_key_hashes, content, queue: AggregationUpdateQueue::new(), } @@ -204,27 +226,36 @@ impl Operation for UpdateCellOperation { is_serializable_cell_content, cell_ref, ref mut dependent_tasks, + #[cfg(feature = "trace_task_dirty")] + has_updated_key_hashes, ref mut content, ref mut queue, } => { - if let Some(dependent_task_id) = dependent_tasks.pop() { - let mut make_stale = true; + if let Some((dependent_task_id, keys)) = dependent_tasks.pop() { + let mut make_stale = false; let dependent = ctx.task(dependent_task_id, TaskDataCategory::All); - if dependent.has_key(&CachedDataItemKey::OutdatedCellDependency { - target: cell_ref, - }) { - // cell dependency is outdated, so it hasn't read the cell yet - // and doesn't need to be invalidated. - // But importantly we still need to make the task dirty as it should no - // longer be considered as "recomputation". - make_stale = false; - } else if !dependent - .has_key(&CachedDataItemKey::CellDependency { target: cell_ref }) - { - // cell dependency has been removed, so the task doesn't depend on the - // cell anymore and doesn't need to be - // invalidated - continue; + for key in keys.iter().copied() { + if dependent.has_key(&CachedDataItemKey::OutdatedCellDependency { + target: cell_ref, + key, + }) { + // cell dependency is outdated, so it hasn't read the cell yet + // and doesn't need to be invalidated. + // We do not need to make the task stale in this case. + // But importantly we still need to make the task dirty as it should + // no longer be considered as + // "recomputation". + } else if !dependent.has_key(&CachedDataItemKey::CellDependency { + target: cell_ref, + key, + }) { + // cell dependency has been removed, so the task doesn't depend on + // the cell anymore and doesn't need + // to be invalidated + continue; + } else { + make_stale = true; + } } make_task_dirty_internal( dependent, @@ -233,6 +264,7 @@ impl Operation for UpdateCellOperation { #[cfg(feature = "trace_task_dirty")] TaskDirtyCause::CellChange { value_type: cell_ref.cell.type_id, + keys: has_updated_key_hashes.then_some(keys).unwrap_or_default(), }, queue, ctx, diff --git a/turbopack/crates/turbo-tasks-backend/src/backend/storage.rs b/turbopack/crates/turbo-tasks-backend/src/backend/storage.rs index 06c3bcda1f2d..f66286329b32 100644 --- a/turbopack/crates/turbo-tasks-backend/src/backend/storage.rs +++ b/turbopack/crates/turbo-tasks-backend/src/backend/storage.rs @@ -12,7 +12,8 @@ use crate::{ backend::dynamic_storage::DynamicStorage, data::{ AggregationNumber, CachedDataItem, CachedDataItemKey, CachedDataItemType, - CachedDataItemValue, CachedDataItemValueRef, CachedDataItemValueRefMut, OutputValue, + CachedDataItemValue, CachedDataItemValueRef, CachedDataItemValueRefMut, LeafDistance, + OutputValue, }, data_storage::{AutoMapStorage, DefaultStorage, OptionStorage}, utils::{ @@ -138,6 +139,7 @@ impl InnerStorageState { } pub struct InnerStorageSnapshot { + leaf_distance: DefaultStorage, aggregation_number: DefaultStorage, output_dependent: AutoMapStorage, output: OptionStorage, @@ -150,6 +152,7 @@ pub struct InnerStorageSnapshot { impl From<&InnerStorage> for InnerStorageSnapshot { fn from(inner: &InnerStorage) -> Self { Self { + leaf_distance: inner.leaf_distance.clone(), aggregation_number: inner.aggregation_number.clone(), output_dependent: inner.output_dependent.clone(), output: inner.output.clone(), @@ -168,6 +171,12 @@ impl InnerStorageSnapshot { use crate::data_storage::Storage; self.dynamic .iter_all() + .chain(self.leaf_distance.iter().map(|(_, value)| { + ( + CachedDataItemKey::LeafDistance {}, + CachedDataItemValueRef::LeafDistance { value }, + ) + })) .chain(self.aggregation_number.iter().map(|(_, value)| { ( CachedDataItemKey::AggregationNumber {}, @@ -197,6 +206,7 @@ impl InnerStorageSnapshot { pub fn len(&self) -> usize { use crate::data_storage::Storage; self.dynamic.len() + + self.leaf_distance.len() + self.aggregation_number.len() + self.output.len() + self.upper.len() @@ -206,6 +216,7 @@ impl InnerStorageSnapshot { #[derive(Debug, Clone)] pub struct InnerStorage { + leaf_distance: DefaultStorage, aggregation_number: DefaultStorage, output_dependent: AutoMapStorage, output: OptionStorage, @@ -217,6 +228,7 @@ pub struct InnerStorage { impl InnerStorage { fn new() -> Self { Self { + leaf_distance: Default::default(), aggregation_number: Default::default(), output_dependent: Default::default(), output: Default::default(), @@ -553,32 +565,36 @@ macro_rules! generate_inner_storage { } generate_inner_storage!( + LeafDistance => leaf_distance, AggregationNumber => aggregation_number, OutputDependent task => output_dependent, Output => output, Upper task => upper, ); -enum InnerStorageIter { - AggregationNumber(A), - OutputDependent(B), - Output(C), - Upper(D), - Dynamic(E), +enum InnerStorageIter { + LeafDistance(A), + AggregationNumber(B), + OutputDependent(C), + Output(D), + Upper(E), + Dynamic(F), } -impl Iterator for InnerStorageIter +impl Iterator for InnerStorageIter where A: Iterator, B: Iterator, C: Iterator, D: Iterator, E: Iterator, + F: Iterator, { type Item = T; fn next(&mut self) -> Option { match self { + InnerStorageIter::LeafDistance(iter) => iter.next(), InnerStorageIter::AggregationNumber(iter) => iter.next(), InnerStorageIter::OutputDependent(iter) => iter.next(), InnerStorageIter::Output(iter) => iter.next(), @@ -595,6 +611,12 @@ impl InnerStorage { use crate::data_storage::Storage; self.dynamic .iter_all() + .chain(self.leaf_distance.iter().map(|(_, value)| { + ( + CachedDataItemKey::LeafDistance {}, + CachedDataItemValueRef::LeafDistance { value }, + ) + })) .chain(self.aggregation_number.iter().map(|(_, value)| { ( CachedDataItemKey::AggregationNumber {}, @@ -624,6 +646,7 @@ impl InnerStorage { pub fn len(&self) -> usize { use crate::data_storage::Storage; self.dynamic.len() + + self.leaf_distance.len() + self.aggregation_number.len() + self.output.len() + self.upper.len() @@ -1231,12 +1254,12 @@ mod tests { // We track this to catch unexpected bloat from type changes. assert_eq!( std::mem::size_of::(), - 128, + 136, "InnerStorage size changed - please review if this is intentional" ); assert_eq!( std::mem::size_of::(), - 128, + 136, "InnerStorageSnapshot size changed - please review if this is intentional" ); } diff --git a/turbopack/crates/turbo-tasks-backend/src/backend/storage_schema.rs b/turbopack/crates/turbo-tasks-backend/src/backend/storage_schema.rs new file mode 100644 index 000000000000..bfd87367c37b --- /dev/null +++ b/turbopack/crates/turbo-tasks-backend/src/backend/storage_schema.rs @@ -0,0 +1,837 @@ +//! Task Storage Schema Definition +//! +//! This module defines the complete schema for task storage using the TaskStorage derive macro. +//! The schema covers all CachedDataItem variants with appropriate storage types and categories. +//! +//! # Storage Types (`storage = "..."`) +//! +//! - `direct` - For single optional values (e.g., Output, Dirty, AggregationNumber) +//! - `auto_set` - For sets of keys with unit values (e.g., Child, OutputDependency) +//! - `counter_map` - For maps with counted references (e.g., Upper, Follower, Collectible) +//! - `auto_map` - For maps with non-counter values (e.g., CellData) +//! - `auto_multimap` - For maps with set values (e.g., CellDependents) +//! - `flag` - For boolean flags stored in TaskFlags bitfield +//! +//! # Categories (`category = "..."`) +//! +//! - `data` - Frequently changed bulk data (dependencies, cell data) +//! - `meta` - Rarely changed metadata (output, aggregation, flags) +//! - `transient` - Not serialized, only exists in memory + +// TODO(PR 2): Remove this once the storage schema is integrated with the rest of the codebase. +// This module is scaffolding for the TaskStorage macro and is not yet used. +#![allow(dead_code)] + +use turbo_tasks::{ + CellId, SharedReference, TaskId, TraitTypeId, TypedSharedReference, ValueTypeId, task_storage, +}; + +use crate::data::{ + ActivenessState, AggregationNumber, CellRef, CollectibleRef, CollectiblesRef, Dirtyness, + InProgressCellState, InProgressState, OutputValue, +}; + +/// Auto-set storage for small sets of keys with unit values. +/// Optimized for small collections (< 8 items use SmallVec inline). +type AutoSet = auto_hash_map::AutoSet, 1>; + +use super::counter_map::CounterMap; + +/// Auto-map storage for key-value pairs. +type AutoMap = + auto_hash_map::AutoMap, 1>; + +/// The complete task storage schema. +/// +/// This struct defines all storage fields for a task. The `#[task_storage]` macro +/// transforms this schema into the actual implementation: +/// - `TaskStorage` struct with inline and lazy field storage +/// - `LazyField` enum for lazy-allocated fields +/// - `TaskFlags` bitfield for boolean flags +/// - Accessor methods and traits +/// +/// Fields are stored lazily in `Vec` by default for memory efficiency. +/// Fields with `inline` are stored directly on TaskStorage (for hot-path access). +/// +/// Note: This struct is consumed by the macro and does not appear in the output. +#[task_storage] +struct TaskStorageSchema { + // ========================================================================= + // INLINE FIELDS (hot path, always allocated inline) + // ========================================================================= + /// The task's aggregation number for the aggregation tree. + /// Uses Default::default() semantics - a zero aggregation number means "not set". + #[field(storage = "direct", category = "meta", inline, default)] + pub aggregation_number: AggregationNumber, + + /// Tasks that depend on this task's output. + #[field(storage = "auto_set", category = "data", inline, filter_transient)] + pub output_dependent: AutoSet, + + /// The task's output value. + /// Filtered during serialization to skip transient outputs (referencing transient tasks). + #[field(storage = "direct", category = "meta", inline, filter_transient)] + pub output: Option, + + /// Upper nodes in the aggregation tree (reference counted). + #[field(storage = "counter_map", category = "meta", inline, filter_transient)] + pub upper: CounterMap, + + // ========================================================================= + // COLLECTIBLES (meta) + // ========================================================================= + /// Collectibles emitted by this task (reference counted). + #[field(storage = "counter_map", category = "meta", filter_transient)] + pub collectibles: CounterMap, + + /// Aggregated collectibles from the subgraph. + #[field(storage = "counter_map", category = "meta", filter_transient)] + pub aggregated_collectibles: CounterMap, + + /// Outdated collectibles to be cleaned up (transient). + #[field(storage = "counter_map", category = "transient")] + pub outdated_collectibles: CounterMap, + + // ========================================================================= + // STATE FIELDS (meta) + // Note: Lazy direct fields use bare types - Vec presence provides optionality + // ========================================================================= + /// Whether the task is dirty (needs re-execution). + /// Absent = clean, present = dirty with the specified Dirtyness state. + #[field(storage = "direct", category = "meta")] + pub dirty: Dirtyness, + + /// Count of dirty containers in the aggregated subgraph. + /// Absent = 0, present = actual count. + #[field(storage = "direct", category = "meta")] + pub aggregated_dirty_container_count: i32, + + /// Individual dirty containers in the aggregated subgraph. + #[field(storage = "counter_map", category = "meta", filter_transient)] + pub aggregated_dirty_containers: CounterMap, + + /// Count of clean containers in current session (transient). + /// Absent = 0, present = actual count. + #[field(storage = "direct", category = "transient")] + pub aggregated_current_session_clean_container_count: i32, + + /// Individual clean containers in current session (transient). + #[field(storage = "counter_map", category = "transient")] + pub aggregated_current_session_clean_containers: CounterMap, + + // ========================================================================= + // FLAGS (meta) - Boolean flags stored in TaskFlags bitfield + // Persisted flags come first, then transient flags. + // ========================================================================= + /// Whether the task has an invalidator. + #[field(storage = "flag", category = "meta")] + pub invalidator: bool, + + /// Whether the task output is immutable (persisted). + #[field(storage = "flag", category = "meta")] + pub immutable: bool, + + /// Whether clean in current session (transient flag). + #[field(storage = "flag", category = "transient")] + pub current_session_clean: bool, + + // ========================================================================= + // INTERNAL STATE FLAGS (transient) - Replaces InnerStorageState + // These flags track internal state for persistence and snapshotting. + // ========================================================================= + /// Whether meta data has been restored from persistent storage. + #[field(storage = "flag", category = "transient")] + pub meta_restored: bool, + + /// Whether data has been restored from persistent storage. + #[field(storage = "flag", category = "transient")] + pub data_restored: bool, + + /// Whether meta was modified before snapshot mode was entered. + #[field(storage = "flag", category = "transient")] + pub meta_modified: bool, + + /// Whether data was modified before snapshot mode was entered. + #[field(storage = "flag", category = "transient")] + pub data_modified: bool, + + /// Whether meta was modified after snapshot mode was entered (snapshot taken). + #[field(storage = "flag", category = "transient")] + pub meta_snapshot: bool, + + /// Whether data was modified after snapshot mode was entered (snapshot taken). + #[field(storage = "flag", category = "transient")] + pub data_snapshot: bool, + + /// Whether dependencies have been prefetched. + #[field(storage = "flag", category = "transient")] + pub prefetched: bool, + + // ========================================================================= + // CHILDREN & AGGREGATION (meta) + // ========================================================================= + /// Child tasks of this task. + #[field(storage = "auto_set", category = "meta", filter_transient)] + pub children: AutoSet, + + /// Follower nodes in the aggregation tree (reference counted). + #[field(storage = "counter_map", category = "meta", filter_transient)] + pub followers: CounterMap, + + // ========================================================================= + // DEPENDENCIES (data) + // ========================================================================= + /// Tasks whose output this task depends on. + #[field(storage = "auto_set", category = "data", filter_transient)] + pub output_dependencies: AutoSet, + + /// Cells this task depends on. + #[field(storage = "auto_set", category = "data", filter_transient)] + pub cell_dependencies: AutoSet, + + /// Collectibles this task depends on. + #[field(storage = "auto_set", category = "data", filter_transient)] + pub collectibles_dependencies: AutoSet, + + /// Outdated output dependencies to be cleaned up (transient). + #[field(storage = "auto_set", category = "transient")] + pub outdated_output_dependencies: AutoSet, + + /// Outdated cell dependencies to be cleaned up (transient). + #[field(storage = "auto_set", category = "transient")] + pub outdated_cell_dependencies: AutoSet, + + /// Outdated collectibles dependencies to be cleaned up (transient). + #[field(storage = "auto_set", category = "transient")] + pub outdated_collectibles_dependencies: AutoSet, + + // ========================================================================= + // DEPENDENTS - Tasks that depend on this task's cells + // ========================================================================= + /// Tasks that depend on specific cells of this task. + /// Maps CellId -> Set + #[field(storage = "auto_set", category = "data", filter_transient)] + pub cell_dependents: AutoSet<(CellId, Option, TaskId)>, + + /// Tasks that depend on collectibles of a specific type from this task. + /// Maps TraitTypeId -> Set + #[field(storage = "auto_set", category = "meta", filter_transient)] + pub collectibles_dependents: AutoSet<(TraitTypeId, TaskId)>, + + // ========================================================================= + // CELL DATA (data) + // ========================================================================= + /// Persistent cell data (serializable). + #[field(storage = "auto_map", category = "data")] + pub cell_data: AutoMap, + + /// Transient cell data (not serializable). + #[field(storage = "auto_map", category = "transient")] + pub transient_cell_data: AutoMap, + + /// Maximum cell index per cell type. + #[field(storage = "auto_map", category = "data")] + pub cell_type_max_index: AutoMap, + + // ========================================================================= + // TRANSIENT EXECUTION STATE (transient) + // ========================================================================= + /// Activeness state for root/once tasks (transient). + /// Note: Lazy storage provides natural optionality - + /// presence in Vec = Some, absence = None. No Option wrapper needed. + #[field(storage = "direct", category = "transient")] + pub activeness: ActivenessState, + + /// In-progress execution state (transient). + /// Note: Lazy storage provides natural optionality - + /// presence in Vec = Some, absence = None. No Option wrapper needed. + #[field(storage = "direct", category = "transient")] + pub in_progress: InProgressState, + + /// In-progress cell state for cells being computed (transient). + #[field(storage = "auto_map", category = "transient")] + pub in_progress_cells: AutoMap, +} + +// ============================================================================= +// TaskFlags helper methods (for InnerStorageState compatibility) +// ============================================================================= + +use crate::backend::TaskDataCategory; + +impl TaskFlags { + /// Set restored flags based on category + pub fn set_restored(&mut self, category: TaskDataCategory) { + match category { + TaskDataCategory::Meta => { + self.set_meta_restored(true); + } + TaskDataCategory::Data => { + self.set_data_restored(true); + } + TaskDataCategory::All => { + self.set_meta_restored(true); + self.set_data_restored(true); + } + } + } + + /// Check if category is restored + pub fn is_restored(&self, category: TaskDataCategory) -> bool { + match category { + TaskDataCategory::Meta => self.meta_restored(), + TaskDataCategory::Data => self.data_restored(), + TaskDataCategory::All => self.meta_restored() && self.data_restored(), + } + } + + /// Check if any snapshot flag is set + pub fn any_snapshot(&self) -> bool { + self.meta_snapshot() || self.data_snapshot() + } + + /// Check if any modified flag is set + pub fn any_modified(&self) -> bool { + self.meta_modified() || self.data_modified() + } +} + +// ============================================================================= +// TaskStorage helper methods +// ============================================================================= + +impl TaskStorage { + /// Find a lazy field by predicate (immutable). + /// + /// The `extract` closure should return `Some(&T)` for the matching variant, + /// or `None` for non-matching variants. + fn find_lazy(&self, extract: impl Fn(&LazyField) -> Option<&T>) -> Option<&T> { + self.lazy.iter().find_map(extract) + } + + /// Find a lazy field by predicate (mutable). + /// + /// The `extract` closure should return `Some(&mut T)` for the matching variant, + /// or `None` for non-matching variants. + pub fn find_lazy_mut( + &mut self, + extract: impl Fn(&mut LazyField) -> Option<&mut T>, + ) -> Option<&mut T> { + self.lazy.iter_mut().find_map(extract) + } + + /// Get or create a lazy field, returning a mutable reference. + /// + /// Uses a single `extract` closure that serves as both the matcher (by returning Some/None) + /// and the value extractor. The closure is first used to find the field position, + /// then to extract the mutable reference. + /// + /// # Example + /// ```ignore + /// let deps = storage.get_or_create_lazy( + /// |f| matches!(f, LazyField::OutputDependencies(_)), + /// |f| match f { + /// LazyField::OutputDependencies(v) => v, + /// _ => unreachable!(), + /// }, + /// || LazyField::OutputDependencies(Default::default()), + /// ); + /// ``` + fn get_or_create_lazy( + &mut self, + matches: impl Fn(&LazyField) -> bool, + extract: impl for<'a> FnOnce(&'a mut LazyField) -> &'a mut T, + create: impl FnOnce() -> LazyField, + ) -> &mut T { + // Find the index of matching field (immutable borrow) + let idx = self.lazy.iter().position(matches); + if let Some(idx) = idx { + extract(&mut self.lazy[idx]) + } else { + self.lazy.push(create()); + extract(self.lazy.last_mut().unwrap()) + } + } + + /// Take a lazy field by predicate, removing it from the Vec. + /// + /// Uses a `matches` predicate to find the field index, then `extract` to + /// unwrap the value from the removed field. + /// + /// Returns `None` if no matching field exists. + fn take_lazy( + &mut self, + matches: impl Fn(&LazyField) -> bool, + extract: impl FnOnce(LazyField) -> T, + ) -> Option { + let idx = self.lazy.iter().position(matches)?; + Some(extract(self.lazy.swap_remove(idx))) + } + + /// Set a lazy field value, replacing any existing value. + /// + /// Uses a `matches` predicate to find an existing field. If found, replaces it + /// in place and extracts the old value. Otherwise pushes the new value. + /// + /// Returns the old value if one existed. + fn set_lazy( + &mut self, + matches: impl Fn(&LazyField) -> bool, + extract: impl FnOnce(LazyField) -> T, + new_value: LazyField, + ) -> Option { + if let Some(idx) = self.lazy.iter().position(matches) { + let old = std::mem::replace(&mut self.lazy[idx], new_value); + Some(extract(old)) + } else { + self.lazy.push(new_value); + None + } + } +} + +// Support serialization filtering for CellDependents and CollectibleDependents + +trait IsTransient { + fn is_transient(&self) -> bool; +} + +impl IsTransient for (TraitTypeId, TaskId) { + fn is_transient(&self) -> bool { + self.1.is_transient() + } +} +impl IsTransient for (CellId, Option, TaskId) { + fn is_transient(&self) -> bool { + self.2.is_transient() + } +} +#[cfg(test)] +mod tests { + use std::mem::size_of; + + use turbo_tasks::{CellId, TaskId}; + + use super::*; + use crate::data::{AggregationNumber, CellRef, Dirtyness, OutputValue}; + + #[test] + fn test_accessors() { + let mut storage = TaskStorage::new(); + + // Inline direct fields (Option-wrapped) + assert_eq!(storage.get_output(), None); + assert_eq!( + storage.set_output(OutputValue::Output(TaskId::new(1).unwrap())), + None + ); + assert_eq!( + storage.get_output(), + Some(&OutputValue::Output(TaskId::new(1).unwrap())) + ); + + assert_eq!(storage.get_aggregation_number(), None); + storage.set_aggregation_number(AggregationNumber { + base: 10, + distance: 5, + effective: 15, + }); + assert!(storage.get_aggregation_number().is_some()); + + // Inline collection fields (always present) + storage.upper_mut().insert(TaskId::new(5).unwrap(), 3); + assert_eq!(storage.upper().get(&TaskId::new(5).unwrap()), Some(&3)); + + storage + .output_dependent_mut() + .insert(TaskId::new(5).unwrap()); + assert!( + storage + .output_dependent() + .contains(&TaskId::new(5).unwrap()) + ); + + // Lazy direct fields + assert!(storage.get_dirty().is_none()); + storage.set_dirty(Dirtyness::SessionDependent); + assert_eq!(storage.get_dirty(), Some(&Dirtyness::SessionDependent)); + + // Lazy collection fields (None until accessed via _mut) + assert!(storage.output_dependencies().is_none()); + storage + .output_dependencies_mut() + .insert(TaskId::new(10).unwrap()); + assert_eq!(storage.output_dependencies().unwrap().len(), 1); + + assert!(storage.children().is_none()); + storage.children_mut().insert(TaskId::new(20).unwrap()); + assert_eq!(storage.children().unwrap().len(), 1); + + // Lazy counter_map + assert!(storage.followers().is_none()); + storage.followers_mut().insert(TaskId::new(30).unwrap(), 5); + assert_eq!( + storage.followers().unwrap().get(&TaskId::new(30).unwrap()), + Some(&5) + ); + } + + #[test] + fn test_flag_fields() { + let mut storage = TaskStorage::new(); + + // Test that flags are default false + assert!(!storage.flags.invalidator()); + assert!(!storage.flags.immutable()); + assert!(!storage.flags.current_session_clean()); + + // Test setting flags + storage.flags.set_immutable(true); + assert!(storage.flags.immutable()); + assert!(!storage.flags.invalidator()); // Other flags unchanged + + storage.flags.set_invalidator(true); + storage.flags.set_immutable(true); + assert!(storage.flags.invalidator()); + assert!(storage.flags.immutable()); + + // Test transient flag (current_session_clean) + storage.flags.set_current_session_clean(true); + assert!(storage.flags.current_session_clean()); + + // Test persisted_bits only includes non-transient flags + // invalidator=bit 0, immutable=bit 1 (persisted) + // current_session_clean=bit 2 (transient) + let persisted = storage.flags.persisted_bits(); + assert_eq!(persisted, 0b11); // Only bits 0, 1 + + // Test TaskFlags constants + assert_eq!(TaskFlags::PERSISTED_MASK, 0b11); // 2 persisted flags + + // Test set_persisted_bits preserves transient flags + let mut storage2 = TaskStorage::new(); + storage2.flags.set_current_session_clean(true); // Set transient flag + storage2.flags.set_persisted_bits(0b10); // Set immutable only + assert!(storage2.flags.immutable()); + assert!(!storage2.flags.invalidator()); + assert!(storage2.flags.current_session_clean()); // Transient flag preserved + } + + #[test] + fn test_internal_state_flags() { + // Test the new internal state flags (formerly InnerStorageState) + let mut storage = TaskStorage::new(); + + // All internal state flags should be default false + assert!(!storage.flags.meta_restored()); + assert!(!storage.flags.data_restored()); + assert!(!storage.flags.meta_modified()); + assert!(!storage.flags.data_modified()); + assert!(!storage.flags.meta_snapshot()); + assert!(!storage.flags.data_snapshot()); + assert!(!storage.flags.prefetched()); + + // Test setting restored flags + storage.flags.set_meta_restored(true); + storage.flags.set_data_restored(true); + assert!(storage.flags.meta_restored()); + assert!(storage.flags.data_restored()); + + // Test setting modified flags + storage.flags.set_meta_modified(true); + storage.flags.set_data_modified(true); + assert!(storage.flags.meta_modified()); + assert!(storage.flags.data_modified()); + + // Test setting snapshot flags + storage.flags.set_meta_snapshot(true); + storage.flags.set_data_snapshot(true); + assert!(storage.flags.meta_snapshot()); + assert!(storage.flags.data_snapshot()); + + // Test prefetched flag + storage.flags.set_prefetched(true); + assert!(storage.flags.prefetched()); + + // Verify these are all transient (not in persisted_bits) + // Only invalidator, immutable should be persisted + let persisted = storage.flags.persisted_bits(); + assert_eq!(persisted, 0b00); // No persisted flags set + + // Set a persisted flag and verify internal state flags are still transient + storage.flags.set_immutable(true); + let persisted = storage.flags.persisted_bits(); + assert_eq!(persisted, 0b10); // Only immutable (bit 1) + } + + // Helper to create encoder + fn new_encoder( + buffer: &mut turbo_bincode::TurboBincodeBuffer, + ) -> turbo_bincode::TurboBincodeEncoder<'_> { + bincode::enc::EncoderImpl::new( + turbo_bincode::TurboBincodeWriter::new(buffer), + turbo_bincode::TURBO_BINCODE_CONFIG, + ) + } + + // Helper to create decoder + fn new_decoder(buffer: &[u8]) -> turbo_bincode::TurboBincodeDecoder<'_> { + bincode::de::DecoderImpl::new( + turbo_bincode::TurboBincodeReader::new(buffer), + turbo_bincode::TURBO_BINCODE_CONFIG, + (), + ) + } + + #[test] + fn test_encode_decode_meta_roundtrip() { + let mut original = TaskStorage::new(); + + // Set inline meta fields via accessor methods + original.set_aggregation_number(AggregationNumber { + base: 10, + distance: 5, + effective: 15, + }); + original.set_output(OutputValue::Output(TaskId::new(42).unwrap())); + original.upper_mut().insert(TaskId::new(100).unwrap(), 7); + original.upper_mut().insert(TaskId::new(200).unwrap(), 3); + original.set_dirty(Dirtyness::SessionDependent); + original.set_aggregated_dirty_container_count(5); + original + .aggregated_dirty_containers_mut() + .insert(TaskId::new(50).unwrap(), 2); + + // Set flags (persisted) + original.flags.set_immutable(true); + // Set transient flag (should NOT be serialized) + original.flags.set_current_session_clean(true); + + // Set lazy meta fields (persisted) + original.children_mut().insert(TaskId::new(1000).unwrap()); + original.children_mut().insert(TaskId::new(1001).unwrap()); + original + .followers_mut() + .insert(TaskId::new(2000).unwrap(), 4); + + // Encode meta fields using turbo_bincode + let mut buffer = turbo_bincode::TurboBincodeBuffer::new(); + { + let mut encoder = new_encoder(&mut buffer); + original.encode_meta(&mut encoder).expect("encode failed"); + } + + // Decode into new storage + let mut decoded = TaskStorage::new(); + // Set transient flag before decode to verify it's preserved + decoded.flags.set_current_session_clean(true); + + { + let mut decoder = new_decoder(&buffer); + decoded.decode_meta(&mut decoder).expect("decode failed"); + } + + // Verify inline meta fields via accessor methods + assert_eq!( + decoded.get_aggregation_number(), + original.get_aggregation_number() + ); + assert_eq!(decoded.get_output(), original.get_output()); + assert_eq!(decoded.upper(), original.upper()); + // Verify lazy meta fields via accessor methods + assert_eq!(decoded.get_dirty(), original.get_dirty()); + assert_eq!( + decoded.get_aggregated_dirty_container_count(), + original.get_aggregated_dirty_container_count() + ); + assert_eq!( + decoded.aggregated_dirty_containers(), + original.aggregated_dirty_containers() + ); + + // Verify flags (persisted bits should match) + assert!(!decoded.flags.invalidator()); + assert!(decoded.flags.immutable()); + // Transient flag should be preserved (was set to true before decode) + assert!(decoded.flags.current_session_clean()); + + // Verify lazy meta fields + assert_eq!(decoded.children().unwrap().len(), 2); + assert!( + decoded + .children() + .unwrap() + .contains(&TaskId::new(1000).unwrap()) + ); + assert!( + decoded + .children() + .unwrap() + .contains(&TaskId::new(1001).unwrap()) + ); + assert_eq!( + *decoded + .followers() + .unwrap() + .get(&TaskId::new(2000).unwrap()) + .unwrap(), + 4 + ); + } + + #[test] + fn test_encode_decode_data_roundtrip() { + let mut original = TaskStorage::new(); + + // Set inline data field via accessor methods + original + .output_dependent_mut() + .insert(TaskId::new(10).unwrap()); + original + .output_dependent_mut() + .insert(TaskId::new(20).unwrap()); + + // Set lazy data fields (persisted) + original + .output_dependencies_mut() + .insert(TaskId::new(100).unwrap()); + original + .output_dependencies_mut() + .insert(TaskId::new(200).unwrap()); + original.cell_dependencies_mut().insert(CellRef { + task: TaskId::new(1).unwrap(), + cell: CellId { + type_id: unsafe { turbo_tasks::ValueTypeId::new_unchecked(1) }, + index: 0, + }, + }); + + // Set lazy data transient field (should NOT be serialized) + original + .outdated_output_dependencies_mut() + .insert(TaskId::new(999).unwrap()); + + // Encode data fields + let mut buffer = turbo_bincode::TurboBincodeBuffer::new(); + { + let mut encoder = new_encoder(&mut buffer); + original.encode_data(&mut encoder).expect("encode failed"); + } + + // Decode into new storage + let mut decoded = TaskStorage::new(); + + { + let mut decoder = new_decoder(&buffer); + decoded.decode_data(&mut decoder).expect("decode failed"); + } + + // Verify inline data field + assert_eq!(decoded.output_dependent().len(), 2); + assert!( + decoded + .output_dependent() + .contains(&TaskId::new(10).unwrap()) + ); + assert!( + decoded + .output_dependent() + .contains(&TaskId::new(20).unwrap()) + ); + + // Verify lazy data fields + assert_eq!(decoded.output_dependencies().unwrap().len(), 2); + assert!( + decoded + .output_dependencies() + .unwrap() + .contains(&TaskId::new(100).unwrap()) + ); + assert!( + decoded + .output_dependencies() + .unwrap() + .contains(&TaskId::new(200).unwrap()) + ); + assert_eq!(decoded.cell_dependencies().unwrap().len(), 1); + + // Verify transient fields were NOT decoded + assert!(decoded.outdated_output_dependencies().is_none()); + } + + #[test] + fn test_encode_decode_empty_storage() { + // Test that empty storage can be encoded/decoded + let original = TaskStorage::new(); + + // Encode meta + let mut meta_buffer = turbo_bincode::TurboBincodeBuffer::new(); + { + let mut encoder = new_encoder(&mut meta_buffer); + original + .encode_meta(&mut encoder) + .expect("encode meta failed"); + } + + // Encode data + let mut data_buffer = turbo_bincode::TurboBincodeBuffer::new(); + { + let mut encoder = new_encoder(&mut data_buffer); + original + .encode_data(&mut encoder) + .expect("encode data failed"); + } + + // Decode meta + let mut decoded = TaskStorage::new(); + { + let mut decoder = new_decoder(&meta_buffer); + decoded + .decode_meta(&mut decoder) + .expect("decode meta failed"); + } + + // Decode data + { + let mut decoder = new_decoder(&data_buffer); + decoded + .decode_data(&mut decoder) + .expect("decode data failed"); + } + + // Verify empty via accessor methods + assert_eq!(decoded.get_aggregation_number(), None); + assert_eq!(decoded.get_output(), None); + assert!(decoded.upper().is_empty()); + assert!(decoded.output_dependent().is_empty()); + assert_eq!(decoded.children(), None); + assert_eq!(decoded.output_dependencies(), None); + } + + // ========================================================================== + // Schema Size Tests + // ========================================================================== + + #[test] + #[cfg(target_pointer_width = "64")] + fn test_schema_size() { + // TaskStorage uses lazy storage for most fields, keeping inline storage minimal. + // Current layout (128 bytes): + // - output_dependent (AutoSet): 24 bytes + // - aggregation_number (AggregationNumber with default): 12 bytes + // - output (Option): 32 bytes + // - upper (CounterMap): 24 bytes + // - flags (TaskFlags): 8 bytes + // - lazy (Vec): 24 bytes + // - padding: 4 bytes + // + // Use exact size check to catch regressions in either direction. + assert_eq!( + size_of::(), + 128, + "TaskStorage size changed! Was 128 bytes, now {} bytes. If this is intentional, \ + update this test.", + size_of::() + ); + } +} diff --git a/turbopack/crates/turbo-tasks-backend/src/data.rs b/turbopack/crates/turbo-tasks-backend/src/data.rs index bff8af1c692d..8abb16fab3a4 100644 --- a/turbopack/crates/turbo-tasks-backend/src/data.rs +++ b/turbopack/crates/turbo-tasks-backend/src/data.rs @@ -1,7 +1,7 @@ use bincode::{Decode, Encode}; use rustc_hash::FxHashSet; use turbo_tasks::{ - CellId, KeyValuePair, SharedReference, TaskExecutionReason, TaskId, TraitTypeId, + CellId, KeyValuePair, SharedReference, TaskExecutionReason, TaskId, TaskPriority, TraitTypeId, TypedSharedReference, ValueTypeId, backend::TurboTasksExecutionError, event::{Event, EventListener}, @@ -38,18 +38,39 @@ pub struct CellRef { pub cell: CellId, } +impl CellRef { + /// Returns true if this cell reference points to a transient task. + pub fn is_transient(&self) -> bool { + self.task.is_transient() + } +} + #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Encode, Decode)] pub struct CollectibleRef { pub collectible_type: TraitTypeId, pub cell: CellRef, } +impl CollectibleRef { + /// Returns true if this collectible reference points to a transient task. + pub fn is_transient(&self) -> bool { + self.cell.is_transient() + } +} + #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Encode, Decode)] pub struct CollectiblesRef { pub task: TaskId, pub collectible_type: TraitTypeId, } +impl CollectiblesRef { + /// Returns true if this collectibles reference points to a transient task. + pub fn is_transient(&self) -> bool { + self.task.is_transient() + } +} + #[derive(Debug, Clone, PartialEq, Eq, Encode, Decode)] pub enum OutputValue { Cell(CellRef), @@ -57,7 +78,11 @@ pub enum OutputValue { Error(TurboTasksExecutionError), } impl OutputValue { - fn is_transient(&self) -> bool { + /// Returns true if this output value references a transient task. + /// + /// Transient values should not be persisted to disk since they reference + /// tasks that will not exist after restart. + pub fn is_transient(&self) -> bool { match self { OutputValue::Cell(cell) => cell.task.is_transient(), OutputValue::Output(task) => task.is_transient(), @@ -142,7 +167,7 @@ impl Eq for ActivenessState {} #[derive(Debug, Clone, Copy, Encode, Decode, PartialEq, Eq)] pub enum Dirtyness { - Dirty, + Dirty(TaskPriority), SessionDependent, } @@ -212,6 +237,29 @@ pub struct AggregationNumber { pub effective: u32, } +/// Monotonic increasing distance range to leaf nodes when following "dependencies" edges. +/// It is a range and ranges might overlap. There is a strictly monotonic increasing `distance` +/// value. `max_distance_in_buffer` value might not be monotonic. The `max_distance_in_buffer` value +/// is used as buffer zone to avoid too many updates to dependent nodes when the leaf distance +/// increases slightly. When the leaf distance is increased it tries to keep the +/// `max_distance_in_buffer` value equal. When increasing there are three cases: +/// - `distance` >= `distance` of the dependency + 1: no change. +/// - `distance` <= `max_distance_in_buffer`: only `distance` is increased to the smallest possible +/// value. +/// - `distance` > `max_distance_in_buffer`: `distance` is increased to the `max_distance_in_buffer` +/// value of the dependency + 1 and `max_distance_in_buffer` is increased to `distance` + buffer +/// zone. +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Encode, Decode)] +pub struct LeafDistance { + /// This is the strictly monotonic increasing minimum leaf distance. + pub distance: u32, + /// A buffer zone value in which is usually safe to increase the leaf distance without causing + /// too many updates to dependent nodes. + /// Newly added dependents might be added within this buffer zone to avoid propagating updates, + /// therefore one can't rely on this being safe. It's only "often safe". + pub max_distance_in_buffer: u32, +} + #[derive(Debug, Clone, KeyValuePair, Encode, Decode)] pub enum CachedDataItem { // Output @@ -263,6 +311,7 @@ pub enum CachedDataItem { }, CellDependency { target: CellRef, + key: Option, value: (), }, CollectiblesDependency { @@ -277,6 +326,7 @@ pub enum CachedDataItem { }, CellDependent { cell: CellId, + key: Option, task: TaskId, value: (), }, @@ -286,6 +336,11 @@ pub enum CachedDataItem { value: (), }, + // Priority + LeafDistance { + value: LeafDistance, + }, + // Aggregation Graph AggregationNumber { value: AggregationNumber, @@ -363,6 +418,8 @@ pub enum CachedDataItem { #[bincode(skip, default = "unreachable_decode")] target: CellRef, #[bincode(skip, default = "unreachable_decode")] + key: Option, + #[bincode(skip, default = "unreachable_decode")] value: (), }, OutdatedCollectiblesDependency { @@ -414,6 +471,7 @@ impl CachedDataItem { CachedDataItem::AggregationNumber { .. } => true, CachedDataItem::Follower { task, .. } => !task.is_transient(), CachedDataItem::Upper { task, .. } => !task.is_transient(), + CachedDataItem::LeafDistance { .. } => true, CachedDataItem::AggregatedDirtyContainer { task, .. } => !task.is_transient(), CachedDataItem::AggregatedCurrentSessionCleanContainer { .. } => false, CachedDataItem::AggregatedCollectible { collectible, .. } => { @@ -479,7 +537,8 @@ impl CachedDataItem { | Self::CellDependency { .. } | Self::CollectiblesDependency { .. } | Self::OutputDependent { .. } - | Self::CellDependent { .. } => TaskDataCategory::Data, + | Self::CellDependent { .. } + | Self::LeafDistance { .. } => TaskDataCategory::Data, Self::Collectible { .. } | Self::Output { .. } @@ -544,6 +603,7 @@ impl CachedDataItemKey { CachedDataItemKey::AggregationNumber { .. } => true, CachedDataItemKey::Follower { task, .. } => !task.is_transient(), CachedDataItemKey::Upper { task, .. } => !task.is_transient(), + CachedDataItemKey::LeafDistance { .. } => true, CachedDataItemKey::AggregatedDirtyContainer { task, .. } => !task.is_transient(), CachedDataItemKey::AggregatedCurrentSessionCleanContainer { .. } => false, CachedDataItemKey::AggregatedCollectible { collectible, .. } => { @@ -577,7 +637,8 @@ impl CachedDataItemType { | Self::CellDependency { .. } | Self::CollectiblesDependency { .. } | Self::OutputDependent { .. } - | Self::CellDependent { .. } => TaskDataCategory::Data, + | Self::CellDependent { .. } + | Self::LeafDistance { .. } => TaskDataCategory::Data, Self::Collectible { .. } | Self::Output { .. } @@ -624,6 +685,7 @@ impl CachedDataItemType { | Self::AggregationNumber | Self::Follower | Self::Upper + | Self::LeafDistance | Self::AggregatedDirtyContainer | Self::AggregatedCollectible | Self::AggregatedDirtyContainerCount @@ -669,8 +731,8 @@ mod tests { #[test] fn test_sizes() { assert_eq!(std::mem::size_of::(), 40); - assert_eq!(std::mem::size_of::(), 20); + assert_eq!(std::mem::size_of::(), 32); assert_eq!(std::mem::size_of::(), 32); - assert_eq!(std::mem::size_of::(), 48); + assert_eq!(std::mem::size_of::(), 56); } } diff --git a/turbopack/crates/turbo-tasks-backend/tests/detached.rs b/turbopack/crates/turbo-tasks-backend/tests/detached.rs index cbd9888e92d2..b66b48ae625c 100644 --- a/turbopack/crates/turbo-tasks-backend/tests/detached.rs +++ b/turbopack/crates/turbo-tasks-backend/tests/detached.rs @@ -73,15 +73,14 @@ async fn spawns_detached( notify: TransientInstance, sender: TransientInstance>>>, ) -> Vc<()> { - tokio::spawn(turbo_tasks().detached_for_testing(Box::pin(async move { + turbo_tasks().spawn_detached_for_testing(Box::pin(async move { println!("spawns_detached: waiting for notify"); notify.0.notified().await; println!("spawns_detached: notified, sending value"); // creating cells after the normal lifetime of the task should be okay, as the parent task // is waiting on us before exiting! sender.0.send(Some(Vc::cell(42))).unwrap(); - Ok(()) - }))); + })); Vc::cell(()) } @@ -145,10 +144,10 @@ async fn spawns_detached_changing( changing_input_outer: Vc, ) -> Vc { let tt = turbo_tasks(); - tokio::spawn(tt.clone().detached_for_testing(Box::pin(async move { + tt.clone().spawn_detached_for_testing(Box::pin(async move { sleep(Duration::from_millis(100)).await; - // nested detached_for_testing calls should work - tokio::spawn(tt.clone().detached_for_testing(Box::pin(async move { + // nested spawn_detached_for_testing calls should work + tt.clone().spawn_detached_for_testing(Box::pin(async move { sleep(Duration::from_millis(100)).await; // creating cells after the normal lifetime of the task should be okay, as the parent // task is waiting on us before exiting! @@ -158,10 +157,8 @@ async fn spawns_detached_changing( *read_changing_input(changing_input_detached).await.unwrap(), ))) .unwrap(); - Ok(()) - }))); - Ok(()) - }))); + })); + })); Vc::cell(*read_changing_input(changing_input_outer).await.unwrap()) } diff --git a/turbopack/crates/turbo-tasks-backend/tests/invalidation.rs b/turbopack/crates/turbo-tasks-backend/tests/invalidation.rs new file mode 100644 index 000000000000..d3b052348e77 --- /dev/null +++ b/turbopack/crates/turbo-tasks-backend/tests/invalidation.rs @@ -0,0 +1,175 @@ +#![feature(arbitrary_self_types)] +#![feature(arbitrary_self_types_pointers)] +#![allow(clippy::needless_return)] // tokio macro-generated code doesn't respect this + +use anyhow::Result; +use rustc_hash::{FxHashMap, FxHashSet}; +use turbo_tasks::{OperationVc, ResolvedVc, State, Vc}; +use turbo_tasks_testing::{Registration, register, run}; + +static REGISTRATION: Registration = register!(); + +#[turbo_tasks::value(transparent)] +struct Step(State); + +#[turbo_tasks::function] +fn create_state() -> Vc { + Step(State::new(0)).cell() +} + +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +async fn invalidation_map() { + run(®ISTRATION, || async { + let state = create_state().to_resolved().await?; + state.await?.set(1); + + let map = create_map(state); + let a = get_value(map, "a".to_string()); + let b = get_value(map, "b".to_string()); + let c = get_value(map, "c".to_string()); + + let a_ref = a.read_strongly_consistent().await?; + let b_ref = b.read_strongly_consistent().await?; + let c_ref = c.read_strongly_consistent().await?; + + assert_eq!(a_ref.value, Some(1)); + assert_eq!(b_ref.value, Some(2)); + assert_eq!(c_ref.value, None); + + state.await?.set(2); + + let a_ref2 = a.read_strongly_consistent().await?; + let b_ref2 = b.read_strongly_consistent().await?; + let c_ref2 = c.read_strongly_consistent().await?; + + assert_eq!(a_ref2.value, Some(1)); + assert_eq!(b_ref2.value, Some(22)); + assert_eq!(c_ref2.value, None); + assert_eq!(a_ref.random, a_ref2.random); + assert_eq!(c_ref.random, c_ref2.random); + + state.await?.set(3); + + let a_ref3 = a.read_strongly_consistent().await?; + let b_ref3 = b.read_strongly_consistent().await?; + let c_ref3 = c.read_strongly_consistent().await?; + + assert_eq!(a_ref3.value, None); + assert_eq!(b_ref3.value, Some(22)); + assert_eq!(c_ref3.value, Some(3)); + assert_eq!(b_ref2.random, b_ref3.random); + + anyhow::Ok(()) + }) + .await + .unwrap() +} + +#[turbo_tasks::value(transparent, cell = "keyed")] +struct Map(FxHashMap); + +#[turbo_tasks::function(operation)] +async fn create_map(step: ResolvedVc) -> Result> { + let step = step.await?; + let step_value = step.get(); + + Ok(Vc::cell(match *step_value { + 1 => FxHashMap::from_iter([("a".to_string(), 1), ("b".to_string(), 2)]), + 2 => FxHashMap::from_iter([("a".to_string(), 1), ("b".to_string(), 22)]), + 3 => FxHashMap::from_iter([("c".to_string(), 3), ("b".to_string(), 22)]), + _ => FxHashMap::default(), + })) +} + +#[turbo_tasks::value] +struct GetValueResult { + value: Option, + random: u32, +} + +#[turbo_tasks::function(operation)] +async fn get_value(map: OperationVc, key: String) -> Result> { + let map = map.connect(); + let value = map.get(&key).await?.as_deref().copied(); + let random = rand::random::(); + Ok(GetValueResult { value, random }.cell()) +} + +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +async fn invalidation_set() { + run(®ISTRATION, || async { + let state = create_state().to_resolved().await?; + state.await?.set(1); + + let set = create_set(state); + let a = has_value(set, "a".to_string()); + let b = has_value(set, "b".to_string()); + let c = has_value(set, "c".to_string()); + + let a_ref = a.read_strongly_consistent().await?; + let b_ref = b.read_strongly_consistent().await?; + let c_ref = c.read_strongly_consistent().await?; + + assert!(a_ref.value); + assert!(b_ref.value); + assert!(!c_ref.value); + + state.await?.set(2); + + let a_ref2 = a.read_strongly_consistent().await?; + let b_ref2 = b.read_strongly_consistent().await?; + let c_ref2 = c.read_strongly_consistent().await?; + + assert!(a_ref2.value); + assert!(b_ref2.value); + assert!(!c_ref2.value); + assert_eq!(a_ref.random, a_ref2.random); + assert_eq!(b_ref.random, b_ref2.random); + assert_eq!(c_ref.random, c_ref2.random); + + state.await?.set(3); + + let a_ref3 = a.read_strongly_consistent().await?; + let b_ref3 = b.read_strongly_consistent().await?; + let c_ref3 = c.read_strongly_consistent().await?; + + assert!(!a_ref3.value); + assert!(b_ref3.value); + assert!(c_ref3.value); + assert_eq!(b_ref2.random, b_ref3.random); + + anyhow::Ok(()) + }) + .await + .unwrap() +} + +#[turbo_tasks::value(transparent, cell = "keyed")] +struct Set(FxHashSet); + +#[turbo_tasks::function(operation)] +async fn create_set(step: ResolvedVc) -> Result> { + let step = step.await?; + let step_value = step.get(); + + Ok(Vc::cell(match *step_value { + 1 => FxHashSet::from_iter(["a".to_string(), "b".to_string()]), + 2 => FxHashSet::from_iter(["e".to_string(), "a".to_string(), "b".to_string()]), + 3 => FxHashSet::from_iter(["c".to_string(), "b".to_string()]), + _ => FxHashSet::default(), + })) +} + +#[turbo_tasks::value] +struct HasValueResult { + value: bool, + random: u32, +} + +#[turbo_tasks::function(operation)] +async fn has_value(set: OperationVc, key: String) -> Result> { + let set = set.connect(); + let value = set.contains_key(&key).await?; + let random = rand::random::(); + Ok(HasValueResult { value, random }.cell()) +} diff --git a/turbopack/crates/turbo-tasks-bytes/src/stream.rs b/turbopack/crates/turbo-tasks-bytes/src/stream.rs index dab0c072949e..86fdca7386e4 100644 --- a/turbopack/crates/turbo-tasks-bytes/src/stream.rs +++ b/turbopack/crates/turbo-tasks-bytes/src/stream.rs @@ -12,7 +12,7 @@ use bincode::{ enc::Encoder, error::{DecodeError, EncodeError}, }; -use futures::{Stream as StreamTrait, StreamExt, TryStreamExt}; +use futures::{Stream as StreamTrait, StreamExt}; /// Streams allow for streaming values from source to sink. /// @@ -77,22 +77,6 @@ impl Stream { } } -impl Stream> { - /// Converts a TryStream into a single value when possible. - pub async fn try_into_single(&self) -> Result, E> { - let mut stream = self.read(); - let Some(first) = stream.try_next().await? else { - return Ok(SingleValue::None); - }; - - if stream.try_next().await?.is_some() { - return Ok(SingleValue::Multiple); - } - - Ok(SingleValue::Single(first)) - } -} - pub enum SingleValue { /// The Stream did not hold a value. None, diff --git a/turbopack/crates/turbo-tasks-fetch/Cargo.toml b/turbopack/crates/turbo-tasks-fetch/Cargo.toml index 80f947b16918..3184cb72b6ae 100644 --- a/turbopack/crates/turbo-tasks-fetch/Cargo.toml +++ b/turbopack/crates/turbo-tasks-fetch/Cargo.toml @@ -11,26 +11,9 @@ bench = false [lints] workspace = true -# Enable specific tls features per-target. -# -# Be careful when selecting tls backend, including change default tls backend. -# If you changed, must verify with ALL build targets with next-swc to ensure -# it works. next-swc have various platforms, some doesn't support native (using openssl-sys) -# and some aren't buildable with rustls. -[target.'cfg(all(target_os = "windows", target_arch = "aarch64"))'.dependencies] -reqwest = { workspace = true, features = ["native-tls"] } - -# If you modify this cfg, make sure you update `FetchClient::try_build_uncached_reqwest_client`, -# `has_rustls_cause`, and `errors_on_tls_connection` -[target.'cfg(not(any(all(target_os = "windows", target_arch = "aarch64"), target_arch="wasm32")))'.dependencies] -reqwest = { workspace = true, features = ["rustls-tls-webpki-roots", "rustls-tls-native-roots"] } -# we just need the `rustls::Error` type (no default features) -rustls = { version = "0.23.0", default-features = false } - [dependencies] anyhow = { workspace = true } quick_cache = { workspace = true } -reqwest = { workspace = true } serde = { workspace = true } tokio = { workspace = true } turbo-rcstr = { workspace = true } @@ -38,9 +21,37 @@ turbo-tasks = { workspace = true } turbo-tasks-fs = { workspace = true } turbopack-core = { workspace = true } +# Enable specific tls features per-target. +# +# Be careful when selecting tls backend. If you must verify ALL build targets of +# next-swc to ensure it works. next-swc have various platforms, some don't +# support native-tls (using openssl-sys) and some aren't buildable with rustls. +# +# The TLS backend used must match with the construction of `request::Client` in +# `src/client.rs`. + +# On macOS, use the default rustls configuration (uses aws-lc-rs). +[target.'cfg(target_os = "macos")'.dependencies] +reqwest = { workspace = true, features = ["rustls"] } + +# On Linux (all architectures) and Windows x86-64, use ring for rustls. +# - Linux: aws-lc-rs has cross-compilation issues in our CI: +# https://github.com/aws/aws-lc-rs/issues/673 +# - On Linux, linking with the native SSL library can be distro-dependent, so +# it's easier for us to statically link ring or aws-lc-rs. +# - Windows: aws-lc-sys requires NASM and CMake which we don't have installed in +# CI, and would complicate the development environment setup. We could +# possibly switch to always using `native-tls` on Windows in the future. +[target.'cfg(any(target_os = "linux", all(windows, not(target_arch = "aarch64"))))'.dependencies] +reqwest = { workspace = true, features = ["rustls-no-provider"] } +rustls = { version = "0.23", default-features = false, features = ["ring", "std", "tls12"] } + +# On Windows ARM64, use native-tls because rustls with ring has build issues. +[target.'cfg(all(windows, target_arch = "aarch64"))'.dependencies] +reqwest = { workspace = true, features = ["native-tls"] } + [dev-dependencies] mockito = { version = "1.7.0", default-features = false } tokio = { workspace = true, features = ["full"] } turbo-tasks-testing = { workspace = true } turbo-tasks-backend = { workspace = true } - diff --git a/turbopack/crates/turbo-tasks-fetch/src/client.rs b/turbopack/crates/turbo-tasks-fetch/src/client.rs index eb07a85aec89..e77d722cec70 100644 --- a/turbopack/crates/turbo-tasks-fetch/src/client.rs +++ b/turbopack/crates/turbo-tasks-fetch/src/client.rs @@ -19,31 +19,8 @@ static CLIENT_CACHE: LazyLock, reqwest::Client> /// This is needed because [`reqwest::ClientBuilder`] does not implement the required traits. This /// factory cannot be a closure because closures do not implement `Eq` or `Hash`. #[turbo_tasks::value(shared)] -#[derive(Hash)] -pub struct FetchClientConfig { - /// Whether to load embedded webpki root certs with rustls. Default is true. - /// - /// Ignored for: - /// - Windows on ARM, which uses `native-tls` instead of `rustls-tls`. - /// - Ignored for WASM targets, which use the runtime's TLS implementation. - pub tls_built_in_webpki_certs: bool, - /// Whether to load native root certs using the `rustls-native-certs` crate. This may make - /// reqwest client initialization slower, so it's not used by default. - /// - /// Ignored for: - /// - Windows on ARM, which uses `native-tls` instead of `rustls-tls`. - /// - Ignored for WASM targets, which use the runtime's TLS implementation. - pub tls_built_in_native_certs: bool, -} - -impl Default for FetchClientConfig { - fn default() -> Self { - Self { - tls_built_in_webpki_certs: true, - tls_built_in_native_certs: false, - } - } -} +#[derive(Hash, Default)] +pub struct FetchClientConfig {} impl FetchClientConfig { /// Returns a cached instance of `reqwest::Client` it exists, otherwise constructs a new one. @@ -68,20 +45,24 @@ impl FetchClientConfig { } fn try_build_uncached_reqwest_client(&self) -> reqwest::Result { - let client_builder = reqwest::Client::builder(); - - // make sure this cfg matches the one in `Cargo.toml`! - #[cfg(not(any( - all(target_os = "windows", target_arch = "aarch64"), - target_arch = "wasm32" - )))] - let client_builder = client_builder - .use_rustls_tls() - .tls_built_in_root_certs(false) - .tls_built_in_webpki_certs(self.tls_built_in_webpki_certs) - .tls_built_in_native_certs(self.tls_built_in_native_certs); - - client_builder.build() + #[allow(unused_mut)] + let mut builder = reqwest::Client::builder(); + #[cfg(any(target_os = "linux", all(windows, not(target_arch = "aarch64"))))] + { + use std::sync::Once; + static ONCE: Once = Once::new(); + ONCE.call_once(|| { + rustls::crypto::ring::default_provider() + .install_default() + .unwrap() + }); + builder = builder.tls_backend_rustls(); + } + #[cfg(all(windows, target_arch = "aarch64"))] + { + builder = builder.tls_backend_native(); + } + builder.build() } } @@ -95,7 +76,6 @@ impl FetchClientConfig { ) -> Result> { let url_ref = &*url; let this = self.await?; - let tls_built_in_native_certs = this.tls_built_in_native_certs; let response_result: reqwest::Result = async move { let reqwest_client = this.try_get_cached_reqwest_client()?; @@ -130,12 +110,9 @@ impl FetchClientConfig { Err(err) => { // the client failed to construct or the HTTP request failed mark_session_dependent(); - Ok(Vc::cell(Err(FetchError::from_reqwest_error( - &err, - &url, - tls_built_in_native_certs, - ) - .resolved_cell()))) + Ok(Vc::cell(Err( + FetchError::from_reqwest_error(&err, &url).resolved_cell() + ))) } } } diff --git a/turbopack/crates/turbo-tasks-fetch/src/error.rs b/turbopack/crates/turbo-tasks-fetch/src/error.rs index f1b75b80ca3b..3fb65725201c 100644 --- a/turbopack/crates/turbo-tasks-fetch/src/error.rs +++ b/turbopack/crates/turbo-tasks-fetch/src/error.rs @@ -7,10 +7,7 @@ use turbopack_core::issue::{Issue, IssueSeverity, IssueStage, OptionStyledString #[derive(Debug)] #[turbo_tasks::value(shared)] pub enum FetchErrorKind { - Connect { - has_system_certs: bool, - has_rustls_cause: bool, - }, + Connect, Timeout, Status(u16), Other, @@ -23,51 +20,10 @@ pub struct FetchError { pub detail: ResolvedVc, } -/// Attempt to determine if there's a `rustls::Error` in the error's source chain. -/// -/// This logic is fragile (e.g. depends that our copy of rustls and the version that reqwest uses -/// match exactly), but it's covered by unit tests. This seems slightly better than using `Display` -/// or `Debug` and inspecting the string. -fn has_rustls_cause(err: &reqwest::Error) -> bool { - // make sure this cfg matches the one in `Cargo.toml`! - #[cfg(not(any( - all(target_os = "windows", target_arch = "aarch64"), - target_arch = "wasm32" - )))] - { - let mut source = std::error::Error::source(err); - while let Some(err) = source { - if err.downcast_ref::().is_some() { - return true; - } - if let Some(err) = err.downcast_ref::() { - // `std::io::Error`'s `source` implementation returns the source of the wrapped - // error instead of the wrapped error itself, so we need to special-case this, - // otherwise we risk skipping over the rustls error. - source = err.get_ref().map(|e| e as &dyn std::error::Error); - } else { - source = std::error::Error::source(err); - } - } - return false; - }; - - // uses native-tls - #[cfg(all(target_os = "windows", target_arch = "aarch64"))] - return false; -} - impl FetchError { - pub(crate) fn from_reqwest_error( - error: &reqwest::Error, - url: &str, - webpki_certs_only: bool, - ) -> FetchError { + pub(crate) fn from_reqwest_error(error: &reqwest::Error, url: &str) -> FetchError { let kind = if error.is_connect() { - FetchErrorKind::Connect { - has_system_certs: webpki_certs_only, - has_rustls_cause: has_rustls_cause(error), - } + FetchErrorKind::Connect } else if error.is_timeout() { FetchErrorKind::Timeout } else if let Some(status) = error.status() { @@ -140,41 +96,12 @@ impl Issue for FetchIssue { Ok(Vc::cell(Some( match kind { - FetchErrorKind::Connect { - has_system_certs, - has_rustls_cause, - } => { - let base_message = StyledString::Line(vec![ - StyledString::Text(rcstr!( - "There was an issue establishing a connection while requesting " - )), - StyledString::Code(url.clone()), - ]); - if !*has_system_certs && *has_rustls_cause { - StyledString::Stack(vec![ - base_message, - StyledString::Line(vec![ - StyledString::Strong(rcstr!("Hint: ")), - StyledString::Text(rcstr!( - "It looks like this error was TLS-related. Try enabling \ - system TLS certificates with " - )), - StyledString::Code(rcstr!( - "NEXT_TURBOPACK_EXPERIMENTAL_USE_SYSTEM_TLS_CERTS=1" - )), - StyledString::Text(rcstr!(" as an environment variable, or set ")), - StyledString::Code(rcstr!( - "experimental.turbopackUseSystemTlsCerts" - )), - StyledString::Text(rcstr!(" in your ")), - StyledString::Code(rcstr!("next.config.js")), - StyledString::Text(rcstr!(" file.")), - ]), - ]) - } else { - base_message - } - } + FetchErrorKind::Connect => StyledString::Line(vec![ + StyledString::Text(rcstr!( + "There was an issue establishing a connection while requesting " + )), + StyledString::Code(url.clone()), + ]), FetchErrorKind::Status(status) => StyledString::Line(vec![ StyledString::Text(rcstr!("Received response with status ")), StyledString::Code(RcStr::from(status.to_string())), diff --git a/turbopack/crates/turbo-tasks-fetch/tests/fetch.rs b/turbopack/crates/turbo-tasks-fetch/tests/fetch.rs index 0f39f76f5633..2c47d92e9770 100644 --- a/turbopack/crates/turbo-tasks-fetch/tests/fetch.rs +++ b/turbopack/crates/turbo-tasks-fetch/tests/fetch.rs @@ -141,13 +141,7 @@ async fn errors_on_failed_connection() { let err_vc = &*response_vc.await?.unwrap_err(); let err = err_vc.await?; - assert!(matches!( - *err.kind.await?, - FetchErrorKind::Connect { - has_rustls_cause: false, - .. - } - )); + assert_eq!(*err.kind.await?, FetchErrorKind::Connect); assert_eq!(*err.url.await?, url); let issue = err_vc.to_issue(IssueSeverity::Error, get_issue_context().owned().await?); @@ -205,63 +199,10 @@ async fn errors_on_404() { .unwrap() } -#[cfg(not(any( - all(target_os = "windows", target_arch = "aarch64"), - target_arch = "wasm32" -)))] -#[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn errors_on_tls_connection() { - let _guard = GLOBAL_TEST_LOCK.lock().await; - run_once(®ISTRATION, || async { - let mut server = mockito::Server::new_async().await; - let _resource_mock = server - .mock("GET", "/") - .with_body("responsebody") - .create_async() - .await; - - // construct an HTTPS url, but mockito runs an HTTP server, so this should fail to connect - let url = RcStr::from(format!("https://{}", server.socket_address())); - - let client_vc = FetchClientConfig { - tls_built_in_webpki_certs: true, - tls_built_in_native_certs: false, - } - .cell(); - - let response_vc = client_vc.fetch(url.clone(), None); - let err_vc = &*response_vc.await?.unwrap_err(); - let err = err_vc.await?; - - assert_eq!( - *err.kind.await?, - FetchErrorKind::Connect { - has_rustls_cause: true, - has_system_certs: false, - } - ); - - let issue = err_vc.to_issue(IssueSeverity::Error, get_issue_context().owned().await?); - let description = issue - .description() - .await? - .unwrap() - .await? - .to_unstyled_string(); - - assert!(description.contains("NEXT_TURBOPACK_EXPERIMENTAL_USE_SYSTEM_TLS_CERTS=1")); - assert!(description.contains("experimental.turbopackUseSystemTlsCerts")); - - anyhow::Ok(()) - }) - .await - .unwrap() -} - #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn client_cache() { // a simple fetch that should always succeed - async fn simple_fetch(path: &str, client: FetchClientConfig) -> anyhow::Result<()> { + async fn simple_fetch(path: &str) -> anyhow::Result<()> { let mut server = mockito::Server::new_async().await; let _resource_mock = server .mock("GET", &*format!("/{path}")) @@ -270,7 +211,7 @@ async fn client_cache() { .await; let url = RcStr::from(format!("{}/{}", server.url(), path)); - let response = match &*client + let response = match &*FetchClientConfig::default() .cell() .fetch(url.clone(), /* user_agent */ None) .await? @@ -293,41 +234,13 @@ async fn client_cache() { __test_only_reqwest_client_cache_clear(); assert_eq!(__test_only_reqwest_client_cache_len(), 0); - simple_fetch( - "/foo", - FetchClientConfig { - tls_built_in_native_certs: false, - ..Default::default() - }, - ) - .await - .unwrap(); + simple_fetch("/foo").await.unwrap(); assert_eq!(__test_only_reqwest_client_cache_len(), 1); // the client is reused if the config is the same (by equality) - simple_fetch( - "/bar", - FetchClientConfig { - tls_built_in_native_certs: false, - ..Default::default() - }, - ) - .await - .unwrap(); + simple_fetch("/bar").await.unwrap(); assert_eq!(__test_only_reqwest_client_cache_len(), 1); - // the client is recreated if the config is different - simple_fetch( - "/bar", - FetchClientConfig { - tls_built_in_native_certs: true, - ..Default::default() - }, - ) - .await - .unwrap(); - assert_eq!(__test_only_reqwest_client_cache_len(), 2); - Ok(()) }) .await diff --git a/turbopack/crates/turbo-tasks-macros/src/derive/mod.rs b/turbopack/crates/turbo-tasks-macros/src/derive/mod.rs index 80c85ee2824e..6cfc6633ba51 100644 --- a/turbopack/crates/turbo-tasks-macros/src/derive/mod.rs +++ b/turbopack/crates/turbo-tasks-macros/src/derive/mod.rs @@ -3,6 +3,7 @@ mod key_value_pair_macro; mod non_local_value_macro; mod operation_value_macro; mod task_input_macro; +mod task_storage_macro; mod trace_raw_vcs_macro; mod value_debug_format_macro; mod value_debug_macro; @@ -13,6 +14,7 @@ pub use non_local_value_macro::derive_non_local_value; pub use operation_value_macro::derive_operation_value; use syn::{Attribute, Meta, Token, punctuated::Punctuated, spanned::Spanned}; pub use task_input_macro::derive_task_input; +pub use task_storage_macro::task_storage; pub use trace_raw_vcs_macro::derive_trace_raw_vcs; pub use value_debug_format_macro::derive_value_debug_format; pub use value_debug_macro::derive_value_debug; diff --git a/turbopack/crates/turbo-tasks-macros/src/derive/task_storage_macro.rs b/turbopack/crates/turbo-tasks-macros/src/derive/task_storage_macro.rs new file mode 100644 index 000000000000..afdeb50978a7 --- /dev/null +++ b/turbopack/crates/turbo-tasks-macros/src/derive/task_storage_macro.rs @@ -0,0 +1,2599 @@ +use proc_macro2::TokenStream; +use quote::quote; +use syn::{Fields, Ident, ItemStruct, Meta, Token, Type, punctuated::Punctuated, spanned::Spanned}; + +/// Derives the TaskStorage trait and generates optimized storage structures. +pub fn task_storage(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + task_storage_impl(input.into()).into() +} + +fn task_storage_impl(input: TokenStream) -> TokenStream { + let input: ItemStruct = match syn::parse2(input) { + Ok(input) => input, + Err(e) => return e.to_compile_error(), + }; + + // Parse field annotations + let storage_fields = match &input.fields { + Fields::Named(fields) => fields + .named + .iter() + .map(parse_field_storage_attributes) + .collect::>(), + _ => { + return syn::Error::new( + input.ident.span(), + "#[task_storage] can only be applied to structs with named fields", + ) + .to_compile_error(); + } + }; + + // Create grouped fields container + let grouped_fields = GroupedFields::new(storage_fields); + + // Generate the implementation (input struct is consumed - not emitted) + generate_task_storage_impl(&input.ident, &grouped_fields) +} + +/// Parsed field information with cached derived values. +/// +/// This struct holds all information about a field extracted from its attributes, +/// along with pre-computed values like the PascalCase variant name. +#[derive(Debug, Clone)] +struct FieldInfo { + /// The field's identifier (snake_case) + field_name: Ident, + /// The PascalCase variant name for use in LazyField enum + variant_name: Ident, + field_type: Type, + storage_type: StorageType, + category: Category, + /// If true, field is lazily allocated in Vec (the default). + /// If false (marked with `inline`), field is stored directly on TaskStorage. + lazy: bool, + /// If true, filter out values that reference transient tasks during encoding. + /// For direct fields: skip encoding if value.is_transient() returns true. + /// For collections: filter out entries where key/value is_transient() returns true. + /// For AutoMultimap: filter is always applied to inner set values automatically. + filter_transient: bool, + /// If true, use Default::default() semantics instead of Option for inline direct fields. + /// The field type should be T (not Option), and empty is represented by T::default(). + use_default: bool, +} + +impl FieldInfo { + /// Whether this field is a boolean flag stored in the TaskFlags bitfield. + fn is_flag(&self) -> bool { + self.storage_type == StorageType::Flag + } + + /// Whether this field is transient (not serialized, in-memory only). + fn is_transient(&self) -> bool { + self.category == Category::Transient + } + + /// Generate the full `self.check_access(...)` call for this field. + fn check_access_call(&self) -> TokenStream { + if self.is_transient() { + quote! { self.check_access(crate::backend::TaskDataCategory::All); } + } else if self.category == Category::Meta { + quote! { self.check_access(crate::backend::TaskDataCategory::Meta); } + } else { + quote! { self.check_access(crate::backend::TaskDataCategory::Data); } + } + } + + /// Generate the full `self.track_modification(...)` call for this field. + fn track_modification_call(&self) -> TokenStream { + if self.category == Category::Meta { + quote! { self.track_modification(crate::backend::storage::SpecificTaskDataCategory::Meta); } + } else { + quote! { self.track_modification(crate::backend::storage::SpecificTaskDataCategory::Data); } + } + } + + /// Whether this field is stored inline (not lazy). + fn is_inline(&self) -> bool { + !self.lazy + } + + /// Generate expression for immutable collection access. + /// + /// Delegates to TaskStorage accessor methods: + /// - For inline fields: `self.typed().{field_name}()` yields `&T` + /// - For lazy fields: `self.typed().{field_name}()` yields `Option<&T>` + /// + /// Note: This is for collection types (AutoSet, CounterMap, AutoMap), not Direct fields. + fn collection_ref_expr(&self) -> TokenStream { + let field_name = &self.field_name; + // Both inline and lazy have accessor methods generated on TaskStorage + quote! { self.typed().#field_name() } + } + + /// Generate expression for mutable collection access (allocates for lazy fields). + /// + /// Delegates to TaskStorage accessor methods: + /// - For inline fields: `self.typed_mut().{field_name}_mut()` yields `&mut T` + /// - For lazy fields: `self.typed_mut().{field_name}_mut()` yields `&mut T` (allocates if + /// needed) + /// + /// Note: This is for collection types (AutoSet, CounterMap, AutoMap), not Direct fields. + fn collection_mut_expr(&self) -> TokenStream { + let field_name_mut = self.mut_ident(); + // Both inline and lazy have accessor methods generated on TaskStorage + quote! { self.typed_mut().#field_name_mut() } + } + + /// Whether immutable access returns `Option<&T>` (lazy) vs `&T` (inline). + /// + /// This affects how read operations need to handle the result: + /// - For inline: `collection_ref_expr().get(key)` returns `Option<&V>` + /// - For lazy: `collection_ref_expr().and_then(|m| m.get(key))` returns `Option<&V>` + fn is_option_ref(&self) -> bool { + self.lazy + } + + // ========================================================================= + // Direct Field Access Helpers + // ========================================================================= + + /// Generate expression to get a Direct field value (returns `Option<&T>`). + /// + /// Delegates to TaskStorage accessor method `get_{field}()`. + fn direct_get_expr(&self) -> TokenStream { + let get_name = self.get_ident(); + quote! { self.typed().#get_name() } + } + + /// Generate expression to set a Direct field value. + /// + /// Delegates to TaskStorage accessor method `set_{field}(value)`. + /// For inline: returns `Option` (old value) + /// For lazy: returns `()` (no return value from current impl) + fn direct_set_expr(&self) -> TokenStream { + let set_name = self.set_ident(); + quote! { self.typed_mut().#set_name } + } + + /// Generate expression to take a Direct field value. + /// + /// Delegates to TaskStorage accessor method `take_{field}()`. + fn direct_take_expr(&self) -> TokenStream { + let take_name = self.take_ident(); + quote! { self.typed_mut().#take_name() } + } + + /// Generate expression to get a mutable reference to a Direct field value. + /// + /// Delegates to TaskStorage accessor method `get_{field}_mut()`. + /// Only available for lazy Direct fields (inline fields can use set/take). + fn direct_get_mut_expr(&self) -> TokenStream { + let get_mut_name = self.get_mut_ident(); + quote! { self.typed_mut().#get_mut_name() } + } + + // ========================================================================= + // TaskStorage Internal Access Helpers + // These generate expressions for use within TaskStorage impl blocks, + // operating on `self` directly rather than `self.typed()`. + // ========================================================================= + + /// Generate the find_lazy extractor closure for this lazy field. + /// + /// Returns `|f| match f { LazyField::Variant(v) => Some(v), _ => None }` + fn lazy_extractor_closure(&self) -> TokenStream { + let variant_name = &self.variant_name; + quote! { + |f| match f { + LazyField::#variant_name(v) => Some(v), + _ => None, + } + } + } + + /// Generate the lazy field constructor expression. + /// + /// Returns `LazyField::Variant(value)` or `LazyField::Variant(Default::default())` + fn lazy_constructor(&self, value_expr: TokenStream) -> TokenStream { + let variant_name = &self.variant_name; + quote! { LazyField::#variant_name(#value_expr) } + } + + /// Generate a matches closure for get_or_create_lazy. + /// + /// Returns `|f| matches!(f, LazyField::Variant(_))` + fn lazy_matches_closure(&self) -> TokenStream { + let variant_name = &self.variant_name; + quote! { + |f| matches!(f, LazyField::#variant_name(_)) + } + } + + /// Generate an unwrap closure that extracts the inner value from a LazyField variant. + /// + /// Returns `|f| match f { LazyField::Variant(v) => v, _ => unreachable!() }` + /// + /// Works for both borrowed and owned contexts (get_or_create_lazy, take_lazy, set_lazy). + fn lazy_unwrap_closure(&self) -> TokenStream { + let variant_name = &self.variant_name; + quote! { + |f| match f { + LazyField::#variant_name(v) => v, + _ => unreachable!(), + } + } + } + + // ========================================================================= + // Method Name Helpers + // Centralized identifier construction for generated method names. + // ========================================================================= + + /// Create an identifier with a prefix: `{prefix}_{field_name}` + fn prefixed_ident(&self, prefix: &str) -> syn::Ident { + syn::Ident::new( + &format!("{}_{}", prefix, self.field_name), + proc_macro2::Span::call_site(), + ) + } + + /// Create an identifier with a suffix: `{field_name}_{suffix}` + fn suffixed_ident(&self, suffix: &str) -> syn::Ident { + syn::Ident::new( + &format!("{}_{}", self.field_name, suffix), + proc_macro2::Span::call_site(), + ) + } + + /// Create an identifier with infix: `{prefix}_{field_name}_{suffix}` + fn infixed_ident(&self, prefix: &str, suffix: &str) -> syn::Ident { + syn::Ident::new( + &format!("{}_{}_{}", prefix, self.field_name, suffix), + proc_macro2::Span::call_site(), + ) + } + + /// Create identifier matching field name (for immutable collection accessors) + fn ref_ident(&self) -> syn::Ident { + self.field_name.clone() + } + + // Convenience methods for common accessor patterns + fn get_ident(&self) -> syn::Ident { + self.prefixed_ident("get") + } + fn set_ident(&self) -> syn::Ident { + self.prefixed_ident("set") + } + fn take_ident(&self) -> syn::Ident { + self.prefixed_ident("take") + } + fn has_ident(&self) -> syn::Ident { + self.prefixed_ident("has") + } + fn get_mut_ident(&self) -> syn::Ident { + self.infixed_ident("get", "mut") + } + fn mut_ident(&self) -> syn::Ident { + self.suffixed_ident("mut") + } + fn iter_ident(&self) -> syn::Ident { + self.prefixed_ident("iter") + } + fn len_ident(&self) -> syn::Ident { + self.suffixed_ident("len") + } + fn is_empty_ident(&self) -> syn::Ident { + syn::Ident::new( + &format!("is_{}_empty", self.field_name), + proc_macro2::Span::call_site(), + ) + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +enum StorageType { + Direct, + AutoSet, + AutoMap, + CounterMap, + Flag, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +enum Category { + Data, + Meta, + Transient, +} + +/// Try to extract a string literal from an expression, emitting an error if it's not a string. +fn expect_string_literal<'a>(expr: &'a syn::Expr, attr_name: &str) -> Option<&'a syn::LitStr> { + if let syn::Expr::Lit(syn::ExprLit { + lit: syn::Lit::Str(lit_str), + .. + }) = expr + { + Some(lit_str) + } else { + expr.span() + .unwrap() + .error(format!("`{attr_name}` value must be a string literal")) + .emit(); + None + } +} + +fn parse_field_storage_attributes(field: &syn::Field) -> FieldInfo { + let field_name = field.ident.as_ref().unwrap().clone(); + let field_type = field.ty.clone(); + + // Pre-compute the PascalCase variant name once + let variant_name = syn::Ident::new(&to_pascal_case(&field_name.to_string()), field_name.span()); + + // Default values + let mut storage_type: Option = None; + let mut category: Option = None; + let mut inline = false; // Default is lazy (not inline) + let mut filter_transient = false; + let mut use_default = false; + + // Find and parse the field attribute + if let Some(attr) = field.attrs.iter().find(|attr| { + attr.path() + .get_ident() + .map(|ident| *ident == "field") + .unwrap_or_default() + }) { + let nested = match attr.parse_args_with(Punctuated::::parse_terminated) { + Ok(punctuated) => punctuated, + Err(e) => { + attr.meta + .span() + .unwrap() + .error(format!("failed to parse field attribute: {e}")) + .emit(); + Punctuated::new() + } + }; + + for meta in nested { + match &meta { + Meta::NameValue(nv) => { + let Some(ident) = nv.path.get_ident() else { + nv.path + .span() + .unwrap() + .error("expected simple identifier") + .emit(); + continue; + }; + + match ident.to_string().as_str() { + "storage" => { + if let Some(lit_str) = expect_string_literal(&nv.value, "storage") { + storage_type = Some(match lit_str.value().as_str() { + "direct" => StorageType::Direct, + "auto_set" => StorageType::AutoSet, + "auto_map" => StorageType::AutoMap, + "counter_map" => StorageType::CounterMap, + "flag" => StorageType::Flag, + other => { + meta.span() + .unwrap() + .error(format!( + "unknown storage type: `{other}`. Expected \ + `direct`, `auto_set`, `auto_map`, \ + `auto_multimap`, `counter_map`, or `flag`" + )) + .emit(); + continue; + } + }); + } + } + "category" => { + if let Some(lit_str) = expect_string_literal(&nv.value, "category") { + category = Some(match lit_str.value().as_str() { + "data" => Category::Data, + "meta" => Category::Meta, + "transient" => Category::Transient, + other => { + meta.span() + .unwrap() + .error(format!( + "unknown category: `{other}`. Expected `data`, \ + `meta`, or `transient`" + )) + .emit(); + continue; + } + }); + } + } + other => { + meta.span() + .unwrap() + .error(format!( + "unknown attribute `{other}`, expected `storage` or `category`" + )) + .emit(); + } + } + } + Meta::Path(path) => { + let Some(ident) = path.get_ident() else { + path.span() + .unwrap() + .error("expected simple identifier") + .emit(); + continue; + }; + + match ident.to_string().as_str() { + "inline" => inline = true, + "filter_transient" => filter_transient = true, + "default" => use_default = true, + other => { + meta.span() + .unwrap() + .error(format!( + "unknown modifier `{other}`, expected `inline`, \ + `filter_transient`, or `default`" + )) + .emit(); + } + } + } + Meta::List(list) => { + meta.span() + .unwrap() + .error(format!( + "unexpected nested list `{}(...)`, expected key-value or modifier", + list.path + .get_ident() + .map(|i| i.to_string()) + .unwrap_or_default() + )) + .emit(); + } + } + } + } else { + field_name + .span() + .unwrap() + .error(format!( + "field `{field_name}` is missing required #[field(...)] attribute. Expected \ + #[field(storage = \"...\", category = \"...\")]" + )) + .emit(); + } + + // Require explicit storage type + let storage_type = match storage_type { + Some(st) => st, + None => { + field_name + .span() + .unwrap() + .error(format!( + "field `{}` requires explicit storage type. Add #[field(storage = \"...\")]. \ + Valid types: \"direct\", \"auto_set\", \"auto_map\", \"auto_multimap\", \ + \"counter_map\", \"flag\"", + field_name + )) + .emit(); + StorageType::Direct // Default to avoid cascading errors + } + }; + + // Require explicit category for all fields + let category = match category { + Some(cat) => cat, + None => { + field_name + .span() + .unwrap() + .error(format!( + "field `{}` requires explicit category. Add #[field(category = \"data\")], \ + #[field(category = \"meta\")], or #[field(category = \"transient\")]", + field_name + )) + .emit(); + Category::Data // Default to avoid cascading errors + } + }; + + FieldInfo { + field_name, + variant_name, + field_type, + storage_type, + category, + lazy: !inline, // Default is lazy; inline = true means lazy = false + filter_transient, + use_default, + } +} + +/// All parsed fields stored in a single vec, with filter methods for different access patterns. +#[derive(Debug)] +struct GroupedFields { + fields: Vec, +} + +impl GroupedFields { + fn new(fields: Vec) -> Self { + Self { fields } + } + + // ========================================================================= + // Flag field iterators + // ========================================================================= + + /// Returns an iterator over all flag fields (persisted first, then transient). + /// This ordering is important for bitfield generation. + fn all_flags(&self) -> impl Iterator { + self.persisted_flags().chain(self.transient_flags()) + } + + /// Returns an iterator over persisted (non-transient) flag fields. + fn persisted_flags(&self) -> impl Iterator { + self.fields + .iter() + .filter(|f| f.is_flag() && !f.is_transient()) + } + + /// Returns an iterator over transient flag fields. + fn transient_flags(&self) -> impl Iterator { + self.fields + .iter() + .filter(|f| f.is_flag() && f.is_transient()) + } + + /// Returns the count of persisted flag fields. + fn persisted_flags_count(&self) -> usize { + self.persisted_flags().count() + } + + /// Returns true if there are any flag fields. + fn has_flags(&self) -> bool { + self.fields.iter().any(|f| f.is_flag()) + } + + // ========================================================================= + // Non-flag field iterators + // ========================================================================= + + /// Returns an iterator over all non-flag fields. + fn all_fields(&self) -> impl Iterator { + self.fields.iter().filter(|f| !f.is_flag()) + } + + /// Returns an iterator over all lazy fields (both data and meta categories). + fn all_lazy(&self) -> impl Iterator { + self.fields.iter().filter(|f| !f.is_flag() && f.lazy) + } + + /// Returns true if there are any lazy fields. + fn has_lazy(&self) -> bool { + self.fields.iter().any(|f| !f.is_flag() && f.lazy) + } + + /// Returns an iterator over all inline (non-lazy, non-flag) fields. + fn all_inline(&self) -> impl Iterator { + self.fields.iter().filter(|f| !f.is_flag() && !f.lazy) + } + + // ========================================================================= + // Category-specific iterators for serialization + // ========================================================================= + + /// Returns an iterator over persistent (non-transient) inline fields for a category. + fn persistent_inline(&self, category: Category) -> impl Iterator { + self.fields + .iter() + .filter(move |f| !f.is_flag() && !f.lazy && !f.is_transient() && f.category == category) + } + + /// Returns an iterator over persistent (non-transient) lazy fields for a category. + fn persistent_lazy(&self, category: Category) -> impl Iterator { + self.fields + .iter() + .filter(move |f| !f.is_flag() && f.lazy && !f.is_transient() && f.category == category) + } +} + +// ============================================================================= +// Code Generation Helpers +// ============================================================================= + +/// Generate inline field clone assignments: `snapshot.field = self.field.clone();` +fn gen_clone_inline_fields<'a>(fields: impl Iterator) -> Vec { + fields + .map(|field| { + let field_name = &field.field_name; + quote! { + snapshot.#field_name = self.#field_name.clone(); + } + }) + .collect() +} + +/// Generate inline field restore assignments: `self.field = source.field;` +fn gen_restore_inline_fields<'a>(fields: impl Iterator) -> Vec { + fields + .map(|field| { + let field_name = &field.field_name; + quote! { + self.#field_name = source.#field_name; + } + }) + .collect() +} + +/// Generate lazy field match arms with a custom body that also receives the index. +/// `LazyField::Variant(data) => { }` +/// +/// The `body_fn` receives the index and field, returning the body TokenStream. +/// The body can use `data` to reference the matched value. +fn gen_lazy_match_arms<'a>( + fields: impl Iterator, + body_fn: impl Fn(usize, &FieldInfo) -> TokenStream, +) -> Vec { + fields + .enumerate() + .map(|(idx, field)| { + let variant_name = &field.variant_name; + let body = body_fn(idx, field); + quote! { + LazyField::#variant_name(data) => { + #body + } + } + }) + .collect() +} + +fn generate_task_storage_impl(_ident: &Ident, grouped_fields: &GroupedFields) -> TokenStream { + // Generate TaskFlags bitfield if there are flag fields + let task_flags_bitfield = generate_task_flags_bitfield(grouped_fields); + + // Generate LazyField enum for lazy fields + let lazy_field_enum = generate_lazy_field_enum(grouped_fields); + + // Generate the unified TaskStorage struct + let typed_storage_struct = generate_typed_storage_struct(grouped_fields); + + // Generate accessor methods + let accessor_methods = generate_accessor_methods(grouped_fields); + + // Generate TaskStorageAccessors trait for all fields + let accessors_trait = generate_task_storage_accessors_trait(grouped_fields); + + // Generate encode/decode methods for serialization + let encode_decode_methods = generate_encode_decode_methods(grouped_fields); + + // Generate snapshot clone and restore methods + let snapshot_restore_methods = generate_snapshot_restore_methods(grouped_fields); + + quote! { + // Import ShrinkToFit trait for the derive macro generated code + use turbo_tasks::ShrinkToFit as _; + + // Generated TaskFlags bitfield + #task_flags_bitfield + + // Generated LazyField enum + #lazy_field_enum + + // Generated TaskStorage struct (unified) + #typed_storage_struct + + // Generated accessor methods + #accessor_methods + + // Generated encode/decode methods + #encode_decode_methods + + // Generated snapshot clone and restore methods + #snapshot_restore_methods + + // Generated TaskStorageAccessors trait + #accessors_trait + } +} + +/// Generate the TaskFlags bitfield using the bitfield crate. +/// +/// Persisted flags come first (bits 0-N), then transient flags (bits N+1-M). +/// This allows serializing only the persisted portion. +fn generate_task_flags_bitfield(grouped_fields: &GroupedFields) -> TokenStream { + let all_flags: Vec<_> = grouped_fields.all_flags().collect(); + + // If no flags, don't generate the bitfield + if all_flags.is_empty() { + return quote! {}; + } + + let persisted_count = grouped_fields.persisted_flags_count(); + + // Generate bitfield accessors + // Format: pub field_name, set_field_name: bit_index; + let bitfield_accessors: Vec<_> = all_flags + .iter() + .enumerate() + .map(|(i, field)| { + let field_name = &field.field_name; + let set_name = field.set_ident(); + // bitfield crate uses usize for bit indices, but literal integers work fine + let bit_idx = i; + quote! { + pub #field_name, #set_name: #bit_idx + } + }) + .collect(); + + // Generate the persisted bits mask + let persisted_mask = (1u16 << persisted_count) - 1; + + quote! { + bitfield::bitfield! { + /// Combined bitfield for task flags. + /// Persisted flags are in the lower bits (0 to N-1). + /// Transient flags are in the higher bits (N and above). + #[derive(Clone, Default, PartialEq, Eq)] + pub struct TaskFlags(u16); + impl Debug; + + #(#bitfield_accessors;)* + } + + #[automatically_derived] + impl TaskFlags { + /// Mask for persisted flags (lower bits only) + pub const PERSISTED_MASK: u16 = #persisted_mask; + + /// Get the raw bits value + pub fn bits(&self) -> u16 { + self.0 + } + + /// Get only the persisted bits (for serialization) + pub fn persisted_bits(&self) -> u16 { + self.0 & Self::PERSISTED_MASK + } + + /// Set bits from a raw value, preserving transient flags + pub fn set_persisted_bits(&mut self, bits: u16) { + self.0 = (self.0 & !Self::PERSISTED_MASK) | (bits & Self::PERSISTED_MASK); + } + + /// Create from raw bits (for deserialization) + pub fn from_bits(bits: u16) -> Self { + Self(bits) + } + } + } +} + +/// Generate the LazyField enum containing all lazy fields +fn generate_lazy_field_enum(grouped_fields: &GroupedFields) -> TokenStream { + let all_lazy_fields: Vec<_> = grouped_fields.all_lazy().collect(); + + // If no lazy_vec fields, don't generate the enum + if all_lazy_fields.is_empty() { + return quote! {}; + } + + // Generate enum variants + let variants: Vec<_> = all_lazy_fields + .iter() + .map(|field| { + let variant_name = &field.variant_name; + let field_type = &field.field_type; + quote! { + #variant_name(#field_type) + } + }) + .collect(); + + // Generate is_empty method arms + let is_empty_arms: Vec<_> = all_lazy_fields + .iter() + .map(|field| { + let variant_name = &field.variant_name; + // For collection types, check if empty; for direct types, presence means non-empty + match field.storage_type { + StorageType::Direct => { + // For direct types, presence of the variant means it's non-empty + // (the Vec provides optionality, not Option) + quote! { + LazyField::#variant_name(_) => false + } + } + _ => { + // For collection types, delegate to is_empty() + quote! { + LazyField::#variant_name(v) => v.is_empty() + } + } + } + }) + .collect(); + + // Generate is_persistent (transient check) method arms + let is_persistent_arms: Vec<_> = all_lazy_fields + .iter() + .map(|field| { + let variant_name = &field.variant_name; + let is_persistent = !field.is_transient(); + quote! { + LazyField::#variant_name(_) => #is_persistent + } + }) + .collect(); + + // Generate is_meta/is_data method arms + let is_meta_arms: Vec<_> = all_lazy_fields + .iter() + .map(|field| { + let variant_name = &field.variant_name; + let is_meta = field.category == Category::Meta; + quote! { + LazyField::#variant_name(_) => #is_meta + } + }) + .collect(); + + quote! { + /// All lazily-allocated fields stored in a single Vec. + /// Fields are stored directly (unboxed) to avoid allocation overhead. + #[automatically_derived] + #[derive(Debug, Clone, PartialEq, turbo_tasks::ShrinkToFit)] + #[shrink_to_fit(crate = "turbo_tasks::macro_helpers::shrink_to_fit")] + pub enum LazyField { + #(#variants),* + } + + #[automatically_derived] + impl LazyField { + /// Returns true if this field is empty (can be removed from the Vec) + pub fn is_empty(&self) -> bool { + match self { + #(#is_empty_arms),* + } + } + + /// Returns true if this field should be persisted (not transient) + pub fn is_persistent(&self) -> bool { + match self { + #(#is_persistent_arms),* + } + } + + /// Returns true if this field belongs to the meta category + pub fn is_meta(&self) -> bool { + match self { + #(#is_meta_arms),* + } + } + + /// Returns true if this field belongs to the data category + pub fn is_data(&self) -> bool { + !self.is_meta() + } + } + } +} + +/// Generate the unified TaskStorage struct with all fields directly on it. +fn generate_typed_storage_struct(grouped_fields: &GroupedFields) -> TokenStream { + let has_lazy = grouped_fields.has_lazy(); + let has_flags = grouped_fields.has_flags(); + + // Collect all field definitions from both categories + let mut field_defs = Vec::new(); + + // Add inline fields directly on TaskStorage (private - use accessor methods) + // Note: No bincode attributes since we don't derive Encode/Decode (manual serialization) + for field in grouped_fields.all_inline() { + let field_name = &field.field_name; + let field_type = &field.field_type; + field_defs.push(quote! { + #field_name: #field_type + }); + } + + // Add flags bitfield if needed (pub(crate) - used by TaskFlags methods) + let flags_field = if has_flags { + quote! { + /// Combined bitfield for boolean flags (persisted + transient) + pub(crate) flags: TaskFlags, + } + } else { + quote! {} + }; + + // Add lazy vec field if needed (pub(crate) - used by helper methods) + // Note: Serialization is handled manually via encode_data/encode_meta methods + let lazy_field = if has_lazy { + quote! { + /// Lazily-allocated fields stored in a single Vec for memory efficiency + pub(crate) lazy: Vec, + } + } else { + quote! {} + }; + + // Note: Helper methods like find_lazy, find_lazy_mut, get_or_create_lazy, and + // remove_if_empty are defined in storage_schema.rs rather than generated here. + // This provides better IDE support (autocomplete, go-to-definition, etc.). + + // Note: We don't derive bincode::Encode/Decode here since serialization + // will be handled manually via encode_data/encode_meta/decode_data/decode_meta methods + quote! { + /// Unified typed storage containing all task fields. + /// This is designed to be embedded in the actual InnerStorage for incremental migration. + #[automatically_derived] + #[derive(Debug, Clone, Default, PartialEq, turbo_tasks::ShrinkToFit)] + #[shrink_to_fit(crate = "turbo_tasks::macro_helpers::shrink_to_fit")] + pub struct TaskStorage { + #(#field_defs,)* + #flags_field + #lazy_field + } + + #[automatically_derived] + impl TaskStorage { + pub fn new() -> Self { + Self::default() + } + } + } +} + +fn generate_accessor_methods(grouped_fields: &GroupedFields) -> TokenStream { + let mut methods = TokenStream::new(); + + // Generate accessor methods for all fields on TaskStorage + // This encapsulates the storage strategy - callers use methods, not field access + for field in grouped_fields.all_fields() { + methods.extend(generate_field_accessors(field)); + } + + quote! { + #[automatically_derived] + impl TaskStorage { + #methods + } + } +} + +/// Generate accessor methods on TaskStorage for a field. +/// +/// Works for both inline and lazy fields. Uses FieldInfo helpers to generate +/// the appropriate access patterns. +/// +/// For Direct fields, generates: `get_{field}()`, `set_{field}()`, `take_{field}()` +/// For Collection fields, generates: `{field}()`, `{field}_mut()` +fn generate_field_accessors(field: &FieldInfo) -> TokenStream { + let field_name = &field.field_name; + let field_type = &field.field_type; + + match field.storage_type { + StorageType::Direct => generate_direct_field_accessors(field), + StorageType::AutoSet | StorageType::AutoMap | StorageType::CounterMap => { + generate_collection_field_accessors(field, field_name, field_type) + } + StorageType::Flag => { + // Flag fields have accessors generated on TaskFlags, not TaskStorage + unreachable!("Flag fields should not reach generate_field_accessors") + } + } +} + +/// Generate Direct field accessors on TaskStorage (get/set/take, and get_mut for lazy). +fn generate_direct_field_accessors(field: &FieldInfo) -> TokenStream { + let field_name = &field.field_name; + let field_type = &field.field_type; + + let get_name = field.get_ident(); + let set_name = field.set_ident(); + let take_name = field.take_ident(); + let get_mut_name = field.get_mut_ident(); + + if field.is_inline() && field.use_default { + // Inline with default: field is T stored directly, uses Default::default() for "empty" + quote! { + fn #get_name(&self) -> Option<&#field_type> { + if self.#field_name != #field_type::default() { + Some(&self.#field_name) + } else { + None + } + } + + fn #set_name(&mut self, value: #field_type) -> Option<#field_type> { + let old = std::mem::replace(&mut self.#field_name, value); + if old != #field_type::default() { + Some(old) + } else { + None + } + } + + fn #take_name(&mut self) -> Option<#field_type> { + let old = std::mem::take(&mut self.#field_name); + if old != #field_type::default() { + Some(old) + } else { + None + } + } + } + } else if field.is_inline() { + // Inline: field is Option stored directly on TaskStorage + let inner_type = extract_option_inner_type(field_type); + + quote! { + fn #get_name(&self) -> Option<&#inner_type> { + self.#field_name.as_ref() + } + + fn #set_name(&mut self, value: #inner_type) -> Option<#inner_type> { + self.#field_name.replace(value) + } + + fn #take_name(&mut self) -> Option<#inner_type> { + self.#field_name.take() + } + } + } else { + // Lazy: field is stored in Vec + let extractor = field.lazy_extractor_closure(); + let matches_closure = field.lazy_matches_closure(); + let unwrap_owned = field.lazy_unwrap_closure(); + let constructor = field.lazy_constructor(quote! { value }); + + quote! { + fn #get_name(&self) -> Option<&#field_type> { + self.find_lazy(#extractor) + } + + /// Set the field value, returning the old value if present. + fn #set_name(&mut self, value: #field_type) -> Option<#field_type> { + self.set_lazy(#matches_closure, #unwrap_owned, #constructor) + } + + fn #take_name(&mut self) -> Option<#field_type> { + self.take_lazy(#matches_closure, #unwrap_owned) + } + + /// Get a mutable reference to the field value (if present). + /// + /// Unlike `get_or_create_lazy` for collections, this does NOT allocate + /// if the field is absent - it returns None instead. + fn #get_mut_name(&mut self) -> Option<&mut #field_type> { + self.find_lazy_mut(#extractor) + } + } + } +} + +/// Generate collection field accessors on TaskStorage (ref/mut). +fn generate_collection_field_accessors( + field: &FieldInfo, + field_name: &syn::Ident, + field_type: &syn::Type, +) -> TokenStream { + let ref_name = field.ref_ident(); + let mut_name = field.mut_ident(); + + if field.is_inline() { + // Inline: direct field access + quote! { + fn #ref_name(&self) -> &#field_type { + &self.#field_name + } + + fn #mut_name(&mut self) -> &mut #field_type { + &mut self.#field_name + } + } + } else { + // Lazy: use find_lazy / get_or_create_lazy + let extractor = field.lazy_extractor_closure(); + let matches_closure = field.lazy_matches_closure(); + let unwrap_closure = field.lazy_unwrap_closure(); + let constructor = field.lazy_constructor(quote! { Default::default() }); + + quote! { + fn #ref_name(&self) -> Option<&#field_type> { + self.find_lazy(#extractor) + } + + fn #mut_name(&mut self) -> &mut #field_type { + self.get_or_create_lazy( + #matches_closure, + #unwrap_closure, + || #constructor, + ) + } + } + } +} + +/// Generates the TaskStorageAccessors trait with accessor methods for all fields. +/// +/// This trait defines: +/// 1. Required methods: `typed()` and `typed_mut(category)` that implementors must provide +/// 2. Provided methods: accessor methods for all fields +/// +/// The trait is designed to be used with TaskGuard, which implements the required methods +/// and gets all the accessor methods for free. +fn generate_task_storage_accessors_trait(grouped_fields: &GroupedFields) -> TokenStream { + let mut trait_methods = TokenStream::new(); + + // Generate accessor methods for all non-flag fields (inline and lazy) + for field in grouped_fields.all_fields() { + trait_methods.extend(generate_trait_accessor_methods(field)); + } + + // Generate accessor methods for flag fields + for field in grouped_fields.all_flags() { + trait_methods.extend(generate_flag_trait_accessor_methods(field)); + } + + quote! { + /// Trait for typed storage accessors. + /// + /// This trait is auto-generated by the TaskStorage macro. + /// Implementors only need to provide `typed()`, `typed_mut()`, `track_modification()`, + /// and `check_access()` methods, and all accessor methods are provided automatically. + /// + /// This is designed to work with TaskGuard. + #[automatically_derived] + pub trait TaskStorageAccessors { + /// Access the typed storage (read-only) + fn typed(&self) -> &TaskStorage; + + /// Access the typed storage (mutable). + /// + /// Note: This does NOT track modifications. Call `track_modification()` separately + /// when the data actually changes. This split allows generated accessors to + /// only track modifications when actual changes occur. + fn typed_mut(&mut self) -> &mut TaskStorage; + + /// Track that a modification occurred for the given category. + /// + /// Should be called after confirming that data actually changed. + /// This is separate from `typed_mut()` to allow optimizations where + /// we only track modifications when something actually changes. + fn track_modification(&mut self, category: crate::backend::storage::SpecificTaskDataCategory); + + /// Verify that the task was accessed with the correct category before reading/writing. + /// + /// This is a debug assertion that catches bugs where code tries to access data + /// without having restored it from storage first. + /// + /// The category parameter uses `TaskDataCategory`: + /// - `Data` or `Meta`: Checks that the task was accessed with that category + /// - `All`: Used for transient data - no check is performed + /// + /// Implementors should check that the provided category matches how the task was accessed. + fn check_access(&self, category: crate::backend::TaskDataCategory); + + /// Shrink all collection fields to fit their current contents. + /// + /// This releases excess memory from hash maps and hash sets that may have + /// grown larger than needed during task execution. + /// + /// Note: This does NOT track modifications since shrink_to_fit doesn't + /// semantically change the data - it only reduces memory usage. + fn shrink_to_fit(&mut self) { + self.typed_mut().shrink_to_fit(); + } + + #trait_methods + } + } +} + +/// Generates trait accessor methods for a field (works for both inline and lazy storage). +/// +/// Uses `FieldInfo` helpers to generate the correct access patterns: +/// - For inline: direct field access via `self.typed().field` / `self.typed_mut().field` +/// - For lazy: delegates to TaskStorage accessors +fn generate_trait_accessor_methods(field: &FieldInfo) -> TokenStream { + let field_type = &field.field_type; + let check_access = field.check_access_call(); + let ref_expr = field.collection_ref_expr(); + let mut_expr = field.collection_mut_expr(); + let is_option = field.is_option_ref(); + + match field.storage_type { + StorageType::Direct => { + // Direct storage delegates to TaskStorage accessor methods + generate_direct_accessors(field) + } + StorageType::AutoSet => { + // For AutoSet types, generate read-only accessor plus add/remove/has/iter/len/is_empty + let ref_name = field.ref_ident(); + + let (return_type, doc_comment) = if is_option { + ( + quote! { Option<&#field_type> }, + "/// Get a reference to the collection (may be None if not allocated, \ + read-only)", + ) + } else { + ( + quote! { &#field_type }, + "/// Get a reference to the collection (read-only)", + ) + }; + + let base_accessor = quote! { + #[doc = #doc_comment] + fn #ref_name(&self) -> #return_type { + #check_access + #ref_expr + } + }; + + let set_ops = generate_autoset_ops(field); + + quote! { + #base_accessor + #set_ops + } + } + StorageType::CounterMap => { + // For CounterMap types, generate read-only accessor plus mutation methods + let ref_name = field.ref_ident(); + + let (return_type, doc_comment) = if is_option { + ( + quote! { Option<&#field_type> }, + "/// Get a reference to the collection (may be None if not allocated, \ + read-only)", + ) + } else { + ( + quote! { &#field_type }, + "/// Get a reference to the collection (read-only)", + ) + }; + + let base_accessor = quote! { + #[doc = #doc_comment] + fn #ref_name(&self) -> #return_type { + #check_access + #ref_expr + } + }; + + let countermap_ops = generate_countermap_ops(field); + + quote! { + #base_accessor + #countermap_ops + } + } + StorageType::AutoMap => { + // For AutoMap types, generate immutable and mutable accessors plus operation methods + let ref_name = field.ref_ident(); + let mut_name = field.mut_ident(); + + let (return_type, ref_doc) = if is_option { + ( + quote! { Option<&#field_type> }, + "/// Get a reference to the collection (may be None if not allocated)", + ) + } else { + ( + quote! { &#field_type }, + "/// Get a reference to the collection", + ) + }; + + let base_accessor = quote! { + #[doc = #ref_doc] + fn #ref_name(&self) -> #return_type { + #check_access + #ref_expr + } + + /// Get a mutable reference to the collection (allocates if needed for lazy fields). + /// + /// Note: This does NOT track modifications. Call `track_modification` after + /// making changes to ensure persistence. + fn #mut_name(&mut self) -> &mut #field_type { + #check_access + #mut_expr + } + }; + + let automap_ops = generate_automap_ops(field); + + quote! { + #base_accessor + #automap_ops + } + } + StorageType::Flag => { + // Flag fields have accessors generated on TaskFlags, not TaskStorageAccessors + unreachable!("Flag fields should not reach generate_trait_accessor_methods") + } + } +} + +/// Generate Direct field accessors for TaskStorageAccessors trait. +/// +/// Uses `FieldInfo` helpers to delegate to TaskStorage accessor methods, +/// which handle the inline/lazy difference internally. +/// +/// Generates methods: +/// - `get_{field}_ref() -> Option<&T>` - Get reference to value +/// - `has_{field}() -> bool` - Check if value exists +/// - `set_{field}(value) -> Option` - Set value, returning old value +/// - `take_{field}() -> Option` - Take value, clearing the field +/// - `get_{field}_mut() -> Option<&mut T>` - Get mutable reference (lazy fields only) +fn generate_direct_accessors(field: &FieldInfo) -> TokenStream { + let field_type = &field.field_type; + let check_access = field.check_access_call(); + let track_modification = field.track_modification_call(); + + // Use FieldInfo helpers for TaskStorage delegation + let get_expr = field.direct_get_expr(); + let set_expr = field.direct_set_expr(); + let take_expr = field.direct_take_expr(); + + // Method names + let get_name = field.get_ident(); + let has_name = field.has_ident(); + let set_name = field.set_ident(); + let take_name = field.take_ident(); + + // For inline fields, the type is Option and we extract T. + // For lazy fields, the type is T directly (Vec presence provides optionality). + let value_type = if field.is_inline() { + extract_option_inner_type(field_type) + } else { + quote! { #field_type } + }; + + // Generate get_mut accessor only for lazy fields + // (for inline fields, use set/take instead) + let get_mut_accessor = if !field.is_inline() { + let get_mut_name = field.get_mut_ident(); + let get_mut_expr = field.direct_get_mut_expr(); + quote! { + /// Get a mutable reference to the field value (if present). + /// + /// Note: This does NOT track modifications. Call `track_modification` after + /// making changes to ensure persistence. + fn #get_mut_name(&mut self) -> Option<&mut #value_type> { + #check_access + #get_mut_expr + } + } + } else { + quote! {} + }; + + quote! { + /// Get a reference to the field value (if present) + fn #get_name(&self) -> Option<&#value_type> { + #check_access + #get_expr + } + + /// Check if this field has a value + fn #has_name(&self) -> bool { + #check_access + #get_expr.is_some() + } + + /// Set the field value, returning the old value if present + fn #set_name(&mut self, value: #value_type) -> Option<#value_type> { + #check_access + #track_modification + #set_expr(value) + } + + /// Take the field value, clearing it + /// + /// Only tracks modification if there was a value to take. + fn #take_name(&mut self) -> Option<#value_type> { + #check_access + let value = #take_expr; + if value.is_some() { + #track_modification + } + value + } + + #get_mut_accessor + } +} + +/// Generate add/remove/has/iter/len/is_empty operations for an AutoSet field. +/// +/// Uses `FieldInfo` helpers to generate the correct access patterns: +/// - For inline: direct field access via `self.typed().field` / `self.typed_mut().field` +/// - For lazy: delegates to TaskStorage accessors +/// +/// Generates methods with `_item` suffix to distinguish single-item operations +/// from potential bulk operations: `add_X_item`, `remove_X_item`, `has_X_item` +fn generate_autoset_ops(field: &FieldInfo) -> TokenStream { + let field_type = &field.field_type; + + let Some(element_type) = extract_set_element_type(field_type) else { + return quote! {}; + }; + + let check_access = field.check_access_call(); + let track_modification = field.track_modification_call(); + let mut_expr = field.collection_mut_expr(); + let ref_expr = field.collection_ref_expr(); + let is_option = field.is_option_ref(); + + let add_name = field.prefixed_ident("add"); + let add_items_name = field.suffixed_ident("extend"); + let remove_name = field.prefixed_ident("remove"); + let has_name = field.prefixed_ident("has"); + let iter_name = field.iter_ident(); + let len_name = field.len_ident(); + let is_empty_name = field.is_empty_ident(); + + // Generate bodies based on whether ref access returns Option or not + let has_body = if is_option { + quote! { #ref_expr.is_some_and(|set| set.contains(item)) } + } else { + quote! { #ref_expr.contains(item) } + }; + + let iter_body = if is_option { + quote! { #ref_expr.into_iter().flat_map(|set| set.iter().copied()) } + } else { + quote! { #ref_expr.iter().copied() } + }; + + let len_body = if is_option { + quote! { #ref_expr.map_or(0, |set| set.len()) } + } else { + quote! { #ref_expr.len() } + }; + + let is_empty_body = if is_option { + quote! { #ref_expr.is_none_or(|set| set.is_empty()) } + } else { + quote! { #ref_expr.is_empty() } + }; + + // Remove uses find_lazy_mut for lazy to avoid allocation. + let remove_body = if is_option { + let extractor = field.lazy_extractor_closure(); + + quote! { + let Some(set) = self.typed_mut().find_lazy_mut(#extractor) else { + return false; + }; + let removed = set.remove(item); + if removed { + #track_modification + } + return removed; + + } + } else { + quote! { + let removed = #mut_expr.remove(item); + if removed { + #track_modification + } + removed + } + }; + + quote! { + /// Check if the set contains an item + fn #has_name(&self, item: &#element_type) -> bool { + #check_access + #has_body + } + + /// Add an item to the set. + /// Returns true if the item was newly added, false if it already existed. + #[must_use] + fn #add_name(&mut self, item: #element_type) -> bool { + #check_access + let added = #mut_expr.insert(item); + if added { + #track_modification + } + added + } + + /// Add multiple items to the set from an iterator. + /// Only tracks modification if at least one item is actually added. + fn #add_items_name(&mut self, items: impl Iterator) { + #check_access + let set = #mut_expr; + let mut any_added = false; + for item in items { + if set.insert(item) { + any_added = true; + } + } + if any_added { + #track_modification + } + } + + /// Remove an item from the set. + /// Returns true if the item was present and removed, false if it wasn't present. + fn #remove_name(&mut self, item: &#element_type) -> bool { + #check_access + #remove_body + } + + /// Iterate over all items in the set + fn #iter_name(&self) -> impl Iterator + '_ { + #check_access + #iter_body + } + + /// Get the number of items in the set + fn #len_name(&self) -> usize { + #check_access + #len_body + } + + /// Check if the set is empty + fn #is_empty_name(&self) -> bool { + #check_access + #is_empty_body + } + } +} + +/// Generate CounterMap operations for a field (works for both inline and lazy storage). +/// +/// Uses `FieldInfo` helpers to generate the correct access patterns: +/// - For inline: direct field access via `self.typed().field` / `self.typed_mut().field` +/// - For lazy: delegates to TaskStorage accessors via `self.typed().field()` / +/// `self.typed_mut().field_mut()` +/// +/// Generates methods for: +/// - `update_{field}_count(key, delta) -> bool` - Returns true if crossed zero boundary +/// - `update_and_get_{field}(key, delta) -> V` - Returns new value +/// - `update_{field}(key, f)` - Closure-based update +/// - `add_{field}(key, value)` - Insert new, panics if exists +/// - `remove_{field}(key) -> Option` - Standard HashMap remove +/// - `update_{field}_positive_crossing(key, delta) -> bool` - For i32 types +/// - `get_{field}_entry(key) -> Option<&V>` - Single-item lookup +fn generate_countermap_ops(field: &FieldInfo) -> TokenStream { + let field_type = &field.field_type; + + let Some((key_type, value_type)) = extract_map_types(field_type, "CounterMap") else { + return quote! {}; + }; + + let check_access = field.check_access_call(); + let track_modification = field.track_modification_call(); + let mut_expr = field.collection_mut_expr(); + let ref_expr = field.collection_ref_expr(); + let is_option = field.is_option_ref(); + + // Method names - use shorter names to match existing API + let update_count_name = field.infixed_ident("update", "count"); + let update_and_get_name = field.prefixed_ident("update_and_get"); + let update_with_name = field.prefixed_ident("update"); + let add_entry_name = field.prefixed_ident("add"); + let remove_name = field.prefixed_ident("remove"); + let update_positive_crossing_name = field.infixed_ident("update", "positive_crossing"); + let get_entry_name = field.infixed_ident("get", "entry"); + let iter_entries_name = field.infixed_ident("iter", "entries"); + let iter_positive_entries_name = field.infixed_ident("iter", "positive_entries"); + let len_name = field.len_ident(); + let is_empty_name = field.is_empty_ident(); + + // Generate get_entry body based on whether ref access returns Option or not + let get_entry_body = if is_option { + quote! { #ref_expr.and_then(|m| m.get(key)) } + } else { + quote! { #ref_expr.get(key) } + }; + + // Generate remove body - for lazy fields, we need to check if the map exists first + // without allocating it. For inline fields, we can use the mut_expr directly. + let remove_body = if is_option { + // Lazy: use find_lazy_mut to avoid allocating, only track modification if something was + let extractor = field.lazy_extractor_closure(); + quote! { + let map = self.typed_mut().find_lazy_mut(#extractor)?; + let result = map.remove(key); + if result.is_some() { + #track_modification + } + result + } + } else { + // Inline: direct access, only track modification if something was removed + quote! { + let result = #mut_expr.remove(key); + if result.is_some() { + #track_modification + } + result + } + }; + + // Generate len body + let len_body = if is_option { + quote! { #ref_expr.map_or(0, |m| m.len()) } + } else { + quote! { #ref_expr.len() } + }; + + // Generate is_empty body + let is_empty_body = if is_option { + quote! { #ref_expr.is_none_or(|m| m.is_empty()) } + } else { + quote! { #ref_expr.is_empty() } + }; + + // Generate iter_entries body + let iter_entries_body = if is_option { + quote! { #ref_expr.into_iter().flat_map(|m| m.iter()) } + } else { + quote! { #ref_expr.iter() } + }; + + // Generate iter_positive_entries body (entries where value > 0) + let iter_positive_entries_body = if is_option { + quote! { + #ref_expr.into_iter().flat_map(|m| { + m.iter().filter_map(|(k, v)| if *v > Default::default() { Some((k, v)) } else { None }) + }) + } + } else { + quote! { + #ref_expr.iter().filter_map(|(k, v)| if *v > Default::default() { Some((k, v)) } else { None }) + } + }; + + quote! { + /// Get a single entry from the counter map + fn #get_entry_name(&self, key: &#key_type) -> Option<&#value_type> { + #check_access + #get_entry_body + } + + /// Update a counter by the given delta. + /// Returns true if the count crossed zero (became zero or became non-zero). + #[must_use] + fn #update_count_name(&mut self, key: #key_type, delta: #value_type) -> bool { + #check_access + #track_modification + #mut_expr.update_count(key, delta) + } + + /// Update a counter by the given delta and return the new value. + fn #update_and_get_name(&mut self, key: #key_type, delta: #value_type) -> #value_type { + #check_access + #track_modification + #mut_expr.update_and_get(key, delta) + } + + /// Update a counter using a closure that receives the current value + /// (or None if not present) and returns the new value (or None to remove). + fn #update_with_name(&mut self, key: #key_type, f: F) + where + F: FnOnce(Option<#value_type>) -> Option<#value_type>, + { + #check_access + #track_modification + #mut_expr.update_with(key, f) + } + + /// Add a new entry, panicking if the entry already exists. + fn #add_entry_name(&mut self, key: #key_type, value: #value_type) { + #check_access + #track_modification + #mut_expr.add_entry(key, value) + } + + /// Remove an entry, returning the value if present. + /// Only tracks modification if an entry was actually removed. + fn #remove_name(&mut self, key: &#key_type) -> Option<#value_type> { + #check_access + #remove_body + } + + /// Update a signed counter by the given delta. + /// Returns true if the count crossed the positive boundary (became positive or non-positive). + #[must_use] + fn #update_positive_crossing_name(&mut self, key: #key_type, delta: #value_type) -> bool { + #check_access + #track_modification + #mut_expr.update_positive_crossing(key, delta) + } + + /// Get the number of entries in the counter map + fn #len_name(&self) -> usize { + #check_access + #len_body + } + + /// Check if the counter map is empty + fn #is_empty_name(&self) -> bool { + #check_access + #is_empty_body + } + + /// Iterate over all key-value pairs in the counter map + fn #iter_entries_name(&self) -> impl Iterator + '_ { + #check_access + #iter_entries_body + } + + /// Iterate over key-value pairs where value > 0 + fn #iter_positive_entries_name(&self) -> impl Iterator + '_ { + #check_access + #iter_positive_entries_body + } + } +} + +/// Generate AutoMap operations for a field (works for both inline and lazy storage). +/// +/// Uses `FieldInfo` helpers to generate the correct access patterns: +/// - For inline: direct field access via `self.typed().field` / `self.typed_mut().field` +/// - For lazy: delegates to TaskStorage accessors +/// +/// Generates methods (using `_entry` suffix for consistency with CounterMap): +/// - `get_{field}_entry(key) -> Option<&V>` - Single-item lookup +/// - `has_{field}_entry(key) -> bool` - Check if key exists +/// - `insert_{field}_entry(key, value) -> Option` - Insert or replace +/// - `remove_{field}_entry(key) -> Option` - Remove entry +/// - `iter_{field}_entries() -> impl Iterator` - Iterate all +/// - `{field}_len() -> usize` - Get count +/// - `is_{field}_empty() -> bool` - Check if empty +fn generate_automap_ops(field: &FieldInfo) -> TokenStream { + let field_type = &field.field_type; + + let Some((key_type, value_type)) = extract_map_types(field_type, "AutoMap") else { + return quote! {}; + }; + + let check_access = field.check_access_call(); + let track_modification = field.track_modification_call(); + let mut_expr = field.collection_mut_expr(); + let ref_expr = field.collection_ref_expr(); + let is_option = field.is_option_ref(); + + // Method names (using `_entry` suffix for consistency with CounterMap) + let get_entry_name = field.infixed_ident("get", "entry"); + let has_entry_name = field.infixed_ident("has", "entry"); + let insert_entry_name = field.infixed_ident("insert", "entry"); + let remove_entry_name = field.infixed_ident("remove", "entry"); + let iter_entries_name = field.infixed_ident("iter", "entries"); + let len_name = field.len_ident(); + let is_empty_name = field.is_empty_ident(); + + // Generate bodies based on whether ref access returns Option or not + let get_entry_body = if is_option { + quote! { #ref_expr.and_then(|m| m.get(key)) } + } else { + quote! { #ref_expr.get(key) } + }; + + let has_entry_body = if is_option { + quote! { #ref_expr.is_some_and(|m| m.contains_key(key)) } + } else { + quote! { #ref_expr.contains_key(key) } + }; + + let iter_body = if is_option { + quote! { #ref_expr.into_iter().flat_map(|m| m.iter()) } + } else { + quote! { #ref_expr.iter() } + }; + + let len_body = if is_option { + quote! { #ref_expr.map_or(0, |m| m.len()) } + } else { + quote! { #ref_expr.len() } + }; + + let is_empty_body = if is_option { + quote! { #ref_expr.is_none_or(|m| m.is_empty()) } + } else { + quote! { #ref_expr.is_empty() } + }; + + // Generate remove body - for lazy fields, avoid allocation if map doesn't exist. + // Using ? operator to early-return None if map doesn't exist. + let remove_body = if is_option { + let extractor = field.lazy_extractor_closure(); + quote! { + let map = self.typed_mut().find_lazy_mut(#extractor)?; + let result = map.remove(key); + if result.is_some() { + #track_modification + } + result + } + } else { + quote! { + let result = #mut_expr.remove(key); + if result.is_some() { + #track_modification + } + result + } + }; + + quote! { + /// Get an entry from the map by key + fn #get_entry_name(&self, key: &#key_type) -> Option<&#value_type> { + #check_access + #get_entry_body + } + + /// Check if the map contains a key + fn #has_entry_name(&self, key: &#key_type) -> bool { + #check_access + #has_entry_body + } + + /// Insert an entry, returning the old value if present. + fn #insert_entry_name(&mut self, key: #key_type, value: #value_type) -> Option<#value_type> { + #check_access + #track_modification + #mut_expr.insert(key, value) + } + + /// Remove an entry, returning the value if present. + /// Only tracks modification if an entry was actually removed. + fn #remove_entry_name(&mut self, key: &#key_type) -> Option<#value_type> { + #check_access + #remove_body + } + + /// Iterate over all key-value pairs in the map + fn #iter_entries_name(&self) -> impl Iterator + '_ { + #check_access + #iter_body + } + + /// Get the number of entries in the map + fn #len_name(&self) -> usize { + #check_access + #len_body + } + + /// Check if the map is empty + fn #is_empty_name(&self) -> bool { + #check_access + #is_empty_body + } + } +} + +/// Extract the inner type from Option, or return the type as-is if not Option +fn extract_option_inner_type(ty: &Type) -> TokenStream { + // Try to parse as Option and extract T + if let Type::Path(type_path) = ty + && let Some(segment) = type_path.path.segments.last() + && segment.ident == "Option" + && let syn::PathArguments::AngleBracketed(args) = &segment.arguments + && let Some(syn::GenericArgument::Type(inner)) = args.args.first() + { + return quote! { #inner }; + } + + // Not Option, return the type as-is + quote! { #ty } +} + +/// Extract the element type K from AutoSet (which is FxHashSet) +fn extract_set_element_type(ty: &Type) -> Option { + if let Type::Path(type_path) = ty + && let Some(segment) = type_path.path.segments.last() + && (segment.ident == "AutoSet" || segment.ident == "FxHashSet") + && let syn::PathArguments::AngleBracketed(args) = &segment.arguments + && let Some(syn::GenericArgument::Type(inner)) = args.args.first() + { + return Some(quote! { #inner }); + } + None +} + +/// Extract key and value types from a map type (e.g., AutoMap or CounterMap) +fn extract_map_types(ty: &Type, expected_name: &str) -> Option<(TokenStream, TokenStream)> { + if let Type::Path(type_path) = ty + && let Some(segment) = type_path.path.segments.last() + && segment.ident == expected_name + && let syn::PathArguments::AngleBracketed(args) = &segment.arguments + { + let mut args_iter = args.args.iter(); + if let Some(syn::GenericArgument::Type(key_type)) = args_iter.next() + && let Some(syn::GenericArgument::Type(value_type)) = args_iter.next() + { + return Some((quote! { #key_type }, quote! { #value_type })); + } + } + None +} + +fn capitalize(s: &str) -> String { + let mut c = s.chars(); + match c.next() { + None => String::new(), + Some(f) => f.to_uppercase().collect::() + c.as_str(), + } +} + +/// Convert snake_case to PascalCase (e.g., "in_progress" -> "InProgress") +fn to_pascal_case(s: &str) -> String { + s.split('_').map(capitalize).collect::() +} + +/// Generates trait accessor methods for a flag field (stored in TaskFlags bitfield) +fn generate_flag_trait_accessor_methods(field: &FieldInfo) -> TokenStream { + let field_name = &field.field_name; + let set_name = field.set_ident(); + + // Flags use check_access_call() which handles transient vs non-transient + let check_access = field.check_access_call(); + // All flags modify meta category (they're stored in the flags bitfield which is meta) + let track_modification = quote! { self.track_modification(crate::backend::storage::SpecificTaskDataCategory::Meta); }; + + quote! { + /// Get the flag value + fn #field_name(&self) -> bool { + #check_access + self.typed().flags.#field_name() + } + + /// Set the flag value + /// + /// Only tracks modification if the value actually changes. + fn #set_name(&mut self, value: bool) { + #check_access + let current = self.typed().flags.#field_name(); + if current != value { + self.typed_mut().flags.#set_name(value); + #track_modification + } + } + } +} + +/// Generate encode body for a category (inline fields + lazy fields). +fn gen_encode_body(grouped_fields: &GroupedFields, category: Category) -> TokenStream { + let inline: Vec<_> = grouped_fields + .persistent_inline(category.clone()) + .map(generate_encode_inline_field) + .collect(); + let lazy: Vec<_> = grouped_fields.persistent_lazy(category).collect(); + let lazy_encode = generate_encode_lazy_fields(&lazy); + + quote! { + #(#inline)* + #lazy_encode + } +} + +/// Generate decode body for a category (inline fields + lazy fields). +fn gen_decode_body(grouped_fields: &GroupedFields, category: Category) -> TokenStream { + let inline: Vec<_> = grouped_fields + .persistent_inline(category.clone()) + .map(|field| { + let field_name = &field.field_name; + quote! { + self.#field_name = bincode::Decode::decode(decoder)?; + } + }) + .collect(); + let lazy: Vec<_> = grouped_fields.persistent_lazy(category).collect(); + let lazy_decode = generate_decode_lazy_fields(&lazy); + + quote! { + #(#inline)* + #lazy_decode + } +} + +/// Generate encode/decode methods for TaskStorage serialization. +/// +/// Generates four methods: +/// - `encode_meta(&self, encoder: &mut E)` - Encode meta category fields +/// - `encode_data(&self, encoder: &mut E)` - Encode data category fields +/// - `decode_meta(&mut self, decoder: &mut D)` - Decode meta category fields +/// - `decode_data(&mut self, decoder: &mut D)` - Decode data category fields +/// +/// Only persistent (non-transient) fields are encoded/decoded. +fn generate_encode_decode_methods(grouped_fields: &GroupedFields) -> TokenStream { + let has_flags = grouped_fields.persisted_flags().next().is_some(); + + let encode_meta_body = gen_encode_body(grouped_fields, Category::Meta); + let encode_data_body = gen_encode_body(grouped_fields, Category::Data); + let decode_meta_body = gen_decode_body(grouped_fields, Category::Meta); + let decode_data_body = gen_decode_body(grouped_fields, Category::Data); + + let encode_flags = if has_flags { + quote! { + // Encode only the persisted flag bits + let persisted_flags = self.flags.persisted_bits(); + bincode::Encode::encode(&persisted_flags, encoder)?; + } + } else { + quote! {} + }; + + let decode_flags = if has_flags { + quote! { + // Decode only the persisted flag bits, preserving transient bits + let persisted_flags: u16 = bincode::Decode::decode(decoder)?; + self.flags.set_persisted_bits(persisted_flags); + } + } else { + quote! {} + }; + + quote! { + #[automatically_derived] + impl TaskStorage { + /// Encode meta category fields directly to bincode. + /// Only persistent (non-transient) fields are encoded. + pub fn encode_meta( + &self, + encoder: &mut E, + ) -> Result<(), bincode::error::EncodeError> { + #encode_meta_body + #encode_flags + Ok(()) + } + + /// Encode data category fields directly to bincode. + /// Only persistent (non-transient) fields are encoded. + pub fn encode_data( + &self, + encoder: &mut E, + ) -> Result<(), bincode::error::EncodeError> { + #encode_data_body + Ok(()) + } + + /// Decode meta category fields from bincode. + /// Only persistent (non-transient) fields are decoded. + pub fn decode_meta( + &mut self, + decoder: &mut D, + ) -> Result<(), bincode::error::DecodeError> { + #decode_meta_body + #decode_flags + Ok(()) + } + + /// Decode data category fields from bincode. + /// Only persistent (non-transient) fields are decoded. + pub fn decode_data( + &mut self, + decoder: &mut D, + ) -> Result<(), bincode::error::DecodeError> { + #decode_data_body + Ok(()) + } + } + } +} + +/// Sentinel byte marking the end of lazy fields in serialization. +const LAZY_FIELD_SENTINEL: u8 = 0x00; + +// ============================================================================= +// Transient Filtering Helpers +// ============================================================================= + +/// Filter predicate type for transient filtering. +/// +/// Describes what type of value the filter applies to: +/// - `Option`: filter predicate for Option inner value +/// - `Set`: filter predicate for set elements +/// - `Map`: filter predicate for map entries (key, value) +/// - `CounterMap`: filter predicate for counter map entries (key only) +#[derive(Clone, Copy)] +enum FilterPredicateType { + Option, + Set, + Map, + CounterMap, +} + +/// Generate the filter predicate closure for a field. +/// +/// Returns the predicate expression (e.g., `|k| !k.is_transient()`) and the predicate type. +/// Returns `None` if no filtering is needed. +fn generate_filter_predicate(field: &FieldInfo) -> Option<(TokenStream, FilterPredicateType)> { + if !field.filter_transient { + return None; + } + + match field.storage_type { + StorageType::Direct => Some(( + quote! { |v| !v.is_transient() }, + FilterPredicateType::Option, + )), + StorageType::AutoSet => Some((quote! { |k| !k.is_transient() }, FilterPredicateType::Set)), + StorageType::CounterMap => Some(( + quote! { |(k, _)| !k.is_transient() }, + FilterPredicateType::CounterMap, + )), + StorageType::AutoMap => Some(( + quote! { |(k, v)| !k.is_transient() && !v.is_transient() }, + FilterPredicateType::Map, + )), + StorageType::Flag => { + // Flags are encoded in TaskFlags bitfield, not individually + unreachable!("Flag fields should not reach generate_filter_predicate") + } + } +} + +/// Generate code to encode a value with transient filtering based on field configuration. +/// +/// This is a shared helper used by both inline field encoding and lazy field encoding. +/// The `value_ref` parameter is an expression that evaluates to a *reference* to the value +/// (e.g., `&self.field_name` for inline fields, or `data` for lazy fields where `data` +/// is already a reference from the match arm). +/// +/// For non-filtered fields, encodes the value directly. +/// For filtered fields, uses a single-pass collect to a Vec, then encodes. +/// This avoids multiple iterations (check non-empty + count + encode). +fn generate_encode_value(field: &FieldInfo, value_ref: TokenStream) -> TokenStream { + let Some((predicate, pred_type)) = generate_filter_predicate(field) else { + // No filtering needed, just encode normally + return quote! { + bincode::Encode::encode(#value_ref, encoder)?; + }; + }; + + match pred_type { + FilterPredicateType::Option => { + // For Option, check if the value is transient and encode None if so + quote! { + { + let filtered_value = (#value_ref).as_ref().filter(#predicate); + bincode::Encode::encode(&filtered_value, encoder)?; + } + } + } + FilterPredicateType::Set => { + // For AutoSet, filter out transient keys - collect once then encode + quote! { + { + let filtered: Vec<_> = (#value_ref).iter().filter(#predicate).collect(); + bincode::Encode::encode(&filtered.len(), encoder)?; + for key in filtered { + bincode::Encode::encode(key, encoder)?; + } + } + } + } + FilterPredicateType::CounterMap => { + // For counter maps, filter out entries with transient keys - collect once + quote! { + { + let filtered: Vec<_> = (#value_ref).iter().filter(#predicate).collect(); + bincode::Encode::encode(&filtered.len(), encoder)?; + for (key, value) in filtered { + bincode::Encode::encode(key, encoder)?; + bincode::Encode::encode(value, encoder)?; + } + } + } + } + FilterPredicateType::Map => { + // For maps, filter out entries with transient keys or values - collect once + quote! { + { + let filtered: Vec<_> = (#value_ref).iter().filter(#predicate).collect(); + bincode::Encode::encode(&filtered.len(), encoder)?; + for (key, value) in filtered { + bincode::Encode::encode(key, encoder)?; + bincode::Encode::encode(value, encoder)?; + } + } + } + } + } +} + +/// Generate code to encode an inline field to bincode. +/// +/// Delegates to `generate_encode_value` with `&self.field_name` as the value reference. +fn generate_encode_inline_field(field: &FieldInfo) -> TokenStream { + let field_name = &field.field_name; + generate_encode_value(field, quote! { &self.#field_name }) +} + +/// Generate code to encode a lazy field value with index. +/// +/// For filtered fields, collects to a Vec first, then checks if non-empty before +/// writing index. This avoids multiple iterations over the data. +fn generate_encode_lazy_field_with_index(field: &FieldInfo, index: u8) -> TokenStream { + let Some((predicate, pred_type)) = generate_filter_predicate(field) else { + // No filtering needed - encode directly + return quote! { + bincode::Encode::encode(&#index, encoder)?; + bincode::Encode::encode(data, encoder)?; + }; + }; + + match pred_type { + FilterPredicateType::Option => { + // For Option, check if the value is transient + quote! { + { + let filtered_value = data.as_ref().filter(#predicate); + if filtered_value.is_some() { + bincode::Encode::encode(&#index, encoder)?; + bincode::Encode::encode(&filtered_value, encoder)?; + } + } + } + } + FilterPredicateType::Set => { + // Collect once, check if non-empty, then encode + quote! { + { + let filtered: Vec<_> = data.iter().filter(#predicate).collect(); + if !filtered.is_empty() { + bincode::Encode::encode(&#index, encoder)?; + bincode::Encode::encode(&filtered.len(), encoder)?; + for key in filtered { + bincode::Encode::encode(key, encoder)?; + } + } + } + } + } + FilterPredicateType::CounterMap | FilterPredicateType::Map => { + // Collect once, check if non-empty, then encode + quote! { + { + let filtered: Vec<_> = data.iter().filter(#predicate).collect(); + if !filtered.is_empty() { + bincode::Encode::encode(&#index, encoder)?; + bincode::Encode::encode(&filtered.len(), encoder)?; + for (key, value) in filtered { + bincode::Encode::encode(key, encoder)?; + bincode::Encode::encode(value, encoder)?; + } + } + } + } + } + } +} + +/// Generate code to encode lazy fields to bincode. +/// Uses sentinel-terminated format: [index, data]... [sentinel] +fn generate_encode_lazy_fields(fields: &[&FieldInfo]) -> TokenStream { + if fields.is_empty() { + return quote! {}; + } + + // Generate match arms for encoding each field variant + let encode_arms = gen_lazy_match_arms(fields.iter().copied(), |idx, field| { + // add 1 so 0 is reserved for the sentinel + let idx = idx as u8 + 1; + generate_encode_lazy_field_with_index(field, idx) + }); + + quote! { + // Encode each persistent lazy field in this category + for field in &self.lazy { + match field { + #(#encode_arms)* + _ => {} // Skip fields not in this category + } + } + // Write sentinel to mark end of lazy fields + bincode::Encode::encode(&#LAZY_FIELD_SENTINEL, encoder)?; + } +} + +/// Generate code to decode lazy fields from bincode. +/// Reads until sentinel byte (0x00) is encountered. +fn generate_decode_lazy_fields(fields: &[&FieldInfo]) -> TokenStream { + if fields.is_empty() { + return quote! {}; + } + + // Generate match arms for decoding each field variant + let decode_arms: Vec<_> = fields + .iter() + .enumerate() + .map(|(idx, field)| { + let variant_name = &field.variant_name; + let idx = idx as u8 + 1; + quote! { + #idx => LazyField::#variant_name(bincode::Decode::decode(decoder)?) + } + }) + .collect(); + + quote! { + // Decode lazy fields until LAZY_FIELD_SENTINEL + loop { + let idx: u8 = bincode::Decode::decode(decoder)?; + let field = match idx { + #(#decode_arms,)* + #LAZY_FIELD_SENTINEL => { + break + } + _ => { + return Err(bincode::error::DecodeError::OtherString( + format!("Unknown lazy field index: {idx}"), + )); + } + }; + self.lazy.push(field); + } + } +} + +/// Generate clone inline statements for a category. +fn gen_clone_inline_for_category( + grouped_fields: &GroupedFields, + category: Category, +) -> Vec { + gen_clone_inline_fields(grouped_fields.persistent_inline(category)) +} + +/// Generate clone lazy match arms for a category. +fn gen_clone_lazy_arms_for_category( + grouped_fields: &GroupedFields, + category: Category, +) -> Vec { + gen_lazy_match_arms(grouped_fields.persistent_lazy(category), |_, field| { + let variant_name = &field.variant_name; + quote! { snapshot.lazy.push(LazyField::#variant_name(data.clone())); } + }) +} + +/// Generate restore inline statements for a category. +fn gen_restore_inline_for_category( + grouped_fields: &GroupedFields, + category: Category, +) -> Vec { + gen_restore_inline_fields(grouped_fields.persistent_inline(category)) +} + +/// Generate snapshot clone and restore methods for TaskStorage. +/// +/// Generates: +/// - `clone_meta_snapshot(&self) -> TaskStorage` - Clone only persistent meta fields +/// - `clone_data_snapshot(&self) -> TaskStorage` - Clone only persistent data fields +/// - `restore_from(&mut self, source, category)` - Restore data by category from decoded storage +/// - `restore_meta_from(&mut self, source)` - Restore meta fields from source +/// - `restore_data_from(&mut self, source)` - Restore data fields from source +/// - `restore_all_from(&mut self, source)` - Restore all fields from source +fn generate_snapshot_restore_methods(grouped_fields: &GroupedFields) -> TokenStream { + let has_flags = grouped_fields.persisted_flags().next().is_some(); + + // Generate field operations by category + let clone_meta_inline = gen_clone_inline_for_category(grouped_fields, Category::Meta); + let clone_data_inline = gen_clone_inline_for_category(grouped_fields, Category::Data); + let clone_meta_lazy_arms = gen_clone_lazy_arms_for_category(grouped_fields, Category::Meta); + let clone_data_lazy_arms = gen_clone_lazy_arms_for_category(grouped_fields, Category::Data); + + let restore_meta_inline = gen_restore_inline_for_category(grouped_fields, Category::Meta); + let restore_data_inline = gen_restore_inline_for_category(grouped_fields, Category::Data); + + // Generate flags handling for clone/merge + let clone_meta_flags = if has_flags { + quote! { + // Clone persisted flags + snapshot.flags.set_persisted_bits(self.flags.persisted_bits()); + } + } else { + quote! {} + }; + + let restore_flags = if has_flags { + quote! { + // Restore persisted flags (preserve transient flags) + let persisted_bits = source.flags.persisted_bits(); + self.flags.set_persisted_bits(persisted_bits); + } + } else { + quote! {} + }; + + quote! { + #[automatically_derived] + impl TaskStorage { + /// Create a snapshot containing all persistent fields (both meta and data). + /// + /// This clones all persistent fields into a new TaskStorage, skipping + /// transient fields that may not be cloneable. Use this for the `Both` + /// snapshot case where both meta and data are dirty. + pub fn clone_snapshot(&self) -> TaskStorage { + let mut snapshot = TaskStorage::new(); + + // Clone inline meta fields + #(#clone_meta_inline)* + + // Clone inline data fields + #(#clone_data_inline)* + + #clone_meta_flags + + // Clone all persistent lazy fields (both meta and data) + for field in &self.lazy { + match field { + #(#clone_data_lazy_arms)* + #(#clone_meta_lazy_arms)* + // Skip transient fields + _ => {} + } + } + + snapshot + } + + /// Create a snapshot containing only meta category fields for serialization. + /// + /// This clones only the persistent meta fields into a new TaskStorage, + /// which can then be serialized outside the lock. + pub fn clone_meta_snapshot(&self) -> TaskStorage { + let mut snapshot = TaskStorage::new(); + + // Clone inline meta fields + #(#clone_meta_inline)* + + #clone_meta_flags + + // Clone lazy meta fields (only persistent ones) + for field in &self.lazy { + match field { + #(#clone_meta_lazy_arms)* + // Skip transient and data fields + _ => {} + } + } + + snapshot + } + + /// Create a snapshot containing only data category fields for serialization. + /// + /// This clones only the persistent data fields into a new TaskStorage, + /// which can then be serialized outside the lock. + pub fn clone_data_snapshot(&self) -> TaskStorage { + let mut snapshot = TaskStorage::new(); + + // Clone inline data fields + #(#clone_data_inline)* + + // Clone lazy data fields (only persistent ones) + for field in &self.lazy { + match field { + #(#clone_data_lazy_arms)* + // Skip transient and meta fields + _ => {} + } + } + + snapshot + } + + /// Restore persisted data from a decoded TaskStorage. + /// + /// This is used during restore operations to copy decoded persisted data + /// into the task's existing storage. It preserves transient state (flags, + /// transient fields) while restoring the persisted data. + /// + /// # Invariant + /// + /// This method assumes the target does NOT already have the persistent fields + /// being restored. This is guaranteed by the restore protocol which only calls + /// this once per category when the task is first accessed. Debug assertions + /// verify this invariant. + /// + /// The `category` parameter specifies which category of data to restore: + /// - `Meta`: Restore meta fields (aggregation_number, output, upper, dirty, etc.) + /// - `Data`: Restore data fields (output_dependent, dependencies, cell_data, etc.) + /// - `All`: Restore both meta and data fields + pub fn restore_from( + &mut self, + source: TaskStorage, + category: crate::backend::TaskDataCategory, + ) { + match category { + crate::backend::TaskDataCategory::Meta => self.restore_meta_from(source), + crate::backend::TaskDataCategory::Data => self.restore_data_from(source), + crate::backend::TaskDataCategory::All => self.restore_all_from(source), + } + } + + /// Restore meta category fields from source. + /// + /// Debug assertions verify that the target doesn't already have the lazy fields + /// being restored. + fn restore_meta_from(&mut self, source: TaskStorage) { + // Debug assertion: verify target doesn't already have persistent meta lazy fields + debug_assert!( + !self.lazy.iter().any(|f| f.is_persistent() && f.is_meta()), + "restore_meta_from called on storage that already has persistent meta lazy fields" + ); + + // Inline meta fields - direct assignment + #(#restore_meta_inline)* + + #restore_flags + + // Extend lazy vec with persistent meta fields from source + self.lazy.extend( + source.lazy.into_iter().filter(|f| f.is_persistent() && f.is_meta()) + ); + } + + /// Restore data category fields from source. + /// + /// Debug assertions verify that the target doesn't already have the lazy fields + /// being restored. + fn restore_data_from(&mut self, source: TaskStorage) { + // Debug assertion: verify target doesn't already have persistent data lazy fields + debug_assert!( + !self.lazy.iter().any(|f| f.is_persistent() && f.is_data()), + "restore_data_from called on storage that already has persistent data lazy fields" + ); + + // Inline data fields - direct assignment + #(#restore_data_inline)* + + // Extend lazy vec with persistent data fields from source + self.lazy.extend( + source.lazy.into_iter().filter(|f| f.is_persistent() && f.is_data()) + ); + } + + /// Restore all fields from source (both meta and data). + /// + /// Debug assertions verify that the target doesn't already have the lazy fields + /// being restored. + fn restore_all_from(&mut self, source: TaskStorage) { + // Debug assertion: verify target doesn't already have any persistent lazy fields + debug_assert!( + !self.lazy.iter().any(|f| f.is_persistent()), + "restore_all_from called on storage that already has persistent lazy fields" + ); + + // Inline meta fields - direct assignment + #(#restore_meta_inline)* + + // Inline data fields - direct assignment + #(#restore_data_inline)* + + #restore_flags + + // Extend lazy vec with all persistent fields from source + self.lazy.extend( + source.lazy.into_iter().filter(|f| f.is_persistent()) + ); + } + } + } +} diff --git a/turbopack/crates/turbo-tasks-macros/src/func.rs b/turbopack/crates/turbo-tasks-macros/src/func.rs index 054f13e13365..7932ceec4aaf 100644 --- a/turbopack/crates/turbo-tasks-macros/src/func.rs +++ b/turbopack/crates/turbo-tasks-macros/src/func.rs @@ -4,14 +4,14 @@ use proc_macro2::{Group, Ident, Span, TokenStream, TokenTree}; use quote::{ToTokens, quote, quote_spanned}; use rustc_hash::FxHashSet; use syn::{ - AngleBracketedGenericArguments, Attribute, Block, Expr, ExprBlock, ExprPath, FnArg, - GenericArgument, Local, LocalInit, Meta, Pat, PatIdent, PatType, Path, PathArguments, - PathSegment, Receiver, ReturnType, Signature, Stmt, Token, Type, TypeGroup, TypePath, - TypeTuple, + AngleBracketedGenericArguments, Attribute, Block, Expr, ExprBlock, FnArg, GenericArgument, + Local, LocalInit, Meta, Pat, PatIdent, PatType, Path, PathArguments, PathSegment, Receiver, + ReturnType, Signature, Stmt, Token, Type, TypeGroup, TypePath, TypeTuple, parse::{Parse, ParseStream}, parse_quote, parse_quote_spanned, punctuated::{Pair, Punctuated}, spanned::Spanned, + token, visit_mut::VisitMut, }; @@ -213,33 +213,23 @@ impl TurboFn<'_> { /// The signature of the exposed function. This is the original signature /// converted to a standard turbo_tasks function signature. - pub fn signature(&self) -> Signature { - let exposed_inputs: Punctuated<_, Token![,]> = self + pub fn signature(&self) -> TokenStream { + let exposed_inputs = self .this .as_ref() .into_iter() .chain(self.exposed_inputs.iter()) .map(|input| { - FnArg::Typed(PatType { - attrs: Vec::new(), - pat: Box::new(Pat::Ident(PatIdent { - attrs: Default::default(), - by_ref: None, - mutability: None, - ident: input.ident.clone(), - subpat: None, - })), - colon_token: Default::default(), - ty: if self.operation { - // operations shouldn't have their arguments rewritten, they require all - // arguments are explicitly `NonLocalValue`s - Box::new(input.ty.clone()) - } else { - Box::new(expand_task_input_type(&input.ty).into_owned()) - }, - }) - }) - .collect(); + let ident = &input.ident; + let ty = if self.operation { + // operations shouldn't have their arguments rewritten, they require all + // arguments are explicitly `NonLocalValue`s + input.ty.to_token_stream() + } else { + expand_task_input_type(&input.ty).to_token_stream() + }; + quote! { #ident: #ty } + }); let ident = &self.ident; let orig_output = &self.output; @@ -249,15 +239,15 @@ impl TurboFn<'_> { .then(|| parse_quote!(turbo_tasks::OperationVc)), ); - parse_quote! { - fn #ident(#exposed_inputs) -> #new_output + quote! { + fn #ident(#(#exposed_inputs),*) -> #new_output } } - pub fn trait_signature(&self) -> Signature { + pub fn trait_signature(&self) -> TokenStream { let signature = self.signature(); - parse_quote! { + quote! { #signature where Self: Sized } } @@ -504,9 +494,9 @@ impl TurboFn<'_> { } } - fn converted_this(&self) -> Option { + fn converted_this(&self) -> Option { self.this.as_ref().map(|Input { ty: _, ident }| { - parse_quote! { + quote! { turbo_tasks::Vc::into_raw(#ident) } }) @@ -546,9 +536,9 @@ impl TurboFn<'_> { } /// The block of the exposed function for a dynamic dispatch call to the given trait. - pub fn dynamic_block(&self, trait_type_ident: &Ident) -> Block { + pub fn dynamic_block(&self, trait_type_ident: &Ident) -> TokenStream { let Some(converted_this) = self.converted_this() else { - return parse_quote! { + return quote! { { unimplemented!("trait methods without self are not yet supported") } @@ -560,7 +550,7 @@ impl TurboFn<'_> { let assertions = self.get_assertions(); let inputs = self.exposed_input_idents(); let persistence = self.persistence_with_this(); - parse_quote! { + quote! { { #assertions let inputs = std::boxed::Box::new((#(#inputs,)*)); @@ -581,7 +571,7 @@ impl TurboFn<'_> { } /// The block of the exposed function for a static dispatch call to the given native function. - pub fn static_block(&self, native_function_ident: &Ident) -> Block { + pub fn static_block(&self, native_function_ident: &Ident) -> TokenStream { let output = &self.output; let inputs = self.inline_input_idents(); let assertions = self.get_assertions(); @@ -589,7 +579,7 @@ impl TurboFn<'_> { && let Some(converted_this) = self.converted_this() { let persistence = self.persistence_with_this(); - parse_quote! { + quote! { { #assertions let inputs = std::boxed::Box::new((#(#inputs,)*)); @@ -607,7 +597,7 @@ impl TurboFn<'_> { } } else { let persistence = self.persistence(); - parse_quote! { + quote! { { #assertions let inputs = std::boxed::Box::new((#(#inputs,)*)); @@ -624,7 +614,7 @@ impl TurboFn<'_> { } }; if self.operation { - block = parse_quote! { + block = quote! { { let vc_output = #block; // Assumption: The turbo-tasks manager will not create a local task for a @@ -774,7 +764,10 @@ impl Parse for FunctionArguments { fn return_type_to_type(return_type: &ReturnType) -> Type { match return_type { - ReturnType::Default => parse_quote! { () }, + ReturnType::Default => Type::Tuple(TypeTuple { + paren_token: token::Paren::default(), + elems: Punctuated::new(), + }), ReturnType::Type(_, return_type) => (**return_type).clone(), } } @@ -1080,7 +1073,7 @@ pub struct FilterTraitCallArgsTokens { pub struct NativeFn { pub function_global_name: TokenStream, pub function_path_string: String, - pub function_path: ExprPath, + pub function_path: TokenStream, pub is_method: bool, /// Used only if `is_method` is true. pub is_self_used: bool, @@ -1088,8 +1081,8 @@ pub struct NativeFn { } impl NativeFn { - pub fn ty(&self) -> Type { - parse_quote! { turbo_tasks::macro_helpers::NativeFunction } + pub fn ty(&self) -> TokenStream { + quote! { turbo_tasks::macro_helpers::NativeFunction } } pub fn definition(&self) -> TokenStream { diff --git a/turbopack/crates/turbo-tasks-macros/src/function_macro.rs b/turbopack/crates/turbo-tasks-macros/src/function_macro.rs index 7549c0501159..28215d6f4a25 100644 --- a/turbopack/crates/turbo-tasks-macros/src/function_macro.rs +++ b/turbopack/crates/turbo-tasks-macros/src/function_macro.rs @@ -1,6 +1,6 @@ use proc_macro::TokenStream; use quote::quote; -use syn::{ItemFn, parse_macro_input, parse_quote}; +use syn::{ItemFn, parse_macro_input}; use crate::{ func::{DefinitionContext, FunctionArguments, NativeFn, TurboFn, filter_inline_attributes}, @@ -60,7 +60,7 @@ pub fn function(args: TokenStream, input: TokenStream) -> TokenStream { let native_fn = NativeFn { function_global_name: global_name(&function_path_string), function_path_string, - function_path: parse_quote! { #inline_function_ident }, + function_path: quote! { #inline_function_ident }, is_method: turbo_fn.is_method(), is_self_used, filter_trait_call_args: None, // not a trait method diff --git a/turbopack/crates/turbo-tasks-macros/src/generic_type_input.rs b/turbopack/crates/turbo-tasks-macros/src/generic_type_input.rs deleted file mode 100644 index ebac1308951e..000000000000 --- a/turbopack/crates/turbo-tasks-macros/src/generic_type_input.rs +++ /dev/null @@ -1,21 +0,0 @@ -use syn::{ - Generics, Result, Token, Type, - parse::{Parse, ParseStream}, -}; - -/// The input of the `generic_type` macro. -#[derive(Debug)] -pub struct GenericTypeInput { - pub generics: Generics, - pub ty: Type, -} - -impl Parse for GenericTypeInput { - fn parse(input: ParseStream) -> Result { - let generics: Generics = input.parse()?; - let _comma: Token![,] = input.parse()?; - let ty: Type = input.parse()?; - - Ok(GenericTypeInput { generics, ty }) - } -} diff --git a/turbopack/crates/turbo-tasks-macros/src/generic_type_macro.rs b/turbopack/crates/turbo-tasks-macros/src/generic_type_macro.rs deleted file mode 100644 index 156d7cb68633..000000000000 --- a/turbopack/crates/turbo-tasks-macros/src/generic_type_macro.rs +++ /dev/null @@ -1,160 +0,0 @@ -use proc_macro::TokenStream; -use quote::quote; -use rustc_hash::FxHashSet; -use syn::{GenericParam, Lifetime, Type, parse_macro_input, spanned::Spanned, visit_mut::VisitMut}; - -use crate::{ - generic_type_input::GenericTypeInput, global_name::global_name, ident::get_type_ident, - value_macro::value_type_and_register, -}; - -pub fn generic_type(input: TokenStream) -> TokenStream { - let mut input = parse_macro_input!(input as GenericTypeInput); - - for param in &input.generics.params { - match param { - syn::GenericParam::Type(ty) => { - if ty.ident == "Vc" { - ty.span() - .unwrap() - .error("Vc is a reserved name in generic_type") - .emit(); - } - } - syn::GenericParam::Lifetime(lt) => { - lt.span() - .unwrap() - .error("lifetime parameters are not supported in generic_type") - .emit(); - } - syn::GenericParam::Const(c) => { - c.span() - .unwrap() - .error("const parameters are not supported in generic_type") - .emit(); - } - } - } - - // Add Send bound to input generics. - - for param in &mut input.generics.params { - if let GenericParam::Type(param) = param { - param.bounds.push(syn::parse_quote! { std::marker::Send }); - } - } - - let (impl_generics, _, where_clause) = input.generics.split_for_impl(); - - let ty = &input.ty; - let repr = replace_generics_with_unit(input.generics.params.iter(), ty); - - let Some(ident) = get_type_ident(ty) else { - return quote! { - // An error occurred while parsing the ident. - } - .into(); - }; - - let mut generics_with_static = input.generics.clone(); - for param in &mut generics_with_static.params { - if let GenericParam::Type(param) = param { - param.bounds.push(syn::TypeParamBound::Lifetime(Lifetime { - ident: syn::Ident::new("static", param.ident.span()), - apostrophe: param.ident.span(), - })) - } - } - - let name = global_name(quote! {stringify!(#repr) }); - let value_type_and_register = value_type_and_register( - &ident, - quote! { #ty }, - Some(&generics_with_static), - quote! { - turbo_tasks::VcTransparentRead<#ty, #ty, #repr> - }, - quote! { - turbo_tasks::VcCellCompareMode<#ty> - }, - quote! { - turbo_tasks::ValueType::new_with_any_serialization::<#repr>(#name) - }, - quote! { true }, - ); - - quote! { - #value_type_and_register - - impl #impl_generics Vc<#ty> #where_clause { - /// Converts this `Vc` to a generic representation. - fn to_repr(vc: Self) -> Vc<#repr> { - unsafe { - turbo_tasks::Vc::from_raw(Vc::into_raw(vc)) - } - } - - /// Converts a generic representation of this `Vc` to the proper `Vc` type. - /// - /// # Safety - /// - /// The caller must ensure that the `repr` is a valid representation of this `Vc`. - unsafe fn from_repr(vc: Vc<#repr>) -> Self { - unsafe { - turbo_tasks::Vc::from_raw(Vc::into_raw(vc)) - } - } - } - } - .into() -} - -struct ReplaceGenericsVisitor<'a> { - generics: &'a FxHashSet, -} - -impl VisitMut for ReplaceGenericsVisitor<'_> { - fn visit_type_mut(&mut self, node: &mut Type) { - if let Type::Path(type_path) = node - && type_path.qself.is_none() - && type_path.path.segments.len() == 1 - && type_path.path.segments[0].arguments.is_none() - && self - .generics - .contains(&type_path.path.segments[0].ident.to_string()) - { - // Replace the whole path with () - *node = syn::parse_quote! { () }; - return; - } - - syn::visit_mut::visit_type_mut(self, node); - } -} - -/// Replaces all instances of `params` generic types in `ty` with the unit type -/// `()`. -fn replace_generics_with_unit<'a, P>(params: P, ty: &Type) -> Type -where - P: IntoIterator, -{ - let generics_set: FxHashSet<_> = params - .into_iter() - .filter_map(|param| { - if let GenericParam::Type(type_param) = param { - Some(type_param.ident.to_string()) - } else { - None - } - }) - .collect(); - - let mut new_ty = ty.clone(); - let mut visitor = ReplaceGenericsVisitor { - generics: &generics_set, - }; - - syn::visit_mut::visit_type_mut(&mut visitor, &mut new_ty); - - new_ty -} diff --git a/turbopack/crates/turbo-tasks-macros/src/lib.rs b/turbopack/crates/turbo-tasks-macros/src/lib.rs index cde19e188303..38f0796c0bf1 100644 --- a/turbopack/crates/turbo-tasks-macros/src/lib.rs +++ b/turbopack/crates/turbo-tasks-macros/src/lib.rs @@ -7,7 +7,6 @@ mod assert_fields; mod derive; mod func; mod function_macro; -mod generic_type_macro; mod global_name; mod primitive_macro; mod value_impl_macro; @@ -15,7 +14,6 @@ mod value_macro; mod value_trait_macro; mod expand; -mod generic_type_input; mod ident; mod primitive_input; mod self_filter; @@ -68,6 +66,15 @@ pub fn derive_key_value_pair(input: TokenStream) -> TokenStream { derive::derive_key_value_pair(input) } +/// +#[proc_macro_attribute] +pub fn task_storage(_args: TokenStream, input: TokenStream) -> TokenStream { + derive::task_storage(input) +} + ///