diff --git a/crates/next-api/src/pages.rs b/crates/next-api/src/pages.rs
index c0e26bd94196..bff0e3dd6616 100644
--- a/crates/next-api/src/pages.rs
+++ b/crates/next-api/src/pages.rs
@@ -233,11 +233,11 @@ impl PagesProject {
}
#[turbo_tasks::function]
- async fn to_endpoint(
+ async fn to_page_endpoint(
self: Vc,
item: Vc,
ty: PageEndpointType,
- ) -> Result>> {
+ ) -> Result> {
let PagesStructureItem {
next_router_path,
original_path,
@@ -245,15 +245,23 @@ impl PagesProject {
} = &*item.await?;
let pathname: RcStr = format!("/{}", next_router_path.path).into();
let original_name = format!("/{}", original_path.path).into();
- let endpoint = Vc::upcast(PageEndpoint::new(
+ Ok(PageEndpoint::new(
ty,
self,
pathname,
original_name,
item,
self.pages_structure(),
- ));
- Ok(endpoint)
+ ))
+ }
+
+ #[turbo_tasks::function]
+ async fn to_endpoint(
+ self: Vc,
+ item: Vc,
+ ty: PageEndpointType,
+ ) -> Result>> {
+ Ok(Vc::upcast(self.to_page_endpoint(item, ty)))
}
#[turbo_tasks::function]
@@ -264,9 +272,16 @@ impl PagesProject {
))
}
+ /// The `/_app` endpoint. Its client chunk group is generated first and seeds the availability
+ /// information of every other page, so it must never depend on an individual page.
+ #[turbo_tasks::function]
+ async fn app_page_endpoint(self: Vc) -> Result> {
+ Ok(self.to_page_endpoint(*self.pages_structure().await?.app, PageEndpointType::Html))
+ }
+
#[turbo_tasks::function]
pub async fn app_endpoint(self: Vc) -> Result>> {
- Ok(self.to_endpoint(*self.pages_structure().await?.app, PageEndpointType::Html))
+ Ok(Vc::upcast(self.app_page_endpoint()))
}
#[turbo_tasks::function]
@@ -797,12 +812,24 @@ impl PageEndpoint {
.iter()
.map(|m| ResolvedVc::upcast(*m))
.collect();
+ // Like App Router layouts, `/_app` is always loaded before the page. Chunk it first so
+ // the page's chunks don't include modules that the browser already downloaded with
+ // `/_app`.
+ let availability_info = if this.pathname == "/_app" {
+ AvailabilityInfo::root()
+ } else {
+ this.pages_project
+ .app_page_endpoint()
+ .client_chunk_group()
+ .await?
+ .availability_info
+ };
let client_chunk_group = client_chunking_context.evaluated_chunk_group(
AssetIdent::from_path(this.page.await?.base_path.clone()).into_vc(),
ChunkGroup::Entry(evaluatable_assets),
module_graph,
OutputAssets::empty(),
- AvailabilityInfo::root(),
+ availability_info,
);
Ok(client_chunk_group)
diff --git a/crates/next-custom-transforms/src/transforms/react_server_components.rs b/crates/next-custom-transforms/src/transforms/react_server_components.rs
index 03559971beae..dd5ff3a6cdcb 100644
--- a/crates/next-custom-transforms/src/transforms/react_server_components.rs
+++ b/crates/next-custom-transforms/src/transforms/react_server_components.rs
@@ -726,6 +726,7 @@ impl ReactServerComponentValidator {
"cacheTag",
"unstable_cacheTag",
"unstable_navigation",
+ "unstable_prefetch",
// "unstable_noStore" // no-op in client, but allowed for legacy reasons
],
),
diff --git a/crates/next-custom-transforms/tests/errors/react-server-components/client-graph/app-dir/unstable-prefetch/input.js b/crates/next-custom-transforms/tests/errors/react-server-components/client-graph/app-dir/unstable-prefetch/input.js
new file mode 100644
index 000000000000..8954009c7a83
--- /dev/null
+++ b/crates/next-custom-transforms/tests/errors/react-server-components/client-graph/app-dir/unstable-prefetch/input.js
@@ -0,0 +1,6 @@
+import { unstable_prefetch } from 'next/cache'
+
+export async function test() {
+ await unstable_prefetch()
+ return null
+}
diff --git a/crates/next-custom-transforms/tests/errors/react-server-components/client-graph/app-dir/unstable-prefetch/output.js b/crates/next-custom-transforms/tests/errors/react-server-components/client-graph/app-dir/unstable-prefetch/output.js
new file mode 100644
index 000000000000..2b30bf988768
--- /dev/null
+++ b/crates/next-custom-transforms/tests/errors/react-server-components/client-graph/app-dir/unstable-prefetch/output.js
@@ -0,0 +1,5 @@
+import { unstable_prefetch } from 'next/cache';
+export async function test() {
+ await unstable_prefetch();
+ return null;
+}
diff --git a/crates/next-custom-transforms/tests/errors/react-server-components/client-graph/app-dir/unstable-prefetch/output.stderr b/crates/next-custom-transforms/tests/errors/react-server-components/client-graph/app-dir/unstable-prefetch/output.stderr
new file mode 100644
index 000000000000..c53340fc7672
--- /dev/null
+++ b/crates/next-custom-transforms/tests/errors/react-server-components/client-graph/app-dir/unstable-prefetch/output.stderr
@@ -0,0 +1,9 @@
+ x You're importing a module that depends on "unstable_prefetch" into a React Client Component module. This API is only available in Server Components but one of its parents is marked with "use
+ | client", so this module is also a Client Component.
+ | Learn more: https://nextjs.org/docs/app/building-your-application/rendering
+ |
+ |
+ ,-[input.js:1:1]
+ 1 | import { unstable_prefetch } from 'next/cache'
+ : ^^^^^^^^^^^^^^^^^
+ `----
diff --git a/crates/next-custom-transforms/tests/errors/react-server-components/client-graph/unstable-prefetch/input.js b/crates/next-custom-transforms/tests/errors/react-server-components/client-graph/unstable-prefetch/input.js
new file mode 100644
index 000000000000..8954009c7a83
--- /dev/null
+++ b/crates/next-custom-transforms/tests/errors/react-server-components/client-graph/unstable-prefetch/input.js
@@ -0,0 +1,6 @@
+import { unstable_prefetch } from 'next/cache'
+
+export async function test() {
+ await unstable_prefetch()
+ return null
+}
diff --git a/crates/next-custom-transforms/tests/errors/react-server-components/client-graph/unstable-prefetch/output.js b/crates/next-custom-transforms/tests/errors/react-server-components/client-graph/unstable-prefetch/output.js
new file mode 100644
index 000000000000..2b30bf988768
--- /dev/null
+++ b/crates/next-custom-transforms/tests/errors/react-server-components/client-graph/unstable-prefetch/output.js
@@ -0,0 +1,5 @@
+import { unstable_prefetch } from 'next/cache';
+export async function test() {
+ await unstable_prefetch();
+ return null;
+}
diff --git a/crates/next-custom-transforms/tests/errors/react-server-components/client-graph/unstable-prefetch/output.stderr b/crates/next-custom-transforms/tests/errors/react-server-components/client-graph/unstable-prefetch/output.stderr
new file mode 100644
index 000000000000..b8232a355a9b
--- /dev/null
+++ b/crates/next-custom-transforms/tests/errors/react-server-components/client-graph/unstable-prefetch/output.stderr
@@ -0,0 +1,8 @@
+ x You're importing a module that depends on "unstable_prefetch". This API is only available in Server Components in the App Router, but you are using it in the Pages Router.
+ | Learn more: https://nextjs.org/docs/app/building-your-application/rendering/server-components
+ |
+ |
+ ,-[input.js:1:1]
+ 1 | import { unstable_prefetch } from 'next/cache'
+ : ^^^^^^^^^^^^^^^^^
+ `----
diff --git a/docs/01-app/02-guides/migrating/app-router-migration.mdx b/docs/01-app/02-guides/migrating/app-router-migration.mdx
index ef794a345737..5cdcb9a33200 100644
--- a/docs/01-app/02-guides/migrating/app-router-migration.mdx
+++ b/docs/01-app/02-guides/migrating/app-router-migration.mdx
@@ -108,7 +108,7 @@ To upgrade your links to Next.js 13, you can use the [`new-link` codemod](/docs/
The behavior of [`next/script`](/docs/app/api-reference/components/script) has been updated to support both `pages` and `app`, but some changes need to be made to ensure a smooth migration:
-- Move any `beforeInteractive` scripts you previously included in `_document.js` to the root layout file (`app/layout.tsx`).
+- Move any `beforeInteractive` scripts you previously included in `_document.js` to a [root layout](/docs/app/api-reference/file-conventions/layout#root-layout), such as `app/layout.tsx` or `app/[locale]/layout.tsx`.
- The experimental `worker` strategy does not yet work in `app` and scripts denoted with this strategy will either have to be removed or modified to use a different strategy (e.g. `lazyOnload`).
- `onLoad`, `onReady`, and `onError` handlers will not work in Server Components so make sure to move them to a [Client Component](/docs/app/getting-started/server-and-client-components) or remove them altogether.
diff --git a/docs/01-app/03-api-reference/02-components/script.mdx b/docs/01-app/03-api-reference/02-components/script.mdx
index 432cf82941ff..226031960ece 100644
--- a/docs/01-app/03-api-reference/02-components/script.mdx
+++ b/docs/01-app/03-api-reference/02-components/script.mdx
@@ -72,7 +72,7 @@ Scripts denoted with this strategy are preloaded and fetched before any first-pa
-`beforeInteractive` scripts must be placed inside the root layout (`app/layout.tsx`) and are designed to load scripts that are needed by the entire site (i.e. the script will load when any page in the application has been loaded server-side).
+Scripts with the `beforeInteractive` strategy must be placed inside a [root layout](/docs/app/api-reference/file-conventions/layout#root-layout), such as `app/layout.tsx` or `app/[locale]/layout.tsx`, and are designed to load scripts that are needed by the entire site (i.e. the script will load when any page in the application has been loaded server-side).
@@ -155,6 +155,12 @@ export default function Document() {
> **Good to know**: Scripts with `beforeInteractive` will always be injected inside the `head` of the HTML document regardless of where it's placed in the component.
+
+
+> **Good to know**: These scripts run once per document load. A client-side navigation does not run them again, including one that only changes a root param, such as `/en` to `/fi`, since the root layout stays the same.
+
+
+
Some examples of scripts that should be fetched as soon as possible with `beforeInteractive` include:
- Bot detectors
diff --git a/docs/01-app/03-api-reference/04-functions/cacheLife.mdx b/docs/01-app/03-api-reference/04-functions/cacheLife.mdx
index b04d33e7fe4a..c989c67cd26e 100644
--- a/docs/01-app/03-api-reference/04-functions/cacheLife.mdx
+++ b/docs/01-app/03-api-reference/04-functions/cacheLife.mdx
@@ -265,7 +265,7 @@ A short cache lifetime changes where the cached content can be delivered from:
- **`revalidate` of `0`, or `expire` under 5 minutes**: excluded from prerenders, becoming a "dynamic hole" resolved at request time.
- **`stale` under 30 seconds**: excluded from prerenders, because a prefetch would expire before the user could click.
-- **`stale` from 30 seconds up to 5 minutes**: included in prerenders, but excluded from the route's [App Shell](/docs/app/glossary#app-shell).
+- **`stale` of at least 30 seconds but under 5 minutes**: included in prerenders, but excluded from the route's [App Shell](/docs/app/glossary#app-shell).
Of the presets, only `seconds` falls under any of these thresholds: its `expire` of 1 minute excludes it from prerenders.
diff --git a/docs/01-app/03-api-reference/07-adapters/index.mdx b/docs/01-app/03-api-reference/07-adapters/index.mdx
index ad82f66b1ff1..72c66258b7c0 100644
--- a/docs/01-app/03-api-reference/07-adapters/index.mdx
+++ b/docs/01-app/03-api-reference/07-adapters/index.mdx
@@ -4,35 +4,3 @@ description: Build deployment adapters for Next.js platforms and infrastructure.
---
Use this section to build and validate deployment adapters that integrate with the Next.js build and runtime model.
-
-
-
-- [Configuration](/docs/app/api-reference/adapters/configuration)
-- [Creating an Adapter](/docs/app/api-reference/adapters/creating-an-adapter)
-- [API Reference](/docs/app/api-reference/adapters/api-reference)
-- [Testing Adapters](/docs/app/api-reference/adapters/testing-adapters)
-- [Routing with `@next/routing`](/docs/app/api-reference/adapters/routing-with-next-routing)
-- [Implementing PPR in an Adapter](/docs/app/api-reference/adapters/implementing-ppr-in-an-adapter)
-- [Runtime Integration](/docs/app/api-reference/adapters/runtime-integration)
-- [Invoking Entrypoints](/docs/app/api-reference/adapters/invoking-entrypoints)
-- [Output Types](/docs/app/api-reference/adapters/output-types)
-- [Routing Information](/docs/app/api-reference/adapters/routing-information)
-- [Use Cases](/docs/app/api-reference/adapters/use-cases)
-- [Supporting Immutable Static Assets](/docs/app/api-reference/adapters/immutable-static-assets)
-
-
-
-
-
-- [Configuration](/docs/pages/api-reference/adapters/configuration)
-- [Creating an Adapter](/docs/pages/api-reference/adapters/creating-an-adapter)
-- [API Reference](/docs/pages/api-reference/adapters/api-reference)
-- [Testing Adapters](/docs/pages/api-reference/adapters/testing-adapters)
-- [Routing with `@next/routing`](/docs/pages/api-reference/adapters/routing-with-next-routing)
-- [Runtime Integration](/docs/pages/api-reference/adapters/runtime-integration)
-- [Invoking Entrypoints](/docs/pages/api-reference/adapters/invoking-entrypoints)
-- [Output Types](/docs/pages/api-reference/adapters/output-types)
-- [Routing Information](/docs/pages/api-reference/adapters/routing-information)
-- [Use Cases](/docs/pages/api-reference/adapters/use-cases)
-
-
diff --git a/errors/no-before-interactive-script-outside-document.mdx b/errors/no-before-interactive-script-outside-document.mdx
index 68965e6758d6..c771e50ef10e 100644
--- a/errors/no-before-interactive-script-outside-document.mdx
+++ b/errors/no-before-interactive-script-outside-document.mdx
@@ -2,17 +2,17 @@
title: No Before Interactive Script Outside Document
---
-> Prevent usage of `next/script`'s `beforeInteractive` strategy outside of `app/layout.jsx` or `pages/_document.js`.
+> Prevent usage of `next/script`'s `beforeInteractive` strategy outside of a root layout or `pages/_document.js`.
## Why This Error Occurred
-You cannot use the `next/script` component with the `beforeInteractive` strategy outside `app/layout.jsx` or `pages/_document.js`. That's because `beforeInteractive` strategy only works inside **`app/layout.jsx`** or **`pages/_document.js`** and is designed to load scripts that are needed by the entire site (i.e. the script will load when any page in the application has been loaded server-side).
+You cannot use the `next/script` component with the `beforeInteractive` strategy outside a root layout or `pages/_document.js`. That's because `beforeInteractive` strategy only works inside a **root layout** or **`pages/_document.js`** and is designed to load scripts that are needed by the entire site (i.e. the script will load when any page in the application has been loaded server-side).
## Possible Ways to Fix It
### App Router
-If you want a global script, and you are using the App Router, move the script inside `app/layout.jsx`.
+If you want a global script, and you are using the App Router, move the script inside a [root layout](/docs/app/api-reference/file-conventions/layout#root-layout), any layout without a `layout.js` above it.
```jsx filename="app/layout.jsx"
import Script from 'next/script'
diff --git a/lerna.json b/lerna.json
index 11b86399f1b5..fc4c9dc558e1 100644
--- a/lerna.json
+++ b/lerna.json
@@ -15,5 +15,5 @@
"registry": "https://registry.npmjs.org/"
}
},
- "version": "16.3.1-canary.26"
+ "version": "16.4.0-canary.0"
}
\ No newline at end of file
diff --git a/packages/create-next-app/package.json b/packages/create-next-app/package.json
index 869ce76e9229..25659c2a969b 100644
--- a/packages/create-next-app/package.json
+++ b/packages/create-next-app/package.json
@@ -1,6 +1,6 @@
{
"name": "create-next-app",
- "version": "16.3.1-canary.26",
+ "version": "16.4.0-canary.0",
"keywords": [
"react",
"next",
diff --git a/packages/devlow-bench/package.json b/packages/devlow-bench/package.json
index dd2d9805f14b..a8bb0272abe9 100644
--- a/packages/devlow-bench/package.json
+++ b/packages/devlow-bench/package.json
@@ -1,7 +1,7 @@
{
"name": "@vercel/devlow-bench",
"private": true,
- "version": "16.3.1-canary.26",
+ "version": "16.4.0-canary.0",
"description": "Benchmarking tool for the developer workflow",
"repository": {
"type": "git",
diff --git a/packages/eslint-config-next/package.json b/packages/eslint-config-next/package.json
index 6a7e604efc7a..3ec4cb0e06e5 100644
--- a/packages/eslint-config-next/package.json
+++ b/packages/eslint-config-next/package.json
@@ -1,6 +1,6 @@
{
"name": "eslint-config-next",
- "version": "16.3.1-canary.26",
+ "version": "16.4.0-canary.0",
"description": "ESLint configuration used by Next.js.",
"license": "MIT",
"repository": {
@@ -12,7 +12,7 @@
"dist"
],
"dependencies": {
- "@next/eslint-plugin-next": "16.3.1-canary.26",
+ "@next/eslint-plugin-next": "16.4.0-canary.0",
"eslint-import-resolver-node": "^0.3.6",
"eslint-import-resolver-typescript": "^3.5.2",
"eslint-plugin-import": "^2.32.0",
diff --git a/packages/eslint-plugin-internal/package.json b/packages/eslint-plugin-internal/package.json
index c15546e2da98..c2cc9b692689 100644
--- a/packages/eslint-plugin-internal/package.json
+++ b/packages/eslint-plugin-internal/package.json
@@ -1,7 +1,7 @@
{
"name": "@next/eslint-plugin-internal",
"private": true,
- "version": "16.3.1-canary.26",
+ "version": "16.4.0-canary.0",
"description": "ESLint plugin for working on Next.js.",
"exports": {
".": "./src/eslint-plugin-internal.js"
diff --git a/packages/eslint-plugin-next/package.json b/packages/eslint-plugin-next/package.json
index 0960d029f5bc..ad6f70a3f860 100644
--- a/packages/eslint-plugin-next/package.json
+++ b/packages/eslint-plugin-next/package.json
@@ -1,6 +1,6 @@
{
"name": "@next/eslint-plugin-next",
- "version": "16.3.1-canary.26",
+ "version": "16.4.0-canary.0",
"description": "ESLint plugin for Next.js.",
"main": "dist/index.js",
"types": "dist/index.d.ts",
diff --git a/packages/font/package.json b/packages/font/package.json
index 7abb3f473558..9bd75a77ca93 100644
--- a/packages/font/package.json
+++ b/packages/font/package.json
@@ -1,7 +1,7 @@
{
"name": "@next/font",
"private": true,
- "version": "16.3.1-canary.26",
+ "version": "16.4.0-canary.0",
"repository": {
"url": "vercel/next.js",
"directory": "packages/font"
diff --git a/packages/next-bundle-analyzer/package.json b/packages/next-bundle-analyzer/package.json
index 5dc4875b6f87..f94720d4e020 100644
--- a/packages/next-bundle-analyzer/package.json
+++ b/packages/next-bundle-analyzer/package.json
@@ -1,6 +1,6 @@
{
"name": "@next/bundle-analyzer",
- "version": "16.3.1-canary.26",
+ "version": "16.4.0-canary.0",
"main": "index.js",
"types": "index.d.ts",
"license": "MIT",
diff --git a/packages/next-codemod/package.json b/packages/next-codemod/package.json
index 4c97378be04f..2cd6f558df73 100644
--- a/packages/next-codemod/package.json
+++ b/packages/next-codemod/package.json
@@ -1,6 +1,6 @@
{
"name": "@next/codemod",
- "version": "16.3.1-canary.26",
+ "version": "16.4.0-canary.0",
"license": "MIT",
"repository": {
"type": "git",
diff --git a/packages/next-env/package.json b/packages/next-env/package.json
index 3cfd563db0fc..31906af5269a 100644
--- a/packages/next-env/package.json
+++ b/packages/next-env/package.json
@@ -1,6 +1,6 @@
{
"name": "@next/env",
- "version": "16.3.1-canary.26",
+ "version": "16.4.0-canary.0",
"keywords": [
"react",
"next",
diff --git a/packages/next-mdx/package.json b/packages/next-mdx/package.json
index eac8d15d5070..6165b322d7f0 100644
--- a/packages/next-mdx/package.json
+++ b/packages/next-mdx/package.json
@@ -1,6 +1,6 @@
{
"name": "@next/mdx",
- "version": "16.3.1-canary.26",
+ "version": "16.4.0-canary.0",
"main": "index.js",
"license": "MIT",
"repository": {
diff --git a/packages/next-playwright/package.json b/packages/next-playwright/package.json
index 57514beb1f05..0fe6e3c379fa 100644
--- a/packages/next-playwright/package.json
+++ b/packages/next-playwright/package.json
@@ -1,6 +1,6 @@
{
"name": "@next/playwright",
- "version": "16.3.1-canary.26",
+ "version": "16.4.0-canary.0",
"repository": {
"url": "vercel/next.js",
"directory": "packages/next-playwright"
diff --git a/packages/next-plugin-storybook/package.json b/packages/next-plugin-storybook/package.json
index 68ba66c5e341..1c01ba6fbdd1 100644
--- a/packages/next-plugin-storybook/package.json
+++ b/packages/next-plugin-storybook/package.json
@@ -1,6 +1,6 @@
{
"name": "@next/plugin-storybook",
- "version": "16.3.1-canary.26",
+ "version": "16.4.0-canary.0",
"repository": {
"url": "vercel/next.js",
"directory": "packages/next-plugin-storybook"
diff --git a/packages/next-polyfill-module/package.json b/packages/next-polyfill-module/package.json
index c09840f99d73..76f382f51a1c 100644
--- a/packages/next-polyfill-module/package.json
+++ b/packages/next-polyfill-module/package.json
@@ -1,6 +1,6 @@
{
"name": "@next/polyfill-module",
- "version": "16.3.1-canary.26",
+ "version": "16.4.0-canary.0",
"description": "A standard library polyfill for ES Modules supporting browsers (Edge 16+, Firefox 60+, Chrome 61+, Safari 10.1+)",
"main": "dist/polyfill-module.js",
"license": "MIT",
diff --git a/packages/next-polyfill-nomodule/package.json b/packages/next-polyfill-nomodule/package.json
index d7629d67a3d7..74db02b6d41e 100644
--- a/packages/next-polyfill-nomodule/package.json
+++ b/packages/next-polyfill-nomodule/package.json
@@ -1,6 +1,6 @@
{
"name": "@next/polyfill-nomodule",
- "version": "16.3.1-canary.26",
+ "version": "16.4.0-canary.0",
"description": "A polyfill for non-dead, nomodule browsers.",
"main": "dist/polyfill-nomodule.js",
"license": "MIT",
diff --git a/packages/next-routing/package.json b/packages/next-routing/package.json
index d1dbef2e96b7..ad578bff1f1e 100644
--- a/packages/next-routing/package.json
+++ b/packages/next-routing/package.json
@@ -1,6 +1,6 @@
{
"name": "@next/routing",
- "version": "16.3.1-canary.26",
+ "version": "16.4.0-canary.0",
"keywords": [
"react",
"next",
diff --git a/packages/next-rspack/package.json b/packages/next-rspack/package.json
index 6b4cf0021831..92a767e099de 100644
--- a/packages/next-rspack/package.json
+++ b/packages/next-rspack/package.json
@@ -1,6 +1,6 @@
{
"name": "next-rspack",
- "version": "16.3.1-canary.26",
+ "version": "16.4.0-canary.0",
"repository": {
"url": "vercel/next.js",
"directory": "packages/next-rspack"
diff --git a/packages/next-swc/package.json b/packages/next-swc/package.json
index 4474bdc1285d..922ac5df7386 100644
--- a/packages/next-swc/package.json
+++ b/packages/next-swc/package.json
@@ -1,6 +1,6 @@
{
"name": "@next/swc",
- "version": "16.3.1-canary.26",
+ "version": "16.4.0-canary.0",
"private": true,
"files": [
"native/"
diff --git a/packages/next/cache.d.ts b/packages/next/cache.d.ts
index b52685ac04de..3a3750edfb8e 100644
--- a/packages/next/cache.d.ts
+++ b/packages/next/cache.d.ts
@@ -156,3 +156,4 @@ export const unstable_cacheLife: typeof cacheLife
export const unstable_cacheTag: typeof cacheTag
export { unstable_navigation } from 'next/dist/server/request/cache-stages'
+export { unstable_prefetch } from 'next/dist/server/request/cache-stages'
diff --git a/packages/next/cache.js b/packages/next/cache.js
index 97c603e80671..3a205e88e92c 100644
--- a/packages/next/cache.js
+++ b/packages/next/cache.js
@@ -26,6 +26,7 @@ if (process.env.NEXT_RUNTIME === '') {
cacheLife: notAvailableInClient('cacheLife'),
cacheTag: notAvailableInClient('cacheTag'),
unstable_navigation: notAvailableInClient('unstable_navigation'),
+ unstable_prefetch: notAvailableInClient('unstable_prefetch'),
}
} else {
// Keep server requires in this branch so browser builds can DCE them.
@@ -52,6 +53,8 @@ if (process.env.NEXT_RUNTIME === '') {
cacheTag: require('next/dist/server/use-cache/cache-tag').cacheTag,
unstable_navigation: require('next/dist/server/request/cache-stages')
.unstable_navigation,
+ unstable_prefetch: require('next/dist/server/request/cache-stages')
+ .unstable_prefetch,
}
}
@@ -99,3 +102,4 @@ exports.unstable_cacheTag = cacheExports.unstable_cacheTag
exports.refresh = cacheExports.refresh
exports.io = cacheExports.io
exports.unstable_navigation = cacheExports.unstable_navigation
+exports.unstable_prefetch = cacheExports.unstable_prefetch
diff --git a/packages/next/errors.json b/packages/next/errors.json
index c653ca8a00b2..6ab0ba34ae0c 100644
--- a/packages/next/errors.json
+++ b/packages/next/errors.json
@@ -1482,5 +1482,13 @@
"1481": "Route %s used \\`unstable_navigation()\\`, which requires Cache Components to be enabled. Learn more: https://nextjs.org/docs/app/api-reference/config/next-config-js/cacheComponents",
"1482": "Route %s used \\`unstable_navigation()\\` inside \\`after()\\` while rendering. The \\`unstable_navigation()\\` function is used to indicate the subsequent code must only run during an actual navigation, but \\`after()\\` executes after the request, so this function is not allowed in this scope. See more info here: https://nextjs.org/docs/app/api-reference/functions/after",
"1483": "Route %s used \\`unstable_navigation()\\` inside \"use cache: private\". This is not currently supported. Instead, move the \"use cache\" directive to a function that's called below \\`await unstable_navigation()\\`, so that the cached content is deferred to the navigation without caching the stage boundary itself. See more info here: https://nextjs.org/docs/messages/next-request-in-use-cache",
- "1484": "Route %s used \\`unstable_navigation()\\` inside \"use cache\". This is not currently supported. Instead, move the \"use cache\" directive to a function that's called below \\`await unstable_navigation()\\`, so that the cached content is deferred to the navigation without caching the stage boundary itself. See more info here: https://nextjs.org/docs/messages/next-request-in-use-cache"
+ "1484": "Route %s used \\`unstable_navigation()\\` inside \"use cache\". This is not currently supported. Instead, move the \"use cache\" directive to a function that's called below \\`await unstable_navigation()\\`, so that the cached content is deferred to the navigation without caching the stage boundary itself. See more info here: https://nextjs.org/docs/messages/next-request-in-use-cache",
+ "1485": "\"unstable_prefetch() is not implemented yet.\"",
+ "1486": "Route %s used \\`unstable_prefetch()\\` inside \"use cache\". This is not currently supported. Instead, move the \"use cache\" directive to a function that's called below \\`await unstable_prefetch()\\`, so that the cached content is deferred to the prefetch without caching the stage boundary itself. See more info here: https://nextjs.org/docs/messages/next-request-in-use-cache",
+ "1487": "`unstable_prefetch` must not be used within a Client Component. Next.js should be preventing `unstable_prefetch` from being included in Client Components statically, but did not in this case.",
+ "1488": "Route %s used \\`unstable_prefetch()\\` inside \\`generateStaticParams\\`. This is not supported because \\`generateStaticParams\\` runs at build time without a prefetch. Read more: https://nextjs.org/docs/messages/next-dynamic-api-wrong-context",
+ "1489": "Route %s used \\`unstable_prefetch()\\` inside a function cached with \\`unstable_cache()\\`. The \\`unstable_prefetch()\\` function is used to indicate the subsequent code must not run in the app shell, but \\`unstable_cache()\\` caches must be able to be produced before a prefetch, so this function is not allowed in this scope. See more info here: https://nextjs.org/docs/app/api-reference/functions/unstable_cache",
+ "1490": "Route %s used \\`unstable_prefetch()\\` inside \\`after()\\` while rendering. The \\`unstable_prefetch()\\` function is used to indicate the subsequent code must not run in the app shell, but \\`after()\\` executes after the request, so this function is not allowed in this scope. See more info here: https://nextjs.org/docs/app/api-reference/functions/after",
+ "1491": "Route %s used \\`unstable_prefetch()\\`, which requires Cache Components to be enabled. Learn more: https://nextjs.org/docs/app/api-reference/config/next-config-js/cacheComponents",
+ "1492": "Route %s used \\`unstable_prefetch()\\` inside \"use cache: private\". This is not currently supported. Instead, move the \"use cache\" directive to a function that's called below \\`await unstable_prefetch()\\`, so that the cached content is deferred to the prefetch without caching the stage boundary itself. See more info here: https://nextjs.org/docs/messages/next-request-in-use-cache"
}
diff --git a/packages/next/package.json b/packages/next/package.json
index 02846e46e059..025c161b891a 100644
--- a/packages/next/package.json
+++ b/packages/next/package.json
@@ -1,6 +1,6 @@
{
"name": "next",
- "version": "16.3.1-canary.26",
+ "version": "16.4.0-canary.0",
"description": "The React Framework",
"main": "./dist/server/next.js",
"license": "MIT",
@@ -100,7 +100,7 @@
]
},
"dependencies": {
- "@next/env": "16.3.1-canary.26",
+ "@next/env": "16.4.0-canary.0",
"@swc/helpers": "0.5.23",
"baseline-browser-mapping": "^2.9.19",
"caniuse-lite": "^1.0.30001579",
@@ -164,11 +164,11 @@
"@modelcontextprotocol/sdk": "1.18.1",
"@mswjs/interceptors": "0.42.0",
"@napi-rs/triples": "1.2.0",
- "@next/font": "16.3.1-canary.26",
- "@next/polyfill-module": "16.3.1-canary.26",
- "@next/polyfill-nomodule": "16.3.1-canary.26",
- "@next/react-refresh-utils": "16.3.1-canary.26",
- "@next/swc": "16.3.1-canary.26",
+ "@next/font": "16.4.0-canary.0",
+ "@next/polyfill-module": "16.4.0-canary.0",
+ "@next/polyfill-nomodule": "16.4.0-canary.0",
+ "@next/react-refresh-utils": "16.4.0-canary.0",
+ "@next/swc": "16.4.0-canary.0",
"@opentelemetry/api": "1.6.0",
"@playwright/test": "1.61.0",
"@rspack/core": "1.6.7",
diff --git a/packages/next/src/build/define-env.ts b/packages/next/src/build/define-env.ts
index ebedb611ac56..556439d2c5bf 100644
--- a/packages/next/src/build/define-env.ts
+++ b/packages/next/src/build/define-env.ts
@@ -172,6 +172,9 @@ export function getDefineEnv({
'process.env.__NEXT_TURBOPACK_SHARED_RUNTIME': Boolean(
config.experimental.turbopackSharedRuntime
),
+ 'process.env.__NEXT_TURBOPACK_CHUNK_UPDATE_LISTENERS_GLOBAL': `${
+ config.turbopack?.chunkLoadingGlobal ?? 'TURBOPACK'
+ }_CHUNK_UPDATE_LISTENERS`,
'process.env.__NEXT_CACHE_COMPONENTS': isCacheComponentsEnabled,
'process.env.__NEXT_EXPERIMENTAL_CACHED_NAVIGATIONS': Boolean(
config.experimental.cachedNavigations
diff --git a/packages/next/src/client/dev/hot-reloader/app/web-socket.ts b/packages/next/src/client/dev/hot-reloader/app/web-socket.ts
index 8ad232bc747f..b3534e799f6a 100644
--- a/packages/next/src/client/dev/hot-reloader/app/web-socket.ts
+++ b/packages/next/src/client/dev/hot-reloader/app/web-socket.ts
@@ -201,6 +201,8 @@ export function createProcessTurbopackMessage(
},
sendMessage,
onUpdateError: (err: unknown) => performFullReload(err, sendMessage),
+ chunkUpdateListenersGlobal:
+ process.env.__NEXT_TURBOPACK_CHUNK_UPDATE_LISTENERS_GLOBAL!,
})
})
diff --git a/packages/next/src/client/next-dev-turbopack.ts b/packages/next/src/client/next-dev-turbopack.ts
index f8c47425f04c..bb887e210736 100644
--- a/packages/next/src/client/next-dev-turbopack.ts
+++ b/packages/next/src/client/next-dev-turbopack.ts
@@ -48,6 +48,8 @@ initialize({
},
sendMessage: devClient.sendTurbopackMessage,
onUpdateError: devClient.handleUpdateError,
+ chunkUpdateListenersGlobal:
+ process.env.__NEXT_TURBOPACK_CHUNK_UPDATE_LISTENERS_GLOBAL!,
})
return pageBootstrap(assetPrefix)
diff --git a/packages/next/src/server/lib/router-utils/cache-life-type-utils.test.ts b/packages/next/src/server/lib/router-utils/cache-life-type-utils.test.ts
index 6d1c22e7cca3..f3164893ede8 100644
--- a/packages/next/src/server/lib/router-utils/cache-life-type-utils.test.ts
+++ b/packages/next/src/server/lib/router-utils/cache-life-type-utils.test.ts
@@ -31,6 +31,7 @@ describe('cache-life-type-utils', () => {
export { unstable_noStore } from 'next/dist/server/web/spec-extension/unstable-no-store'
export { io } from 'next/dist/server/request/io'
export { unstable_navigation } from 'next/dist/server/request/cache-stages'
+ export { unstable_prefetch } from 'next/dist/server/request/cache-stages'
/**
@@ -190,6 +191,7 @@ describe('cache-life-type-utils', () => {
export { unstable_noStore } from 'next/dist/server/web/spec-extension/unstable-no-store'
export { io } from 'next/dist/server/request/io'
export { unstable_navigation } from 'next/dist/server/request/cache-stages'
+ export { unstable_prefetch } from 'next/dist/server/request/cache-stages'
/**
@@ -269,6 +271,7 @@ describe('cache-life-type-utils', () => {
export { unstable_noStore } from 'next/dist/server/web/spec-extension/unstable-no-store'
export { io } from 'next/dist/server/request/io'
export { unstable_navigation } from 'next/dist/server/request/cache-stages'
+ export { unstable_prefetch } from 'next/dist/server/request/cache-stages'
/**
@@ -347,6 +350,7 @@ describe('cache-life-type-utils', () => {
export { unstable_noStore } from 'next/dist/server/web/spec-extension/unstable-no-store'
export { io } from 'next/dist/server/request/io'
export { unstable_navigation } from 'next/dist/server/request/cache-stages'
+ export { unstable_prefetch } from 'next/dist/server/request/cache-stages'
/**
@@ -426,6 +430,7 @@ describe('cache-life-type-utils', () => {
export { unstable_noStore } from 'next/dist/server/web/spec-extension/unstable-no-store'
export { io } from 'next/dist/server/request/io'
export { unstable_navigation } from 'next/dist/server/request/cache-stages'
+ export { unstable_prefetch } from 'next/dist/server/request/cache-stages'
/**
@@ -509,6 +514,7 @@ describe('cache-life-type-utils', () => {
export { unstable_noStore } from 'next/dist/server/web/spec-extension/unstable-no-store'
export { io } from 'next/dist/server/request/io'
export { unstable_navigation } from 'next/dist/server/request/cache-stages'
+ export { unstable_prefetch } from 'next/dist/server/request/cache-stages'
/**
diff --git a/packages/next/src/server/lib/router-utils/cache-life-type-utils.ts b/packages/next/src/server/lib/router-utils/cache-life-type-utils.ts
index 41b56de28848..8f4e39d0a757 100644
--- a/packages/next/src/server/lib/router-utils/cache-life-type-utils.ts
+++ b/packages/next/src/server/lib/router-utils/cache-life-type-utils.ts
@@ -179,6 +179,7 @@ declare module 'next/cache' {
export { unstable_noStore } from 'next/dist/server/web/spec-extension/unstable-no-store'
export { io } from 'next/dist/server/request/io'
export { unstable_navigation } from 'next/dist/server/request/cache-stages'
+ export { unstable_prefetch } from 'next/dist/server/request/cache-stages'
${overloads}
diff --git a/packages/next/src/server/request/cache-stages.ts b/packages/next/src/server/request/cache-stages.ts
index 6c0c9b72c2ad..b1ebfb99265e 100644
--- a/packages/next/src/server/request/cache-stages.ts
+++ b/packages/next/src/server/request/cache-stages.ts
@@ -5,12 +5,150 @@ import {
} from '../app-render/work-unit-async-storage.external'
import {
applyOwnerStack,
+ RENDER_STAGES_BY_DATA_KIND,
trackIncompatibleShellContent,
} from '../dynamic-rendering-utils'
import { isRequestApiAllowedInCurrentPhase } from './utils'
import { InvariantError } from '../../shared/lib/invariant-error'
import { RenderStage } from '../app-render/staged-rendering'
+/**
+ * When `partialPrefetching` is enabled, this function allows you to indicate
+ * that the subsequent code should be excluded from the shell. It will be deferred until
+ * a prefetch (i.e. when using ``) or a navigation.
+ *
+ * It has no effect during static prerendering — static output is computed
+ * once and shared across many clients, so there's no per-request cost to
+ * save — and no effect on the initial load of a page.
+ *
+ * Unlike `connection()`, it does not mark the subtree as request-dependent —
+ * content below `await unstable_prefetch()` remains fully cacheable.
+ */
+export function unstable_prefetch(): Promise {
+ const workStore = workAsyncStorage.getStore()
+ const workUnitStore = workUnitAsyncStorage.getStore()
+
+ if (!workStore || !workUnitStore) {
+ const callingExpression = 'unstable_prefetch'
+ throwForMissingRequestStore(callingExpression)
+ }
+ if (!process.env.__NEXT_CACHE_COMPONENTS) {
+ throw new Error(
+ `Route ${workStore.route} used \`unstable_prefetch()\`, which requires Cache Components to be enabled. Learn more: https://nextjs.org/docs/app/api-reference/config/next-config-js/cacheComponents`
+ )
+ }
+
+ if (!isRequestApiAllowedInCurrentPhase(workUnitStore)) {
+ throw new Error(
+ `Route ${workStore.route} used \`unstable_prefetch()\` inside \`after()\` while rendering. The \`unstable_prefetch()\` function is used to indicate the subsequent code must not run in the app shell, but \`after()\` executes after the request, so this function is not allowed in this scope. See more info here: https://nextjs.org/docs/app/api-reference/functions/after`
+ )
+ }
+
+ switch (workUnitStore.type) {
+ case 'prerender': {
+ // Content below `prefetch()` is excluded from the shell, but it's
+ // deliberately included in the static output (and thus in static
+ // prefetches), so we only delay it until the static prefetch stage.
+ const { stagedRendering } = workUnitStore
+ if (!stagedRendering) {
+ // Prospective prerender
+ return Promise.resolve(undefined)
+ } else {
+ // Final prerender
+ return stagedRendering.delayUntilStage(
+ RENDER_STAGES_BY_DATA_KIND.staticLinkData,
+ 'unstable_prefetch',
+ undefined
+ )
+ }
+ }
+ case 'prerender-runtime': {
+ // In a shell render, prefetch() doesn't resolve, because it doesn't reach
+ // `Runtime`. It'll resolve in a runtime prefetch, and in a runtime
+ // prerender produced during a navigation.
+ // Note that this does not mark the subtree as dynamic -- content guarded by
+ // prefetch() is still considered cacheable.
+ const { stagedRendering } = workUnitStore
+ if (!stagedRendering) {
+ // Prospective prerender
+ return Promise.resolve(undefined)
+ } else {
+ // Final prerender
+ return stagedRendering.delayUntilStage(
+ RENDER_STAGES_BY_DATA_KIND.runtimeLinkData,
+ 'unstable_prefetch',
+ undefined
+ )
+ }
+ }
+ case 'request': {
+ const { stagedRendering } = workUnitStore
+ if (stagedRendering) {
+ // We can either recover a static shell or a runtime shell, but not both.
+ trackIncompatibleShellContent(workUnitStore)
+ const stage = workUnitStore.needsAppShell
+ ? RENDER_STAGES_BY_DATA_KIND.runtimeLinkData // Match the timing of 'prerender-runtime'.
+ : RENDER_STAGES_BY_DATA_KIND.staticLinkData // Match the timing of 'prerender'.
+
+ return stagedRendering.delayUntilStage(
+ stage,
+ 'unstable_prefetch',
+ undefined
+ )
+ }
+ return Promise.resolve(undefined)
+ }
+
+ case 'cache': {
+ const error = new Error(
+ `Route ${workStore.route} used \`unstable_prefetch()\` inside "use cache". This is not currently supported. Instead, move the "use cache" directive to a function that's called below \`await unstable_prefetch()\`, so that the cached content is deferred to the prefetch without caching the stage boundary itself. See more info here: https://nextjs.org/docs/messages/next-request-in-use-cache`
+ )
+ Error.captureStackTrace(error, unstable_prefetch)
+ applyOwnerStack(error)
+ workStore.invalidDynamicUsageError ??= error
+ throw error
+ }
+ case 'private-cache': {
+ const error = new Error(
+ `Route ${workStore.route} used \`unstable_prefetch()\` inside "use cache: private". This is not currently supported. Instead, move the "use cache" directive to a function that's called below \`await unstable_prefetch()\`, so that the cached content is deferred to the prefetch without caching the stage boundary itself. See more info here: https://nextjs.org/docs/messages/next-request-in-use-cache`
+ )
+ Error.captureStackTrace(error, unstable_prefetch)
+ applyOwnerStack(error)
+ workStore.invalidDynamicUsageError ??= error
+ throw error
+ }
+ case 'unstable-cache': {
+ throw new Error(
+ `Route ${workStore.route} used \`unstable_prefetch()\` inside a function cached with \`unstable_cache()\`. The \`unstable_prefetch()\` function is used to indicate the subsequent code must not run in the app shell, but \`unstable_cache()\` caches must be able to be produced before a prefetch, so this function is not allowed in this scope. See more info here: https://nextjs.org/docs/app/api-reference/functions/unstable_cache`
+ )
+ }
+ case 'generate-static-params': {
+ throw new Error(
+ `Route ${workStore.route} used \`unstable_prefetch()\` inside \`generateStaticParams\`. This is not supported because \`generateStaticParams\` runs at build time without a prefetch. Read more: https://nextjs.org/docs/messages/next-dynamic-api-wrong-context`
+ )
+ }
+ case 'prerender-client':
+ case 'validation-client': {
+ const exportName = '`unstable_prefetch`'
+ throw new InvariantError(
+ `${exportName} must not be used within a Client Component. Next.js should be preventing ${exportName} from being included in Client Components statically, but did not in this case.`
+ )
+ }
+ case 'prerender-legacy': {
+ // NOTE: Should not be reachable, because we don't use this mode in cacheComponents,
+ // which we require at the top
+ throw new Error(
+ `Route ${workStore.route} used \`unstable_prefetch()\`, which requires Cache Components to be enabled. Learn more: https://nextjs.org/docs/app/api-reference/config/next-config-js/cacheComponents`
+ )
+ }
+
+ default: {
+ workUnitStore satisfies never
+ return Promise.resolve(undefined)
+ }
+ }
+}
+
/**
* This function allows you to indicate that the subsequent code should be
* deferred to the actual navigation instead of rendering during a runtime
diff --git a/packages/react-refresh-utils/package.json b/packages/react-refresh-utils/package.json
index db5970d0938c..0f25c6edd49d 100644
--- a/packages/react-refresh-utils/package.json
+++ b/packages/react-refresh-utils/package.json
@@ -1,6 +1,6 @@
{
"name": "@next/react-refresh-utils",
- "version": "16.3.1-canary.26",
+ "version": "16.4.0-canary.0",
"description": "An experimental package providing utilities for React Refresh.",
"repository": {
"url": "vercel/next.js",
diff --git a/packages/third-parties/package.json b/packages/third-parties/package.json
index a5f9b4ee844c..e909ad8ca342 100644
--- a/packages/third-parties/package.json
+++ b/packages/third-parties/package.json
@@ -1,6 +1,6 @@
{
"name": "@next/third-parties",
- "version": "16.3.1-canary.26",
+ "version": "16.4.0-canary.0",
"repository": {
"url": "vercel/next.js",
"directory": "packages/third-parties"
@@ -26,7 +26,7 @@
"third-party-capital": "1.0.20"
},
"devDependencies": {
- "next": "16.3.1-canary.26",
+ "next": "16.4.0-canary.0",
"outdent": "0.8.0",
"prettier": "2.5.1",
"typescript": "6.0.2"
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index a483fe7d014f..5d1ebfcb597b 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -1024,7 +1024,7 @@ importers:
packages/eslint-config-next:
dependencies:
'@next/eslint-plugin-next':
- specifier: 16.3.1-canary.26
+ specifier: 16.4.0-canary.0
version: link:../eslint-plugin-next
eslint:
specifier: '>=9.0.0'
@@ -1107,7 +1107,7 @@ importers:
packages/next:
dependencies:
'@next/env':
- specifier: 16.3.1-canary.26
+ specifier: 16.4.0-canary.0
version: link:../next-env
'@swc/helpers':
specifier: 0.5.23
@@ -1228,19 +1228,19 @@ importers:
specifier: 1.2.0
version: 1.2.0
'@next/font':
- specifier: 16.3.1-canary.26
+ specifier: 16.4.0-canary.0
version: link:../font
'@next/polyfill-module':
- specifier: 16.3.1-canary.26
+ specifier: 16.4.0-canary.0
version: link:../next-polyfill-module
'@next/polyfill-nomodule':
- specifier: 16.3.1-canary.26
+ specifier: 16.4.0-canary.0
version: link:../next-polyfill-nomodule
'@next/react-refresh-utils':
- specifier: 16.3.1-canary.26
+ specifier: 16.4.0-canary.0
version: link:../react-refresh-utils
'@next/swc':
- specifier: 16.3.1-canary.26
+ specifier: 16.4.0-canary.0
version: link:../next-swc
'@opentelemetry/api':
specifier: 1.6.0
@@ -1983,7 +1983,7 @@ importers:
version: 1.0.20
devDependencies:
next:
- specifier: 16.3.1-canary.26
+ specifier: 16.4.0-canary.0
version: link:../next
outdent:
specifier: 0.8.0
diff --git a/scripts/sync-react.js b/scripts/sync-react.js
index 1201d90cbac4..21396355f4dd 100644
--- a/scripts/sync-react.js
+++ b/scripts/sync-react.js
@@ -301,6 +301,43 @@ async function findHighestNPMReactVersion(versionLike) {
})[0]
}
+/**
+ * Assigns `actor` to the given Pull Request if they can be assigned.
+ * On scheduled runs `github.actor` often resolves to a bot like
+ * `github-actions[bot]`, which cannot be assigned. User tokens silently
+ * ignore non-assignable assignees but GitHub App tokens fail the whole
+ * request with 403, so check assignability first and skip instead.
+ * @param {InstanceType} octokit
+ * @param {string | undefined} actor
+ * @param {number} pullRequestNumber
+ */
+async function assignActorIfAssignable(octokit, actor, pullRequestNumber) {
+ if (actor === undefined) {
+ return null
+ }
+ try {
+ await octokit.rest.issues.checkUserCanBeAssigned({
+ owner: repoOwner,
+ repo: repoName,
+ assignee: actor,
+ })
+ } catch (error) {
+ if (error instanceof Error && 'status' in error && error.status === 404) {
+ console.warn(
+ `'${actor}' cannot be assigned in ${repoOwner}/${repoName}. Skipping assignment.`
+ )
+ return null
+ }
+ throw error
+ }
+ return octokit.rest.issues.addAssignees({
+ owner: repoOwner,
+ repo: repoName,
+ issue_number: pullRequestNumber,
+ assignees: [actor],
+ })
+}
+
async function main() {
const cwd = process.cwd()
const errors = []
@@ -733,15 +770,8 @@ Or run this command again without the --no-install flag to do both automatically
{ pullRequestId: pullRequest.data.node_id }
)
- await Promise.all([
- actor
- ? octokit.rest.issues.addAssignees({
- owner: repoOwner,
- repo: repoName,
- issue_number: pullRequest.data.number,
- assignees: [actor],
- })
- : Promise.resolve(),
+ const finalizeResults = await Promise.allSettled([
+ assignActorIfAssignable(octokit, actor, pullRequest.data.number),
octokit.rest.pulls.requestReviewers({
owner: repoOwner,
repo: repoName,
@@ -755,6 +785,16 @@ Or run this command again without the --no-install flag to do both automatically
labels: pullRequestLabels,
}),
])
+ const failures = finalizeResults.filter(
+ (result) => result.status === 'rejected'
+ )
+ if (failures.length > 0) {
+ // eslint-disable-next-line no-undef -- Defined in Node.js
+ throw new AggregateError(
+ failures.map((failure) => failure.reason),
+ `${failures.length} of ${finalizeResults.length} requests to finalize the Pull Request failed.`
+ )
+ }
}
console.log(prDescription)
diff --git a/test/development/acceptance-app/rsc-build-errors-poisoned-imports.test.ts b/test/development/acceptance-app/rsc-build-errors-poisoned-imports.test.ts
index d1c1265edaa6..f9cbe381682a 100644
--- a/test/development/acceptance-app/rsc-build-errors-poisoned-imports.test.ts
+++ b/test/development/acceptance-app/rsc-build-errors-poisoned-imports.test.ts
@@ -94,6 +94,12 @@ runRscBuildErrorsTests(({ next, isTurbopack }) => {
)
})
+ // In Webpack, proxy runs in the Node.js server compiler, which is also
+ // invalidated when the app route is added on demand. If the initial proxy
+ // error reaches the browser before that follow-up build, the HMR client sees
+ // an update after a runtime error and reloads, clearing the overlay. Defer
+ // that case until after hydration. Turbopack does not have this compiler
+ // invalidation race, so its proxy case covers both initial and HMR errors.
test.each([
['middleware.js', 'export function middleware() {}'],
['proxy.js', 'export function proxy() {}'],
@@ -101,6 +107,12 @@ runRscBuildErrorsTests(({ next, isTurbopack }) => {
])(
'should error when catchError from next/error is imported in %s',
async (entryFile, exportCode) => {
+ const isProxy = entryFile === 'proxy.js'
+ const deferPoisonedImport = !isTurbopack && isProxy
+ const entryContent = outdent`
+ import { catchError } from 'next/error'
+ ${exportCode}
+ `
await using sandbox = await createSandbox(
next,
new Map([
@@ -112,21 +124,29 @@ runRscBuildErrorsTests(({ next, isTurbopack }) => {
}
`,
],
- [
- entryFile,
- outdent`
- import { catchError } from 'next/error'
- ${exportCode}
- `,
- ],
+ [entryFile, deferPoisonedImport ? exportCode : entryContent],
])
)
const { session } = sandbox
- await session.waitForRedbox()
- expect(await session.getRedboxSource()).toInclude(
- 'You\'re importing a module that depends on `catchError` into a React Server Component module. This API is only available in Client Components. To fix, mark the file (or its parent) with the `"use client"` directive.'
- )
+ if (deferPoisonedImport) {
+ await session.write(entryFile, entryContent)
+ }
+
+ const expectPoisonedImportRedbox = async () => {
+ await session.waitForRedbox()
+ expect(await session.getRedboxSource()).toInclude(
+ 'You\'re importing a module that depends on `catchError` into a React Server Component module. This API is only available in Client Components. To fix, mark the file (or its parent) with the `"use client"` directive.'
+ )
+ }
+ await expectPoisonedImportRedbox()
+
+ if (isTurbopack && isProxy) {
+ await session.patch(entryFile, exportCode)
+ await session.waitForNoRedbox()
+ await session.write(entryFile, entryContent)
+ await expectPoisonedImportRedbox()
+ }
}
)
})
diff --git a/test/development/app-dir/cache-components-dev-warmup/dev-warmup.util.ts b/test/development/app-dir/cache-components-dev-warmup/dev-warmup.util.ts
index 9b2ca16200f8..8c2d0fa50854 100644
--- a/test/development/app-dir/cache-components-dev-warmup/dev-warmup.util.ts
+++ b/test/development/app-dir/cache-components-dev-warmup/dev-warmup.util.ts
@@ -341,6 +341,19 @@ export function runDevWarmupTests({
assertLog(logs, `after params`, 'Prefetch')
assertLog(logs, `after searchParams`, 'Prefetch')
+ assertLog(
+ logs,
+ `after prefetch`,
+ // Same as navigation() below: static prerender timing on initial
+ // load, app-shell timing for a client nav when there's a runtime
+ // prefetch.
+ isInitialLoad
+ ? 'Prerender'
+ : partialPrefetching || hasRuntimePrefetch
+ ? 'Prefetch'
+ : 'Prerender'
+ )
+
assertLog(
logs,
`after navigation`,
diff --git a/test/development/app-dir/cache-components-dev-warmup/fixtures/with-prefetch-config/app/apis/[param]/page.tsx b/test/development/app-dir/cache-components-dev-warmup/fixtures/with-prefetch-config/app/apis/[param]/page.tsx
index c5ae2e7de207..0302739ca439 100644
--- a/test/development/app-dir/cache-components-dev-warmup/fixtures/with-prefetch-config/app/apis/[param]/page.tsx
+++ b/test/development/app-dir/cache-components-dev-warmup/fixtures/with-prefetch-config/app/apis/[param]/page.tsx
@@ -1,7 +1,10 @@
import { cookies, headers } from 'next/headers'
import { CachedData } from '../../data-fetching'
import { connection } from 'next/server'
-import { unstable_navigation as navigation } from 'next/cache'
+import {
+ unstable_navigation as navigation,
+ unstable_prefetch,
+} from 'next/cache'
import { Suspense } from 'react'
export const instant = true
@@ -23,6 +26,7 @@ export default function Page({ params, searchParams }) {
headers()} />
params} />
searchParams} />
+ unstable_prefetch()} />
navigation()} />
{/* Dynamic */}
diff --git a/test/development/app-dir/cache-components-dev-warmup/fixtures/without-prefetch-config/app/apis/[param]/page.tsx b/test/development/app-dir/cache-components-dev-warmup/fixtures/without-prefetch-config/app/apis/[param]/page.tsx
index 151b6680bd96..737488ed9d64 100644
--- a/test/development/app-dir/cache-components-dev-warmup/fixtures/without-prefetch-config/app/apis/[param]/page.tsx
+++ b/test/development/app-dir/cache-components-dev-warmup/fixtures/without-prefetch-config/app/apis/[param]/page.tsx
@@ -1,7 +1,10 @@
import { cookies, headers } from 'next/headers'
import { CachedData } from '../../data-fetching'
import { connection } from 'next/server'
-import { unstable_navigation as navigation } from 'next/cache'
+import {
+ unstable_navigation as navigation,
+ unstable_prefetch,
+} from 'next/cache'
import { Suspense } from 'react'
const CACHE_KEY = __dirname + '/__PAGE__'
@@ -20,6 +23,7 @@ export default function Page({ params, searchParams }) {
headers()} />
params} />
searchParams} />
+ unstable_prefetch()} />
navigation()} />
{/* Dynamic */}
diff --git a/test/development/app-hmr/fixtures/default-template/next.config.js b/test/development/app-hmr/fixtures/default-template/next.config.js
index eba9d47557b5..c90c5aa5ab9f 100644
--- a/test/development/app-hmr/fixtures/default-template/next.config.js
+++ b/test/development/app-hmr/fixtures/default-template/next.config.js
@@ -1,4 +1,8 @@
/**
* @type {import('next').NextConfig}
*/
-module.exports = {}
+module.exports = {
+ turbopack: {
+ chunkLoadingGlobal: 'hmrApp',
+ },
+}
diff --git a/test/development/basic/hmr/hot-module-reload-no-base-path-no-asset-prefix.test.ts b/test/development/basic/hmr/hot-module-reload-no-base-path-no-asset-prefix.test.ts
index c95910722ada..3e4f3d376d33 100644
--- a/test/development/basic/hmr/hot-module-reload-no-base-path-no-asset-prefix.test.ts
+++ b/test/development/basic/hmr/hot-module-reload-no-base-path-no-asset-prefix.test.ts
@@ -1,6 +1,12 @@
import { runHotModuleReloadHmrTest } from './run-hot-module-reload-hmr-test.util'
-const nextConfig = { basePath: '', assetPrefix: '' }
+const nextConfig = {
+ basePath: '',
+ assetPrefix: '',
+ turbopack: {
+ chunkLoadingGlobal: 'hmrPages',
+ },
+}
describe(`HMR - Hot Module Reload, nextConfig: ${JSON.stringify(nextConfig)}`, () => {
runHotModuleReloadHmrTest(nextConfig)
diff --git a/test/development/basic/hmr/run-hot-module-reload-hmr-test.util.ts b/test/development/basic/hmr/run-hot-module-reload-hmr-test.util.ts
index 7191dc0f3829..dfff102668bc 100644
--- a/test/development/basic/hmr/run-hot-module-reload-hmr-test.util.ts
+++ b/test/development/basic/hmr/run-hot-module-reload-hmr-test.util.ts
@@ -5,6 +5,9 @@ import { nextTestSetup } from 'e2e-utils'
export function runHotModuleReloadHmrTest(nextConfig: {
basePath: string
assetPrefix: string
+ turbopack?: {
+ chunkLoadingGlobal: string
+ }
}) {
const { next } = nextTestSetup({
files: __dirname,
diff --git a/test/e2e/app-dir/instant-validation/app/shells/(default)/invalid-prefetch-without-suspense/page.tsx b/test/e2e/app-dir/instant-validation/app/shells/(default)/invalid-prefetch-without-suspense/page.tsx
new file mode 100644
index 000000000000..47b21b5f7a24
--- /dev/null
+++ b/test/e2e/app-dir/instant-validation/app/shells/(default)/invalid-prefetch-without-suspense/page.tsx
@@ -0,0 +1,25 @@
+import { Instant } from 'next'
+import { unstable_prefetch } from 'next/cache'
+
+export const instant: Instant = {
+ level: 'experimental-error',
+}
+
+export const prefetch = 'partial'
+
+export default async function Page() {
+ return (
+
+
+ This page is missing a suspense around prefetch(), so we can't render a
+ shell.
+
+ This page uses sync IO after awaiting prefetch():
+ {/*
+ In partialPrefetching, prefetch() is not allowed in shells,
+ so we need a Suspense.
+ Before partialPrefetching everything is static, so we could skip it,
+ but that's not relevant to this test.
+ */}
+
+
+
+
+
+ )
+}
+
+async function SyncIOAfterPrefetch() {
+ await unstable_prefetch()
+ return Date.now()
+}
diff --git a/test/e2e/app-dir/instant-validation/head-and-reporting.util.ts b/test/e2e/app-dir/instant-validation/head-and-reporting.util.ts
index 43680a51f962..c6efa5031743 100644
--- a/test/e2e/app-dir/instant-validation/head-and-reporting.util.ts
+++ b/test/e2e/app-dir/instant-validation/head-and-reporting.util.ts
@@ -970,6 +970,80 @@ export function registerHeadAndReportingTests(
}
})
+ it('invalid - unguarded prefetch() in a shell', async () => {
+ if (isNextDev) {
+ const browser = await navigateTo(
+ '/shells/invalid-prefetch-without-suspense'
+ )
+ await expect(browser).toDisplayCollapsedRedbox(`
+ {
+ "cause": [
+ {
+ "label": "Caused by: Instant Validation",
+ "source": "app/shells/(default)/invalid-prefetch-without-suspense/page.tsx (4:33) @ instant
+ > 4 | export const instant: Instant = {
+ | ^",
+ "stack": [
+ "instant app/shells/(default)/invalid-prefetch-without-suspense/page.tsx (4:33)",
+ "Set.forEach ",
+ ],
+ },
+ ],
+ "code": "E1439",
+ "description": "Next.js encountered URL data outside of Suspense.",
+ "environmentLabel": "Server",
+ "label": "Instant",
+ "source": "app/shells/(default)/invalid-prefetch-without-suspense/page.tsx (23:26) @ PrefetchContent
+ > 23 | await unstable_prefetch()
+ | ^",
+ "stack": [
+ "PrefetchContent app/shells/(default)/invalid-prefetch-without-suspense/page.tsx (23:26)",
+ "Page app/shells/(default)/invalid-prefetch-without-suspense/page.tsx (17:7)",
+ ],
+ }
+ `)
+ } else {
+ const result = await prerender(
+ '/shells/(default)/invalid-prefetch-without-suspense'
+ )
+ expect(extractBuildValidationError(result.cliOutput))
+ .toMatchInlineSnapshot(`
+ "Error: Route "/shells/invalid-prefetch-without-suspense": Next.js encountered URL data during prerendering or a navigation.
+
+ \`params\` or \`searchParams\` accessed outside of \`\` may prevent the navigation from being instant, leading to a slower user experience.
+
+ Ways to fix this:
+ - [stream] Provide a placeholder with \`\` around the data access
+ - [block] Set \`export const instant = false\` to allow a blocking route
+
+ Learn more: https://nextjs.org/docs/messages/instant-shell-url-data
+ at main ()
+ at body ()
+ at html ()
+ Build-time instant validation failed for route "/shells/invalid-prefetch-without-suspense".
+ To get a more detailed stack trace and pinpoint the issue, try one of the following:
+ - Start the app in development mode by running \`next dev\`, then open "/shells/invalid-prefetch-without-suspense" in your browser to investigate the error.
+ - Rerun the production build with \`next build --debug-prerender\` to generate better stack traces.
+ Stopping prerender due to instant validation errors."
+ `)
+ expect(result.exitCode).toBe(1)
+ }
+ })
+
+ it('valid - prefetch() with suspense in a shell', async () => {
+ if (isNextDev) {
+ const browser = await navigateTo(
+ '/shells/valid-prefetch-with-suspense'
+ )
+ await expectNoDevValidationErrors(browser, await browser.url())
+ } else {
+ const result = await prerender(
+ '/shells/(default)/valid-prefetch-with-suspense'
+ )
+ expectNoBuildValidationErrors(result)
+ }
+ })
+
it('valid - unguarded root param', async () => {
if (isNextDev) {
const browser = await navigateTo(
@@ -1026,6 +1100,19 @@ export function registerHeadAndReportingTests(
expectNoBuildValidationErrors(result)
}
})
+ it('valid - unguarded prefetch', async () => {
+ if (isNextDev) {
+ const browser = await navigateTo(
+ '/suspense-in-root/non-app-shell/valid-unguarded-prefetch'
+ )
+ await expectNoDevValidationErrors(browser, await browser.url())
+ } else {
+ const result = await prerender(
+ '/suspense-in-root/non-app-shell/valid-unguarded-prefetch'
+ )
+ expectNoBuildValidationErrors(result)
+ }
+ })
})
}
diff --git a/test/e2e/app-dir/instant-validation/sync-io-and-blocking.util.ts b/test/e2e/app-dir/instant-validation/sync-io-and-blocking.util.ts
index bf14af5a0514..e592ee9140c7 100644
--- a/test/e2e/app-dir/instant-validation/sync-io-and-blocking.util.ts
+++ b/test/e2e/app-dir/instant-validation/sync-io-and-blocking.util.ts
@@ -134,6 +134,65 @@ export function registerSyncIoAndBlockingTests(
}
})
+ it('sync IO after prefetch()', async () => {
+ if (isNextDev) {
+ const browser = await navigateTo(
+ '/suspense-in-root/sync-io/sync-io-after-prefetch'
+ )
+ await expect(browser).toDisplayCollapsedRedbox(`
+ {
+ "code": "E1432",
+ "description": "Next.js encountered the unstable value Date.now() while prerendering.",
+ "environmentLabel": "Server",
+ "label": "Blocking Route",
+ "source": "app/suspense-in-root/sync-io/sync-io-after-prefetch/page.tsx (27:15) @ SyncIOAfterPrefetch
+ > 27 | return Date.now()
+ | ^",
+ "stack": [
+ "SyncIOAfterPrefetch app/suspense-in-root/sync-io/sync-io-after-prefetch/page.tsx (27:15)",
+ "Page app/suspense-in-root/sync-io/sync-io-after-prefetch/page.tsx (18:11)",
+ ],
+ }
+ `)
+ } else {
+ const result = await prerender(
+ '/suspense-in-root/sync-io/sync-io-after-prefetch'
+ )
+ // `await prefetch()` resolves during a static prerender, so
+ // we hit the sync IO there and error before reaching instant validation.
+ expect(
+ getPrerenderOutput(result.cliOutput, {
+ isMinified: true,
+ })
+ ).toMatchInlineSnapshot(`
+ "Error: Route "/suspense-in-root/sync-io/sync-io-after-prefetch": Next.js encountered the unstable value \`Date.now()\` while prerendering.
+
+ This value can change between renders, so it must be either prerendered or computed later.
+
+ Ways to fix this:
+ - [dynamic] Render at request time by adding a dynamic data access (e.g. \`await connection()\`) before this call
+ - [cache] Prerender and cache the value with \`"use cache"\`
+ - [client] Render the value on the client with \`"use client"\`
+ - [measure] If the value is for telemetry, use a timing API such as \`performance.now()\`
+
+ Learn more: https://nextjs.org/docs/messages/blocking-prerender-current-time
+ at a (app/suspense-in-root/sync-io/sync-io-after-prefetch/page.tsx:27:15)
+ 25 | async function SyncIOAfterPrefetch() {
+ 26 | await unstable_prefetch()
+ > 27 | return Date.now()
+ | ^
+ 28 | }
+ 29 |
+ To get a more detailed stack trace and pinpoint the issue, try one of the following:
+ - Start the app in development mode by running \`next dev\`, then open "/suspense-in-root/sync-io/sync-io-after-prefetch" in your browser to investigate the error.
+ - Rerun the production build with \`next build --debug-prerender\` to generate better stack traces.
+ Error occurred prerendering page "/suspense-in-root/sync-io/sync-io-after-prefetch". Read more: https://nextjs.org/docs/messages/prerender-error
+ Export encountered an error on /suspense-in-root/sync-io/sync-io-after-prefetch/page: /suspense-in-root/sync-io/sync-io-after-prefetch, exiting the build."
+ `)
+ expect(result.exitCode).toBe(1)
+ }
+ })
+
it('sync IO after cache with session data input', async () => {
if (isNextDev) {
const browser = await navigateTo(
diff --git a/test/e2e/app-dir/segment-cache/cached-navigations/cached-navigations-partial-prefetching.test.ts b/test/e2e/app-dir/segment-cache/cached-navigations/cached-navigations-partial-prefetching.test.ts
index 72df150846c3..90cbb92ef937 100644
--- a/test/e2e/app-dir/segment-cache/cached-navigations/cached-navigations-partial-prefetching.test.ts
+++ b/test/e2e/app-dir/segment-cache/cached-navigations/cached-navigations-partial-prefetching.test.ts
@@ -75,6 +75,9 @@ describe('cached navigations - global partialPrefetching', () => {
expect(await browser.elementById('navigation-boundary').text()).toContain(
'Navigation content'
)
+ expect(await browser.elementById('prefetch-boundary').text()).toContain(
+ 'Prefetch content'
+ )
// Only connection() shows a Suspense fallback — it's truly dynamic.
expect(await browser.elementById('connection-boundary').text()).toBe(
diff --git a/test/e2e/app-dir/segment-cache/cached-navigations/partial-prefetching/app/runtime-prefetchable/page.tsx b/test/e2e/app-dir/segment-cache/cached-navigations/partial-prefetching/app/runtime-prefetchable/page.tsx
index c855984a78dc..683c7eae60d0 100644
--- a/test/e2e/app-dir/segment-cache/cached-navigations/partial-prefetching/app/runtime-prefetchable/page.tsx
+++ b/test/e2e/app-dir/segment-cache/cached-navigations/partial-prefetching/app/runtime-prefetchable/page.tsx
@@ -1,6 +1,9 @@
import { cookies, headers } from 'next/headers'
import { connection } from 'next/server'
-import { unstable_navigation as navigation } from 'next/cache'
+import {
+ unstable_navigation as navigation,
+ unstable_prefetch,
+} from 'next/cache'
import { Suspense } from 'react'
// Note: intentionally no `export const prefetch` and no `instant` config. This
@@ -40,6 +43,11 @@ export default async function Page({
+
+
+ Runtime prefetch post "speculative-1" (prefetch=true)
+
+
+
)
}
diff --git a/test/e2e/app-dir/segment-cache/prefetch-app-shell/app/(default)/runtime-prefetch/[id]/page.tsx b/test/e2e/app-dir/segment-cache/prefetch-app-shell/app/(default)/runtime-prefetch/[id]/page.tsx
new file mode 100644
index 000000000000..048228c27999
--- /dev/null
+++ b/test/e2e/app-dir/segment-cache/prefetch-app-shell/app/(default)/runtime-prefetch/[id]/page.tsx
@@ -0,0 +1,48 @@
+import { Suspense } from 'react'
+import { unstable_prefetch } from 'next/cache'
+import { cookies } from 'next/headers'
+import { connection } from 'next/server'
+
+type Params = { id: string }
+
+export const prefetch = 'partial'
+
+export default async function Page({ params }: { params: Promise }) {
+ return (
+
+ Loading prefetch...
}>
+
+
+ {/* The fallback is the App Shell — the part of the page that
+ doesn't depend on params. */}
+ App shell for prefetch}>
+
+
+
+ )
+}
+
+async function PrefetchData() {
+ await cookies() // Makes sure this page uses a runtime prefetch
+ await unstable_prefetch() // Exclude the contents below from runtime app shells
+ return
+}
diff --git a/test/e2e/app-dir/segment-cache/prefetch-app-shell/app/(default)/static-prefetch/[id]/page.tsx b/test/e2e/app-dir/segment-cache/prefetch-app-shell/app/(default)/static-prefetch/[id]/page.tsx
new file mode 100644
index 000000000000..9656d4677b6b
--- /dev/null
+++ b/test/e2e/app-dir/segment-cache/prefetch-app-shell/app/(default)/static-prefetch/[id]/page.tsx
@@ -0,0 +1,52 @@
+import { Suspense } from 'react'
+import { unstable_prefetch } from 'next/cache'
+import { connection } from 'next/server'
+
+export async function generateStaticParams() {
+ return [{ id: '1' }, { id: '2' }]
+}
+
+type Params = { id: string }
+
+export const prefetch = 'partial'
+
+export default async function Page({ params }: { params: Promise }) {
+ return (
+
+ App shell for prefetch}>
+
+
+ Loading prefetch...}>
+
+
+
+ )
+}
+
+async function PrefetchData() {
+ await unstable_prefetch() // Exclude the contents below from the shell
+ return
Prefetch content
+}
+
+async function ParamsDependent({ params }: { params: Promise }) {
+ // Make sure the static prefetch varies on params so that the client router
+ // has to extract a static shell from it when navigating to another param value.
+ // If the static prefetch doesn't vary on params, it'll be used instead of
+ // the app shell
+ const { id } = await params
+ return (
+ <>
+
+}
diff --git a/test/e2e/app-dir/segment-cache/prefetch-static-shell/app/page.tsx b/test/e2e/app-dir/segment-cache/prefetch-static-shell/app/page.tsx
index a2c4899c824d..d44acbfd8dac 100644
--- a/test/e2e/app-dir/segment-cache/prefetch-static-shell/app/page.tsx
+++ b/test/e2e/app-dir/segment-cache/prefetch-static-shell/app/page.tsx
@@ -35,6 +35,16 @@ export default function Page() {
Uses navigation() on a static page
+
+
+ Uses runtime APIs after prefetch()
+
+
+
+
+ Uses prefetch() on a static page
+
+
Dynamic param one
diff --git a/test/e2e/app-dir/segment-cache/prefetch-static-shell/app/uses-prefetch-static/page.tsx b/test/e2e/app-dir/segment-cache/prefetch-static-shell/app/uses-prefetch-static/page.tsx
new file mode 100644
index 000000000000..7f513d06a56f
--- /dev/null
+++ b/test/e2e/app-dir/segment-cache/prefetch-static-shell/app/uses-prefetch-static/page.tsx
@@ -0,0 +1,17 @@
+import { Suspense } from 'react'
+import { unstable_prefetch } from 'next/cache'
+
+export default function Page() {
+ return (
+
+ Loading prefetch...}>
+
+
+
+ )
+}
+
+async function PrefetchContent() {
+ await unstable_prefetch()
+ return
Fully static page content (with prefetch())
+}
diff --git a/test/e2e/app-dir/segment-cache/prefetch-static-shell/app/uses-runtime-after-prefetch/page.tsx b/test/e2e/app-dir/segment-cache/prefetch-static-shell/app/uses-runtime-after-prefetch/page.tsx
new file mode 100644
index 000000000000..a1934c3feb66
--- /dev/null
+++ b/test/e2e/app-dir/segment-cache/prefetch-static-shell/app/uses-runtime-after-prefetch/page.tsx
@@ -0,0 +1,41 @@
+// A page that calls cookies and headers after awaiting `unstable_prefetch()`.
+// Unlike `navigation()`, `prefetch()` doesn't stop runtime-data tracking — the
+// reads below it still count — so the tree hint stays unset and this route
+// can't be prefetched statically.
+
+import { cookies, headers } from 'next/headers'
+import { unstable_prefetch } from 'next/cache'
+import { Suspense } from 'react'
+
+export default async function Page() {
+ return (
+
+
+}
diff --git a/test/e2e/app-dir/segment-cache/prefetch-static-shell/prefetch-static-shell.test.ts b/test/e2e/app-dir/segment-cache/prefetch-static-shell/prefetch-static-shell.test.ts
index df2c46b1f998..b95df1163cf6 100644
--- a/test/e2e/app-dir/segment-cache/prefetch-static-shell/prefetch-static-shell.test.ts
+++ b/test/e2e/app-dir/segment-cache/prefetch-static-shell/prefetch-static-shell.test.ts
@@ -144,6 +144,41 @@ describe('static App Shell prefetch attempt', () => {
}, 'no-requests')
})
+ it('prefetches a fully static route that uses prefetch() with static requests only, then navigates instantly from cache', async () => {
+ let page: Playwright.Page
+ const browser = await next.browser('/', {
+ beforePageLoad(p: Playwright.Page) {
+ page = p
+ },
+ })
+ const act = createRouterAct(page, { includeAppShellRequests: true })
+
+ // prefetch() resolves during a static prerender, and the route accesses no
+ // runtime data, so the static attempt is sufficient.
+ await act(async () => {
+ await browser
+ .elementByCss('input[data-link-accordion="/uses-prefetch-static"]')
+ .click()
+ }, [
+ {
+ includes: 'Fully static page content (with prefetch())',
+ kind: 'static',
+ },
+ {
+ includes: 'Fully static page content (with prefetch())',
+ kind: 'runtime',
+ block: 'reject',
+ },
+ ])
+
+ await act(async () => {
+ await browser.elementByCss('a[href="/uses-prefetch-static"]').click()
+ expect(await browser.elementById('page-content').text()).toBe(
+ 'Fully static page content (with prefetch())'
+ )
+ }, 'no-requests')
+ })
+
it('goes straight to a runtime shell prefetch when the shell reads cookies (hint unset)', async () => {
let page: Playwright.Page
const browser = await next.browser('/', {
@@ -335,6 +370,35 @@ describe('static App Shell prefetch attempt', () => {
)
})
+ it('goes straight to a runtime shell prefetch for a partial segment that calls runtime APIs after prefetch() (hint unset)', async () => {
+ let page: Playwright.Page
+ const browser = await next.browser('/', {
+ beforePageLoad(p: Playwright.Page) {
+ page = p
+ },
+ })
+ const act = createRouterAct(page, { includeAppShellRequests: true })
+
+ await act(async () => {
+ await browser
+ .elementByCss(
+ 'input[data-link-accordion="/uses-runtime-after-prefetch"]'
+ )
+ .click()
+ }, [
+ // Unlike navigation(), prefetch() doesn't stop runtime-data tracking, so
+ // the cookies()/headers() reads below it leave the tree hint unset and
+ // the shell arrives in a runtime response.
+ { includes: 'Runtime APIs called after prefetch()', kind: 'runtime' },
+ // No static attempt precedes it.
+ {
+ includes: 'Runtime APIs called after prefetch()',
+ kind: 'static',
+ block: 'reject',
+ },
+ ])
+ })
+
it('reuses the static App Shell across different param values of a dynamic route', async () => {
let page: Playwright.Page
const browser = await next.browser('/', {
@@ -405,6 +469,9 @@ describe('static App Shell prefetch attempt', () => {
expect(await browser.elementById('navigation-loading').text()).toBe(
'Loading navigation content...'
)
+ expect(await browser.elementById('prefetch-loading').text()).toBe(
+ 'Loading prefetch content...'
+ )
},
// The param content arrives with the navigation response.
{ includes: 'Dynamic param content: two' }
diff --git a/test/e2e/app-document-import-order/app-document-import-order.test.ts b/test/e2e/app-document-import-order/app-document-import-order.test.ts
index e911fc32a74d..b248c886a9a1 100644
--- a/test/e2e/app-document-import-order/app-document-import-order.test.ts
+++ b/test/e2e/app-document-import-order/app-document-import-order.test.ts
@@ -2,7 +2,7 @@
import { nextTestSetup } from 'e2e-utils'
describe('Root components import order', () => {
- const { next, isTurbopack } = nextTestSetup({
+ const { next, isTurbopack, isNextDev } = nextTestSetup({
files: __dirname,
})
@@ -16,6 +16,34 @@ describe('Root components import order', () => {
expect($(sideEffectCall).text()).toEqual(expectSideEffectsOrder[index])
})
})
+ // Only asserted for production builds: in development each entry is chunked from its own
+ // per-page module graph, which can still merge a shared module into per-entry units.
+ ;(isNextDev ? it.skip : it)(
+ 'loads modules shared by _app and the page only once',
+ async () => {
+ const browser = await next.browser('/', { waitHydration: false })
+ const markerCount = await browser.eval(async () => {
+ const chunkUrls = [
+ ...new Set(
+ performance
+ .getEntriesByType('resource')
+ .map((entry) => entry.name)
+ .filter(
+ (url) => url.includes('/_next/static/') && url.endsWith('.js')
+ )
+ ),
+ ]
+ const chunks = await Promise.all(
+ chunkUrls.map((url) => fetch(url).then((response) => response.text()))
+ )
+ return chunks.filter((chunk) =>
+ chunk.includes('APP_PAGE_SHARED_MODULE_MARKER')
+ ).length
+ })
+
+ expect(markerCount).toBe(1)
+ }
+ )
// Test relies on webpack splitChunks overrides.
;(isTurbopack ? it.skip : it)(
diff --git a/test/e2e/app-document-import-order/sideEffectModule.js b/test/e2e/app-document-import-order/sideEffectModule.js
index 378e2b39095d..d701d9538f90 100644
--- a/test/e2e/app-document-import-order/sideEffectModule.js
+++ b/test/e2e/app-document-import-order/sideEffectModule.js
@@ -7,4 +7,6 @@ const sideEffect = (arg) => {
return sideEffect.callArguments
}
+globalThis.__appPageSharedModuleMarker = 'APP_PAGE_SHARED_MODULE_MARKER'
+
export default sideEffect
diff --git a/turbopack/crates/turbopack-cli/js/src/entry/client.ts b/turbopack/crates/turbopack-cli/js/src/entry/client.ts
index 6870201f6f2c..74f65b8f59cc 100644
--- a/turbopack/crates/turbopack-cli/js/src/entry/client.ts
+++ b/turbopack/crates/turbopack-cli/js/src/entry/client.ts
@@ -1,4 +1,7 @@
-import { connect } from '@vercel/turbopack-ecmascript-runtime/browser/dev/hmr-client/hmr-client'
+import {
+ connect,
+ TURBOPACK_CHUNK_UPDATE_LISTENERS_GLOBAL,
+} from '@vercel/turbopack-ecmascript-runtime/browser/dev/hmr-client/hmr-client'
import { connectHMR, addMessageListener, sendMessage } from './websocket'
export function initializeHMR(options: { assetPrefix: string }) {
@@ -6,6 +9,7 @@ export function initializeHMR(options: { assetPrefix: string }) {
addMessageListener,
sendMessage,
onUpdateError: console.error,
+ chunkUpdateListenersGlobal: TURBOPACK_CHUNK_UPDATE_LISTENERS_GLOBAL,
})
connectHMR({
assetPrefix: options.assetPrefix,
diff --git a/turbopack/crates/turbopack-ecmascript-runtime/js/src/browser/dev/hmr-client/hmr-client.ts b/turbopack/crates/turbopack-ecmascript-runtime/js/src/browser/dev/hmr-client/hmr-client.ts
index fabe2cfc0557..699af948c792 100644
--- a/turbopack/crates/turbopack-ecmascript-runtime/js/src/browser/dev/hmr-client/hmr-client.ts
+++ b/turbopack/crates/turbopack-ecmascript-runtime/js/src/browser/dev/hmr-client/hmr-client.ts
@@ -17,12 +17,17 @@ export type ClientOptions = {
addMessageListener: (cb: (msg: WebSocketMessage) => void) => void
sendMessage: SendMessage
onUpdateError: (err: unknown) => void
+ chunkUpdateListenersGlobal: string
}
+export const TURBOPACK_CHUNK_UPDATE_LISTENERS_GLOBAL =
+ 'TURBOPACK_CHUNK_UPDATE_LISTENERS'
+
export function connect({
addMessageListener,
sendMessage,
onUpdateError = console.error,
+ chunkUpdateListenersGlobal,
}: ClientOptions) {
addMessageListener((msg) => {
switch (msg.type) {
@@ -55,11 +60,15 @@ export function connect({
}
})
- const queued = globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS
+ const global = globalThis as unknown as Record<
+ string,
+ ChunkUpdateProvider | [ChunkListPath, UpdateCallback][] | undefined
+ >
+ const queued = global[chunkUpdateListenersGlobal]
if (queued != null && !Array.isArray(queued)) {
throw new Error('A separate HMR handler was already registered')
}
- globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = {
+ global[chunkUpdateListenersGlobal] = {
push: ([chunkPath, callback]: [ChunkListPath, UpdateCallback]) => {
subscribeToChunkUpdate(chunkPath, sendMessage, callback)
},
diff --git a/turbopack/crates/turbopack-ecmascript-runtime/js/src/browser/runtime/base/dev-base.ts b/turbopack/crates/turbopack-ecmascript-runtime/js/src/browser/runtime/base/dev-base.ts
index 68701619faf2..bcd2600d3138 100644
--- a/turbopack/crates/turbopack-ecmascript-runtime/js/src/browser/runtime/base/dev-base.ts
+++ b/turbopack/crates/turbopack-ecmascript-runtime/js/src/browser/runtime/base/dev-base.ts
@@ -579,7 +579,7 @@ function registerChunkList(chunkList: ChunkList) {
const chunkListPath = getPathFromScript(chunkListScript)
// The "chunk" is also registered to finish the loading in the backend
BACKEND.registerChunk(chunkListPath as string as ChunkPath)
- globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS!.push([
+ CHUNK_UPDATE_LISTENERS.push([
chunkListPath,
handleApply.bind(null, chunkListPath),
])
@@ -601,5 +601,3 @@ function registerChunkList(chunkList: ChunkList) {
markChunkListAsRuntime(chunkListPath)
}
}
-
-globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS ??= []
diff --git a/turbopack/crates/turbopack-ecmascript-runtime/js/src/shared/runtime/dev-globals.d.ts b/turbopack/crates/turbopack-ecmascript-runtime/js/src/shared/runtime/dev-globals.d.ts
index 26eab9347386..4b4ebd1f26f0 100644
--- a/turbopack/crates/turbopack-ecmascript-runtime/js/src/shared/runtime/dev-globals.d.ts
+++ b/turbopack/crates/turbopack-ecmascript-runtime/js/src/shared/runtime/dev-globals.d.ts
@@ -11,10 +11,7 @@ type ChunkUpdateProvider = {
push: (registration: [ChunkListPath, UpdateCallback]) => void
}
-declare var TURBOPACK_CHUNK_UPDATE_LISTENERS:
- | ChunkUpdateProvider
- | [ChunkListPath, UpdateCallback][]
- | undefined
+declare var CHUNK_UPDATE_LISTENERS: ChunkUpdateProvider
// This is used by the Next.js integration test suite to notify it when HMR
// updates have been completed.
declare var __NEXT_HMR_CB: undefined | null | (() => void)
diff --git a/turbopack/crates/turbopack-ecmascript-runtime/src/browser_runtime.rs b/turbopack/crates/turbopack-ecmascript-runtime/src/browser_runtime.rs
index 31622c784933..a1abe0a302f3 100644
--- a/turbopack/crates/turbopack-ecmascript-runtime/src/browser_runtime.rs
+++ b/turbopack/crates/turbopack-ecmascript-runtime/src/browser_runtime.rs
@@ -14,6 +14,23 @@ use turbopack_ecmascript::utils::StringifyJs;
use crate::{RuntimeType, embed_js::embed_static_code};
+pub fn chunk_update_listeners_global_name(chunk_loading_global: &str) -> String {
+ format!("{chunk_loading_global}_CHUNK_UPDATE_LISTENERS")
+}
+
+#[cfg(test)]
+mod tests {
+ use super::chunk_update_listeners_global_name;
+
+ #[test]
+ fn scopes_chunk_update_listeners_to_chunk_loading_global() {
+ assert_eq!(
+ chunk_update_listeners_global_name("TURBOPACK_APP"),
+ "TURBOPACK_APP_CHUNK_UPDATE_LISTENERS"
+ );
+ }
+}
+
/// Returns the code for the ECMAScript runtime.
#[turbo_tasks::function]
pub async fn get_browser_runtime_code(
@@ -94,6 +111,8 @@ pub async fn get_browser_runtime_code(
let chunk_loading_global = chunk_loading_global.await?;
let cross_origin = *cross_origin.await?;
let chunk_lists_global = format!("{}_CHUNK_LISTS", chunk_loading_global);
+ let chunk_update_listeners_global =
+ chunk_update_listeners_global_name(chunk_loading_global.as_str());
if *environment
.runtime_versions()
@@ -130,6 +149,19 @@ pub async fn get_browser_runtime_code(
support_component_chunks,
)?;
+ if matches!(runtime_type, RuntimeType::Development) {
+ writedoc!(
+ code,
+ r#"
+ globalThis[{chunk_update_listeners_global}] ||= [];
+ var CHUNK_UPDATE_LISTENERS = {{
+ push: (registration) => globalThis[{chunk_update_listeners_global}].push(registration),
+ }};
+ "#,
+ chunk_update_listeners_global = StringifyJs(&chunk_update_listeners_global),
+ )?;
+ }
+
match &*asset_suffix {
AssetSuffix::None => {
writedoc!(
diff --git a/turbopack/crates/turbopack-ecmascript-runtime/src/lib.rs b/turbopack/crates/turbopack-ecmascript-runtime/src/lib.rs
index 13c5b544a6fa..02d6cbee972a 100644
--- a/turbopack/crates/turbopack-ecmascript-runtime/src/lib.rs
+++ b/turbopack/crates/turbopack-ecmascript-runtime/src/lib.rs
@@ -8,7 +8,9 @@ pub(crate) mod embed_js;
pub(crate) mod nodejs_runtime;
pub(crate) mod runtime_type;
-pub use browser_runtime::{get_browser_runtime_code, get_worker_runtime_code};
+pub use browser_runtime::{
+ chunk_update_listeners_global_name, get_browser_runtime_code, get_worker_runtime_code,
+};
#[cfg(feature = "test")]
pub use dummy_runtime::get_dummy_runtime_code;
pub use embed_js::{embed_file, embed_file_path, embed_fs, turbopack_runtime_import_map};
diff --git a/turbopack/crates/turbopack-ecmascript/src/references/import_meta_glob.rs b/turbopack/crates/turbopack-ecmascript/src/references/import_meta_glob.rs
index 574afdaba4f2..6e88c23849c7 100644
--- a/turbopack/crates/turbopack-ecmascript/src/references/import_meta_glob.rs
+++ b/turbopack/crates/turbopack-ecmascript/src/references/import_meta_glob.rs
@@ -846,8 +846,9 @@ impl EcmascriptChunkPlaceable for ImportMetaGlobAsset {
// Generate the value expression based on eager/lazy and import options
let value_expr = if this.eager {
- // Eager: direct synchronous require
- let module_expr = pm.create_require(Cow::Borrowed(&key_expr));
+ // Eager: synchronously evaluate the module and use its ESM namespace,
+ // matching what a static `import * as ns from "..."` would produce.
+ let module_expr = pm.create_esm_require(Cow::Borrowed(&key_expr));
// If `import` option is set, access the named export
if let Some(named) = &this.import {
quote!(
diff --git a/turbopack/crates/turbopack-ecmascript/src/references/pattern_mapping.rs b/turbopack/crates/turbopack-ecmascript/src/references/pattern_mapping.rs
index 7f2a11b948e1..ff88a59f408e 100644
--- a/turbopack/crates/turbopack-ecmascript/src/references/pattern_mapping.rs
+++ b/turbopack/crates/turbopack-ecmascript/src/references/pattern_mapping.rs
@@ -141,6 +141,34 @@ impl SinglePatternMapping {
}
}
+ /// Like [`Self::create_require`], but evaluates to the ESM *namespace* of the
+ /// module instead of its CommonJS `exports` object, so that the CommonJS
+ /// interop applies. This is what a static `import * as ns from "..."`
+ /// produces, and it is the difference between a JSON (or CommonJS) module
+ /// having a `default` export and not having one.
+ pub fn create_esm_require(&self, key_expr: Cow<'_, Expr>) -> Expr {
+ match self {
+ Self::Invalid => self.create_id(key_expr),
+ Self::Unresolvable(request) => throw_module_not_found_expr(request),
+ Self::Ignored => quote!("{}" as Expr),
+ Self::Dropped => quote!("0" as Expr),
+ Self::Module(_) | Self::ModuleLoader(_) => quote!(
+ "$turbopack_import($arg)" as Expr,
+ turbopack_import: Expr = TURBOPACK_IMPORT.into(),
+ arg: Expr = self.create_id(key_expr)
+ ),
+ Self::External(request, ExternalType::CommonJs) => quote!(
+ "$turbopack_external_require($arg, () => require($arg), true)" as Expr,
+ turbopack_external_require: Expr = TURBOPACK_EXTERNAL_REQUIRE.into(),
+ arg: Expr = request.as_str().into()
+ ),
+ Self::External(request, ty) => throw_module_not_found_error_expr(
+ request,
+ &format!("Unsupported external type {ty:?} for esm reference"),
+ ),
+ }
+ }
+
pub fn create_import(&self, key_expr: Cow<'_, Expr>, import_externals: bool) -> Expr {
match self {
Self::Invalid => {
diff --git a/turbopack/crates/turbopack-tests/tests/execution/turbopack/resolving/import-meta-glob-json/input/data/cjs.js b/turbopack/crates/turbopack-tests/tests/execution/turbopack/resolving/import-meta-glob-json/input/data/cjs.js
new file mode 100644
index 000000000000..26d1bed3d52c
--- /dev/null
+++ b/turbopack/crates/turbopack-tests/tests/execution/turbopack/resolving/import-meta-glob-json/input/data/cjs.js
@@ -0,0 +1 @@
+module.exports = { hello: 'cjs' }
diff --git a/turbopack/crates/turbopack-tests/tests/execution/turbopack/resolving/import-meta-glob-json/input/data/data.json b/turbopack/crates/turbopack-tests/tests/execution/turbopack/resolving/import-meta-glob-json/input/data/data.json
new file mode 100644
index 000000000000..de0657ddeaa9
--- /dev/null
+++ b/turbopack/crates/turbopack-tests/tests/execution/turbopack/resolving/import-meta-glob-json/input/data/data.json
@@ -0,0 +1 @@
+{ "hello": "world" }
diff --git a/turbopack/crates/turbopack-tests/tests/execution/turbopack/resolving/import-meta-glob-json/input/data/esm.mjs b/turbopack/crates/turbopack-tests/tests/execution/turbopack/resolving/import-meta-glob-json/input/data/esm.mjs
new file mode 100644
index 000000000000..7b1a863b6c9a
--- /dev/null
+++ b/turbopack/crates/turbopack-tests/tests/execution/turbopack/resolving/import-meta-glob-json/input/data/esm.mjs
@@ -0,0 +1,2 @@
+export default 'esm'
+export const value = 7
diff --git a/turbopack/crates/turbopack-tests/tests/execution/turbopack/resolving/import-meta-glob-json/input/index.js b/turbopack/crates/turbopack-tests/tests/execution/turbopack/resolving/import-meta-glob-json/input/index.js
new file mode 100644
index 000000000000..5e828493f7dc
--- /dev/null
+++ b/turbopack/crates/turbopack-tests/tests/execution/turbopack/resolving/import-meta-glob-json/input/index.js
@@ -0,0 +1,57 @@
+// An eager `import.meta.glob` must produce the same module namespace a
+// hand-written `import * as ns from '...'` produces, including the `default`
+// export that the CommonJS interop adds for JSON and CommonJS modules.
+
+import * as jsonNamespace from './data/data.json'
+import * as cjsNamespace from './data/cjs.js'
+
+const eager = import.meta.glob('./data/*', { eager: true })
+
+it('should expose the default export of a JSON module', () => {
+ expect(Object.keys(eager)).toEqual([
+ './data/cjs.js',
+ './data/data.json',
+ './data/esm.mjs',
+ ])
+ expect(eager['./data/data.json'].default).toEqual({ hello: 'world' })
+})
+
+it('should match a hand-written namespace import for JSON', () => {
+ expect(jsonNamespace.default).toEqual({ hello: 'world' })
+ expect({ ...eager['./data/data.json'] }).toEqual({ ...jsonNamespace })
+})
+
+it('should match a hand-written namespace import for CommonJS', () => {
+ expect(eager['./data/cjs.js'].default).toEqual({ hello: 'cjs' })
+ expect({ ...eager['./data/cjs.js'] }).toEqual({ ...cjsNamespace })
+})
+
+it('should keep working for ES modules', () => {
+ expect(eager['./data/esm.mjs'].default).toBe('esm')
+ expect(eager['./data/esm.mjs'].value).toBe(7)
+})
+
+const eagerDefault = import.meta.glob('./data/*', {
+ eager: true,
+ import: 'default',
+})
+
+it('should support import: "default" eagerly', () => {
+ expect(eagerDefault['./data/data.json']).toEqual({ hello: 'world' })
+ expect(eagerDefault['./data/cjs.js']).toEqual({ hello: 'cjs' })
+ expect(eagerDefault['./data/esm.mjs']).toBe('esm')
+})
+
+const lazy = import.meta.glob('./data/*')
+
+it('should expose the default export of a JSON module lazily', async () => {
+ const mod = await lazy['./data/data.json']()
+ expect(mod.default).toEqual({ hello: 'world' })
+})
+
+const lazyDefault = import.meta.glob('./data/*', { import: 'default' })
+
+it('should support import: "default" lazily', async () => {
+ expect(await lazyDefault['./data/data.json']()).toEqual({ hello: 'world' })
+ expect(await lazyDefault['./data/esm.mjs']()).toBe('esm')
+})
diff --git a/turbopack/crates/turbopack-tests/tests/snapshot/debug-ids/browser/output/1do3_crates_turbopack-tests_tests_snapshot_debug-ids_browser_input_index_19boa0e.js.map b/turbopack/crates/turbopack-tests/tests/snapshot/debug-ids/browser/output/1do3_crates_turbopack-tests_tests_snapshot_debug-ids_browser_input_index_19boa0e.js.map
index b89d466a304c..18a20f4787b5 100644
--- a/turbopack/crates/turbopack-tests/tests/snapshot/debug-ids/browser/output/1do3_crates_turbopack-tests_tests_snapshot_debug-ids_browser_input_index_19boa0e.js.map
+++ b/turbopack/crates/turbopack-tests/tests/snapshot/debug-ids/browser/output/1do3_crates_turbopack-tests_tests_snapshot_debug-ids_browser_input_index_19boa0e.js.map
@@ -1,13 +1,13 @@
{
"version": 3,
"sources": [],
- "debugId": "64c9678c-f7a9-2121-4902-35dfa89f5d34",
+ "debugId": "ee80707f-230b-76ad-c42e-fca99f56d165",
"sections": [
- {"offset": {"line": 22, "column": 0}, "map": {"version":3,"sources":["turbopack:///[turbopack]/shared/runtime/runtime-utils.ts"],"sourcesContent":["/**\n * This file contains runtime types and functions that are shared between all\n * TurboPack ECMAScript runtimes.\n *\n * It will be prepended to the runtime code of each runtime.\n */\n\n/* eslint-disable @typescript-eslint/no-unused-vars */\n\n/// \n/// \n\ntype EsmNamespaceObject = Record\n\n/**\n * Describes why a module was instantiated.\n * Shared between browser and Node.js runtimes.\n */\nenum SourceType {\n /**\n * The module was instantiated because it was included in an evaluated chunk's\n * runtime.\n * SourceData is a ChunkPath.\n */\n Runtime = 0,\n /**\n * The module was instantiated because a parent module imported it.\n * SourceData is a ModuleId.\n */\n Parent = 1,\n /**\n * The module was instantiated because it was included in a chunk's hot module\n * update.\n * SourceData is an array of ModuleIds or undefined.\n */\n Update = 2,\n}\n\ntype SourceData = ChunkPath | ModuleId | ModuleId[] | undefined\n\n// @ts-ignore Defined in `dev-base.ts`\ndeclare function getOrInstantiateModuleFromParent(\n id: ModuleId,\n sourceModule: M\n): M\n\n// @ts-ignore Defined in `hmr-runtime.ts` (dev mode only)\ndeclare let devModuleCache: Record | undefined\n\n/**\n * Flag indicating which module object type to create when a module is merged. Set to `true`\n * by each runtime that uses ModuleWithDirection (browser dev-base.ts, nodejs dev-base.ts,\n * nodejs build-base.ts). Browser production (build-base.ts) leaves it as `false` since it\n * uses plain Module objects.\n */\nlet createModuleWithDirectionFlag = false\n\nconst REEXPORTED_OBJECTS = new WeakMap()\n\n/**\n * Constructs the `__turbopack_context__` object for a module.\n */\nfunction Context(\n this: TurbopackBaseContext,\n module: Module,\n exports: Exports\n) {\n this.m = module\n // We need to store this here instead of accessing it from the module object to:\n // 1. Make it available to factories directly, since we rewrite `this` to\n // `__turbopack_context__.e` in CJS modules.\n // 2. Support async modules which rewrite `module.exports` to a promise, so we\n // can still access the original exports object from functions like\n // `esmExport`\n // Ideally we could find a new approach for async modules and drop this property altogether.\n this.e = exports\n}\nconst contextPrototype = Context.prototype as TurbopackBaseContext\n\ntype ModuleContextMap = Record\n\ninterface ModuleContextEntry {\n id: () => ModuleId\n module: () => any\n}\n\ninterface ModuleContext {\n // require call\n (moduleId: string): Exports | EsmNamespaceObject\n\n // async import call\n import(moduleId: string): Promise\n\n keys(): ModuleId[]\n\n resolve(moduleId: string): ModuleId\n}\n\ntype GetOrInstantiateModuleFromParent = (\n moduleId: M['id'],\n parentModule: M\n) => M\n\ndeclare function getOrInstantiateRuntimeModule(\n chunkPath: ChunkPath,\n moduleId: ModuleId\n): Module\n\nconst hasOwnProperty = Object.prototype.hasOwnProperty\nconst toStringTag = typeof Symbol !== 'undefined' && Symbol.toStringTag\n\nfunction defineProp(\n obj: any,\n name: PropertyKey,\n options: PropertyDescriptor & ThisType\n) {\n if (!hasOwnProperty.call(obj, name)) Object.defineProperty(obj, name, options)\n}\n\nfunction getOverwrittenModule(\n moduleCache: ModuleCache,\n id: ModuleId\n): Module {\n let module = moduleCache[id]\n if (!module) {\n if (createModuleWithDirectionFlag) {\n // set in development modes for hmr support\n module = createModuleWithDirection(id)\n } else {\n module = createModuleObject(id)\n }\n moduleCache[id] = module\n }\n return module\n}\n\n/**\n * Creates the module object. Only done here to ensure all module objects have the same shape.\n */\nfunction createModuleObject(id: ModuleId): Module {\n return {\n exports: {},\n error: undefined,\n id,\n namespaceObject: undefined,\n }\n}\n\nfunction createModuleWithDirection(id: ModuleId): ModuleWithDirection {\n return {\n exports: {},\n error: undefined,\n id,\n namespaceObject: undefined,\n parents: [],\n children: [],\n }\n}\n\ntype BindingTag = 0\nconst BindingTag_Value = 0 as BindingTag\n\n// an arbitrary sequence of bindings as\n// - a prop name\n// - BindingTag_Value, a value to be bound directly, or\n// - 1 or 2 functions to bind as getters and sdetters\ntype EsmBindings = Array<\n string | BindingTag | (() => unknown) | ((v: unknown) => void) | unknown\n>\n\n/**\n * Adds the getters to the exports object.\n */\nfunction esm(exports: Exports, bindings: EsmBindings, dynamic?: boolean) {\n defineProp(exports, '__esModule', { value: true })\n if (toStringTag) defineProp(exports, toStringTag, { value: 'Module' })\n let i = 0\n while (i < bindings.length) {\n const propName = bindings[i++] as string\n const tagOrFunction = bindings[i++]\n if (typeof tagOrFunction === 'number') {\n if (tagOrFunction === BindingTag_Value) {\n defineProp(exports, propName, {\n value: bindings[i++],\n enumerable: true,\n writable: false,\n })\n } else {\n throw new Error(`unexpected tag: ${tagOrFunction}`)\n }\n } else {\n const getterFn = tagOrFunction as () => unknown\n if (typeof bindings[i] === 'function') {\n const setterFn = bindings[i++] as (v: unknown) => void\n defineProp(exports, propName, {\n get: getterFn,\n set: setterFn,\n enumerable: true,\n })\n } else {\n defineProp(exports, propName, {\n get: getterFn,\n enumerable: true,\n })\n }\n }\n }\n // The properties defined above are already non-configurable and\n // non-writable, so the namespace's existing exports are effectively\n // immutable. Sealing additionally makes the object non-extensible, matching\n // real ESM-namespace semantics. Modules with dynamic re-exports\n // (`export *` from a CommonJS module) must stay extensible so the dynamic\n // export proxy can surface keys discovered at runtime, so skip the seal for\n // them.\n if (!dynamic) Object.seal(exports)\n}\n\n/**\n * Makes the module an ESM with exports\n */\nfunction esmExport(\n this: TurbopackBaseContext,\n bindings: EsmBindings,\n id: ModuleId | undefined,\n dynamic?: boolean\n) {\n let module: Module\n let exports: Module['exports']\n if (id != null) {\n module = getOverwrittenModule(this.c, id)\n exports = module.exports\n } else {\n module = this.m\n exports = this.e\n }\n module.namespaceObject = exports\n esm(exports, bindings, dynamic)\n}\ncontextPrototype.s = esmExport\n\ntype ReexportedObjects = Record[]\nfunction ensureDynamicExports(\n module: Module,\n exports: Exports\n): ReexportedObjects {\n let reexportedObjects: ReexportedObjects | undefined =\n REEXPORTED_OBJECTS.get(module)\n\n if (!reexportedObjects) {\n REEXPORTED_OBJECTS.set(module, (reexportedObjects = []))\n // Returns the re-exported object that provides `prop` as an own property,\n // or `undefined` if none does. The traps share this logic so they always\n // agree on which keys are synthesized from `reexportedObjects`. `default`\n // is never re-exported by `export *`, so it is never synthesized.\n const reexportOwning = (prop: PropertyKey) => {\n if (prop !== 'default') {\n for (const obj of reexportedObjects!) {\n if (hasOwnProperty.call(obj, prop)) return obj\n }\n }\n return undefined\n }\n // Modules with dynamic re-exports are not sealed by `esm()`, so the\n // target beneath the namespace stays extensible. That is what lets the\n // `ownKeys` and `getOwnPropertyDescriptor` traps legally report keys that\n // exist on `reexportedObjects` but not on the target itself.\n module.exports = module.namespaceObject = new Proxy(exports, {\n get(target, prop) {\n if (\n hasOwnProperty.call(target, prop) ||\n prop === 'default' ||\n prop === '__esModule'\n ) {\n return Reflect.get(target, prop)\n }\n const obj = reexportOwning(prop)\n return obj && Reflect.get(obj, prop)\n },\n // The namespace is read-only, like a real esm namespace object. The\n // re-exported modules can still mutate their own exports (exposed live\n // via `get`), but mutating the namespace itself is rejected. Refusing\n // here, rather than forwarding to the extensible target, also prevents an\n // assignment/definition from shadowing a dynamic re-export. It also\n // prevents delete from removing a static export.\n set() {\n return false\n },\n defineProperty() {\n return false\n },\n deleteProperty() {\n return false\n },\n // The `has` trap ensures that `'exportName' in starImports` will reflect\n // the truth of whether a key is exported.\n has(target, prop) {\n if (Reflect.has(target, prop)) return true\n if (prop === 'default' || prop === '__esModule') return false\n return reexportOwning(prop) !== undefined\n },\n // ownKeys and getOwnPropertyDescriptor together make the keys enumerable.\n // If a value is returned from `ownKeys` but its property descriptor is\n // not enumerable, it will not be visible to iterator methods.\n // Collectively, they allow code like the following:\n //\n // ```\n // // module.js re-exports dynamic CJS exports\n // export * from './legacyModule.cjs'\n //\n // // from another JS file, reference the re-exported dynamic values\n // import * as Namespace from './module.js'\n // Object.keys(Namespace)\n // ```\n ownKeys(target) {\n const keys = Reflect.ownKeys(target)\n for (const obj of reexportedObjects!) {\n for (const key of Reflect.ownKeys(obj)) {\n if (key !== 'default' && !keys.includes(key)) keys.push(key)\n }\n }\n return keys\n },\n getOwnPropertyDescriptor(target, prop) {\n const own = Reflect.getOwnPropertyDescriptor(target, prop)\n if (own || prop === 'default' || prop === '__esModule') return own\n const obj = reexportOwning(prop)\n if (obj) {\n // Synthetic keys don't exist on the target, so they MUST be\n // reported as configurable. However the set/delete traps above will\n // prevent them from actually being changed\n return {\n enumerable: true,\n configurable: true,\n get: () => Reflect.get(obj, prop),\n }\n }\n return undefined\n },\n })\n }\n return reexportedObjects\n}\n\n/**\n * Dynamically exports properties from an object\n */\nfunction dynamicExport(\n this: TurbopackBaseContext,\n object: Record,\n id: ModuleId | undefined\n) {\n let module: Module\n let exports: Exports\n if (id != null) {\n module = getOverwrittenModule(this.c, id)\n exports = module.exports\n } else {\n module = this.m\n exports = this.e\n }\n const reexportedObjects = ensureDynamicExports(module, exports)\n\n if (typeof object === 'object' && object !== null) {\n reexportedObjects.push(object)\n }\n}\ncontextPrototype.j = dynamicExport\n\nfunction exportValue(\n this: TurbopackBaseContext,\n value: any,\n id: ModuleId | undefined\n) {\n let module: Module\n if (id != null) {\n module = getOverwrittenModule(this.c, id)\n } else {\n module = this.m\n }\n module.exports = value\n}\ncontextPrototype.v = exportValue\n\nfunction exportNamespace(\n this: TurbopackBaseContext,\n namespace: any,\n id: ModuleId | undefined\n) {\n let module: Module\n if (id != null) {\n module = getOverwrittenModule(this.c, id)\n } else {\n module = this.m\n }\n module.exports = module.namespaceObject = namespace\n}\ncontextPrototype.n = exportNamespace\n\nfunction createGetter(obj: Record, key: string | symbol) {\n return () => obj[key]\n}\n\n/**\n * @returns prototype of the object\n */\nconst getProto: (obj: any) => any = Object.getPrototypeOf\n ? (obj) => Object.getPrototypeOf(obj)\n : (obj) => obj.__proto__\n\n/** Prototypes that are not expanded for exports */\nconst LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)]\n\n/**\n * @param raw\n * @param ns\n * @param allowExportDefault\n * * `false`: will have the raw module as default export\n * * `true`: will have the default property as default export\n */\nfunction interopEsm(\n raw: Exports,\n ns: EsmNamespaceObject,\n allowExportDefault?: boolean\n) {\n const bindings: EsmBindings = []\n let defaultLocation = -1\n for (\n let current = raw;\n (typeof current === 'object' || typeof current === 'function') &&\n !LEAF_PROTOTYPES.includes(current);\n current = getProto(current)\n ) {\n for (const key of Object.getOwnPropertyNames(current)) {\n bindings.push(key, createGetter(raw, key))\n if (defaultLocation === -1 && key === 'default') {\n defaultLocation = bindings.length - 1\n }\n }\n }\n\n // this is not really correct\n // we should set the `default` getter if the imported module is a `.cjs file`\n if (!(allowExportDefault && defaultLocation >= 0)) {\n // Replace the binding with one for the namespace itself in order to preserve iteration order.\n if (defaultLocation >= 0) {\n // Replace the getter with the value\n bindings.splice(defaultLocation, 1, BindingTag_Value, raw)\n } else {\n bindings.push('default', BindingTag_Value, raw)\n }\n }\n\n esm(ns, bindings)\n return ns\n}\n\nfunction createNS(raw: Module['exports']): EsmNamespaceObject {\n if (typeof raw === 'function') {\n return function (this: any, ...args: any[]) {\n return raw.apply(this, args)\n }\n } else {\n return Object.create(null)\n }\n}\n\nfunction esmImport(\n this: TurbopackBaseContext,\n id: ModuleId\n): Exclude {\n const module = getOrInstantiateModuleFromParent(id, this.m)\n\n // any ES module has to have `module.namespaceObject` defined.\n if (module.namespaceObject) return module.namespaceObject\n\n // only ESM can be an async module, so we don't need to worry about exports being a promise here.\n const raw = module.exports\n return (module.namespaceObject = interopEsm(\n raw,\n createNS(raw),\n raw && (raw as any).__esModule\n ))\n}\ncontextPrototype.i = esmImport\n\nfunction asyncLoader(\n this: TurbopackBaseContext,\n moduleId: ModuleId\n): Promise {\n const loader = this.r(moduleId) as (\n importFunction: EsmImport\n ) => Promise\n return loader(esmImport.bind(this))\n}\ncontextPrototype.A = asyncLoader\n\n// Add a simple runtime require so that environments without one can still pass\n// `typeof require` CommonJS checks so that exports are correctly registered.\nconst runtimeRequire =\n // @ts-ignore\n typeof require === 'function'\n ? // @ts-ignore\n require\n : function require() {\n throw new Error('Unexpected use of runtime require')\n }\ncontextPrototype.t = runtimeRequire\n\nfunction commonJsRequire(\n this: TurbopackBaseContext,\n id: ModuleId\n): Exports {\n return getOrInstantiateModuleFromParent(id, this.m).exports\n}\ncontextPrototype.r = commonJsRequire\n\n/**\n * Remove fragments and query parameters since they are never part of the context map keys\n *\n * This matches how we parse patterns at resolving time. Arguably we should only do this for\n * strings passed to `import` but the resolve does it for `import` and `require` and so we do\n * here as well.\n */\nfunction parseRequest(request: string): string {\n // Per the URI spec fragments can contain `?` characters, so we should trim it off first\n // https://datatracker.ietf.org/doc/html/rfc3986#section-3.5\n const hashIndex = request.indexOf('#')\n if (hashIndex !== -1) {\n request = request.substring(0, hashIndex)\n }\n\n const queryIndex = request.indexOf('?')\n if (queryIndex !== -1) {\n request = request.substring(0, queryIndex)\n }\n\n return request\n}\n/**\n * `require.context` and require/import expression runtime.\n */\nfunction moduleContext(map: ModuleContextMap): ModuleContext {\n function moduleContext(id: string): Exports {\n id = parseRequest(id)\n if (hasOwnProperty.call(map, id)) {\n return map[id].module()\n }\n\n const e = new Error(`Cannot find module '${id}'`)\n ;(e as any).code = 'MODULE_NOT_FOUND'\n throw e\n }\n\n moduleContext.keys = (): string[] => {\n return Object.keys(map)\n }\n\n moduleContext.resolve = (id: string): ModuleId => {\n id = parseRequest(id)\n if (hasOwnProperty.call(map, id)) {\n return map[id].id()\n }\n\n const e = new Error(`Cannot find module '${id}'`)\n ;(e as any).code = 'MODULE_NOT_FOUND'\n throw e\n }\n\n moduleContext.import = async (id: string) => {\n return await (moduleContext(id) as Promise)\n }\n\n return moduleContext\n}\ncontextPrototype.f = moduleContext\n\n/**\n * Returns the path of a chunk defined by its data.\n */\nfunction getChunkPath(chunkData: ChunkData): ChunkPath {\n return typeof chunkData === 'string' ? chunkData : chunkData.path\n}\n\n// Load the CompressedmoduleFactories of a chunk into the `moduleFactories` Map.\n// The CompressedModuleFactories format is\n// - 1 or more module ids\n// - a module factory function\n// So walking this is a little complex but the flat structure is also fast to\n// traverse, we can use `typeof` operators to distinguish the two cases.\nfunction installCompressedModuleFactories(\n chunkModules: CompressedModuleFactories,\n offset: number,\n moduleFactories: ModuleFactories,\n newModuleId?: (id: ModuleId) => void\n) {\n let i = offset\n while (i < chunkModules.length) {\n let end = i + 1\n // Find our factory function\n while (\n end < chunkModules.length &&\n typeof chunkModules[end] !== 'function'\n ) {\n end++\n }\n if (end === chunkModules.length) {\n throw new Error('malformed chunk format, expected a factory function')\n }\n\n // Install the factory for each module ID that doesn't already have one.\n // When some IDs in this group already have a factory, reuse that existing\n // group factory for the missing IDs to keep all IDs in the group consistent.\n // Otherwise, install the factory from this chunk.\n const moduleFactoryFn = chunkModules[end] as Function\n let existingGroupFactory: Function | undefined = undefined\n for (let j = i; j < end; j++) {\n const id = chunkModules[j] as ModuleId\n const existingFactory = moduleFactories.get(id)\n if (existingFactory) {\n existingGroupFactory = existingFactory\n break\n }\n }\n const factoryToInstall = existingGroupFactory ?? moduleFactoryFn\n\n let didInstallFactory = false\n for (let j = i; j < end; j++) {\n const id = chunkModules[j] as ModuleId\n if (!moduleFactories.has(id)) {\n if (!didInstallFactory) {\n if (factoryToInstall === moduleFactoryFn) {\n applyModuleFactoryName(moduleFactoryFn)\n }\n didInstallFactory = true\n }\n moduleFactories.set(id, factoryToInstall)\n newModuleId?.(id)\n }\n }\n i = end + 1 // end is pointing at the last factory advance to the next id or the end of the array.\n }\n}\n\n/**\n * A pseudo \"fake\" URL object to resolve to its relative path.\n *\n * When UrlRewriteBehavior is set to relative, calls to the `new URL()` will construct url without base using this\n * runtime function to generate context-agnostic urls between different rendering context, i.e ssr / client to avoid\n * hydration mismatch.\n *\n * This is based on webpack's existing implementation:\n * https://github.com/webpack/webpack/blob/87660921808566ef3b8796f8df61bd79fc026108/lib/runtime/RelativeUrlRuntimeModule.js\n */\nconst relativeURL = function relativeURL(this: any, inputUrl: string) {\n const realUrl = new URL(inputUrl, 'x:/')\n const values: Record = {}\n for (const key in realUrl) values[key] = (realUrl as any)[key]\n values.href = inputUrl\n values.pathname = inputUrl.replace(/[?#].*/, '')\n values.origin = values.protocol = ''\n values.toString = values.toJSON = (..._args: Array) => inputUrl\n for (const key in values)\n Object.defineProperty(this, key, {\n enumerable: true,\n configurable: true,\n value: values[key],\n })\n}\nrelativeURL.prototype = URL.prototype\ncontextPrototype.U = relativeURL\n\n/**\n * Utility function to ensure all variants of an enum are handled.\n */\nfunction invariant(never: never, computeMessage: (arg: any) => string): never {\n throw new Error(`Invariant: ${computeMessage(never)}`)\n}\n\n/**\n * Constructs an error message for when a module factory is not available.\n */\nfunction factoryNotAvailableMessage(\n moduleId: ModuleId,\n sourceType: SourceType,\n sourceData: SourceData\n): string {\n let instantiationReason: string\n switch (sourceType) {\n case SourceType.Runtime:\n instantiationReason = `as a runtime entry of chunk ${sourceData}`\n break\n case SourceType.Parent:\n instantiationReason = `because it was required from module ${sourceData}`\n break\n case SourceType.Update:\n instantiationReason = 'because of an HMR update'\n break\n default:\n invariant(\n sourceType,\n (sourceType) => `Unknown source type: ${sourceType}`\n )\n }\n return `Module ${moduleId} was instantiated ${instantiationReason}, but the module factory is not available.`\n}\n\n/**\n * A stub function to make `require` available but non-functional in ESM.\n */\nfunction requireStub(_moduleId: ModuleId): never {\n throw new Error('dynamic usage of require is not supported')\n}\ncontextPrototype.z = requireStub\n\n// Make `globalThis` available to the module in a way that cannot be shadowed by a local variable.\ncontextPrototype.g = globalThis\n\ntype ContextConstructor = {\n new (module: Module, exports: Exports): TurbopackBaseContext\n}\n\nfunction applyModuleFactoryName(factory: Function) {\n // Give the module factory a nice name to improve stack traces.\n Object.defineProperty(factory, 'name', {\n value: 'module evaluation',\n })\n}\n"],"names":["SourceType","createModuleWithDirectionFlag","REEXPORTED_OBJECTS","WeakMap","Context","module","exports","m","e","contextPrototype","prototype","hasOwnProperty","Object","toStringTag","Symbol","defineProp","obj","name","options","call","defineProperty","getOverwrittenModule","moduleCache","id","createModuleWithDirection","createModuleObject","error","undefined","namespaceObject","parents","children","BindingTag_Value","esm","bindings","dynamic","value","i","length","propName","tagOrFunction","enumerable","writable","Error","getterFn","setterFn","get","set","seal","esmExport","c","s","ensureDynamicExports","reexportedObjects","reexportOwning","prop","Proxy","target","Reflect","deleteProperty","has","ownKeys","keys","key","includes","push","getOwnPropertyDescriptor","own","configurable","dynamicExport","object","j","exportValue","v","exportNamespace","namespace","n","createGetter","getProto","getPrototypeOf","__proto__","LEAF_PROTOTYPES","interopEsm","raw","ns","allowExportDefault","defaultLocation","current","getOwnPropertyNames","splice","createNS","args","apply","create","esmImport","getOrInstantiateModuleFromParent","__esModule","asyncLoader","moduleId","loader","r","bind","A","runtimeRequire","require","require1","t","commonJsRequire","parseRequest","request","hashIndex","indexOf","substring","queryIndex","moduleContext","map","code","resolve","import","f","getChunkPath","chunkData","path","installCompressedModuleFactories","chunkModules","offset","moduleFactories","newModuleId","end","moduleFactoryFn","existingGroupFactory","existingFactory","factoryToInstall","didInstallFactory","applyModuleFactoryName","relativeURL","inputUrl","realUrl","URL","values","href","pathname","replace","origin","protocol","toString","toJSON","_args","U","invariant","never","computeMessage","factoryNotAvailableMessage","sourceType","sourceData","instantiationReason","requireStub","_moduleId","z","g","globalThis","factory"],"mappings":"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","ignoreList":[0]}},
- {"offset": {"line": 547, "column": 0}, "map": {"version":3,"sources":["turbopack:///[turbopack]/shared/runtime/async-module.ts"],"sourcesContent":["/// \n/// \n\n/**\n * Top-level-await / async-module machinery. This is only included in the runtime\n * when the module graph actually contains an async module (a module with\n * top-level await, or one that transitively depends on one). When no async\n * module is present, the chunk items never reference `__turbopack_context__.a`,\n * so this whole file can be omitted.\n *\n * everything below is adapted from webpack\n * https://github.com/webpack/webpack/blob/6be4065ade1e252c1d8dcba4af0f43e32af1bdc1/lib/runtime/AsyncModuleRuntimeModule.js#L13\n */\n\nconst turbopackQueues = Symbol('turbopack queues')\nconst turbopackExports = Symbol('turbopack exports')\nconst turbopackError = Symbol('turbopack error')\n\nconst enum QueueStatus {\n Unknown = -1,\n Unresolved = 0,\n Resolved = 1,\n}\n\ntype AsyncQueueFn = (() => void) & { queueCount: number }\ntype AsyncQueue = AsyncQueueFn[] & {\n status: QueueStatus\n}\n\ntype Dep = Exports | AsyncModulePromise | Promise\n\ntype AsyncModuleExt = {\n [turbopackQueues]: (fn: (queue: AsyncQueue) => void) => void\n [turbopackExports]: Exports\n [turbopackError]?: any\n}\n\ntype AsyncModulePromise = Promise & AsyncModuleExt\n\nfunction isPromise(maybePromise: any): maybePromise is Promise {\n return (\n maybePromise != null &&\n typeof maybePromise === 'object' &&\n 'then' in maybePromise &&\n typeof maybePromise.then === 'function'\n )\n}\n\nfunction isAsyncModuleExt(obj: T): obj is AsyncModuleExt & T {\n return turbopackQueues in obj\n}\n\nfunction createPromise() {\n let resolve: (value: T | PromiseLike) => void\n let reject: (reason?: any) => void\n\n const promise = new Promise((res, rej) => {\n reject = rej\n resolve = res\n })\n\n return {\n promise,\n resolve: resolve!,\n reject: reject!,\n }\n}\n\nfunction resolveQueue(queue?: AsyncQueue) {\n if (queue && queue.status !== QueueStatus.Resolved) {\n queue.status = QueueStatus.Resolved\n queue.forEach((fn) => fn.queueCount--)\n queue.forEach((fn) => (fn.queueCount-- ? fn.queueCount++ : fn()))\n }\n}\n\nfunction wrapDeps(deps: Dep[]): AsyncModuleExt[] {\n return deps.map((dep): AsyncModuleExt => {\n if (dep !== null && typeof dep === 'object') {\n if (isAsyncModuleExt(dep)) return dep\n if (isPromise(dep)) {\n const queue: AsyncQueue = Object.assign([], {\n status: QueueStatus.Unresolved,\n })\n\n const obj: AsyncModuleExt = {\n [turbopackExports]: {},\n [turbopackQueues]: (fn: (queue: AsyncQueue) => void) => fn(queue),\n }\n\n dep.then(\n (res) => {\n obj[turbopackExports] = res\n resolveQueue(queue)\n },\n (err) => {\n obj[turbopackError] = err\n resolveQueue(queue)\n }\n )\n\n return obj\n }\n }\n\n return {\n [turbopackExports]: dep,\n [turbopackQueues]: () => {},\n }\n })\n}\n\nfunction asyncModule(\n this: TurbopackBaseContext,\n body: (\n handleAsyncDependencies: (\n deps: Dep[]\n ) => Exports[] | Promise<() => Exports[]>,\n asyncResult: (err?: any) => void\n ) => void,\n hasAwait: boolean\n) {\n const module = this.m\n const queue: AsyncQueue | undefined = hasAwait\n ? Object.assign([], { status: QueueStatus.Unknown })\n : undefined\n\n const depQueues: Set = new Set()\n\n const { resolve, reject, promise: rawPromise } = createPromise()\n\n const promise: AsyncModulePromise = Object.assign(rawPromise, {\n [turbopackExports]: module.exports,\n [turbopackQueues]: (fn) => {\n queue && fn(queue)\n depQueues.forEach(fn)\n promise['catch'](() => {})\n },\n } satisfies AsyncModuleExt)\n\n const attributes: PropertyDescriptor = {\n get(): any {\n return promise\n },\n set(v: any) {\n // Calling `esmExport` leads to this.\n if (v !== promise) {\n promise[turbopackExports] = v\n }\n },\n }\n\n Object.defineProperty(module, 'exports', attributes)\n Object.defineProperty(module, 'namespaceObject', attributes)\n\n function handleAsyncDependencies(deps: Dep[]) {\n const currentDeps = wrapDeps(deps)\n\n const getResult = () =>\n currentDeps.map((d) => {\n if (d[turbopackError]) throw d[turbopackError]\n return d[turbopackExports]\n })\n\n const { promise, resolve } = createPromise<() => Exports[]>()\n\n const fn: AsyncQueueFn = Object.assign(() => resolve(getResult), {\n queueCount: 0,\n })\n\n function fnQueue(q: AsyncQueue) {\n if (q !== queue && !depQueues.has(q)) {\n depQueues.add(q)\n if (q && q.status === QueueStatus.Unresolved) {\n fn.queueCount++\n q.push(fn)\n }\n }\n }\n\n currentDeps.map((dep) => dep[turbopackQueues](fnQueue))\n\n return fn.queueCount ? promise : getResult()\n }\n\n function asyncResult(err?: any) {\n if (err) {\n reject((promise[turbopackError] = err))\n } else {\n resolve(promise[turbopackExports])\n }\n\n resolveQueue(queue)\n }\n\n body(handleAsyncDependencies, asyncResult)\n\n if (queue && queue.status === QueueStatus.Unknown) {\n queue.status = QueueStatus.Unresolved\n }\n}\ncontextPrototype.a = asyncModule\n"],"names":["turbopackQueues","Symbol","turbopackExports","turbopackError","isPromise","maybePromise","then","isAsyncModuleExt","obj","createPromise","resolve","reject","promise","Promise","res","rej","resolveQueue","queue","status","forEach","fn","queueCount","wrapDeps","deps","map","dep","Object","assign","err","asyncModule","body","hasAwait","module","m","undefined","depQueues","Set","rawPromise","exports","attributes","get","set","v","defineProperty","handleAsyncDependencies","currentDeps","getResult","d","fnQueue","q","has","add","push","asyncResult","contextPrototype","a"],"mappings":"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","ignoreList":[0]}},
- {"offset": {"line": 679, "column": 0}, "map": {"version":3,"sources":["turbopack:///[turbopack]/browser/runtime/base/runtime-base.ts"],"sourcesContent":["/**\n * This file contains runtime types and functions that are shared between all\n * Turbopack *browser* ECMAScript runtimes.\n *\n * It will be appended to the runtime code of each runtime right after the\n * shared runtime utils.\n */\n\n/* eslint-disable @typescript-eslint/no-unused-vars */\n\n/// \n/// \n\n// Used in WebWorkers to tell the runtime about the chunk suffix\ndeclare var TURBOPACK_ASSET_SUFFIX: string\n// Used in WebWorkers to tell the runtime about the current chunk url since it\n// can't be detected via `document.currentScript`. Note it's stored in reversed\n// order to use `push` and `pop`\ndeclare var TURBOPACK_NEXT_CHUNK_URLS: ChunkUrl[] | undefined\n// Used in WebWorkers to override the regular chunk base path with the base\n// used for the worker entrypoint and its initial chunks.\ndeclare var TURBOPACK_CHUNK_BASE_PATH: string | undefined\n\n// Injected by rust code\ndeclare var CHUNK_BASE_PATH: string\ndeclare var ASSET_SUFFIX: string\ndeclare var CROSS_ORIGIN: 'anonymous' | 'use-credentials' | null\ndeclare var CHUNK_LOAD_RETRY_MAX_ATTEMPTS: number\ndeclare var CHUNK_LOAD_RETRY_BASE_DELAY_MS: number\ndeclare var CHUNK_LOAD_RETRY_MAX_JITTER_MS: number\ndeclare const SUPPORT_COMPONENT_CHUNKS: boolean\n\ninterface TurbopackBrowserBaseContext extends TurbopackBaseContext {\n R: ResolvePathFromModule\n}\n\nconst browserContextPrototype =\n Context.prototype as TurbopackBrowserBaseContext\n\nconst RUNTIME_CHUNK_BASE_PATH =\n typeof TURBOPACK_CHUNK_BASE_PATH === 'string'\n ? TURBOPACK_CHUNK_BASE_PATH\n : CHUNK_BASE_PATH\n\n// Provided by build or dev base\ndeclare function instantiateModule(\n id: ModuleId,\n sourceType: SourceType,\n sourceData: SourceData\n): Module\n\ntype RuntimeParams = {\n otherChunks: ChunkData[]\n runtimeModuleIds: ModuleId[]\n}\n\ntype ChunkRegistrationChunk =\n | ChunkPath\n | { getAttribute: (name: string) => string | null }\n | undefined\n\ntype ChunkRegistration = [\n chunkPath: ChunkRegistrationChunk,\n ...([RuntimeParams] | CompressedModuleFactories),\n]\n\ntype ChunkList = {\n script: ChunkRegistrationChunk\n chunks: ChunkData[]\n source: 'entry' | 'dynamic'\n}\n\ninterface RuntimeBackend {\n /**\n * Registers a chunk. `chunk` is `undefined` for an inlined entry-only registration\n * (no source chunk): the params' other chunks are loaded and its runtime modules run\n * with no self chunk identity.\n */\n registerChunk: (\n chunk: ChunkPath | ChunkScript | undefined,\n params?: RuntimeParams\n ) => void\n /**\n * Returns the same Promise for the same chunk URL.\n */\n loadChunkCached: (sourceType: SourceType, chunkUrl: ChunkUrl) => Promise\n}\n\ninterface DevRuntimeBackend {\n reloadChunk?: (chunkUrl: ChunkUrl) => Promise\n unloadChunk?: (chunkUrl: ChunkUrl) => void\n restart: () => void\n}\n\nconst moduleFactories: ModuleFactories = new Map()\ncontextPrototype.M = moduleFactories\n\nconst availableModules: Map | true> = new Map()\n\nconst availableModuleChunks: Map | true> = new Map()\n\n// Registry mapping a merged chunk's path to its constituent component chunk paths.\nconst chunkComponents: Map = new Map()\n\n// Registry mapping a component chunk's path to its size in bytes, used by the\n// split-vs-whole cost heuristic.\nconst componentChunkSizes: Map = new Map()\n\nfunction registerComponentChunkSizes(\n componentChunks: ChunkPath[],\n sizes: number[]\n): void {\n for (let i = 0; i < componentChunks.length; i++) {\n const size = sizes[i]\n if (size !== undefined) {\n componentChunkSizes.set(componentChunks[i], size)\n }\n }\n}\n\ntype ChunkUrlOrMerged = ChunkUrl | [ChunkUrl, ChunkPath[], number[]]\n\n// Memoizes the composite promise returned for a merged chunk loaded by URL, keyed by URL.\nconst splitChunkPromises: Map> = new Map()\n\nfunction loadChunk(\n this: TurbopackBrowserBaseContext,\n chunkData: ChunkData\n): Promise {\n return loadChunkInternal(SourceType.Parent, this.m.id, chunkData)\n}\nbrowserContextPrototype.l = loadChunk\n\n// `chunkPath` is the source chunk; it is `undefined` for entry-only registrations,\n// which have no self chunk.\nfunction loadInitialChunk(\n chunkPath: ChunkPath | undefined,\n chunkData: ChunkData\n) {\n return loadChunkInternal(SourceType.Runtime, chunkPath, chunkData)\n}\n\nasync function loadChunkInternal(\n sourceType: SourceType,\n sourceData: SourceData,\n chunkData: ChunkData\n): Promise {\n if (typeof chunkData === 'string') {\n return loadChunkPath(sourceType, sourceData, chunkData)\n }\n\n const includedList = chunkData.included || []\n const modulesPromises = includedList.map((included) => {\n if (moduleFactories.has(included)) return true\n return availableModules.get(included)\n })\n if (modulesPromises.length > 0 && modulesPromises.every((p) => p)) {\n // When all included items are already loaded or loading, we can skip loading ourselves\n await Promise.all(modulesPromises)\n return\n }\n\n let promise: Promise\n if (SUPPORT_COMPONENT_CHUNKS) {\n const componentChunks = chunkData.moduleChunks || []\n // We already have this chunk's component list inline (chunkData.moduleChunks) and split on it\n // here, so the whole-chunk fallback uses loadChunkByUrlWhole to skip loadChunkByUrlInternal's\n // chunkComponents-registry lookup, which would just repeat the same split decision.\n promise = loadComponentChunksOrWhole(\n sourceType,\n sourceData,\n componentChunks,\n getChunkRelativeUrl(chunkData.path)\n )\n } else {\n promise = loadChunkByUrlWhole(\n sourceType,\n sourceData,\n getChunkRelativeUrl(chunkData.path)\n )\n }\n\n for (const included of includedList) {\n if (!availableModules.has(included)) {\n // It might be better to race old and new promises, but it's rare that the new promise will be faster than a request started earlier.\n // In production it's even more rare, because the chunk optimization tries to deduplicate modules anyway.\n availableModules.set(included, promise)\n }\n }\n\n await promise\n}\n\n/**\n * Approximate cost of an extra HTTP request, expressed in emitted (minified, uncompressed) chunk\n * bytes, used to decide whether splitting a merged chunk into individually-cached component\n * chunks is worthwhile.\n */\nconst REQUEST_COST_BYTES = 20_000\n\n/**\n * Decides whether to load a merged chunk's component chunks individually instead of the whole\n * merged chunk, weighing the bytes saved (the available components we avoid re-downloading)\n * against the extra network requests splitting incurs.\n *\n * Splitting issues one request per unavailable component vs. a single request for the merged\n * chunk, so it adds `unavailableCount - 1` extra requests. When at most one component needs the\n * network, splitting never costs more requests than the merged load (and transfers fewer bytes),\n * so it always wins. Otherwise it's only worth it when the available bytes exceed the extra\n * request cost.\n */\nfunction shouldLoadComponentChunks(\n availableBytes: number,\n unavailableCount: number\n): boolean {\n if (unavailableCount <= 1) {\n return true\n }\n return availableBytes > REQUEST_COST_BYTES * (unavailableCount - 1)\n}\n\n/**\n * Loads a chunk's component chunks individually when enough of them are already available\n * in memory (avoiding re-downloading the ones we have, per `shouldLoadComponentChunks`),\n * otherwise loads the whole chunk from `chunkUrl` and records its component chunks as available.\n */\nfunction loadComponentChunksOrWhole(\n sourceType: SourceType,\n sourceData: SourceData,\n componentChunks: ChunkPath[],\n chunkUrl: ChunkUrl\n): Promise {\n const componentChunkPromises: Array | true> = []\n let availableBytes = 0\n let unavailableCount = 0\n for (const componentChunk of componentChunks) {\n const available = availableModuleChunks.get(componentChunk)\n if (available) {\n componentChunkPromises.push(available)\n availableBytes += componentChunkSizes.get(componentChunk) ?? 0\n } else {\n unavailableCount++\n }\n }\n\n if (\n componentChunkPromises.length > 0 &&\n shouldLoadComponentChunks(availableBytes, unavailableCount)\n ) {\n // Enough component chunks are already loaded or loading that splitting saves more\n // bytes than the extra requests cost.\n for (const componentChunk of componentChunks) {\n if (!availableModuleChunks.has(componentChunk)) {\n const promise = loadChunkPath(sourceType, sourceData, componentChunk)\n availableModuleChunks.set(componentChunk, promise)\n componentChunkPromises.push(promise)\n }\n }\n return Promise.all(componentChunkPromises)\n }\n\n // Not enough is available in memory for splitting to pay off. Load the\n // whole chunk in a single request and record its component chunks as available.\n const promise = loadChunkByUrlWhole(sourceType, sourceData, chunkUrl)\n for (const componentChunk of componentChunks) {\n if (!availableModuleChunks.has(componentChunk)) {\n availableModuleChunks.set(componentChunk, promise)\n }\n }\n return promise\n}\n\nconst loadedChunk = Promise.resolve(undefined)\nconst instrumentedBackendLoadChunks = new WeakMap<\n Promise,\n Promise | typeof loadedChunk\n>()\n// Do not make this async. React relies on referential equality of the returned Promise.\nfunction loadChunkByUrl(\n this: TurbopackBrowserBaseContext,\n chunkEntry: ChunkUrlOrMerged\n) {\n return loadChunkByUrlInternal(SourceType.Parent, this.m.id, chunkEntry)\n}\nbrowserContextPrototype.L = loadChunkByUrl\n\n// Do not make this async. React relies on referential equality of the returned Promise.\nfunction loadChunkByUrlInternal(\n sourceType: SourceType,\n sourceData: SourceData,\n chunkEntry: ChunkUrlOrMerged\n): Promise {\n if (SUPPORT_COMPONENT_CHUNKS) {\n // A merged chunk arrives as a `[url, componentChunkPaths, componentChunkSizes]` array. Register\n // the components so a by-URL load of this merged chunk — now or from a later navigation — can\n // be split, and so `registerChunk` can mark them available when the whole chunk loads.\n let chunkUrl: ChunkUrl\n let components: ChunkPath[] | undefined\n if (typeof chunkEntry === 'string') {\n chunkUrl = chunkEntry\n } else {\n let componentSizes: number[]\n ;[chunkUrl, components, componentSizes] = chunkEntry\n registerComponentChunkSizes(components, componentSizes)\n }\n const chunkPath = chunkUrlToPath(chunkUrl)\n if (components !== undefined) {\n chunkComponents.set(chunkPath, components)\n } else {\n // A plain URL may still be a merged chunk we already registered from its array.\n components = chunkComponents.get(chunkPath)\n }\n\n // If we have component chunks for this merged chunk, load only the ones we don't already have\n // instead of the whole merged chunk.\n if (components !== undefined) {\n let promise = splitChunkPromises.get(chunkUrl)\n if (promise === undefined) {\n promise = loadComponentChunksOrWhole(\n sourceType,\n sourceData,\n components,\n chunkUrl\n )\n splitChunkPromises.set(chunkUrl, promise)\n }\n return promise\n }\n\n // This is a non-merged chunk. If its modules were already loaded — e.g. this chunk is a\n // component of a merged chunk fetched on a previous navigation — reuse that load instead of\n // re-downloading.\n const existing = availableModuleChunks.get(chunkPath)\n if (existing !== undefined) {\n return existing === true ? loadedChunk : existing\n }\n const promise = loadChunkByUrlWhole(sourceType, sourceData, chunkUrl)\n availableModuleChunks.set(chunkPath, promise)\n return promise\n }\n\n // Component chunks are disabled, so the chunking context never emits merged arrays and every\n // entry is a plain chunk URL. Load it whole; the backend dedupes repeated URLs.\n return loadChunkByUrlWhole(sourceType, sourceData, chunkEntry as ChunkUrl)\n}\n\n// Convert a chunk URL back to its ChunkPath (strip base path, query/hash, decode), to\n// match the keys stored in `chunkComponents`.\nfunction chunkUrlToPath(chunkUrl: ChunkUrl): ChunkPath {\n const src = decodeURIComponent(chunkUrl.replace(/[?#].*$/, ''))\n return (\n src.startsWith(RUNTIME_CHUNK_BASE_PATH)\n ? src.slice(RUNTIME_CHUNK_BASE_PATH.length)\n : src\n ) as ChunkPath\n}\n\n/**\n * When a merged chunk finishes registering (e.g. an initial-load `