diff --git a/crates/next-core/src/next_config.rs b/crates/next-core/src/next_config.rs index 14b90f4544b83..1f77c5faa1777 100644 --- a/crates/next-core/src/next_config.rs +++ b/crates/next-core/src/next_config.rs @@ -1073,11 +1073,6 @@ impl NextConfig { Vc::cell(self.experimental.taint.unwrap_or(false)) } - #[turbo_tasks::function] - pub fn enable_dynamic_io(&self) -> Vc { - Vc::cell(self.experimental.dynamic_io.unwrap_or(false)) - } - #[turbo_tasks::function] pub fn use_swc_css(&self) -> Vc { Vc::cell( diff --git a/crates/next-core/src/next_import_map.rs b/crates/next-core/src/next_import_map.rs index d7c4739868396..20204cd84852e 100644 --- a/crates/next-core/src/next_import_map.rs +++ b/crates/next-core/src/next_import_map.rs @@ -117,14 +117,12 @@ pub async fn get_next_client_import_map( match ty.into_value() { ClientContextType::Pages { .. } => {} ClientContextType::App { app_dir } => { - let react_flavor = if *next_config.enable_ppr().await? - || *next_config.enable_taint().await? - || *next_config.enable_dynamic_io().await? - { - "-experimental" - } else { - "" - }; + let react_flavor = + if *next_config.enable_ppr().await? || *next_config.enable_taint().await? { + "-experimental" + } else { + "" + }; import_map.insert_exact_alias( "react", @@ -686,12 +684,7 @@ async fn rsc_aliases( ) -> Result<()> { let ppr = *next_config.enable_ppr().await?; let taint = *next_config.enable_taint().await?; - let dynamic_io = *next_config.enable_dynamic_io().await?; - let react_channel = if ppr || taint || dynamic_io { - "-experimental" - } else { - "" - }; + let react_channel = if ppr || taint { "-experimental" } else { "" }; let react_client_package = get_react_client_package(&next_config).await?; let mut alias = IndexMap::new(); diff --git a/docs/02-app/01-building-your-application/04-caching/index.mdx b/docs/02-app/01-building-your-application/04-caching/index.mdx index 2ed1ca6b93a99..3a2dcc95ace14 100644 --- a/docs/02-app/01-building-your-application/04-caching/index.mdx +++ b/docs/02-app/01-building-your-application/04-caching/index.mdx @@ -33,7 +33,7 @@ Caching behavior changes depending on whether the route is statically or dynamic ## Request Memoization -Next.js extends the [`fetch` API](#fetch) to automatically **memoize** requests that have the same URL and options. This means you can call a fetch function for the same data in multiple places in a React component tree while only executing it once. +React extends the [`fetch` API](#fetch) to automatically **memoize** requests that have the same URL and options. This means you can call a fetch function for the same data in multiple places in a React component tree while only executing it once. Deduplicated Fetch Requests`](#link) | Cache | | | | -| [`router.prefetch`](#routerprefetch) | Cache | | | | -| [`router.refresh`](#routerrefresh) | Revalidate | | | | -| [`fetch`](#fetch) | | | Cache | Cache | -| [`fetch` `options.cache`](#fetch-optionscache) | | | Cache or Opt out | | -| [`fetch` `options.next.revalidate`](#fetch-optionsnextrevalidate) | | Revalidate | Revalidate | | -| [`fetch` `options.next.tags`](#fetch-optionsnexttags-and-revalidatetag) | | Cache | Cache | | -| [`revalidateTag`](#fetch-optionsnexttags-and-revalidatetag) | Revalidate (Server Action) | Revalidate | Revalidate | | -| [`revalidatePath`](#revalidatepath) | Revalidate (Server Action) | Revalidate | Revalidate | | -| [`const revalidate`](#segment-config-options) | | Revalidate or Opt out | Revalidate or Opt out | | -| [`const dynamic`](#segment-config-options) | | Cache or Opt out | Cache or Opt out | | -| [`cookies`](#cookies) | Revalidate (Server Action) | Opt out | | | -| [`headers`, `searchParams`](#dynamic-functions) | | Opt out | | | -| [`generateStaticParams`](#generatestaticparams) | | Cache | | | -| [`React.cache`](#react-cache-function) | | | | Cache | -| [`unstable_cache`](/docs/app/api-reference/functions/unstable_cache) | | | Cache | | +| API | Router Cache | Full Route Cache | Data Cache | React Request Memoization | +| ----------------------------------------------------------------------- | -------------------------- | --------------------- | --------------------- | ------------------------- | +| [``](#link) | Cache | | | | +| [`router.prefetch`](#routerprefetch) | Cache | | | | +| [`router.refresh`](#routerrefresh) | Revalidate | | | | +| [`fetch`](#fetch) | | | Cache | Cache | +| [`fetch` `options.cache`](#fetch-optionscache) | | | Cache or Opt out | | +| [`fetch` `options.next.revalidate`](#fetch-optionsnextrevalidate) | | Revalidate | Revalidate | | +| [`fetch` `options.next.tags`](#fetch-optionsnexttags-and-revalidatetag) | | Cache | Cache | | +| [`revalidateTag`](#fetch-optionsnexttags-and-revalidatetag) | Revalidate (Server Action) | Revalidate | Revalidate | | +| [`revalidatePath`](#revalidatepath) | Revalidate (Server Action) | Revalidate | Revalidate | | +| [`const revalidate`](#segment-config-options) | | Revalidate or Opt out | Revalidate or Opt out | | +| [`const dynamic`](#segment-config-options) | | Cache or Opt out | Cache or Opt out | | +| [`cookies`](#cookies) | Revalidate (Server Action) | Opt out | | | +| [`headers`, `searchParams`](#dynamic-functions) | | Opt out | | | +| [`generateStaticParams`](#generatestaticparams) | | Cache | | | +| [`React.cache`](#react-cache-function) | | | | Cache | +| [`unstable_cache`](/docs/app/api-reference/functions/unstable_cache) | | | Cache | | ### `` diff --git a/docs/03-pages/02-api-reference/01-components/head.mdx b/docs/03-pages/02-api-reference/01-components/head.mdx index 8328603b80abf..a32354b873360 100644 --- a/docs/03-pages/02-api-reference/01-components/head.mdx +++ b/docs/03-pages/02-api-reference/01-components/head.mdx @@ -57,6 +57,8 @@ export default IndexPage In this case only the second `` is rendered. `meta` tags with duplicate `key` attributes are automatically handled. +> **Good to know**: `` and `<base>` tags are automatically checked for duplicates by Next.js, so using key is not necessary for these tags. + > The contents of `head` get cleared upon unmounting the component, so make sure each page completely defines what it needs in `head`, without making assumptions about what other pages added. ## Use minimal nesting diff --git a/errors/next-request-in-use-cache.md b/errors/next-request-in-use-cache.md new file mode 100644 index 0000000000000..a3855e089c6c6 --- /dev/null +++ b/errors/next-request-in-use-cache.md @@ -0,0 +1,51 @@ +--- +title: Cannot access `cookies()` or `headers()` in `"use cache"` +--- + +#### Why This Error Occurred + +A function is trying to read from the current incoming request inside the scope of a function annotated with `"use cache"`. This is not supported because it would make the cache invalidated by every request which is probably not what you intended. + +#### Possible Ways to Fix It + +Instead of calling this inside the `"use cache"` function, move it outside the function and pass the value in as an argument. The specific value will now be part of the cache key through its arguments. + +Before: + +```jsx filename="app/page.js" +import { cookies } from 'next/headers' + +async function getExampleData() { + "use cache" +- const isLoggedIn = (await cookies()).has('token') + ... +} + +export default async function Page() { + const data = await getExampleData() + return ... +} +``` + +After: + +```jsx filename="app/page.js" +import { cookies } from 'next/headers' + +async function getExampleData(isLoggedIn) { + "use cache" + ... +} + +export default async function Page() { ++ const isLoggedIn = (await cookies()).has('token') + const data = await getExampleData(isLoggedIn) + return ... +} +``` + +### Useful Links + +- [`headers()` function](https://nextjs.org/docs/app/api-reference/functions/headers) +- [`cookies()` function](https://nextjs.org/docs/app/api-reference/functions/cookies) +- [`draftMode()` function](https://nextjs.org/docs/app/api-reference/functions/draft-mode) diff --git a/examples/environment-variables/app/layout.tsx b/examples/environment-variables/app/layout.tsx new file mode 100644 index 0000000000000..5ff842ef07b83 --- /dev/null +++ b/examples/environment-variables/app/layout.tsx @@ -0,0 +1,16 @@ +export const metadata = { + title: "Next.js", + description: "Generated by Next.js", +}; + +export default function RootLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( + <html lang="en"> + <body>{children}</body> + </html> + ); +} diff --git a/examples/environment-variables/app/page.tsx b/examples/environment-variables/app/page.tsx new file mode 100644 index 0000000000000..d8b6704d0963a --- /dev/null +++ b/examples/environment-variables/app/page.tsx @@ -0,0 +1,123 @@ +import Link from "next/link"; +import styles from "../styles.module.css"; + +type CodeProps = { + children: React.ReactNode; +}; + +const Code = ({ children }: CodeProps) => ( + <code className={styles.inlineCode}>{children}</code> +); + +const IndexPage = () => { + // The following console.log statements will only be executed on Node.js. + // Check the terminal to see the environment variables. + // Using the variables below in the browser will return `undefined`. + // Next.js doesn't expose environment variables unless they start with `NEXT_PUBLIC_`. + console.log("[Node.js only] ENV_VARIABLE:", process.env.ENV_VARIABLE); + console.log( + "[Node.js only] ENV_LOCAL_VARIABLE:", + process.env.ENV_LOCAL_VARIABLE, + ); + + return ( + <div className={styles.container}> + <div className={styles.card}> + <h1>Environment Variables with Next.js</h1> + <hr className={styles.hr} /> + <p> + In the table below you'll see how{" "} + <Link href="https://nextjs.org/docs/app/building-your-application/configuring/environment-variables"> + environment variables can be exposed to the browser + </Link>{" "} + with Next.js. + </p> + <p> + In general only <Code>.env.local</Code> or <Code>.env</Code> are + needed for this, but the table also features the usage of{" "} + <Code>.env.development</Code> and <Code>.env.production</Code>. + </p> + <table className={styles.table}> + <thead> + <tr> + <th>Variable Name</th> + <th>Value</th> + <th>Added By</th> + </tr> + </thead> + <tbody> + <tr> + <td>NEXT_PUBLIC_ENV_VARIABLE</td> + <td>{process.env.NEXT_PUBLIC_ENV_VARIABLE}</td> + <td> + <Code>.env</Code> + </td> + </tr> + <tr> + <td>NEXT_PUBLIC_ENV_LOCAL_VARIABLE</td> + <td>{process.env.NEXT_PUBLIC_ENV_LOCAL_VARIABLE}</td> + <td> + <Code>.env.local</Code> + </td> + </tr> + <tr> + <td>NEXT_PUBLIC_DEVELOPMENT_ENV_VARIABLE</td> + + <td>{process.env.NEXT_PUBLIC_DEVELOPMENT_ENV_VARIABLE}</td> + <td> + <Code>.env.development</Code> + </td> + </tr> + <tr> + <td>NEXT_PUBLIC_PRODUCTION_ENV_VARIABLE</td> + + <td>{process.env.NEXT_PUBLIC_PRODUCTION_ENV_VARIABLE}</td> + <td> + <Code>.env.production</Code> + </td> + </tr> + </tbody> + </table> + <p> + <Code>.env.local</Code> is not added by the example, because it must + be ignored by git, but you can add it manually: + </p> + <pre> + <code>cp .env.local.example .env.local</code> + </pre> + <p> + Variables in <Code>.env.production</Code> won't be available if the + app is running in development: + </p> + <pre> + <code>npm run dev</code> + </pre> + <p> + Similarly, variables in <Code>.env.development</Code> won't be + available if the app is running on production: + </p> + <pre> + <code>npm run build && npm run start</code> + </pre> + <p>Once you run the app, you'll see logs like these in the terminal:</p> + <pre> + <code> + info - Loaded env from /home/user/../.env.local{"\n"} + info - Loaded env from /home/user/../.env.development{"\n"} + info - Loaded env from /home/user/../.env{"\n"} + </code> + </pre> + <p> + The order is important, the first loaded env will have a higher + priority. + </p> + <p> + <Code>.env</Code> will not overwrite any variables defined in{" "} + <Code>.env.local</Code> or <Code>.env.development</Code>. + </p> + </div> + </div> + ); +}; + +export default IndexPage; diff --git a/examples/environment-variables/next-env.d.ts b/examples/environment-variables/next-env.d.ts index a4a7b3f5cfa2f..40c3d68096c27 100644 --- a/examples/environment-variables/next-env.d.ts +++ b/examples/environment-variables/next-env.d.ts @@ -2,4 +2,4 @@ /// <reference types="next/image-types/global" /> // NOTE: This file should not be edited -// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information. +// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information. diff --git a/examples/environment-variables/package.json b/examples/environment-variables/package.json index be18b903df87a..3dc5c56184231 100644 --- a/examples/environment-variables/package.json +++ b/examples/environment-variables/package.json @@ -1,19 +1,19 @@ { "private": true, "scripts": { - "dev": "next", + "dev": "next dev", "build": "next build", "start": "next start" }, "dependencies": { "next": "latest", - "react": "^18.2.0", - "react-dom": "^18.2.0" + "react": "^18.3.1", + "react-dom": "^18.3.1" }, "devDependencies": { - "@types/node": "^18.11.5", - "@types/react": "^18.0.23", - "@types/react-dom": "^18.0.7", - "typescript": "^4.8.4" + "@types/node": "^22.7.4", + "@types/react": "^18.3.10", + "@types/react-dom": "^18.3.0", + "typescript": "^5.6.2" } } diff --git a/examples/environment-variables/pages/index.tsx b/examples/environment-variables/pages/index.tsx deleted file mode 100644 index 3df6221da8cad..0000000000000 --- a/examples/environment-variables/pages/index.tsx +++ /dev/null @@ -1,125 +0,0 @@ -import Link from "next/link"; -import styles from "../styles.module.css"; - -type CodeProps = { - children: React.ReactNode; -}; - -const Code = ({ children }: CodeProps) => ( - <code className={styles.inlineCode}>{children}</code> -); - -const IndexPage = () => ( - <div className={styles.container}> - <div className={styles.card}> - <h1>Environment Variables with Next.js</h1> - <hr className={styles.hr} /> - <p> - In the table below you'll see how{" "} - <Link href="https://nextjs.org/docs/basic-features/environment-variables#exposing-environment-variables-to-the-browser"> - environment variables can be exposed to the browser - </Link>{" "} - with Next.js. - </p> - <p> - In general only <Code>.env.local</Code> or <Code>.env</Code> are needed - for this, but the table also features the usage of{" "} - <Code>.env.development</Code> and <Code>.env.production</Code>. - </p> - <table className={styles.table}> - <thead> - <tr> - <th>Variable Name</th> - <th>Value</th> - <th>Added By</th> - </tr> - </thead> - <tbody> - <tr> - <td>NEXT_PUBLIC_ENV_VARIABLE</td> - <td>{process.env.NEXT_PUBLIC_ENV_VARIABLE}</td> - <td> - <Code>.env</Code> - </td> - </tr> - <tr> - <td>NEXT_PUBLIC_ENV_LOCAL_VARIABLE</td> - <td>{process.env.NEXT_PUBLIC_ENV_LOCAL_VARIABLE}</td> - <td> - <Code>.env.local</Code> - </td> - </tr> - <tr> - <td>NEXT_PUBLIC_DEVELOPMENT_ENV_VARIABLE</td> - - <td>{process.env.NEXT_PUBLIC_DEVELOPMENT_ENV_VARIABLE}</td> - <td> - <Code>.env.development</Code> - </td> - </tr> - <tr> - <td>NEXT_PUBLIC_PRODUCTION_ENV_VARIABLE</td> - - <td>{process.env.NEXT_PUBLIC_PRODUCTION_ENV_VARIABLE}</td> - <td> - <Code>.env.production</Code> - </td> - </tr> - </tbody> - </table> - <p> - <Code>.env.local</Code> is not added by the example, because it must be - ignored by git, but you can add it manually: - </p> - <pre> - <code>cp .env.local.example .env.local</code> - </pre> - <p> - Variables in <Code>.env.production</Code> won't be available if the app - is running in development: - </p> - <pre> - <code>npm run dev</code> - </pre> - <p> - Similarly, variables in <Code>.env.development</Code> won't be available - if the app is running on production: - </p> - <pre> - <code>npm run build && npm run start</code> - </pre> - <p>Once you run the app, you'll see logs like these in the terminal:</p> - <pre> - <code> - info - Loaded env from /home/user/../.env.local{"\n"} - info - Loaded env from /home/user/../.env.development{"\n"} - info - Loaded env from /home/user/../.env{"\n"} - </code> - </pre> - <p> - The order is important, the first loaded env will have a higher - priority. - </p> - <p> - <Code>.env</Code> will not overwrite any variables defined in{" "} - <Code>.env.local</Code> or <Code>.env.development</Code>. - </p> - </div> - </div> -); - -// `getStaticProps`, and similar Next.js methods like `getStaticPaths` and `getServerSideProps` -// only run in Node.js. Check the terminal to see the environment variables -export async function getStaticProps() { - // Using the variables below in the browser will return `undefined`. Next.js doesn't - // expose environment variables unless they start with `NEXT_PUBLIC_` - console.log("[Node.js only] ENV_VARIABLE:", process.env.ENV_VARIABLE); - console.log( - "[Node.js only] ENV_LOCAL_VARIABLE:", - process.env.ENV_LOCAL_VARIABLE, - ); - - return { props: {} }; -} - -export default IndexPage; diff --git a/examples/environment-variables/readme.md b/examples/environment-variables/readme.md index ea86f6b5a6ae1..8347fe8c67fdc 100644 --- a/examples/environment-variables/readme.md +++ b/examples/environment-variables/readme.md @@ -2,7 +2,7 @@ This example shows how to use [environment variables in Next.js](https://nextjs.org/docs/basic-features/environment-variables). -The index page ([pages/index.js](pages/index.js)) will show you how to [access environment variables in the server](https://nextjs.org/docs/basic-features/environment-variables#loading-environment-variables), and how to [expose environment variables to the browser](https://nextjs.org/docs/basic-features/environment-variables#exposing-environment-variables-to-the-browser). +The index page ([app/page.tsx](app/page.tsx)) will show you how to [access environment variables in the server](https://nextjs.org/docs/app/building-your-application/configuring/environment-variables), and how to [expose environment variables to the browser](https://nextjs.org/docs/basic-features/environment-variables#exposing-environment-variables-to-the-browser). ## Deploy your own diff --git a/examples/environment-variables/tsconfig.json b/examples/environment-variables/tsconfig.json index 0c8fa8791dfd6..42f19dc05c424 100644 --- a/examples/environment-variables/tsconfig.json +++ b/examples/environment-variables/tsconfig.json @@ -13,8 +13,20 @@ "resolveJsonModule": true, "isolatedModules": true, "jsx": "preserve", - "incremental": true + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "strictNullChecks": true }, - "include": ["next-env.d.ts", "environment.d.ts", "**/*.ts", "**/*.tsx"], + "include": [ + "next-env.d.ts", + "environment.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts" + ], "exclude": ["node_modules"] } diff --git a/examples/reproduction-template/package.json b/examples/reproduction-template/package.json index 5cb957f196733..51065260756e0 100644 --- a/examples/reproduction-template/package.json +++ b/examples/reproduction-template/package.json @@ -7,8 +7,8 @@ }, "dependencies": { "next": "canary", - "react": "19.0.0-rc-3edc000d-20240926", - "react-dom": "19.0.0-rc-3edc000d-20240926" + "react": "19.0.0-rc-2d16326d-20240930", + "react-dom": "19.0.0-rc-2d16326d-20240930" }, "devDependencies": { "@types/node": "20.12.12", diff --git a/lerna.json b/lerna.json index dc728c88e58f1..c4ecf791d1447 100644 --- a/lerna.json +++ b/lerna.json @@ -16,5 +16,5 @@ "registry": "https://registry.npmjs.org/" } }, - "version": "15.0.0-canary.173" + "version": "15.0.0-canary.174" } diff --git a/package.json b/package.json index fafaa93176037..ce38a48dbdd18 100644 --- a/package.json +++ b/package.json @@ -208,19 +208,19 @@ "pretty-bytes": "5.3.0", "pretty-ms": "7.0.0", "random-seed": "0.3.0", - "react": "19.0.0-rc-3edc000d-20240926", + "react": "19.0.0-rc-2d16326d-20240930", "react-17": "npm:react@17.0.2", - "react-builtin": "npm:react@19.0.0-rc-3edc000d-20240926", - "react-dom": "19.0.0-rc-3edc000d-20240926", + "react-builtin": "npm:react@19.0.0-rc-2d16326d-20240930", + "react-dom": "19.0.0-rc-2d16326d-20240930", "react-dom-17": "npm:react-dom@17.0.2", - "react-dom-builtin": "npm:react-dom@19.0.0-rc-3edc000d-20240926", - "react-dom-experimental-builtin": "npm:react-dom@0.0.0-experimental-3edc000d-20240926", - "react-experimental-builtin": "npm:react@0.0.0-experimental-3edc000d-20240926", - "react-is-builtin": "npm:react-is@19.0.0-rc-3edc000d-20240926", - "react-server-dom-turbopack": "19.0.0-rc-3edc000d-20240926", - "react-server-dom-turbopack-experimental": "npm:react-server-dom-turbopack@0.0.0-experimental-3edc000d-20240926", - "react-server-dom-webpack": "19.0.0-rc-3edc000d-20240926", - "react-server-dom-webpack-experimental": "npm:react-server-dom-webpack@0.0.0-experimental-3edc000d-20240926", + "react-dom-builtin": "npm:react-dom@19.0.0-rc-2d16326d-20240930", + "react-dom-experimental-builtin": "npm:react-dom@0.0.0-experimental-2d16326d-20240930", + "react-experimental-builtin": "npm:react@0.0.0-experimental-2d16326d-20240930", + "react-is-builtin": "npm:react-is@19.0.0-rc-2d16326d-20240930", + "react-server-dom-turbopack": "19.0.0-rc-2d16326d-20240930", + "react-server-dom-turbopack-experimental": "npm:react-server-dom-turbopack@0.0.0-experimental-2d16326d-20240930", + "react-server-dom-webpack": "19.0.0-rc-2d16326d-20240930", + "react-server-dom-webpack-experimental": "npm:react-server-dom-webpack@0.0.0-experimental-2d16326d-20240930", "react-ssr-prepass": "1.0.8", "react-virtualized": "9.22.3", "relay-compiler": "13.0.2", @@ -230,8 +230,8 @@ "resolve-from": "5.0.0", "sass": "1.54.0", "satori": "0.10.9", - "scheduler-builtin": "npm:scheduler@0.25.0-rc-3edc000d-20240926", - "scheduler-experimental-builtin": "npm:scheduler@0.0.0-experimental-3edc000d-20240926", + "scheduler-builtin": "npm:scheduler@0.25.0-rc-2d16326d-20240930", + "scheduler-experimental-builtin": "npm:scheduler@0.0.0-experimental-2d16326d-20240930", "seedrandom": "3.0.5", "semver": "7.3.7", "shell-quote": "1.7.3", @@ -271,10 +271,10 @@ "@babel/traverse": "7.22.5", "@types/react": "npm:types-react@19.0.0-rc.0", "@types/react-dom": "npm:types-react-dom@19.0.0-rc.0", - "react": "19.0.0-rc-3edc000d-20240926", - "react-dom": "19.0.0-rc-3edc000d-20240926", - "react-is": "19.0.0-rc-3edc000d-20240926", - "scheduler": "0.25.0-rc-3edc000d-20240926" + "react": "19.0.0-rc-2d16326d-20240930", + "react-dom": "19.0.0-rc-2d16326d-20240930", + "react-is": "19.0.0-rc-2d16326d-20240930", + "scheduler": "0.25.0-rc-2d16326d-20240930" }, "patchedDependencies": { "webpack-sources@3.2.3": "patches/webpack-sources@3.2.3.patch" diff --git a/packages/create-next-app/package.json b/packages/create-next-app/package.json index 70572d3a5bf02..8989bf780018c 100644 --- a/packages/create-next-app/package.json +++ b/packages/create-next-app/package.json @@ -1,6 +1,6 @@ { "name": "create-next-app", - "version": "15.0.0-canary.173", + "version": "15.0.0-canary.174", "keywords": [ "react", "next", diff --git a/packages/create-next-app/templates/index.ts b/packages/create-next-app/templates/index.ts index 6ddaba79c0dff..81595566bf5bb 100644 --- a/packages/create-next-app/templates/index.ts +++ b/packages/create-next-app/templates/index.ts @@ -13,7 +13,7 @@ import { GetTemplateFileArgs, InstallTemplateArgs } from "./types"; // Do not rename or format. sync-react script relies on this line. // prettier-ignore -const nextjsReactPeerVersion = "19.0.0-rc-3edc000d-20240926"; +const nextjsReactPeerVersion = "19.0.0-rc-2d16326d-20240930"; /** * Get the file path for a given file in a template, e.g. "next.config.js". diff --git a/packages/eslint-config-next/package.json b/packages/eslint-config-next/package.json index d965081677a85..3d03112f9ba6f 100644 --- a/packages/eslint-config-next/package.json +++ b/packages/eslint-config-next/package.json @@ -1,6 +1,6 @@ { "name": "eslint-config-next", - "version": "15.0.0-canary.173", + "version": "15.0.0-canary.174", "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": "15.0.0-canary.173", + "@next/eslint-plugin-next": "15.0.0-canary.174", "@rushstack/eslint-patch": "^1.3.3", "@typescript-eslint/eslint-plugin": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", diff --git a/packages/eslint-plugin-next/package.json b/packages/eslint-plugin-next/package.json index 5ccbb6eac36ed..00255e39c7bc3 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": "15.0.0-canary.173", + "version": "15.0.0-canary.174", "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 15a621e4e558b..1384aafa960ba 100644 --- a/packages/font/package.json +++ b/packages/font/package.json @@ -1,7 +1,7 @@ { "name": "@next/font", "private": true, - "version": "15.0.0-canary.173", + "version": "15.0.0-canary.174", "repository": { "url": "vercel/next.js", "directory": "packages/font" diff --git a/packages/font/src/google/font-data.json b/packages/font/src/google/font-data.json index be595e1ed7b5f..97d67206abba4 100644 --- a/packages/font/src/google/font-data.json +++ b/packages/font/src/google/font-data.json @@ -123,6 +123,37 @@ "vietnamese" ] }, + "Afacad Flux": { + "weights": [ + "100", + "200", + "300", + "400", + "500", + "600", + "700", + "800", + "900", + "1000", + "variable" + ], + "styles": ["normal"], + "axes": [ + { + "tag": "slnt", + "min": -14, + "max": 14, + "defaultValue": 0 + }, + { + "tag": "wght", + "min": 100, + "max": 1000, + "defaultValue": 400 + } + ], + "subsets": ["latin", "latin-ext", "vietnamese"] + }, "Agbalumo": { "weights": ["400"], "styles": ["normal"], @@ -6443,7 +6474,7 @@ "defaultValue": 400 } ], - "subsets": ["latin", "latin-ext", "vietnamese"] + "subsets": ["cyrillic", "cyrillic-ext", "latin", "latin-ext", "vietnamese"] }, "Licorice": { "weights": ["400"], @@ -13709,6 +13740,37 @@ ], "subsets": ["latin", "latin-ext", "math", "symbols"] }, + "Sixtyfour Convergence": { + "weights": ["400", "variable"], + "styles": ["normal"], + "axes": [ + { + "tag": "BLED", + "min": 0, + "max": 100, + "defaultValue": 0 + }, + { + "tag": "SCAN", + "min": -53, + "max": 100, + "defaultValue": 0 + }, + { + "tag": "XELA", + "min": -100, + "max": 100, + "defaultValue": 0 + }, + { + "tag": "YELA", + "min": -100, + "max": 100, + "defaultValue": 0 + } + ], + "subsets": ["latin", "latin-ext", "math", "symbols"] + }, "Skranji": { "weights": ["400", "700"], "styles": ["normal"], diff --git a/packages/font/src/google/index.ts b/packages/font/src/google/index.ts index e014c9a02fef6..3e47782f2a84e 100644 --- a/packages/font/src/google/index.ts +++ b/packages/font/src/google/index.ts @@ -210,6 +210,42 @@ export declare function Afacad< 'cyrillic-ext' | 'latin' | 'latin-ext' | 'math' | 'symbols' | 'vietnamese' > }): T extends undefined ? NextFont : NextFontWithVariable +export declare function Afacad_Flux< + T extends CssVariable | undefined = undefined, +>(options?: { + weight?: + | '100' + | '200' + | '300' + | '400' + | '500' + | '600' + | '700' + | '800' + | '900' + | '1000' + | 'variable' + | Array< + | '100' + | '200' + | '300' + | '400' + | '500' + | '600' + | '700' + | '800' + | '900' + | '1000' + > + style?: 'normal' | Array<'normal'> + display?: Display + variable?: T + preload?: boolean + fallback?: string[] + adjustFontFallback?: boolean + subsets?: Array<'latin' | 'latin-ext' | 'vietnamese'> + axes?: 'slnt'[] +}): T extends undefined ? NextFont : NextFontWithVariable export declare function Agbalumo< T extends CssVariable | undefined = undefined, >(options: { @@ -11463,7 +11499,9 @@ export declare function Libre_Franklin< preload?: boolean fallback?: string[] adjustFontFallback?: boolean - subsets?: Array<'latin' | 'latin-ext' | 'vietnamese'> + subsets?: Array< + 'cyrillic' | 'cyrillic-ext' | 'latin' | 'latin-ext' | 'vietnamese' + > }): T extends undefined ? NextFont : NextFontWithVariable export declare function Licorice< T extends CssVariable | undefined = undefined, @@ -22986,6 +23024,19 @@ export declare function Sixtyfour< subsets?: Array<'latin' | 'latin-ext' | 'math' | 'symbols'> axes?: ('BLED' | 'SCAN')[] }): T extends undefined ? NextFont : NextFontWithVariable +export declare function Sixtyfour_Convergence< + T extends CssVariable | undefined = undefined, +>(options?: { + weight?: '400' | 'variable' | Array<'400'> + style?: 'normal' | Array<'normal'> + display?: Display + variable?: T + preload?: boolean + fallback?: string[] + adjustFontFallback?: boolean + subsets?: Array<'latin' | 'latin-ext' | 'math' | 'symbols'> + axes?: ('BLED' | 'SCAN' | 'XELA' | 'YELA')[] +}): T extends undefined ? NextFont : NextFontWithVariable export declare function Skranji< T extends CssVariable | undefined = undefined, >(options: { diff --git a/packages/next-bundle-analyzer/package.json b/packages/next-bundle-analyzer/package.json index d65332f296e65..3d50987d41d06 100644 --- a/packages/next-bundle-analyzer/package.json +++ b/packages/next-bundle-analyzer/package.json @@ -1,6 +1,6 @@ { "name": "@next/bundle-analyzer", - "version": "15.0.0-canary.173", + "version": "15.0.0-canary.174", "main": "index.js", "types": "index.d.ts", "license": "MIT", diff --git a/packages/next-codemod/bin/next-codemod.ts b/packages/next-codemod/bin/next-codemod.ts index d47e596a481c5..58f4964b365e1 100644 --- a/packages/next-codemod/bin/next-codemod.ts +++ b/packages/next-codemod/bin/next-codemod.ts @@ -46,7 +46,12 @@ program .description( 'Upgrade Next.js apps to desired versions with a single command.' ) - .usage('[options]') + + .argument( + '[revision]', + 'NPM dist tag or exact version to upgrade to (e.g. "latest" or "15.0.0-canary.167"). Prompts to choose a dist tag if omitted.' + ) + .option('--verbose', 'Verbose output', false) .action(runUpgrade) program.parse(process.argv) diff --git a/packages/next-codemod/bin/transform.ts b/packages/next-codemod/bin/transform.ts index 4ef9f14017c87..13d95c264bff3 100644 --- a/packages/next-codemod/bin/transform.ts +++ b/packages/next-codemod/bin/transform.ts @@ -2,7 +2,7 @@ import execa from 'execa' import globby from 'globby' import prompts from 'prompts' import { join } from 'node:path' -import { installPackage, uninstallPackage } from '../lib/handle-package' +import { installPackages, uninstallPackage } from '../lib/handle-package' import { checkGitStatus, TRANSFORMER_INQUIRER_CHOICES } from '../lib/utils' function expandFilePathsIfNeeded(filesBeforeExpansion) { @@ -128,6 +128,6 @@ export async function runTransform( if (!dry && transformer === 'next-request-geo-ip') { console.log('Installing `@vercel/functions`...') - installPackage('@vercel/functions') + installPackages(['@vercel/functions']) } } diff --git a/packages/next-codemod/bin/upgrade.ts b/packages/next-codemod/bin/upgrade.ts index c470fd8059d57..12d4ece813ced 100644 --- a/packages/next-codemod/bin/upgrade.ts +++ b/packages/next-codemod/bin/upgrade.ts @@ -5,7 +5,8 @@ import path from 'path' import { compareVersions } from 'compare-versions' import chalk from 'chalk' import { availableCodemods } from '../lib/codemods' -import { getPkgManager, installPackage } from '../lib/handle-package' +import { getPkgManager, installPackages } from '../lib/handle-package' +import { runTransform } from './transform' type StandardVersionSpecifier = 'canary' | 'rc' | 'latest' type CustomVersionSpecifier = string @@ -16,26 +17,49 @@ interface Response { version: StandardVersionSpecifier } -export async function runUpgrade(): Promise<void> { +/** + * @param query + * @example loadHighestNPMVersionMatching("react@^18.3.0 || ^19.0.0") === Promise<"19.0.0"> + */ +async function loadHighestNPMVersionMatching(query: string) { + const versionsJSON = execSync( + `npm --silent view "${query}" --json --field version`, + { encoding: 'utf-8' } + ) + const versions = JSON.parse(versionsJSON) + if (versions.length < 1) { + throw new Error( + `Found no React versions matching "${query}". This is a bug in the upgrade tool.` + ) + } + + return versions[versions.length - 1] +} + +export async function runUpgrade( + revision: string | undefined, + options: { verbose: boolean } +): Promise<void> { + const { verbose } = options const appPackageJsonPath = path.resolve(process.cwd(), 'package.json') let appPackageJson = JSON.parse(fs.readFileSync(appPackageJsonPath, 'utf8')) await detectWorkspace(appPackageJson) - let targetNextPackageJson + let targetNextPackageJson: { + version: string + peerDependencies: Record<string, string> + } let targetVersionSpecifier: VersionSpecifier = '' - const shortcutVersion = process.argv[2]?.replace('@', '') - if (shortcutVersion) { - const res = await fetch( - `https://registry.npmjs.org/next/${shortcutVersion}` - ) + if (revision !== undefined) { + const res = await fetch(`https://registry.npmjs.org/next/${revision}`) if (res.status === 200) { targetNextPackageJson = await res.json() targetVersionSpecifier = targetNextPackageJson.version } else { console.error( - `${chalk.yellow('Next.js ' + shortcutVersion)} does not exist. Check available versions at ${chalk.underline('https://www.npmjs.com/package/next?activeTab=versions')}, or choose one from below\n` + `${chalk.yellow(`next@${revision}`)} does not exist. Check available versions at ${chalk.underline('https://www.npmjs.com/package/next?activeTab=versions')}, or choose one from below\n` ) } } @@ -115,10 +139,28 @@ export async function runUpgrade(): Promise<void> { const targetNextVersion = targetNextPackageJson.version - if ( - targetNextVersion && - compareVersions(targetNextVersion, '15.0.0-canary') >= 0 - ) { + // We're resolving a specific version here to avoid including "ugly" version queries + // in the manifest. + // E.g. in peerDependencies we could have `^18.2.0 || ^19.0.0 || 20.0.0-canary` + // If we'd just `npm add` that, the manifest would read the same version query. + // This is basically a `npm --save-exact react@$versionQuery` that works for every package manager. + const [ + targetReactVersion, + targetReactTypesVersion, + targetReactDOMTypesVersion, + ] = await Promise.all([ + loadHighestNPMVersionMatching( + `react@${targetNextPackageJson.peerDependencies['react']}` + ), + loadHighestNPMVersionMatching( + `@types/react@${targetNextPackageJson.peerDependencies['react']}` + ), + loadHighestNPMVersionMatching( + `@types/react-dom@${targetNextPackageJson.peerDependencies['react']}` + ), + ]) + + if (compareVersions(targetNextVersion, '15.0.0-canary') >= 0) { await suggestTurbopack(appPackageJson) } @@ -127,18 +169,30 @@ export async function runUpgrade(): Promise<void> { const packageManager: PackageManager = getPkgManager(process.cwd()) const nextDependency = `next@${targetNextVersion}` const reactDependencies = [ - `react@${targetNextPackageJson.peerDependencies['react']}`, - `@types/react@${targetNextPackageJson.devDependencies['@types/react']}`, - `react-dom@${targetNextPackageJson.peerDependencies['react-dom']}`, - `@types/react-dom@${targetNextPackageJson.devDependencies['@types/react-dom']}`, + `react@${targetReactVersion}`, + `react-dom@${targetReactVersion}`, ] - - installPackage([nextDependency, ...reactDependencies], packageManager) + if ( + targetReactVersion.startsWith('19.0.0-canary') || + targetReactVersion.startsWith('19.0.0-beta') || + targetReactVersion.startsWith('19.0.0-rc') + ) { + reactDependencies.push(`@types/react@npm:types-react@rc`) + reactDependencies.push(`@types/react-dom@npm:types-react-dom@rc`) + } else { + reactDependencies.push(`@types/react@${targetReactTypesVersion}`) + reactDependencies.push(`@types/react-dom@${targetReactDOMTypesVersion}`) + } console.log( `Upgrading your project to ${chalk.blue('Next.js ' + targetVersionSpecifier)}...\n` ) + installPackages([nextDependency, ...reactDependencies], { + packageManager, + silent: !verbose, + }) + await suggestCodemods(installedNextVersion, targetNextVersion) console.log( @@ -284,20 +338,18 @@ async function suggestCodemods( return } - let codemodsString = `\nThe following ${chalk.blue('codemods')} are available for your upgrade:` - relevantCodemods.forEach((codemod) => { - codemodsString += `\n- ${codemod.title} ${chalk.gray(`(${codemod.value})`)}` - }) - codemodsString += '\n' - - console.log(codemodsString) - - const responseCodemods = await prompts( + const { codemods } = await prompts( { - type: 'confirm', - name: 'apply', - message: `Do you want to apply these codemods?`, - initial: true, + type: 'multiselect', + name: 'codemods', + message: `\nThe following ${chalk.blue('codemods')} are recommended for your upgrade. Would you like to apply them?`, + choices: relevantCodemods.map((codemod) => { + return { + title: `${codemod.title} ${chalk.grey(`(${codemod.value})`)}`, + value: codemod.value, + selected: true, + } + }), }, { onCancel: () => { @@ -306,16 +358,7 @@ async function suggestCodemods( } ) - if (!responseCodemods.apply) { - return - } - - for (const codemod of relevantCodemods) { - execSync( - `npx @next/codemod@latest ${codemod.value} ${process.cwd()} --force`, - { - stdio: 'inherit', - } - ) + for (const codemod of codemods) { + await runTransform(codemod, process.cwd(), { force: true }) } } diff --git a/packages/next-codemod/lib/codemods.ts b/packages/next-codemod/lib/codemods.ts index e22dc96a89bf2..42dd10aef757c 100644 --- a/packages/next-codemod/lib/codemods.ts +++ b/packages/next-codemod/lib/codemods.ts @@ -94,16 +94,21 @@ export const availableCodemods: VersionCodemods[] = [ ], }, { - version: '15.0', + version: '15.0.0-canary.153', codemods: [ - { - title: 'Transforms usage of Next.js async Request APIs', - value: 'next-async-request-api', - }, { title: 'Migrate `geo` and `ip` properties on `NextRequest`', value: 'next-request-geo-ip', }, ], }, + { + version: '15.0.0-canary.171', + codemods: [ + { + title: 'Transforms usage of Next.js async Request APIs', + value: 'next-async-request-api', + }, + ], + }, ] diff --git a/packages/next-codemod/lib/handle-package.ts b/packages/next-codemod/lib/handle-package.ts index 88c6486ae720b..d4b298642f216 100644 --- a/packages/next-codemod/lib/handle-package.ts +++ b/packages/next-codemod/lib/handle-package.ts @@ -56,19 +56,20 @@ export function uninstallPackage( execa.sync(pkgManager, [command, packageToUninstall], { stdio: 'inherit' }) } -export function installPackage( - packageToInstall: string | string[], - pkgManager?: PackageManager +export function installPackages( + packageToInstall: string[], + options: { packageManager?: PackageManager; silent?: boolean } = {} ) { - pkgManager ??= getPkgManager(process.cwd()) - if (!pkgManager) throw new Error('Failed to find package manager') + const { packageManager = getPkgManager(process.cwd()), silent = false } = + options - if (Array.isArray(packageToInstall)) { - packageToInstall = packageToInstall.join(' ') - } + if (!packageManager) throw new Error('Failed to find package manager') try { - execa.sync(pkgManager, ['add', packageToInstall], { stdio: 'inherit' }) + execa.sync(packageManager, ['add', ...packageToInstall], { + // Keeping stderr since it'll likely be relevant later when it fails. + stdio: silent ? ['ignore', 'ignore', 'inherit'] : 'inherit', + }) } catch (error) { throw new Error( `Failed to install "${packageToInstall}". Please install it manually.`, diff --git a/packages/next-codemod/package.json b/packages/next-codemod/package.json index d8506f7538366..e0cc94b654b26 100644 --- a/packages/next-codemod/package.json +++ b/packages/next-codemod/package.json @@ -1,6 +1,6 @@ { "name": "@next/codemod", - "version": "15.0.0-canary.173", + "version": "15.0.0-canary.174", "license": "MIT", "repository": { "type": "git", diff --git a/packages/next-env/package.json b/packages/next-env/package.json index 6afa634b21406..c1e61b70a3067 100644 --- a/packages/next-env/package.json +++ b/packages/next-env/package.json @@ -1,6 +1,6 @@ { "name": "@next/env", - "version": "15.0.0-canary.173", + "version": "15.0.0-canary.174", "keywords": [ "react", "next", diff --git a/packages/next-mdx/package.json b/packages/next-mdx/package.json index 87008a2e23bf2..a10134237ade4 100644 --- a/packages/next-mdx/package.json +++ b/packages/next-mdx/package.json @@ -1,6 +1,6 @@ { "name": "@next/mdx", - "version": "15.0.0-canary.173", + "version": "15.0.0-canary.174", "main": "index.js", "license": "MIT", "repository": { diff --git a/packages/next-plugin-storybook/package.json b/packages/next-plugin-storybook/package.json index 1c742fb5181ea..3864f6fac0f8c 100644 --- a/packages/next-plugin-storybook/package.json +++ b/packages/next-plugin-storybook/package.json @@ -1,6 +1,6 @@ { "name": "@next/plugin-storybook", - "version": "15.0.0-canary.173", + "version": "15.0.0-canary.174", "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 1d55337b59453..0059628b24bc7 100644 --- a/packages/next-polyfill-module/package.json +++ b/packages/next-polyfill-module/package.json @@ -1,6 +1,6 @@ { "name": "@next/polyfill-module", - "version": "15.0.0-canary.173", + "version": "15.0.0-canary.174", "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 35a39c1671c24..7467246da7e69 100644 --- a/packages/next-polyfill-nomodule/package.json +++ b/packages/next-polyfill-nomodule/package.json @@ -1,6 +1,6 @@ { "name": "@next/polyfill-nomodule", - "version": "15.0.0-canary.173", + "version": "15.0.0-canary.174", "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 65ed422cf1d2f..ff54759423f9b 100644 --- a/packages/next-swc/package.json +++ b/packages/next-swc/package.json @@ -1,6 +1,6 @@ { "name": "@next/swc", - "version": "15.0.0-canary.173", + "version": "15.0.0-canary.174", "private": true, "scripts": { "clean": "node ../../scripts/rm.mjs native", diff --git a/packages/next/package.json b/packages/next/package.json index 9339734d10f9f..800335415e313 100644 --- a/packages/next/package.json +++ b/packages/next/package.json @@ -1,6 +1,6 @@ { "name": "next", - "version": "15.0.0-canary.173", + "version": "15.0.0-canary.174", "description": "The React Framework", "main": "./dist/server/next.js", "license": "MIT", @@ -95,7 +95,7 @@ ] }, "dependencies": { - "@next/env": "15.0.0-canary.173", + "@next/env": "15.0.0-canary.174", "@swc/counter": "0.1.3", "@swc/helpers": "0.5.13", "busboy": "1.6.0", @@ -107,8 +107,8 @@ "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.41.2", "babel-plugin-react-compiler": "*", - "react": "^18.2.0 || 19.0.0-rc-3edc000d-20240926", - "react-dom": "^18.2.0 || 19.0.0-rc-3edc000d-20240926", + "react": "^18.2.0 || 19.0.0-rc-2d16326d-20240930", + "react-dom": "^18.2.0 || 19.0.0-rc-2d16326d-20240930", "sass": "^1.3.0" }, "peerDependenciesMeta": { @@ -159,11 +159,11 @@ "@jest/types": "29.5.0", "@mswjs/interceptors": "0.23.0", "@napi-rs/triples": "1.2.0", - "@next/font": "15.0.0-canary.173", - "@next/polyfill-module": "15.0.0-canary.173", - "@next/polyfill-nomodule": "15.0.0-canary.173", - "@next/react-refresh-utils": "15.0.0-canary.173", - "@next/swc": "15.0.0-canary.173", + "@next/font": "15.0.0-canary.174", + "@next/polyfill-module": "15.0.0-canary.174", + "@next/polyfill-nomodule": "15.0.0-canary.174", + "@next/react-refresh-utils": "15.0.0-canary.174", + "@next/swc": "15.0.0-canary.174", "@opentelemetry/api": "1.6.0", "@playwright/test": "1.41.2", "@swc/core": "1.7.0-nightly-20240714.1", diff --git a/packages/next/server.d.ts b/packages/next/server.d.ts index e3ba1fa950e07..2b94d798ff84e 100644 --- a/packages/next/server.d.ts +++ b/packages/next/server.d.ts @@ -14,5 +14,6 @@ export { URLPattern } from 'next/dist/compiled/@edge-runtime/primitives/url' export { ImageResponse } from 'next/dist/server/web/spec-extension/image-response' export type { ImageResponseOptions } from 'next/dist/compiled/@vercel/og/types' export { unstable_after } from 'next/dist/server/after' +export { connection } from 'next/dist/server/request/connection' export type { UnsafeUnwrappedSearchParams } from 'next/dist/server/request/search-params' export type { UnsafeUnwrappedParams } from 'next/dist/server/request/params' diff --git a/packages/next/server.js b/packages/next/server.js index 589a789dfe66b..ff224a2bb5a93 100644 --- a/packages/next/server.js +++ b/packages/next/server.js @@ -12,6 +12,7 @@ const serverExports = { URLPattern: require('next/dist/server/web/spec-extension/url-pattern') .URLPattern, unstable_after: require('next/dist/server/after').unstable_after, + connection: require('next/dist/server/request/connection').connection, } // https://nodejs.org/api/esm.html#commonjs-namespaces @@ -26,3 +27,4 @@ exports.userAgentFromString = serverExports.userAgentFromString exports.userAgent = serverExports.userAgent exports.URLPattern = serverExports.URLPattern exports.unstable_after = serverExports.unstable_after +exports.connection = serverExports.connection diff --git a/packages/next/src/build/analysis/get-page-static-info.ts b/packages/next/src/build/analysis/get-page-static-info.ts index ef8a8fb642e44..fa836500fc09b 100644 --- a/packages/next/src/build/analysis/get-page-static-info.ts +++ b/packages/next/src/build/analysis/get-page-static-info.ts @@ -437,9 +437,11 @@ function warnAboutExperimentalEdge(apiRoute: string | null) { ) { return } + if (apiRouteWarnings.has(apiRoute)) { return } + Log.warn( apiRoute ? `${apiRoute} provided runtime 'experimental-edge'. It can be updated to 'edge' instead.` diff --git a/packages/next/src/build/app-segments/app-segment-config.ts b/packages/next/src/build/app-segments/app-segment-config.ts new file mode 100644 index 0000000000000..aaed6dbfd0494 --- /dev/null +++ b/packages/next/src/build/app-segments/app-segment-config.ts @@ -0,0 +1,125 @@ +import { z } from 'next/dist/compiled/zod' + +/** + * The schema for configuration for a page. + * + * @internal + */ +export const AppSegmentConfigSchema = z.object({ + /** + * The number of seconds to revalidate the page or false to disable revalidation. + */ + revalidate: z + .union([z.number().int().nonnegative(), z.literal(false)]) + .optional(), + + /** + * Whether the page supports dynamic parameters. + */ + dynamicParams: z.boolean().optional(), + + /** + * The dynamic behavior of the page. + */ + dynamic: z + .enum(['auto', 'error', 'force-static', 'force-dynamic']) + .optional(), + + /** + * The caching behavior of the page. + */ + fetchCache: z + .enum([ + 'auto', + 'default-cache', + 'only-cache', + 'force-cache', + 'force-no-store', + 'default-no-store', + 'only-no-store', + ]) + .optional(), + + /** + * The preferred region for the page. + */ + preferredRegion: z.union([z.string(), z.array(z.string())]).optional(), + + /** + * Whether the page supports partial prerendering. When true, the page will be + * served using partial prerendering. This setting will only take affect if + * it's enabled via the `experimental.ppr = "incremental"` option. + */ + experimental_ppr: z.boolean().optional(), + + /** + * The runtime to use for the page. + */ + runtime: z.enum(['edge', 'nodejs']).optional(), + + /** + * The maximum duration for the page in seconds. + */ + maxDuration: z.number().int().nonnegative().optional(), +}) + +/** + * The configuration for a page. + */ +export type AppSegmentConfig = { + /** + * The revalidation period for the page in seconds, or false to disable ISR. + */ + revalidate?: number | false + + /** + * Whether the page supports dynamic parameters. + */ + dynamicParams?: boolean + + /** + * The dynamic behavior of the page. + */ + dynamic?: 'auto' | 'error' | 'force-static' | 'force-dynamic' + + /** + * The caching behavior of the page. + */ + fetchCache?: + | 'auto' + | 'default-cache' + | 'default-no-store' + | 'force-cache' + | 'force-no-store' + | 'only-cache' + | 'only-no-store' + + /** + * The preferred region for the page. + */ + preferredRegion?: string | string[] + + /** + * Whether the page supports partial prerendering. When true, the page will be + * served using partial prerendering. This setting will only take affect if + * it's enabled via the `experimental.ppr = "incremental"` option. + */ + experimental_ppr?: boolean + + /** + * The runtime to use for the page. + */ + runtime?: 'edge' | 'nodejs' + + /** + * The maximum duration for the page in seconds. + */ + maxDuration?: number +} + +/** + * The keys of the configuration for a page. + * + * @internal + */ +export const AppSegmentConfigSchemaKeys = AppSegmentConfigSchema.keyof().options diff --git a/packages/next/src/build/app-segments/collect-app-segments.ts b/packages/next/src/build/app-segments/collect-app-segments.ts new file mode 100644 index 0000000000000..b907c4b409027 --- /dev/null +++ b/packages/next/src/build/app-segments/collect-app-segments.ts @@ -0,0 +1,175 @@ +import type { LoadComponentsReturnType } from '../../server/load-components' +import type { Params } from '../../server/request/params' +import type { + AppPageRouteModule, + AppPageModule, +} from '../../server/route-modules/app-page/module.compiled' +import type { + AppRouteRouteModule, + AppRouteModule, +} from '../../server/route-modules/app-route/module.compiled' +import { + type AppSegmentConfig, + AppSegmentConfigSchema, +} from './app-segment-config' + +import { InvariantError } from '../../shared/lib/invariant-error' +import { + isAppRouteRouteModule, + isAppPageRouteModule, +} from '../../server/route-modules/checks' +import { isClientReference } from '../../lib/client-reference' +import { getSegmentParam } from '../../server/app-render/get-segment-param' +import { getLayoutOrPageModule } from '../../server/lib/app-dir-module' + +type GenerateStaticParams = (options: { params?: Params }) => Promise<Params[]> + +/** + * Parses the app config and attaches it to the segment. + */ +function attach(segment: AppSegment, userland: unknown) { + // If the userland is not an object, then we can't do anything with it. + if (typeof userland !== 'object' || userland === null) { + return + } + + // Try to parse the application configuration. If there were any keys, attach + // it to the segment. + const config = AppSegmentConfigSchema.safeParse(userland) + if (config.success && Object.keys(config.data).length > 0) { + segment.config = config.data + } + + if ( + 'generateStaticParams' in userland && + typeof userland.generateStaticParams === 'function' + ) { + segment.generateStaticParams = + userland.generateStaticParams as GenerateStaticParams + + // Validate that `generateStaticParams` makes sense in this context. + if (segment.config?.runtime === 'edge') { + throw new Error( + 'Edge runtime is not supported with `generateStaticParams`.' + ) + } + } +} + +export type AppSegment = { + name: string + param: string | undefined + filePath: string | undefined + config: AppSegmentConfig | undefined + isDynamicSegment: boolean + generateStaticParams: GenerateStaticParams | undefined +} + +/** + * Walks the loader tree and collects the generate parameters for each segment. + * + * @param routeModule the app page route module + * @returns the segments for the app page route module + */ +async function collectAppPageSegments(routeModule: AppPageRouteModule) { + const segments: AppSegment[] = [] + + let current = routeModule.userland.loaderTree + while (current) { + const [name, parallelRoutes] = current + const { mod: userland, filePath } = await getLayoutOrPageModule(current) + + const isClientComponent: boolean = userland && isClientReference(userland) + const isDynamicSegment = /^\[.*\]$/.test(name) + const param = isDynamicSegment ? getSegmentParam(name)?.param : undefined + + const segment: AppSegment = { + name, + param, + filePath, + config: undefined, + isDynamicSegment, + generateStaticParams: undefined, + } + + // Only server components can have app segment configurations. If this isn't + // an object, then we should skip it. This can happen when parsing the + // error components. + if (!isClientComponent) { + attach(segment, userland) + } + + segments.push(segment) + + // Use this route's parallel route children as the next segment. + current = parallelRoutes.children + } + + return segments +} + +/** + * Collects the segments for a given app route module. + * + * @param routeModule the app route module + * @returns the segments for the app route module + */ +function collectAppRouteSegments( + routeModule: AppRouteRouteModule +): AppSegment[] { + // Get the pathname parts, slice off the first element (which is empty). + const parts = routeModule.definition.pathname.split('/').slice(1) + if (parts.length === 0) { + throw new InvariantError('Expected at least one segment') + } + + // Generate all the segments. + const segments: AppSegment[] = parts.map((name) => { + const isDynamicSegment = /^\[.*\]$/.test(name) + const param = isDynamicSegment ? getSegmentParam(name)?.param : undefined + + return { + name, + param, + filePath: undefined, + isDynamicSegment, + config: undefined, + generateStaticParams: undefined, + } + }) + + // We know we have at least one, we verified this above. We should get the + // last segment which represents the root route module. + const segment = segments[segments.length - 1] + + segment.filePath = routeModule.definition.filename + + // Extract the segment config from the userland module. + attach(segment, routeModule.userland) + + return segments +} + +/** + * Collects the segments for a given route module. + * + * @param components the loaded components + * @returns the segments for the route module + */ +export function collectSegments({ + routeModule, +}: LoadComponentsReturnType<AppPageModule | AppRouteModule>): + | Promise<AppSegment[]> + | AppSegment[] { + if (isAppRouteRouteModule(routeModule)) { + return collectAppRouteSegments(routeModule) + } + + if (isAppPageRouteModule(routeModule)) { + return collectAppPageSegments(routeModule) + } + + throw new InvariantError( + 'Expected a route module to be one of app route or page' + ) +} diff --git a/packages/next/src/build/index.ts b/packages/next/src/build/index.ts index fba27b7a3e7a8..be1ea1d6b4754 100644 --- a/packages/next/src/build/index.ts +++ b/packages/next/src/build/index.ts @@ -130,7 +130,8 @@ import { collectMeta, // getSupportedBrowsers, } from './utils' -import type { PageInfo, PageInfos, AppConfig, PrerenderedRoute } from './utils' +import type { PageInfo, PageInfos, PrerenderedRoute } from './utils' +import type { AppSegmentConfig } from './app-segments/app-segment-config' import { writeBuildId } from './write-build-id' import { normalizeLocalePath } from '../shared/lib/i18n/normalize-locale-path' import isError from '../lib/is-error' @@ -1818,7 +1819,7 @@ export default async function build( const staticPaths = new Map<string, PrerenderedRoute[]>() const appNormalizedPaths = new Map<string, string>() const fallbackModes = new Map<string, FallbackMode>() - const appDefaultConfigs = new Map<string, AppConfig>() + const appDefaultConfigs = new Map<string, AppSegmentConfig>() const pageInfos: PageInfos = new Map<string, PageInfo>() let pagesManifest = await readManifest<PagesManifest>(pagesManifestPath) const buildManifest = await readManifest<BuildManifest>(buildManifestPath) diff --git a/packages/next/src/build/utils.ts b/packages/next/src/build/utils.ts index d6c3a3f4a1d13..f6e3374b1af4d 100644 --- a/packages/next/src/build/utils.ts +++ b/packages/next/src/build/utils.ts @@ -22,7 +22,6 @@ import type { import type { WebpackLayerName } from '../lib/constants' import type { AppPageModule } from '../server/route-modules/app-page/module' import type { RouteModule } from '../server/route-modules/route-module' -import type { LoaderTree } from '../server/lib/app-dir-module' import type { NextComponentType } from '../shared/lib/utils' import '../server/require-hook' @@ -77,13 +76,13 @@ import { normalizePagePath } from '../shared/lib/page-path/normalize-page-path' import { getRuntimeContext } from '../server/web/sandbox' import { isClientReference } from '../lib/client-reference' import { withStaticGenerationStore } from '../server/async-storage/with-static-generation-store' +import type { CacheHandler } from '../server/lib/incremental-cache' import { IncrementalCache } from '../server/lib/incremental-cache' import { nodeFs } from '../server/lib/node-fs-methods' import * as ciEnvironment from '../server/ci-info' import { normalizeAppPath } from '../shared/lib/router/utils/app-paths' import { denormalizeAppPagePath } from '../shared/lib/page-path/denormalize-app-path' import { RouteKind } from '../server/route-kind' -import { isAppRouteRouteModule } from '../server/route-modules/checks' import { interopDefault } from '../lib/interop-default' import type { PageExtensions } from './page-extensions-type' import { formatDynamicImportPath } from '../lib/format-dynamic-import-path' @@ -97,6 +96,9 @@ import { } from '../lib/fallback' import { getParamKeys } from '../server/request/fallback-params' import type { OutgoingHttpHeaders } from 'http' +import type { AppSegmentConfig } from './app-segments/app-segment-config' +import type { AppSegment } from './app-segments/collect-app-segments' +import { collectSegments } from './app-segments/collect-app-segments' export type ROUTER_TYPE = 'pages' | 'app' @@ -1121,7 +1123,7 @@ export async function buildStaticPaths({ (!repeat && typeof paramValue !== 'string') ) { // If this is from app directory, and not all params were provided, - // then filter this out if the route is not PPR enabled. + // then filter this out. if (appDir && typeof paramValue === 'undefined') { builtPage = '' encodedBuiltPage = '' @@ -1200,146 +1202,6 @@ export async function buildStaticPaths({ } } -export type AppConfigDynamic = - | 'auto' - | 'error' - | 'force-static' - | 'force-dynamic' - -export type AppConfig = { - revalidate?: number | false - dynamicParams?: true | false - dynamic?: AppConfigDynamic - fetchCache?: 'force-cache' | 'only-cache' - preferredRegion?: string - - /** - * When true, the page will be served using partial prerendering. - * This setting will only take affect if it's enabled via - * the `experimental.ppr = "incremental"` option. - */ - experimental_ppr?: boolean -} - -type GenerateStaticParams = (options: { params?: Params }) => Promise<Params[]> - -type GenerateParamsResult = { - config?: AppConfig - isDynamicSegment?: boolean - segmentPath: string - generateStaticParams?: GenerateStaticParams - isLayout?: boolean -} - -export type GenerateParamsResults = GenerateParamsResult[] - -const collectAppConfig = ( - mod: Partial<AppConfig> | undefined -): AppConfig | undefined => { - let hasConfig = false - const config: AppConfig = {} - - if (typeof mod?.revalidate !== 'undefined') { - config.revalidate = mod.revalidate - hasConfig = true - } - if (typeof mod?.dynamicParams !== 'undefined') { - config.dynamicParams = mod.dynamicParams - hasConfig = true - } - if (typeof mod?.dynamic !== 'undefined') { - config.dynamic = mod.dynamic - hasConfig = true - } - if (typeof mod?.fetchCache !== 'undefined') { - config.fetchCache = mod.fetchCache - hasConfig = true - } - if (typeof mod?.preferredRegion !== 'undefined') { - config.preferredRegion = mod.preferredRegion - hasConfig = true - } - if (typeof mod?.experimental_ppr !== 'undefined') { - config.experimental_ppr = mod.experimental_ppr - hasConfig = true - } - - if (!hasConfig) return undefined - - return config -} - -/** - * Walks the loader tree and collects the generate parameters for each segment. - * - * @param tree the loader tree - * @returns the generate parameters for each segment - */ -export async function collectGenerateParams(tree: LoaderTree) { - const generateParams: GenerateParamsResults = [] - const parentSegments: string[] = [] - - let currentLoaderTree = tree - while (currentLoaderTree) { - const [ - // TODO: check if this is ever undefined - page = '', - parallelRoutes, - components, - ] = currentLoaderTree - - // If the segment doesn't have any components, then skip it. - if (!components) continue - - const isLayout = !!components.layout - const mod = await (isLayout - ? components.layout?.[0]?.() - : components.page?.[0]?.()) - - if (page) { - parentSegments.push(page) - } - - const config = mod ? collectAppConfig(mod) : undefined - const isClientComponent = isClientReference(mod) - - const isDynamicSegment = /^\[.+\]$/.test(page) - - const { generateStaticParams } = mod || {} - - if (isDynamicSegment && isClientComponent && generateStaticParams) { - throw new Error( - `Page "${page}" cannot export "generateStaticParams()" because it is a client component` - ) - } - - const segmentPath = `/${parentSegments.join('/')}${ - page && parentSegments.length > 0 ? '/' : '' - }${page}` - - const result: GenerateParamsResult = { - isLayout, - isDynamicSegment, - segmentPath, - config, - generateStaticParams: !isClientComponent - ? generateStaticParams - : undefined, - } - - // If the configuration contributes to the static generation, then add it - // to the list. - if (result.config || result.generateStaticParams || isDynamicSegment) { - generateParams.push(result) - } - - // Use this route's parallel route children as the next segment. - currentLoaderTree = parallelRoutes.children - } - - return generateParams -} - export type PartialStaticPathsResult = { [P in keyof StaticPathsResult]: StaticPathsResult[P] | undefined } @@ -1350,7 +1212,7 @@ export async function buildAppStaticPaths({ distDir, dynamicIO, configFileName, - generateParams, + segments, isrFlushToDisk, cacheHandler, requestHeaders, @@ -1366,7 +1228,7 @@ export async function buildAppStaticPaths({ page: string dynamicIO: boolean configFileName: string - generateParams: GenerateParamsResults + segments: AppSegment[] distDir: string isrFlushToDisk?: boolean fetchCacheKeyPrefix?: string @@ -1379,12 +1241,20 @@ export async function buildAppStaticPaths({ isAppPPRFallbacksEnabled: boolean | undefined buildId: string }): Promise<PartialStaticPathsResult> { - ComponentMod.patchFetch() + if ( + segments.some((generate) => generate.config?.dynamicParams === true) && + nextConfigOutput === 'export' + ) { + throw new Error( + '"dynamicParams: true" cannot be used with "output: export". See more info here: https://nextjs.org/docs/app/building-your-application/deploying/static-exports' + ) + } - let CacheHandler: any + ComponentMod.patchFetch() + let CurCacheHandler: typeof CacheHandler | undefined if (cacheHandler) { - CacheHandler = interopDefault( + CurCacheHandler = interopDefault( await import(formatDynamicImportPath(dir, cacheHandler)).then( (mod) => mod.default || mod ) @@ -1406,12 +1276,25 @@ export async function buildAppStaticPaths({ notFoundRoutes: [], preview: null as any, // `preview` is special case read in next-dev-server }), - CurCacheHandler: CacheHandler, + CurCacheHandler, requestHeaders, minimalMode: ciEnvironment.hasNextSupport, }) - return withStaticGenerationStore( + const paramKeys = new Set<string>() + + const staticParamKeys = new Set<string>() + for (const segment of segments) { + if (segment.param) { + paramKeys.add(segment.param) + + if (segment.config?.dynamicParams === false) { + staticParamKeys.add(segment.param) + } + } + } + + const routeParams = await withStaticGenerationStore( ComponentMod.staticGenerationAsyncStorage, { page, @@ -1429,134 +1312,148 @@ export async function buildAppStaticPaths({ buildId, }, }, - async (): Promise<PartialStaticPathsResult> => { - let hadAllParamsGenerated = false - - const buildParams = async ( - paramsItems: Params[] = [{}], + async (store) => { + async function builtRouteParams( + parentsParams: Params[] = [], idx = 0 - ): Promise<Params[]> => { - const current = generateParams[idx] + ): Promise<Params[]> { + // If we don't have any more to process, then we're done. + if (idx === segments.length) return parentsParams - if (idx === generateParams.length) { - return paramsItems - } + const current = segments[idx] if ( typeof current.generateStaticParams !== 'function' && - idx < generateParams.length + idx < segments.length ) { - if (current.isDynamicSegment) { - // This dynamic level has no generateStaticParams so we change - // this flag to false, but it could be covered by a later - // generateStaticParams so it could be set back to true. - hadAllParamsGenerated = false - } - return buildParams(paramsItems, idx + 1) + return builtRouteParams(parentsParams, idx + 1) } - hadAllParamsGenerated = true - const newParams: Params[] = [] + const params: Params[] = [] if (current.generateStaticParams) { - const store = ComponentMod.staticGenerationAsyncStorage.getStore() - - if (store) { - if (typeof current?.config?.fetchCache !== 'undefined') { - store.fetchCache = current.config.fetchCache - } - if (typeof current?.config?.revalidate !== 'undefined') { - store.revalidate = current.config.revalidate - } - if (current?.config?.dynamic === 'force-dynamic') { - store.forceDynamic = true - } + if (typeof current.config?.fetchCache !== 'undefined') { + store.fetchCache = current.config.fetchCache + } + if (typeof current.config?.revalidate !== 'undefined') { + store.revalidate = current.config.revalidate + } + if (current.config?.dynamic === 'force-dynamic') { + store.forceDynamic = true } - for (const params of paramsItems) { - const result = await current.generateStaticParams({ - params, - }) + if (parentsParams.length > 0) { + for (const parentParams of parentsParams) { + const result = await current.generateStaticParams({ + params: parentParams, + }) - // TODO: validate the result is valid here or wait for buildStaticPaths to validate? - for (const item of result) { - newParams.push({ ...params, ...item }) + for (const item of result) { + params.push({ ...parentParams, ...item }) + } } + } else { + const result = await current.generateStaticParams({ params: {} }) + + params.push(...result) } } - if (idx < generateParams.length) { - return buildParams(newParams, idx + 1) + if (idx < segments.length) { + return builtRouteParams(params, idx + 1) } - return newParams + return params } - const builtParams = await buildParams() + return builtRouteParams() + } + ) + + for (const segment of segments) { + // Check to see if there are any missing params for segments that have + // dynamicParams set to false. + if ( + segment.param && + segment.isDynamicSegment && + segment.config?.dynamicParams === false + ) { + for (const params of routeParams) { + if (segment.param in params) continue + + const relative = segment.filePath + ? path.relative(dir, segment.filePath) + : undefined - if ( - generateParams.some( - (generate) => generate.config?.dynamicParams === true - ) && - nextConfigOutput === 'export' - ) { throw new Error( - '"dynamicParams: true" cannot be used with "output: export". See more info here: https://nextjs.org/docs/app/building-your-application/deploying/static-exports' + `Segment "${relative}" exports "dynamicParams: false" but the param "${segment.param}" is missing from the generated route params.` ) } + } + } - // TODO: dynamic params should be allowed to be granular per segment but - // we need additional information stored/leveraged in the prerender - // manifest to allow this behavior. - const dynamicParams = generateParams.every( - (param) => param.config?.dynamicParams !== false - ) - - const isProduction = process.env.NODE_ENV === 'production' + // Determine if all the segments have had their parameters provided. If there + // was no dynamic parameters, then we've collected all the params. + const hadAllParamsGenerated = + paramKeys.size === 0 || + (routeParams.length > 0 && + routeParams.every((params) => { + for (const key of paramKeys) { + if (key in params) continue + return false + } + return true + })) + + // TODO: dynamic params should be allowed to be granular per segment but + // we need additional information stored/leveraged in the prerender + // manifest to allow this behavior. + const dynamicParams = segments.every( + (segment) => segment.config?.dynamicParams !== false + ) - const supportsStaticGeneration = hadAllParamsGenerated || isProduction + const supportsRoutePreGeneration = + hadAllParamsGenerated || process.env.NODE_ENV === 'production' - const supportsPPRFallbacks = isRoutePPREnabled && isAppPPRFallbacksEnabled + const supportsPPRFallbacks = isRoutePPREnabled && isAppPPRFallbacksEnabled - const fallbackMode = dynamicParams - ? supportsStaticGeneration - ? supportsPPRFallbacks - ? FallbackMode.PRERENDER - : FallbackMode.BLOCKING_STATIC_RENDER - : undefined - : FallbackMode.NOT_FOUND + const fallbackMode = dynamicParams + ? supportsRoutePreGeneration + ? supportsPPRFallbacks + ? FallbackMode.PRERENDER + : FallbackMode.BLOCKING_STATIC_RENDER + : undefined + : FallbackMode.NOT_FOUND - let result: PartialStaticPathsResult = { - fallbackMode, - prerenderedRoutes: undefined, - } + let result: PartialStaticPathsResult = { + fallbackMode, + prerenderedRoutes: undefined, + } - if (hadAllParamsGenerated && fallbackMode) { - result = await buildStaticPaths({ - staticPathsResult: { - fallback: fallbackModeToStaticPathsResult(fallbackMode), - paths: builtParams.map((params) => ({ params })), - }, - page, - configFileName, - appDir: true, - }) - } + if (hadAllParamsGenerated && fallbackMode) { + result = await buildStaticPaths({ + staticPathsResult: { + fallback: fallbackModeToStaticPathsResult(fallbackMode), + paths: routeParams.map((params) => ({ params })), + }, + page, + configFileName, + appDir: true, + }) + } - // If the fallback mode is a prerender, we want to include the dynamic - // route in the prerendered routes too. - if (isRoutePPREnabled && isAppPPRFallbacksEnabled) { - result.prerenderedRoutes ??= [] - result.prerenderedRoutes.unshift({ - path: page, - encoded: page, - fallbackRouteParams: getParamKeys(page), - }) - } + // If the fallback mode is a prerender, we want to include the dynamic + // route in the prerendered routes too. + if (isRoutePPREnabled && isAppPPRFallbacksEnabled) { + result.prerenderedRoutes ??= [] + result.prerenderedRoutes.unshift({ + path: page, + encoded: page, + fallbackRouteParams: getParamKeys(page), + }) + } - return result - } - ) + return result } type PageIsStaticResult = { @@ -1571,7 +1468,7 @@ type PageIsStaticResult = { isNextImageImported?: boolean traceIncludes?: string[] traceExcludes?: string[] - appConfig?: AppConfig + appConfig?: AppSegmentConfig } export async function isPageStatic({ @@ -1632,7 +1529,7 @@ export async function isPageStatic({ let componentsResult: LoadComponentsReturnType let prerenderedRoutes: PrerenderedRoute[] | undefined let prerenderFallbackMode: FallbackMode | undefined - let appConfig: AppConfig = {} + let appConfig: AppSegmentConfig = {} let isClientComponent: boolean = false const pathIsEdgeRuntime = isEdgeRuntime(pageRuntime) @@ -1654,13 +1551,19 @@ export async function isPageStatic({ await runtime.context._ENTRIES[`middleware_${edgeInfo.name}`] ).ComponentMod + // This is not needed during require. + const buildManifest = {} as BuildManifest + isClientComponent = isClientReference(mod) componentsResult = { Component: mod.default, + Document: mod.Document, + App: mod.App, + routeModule: mod.routeModule, + page, ComponentMod: mod, pageConfig: mod.config || {}, - // @ts-expect-error this is not needed during require - buildManifest: {}, + buildManifest, reactLoadableManifest: {}, getServerSideProps: mod.getServerSideProps, getStaticPaths: mod.getStaticPaths, @@ -1676,8 +1579,7 @@ export async function isPageStatic({ const Comp = componentsResult.Component as NextComponentType | undefined let staticPathsResult: GetStaticPathsResult | undefined - const routeModule: RouteModule = - componentsResult.ComponentMod?.routeModule + const routeModule: RouteModule = componentsResult.routeModule let isRoutePPREnabled: boolean = false @@ -1686,25 +1588,16 @@ export async function isPageStatic({ isClientComponent = isClientReference(componentsResult.ComponentMod) - const { tree } = ComponentMod - - const generateParams: GenerateParamsResults = - routeModule && isAppRouteRouteModule(routeModule) - ? [ - { - config: { - revalidate: routeModule.userland.revalidate, - dynamic: routeModule.userland.dynamic, - dynamicParams: routeModule.userland.dynamicParams, - }, - generateStaticParams: - routeModule.userland.generateStaticParams, - segmentPath: page, - }, - ] - : await collectGenerateParams(tree) - - appConfig = reduceAppConfig(generateParams) + let segments + try { + segments = await collectSegments(componentsResult) + } catch (err) { + throw new Error(`Failed to collect configuration for ${page}`, { + cause: err, + }) + } + + appConfig = reduceAppConfig(await collectSegments(componentsResult)) if (appConfig.dynamic === 'force-static' && pathIsEdgeRuntime) { Log.warn( @@ -1734,7 +1627,7 @@ export async function isPageStatic({ page, dynamicIO, configFileName, - generateParams, + segments, distDir, requestHeaders: {}, isrFlushToDisk, @@ -1839,7 +1732,7 @@ export async function isPageStatic({ } type ReducedAppConfig = Pick< - AppConfig, + AppSegmentConfig, | 'dynamic' | 'fetchCache' | 'preferredRegion' @@ -1854,21 +1747,17 @@ type ReducedAppConfig = Pick< * @param segments the generate param segments * @returns the reduced app config */ -export function reduceAppConfig( - segments: GenerateParamsResults -): ReducedAppConfig { +export function reduceAppConfig(segments: AppSegment[]): ReducedAppConfig { const config: ReducedAppConfig = {} for (const segment of segments) { - if (!segment.config) continue - const { dynamic, fetchCache, preferredRegion, revalidate, experimental_ppr, - } = segment.config + } = segment.config || {} // TODO: should conflicting configs here throw an error // e.g. if layout defines one region but page defines another diff --git a/packages/next/src/client/components/request-async-storage.external.ts b/packages/next/src/client/components/request-async-storage.external.ts index 3a55cfb27693d..eb892c02d0bb7 100644 --- a/packages/next/src/client/components/request-async-storage.external.ts +++ b/packages/next/src/client/components/request-async-storage.external.ts @@ -10,6 +10,8 @@ import type { DeepReadonly } from '../../shared/lib/deep-readonly' import type { AfterContext } from '../../server/after/after-context' import type { ServerComponentsHmrCache } from '../../server/response-cache' +import { cacheAsyncStorage } from '../../server/app-render/cache-async-storage.external' + export interface RequestStore { /** * The URL of the request. This only specifies the pathname and the search @@ -48,6 +50,11 @@ export { requestAsyncStorage } export function getExpectedRequestStore(callingExpression: string) { const store = requestAsyncStorage.getStore() if (store) return store + if (cacheAsyncStorage.getStore()) { + throw new Error( + `\`${callingExpression}\` cannot be called inside "use cache". Call it outside and pass an argument instead. Read more: https://nextjs.org/docs/messages/next-request-in-use-cache` + ) + } throw new Error( `\`${callingExpression}\` was called outside a request scope. Read more: https://nextjs.org/docs/messages/next-dynamic-api-wrong-context` ) diff --git a/packages/next/src/client/components/router-reducer/aliased-prefetch-navigations.ts b/packages/next/src/client/components/router-reducer/aliased-prefetch-navigations.ts index 71e44eaf53d2f..10e9dd3f8cc74 100644 --- a/packages/next/src/client/components/router-reducer/aliased-prefetch-navigations.ts +++ b/packages/next/src/client/components/router-reducer/aliased-prefetch-navigations.ts @@ -223,7 +223,6 @@ export function addSearchParamsToPageSegments( // If it's a page segment, modify the segment by adding search params if (segment.includes(PAGE_SEGMENT_KEY)) { const newSegment = addSearchParamsIfPageSegment(segment, searchParams) - console.log({ existingSegment: segment, newSegment }) return [newSegment, parallelRoutes, ...rest] } diff --git a/packages/next/src/client/components/router-reducer/ppr-navigations.ts b/packages/next/src/client/components/router-reducer/ppr-navigations.ts index e07e8097c3602..19572b8a2a024 100644 --- a/packages/next/src/client/components/router-reducer/ppr-navigations.ts +++ b/packages/next/src/client/components/router-reducer/ppr-navigations.ts @@ -9,10 +9,7 @@ import type { ChildSegmentMap, ReadyCacheNode, } from '../../../shared/lib/app-router-context.shared-runtime' -import { - DEFAULT_SEGMENT_KEY, - PAGE_SEGMENT_KEY, -} from '../../../shared/lib/segment' +import { DEFAULT_SEGMENT_KEY } from '../../../shared/lib/segment' import { matchSegment } from '../match-segments' import { createRouterCacheKey } from './create-router-cache-key' import type { FetchServerResponseResult } from './fetch-server-response' @@ -124,27 +121,13 @@ export function updateCacheNodeOnNavigation( const oldSegmentChild = oldRouterStateChild !== undefined ? oldRouterStateChild[0] : undefined - // A dynamic segment will be an array, and doesn't correspond with a page segment. - const isPageSegment = Array.isArray(newSegmentChild) - ? false - : // A page segment might contain search parameters, so we verify that it starts with the page segment key. - newSegmentChild.startsWith(PAGE_SEGMENT_KEY) - const oldCacheNodeChild = oldSegmentMapChild !== undefined ? oldSegmentMapChild.get(newSegmentKeyChild) : undefined let taskChild: Task | null - if (isPageSegment) { - // This is a leaf segment — a page, not a shared layout. We always apply - // its data. - taskChild = spawnPendingTask( - newRouterStateChild, - prefetchDataChild !== undefined ? prefetchDataChild : null, - prefetchHead - ) - } else if (newSegmentChild === DEFAULT_SEGMENT_KEY) { + if (newSegmentChild === DEFAULT_SEGMENT_KEY) { // This is another kind of leaf segment — a default route. // // Default routes have special behavior. When there's no matching segment diff --git a/packages/next/src/client/components/static-generation-async-storage.external.ts b/packages/next/src/client/components/static-generation-async-storage.external.ts index 610a6227d1fdd..2c1a120f8c5cb 100644 --- a/packages/next/src/client/components/static-generation-async-storage.external.ts +++ b/packages/next/src/client/components/static-generation-async-storage.external.ts @@ -7,6 +7,7 @@ import type { FallbackRouteParams } from '../../server/request/fallback-params' // Share the instance module in the next-shared layer import { staticGenerationAsyncStorage } from './static-generation-async-storage-instance' with { 'turbopack-transition': 'next-shared' } +import type { AppSegmentConfig } from '../../build/app-segments/app-segment-config' export interface StaticGenerationStore { readonly isStaticGeneration: boolean @@ -35,13 +36,7 @@ export interface StaticGenerationStore { readonly isUnstableCacheCallback?: boolean forceDynamic?: boolean - fetchCache?: - | 'only-cache' - | 'force-cache' - | 'default-cache' - | 'force-no-store' - | 'default-no-store' - | 'only-no-store' + fetchCache?: AppSegmentConfig['fetchCache'] revalidate?: Revalidate forceStatic?: boolean diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-client.development.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-client.development.js index 985c14f9052a1..5f6ae4052126e 100644 --- a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-client.development.js +++ b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-client.development.js @@ -24933,11 +24933,11 @@ }; (function () { var isomorphicReactPackageVersion = React.version; - if ("19.0.0-experimental-3edc000d-20240926" !== isomorphicReactPackageVersion) + if ("19.0.0-experimental-2d16326d-20240930" !== isomorphicReactPackageVersion) throw Error( 'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' + (isomorphicReactPackageVersion + - "\n - react-dom: 19.0.0-experimental-3edc000d-20240926\nLearn more: https://react.dev/warnings/version-mismatch") + "\n - react-dom: 19.0.0-experimental-2d16326d-20240930\nLearn more: https://react.dev/warnings/version-mismatch") ); })(); ("function" === typeof Map && @@ -24974,11 +24974,11 @@ !(function () { var internals = { bundleType: 1, - version: "19.0.0-experimental-3edc000d-20240926", + version: "19.0.0-experimental-2d16326d-20240930", rendererPackageName: "react-dom", currentDispatcherRef: ReactSharedInternals, findFiberByHostInstance: getClosestInstanceFromNode, - reconcilerVersion: "19.0.0-experimental-3edc000d-20240926" + reconcilerVersion: "19.0.0-experimental-2d16326d-20240930" }; internals.overrideHookState = overrideHookState; internals.overrideHookStateDeletePath = overrideHookStateDeletePath; @@ -25120,7 +25120,7 @@ listenToAllSupportedEvents(container); return new ReactDOMHydrationRoot(initialChildren); }; - exports.version = "19.0.0-experimental-3edc000d-20240926"; + exports.version = "19.0.0-experimental-2d16326d-20240930"; "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-client.production.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-client.production.js index b2f3705fd9b1f..565310563532e 100644 --- a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-client.production.js +++ b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-client.production.js @@ -15170,14 +15170,14 @@ ReactDOMHydrationRoot.prototype.unstable_scheduleHydration = function (target) { }; var isomorphicReactPackageVersion$jscomp$inline_1659 = React.version; if ( - "19.0.0-experimental-3edc000d-20240926" !== + "19.0.0-experimental-2d16326d-20240930" !== isomorphicReactPackageVersion$jscomp$inline_1659 ) throw Error( formatProdErrorMessage( 527, isomorphicReactPackageVersion$jscomp$inline_1659, - "19.0.0-experimental-3edc000d-20240926" + "19.0.0-experimental-2d16326d-20240930" ) ); ReactDOMSharedInternals.findDOMNode = function (componentOrElement) { @@ -15199,11 +15199,11 @@ ReactDOMSharedInternals.findDOMNode = function (componentOrElement) { }; var internals$jscomp$inline_2124 = { bundleType: 0, - version: "19.0.0-experimental-3edc000d-20240926", + version: "19.0.0-experimental-2d16326d-20240930", rendererPackageName: "react-dom", currentDispatcherRef: ReactSharedInternals, findFiberByHostInstance: getClosestInstanceFromNode, - reconcilerVersion: "19.0.0-experimental-3edc000d-20240926" + reconcilerVersion: "19.0.0-experimental-2d16326d-20240930" }; if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { var hook$jscomp$inline_2125 = __REACT_DEVTOOLS_GLOBAL_HOOK__; @@ -15307,4 +15307,4 @@ exports.hydrateRoot = function (container, initialChildren, options) { listenToAllSupportedEvents(container); return new ReactDOMHydrationRoot(initialChildren); }; -exports.version = "19.0.0-experimental-3edc000d-20240926"; +exports.version = "19.0.0-experimental-2d16326d-20240930"; diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-profiling.development.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-profiling.development.js index 1fd91cc16ae5a..89e846f94100f 100644 --- a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-profiling.development.js +++ b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-profiling.development.js @@ -24990,11 +24990,11 @@ }; (function () { var isomorphicReactPackageVersion = React.version; - if ("19.0.0-experimental-3edc000d-20240926" !== isomorphicReactPackageVersion) + if ("19.0.0-experimental-2d16326d-20240930" !== isomorphicReactPackageVersion) throw Error( 'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' + (isomorphicReactPackageVersion + - "\n - react-dom: 19.0.0-experimental-3edc000d-20240926\nLearn more: https://react.dev/warnings/version-mismatch") + "\n - react-dom: 19.0.0-experimental-2d16326d-20240930\nLearn more: https://react.dev/warnings/version-mismatch") ); })(); ("function" === typeof Map && @@ -25031,11 +25031,11 @@ !(function () { var internals = { bundleType: 1, - version: "19.0.0-experimental-3edc000d-20240926", + version: "19.0.0-experimental-2d16326d-20240930", rendererPackageName: "react-dom", currentDispatcherRef: ReactSharedInternals, findFiberByHostInstance: getClosestInstanceFromNode, - reconcilerVersion: "19.0.0-experimental-3edc000d-20240926" + reconcilerVersion: "19.0.0-experimental-2d16326d-20240930" }; internals.overrideHookState = overrideHookState; internals.overrideHookStateDeletePath = overrideHookStateDeletePath; @@ -25507,7 +25507,7 @@ exports.useFormStatus = function () { return resolveDispatcher().useHostTransitionStatus(); }; - exports.version = "19.0.0-experimental-3edc000d-20240926"; + exports.version = "19.0.0-experimental-2d16326d-20240930"; "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-profiling.profiling.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-profiling.profiling.js index 97c9fb415ca9a..9e8edb55a908b 100644 --- a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-profiling.profiling.js +++ b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-profiling.profiling.js @@ -16056,14 +16056,14 @@ ReactDOMHydrationRoot.prototype.unstable_scheduleHydration = function (target) { }; var isomorphicReactPackageVersion$jscomp$inline_1732 = React.version; if ( - "19.0.0-experimental-3edc000d-20240926" !== + "19.0.0-experimental-2d16326d-20240930" !== isomorphicReactPackageVersion$jscomp$inline_1732 ) throw Error( formatProdErrorMessage( 527, isomorphicReactPackageVersion$jscomp$inline_1732, - "19.0.0-experimental-3edc000d-20240926" + "19.0.0-experimental-2d16326d-20240930" ) ); ReactDOMSharedInternals.findDOMNode = function (componentOrElement) { @@ -16085,11 +16085,11 @@ ReactDOMSharedInternals.findDOMNode = function (componentOrElement) { }; var internals$jscomp$inline_2170 = { bundleType: 0, - version: "19.0.0-experimental-3edc000d-20240926", + version: "19.0.0-experimental-2d16326d-20240930", rendererPackageName: "react-dom", currentDispatcherRef: ReactSharedInternals, findFiberByHostInstance: getClosestInstanceFromNode, - reconcilerVersion: "19.0.0-experimental-3edc000d-20240926" + reconcilerVersion: "19.0.0-experimental-2d16326d-20240930" }; if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { var hook$jscomp$inline_2171 = __REACT_DEVTOOLS_GLOBAL_HOOK__; @@ -16354,7 +16354,7 @@ exports.useFormState = function (action, initialState, permalink) { exports.useFormStatus = function () { return ReactSharedInternals.H.useHostTransitionStatus(); }; -exports.version = "19.0.0-experimental-3edc000d-20240926"; +exports.version = "19.0.0-experimental-2d16326d-20240930"; "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server-legacy.browser.development.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server-legacy.browser.development.js index ce30e2a59f72e..160085ea6b5cb 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 @@ -9291,5 +9291,5 @@ 'The server used "renderToString" which does not support Suspense. If you intended for this Suspense boundary to render the fallback content on the server consider throwing an Error somewhere within the Suspense boundary. If you intended to have the server wait for the suspended component please switch to "renderToReadableStream" which supports Suspense on the server' ); }; - exports.version = "19.0.0-experimental-3edc000d-20240926"; + exports.version = "19.0.0-experimental-2d16326d-20240930"; })(); diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server-legacy.browser.production.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server-legacy.browser.production.js index 2e1222ac14d28..7be2214bc5e2d 100644 --- a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server-legacy.browser.production.js +++ b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server-legacy.browser.production.js @@ -6058,4 +6058,4 @@ exports.renderToString = function (children, options) { 'The server used "renderToString" which does not support Suspense. If you intended for this Suspense boundary to render the fallback content on the server consider throwing an Error somewhere within the Suspense boundary. If you intended to have the server wait for the suspended component please switch to "renderToReadableStream" which supports Suspense on the server' ); }; -exports.version = "19.0.0-experimental-3edc000d-20240926"; +exports.version = "19.0.0-experimental-2d16326d-20240930"; diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server-legacy.node.development.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server-legacy.node.development.js index d50f6e4ac1d13..fc2f1b435a219 100644 --- a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server-legacy.node.development.js +++ b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server-legacy.node.development.js @@ -9291,5 +9291,5 @@ 'The server used "renderToString" which does not support Suspense. If you intended for this Suspense boundary to render the fallback content on the server consider throwing an Error somewhere within the Suspense boundary. If you intended to have the server wait for the suspended component please switch to "renderToPipeableStream" which supports Suspense on the server' ); }; - exports.version = "19.0.0-experimental-3edc000d-20240926"; + exports.version = "19.0.0-experimental-2d16326d-20240930"; })(); diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server-legacy.node.production.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server-legacy.node.production.js index 410c3bc776f03..f38e18c012a65 100644 --- a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server-legacy.node.production.js +++ b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server-legacy.node.production.js @@ -6150,4 +6150,4 @@ exports.renderToString = function (children, options) { 'The server used "renderToString" which does not support Suspense. If you intended for this Suspense boundary to render the fallback content on the server consider throwing an Error somewhere within the Suspense boundary. If you intended to have the server wait for the suspended component please switch to "renderToPipeableStream" which supports Suspense on the server' ); }; -exports.version = "19.0.0-experimental-3edc000d-20240926"; +exports.version = "19.0.0-experimental-2d16326d-20240930"; diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.browser.development.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.browser.development.js index d4aad50bec51a..dbd60c9759270 100644 --- a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.browser.development.js +++ b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.browser.development.js @@ -8189,11 +8189,11 @@ } function ensureCorrectIsomorphicReactVersion() { var isomorphicReactPackageVersion = React.version; - if ("19.0.0-experimental-3edc000d-20240926" !== isomorphicReactPackageVersion) + if ("19.0.0-experimental-2d16326d-20240930" !== isomorphicReactPackageVersion) throw Error( 'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' + (isomorphicReactPackageVersion + - "\n - react-dom: 19.0.0-experimental-3edc000d-20240926\nLearn more: https://react.dev/warnings/version-mismatch") + "\n - react-dom: 19.0.0-experimental-2d16326d-20240930\nLearn more: https://react.dev/warnings/version-mismatch") ); } var React = require("next/dist/compiled/react-experimental"), @@ -9973,5 +9973,5 @@ startWork(request); }); }; - exports.version = "19.0.0-experimental-3edc000d-20240926"; + exports.version = "19.0.0-experimental-2d16326d-20240930"; })(); diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.browser.production.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.browser.production.js index 1cce21cb3d4f2..ab8ca32d547ed 100644 --- a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.browser.production.js +++ b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.browser.production.js @@ -6587,12 +6587,12 @@ function getPostponedState(request) { } function ensureCorrectIsomorphicReactVersion() { var isomorphicReactPackageVersion = React.version; - if ("19.0.0-experimental-3edc000d-20240926" !== isomorphicReactPackageVersion) + if ("19.0.0-experimental-2d16326d-20240930" !== isomorphicReactPackageVersion) throw Error( formatProdErrorMessage( 527, isomorphicReactPackageVersion, - "19.0.0-experimental-3edc000d-20240926" + "19.0.0-experimental-2d16326d-20240930" ) ); } @@ -6847,4 +6847,4 @@ exports.resumeAndPrerender = function (children, postponedState, options) { startWork(request); }); }; -exports.version = "19.0.0-experimental-3edc000d-20240926"; +exports.version = "19.0.0-experimental-2d16326d-20240930"; diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.bun.production.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.bun.production.js index a8e6ca1dbe80e..a41ccc466b676 100644 --- a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.bun.production.js +++ b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.bun.production.js @@ -6069,13 +6069,13 @@ function addToReplayParent(node, parentKeyPath, trackedPostpones) { } var isomorphicReactPackageVersion$jscomp$inline_779 = React.version; if ( - "19.0.0-experimental-3edc000d-20240926" !== + "19.0.0-experimental-2d16326d-20240930" !== isomorphicReactPackageVersion$jscomp$inline_779 ) throw Error( 'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' + (isomorphicReactPackageVersion$jscomp$inline_779 + - "\n - react-dom: 19.0.0-experimental-3edc000d-20240926\nLearn more: https://react.dev/warnings/version-mismatch") + "\n - react-dom: 19.0.0-experimental-2d16326d-20240930\nLearn more: https://react.dev/warnings/version-mismatch") ); exports.renderToReadableStream = function (children, options) { return new Promise(function (resolve, reject) { @@ -6166,4 +6166,4 @@ exports.renderToReadableStream = function (children, options) { startWork(request); }); }; -exports.version = "19.0.0-experimental-3edc000d-20240926"; +exports.version = "19.0.0-experimental-2d16326d-20240930"; diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.edge.development.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.edge.development.js index ee2ad518fe83f..cb99a49dce055 100644 --- a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.edge.development.js +++ b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.edge.development.js @@ -8206,11 +8206,11 @@ } function ensureCorrectIsomorphicReactVersion() { var isomorphicReactPackageVersion = React.version; - if ("19.0.0-experimental-3edc000d-20240926" !== isomorphicReactPackageVersion) + if ("19.0.0-experimental-2d16326d-20240930" !== isomorphicReactPackageVersion) throw Error( 'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' + (isomorphicReactPackageVersion + - "\n - react-dom: 19.0.0-experimental-3edc000d-20240926\nLearn more: https://react.dev/warnings/version-mismatch") + "\n - react-dom: 19.0.0-experimental-2d16326d-20240930\nLearn more: https://react.dev/warnings/version-mismatch") ); } var React = require("next/dist/compiled/react-experimental"), @@ -9997,5 +9997,5 @@ const setTimeoutOrImmediate = ? globalThis['set' + 'Immediate'] : setTimeout; - exports.version = "19.0.0-experimental-3edc000d-20240926"; + exports.version = "19.0.0-experimental-2d16326d-20240930"; })(); diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.edge.production.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.edge.production.js index 0a4c44aca1537..95a1295cf8f01 100644 --- a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.edge.production.js +++ b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.edge.production.js @@ -6689,11 +6689,11 @@ function getPostponedState(request) { } function ensureCorrectIsomorphicReactVersion() { var isomorphicReactPackageVersion = React.version; - if ("19.0.0-experimental-3edc000d-20240926" !== isomorphicReactPackageVersion) + if ("19.0.0-experimental-2d16326d-20240930" !== isomorphicReactPackageVersion) throw Error( 'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' + (isomorphicReactPackageVersion + - "\n - react-dom: 19.0.0-experimental-3edc000d-20240926\nLearn more: https://react.dev/warnings/version-mismatch") + "\n - react-dom: 19.0.0-experimental-2d16326d-20240930\nLearn more: https://react.dev/warnings/version-mismatch") ); } ensureCorrectIsomorphicReactVersion(); @@ -6958,4 +6958,4 @@ const setTimeoutOrImmediate = ? globalThis['set' + 'Immediate'] : setTimeout; -exports.version = "19.0.0-experimental-3edc000d-20240926"; +exports.version = "19.0.0-experimental-2d16326d-20240930"; diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.node.development.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.node.development.js index b9a44eb4ede4d..b5f342f00be3b 100644 --- a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.node.development.js +++ b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.node.development.js @@ -8070,11 +8070,11 @@ } function ensureCorrectIsomorphicReactVersion() { var isomorphicReactPackageVersion = React.version; - if ("19.0.0-experimental-3edc000d-20240926" !== isomorphicReactPackageVersion) + if ("19.0.0-experimental-2d16326d-20240930" !== isomorphicReactPackageVersion) throw Error( 'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' + (isomorphicReactPackageVersion + - "\n - react-dom: 19.0.0-experimental-3edc000d-20240926\nLearn more: https://react.dev/warnings/version-mismatch") + "\n - react-dom: 19.0.0-experimental-2d16326d-20240930\nLearn more: https://react.dev/warnings/version-mismatch") ); } function createDrainHandler(destination, request) { @@ -9847,5 +9847,5 @@ } }; }; - exports.version = "19.0.0-experimental-3edc000d-20240926"; + exports.version = "19.0.0-experimental-2d16326d-20240930"; })(); diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.node.production.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.node.production.js index b252b2a413259..35e364eedde84 100644 --- a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.node.production.js +++ b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server.node.production.js @@ -6568,11 +6568,11 @@ function getPostponedState(request) { } function ensureCorrectIsomorphicReactVersion() { var isomorphicReactPackageVersion = React.version; - if ("19.0.0-experimental-3edc000d-20240926" !== isomorphicReactPackageVersion) + if ("19.0.0-experimental-2d16326d-20240930" !== isomorphicReactPackageVersion) throw Error( 'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' + (isomorphicReactPackageVersion + - "\n - react-dom: 19.0.0-experimental-3edc000d-20240926\nLearn more: https://react.dev/warnings/version-mismatch") + "\n - react-dom: 19.0.0-experimental-2d16326d-20240930\nLearn more: https://react.dev/warnings/version-mismatch") ); } ensureCorrectIsomorphicReactVersion(); @@ -6823,4 +6823,4 @@ exports.resumeToPipeableStream = function (children, postponedState, options) { } }; }; -exports.version = "19.0.0-experimental-3edc000d-20240926"; +exports.version = "19.0.0-experimental-2d16326d-20240930"; diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-unstable_testing.development.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-unstable_testing.development.js index bbab11aa8a421..2252aaa0b79b4 100644 --- a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-unstable_testing.development.js +++ b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-unstable_testing.development.js @@ -25267,11 +25267,11 @@ }; (function () { var isomorphicReactPackageVersion = React.version; - if ("19.0.0-experimental-3edc000d-20240926" !== isomorphicReactPackageVersion) + if ("19.0.0-experimental-2d16326d-20240930" !== isomorphicReactPackageVersion) throw Error( 'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' + (isomorphicReactPackageVersion + - "\n - react-dom: 19.0.0-experimental-3edc000d-20240926\nLearn more: https://react.dev/warnings/version-mismatch") + "\n - react-dom: 19.0.0-experimental-2d16326d-20240930\nLearn more: https://react.dev/warnings/version-mismatch") ); })(); ("function" === typeof Map && @@ -25308,11 +25308,11 @@ !(function () { var internals = { bundleType: 1, - version: "19.0.0-experimental-3edc000d-20240926", + version: "19.0.0-experimental-2d16326d-20240930", rendererPackageName: "react-dom", currentDispatcherRef: ReactSharedInternals, findFiberByHostInstance: getClosestInstanceFromNode, - reconcilerVersion: "19.0.0-experimental-3edc000d-20240926" + reconcilerVersion: "19.0.0-experimental-2d16326d-20240930" }; internals.overrideHookState = overrideHookState; internals.overrideHookStateDeletePath = overrideHookStateDeletePath; @@ -25620,5 +25620,5 @@ } }; }; - exports.version = "19.0.0-experimental-3edc000d-20240926"; + exports.version = "19.0.0-experimental-2d16326d-20240930"; })(); diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-unstable_testing.production.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-unstable_testing.production.js index 4895851f567e9..9c0d8699de540 100644 --- a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-unstable_testing.production.js +++ b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-unstable_testing.production.js @@ -15499,14 +15499,14 @@ ReactDOMHydrationRoot.prototype.unstable_scheduleHydration = function (target) { }; var isomorphicReactPackageVersion$jscomp$inline_1688 = React.version; if ( - "19.0.0-experimental-3edc000d-20240926" !== + "19.0.0-experimental-2d16326d-20240930" !== isomorphicReactPackageVersion$jscomp$inline_1688 ) throw Error( formatProdErrorMessage( 527, isomorphicReactPackageVersion$jscomp$inline_1688, - "19.0.0-experimental-3edc000d-20240926" + "19.0.0-experimental-2d16326d-20240930" ) ); ReactDOMSharedInternals.findDOMNode = function (componentOrElement) { @@ -15528,11 +15528,11 @@ ReactDOMSharedInternals.findDOMNode = function (componentOrElement) { }; var internals$jscomp$inline_2158 = { bundleType: 0, - version: "19.0.0-experimental-3edc000d-20240926", + version: "19.0.0-experimental-2d16326d-20240930", rendererPackageName: "react-dom", currentDispatcherRef: ReactSharedInternals, findFiberByHostInstance: getClosestInstanceFromNode, - reconcilerVersion: "19.0.0-experimental-3edc000d-20240926" + reconcilerVersion: "19.0.0-experimental-2d16326d-20240930" }; if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { var hook$jscomp$inline_2159 = __REACT_DEVTOOLS_GLOBAL_HOOK__; @@ -15787,4 +15787,4 @@ exports.observeVisibleRects = function ( } }; }; -exports.version = "19.0.0-experimental-3edc000d-20240926"; +exports.version = "19.0.0-experimental-2d16326d-20240930"; diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom.development.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom.development.js index b0b76650dce52..156f2f0717af0 100644 --- a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom.development.js +++ b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom.development.js @@ -416,7 +416,7 @@ exports.useFormStatus = function () { return resolveDispatcher().useHostTransitionStatus(); }; - exports.version = "19.0.0-experimental-3edc000d-20240926"; + exports.version = "19.0.0-experimental-2d16326d-20240930"; "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom.production.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom.production.js index 8e5cb04ddaeb4..f733250e2bc49 100644 --- a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom.production.js +++ b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom.production.js @@ -207,4 +207,4 @@ exports.useFormState = function (action, initialState, permalink) { exports.useFormStatus = function () { return ReactSharedInternals.H.useHostTransitionStatus(); }; -exports.version = "19.0.0-experimental-3edc000d-20240926"; +exports.version = "19.0.0-experimental-2d16326d-20240930"; diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom.react-server.development.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom.react-server.development.js index dd4b2220d2df4..31cacf29d728d 100644 --- a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom.react-server.development.js +++ b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom.react-server.development.js @@ -336,5 +336,5 @@ })) : Internals.d.m(href)); }; - exports.version = "19.0.0-experimental-3edc000d-20240926"; + exports.version = "19.0.0-experimental-2d16326d-20240930"; })(); diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom.react-server.production.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom.react-server.production.js index 7f66a4790e1a8..9b81c5a938255 100644 --- a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom.react-server.production.js +++ b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom.react-server.production.js @@ -149,4 +149,4 @@ exports.preloadModule = function (href, options) { }); } else Internals.d.m(href); }; -exports.version = "19.0.0-experimental-3edc000d-20240926"; +exports.version = "19.0.0-experimental-2d16326d-20240930"; diff --git a/packages/next/src/compiled/react-dom-experimental/package.json b/packages/next/src/compiled/react-dom-experimental/package.json index ac33bf5e16e93..522c2e0df1867 100644 --- a/packages/next/src/compiled/react-dom-experimental/package.json +++ b/packages/next/src/compiled/react-dom-experimental/package.json @@ -72,10 +72,10 @@ "./package.json": "./package.json" }, "dependencies": { - "scheduler": "0.0.0-experimental-3edc000d-20240926" + "scheduler": "0.0.0-experimental-2d16326d-20240930" }, "peerDependencies": { - "react": "0.0.0-experimental-3edc000d-20240926" + "react": "0.0.0-experimental-2d16326d-20240930" }, "browser": { "./server.js": "./server.browser.js", diff --git a/packages/next/src/compiled/react-dom/cjs/react-dom-client.development.js b/packages/next/src/compiled/react-dom/cjs/react-dom-client.development.js index ae471bbb411b6..b46ab9153af47 100644 --- a/packages/next/src/compiled/react-dom/cjs/react-dom-client.development.js +++ b/packages/next/src/compiled/react-dom/cjs/react-dom-client.development.js @@ -24465,11 +24465,11 @@ }; (function () { var isomorphicReactPackageVersion = React.version; - if ("19.0.0-rc-3edc000d-20240926" !== isomorphicReactPackageVersion) + if ("19.0.0-rc-2d16326d-20240930" !== isomorphicReactPackageVersion) throw Error( 'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' + (isomorphicReactPackageVersion + - "\n - react-dom: 19.0.0-rc-3edc000d-20240926\nLearn more: https://react.dev/warnings/version-mismatch") + "\n - react-dom: 19.0.0-rc-2d16326d-20240930\nLearn more: https://react.dev/warnings/version-mismatch") ); })(); ("function" === typeof Map && @@ -24506,11 +24506,11 @@ !(function () { var internals = { bundleType: 1, - version: "19.0.0-rc-3edc000d-20240926", + version: "19.0.0-rc-2d16326d-20240930", rendererPackageName: "react-dom", currentDispatcherRef: ReactSharedInternals, findFiberByHostInstance: getClosestInstanceFromNode, - reconcilerVersion: "19.0.0-rc-3edc000d-20240926" + reconcilerVersion: "19.0.0-rc-2d16326d-20240930" }; internals.overrideHookState = overrideHookState; internals.overrideHookStateDeletePath = overrideHookStateDeletePath; @@ -24654,7 +24654,7 @@ listenToAllSupportedEvents(container); return new ReactDOMHydrationRoot(initialChildren); }; - exports.version = "19.0.0-rc-3edc000d-20240926"; + exports.version = "19.0.0-rc-2d16326d-20240930"; "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && diff --git a/packages/next/src/compiled/react-dom/cjs/react-dom-client.production.js b/packages/next/src/compiled/react-dom/cjs/react-dom-client.production.js index fae141b27c13e..dfa20385a8fb0 100644 --- a/packages/next/src/compiled/react-dom/cjs/react-dom-client.production.js +++ b/packages/next/src/compiled/react-dom/cjs/react-dom-client.production.js @@ -15008,14 +15008,14 @@ ReactDOMHydrationRoot.prototype.unstable_scheduleHydration = function (target) { }; var isomorphicReactPackageVersion$jscomp$inline_1666 = React.version; if ( - "19.0.0-rc-3edc000d-20240926" !== + "19.0.0-rc-2d16326d-20240930" !== isomorphicReactPackageVersion$jscomp$inline_1666 ) throw Error( formatProdErrorMessage( 527, isomorphicReactPackageVersion$jscomp$inline_1666, - "19.0.0-rc-3edc000d-20240926" + "19.0.0-rc-2d16326d-20240930" ) ); ReactDOMSharedInternals.findDOMNode = function (componentOrElement) { @@ -15037,11 +15037,11 @@ ReactDOMSharedInternals.findDOMNode = function (componentOrElement) { }; var internals$jscomp$inline_2137 = { bundleType: 0, - version: "19.0.0-rc-3edc000d-20240926", + version: "19.0.0-rc-2d16326d-20240930", rendererPackageName: "react-dom", currentDispatcherRef: ReactSharedInternals, findFiberByHostInstance: getClosestInstanceFromNode, - reconcilerVersion: "19.0.0-rc-3edc000d-20240926" + reconcilerVersion: "19.0.0-rc-2d16326d-20240930" }; if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { var hook$jscomp$inline_2138 = __REACT_DEVTOOLS_GLOBAL_HOOK__; @@ -15145,4 +15145,4 @@ exports.hydrateRoot = function (container, initialChildren, options) { listenToAllSupportedEvents(container); return new ReactDOMHydrationRoot(initialChildren); }; -exports.version = "19.0.0-rc-3edc000d-20240926"; +exports.version = "19.0.0-rc-2d16326d-20240930"; diff --git a/packages/next/src/compiled/react-dom/cjs/react-dom-profiling.development.js b/packages/next/src/compiled/react-dom/cjs/react-dom-profiling.development.js index 3c066010c10d0..8106f302b219a 100644 --- a/packages/next/src/compiled/react-dom/cjs/react-dom-profiling.development.js +++ b/packages/next/src/compiled/react-dom/cjs/react-dom-profiling.development.js @@ -24522,11 +24522,11 @@ }; (function () { var isomorphicReactPackageVersion = React.version; - if ("19.0.0-rc-3edc000d-20240926" !== isomorphicReactPackageVersion) + if ("19.0.0-rc-2d16326d-20240930" !== isomorphicReactPackageVersion) throw Error( 'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' + (isomorphicReactPackageVersion + - "\n - react-dom: 19.0.0-rc-3edc000d-20240926\nLearn more: https://react.dev/warnings/version-mismatch") + "\n - react-dom: 19.0.0-rc-2d16326d-20240930\nLearn more: https://react.dev/warnings/version-mismatch") ); })(); ("function" === typeof Map && @@ -24563,11 +24563,11 @@ !(function () { var internals = { bundleType: 1, - version: "19.0.0-rc-3edc000d-20240926", + version: "19.0.0-rc-2d16326d-20240930", rendererPackageName: "react-dom", currentDispatcherRef: ReactSharedInternals, findFiberByHostInstance: getClosestInstanceFromNode, - reconcilerVersion: "19.0.0-rc-3edc000d-20240926" + reconcilerVersion: "19.0.0-rc-2d16326d-20240930" }; internals.overrideHookState = overrideHookState; internals.overrideHookStateDeletePath = overrideHookStateDeletePath; @@ -25041,7 +25041,7 @@ exports.useFormStatus = function () { return resolveDispatcher().useHostTransitionStatus(); }; - exports.version = "19.0.0-rc-3edc000d-20240926"; + exports.version = "19.0.0-rc-2d16326d-20240930"; "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && diff --git a/packages/next/src/compiled/react-dom/cjs/react-dom-profiling.profiling.js b/packages/next/src/compiled/react-dom/cjs/react-dom-profiling.profiling.js index 00042bd0d4f26..514d63ba58746 100644 --- a/packages/next/src/compiled/react-dom/cjs/react-dom-profiling.profiling.js +++ b/packages/next/src/compiled/react-dom/cjs/react-dom-profiling.profiling.js @@ -15658,14 +15658,14 @@ ReactDOMHydrationRoot.prototype.unstable_scheduleHydration = function (target) { }; var isomorphicReactPackageVersion$jscomp$inline_1757 = React.version; if ( - "19.0.0-rc-3edc000d-20240926" !== + "19.0.0-rc-2d16326d-20240930" !== isomorphicReactPackageVersion$jscomp$inline_1757 ) throw Error( formatProdErrorMessage( 527, isomorphicReactPackageVersion$jscomp$inline_1757, - "19.0.0-rc-3edc000d-20240926" + "19.0.0-rc-2d16326d-20240930" ) ); ReactDOMSharedInternals.findDOMNode = function (componentOrElement) { @@ -15687,11 +15687,11 @@ ReactDOMSharedInternals.findDOMNode = function (componentOrElement) { }; var internals$jscomp$inline_1764 = { bundleType: 0, - version: "19.0.0-rc-3edc000d-20240926", + version: "19.0.0-rc-2d16326d-20240930", rendererPackageName: "react-dom", currentDispatcherRef: ReactSharedInternals, findFiberByHostInstance: getClosestInstanceFromNode, - reconcilerVersion: "19.0.0-rc-3edc000d-20240926", + reconcilerVersion: "19.0.0-rc-2d16326d-20240930", getLaneLabelMap: function () { for ( var map = new Map(), lane = 1, index$275 = 0; @@ -15971,7 +15971,7 @@ exports.useFormState = function (action, initialState, permalink) { exports.useFormStatus = function () { return ReactSharedInternals.H.useHostTransitionStatus(); }; -exports.version = "19.0.0-rc-3edc000d-20240926"; +exports.version = "19.0.0-rc-2d16326d-20240930"; "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && diff --git a/packages/next/src/compiled/react-dom/cjs/react-dom-server-legacy.browser.development.js b/packages/next/src/compiled/react-dom/cjs/react-dom-server-legacy.browser.development.js index ecc00a0e90f48..b4b22de24837d 100644 --- a/packages/next/src/compiled/react-dom/cjs/react-dom-server-legacy.browser.development.js +++ b/packages/next/src/compiled/react-dom/cjs/react-dom-server-legacy.browser.development.js @@ -8566,5 +8566,5 @@ 'The server used "renderToString" which does not support Suspense. If you intended for this Suspense boundary to render the fallback content on the server consider throwing an Error somewhere within the Suspense boundary. If you intended to have the server wait for the suspended component please switch to "renderToReadableStream" which supports Suspense on the server' ); }; - exports.version = "19.0.0-rc-3edc000d-20240926"; + exports.version = "19.0.0-rc-2d16326d-20240930"; })(); diff --git a/packages/next/src/compiled/react-dom/cjs/react-dom-server-legacy.browser.production.js b/packages/next/src/compiled/react-dom/cjs/react-dom-server-legacy.browser.production.js index 32cd5bd85f807..332ca5229c82d 100644 --- a/packages/next/src/compiled/react-dom/cjs/react-dom-server-legacy.browser.production.js +++ b/packages/next/src/compiled/react-dom/cjs/react-dom-server-legacy.browser.production.js @@ -5621,4 +5621,4 @@ exports.renderToString = function (children, options) { 'The server used "renderToString" which does not support Suspense. If you intended for this Suspense boundary to render the fallback content on the server consider throwing an Error somewhere within the Suspense boundary. If you intended to have the server wait for the suspended component please switch to "renderToReadableStream" which supports Suspense on the server' ); }; -exports.version = "19.0.0-rc-3edc000d-20240926"; +exports.version = "19.0.0-rc-2d16326d-20240930"; diff --git a/packages/next/src/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js b/packages/next/src/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js index 6dcbcd0f906d3..413c6e7e16ba7 100644 --- a/packages/next/src/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js +++ b/packages/next/src/compiled/react-dom/cjs/react-dom-server-legacy.node.development.js @@ -8566,5 +8566,5 @@ 'The server used "renderToString" which does not support Suspense. If you intended for this Suspense boundary to render the fallback content on the server consider throwing an Error somewhere within the Suspense boundary. If you intended to have the server wait for the suspended component please switch to "renderToPipeableStream" which supports Suspense on the server' ); }; - exports.version = "19.0.0-rc-3edc000d-20240926"; + exports.version = "19.0.0-rc-2d16326d-20240930"; })(); diff --git a/packages/next/src/compiled/react-dom/cjs/react-dom-server-legacy.node.production.js b/packages/next/src/compiled/react-dom/cjs/react-dom-server-legacy.node.production.js index 856f5d82ff025..35b6137391907 100644 --- a/packages/next/src/compiled/react-dom/cjs/react-dom-server-legacy.node.production.js +++ b/packages/next/src/compiled/react-dom/cjs/react-dom-server-legacy.node.production.js @@ -5699,4 +5699,4 @@ exports.renderToString = function (children, options) { 'The server used "renderToString" which does not support Suspense. If you intended for this Suspense boundary to render the fallback content on the server consider throwing an Error somewhere within the Suspense boundary. If you intended to have the server wait for the suspended component please switch to "renderToPipeableStream" which supports Suspense on the server' ); }; -exports.version = "19.0.0-rc-3edc000d-20240926"; +exports.version = "19.0.0-rc-2d16326d-20240930"; diff --git a/packages/next/src/compiled/react-dom/cjs/react-dom-server.browser.development.js b/packages/next/src/compiled/react-dom/cjs/react-dom-server.browser.development.js index 9bca8d31bf2e8..aaa45c9242668 100644 --- a/packages/next/src/compiled/react-dom/cjs/react-dom-server.browser.development.js +++ b/packages/next/src/compiled/react-dom/cjs/react-dom-server.browser.development.js @@ -8751,11 +8751,11 @@ didWarnAboutMaps = !1; (function () { var isomorphicReactPackageVersion = React.version; - if ("19.0.0-rc-3edc000d-20240926" !== isomorphicReactPackageVersion) + if ("19.0.0-rc-2d16326d-20240930" !== isomorphicReactPackageVersion) throw Error( 'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' + (isomorphicReactPackageVersion + - "\n - react-dom: 19.0.0-rc-3edc000d-20240926\nLearn more: https://react.dev/warnings/version-mismatch") + "\n - react-dom: 19.0.0-rc-2d16326d-20240930\nLearn more: https://react.dev/warnings/version-mismatch") ); })(); exports.renderToReadableStream = function (children, options) { @@ -8848,5 +8848,5 @@ startWork(request$jscomp$0); }); }; - exports.version = "19.0.0-rc-3edc000d-20240926"; + exports.version = "19.0.0-rc-2d16326d-20240930"; })(); diff --git a/packages/next/src/compiled/react-dom/cjs/react-dom-server.browser.production.js b/packages/next/src/compiled/react-dom/cjs/react-dom-server.browser.production.js index 23fcb690b0030..749f4d89cd80b 100644 --- a/packages/next/src/compiled/react-dom/cjs/react-dom-server.browser.production.js +++ b/packages/next/src/compiled/react-dom/cjs/react-dom-server.browser.production.js @@ -5908,14 +5908,14 @@ function abort(request, reason) { } var isomorphicReactPackageVersion$jscomp$inline_729 = React.version; if ( - "19.0.0-rc-3edc000d-20240926" !== + "19.0.0-rc-2d16326d-20240930" !== isomorphicReactPackageVersion$jscomp$inline_729 ) throw Error( formatProdErrorMessage( 527, isomorphicReactPackageVersion$jscomp$inline_729, - "19.0.0-rc-3edc000d-20240926" + "19.0.0-rc-2d16326d-20240930" ) ); exports.renderToReadableStream = function (children, options) { @@ -6007,4 +6007,4 @@ exports.renderToReadableStream = function (children, options) { startWork(request); }); }; -exports.version = "19.0.0-rc-3edc000d-20240926"; +exports.version = "19.0.0-rc-2d16326d-20240930"; diff --git a/packages/next/src/compiled/react-dom/cjs/react-dom-server.bun.production.js b/packages/next/src/compiled/react-dom/cjs/react-dom-server.bun.production.js index 8488ff0a712c2..745cff7e59244 100644 --- a/packages/next/src/compiled/react-dom/cjs/react-dom-server.bun.production.js +++ b/packages/next/src/compiled/react-dom/cjs/react-dom-server.bun.production.js @@ -5592,13 +5592,13 @@ function abort(request, reason) { } var isomorphicReactPackageVersion$jscomp$inline_731 = React.version; if ( - "19.0.0-rc-3edc000d-20240926" !== + "19.0.0-rc-2d16326d-20240930" !== isomorphicReactPackageVersion$jscomp$inline_731 ) throw Error( 'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' + (isomorphicReactPackageVersion$jscomp$inline_731 + - "\n - react-dom: 19.0.0-rc-3edc000d-20240926\nLearn more: https://react.dev/warnings/version-mismatch") + "\n - react-dom: 19.0.0-rc-2d16326d-20240930\nLearn more: https://react.dev/warnings/version-mismatch") ); exports.renderToReadableStream = function (children, options) { return new Promise(function (resolve, reject) { @@ -5689,4 +5689,4 @@ exports.renderToReadableStream = function (children, options) { startWork(request); }); }; -exports.version = "19.0.0-rc-3edc000d-20240926"; +exports.version = "19.0.0-rc-2d16326d-20240930"; diff --git a/packages/next/src/compiled/react-dom/cjs/react-dom-server.edge.development.js b/packages/next/src/compiled/react-dom/cjs/react-dom-server.edge.development.js index 80dfb5da4c057..69a54eb929ad1 100644 --- a/packages/next/src/compiled/react-dom/cjs/react-dom-server.edge.development.js +++ b/packages/next/src/compiled/react-dom/cjs/react-dom-server.edge.development.js @@ -8764,11 +8764,11 @@ didWarnAboutMaps = !1; (function () { var isomorphicReactPackageVersion = React.version; - if ("19.0.0-rc-3edc000d-20240926" !== isomorphicReactPackageVersion) + if ("19.0.0-rc-2d16326d-20240930" !== isomorphicReactPackageVersion) throw Error( 'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' + (isomorphicReactPackageVersion + - "\n - react-dom: 19.0.0-rc-3edc000d-20240926\nLearn more: https://react.dev/warnings/version-mismatch") + "\n - react-dom: 19.0.0-rc-2d16326d-20240930\nLearn more: https://react.dev/warnings/version-mismatch") ); })(); exports.renderToReadableStream = function (children, options) { @@ -8872,5 +8872,5 @@ const setTimeoutOrImmediate = ? globalThis['set' + 'Immediate'] : setTimeout; - exports.version = "19.0.0-rc-3edc000d-20240926"; + exports.version = "19.0.0-rc-2d16326d-20240930"; })(); diff --git a/packages/next/src/compiled/react-dom/cjs/react-dom-server.edge.production.js b/packages/next/src/compiled/react-dom/cjs/react-dom-server.edge.production.js index 3d7a3b8e58f7c..a643c2037e4ac 100644 --- a/packages/next/src/compiled/react-dom/cjs/react-dom-server.edge.production.js +++ b/packages/next/src/compiled/react-dom/cjs/react-dom-server.edge.production.js @@ -5996,13 +5996,13 @@ function abort(request, reason) { } var isomorphicReactPackageVersion$jscomp$inline_732 = React.version; if ( - "19.0.0-rc-3edc000d-20240926" !== + "19.0.0-rc-2d16326d-20240930" !== isomorphicReactPackageVersion$jscomp$inline_732 ) throw Error( 'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' + (isomorphicReactPackageVersion$jscomp$inline_732 + - "\n - react-dom: 19.0.0-rc-3edc000d-20240926\nLearn more: https://react.dev/warnings/version-mismatch") + "\n - react-dom: 19.0.0-rc-2d16326d-20240930\nLearn more: https://react.dev/warnings/version-mismatch") ); exports.renderToReadableStream = function (children, options) { return new Promise(function (resolve, reject) { @@ -6104,4 +6104,4 @@ const setTimeoutOrImmediate = ? globalThis['set' + 'Immediate'] : setTimeout; -exports.version = "19.0.0-rc-3edc000d-20240926"; +exports.version = "19.0.0-rc-2d16326d-20240930"; diff --git a/packages/next/src/compiled/react-dom/cjs/react-dom-server.node.development.js b/packages/next/src/compiled/react-dom/cjs/react-dom-server.node.development.js index 7e5ba246570d1..ac92cb8a8f958 100644 --- a/packages/next/src/compiled/react-dom/cjs/react-dom-server.node.development.js +++ b/packages/next/src/compiled/react-dom/cjs/react-dom-server.node.development.js @@ -8621,11 +8621,11 @@ didWarnAboutMaps = !1; (function () { var isomorphicReactPackageVersion = React.version; - if ("19.0.0-rc-3edc000d-20240926" !== isomorphicReactPackageVersion) + if ("19.0.0-rc-2d16326d-20240930" !== isomorphicReactPackageVersion) throw Error( 'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' + (isomorphicReactPackageVersion + - "\n - react-dom: 19.0.0-rc-3edc000d-20240926\nLearn more: https://react.dev/warnings/version-mismatch") + "\n - react-dom: 19.0.0-rc-2d16326d-20240930\nLearn more: https://react.dev/warnings/version-mismatch") ); })(); exports.renderToPipeableStream = function (children, options) { @@ -8667,5 +8667,5 @@ } }; }; - exports.version = "19.0.0-rc-3edc000d-20240926"; + exports.version = "19.0.0-rc-2d16326d-20240930"; })(); diff --git a/packages/next/src/compiled/react-dom/cjs/react-dom-server.node.production.js b/packages/next/src/compiled/react-dom/cjs/react-dom-server.node.production.js index b1e7ce5cfc674..e22717f0c5d87 100644 --- a/packages/next/src/compiled/react-dom/cjs/react-dom-server.node.production.js +++ b/packages/next/src/compiled/react-dom/cjs/react-dom-server.node.production.js @@ -5624,13 +5624,13 @@ function abort(request, reason) { } var isomorphicReactPackageVersion$jscomp$inline_759 = React.version; if ( - "19.0.0-rc-3edc000d-20240926" !== + "19.0.0-rc-2d16326d-20240930" !== isomorphicReactPackageVersion$jscomp$inline_759 ) throw Error( 'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' + (isomorphicReactPackageVersion$jscomp$inline_759 + - "\n - react-dom: 19.0.0-rc-3edc000d-20240926\nLearn more: https://react.dev/warnings/version-mismatch") + "\n - react-dom: 19.0.0-rc-2d16326d-20240930\nLearn more: https://react.dev/warnings/version-mismatch") ); function createDrainHandler(destination, request) { return function () { @@ -5932,4 +5932,4 @@ exports.renderToPipeableStream = function (children, options) { } }; }; -exports.version = "19.0.0-rc-3edc000d-20240926"; +exports.version = "19.0.0-rc-2d16326d-20240930"; diff --git a/packages/next/src/compiled/react-dom/cjs/react-dom.development.js b/packages/next/src/compiled/react-dom/cjs/react-dom.development.js index fe588e5c0f82c..72c60599d9bae 100644 --- a/packages/next/src/compiled/react-dom/cjs/react-dom.development.js +++ b/packages/next/src/compiled/react-dom/cjs/react-dom.development.js @@ -416,7 +416,7 @@ exports.useFormStatus = function () { return resolveDispatcher().useHostTransitionStatus(); }; - exports.version = "19.0.0-rc-3edc000d-20240926"; + exports.version = "19.0.0-rc-2d16326d-20240930"; "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && diff --git a/packages/next/src/compiled/react-dom/cjs/react-dom.production.js b/packages/next/src/compiled/react-dom/cjs/react-dom.production.js index 398f6612d895b..9dc23312c5333 100644 --- a/packages/next/src/compiled/react-dom/cjs/react-dom.production.js +++ b/packages/next/src/compiled/react-dom/cjs/react-dom.production.js @@ -207,4 +207,4 @@ exports.useFormState = function (action, initialState, permalink) { exports.useFormStatus = function () { return ReactSharedInternals.H.useHostTransitionStatus(); }; -exports.version = "19.0.0-rc-3edc000d-20240926"; +exports.version = "19.0.0-rc-2d16326d-20240930"; diff --git a/packages/next/src/compiled/react-dom/cjs/react-dom.react-server.development.js b/packages/next/src/compiled/react-dom/cjs/react-dom.react-server.development.js index 7513c2d59ccb2..85e764f7f0c2d 100644 --- a/packages/next/src/compiled/react-dom/cjs/react-dom.react-server.development.js +++ b/packages/next/src/compiled/react-dom/cjs/react-dom.react-server.development.js @@ -336,5 +336,5 @@ })) : Internals.d.m(href)); }; - exports.version = "19.0.0-rc-3edc000d-20240926"; + exports.version = "19.0.0-rc-2d16326d-20240930"; })(); diff --git a/packages/next/src/compiled/react-dom/cjs/react-dom.react-server.production.js b/packages/next/src/compiled/react-dom/cjs/react-dom.react-server.production.js index ff711cddad1e1..eda85fed0cbf7 100644 --- a/packages/next/src/compiled/react-dom/cjs/react-dom.react-server.production.js +++ b/packages/next/src/compiled/react-dom/cjs/react-dom.react-server.production.js @@ -149,4 +149,4 @@ exports.preloadModule = function (href, options) { }); } else Internals.d.m(href); }; -exports.version = "19.0.0-rc-3edc000d-20240926"; +exports.version = "19.0.0-rc-2d16326d-20240930"; diff --git a/packages/next/src/compiled/react-dom/package.json b/packages/next/src/compiled/react-dom/package.json index f66b0f4591403..212e84213ac29 100644 --- a/packages/next/src/compiled/react-dom/package.json +++ b/packages/next/src/compiled/react-dom/package.json @@ -67,10 +67,10 @@ "./package.json": "./package.json" }, "dependencies": { - "scheduler": "0.25.0-rc-3edc000d-20240926" + "scheduler": "0.25.0-rc-2d16326d-20240930" }, "peerDependencies": { - "react": "19.0.0-rc-3edc000d-20240926" + "react": "19.0.0-rc-2d16326d-20240930" }, "browser": { "./server.js": "./server.browser.js", diff --git a/packages/next/src/compiled/react-experimental/cjs/react.development.js b/packages/next/src/compiled/react-experimental/cjs/react.development.js index 901f7a7931fd0..2e815bb15773a 100644 --- a/packages/next/src/compiled/react-experimental/cjs/react.development.js +++ b/packages/next/src/compiled/react-experimental/cjs/react.development.js @@ -1232,7 +1232,7 @@ exports.useTransition = function () { return resolveDispatcher().useTransition(); }; - exports.version = "19.0.0-experimental-3edc000d-20240926"; + exports.version = "19.0.0-experimental-2d16326d-20240930"; "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && diff --git a/packages/next/src/compiled/react-experimental/cjs/react.production.js b/packages/next/src/compiled/react-experimental/cjs/react.production.js index cc1dc6b77affc..4efb1d261fd16 100644 --- a/packages/next/src/compiled/react-experimental/cjs/react.production.js +++ b/packages/next/src/compiled/react-experimental/cjs/react.production.js @@ -562,4 +562,4 @@ exports.useSyncExternalStore = function ( exports.useTransition = function () { return ReactSharedInternals.H.useTransition(); }; -exports.version = "19.0.0-experimental-3edc000d-20240926"; +exports.version = "19.0.0-experimental-2d16326d-20240930"; diff --git a/packages/next/src/compiled/react-experimental/cjs/react.react-server.development.js b/packages/next/src/compiled/react-experimental/cjs/react.react-server.development.js index 70bb20585610a..558b958f4587e 100644 --- a/packages/next/src/compiled/react-experimental/cjs/react.react-server.development.js +++ b/packages/next/src/compiled/react-experimental/cjs/react.react-server.development.js @@ -978,5 +978,5 @@ exports.useMemo = function (create, deps) { return resolveDispatcher().useMemo(create, deps); }; - exports.version = "19.0.0-experimental-3edc000d-20240926"; + exports.version = "19.0.0-experimental-2d16326d-20240930"; })(); diff --git a/packages/next/src/compiled/react-experimental/cjs/react.react-server.production.js b/packages/next/src/compiled/react-experimental/cjs/react.react-server.production.js index 2926f0a2b730c..43840352a0715 100644 --- a/packages/next/src/compiled/react-experimental/cjs/react.react-server.production.js +++ b/packages/next/src/compiled/react-experimental/cjs/react.react-server.production.js @@ -567,4 +567,4 @@ exports.useId = function () { exports.useMemo = function (create, deps) { return ReactSharedInternals.H.useMemo(create, deps); }; -exports.version = "19.0.0-experimental-3edc000d-20240926"; +exports.version = "19.0.0-experimental-2d16326d-20240930"; diff --git a/packages/next/src/compiled/react-is/package.json b/packages/next/src/compiled/react-is/package.json index 00ad5547e880f..2dc37470144b3 100644 --- a/packages/next/src/compiled/react-is/package.json +++ b/packages/next/src/compiled/react-is/package.json @@ -1,6 +1,6 @@ { "name": "react-is", - "version": "19.0.0-rc-3edc000d-20240926", + "version": "19.0.0-rc-2d16326d-20240930", "description": "Brand checking of React Elements.", "main": "index.js", "sideEffects": false, diff --git a/packages/next/src/compiled/react-server-dom-turbopack-experimental/cjs/react-server-dom-turbopack-client.browser.development.js b/packages/next/src/compiled/react-server-dom-turbopack-experimental/cjs/react-server-dom-turbopack-client.browser.development.js index cdae6067705d4..b1db236ca6cb8 100644 --- a/packages/next/src/compiled/react-server-dom-turbopack-experimental/cjs/react-server-dom-turbopack-client.browser.development.js +++ b/packages/next/src/compiled/react-server-dom-turbopack-experimental/cjs/react-server-dom-turbopack-client.browser.development.js @@ -2499,10 +2499,10 @@ return hook.checkDCE ? !0 : !1; })({ bundleType: 1, - version: "19.0.0-experimental-3edc000d-20240926", + version: "19.0.0-experimental-2d16326d-20240930", rendererPackageName: "react-server-dom-turbopack", currentDispatcherRef: ReactSharedInternals, - reconcilerVersion: "19.0.0-experimental-3edc000d-20240926", + reconcilerVersion: "19.0.0-experimental-2d16326d-20240930", getCurrentComponentInfo: function () { return currentOwnerInDEV; } diff --git a/packages/next/src/compiled/react-server-dom-turbopack-experimental/package.json b/packages/next/src/compiled/react-server-dom-turbopack-experimental/package.json index d10f9189f7543..075fde27d4bbf 100644 --- a/packages/next/src/compiled/react-server-dom-turbopack-experimental/package.json +++ b/packages/next/src/compiled/react-server-dom-turbopack-experimental/package.json @@ -48,7 +48,7 @@ "neo-async": "^2.6.1" }, "peerDependencies": { - "react": "0.0.0-experimental-3edc000d-20240926", - "react-dom": "0.0.0-experimental-3edc000d-20240926" + "react": "0.0.0-experimental-2d16326d-20240930", + "react-dom": "0.0.0-experimental-2d16326d-20240930" } } \ No newline at end of file diff --git a/packages/next/src/compiled/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js b/packages/next/src/compiled/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js index dd94d0d63c8d0..0f577cf18c7db 100644 --- a/packages/next/src/compiled/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js +++ b/packages/next/src/compiled/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js @@ -2299,10 +2299,10 @@ return hook.checkDCE ? !0 : !1; })({ bundleType: 1, - version: "19.0.0-rc-3edc000d-20240926", + version: "19.0.0-rc-2d16326d-20240930", rendererPackageName: "react-server-dom-turbopack", currentDispatcherRef: ReactSharedInternals, - reconcilerVersion: "19.0.0-rc-3edc000d-20240926", + reconcilerVersion: "19.0.0-rc-2d16326d-20240930", getCurrentComponentInfo: function () { return currentOwnerInDEV; } diff --git a/packages/next/src/compiled/react-server-dom-turbopack/package.json b/packages/next/src/compiled/react-server-dom-turbopack/package.json index 236daf1e4e4de..d741006371ee1 100644 --- a/packages/next/src/compiled/react-server-dom-turbopack/package.json +++ b/packages/next/src/compiled/react-server-dom-turbopack/package.json @@ -48,7 +48,7 @@ "neo-async": "^2.6.1" }, "peerDependencies": { - "react": "19.0.0-rc-3edc000d-20240926", - "react-dom": "19.0.0-rc-3edc000d-20240926" + "react": "19.0.0-rc-2d16326d-20240930", + "react-dom": "19.0.0-rc-2d16326d-20240930" } } \ No newline at end of file diff --git a/packages/next/src/compiled/react-server-dom-webpack-experimental/cjs/react-server-dom-webpack-client.browser.development.js b/packages/next/src/compiled/react-server-dom-webpack-experimental/cjs/react-server-dom-webpack-client.browser.development.js index 573dbfdcc31fa..03dec13b5ab89 100644 --- a/packages/next/src/compiled/react-server-dom-webpack-experimental/cjs/react-server-dom-webpack-client.browser.development.js +++ b/packages/next/src/compiled/react-server-dom-webpack-experimental/cjs/react-server-dom-webpack-client.browser.development.js @@ -2512,10 +2512,10 @@ return hook.checkDCE ? !0 : !1; })({ bundleType: 1, - version: "19.0.0-experimental-3edc000d-20240926", + version: "19.0.0-experimental-2d16326d-20240930", rendererPackageName: "react-server-dom-webpack", currentDispatcherRef: ReactSharedInternals, - reconcilerVersion: "19.0.0-experimental-3edc000d-20240926", + reconcilerVersion: "19.0.0-experimental-2d16326d-20240930", getCurrentComponentInfo: function () { return currentOwnerInDEV; } diff --git a/packages/next/src/compiled/react-server-dom-webpack-experimental/package.json b/packages/next/src/compiled/react-server-dom-webpack-experimental/package.json index 0b37f8ef37d46..798c78cdba57c 100644 --- a/packages/next/src/compiled/react-server-dom-webpack-experimental/package.json +++ b/packages/next/src/compiled/react-server-dom-webpack-experimental/package.json @@ -64,8 +64,8 @@ "webpack-sources": "^3.2.0" }, "peerDependencies": { - "react": "0.0.0-experimental-3edc000d-20240926", - "react-dom": "0.0.0-experimental-3edc000d-20240926", + "react": "0.0.0-experimental-2d16326d-20240930", + "react-dom": "0.0.0-experimental-2d16326d-20240930", "webpack": "^5.59.0" } } \ No newline at end of file diff --git a/packages/next/src/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js b/packages/next/src/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js index cc80028cdb6ed..4c5d8faefc732 100644 --- a/packages/next/src/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js +++ b/packages/next/src/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js @@ -2312,10 +2312,10 @@ return hook.checkDCE ? !0 : !1; })({ bundleType: 1, - version: "19.0.0-rc-3edc000d-20240926", + version: "19.0.0-rc-2d16326d-20240930", rendererPackageName: "react-server-dom-webpack", currentDispatcherRef: ReactSharedInternals, - reconcilerVersion: "19.0.0-rc-3edc000d-20240926", + reconcilerVersion: "19.0.0-rc-2d16326d-20240930", getCurrentComponentInfo: function () { return currentOwnerInDEV; } diff --git a/packages/next/src/compiled/react-server-dom-webpack/package.json b/packages/next/src/compiled/react-server-dom-webpack/package.json index df48294413836..212eb8110eb53 100644 --- a/packages/next/src/compiled/react-server-dom-webpack/package.json +++ b/packages/next/src/compiled/react-server-dom-webpack/package.json @@ -64,8 +64,8 @@ "webpack-sources": "^3.2.0" }, "peerDependencies": { - "react": "19.0.0-rc-3edc000d-20240926", - "react-dom": "19.0.0-rc-3edc000d-20240926", + "react": "19.0.0-rc-2d16326d-20240930", + "react-dom": "19.0.0-rc-2d16326d-20240930", "webpack": "^5.59.0" } } \ No newline at end of file diff --git a/packages/next/src/compiled/react/cjs/react.development.js b/packages/next/src/compiled/react/cjs/react.development.js index 864e2728b4106..3ec2a969fc470 100644 --- a/packages/next/src/compiled/react/cjs/react.development.js +++ b/packages/next/src/compiled/react/cjs/react.development.js @@ -1516,7 +1516,7 @@ exports.useTransition = function () { return resolveDispatcher().useTransition(); }; - exports.version = "19.0.0-rc-3edc000d-20240926"; + exports.version = "19.0.0-rc-2d16326d-20240930"; "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && diff --git a/packages/next/src/compiled/react/cjs/react.production.js b/packages/next/src/compiled/react/cjs/react.production.js index da0da48ad01f5..61da7506f8c98 100644 --- a/packages/next/src/compiled/react/cjs/react.production.js +++ b/packages/next/src/compiled/react/cjs/react.production.js @@ -536,4 +536,4 @@ exports.useSyncExternalStore = function ( exports.useTransition = function () { return ReactSharedInternals.H.useTransition(); }; -exports.version = "19.0.0-rc-3edc000d-20240926"; +exports.version = "19.0.0-rc-2d16326d-20240930"; diff --git a/packages/next/src/compiled/react/cjs/react.react-server.development.js b/packages/next/src/compiled/react/cjs/react.react-server.development.js index fc7a2ad8687a4..f159898a062e9 100644 --- a/packages/next/src/compiled/react/cjs/react.react-server.development.js +++ b/packages/next/src/compiled/react/cjs/react.react-server.development.js @@ -1113,5 +1113,5 @@ exports.useMemo = function (create, deps) { return resolveDispatcher().useMemo(create, deps); }; - exports.version = "19.0.0-rc-3edc000d-20240926"; + exports.version = "19.0.0-rc-2d16326d-20240930"; })(); diff --git a/packages/next/src/compiled/react/cjs/react.react-server.production.js b/packages/next/src/compiled/react/cjs/react.react-server.production.js index d86f38f1bef01..82f37c62674a0 100644 --- a/packages/next/src/compiled/react/cjs/react.react-server.production.js +++ b/packages/next/src/compiled/react/cjs/react.react-server.production.js @@ -424,4 +424,4 @@ exports.useId = function () { exports.useMemo = function (create, deps) { return ReactSharedInternals.H.useMemo(create, deps); }; -exports.version = "19.0.0-rc-3edc000d-20240926"; +exports.version = "19.0.0-rc-2d16326d-20240930"; diff --git a/packages/next/src/compiled/unistore/unistore.js b/packages/next/src/compiled/unistore/unistore.js index 5c9b2d4eae5aa..b6368abb2b14e 100644 --- a/packages/next/src/compiled/unistore/unistore.js +++ b/packages/next/src/compiled/unistore/unistore.js @@ -1 +1 @@ -(()=>{var t={80:t=>{function n(t,i){for(var _ in i)t[_]=i[_];return t}t.exports=function(t){var i=[];function u(t){for(var _=[],a=0;a<i.length;a++)i[a]===t?t=null:_.push(i[a]);i=_}function e(_,a,f){t=a?_:n(n({},t),_);for(var o=i,c=0;c<o.length;c++)o[c](t,f)}return t=t||{},{action:function(i){function r(t){e(t,!1,i)}return function(){for(var _=arguments,a=[t],f=0;f<arguments.length;f++)a.push(_[f]);var o=i.apply(this,a);if(null!=o)return o.then?o.then(r):r(o)}},setState:e,subscribe:function(t){return i.push(t),function(){u(t)}},unsubscribe:u,getState:function(){return t}}}}};var i={};function __nccwpck_require__(_){var a=i[_];if(a!==undefined){return a.exports}var f=i[_]={exports:{}};var o=true;try{t[_](f,f.exports,__nccwpck_require__);o=false}finally{if(o)delete i[_]}return f.exports}if(typeof __nccwpck_require__!=="undefined")__nccwpck_require__.ab=__dirname+"/";var _=__nccwpck_require__(80);module.exports=_})(); \ No newline at end of file +(()=>{var t={826:t=>{function n(t,i){for(var _ in i)t[_]=i[_];return t}t.exports=function(t){var i=[];function u(t){for(var _=[],a=0;a<i.length;a++)i[a]===t?t=null:_.push(i[a]);i=_}function e(_,a,f){t=a?_:n(n({},t),_);for(var o=i,c=0;c<o.length;c++)o[c](t,f)}return t=t||{},{action:function(i){function r(t){e(t,!1,i)}return function(){for(var _=arguments,a=[t],f=0;f<arguments.length;f++)a.push(_[f]);var o=i.apply(this,a);if(null!=o)return o.then?o.then(r):r(o)}},setState:e,subscribe:function(t){return i.push(t),function(){u(t)}},unsubscribe:u,getState:function(){return t}}}}};var i={};function __nccwpck_require__(_){var a=i[_];if(a!==undefined){return a.exports}var f=i[_]={exports:{}};var o=true;try{t[_](f,f.exports,__nccwpck_require__);o=false}finally{if(o)delete i[_]}return f.exports}if(typeof __nccwpck_require__!=="undefined")__nccwpck_require__.ab=__dirname+"/";var _=__nccwpck_require__(826);module.exports=_})(); \ No newline at end of file diff --git a/packages/next/src/lib/metadata/resolve-metadata.ts b/packages/next/src/lib/metadata/resolve-metadata.ts index 508643c49c98c..0a8c490bd1181 100644 --- a/packages/next/src/lib/metadata/resolve-metadata.ts +++ b/packages/next/src/lib/metadata/resolve-metadata.ts @@ -441,7 +441,10 @@ export async function collectMetadata({ mod = await getComponentTypeModule(tree, 'layout') modType = errorConvention } else { - ;[mod, modType] = await getLayoutOrPageModule(tree) + const { mod: layoutOrPageMod, modType: layoutOrPageModType } = + await getLayoutOrPageModule(tree) + mod = layoutOrPageMod + modType = layoutOrPageModType } if (modType) { diff --git a/packages/next/src/lib/needs-experimental-react.ts b/packages/next/src/lib/needs-experimental-react.ts index b8d2b05cdfc0e..373d4d61b146e 100644 --- a/packages/next/src/lib/needs-experimental-react.ts +++ b/packages/next/src/lib/needs-experimental-react.ts @@ -1,9 +1,5 @@ import type { NextConfig } from '../server/config-shared' export function needsExperimentalReact(config: NextConfig) { - return Boolean( - config.experimental?.ppr || - config.experimental?.taint || - config.experimental?.dynamicIO - ) + return Boolean(config.experimental?.ppr || config.experimental?.taint) } diff --git a/packages/next/src/lib/scheduler.ts b/packages/next/src/lib/scheduler.ts index 3ed6b6a1c6695..212d87d0d017f 100644 --- a/packages/next/src/lib/scheduler.ts +++ b/packages/next/src/lib/scheduler.ts @@ -15,7 +15,11 @@ export const scheduleOnNextTick = <T = void>(cb: ScheduledFn<T>): void => { // This was inspired by the implementation of the DataLoader interface: https://github.com/graphql/dataloader/blob/d336bd15282664e0be4b4a657cb796f09bafbc6b/src/index.js#L213-L255 // Promise.resolve().then(() => { - process.nextTick(cb) + if (process.env.NEXT_RUNTIME === 'edge') { + setTimeout(cb, 0) + } else { + process.nextTick(cb) + } }) } diff --git a/packages/next/src/server/app-render/action-handler.ts b/packages/next/src/server/app-render/action-handler.ts index b2e4f86df9c6e..68423cea8b924 100644 --- a/packages/next/src/server/app-render/action-handler.ts +++ b/packages/next/src/server/app-render/action-handler.ts @@ -725,6 +725,7 @@ export async function handleAction({ if (isMultipartAction) { if (isFetchAction) { const busboy = (require('busboy') as typeof import('busboy'))({ + defParamCharset: 'utf8', headers: req.headers, limits: { fieldSize: bodySizeLimitBytes }, }) diff --git a/packages/next/src/server/app-render/app-render.tsx b/packages/next/src/server/app-render/app-render.tsx index 740444cd7cbfb..61e5cb3d9b1e2 100644 --- a/packages/next/src/server/app-render/app-render.tsx +++ b/packages/next/src/server/app-render/app-render.tsx @@ -155,6 +155,8 @@ import { import { CacheSignal } from './cache-signal' import { getTracedMetadata } from '../lib/trace/utils' +import './clean-async-snapshot.external' + export type GetDynamicParamFromSegment = ( // [slug] / [[slug]] / [...slug] segment: string @@ -512,6 +514,22 @@ async function generateDynamicFlightRenderResult( onError, } ) + await waitAtLeastOneReactRenderTask() + + if ( + ctx.staticGenerationStore.pendingRevalidates || + ctx.staticGenerationStore.revalidatedTags || + ctx.staticGenerationStore.pendingRevalidateWrites + ) { + const promises = Promise.all([ + ctx.staticGenerationStore.incrementalCache?.revalidateTag( + ctx.staticGenerationStore.revalidatedTags || [] + ), + ...Object.values(ctx.staticGenerationStore.pendingRevalidates || {}), + ...(ctx.staticGenerationStore.pendingRevalidateWrites || []), + ]) + ctx.renderOpts.waitUntil = (p) => promises.then(() => p) + } return new FlightRenderResult(flightReadableStream, { fetchMetrics: ctx.staticGenerationStore.fetchMetrics, @@ -1084,7 +1102,8 @@ async function renderToHTMLOrFlightImpl( // If we have pending revalidates, wait until they are all resolved. if ( staticGenerationStore.pendingRevalidates || - staticGenerationStore.pendingRevalidateWrites + staticGenerationStore.pendingRevalidateWrites || + staticGenerationStore.revalidatedTags ) { options.waitUntil = Promise.all([ staticGenerationStore.incrementalCache?.revalidateTag( @@ -1193,7 +1212,8 @@ async function renderToHTMLOrFlightImpl( // If we have pending revalidates, wait until they are all resolved. if ( staticGenerationStore.pendingRevalidates || - staticGenerationStore.pendingRevalidateWrites + staticGenerationStore.pendingRevalidateWrites || + staticGenerationStore.revalidatedTags ) { options.waitUntil = Promise.all([ staticGenerationStore.incrementalCache?.revalidateTag( @@ -1841,6 +1861,20 @@ async function prerenderToStream( } let flightController = new AbortController() + + let reactServerIsDynamic = false + function onError(err: unknown) { + if (err === abortReason) { + reactServerIsDynamic = true + return PRERENDER_COMPLETE + } else if (isPrerenderInterruptedError(err)) { + reactServerIsDynamic = true + return err.digest + } + + return serverComponentsErrorHandler(err) + } + // We're not going to use the result of this render because the only time it could be used // is if it completes in a microtask and that's likely very rare for any non-trivial app const firstAttemptRSCPayload = await prerenderAsyncStorage.run( @@ -1851,6 +1885,8 @@ async function prerenderToStream( res.statusCode === 404 ) + let didError = false + let prospectiveRenderError: unknown = null ;( prerenderAsyncStorage.run( // The store to scope @@ -1862,23 +1898,41 @@ async function prerenderToStream( clientReferenceManifest.clientModules, { // This render will be thrown away so we don't need to track errors or postpones - onError: undefined, + onError, onPostpone: undefined, // we don't care to track postpones during the prospective render because we need // to always do a final render anyway signal: flightController.signal, } ) as Promise<ReactServerPrerenderResolveToType> - ).catch(() => {}) + ).catch((err) => { + if ( + err !== abortReason && + !isPrerenderInterruptedError(err) && + !isDynamicServerError(err) + ) { + didError = true + prospectiveRenderError = err + } + }) // When this resolves the cache has no inflight reads and we can ascertain the dynamic outcome await cacheSignal.cacheReady() flightController.abort(abortReason) + // We wait a microtask to to ensure the catch handler has a chance to run if the root errors when we abort. + await 1 + if (didError) { + // We errored with something other than prerender errors during the warmup. We throw here + // to allow the user error to be handled + throw prospectiveRenderError + } + // When PPR is enabled we don't synchronously abort the render when performing a prospective render // because it might prevent us from discovering all caches during the render which is essential // when we perform the second single-task render. // Reset the dynamic IO state for the final render + reactServerIsDynamic = false flightController = new AbortController() dynamicTracking = createDynamicTrackingState( renderOpts.isDebugDynamicAccesses @@ -1893,16 +1947,6 @@ async function prerenderToStream( dynamicTracking, } - let reactServerIsDynamic = false - function onError(err: unknown) { - if (err === abortReason || isPrerenderInterruptedError(err)) { - reactServerIsDynamic = true - return - } - - return serverComponentsErrorHandler(err) - } - function onPostpone(reason: string) { if ( reason === PRERENDER_COMPLETE || @@ -2124,21 +2168,12 @@ async function prerenderToStream( const PRERENDER_COMPLETE = 'NEXT_PRERENDER_COMPLETE' const abortReason = new Error(PRERENDER_COMPLETE) + ;(abortReason as any).digest = PRERENDER_COMPLETE // We need to scope the dynamic IO state per render because we don't want to leak // details between the prospective render and the final render let flightController = new AbortController() - let reactServerIsDynamic = false - function onError(err: unknown) { - if (err === abortReason || isPrerenderInterruptedError(err)) { - reactServerIsDynamic = true - return - } - - return serverComponentsErrorHandler(err) - } - dynamicTracking = createDynamicTrackingState( renderOpts.isDebugDynamicAccesses ) @@ -2160,14 +2195,28 @@ async function prerenderToStream( ctx, res.statusCode === 404 ) - // We're not going to use the result of this render because the only time it could be used - // is if it completes in a microtask and that's likely very rare for any non-trivial app - ;( - prerenderAsyncStorage.run( + + let reactServerIsDynamic = false + let reactServerIsSynchronouslyDynamic = false + + function onError(err: unknown) { + if (err === abortReason) { + reactServerIsDynamic = true + return PRERENDER_COMPLETE + } else if (isPrerenderInterruptedError(err)) { + reactServerIsSynchronouslyDynamic = true + return err.digest + } + + return serverComponentsErrorHandler(err) + } + + try { + const prospectiveStream = prerenderAsyncStorage.run( // The store to scope prospectiveRenderPrerenderStore, // The function to run - ComponentMod.prerender, + ComponentMod.renderToReadableStream, // ... the arguments for the function to run firstAttemptRSCPayload, clientReferenceManifest.clientModules, @@ -2175,34 +2224,27 @@ async function prerenderToStream( onError, signal: flightController.signal, } - ) as Promise<ReactServerPrerenderResolveToType> - ).catch(() => {}) + ) as ReadableStream<Uint8Array> - // When this resolves the cache has no inflight reads and we can ascertain the dynamic outcome - await cacheSignal.cacheReady() - if (reactServerIsDynamic) { - // During a prospective render the only dynamic thing that can happen is a synchronous dynamic - // API access. We expect to have a tracked expression to use for our dynamic error but we fall back - // to a generic error if we don't. - const dynamicReason = getFirstDynamicReason(dynamicTracking) - if (dynamicReason) { - throw new DynamicServerError( - `Route ${staticGenerationStore.route} couldn't be rendered statically because it used \`${dynamicReason}\`. See more info here: https://nextjs.org/docs/messages/dynamic-server-error` - ) + // When this resolves the cache has no inflight reads and we can ascertain the dynamic outcome + await cacheSignal.cacheReady() + // Even though we could detect whether a sync dynamic API was used we still need to render SSR to + // do error validation so we just abort and re-render. + flightController.abort(abortReason) + + await warmFlightResponse(prospectiveStream, clientReferenceManifest) + } catch (err) { + if ( + err === abortReason || + isPrerenderInterruptedError(err) || + isDynamicServerError(err) + ) { + // We aborted with an incomplete shell. We'll handle this below with the handling + // for dynamic. } else { - console.error( - 'Expected Next.js to keep track of reason for opting out of static rendering but one was not found. This is a bug in Next.js' - ) - throw new DynamicServerError( - `Route ${staticGenerationStore.route} couldn't be rendered statically because it used a dynamic API. See more info here: https://nextjs.org/docs/messages/dynamic-server-error` - ) + // We have some other kind of shell error, we want to bubble this up to be handled + throw err } - } else { - // The render didn't explicitly use any Dynamic APIs but it might have IO so we need to retry - // the render. We abort the current render here to avoid doing unecessary work. - // Keep in mind that while the render is aborted, inflight async ServerComponents can still continue - // and might call dynamic APIs. - flightController.abort(abortReason) } // Reset the prerenderState because we are going to retry the render @@ -2211,6 +2253,8 @@ async function prerenderToStream( renderOpts.isDebugDynamicAccesses ) reactServerIsDynamic = false + reactServerIsSynchronouslyDynamic = false + let SSRIsDynamic = false const finalRenderPrerenderStore: PrerenderStore = { // During the final prerender we don't need to track cache access so we omit the signal @@ -2219,6 +2263,18 @@ async function prerenderToStream( dynamicTracking, } + const SSRController = new AbortController() + const ssrPrerenderStore: PrerenderStore = { + // For HTML Generation we don't need to track cache reads (RSC only) + cacheSignal: null, + // We expect the SSR render to complete in a single Task and need to be able to synchronously abort + // When you use APIs that are considered dynamic or synchronous IO. + controller: SSRController, + // We do track dynamic access because searchParams and certain hooks can still be + // dynamic during SSR + dynamicTracking, + } + const finalAttemptRSCPayload = await prerenderAsyncStorage.run( finalRenderPrerenderStore, getRSCPayload, @@ -2227,15 +2283,29 @@ async function prerenderToStream( res.statusCode === 404 ) - const reactServerResult = (reactServerPrerenderResult = - await createReactServerPrerenderResult( - prerenderAndAbortInSequentialTasks( - () => + function SSROnError(err: unknown, errorInfo?: ErrorInfo) { + if (err === abortReason) { + SSRIsDynamic = true + return PRERENDER_COMPLETE + } else if (isPrerenderInterruptedError(err)) { + SSRIsDynamic = true + return err.digest + } + + return htmlRendererErrorHandler(err, errorInfo) + } + + let reactServerStream: ReadableStream<Uint8Array> + let htmlStream + try { + htmlStream = await prerenderAndAbortInSequentialTasks( + () => { + const teedStream = ( prerenderAsyncStorage.run( // The store to scope finalRenderPrerenderStore, // The function to run - ComponentMod.prerender, + ComponentMod.renderToReadableStream, // ... the arguments for the function to run finalAttemptRSCPayload, clientReferenceManifest.clientModules, @@ -2243,66 +2313,19 @@ async function prerenderToStream( onError, signal: flightController.signal, } - ), - () => { - flightController.abort(abortReason) - } - ) - )) - - if (reactServerIsDynamic) { - // There was unfinished work after we aborted after the first render Task. This means there is some IO - // that is not covered by a cache and we need to bail out of static generation. - const err = new DynamicServerError( - `Route ${staticGenerationStore.route} couldn't be rendered statically because it used IO that was not cached in a Server Component. See more info here: https://nextjs.org/docs/messages/dynamic-io` - ) - serverComponentsErrorHandler(err) - throw err - } + ) as ReadableStream<Uint8Array> + ).tee() - await warmFlightResponse( - reactServerResult.asStream(), - clientReferenceManifest - ) + reactServerStream = teedStream[0] + const rscForSSRStream = teedStream[1] - const SSRController = new AbortController() - const ssrPrerenderStore: PrerenderStore = { - // For HTML Generation we don't need to track cache reads (RSC only) - cacheSignal: null, - // We expect the SSR render to complete in a single Task and need to be able to synchronously abort - // When you use APIs that are considered dynamic or synchronous IO. - controller: SSRController, - // We do track dynamic access because searchParams and certain hooks can still be - // dynamic during SSR - dynamicTracking, - } - let SSRIsDynamic = false - function SSROnError(err: unknown) { - if (err === abortReason || isPrerenderInterruptedError(err)) { - SSRIsDynamic = true - return - } - - return htmlRendererErrorHandler(err) - } - function SSROnPostpone(_: string) { - // We don't really support postponing when PPR is off but since experimental react - // has this API enabled we need to account for it. For now we'll just treat any postpone - // as dynamic. - SSRIsDynamic = true - return - } - - const prerender = require('react-dom/static.edge') - .prerender as (typeof import('react-dom/static.edge'))['prerender'] - const { prelude: htmlStream } = - await prerenderAndAbortInSequentialTasks( - () => - prerenderAsyncStorage.run( + const renderToReadableStream = require('react-dom/server.edge') + .renderToReadableStream as (typeof import('react-dom/server.edge'))['renderToReadableStream'] + const pendingHTMLStream = prerenderAsyncStorage.run( ssrPrerenderStore, - prerender, + renderToReadableStream, <App - reactServerStream={reactServerResult.asUnclosingStream()} + reactServerStream={rscForSSRStream} preinitScripts={preinitScripts} clientReferenceManifest={clientReferenceManifest} ServerInsertedHTMLProvider={ServerInsertedHTMLProvider} @@ -2311,18 +2334,30 @@ async function prerenderToStream( { signal: SSRController.signal, onError: SSROnError, - onPostpone: SSROnPostpone, // When debugging the static shell, client-side rendering should be // disabled to prevent blanking out the page. bootstrapScripts: renderOpts.isDebugStaticShell ? [] : [bootstrapScript], } - ), + ) + pendingHTMLStream.catch(() => {}) + return pendingHTMLStream + }, () => { SSRController.abort(abortReason) + flightController.abort(abortReason) } ) + } catch (err) { + if (err === abortReason || isPrerenderInterruptedError(err)) { + // We aborted with an incomplete shell. We'll handle this below with the handling + // for dynamic. + } else { + // We have some other kind of shell error, we want to bubble this up to be handled + throw err + } + } if (SSRIsDynamic) { // Something dynamic happened in the SSR phase of the render. This could be IO or it could be @@ -2337,8 +2372,33 @@ async function prerenderToStream( `Route ${staticGenerationStore.route} couldn't be rendered statically because it used IO that was not cached in a Client Component. See more info here: https://nextjs.org/docs/messages/dynamic-io` ) } + } else if (reactServerIsSynchronouslyDynamic) { + const dynamicReason = getFirstDynamicReason(dynamicTracking) + if (dynamicReason) { + throw new DynamicServerError( + `Route ${staticGenerationStore.route} couldn't be rendered statically because it used \`${dynamicReason}\`. See more info here: https://nextjs.org/docs/messages/dynamic-server-error` + ) + } else { + console.error( + 'Expected Next.js to keep track of reason for opting out of static rendering but one was not found. This is a bug in Next.js' + ) + throw new DynamicServerError( + `Route ${staticGenerationStore.route} couldn't be rendered statically because it used a dynamic API. See more info here: https://nextjs.org/docs/messages/dynamic-server-error` + ) + } + } else if (reactServerIsDynamic) { + // There was unfinished work after we aborted after the first render Task. This means there is some IO + // that is not covered by a cache and we need to bail out of static generation. + const err = new DynamicServerError( + `Route ${staticGenerationStore.route} couldn't be rendered statically because it used IO that was not cached in a Server Component. See more info here: https://nextjs.org/docs/messages/dynamic-io` + ) + serverComponentsErrorHandler(err) + throw err } + const reactServerResult = + await createReactServerPrerenderResultFromRender(reactServerStream!) + metadata.flightData = await streamToBuffer(reactServerResult.asStream()) const getServerInsertedHTML = makeGetServerInsertedHTML({ @@ -2352,7 +2412,7 @@ async function prerenderToStream( return { digestErrorsMap: reactServerErrorsByDigest, ssrErrors: allCapturedErrors, - stream: await continueFizzStream(htmlStream, { + stream: await continueFizzStream(htmlStream!, { inlinedDataStream: createInlinedDataReadableStream( reactServerResult.consumeAsStream(), ctx.nonce, @@ -2792,7 +2852,7 @@ function trackChunkLoading(load: Promise<unknown>) { } export async function warmFlightResponse( - flightStream: BinaryStreamOf<any>, + flightStream: ReadableStream<Uint8Array>, clientReferenceManifest: DeepReadonly<ClientReferenceManifest> ) { let createFromReadableStream diff --git a/packages/next/src/server/app-render/cache-async-storage-instance.ts b/packages/next/src/server/app-render/cache-async-storage-instance.ts new file mode 100644 index 0000000000000..7e3dd96a92ba0 --- /dev/null +++ b/packages/next/src/server/app-render/cache-async-storage-instance.ts @@ -0,0 +1,4 @@ +import type { CacheAsyncStorage } from './cache-async-storage.external' +import { createAsyncLocalStorage } from '../../client/components/async-local-storage' + +export const cacheAsyncStorage: CacheAsyncStorage = createAsyncLocalStorage() diff --git a/packages/next/src/server/app-render/cache-async-storage.external.ts b/packages/next/src/server/app-render/cache-async-storage.external.ts new file mode 100644 index 0000000000000..3ae7f5de064d3 --- /dev/null +++ b/packages/next/src/server/app-render/cache-async-storage.external.ts @@ -0,0 +1,15 @@ +import type { AsyncLocalStorage } from 'async_hooks' + +// Share the instance module in the next-shared layer +import { cacheAsyncStorage } from './cache-async-storage-instance' with { 'turbopack-transition': 'next-shared' } + +/** + * The Cache store is for tracking information inside a "use cache" or unstable_cache context. + * Inside this context we should never expose any request or page specific information. + */ +export type CacheStore = { + // TODO: Inside this scope we'll track tags and life times of this scope. +} + +export type CacheAsyncStorage = AsyncLocalStorage<CacheStore> +export { cacheAsyncStorage } diff --git a/packages/next/src/server/app-render/clean-async-snapshot-instance.ts b/packages/next/src/server/app-render/clean-async-snapshot-instance.ts new file mode 100644 index 0000000000000..27ff09044ce27 --- /dev/null +++ b/packages/next/src/server/app-render/clean-async-snapshot-instance.ts @@ -0,0 +1,6 @@ +import { createSnapshot } from '../../client/components/async-local-storage' + +export const runInCleanSnapshot: <R, TArgs extends any[]>( + fn: (...args: TArgs) => R, + ...args: TArgs +) => R = createSnapshot() diff --git a/packages/next/src/server/app-render/clean-async-snapshot.external.ts b/packages/next/src/server/app-render/clean-async-snapshot.external.ts new file mode 100644 index 0000000000000..44aa9ff8f0361 --- /dev/null +++ b/packages/next/src/server/app-render/clean-async-snapshot.external.ts @@ -0,0 +1,4 @@ +// Share the instance module in the next-shared layer +import { runInCleanSnapshot } from './clean-async-snapshot-instance' with { 'turbopack-transition': 'next-shared' } + +export { runInCleanSnapshot } diff --git a/packages/next/src/server/app-render/create-component-tree.tsx b/packages/next/src/server/app-render/create-component-tree.tsx index dfb0c2d39cae5..20bb19cae0bf6 100644 --- a/packages/next/src/server/app-render/create-component-tree.tsx +++ b/packages/next/src/server/app-render/create-component-tree.tsx @@ -159,7 +159,7 @@ async function createComponentTreeInternal({ const isLayout = typeof layout !== 'undefined' const isPage = typeof page !== 'undefined' - const [layoutOrPageMod] = await getTracer().trace( + const { mod: layoutOrPageMod } = await getTracer().trace( NextNodeServerSpan.getLayoutOrPageModule, { hideSpan: !(isLayout || isPage), diff --git a/packages/next/src/server/app-render/dynamic-rendering.ts b/packages/next/src/server/app-render/dynamic-rendering.ts index c0ac2cebd6ee3..7ec0e3988384a 100644 --- a/packages/next/src/server/app-render/dynamic-rendering.ts +++ b/packages/next/src/server/app-render/dynamic-rendering.ts @@ -300,7 +300,7 @@ export function abortAndThrowOnSynchronousDynamicDataAccess( prerenderStore: PrerenderStore ): never { abortOnSynchronousDynamicDataAccess(route, expression, prerenderStore) - throw new Error( + throw createPrerenderInterruptedError( `Route ${route} needs to bail out of prerendering at this point because it used ${expression}.` ) } @@ -405,7 +405,13 @@ function createPrerenderInterruptedError(message: string): Error { return error } -export function isPrerenderInterruptedError(error: unknown) { +type DigestError = Error & { + digest: string +} + +export function isPrerenderInterruptedError( + error: unknown +): error is DigestError { return ( typeof error === 'object' && error !== null && diff --git a/packages/next/src/server/async-storage/cache-scope.ts b/packages/next/src/server/async-storage/cache-scope.ts index f8d0970dc94ad..763bcc1a792c3 100644 --- a/packages/next/src/server/async-storage/cache-scope.ts +++ b/packages/next/src/server/async-storage/cache-scope.ts @@ -1,11 +1,11 @@ -import { AsyncLocalStorage } from 'async_hooks' +import { createAsyncLocalStorage } from '../../client/components/async-local-storage' export interface CacheScopeStore { cache?: Map<string, any> } export const cacheScopeAsyncLocalStorage = - new AsyncLocalStorage<CacheScopeStore>() + createAsyncLocalStorage<CacheScopeStore>() /** * For dynamic IO handling we want to have a scoped memory diff --git a/packages/next/src/server/async-storage/with-static-generation-store.ts b/packages/next/src/server/async-storage/with-static-generation-store.ts index a6458fe9125ac..8054a81de0fb6 100644 --- a/packages/next/src/server/async-storage/with-static-generation-store.ts +++ b/packages/next/src/server/async-storage/with-static-generation-store.ts @@ -6,6 +6,7 @@ import type { RenderOptsPartial } from '../app-render/types' import type { FetchMetric } from '../base-http' import type { RequestLifecycleOpts } from '../base-server' import type { FallbackRouteParams } from '../../server/request/fallback-params' +import type { AppSegmentConfig } from '../../build/app-segments/app-segment-config' import { normalizeAppPath } from '../../shared/lib/router/utils/app-paths' @@ -25,7 +26,7 @@ export type StaticGenerationContext = { renderOpts: { incrementalCache?: IncrementalCache isOnDemandRevalidate?: boolean - fetchCache?: StaticGenerationStore['fetchCache'] + fetchCache?: AppSegmentConfig['fetchCache'] isServerAction?: boolean pendingWaitUntil?: Promise<any> experimental: Pick< diff --git a/packages/next/src/server/dev/static-paths-worker.ts b/packages/next/src/server/dev/static-paths-worker.ts index 1d3e5071b4f59..cde0bdd14d44c 100644 --- a/packages/next/src/server/dev/static-paths-worker.ts +++ b/packages/next/src/server/dev/static-paths-worker.ts @@ -6,24 +6,19 @@ import '../node-environment' import { buildAppStaticPaths, buildStaticPaths, - collectGenerateParams, reduceAppConfig, } from '../../build/utils' -import type { - GenerateParamsResults, - PartialStaticPathsResult, -} from '../../build/utils' +import { collectSegments } from '../../build/app-segments/collect-app-segments' +import type { PartialStaticPathsResult } from '../../build/utils' import { loadComponents } from '../load-components' import { setHttpClientAndAgentOptions } from '../setup-http-agent-env' import type { IncrementalCache } from '../lib/incremental-cache' -import { - isAppPageRouteModule, - isAppRouteRouteModule, -} from '../route-modules/checks' +import { isAppPageRouteModule } from '../route-modules/checks' import { checkIsRoutePPREnabled, type ExperimentalPPRConfig, } from '../lib/experimental/ppr' +import { InvariantError } from '../../shared/lib/invariant-error' type RuntimeConfig = { pprConfig: ExperimentalPPRConfig | undefined @@ -86,40 +81,18 @@ export async function loadStaticPaths({ isAppPath, }) - if (!components.getStaticPaths && !isAppPath) { - // we shouldn't get to this point since the worker should - // only be called for SSG pages with getStaticPaths - throw new Error( - `Invariant: failed to load page with getStaticPaths for ${pathname}` - ) - } - if (isAppPath) { - const { routeModule } = components - const generateParams: GenerateParamsResults = - routeModule && isAppRouteRouteModule(routeModule) - ? [ - { - config: { - revalidate: routeModule.userland.revalidate, - dynamic: routeModule.userland.dynamic, - dynamicParams: routeModule.userland.dynamicParams, - }, - generateStaticParams: routeModule.userland.generateStaticParams, - segmentPath: pathname, - }, - ] - : await collectGenerateParams(components.ComponentMod.tree) + const segments = await collectSegments(components) const isRoutePPREnabled = - isAppPageRouteModule(routeModule) && - checkIsRoutePPREnabled(config.pprConfig, reduceAppConfig(generateParams)) + isAppPageRouteModule(components.routeModule) && + checkIsRoutePPREnabled(config.pprConfig, reduceAppConfig(segments)) - return await buildAppStaticPaths({ + return buildAppStaticPaths({ dir, page: pathname, dynamicIO: config.dynamicIO, - generateParams, + segments, configFileName: config.configFileName, distDir, requestHeaders, @@ -133,9 +106,15 @@ export async function loadStaticPaths({ isAppPPRFallbacksEnabled, buildId, }) + } else if (!components.getStaticPaths) { + // We shouldn't get to this point since the worker should only be called for + // SSG pages with getStaticPaths. + throw new InvariantError( + `Failed to load page with getStaticPaths for ${pathname}` + ) } - return await buildStaticPaths({ + return buildStaticPaths({ page: pathname, getStaticPaths: components.getStaticPaths, configFileName: config.configFileName, diff --git a/packages/next/src/server/lib/app-dir-module.ts b/packages/next/src/server/lib/app-dir-module.ts index 9de970147a2a9..3e2438ed074a5 100644 --- a/packages/next/src/server/lib/app-dir-module.ts +++ b/packages/next/src/server/lib/app-dir-module.ts @@ -17,21 +17,25 @@ export async function getLayoutOrPageModule(loaderTree: LoaderTree) { const isDefaultPage = typeof defaultPage !== 'undefined' && loaderTree[0] === DEFAULT_SEGMENT_KEY - let value = undefined + let mod = undefined let modType: 'layout' | 'page' | undefined = undefined + let filePath = undefined if (isLayout) { - value = await layout[0]() + mod = await layout[0]() modType = 'layout' + filePath = layout[1] } else if (isPage) { - value = await page[0]() + mod = await page[0]() modType = 'page' + filePath = page[1] } else if (isDefaultPage) { - value = await defaultPage[0]() + mod = await defaultPage[0]() modType = 'page' + filePath = defaultPage[1] } - return [value, modType] as const + return { mod, modType, filePath } } export async function getComponentTypeModule( diff --git a/packages/next/src/server/request/connection.ts b/packages/next/src/server/request/connection.ts new file mode 100644 index 0000000000000..8ea2af93ac9c4 --- /dev/null +++ b/packages/next/src/server/request/connection.ts @@ -0,0 +1,72 @@ +import { staticGenerationAsyncStorage } from '../../client/components/static-generation-async-storage.external' +import { + isDynamicIOPrerender, + prerenderAsyncStorage, +} from '../app-render/prerender-async-storage.external' +import { + postponeWithTracking, + throwToInterruptStaticGeneration, + trackDynamicDataInDynamicRender, +} from '../app-render/dynamic-rendering' +import { StaticGenBailoutError } from '../../client/components/static-generation-bailout' +import { makeHangingPromise } from '../dynamic-rendering-utils' + +/** + * This function allows you to indicate that you require an actual user Request before continuing. + * + * During prerendering it will never resolve and during rendering it resolves immediately. + */ +export function connection(): Promise<void> { + const staticGenerationStore = staticGenerationAsyncStorage.getStore() + const prerenderStore = prerenderAsyncStorage.getStore() + + if (staticGenerationStore) { + if (staticGenerationStore.forceStatic) { + // When using forceStatic we override all other logic and always just return an empty + // headers object without tracking + return Promise.resolve(undefined) + } + + if (staticGenerationStore.isUnstableCacheCallback) { + throw new Error( + `Route ${staticGenerationStore.route} used "connection" inside a function cached with "unstable_cache(...)". The \`connection()\` function is used to indicate the subsequent code must only run when there is an actual Request, but caches must be able to be produced before a Request so this function is not allowed in this scope. See more info here: https://nextjs.org/docs/app/api-reference/functions/unstable_cache` + ) + } else if (staticGenerationStore.dynamicShouldError) { + throw new StaticGenBailoutError( + `Route ${staticGenerationStore.route} with \`dynamic = "error"\` couldn't be rendered statically because it used \`connection\`. See more info here: https://nextjs.org/docs/app/building-your-application/rendering/static-and-dynamic#dynamic-rendering` + ) + } + + if (prerenderStore) { + // We are in PPR and/or dynamicIO mode and prerendering + + if (isDynamicIOPrerender(prerenderStore)) { + // We use the controller and cacheSignal as an indication we are in dynamicIO mode. + // When resolving headers for a prerender with dynamic IO we return a forever promise + // along with property access tracked synchronous headers. + + // We don't track dynamic access here because access will be tracked when you access + // one of the properties of the headers object. + return makeHangingPromise() + } else { + // We are prerendering with PPR. We need track dynamic access here eagerly + // to keep continuity with how headers has worked in PPR without dynamicIO. + // TODO consider switching the semantic to throw on property access intead + postponeWithTracking( + staticGenerationStore.route, + 'connection', + prerenderStore.dynamicTracking + ) + } + } else if (staticGenerationStore.isStaticGeneration) { + // We are in a legacy static generation mode while prerendering + // We treat this function call as a bailout of static generation + throwToInterruptStaticGeneration('connection', staticGenerationStore) + } + // We fall through to the dynamic context below but we still track dynamic access + // because in dev we can still error for things like using headers inside a cache context + trackDynamicDataInDynamicRender(staticGenerationStore) + } + + return Promise.resolve(undefined) +} diff --git a/packages/next/src/server/request/utils.ts b/packages/next/src/server/request/utils.ts index ebfac7d5be2ca..7f2e75f0b6617 100644 --- a/packages/next/src/server/request/utils.ts +++ b/packages/next/src/server/request/utils.ts @@ -33,7 +33,7 @@ export function describeHasCheckingStringProperty( prop: string ) { const stringifiedProp = JSON.stringify(prop) - return `\`Reflect.has(${target}, ${stringifiedProp}\`, \`${stringifiedProp} in ${target}\`, or similar` + return `\`Reflect.has(${target}, ${stringifiedProp})\`, \`${stringifiedProp} in ${target}\`, or similar` } export function throwWithStaticGenerationBailoutError( diff --git a/packages/next/src/server/route-modules/app-route/module.ts b/packages/next/src/server/route-modules/app-route/module.ts index 74a70bc354895..fc37dd349598c 100644 --- a/packages/next/src/server/route-modules/app-route/module.ts +++ b/packages/next/src/server/route-modules/app-route/module.ts @@ -1,6 +1,6 @@ import type { NextConfig } from '../../config-shared' import type { AppRouteRouteDefinition } from '../../route-definitions/app-route-route-definition' -import type { AppConfig } from '../../../build/utils' +import type { AppSegmentConfig } from '../../../build/app-segments/app-segment-config' import type { NextRequest } from '../../web/spec-extension/request' import type { PrerenderManifest } from '../../../build' import type { NextURL } from '../../web/next-url' @@ -69,6 +69,7 @@ import type { RenderOptsPartial } from '../../app-render/types' import { CacheSignal } from '../../app-render/cache-signal' import { scheduleImmediate } from '../../../lib/scheduler' import { createServerParamsForRoute } from '../../request/params' +import type { AppSegment } from '../../../build/app-segments/collect-app-segments' /** * The AppRouteModule is the type of the module exported by the bundled App @@ -123,10 +124,11 @@ export type AppRouteHandlers = { * routes. This contains all the user generated code. */ export type AppRouteUserlandModule = AppRouteHandlers & - Pick<AppConfig, 'dynamic' | 'revalidate' | 'dynamicParams' | 'fetchCache'> & { - // TODO: (wyattjoh) create a type for this - generateStaticParams?: any - } + Pick< + AppSegmentConfig, + 'dynamic' | 'revalidate' | 'dynamicParams' | 'fetchCache' + > & + Pick<AppSegment, 'generateStaticParams'> /** * AppRouteRouteModuleOptions is the options that are passed to the app route diff --git a/packages/next/src/server/use-cache/use-cache-wrapper.ts b/packages/next/src/server/use-cache/use-cache-wrapper.ts index 69730c3f01d8e..daf4d29d4c8f7 100644 --- a/packages/next/src/server/use-cache/use-cache-wrapper.ts +++ b/packages/next/src/server/use-cache/use-cache-wrapper.ts @@ -1,5 +1,4 @@ import type { DeepReadonly } from '../../shared/lib/deep-readonly' -import { createSnapshot } from '../../client/components/async-local-storage' /* eslint-disable import/no-extraneous-dependencies */ import { renderToReadableStream, @@ -15,6 +14,9 @@ import { import type { StaticGenerationStore } from '../../client/components/static-generation-async-storage.external' import { staticGenerationAsyncStorage } from '../../client/components/static-generation-async-storage.external' +import type { CacheStore } from '../app-render/cache-async-storage.external' +import { cacheAsyncStorage } from '../app-render/cache-async-storage.external' +import { runInCleanSnapshot } from '../app-render/clean-async-snapshot.external' import type { ClientReferenceManifest } from '../../build/webpack/plugins/flight-manifest-plugin' @@ -73,10 +75,80 @@ cacheHandlerMap.set('default', { }, }) -// TODO: Consider moving this another module that is guaranteed to be required in a safe scope. -const runInCleanSnapshot = createSnapshot() +function generateCacheEntry( + staticGenerationStore: StaticGenerationStore, + clientReferenceManifest: DeepReadonly<ClientReferenceManifest>, + cacheHandler: CacheHandler, + serializedCacheKey: string | ArrayBuffer, + encodedArguments: FormData | string, + fn: any +): Promise<any> { + // We need to run this inside a clean AsyncLocalStorage snapshot so that the cache + // generation cannot read anything from the context we're currently executing which + // might include request specific things like cookies() inside a React.cache(). + // Note: It is important that we await at least once before this because it lets us + // pop out of any stack specific contexts as well - aka "Sync" Local Storage. + return runInCleanSnapshot( + generateCacheEntryWithRestoredStaticGenerationStore, + staticGenerationStore, + clientReferenceManifest, + cacheHandler, + serializedCacheKey, + encodedArguments, + fn + ) +} + +function generateCacheEntryWithRestoredStaticGenerationStore( + staticGenerationStore: StaticGenerationStore, + clientReferenceManifest: DeepReadonly<ClientReferenceManifest>, + cacheHandler: CacheHandler, + serializedCacheKey: string | ArrayBuffer, + encodedArguments: FormData | string, + fn: any +) { + // Since we cleared the AsyncLocalStorage we need to restore the staticGenerationStore. + // Note: We explicitly don't restore the RequestStore nor the PrerenderStore. + // We don't want any request specific information leaking an we don't want to create a + // bloated fake request mock for every cache call. So any feature that currently lives + // in RequestStore but should be available to Caches need to move to StaticGenerationStore. + // PrerenderStore is not needed inside the cache scope because the outer most one will + // be the one to report its result to the outer Prerender. + return staticGenerationAsyncStorage.run( + staticGenerationStore, + generateCacheEntryWithCacheContext, + staticGenerationStore, + clientReferenceManifest, + cacheHandler, + serializedCacheKey, + encodedArguments, + fn + ) +} + +function generateCacheEntryWithCacheContext( + staticGenerationStore: StaticGenerationStore, + clientReferenceManifest: DeepReadonly<ClientReferenceManifest>, + cacheHandler: CacheHandler, + serializedCacheKey: string | ArrayBuffer, + encodedArguments: FormData | string, + fn: any +) { + // Initialize the Store for this Cache entry. + const cacheStore: CacheStore = {} + return cacheAsyncStorage.run( + cacheStore, + generateCacheEntryImpl, + staticGenerationStore, + clientReferenceManifest, + cacheHandler, + serializedCacheKey, + encodedArguments, + fn + ) +} -async function generateCacheEntry( +async function generateCacheEntryImpl( staticGenerationStore: StaticGenerationStore, clientReferenceManifest: DeepReadonly<ClientReferenceManifest>, cacheHandler: CacheHandler, @@ -230,8 +302,7 @@ export function cache(kind: string, id: string, fn: any) { const clientReferenceManifestSingleton = getClientReferenceManifestSingleton() - stream = await runInCleanSnapshot( - generateCacheEntry, + stream = await generateCacheEntry( staticGenerationStore, clientReferenceManifestSingleton, cacheHandler, @@ -246,8 +317,7 @@ export function cache(kind: string, id: string, fn: any) { // then we should warm up the cache with a fresh revalidated entry. const clientReferenceManifestSingleton = getClientReferenceManifestSingleton() - const ignoredStream = await runInCleanSnapshot( - generateCacheEntry, + const ignoredStream = await generateCacheEntry( staticGenerationStore, clientReferenceManifestSingleton, cacheHandler, diff --git a/packages/next/src/server/web/exports/index.ts b/packages/next/src/server/web/exports/index.ts index 942bc5a9caf9a..fc5fc2bbb4883 100644 --- a/packages/next/src/server/web/exports/index.ts +++ b/packages/next/src/server/web/exports/index.ts @@ -6,3 +6,4 @@ export { NextResponse } from '../spec-extension/response' export { userAgent, userAgentFromString } from '../spec-extension/user-agent' export { URLPattern } from '../spec-extension/url-pattern' export { unstable_after } from '../../after' +export { connection } from '../../request/connection' diff --git a/packages/next/types/$$compiled.internal.d.ts b/packages/next/types/$$compiled.internal.d.ts index c5b048b6cecf1..ba1de837ef409 100644 --- a/packages/next/types/$$compiled.internal.d.ts +++ b/packages/next/types/$$compiled.internal.d.ts @@ -523,8 +523,8 @@ declare module 'next/dist/compiled/@opentelemetry/api' { } declare module 'next/dist/compiled/zod' { - import * as m from 'zod' - export = m + import * as z from 'zod' + export = z } declare module 'mini-css-extract-plugin' diff --git a/packages/react-refresh-utils/package.json b/packages/react-refresh-utils/package.json index eef529c3e9a94..6ba7530a0a7d7 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": "15.0.0-canary.173", + "version": "15.0.0-canary.174", "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 8640d22c5bd47..13d79f8f64f56 100644 --- a/packages/third-parties/package.json +++ b/packages/third-parties/package.json @@ -1,6 +1,6 @@ { "name": "@next/third-parties", - "version": "15.0.0-canary.173", + "version": "15.0.0-canary.174", "repository": { "url": "vercel/next.js", "directory": "packages/third-parties" @@ -26,7 +26,7 @@ "third-party-capital": "1.0.20" }, "devDependencies": { - "next": "15.0.0-canary.173", + "next": "15.0.0-canary.174", "outdent": "0.8.0", "prettier": "2.5.1" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 14ab2cfeee75c..2fe127c861bf5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -15,10 +15,10 @@ overrides: '@babel/traverse': 7.22.5 '@types/react': npm:types-react@19.0.0-rc.0 '@types/react-dom': npm:types-react-dom@19.0.0-rc.0 - react: 19.0.0-rc-3edc000d-20240926 - react-dom: 19.0.0-rc-3edc000d-20240926 - react-is: 19.0.0-rc-3edc000d-20240926 - scheduler: 0.25.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 + react-dom: 19.0.0-rc-2d16326d-20240930 + react-is: 19.0.0-rc-2d16326d-20240930 + scheduler: 0.25.0-rc-2d16326d-20240930 patchedDependencies: webpack-sources@3.2.3: @@ -64,7 +64,7 @@ importers: version: 11.11.0 '@emotion/react': specifier: 11.11.1 - version: 11.11.1(react@19.0.0-rc-3edc000d-20240926)(types-react@19.0.0-rc.0) + version: 11.11.1(react@19.0.0-rc-2d16326d-20240930)(types-react@19.0.0-rc.0) '@fullhuman/postcss-purgecss': specifier: 1.3.0 version: 1.3.0 @@ -73,7 +73,7 @@ importers: version: 2.2.1(webpack@5.90.0(@swc/core@1.6.13(@swc/helpers@0.5.13))) '@mdx-js/react': specifier: 2.2.1 - version: 2.2.1(react@19.0.0-rc-3edc000d-20240926) + version: 2.2.1(react@19.0.0-rc-2d16326d-20240930) '@next/bundle-analyzer': specifier: workspace:* version: link:packages/next-bundle-analyzer @@ -142,7 +142,7 @@ importers: version: 6.1.2(@jest/globals@29.7.0)(@types/jest@29.5.5)(jest@29.7.0(@types/node@20.12.3)(babel-plugin-macros@3.1.0)) '@testing-library/react': specifier: ^15.0.5 - version: 15.0.7(react-dom@19.0.0-rc-3edc000d-20240926(react@19.0.0-rc-3edc000d-20240926))(react@19.0.0-rc-3edc000d-20240926)(types-react@19.0.0-rc.0) + version: 15.0.7(react-dom@19.0.0-rc-2d16326d-20240930(react@19.0.0-rc-2d16326d-20240930))(react@19.0.0-rc-2d16326d-20240930)(types-react@19.0.0-rc.0) '@types/busboy': specifier: 1.5.3 version: 1.5.3 @@ -453,50 +453,50 @@ importers: specifier: 0.3.0 version: 0.3.0 react: - specifier: 19.0.0-rc-3edc000d-20240926 - version: 19.0.0-rc-3edc000d-20240926 + specifier: 19.0.0-rc-2d16326d-20240930 + version: 19.0.0-rc-2d16326d-20240930 react-17: specifier: npm:react@17.0.2 version: react@17.0.2 react-builtin: - specifier: npm:react@19.0.0-rc-3edc000d-20240926 - version: react@19.0.0-rc-3edc000d-20240926 + specifier: npm:react@19.0.0-rc-2d16326d-20240930 + version: react@19.0.0-rc-2d16326d-20240930 react-dom: - specifier: 19.0.0-rc-3edc000d-20240926 - version: 19.0.0-rc-3edc000d-20240926(react@19.0.0-rc-3edc000d-20240926) + specifier: 19.0.0-rc-2d16326d-20240930 + version: 19.0.0-rc-2d16326d-20240930(react@19.0.0-rc-2d16326d-20240930) react-dom-17: specifier: npm:react-dom@17.0.2 - version: react-dom@17.0.2(react@19.0.0-rc-3edc000d-20240926) + version: react-dom@17.0.2(react@19.0.0-rc-2d16326d-20240930) react-dom-builtin: - specifier: npm:react-dom@19.0.0-rc-3edc000d-20240926 - version: react-dom@19.0.0-rc-3edc000d-20240926(react@19.0.0-rc-3edc000d-20240926) + specifier: npm:react-dom@19.0.0-rc-2d16326d-20240930 + version: react-dom@19.0.0-rc-2d16326d-20240930(react@19.0.0-rc-2d16326d-20240930) react-dom-experimental-builtin: - specifier: npm:react-dom@0.0.0-experimental-3edc000d-20240926 - version: react-dom@0.0.0-experimental-3edc000d-20240926(react@19.0.0-rc-3edc000d-20240926) + specifier: npm:react-dom@0.0.0-experimental-2d16326d-20240930 + version: react-dom@0.0.0-experimental-2d16326d-20240930(react@19.0.0-rc-2d16326d-20240930) react-experimental-builtin: - specifier: npm:react@0.0.0-experimental-3edc000d-20240926 - version: react@0.0.0-experimental-3edc000d-20240926 + specifier: npm:react@0.0.0-experimental-2d16326d-20240930 + version: react@0.0.0-experimental-2d16326d-20240930 react-is-builtin: - specifier: npm:react-is@19.0.0-rc-3edc000d-20240926 - version: react-is@19.0.0-rc-3edc000d-20240926 + specifier: npm:react-is@19.0.0-rc-2d16326d-20240930 + version: react-is@19.0.0-rc-2d16326d-20240930 react-server-dom-turbopack: - specifier: 19.0.0-rc-3edc000d-20240926 - version: 19.0.0-rc-3edc000d-20240926(react-dom@19.0.0-rc-3edc000d-20240926(react@19.0.0-rc-3edc000d-20240926))(react@19.0.0-rc-3edc000d-20240926) + specifier: 19.0.0-rc-2d16326d-20240930 + version: 19.0.0-rc-2d16326d-20240930(react-dom@19.0.0-rc-2d16326d-20240930(react@19.0.0-rc-2d16326d-20240930))(react@19.0.0-rc-2d16326d-20240930) react-server-dom-turbopack-experimental: - specifier: npm:react-server-dom-turbopack@0.0.0-experimental-3edc000d-20240926 - version: react-server-dom-turbopack@0.0.0-experimental-3edc000d-20240926(react-dom@19.0.0-rc-3edc000d-20240926(react@19.0.0-rc-3edc000d-20240926))(react@19.0.0-rc-3edc000d-20240926) + specifier: npm:react-server-dom-turbopack@0.0.0-experimental-2d16326d-20240930 + version: react-server-dom-turbopack@0.0.0-experimental-2d16326d-20240930(react-dom@19.0.0-rc-2d16326d-20240930(react@19.0.0-rc-2d16326d-20240930))(react@19.0.0-rc-2d16326d-20240930) react-server-dom-webpack: - specifier: 19.0.0-rc-3edc000d-20240926 - version: 19.0.0-rc-3edc000d-20240926(react-dom@19.0.0-rc-3edc000d-20240926(react@19.0.0-rc-3edc000d-20240926))(react@19.0.0-rc-3edc000d-20240926)(webpack@5.90.0(@swc/core@1.6.13(@swc/helpers@0.5.13))) + specifier: 19.0.0-rc-2d16326d-20240930 + version: 19.0.0-rc-2d16326d-20240930(react-dom@19.0.0-rc-2d16326d-20240930(react@19.0.0-rc-2d16326d-20240930))(react@19.0.0-rc-2d16326d-20240930)(webpack@5.90.0(@swc/core@1.6.13(@swc/helpers@0.5.13))) react-server-dom-webpack-experimental: - specifier: npm:react-server-dom-webpack@0.0.0-experimental-3edc000d-20240926 - version: react-server-dom-webpack@0.0.0-experimental-3edc000d-20240926(react-dom@19.0.0-rc-3edc000d-20240926(react@19.0.0-rc-3edc000d-20240926))(react@19.0.0-rc-3edc000d-20240926)(webpack@5.90.0(@swc/core@1.6.13(@swc/helpers@0.5.13))) + specifier: npm:react-server-dom-webpack@0.0.0-experimental-2d16326d-20240930 + version: react-server-dom-webpack@0.0.0-experimental-2d16326d-20240930(react-dom@19.0.0-rc-2d16326d-20240930(react@19.0.0-rc-2d16326d-20240930))(react@19.0.0-rc-2d16326d-20240930)(webpack@5.90.0(@swc/core@1.6.13(@swc/helpers@0.5.13))) react-ssr-prepass: specifier: 1.0.8 - version: 1.0.8(react-is@19.0.0-rc-f90a6bcc-20240827)(react@19.0.0-rc-3edc000d-20240926) + version: 1.0.8(react-is@19.0.0-rc-f90a6bcc-20240827)(react@19.0.0-rc-2d16326d-20240930) react-virtualized: specifier: 9.22.3 - version: 9.22.3(react-dom@19.0.0-rc-3edc000d-20240926(react@19.0.0-rc-3edc000d-20240926))(react@19.0.0-rc-3edc000d-20240926) + version: 9.22.3(react-dom@19.0.0-rc-2d16326d-20240930(react@19.0.0-rc-2d16326d-20240930))(react@19.0.0-rc-2d16326d-20240930) relay-compiler: specifier: 13.0.2 version: 13.0.2 @@ -519,11 +519,11 @@ importers: specifier: 0.10.9 version: 0.10.9 scheduler-builtin: - specifier: npm:scheduler@0.25.0-rc-3edc000d-20240926 - version: scheduler@0.25.0-rc-3edc000d-20240926 + specifier: npm:scheduler@0.25.0-rc-2d16326d-20240930 + version: scheduler@0.25.0-rc-2d16326d-20240930 scheduler-experimental-builtin: - specifier: npm:scheduler@0.0.0-experimental-3edc000d-20240926 - version: scheduler@0.0.0-experimental-3edc000d-20240926 + specifier: npm:scheduler@0.0.0-experimental-2d16326d-20240930 + version: scheduler@0.0.0-experimental-2d16326d-20240930 seedrandom: specifier: 3.0.5 version: 3.0.5 @@ -538,16 +538,16 @@ importers: version: 6.0.0 styled-components: specifier: 6.0.0-rc.3 - version: 6.0.0-rc.3(react-dom@19.0.0-rc-3edc000d-20240926(react@19.0.0-rc-3edc000d-20240926))(react@19.0.0-rc-3edc000d-20240926) + version: 6.0.0-rc.3(react-dom@19.0.0-rc-2d16326d-20240930(react@19.0.0-rc-2d16326d-20240930))(react@19.0.0-rc-2d16326d-20240930) styled-jsx: specifier: 5.1.6 - version: 5.1.6(@babel/core@7.22.5)(babel-plugin-macros@3.1.0)(react@19.0.0-rc-3edc000d-20240926) + version: 5.1.6(@babel/core@7.22.5)(babel-plugin-macros@3.1.0)(react@19.0.0-rc-2d16326d-20240930) styled-jsx-plugin-postcss: specifier: 3.0.2 version: 3.0.2 swr: specifier: ^2.2.4 - version: 2.2.4(react@19.0.0-rc-3edc000d-20240926) + version: 2.2.4(react@19.0.0-rc-2d16326d-20240930) tailwindcss: specifier: 3.2.7 version: 3.2.7(postcss@8.4.31) @@ -792,7 +792,7 @@ importers: packages/eslint-config-next: dependencies: '@next/eslint-plugin-next': - specifier: 15.0.0-canary.173 + specifier: 15.0.0-canary.174 version: link:../eslint-plugin-next '@rushstack/eslint-patch': specifier: ^1.3.3 @@ -853,7 +853,7 @@ importers: packages/next: dependencies: '@next/env': - specifier: 15.0.0-canary.173 + specifier: 15.0.0-canary.174 version: link:../next-env '@swc/counter': specifier: 0.1.3 @@ -863,7 +863,7 @@ importers: version: 0.5.13 babel-plugin-react-compiler: specifier: '*' - version: 0.0.0-experimental-b12479e-20240926 + version: 0.0.0-experimental-3feb7e4-20240930 busboy: specifier: 1.6.0 version: 1.6.0 @@ -874,17 +874,17 @@ importers: specifier: 8.4.31 version: 8.4.31 react: - specifier: 19.0.0-rc-3edc000d-20240926 - version: 19.0.0-rc-3edc000d-20240926 + specifier: 19.0.0-rc-2d16326d-20240930 + version: 19.0.0-rc-2d16326d-20240930 react-dom: - specifier: 19.0.0-rc-3edc000d-20240926 - version: 19.0.0-rc-3edc000d-20240926(react@19.0.0-rc-3edc000d-20240926) + specifier: 19.0.0-rc-2d16326d-20240930 + version: 19.0.0-rc-2d16326d-20240930(react@19.0.0-rc-2d16326d-20240930) sass: specifier: ^1.3.0 version: 1.77.8 styled-jsx: specifier: 5.1.6 - version: 5.1.6(@babel/core@7.22.5)(babel-plugin-macros@3.1.0)(react@19.0.0-rc-3edc000d-20240926) + version: 5.1.6(@babel/core@7.22.5)(babel-plugin-macros@3.1.0)(react@19.0.0-rc-2d16326d-20240930) optionalDependencies: sharp: specifier: ^0.33.5 @@ -981,19 +981,19 @@ importers: specifier: 1.2.0 version: 1.2.0 '@next/font': - specifier: 15.0.0-canary.173 + specifier: 15.0.0-canary.174 version: link:../font '@next/polyfill-module': - specifier: 15.0.0-canary.173 + specifier: 15.0.0-canary.174 version: link:../next-polyfill-module '@next/polyfill-nomodule': - specifier: 15.0.0-canary.173 + specifier: 15.0.0-canary.174 version: link:../next-polyfill-nomodule '@next/react-refresh-utils': - specifier: 15.0.0-canary.173 + specifier: 15.0.0-canary.174 version: link:../react-refresh-utils '@next/swc': - specifier: 15.0.0-canary.173 + specifier: 15.0.0-canary.174 version: link:../next-swc '@opentelemetry/api': specifier: 1.6.0 @@ -1465,7 +1465,7 @@ importers: version: 1.0.35 unistore: specifier: 3.4.1 - version: 3.4.1(react@19.0.0-rc-3edc000d-20240926) + version: 3.4.1(react@19.0.0-rc-2d16326d-20240930) util: specifier: 0.12.4 version: 0.12.4 @@ -1605,14 +1605,14 @@ importers: packages/third-parties: dependencies: react: - specifier: 19.0.0-rc-3edc000d-20240926 - version: 19.0.0-rc-3edc000d-20240926 + specifier: 19.0.0-rc-2d16326d-20240930 + version: 19.0.0-rc-2d16326d-20240930 third-party-capital: specifier: 1.0.20 version: 1.0.20 devDependencies: next: - specifier: 15.0.0-canary.173 + specifier: 15.0.0-canary.174 version: link:../next outdent: specifier: 0.8.0 @@ -1666,14 +1666,14 @@ importers: specifier: 29.5.0 version: 29.5.0 react: - specifier: 19.0.0-rc-3edc000d-20240926 - version: 19.0.0-rc-3edc000d-20240926 + specifier: 19.0.0-rc-2d16326d-20240930 + version: 19.0.0-rc-2d16326d-20240930 react-test-renderer: specifier: 18.2.0 - version: 18.2.0(react@19.0.0-rc-3edc000d-20240926) + version: 18.2.0(react@19.0.0-rc-2d16326d-20240930) styled-jsx: specifier: ^5.1.2 - version: 5.1.6(@babel/core@7.22.5)(babel-plugin-macros@3.1.0)(react@19.0.0-rc-3edc000d-20240926) + version: 5.1.6(@babel/core@7.22.5)(babel-plugin-macros@3.1.0)(react@19.0.0-rc-2d16326d-20240930) turbopack/packages/devlow-bench: dependencies: @@ -3317,7 +3317,7 @@ packages: resolution: {integrity: sha512-5mlW1DquU5HaxjLkfkGN1GA/fvVGdyHURRiX/0FHl2cfIfRxSOfmxEH5YS43edp0OldZrZ+dkBKbngxcNCdZvA==} peerDependencies: '@types/react': '*' - react: 19.0.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 peerDependenciesMeta: '@types/react': optional: true @@ -3334,7 +3334,7 @@ packages: '@emotion/use-insertion-effect-with-fallbacks@1.0.1': resolution: {integrity: sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==} peerDependencies: - react: 19.0.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 '@emotion/utils@1.2.1': resolution: {integrity: sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==} @@ -3527,14 +3527,14 @@ packages: '@floating-ui/react-dom@2.1.0': resolution: {integrity: sha512-lNzj5EQmEKn5FFKc04+zasr09h/uX8RtJRNj5gUXsSQIXHVWTVh+hVAg1vOMCexkX8EgvemMvIFpQfkosnVNyA==} peerDependencies: - react: 19.0.0-rc-3edc000d-20240926 - react-dom: 19.0.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 + react-dom: 19.0.0-rc-2d16326d-20240930 '@floating-ui/react@0.26.16': resolution: {integrity: sha512-HEf43zxZNAI/E781QIVpYSF3K2VH4TTYZpqecjdsFkjsaU1EbaWcM++kw0HXFffj7gDUcBFevX8s0rQGQpxkow==} peerDependencies: - react: 19.0.0-rc-3edc000d-20240926 - react-dom: 19.0.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 + react-dom: 19.0.0-rc-2d16326d-20240930 '@floating-ui/utils@0.2.2': resolution: {integrity: sha512-J4yDIIthosAsRZ5CPYP/jQvUAQtlZTTD/4suA08/FEnlxqW3sKS9iAhgsa9VYLZ6vDHn/ixJgIqRQPotoBjxIw==} @@ -4174,13 +4174,13 @@ packages: resolution: {integrity: sha512-l9ypojKN3PjwO1CSLIsqxi7mA25+7w+xc71Q+JuCCREI0tuGwkZsKbIOpuTATIJOjPh8ycLiW7QxX1LYsRTq6w==} peerDependencies: '@mantine/hooks': 7.10.1 - react: 19.0.0-rc-3edc000d-20240926 - react-dom: 19.0.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 + react-dom: 19.0.0-rc-2d16326d-20240930 '@mantine/hooks@7.11.2': resolution: {integrity: sha512-jhyVe/sbDEG2U8rr2lMecUPgQxcfr5hh9HazqGfkS7ZRIMDO7uJ947yAcTMGGkp5Lxtt5TBFt1Cb6tiB2/1agg==} peerDependencies: - react: 19.0.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 '@mapbox/node-pre-gyp@1.0.5': resolution: {integrity: sha512-4srsKPXWlIxp5Vbqz5uLfBN+du2fJChBoYn/f2h991WLdk7jUvcSk/McVLSv/X+xQIPI8eGD5GjrnygdyHnhPA==} @@ -4197,7 +4197,7 @@ packages: '@mdx-js/react@2.2.1': resolution: {integrity: sha512-YdXcMcEnqZhzql98RNrqYo9cEhTTesBiCclEtoiQUbJwx87q9453GTapYU6kJ8ZZ2ek1Vp25SiAXEFy5O/eAPw==} peerDependencies: - react: 19.0.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 '@mswjs/cookies@1.1.0': resolution: {integrity: sha512-0ZcCVQxifZmhwNBoQIrystCb+2sWBY2Zw8lpfJBPCHGCA/HWqehITeCRVIv4VMy8MPlaHo2w2pTHFV2pFfqKPw==} @@ -4880,8 +4880,8 @@ packages: engines: {node: '>=18'} peerDependencies: '@types/react': npm:types-react@19.0.0-rc.0 - react: 19.0.0-rc-3edc000d-20240926 - react-dom: 19.0.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 + react-dom: 19.0.0-rc-2d16326d-20240930 peerDependenciesMeta: '@types/react': optional: true @@ -5953,8 +5953,8 @@ packages: peerDependencies: '@babel/core': 7.22.5 - babel-plugin-react-compiler@0.0.0-experimental-b12479e-20240926: - resolution: {integrity: sha512-QoiS1tZsE7gDdd3EFLpprvM4edUBhNrV98El2G073Onhg2vJ+wub+RpEtztoNTNGrAwogj+CcFU9j1VxxzhiPQ==} + babel-plugin-react-compiler@0.0.0-experimental-3feb7e4-20240930: + resolution: {integrity: sha512-+zfcqLj8SFwmt5lfkMCUfNgjxm4u2A072u9H0W68CEgQkmeBNrpHtTX/9s2BmqPx3XyejHFlV0oVcq8+ke8YSg==} babel-plugin-react-compiler@0.0.0-experimental-c23de8d-20240515: resolution: {integrity: sha512-0XN2gmpT55QtAz5n7d5g91y1AuO9tRhWBaLgCRyc4ExHrlr7+LfxW+YTb3mOwxngkkiggwM8HyYsaEK9MqhnlQ==} @@ -10353,7 +10353,7 @@ packages: lucide-react@0.383.0: resolution: {integrity: sha512-13xlG0CQCJtzjSQYwwJ3WRqMHtRj3EXmLlorrARt7y+IHnxUCp3XyFNL1DfaGySWxHObDvnu1u1dV+0VMKHUSg==} peerDependencies: - react: 19.0.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 lz-string@1.5.0: resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} @@ -12568,28 +12568,28 @@ packages: resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} hasBin: true - react-dom@0.0.0-experimental-3edc000d-20240926: - resolution: {integrity: sha512-eaj/y1+vx2/ihB0iFwqud78HnEAsIp0ULV+PsFJTlHZmQcXgoeVCLhW//KqyMjiAvrkqqlpgi3CZVKOhe7Rfhg==} + react-dom@0.0.0-experimental-2d16326d-20240930: + resolution: {integrity: sha512-T+BiGsehI8sG/erfwttI6LmcAk+MQLMJs5bBhZwW5MSsVxyEMNugnYMLBhDTEMxXfUFu/7fYnBQmOzi6AJOdqA==} peerDependencies: - react: 19.0.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 react-dom@17.0.2: resolution: {integrity: sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==} peerDependencies: - react: 19.0.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 - react-dom@19.0.0-rc-3edc000d-20240926: - resolution: {integrity: sha512-0nEYp9I8IF5GZQOJdKSPhkwVFgBmYFiFJOzw5xfPD1USj/Wf8Z7lpruV7WStKD4uxbtfLamDMGZTRkSby7eAwQ==} + react-dom@19.0.0-rc-2d16326d-20240930: + resolution: {integrity: sha512-eBmzUwg2n0SkG+LFoQbRM/b6GyKSDFDnUEPWS+Oepbv6O6XCLSEzoJzPu7bFgNzL0tOA8gjjtP4ZJChcasldqA==} peerDependencies: - react: 19.0.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 react-dom@19.0.0-rc-f90a6bcc-20240827: resolution: {integrity: sha512-oUa/reDvGtjRcxi8u+GYHaDHanudaO28+G+Wvxm50CItW1xwIFN2Nn7foJxxDS9lFLGdRWZvjxldZEPAUSuXbg==} peerDependencies: - react: 19.0.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 - react-is@19.0.0-rc-3edc000d-20240926: - resolution: {integrity: sha512-TE1RnDFWt0476VWgGbU0ce8lLp2WDKDLZNlH62waFv+BhioGW0clkz+E8UFoJ7IVem00xNw+uKEMS2FjfTHG8A==} + react-is@19.0.0-rc-2d16326d-20240930: + resolution: {integrity: sha512-UH59Lq0Pd2CCEyvyJXZYfaV4SI29UIXttGY7kLzGxPIqEjH9vzyJdV7ikJsv2jktjmEiq9itakFL9YtgieWGGQ==} react-is@19.0.0-rc-f90a6bcc-20240827: resolution: {integrity: sha512-1tXoLFzVbqHAQeY3CwpyF5IYbkwgSoNHhrhS8qOrfiZIh2461h/C1BP/JVIxwyL51wHhUgLsAc/M8g0OcEhV1A==} @@ -12600,8 +12600,8 @@ packages: react-number-format@5.4.0: resolution: {integrity: sha512-NWdICrqLhI7rAS8yUeLVd6Wr4cN7UjJ9IBTS0f/a9i7UB4x4Ti70kGnksBtZ7o4Z7YRbvCMMR/jQmkoOBa/4fg==} peerDependencies: - react: 19.0.0-rc-3edc000d-20240926 - react-dom: 19.0.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 + react-dom: 19.0.0-rc-2d16326d-20240930 react-refresh@0.12.0: resolution: {integrity: sha512-suLIhrU2IHKL5JEKR/fAwJv7bbeq4kJ+pJopf77jHwuR+HmJS/HbrPIGsTBUVfw7tXPOmYv7UJ7PCaN49e8x4A==} @@ -12612,7 +12612,7 @@ packages: engines: {node: '>=10'} peerDependencies: '@types/react': npm:types-react@19.0.0-rc.0 - react: 19.0.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 peerDependenciesMeta: '@types/react': optional: true @@ -12622,58 +12622,58 @@ packages: engines: {node: '>=10'} peerDependencies: '@types/react': npm:types-react@19.0.0-rc.0 - react: 19.0.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 peerDependenciesMeta: '@types/react': optional: true - react-server-dom-turbopack@0.0.0-experimental-3edc000d-20240926: - resolution: {integrity: sha512-ljyevm9BnlppDt9hafJwARxRN/B68Ovxzxf5O4zPkc4nj+2J+PjgvazEFqcx1ZlgtSNnIsEGBOQo0k+ZOmo/9A==} + react-server-dom-turbopack@0.0.0-experimental-2d16326d-20240930: + resolution: {integrity: sha512-bBU20o2XdhV8jg/Jj7hP4zRy/rNz4P77f7TwrQ1RjNIT9+ymy+BmMm+V9hhqDqAm/yUM7XhuXNpPCO4RaZIb0Q==} engines: {node: '>=0.10.0'} peerDependencies: - react: 19.0.0-rc-3edc000d-20240926 - react-dom: 19.0.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 + react-dom: 19.0.0-rc-2d16326d-20240930 - react-server-dom-turbopack@19.0.0-rc-3edc000d-20240926: - resolution: {integrity: sha512-euKnl9w60UAMDa0w58PJVClmoBguiQHD5Hnrd7VD/6GuncbMtdSJ0r9a5AIgXtOmC63KK1U92yklXEJGNxXBxA==} + react-server-dom-turbopack@19.0.0-rc-2d16326d-20240930: + resolution: {integrity: sha512-D6TSjx+H/x4bPIH9fd2Jy+bxGVK9q2Qu9RZqMCe0opb64YN6KYu+9G3p2q00Nx1vTheQSowfiKPVEWLdwZatQQ==} engines: {node: '>=0.10.0'} peerDependencies: - react: 19.0.0-rc-3edc000d-20240926 - react-dom: 19.0.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 + react-dom: 19.0.0-rc-2d16326d-20240930 - react-server-dom-webpack@0.0.0-experimental-3edc000d-20240926: - resolution: {integrity: sha512-IBc4w3RSF0zaV3u4AN3BS1f1VMqe80vTMVQ1IHg9FMPze6qZeqIiCYncFmThdx+IW+om+4LVTMA7nmsmpFsR1Q==} + react-server-dom-webpack@0.0.0-experimental-2d16326d-20240930: + resolution: {integrity: sha512-5Vca3LqZSFtEP6ssJhtLDU2YxWUiuZicD9eF5xWKJfW7kEbN53wh84rIhJmFJoZU+axCLPhhBiH8t1SjGN7fsQ==} engines: {node: '>=0.10.0'} peerDependencies: - react: 19.0.0-rc-3edc000d-20240926 - react-dom: 19.0.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 + react-dom: 19.0.0-rc-2d16326d-20240930 webpack: 5.90.0 - react-server-dom-webpack@19.0.0-rc-3edc000d-20240926: - resolution: {integrity: sha512-V9sz7nqxYDTQh/aqLv8Q+TIj1fawh1lYZrnBPAuAjhSp/ieQfR6vZ9cyzpoBPPMyJB09wY3xCz5VEum9TgTUvQ==} + react-server-dom-webpack@19.0.0-rc-2d16326d-20240930: + resolution: {integrity: sha512-fdXXLJwk+uurnUeVqttDeEa0x8/3PjbztKmMwlj0Lp67/GASZ06QPOSkzfSuZElB09BUrHmjGmVy2clz1JtIWQ==} engines: {node: '>=0.10.0'} peerDependencies: - react: 19.0.0-rc-3edc000d-20240926 - react-dom: 19.0.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 + react-dom: 19.0.0-rc-2d16326d-20240930 webpack: 5.90.0 react-shallow-renderer@16.15.0: resolution: {integrity: sha512-oScf2FqQ9LFVQgA73vr86xl2NaOIX73rh+YFqcOp68CWj56tSfgtGKrEbyhCj0rSijyG9M1CYprTh39fBi5hzA==} peerDependencies: - react: 19.0.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 react-ssr-prepass@1.0.8: resolution: {integrity: sha512-O0gfRA1SaK+9ITKxqfnXsej2jF+OHGP/+GxD4unROQaM/0/UczGF9fuF+wTboxaQoKdIf4FvS3h/OigWh704VA==} peerDependencies: - react: 19.0.0-rc-3edc000d-20240926 - react-is: 19.0.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 + react-is: 19.0.0-rc-2d16326d-20240930 react-style-singleton@2.2.1: resolution: {integrity: sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==} engines: {node: '>=10'} peerDependencies: '@types/react': npm:types-react@19.0.0-rc.0 - react: 19.0.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 peerDependenciesMeta: '@types/react': optional: true @@ -12681,30 +12681,30 @@ packages: react-test-renderer@18.2.0: resolution: {integrity: sha512-JWD+aQ0lh2gvh4NM3bBM42Kx+XybOxCpgYK7F8ugAlpaTSnWsX+39Z4XkOykGZAHrjwwTZT3x3KxswVWxHPUqA==} peerDependencies: - react: 19.0.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 react-textarea-autosize@8.5.3: resolution: {integrity: sha512-XT1024o2pqCuZSuBt9FwHlaDeNtVrtCXu0Rnz88t1jUGheCLa3PhjE1GH8Ctm2axEtvdCl5SUHYschyQ0L5QHQ==} engines: {node: '>=10'} peerDependencies: - react: 19.0.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 react-virtualized@9.22.3: resolution: {integrity: sha512-MKovKMxWTcwPSxE1kK1HcheQTWfuCxAuBoSTf2gwyMM21NdX/PXUhnoP8Uc5dRKd+nKm8v41R36OellhdCpkrw==} peerDependencies: - react: 19.0.0-rc-3edc000d-20240926 - react-dom: 19.0.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 + react-dom: 19.0.0-rc-2d16326d-20240930 - react@0.0.0-experimental-3edc000d-20240926: - resolution: {integrity: sha512-yQZ+ss5qnFvqbxw0idfNw/bcZwW4ZnDFLel02mQ8992g/FuQr32kWL+u3ExDJD61slrcSWFa43ybcqcz5d626A==} + react@0.0.0-experimental-2d16326d-20240930: + resolution: {integrity: sha512-5YyNWeER8j/MORtS2ujfEjx0J/fgp3HdwtsCpmeJC5MdpqTqpA59TLxaeQZgumaB5BMQmatgw6oVThzQkYB/Ag==} engines: {node: '>=0.10.0'} react@17.0.2: resolution: {integrity: sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==} engines: {node: '>=0.10.0'} - react@19.0.0-rc-3edc000d-20240926: - resolution: {integrity: sha512-twH/qd0P8clqn+Z5hAxDi+3nh9pJv3zV9kzhjpbwBW/FlCimK7ypfAoElMIm5QnkhBX/YtkSj1Th49ZcRhjpGA==} + react@19.0.0-rc-2d16326d-20240930: + resolution: {integrity: sha512-XeaCnXQ5lZoOtPaVZPDEcx2TUDDt6JPIEviTKhIBkQNAYKcQkAT6SPbEqxC2KqkLPnilvPi9zz+c8iikstrwRg==} engines: {node: '>=0.10.0'} react@19.0.0-rc-f90a6bcc-20240827: @@ -13225,11 +13225,11 @@ packages: resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} engines: {node: '>=v12.22.7'} - scheduler@0.0.0-experimental-3edc000d-20240926: - resolution: {integrity: sha512-360BMNajOhMyrirau0pzWVgeakvrfjbfdqHnX2K+tSGTmn6tBN+6K5NhhaebqeXXWyCU3rl5FApjgF2GN0W5JA==} + scheduler@0.0.0-experimental-2d16326d-20240930: + resolution: {integrity: sha512-ikUX4on2GTFJjfJrU49Y4gaIPQuE8um9/TR8NImUsbCCGNFkMz5c9xcP9crSa2i5RRLaZxPFijsJn1bl5zKx6g==} - scheduler@0.25.0-rc-3edc000d-20240926: - resolution: {integrity: sha512-qAWyPrLLFM96Py4gnrFQLhYDrHkVXGw3P/hPrR3E6b5rriPeAA1a8YZBWlqH8Eehbc9waTih/WyDSyuwkxWWMw==} + scheduler@0.25.0-rc-2d16326d-20240930: + resolution: {integrity: sha512-P0lFGsD0rOhDQR2AA3ls0MYXeWnw/Tuu5bERwBC92DXSASB/493N9LQKe4AuCwVC671tjktLckGAxghUqJq7yg==} schema-utils@2.7.1: resolution: {integrity: sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==} @@ -13794,8 +13794,8 @@ packages: engines: {node: '>= 16'} peerDependencies: babel-plugin-styled-components: '>= 2' - react: 19.0.0-rc-3edc000d-20240926 - react-dom: 19.0.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 + react-dom: 19.0.0-rc-2d16326d-20240930 peerDependenciesMeta: babel-plugin-styled-components: optional: true @@ -13809,7 +13809,7 @@ packages: peerDependencies: '@babel/core': '*' babel-plugin-macros: '*' - react: 19.0.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 peerDependenciesMeta: '@babel/core': optional: true @@ -13886,7 +13886,7 @@ packages: swr@2.2.4: resolution: {integrity: sha512-njiZ/4RiIhoOlAaLYDqwz5qH/KZXVilRLvomrx83HjzCWTfa+InyfAjv05PSFxnmLzZkNO9ZfvgoqzAaEI4sGQ==} peerDependencies: - react: 19.0.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 symbol-observable@1.0.1: resolution: {integrity: sha512-Kb3PrPYz4HanVF1LVGuAdW6LoVgIwjUYJGzFe7NDrBLCN4lsV/5J0MFurV+ygS4bRVwrCEt2c7MQ1R2a72oJDw==} @@ -14627,7 +14627,7 @@ packages: engines: {node: '>=10'} peerDependencies: '@types/react': npm:types-react@19.0.0-rc.0 - react: 19.0.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 peerDependenciesMeta: '@types/react': optional: true @@ -14635,13 +14635,13 @@ packages: use-composed-ref@1.3.0: resolution: {integrity: sha512-GLMG0Jc/jiKov/3Ulid1wbv3r54K9HlMW29IWcDFPEqFkSO2nS0MuefWgMJpeHQ9YJeXDL3ZUF+P3jdXlZX/cQ==} peerDependencies: - react: 19.0.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 use-isomorphic-layout-effect@1.1.2: resolution: {integrity: sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==} peerDependencies: '@types/react': '*' - react: 19.0.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 peerDependenciesMeta: '@types/react': optional: true @@ -14650,7 +14650,7 @@ packages: resolution: {integrity: sha512-xA+AVm/Wlg3e2P/JiItTziwS7FK92LWrDB0p+hgXloIMuVCeJJ8v6f0eeHyPZaJrM+usM1FkFfbNCrJGs8A/zw==} peerDependencies: '@types/react': '*' - react: 19.0.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 peerDependenciesMeta: '@types/react': optional: true @@ -14660,7 +14660,7 @@ packages: engines: {node: '>=10'} peerDependencies: '@types/react': npm:types-react@19.0.0-rc.0 - react: 19.0.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 peerDependenciesMeta: '@types/react': optional: true @@ -14668,7 +14668,7 @@ packages: use-sync-external-store@1.2.0: resolution: {integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==} peerDependencies: - react: 19.0.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} @@ -17193,17 +17193,17 @@ snapshots: '@emotion/memoize@0.8.1': {} - '@emotion/react@11.11.1(react@19.0.0-rc-3edc000d-20240926)(types-react@19.0.0-rc.0)': + '@emotion/react@11.11.1(react@19.0.0-rc-2d16326d-20240930)(types-react@19.0.0-rc.0)': dependencies: '@babel/runtime': 7.22.5 '@emotion/babel-plugin': 11.11.0 '@emotion/cache': 11.11.0 '@emotion/serialize': 1.1.2 - '@emotion/use-insertion-effect-with-fallbacks': 1.0.1(react@19.0.0-rc-3edc000d-20240926) + '@emotion/use-insertion-effect-with-fallbacks': 1.0.1(react@19.0.0-rc-2d16326d-20240930) '@emotion/utils': 1.2.1 '@emotion/weak-memoize': 0.3.1 hoist-non-react-statics: 3.3.2 - react: 19.0.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 optionalDependencies: '@types/react': types-react@19.0.0-rc.0 transitivePeerDependencies: @@ -17221,9 +17221,9 @@ snapshots: '@emotion/unitless@0.8.1': {} - '@emotion/use-insertion-effect-with-fallbacks@1.0.1(react@19.0.0-rc-3edc000d-20240926)': + '@emotion/use-insertion-effect-with-fallbacks@1.0.1(react@19.0.0-rc-2d16326d-20240930)': dependencies: - react: 19.0.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 '@emotion/utils@1.2.1': {} @@ -18583,11 +18583,11 @@ snapshots: transitivePeerDependencies: - supports-color - '@mdx-js/react@2.2.1(react@19.0.0-rc-3edc000d-20240926)': + '@mdx-js/react@2.2.1(react@19.0.0-rc-2d16326d-20240930)': dependencies: '@types/mdx': 2.0.3 '@types/react': types-react@19.0.0-rc.0 - react: 19.0.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 '@mdx-js/react@2.2.1(react@19.0.0-rc-f90a6bcc-20240827)': dependencies: @@ -19408,13 +19408,13 @@ snapshots: '@types/jest': 29.5.5 jest: 29.7.0(@types/node@20.12.3)(babel-plugin-macros@3.1.0) - '@testing-library/react@15.0.7(react-dom@19.0.0-rc-3edc000d-20240926(react@19.0.0-rc-3edc000d-20240926))(react@19.0.0-rc-3edc000d-20240926)(types-react@19.0.0-rc.0)': + '@testing-library/react@15.0.7(react-dom@19.0.0-rc-2d16326d-20240930(react@19.0.0-rc-2d16326d-20240930))(react@19.0.0-rc-2d16326d-20240930)(types-react@19.0.0-rc.0)': dependencies: '@babel/runtime': 7.22.5 '@testing-library/dom': 10.1.0 '@types/react-dom': types-react-dom@19.0.0-rc.0 - react: 19.0.0-rc-3edc000d-20240926 - react-dom: 19.0.0-rc-3edc000d-20240926(react@19.0.0-rc-3edc000d-20240926) + react: 19.0.0-rc-2d16326d-20240930 + react-dom: 19.0.0-rc-2d16326d-20240930(react@19.0.0-rc-2d16326d-20240930) optionalDependencies: '@types/react': types-react@19.0.0-rc.0 @@ -20682,7 +20682,7 @@ snapshots: - supports-color optional: true - babel-plugin-react-compiler@0.0.0-experimental-b12479e-20240926: + babel-plugin-react-compiler@0.0.0-experimental-3feb7e4-20240930: dependencies: '@babel/generator': 7.2.0 '@babel/types': 7.22.5 @@ -24359,7 +24359,7 @@ snapshots: hoist-non-react-statics@3.3.2: dependencies: - react-is: 19.0.0-rc-3edc000d-20240926 + react-is: 19.0.0-rc-2d16326d-20240930 homedir-polyfill@1.0.3: dependencies: @@ -28715,25 +28715,25 @@ snapshots: '@jest/types': 24.9.0 ansi-regex: 4.1.0 ansi-styles: 3.2.1 - react-is: 19.0.0-rc-3edc000d-20240926 + react-is: 19.0.0-rc-2d16326d-20240930 pretty-format@27.5.1: dependencies: ansi-regex: 5.0.1 ansi-styles: 5.2.0 - react-is: 19.0.0-rc-3edc000d-20240926 + react-is: 19.0.0-rc-2d16326d-20240930 pretty-format@29.5.0: dependencies: '@jest/schemas': 29.4.3 ansi-styles: 5.2.0 - react-is: 19.0.0-rc-3edc000d-20240926 + react-is: 19.0.0-rc-2d16326d-20240930 pretty-format@29.7.0: dependencies: '@jest/schemas': 29.6.3 ansi-styles: 5.2.0 - react-is: 19.0.0-rc-3edc000d-20240926 + react-is: 19.0.0-rc-2d16326d-20240930 pretty-ms@7.0.0: dependencies: @@ -28790,7 +28790,7 @@ snapshots: dependencies: loose-envify: 1.4.0 object-assign: 4.1.1 - react-is: 19.0.0-rc-3edc000d-20240926 + react-is: 19.0.0-rc-2d16326d-20240930 property-information@5.6.0: dependencies: @@ -28964,29 +28964,29 @@ snapshots: minimist: 1.2.8 strip-json-comments: 2.0.1 - react-dom@0.0.0-experimental-3edc000d-20240926(react@19.0.0-rc-3edc000d-20240926): + react-dom@0.0.0-experimental-2d16326d-20240930(react@19.0.0-rc-2d16326d-20240930): dependencies: - react: 19.0.0-rc-3edc000d-20240926 - scheduler: 0.25.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 + scheduler: 0.25.0-rc-2d16326d-20240930 - react-dom@17.0.2(react@19.0.0-rc-3edc000d-20240926): + react-dom@17.0.2(react@19.0.0-rc-2d16326d-20240930): dependencies: loose-envify: 1.4.0 object-assign: 4.1.1 - react: 19.0.0-rc-3edc000d-20240926 - scheduler: 0.25.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 + scheduler: 0.25.0-rc-2d16326d-20240930 - react-dom@19.0.0-rc-3edc000d-20240926(react@19.0.0-rc-3edc000d-20240926): + react-dom@19.0.0-rc-2d16326d-20240930(react@19.0.0-rc-2d16326d-20240930): dependencies: - react: 19.0.0-rc-3edc000d-20240926 - scheduler: 0.25.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 + scheduler: 0.25.0-rc-2d16326d-20240930 react-dom@19.0.0-rc-f90a6bcc-20240827(react@19.0.0-rc-f90a6bcc-20240827): dependencies: react: 19.0.0-rc-f90a6bcc-20240827 - scheduler: 0.25.0-rc-3edc000d-20240926 + scheduler: 0.25.0-rc-2d16326d-20240930 - react-is@19.0.0-rc-3edc000d-20240926: {} + react-is@19.0.0-rc-2d16326d-20240930: {} react-is@19.0.0-rc-f90a6bcc-20240827: {} @@ -29019,48 +29019,48 @@ snapshots: optionalDependencies: '@types/react': types-react@19.0.0-rc.0 - react-server-dom-turbopack@0.0.0-experimental-3edc000d-20240926(react-dom@19.0.0-rc-3edc000d-20240926(react@19.0.0-rc-3edc000d-20240926))(react@19.0.0-rc-3edc000d-20240926): + react-server-dom-turbopack@0.0.0-experimental-2d16326d-20240930(react-dom@19.0.0-rc-2d16326d-20240930(react@19.0.0-rc-2d16326d-20240930))(react@19.0.0-rc-2d16326d-20240930): dependencies: acorn-loose: 8.3.0 neo-async: 2.6.1 - react: 19.0.0-rc-3edc000d-20240926 - react-dom: 19.0.0-rc-3edc000d-20240926(react@19.0.0-rc-3edc000d-20240926) + react: 19.0.0-rc-2d16326d-20240930 + react-dom: 19.0.0-rc-2d16326d-20240930(react@19.0.0-rc-2d16326d-20240930) - react-server-dom-turbopack@19.0.0-rc-3edc000d-20240926(react-dom@19.0.0-rc-3edc000d-20240926(react@19.0.0-rc-3edc000d-20240926))(react@19.0.0-rc-3edc000d-20240926): + react-server-dom-turbopack@19.0.0-rc-2d16326d-20240930(react-dom@19.0.0-rc-2d16326d-20240930(react@19.0.0-rc-2d16326d-20240930))(react@19.0.0-rc-2d16326d-20240930): dependencies: acorn-loose: 8.3.0 neo-async: 2.6.1 - react: 19.0.0-rc-3edc000d-20240926 - react-dom: 19.0.0-rc-3edc000d-20240926(react@19.0.0-rc-3edc000d-20240926) + react: 19.0.0-rc-2d16326d-20240930 + react-dom: 19.0.0-rc-2d16326d-20240930(react@19.0.0-rc-2d16326d-20240930) - react-server-dom-webpack@0.0.0-experimental-3edc000d-20240926(react-dom@19.0.0-rc-3edc000d-20240926(react@19.0.0-rc-3edc000d-20240926))(react@19.0.0-rc-3edc000d-20240926)(webpack@5.90.0(@swc/core@1.6.13(@swc/helpers@0.5.13))): + react-server-dom-webpack@0.0.0-experimental-2d16326d-20240930(react-dom@19.0.0-rc-2d16326d-20240930(react@19.0.0-rc-2d16326d-20240930))(react@19.0.0-rc-2d16326d-20240930)(webpack@5.90.0(@swc/core@1.6.13(@swc/helpers@0.5.13))): dependencies: acorn-loose: 8.3.0 neo-async: 2.6.1 - react: 19.0.0-rc-3edc000d-20240926 - react-dom: 19.0.0-rc-3edc000d-20240926(react@19.0.0-rc-3edc000d-20240926) + react: 19.0.0-rc-2d16326d-20240930 + react-dom: 19.0.0-rc-2d16326d-20240930(react@19.0.0-rc-2d16326d-20240930) webpack: 5.90.0(@swc/core@1.6.13(@swc/helpers@0.5.13)) webpack-sources: 3.2.3(patch_hash=jbynf5dc46ambamq3wuyho6hkq) - react-server-dom-webpack@19.0.0-rc-3edc000d-20240926(react-dom@19.0.0-rc-3edc000d-20240926(react@19.0.0-rc-3edc000d-20240926))(react@19.0.0-rc-3edc000d-20240926)(webpack@5.90.0(@swc/core@1.6.13(@swc/helpers@0.5.13))): + react-server-dom-webpack@19.0.0-rc-2d16326d-20240930(react-dom@19.0.0-rc-2d16326d-20240930(react@19.0.0-rc-2d16326d-20240930))(react@19.0.0-rc-2d16326d-20240930)(webpack@5.90.0(@swc/core@1.6.13(@swc/helpers@0.5.13))): dependencies: acorn-loose: 8.3.0 neo-async: 2.6.1 - react: 19.0.0-rc-3edc000d-20240926 - react-dom: 19.0.0-rc-3edc000d-20240926(react@19.0.0-rc-3edc000d-20240926) + react: 19.0.0-rc-2d16326d-20240930 + react-dom: 19.0.0-rc-2d16326d-20240930(react@19.0.0-rc-2d16326d-20240930) webpack: 5.90.0(@swc/core@1.6.13(@swc/helpers@0.5.13)) webpack-sources: 3.2.3(patch_hash=jbynf5dc46ambamq3wuyho6hkq) - react-shallow-renderer@16.15.0(react@19.0.0-rc-3edc000d-20240926): + react-shallow-renderer@16.15.0(react@19.0.0-rc-2d16326d-20240930): dependencies: object-assign: 4.1.1 - react: 19.0.0-rc-3edc000d-20240926 - react-is: 19.0.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 + react-is: 19.0.0-rc-2d16326d-20240930 - react-ssr-prepass@1.0.8(react-is@19.0.0-rc-f90a6bcc-20240827)(react@19.0.0-rc-3edc000d-20240926): + react-ssr-prepass@1.0.8(react-is@19.0.0-rc-f90a6bcc-20240827)(react@19.0.0-rc-2d16326d-20240930): dependencies: object-is: 1.0.2 - react: 19.0.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 react-is: 19.0.0-rc-f90a6bcc-20240827 react-style-singleton@2.2.1(react@19.0.0-rc-f90a6bcc-20240827)(types-react@19.0.0-rc.0): @@ -29072,12 +29072,12 @@ snapshots: optionalDependencies: '@types/react': types-react@19.0.0-rc.0 - react-test-renderer@18.2.0(react@19.0.0-rc-3edc000d-20240926): + react-test-renderer@18.2.0(react@19.0.0-rc-2d16326d-20240930): dependencies: - react: 19.0.0-rc-3edc000d-20240926 - react-is: 19.0.0-rc-3edc000d-20240926 - react-shallow-renderer: 16.15.0(react@19.0.0-rc-3edc000d-20240926) - scheduler: 0.25.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 + react-is: 19.0.0-rc-2d16326d-20240930 + react-shallow-renderer: 16.15.0(react@19.0.0-rc-2d16326d-20240930) + scheduler: 0.25.0-rc-2d16326d-20240930 react-textarea-autosize@8.5.3(react@19.0.0-rc-f90a6bcc-20240827)(types-react@19.0.0-rc.0): dependencies: @@ -29088,25 +29088,25 @@ snapshots: transitivePeerDependencies: - '@types/react' - react-virtualized@9.22.3(react-dom@19.0.0-rc-3edc000d-20240926(react@19.0.0-rc-3edc000d-20240926))(react@19.0.0-rc-3edc000d-20240926): + react-virtualized@9.22.3(react-dom@19.0.0-rc-2d16326d-20240930(react@19.0.0-rc-2d16326d-20240930))(react@19.0.0-rc-2d16326d-20240930): dependencies: '@babel/runtime': 7.22.5 clsx: 1.1.1 dom-helpers: 5.2.1 loose-envify: 1.4.0 prop-types: 15.8.1 - react: 19.0.0-rc-3edc000d-20240926 - react-dom: 19.0.0-rc-3edc000d-20240926(react@19.0.0-rc-3edc000d-20240926) + react: 19.0.0-rc-2d16326d-20240930 + react-dom: 19.0.0-rc-2d16326d-20240930(react@19.0.0-rc-2d16326d-20240930) react-lifecycles-compat: 3.0.4 - react@0.0.0-experimental-3edc000d-20240926: {} + react@0.0.0-experimental-2d16326d-20240930: {} react@17.0.2: dependencies: loose-envify: 1.4.0 object-assign: 4.1.1 - react@19.0.0-rc-3edc000d-20240926: {} + react@19.0.0-rc-2d16326d-20240930: {} react@19.0.0-rc-f90a6bcc-20240827: {} @@ -29802,9 +29802,9 @@ snapshots: dependencies: xmlchars: 2.2.0 - scheduler@0.0.0-experimental-3edc000d-20240926: {} + scheduler@0.0.0-experimental-2d16326d-20240930: {} - scheduler@0.25.0-rc-3edc000d-20240926: {} + scheduler@0.25.0-rc-2d16326d-20240930: {} schema-utils@2.7.1: dependencies: @@ -30441,7 +30441,7 @@ snapshots: dependencies: inline-style-parser: 0.1.1 - styled-components@6.0.0-rc.3(react-dom@19.0.0-rc-3edc000d-20240926(react@19.0.0-rc-3edc000d-20240926))(react@19.0.0-rc-3edc000d-20240926): + styled-components@6.0.0-rc.3(react-dom@19.0.0-rc-2d16326d-20240930(react@19.0.0-rc-2d16326d-20240930))(react@19.0.0-rc-2d16326d-20240930): dependencies: '@babel/cli': 7.21.5(@babel/core@7.22.5) '@babel/core': 7.22.5 @@ -30456,8 +30456,8 @@ snapshots: '@emotion/unitless': 0.8.1 css-to-react-native: 3.2.0 postcss: 8.4.31 - react: 19.0.0-rc-3edc000d-20240926 - react-dom: 19.0.0-rc-3edc000d-20240926(react@19.0.0-rc-3edc000d-20240926) + react: 19.0.0-rc-2d16326d-20240930 + react-dom: 19.0.0-rc-2d16326d-20240930(react@19.0.0-rc-2d16326d-20240930) shallowequal: 1.1.0 stylis: 4.2.0 tslib: 2.5.3 @@ -30469,10 +30469,10 @@ snapshots: postcss: 7.0.32 postcss-load-plugins: 2.3.0 - styled-jsx@5.1.6(@babel/core@7.22.5)(babel-plugin-macros@3.1.0)(react@19.0.0-rc-3edc000d-20240926): + styled-jsx@5.1.6(@babel/core@7.22.5)(babel-plugin-macros@3.1.0)(react@19.0.0-rc-2d16326d-20240930): dependencies: client-only: 0.0.1 - react: 19.0.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 optionalDependencies: '@babel/core': 7.22.5 babel-plugin-macros: 3.1.0 @@ -30562,11 +30562,11 @@ snapshots: picocolors: 1.0.1 stable: 0.1.8 - swr@2.2.4(react@19.0.0-rc-3edc000d-20240926): + swr@2.2.4(react@19.0.0-rc-2d16326d-20240930): dependencies: client-only: 0.0.1 - react: 19.0.0-rc-3edc000d-20240926 - use-sync-external-store: 1.2.0(react@19.0.0-rc-3edc000d-20240926) + react: 19.0.0-rc-2d16326d-20240930 + use-sync-external-store: 1.2.0(react@19.0.0-rc-2d16326d-20240930) symbol-observable@1.0.1: {} @@ -31268,9 +31268,9 @@ snapshots: unist-util-is: 5.2.0 unist-util-visit-parents: 5.1.3 - unistore@3.4.1(react@19.0.0-rc-3edc000d-20240926): + unistore@3.4.1(react@19.0.0-rc-2d16326d-20240930): optionalDependencies: - react: 19.0.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 universal-github-app-jwt@1.1.1: dependencies: @@ -31388,9 +31388,9 @@ snapshots: optionalDependencies: '@types/react': types-react@19.0.0-rc.0 - use-sync-external-store@1.2.0(react@19.0.0-rc-3edc000d-20240926): + use-sync-external-store@1.2.0(react@19.0.0-rc-2d16326d-20240930): dependencies: - react: 19.0.0-rc-3edc000d-20240926 + react: 19.0.0-rc-2d16326d-20240930 util-deprecate@1.0.2: {} diff --git a/run-tests.js b/run-tests.js index 0ee3558ae1490..3208165475fb0 100644 --- a/run-tests.js +++ b/run-tests.js @@ -20,7 +20,7 @@ const { getTestFilter } = require('./test/get-test-filter') // Do not rename or format. sync-react script relies on this line. // prettier-ignore -const nextjsReactPeerVersion = "19.0.0-rc-3edc000d-20240926"; +const nextjsReactPeerVersion = "19.0.0-rc-2d16326d-20240930"; let argv = require('yargs/yargs')(process.argv.slice(2)) .string('type') diff --git a/test/.stats-app/app/app-edge-ssr/page.js b/test/.stats-app/app/app-edge-ssr/page.js index 1e074ce268e19..86d6b6fd8e99e 100644 --- a/test/.stats-app/app/app-edge-ssr/page.js +++ b/test/.stats-app/app/app-edge-ssr/page.js @@ -2,4 +2,4 @@ export default function page() { return 'app-edge-ssr' } -export const runtime = 'experimental-edge' +export const runtime = 'edge' diff --git a/test/.stats-app/package.json b/test/.stats-app/package.json index edae10ee8228d..3d2ec1401d3e0 100644 --- a/test/.stats-app/package.json +++ b/test/.stats-app/package.json @@ -4,8 +4,8 @@ "license": "MIT", "dependencies": { "next": "latest", - "react": "19.0.0-rc-3edc000d-20240926", - "react-dom": "19.0.0-rc-3edc000d-20240926" + "react": "19.0.0-rc-2d16326d-20240930", + "react-dom": "19.0.0-rc-2d16326d-20240930" }, "engines": { "node": ">=18.18.0" diff --git a/test/e2e/app-dir/actions/app-action.test.ts b/test/e2e/app-dir/actions/app-action.test.ts index 58d1c2dcf363b..016dc365bc597 100644 --- a/test/e2e/app-dir/actions/app-action.test.ts +++ b/test/e2e/app-dir/actions/app-action.test.ts @@ -336,7 +336,7 @@ describe('app-dir action handling', () => { // Fake a file to upload await browser.eval(` - const file = new File(['hello'], 'hello.txt', { type: 'text/plain' }); + const file = new File(['hello'], 'hello你好テスト.txt', { type: 'text/plain' }); const list = new DataTransfer(); list.items.add(file); document.getElementById('file').files = list.files; @@ -347,7 +347,9 @@ describe('app-dir action handling', () => { // we don't have access to runtime logs on deploy if (!isNextDeploy) { await check(() => { - return logs.some((log) => log.includes('File name: hello.txt size: 5')) + return logs.some((log) => + log.includes('File name: hello你好テスト.txt size: 5') + ) ? 'yes' : '' }, 'yes') diff --git a/test/e2e/app-dir/app-css/app/dashboard/page.js b/test/e2e/app-dir/app-css/app/dashboard/page.js index 5a3e15c25c935..588a0bf594643 100644 --- a/test/e2e/app-dir/app-css/app/dashboard/page.js +++ b/test/e2e/app-dir/app-css/app/dashboard/page.js @@ -13,4 +13,4 @@ export default function DashboardPage(props) { ) } -export const runtime = 'experimental-edge' +export const runtime = 'edge' diff --git a/test/e2e/app-dir/app-edge-root-layout/app/layout.js b/test/e2e/app-dir/app-edge-root-layout/app/layout.js index 76ddc3fd4fa08..6f828ac76e275 100644 --- a/test/e2e/app-dir/app-edge-root-layout/app/layout.js +++ b/test/e2e/app-dir/app-edge-root-layout/app/layout.js @@ -6,4 +6,4 @@ export default function layout({ children }) { ) } -export const runtime = 'experimental-edge' +export const runtime = 'edge' diff --git a/test/e2e/app-dir/app-routes/app/edge/advanced/body/json/route.ts b/test/e2e/app-dir/app-routes/app/edge/advanced/body/json/route.ts index e55869eeba3d9..a563f930bd365 100644 --- a/test/e2e/app-dir/app-routes/app/edge/advanced/body/json/route.ts +++ b/test/e2e/app-dir/app-routes/app/edge/advanced/body/json/route.ts @@ -1,7 +1,7 @@ import type { NextRequest } from 'next/server' import { withRequestMeta } from '../../../../../helpers' -export const runtime = 'experimental-edge' +export const runtime = 'edge' export async function POST(request: NextRequest) { const body = await request.json() diff --git a/test/e2e/app-dir/app-routes/app/edge/advanced/body/streaming/route.ts b/test/e2e/app-dir/app-routes/app/edge/advanced/body/streaming/route.ts index af98c4c380166..72e338aeeaa94 100644 --- a/test/e2e/app-dir/app-routes/app/edge/advanced/body/streaming/route.ts +++ b/test/e2e/app-dir/app-routes/app/edge/advanced/body/streaming/route.ts @@ -1,6 +1,6 @@ import type { NextRequest } from 'next/server' -export const runtime = 'experimental-edge' +export const runtime = 'edge' export async function POST(request: NextRequest) { const reader = request.body?.getReader() diff --git a/test/e2e/app-dir/app-routes/app/edge/advanced/body/text/route.ts b/test/e2e/app-dir/app-routes/app/edge/advanced/body/text/route.ts index aa39c6f22529a..7552b0ab2439c 100644 --- a/test/e2e/app-dir/app-routes/app/edge/advanced/body/text/route.ts +++ b/test/e2e/app-dir/app-routes/app/edge/advanced/body/text/route.ts @@ -1,7 +1,7 @@ import type { NextRequest } from 'next/server' import { withRequestMeta } from '../../../../../helpers' -export const runtime = 'experimental-edge' +export const runtime = 'edge' export async function POST(request: NextRequest) { const body = await request.text() diff --git a/test/e2e/app-dir/app-routes/app/edge/advanced/query/route.ts b/test/e2e/app-dir/app-routes/app/edge/advanced/query/route.ts index 15ed371f6848e..95c25743f35d8 100644 --- a/test/e2e/app-dir/app-routes/app/edge/advanced/query/route.ts +++ b/test/e2e/app-dir/app-routes/app/edge/advanced/query/route.ts @@ -1,7 +1,7 @@ import { withRequestMeta } from '../../../../helpers' import { NextRequest } from 'next/server' -export const runtime = 'experimental-edge' +export const runtime = 'edge' export async function GET(request: NextRequest): Promise<Response> { const { searchParams } = request.nextUrl diff --git a/test/e2e/app-dir/app-routes/app/edge/headers/route.ts b/test/e2e/app-dir/app-routes/app/edge/headers/route.ts index 7a6833be3d22a..6647fb4c12915 100644 --- a/test/e2e/app-dir/app-routes/app/edge/headers/route.ts +++ b/test/e2e/app-dir/app-routes/app/edge/headers/route.ts @@ -2,7 +2,7 @@ import { headers } from 'next/headers' import { NextResponse } from 'next/server' import { getRequestMeta } from '../../../helpers' -export const runtime = 'experimental-edge' +export const runtime = 'edge' export async function GET() { const meta = getRequestMeta(await headers()) diff --git a/test/e2e/app-dir/app-static/app/dynamic-param-edge/[slug]/page.tsx b/test/e2e/app-dir/app-static/app/dynamic-param-edge/[slug]/page.tsx index 4da62f81383f1..8dbc46a05254e 100644 --- a/test/e2e/app-dir/app-static/app/dynamic-param-edge/[slug]/page.tsx +++ b/test/e2e/app-dir/app-static/app/dynamic-param-edge/[slug]/page.tsx @@ -2,14 +2,4 @@ export default async function Hello({ params }) { return <h1 id="slug">{(await params).slug}</h1> } -export function generateStaticParams() { - return [ - { - params: { - slug: 'hello', - }, - }, - ] -} - export const runtime = 'edge' diff --git a/test/e2e/app-dir/app-static/app/variable-revalidate-edge/body/page.js b/test/e2e/app-dir/app-static/app/variable-revalidate-edge/body/page.js index faaa6e61e5478..7dbf025136058 100644 --- a/test/e2e/app-dir/app-static/app/variable-revalidate-edge/body/page.js +++ b/test/e2e/app-dir/app-static/app/variable-revalidate-edge/body/page.js @@ -1,4 +1,4 @@ -export const runtime = 'experimental-edge' +export const runtime = 'edge' export default async function Page() { const data = await fetch( diff --git a/test/e2e/app-dir/app-static/app/variable-revalidate-edge/encoding/page.js b/test/e2e/app-dir/app-static/app/variable-revalidate-edge/encoding/page.js index 06e180abd09f4..e0e4e00e0e22a 100644 --- a/test/e2e/app-dir/app-static/app/variable-revalidate-edge/encoding/page.js +++ b/test/e2e/app-dir/app-static/app/variable-revalidate-edge/encoding/page.js @@ -1,4 +1,4 @@ -export const runtime = 'experimental-edge' +export const runtime = 'edge' export default async function Page() { const data = await fetch( diff --git a/test/e2e/app-dir/app-static/app/variable-revalidate-edge/no-store/page.js b/test/e2e/app-dir/app-static/app/variable-revalidate-edge/no-store/page.js index bf54997d27663..22ec8c03235e3 100644 --- a/test/e2e/app-dir/app-static/app/variable-revalidate-edge/no-store/page.js +++ b/test/e2e/app-dir/app-static/app/variable-revalidate-edge/no-store/page.js @@ -1,6 +1,6 @@ import { cache, use } from 'react' -export const runtime = 'experimental-edge' +export const runtime = 'edge' export default function Page() { const getData = cache(() => diff --git a/test/e2e/app-dir/app-static/app/variable-revalidate-edge/post-method-request/page.js b/test/e2e/app-dir/app-static/app/variable-revalidate-edge/post-method-request/page.js index 3361a86b1b3d1..e441a7e474f73 100644 --- a/test/e2e/app-dir/app-static/app/variable-revalidate-edge/post-method-request/page.js +++ b/test/e2e/app-dir/app-static/app/variable-revalidate-edge/post-method-request/page.js @@ -1,4 +1,4 @@ -export const runtime = 'experimental-edge' +export const runtime = 'edge' export default async function Page() { const data = await fetch( diff --git a/test/e2e/app-dir/app-static/app/variable-revalidate-edge/post-method/page.js b/test/e2e/app-dir/app-static/app/variable-revalidate-edge/post-method/page.js index 0ca937144c965..219fe314cabc9 100644 --- a/test/e2e/app-dir/app-static/app/variable-revalidate-edge/post-method/page.js +++ b/test/e2e/app-dir/app-static/app/variable-revalidate-edge/post-method/page.js @@ -1,6 +1,6 @@ import { fetchRetry } from '../../../lib/fetch-retry' -export const runtime = 'experimental-edge' +export const runtime = 'edge' export default async function Page() { const data = await fetchRetry( diff --git a/test/e2e/app-dir/app-static/app/variable-revalidate-edge/revalidate-3/page.js b/test/e2e/app-dir/app-static/app/variable-revalidate-edge/revalidate-3/page.js index e78de6628c86e..1f015f816e89e 100644 --- a/test/e2e/app-dir/app-static/app/variable-revalidate-edge/revalidate-3/page.js +++ b/test/e2e/app-dir/app-static/app/variable-revalidate-edge/revalidate-3/page.js @@ -1,6 +1,6 @@ import { cache, use } from 'react' -export const runtime = 'experimental-edge' +export const runtime = 'edge' export const dynamic = 'force-static' export default function Page() { diff --git a/test/e2e/app-dir/app/app/(rootonly)/dashboard/hello/page.js b/test/e2e/app-dir/app/app/(rootonly)/dashboard/hello/page.js index 8ffa7eec6cb8c..475a4b3c25d6e 100644 --- a/test/e2e/app-dir/app/app/(rootonly)/dashboard/hello/page.js +++ b/test/e2e/app-dir/app/app/(rootonly)/dashboard/hello/page.js @@ -6,5 +6,5 @@ export default function HelloPage(props) { ) } -export const runtime = 'experimental-edge' +export const runtime = 'edge' export const preferredRegion = ['iad1', 'sfo1'] diff --git a/test/e2e/app-dir/app/app/slow-page-no-loading/page.js b/test/e2e/app-dir/app/app/slow-page-no-loading/page.js index 965ac1f019edc..4ceba1aeb381e 100644 --- a/test/e2e/app-dir/app/app/slow-page-no-loading/page.js +++ b/test/e2e/app-dir/app/app/slow-page-no-loading/page.js @@ -13,5 +13,5 @@ export default function SlowPage(props) { return <h1 id="slow-page-message">{data.message}</h1> } -export const runtime = 'experimental-edge' +export const runtime = 'edge' export const preferredRegion = 'global' diff --git a/test/e2e/app-dir/app/app/slow-page-with-loading/page.js b/test/e2e/app-dir/app/app/slow-page-with-loading/page.js index 71854491d1280..69d1928970433 100644 --- a/test/e2e/app-dir/app/app/slow-page-with-loading/page.js +++ b/test/e2e/app-dir/app/app/slow-page-with-loading/page.js @@ -13,4 +13,4 @@ export default function SlowPage(props) { return <h1 id="slow-page-message">{data.message}</h1> } -export const runtime = 'experimental-edge' +export const runtime = 'edge' diff --git a/test/e2e/app-dir/app/app/test-page/page.js b/test/e2e/app-dir/app/app/test-page/page.js index ff78b5e67c14c..a707e77382849 100644 --- a/test/e2e/app-dir/app/app/test-page/page.js +++ b/test/e2e/app-dir/app/app/test-page/page.js @@ -2,5 +2,5 @@ export default function Page() { return <p id="page">Page</p> } -export const runtime = 'experimental-edge' +export const runtime = 'edge' export const preferredRegion = 'home' diff --git a/test/e2e/app-dir/dynamic-data/dynamic-data.test.ts b/test/e2e/app-dir/dynamic-data/dynamic-data.test.ts index 9b627b2480234..8ba6ec4a9a7f2 100644 --- a/test/e2e/app-dir/dynamic-data/dynamic-data.test.ts +++ b/test/e2e/app-dir/dynamic-data/dynamic-data.test.ts @@ -199,6 +199,16 @@ describe('dynamic-data with dynamic = "error"', () => { await browser.close() } + browser = await next.browser('/connection') + try { + await assertHasRedbox(browser) + expect(await getRedboxHeader(browser)).toMatch( + 'Error: Route /connection with `dynamic = "error"` couldn\'t be rendered statically because it used `connection`' + ) + } finally { + await browser.close() + } + browser = await next.browser('/headers?foo=foosearch') try { await assertHasRedbox(browser) @@ -230,6 +240,9 @@ describe('dynamic-data with dynamic = "error"', () => { expect(next.cliOutput).toMatch( 'Error: Route /cookies with `dynamic = "error"` couldn\'t be rendered statically because it used `cookies`' ) + expect(next.cliOutput).toMatch( + 'Error: Route /connection with `dynamic = "error"` couldn\'t be rendered statically because it used `connection`' + ) expect(next.cliOutput).toMatch( 'Error: Route /headers with `dynamic = "error"` couldn\'t be rendered statically because it used `headers`' ) @@ -277,6 +290,16 @@ describe('dynamic-data inside cache scope', () => { await browser.close() } + browser = await next.browser('/connection') + try { + await assertHasRedbox(browser) + expect(await getRedboxHeader(browser)).toMatch( + 'Error: Route /connection used "connection" inside a function cached with "unstable_cache(...)".' + ) + } finally { + await browser.close() + } + browser = await next.browser('/headers') try { await assertHasRedbox(browser) @@ -297,6 +320,9 @@ describe('dynamic-data inside cache scope', () => { expect(next.cliOutput).toMatch( 'Error: Route /cookies used "cookies" inside a function cached with "unstable_cache(...)".' ) + expect(next.cliOutput).toMatch( + 'Error: Route /connection used "connection" inside a function cached with "unstable_cache(...)".' + ) expect(next.cliOutput).toMatch( 'Error: Route /headers used "headers" inside a function cached with "unstable_cache(...)".' ) diff --git a/test/e2e/app-dir/dynamic-data/fixtures/cache-scoped/app/connection/page.js b/test/e2e/app-dir/dynamic-data/fixtures/cache-scoped/app/connection/page.js new file mode 100644 index 0000000000000..d15afc39b167a --- /dev/null +++ b/test/e2e/app-dir/dynamic-data/fixtures/cache-scoped/app/connection/page.js @@ -0,0 +1,16 @@ +import { connection } from 'next/server' +import { unstable_cache as cache } from 'next/cache' + +const cachedConnection = cache(async () => connection()) + +export default async function Page({ searchParams }) { + await cachedConnection() + return ( + <div> + <section> + This example uses `connection()` inside `unstable_cache` which should + cause the build to fail + </section> + </div> + ) +} diff --git a/test/e2e/app-dir/dynamic-data/fixtures/main/app/force-dynamic/page.js b/test/e2e/app-dir/dynamic-data/fixtures/main/app/force-dynamic/page.js index 6cf7cbf960760..cfee26df62328 100644 --- a/test/e2e/app-dir/dynamic-data/fixtures/main/app/force-dynamic/page.js +++ b/test/e2e/app-dir/dynamic-data/fixtures/main/app/force-dynamic/page.js @@ -1,17 +1,19 @@ import { headers, cookies } from 'next/headers' +import { connection } from 'next/server' import { PageSentinel } from '../getSentinelValue' export const dynamic = 'force-dynamic' export default async function Page({ searchParams }) { + await connection() return ( <div> <PageSentinel /> <section> - This example uses headers/cookies/searchParams directly in a Page - configured with `dynamic = 'force-dynamic'`. This should cause the page - to always render dynamically regardless of dynamic APIs used + This example uses headers/cookies/connection/searchParams directly in a + Page configured with `dynamic = 'force-dynamic'`. This should cause the + page to always render dynamically regardless of dynamic APIs used </section> <section id="headers"> <h3>headers</h3> diff --git a/test/e2e/app-dir/dynamic-data/fixtures/main/app/force-static/page.js b/test/e2e/app-dir/dynamic-data/fixtures/main/app/force-static/page.js index 1137df1923ddd..6974704ef9b89 100644 --- a/test/e2e/app-dir/dynamic-data/fixtures/main/app/force-static/page.js +++ b/test/e2e/app-dir/dynamic-data/fixtures/main/app/force-static/page.js @@ -1,17 +1,19 @@ import { headers, cookies } from 'next/headers' +import { connection } from 'next/server' import { PageSentinel } from '../getSentinelValue' export const dynamic = 'force-static' export default async function Page({ searchParams }) { + await connection() return ( <div> <PageSentinel /> <section> - This example uses headers/cookies/searchParams directly in a Page - configured with `dynamic = 'force-static'`. This should cause the page - to always statically render but without exposing dynamic data + This example uses headers/cookies/connection/searchParams directly in a + Page configured with `dynamic = 'force-static'`. This should cause the + page to always statically render but without exposing dynamic data </section> <section id="headers"> <h3>headers</h3> diff --git a/test/e2e/app-dir/dynamic-data/fixtures/main/app/top-level/page.js b/test/e2e/app-dir/dynamic-data/fixtures/main/app/top-level/page.js index 73e446eb15aa4..a99598bd4dfa5 100644 --- a/test/e2e/app-dir/dynamic-data/fixtures/main/app/top-level/page.js +++ b/test/e2e/app-dir/dynamic-data/fixtures/main/app/top-level/page.js @@ -1,8 +1,10 @@ import { headers, cookies } from 'next/headers' +import { connection } from 'next/server' import { PageSentinel } from '../getSentinelValue' export default async function Page({ searchParams }) { + await connection() return ( <div> <PageSentinel /> diff --git a/test/e2e/app-dir/dynamic-data/fixtures/require-static/app/connection/page.js b/test/e2e/app-dir/dynamic-data/fixtures/require-static/app/connection/page.js new file mode 100644 index 0000000000000..c45ca779f1200 --- /dev/null +++ b/test/e2e/app-dir/dynamic-data/fixtures/require-static/app/connection/page.js @@ -0,0 +1,17 @@ +import Server, { connection } from 'next/server' + +console.log('Server', Server) + +export const dynamic = 'error' + +export default async function Page({ searchParams }) { + await connection() + return ( + <div> + <section> + This example uses `connection()` but is configured with `dynamic = + 'error'` which should cause the page to fail to build + </section> + </div> + ) +} diff --git a/test/e2e/app-dir/dynamic-io/app/connection/static-behavior/boundary/page.tsx b/test/e2e/app-dir/dynamic-io/app/connection/static-behavior/boundary/page.tsx new file mode 100644 index 0000000000000..187ac9a0cb7b1 --- /dev/null +++ b/test/e2e/app-dir/dynamic-io/app/connection/static-behavior/boundary/page.tsx @@ -0,0 +1,34 @@ +import { Suspense } from 'react' +import { connection } from 'next/server' + +import { getSentinelValue } from '../../../getSentinelValue' +/** + * This test case is constructed to demonstrate how using the async form of cookies can lead to a better + * prerender with dynamic IO when PPR is on. There is no difference when PPR is off. When PPR is on the second component + * can finish rendering before the prerender completes and so we can produce a static shell where the Fallback closest + * to Cookies access is read + */ +export default async function Page() { + return ( + <> + <Suspense fallback="loading..."> + <Component /> + </Suspense> + <ComponentTwo /> + <div id="page">{getSentinelValue()}</div> + </> + ) +} + +async function Component() { + await connection() + return ( + <div> + cookie <span id="foo">foo</span> + </div> + ) +} + +function ComponentTwo() { + return <p>footer</p> +} diff --git a/test/e2e/app-dir/dynamic-io/app/connection/static-behavior/pass-deeply/page.tsx b/test/e2e/app-dir/dynamic-io/app/connection/static-behavior/pass-deeply/page.tsx new file mode 100644 index 0000000000000..84a13e6876f6c --- /dev/null +++ b/test/e2e/app-dir/dynamic-io/app/connection/static-behavior/pass-deeply/page.tsx @@ -0,0 +1,46 @@ +import { Suspense } from 'react' +import { connection } from 'next/server' + +import { getSentinelValue } from '../../../getSentinelValue' + +export default async function Page() { + const pendingConnection = connection() + return ( + <section> + <h1>Deep Connection Reader</h1> + <p> + This component was passed the connection promise returned by + `connection()`. It is rendered inside a Suspense boundary. + </p> + <p> + If dynamicIO is turned off the `connection()` call would trigger a + dynamic point at the callsite and the suspense boundary would also be + blocked for over one second + </p> + <Suspense + fallback={ + <> + <p>loading connection...</p> + <div id="fallback">{getSentinelValue()}</div> + </> + } + > + <DeepConnectionReader pendingConnection={pendingConnection} /> + </Suspense> + </section> + ) +} + +async function DeepConnectionReader({ + pendingConnection, +}: { + pendingConnection: ReturnType<typeof connection> +}) { + await pendingConnection + return ( + <> + <p>The connection was awaited</p> + <div id="page">{getSentinelValue()}</div> + </> + ) +} diff --git a/test/e2e/app-dir/dynamic-io/app/connection/static-behavior/root/page.tsx b/test/e2e/app-dir/dynamic-io/app/connection/static-behavior/root/page.tsx new file mode 100644 index 0000000000000..f5ad949a2e3d3 --- /dev/null +++ b/test/e2e/app-dir/dynamic-io/app/connection/static-behavior/root/page.tsx @@ -0,0 +1,31 @@ +import { connection } from 'next/server' + +import { getSentinelValue } from '../../../getSentinelValue' +/** + * This test case is constructed to demonstrate how using the async form of cookies can lead to a better + * prerender with dynamic IO when PPR is on. There is no difference when PPR is off. When PPR is on the second component + * can finish rendering before the prerender completes and so we can produce a static shell where the Fallback closest + * to Cookies access is read + */ +export default async function Page() { + return ( + <> + <Component /> + <ComponentTwo /> + <div id="page">{getSentinelValue()}</div> + </> + ) +} + +async function Component() { + await connection() + return ( + <div> + cookie <span id="foo">foo</span> + </div> + ) +} + +function ComponentTwo() { + return <p>footer</p> +} diff --git a/test/e2e/app-dir/dynamic-io/app/params/semantics/[lowcard]/[highcard]/sync/layout-access/client/layout.tsx b/test/e2e/app-dir/dynamic-io/app/params/semantics/[lowcard]/[highcard]/sync/layout-access/client/layout.tsx index 89fb9d3da541f..dd188f38d293e 100644 --- a/test/e2e/app-dir/dynamic-io/app/params/semantics/[lowcard]/[highcard]/sync/layout-access/client/layout.tsx +++ b/test/e2e/app-dir/dynamic-io/app/params/semantics/[lowcard]/[highcard]/sync/layout-access/client/layout.tsx @@ -11,6 +11,10 @@ export default async function Page({ params: Promise<{ lowcard: string; highcard: string }> children: React.ReactNode }) { + // We wait an extra microtask to avoid erroring before some sibling branches have completed. + // In a future update we will make this a build error and explicitly test it but to keep the spirit of + // this test in tact we contrive a slightly delayed sync access + await 1 const syncParams = params as unknown as UnsafeUnwrappedParams<typeof params> return ( <section> diff --git a/test/e2e/app-dir/dynamic-io/app/params/semantics/[lowcard]/[highcard]/sync/layout-has/client/layout.tsx b/test/e2e/app-dir/dynamic-io/app/params/semantics/[lowcard]/[highcard]/sync/layout-has/client/layout.tsx index eebd0ddcfab66..7c1fbbed0bb59 100644 --- a/test/e2e/app-dir/dynamic-io/app/params/semantics/[lowcard]/[highcard]/sync/layout-has/client/layout.tsx +++ b/test/e2e/app-dir/dynamic-io/app/params/semantics/[lowcard]/[highcard]/sync/layout-has/client/layout.tsx @@ -11,6 +11,10 @@ export default async function Page({ params: Promise<{ lowcard: string; highcard: string }> children: React.ReactNode }) { + // We wait an extra microtask to avoid erroring before some sibling branches have completed. + // In a future update we will make this a build error and explicitly test it but to keep the spirit of + // this test in tact we contrive a slightly delayed sync access + await 1 const syncParams = params as unknown as UnsafeUnwrappedParams<typeof params> return ( <section> diff --git a/test/e2e/app-dir/dynamic-io/app/params/semantics/[lowcard]/[highcard]/sync/layout-spread/client/layout.tsx b/test/e2e/app-dir/dynamic-io/app/params/semantics/[lowcard]/[highcard]/sync/layout-spread/client/layout.tsx index 183e02961577b..a93ab56886680 100644 --- a/test/e2e/app-dir/dynamic-io/app/params/semantics/[lowcard]/[highcard]/sync/layout-spread/client/layout.tsx +++ b/test/e2e/app-dir/dynamic-io/app/params/semantics/[lowcard]/[highcard]/sync/layout-spread/client/layout.tsx @@ -11,6 +11,10 @@ export default async function Page({ params: Promise<{ lowcard: string; highcard: string }> children: React.ReactNode }) { + // We wait an extra microtask to avoid erroring before some sibling branches have completed. + // In a future update we will make this a build error and explicitly test it but to keep the spirit of + // this test in tact we contrive a slightly delayed sync access + await 1 const syncParams = params as unknown as UnsafeUnwrappedParams<typeof params> const copied = { ...syncParams } return ( diff --git a/test/e2e/app-dir/dynamic-io/app/params/semantics/[lowcard]/[highcard]/sync/page-access/client/page.tsx b/test/e2e/app-dir/dynamic-io/app/params/semantics/[lowcard]/[highcard]/sync/page-access/client/page.tsx index 490bc3e73435c..19aae1c3a25e4 100644 --- a/test/e2e/app-dir/dynamic-io/app/params/semantics/[lowcard]/[highcard]/sync/page-access/client/page.tsx +++ b/test/e2e/app-dir/dynamic-io/app/params/semantics/[lowcard]/[highcard]/sync/page-access/client/page.tsx @@ -9,6 +9,10 @@ export default async function Page({ }: { params: Promise<{ lowcard: string; highcard: string }> }) { + // We wait an extra microtask to avoid erroring before some sibling branches have completed. + // In a future update we will make this a build error and explicitly test it but to keep the spirit of + // this test in tact we contrive a slightly delayed sync access + await 1 const syncParams = params as unknown as UnsafeUnwrappedParams<typeof params> return ( <section> diff --git a/test/e2e/app-dir/dynamic-io/app/params/semantics/[lowcard]/[highcard]/sync/page-has/client/page.tsx b/test/e2e/app-dir/dynamic-io/app/params/semantics/[lowcard]/[highcard]/sync/page-has/client/page.tsx index d76a426661a24..89bc9544063aa 100644 --- a/test/e2e/app-dir/dynamic-io/app/params/semantics/[lowcard]/[highcard]/sync/page-has/client/page.tsx +++ b/test/e2e/app-dir/dynamic-io/app/params/semantics/[lowcard]/[highcard]/sync/page-has/client/page.tsx @@ -9,6 +9,10 @@ export default async function Page({ }: { params: Promise<{ lowcard: string; highcard: string }> }) { + // We wait an extra microtask to avoid erroring before some sibling branches have completed. + // In a future update we will make this a build error and explicitly test it but to keep the spirit of + // this test in tact we contrive a slightly delayed sync access + await 1 const syncParams = params as unknown as UnsafeUnwrappedParams<typeof params> return ( <section> diff --git a/test/e2e/app-dir/dynamic-io/app/params/semantics/[lowcard]/[highcard]/sync/page-spread/client/page.tsx b/test/e2e/app-dir/dynamic-io/app/params/semantics/[lowcard]/[highcard]/sync/page-spread/client/page.tsx index a4cb1e5bb7fa4..de695d9c8a682 100644 --- a/test/e2e/app-dir/dynamic-io/app/params/semantics/[lowcard]/[highcard]/sync/page-spread/client/page.tsx +++ b/test/e2e/app-dir/dynamic-io/app/params/semantics/[lowcard]/[highcard]/sync/page-spread/client/page.tsx @@ -9,6 +9,10 @@ export default async function Page({ }: { params: Promise<{ lowcard: string; highcard: string }> }) { + // We wait an extra microtask to avoid erroring before some sibling branches have completed. + // In a future update we will make this a build error and explicitly test it but to keep the spirit of + // this test in tact we contrive a slightly delayed sync access + await 1 const syncParams = params as unknown as UnsafeUnwrappedParams<typeof params> const copied = { ...syncParams } return ( diff --git a/test/e2e/app-dir/dynamic-io/app/routes/-edge/[dyn]/async/route.ts b/test/e2e/app-dir/dynamic-io/app/routes/-edge/[dyn]/async/route.ts index 3d6f8b0c15d36..b6fbf9a877750 100644 --- a/test/e2e/app-dir/dynamic-io/app/routes/-edge/[dyn]/async/route.ts +++ b/test/e2e/app-dir/dynamic-io/app/routes/-edge/[dyn]/async/route.ts @@ -4,14 +4,6 @@ import { getSentinelValue } from '../../../../getSentinelValue' export const runtime = 'edge' -export async function generateStaticParams() { - return [ - { - dyn: '1', - }, - ] -} - export async function GET( request: NextRequest, props: { params: Promise<{ dyn: string }> } diff --git a/test/e2e/app-dir/dynamic-io/app/routes/-edge/[dyn]/sync/route.ts b/test/e2e/app-dir/dynamic-io/app/routes/-edge/[dyn]/sync/route.ts index 9b7af314b610b..00e2a5a8436dd 100644 --- a/test/e2e/app-dir/dynamic-io/app/routes/-edge/[dyn]/sync/route.ts +++ b/test/e2e/app-dir/dynamic-io/app/routes/-edge/[dyn]/sync/route.ts @@ -4,14 +4,6 @@ import { getSentinelValue } from '../../../../getSentinelValue' export const runtime = 'edge' -export async function generateStaticParams() { - return [ - { - dyn: '1', - }, - ] -} - export async function GET( request: NextRequest, props: { params: Promise<{ dyn: string }> } diff --git a/test/e2e/app-dir/dynamic-io/dynamic-io.connection.test.ts b/test/e2e/app-dir/dynamic-io/dynamic-io.connection.test.ts new file mode 100644 index 0000000000000..b859bf8eedf41 --- /dev/null +++ b/test/e2e/app-dir/dynamic-io/dynamic-io.connection.test.ts @@ -0,0 +1,79 @@ +import { nextTestSetup } from 'e2e-utils' + +const WITH_PPR = !!process.env.__NEXT_EXPERIMENTAL_PPR + +describe('dynamic-io', () => { + const { next, isNextDev, skipped } = nextTestSetup({ + files: __dirname, + skipDeployment: true, + }) + + if (skipped) { + return + } + + if (WITH_PPR) { + it('should partially prerender pages that use connection', async () => { + let $ = await next.render$('/connection/static-behavior/boundary', {}) + if (isNextDev) { + expect($('#layout').text()).toBe('at runtime') + expect($('#page').text()).toBe('at runtime') + expect($('#foo').text()).toBe('foo') + } else { + expect($('#layout').text()).toBe('at buildtime') + expect($('#page').text()).toBe('at buildtime') + expect($('#foo').text()).toBe('foo') + } + + $ = await next.render$('/connection/static-behavior/root', {}) + if (isNextDev) { + expect($('#layout').text()).toBe('at runtime') + expect($('#page').text()).toBe('at runtime') + expect($('#foo').text()).toBe('foo') + } else { + expect($('#layout').text()).toBe('at runtime') + expect($('#page').text()).toBe('at runtime') + expect($('#foo').text()).toBe('foo') + } + }) + } else { + it('should produce dynamic pages when using connection', async () => { + let $ = await next.render$('/connection/static-behavior/boundary', {}) + if (isNextDev) { + expect($('#layout').text()).toBe('at runtime') + expect($('#page').text()).toBe('at runtime') + expect($('#foo').text()).toBe('foo') + } else { + expect($('#layout').text()).toBe('at runtime') + expect($('#page').text()).toBe('at runtime') + expect($('#foo').text()).toBe('foo') + } + + $ = await next.render$('/connection/static-behavior/root', {}) + if (isNextDev) { + expect($('#layout').text()).toBe('at runtime') + expect($('#page').text()).toBe('at runtime') + expect($('#foo').text()).toBe('foo') + } else { + expect($('#layout').text()).toBe('at runtime') + expect($('#page').text()).toBe('at runtime') + expect($('#foo').text()).toBe('foo') + } + }) + } + + if (WITH_PPR) { + it('should be able to pass connection as a promise to another component and trigger an intermediate Suspense boundary', async () => { + const $ = await next.render$('/connection/static-behavior/pass-deeply') + if (isNextDev) { + expect($('#layout').text()).toBe('at runtime') + expect($('#fallback').length).toBe(0) + expect($('#page').text()).toBe('at runtime') + } else { + expect($('#layout').text()).toBe('at buildtime') + expect($('#fallback').text()).toBe('at buildtime') + expect($('#page').text()).toBe('at runtime') + } + }) + } +}) diff --git a/test/e2e/app-dir/dynamic-io/dynamic-io.search.test.ts b/test/e2e/app-dir/dynamic-io/dynamic-io.search.test.ts index 85d0c7af425a8..c1464ea24c312 100644 --- a/test/e2e/app-dir/dynamic-io/dynamic-io.search.test.ts +++ b/test/e2e/app-dir/dynamic-io/dynamic-io.search.test.ts @@ -287,10 +287,10 @@ describe('dynamic-io', () => { expect($('#page').text()).toBe('at runtime') expect(searchWarnings).toEqual([ expect.stringContaining( - '`Reflect.has(searchParams, "sentinel"`, `"sentinel" in searchParams`, or similar' + '`Reflect.has(searchParams, "sentinel")`, `"sentinel" in searchParams`, or similar' ), expect.stringContaining( - '`Reflect.has(searchParams, "foo"`, `"foo" in searchParams`, or similar' + '`Reflect.has(searchParams, "foo")`, `"foo" in searchParams`, or similar' ), ]) } else { @@ -314,10 +314,10 @@ describe('dynamic-io', () => { expect($('#page').text()).toBe('at runtime') expect(searchWarnings).toEqual([ expect.stringContaining( - '`Reflect.has(searchParams, "sentinel"`, `"sentinel" in searchParams`, or similar' + '`Reflect.has(searchParams, "sentinel")`, `"sentinel" in searchParams`, or similar' ), expect.stringContaining( - '`Reflect.has(searchParams, "foo"`, `"foo" in searchParams`, or similar' + '`Reflect.has(searchParams, "foo")`, `"foo" in searchParams`, or similar' ), ]) } else { @@ -341,10 +341,10 @@ describe('dynamic-io', () => { expect($('#page').text()).toBe('at runtime') expect(searchWarnings).toEqual([ expect.stringContaining( - '`Reflect.has(searchParams, "sentinel"`, `"sentinel" in searchParams`, or similar' + '`Reflect.has(searchParams, "sentinel")`, `"sentinel" in searchParams`, or similar' ), expect.stringContaining( - '`Reflect.has(searchParams, "foo"`, `"foo" in searchParams`, or similar' + '`Reflect.has(searchParams, "foo")`, `"foo" in searchParams`, or similar' ), ]) } else { @@ -366,10 +366,10 @@ describe('dynamic-io', () => { expect($('#page').text()).toBe('at runtime') expect(searchWarnings).toEqual([ expect.stringContaining( - '`Reflect.has(searchParams, "sentinel"`, `"sentinel" in searchParams`, or similar' + '`Reflect.has(searchParams, "sentinel")`, `"sentinel" in searchParams`, or similar' ), expect.stringContaining( - '`Reflect.has(searchParams, "foo"`, `"foo" in searchParams`, or similar' + '`Reflect.has(searchParams, "foo")`, `"foo" in searchParams`, or similar' ), ]) } else { @@ -605,10 +605,10 @@ describe('dynamic-io', () => { expect($('#page').text()).toBe('at runtime') expect(searchWarnings).toEqual([ expect.stringContaining( - '`Reflect.has(searchParams, "sentinel"`, `"sentinel" in searchParams`, or similar.' + '`Reflect.has(searchParams, "sentinel")`, `"sentinel" in searchParams`, or similar.' ), expect.stringContaining( - 'Reflect.has(searchParams, "foo"`, `"foo" in searchParams`, or similar.' + 'Reflect.has(searchParams, "foo")`, `"foo" in searchParams`, or similar.' ), ]) } else { @@ -628,10 +628,10 @@ describe('dynamic-io', () => { expect($('#page').text()).toBe('at runtime') expect(searchWarnings).toEqual([ expect.stringContaining( - '`Reflect.has(searchParams, "sentinel"`, `"sentinel" in searchParams`, or similar.' + '`Reflect.has(searchParams, "sentinel")`, `"sentinel" in searchParams`, or similar.' ), expect.stringContaining( - 'Reflect.has(searchParams, "foo"`, `"foo" in searchParams`, or similar.' + 'Reflect.has(searchParams, "foo")`, `"foo" in searchParams`, or similar.' ), ]) } else { @@ -655,10 +655,10 @@ describe('dynamic-io', () => { expect($('#page').text()).toBe('at runtime') expect(searchWarnings).toEqual([ expect.stringContaining( - '`Reflect.has(searchParams, "sentinel"`, `"sentinel" in searchParams`, or similar.' + '`Reflect.has(searchParams, "sentinel")`, `"sentinel" in searchParams`, or similar.' ), expect.stringContaining( - 'Reflect.has(searchParams, "foo"`, `"foo" in searchParams`, or similar.' + 'Reflect.has(searchParams, "foo")`, `"foo" in searchParams`, or similar.' ), ]) } else { @@ -678,10 +678,10 @@ describe('dynamic-io', () => { expect($('#page').text()).toBe('at runtime') expect(searchWarnings).toEqual([ expect.stringContaining( - '`Reflect.has(searchParams, "sentinel"`, `"sentinel" in searchParams`, or similar.' + '`Reflect.has(searchParams, "sentinel")`, `"sentinel" in searchParams`, or similar.' ), expect.stringContaining( - 'Reflect.has(searchParams, "foo"`, `"foo" in searchParams`, or similar.' + 'Reflect.has(searchParams, "foo")`, `"foo" in searchParams`, or similar.' ), ]) } else { diff --git a/test/e2e/app-dir/dynamic-io/dynamic-io.test.ts b/test/e2e/app-dir/dynamic-io/dynamic-io.test.ts index 6b655621bf15c..a06d80877a7b6 100644 --- a/test/e2e/app-dir/dynamic-io/dynamic-io.test.ts +++ b/test/e2e/app-dir/dynamic-io/dynamic-io.test.ts @@ -12,6 +12,11 @@ describe('dynamic-io', () => { return } + it('should not have route specific errors', async () => { + expect(next.cliOutput).not.toMatch('Error: Route /') + expect(next.cliOutput).not.toMatch('Error occurred prerendering page') + }) + it('should prerender fully static pages', async () => { let $ = await next.render$('/cases/static', {}) if (isNextDev) { diff --git a/test/e2e/app-dir/metadata/app/basic-edge/page.tsx b/test/e2e/app-dir/metadata/app/basic-edge/page.tsx index a54fd7bd4e72f..6aa3fd5913282 100644 --- a/test/e2e/app-dir/metadata/app/basic-edge/page.tsx +++ b/test/e2e/app-dir/metadata/app/basic-edge/page.tsx @@ -2,7 +2,7 @@ import type { Metadata } from 'next' import Link from 'next/link' import Client from './client' -export const runtime = 'experimental-edge' +export const runtime = 'edge' export default function Page() { return ( diff --git a/test/e2e/app-dir/next-font/app/(preload)/page.js b/test/e2e/app-dir/next-font/app/(preload)/page.js index 64e1768d9e36c..fab157e5961ae 100644 --- a/test/e2e/app-dir/next-font/app/(preload)/page.js +++ b/test/e2e/app-dir/next-font/app/(preload)/page.js @@ -13,4 +13,4 @@ export default function HomePage() { ) } -export const runtime = 'experimental-edge' +export const runtime = 'edge' diff --git a/test/e2e/app-dir/next-image/app/legacy-edge-runtime/layout.js b/test/e2e/app-dir/next-image/app/legacy-edge-runtime/layout.js index 7fdd2e1fcfe19..a98ab29e02ea0 100644 --- a/test/e2e/app-dir/next-image/app/legacy-edge-runtime/layout.js +++ b/test/e2e/app-dir/next-image/app/legacy-edge-runtime/layout.js @@ -1,7 +1,7 @@ import Image from 'next/legacy/image' import testPng from '../../images/test.png' -export const runtime = 'experimental-edge' +export const runtime = 'edge' export default function LegacyEdgeLayout({ children }) { return ( diff --git a/test/e2e/app-dir/next-image/app/page.js b/test/e2e/app-dir/next-image/app/page.js index 5402e817dd4c0..1caffc0bf5db6 100644 --- a/test/e2e/app-dir/next-image/app/page.js +++ b/test/e2e/app-dir/next-image/app/page.js @@ -19,4 +19,4 @@ export default function Page() { ) } -export const runtime = 'experimental-edge' +export const runtime = 'edge' diff --git a/test/e2e/app-dir/revalidatetag-rsc/app/RevalidateViaForm.tsx b/test/e2e/app-dir/revalidatetag-rsc/app/RevalidateViaForm.tsx new file mode 100644 index 0000000000000..762d46859ca11 --- /dev/null +++ b/test/e2e/app-dir/revalidatetag-rsc/app/RevalidateViaForm.tsx @@ -0,0 +1,17 @@ +'use client' + +import { revalidate } from './actions/revalidate' + +export default function RevalidateViaForm({ tag }: { tag: string }) { + const handleRevalidate = async () => { + await revalidate(tag) + } + + return ( + <form action={handleRevalidate}> + <button type="submit" id="submit-form" className="underline"> + Revalidate via form + </button> + </form> + ) +} diff --git a/test/e2e/app-dir/revalidatetag-rsc/app/actions/revalidate.ts b/test/e2e/app-dir/revalidatetag-rsc/app/actions/revalidate.ts new file mode 100644 index 0000000000000..2fba1ff18f207 --- /dev/null +++ b/test/e2e/app-dir/revalidatetag-rsc/app/actions/revalidate.ts @@ -0,0 +1,11 @@ +'use server' + +import { revalidateTag } from 'next/cache' + +export const revalidate = async ( + tag: string +): Promise<{ revalidated: boolean }> => { + revalidateTag(tag) + + return { revalidated: true } +} diff --git a/test/e2e/app-dir/revalidatetag-rsc/app/layout.tsx b/test/e2e/app-dir/revalidatetag-rsc/app/layout.tsx new file mode 100644 index 0000000000000..716a8db36f52c --- /dev/null +++ b/test/e2e/app-dir/revalidatetag-rsc/app/layout.tsx @@ -0,0 +1,9 @@ +import { ReactNode } from 'react' + +export default function Root({ children }: { children: ReactNode }) { + return ( + <html> + <body>{children}</body> + </html> + ) +} diff --git a/test/e2e/app-dir/revalidatetag-rsc/app/page.tsx b/test/e2e/app-dir/revalidatetag-rsc/app/page.tsx new file mode 100644 index 0000000000000..e4ced2724de32 --- /dev/null +++ b/test/e2e/app-dir/revalidatetag-rsc/app/page.tsx @@ -0,0 +1,24 @@ +import RevalidateViaForm from './RevalidateViaForm' +import Link from 'next/link' + +export default async function Page() { + const data = await fetch( + 'https://next-data-api-endpoint.vercel.app/api/random', + { + next: { + tags: ['data'], + revalidate: false, + }, + } + ).then((res) => res.text()) + + return ( + <div> + <span id="data">{data}</span> + <RevalidateViaForm tag="data" /> + <Link href="/revalidate_via_page?tag=data" id="revalidate-via-page"> + Revalidate via page + </Link> + </div> + ) +} diff --git a/test/e2e/app-dir/revalidatetag-rsc/app/revalidate_via_page/page.tsx b/test/e2e/app-dir/revalidatetag-rsc/app/revalidate_via_page/page.tsx new file mode 100644 index 0000000000000..319a31582f655 --- /dev/null +++ b/test/e2e/app-dir/revalidatetag-rsc/app/revalidate_via_page/page.tsx @@ -0,0 +1,24 @@ +'use server' + +import Link from 'next/link' +import { revalidateTag } from 'next/cache' + +const RevalidateViaPage = async ({ + searchParams, +}: { + searchParams: Promise<{ tag: string }> +}) => { + const { tag } = await searchParams + revalidateTag(tag) + + return ( + <div className="flex flex-col items-center justify-center h-screen"> + <pre>Tag [{tag}] has been revalidated</pre> + <Link href="/" id="home"> + To Home + </Link> + </div> + ) +} + +export default RevalidateViaPage diff --git a/test/e2e/app-dir/revalidatetag-rsc/next.config.js b/test/e2e/app-dir/revalidatetag-rsc/next.config.js new file mode 100644 index 0000000000000..807126e4cf0bf --- /dev/null +++ b/test/e2e/app-dir/revalidatetag-rsc/next.config.js @@ -0,0 +1,6 @@ +/** + * @type {import('next').NextConfig} + */ +const nextConfig = {} + +module.exports = nextConfig diff --git a/test/e2e/app-dir/revalidatetag-rsc/revalidatetag-rsc.test.ts b/test/e2e/app-dir/revalidatetag-rsc/revalidatetag-rsc.test.ts new file mode 100644 index 0000000000000..5355fb7d1c602 --- /dev/null +++ b/test/e2e/app-dir/revalidatetag-rsc/revalidatetag-rsc.test.ts @@ -0,0 +1,38 @@ +import { nextTestSetup } from 'e2e-utils' +import { retry } from 'next-test-utils' + +describe('revalidateTag-rsc', () => { + const { next } = nextTestSetup({ + files: __dirname, + }) + + it('should revalidate fetch cache if revalidateTag invoked via server action', async () => { + const browser = await next.browser('/') + const randomNumber = await browser.elementById('data').text() + await browser.refresh() + const randomNumber2 = await browser.elementById('data').text() + expect(randomNumber).toEqual(randomNumber2) + + await browser.elementByCss('#submit-form').click() + + await retry(async () => { + const randomNumber3 = await browser.elementById('data').text() + expect(randomNumber3).not.toEqual(randomNumber) + }) + }) + + it('should revalidate fetch cache if revalidateTag invoked via server component', async () => { + const browser = await next.browser('/') + const randomNumber = await browser.elementById('data').text() + await browser.refresh() + const randomNumber2 = await browser.elementById('data').text() + expect(randomNumber).toEqual(randomNumber2) + + await browser.elementByCss('#revalidate-via-page').click() + await browser.waitForElementByCss('#home') + await browser.elementByCss('#home').click() + await browser.waitForElementByCss('#data') + const randomNumber3 = await browser.elementById('data').text() + expect(randomNumber3).not.toEqual(randomNumber) + }) +}) diff --git a/test/e2e/app-dir/rsc-basic/app/edge/dynamic/[id]/page.js b/test/e2e/app-dir/rsc-basic/app/edge/dynamic/[id]/page.js index 6f2b162798eb9..91f7bd0199df1 100644 --- a/test/e2e/app-dir/rsc-basic/app/edge/dynamic/[id]/page.js +++ b/test/e2e/app-dir/rsc-basic/app/edge/dynamic/[id]/page.js @@ -2,4 +2,4 @@ export default function page() { return 'dynamic route [id] page' } -export const runtime = 'experimental-edge' +export const runtime = 'edge' diff --git a/test/e2e/app-dir/rsc-basic/app/edge/dynamic/page.js b/test/e2e/app-dir/rsc-basic/app/edge/dynamic/page.js index 356b786c602f3..17cf8f0f419e6 100644 --- a/test/e2e/app-dir/rsc-basic/app/edge/dynamic/page.js +++ b/test/e2e/app-dir/rsc-basic/app/edge/dynamic/page.js @@ -2,4 +2,4 @@ export default function page() { return 'dynamic route index page' } -export const runtime = 'experimental-edge' +export const runtime = 'edge' diff --git a/test/e2e/app-dir/set-cookies/app/api/app/experimental-edge/route.js b/test/e2e/app-dir/set-cookies/app/api/app/experimental-edge/route.js deleted file mode 100644 index 6ba240c8e899c..0000000000000 --- a/test/e2e/app-dir/set-cookies/app/api/app/experimental-edge/route.js +++ /dev/null @@ -1,12 +0,0 @@ -export const runtime = 'experimental-edge' - -import cookies from '../../../../cookies.mjs' - -export async function GET() { - const headers = new Headers() - for (const cookie of cookies) { - headers.append('set-cookie', cookie) - } - - return new Response(null, { headers }) -} diff --git a/test/e2e/app-dir/set-cookies/set-cookies.test.ts b/test/e2e/app-dir/set-cookies/set-cookies.test.ts index 12f5ba8851c24..ab4f3d886d5f3 100644 --- a/test/e2e/app-dir/set-cookies/set-cookies.test.ts +++ b/test/e2e/app-dir/set-cookies/set-cookies.test.ts @@ -21,28 +21,28 @@ describe('set-cookies', () => { return } - describe.each(['edge', 'experimental-edge', 'node'])( - 'for %s runtime', - (runtime) => { - describe.each(['pages', 'app'])('for /%s', (dir) => { - it('should set two set-cookie headers', async () => { - let res = await next.fetch(`/api/${dir}/${runtime}`) + describe.each([ + { dir: 'pages', runtimes: ['edge', 'experimental-edge', 'node'] }, + { dir: 'app', runtimes: ['edge', 'node'] }, + ])('for /$dir', ({ dir, runtimes }) => { + describe.each(runtimes)('for %s runtime', (runtime) => { + it('should set two set-cookie headers', async () => { + let res = await next.fetch(`/api/${dir}/${runtime}`) - let headers = getSetCookieHeaders(res) + let headers = getSetCookieHeaders(res) - expect(headers).toHaveLength(2) - expect(headers).toEqual(cookies) + expect(headers).toHaveLength(2) + expect(headers).toEqual(cookies) - res = await next.fetch( - `/api/${dir}/${runtime}?next-config-headers=true` - ) + res = await next.fetch( + `/api/${dir}/${runtime}?next-config-headers=true` + ) - headers = getSetCookieHeaders(res) + headers = getSetCookieHeaders(res) - expect(headers).toHaveLength(4) - expect(headers).toEqual([...nextConfigHeaders, ...cookies]) - }) + expect(headers).toHaveLength(4) + expect(headers).toEqual([...nextConfigHeaders, ...cookies]) }) - } - ) + }) + }) }) diff --git a/test/e2e/app-dir/use-cache/app/errors/error-boundary.tsx b/test/e2e/app-dir/use-cache/app/errors/error-boundary.tsx new file mode 100644 index 0000000000000..93472e5662b11 --- /dev/null +++ b/test/e2e/app-dir/use-cache/app/errors/error-boundary.tsx @@ -0,0 +1,19 @@ +'use client' + +import { Component } from 'react' + +export default class ErrorBoundary extends Component< + { id: string; children: React.ReactNode }, + { message: null | string } +> { + state = { message: null } + static getDerivedStateFromError(error: any) { + return { message: error.message } + } + render() { + if (this.state.message !== null) { + return <p id={this.props.id}>{this.state.message}</p> + } + return this.props.children + } +} diff --git a/test/e2e/app-dir/use-cache/app/errors/page.tsx b/test/e2e/app-dir/use-cache/app/errors/page.tsx new file mode 100644 index 0000000000000..42278f43b4b18 --- /dev/null +++ b/test/e2e/app-dir/use-cache/app/errors/page.tsx @@ -0,0 +1,37 @@ +import ErrorBoundary from './error-boundary' + +import { cookies } from 'next/headers' + +import { currentUser, currentReferer, isEditing } from './util' + +async function Cookie() { + 'use cache' + return <div>User: {currentUser()}</div> +} + +async function Header() { + 'use cache' + return <div>Referer: {currentReferer()}</div> +} + +async function DraftMode() { + 'use cache' + return <div>Editing: {isEditing()}</div> +} + +export default async function Page() { + await cookies() + return ( + <div> + <ErrorBoundary id="cookies"> + <Cookie /> + </ErrorBoundary> + <ErrorBoundary id="headers"> + <Header /> + </ErrorBoundary> + <ErrorBoundary id="draft-mode"> + <DraftMode /> + </ErrorBoundary> + </div> + ) +} diff --git a/test/e2e/app-dir/use-cache/app/errors/util.ts b/test/e2e/app-dir/use-cache/app/errors/util.ts new file mode 100644 index 0000000000000..923e84f6a4838 --- /dev/null +++ b/test/e2e/app-dir/use-cache/app/errors/util.ts @@ -0,0 +1,13 @@ +import { cookies, headers, draftMode } from 'next/headers' + +export async function currentUser() { + return (await cookies()).get('user')?.value +} + +export async function currentReferer() { + return (await headers()).get('referer') +} + +export async function isEditing() { + return (await draftMode()).isEnabled +} diff --git a/test/e2e/app-dir/use-cache/app/layout.tsx b/test/e2e/app-dir/use-cache/app/layout.tsx index e7077399c03ce..2d8f3d5939bc0 100644 --- a/test/e2e/app-dir/use-cache/app/layout.tsx +++ b/test/e2e/app-dir/use-cache/app/layout.tsx @@ -1,7 +1,11 @@ +import { Suspense } from 'react' + export default function Root({ children }: { children: React.ReactNode }) { return ( <html> - <body>{children}</body> + <body> + <Suspense fallback={null}>{children}</Suspense> + </body> </html> ) } diff --git a/test/e2e/app-dir/use-cache/app/react-cache/page.tsx b/test/e2e/app-dir/use-cache/app/react-cache/page.tsx new file mode 100644 index 0000000000000..a111424eebcab --- /dev/null +++ b/test/e2e/app-dir/use-cache/app/react-cache/page.tsx @@ -0,0 +1,24 @@ +import { cache } from 'react' + +const number = cache(() => { + return Math.random() +}) + +function Component() { + // Read number again in a component. This should be deduped. + return <p id="b">{number()}</p> +} + +async function getCachedComponent() { + 'use cache' + return ( + <div> + <p id="a">{number()}</p> + <Component /> + </div> + ) +} + +export default async function Page() { + return <div>{getCachedComponent()}</div> +} diff --git a/test/e2e/app-dir/use-cache/use-cache.test.ts b/test/e2e/app-dir/use-cache/use-cache.test.ts index 922838f628b6d..d946bcb2f1037 100644 --- a/test/e2e/app-dir/use-cache/use-cache.test.ts +++ b/test/e2e/app-dir/use-cache/use-cache.test.ts @@ -1,8 +1,11 @@ // @ts-check import { nextTestSetup } from 'e2e-utils' +const GENERIC_RSC_ERROR = + 'An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.' + describe('use-cache', () => { - const { next } = nextTestSetup({ + const { next, isNextDev, isNextDeploy } = nextTestSetup({ files: __dirname, }) @@ -25,4 +28,44 @@ describe('use-cache', () => { // The navigation to n=2 should be some other random value. expect(random1a).not.toBe(random2) }) + + it('should dedupe with react cache inside "use cache"', async () => { + const browser = await next.browser('/react-cache') + const a = await browser.waitForElementByCss('#a').text() + const b = await browser.waitForElementByCss('#b').text() + // TODO: This is broken. It is expected to pass once we fix it. + expect(a).not.toBe(b) + }) + + it('should error when cookies/headers/draftMode is used inside "use cache"', async () => { + const browser = await next.browser('/errors') + expect(await browser.waitForElementByCss('#cookies').text()).toContain( + isNextDev + ? '`cookies` cannot be called inside "use cache".' + : GENERIC_RSC_ERROR + ) + expect(await browser.waitForElementByCss('#headers').text()).toContain( + isNextDev + ? '`headers` cannot be called inside "use cache".' + : GENERIC_RSC_ERROR + ) + expect(await browser.waitForElementByCss('#draft-mode').text()).toContain( + isNextDev + ? '`draftMode` cannot be called inside "use cache".' + : GENERIC_RSC_ERROR + ) + + // CLI assertions are skipped in deploy mode because `next.cliOutput` will only contain build-time logs. + if (!isNextDeploy) { + expect(next.cliOutput).toContain( + '`cookies` cannot be called inside "use cache".' + ) + expect(next.cliOutput).toContain( + '`headers` cannot be called inside "use cache".' + ) + expect(next.cliOutput).toContain( + '`draftMode` cannot be called inside "use cache".' + ) + } + }) }) diff --git a/test/e2e/favicon-short-circuit/app/layout.js b/test/e2e/favicon-short-circuit/app/layout.js new file mode 100644 index 0000000000000..803f17d863c8a --- /dev/null +++ b/test/e2e/favicon-short-circuit/app/layout.js @@ -0,0 +1,7 @@ +export default function RootLayout({ children }) { + return ( + <html> + <body>{children}</body> + </html> + ) +} diff --git a/test/e2e/next-test/first-time-setup-js/package.json b/test/e2e/next-test/first-time-setup-js/package.json index 259052d14ff04..16d3e117a3045 100644 --- a/test/e2e/next-test/first-time-setup-js/package.json +++ b/test/e2e/next-test/first-time-setup-js/package.json @@ -8,7 +8,7 @@ }, "dependencies": { "next": "canary", - "react": "19.0.0-rc-3edc000d-20240926", - "react-dom": "19.0.0-rc-3edc000d-20240926" + "react": "19.0.0-rc-2d16326d-20240930", + "react-dom": "19.0.0-rc-2d16326d-20240930" } } diff --git a/test/e2e/next-test/first-time-setup-ts/package.json b/test/e2e/next-test/first-time-setup-ts/package.json index e90b2966fb405..99cd0dfc58c72 100644 --- a/test/e2e/next-test/first-time-setup-ts/package.json +++ b/test/e2e/next-test/first-time-setup-ts/package.json @@ -8,8 +8,8 @@ }, "dependencies": { "next": "canary", - "react": "19.0.0-rc-3edc000d-20240926", - "react-dom": "19.0.0-rc-3edc000d-20240926" + "react": "19.0.0-rc-2d16326d-20240930", + "react-dom": "19.0.0-rc-2d16326d-20240930" }, "devDependencies": { "@types/react": "^18", diff --git a/test/integration/styled-jsx-plugin/test/index.test.js b/test/integration/styled-jsx-plugin/test/index.test.js index 4dc864ea1f670..421947697118e 100644 --- a/test/integration/styled-jsx-plugin/test/index.test.js +++ b/test/integration/styled-jsx-plugin/test/index.test.js @@ -20,25 +20,29 @@ function runTests() { }) } -describe('styled-jsx using in node_modules', () => { - ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( - 'production mode', - () => { - beforeAll(async () => { - const output = await nextBuild(appDir, undefined, { - stdout: true, - stderr: true, - cwd: appDir, - }) +// This test is skipped in Turbopack because it uses a custom babelrc. +;(process.env.TURBOPACK ? describe.skip : describe)( + 'styled-jsx using in node_modules', + () => { + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + beforeAll(async () => { + const output = await nextBuild(appDir, undefined, { + stdout: true, + stderr: true, + cwd: appDir, + }) - console.log(output.stdout, output.stderr) + console.log(output.stdout, output.stderr) - appPort = await findPort() - app = await nextStart(appDir, appPort) - }) - afterAll(() => killApp(app)) + appPort = await findPort() + app = await nextStart(appDir, appPort) + }) + afterAll(() => killApp(app)) - runTests() - } - ) -}) + runTests() + } + ) + } +) diff --git a/test/lib/next-modes/base.ts b/test/lib/next-modes/base.ts index f97a3c127f775..6fea66295cc55 100644 --- a/test/lib/next-modes/base.ts +++ b/test/lib/next-modes/base.ts @@ -51,7 +51,7 @@ type OmitFirstArgument<F> = F extends ( // Do not rename or format. sync-react script relies on this line. // prettier-ignore -const nextjsReactPeerVersion = "19.0.0-rc-3edc000d-20240926"; +const nextjsReactPeerVersion = "19.0.0-rc-2d16326d-20240930"; export class NextInstance { protected files: FileRef | { [filename: string]: string | FileRef } diff --git a/test/turbopack-build-tests-manifest.json b/test/turbopack-build-tests-manifest.json index 1b766dfa481b4..e75b1b19d5539 100644 --- a/test/turbopack-build-tests-manifest.json +++ b/test/turbopack-build-tests-manifest.json @@ -4732,10 +4732,10 @@ "runtimeError": false }, "test/e2e/favicon-short-circuit/favicon-short-circuit.test.ts": { - "passed": [], - "failed": [ + "passed": [ "favicon-short-circuit should not short circuit the favicon in production" ], + "failed": [], "pending": [], "flakey": [], "runtimeError": false @@ -14958,10 +14958,10 @@ }, "test/integration/styled-jsx-plugin/test/index.test.js": { "passed": [], - "failed": [ + "failed": [], + "pending": [ "styled-jsx using in node_modules production mode should serve a page correctly" ], - "pending": [], "flakey": [], "runtimeError": false }, @@ -15856,6 +15856,26 @@ "flakey": [], "runtimeError": false }, + "test/production/app-dir/server-action-period-hash/server-action-period-hash.test.ts": { + "passed": [], + "failed": [ + "app-dir - server-action-period-hash should have same manifest between continuous two builds", + "app-dir - server-action-period-hash should have different manifest between two builds with period hash" + ], + "pending": [], + "flakey": [], + "runtimeError": false + }, + "test/production/app-dir/server-action-period-hash/server-action-period-hash-custom-key.test.ts": { + "passed": [], + "failed": [ + "app-dir - server-action-period-hash-custom-key should have different manifest if the encryption key from process env is changed", + "app-dir - server-action-period-hash-custom-key should have different manifest if the encryption key from process env is same" + ], + "pending": [], + "flakey": [], + "runtimeError": false + }, "test/production/app-dir/ssg-single-pass/ssg-single-pass.test.ts": { "passed": [ "ssg-single-pass should only render the page once during an ISR revalidation", diff --git a/turbopack/crates/turbopack-core/src/chunk/module_id_strategies.rs b/turbopack/crates/turbopack-core/src/chunk/module_id_strategies.rs index fa9bfb900a5cb..06f598129ae90 100644 --- a/turbopack/crates/turbopack-core/src/chunk/module_id_strategies.rs +++ b/turbopack/crates/turbopack-core/src/chunk/module_id_strategies.rs @@ -1,6 +1,5 @@ -use std::collections::HashMap; - use anyhow::Result; +use indexmap::IndexMap; use turbo_tasks::{RcStr, ValueToString, Vc}; use turbo_tasks_hash::hash_xxh3_hash64; @@ -31,11 +30,11 @@ impl ModuleIdStrategy for DevModuleIdStrategy { #[turbo_tasks::value] pub struct GlobalModuleIdStrategy { - module_id_map: HashMap<RcStr, Vc<ModuleId>>, + module_id_map: IndexMap<RcStr, ModuleId>, } impl GlobalModuleIdStrategy { - pub async fn new(module_id_map: HashMap<RcStr, Vc<ModuleId>>) -> Result<Vc<Self>> { + pub async fn new(module_id_map: IndexMap<RcStr, ModuleId>) -> Result<Vc<Self>> { Ok(GlobalModuleIdStrategy { module_id_map }.cell()) } } @@ -46,10 +45,8 @@ impl ModuleIdStrategy for GlobalModuleIdStrategy { async fn get_module_id(&self, ident: Vc<AssetIdent>) -> Result<Vc<ModuleId>> { let ident_string = ident.to_string().await?.clone_value(); if let Some(module_id) = self.module_id_map.get(&ident_string) { - // dbg!(format!("Hit {}", ident.to_string().await?)); - return Ok(*module_id); + return Ok(module_id.clone().cell()); } - // dbg!(format!("Miss {}", ident.to_string().await?)); Ok(ModuleId::String( hash_xxh3_hash64(ident.to_string().await?) .to_string() diff --git a/turbopack/crates/turbopack-ecmascript/src/global_module_id_strategy.rs b/turbopack/crates/turbopack-ecmascript/src/global_module_id_strategy.rs index dd0d84446d145..d529cd8cd3115 100644 --- a/turbopack/crates/turbopack-ecmascript/src/global_module_id_strategy.rs +++ b/turbopack/crates/turbopack-ecmascript/src/global_module_id_strategy.rs @@ -1,6 +1,5 @@ -use std::collections::{HashMap, HashSet}; - use anyhow::Result; +use indexmap::{IndexMap, IndexSet}; use turbo_tasks::{ graph::{AdjacencyMap, GraphTraversal}, RcStr, TryJoinIterExt, ValueToString, Vc, @@ -19,7 +18,7 @@ pub struct PreprocessedChildrenIdents { // ident.to_string() -> full hash // We save the full hash to avoid re-hashing in `merge_preprocessed_module_ids` // if this endpoint did not change. - modules_idents: HashMap<RcStr, u64>, + modules_idents: IndexMap<RcStr, u64>, } #[derive(Clone, Hash)] @@ -49,7 +48,7 @@ pub struct ReferencedModules(Vec<Vc<ReferencedModule>>); async fn referenced_modules(module: Vc<Box<dyn Module>>) -> Result<Vc<ReferencedModules>> { let references = module.references().await?; - let mut set = HashSet::new(); + let mut set = IndexSet::new(); let modules_and_async_loaders: ModulesAndAsyncLoaders = references .iter() .map(|reference| async move { @@ -134,7 +133,7 @@ pub async fn children_modules_idents( .into_reverse_topological(); // module_id -> full hash - let mut modules_idents = HashMap::new(); + let mut modules_idents = IndexMap::new(); for child_module in children_modules_iter { match *child_module.await? { ReferencedModule::Module(module) => { @@ -164,58 +163,43 @@ pub async fn children_modules_idents( Ok(PreprocessedChildrenIdents { modules_idents }.cell()) } +const JS_MAX_SAFE_INTEGER: u64 = (1u64 << 53) - 1; + // Note(LichuAcu): This could be split into two functions: one that merges the preprocessed module // ids and another that generates the final, optimized module ids. Thoughts? pub async fn merge_preprocessed_module_ids( preprocessed_module_ids: Vec<Vc<PreprocessedChildrenIdents>>, -) -> Result<HashMap<RcStr, Vc<ModuleId>>> { - let mut module_id_map: HashMap<RcStr, Vc<ModuleId>> = HashMap::new(); - let mut used_ids: HashSet<u64> = HashSet::new(); +) -> Result<IndexMap<RcStr, ModuleId>> { + let mut merged_module_ids = IndexMap::new(); for preprocessed_module_ids in preprocessed_module_ids { - for (module_ident, full_hash) in preprocessed_module_ids.await?.modules_idents.iter() { - process_module( - module_ident.clone(), - *full_hash, - &mut module_id_map, - &mut used_ids, - ) - .await?; + for (module_ident, full_hash) in &preprocessed_module_ids.await?.modules_idents { + merged_module_ids.insert(module_ident.clone(), *full_hash); } } - Ok(module_id_map) -} - -pub async fn process_module( - ident_str: RcStr, - full_hash: u64, - id_map: &mut HashMap<RcStr, Vc<ModuleId>>, - used_ids: &mut HashSet<u64>, -) -> Result<()> { - if id_map.contains_key(&ident_str) { - return Ok(()); - } - - let mut trimmed_hash = full_hash % 10; - let mut power = 10; - while used_ids.contains(&trimmed_hash) { - if power >= u64::MAX / 10 { - // We don't want to take the next power as it would overflow - if used_ids.contains(&full_hash) { - return Err(anyhow::anyhow!("This is a... 64-bit hash collision?")); - } - trimmed_hash = full_hash; - break; + // 5% fill rate, as done in Webpack + // https://github.com/webpack/webpack/blob/27cf3e59f5f289dfc4d76b7a1df2edbc4e651589/lib/ids/IdHelpers.js#L366-L405 + let optimal_range = merged_module_ids.len() * 20; + let digit_mask = std::cmp::min( + 10u64.pow((optimal_range as f64).log10().ceil() as u32), + JS_MAX_SAFE_INTEGER, + ); + + let mut module_id_map = IndexMap::new(); + let mut used_ids = IndexSet::new(); + + for (module_ident, full_hash) in merged_module_ids.iter() { + let mut trimmed_hash = full_hash % digit_mask; + let mut i = 1; + while used_ids.contains(&trimmed_hash) { + // If the id is already used, seek to find another available id. + trimmed_hash = hash_xxh3_hash64(full_hash + i) % digit_mask; + i += 1; } - power *= 10; - trimmed_hash = full_hash % power; + used_ids.insert(trimmed_hash); + module_id_map.insert(module_ident.clone(), ModuleId::Number(trimmed_hash)); } - let hashed_module_id = ModuleId::Number(trimmed_hash); - - id_map.insert(ident_str, hashed_module_id.cell()); - used_ids.insert(trimmed_hash); - - Ok(()) + Ok(module_id_map) }