From 3e77d69ca0914a51f88aa1d9e42f2d36fa0db3c4 Mon Sep 17 00:00:00 2001 From: Zack Tanner Date: Mon, 16 Oct 2023 08:36:34 -0700 Subject: [PATCH 01/21] improve next-image-proxy test (#56893) This fixes a warning where the test server was exiting before all the proxy requests finished. This also throws an error to fail the test if any of the proxied requests aren't fulfilled. [slack x-ref](https://vercel.slack.com/archives/C04DUD7EB1B/p1697465502593889?thread_ts=1697143786.511779&cid=C04DUD7EB1B) --- .../app-dir/next-image/next-image-proxy.test.ts | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/test/e2e/app-dir/next-image/next-image-proxy.test.ts b/test/e2e/app-dir/next-image/next-image-proxy.test.ts index f38eebba02dad..cce1a91812e61 100644 --- a/test/e2e/app-dir/next-image/next-image-proxy.test.ts +++ b/test/e2e/app-dir/next-image/next-image-proxy.test.ts @@ -1,5 +1,5 @@ import { join } from 'path' -import { findPort } from 'next-test-utils' +import { findPort, check } from 'next-test-utils' import https from 'https' import httpProxy from 'http-proxy' import fs from 'fs' @@ -40,7 +40,7 @@ createNextDescribe( }) proxy.on('error', (err) => { - console.warn('Failed to proxy', err) + throw new Error('Failed to proxy: ' + err.message) }) await new Promise((resolve) => { @@ -50,6 +50,7 @@ createNextDescribe( it('loads images without any errors', async () => { let failCount = 0 + let fulfilledCount = 0 const browser = await webdriver(`https://localhost:${proxyPort}`, '/', { ignoreHTTPSErrors: true, @@ -66,6 +67,8 @@ createNextDescribe( console.log(`Request failed: ${url}`) failCount++ } + + fulfilledCount++ }) }, }) @@ -77,10 +80,15 @@ createNextDescribe( '/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Ftest.3f1a293b.png&w=828&q=90' ) - expect(failCount).toBe(0) + await check(() => { + // we expect 3 images to load and for none of them to have errors + if (fulfilledCount === 3 && failCount === 0) { + return 'success' + } + }, 'success') }) - afterAll(async () => { + afterAll(() => { proxyServer.close() }) } From d32121b736098ac78544996fb2c5935d0c3128fd Mon Sep 17 00:00:00 2001 From: Steven Date: Mon, 16 Oct 2023 14:48:29 -0400 Subject: [PATCH 02/21] chore(test): test remote image from proxy (#56895) This PR adds a test to ensure we don't regress again when using proxies in front of Next.js with `connection: 'upgrade'`. - Regression introduced in https://github.com/vercel/next.js/pull/56226 - Issue reported in https://github.com/vercel/next.js/issues/56038 - Rolled back in https://github.com/vercel/next.js/pull/56836 --- test/e2e/app-dir/next-image/app/page.js | 7 ++++ .../next-image/next-image-proxy.test.ts | 35 +++++++++++++------ test/e2e/app-dir/next-image/next.config.js | 6 +++- 3 files changed, 37 insertions(+), 11 deletions(-) diff --git a/test/e2e/app-dir/next-image/app/page.js b/test/e2e/app-dir/next-image/app/page.js index db37c8339182c..5402e817dd4c0 100644 --- a/test/e2e/app-dir/next-image/app/page.js +++ b/test/e2e/app-dir/next-image/app/page.js @@ -7,6 +7,13 @@ export default function Page() { <>

app-page

+ ) diff --git a/test/e2e/app-dir/next-image/next-image-proxy.test.ts b/test/e2e/app-dir/next-image/next-image-proxy.test.ts index cce1a91812e61..9286aeba371eb 100644 --- a/test/e2e/app-dir/next-image/next-image-proxy.test.ts +++ b/test/e2e/app-dir/next-image/next-image-proxy.test.ts @@ -73,19 +73,34 @@ createNextDescribe( }, }) - const image = browser.elementByCss('#app-page') - const src = await image.getAttribute('src') - - expect(src).toContain( + const local = await browser.elementByCss('#app-page').getAttribute('src') + expect(local).toContain( '/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Ftest.3f1a293b.png&w=828&q=90' ) - await check(() => { - // we expect 3 images to load and for none of them to have errors - if (fulfilledCount === 3 && failCount === 0) { - return 'success' - } - }, 'success') + const remote = await browser + .elementByCss('#remote-app-page') + .getAttribute('src') + expect(remote).toBe( + '/_next/image?url=https%3A%2F%2Fimage-optimization-test.vercel.app%2Ftest.jpg&w=640&q=90' + ) + + const expected = JSON.stringify({ fulfilledCount: 4, failCount: 0 }) + await check(() => JSON.stringify({ fulfilledCount, failCount }), expected) + }) + + it('should work with connection upgrade by removing it via filterReqHeaders()', async () => { + const opts = { headers: { connection: 'upgrade' } } + const res1 = await next.fetch( + '/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Ftest.3f1a293b.png&w=828&q=90', + opts + ) + expect(res1.status).toBe(200) + const res2 = await next.fetch( + '/_next/image?url=https%3A%2F%2Fimage-optimization-test.vercel.app%2Ftest.jpg&w=640&q=90', + opts + ) + expect(res2.status).toBe(200) }) afterAll(() => { diff --git a/test/e2e/app-dir/next-image/next.config.js b/test/e2e/app-dir/next-image/next.config.js index 4ba52ba2c8df6..dd7057b8a3534 100644 --- a/test/e2e/app-dir/next-image/next.config.js +++ b/test/e2e/app-dir/next-image/next.config.js @@ -1 +1,5 @@ -module.exports = {} +module.exports = { + images: { + remotePatterns: [{ hostname: 'image-optimization-test.vercel.app' }], + }, +} From 9fda481af18cbd3fe51fdaa02a162adebca93e7d Mon Sep 17 00:00:00 2001 From: Jimmy Lai Date: Mon, 16 Oct 2023 22:29:07 +0200 Subject: [PATCH 03/21] perf: fix server trace file logic (#56898) --- .../next/src/build/collect-build-traces.ts | 83 +++++++++++++++++-- 1 file changed, 74 insertions(+), 9 deletions(-) diff --git a/packages/next/src/build/collect-build-traces.ts b/packages/next/src/build/collect-build-traces.ts index c1fb4cc983672..48918afc66ed9 100644 --- a/packages/next/src/build/collect-build-traces.ts +++ b/packages/next/src/build/collect-build-traces.ts @@ -25,9 +25,44 @@ import { nodeFileTrace } from 'next/dist/compiled/@vercel/nft' import { normalizePagePath } from '../shared/lib/page-path/normalize-page-path' import { normalizeAppPath } from '../shared/lib/router/utils/app-paths' import isError from '../lib/is-error' +import type { NodeFileTraceReasons } from '@vercel/nft' const debug = debugOriginal('next:build:build-traces') +function shouldIgnore( + file: string, + serverIgnoreFn: (file: string) => boolean, + reasons: NodeFileTraceReasons, + cachedIgnoreFiles: Map +) { + if (cachedIgnoreFiles.has(file)) { + return cachedIgnoreFiles.get(file) + } + + if (serverIgnoreFn(file)) { + cachedIgnoreFiles.set(file, true) + return true + } + + const reason = reasons.get(file) + if (!reason || reason.parents.size === 0 || reason.type.includes('initial')) { + cachedIgnoreFiles.set(file, false) + return false + } + + if ( + [...reason.parents.values()].every((parent) => + shouldIgnore(parent, serverIgnoreFn, reasons, cachedIgnoreFiles) + ) + ) { + cachedIgnoreFiles.set(file, true) + return true + } + + cachedIgnoreFiles.set(file, false) + return false +} + export async function collectBuildTraces({ dir, config, @@ -237,6 +272,8 @@ export async function collectBuildTraces({ const serverIgnores = [ '**/*.d.ts', '**/*.map', + '**/next/dist/compiled/next-server/**/*.dev.js', + '**/node_modules/react{,-dom,-dom-server-turbopack}/**/*.development.js', isStandalone ? null : '**/next/dist/compiled/jest-worker/**/*', '**/next/dist/compiled/webpack/(bundle4|bundle5).js', '**/node_modules/webpack5/**/*', @@ -264,15 +301,25 @@ export async function collectBuildTraces({ ...(config.experimental.outputFileTracingIgnores || []), ].filter(nonNullable) - const serverIgnoreFn = (pathname: string) => { + const minimalServerIgnores = [ + ...serverIgnores, + '**/next/dist/compiled/edge-runtime/**/*', + '**/next/dist/server/web/sandbox/**/*', + ] + + const serverIgnoreFn = (minimal: boolean) => (pathname: string) => { if (path.isAbsolute(pathname) && !pathname.startsWith(root)) { return true } - return isMatch(pathname, serverIgnores, { - contains: true, - dot: true, - }) + return isMatch( + pathname, + minimal ? minimalServerIgnores : serverIgnores, + { + contains: true, + dot: true, + } + ) } const traceContext = path.join(nextServerEntry, '..', '..') const serverTracedFiles = new Set() @@ -324,7 +371,11 @@ export async function collectBuildTraces({ [minimalServerTracedFiles, minimalFiles], ] as [Set, string[]][]) { for (const file of files) { - if (!serverIgnoreFn(path.join(traceContext, file))) { + if ( + !serverIgnoreFn(set === minimalServerTracedFiles)( + path.join(traceContext, file) + ) + ) { addToTracedFiles(traceContext, file, set) } } @@ -386,7 +437,10 @@ export async function collectBuildTraces({ for (const file of result.esmFileList) { fileList.add(file) } + const parentFilesMap = getFilesMapFromReasons(fileList, reasons) + const cachedIgnoreFiles = new Map() + const cachedIgnoreFilesMinimal = new Map() for (const [entries, tracedFiles] of [ [serverEntries, serverTracedFiles], @@ -401,7 +455,16 @@ export async function collectBuildTraces({ for (const curFile of curFiles || []) { const filePath = path.join(outputFileTracingRoot, curFile) - if (!serverIgnoreFn(filePath)) { + if ( + !shouldIgnore( + curFile, + serverIgnoreFn(tracedFiles === minimalServerTracedFiles), + reasons, + tracedFiles === minimalServerTracedFiles + ? cachedIgnoreFilesMinimal + : cachedIgnoreFiles + ) + ) { tracedFiles.add( path.relative(distDir, filePath).replace(/\\/g, '/') ) @@ -493,8 +556,10 @@ export async function collectBuildTraces({ for (const item of await fs.readdir(contextDir)) { const itemPath = path.relative(root, path.join(contextDir, item)) - addToTracedFiles(root, itemPath, serverTracedFiles) - addToTracedFiles(root, itemPath, minimalServerTracedFiles) + if (!serverIgnoreFn(false)(itemPath)) { + addToTracedFiles(root, itemPath, serverTracedFiles) + addToTracedFiles(root, itemPath, minimalServerTracedFiles) + } } addToTracedFiles(root, relativeModulePath, serverTracedFiles) addToTracedFiles(root, relativeModulePath, minimalServerTracedFiles) From 1ff7f078752b7d298aad3063c2fc9e1120a86422 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20Orb=C3=A1n?= Date: Mon, 16 Oct 2023 23:41:38 +0200 Subject: [PATCH 04/21] feat: drop Node.js 16 (#56896) ### What? BREAKING CHANGE: Bump the minimum required Node.js version. ### Why? Node.js 16 has reached end-of-life in September. Bumped to `18.18.2` since it contained some security-related patches: https://nodejs.org/en/blog/vulnerability/october-2023-security-releases ### How? Bumped `engines` where needed, upgraded the workflows. This will allow us to remove quite a few polyfills, I'll open separate PRs for those. --- .github/actions/needs-triage/action.yaml | 2 +- .github/actions/next-stats-action/Dockerfile | 2 +- .github/actions/next-stats-action/package.json | 2 +- .github/workflows/build_and_deploy.yml | 3 +-- .github/workflows/build_and_test.yml | 7 +++---- .github/workflows/build_reusable.yml | 3 +-- .github/workflows/code_freeze.yml | 3 +-- .github/workflows/pull_request_stats.yml | 3 +-- .github/workflows/test_e2e_deploy.yml | 3 +-- .github/workflows/test_examples.yml | 4 ++-- .github/workflows/trigger_release.yml | 3 +-- .github/workflows/update_fonts_data.yml | 2 +- azure-pipelines.yml | 10 +++++----- docs/04-architecture/supported-browsers.mdx | 4 ---- package.json | 2 +- packages/create-next-app/package.json | 2 +- packages/next/package.json | 2 +- packages/next/src/bin/next.ts | 16 ---------------- test/.stats-app/package.json | 2 +- .../app-action-progressive-enhancement.test.ts | 4 ++-- test/e2e/app-dir/actions/app-action.test.ts | 2 +- .../index.test.ts | 18 +++++++----------- 22 files changed, 34 insertions(+), 65 deletions(-) diff --git a/.github/actions/needs-triage/action.yaml b/.github/actions/needs-triage/action.yaml index 41bac297eb8d0..e32b61a897d95 100644 --- a/.github/actions/needs-triage/action.yaml +++ b/.github/actions/needs-triage/action.yaml @@ -2,5 +2,5 @@ name: 'Issue auto label' description: 'vercel/next.js specific auto-labeling action' author: 'Next.js team' runs: - using: 'node16' + using: 'node20' main: 'index.js' diff --git a/.github/actions/next-stats-action/Dockerfile b/.github/actions/next-stats-action/Dockerfile index c4cece13794ec..bf40f16aecf3e 100644 --- a/.github/actions/next-stats-action/Dockerfile +++ b/.github/actions/next-stats-action/Dockerfile @@ -9,7 +9,7 @@ RUN apt install unzip wget curl nano htop screen build-essential pkg-config libs RUN ln $(which python3) /usr/bin/python -RUN curl -sfLS https://install-node.vercel.app/v18 | bash -s -- -f +RUN curl -sfLS https://install-node.vercel.app/v18.18.2 | bash -s -- -f RUN corepack enable WORKDIR /next-stats diff --git a/.github/actions/next-stats-action/package.json b/.github/actions/next-stats-action/package.json index d5e4c5384aba5..e70b389294359 100644 --- a/.github/actions/next-stats-action/package.json +++ b/.github/actions/next-stats-action/package.json @@ -18,7 +18,7 @@ "typescript": "5.1.6" }, "engines": { - "node": ">=16.14.0", + "node": ">=18.18.2", "pnpm": "8.9.0" }, "packageManager": "pnpm@8.9.0" diff --git a/.github/workflows/build_and_deploy.yml b/.github/workflows/build_and_deploy.yml index 0547c39f95d7f..599ba653c36c1 100644 --- a/.github/workflows/build_and_deploy.yml +++ b/.github/workflows/build_and_deploy.yml @@ -8,8 +8,7 @@ on: env: NAPI_CLI_VERSION: 2.16.2 TURBO_VERSION: 1.10.9 - NODE_MAINTENANCE_VERSION: 16 - NODE_LTS_VERSION: 18 + NODE_LTS_VERSION: 20 CARGO_PROFILE_RELEASE_LTO: 'true' TURBO_TEAM: 'vercel' TURBO_REMOTE_ONLY: 'true' diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 1f4d50d639ed3..cbe0673cac917 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -9,8 +9,7 @@ on: env: NAPI_CLI_VERSION: 2.14.7 TURBO_VERSION: 1.10.9 - NODE_MAINTENANCE_VERSION: 16 - NODE_LTS_VERSION: 18 + NODE_LTS_VERSION: 20 TEST_CONCURRENCY: 8 # disable backtrace for test snapshots RUST_BACKTRACE: 0 @@ -147,7 +146,7 @@ jobs: group: [1, 2, 3, 4, 5] uses: ./.github/workflows/build_reusable.yml with: - nodeVersion: 16 + nodeVersion: 18.18.2 skipForDocsOnly: 'yes' afterBuild: RUST_BACKTRACE=0 NEXT_EXTERNAL_TESTS_FILTERS="$(pwd)/test/turbopack-tests-manifest.json" TURBOPACK=1 node run-tests.js --timings -g ${{ matrix.group }}/5 -c ${TEST_CONCURRENCY} --type integration secrets: inherit @@ -212,7 +211,7 @@ jobs: uses: ./.github/workflows/build_reusable.yml with: - nodeVersion: 16 + nodeVersion: 18.18.2 skipForDocsOnly: 'yes' afterBuild: node run-tests.js --timings -g ${{ matrix.group }}/12 -c ${TEST_CONCURRENCY} --type integration secrets: inherit diff --git a/.github/workflows/build_reusable.yml b/.github/workflows/build_reusable.yml index be5bc2afa1e45..849580725961a 100644 --- a/.github/workflows/build_reusable.yml +++ b/.github/workflows/build_reusable.yml @@ -57,8 +57,7 @@ on: env: NAPI_CLI_VERSION: 2.14.7 TURBO_VERSION: 1.10.9 - NODE_MAINTENANCE_VERSION: 16 - NODE_LTS_VERSION: 18 + NODE_LTS_VERSION: 20 TEST_CONCURRENCY: 8 # disable backtrace for test snapshots RUST_BACKTRACE: 0 diff --git a/.github/workflows/code_freeze.yml b/.github/workflows/code_freeze.yml index 3c4c8b23f6bf4..e7813a5b1868e 100644 --- a/.github/workflows/code_freeze.yml +++ b/.github/workflows/code_freeze.yml @@ -18,8 +18,7 @@ name: Code Freeze env: NAPI_CLI_VERSION: 2.14.7 TURBO_VERSION: 1.10.9 - NODE_MAINTENANCE_VERSION: 16 - NODE_LTS_VERSION: 18 + NODE_LTS_VERSION: 20 jobs: start: diff --git a/.github/workflows/pull_request_stats.yml b/.github/workflows/pull_request_stats.yml index a4e60b6cfac11..c88e5a76ad256 100644 --- a/.github/workflows/pull_request_stats.yml +++ b/.github/workflows/pull_request_stats.yml @@ -7,8 +7,7 @@ name: Generate Pull Request Stats env: NAPI_CLI_VERSION: 2.14.7 TURBO_VERSION: 1.10.9 - NODE_MAINTENANCE_VERSION: 16 - NODE_LTS_VERSION: 18 + NODE_LTS_VERSION: 20 TEST_CONCURRENCY: 6 TURBO_TEAM: 'vercel' diff --git a/.github/workflows/test_e2e_deploy.yml b/.github/workflows/test_e2e_deploy.yml index 91862bb3b1e50..8046bfd136d41 100644 --- a/.github/workflows/test_e2e_deploy.yml +++ b/.github/workflows/test_e2e_deploy.yml @@ -16,8 +16,7 @@ jobs: DATADOG_API_KEY: ${{ secrets.DATA_DOG_API_KEY }} NAPI_CLI_VERSION: 2.16.2 TURBO_VERSION: 1.10.9 - NODE_MAINTENANCE_VERSION: 16 - NODE_LTS_VERSION: 18 + NODE_LTS_VERSION: 20 CARGO_PROFILE_RELEASE_LTO: 'true' TURBO_TEAM: 'vercel' TURBO_REMOTE_ONLY: 'true' diff --git a/.github/workflows/test_examples.yml b/.github/workflows/test_examples.yml index 11518dd209b22..be97239a4296c 100644 --- a/.github/workflows/test_examples.yml +++ b/.github/workflows/test_examples.yml @@ -25,7 +25,7 @@ jobs: strategy: fail-fast: false matrix: - node: [16, 18] + node: [18, 20] steps: - uses: actions/checkout@v3 with: @@ -37,7 +37,7 @@ jobs: - name: Setup node uses: actions/setup-node@v3 with: - node-version: 16 + node-version: 18 check-latest: true - run: corepack enable diff --git a/.github/workflows/trigger_release.yml b/.github/workflows/trigger_release.yml index 6faec5b1c37ea..cac8403d282a7 100644 --- a/.github/workflows/trigger_release.yml +++ b/.github/workflows/trigger_release.yml @@ -30,8 +30,7 @@ name: Trigger Release env: NAPI_CLI_VERSION: 2.14.7 TURBO_VERSION: 1.10.9 - NODE_MAINTENANCE_VERSION: 16 - NODE_LTS_VERSION: 18 + NODE_LTS_VERSION: 20 jobs: start: diff --git a/.github/workflows/update_fonts_data.yml b/.github/workflows/update_fonts_data.yml index 18b53609aa77c..c47e205bf75c9 100644 --- a/.github/workflows/update_fonts_data.yml +++ b/.github/workflows/update_fonts_data.yml @@ -8,7 +8,7 @@ on: workflow_dispatch: env: - NODE_LTS_VERSION: 18 + NODE_LTS_VERSION: 20 jobs: create-pull-request: diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 21603e2d97239..1b5a1d5f9624e 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -34,7 +34,7 @@ pr: variables: PNPM_CACHE_FOLDER: $(Pipeline.Workspace)/.pnpm-store NEXT_TELEMETRY_DISABLED: '1' - node_16_version: ^16.14.0 + node_version: ^18.18.2 stages: - stage: Test @@ -45,7 +45,7 @@ stages: steps: - task: NodeTool@0 inputs: - versionSpec: $(node_16_version) + versionSpec: $(node_version) displayName: 'Install Node.js' - bash: | @@ -84,7 +84,7 @@ stages: - task: NodeTool@0 inputs: - versionSpec: $(node_16_version) + versionSpec: $(node_version) displayName: 'Install Node.js' - bash: | @@ -117,7 +117,7 @@ stages: steps: - task: NodeTool@0 inputs: - versionSpec: $(node_16_version) + versionSpec: $(node_version) displayName: 'Install Node.js' - bash: | @@ -154,7 +154,7 @@ stages: steps: - task: NodeTool@0 inputs: - versionSpec: $(node_16_version) + versionSpec: $(node_version) displayName: 'Install Node.js' - bash: | diff --git a/docs/04-architecture/supported-browsers.mdx b/docs/04-architecture/supported-browsers.mdx index 1d5f7eb53d49d..1ad6841388ffe 100644 --- a/docs/04-architecture/supported-browsers.mdx +++ b/docs/04-architecture/supported-browsers.mdx @@ -57,10 +57,6 @@ Next.js allows you to use the latest JavaScript features out of the box. In addi - [Class Fields](https://github.com/tc39/proposal-class-fields) and [Static Properties](https://github.com/tc39/proposal-static-class-features) (part of stage 3 proposal) - and more! -### Server-Side Polyfills - -In addition to `fetch()` on the client-side, Next.js polyfills `fetch()` in the Node.js environment where it's not yet available. It uses `undici`, the same implementation that Node.js itself uses. You can use `fetch()` in your server code (such as `getStaticProps`/`getServerSideProps`) without using polyfills such as `isomorphic-unfetch` or `node-fetch`. - ### TypeScript Features Next.js has built-in TypeScript support. [Learn more here](/docs/pages/building-your-application/configuring/typescript). diff --git a/package.json b/package.json index 308ea40e9d7f4..3e85a88c003f2 100644 --- a/package.json +++ b/package.json @@ -249,7 +249,7 @@ "@types/react-dom": "18.2.4" }, "engines": { - "node": ">=16.14.0", + "node": ">=18.18.2", "pnpm": "8.9.0" }, "packageManager": "pnpm@8.9.0" diff --git a/packages/create-next-app/package.json b/packages/create-next-app/package.json index 3e4f08875ee1b..e55debc859eb4 100644 --- a/packages/create-next-app/package.json +++ b/packages/create-next-app/package.json @@ -52,6 +52,6 @@ "validate-npm-package-name": "3.0.0" }, "engines": { - "node": ">=16.14.0" + "node": ">=18.18.2" } } diff --git a/packages/next/package.json b/packages/next/package.json index 667f7734541cf..9e4765bee3637 100644 --- a/packages/next/package.json +++ b/packages/next/package.json @@ -316,6 +316,6 @@ "zod": "3.22.3" }, "engines": { - "node": ">=16.14.0" + "node": ">=18.18.2" } } diff --git a/packages/next/src/bin/next.ts b/packages/next/src/bin/next.ts index 2bde7eb71a911..9f84b7d1774e3 100755 --- a/packages/next/src/bin/next.ts +++ b/packages/next/src/bin/next.ts @@ -94,22 +94,6 @@ if (process.env.NODE_ENV) { ;(process.env as any).NODE_ENV = process.env.NODE_ENV || defaultEnv ;(process.env as any).NEXT_RUNTIME = 'nodejs' -// x-ref: https://github.com/vercel/next.js/pull/34688#issuecomment-1047994505 -if (process.versions.pnp === '3') { - const nodeVersionParts = process.versions.node - .split('.') - .map((v) => Number(v)) - - if ( - nodeVersionParts[0] < 16 || - (nodeVersionParts[0] === 16 && nodeVersionParts[1] < 14) - ) { - log.warn( - 'Node.js 16.14+ is required for Yarn PnP 3.20+. More info: https://github.com/vercel/next.js/pull/34688#issuecomment-1047994505' - ) - } -} - // Make sure commands gracefully respect termination signals (e.g. from Docker) // Allow the graceful termination to be manually configurable if (!process.env.NEXT_MANUAL_SIG_HANDLE && command !== 'dev') { diff --git a/test/.stats-app/package.json b/test/.stats-app/package.json index ffb2a82e51e95..ba87edd44c8f1 100644 --- a/test/.stats-app/package.json +++ b/test/.stats-app/package.json @@ -8,7 +8,7 @@ "react-dom": "latest" }, "engines": { - "node": ">=16.14.0", + "node": ">=18.18.2", "pnpm": "8.9.0" }, "packageManager": "pnpm@8.9.0" diff --git a/test/e2e/app-dir/actions/app-action-progressive-enhancement.test.ts b/test/e2e/app-dir/actions/app-action-progressive-enhancement.test.ts index 65f47467b28ff..13951b3448006 100644 --- a/test/e2e/app-dir/actions/app-action-progressive-enhancement.test.ts +++ b/test/e2e/app-dir/actions/app-action-progressive-enhancement.test.ts @@ -24,7 +24,7 @@ createNextDescribe( await check(() => { return browser.eval('window.location.pathname + window.location.search') - }, '/header?name=test&constructor=FormData&hidden-info=hi') + }, '/header?name=test&constructor=_FormData&hidden-info=hi') }) it('should support actions from client without JS', async () => { @@ -39,7 +39,7 @@ createNextDescribe( await check(() => { return browser.eval('window.location.pathname + window.location.search') - }, '/header?name=test&constructor=FormData&hidden-info=hi') + }, '/header?name=test&constructor=_FormData&hidden-info=hi') }) } ) diff --git a/test/e2e/app-dir/actions/app-action.test.ts b/test/e2e/app-dir/actions/app-action.test.ts index 6a6865985e88f..7d05879d1877d 100644 --- a/test/e2e/app-dir/actions/app-action.test.ts +++ b/test/e2e/app-dir/actions/app-action.test.ts @@ -134,7 +134,7 @@ createNextDescribe( await check(() => { return browser.eval('window.location.pathname + window.location.search') - }, '/header?name=test&constructor=FormData&hidden-info=hi') + }, '/header?name=test&constructor=_FormData&hidden-info=hi') }) it('should support .bind', async () => { diff --git a/test/e2e/edge-compiler-can-import-blob-assets/index.test.ts b/test/e2e/edge-compiler-can-import-blob-assets/index.test.ts index ede2ce1606c94..e90dbd4c73897 100644 --- a/test/e2e/edge-compiler-can-import-blob-assets/index.test.ts +++ b/test/e2e/edge-compiler-can-import-blob-assets/index.test.ts @@ -5,7 +5,10 @@ import path from 'path' import { promises as fs } from 'fs' import { readJson } from 'fs-extra' -describe('Edge Compiler can import asset assets', () => { +// TODO: `node-fetch` hangs on some of these tests in Node.js. +// Re-enable when `node-fetch` is dropped. +// See: https://github.com/vercel/next.js/pull/55112 +describe.skip('Edge Compiler can import asset assets', () => { let next: NextInstance // TODO: remove after this is supported for deploy @@ -29,16 +32,9 @@ describe('Edge Compiler can import asset assets', () => { }) it('allows to fetch a remote URL with a path and basename', async () => { - const response = await fetchViaHTTP( - next.url, - '/api/edge', - { - handler: 'remote-with-base', - }, - { - compress: true, - } - ) + const response = await fetchViaHTTP(next.url, '/api/edge', { + handler: 'remote-with-base', + }) expect(await response.text()).toContain('Example Domain') }) From e7fc6f370887c7747fc1a621de268c717fde7b87 Mon Sep 17 00:00:00 2001 From: Zack Tanner Date: Mon, 16 Oct 2023 15:00:02 -0700 Subject: [PATCH 05/21] ensure kodiak is re-added to apps list after code-freeze action (#56907) ensures that after the code-freeze action, Kodiak is re-added to the restrictions list [slack x-ref](https://vercel.slack.com/archives/C04DUD7EB1B/p1697491473466249) --- scripts/code-freeze.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/code-freeze.js b/scripts/code-freeze.js index aa6bd7b343bd5..1b0faf3a3d984 100644 --- a/scripts/code-freeze.js +++ b/scripts/code-freeze.js @@ -69,7 +69,7 @@ async function getCurrentRules() { restrictions: { users: data.restrictions.users?.map((user) => user.login) || [], teams: data.restrictions.teams?.map((team) => team.slug) || [], - apps: [], + apps: data.restrictions.apps?.map((app) => app.slug) || [], }, } } From 3c7d15b992aa713fa1a0da45eef5c71176836797 Mon Sep 17 00:00:00 2001 From: vercel-release-bot Date: Mon, 16 Oct 2023 22:04:56 +0000 Subject: [PATCH 06/21] v13.5.6-canary.0 --- lerna.json | 2 +- packages/create-next-app/package.json | 2 +- packages/eslint-config-next/package.json | 4 ++-- packages/eslint-plugin-next/package.json | 2 +- packages/font/package.json | 2 +- packages/next-bundle-analyzer/package.json | 2 +- packages/next-codemod/package.json | 2 +- packages/next-env/package.json | 2 +- packages/next-mdx/package.json | 2 +- packages/next-plugin-storybook/package.json | 2 +- packages/next-polyfill-module/package.json | 2 +- packages/next-polyfill-nomodule/package.json | 2 +- packages/next-swc/package.json | 2 +- packages/next/package.json | 14 +++++++------- packages/react-dev-overlay/package.json | 2 +- packages/react-refresh-utils/package.json | 2 +- packages/third-parties/package.json | 4 ++-- pnpm-lock.yaml | 16 ++++++++-------- 18 files changed, 33 insertions(+), 33 deletions(-) diff --git a/lerna.json b/lerna.json index 9d87d813db8c9..4c426bafdf61e 100644 --- a/lerna.json +++ b/lerna.json @@ -16,5 +16,5 @@ "registry": "https://registry.npmjs.org/" } }, - "version": "13.5.5" + "version": "13.5.6-canary.0" } diff --git a/packages/create-next-app/package.json b/packages/create-next-app/package.json index e55debc859eb4..add5a8dcf134e 100644 --- a/packages/create-next-app/package.json +++ b/packages/create-next-app/package.json @@ -1,6 +1,6 @@ { "name": "create-next-app", - "version": "13.5.5", + "version": "13.5.6-canary.0", "keywords": [ "react", "next", diff --git a/packages/eslint-config-next/package.json b/packages/eslint-config-next/package.json index dac86a43dfb3c..e8851baba2d99 100644 --- a/packages/eslint-config-next/package.json +++ b/packages/eslint-config-next/package.json @@ -1,6 +1,6 @@ { "name": "eslint-config-next", - "version": "13.5.5", + "version": "13.5.6-canary.0", "description": "ESLint configuration used by Next.js.", "main": "index.js", "license": "MIT", @@ -10,7 +10,7 @@ }, "homepage": "https://nextjs.org/docs/app/building-your-application/configuring/eslint#eslint-config", "dependencies": { - "@next/eslint-plugin-next": "13.5.5", + "@next/eslint-plugin-next": "13.5.6-canary.0", "@rushstack/eslint-patch": "^1.3.3", "@typescript-eslint/parser": "^5.4.2 || ^6.0.0", "eslint-import-resolver-node": "^0.3.6", diff --git a/packages/eslint-plugin-next/package.json b/packages/eslint-plugin-next/package.json index 6ae848a1df65a..bf3f6706e66f1 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": "13.5.5", + "version": "13.5.6-canary.0", "description": "ESLint plugin for Next.js.", "main": "dist/index.js", "license": "MIT", diff --git a/packages/font/package.json b/packages/font/package.json index e8daf9b46893d..6e48e8cb8511b 100644 --- a/packages/font/package.json +++ b/packages/font/package.json @@ -1,6 +1,6 @@ { "name": "@next/font", - "version": "13.5.5", + "version": "13.5.6-canary.0", "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 7c961c69583e0..73a067767c7c7 100644 --- a/packages/next-bundle-analyzer/package.json +++ b/packages/next-bundle-analyzer/package.json @@ -1,6 +1,6 @@ { "name": "@next/bundle-analyzer", - "version": "13.5.5", + "version": "13.5.6-canary.0", "main": "index.js", "types": "index.d.ts", "license": "MIT", diff --git a/packages/next-codemod/package.json b/packages/next-codemod/package.json index e0c1edda19e57..1682e371de6ce 100644 --- a/packages/next-codemod/package.json +++ b/packages/next-codemod/package.json @@ -1,6 +1,6 @@ { "name": "@next/codemod", - "version": "13.5.5", + "version": "13.5.6-canary.0", "license": "MIT", "repository": { "type": "git", diff --git a/packages/next-env/package.json b/packages/next-env/package.json index eea98a1b94276..868e862350ebe 100644 --- a/packages/next-env/package.json +++ b/packages/next-env/package.json @@ -1,6 +1,6 @@ { "name": "@next/env", - "version": "13.5.5", + "version": "13.5.6-canary.0", "keywords": [ "react", "next", diff --git a/packages/next-mdx/package.json b/packages/next-mdx/package.json index c3821233412a8..78fd349096489 100644 --- a/packages/next-mdx/package.json +++ b/packages/next-mdx/package.json @@ -1,6 +1,6 @@ { "name": "@next/mdx", - "version": "13.5.5", + "version": "13.5.6-canary.0", "main": "index.js", "license": "MIT", "repository": { diff --git a/packages/next-plugin-storybook/package.json b/packages/next-plugin-storybook/package.json index c8c702d3d7c92..a7565be7c750a 100644 --- a/packages/next-plugin-storybook/package.json +++ b/packages/next-plugin-storybook/package.json @@ -1,6 +1,6 @@ { "name": "@next/plugin-storybook", - "version": "13.5.5", + "version": "13.5.6-canary.0", "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 106c3124c5825..b990414422f00 100644 --- a/packages/next-polyfill-module/package.json +++ b/packages/next-polyfill-module/package.json @@ -1,6 +1,6 @@ { "name": "@next/polyfill-module", - "version": "13.5.5", + "version": "13.5.6-canary.0", "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 0698bfaf3a49b..116a30e2b0475 100644 --- a/packages/next-polyfill-nomodule/package.json +++ b/packages/next-polyfill-nomodule/package.json @@ -1,6 +1,6 @@ { "name": "@next/polyfill-nomodule", - "version": "13.5.5", + "version": "13.5.6-canary.0", "description": "A polyfill for non-dead, nomodule browsers.", "main": "dist/polyfill-nomodule.js", "license": "MIT", diff --git a/packages/next-swc/package.json b/packages/next-swc/package.json index 8fc9bea0c8514..0d77fe6ca13c3 100644 --- a/packages/next-swc/package.json +++ b/packages/next-swc/package.json @@ -1,6 +1,6 @@ { "name": "@next/swc", - "version": "13.5.5", + "version": "13.5.6-canary.0", "private": true, "scripts": { "clean": "node ../../scripts/rm.mjs native", diff --git a/packages/next/package.json b/packages/next/package.json index 9e4765bee3637..51426d6b86d15 100644 --- a/packages/next/package.json +++ b/packages/next/package.json @@ -1,6 +1,6 @@ { "name": "next", - "version": "13.5.5", + "version": "13.5.6-canary.0", "description": "The React Framework", "main": "./dist/server/next.js", "license": "MIT", @@ -90,7 +90,7 @@ ] }, "dependencies": { - "@next/env": "13.5.5", + "@next/env": "13.5.6-canary.0", "@swc/helpers": "0.5.2", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001406", @@ -144,11 +144,11 @@ "@mswjs/interceptors": "0.23.0", "@napi-rs/cli": "2.16.2", "@napi-rs/triples": "1.1.0", - "@next/polyfill-module": "13.5.5", - "@next/polyfill-nomodule": "13.5.5", - "@next/react-dev-overlay": "13.5.5", - "@next/react-refresh-utils": "13.5.5", - "@next/swc": "13.5.5", + "@next/polyfill-module": "13.5.6-canary.0", + "@next/polyfill-nomodule": "13.5.6-canary.0", + "@next/react-dev-overlay": "13.5.6-canary.0", + "@next/react-refresh-utils": "13.5.6-canary.0", + "@next/swc": "13.5.6-canary.0", "@opentelemetry/api": "1.4.1", "@playwright/test": "^1.35.1", "@taskr/clear": "1.1.0", diff --git a/packages/react-dev-overlay/package.json b/packages/react-dev-overlay/package.json index 0fac3b45960d6..0bae613be84f8 100644 --- a/packages/react-dev-overlay/package.json +++ b/packages/react-dev-overlay/package.json @@ -1,6 +1,6 @@ { "name": "@next/react-dev-overlay", - "version": "13.5.5", + "version": "13.5.6-canary.0", "description": "A development-only overlay for developing React applications.", "repository": { "url": "vercel/next.js", diff --git a/packages/react-refresh-utils/package.json b/packages/react-refresh-utils/package.json index fc9d80c654267..61e8d36c28ade 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": "13.5.5", + "version": "13.5.6-canary.0", "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 bcf86ea0311b1..b64446375e794 100644 --- a/packages/third-parties/package.json +++ b/packages/third-parties/package.json @@ -1,6 +1,6 @@ { "name": "@next/third-parties", - "version": "13.5.5", + "version": "13.5.6-canary.0", "private": true, "repository": { "url": "vercel/next.js", @@ -23,7 +23,7 @@ "third-party-capital": "1.0.20" }, "devDependencies": { - "next": "13.5.5", + "next": "13.5.6-canary.0", "outdent": "0.8.0", "prettier": "2.5.1" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bacd30ce38784..b9110fad7717e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -735,7 +735,7 @@ importers: packages/eslint-config-next: dependencies: '@next/eslint-plugin-next': - specifier: 13.5.5 + specifier: 13.5.6-canary.0 version: link:../eslint-plugin-next '@rushstack/eslint-patch': specifier: ^1.3.3 @@ -796,7 +796,7 @@ importers: packages/next: dependencies: '@next/env': - specifier: 13.5.5 + specifier: 13.5.6-canary.0 version: link:../next-env '@swc/helpers': specifier: 0.5.2 @@ -920,19 +920,19 @@ importers: specifier: 1.1.0 version: 1.1.0 '@next/polyfill-module': - specifier: 13.5.5 + specifier: 13.5.6-canary.0 version: link:../next-polyfill-module '@next/polyfill-nomodule': - specifier: 13.5.5 + specifier: 13.5.6-canary.0 version: link:../next-polyfill-nomodule '@next/react-dev-overlay': - specifier: 13.5.5 + specifier: 13.5.6-canary.0 version: link:../react-dev-overlay '@next/react-refresh-utils': - specifier: 13.5.5 + specifier: 13.5.6-canary.0 version: link:../react-refresh-utils '@next/swc': - specifier: 13.5.5 + specifier: 13.5.6-canary.0 version: link:../next-swc '@opentelemetry/api': specifier: 1.4.1 @@ -1586,7 +1586,7 @@ importers: version: 1.0.20 devDependencies: next: - specifier: 13.5.5 + specifier: 13.5.6-canary.0 version: link:../next outdent: specifier: 0.8.0 From 26d0bf27fb55543c17f236585aaee45b0185bd42 Mon Sep 17 00:00:00 2001 From: Dmitriy Glazkov Date: Tue, 17 Oct 2023 02:21:44 +0400 Subject: [PATCH 07/21] Update 05-mdx.mdx . Fix key of the prop (#56883) Fix key of the prop Also the same key prop we can find in `next-mdx-remote` [example with getStaticProps](https://github.com/hashicorp/next-mdx-remote#typescript) --- .../01-building-your-application/07-configuring/05-mdx.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/02-app/01-building-your-application/07-configuring/05-mdx.mdx b/docs/02-app/01-building-your-application/07-configuring/05-mdx.mdx index 6b16ba73d3514..f758c7c7912a3 100644 --- a/docs/02-app/01-building-your-application/07-configuring/05-mdx.mdx +++ b/docs/02-app/01-building-your-application/07-configuring/05-mdx.mdx @@ -185,7 +185,7 @@ export async function getStaticProps() { const res = await fetch('https:...') const mdxText = await res.text() const mdxSource = await serialize(mdxText) - return { props: { source: mdxSource } } + return { props: { mdxSource } } } ``` @@ -202,7 +202,7 @@ export async function getStaticProps() { const res = await fetch('https:...') const mdxText = await res.text() const mdxSource = await serialize(mdxText) - return { props: { source: mdxSource } } + return { props: { mdxSource } } } ``` From 0a80017d038e7de7ac16894d4ebc8d64cf7988eb Mon Sep 17 00:00:00 2001 From: Josh Story Date: Mon, 16 Oct 2023 15:46:10 -0700 Subject: [PATCH 08/21] Update React from d900fadbf to 09fbee89d. Removes server context and experimental prefix for server action APIs (#56809) The latest React canary builds have a few changes that need to be adopted for compatability. 1. the `useFormState` and `useFormStatus` hooks in `react-dom` and the `formData` opiont in `react-dom/server` are no longer prefixed with `experimental_` 2. server content (an undocumented React feature) has been removed. Next only had trivial intenral use of this API and did not expose a coherent feature to Next users (no ability to seed context on refetches). It is still possible that some users used the React server context APIs which is why this should go into Next 14. ### React upstream changes - https://github.com/facebook/react/pull/27513 - https://github.com/facebook/react/pull/27514 - https://github.com/facebook/react/pull/27511 - https://github.com/facebook/react/pull/27508 - https://github.com/facebook/react/pull/27502 - https://github.com/facebook/react/pull/27474 - https://github.com/facebook/react/pull/26789 - https://github.com/facebook/react/pull/27500 - https://github.com/facebook/react/pull/27488 - https://github.com/facebook/react/pull/27458 - https://github.com/facebook/react/pull/27471 - https://github.com/facebook/react/pull/27470 - https://github.com/facebook/react/pull/27464 - https://github.com/facebook/react/pull/27456 - https://github.com/facebook/react/pull/27462 - https://github.com/facebook/react/pull/27461 - https://github.com/facebook/react/pull/27460 - https://github.com/facebook/react/pull/27459 - https://github.com/facebook/react/pull/27454 - https://github.com/facebook/react/pull/27457 - https://github.com/facebook/react/pull/27453 - https://github.com/facebook/react/pull/27401 - https://github.com/facebook/react/pull/27443 - https://github.com/facebook/react/pull/27445 - https://github.com/facebook/react/pull/27364 - https://github.com/facebook/react/pull/27440 - https://github.com/facebook/react/pull/27436 --------- Co-authored-by: Zack Tanner Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com> Co-authored-by: Jiachi Liu --- .../03-forms-and-mutations.mdx | 10 +- examples/next-forms/app/add-form.tsx | 2 +- examples/next-forms/app/delete-form.tsx | 3 +- examples/with-fauna/components/EntryForm.tsx | 5 +- package.json | 28 +- .../core/src/react_server_components.rs | 4 +- .../server-graph/react-dom-api/input.js | 5 +- .../server-graph/react-dom-api/output.js | 2 +- .../server-graph/react-dom-api/output.stderr | 12 +- .../react-dom-api/input.js | 5 +- .../react-dom-api/output.js | 2 +- packages/next/src/client/app-index.tsx | 2 +- ...t-dom-server-legacy.browser.development.js | 214 ++- ...om-server-legacy.browser.production.min.js | 273 ++-- ...eact-dom-server-legacy.node.development.js | 214 ++- ...t-dom-server-legacy.node.production.min.js | 297 ++-- ...t-dom-server-rendering-stub.development.js | 41 +- ...om-server-rendering-stub.production.min.js | 9 +- .../react-dom-server.browser.development.js | 218 ++- ...react-dom-server.browser.production.min.js | 331 ++-- .../cjs/react-dom-server.edge.development.js | 218 ++- .../react-dom-server.edge.production.min.js | 349 +++-- .../cjs/react-dom-server.node.development.js | 218 ++- .../react-dom-server.node.production.min.js | 335 ++-- .../react-dom-unstable_testing.development.js | 223 ++- ...act-dom-unstable_testing.production.min.js | 837 +++++----- .../cjs/react-dom.development.js | 223 ++- .../cjs/react-dom.production.min.js | 807 +++++----- .../cjs/react-dom.profiling.min.js | 845 +++++------ .../react-dom-experimental/package.json | 4 +- ...t-dom-server-legacy.browser.development.js | 583 +++++-- ...om-server-legacy.browser.production.min.js | 313 ++-- ...eact-dom-server-legacy.node.development.js | 583 +++++-- ...t-dom-server-legacy.node.production.min.js | 336 ++-- ...t-dom-server-rendering-stub.development.js | 68 +- ...om-server-rendering-stub.production.min.js | 15 +- .../react-dom-server.browser.development.js | 584 +++++-- ...react-dom-server.browser.production.min.js | 330 ++-- .../cjs/react-dom-server.edge.development.js | 584 +++++-- .../react-dom-server.edge.production.min.js | 353 +++-- .../cjs/react-dom-server.node.development.js | 499 ++++-- .../react-dom-server.node.production.min.js | 325 ++-- .../react-dom/cjs/react-dom.development.js | 1350 ++++++++++++++++- .../react-dom/cjs/react-dom.production.min.js | 798 +++++----- .../react-dom/cjs/react-dom.profiling.min.js | 840 +++++----- .../next/src/compiled/react-dom/package.json | 4 +- .../cjs/react.development.js | 102 +- .../cjs/react.production.min.js | 15 +- .../cjs/react.shared-subset.development.js | 173 ++- .../cjs/react.shared-subset.production.min.js | 45 +- ...om-turbopack-client.browser.development.js | 60 +- ...turbopack-client.browser.production.min.js | 38 +- ...r-dom-turbopack-client.edge.development.js | 60 +- ...om-turbopack-client.edge.production.min.js | 57 +- ...r-dom-turbopack-client.node.development.js | 60 +- ...om-turbopack-client.node.production.min.js | 53 +- ...opack-client.node.unbundled.development.js | 60 +- ...ck-client.node.unbundled.production.min.js | 51 +- ...om-turbopack-server.browser.development.js | 155 +- ...turbopack-server.browser.production.min.js | 117 +- ...r-dom-turbopack-server.edge.development.js | 155 +- ...om-turbopack-server.edge.production.min.js | 119 +- ...r-dom-turbopack-server.node.development.js | 155 +- ...om-turbopack-server.node.production.min.js | 127 +- ...opack-server.node.unbundled.development.js | 155 +- ...ck-server.node.unbundled.production.min.js | 121 +- .../package.json | 4 +- ...om-turbopack-client.browser.development.js | 60 +- ...turbopack-client.browser.production.min.js | 46 +- ...r-dom-turbopack-client.edge.development.js | 60 +- ...om-turbopack-client.edge.production.min.js | 49 +- ...r-dom-turbopack-client.node.development.js | 60 +- ...om-turbopack-client.node.production.min.js | 47 +- ...opack-client.node.unbundled.development.js | 60 +- ...ck-client.node.unbundled.production.min.js | 47 +- ...om-turbopack-server.browser.development.js | 71 +- ...turbopack-server.browser.production.min.js | 83 +- ...r-dom-turbopack-server.edge.development.js | 71 +- ...om-turbopack-server.edge.production.min.js | 87 +- ...r-dom-turbopack-server.node.development.js | 71 +- ...om-turbopack-server.node.production.min.js | 93 +- ...opack-server.node.unbundled.development.js | 71 +- ...ck-server.node.unbundled.production.min.js | 87 +- .../react-server-dom-turbopack/package.json | 4 +- ...-dom-webpack-client.browser.development.js | 60 +- ...m-webpack-client.browser.production.min.js | 40 +- ...ver-dom-webpack-client.edge.development.js | 60 +- ...-dom-webpack-client.edge.production.min.js | 57 +- ...ver-dom-webpack-client.node.development.js | 60 +- ...-dom-webpack-client.node.production.min.js | 53 +- ...bpack-client.node.unbundled.development.js | 60 +- ...ck-client.node.unbundled.production.min.js | 51 +- ...-dom-webpack-server.browser.development.js | 155 +- ...m-webpack-server.browser.production.min.js | 119 +- ...ver-dom-webpack-server.edge.development.js | 155 +- ...-dom-webpack-server.edge.production.min.js | 121 +- ...ver-dom-webpack-server.node.development.js | 155 +- ...-dom-webpack-server.node.production.min.js | 127 +- ...bpack-server.node.unbundled.development.js | 155 +- ...ck-server.node.unbundled.production.min.js | 121 +- .../package.json | 4 +- ...-dom-webpack-client.browser.development.js | 60 +- ...m-webpack-client.browser.production.min.js | 46 +- ...ver-dom-webpack-client.edge.development.js | 60 +- ...-dom-webpack-client.edge.production.min.js | 49 +- ...ver-dom-webpack-client.node.development.js | 60 +- ...-dom-webpack-client.node.production.min.js | 47 +- ...bpack-client.node.unbundled.development.js | 60 +- ...ck-client.node.unbundled.production.min.js | 47 +- ...-dom-webpack-server.browser.development.js | 71 +- ...m-webpack-server.browser.production.min.js | 87 +- ...ver-dom-webpack-server.edge.development.js | 71 +- ...-dom-webpack-server.edge.production.min.js | 89 +- ...ver-dom-webpack-server.node.development.js | 71 +- ...-dom-webpack-server.node.production.min.js | 95 +- ...bpack-server.node.unbundled.development.js | 71 +- ...ck-server.node.unbundled.production.min.js | 89 +- .../react-server-dom-webpack/package.json | 4 +- .../cjs/react-jsx-dev-runtime.development.js | 7 - .../cjs/react-jsx-runtime.development.js | 7 - .../compiled/react/cjs/react.development.js | 102 +- .../react/cjs/react.production.min.js | 39 +- .../cjs/react.shared-subset.development.js | 136 +- .../cjs/react.shared-subset.production.min.js | 30 +- packages/next/src/lib/metadata/metadata.tsx | 1 - .../next/src/server/app-render/app-render.tsx | 20 +- .../create-server-components-renderer.tsx | 5 - .../server/app-render/required-scripts.tsx | 2 +- .../walk-tree-with-flight-router-state.tsx | 1 - .../src/internal/components/ShadowPortal.tsx | 4 +- pnpm-lock.yaml | 172 +-- .../(foo)/product-category/[...slugs]/page.js | 2 +- .../app/client/form-state/page-2/page.js | 4 +- .../actions/app/client/form-state/page.js | 4 +- 134 files changed, 12013 insertions(+), 7403 deletions(-) diff --git a/docs/02-app/01-building-your-application/02-data-fetching/03-forms-and-mutations.mdx b/docs/02-app/01-building-your-application/02-data-fetching/03-forms-and-mutations.mdx index d52e1f1e83373..236b7e88200ee 100644 --- a/docs/02-app/01-building-your-application/02-data-fetching/03-forms-and-mutations.mdx +++ b/docs/02-app/01-building-your-application/02-data-fetching/03-forms-and-mutations.mdx @@ -377,7 +377,7 @@ For example, the following submit button: ```tsx filename="app/submit-button.tsx" switcher 'use client' -import { experimental_useFormStatus as useFormStatus } from 'react-dom' +import { useFormStatus } from 'react-dom' export function SubmitButton() { const { pending } = useFormStatus() @@ -393,7 +393,7 @@ export function SubmitButton() { ```jsx filename="app/submit-button.jsx" switcher 'use client' -import { experimental_useFormStatus as useFormStatus } from 'react-dom' +import { useFormStatus } from 'react-dom' export function SubmitButton() { const { pending } = useFormStatus() @@ -557,8 +557,7 @@ Then, from a Client Component, you can read this value and display an error mess ```tsx filename="app/add-form.tsx" switcher 'use client' -import { experimental_useFormState as useFormState } from 'react-dom' -import { experimental_useFormStatus as useFormStatus } from 'react-dom' +import { useFormState, useFormStatus } from 'react-dom' import { createTodo } from '@/app/actions' const initialState = { @@ -594,8 +593,7 @@ export function AddForm() { ```jsx filename="app/add-form.jsx" switcher 'use client' -import { experimental_useFormState as useFormState } from 'react-dom' -import { experimental_useFormStatus as useFormStatus } from 'react-dom' +import { useFormState, useFormStatus } from 'react-dom' import { createTodo } from '@/app/actions' const initialState = { diff --git a/examples/next-forms/app/add-form.tsx b/examples/next-forms/app/add-form.tsx index 8fb469731baf9..45725efe1f4dc 100644 --- a/examples/next-forms/app/add-form.tsx +++ b/examples/next-forms/app/add-form.tsx @@ -1,7 +1,7 @@ 'use client' import { experimental_useFormState as useFormState } from 'react-dom' -import { experimental_useFormStatus as useFormStatus } from 'react-dom' +import { useFormStatus } from 'react-dom' import { createTodo } from '@/app/actions' const initialState = { diff --git a/examples/next-forms/app/delete-form.tsx b/examples/next-forms/app/delete-form.tsx index f3901143b2e85..221b11f1a5442 100644 --- a/examples/next-forms/app/delete-form.tsx +++ b/examples/next-forms/app/delete-form.tsx @@ -1,7 +1,6 @@ 'use client' -import { experimental_useFormState as useFormState } from 'react-dom' -import { experimental_useFormStatus as useFormStatus } from 'react-dom' +import { useFormState, useFormStatus } from 'react-dom' import { deleteTodo } from '@/app/actions' const initialState = { diff --git a/examples/with-fauna/components/EntryForm.tsx b/examples/with-fauna/components/EntryForm.tsx index 71d8675905967..5f3cea173b20c 100644 --- a/examples/with-fauna/components/EntryForm.tsx +++ b/examples/with-fauna/components/EntryForm.tsx @@ -3,8 +3,7 @@ import cn from 'classnames' import { createEntryAction } from '@/actions/entry' // @ts-ignore -import { experimental_useFormState as useFormState } from 'react-dom' -import { experimental_useFormStatus as useFormStatus } from 'react-dom' +import { useFormState, useFormStatus } from 'react-dom' import LoadingSpinner from '@/components/LoadingSpinner' import SuccessMessage from '@/components/SuccessMessage' import ErrorMessage from '@/components/ErrorMessage' @@ -26,7 +25,7 @@ export default function EntryForm() { return ( <> -
+ =18.18.2", diff --git a/packages/next-swc/crates/core/src/react_server_components.rs b/packages/next-swc/crates/core/src/react_server_components.rs index 8d136e78b09d8..e383df5e4f4c5 100644 --- a/packages/next-swc/crates/core/src/react_server_components.rs +++ b/packages/next-swc/crates/core/src/react_server_components.rs @@ -612,8 +612,8 @@ pub fn server_components( JsWord::from("findDOMNode"), JsWord::from("flushSync"), JsWord::from("unstable_batchedUpdates"), - JsWord::from("experimental_useFormStatus"), - JsWord::from("experimental_useFormState"), + JsWord::from("useFormStatus"), + JsWord::from("useFormState"), ], invalid_server_react_apis: vec![ JsWord::from("Component"), diff --git a/packages/next-swc/crates/core/tests/errors/react-server-components/server-graph/react-dom-api/input.js b/packages/next-swc/crates/core/tests/errors/react-server-components/server-graph/react-dom-api/input.js index d29c808451c59..3b7a161c4b373 100644 --- a/packages/next-swc/crates/core/tests/errors/react-server-components/server-graph/react-dom-api/input.js +++ b/packages/next-swc/crates/core/tests/errors/react-server-components/server-graph/react-dom-api/input.js @@ -1,9 +1,6 @@ import { findDOMNode, flushSync, unstable_batchedUpdates } from 'react-dom' -import { - experimental_useFormStatus, - experimental_useFormState, -} from 'react-dom' +import { useFormStatus, useFormState } from 'react-dom' export default function () { return null diff --git a/packages/next-swc/crates/core/tests/errors/react-server-components/server-graph/react-dom-api/output.js b/packages/next-swc/crates/core/tests/errors/react-server-components/server-graph/react-dom-api/output.js index 8df6e6178d5de..742749a85ed92 100644 --- a/packages/next-swc/crates/core/tests/errors/react-server-components/server-graph/react-dom-api/output.js +++ b/packages/next-swc/crates/core/tests/errors/react-server-components/server-graph/react-dom-api/output.js @@ -1,5 +1,5 @@ import { findDOMNode, flushSync, unstable_batchedUpdates } from 'react-dom'; -import { experimental_useFormStatus, experimental_useFormState } from 'react-dom'; +import { useFormStatus, useFormState } from 'react-dom'; export default function() { return null; } diff --git a/packages/next-swc/crates/core/tests/errors/react-server-components/server-graph/react-dom-api/output.stderr b/packages/next-swc/crates/core/tests/errors/react-server-components/server-graph/react-dom-api/output.stderr index 786dd9f145dc8..7f4365f073eb7 100644 --- a/packages/next-swc/crates/core/tests/errors/react-server-components/server-graph/react-dom-api/output.stderr +++ b/packages/next-swc/crates/core/tests/errors/react-server-components/server-graph/react-dom-api/output.stderr @@ -17,18 +17,18 @@ : ^^^^^^^^^^^^^^^^^^^^^^^ `---- - x NEXT_RSC_ERR_REACT_API: experimental_useFormStatus + x NEXT_RSC_ERR_REACT_API: useFormStatus ,-[input.js:3:1] 3 | import { - 4 | experimental_useFormStatus, + 4 | useFormStatus, : ^^^^^^^^^^^^^^^^^^^^^^^^^^ - 5 | experimental_useFormState, + 5 | useFormState, `---- - x NEXT_RSC_ERR_REACT_API: experimental_useFormState + x NEXT_RSC_ERR_REACT_API: useFormState ,-[input.js:4:1] - 4 | experimental_useFormStatus, - 5 | experimental_useFormState, + 4 | useFormStatus, + 5 | useFormState, : ^^^^^^^^^^^^^^^^^^^^^^^^^ 6 | } from 'react-dom' `---- diff --git a/packages/next-swc/crates/core/tests/fixture/react-server-components/server-graph-no-checks/react-dom-api/input.js b/packages/next-swc/crates/core/tests/fixture/react-server-components/server-graph-no-checks/react-dom-api/input.js index d29c808451c59..3b7a161c4b373 100644 --- a/packages/next-swc/crates/core/tests/fixture/react-server-components/server-graph-no-checks/react-dom-api/input.js +++ b/packages/next-swc/crates/core/tests/fixture/react-server-components/server-graph-no-checks/react-dom-api/input.js @@ -1,9 +1,6 @@ import { findDOMNode, flushSync, unstable_batchedUpdates } from 'react-dom' -import { - experimental_useFormStatus, - experimental_useFormState, -} from 'react-dom' +import { useFormStatus, useFormState } from 'react-dom' export default function () { return null diff --git a/packages/next-swc/crates/core/tests/fixture/react-server-components/server-graph-no-checks/react-dom-api/output.js b/packages/next-swc/crates/core/tests/fixture/react-server-components/server-graph-no-checks/react-dom-api/output.js index 9621b75b305da..c8a9310228464 100644 --- a/packages/next-swc/crates/core/tests/fixture/react-server-components/server-graph-no-checks/react-dom-api/output.js +++ b/packages/next-swc/crates/core/tests/fixture/react-server-components/server-graph-no-checks/react-dom-api/output.js @@ -1,5 +1,5 @@ import { findDOMNode, flushSync, unstable_batchedUpdates } from 'react-dom'; -import { experimental_useFormStatus, experimental_useFormState } from 'react-dom'; +import { useFormStatus, useFormState } from 'react-dom'; export default function() { return null; diff --git a/packages/next/src/client/app-index.tsx b/packages/next/src/client/app-index.tsx index c4053df4e82be..43a57aa3551db 100644 --- a/packages/next/src/client/app-index.tsx +++ b/packages/next/src/client/app-index.tsx @@ -299,7 +299,7 @@ export function hydrate() { React.startTransition(() => (ReactDOMClient as any).hydrateRoot(appElement, reactEl, { ...options, - experimental_formState: initialFormStateData, + formState: initialFormStateData, }) ) } 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 d19392ed8d2cd..4c98eb4058596 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 @@ -17,7 +17,7 @@ if (process.env.NODE_ENV !== "production") { var React = require("next/dist/compiled/react-experimental"); var ReactDOM = require('react-dom'); -var ReactVersion = '18.3.0-experimental-d900fadbf-20230929'; +var ReactVersion = '18.3.0-experimental-09fbee89d-20231013'; var ReactSharedInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; @@ -3962,26 +3962,7 @@ function pushStartCustomElement(target, props, tag) { continue; } - if ((typeof propValue === 'function' || typeof propValue === 'object')) { - // It is normal to render functions and objects on custom elements when - // client rendering, but when server rendering the output isn't useful, - // so skip it. - continue; - } - - if (propValue === false) { - continue; - } - - if (propValue === true) { - propValue = ''; - } - - if (propKey === 'className') { - // className gets rendered as class on the client, so it should be - // rendered as class on the server. - propKey = 'class'; - } + var attributeName = propKey; switch (propKey) { case 'children': @@ -4001,9 +3982,28 @@ function pushStartCustomElement(target, props, tag) { // Ignored. These are built-in to React on the client. break; + case 'className': + { + // className gets rendered as class on the client, so it should be + // rendered as class on the server. + attributeName = 'class'; + } + + // intentional fallthrough + default: if (isAttributeNameSafe(propKey) && typeof propValue !== 'function' && typeof propValue !== 'symbol') { - target.push(attributeSeparator, stringToChunk(propKey), attributeAssign, stringToChunk(escapeTextForBrowser(propValue)), attributeEnd); + { + if (propValue === false) { + continue; + } else if (propValue === true) { + propValue = ''; + } else if (typeof propValue === 'object') { + continue; + } + } + + target.push(attributeSeparator, stringToChunk(attributeName), attributeAssign, stringToChunk(escapeTextForBrowser(propValue)), attributeEnd); } break; @@ -8196,9 +8196,12 @@ function useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot) { return getServerSnapshot(); } -function useDeferredValue(value) { +function useDeferredValue(value, initialValue) { resolveCurrentlyRenderingComponent(); - return value; + + { + return initialValue !== undefined ? initialValue : value; + } } function unsupportedStartTransition() { @@ -8983,11 +8986,7 @@ function replaySuspenseBoundary(request, task, keyPath, props, id, childNodes, c try { // We use the safe form because we don't handle suspending here. Only error handling. - if (typeof childSlots === 'number') { - resumeNode(request, task, childSlots, content, -1); - } else { - renderNode(request, task, content, -1); - } + renderNode(request, task, content, -1); if (task.replay.pendingTasks === 1 && task.replay.nodes.length > 0) { throw new Error("Couldn't find all resumable slots by key/index during replaying. " + "The tree doesn't match so React will fallback to client rendering."); @@ -9038,24 +9037,15 @@ function replaySuspenseBoundary(request, task, keyPath, props, id, childNodes, c task.keyPath = prevKeyPath; } - var fallbackKeyPath = [keyPath[0], 'Suspense Fallback', keyPath[2]]; - var suspendedFallbackTask; // We create suspended task for the fallback because we don't want to actually work + var fallbackKeyPath = [keyPath[0], 'Suspense Fallback', keyPath[2]]; // We create suspended task for the fallback because we don't want to actually work // on it yet in case we finish the main content, so we queue for later. - if (typeof fallbackSlots === 'number') { - // Resuming directly in the fallback. - var resumedSegment = createPendingSegment(request, 0, null, task.formatContext, false, false); - resumedSegment.id = fallbackSlots; - resumedSegment.parentFlushed = true; - suspendedFallbackTask = createRenderTask(request, null, fallback, -1, parentBoundary, resumedSegment, fallbackAbortSet, fallbackKeyPath, task.formatContext, task.legacyContext, task.context, task.treeContext); - } else { - var fallbackReplay = { - nodes: fallbackNodes, - slots: fallbackSlots, - pendingTasks: 0 - }; - suspendedFallbackTask = createReplayTask(request, null, fallbackReplay, fallback, -1, parentBoundary, fallbackAbortSet, fallbackKeyPath, task.formatContext, task.legacyContext, task.context, task.treeContext); - } + var fallbackReplay = { + nodes: fallbackNodes, + slots: fallbackSlots, + pendingTasks: 0 + }; + var suspendedFallbackTask = createReplayTask(request, null, fallbackReplay, fallback, -1, parentBoundary, fallbackAbortSet, fallbackKeyPath, task.formatContext, task.legacyContext, task.context, task.treeContext); { suspendedFallbackTask.componentStack = task.componentStack; @@ -9063,8 +9053,7 @@ function replaySuspenseBoundary(request, task, keyPath, props, id, childNodes, c // on preparing fallbacks if we don't have any more main content to task on. - request.pingedTasks.push(suspendedFallbackTask); // TODO: Should this be in the finally? - + request.pingedTasks.push(suspendedFallbackTask); popComponentStackInDEV(task); } @@ -9605,37 +9594,6 @@ function resumeNode(request, task, segmentId, node, childIndex) { } } -function resumeElement(request, task, keyPath, segmentId, prevThenableState, type, props, ref) { - var prevReplay = task.replay; - var blockedBoundary = task.blockedBoundary; - var resumedSegment = createPendingSegment(request, 0, null, task.formatContext, false, false); - resumedSegment.id = segmentId; - resumedSegment.parentFlushed = true; - - try { - // Convert the current ReplayTask to a RenderTask. - var renderTask = task; - renderTask.replay = null; - renderTask.blockedSegment = resumedSegment; - renderElement(request, task, keyPath, prevThenableState, type, props, ref); - resumedSegment.status = COMPLETED; - - if (blockedBoundary === null) { - request.completedRootSegment = resumedSegment; - } else { - queueCompletedSegment(blockedBoundary, resumedSegment); - - if (blockedBoundary.parentFlushed) { - request.partialBoundaries.push(blockedBoundary); - } - } - } finally { - // Restore to a ReplayTask. - task.replay = prevReplay; - task.blockedSegment = null; - } -} - function replayElement(request, task, keyPath, prevThenableState, name, keyOrIndex, childIndex, type, props, ref, replay) { // We're replaying. Find the path to follow. var replayNodes = replay.nodes; @@ -9646,17 +9604,18 @@ function replayElement(request, task, keyPath, prevThenableState, name, keyOrInd if (keyOrIndex !== node[1]) { continue; - } // Let's double check that the component name matches as a precaution. - - - if (name !== null && name !== node[0]) { - throw new Error('Expected to see a component of type "' + name + '" in this slot. ' + "The tree doesn't match so React will fallback to client rendering."); } if (node.length === 4) { // Matched a replayable path. + // Let's double check that the component name matches as a precaution. + if (name !== null && name !== node[0]) { + throw new Error('Expected the resume to render <' + node[0] + '> in this slot but instead it rendered <' + name + '>. ' + "The tree doesn't match so React will fallback to client rendering."); + } + var childNodes = node[2]; var childSlots = node[3]; + var currentNode = task.node; task.replay = { nodes: childNodes, slots: childSlots, @@ -9664,37 +9623,40 @@ function replayElement(request, task, keyPath, prevThenableState, name, keyOrInd }; try { - if (typeof childSlots === 'number') { - // Matched a resumable element. - resumeElement(request, task, keyPath, childSlots, prevThenableState, type, props, ref); - } else { - renderElement(request, task, keyPath, prevThenableState, type, props, ref); - } + renderElement(request, task, keyPath, prevThenableState, type, props, ref); if (task.replay.pendingTasks === 1 && task.replay.nodes.length > 0 // TODO check remaining slots ) { throw new Error("Couldn't find all resumable slots by key/index during replaying. " + "The tree doesn't match so React will fallback to client rendering."); } + + task.replay.pendingTasks--; } catch (x) { if (typeof x === 'object' && x !== null && (x === SuspenseException || typeof x.then === 'function')) { // Suspend + if (task.node === currentNode) { + // This same element suspended so we need to pop the replay we just added. + task.replay = replay; + } + throw x; - } // Unlike regular render, we don't terminate the siblings if we error + } + + task.replay.pendingTasks--; // Unlike regular render, we don't terminate the siblings if we error // during a replay. That's because this component didn't actually error // in the original prerender. What's unable to complete is the child // replay nodes which might be Suspense boundaries which are able to // absorb the error and we can still continue with siblings. - erroredReplay(request, task.blockedBoundary, x, childNodes, childSlots); - } finally { - task.replay.pendingTasks--; - task.replay = replay; } + + task.replay = replay; } else { // Let's double check that the component type matches. if (type !== REACT_SUSPENSE_TYPE) { - throw new Error('Expected to see a Suspense boundary in this slot. ' + "The tree doesn't match so React will fallback to client rendering."); + var expectedType = 'Suspense'; + throw new Error('Expected the resume to render <' + expectedType + '> in this slot but instead it rendered <' + (getComponentNameFromType(type) || 'Unknown') + '>. ' + "The tree doesn't match so React will fallback to client rendering."); } // Matched a replayable path. @@ -9758,8 +9720,15 @@ prevThenableState, node, childIndex) { function renderNodeDestructiveImpl(request, task, prevThenableState, node, childIndex) { - // Stash the node we're working on. We'll pick up from this task in case + if (task.replay !== null && typeof task.replay.slots === 'number') { + // TODO: Figure out a cheaper place than this hot path to do this check. + var resumeSegmentID = task.replay.slots; + resumeNode(request, task, resumeSegmentID, node, childIndex); + return; + } // Stash the node we're working on. We'll pick up from this task in case // something suspends. + + task.node = node; task.childIndex = childIndex; // Handle object types @@ -9937,24 +9906,26 @@ function replayFragment(request, task, children, childIndex) { if (task.replay.pendingTasks === 1 && task.replay.nodes.length > 0) { throw new Error("Couldn't find all resumable slots by key/index during replaying. " + "The tree doesn't match so React will fallback to client rendering."); } + + task.replay.pendingTasks--; } catch (x) { if (typeof x === 'object' && x !== null && (x === SuspenseException || typeof x.then === 'function')) { // Suspend throw x; - } // Unlike regular render, we don't terminate the siblings if we error + } + + task.replay.pendingTasks--; // Unlike regular render, we don't terminate the siblings if we error // during a replay. That's because this component didn't actually error // in the original prerender. What's unable to complete is the child // replay nodes which might be Suspense boundaries which are able to // absorb the error and we can still continue with siblings. - + // This is an error, stash the component stack if it is null. erroredReplay(request, task.blockedBoundary, x, childNodes, childSlots); - } finally { - task.replay.pendingTasks--; - task.replay = replay; - } // We finished rendering this node, so now we can consume this - // slot. This must happen after in case we rerender this task. + } + task.replay = replay; // We finished rendering this node, so now we can consume this + // slot. This must happen after in case we rerender this task. replayNodes.splice(j, 1); break; @@ -9989,7 +9960,7 @@ function renderChildrenArray(request, task, children, childIndex) { task.treeContext = pushTreeContext(prevTreeContext, totalChildren, i); // We need to use the non-destructive form so that we can safely pop back // up and render the sibling if something suspends. - var resumeSegmentID = resumeSlots[i]; + var resumeSegmentID = resumeSlots[i]; // TODO: If this errors we should still continue with the next sibling. if (typeof resumeSegmentID === 'number') { resumeNode(request, task, resumeSegmentID, node, i); // We finished rendering this node, so now we can consume this @@ -10314,6 +10285,7 @@ function renderNode(request, task, node, childIndex) { task.componentStack = previousComponentStack; } + lastBoundaryErrorComponentStackDev = null; return; } } @@ -10375,6 +10347,7 @@ function erroredTask(request, boundary, error) { } if (boundary === null) { + lastBoundaryErrorComponentStackDev = null; fatalError(request, error); } else { boundary.pendingTasks--; @@ -10396,6 +10369,8 @@ function erroredTask(request, boundary, error) { // We reuse the same queue for errors. request.clientRenderedBoundaries.push(boundary); } + } else { + lastBoundaryErrorComponentStackDev = null; } } @@ -10509,8 +10484,6 @@ function abortTask(task, request, error) { } if (boundary === null) { - request.allPendingTasks--; - if (request.status !== CLOSING && request.status !== CLOSED) { var replay = task.replay; @@ -10519,6 +10492,7 @@ function abortTask(task, request, error) { // the request; logRecoverableError(request, error); fatalError(request, error); + return; } else { // If the shell aborts during a replay, that's not a fatal error. Instead // we should be able to recover by client rendering all the root boundaries in @@ -10529,6 +10503,14 @@ function abortTask(task, request, error) { var errorDigest = logRecoverableError(request, error); abortRemainingReplayNodes(request, null, replay.nodes, replay.slots, error, errorDigest); } + + request.pendingRootTasks--; + + if (request.pendingRootTasks === 0) { + request.onShellError = noop; + var onShellReady = request.onShellReady; + onShellReady(); + } } } } else { @@ -10570,12 +10552,13 @@ function abortTask(task, request, error) { return abortTask(fallbackTask, request, error); }); boundary.fallbackAbortableTasks.clear(); - request.allPendingTasks--; + } - if (request.allPendingTasks === 0) { - var onAllReady = request.onAllReady; - onAllReady(); - } + request.allPendingTasks--; + + if (request.allPendingTasks === 0) { + var onAllReady = request.onAllReady; + onAllReady(); } } @@ -10759,6 +10742,7 @@ function retryRenderTask(request, task, segment) { logPostpone(request, postponeInstance.message); trackPostpone(request, trackedPostpones, task, segment); finishedTask(request, task.blockedBoundary, segment); + lastBoundaryErrorComponentStackDev = null; return; } } @@ -10835,6 +10819,14 @@ function retryReplayTask(request, task) { task.replay.pendingTasks--; task.abortSet.delete(task); erroredReplay(request, task.blockedBoundary, x, task.replay.nodes, task.replay.slots); + request.pendingRootTasks--; + + if (request.pendingRootTasks === 0) { + request.onShellError = noop; + var onShellReady = request.onShellReady; + onShellReady(); + } + request.allPendingTasks--; if (request.allPendingTasks === 0) { diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server-legacy.browser.production.min.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server-legacy.browser.production.min.js index 3bfe9118b1b45..58d1d3b414b7e 100644 --- a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server-legacy.browser.production.min.js +++ b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server-legacy.browser.production.min.js @@ -31,11 +31,11 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -'use strict';var ca=require("next/dist/compiled/react-experimental"),ia=require("react-dom");function q(a){for(var b="https://reactjs.org/docs/error-decoder.html?invariant="+a,c=1;c>>16)&65535)<<16)&4294967295;f=f<<15|f>>>17;f=461845907*(f&65535)+((461845907*(f>>>16)&65535)<<16)&4294967295;e^=f;e=e<<13|e>>>19;e=5*(e&65535)+((5*(e>>>16)&65535)<<16)&4294967295;e=(e&65535)+27492+(((e>>>16)+58964&65535)<<16)}f=0;switch(c){case 3:f^=(a.charCodeAt(b+2)&255)<< +'use strict';var da=require("next/dist/compiled/react-experimental"),ja=require("react-dom");function n(a){for(var b="https://reactjs.org/docs/error-decoder.html?invariant="+a,c=1;c>>16)&65535)<<16)&4294967295;f=f<<15|f>>>17;f=461845907*(f&65535)+((461845907*(f>>>16)&65535)<<16)&4294967295;e^=f;e=e<<13|e>>>19;e=5*(e&65535)+((5*(e>>>16)&65535)<<16)&4294967295;e=(e&65535)+27492+(((e>>>16)+58964&65535)<<16)}f=0;switch(c){case 3:f^=(a.charCodeAt(b+2)&255)<< 16;case 2:f^=(a.charCodeAt(b+1)&255)<<8;case 1:f^=a.charCodeAt(b)&255,f=3432918353*(f&65535)+((3432918353*(f>>>16)&65535)<<16)&4294967295,f=f<<15|f>>>17,e^=461845907*(f&65535)+((461845907*(f>>>16)&65535)<<16)&4294967295}e^=a.length;e^=e>>>16;e=2246822507*(e&65535)+((2246822507*(e>>>16)&65535)<<16)&4294967295;e^=e>>>13;e=3266489909*(e&65535)+((3266489909*(e>>>16)&65535)<<16)&4294967295;return(e^e>>>16)>>>0} -var t=Object.assign,v=Object.prototype.hasOwnProperty,ka=RegExp("^[:A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][:A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$"),la={},wa={}; -function xa(a){if(v.call(wa,a))return!0;if(v.call(la,a))return!1;if(ka.test(a))return wa[a]=!0;la[a]=!0;return!1} +var t=Object.assign,w=Object.prototype.hasOwnProperty,la=RegExp("^[:A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][:A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$"),ma={},wa={}; +function xa(a){if(w.call(wa,a))return!0;if(w.call(ma,a))return!1;if(la.test(a))return wa[a]=!0;ma[a]=!0;return!1} var ya=new Set("animationIterationCount aspectRatio borderImageOutset borderImageSlice borderImageWidth boxFlex boxFlexGroup boxOrdinalGroup columnCount columns flex flexGrow flexPositive flexShrink flexNegative flexOrder gridArea gridRow gridRowEnd gridRowSpan gridRowStart gridColumn gridColumnEnd gridColumnSpan gridColumnStart fontWeight lineClamp lineHeight opacity order orphans scale tabSize widows zIndex zoom fillOpacity floodOpacity stopOpacity strokeDasharray strokeDashoffset strokeMiterlimit strokeOpacity strokeWidth MozAnimationIterationCount MozBoxFlex MozBoxFlexGroup MozLineClamp msAnimationIterationCount msFlex msZoom msFlexGrow msFlexNegative msFlexOrder msFlexPositive msFlexShrink msGridColumn msGridColumnSpan msGridRow msGridRowSpan WebkitAnimationIterationCount WebkitBoxFlex WebKitBoxFlexGroup WebkitBoxOrdinalGroup WebkitColumnCount WebkitColumns WebkitFlex WebkitFlexGrow WebkitFlexPositive WebkitFlexShrink WebkitLineClamp".split(" ")),za= new Map([["acceptCharset","accept-charset"],["htmlFor","for"],["httpEquiv","http-equiv"],["crossOrigin","crossorigin"],["accentHeight","accent-height"],["alignmentBaseline","alignment-baseline"],["arabicForm","arabic-form"],["baselineShift","baseline-shift"],["capHeight","cap-height"],["clipPath","clip-path"],["clipRule","clip-rule"],["colorInterpolation","color-interpolation"],["colorInterpolationFilters","color-interpolation-filters"],["colorProfile","color-profile"],["colorRendering","color-rendering"], ["dominantBaseline","dominant-baseline"],["enableBackground","enable-background"],["fillOpacity","fill-opacity"],["fillRule","fill-rule"],["floodColor","flood-color"],["floodOpacity","flood-opacity"],["fontFamily","font-family"],["fontSize","font-size"],["fontSizeAdjust","font-size-adjust"],["fontStretch","font-stretch"],["fontStyle","font-style"],["fontVariant","font-variant"],["fontWeight","font-weight"],["glyphName","glyph-name"],["glyphOrientationHorizontal","glyph-orientation-horizontal"],["glyphOrientationVertical", @@ -43,154 +43,153 @@ new Map([["acceptCharset","accept-charset"],["htmlFor","for"],["httpEquiv","http "shape-rendering"],["stopColor","stop-color"],["stopOpacity","stop-opacity"],["strikethroughPosition","strikethrough-position"],["strikethroughThickness","strikethrough-thickness"],["strokeDasharray","stroke-dasharray"],["strokeDashoffset","stroke-dashoffset"],["strokeLinecap","stroke-linecap"],["strokeLinejoin","stroke-linejoin"],["strokeMiterlimit","stroke-miterlimit"],["strokeOpacity","stroke-opacity"],["strokeWidth","stroke-width"],["textAnchor","text-anchor"],["textDecoration","text-decoration"], ["textRendering","text-rendering"],["transformOrigin","transform-origin"],["underlinePosition","underline-position"],["underlineThickness","underline-thickness"],["unicodeBidi","unicode-bidi"],["unicodeRange","unicode-range"],["unitsPerEm","units-per-em"],["vAlphabetic","v-alphabetic"],["vHanging","v-hanging"],["vIdeographic","v-ideographic"],["vMathematical","v-mathematical"],["vectorEffect","vector-effect"],["vertAdvY","vert-adv-y"],["vertOriginX","vert-origin-x"],["vertOriginY","vert-origin-y"], ["wordSpacing","word-spacing"],["writingMode","writing-mode"],["xmlnsXlink","xmlns:xlink"],["xHeight","x-height"]]),Aa=/["'&<>]/; -function w(a){if("boolean"===typeof a||"number"===typeof a)return""+a;a=""+a;var b=Aa.exec(a);if(b){var c="",d,e=0;for(d=b.index;d")} -function Cb(a,b,c,d,e,f,g,h){var k=null;"function"===typeof d&&("function"===typeof d.$$FORM_ACTION?(e=zb(b),b=d.$$FORM_ACTION(e),h=b.name,d=b.action||"",e=b.encType,f=b.method,g=b.target,k=b.data):(a.push(" ","formAction",'="',Ab,'"'),g=f=e=d=h=null,Db(b,c)));null!=h&&G(a,"name",h);null!=d&&G(a,"formAction",d);null!=e&&G(a,"formEncType",e);null!=f&&G(a,"formMethod",f);null!=g&&G(a,"formTarget",g);return k} -function G(a,b,c){switch(b){case "className":F(a,"class",c);break;case "tabIndex":F(a,"tabindex",c);break;case "dir":case "role":case "viewBox":case "width":case "height":F(a,b,c);break;case "style":ob(a,c);break;case "src":case "href":if(""===c)break;case "action":case "formAction":if(null==c||"function"===typeof c||"symbol"===typeof c||"boolean"===typeof c)break;a.push(" ",b,'="',w(""+c),'"');break;case "defaultValue":case "defaultChecked":case "innerHTML":case "suppressContentEditableWarning":case "suppressHydrationWarning":break; -case "autoFocus":case "multiple":case "muted":yb(a,b.toLowerCase(),c);break;case "xlinkHref":if("function"===typeof c||"symbol"===typeof c||"boolean"===typeof c)break;a.push(" ","xlink:href",'="',w(""+c),'"');break;case "contentEditable":case "spellCheck":case "draggable":case "value":case "autoReverse":case "externalResourcesRequired":case "focusable":case "preserveAlpha":"function"!==typeof c&&"symbol"!==typeof c&&a.push(" ",b,'="',w(c),'"');break;case "allowFullScreen":case "async":case "autoPlay":case "controls":case "default":case "defer":case "disabled":case "disablePictureInPicture":case "disableRemotePlayback":case "formNoValidate":case "hidden":case "loop":case "noModule":case "noValidate":case "open":case "playsInline":case "readOnly":case "required":case "reversed":case "scoped":case "seamless":case "itemScope":c&& -"function"!==typeof c&&"symbol"!==typeof c&&a.push(" ",b,'=""');break;case "capture":case "download":!0===c?a.push(" ",b,'=""'):!1!==c&&"function"!==typeof c&&"symbol"!==typeof c&&a.push(" ",b,'="',w(c),'"');break;case "cols":case "rows":case "size":case "span":"function"!==typeof c&&"symbol"!==typeof c&&!isNaN(c)&&1<=c&&a.push(" ",b,'="',w(c),'"');break;case "rowSpan":case "start":"function"===typeof c||"symbol"===typeof c||isNaN(c)||a.push(" ",b,'="',w(c),'"');break;case "xlinkActuate":F(a,"xlink:actuate", -c);break;case "xlinkArcrole":F(a,"xlink:arcrole",c);break;case "xlinkRole":F(a,"xlink:role",c);break;case "xlinkShow":F(a,"xlink:show",c);break;case "xlinkTitle":F(a,"xlink:title",c);break;case "xlinkType":F(a,"xlink:type",c);break;case "xmlBase":F(a,"xml:base",c);break;case "xmlLang":F(a,"xml:lang",c);break;case "xmlSpace":F(a,"xml:space",c);break;default:if(!(2")} +function Cb(a,b,c,d,e,f,g,h){var k=null;"function"===typeof d&&("function"===typeof d.$$FORM_ACTION?(e=zb(b),b=d.$$FORM_ACTION(e),h=b.name,d=b.action||"",e=b.encType,f=b.method,g=b.target,k=b.data):(a.push(" ","formAction",'="',Ab,'"'),g=f=e=d=h=null,Db(b,c)));null!=h&&E(a,"name",h);null!=d&&E(a,"formAction",d);null!=e&&E(a,"formEncType",e);null!=f&&E(a,"formMethod",f);null!=g&&E(a,"formTarget",g);return k} +function E(a,b,c){switch(b){case "className":D(a,"class",c);break;case "tabIndex":D(a,"tabindex",c);break;case "dir":case "role":case "viewBox":case "width":case "height":D(a,b,c);break;case "style":ob(a,c);break;case "src":case "href":if(""===c)break;case "action":case "formAction":if(null==c||"function"===typeof c||"symbol"===typeof c||"boolean"===typeof c)break;a.push(" ",b,'="',x(""+c),'"');break;case "defaultValue":case "defaultChecked":case "innerHTML":case "suppressContentEditableWarning":case "suppressHydrationWarning":break; +case "autoFocus":case "multiple":case "muted":yb(a,b.toLowerCase(),c);break;case "xlinkHref":if("function"===typeof c||"symbol"===typeof c||"boolean"===typeof c)break;a.push(" ","xlink:href",'="',x(""+c),'"');break;case "contentEditable":case "spellCheck":case "draggable":case "value":case "autoReverse":case "externalResourcesRequired":case "focusable":case "preserveAlpha":"function"!==typeof c&&"symbol"!==typeof c&&a.push(" ",b,'="',x(c),'"');break;case "allowFullScreen":case "async":case "autoPlay":case "controls":case "default":case "defer":case "disabled":case "disablePictureInPicture":case "disableRemotePlayback":case "formNoValidate":case "hidden":case "loop":case "noModule":case "noValidate":case "open":case "playsInline":case "readOnly":case "required":case "reversed":case "scoped":case "seamless":case "itemScope":c&& +"function"!==typeof c&&"symbol"!==typeof c&&a.push(" ",b,'=""');break;case "capture":case "download":!0===c?a.push(" ",b,'=""'):!1!==c&&"function"!==typeof c&&"symbol"!==typeof c&&a.push(" ",b,'="',x(c),'"');break;case "cols":case "rows":case "size":case "span":"function"!==typeof c&&"symbol"!==typeof c&&!isNaN(c)&&1<=c&&a.push(" ",b,'="',x(c),'"');break;case "rowSpan":case "start":"function"===typeof c||"symbol"===typeof c||isNaN(c)||a.push(" ",b,'="',x(c),'"');break;case "xlinkActuate":D(a,"xlink:actuate", +c);break;case "xlinkArcrole":D(a,"xlink:arcrole",c);break;case "xlinkRole":D(a,"xlink:role",c);break;case "xlinkShow":D(a,"xlink:show",c);break;case "xlinkTitle":D(a,"xlink:title",c);break;case "xlinkType":D(a,"xlink:type",c);break;case "xmlBase":D(a,"xml:base",c);break;case "xmlLang":D(a,"xml:lang",c);break;case "xmlSpace":D(a,"xml:space",c);break;default:if(!(2"))} -function Fb(a,b,c,d,e,f,g){var h=b.rel,k=b.href,l=b.precedence;if(3===f||g||null!=b.itemProp||"string"!==typeof h||"string"!==typeof k||""===k)return L(a,b),null;if("stylesheet"===b.rel){if("string"!==typeof l||null!=b.disabled||b.onLoad||b.onError)return L(a,b);f=d.styles.get(l);g=c.styleResources.hasOwnProperty(k)?c.styleResources[k]:void 0;null!==g?(c.styleResources[k]=null,f||(f={precedence:w(l),rules:[],hrefs:[],sheets:new Map},d.styles.set(l,f)),b={state:0,props:t({},b,{"data-precedence":b.precedence, -precedence:null})},g&&(2===g.length&&Gb(b.props,g),(c=d.preloads.stylesheets.get(k))&&0");return null}function Hb(a,b,c){a.push(M(c));for(var d in b)if(v.call(b,d)){var e=b[d];if(null!=e)switch(d){case "children":case "dangerouslySetInnerHTML":throw Error(q(399,c));default:G(a,d,e)}}a.push("/>");return null} -function Ib(a,b){a.push(M("title"));var c=null,d=null,e;for(e in b)if(v.call(b,e)){var f=b[e];if(null!=f)switch(e){case "children":c=f;break;case "dangerouslySetInnerHTML":d=f;break;default:G(a,e,f)}}a.push(">");b=Array.isArray(c)?2>c.length?c[0]:null:c;"function"!==typeof b&&"symbol"!==typeof b&&null!==b&&void 0!==b&&a.push(w(""+b));H(a,d,c);a.push("");return null} -function Jb(a,b){a.push(M("script"));var c=null,d=null,e;for(e in b)if(v.call(b,e)){var f=b[e];if(null!=f)switch(e){case "children":c=f;break;case "dangerouslySetInnerHTML":d=f;break;default:G(a,e,f)}}a.push(">");H(a,d,c);"string"===typeof c&&a.push(w(c));a.push("");return null} -function Kb(a,b,c){a.push(M(c));var d=c=null,e;for(e in b)if(v.call(b,e)){var f=b[e];if(null!=f)switch(e){case "children":c=f;break;case "dangerouslySetInnerHTML":d=f;break;default:G(a,e,f)}}a.push(">");H(a,d,c);return"string"===typeof c?(a.push(w(c)),null):c}var Lb=/^[a-zA-Z][a-zA-Z:_\.\-\d]*$/,Mb=new Map;function M(a){var b=Mb.get(a);if(void 0===b){if(!Lb.test(a))throw Error(q(65,a));b="<"+a;Mb.set(a,b)}return b} -function Nb(a,b,c,d,e,f,g){switch(b){case "div":case "span":case "svg":case "path":case "a":case "g":case "p":case "li":break;case "select":a.push(M("select"));var h=null,k=null,l;for(l in c)if(v.call(c,l)){var p=c[l];if(null!=p)switch(l){case "children":h=p;break;case "dangerouslySetInnerHTML":k=p;break;case "defaultValue":case "value":break;default:G(a,l,p)}}a.push(">");H(a,k,h);return h;case "option":var r=f.selectedValue;a.push(M("option"));var m=null,u=null,I=null,A=null,B;for(B in c)if(v.call(c, -B)){var n=c[B];if(null!=n)switch(B){case "children":m=n;break;case "selected":I=n;break;case "dangerouslySetInnerHTML":A=n;break;case "value":u=n;default:G(a,B,n)}}if(null!=r){var z=null!==u?""+u:Eb(m);if(Ha(r))for(var Z=0;Z");H(a,A,m);return m;case "textarea":a.push(M("textarea"));var J=null,x=null,D=null,C;for(C in c)if(v.call(c,C)){var K=c[C];if(null!=K)switch(C){case "children":D= -K;break;case "value":J=K;break;case "defaultValue":x=K;break;case "dangerouslySetInnerHTML":throw Error(q(91));default:G(a,C,K)}}null===J&&null!==x&&(J=x);a.push(">");if(null!=D){if(null!=J)throw Error(q(92));if(Ha(D)){if(1");null!==pb&&pb.forEach(Bb,a);return null;case "button":a.push(M("button"));var V=null,oa=null,pa=null,qa=null,Sa=null,ra=null,Dc=null,Ta;for(Ta in c)if(v.call(c,Ta)){var ba=c[Ta];if(null!=ba)switch(Ta){case "children":V=ba;break;case "dangerouslySetInnerHTML":oa=ba;break;case "name":pa=ba;break;case "formAction":qa=ba;break;case "formEncType":Sa=ba;break;case "formMethod":ra=ba;break;case "formTarget":Dc=ba;break;default:G(a,Ta,ba)}}var Ec=Cb(a,d,e,qa,Sa,ra,Dc,pa);a.push(">");null!== -Ec&&Ec.forEach(Bb,a);H(a,oa,V);if("string"===typeof V){a.push(w(V));var Fc=null}else Fc=V;return Fc;case "form":a.push(M("form"));var Ua=null,Gc=null,ea=null,Va=null,Wa=null,Xa=null,Ya;for(Ya in c)if(v.call(c,Ya)){var fa=c[Ya];if(null!=fa)switch(Ya){case "children":Ua=fa;break;case "dangerouslySetInnerHTML":Gc=fa;break;case "action":ea=fa;break;case "encType":Va=fa;break;case "method":Wa=fa;break;case "target":Xa=fa;break;default:G(a,Ya,fa)}}var Vb=null,Wb=null;if("function"===typeof ea)if("function"=== -typeof ea.$$FORM_ACTION){var ge=zb(d),Da=ea.$$FORM_ACTION(ge);ea=Da.action||"";Va=Da.encType;Wa=Da.method;Xa=Da.target;Vb=Da.data;Wb=Da.name}else a.push(" ","action",'="',Ab,'"'),Xa=Wa=Va=ea=null,Db(d,e);null!=ea&&G(a,"action",ea);null!=Va&&G(a,"encType",Va);null!=Wa&&G(a,"method",Wa);null!=Xa&&G(a,"target",Xa);a.push(">");null!==Wb&&(a.push('"),null!==Vb&&Vb.forEach(Bb,a));H(a,Gc,Ua);if("string"===typeof Ua){a.push(w(Ua));var Hc=null}else Hc=Ua;return Hc; -case "menuitem":a.push(M("menuitem"));for(var qb in c)if(v.call(c,qb)){var Ic=c[qb];if(null!=Ic)switch(qb){case "children":case "dangerouslySetInnerHTML":throw Error(q(400));default:G(a,qb,Ic)}}a.push(">");return null;case "title":if(3===f.insertionMode||f.tagScope&1||null!=c.itemProp)var Jc=Ib(a,c);else Ib(e.hoistableChunks,c),Jc=null;return Jc;case "link":return Fb(a,c,d,e,g,f.insertionMode,!!(f.tagScope&1));case "script":var Xb=c.async;if("string"!==typeof c.src||!c.src||!Xb||"function"===typeof Xb|| -"symbol"===typeof Xb||c.onLoad||c.onError||3===f.insertionMode||f.tagScope&1||null!=c.itemProp)var Kc=Jb(a,c);else{var rb=c.src;if("module"===c.type){var sb=d.moduleScriptResources;var Lc=e.preloads.moduleScripts}else sb=d.scriptResources,Lc=e.preloads.scripts;var tb=sb.hasOwnProperty(rb)?sb[rb]:void 0;if(null!==tb){sb[rb]=null;var Yb=c;if(tb){2===tb.length&&(Yb=t({},c),Gb(Yb,tb));var Mc=Lc.get(rb);Mc&&(Mc.length=0)}var Nc=[];e.scripts.add(Nc);Jb(Nc,Yb)}g&&a.push("\x3c!-- --\x3e");Kc=null}return Kc; -case "style":var ub=c.precedence,sa=c.href;if(3===f.insertionMode||f.tagScope&1||null!=c.itemProp||"string"!==typeof ub||"string"!==typeof sa||""===sa){a.push(M("style"));var Ea=null,Oc=null,Za;for(Za in c)if(v.call(c,Za)){var vb=c[Za];if(null!=vb)switch(Za){case "children":Ea=vb;break;case "dangerouslySetInnerHTML":Oc=vb;break;default:G(a,Za,vb)}}a.push(">");var $a=Array.isArray(Ea)?2>Ea.length?Ea[0]:null:Ea;"function"!==typeof $a&&"symbol"!==typeof $a&&null!==$a&&void 0!==$a&&a.push(w(""+$a));H(a, -Oc,Ea);a.push("");var Pc=null}else{var ta=e.styles.get(ub);if(null!==(d.styleResources.hasOwnProperty(sa)?d.styleResources[sa]:void 0)){d.styleResources[sa]=null;ta?ta.hrefs.push(w(sa)):(ta={precedence:w(ub),rules:[],hrefs:[w(sa)],sheets:new Map},e.styles.set(ub,ta));var Qc=ta.rules,Fa=null,Rc=null,wb;for(wb in c)if(v.call(c,wb)){var Zb=c[wb];if(null!=Zb)switch(wb){case "children":Fa=Zb;break;case "dangerouslySetInnerHTML":Rc=Zb}}var ab=Array.isArray(Fa)?2>Fa.length?Fa[0]:null:Fa;"function"!== -typeof ab&&"symbol"!==typeof ab&&null!==ab&&void 0!==ab&&Qc.push(w(""+ab));H(Qc,Rc,Fa)}ta&&e.boundaryResources&&e.boundaryResources.styles.add(ta);g&&a.push("\x3c!-- --\x3e");Pc=void 0}return Pc;case "meta":if(3===f.insertionMode||f.tagScope&1||null!=c.itemProp)var Sc=Hb(a,c,"meta");else g&&a.push("\x3c!-- --\x3e"),Sc="string"===typeof c.charSet?Hb(e.charsetChunks,c,"meta"):"viewport"===c.name?Hb(e.preconnectChunks,c,"meta"):Hb(e.hoistableChunks,c,"meta");return Sc;case "listing":case "pre":a.push(M(b)); -var bb=null,cb=null,db;for(db in c)if(v.call(c,db)){var xb=c[db];if(null!=xb)switch(db){case "children":bb=xb;break;case "dangerouslySetInnerHTML":cb=xb;break;default:G(a,db,xb)}}a.push(">");if(null!=cb){if(null!=bb)throw Error(q(60));if("object"!==typeof cb||!("__html"in cb))throw Error(q(61));var ua=cb.__html;null!==ua&&void 0!==ua&&("string"===typeof ua&&0e.highImagePreloads.size)$b.delete(eb),e.highImagePreloads.add(va)}else d.imageResources.hasOwnProperty(eb)||(d.imageResources[eb]=kb,va=[],L(va,{rel:"preload",as:"image",href:E?void 0:P,imageSrcSet:E,imageSizes:Tc,crossOrigin:c.crossOrigin,integrity:c.integrity,type:c.type,fetchPriority:c.fetchPriority,referrerPolicy:c.referrerPolicy}),"high"===c.fetchPriority||10>e.highImagePreloads.size?e.highImagePreloads.add(va):(e.bulkPreloads.add(va),$b.set(eb, +function Fb(a,b,c,d,e,f,g){var h=b.rel,k=b.href,l=b.precedence;if(3===f||g||null!=b.itemProp||"string"!==typeof h||"string"!==typeof k||""===k)return I(a,b),null;if("stylesheet"===b.rel){if("string"!==typeof l||null!=b.disabled||b.onLoad||b.onError)return I(a,b);f=d.styles.get(l);g=c.styleResources.hasOwnProperty(k)?c.styleResources[k]:void 0;null!==g?(c.styleResources[k]=null,f||(f={precedence:x(l),rules:[],hrefs:[],sheets:new Map},d.styles.set(l,f)),b={state:0,props:t({},b,{"data-precedence":b.precedence, +precedence:null})},g&&(2===g.length&&Gb(b.props,g),(c=d.preloads.stylesheets.get(k))&&0");return null}function Hb(a,b,c){a.push(J(c));for(var d in b)if(w.call(b,d)){var e=b[d];if(null!=e)switch(d){case "children":case "dangerouslySetInnerHTML":throw Error(n(399,c));default:E(a,d,e)}}a.push("/>");return null} +function Ib(a,b){a.push(J("title"));var c=null,d=null,e;for(e in b)if(w.call(b,e)){var f=b[e];if(null!=f)switch(e){case "children":c=f;break;case "dangerouslySetInnerHTML":d=f;break;default:E(a,e,f)}}a.push(">");b=Array.isArray(c)?2>c.length?c[0]:null:c;"function"!==typeof b&&"symbol"!==typeof b&&null!==b&&void 0!==b&&a.push(x(""+b));F(a,d,c);a.push("");return null} +function Jb(a,b){a.push(J("script"));var c=null,d=null,e;for(e in b)if(w.call(b,e)){var f=b[e];if(null!=f)switch(e){case "children":c=f;break;case "dangerouslySetInnerHTML":d=f;break;default:E(a,e,f)}}a.push(">");F(a,d,c);"string"===typeof c&&a.push(x(c));a.push("");return null} +function Kb(a,b,c){a.push(J(c));var d=c=null,e;for(e in b)if(w.call(b,e)){var f=b[e];if(null!=f)switch(e){case "children":c=f;break;case "dangerouslySetInnerHTML":d=f;break;default:E(a,e,f)}}a.push(">");F(a,d,c);return"string"===typeof c?(a.push(x(c)),null):c}var Lb=/^[a-zA-Z][a-zA-Z:_\.\-\d]*$/,Mb=new Map;function J(a){var b=Mb.get(a);if(void 0===b){if(!Lb.test(a))throw Error(n(65,a));b="<"+a;Mb.set(a,b)}return b} +function Nb(a,b,c,d,e,f,g){switch(b){case "div":case "span":case "svg":case "path":case "a":case "g":case "p":case "li":break;case "select":a.push(J("select"));var h=null,k=null,l;for(l in c)if(w.call(c,l)){var p=c[l];if(null!=p)switch(l){case "children":h=p;break;case "dangerouslySetInnerHTML":k=p;break;case "defaultValue":case "value":break;default:E(a,l,p)}}a.push(">");F(a,k,h);return h;case "option":var r=f.selectedValue;a.push(J("option"));var m=null,z=null,B=null,R=null,N;for(N in c)if(w.call(c, +N)){var q=c[N];if(null!=q)switch(N){case "children":m=q;break;case "selected":B=q;break;case "dangerouslySetInnerHTML":R=q;break;case "value":z=q;default:E(a,N,q)}}if(null!=r){var u=null!==z?""+z:Eb(m);if(Ha(r))for(var aa=0;aa");F(a,R,m);return m;case "textarea":a.push(J("textarea"));var G=null,O=null,v=null,A;for(A in c)if(w.call(c,A)){var V=c[A];if(null!=V)switch(A){case "children":v= +V;break;case "value":G=V;break;case "defaultValue":O=V;break;case "dangerouslySetInnerHTML":throw Error(n(91));default:E(a,A,V)}}null===G&&null!==O&&(G=O);a.push(">");if(null!=v){if(null!=G)throw Error(n(92));if(Ha(v)){if(1");null!==pb&&pb.forEach(Bb,a);return null;case "button":a.push(J("button"));var W=null,oa=null,pa=null,qa=null,Ra=null,ra=null,Dc=null,Sa;for(Sa in c)if(w.call(c,Sa)){var ca=c[Sa];if(null!=ca)switch(Sa){case "children":W=ca;break;case "dangerouslySetInnerHTML":oa=ca;break;case "name":pa=ca;break;case "formAction":qa=ca;break;case "formEncType":Ra=ca;break;case "formMethod":ra=ca;break;case "formTarget":Dc=ca;break;default:E(a,Sa,ca)}}var Ec=Cb(a,d,e,qa,Ra,ra,Dc,pa);a.push(">");null!== +Ec&&Ec.forEach(Bb,a);F(a,oa,W);if("string"===typeof W){a.push(x(W));var Fc=null}else Fc=W;return Fc;case "form":a.push(J("form"));var Ta=null,Gc=null,ha=null,Ua=null,Va=null,Wa=null,Xa;for(Xa in c)if(w.call(c,Xa)){var ia=c[Xa];if(null!=ia)switch(Xa){case "children":Ta=ia;break;case "dangerouslySetInnerHTML":Gc=ia;break;case "action":ha=ia;break;case "encType":Ua=ia;break;case "method":Va=ia;break;case "target":Wa=ia;break;default:E(a,Xa,ia)}}var Ub=null,Vb=null;if("function"===typeof ha)if("function"=== +typeof ha.$$FORM_ACTION){var he=zb(d),Ca=ha.$$FORM_ACTION(he);ha=Ca.action||"";Ua=Ca.encType;Va=Ca.method;Wa=Ca.target;Ub=Ca.data;Vb=Ca.name}else a.push(" ","action",'="',Ab,'"'),Wa=Va=Ua=ha=null,Db(d,e);null!=ha&&E(a,"action",ha);null!=Ua&&E(a,"encType",Ua);null!=Va&&E(a,"method",Va);null!=Wa&&E(a,"target",Wa);a.push(">");null!==Vb&&(a.push('"),null!==Ub&&Ub.forEach(Bb,a));F(a,Gc,Ta);if("string"===typeof Ta){a.push(x(Ta));var Hc=null}else Hc=Ta;return Hc; +case "menuitem":a.push(J("menuitem"));for(var qb in c)if(w.call(c,qb)){var Ic=c[qb];if(null!=Ic)switch(qb){case "children":case "dangerouslySetInnerHTML":throw Error(n(400));default:E(a,qb,Ic)}}a.push(">");return null;case "title":if(3===f.insertionMode||f.tagScope&1||null!=c.itemProp)var Jc=Ib(a,c);else Ib(e.hoistableChunks,c),Jc=null;return Jc;case "link":return Fb(a,c,d,e,g,f.insertionMode,!!(f.tagScope&1));case "script":var Wb=c.async;if("string"!==typeof c.src||!c.src||!Wb||"function"===typeof Wb|| +"symbol"===typeof Wb||c.onLoad||c.onError||3===f.insertionMode||f.tagScope&1||null!=c.itemProp)var Kc=Jb(a,c);else{var rb=c.src;if("module"===c.type){var sb=d.moduleScriptResources;var Lc=e.preloads.moduleScripts}else sb=d.scriptResources,Lc=e.preloads.scripts;var tb=sb.hasOwnProperty(rb)?sb[rb]:void 0;if(null!==tb){sb[rb]=null;var Xb=c;if(tb){2===tb.length&&(Xb=t({},c),Gb(Xb,tb));var Mc=Lc.get(rb);Mc&&(Mc.length=0)}var Nc=[];e.scripts.add(Nc);Jb(Nc,Xb)}g&&a.push("\x3c!-- --\x3e");Kc=null}return Kc; +case "style":var ub=c.precedence,sa=c.href;if(3===f.insertionMode||f.tagScope&1||null!=c.itemProp||"string"!==typeof ub||"string"!==typeof sa||""===sa){a.push(J("style"));var Da=null,Oc=null,Ya;for(Ya in c)if(w.call(c,Ya)){var vb=c[Ya];if(null!=vb)switch(Ya){case "children":Da=vb;break;case "dangerouslySetInnerHTML":Oc=vb;break;default:E(a,Ya,vb)}}a.push(">");var Za=Array.isArray(Da)?2>Da.length?Da[0]:null:Da;"function"!==typeof Za&&"symbol"!==typeof Za&&null!==Za&&void 0!==Za&&a.push(x(""+Za));F(a, +Oc,Da);a.push("");var Pc=null}else{var ta=e.styles.get(ub);if(null!==(d.styleResources.hasOwnProperty(sa)?d.styleResources[sa]:void 0)){d.styleResources[sa]=null;ta?ta.hrefs.push(x(sa)):(ta={precedence:x(ub),rules:[],hrefs:[x(sa)],sheets:new Map},e.styles.set(ub,ta));var Qc=ta.rules,Ea=null,Rc=null,wb;for(wb in c)if(w.call(c,wb)){var Yb=c[wb];if(null!=Yb)switch(wb){case "children":Ea=Yb;break;case "dangerouslySetInnerHTML":Rc=Yb}}var $a=Array.isArray(Ea)?2>Ea.length?Ea[0]:null:Ea;"function"!== +typeof $a&&"symbol"!==typeof $a&&null!==$a&&void 0!==$a&&Qc.push(x(""+$a));F(Qc,Rc,Ea)}ta&&e.boundaryResources&&e.boundaryResources.styles.add(ta);g&&a.push("\x3c!-- --\x3e");Pc=void 0}return Pc;case "meta":if(3===f.insertionMode||f.tagScope&1||null!=c.itemProp)var Sc=Hb(a,c,"meta");else g&&a.push("\x3c!-- --\x3e"),Sc="string"===typeof c.charSet?Hb(e.charsetChunks,c,"meta"):"viewport"===c.name?Hb(e.preconnectChunks,c,"meta"):Hb(e.hoistableChunks,c,"meta");return Sc;case "listing":case "pre":a.push(J(b)); +var ab=null,bb=null,cb;for(cb in c)if(w.call(c,cb)){var xb=c[cb];if(null!=xb)switch(cb){case "children":ab=xb;break;case "dangerouslySetInnerHTML":bb=xb;break;default:E(a,cb,xb)}}a.push(">");if(null!=bb){if(null!=ab)throw Error(n(60));if("object"!==typeof bb||!("__html"in bb))throw Error(n(61));var ua=bb.__html;null!==ua&&void 0!==ua&&("string"===typeof ua&&0e.highImagePreloads.size)Zb.delete(db),e.highImagePreloads.add(va)}else d.imageResources.hasOwnProperty(db)||(d.imageResources[db]=kb,va=[],I(va,{rel:"preload",as:"image",href:C?void 0:L,imageSrcSet:C,imageSizes:Tc,crossOrigin:c.crossOrigin,integrity:c.integrity,type:c.type,fetchPriority:c.fetchPriority,referrerPolicy:c.referrerPolicy}),"high"===c.fetchPriority||10>e.highImagePreloads.size?e.highImagePreloads.add(va):(e.bulkPreloads.add(va),Zb.set(db, va)))}return Hb(a,c,"img");case "base":case "area":case "br":case "col":case "embed":case "hr":case "keygen":case "param":case "source":case "track":case "wbr":return Hb(a,c,b);case "annotation-xml":case "color-profile":case "font-face":case "font-face-src":case "font-face-uri":case "font-face-format":case "font-face-name":case "missing-glyph":break;case "head":if(2>f.insertionMode&&null===e.headChunks){e.headChunks=[];var Uc=Kb(e.headChunks,c,"head")}else Uc=Kb(a,c,"head");return Uc;case "html":if(0=== -f.insertionMode&&null===e.htmlChunks){e.htmlChunks=[""];var Vc=Kb(e.htmlChunks,c,"html")}else Vc=Kb(a,c,"html");return Vc;default:if(-1!==b.indexOf("-")){a.push(M(b));var ac=null,Wc=null,ha;for(ha in c)if(v.call(c,ha)){var S=c[ha];if(null!=S&&"function"!==typeof S&&"object"!==typeof S&&!1!==S)switch(!0===S&&(S=""),"className"===ha&&(ha="class"),ha){case "children":ac=S;break;case "dangerouslySetInnerHTML":Wc=S;break;case "style":ob(a,S);break;case "suppressContentEditableWarning":case "suppressHydrationWarning":break; -default:xa(ha)&&"function"!==typeof S&&"symbol"!==typeof S&&a.push(" ",ha,'="',w(S),'"')}}a.push(">");H(a,Wc,ac);return ac}}return Kb(a,c,b)}function Ob(a,b){b=b.bootstrapChunks;for(var c=0;c')} +f.insertionMode&&null===e.htmlChunks){e.htmlChunks=[""];var Vc=Kb(e.htmlChunks,c,"html")}else Vc=Kb(a,c,"html");return Vc;default:if(-1!==b.indexOf("-")){a.push(J(b));var $b=null,Wc=null,Fa;for(Fa in c)if(w.call(c,Fa)){var S=c[Fa];if(null!=S){var Xc=Fa;switch(Fa){case "children":$b=S;break;case "dangerouslySetInnerHTML":Wc=S;break;case "style":ob(a,S);break;case "suppressContentEditableWarning":case "suppressHydrationWarning":break;case "className":Xc="class";default:if(xa(Fa)&&"function"!==typeof S&& +"symbol"!==typeof S&&!1!==S){if(!0===S)S="";else if("object"===typeof S)continue;a.push(" ",Xc,'="',x(S),'"')}}}}a.push(">");F(a,Wc,$b);return $b}}return Kb(a,c,b)}function Ob(a,b){b=b.bootstrapChunks;for(var c=0;c')} function Qb(a,b,c,d){switch(c.insertionMode){case 0:case 1:case 2:return a.push('