diff --git a/.devcontainer/rust/devcontainer-feature.json b/.devcontainer/rust/devcontainer-feature.json
index 63aec9dbf9363..d173b4d99d3f7 100644
--- a/.devcontainer/rust/devcontainer-feature.json
+++ b/.devcontainer/rust/devcontainer-feature.json
@@ -5,7 +5,7 @@
"dependsOn": {
"ghcr.io/devcontainers/features/rust:1": {
// this should match the `rust-toolchain.toml`
- "version": "nightly-2026-02-05",
+ "version": "nightly-2026-02-18",
"profile": "minimal",
"components": "rustfmt,clippy,rust-analyzer"
}
diff --git a/crates/next-api/src/project.rs b/crates/next-api/src/project.rs
index 32814587bf64c..9bdb7ab6176d6 100644
--- a/crates/next-api/src/project.rs
+++ b/crates/next-api/src/project.rs
@@ -362,6 +362,7 @@ pub struct ProjectOptions {
pub is_persistent_caching_enabled: bool,
}
+#[derive(Default)]
pub struct PartialProjectOptions {
/// A root path from which all files must be nested under. Trying to access
/// a file outside this root will fail. Think of this as a chroot.
diff --git a/crates/next-napi-bindings/src/next_api/project.rs b/crates/next-napi-bindings/src/next_api/project.rs
index c9529c45121ab..d45cdfa790adb 100644
--- a/crates/next-napi-bindings/src/next_api/project.rs
+++ b/crates/next-napi-bindings/src/next_api/project.rs
@@ -1206,27 +1206,6 @@ async fn invalidate_deferred_entry_source_dirs_after_callback(
Ok(())
}
-fn partial_project_options_with_debug_build_paths(
- debug_build_paths: DebugBuildPaths,
-) -> PartialProjectOptions {
- PartialProjectOptions {
- root_path: None,
- project_path: None,
- next_config: None,
- env: None,
- define_env: None,
- watch: None,
- dev: None,
- encryption_key: None,
- build_id: None,
- preview_props: None,
- browserslist_query: None,
- no_mangling: None,
- write_routes_hashes_manifest: None,
- debug_build_paths: Some(debug_build_paths),
- }
-}
-
fn is_deferred_endpoint_group(key: &EndpointGroupKey, deferred_entries: &[RcStr]) -> bool {
if deferred_entries.is_empty() {
return false;
@@ -1353,9 +1332,10 @@ pub async fn project_write_all_entrypoints_to_disk(
let non_deferred_build_paths = phase_build_paths.non_deferred.clone();
tt.run(async move {
container
- .update(partial_project_options_with_debug_build_paths(
- non_deferred_build_paths,
- ))
+ .update(PartialProjectOptions {
+ debug_build_paths: Some(non_deferred_build_paths),
+ ..Default::default()
+ })
.await?;
Ok(())
})
@@ -1425,9 +1405,10 @@ pub async fn project_write_all_entrypoints_to_disk(
let all_build_paths = phase_build_paths.all.clone();
tt.run(async move {
container
- .update(partial_project_options_with_debug_build_paths(
- all_build_paths,
- ))
+ .update(PartialProjectOptions {
+ debug_build_paths: Some(all_build_paths),
+ ..Default::default()
+ })
.await?;
Ok(())
})
diff --git a/lerna.json b/lerna.json
index 0dbeb370d4908..bf4542af2ed87 100644
--- a/lerna.json
+++ b/lerna.json
@@ -15,5 +15,5 @@
"registry": "https://registry.npmjs.org/"
}
},
- "version": "16.2.0-canary.50"
+ "version": "16.2.0-canary.51"
}
\ No newline at end of file
diff --git a/packages/create-next-app/package.json b/packages/create-next-app/package.json
index 0f7cf62100432..6e8f2a87199cd 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.2.0-canary.50",
+ "version": "16.2.0-canary.51",
"keywords": [
"react",
"next",
diff --git a/packages/eslint-config-next/package.json b/packages/eslint-config-next/package.json
index e3fc2b8dc51ec..c1a094d141233 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.2.0-canary.50",
+ "version": "16.2.0-canary.51",
"description": "ESLint configuration used by Next.js.",
"license": "MIT",
"repository": {
@@ -12,7 +12,7 @@
"dist"
],
"dependencies": {
- "@next/eslint-plugin-next": "16.2.0-canary.50",
+ "@next/eslint-plugin-next": "16.2.0-canary.51",
"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 6fb0f33b3cd72..1869a39ea362a 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.2.0-canary.50",
+ "version": "16.2.0-canary.51",
"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 6d8a2852c5600..4b58cec2d4af6 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.2.0-canary.50",
+ "version": "16.2.0-canary.51",
"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 f669efb7eb7d6..b074617fb0144 100644
--- a/packages/font/package.json
+++ b/packages/font/package.json
@@ -1,7 +1,7 @@
{
"name": "@next/font",
"private": true,
- "version": "16.2.0-canary.50",
+ "version": "16.2.0-canary.51",
"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 51317875e773e..44646ea69a133 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.2.0-canary.50",
+ "version": "16.2.0-canary.51",
"main": "index.js",
"types": "index.d.ts",
"license": "MIT",
diff --git a/packages/next-codemod/package.json b/packages/next-codemod/package.json
index 61a0a10755a1f..f289b2daa5868 100644
--- a/packages/next-codemod/package.json
+++ b/packages/next-codemod/package.json
@@ -1,6 +1,6 @@
{
"name": "@next/codemod",
- "version": "16.2.0-canary.50",
+ "version": "16.2.0-canary.51",
"license": "MIT",
"repository": {
"type": "git",
diff --git a/packages/next-env/package.json b/packages/next-env/package.json
index e36dd0ca58d2c..5f99d6e2dc112 100644
--- a/packages/next-env/package.json
+++ b/packages/next-env/package.json
@@ -1,6 +1,6 @@
{
"name": "@next/env",
- "version": "16.2.0-canary.50",
+ "version": "16.2.0-canary.51",
"keywords": [
"react",
"next",
diff --git a/packages/next-mdx/package.json b/packages/next-mdx/package.json
index 1c011660948e3..b294c5ce030fa 100644
--- a/packages/next-mdx/package.json
+++ b/packages/next-mdx/package.json
@@ -1,6 +1,6 @@
{
"name": "@next/mdx",
- "version": "16.2.0-canary.50",
+ "version": "16.2.0-canary.51",
"main": "index.js",
"license": "MIT",
"repository": {
diff --git a/packages/next-plugin-storybook/package.json b/packages/next-plugin-storybook/package.json
index 996870eb3b4ee..b93add3a54ee5 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.2.0-canary.50",
+ "version": "16.2.0-canary.51",
"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 6f2fbe0db6552..add0540f85125 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.2.0-canary.50",
+ "version": "16.2.0-canary.51",
"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 ee3e9f2c54376..a7ec189017ff6 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.2.0-canary.50",
+ "version": "16.2.0-canary.51",
"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 5dc26ce2b2565..b4f4070f8e60a 100644
--- a/packages/next-routing/package.json
+++ b/packages/next-routing/package.json
@@ -1,6 +1,6 @@
{
"name": "@next/routing",
- "version": "16.2.0-canary.50",
+ "version": "16.2.0-canary.51",
"keywords": [
"react",
"next",
diff --git a/packages/next-rspack/package.json b/packages/next-rspack/package.json
index e1ec315a17d0c..c6eb114dc4a14 100644
--- a/packages/next-rspack/package.json
+++ b/packages/next-rspack/package.json
@@ -1,6 +1,6 @@
{
"name": "next-rspack",
- "version": "16.2.0-canary.50",
+ "version": "16.2.0-canary.51",
"repository": {
"url": "vercel/next.js",
"directory": "packages/next-rspack"
diff --git a/packages/next-swc/package.json b/packages/next-swc/package.json
index dfa235bdc1d27..b93d3d64cfb2d 100644
--- a/packages/next-swc/package.json
+++ b/packages/next-swc/package.json
@@ -1,6 +1,6 @@
{
"name": "@next/swc",
- "version": "16.2.0-canary.50",
+ "version": "16.2.0-canary.51",
"private": true,
"files": [
"native/"
diff --git a/packages/next/package.json b/packages/next/package.json
index 2b744a0f9ab92..79b1ac26db301 100644
--- a/packages/next/package.json
+++ b/packages/next/package.json
@@ -1,6 +1,6 @@
{
"name": "next",
- "version": "16.2.0-canary.50",
+ "version": "16.2.0-canary.51",
"description": "The React Framework",
"main": "./dist/server/next.js",
"license": "MIT",
@@ -97,7 +97,7 @@
]
},
"dependencies": {
- "@next/env": "16.2.0-canary.50",
+ "@next/env": "16.2.0-canary.51",
"@swc/helpers": "0.5.15",
"baseline-browser-mapping": "^2.9.19",
"caniuse-lite": "^1.0.30001579",
@@ -162,11 +162,11 @@
"@modelcontextprotocol/sdk": "1.18.1",
"@mswjs/interceptors": "0.23.0",
"@napi-rs/triples": "1.2.0",
- "@next/font": "16.2.0-canary.50",
- "@next/polyfill-module": "16.2.0-canary.50",
- "@next/polyfill-nomodule": "16.2.0-canary.50",
- "@next/react-refresh-utils": "16.2.0-canary.50",
- "@next/swc": "16.2.0-canary.50",
+ "@next/font": "16.2.0-canary.51",
+ "@next/polyfill-module": "16.2.0-canary.51",
+ "@next/polyfill-nomodule": "16.2.0-canary.51",
+ "@next/react-refresh-utils": "16.2.0-canary.51",
+ "@next/swc": "16.2.0-canary.51",
"@opentelemetry/api": "1.6.0",
"@playwright/test": "1.51.1",
"@rspack/core": "1.6.7",
diff --git a/packages/next/src/server/app-render/app-render.tsx b/packages/next/src/server/app-render/app-render.tsx
index 26c1c8b2c84da..e6967bda4bc1d 100644
--- a/packages/next/src/server/app-render/app-render.tsx
+++ b/packages/next/src/server/app-render/app-render.tsx
@@ -223,7 +223,6 @@ import { ImageConfigContext } from '../../shared/lib/image-config-context.shared
import { imageConfigDefault } from '../../shared/lib/image-config'
import { RenderStage, StagedRenderingController } from './staged-rendering'
import {
- anySegmentHasRuntimePrefetchEnabled,
isPageAllowedToBlock,
anySegmentNeedsInstantValidation,
} from './instant-validation/instant-config'
@@ -754,24 +753,19 @@ async function stagedRenderToReadableStreamWithoutCachesInDev(
// which relies on mechanisms we've set up for staged rendering,
// so we do a 2-task version (Static -> Dynamic) instead.
- // We aren't doing any validation in this kind of render so we say there
- // is not runtime prefetch regardless of whether there is or not
- const hasRuntimePrefetch = false
-
// We aren't filling caches so we don't need to abort this render, it'll
// stream in a single pass
const abortSignal = null
- const stageController = new StagedRenderingController(
- abortSignal,
- hasRuntimePrefetch
- )
+ const stageController = new StagedRenderingController(abortSignal)
const environmentName = () => {
const currentStage = stageController.currentStage
switch (currentStage) {
case RenderStage.Before:
+ case RenderStage.EarlyStatic:
case RenderStage.Static:
return 'Prerender'
+ case RenderStage.EarlyRuntime:
case RenderStage.Runtime:
case RenderStage.Dynamic:
case RenderStage.Abandoned:
@@ -914,8 +908,7 @@ async function generateDynamicFlightRenderResultWithStagesInDev(
const {
stream: serverStream,
accumulatedChunksPromise,
- staticInterruptReason,
- runtimeInterruptReason,
+ syncInterruptReason,
startTime,
staticStageEndTime,
runtimeStageEndTime,
@@ -940,8 +933,7 @@ async function generateDynamicFlightRenderResultWithStagesInDev(
{ dim: true },
spawnStaticShellValidationInDev,
accumulatedChunksPromise,
- staticInterruptReason,
- runtimeInterruptReason,
+ syncInterruptReason,
startTime,
staticStageEndTime,
runtimeStageEndTime,
@@ -1346,8 +1338,7 @@ async function finalRuntimeServerPrerender(
)
const finalStageController = new StagedRenderingController(
- finalServerController.signal,
- true
+ finalServerController.signal
)
const finalServerPrerenderStore: PrerenderStoreModernRuntime = {
@@ -1371,7 +1362,7 @@ async function finalRuntimeServerPrerender(
hmrRefreshHash: undefined,
// TODO: Enable vary params tracking for runtime prefetches.
varyParamsAccumulator: null,
- // Used to separate the "Static" stage from the "Runtime" stage.
+ // Used to separate the stages in the 5-task pipeline.
stagedRendering: finalStageController,
// These are not present in regular prerenders, but allowed in a runtime prerender.
headers,
@@ -1389,7 +1380,10 @@ async function finalRuntimeServerPrerender(
let prerenderIsPending = true
const result = await runInSequentialTasks(
async () => {
- // Static stage
+ // EarlyStatic stage: render begins.
+ // Runtime-prefetchable segments render immediately.
+ // Non-prefetchable segments are gated until the Static stage.
+ finalStageController.advanceStage(RenderStage.EarlyStatic)
const prerenderResult = await workUnitAsyncStorage.run(
finalServerPrerenderStore,
ComponentMod.prerender,
@@ -1405,13 +1399,18 @@ async function finalRuntimeServerPrerender(
return prerenderResult
},
() => {
- // Advance to the runtime stage.
- //
- // We make runtime APIs hang during the first task (above), and unblock them in the following task (here).
- // This makes sure that, at this point, we'll have finished all the static parts (what we'd prerender statically).
- // We know that they don't contain any incorrect sync IO, because that'd have caused a build error.
- // After we unblock Runtime APIs, if we encounter sync IO (e.g. `await cookies(); Date.now()`),
- // we'll abort, but we'll produce at least as much output as a static prerender would.
+ // Advance to Static stage: resolve promise holding back
+ // non-prefetchable segments so they can begin rendering.
+ finalStageController.advanceStage(RenderStage.Static)
+ },
+ () => {
+ // Advance to EarlyRuntime stage: resolve cookies/headers for
+ // runtime-prefetchable segments. Sync IO is checked here.
+ finalStageController.advanceStage(RenderStage.EarlyRuntime)
+ },
+ () => {
+ // Advance to Runtime stage: resolve cookies/headers for
+ // non-prefetchable segments. Sync IO is allowed here.
finalStageController.advanceStage(RenderStage.Runtime)
},
() => {
@@ -1554,6 +1553,7 @@ async function getRSCPayload(
ctx,
loaderTree: tree,
parentParams: {},
+ parentRuntimePrefetchable: false,
injectedCSS,
injectedJS,
injectedFontPreloadTags,
@@ -2776,8 +2776,7 @@ async function renderToStream(
const {
stream: serverStream,
accumulatedChunksPromise,
- staticInterruptReason,
- runtimeInterruptReason,
+ syncInterruptReason,
startTime,
staticStageEndTime,
runtimeStageEndTime,
@@ -2802,8 +2801,7 @@ async function renderToStream(
{ dim: true },
spawnStaticShellValidationInDev,
accumulatedChunksPromise,
- staticInterruptReason,
- runtimeInterruptReason,
+ syncInterruptReason,
startTime,
staticStageEndTime,
runtimeStageEndTime,
@@ -3241,21 +3239,10 @@ async function renderWithRestartOnCacheMissInDev(
getPayload: (requestStore: RequestStore) => Promise,
onError: (error: unknown) => void
) {
- const {
- htmlRequestId,
- renderOpts,
- componentMod: {
- routeModule: {
- userland: { loaderTree },
- },
- },
- } = ctx
+ const { htmlRequestId, renderOpts } = ctx
const { ComponentMod, setCacheStatus, setReactDebugChannel } = renderOpts
- const hasRuntimePrefetch =
- await anySegmentHasRuntimePrefetchEnabled(loaderTree)
-
let startTime = -Infinity
// If the render is restarted, we'll recreate a fresh request store
@@ -3265,10 +3252,13 @@ async function renderWithRestartOnCacheMissInDev(
const currentStage = requestStore.stagedRendering!.currentStage
switch (currentStage) {
case RenderStage.Before:
+ case RenderStage.EarlyStatic:
case RenderStage.Static:
return 'Prerender'
+ case RenderStage.EarlyRuntime:
+ return 'Prefetch'
case RenderStage.Runtime:
- return hasRuntimePrefetch ? 'Prefetch' : 'Prefetchable'
+ return 'Prefetchable'
case RenderStage.Dynamic:
case RenderStage.Abandoned:
return 'Server'
@@ -3301,7 +3291,6 @@ async function renderWithRestartOnCacheMissInDev(
const initialAbandonController = new AbortController() // Controls whether this render is abandoned
const initialStageController = new StagedRenderingController(
initialDataController.signal,
- hasRuntimePrefetch,
initialAbandonController
)
@@ -3327,7 +3316,7 @@ async function renderWithRestartOnCacheMissInDev(
const initialStreamResult = await runInSequentialTasks(
() => {
- initialStageController.advanceStage(RenderStage.Static)
+ initialStageController.advanceStage(RenderStage.EarlyStatic)
startTime = performance.now() + performance.timeOrigin
const streamPair = workUnitAsyncStorage
@@ -3371,6 +3360,24 @@ async function renderWithRestartOnCacheMissInDev(
accumulatedChunksPromise,
}
},
+ () => {
+ if (initialAbandonController.signal.aborted === true) {
+ return
+ } else if (cacheSignal.hasPendingReads()) {
+ initialAbandonController.abort()
+ } else {
+ initialStageController.advanceStage(RenderStage.Static)
+ }
+ },
+ () => {
+ if (initialAbandonController.signal.aborted === true) {
+ return
+ } else if (cacheSignal.hasPendingReads()) {
+ initialAbandonController.abort()
+ } else {
+ initialStageController.advanceStage(RenderStage.EarlyRuntime)
+ }
+ },
() => {
if (initialAbandonController.signal.aborted === true) {
return
@@ -3396,9 +3403,7 @@ async function renderWithRestartOnCacheMissInDev(
return {
stream: initialStreamResult.stream,
accumulatedChunksPromise: initialStreamResult.accumulatedChunksPromise,
- staticInterruptReason: initialStageController.getStaticInterruptReason(),
- runtimeInterruptReason:
- initialStageController.getRuntimeInterruptReason(),
+ syncInterruptReason: initialStageController.getSyncInterruptReason(),
startTime,
staticStageEndTime: initialStageController.getStaticStageEndTime(),
runtimeStageEndTime: initialStageController.getRuntimeStageEndTime(),
@@ -3433,10 +3438,7 @@ async function renderWithRestartOnCacheMissInDev(
// We are going to render this pass all the way through because we've already
// filled any caches so we won't be aborting this time.
const abortSignal = null
- const finalStageController = new StagedRenderingController(
- abortSignal,
- hasRuntimePrefetch
- )
+ const finalStageController = new StagedRenderingController(abortSignal)
// We've filled the caches, so now we can render as usual,
// without any cache-filling mechanics.
@@ -3463,7 +3465,7 @@ async function renderWithRestartOnCacheMissInDev(
const finalStreamResult = await runInSequentialTasks(
() => {
- finalStageController.advanceStage(RenderStage.Static)
+ finalStageController.advanceStage(RenderStage.EarlyStatic)
startTime = performance.now() + performance.timeOrigin
const streamPair = workUnitAsyncStorage
@@ -3491,6 +3493,14 @@ async function renderWithRestartOnCacheMissInDev(
),
}
},
+ () => {
+ // Static stage
+ finalStageController.advanceStage(RenderStage.Static)
+ },
+ () => {
+ // EarlyRuntime stage
+ finalStageController.advanceStage(RenderStage.EarlyRuntime)
+ },
() => {
// Runtime stage
finalStageController.advanceStage(RenderStage.Runtime)
@@ -3508,8 +3518,7 @@ async function renderWithRestartOnCacheMissInDev(
return {
stream: finalStreamResult.stream,
accumulatedChunksPromise: finalStreamResult.accumulatedChunksPromise,
- staticInterruptReason: finalStageController.getStaticInterruptReason(),
- runtimeInterruptReason: finalStageController.getRuntimeInterruptReason(),
+ syncInterruptReason: finalStageController.getSyncInterruptReason(),
startTime,
staticStageEndTime: finalStageController.getStaticStageEndTime(),
runtimeStageEndTime: finalStageController.getRuntimeStageEndTime(),
@@ -3558,9 +3567,11 @@ async function accumulateStreamChunks(
throw new InvariantError(
'Unexpected stream chunk while in Before stage'
)
+ case RenderStage.EarlyStatic:
case RenderStage.Static:
staticChunks.push(value)
// fall through
+ case RenderStage.EarlyRuntime:
case RenderStage.Runtime:
runtimeChunks.push(value)
// fall through
@@ -3590,33 +3601,58 @@ function createAsyncApiPromisesInDev(
headers: RequestStore['headers']
): NonNullable {
return {
- // Runtime APIs
+ // Runtime APIs (for prefetch segments)
cookies: stagedRendering.delayUntilStage(
RenderStage.Runtime,
'cookies',
cookies
),
+ earlyCookies: stagedRendering.delayUntilStage(
+ RenderStage.EarlyRuntime,
+ 'cookies',
+ cookies
+ ),
mutableCookies: stagedRendering.delayUntilStage(
RenderStage.Runtime,
'cookies',
mutableCookies as RequestStore['cookies']
),
+ earlyMutableCookies: stagedRendering.delayUntilStage(
+ RenderStage.EarlyRuntime,
+ 'cookies',
+ mutableCookies as RequestStore['cookies']
+ ),
headers: stagedRendering.delayUntilStage(
RenderStage.Runtime,
'headers',
headers
),
+ earlyHeaders: stagedRendering.delayUntilStage(
+ RenderStage.EarlyRuntime,
+ 'headers',
+ headers
+ ),
// These are not used directly, but we chain other `params`/`searchParams` promises off of them.
sharedParamsParent: stagedRendering.delayUntilStage(
RenderStage.Runtime,
undefined,
''
),
+ earlySharedParamsParent: stagedRendering.delayUntilStage(
+ RenderStage.EarlyRuntime,
+ undefined,
+ ''
+ ),
sharedSearchParamsParent: stagedRendering.delayUntilStage(
RenderStage.Runtime,
undefined,
''
),
+ earlySharedSearchParamsParent: stagedRendering.delayUntilStage(
+ RenderStage.EarlyRuntime,
+ undefined,
+ ''
+ ),
connection: stagedRendering.delayUntilStage(
RenderStage.Dynamic,
'connection',
@@ -3686,8 +3722,7 @@ async function logMessagesAndSendErrorsToBrowser(
*/
async function spawnStaticShellValidationInDev(
accumulatedChunksPromise: Promise,
- staticInterruptReason: Error | null,
- runtimeInterruptReason: Error | null,
+ syncInterruptReason: Error | null,
startTime: number,
staticStageEndTime: number,
runtimeStageEndTime: number,
@@ -3723,12 +3758,8 @@ async function spawnStaticShellValidationInDev(
return logMessagesAndSendErrorsToBrowser([invalidDynamicUsageError], ctx)
}
- if (staticInterruptReason) {
- return logMessagesAndSendErrorsToBrowser([staticInterruptReason], ctx)
- }
-
- if (runtimeInterruptReason) {
- return logMessagesAndSendErrorsToBrowser([runtimeInterruptReason], ctx)
+ if (syncInterruptReason) {
+ return logMessagesAndSendErrorsToBrowser([syncInterruptReason], ctx)
}
let debugChunks: Uint8Array[] | null = null
diff --git a/packages/next/src/server/app-render/create-component-tree.tsx b/packages/next/src/server/app-render/create-component-tree.tsx
index 5983c34b86ab7..0f1242519b63f 100644
--- a/packages/next/src/server/app-render/create-component-tree.tsx
+++ b/packages/next/src/server/app-render/create-component-tree.tsx
@@ -41,13 +41,17 @@ import {
getConventionPathByType,
isNextjsBuiltinFilePath,
} from './segment-explorer-path'
+import type { AppSegmentConfig } from '../../build/segment-config/app/app-segment-config'
+import { RenderStage, type StagedRenderingController } from './staged-rendering'
/**
* Use the provided loader tree to create the React Component tree.
*/
+// TODO convert these arguments to non-object form. the entrypoint doesn't need most of them
export function createComponentTree(props: {
loaderTree: LoaderTree
parentParams: Params
+ parentRuntimePrefetchable: false
rootLayoutIncluded: boolean
injectedCSS: Set
injectedJS: Set
@@ -83,6 +87,7 @@ async function createComponentTreeInternal(
{
loaderTree: tree,
parentParams,
+ parentRuntimePrefetchable,
rootLayoutIncluded,
injectedCSS,
injectedJS,
@@ -95,6 +100,7 @@ async function createComponentTreeInternal(
}: {
loaderTree: LoaderTree
parentParams: Params
+ parentRuntimePrefetchable: boolean
rootLayoutIncluded: boolean
injectedCSS: Set
injectedJS: Set
@@ -224,6 +230,15 @@ async function createComponentTreeInternal(
})
: []
+ const instantConfig = layoutOrPageMod
+ ? (layoutOrPageMod as AppSegmentConfig).unstable_instant
+ : undefined
+ const hasRuntimePrefetch =
+ instantConfig && typeof instantConfig === 'object'
+ ? instantConfig.prefetch === 'runtime'
+ : false
+ const isRuntimePrefetchable = hasRuntimePrefetch || parentRuntimePrefetchable
+
const [Forbidden, forbiddenStyles] =
authInterrupts && forbidden
? await createComponentStylesAndScripts({
@@ -526,6 +541,7 @@ async function createComponentTreeInternal(
{
loaderTree: parallelRoute,
parentParams: currentParams,
+ parentRuntimePrefetchable: isRuntimePrefetchable,
rootLayoutIncluded: rootLayoutIncludedAtThisLevelOrAbove,
injectedCSS: injectedCSSWithCurrentLayout,
injectedJS: injectedJSWithCurrentLayout,
@@ -685,6 +701,8 @@ async function createComponentTreeInternal(
parallelRouteCacheNodeSeedData,
loadingData,
isPossiblyPartialResponse,
+ isRuntimePrefetchable,
+
// No user-provided component, so no params will be accessed. Use the
// pre-resolved empty tracker.
emptyVaryParamsAccumulator
@@ -724,6 +742,8 @@ async function createComponentTreeInternal(
parallelRouteCacheNodeSeedData,
loadingData,
true,
+ isRuntimePrefetchable,
+
// force-dynamic postpones without rendering the component, so no params
// are accessed. The vary params are empty.
emptyVaryParamsAccumulator
@@ -790,7 +810,8 @@ async function createComponentTreeInternal(
const params = createServerParamsForServerSegment(
currentParams,
workStore,
- varyParamsAccumulator
+ varyParamsAccumulator,
+ isRuntimePrefetchable
)
// If we are passing searchParams to a server component Page we need to
@@ -799,7 +820,8 @@ async function createComponentTreeInternal(
let searchParams = createServerSearchParamsForServerPage(
query,
workStore,
- varyParamsAccumulator
+ varyParamsAccumulator,
+ isRuntimePrefetchable
)
if (isUseCacheFunction(PageComponent)) {
@@ -851,6 +873,8 @@ async function createComponentTreeInternal(
parallelRouteCacheNodeSeedData,
loadingData,
isPossiblyPartialResponse,
+ isRuntimePrefetchable,
+
varyParamsAccumulator
)
} else {
@@ -970,7 +994,8 @@ async function createComponentTreeInternal(
const params = createServerParamsForServerSegment(
currentParams,
workStore,
- varyParamsAccumulator
+ varyParamsAccumulator,
+ isRuntimePrefetchable
)
let serverSegment: React.ReactNode
@@ -1065,6 +1090,8 @@ async function createComponentTreeInternal(
parallelRouteCacheNodeSeedData,
loadingData,
isPossiblyPartialResponse,
+ isRuntimePrefetchable,
+
varyParamsAccumulator
)
}
@@ -1216,8 +1243,46 @@ function createSeedData(
parallelRoutes: Record,
loading: LoadingModuleData | null,
isPossiblyPartialResponse: boolean,
+ isRuntimePrefetchable: boolean,
varyParamsAccumulator: VaryParamsAccumulator | null
): CacheNodeSeedData {
+ const createElement = ctx.componentMod.createElement
+
+ // When this segment is NOT runtime-prefetchable, delay it until the Static
+ // stage by wrapping the node in a promise. This allows runtime-prefetchable
+ // segments (the lower tree) to render first during EarlyStatic, so their
+ // runtime data resolves in EarlyRuntime where sync IO can be checked.
+ // React will suspend on the thenable and resume when the stage advances.
+ if (!isRuntimePrefetchable) {
+ const workUnitStore = workUnitAsyncStorage.getStore()
+ if (workUnitStore) {
+ let stagedRendering: StagedRenderingController | null | undefined
+ switch (workUnitStore.type) {
+ case 'request':
+ case 'prerender-runtime':
+ stagedRendering = workUnitStore.stagedRendering
+ if (stagedRendering) {
+ const deferredRsc = rsc
+ rsc = stagedRendering
+ .waitForStage(RenderStage.Static)
+ .then(() => deferredRsc)
+ }
+ break
+ case 'prerender':
+ case 'prerender-client':
+ case 'validation-client':
+ case 'prerender-ppr':
+ case 'prerender-legacy':
+ case 'cache':
+ case 'private-cache':
+ case 'unstable-cache':
+ break
+ default:
+ workUnitStore satisfies never
+ }
+ }
+ }
+
if (loading !== null) {
// If a loading.tsx boundary is present, wrap the component data in an
// additional context provider to pass the loading data to the next
@@ -1225,7 +1290,6 @@ function createSeedData(
// NOTE: The reason this is a separate wrapper from LayoutRouter is because
// not all segments render a LayoutRouter component, e.g. the root segment.
const LoadingBoundaryProvider = ctx.componentMod.LoadingBoundaryProvider
- const createElement = ctx.componentMod.createElement
rsc = createElement(LoadingBoundaryProvider, {
loading: loading,
children: rsc,
diff --git a/packages/next/src/server/app-render/dynamic-rendering.ts b/packages/next/src/server/app-render/dynamic-rendering.ts
index 5301a63c457b6..043f09a1ffb89 100644
--- a/packages/next/src/server/app-render/dynamic-rendering.ts
+++ b/packages/next/src/server/app-render/dynamic-rendering.ts
@@ -25,7 +25,6 @@ import type {
WorkUnitStore,
PrerenderStoreLegacy,
PrerenderStoreModern,
- PrerenderStoreModernRuntime,
ValidationStoreClient,
} from '../app-render/work-unit-async-storage.external'
@@ -38,9 +37,8 @@ import {
throwForMissingRequestStore,
workUnitAsyncStorage,
} from './work-unit-async-storage.external'
-import { RenderStage } from './staged-rendering'
import { workAsyncStorage } from '../app-render/work-async-storage.external'
-import { makeHangingPromise } from '../dynamic-rendering-utils'
+import { makeHangingPromise, getRuntimeStage } from '../dynamic-rendering-utils'
import {
METADATA_BOUNDARY_NAME,
VIEWPORT_BOUNDARY_NAME,
@@ -547,8 +545,9 @@ export function createHangingInputAbortSignal(
workUnitStore.type === 'prerender-runtime' &&
workUnitStore.stagedRendering
) {
- workUnitStore.stagedRendering
- .waitForStage(RenderStage.Runtime)
+ const { stagedRendering } = workUnitStore
+ stagedRendering
+ .waitForStage(getRuntimeStage(stagedRendering))
.then(() => scheduleOnNextTick(() => controller.abort()))
} else {
scheduleOnNextTick(() => controller.abort())
@@ -1259,15 +1258,3 @@ export function getNavigationDisallowedDynamicReasons(
// We had a non-empty prelude and there are no dynamic holes
return []
}
-
-export function delayUntilRuntimeStage(
- prerenderStore: PrerenderStoreModernRuntime,
- result: Promise
-): Promise {
- if (prerenderStore.stagedRendering) {
- return prerenderStore.stagedRendering
- .waitForStage(RenderStage.Runtime)
- .then(() => result)
- }
- return result
-}
diff --git a/packages/next/src/server/app-render/staged-rendering.ts b/packages/next/src/server/app-render/staged-rendering.ts
index e985c4580e236..112de7502c695 100644
--- a/packages/next/src/server/app-render/staged-rendering.ts
+++ b/packages/next/src/server/app-render/staged-rendering.ts
@@ -3,31 +3,39 @@ import { createPromiseWithResolvers } from '../../shared/lib/promise-with-resolv
export enum RenderStage {
Before = 1,
- Static = 2,
- Runtime = 3,
- Dynamic = 4,
- Abandoned = 5,
+ EarlyStatic = 2,
+ Static = 3,
+ EarlyRuntime = 4,
+ Runtime = 5,
+ Dynamic = 6,
+ Abandoned = 7,
}
-export type NonStaticRenderStage = RenderStage.Runtime | RenderStage.Dynamic
+export type AdvanceableRenderStage =
+ | RenderStage.Static
+ | RenderStage.EarlyRuntime
+ | RenderStage.Runtime
+ | RenderStage.Dynamic
export class StagedRenderingController {
currentStage: RenderStage = RenderStage.Before
- staticInterruptReason: Error | null = null
- runtimeInterruptReason: Error | null = null
+ syncInterruptReason: Error | null = null
staticStageEndTime: number = Infinity
runtimeStageEndTime: number = Infinity
+ private staticStageListeners: Array<() => void> = []
+ private earlyRuntimeStageListeners: Array<() => void> = []
private runtimeStageListeners: Array<() => void> = []
private dynamicStageListeners: Array<() => void> = []
+ private staticStagePromise = createPromiseWithResolvers()
+ private earlyRuntimeStagePromise = createPromiseWithResolvers()
private runtimeStagePromise = createPromiseWithResolvers()
private dynamicStagePromise = createPromiseWithResolvers()
constructor(
private abortSignal: AbortSignal | null = null,
- private hasRuntimePrefetch: boolean,
private abandonController: AbortController | null = null
) {
if (abortSignal) {
@@ -39,6 +47,10 @@ export class StagedRenderingController {
// is a no-op. The ignoreReject handler suppresses unhandled
// rejection warnings for promises that no one is awaiting.
const { reason } = abortSignal
+ this.staticStagePromise.promise.catch(ignoreReject)
+ this.staticStagePromise.reject(reason)
+ this.earlyRuntimeStagePromise.promise.catch(ignoreReject)
+ this.earlyRuntimeStagePromise.reject(reason)
this.runtimeStagePromise.promise.catch(ignoreReject)
this.runtimeStagePromise.reject(reason)
this.dynamicStagePromise.promise.catch(ignoreReject)
@@ -59,9 +71,13 @@ export class StagedRenderingController {
}
}
- onStage(stage: NonStaticRenderStage, callback: () => void) {
+ onStage(stage: AdvanceableRenderStage, callback: () => void) {
if (this.currentStage >= stage) {
callback()
+ } else if (stage === RenderStage.Static) {
+ this.staticStageListeners.push(callback)
+ } else if (stage === RenderStage.EarlyRuntime) {
+ this.earlyRuntimeStageListeners.push(callback)
} else if (stage === RenderStage.Runtime) {
this.runtimeStageListeners.push(callback)
} else if (stage === RenderStage.Dynamic) {
@@ -78,10 +94,24 @@ export class StagedRenderingController {
return false
}
- const boundaryStage = this.hasRuntimePrefetch
- ? RenderStage.Dynamic
- : RenderStage.Runtime
- return this.currentStage < boundaryStage
+ switch (this.currentStage) {
+ case RenderStage.EarlyStatic:
+ case RenderStage.Static:
+ return true
+ case RenderStage.EarlyRuntime:
+ // EarlyRuntime is for runtime-prefetchable segments. Sync IO
+ // should error because it would abort a runtime prefetch.
+ return true
+ case RenderStage.Runtime:
+ // Runtime is for non-prefetchable segments. Sync IO is fine there
+ // because in practice this segment will never be runtime prefetched
+ return false
+ case RenderStage.Dynamic:
+ case RenderStage.Abandoned:
+ return false
+ default:
+ return false
+ }
}
syncInterruptCurrentStageWithReason(reason: Error) {
@@ -105,22 +135,18 @@ export class StagedRenderingController {
// If we're in the final render, we cannot abandon it. We need to advance to the Dynamic stage
// and capture the interruption reason.
switch (this.currentStage) {
- case RenderStage.Static: {
- this.staticInterruptReason = reason
+ case RenderStage.EarlyStatic:
+ case RenderStage.Static:
+ case RenderStage.EarlyRuntime: {
+ // EarlyRuntime is for runtime-prefetchable segments. Sync IO here
+ // means the prefetch would be aborted too early.
+ this.syncInterruptReason = reason
this.advanceStage(RenderStage.Dynamic)
return
}
case RenderStage.Runtime: {
- // We only error for Sync IO in the runtime stage if the route
- // is configured to use runtime prefetching.
- // We do this to reflect the fact that during a runtime prefetch,
- // Sync IO aborts aborts the render.
- // Note that `canSyncInterrupt` should prevent us from getting here at all
- // if runtime prefetching isn't enabled.
- if (this.hasRuntimePrefetch) {
- this.runtimeInterruptReason = reason
- this.advanceStage(RenderStage.Dynamic)
- }
+ // canSyncInterrupt returns false for Runtime, so we should
+ // never get here. Defensive no-op.
return
}
case RenderStage.Dynamic:
@@ -128,12 +154,8 @@ export class StagedRenderingController {
}
}
- getStaticInterruptReason() {
- return this.staticInterruptReason
- }
-
- getRuntimeInterruptReason() {
- return this.runtimeInterruptReason
+ getSyncInterruptReason() {
+ return this.syncInterruptReason
}
getStaticStageEndTime() {
@@ -152,15 +174,22 @@ export class StagedRenderingController {
// (this might be a lazy intitialization of a module,
// so we still want to restart in this case and see if it still occurs)
// In either case, we'll be doing another render after this one,
- // so we only want to unblock the Runtime stage, not Dynamic, because
+ // so we only want to unblock the next stage, not Dynamic, because
// unblocking the dynamic stage would likely lead to wasted (uncached) IO.
const { currentStage } = this
switch (currentStage) {
+ case RenderStage.EarlyStatic: {
+ this.resolveStaticStage()
+ }
+ // intentional fallthrough
case RenderStage.Static: {
- this.currentStage = RenderStage.Abandoned
+ this.resolveEarlyRuntimeStage()
+ }
+ // intentional fallthrough
+ case RenderStage.EarlyRuntime: {
this.resolveRuntimeStage()
- return
}
+ // intentional fallthrough
case RenderStage.Runtime: {
this.currentStage = RenderStage.Abandoned
return
@@ -176,7 +205,12 @@ export class StagedRenderingController {
}
advanceStage(
- stage: RenderStage.Static | RenderStage.Runtime | RenderStage.Dynamic
+ stage:
+ | RenderStage.EarlyStatic
+ | RenderStage.Static
+ | RenderStage.EarlyRuntime
+ | RenderStage.Runtime
+ | RenderStage.Dynamic
) {
// If we're already at the target stage or beyond, do nothing.
// (this can happen e.g. if sync IO advanced us to the dynamic stage)
@@ -187,6 +221,15 @@ export class StagedRenderingController {
let currentStage = this.currentStage
this.currentStage = stage
+ if (currentStage < RenderStage.Static && stage >= RenderStage.Static) {
+ this.resolveStaticStage()
+ }
+ if (
+ currentStage < RenderStage.EarlyRuntime &&
+ stage >= RenderStage.EarlyRuntime
+ ) {
+ this.resolveEarlyRuntimeStage()
+ }
if (currentStage < RenderStage.Runtime && stage >= RenderStage.Runtime) {
this.staticStageEndTime = performance.now() + performance.timeOrigin
this.resolveRuntimeStage()
@@ -198,6 +241,26 @@ export class StagedRenderingController {
}
}
+ /** Fire the `onStage` listeners for the static stage and unblock any promises waiting for it. */
+ private resolveStaticStage() {
+ const staticListeners = this.staticStageListeners
+ for (let i = 0; i < staticListeners.length; i++) {
+ staticListeners[i]()
+ }
+ staticListeners.length = 0
+ this.staticStagePromise.resolve()
+ }
+
+ /** Fire the `onStage` listeners for the early runtime stage and unblock any promises waiting for it. */
+ private resolveEarlyRuntimeStage() {
+ const earlyRuntimeListeners = this.earlyRuntimeStageListeners
+ for (let i = 0; i < earlyRuntimeListeners.length; i++) {
+ earlyRuntimeListeners[i]()
+ }
+ earlyRuntimeListeners.length = 0
+ this.earlyRuntimeStagePromise.resolve()
+ }
+
/** Fire the `onStage` listeners for the runtime stage and unblock any promises waiting for it. */
private resolveRuntimeStage() {
const runtimeListeners = this.runtimeStageListeners
@@ -218,8 +281,14 @@ export class StagedRenderingController {
this.dynamicStagePromise.resolve()
}
- private getStagePromise(stage: NonStaticRenderStage): Promise {
+ private getStagePromise(stage: AdvanceableRenderStage): Promise {
switch (stage) {
+ case RenderStage.Static: {
+ return this.staticStagePromise.promise
+ }
+ case RenderStage.EarlyRuntime: {
+ return this.earlyRuntimeStagePromise.promise
+ }
case RenderStage.Runtime: {
return this.runtimeStagePromise.promise
}
@@ -233,12 +302,12 @@ export class StagedRenderingController {
}
}
- waitForStage(stage: NonStaticRenderStage) {
+ waitForStage(stage: AdvanceableRenderStage) {
return this.getStagePromise(stage)
}
delayUntilStage(
- stage: NonStaticRenderStage,
+ stage: AdvanceableRenderStage,
displayName: string | undefined,
resolvedValue: T
) {
diff --git a/packages/next/src/server/app-render/walk-tree-with-flight-router-state.tsx b/packages/next/src/server/app-render/walk-tree-with-flight-router-state.tsx
index ac0f0792dd6a1..9a2f0e8e4695d 100644
--- a/packages/next/src/server/app-render/walk-tree-with-flight-router-state.tsx
+++ b/packages/next/src/server/app-render/walk-tree-with-flight-router-state.tsx
@@ -225,6 +225,7 @@ export async function walkTreeWithFlightRouterState({
ctx,
loaderTree: loaderTreeToFilter,
parentParams: currentParams,
+ parentRuntimePrefetchable: false,
injectedCSS,
injectedJS,
injectedFontPreloadTags,
@@ -342,6 +343,7 @@ export async function createFullTreeFlightDataForNavigation({
ctx,
loaderTree,
parentParams: {},
+ parentRuntimePrefetchable: false,
injectedCSS,
injectedJS,
injectedFontPreloadTags,
diff --git a/packages/next/src/server/app-render/work-unit-async-storage.external.ts b/packages/next/src/server/app-render/work-unit-async-storage.external.ts
index f56b736d4cb2b..ba001d05bc064 100644
--- a/packages/next/src/server/app-render/work-unit-async-storage.external.ts
+++ b/packages/next/src/server/app-render/work-unit-async-storage.external.ts
@@ -21,6 +21,7 @@ import type { WorkStore } from './work-async-storage.external'
import { NEXT_HMR_REFRESH_HASH_COOKIE } from '../../client/components/app-router-headers'
import { InvariantError } from '../../shared/lib/invariant-error'
import type { StagedRenderingController } from './staged-rendering'
+import { RenderStage } from './staged-rendering'
import type { ValidationBoundaryTracking } from './instant-validation/boundary-tracking'
export type WorkUnitPhase = 'action' | 'render' | 'after'
@@ -79,15 +80,42 @@ export interface RequestStore extends CommonWorkUnitStore {
type DevAsyncApiPromises = {
cookies: Promise
+ earlyCookies: Promise
+
mutableCookies: Promise
+ earlyMutableCookies: Promise
+
headers: Promise
+ earlyHeaders: Promise
sharedParamsParent: Promise
+ earlySharedParamsParent: Promise
+
sharedSearchParamsParent: Promise
+ earlySharedSearchParamsParent: Promise
+ // Connection is not a runtime promise and doesn't
+ // need to distinguish between early and late
connection: Promise
}
+/**
+ * Returns true if the current render stage is an early stage (EarlyStatic or
+ * EarlyRuntime). The early stages are for runtime-prefetchable segments. When
+ * true, runtime APIs should use the early promise variant that resolves at
+ * EarlyRuntime rather than Runtime.
+ */
+export function isInEarlyRenderStage(requestStore: RequestStore): boolean {
+ const stagedRendering = requestStore.stagedRendering
+ if (stagedRendering) {
+ return (
+ stagedRendering.currentStage === RenderStage.EarlyStatic ||
+ stagedRendering.currentStage === RenderStage.EarlyRuntime
+ )
+ }
+ return false
+}
+
/**
* The Prerender store is for tracking information related to prerenders.
*
diff --git a/packages/next/src/server/dynamic-rendering-utils.ts b/packages/next/src/server/dynamic-rendering-utils.ts
index f6295a61547d6..0f7063dca4ea7 100644
--- a/packages/next/src/server/dynamic-rendering-utils.ts
+++ b/packages/next/src/server/dynamic-rendering-utils.ts
@@ -1,5 +1,12 @@
-import type { NonStaticRenderStage } from './app-render/staged-rendering'
-import type { RequestStore } from './app-render/work-unit-async-storage.external'
+import {
+ RenderStage,
+ type AdvanceableRenderStage,
+ type StagedRenderingController,
+} from './app-render/staged-rendering'
+import type {
+ PrerenderStoreModernRuntime,
+ RequestStore,
+} from './app-render/work-unit-async-storage.external'
export function isHangingPromiseRejectionError(
err: unknown
@@ -79,7 +86,7 @@ function ignoreReject() {}
export function makeDevtoolsIOAwarePromise(
underlying: T,
requestStore: RequestStore,
- stage: NonStaticRenderStage
+ stage: AdvanceableRenderStage
): Promise {
if (requestStore.stagedRendering) {
// We resolve each stage in a timeout, so React DevTools will pick this up as IO.
@@ -98,3 +105,46 @@ export function makeDevtoolsIOAwarePromise(
}, 0)
})
}
+
+/**
+ * Returns the appropriate runtime stage for the current point in the render.
+ * Runtime-prefetchable segments render in the early stages and should wait
+ * for EarlyRuntime. Non-prefetchable segments render in the later stages
+ * and should wait for Runtime.
+ */
+export function getRuntimeStage(
+ stagedRendering: StagedRenderingController
+): RenderStage.EarlyRuntime | RenderStage.Runtime {
+ if (
+ stagedRendering.currentStage === RenderStage.EarlyStatic ||
+ stagedRendering.currentStage === RenderStage.EarlyRuntime
+ ) {
+ return RenderStage.EarlyRuntime
+ }
+ return RenderStage.Runtime
+}
+
+/**
+ * Delays until the appropriate runtime stage based on the current stage of
+ * the rendering pipeline:
+ *
+ * - Early stages → wait for EarlyRuntime
+ * (for runtime-prefetchable segments)
+ * - Later stages → wait for Runtime
+ * (for segments not using runtime prefetch)
+ *
+ * This ensures that cookies()/headers()/etc. resolve at the right time for
+ * each segment type.
+ */
+export function delayUntilRuntimeStage(
+ prerenderStore: PrerenderStoreModernRuntime,
+ result: Promise
+): Promise {
+ const { stagedRendering } = prerenderStore
+ if (!stagedRendering) {
+ return result
+ }
+ return stagedRendering
+ .waitForStage(getRuntimeStage(stagedRendering))
+ .then(() => result)
+}
diff --git a/packages/next/src/server/node-environment-extensions/io-utils.tsx b/packages/next/src/server/node-environment-extensions/io-utils.tsx
index f98b5e45c8f0b..d8c5449bc0a98 100644
--- a/packages/next/src/server/node-environment-extensions/io-utils.tsx
+++ b/packages/next/src/server/node-environment-extensions/io-utils.tsx
@@ -87,7 +87,10 @@ export function io(expression: string, type: ApiType) {
const stageController = workUnitStore.stagedRendering
if (stageController && stageController.canSyncInterrupt()) {
let message: string
- if (stageController.currentStage === RenderStage.Static) {
+ if (
+ stageController.currentStage === RenderStage.Static ||
+ stageController.currentStage === RenderStage.EarlyStatic
+ ) {
switch (type) {
case 'time':
message = `Route "${workStore.route}" used ${expression} before accessing either uncached data (e.g. \`fetch()\`) or Request data (e.g. \`cookies()\`, \`headers()\`, \`connection()\`, and \`searchParams\`). Accessing the current time in a Server Component requires reading one of these data sources first. Alternatively, consider moving this expression into a Client Component or Cache Component. See more info here: https://nextjs.org/docs/messages/next-prerender-current-time`
diff --git a/packages/next/src/server/request/cookies.ts b/packages/next/src/server/request/cookies.ts
index dc8e0b8304890..12413cc32d52c 100644
--- a/packages/next/src/server/request/cookies.ts
+++ b/packages/next/src/server/request/cookies.ts
@@ -13,15 +13,16 @@ import {
workUnitAsyncStorage,
type PrerenderStoreModern,
type RequestStore,
+ isInEarlyRenderStage,
} from '../app-render/work-unit-async-storage.external'
import {
- delayUntilRuntimeStage,
postponeWithTracking,
throwToInterruptStaticGeneration,
trackDynamicDataInDynamicRender,
} from '../app-render/dynamic-rendering'
import { StaticGenBailoutError } from '../../client/components/static-generation-bailout'
import {
+ delayUntilRuntimeStage,
makeDevtoolsIOAwarePromise,
makeHangingPromise,
} from '../dynamic-rendering-utils'
@@ -191,11 +192,16 @@ function makeUntrackedCookiesWithDevWarnings(
route?: string
): Promise {
if (requestStore.asyncApiPromises) {
+ const early = isInEarlyRenderStage(requestStore)
let promise: Promise
if (underlyingCookies === requestStore.mutableCookies) {
- promise = requestStore.asyncApiPromises.mutableCookies
+ promise = early
+ ? requestStore.asyncApiPromises.earlyMutableCookies
+ : requestStore.asyncApiPromises.mutableCookies
} else if (underlyingCookies === requestStore.cookies) {
- promise = requestStore.asyncApiPromises.cookies
+ promise = early
+ ? requestStore.asyncApiPromises.earlyCookies
+ : requestStore.asyncApiPromises.cookies
} else {
throw new InvariantError(
'Received an underlying cookies object that does not match either `cookies` or `mutableCookies`'
diff --git a/packages/next/src/server/request/draft-mode.ts b/packages/next/src/server/request/draft-mode.ts
index e1621a58bf655..b2f604515dc7e 100644
--- a/packages/next/src/server/request/draft-mode.ts
+++ b/packages/next/src/server/request/draft-mode.ts
@@ -12,7 +12,6 @@ import {
import { workUnitAsyncStorage } from '../app-render/work-unit-async-storage.external'
import {
abortAndThrowOnSynchronousRequestDataAccess,
- delayUntilRuntimeStage,
postponeWithTracking,
trackDynamicDataInDynamicRender,
} from '../app-render/dynamic-rendering'
@@ -20,6 +19,7 @@ import { createDedupedByCallsiteServerErrorLoggerDev } from '../create-deduped-b
import { StaticGenBailoutError } from '../../client/components/static-generation-bailout'
import { DynamicServerError } from '../../client/components/hooks-server-context'
import { InvariantError } from '../../shared/lib/invariant-error'
+import { delayUntilRuntimeStage } from '../dynamic-rendering-utils'
import { ReflectAdapter } from '../web/spec-extension/adapters/reflect'
export function draftMode(): Promise {
diff --git a/packages/next/src/server/request/headers.ts b/packages/next/src/server/request/headers.ts
index 02ad26f9ce216..edff9c5d69e14 100644
--- a/packages/next/src/server/request/headers.ts
+++ b/packages/next/src/server/request/headers.ts
@@ -11,15 +11,16 @@ import {
workUnitAsyncStorage,
type PrerenderStoreModern,
type RequestStore,
+ isInEarlyRenderStage,
} from '../app-render/work-unit-async-storage.external'
import {
- delayUntilRuntimeStage,
postponeWithTracking,
throwToInterruptStaticGeneration,
trackDynamicDataInDynamicRender,
} from '../app-render/dynamic-rendering'
import { StaticGenBailoutError } from '../../client/components/static-generation-bailout'
import {
+ delayUntilRuntimeStage,
makeDevtoolsIOAwarePromise,
makeHangingPromise,
} from '../dynamic-rendering-utils'
@@ -201,7 +202,9 @@ function makeUntrackedHeadersWithDevWarnings(
requestStore: RequestStore
): Promise {
if (requestStore.asyncApiPromises) {
- const promise = requestStore.asyncApiPromises.headers
+ const promise = isInEarlyRenderStage(requestStore)
+ ? requestStore.asyncApiPromises.earlyHeaders
+ : requestStore.asyncApiPromises.headers
return instrumentHeadersPromiseWithDevWarnings(promise, route)
}
diff --git a/packages/next/src/server/request/params.ts b/packages/next/src/server/request/params.ts
index a2e2195ddc06c..59cc5de188292 100644
--- a/packages/next/src/server/request/params.ts
+++ b/packages/next/src/server/request/params.ts
@@ -13,7 +13,6 @@ import { ReflectAdapter } from '../web/spec-extension/adapters/reflect'
import {
throwToInterruptStaticGeneration,
postponeWithTracking,
- delayUntilRuntimeStage,
} from '../app-render/dynamic-rendering'
import {
@@ -82,11 +81,14 @@ export function createParamsFromClient(
// but since you would never use next dev with production NODE_ENV we use this
// as a proxy so we can statically exclude this code from production builds.
const devFallbackParams = workUnitStore.devFallbackParams
+ // Client params are not runtime prefetchable
+ const isRuntimePrefetchable = false
return createRenderParamsInDev(
underlyingParams,
devFallbackParams,
workStore,
- workUnitStore
+ workUnitStore,
+ isRuntimePrefetchable
)
} else {
return createRenderParamsInProd(underlyingParams)
@@ -99,6 +101,8 @@ export function createParamsFromClient(
}
// generateMetadata always runs in RSC context so it is equivalent to a Server Page Component
+// TODO: metadata should inherit the runtime prefetchability of the page segment
+const metadataIsRuntimePrefetchable = false
export type CreateServerParamsForMetadata = typeof createServerParamsForMetadata
export function createServerParamsForMetadata(
underlyingParams: Params,
@@ -108,7 +112,8 @@ export function createServerParamsForMetadata(
return createServerParamsForServerSegment(
underlyingParams,
workStore,
- metadataVaryParamsAccumulator
+ metadataVaryParamsAccumulator,
+ metadataIsRuntimePrefetchable
)
}
@@ -141,23 +146,30 @@ export function createServerParamsForRoute(
throw new InvariantError(
'createServerParamsForRoute should not be called in cache contexts.'
)
- case 'prerender-runtime':
+ case 'prerender-runtime': {
+ // Route params are not runtime prefetchable
+ const isRuntimePrefetchable = false
return createRuntimePrerenderParams(
underlyingParams,
workUnitStore,
- varyParamsAccumulator
+ varyParamsAccumulator,
+ isRuntimePrefetchable
)
+ }
case 'request':
if (process.env.NODE_ENV === 'development') {
// Semantically we only need the dev tracking when running in `next dev`
// but since you would never use next dev with production NODE_ENV we use this
// as a proxy so we can statically exclude this code from production builds.
const devFallbackParams = workUnitStore.devFallbackParams
+ // Route params are not runtime prefetchable
+ const isRuntimePrefetchable = false
return createRenderParamsInDev(
underlyingParams,
devFallbackParams,
workStore,
- workUnitStore
+ workUnitStore,
+ isRuntimePrefetchable
)
} else {
return createRenderParamsInProd(underlyingParams)
@@ -172,7 +184,8 @@ export function createServerParamsForRoute(
export function createServerParamsForServerSegment(
underlyingParams: Params,
workStore: WorkStore,
- varyParamsAccumulator: VaryParamsAccumulator | null = null
+ varyParamsAccumulator: VaryParamsAccumulator | null,
+ isRuntimePrefetchable: boolean
): Promise {
const workUnitStore = workUnitAsyncStorage.getStore()
if (workUnitStore) {
@@ -200,7 +213,8 @@ export function createServerParamsForServerSegment(
return createRuntimePrerenderParams(
underlyingParams,
workUnitStore,
- varyParamsAccumulator
+ varyParamsAccumulator,
+ isRuntimePrefetchable
)
case 'request':
if (process.env.NODE_ENV === 'development') {
@@ -212,7 +226,8 @@ export function createServerParamsForServerSegment(
underlyingParams,
devFallbackParams,
workStore,
- workUnitStore
+ workUnitStore,
+ isRuntimePrefetchable
)
} else {
return createRenderParamsInProd(underlyingParams)
@@ -340,17 +355,23 @@ function createStaticPrerenderParams(
function createRuntimePrerenderParams(
underlyingParams: Params,
workUnitStore: PrerenderStoreModernRuntime,
- varyParamsAccumulator: VaryParamsAccumulator | null
+ varyParamsAccumulator: VaryParamsAccumulator | null,
+ isRuntimePrefetchable: boolean
): Promise {
const underlyingParamsWithVarying =
varyParamsAccumulator !== null
? createVaryingParams(varyParamsAccumulator, underlyingParams)
: underlyingParams
- return delayUntilRuntimeStage(
- workUnitStore,
- makeUntrackedParams(underlyingParamsWithVarying)
- )
+ const result = makeUntrackedParams(underlyingParamsWithVarying)
+ const { stagedRendering } = workUnitStore
+ if (!stagedRendering) {
+ return result
+ }
+ const stage = isRuntimePrefetchable
+ ? RenderStage.EarlyRuntime
+ : RenderStage.Runtime
+ return stagedRendering.waitForStage(stage).then(() => result)
}
function createRenderParamsInProd(underlyingParams: Params): Promise {
@@ -361,7 +382,8 @@ function createRenderParamsInDev(
underlyingParams: Params,
devFallbackParams: OpaqueFallbackRouteParams | null | undefined,
workStore: WorkStore,
- requestStore: RequestStore
+ requestStore: RequestStore,
+ isRuntimePrefetchable: boolean
): Promise {
let hasFallbackParams = false
if (devFallbackParams) {
@@ -377,7 +399,8 @@ function createRenderParamsInDev(
underlyingParams,
hasFallbackParams,
workStore,
- requestStore
+ requestStore,
+ isRuntimePrefetchable
)
}
@@ -510,7 +533,8 @@ function makeDynamicallyTrackedParamsWithDevWarnings(
underlyingParams: Params,
hasFallbackParams: boolean,
workStore: WorkStore,
- requestStore: RequestStore
+ requestStore: RequestStore,
+ isRuntimePrefetchable: boolean
): Promise {
if (requestStore.asyncApiPromises && hasFallbackParams) {
// We wrap each instance of params in a `new Promise()`, because deduping
@@ -518,7 +542,9 @@ function makeDynamicallyTrackedParamsWithDevWarnings(
// await a different set of values. This is important when all awaits
// are in third party which would otherwise track all the way to the
// internal params.
- const sharedParamsParent = requestStore.asyncApiPromises.sharedParamsParent
+ const sharedParamsParent = isRuntimePrefetchable
+ ? requestStore.asyncApiPromises.earlySharedParamsParent
+ : requestStore.asyncApiPromises.sharedParamsParent
const promise: Promise = new Promise((resolve, reject) => {
sharedParamsParent.then(() => resolve(underlyingParams), reject)
})
diff --git a/packages/next/src/server/request/pathname.ts b/packages/next/src/server/request/pathname.ts
index 31e097c44791b..c1a6433bcdacb 100644
--- a/packages/next/src/server/request/pathname.ts
+++ b/packages/next/src/server/request/pathname.ts
@@ -1,7 +1,6 @@
import type { WorkStore } from '../app-render/work-async-storage.external'
import {
- delayUntilRuntimeStage,
postponeWithTracking,
type DynamicTrackingState,
} from '../app-render/dynamic-rendering'
@@ -13,7 +12,10 @@ import {
type PrerenderStoreModernServer,
type PrerenderStorePPR,
} from '../app-render/work-unit-async-storage.external'
-import { makeHangingPromise } from '../dynamic-rendering-utils'
+import {
+ delayUntilRuntimeStage,
+ makeHangingPromise,
+} from '../dynamic-rendering-utils'
import { InvariantError } from '../../shared/lib/invariant-error'
export function createServerPathnameForMetadata(
diff --git a/packages/next/src/server/request/search-params.ts b/packages/next/src/server/request/search-params.ts
index 6e1caa8115aec..46d4774761aed 100644
--- a/packages/next/src/server/request/search-params.ts
+++ b/packages/next/src/server/request/search-params.ts
@@ -10,7 +10,6 @@ import {
throwToInterruptStaticGeneration,
postponeWithTracking,
annotateDynamicAccess,
- delayUntilRuntimeStage,
} from '../app-render/dynamic-rendering'
import {
@@ -68,10 +67,13 @@ export function createSearchParamsFromClient(
'createSearchParamsFromClient should not be called in cache contexts.'
)
case 'request':
+ // Client searchParams are not runtime prefetchable
+ const isRuntimePrefetchable = false
return createRenderSearchParams(
underlyingSearchParams,
workStore,
- workUnitStore
+ workUnitStore,
+ isRuntimePrefetchable
)
default:
workUnitStore satisfies never
@@ -81,6 +83,8 @@ export function createSearchParamsFromClient(
}
// generateMetadata always runs in RSC context so it is equivalent to a Server Page Component
+// TODO: metadata should inherit the runtime prefetchability of the page segment
+const metadataIsRuntimePrefetchable = false
export function createServerSearchParamsForMetadata(
underlyingSearchParams: SearchParams,
workStore: WorkStore
@@ -89,14 +93,16 @@ export function createServerSearchParamsForMetadata(
return createServerSearchParamsForServerPage(
underlyingSearchParams,
workStore,
- metadataVaryParamsAccumulator
+ metadataVaryParamsAccumulator,
+ metadataIsRuntimePrefetchable
)
}
export function createServerSearchParamsForServerPage(
underlyingSearchParams: SearchParams,
workStore: WorkStore,
- varyParamsAccumulator: VaryParamsAccumulator | null = null
+ varyParamsAccumulator: VaryParamsAccumulator | null,
+ isRuntimePrefetchable: boolean
): Promise {
const workUnitStore = workUnitAsyncStorage.getStore()
if (workUnitStore) {
@@ -120,13 +126,15 @@ export function createServerSearchParamsForServerPage(
return createRuntimePrerenderSearchParams(
underlyingSearchParams,
workUnitStore,
- varyParamsAccumulator
+ varyParamsAccumulator,
+ isRuntimePrefetchable
)
case 'request':
return createRenderSearchParams(
underlyingSearchParams,
workStore,
- workUnitStore
+ workUnitStore,
+ isRuntimePrefetchable
)
default:
workUnitStore satisfies never
@@ -209,22 +217,30 @@ function createStaticPrerenderSearchParams(
function createRuntimePrerenderSearchParams(
underlyingSearchParams: SearchParams,
workUnitStore: PrerenderStoreModernRuntime,
- varyParamsAccumulator: VaryParamsAccumulator | null
+ varyParamsAccumulator: VaryParamsAccumulator | null,
+ isRuntimePrefetchable: boolean
): Promise {
const underlyingSearchParamsWithVarying =
varyParamsAccumulator !== null
? createVaryingSearchParams(varyParamsAccumulator, underlyingSearchParams)
: underlyingSearchParams
- return delayUntilRuntimeStage(
- workUnitStore,
- makeUntrackedSearchParams(underlyingSearchParamsWithVarying)
- )
+
+ const result = makeUntrackedSearchParams(underlyingSearchParamsWithVarying)
+ const { stagedRendering } = workUnitStore
+ if (!stagedRendering) {
+ return result
+ }
+ const stage = isRuntimePrefetchable
+ ? RenderStage.EarlyRuntime
+ : RenderStage.Runtime
+ return stagedRendering.waitForStage(stage).then(() => result)
}
function createRenderSearchParams(
underlyingSearchParams: SearchParams,
workStore: WorkStore,
- requestStore: RequestStore
+ requestStore: RequestStore,
+ isRuntimePrefetchable: boolean
): Promise {
if (workStore.forceStatic) {
// When using forceStatic we override all other logic and always just return an empty
@@ -238,7 +254,8 @@ function createRenderSearchParams(
return makeUntrackedSearchParamsWithDevWarnings(
underlyingSearchParams,
workStore,
- requestStore
+ requestStore,
+ isRuntimePrefetchable
)
} else {
return makeUntrackedSearchParams(underlyingSearchParams)
@@ -416,7 +433,8 @@ function makeUntrackedSearchParams(
function makeUntrackedSearchParamsWithDevWarnings(
underlyingSearchParams: SearchParams,
workStore: WorkStore,
- requestStore: RequestStore
+ requestStore: RequestStore,
+ isRuntimePrefetchable: boolean
): Promise {
if (requestStore.asyncApiPromises) {
// Do not cache the resulting promise. If we do, we'll only show the first "awaited at"
@@ -424,7 +442,8 @@ function makeUntrackedSearchParamsWithDevWarnings(
return makeUntrackedSearchParamsWithDevWarningsImpl(
underlyingSearchParams,
workStore,
- requestStore
+ requestStore,
+ isRuntimePrefetchable
)
} else {
const cachedSearchParams = CachedSearchParams.get(underlyingSearchParams)
@@ -434,7 +453,8 @@ function makeUntrackedSearchParamsWithDevWarnings(
const promise = makeUntrackedSearchParamsWithDevWarningsImpl(
underlyingSearchParams,
workStore,
- requestStore
+ requestStore,
+ isRuntimePrefetchable
)
CachedSearchParams.set(requestStore, promise)
return promise
@@ -444,7 +464,8 @@ function makeUntrackedSearchParamsWithDevWarnings(
function makeUntrackedSearchParamsWithDevWarningsImpl(
underlyingSearchParams: SearchParams,
workStore: WorkStore,
- requestStore: RequestStore
+ requestStore: RequestStore,
+ isRuntimePrefetchable: boolean
): Promise {
const promiseInitialized = { current: false }
const proxiedUnderlying = instrumentSearchParamsObjectWithDevWarnings(
@@ -458,8 +479,9 @@ function makeUntrackedSearchParamsWithDevWarningsImpl(
// We wrap each instance of searchParams in a `new Promise()`.
// This is important when all awaits are in third party which would otherwise
// track all the way to the internal params.
- const sharedSearchParamsParent =
- requestStore.asyncApiPromises.sharedSearchParamsParent
+ const sharedSearchParamsParent = isRuntimePrefetchable
+ ? requestStore.asyncApiPromises.earlySharedSearchParamsParent
+ : requestStore.asyncApiPromises.sharedSearchParamsParent
promise = new Promise((resolve, reject) => {
sharedSearchParamsParent.then(() => resolve(proxiedUnderlying), reject)
})
diff --git a/packages/next/src/server/use-cache/use-cache-wrapper.ts b/packages/next/src/server/use-cache/use-cache-wrapper.ts
index 8a80351a2a21d..2956ba8cb7cfd 100644
--- a/packages/next/src/server/use-cache/use-cache-wrapper.ts
+++ b/packages/next/src/server/use-cache/use-cache-wrapper.ts
@@ -38,6 +38,7 @@ import {
} from '../app-render/work-unit-async-storage.external'
import {
+ getRuntimeStage,
makeDevtoolsIOAwarePromise,
makeHangingPromise,
} from '../dynamic-rendering-utils'
@@ -1055,22 +1056,25 @@ export async function cache(
switch (outerWorkUnitStore.type) {
case 'prerender-runtime': {
// In a runtime prerender, we have to make sure that APIs that would hang during a static prerender
- // are resolved with a delay, in the runtime stage. Private caches are one of these.
+ // are resolved with a delay, in the appropriate runtime stage. Private caches read from
+ // Segments not using runtime prefetch resolve at EarlyRuntime,
+ // while runtime-prefetchable segments resolve at Runtime.
const stagedRendering = outerWorkUnitStore.stagedRendering
if (stagedRendering) {
- await stagedRendering.waitForStage(RenderStage.Runtime)
+ await stagedRendering.waitForStage(getRuntimeStage(stagedRendering))
}
break
}
case 'request': {
if (process.env.NODE_ENV === 'development') {
// Similar to runtime prerenders, private caches should not resolve in the static stage
- // of a dev request, so we delay them.
- await makeDevtoolsIOAwarePromise(
- undefined,
- outerWorkUnitStore,
- RenderStage.Runtime
- )
+ // of a dev request, so we delay them. We pick the appropriate runtime stage based on
+ // whether we're in the early or late stages.
+ const stagedRendering = outerWorkUnitStore.stagedRendering
+ const stage = stagedRendering
+ ? getRuntimeStage(stagedRendering)
+ : RenderStage.Runtime
+ await makeDevtoolsIOAwarePromise(undefined, outerWorkUnitStore, stage)
}
break
}
@@ -1366,10 +1370,12 @@ export async function cache(
case 'prerender-runtime': {
// In the final phase of a runtime prerender, we have to make
// sure that APIs that would hang during a static prerender
- // are resolved with a delay, in the runtime stage.
+ // are resolved with a delay, in the appropriate runtime stage.
const stagedRendering = workUnitStore.stagedRendering
if (stagedRendering) {
- await stagedRendering.waitForStage(RenderStage.Runtime)
+ await stagedRendering.waitForStage(
+ getRuntimeStage(stagedRendering)
+ )
}
break
}
@@ -1399,10 +1405,14 @@ export async function cache(
// TODO(restart-on-cache-miss): Optimize this to avoid unnecessary restarts.
// We don't end the cache read here, so this will always appear as a cache miss in the static stage,
// and thus will cause a restart even if all caches are filled.
+ const stagedRendering = workUnitStore.stagedRendering
+ const stage = stagedRendering
+ ? getRuntimeStage(stagedRendering)
+ : RenderStage.Runtime
await makeDevtoolsIOAwarePromise(
undefined,
workUnitStore,
- RenderStage.Runtime
+ stage
)
}
break
@@ -1652,11 +1662,11 @@ export async function cache(
// TODO(restart-on-cache-miss): Optimize this to avoid unnecessary restarts.
// We don't end the cache read here, so this will always appear as a cache miss in the static stage,
// and thus will cause a restart even if all caches are filled.
- await makeDevtoolsIOAwarePromise(
- undefined,
- workUnitStore,
- RenderStage.Runtime
- )
+ const stagedRendering = workUnitStore.stagedRendering
+ const stage = stagedRendering
+ ? getRuntimeStage(stagedRendering)
+ : RenderStage.Runtime
+ await makeDevtoolsIOAwarePromise(undefined, workUnitStore, stage)
}
break
}
diff --git a/packages/next/src/server/web/next-url.ts b/packages/next/src/server/web/next-url.ts
index 7f2b52955f045..ec322597a1313 100644
--- a/packages/next/src/server/web/next-url.ts
+++ b/packages/next/src/server/web/next-url.ts
@@ -20,13 +20,14 @@ interface Options {
}
const REGEX_LOCALHOST_HOSTNAME =
- /(?!^https?:\/\/)(127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}|\[::1\]|localhost)/
+ /^(?:127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}|\[::1\]|localhost)$/
function parseURL(url: string | URL, base?: string | URL) {
- return new URL(
- String(url).replace(REGEX_LOCALHOST_HOSTNAME, 'localhost'),
- base && String(base).replace(REGEX_LOCALHOST_HOSTNAME, 'localhost')
- )
+ const parsed = new URL(String(url), base && String(base))
+ if (REGEX_LOCALHOST_HOSTNAME.test(parsed.hostname)) {
+ parsed.hostname = 'localhost'
+ }
+ return parsed
}
const Internal = Symbol('NextURLInternal')
diff --git a/packages/react-refresh-utils/package.json b/packages/react-refresh-utils/package.json
index bff2cfc3a062b..efa496713e54b 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.2.0-canary.50",
+ "version": "16.2.0-canary.51",
"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 a65570157c8ec..32708d0716773 100644
--- a/packages/third-parties/package.json
+++ b/packages/third-parties/package.json
@@ -1,6 +1,6 @@
{
"name": "@next/third-parties",
- "version": "16.2.0-canary.50",
+ "version": "16.2.0-canary.51",
"repository": {
"url": "vercel/next.js",
"directory": "packages/third-parties"
@@ -26,7 +26,7 @@
"third-party-capital": "1.0.20"
},
"devDependencies": {
- "next": "16.2.0-canary.50",
+ "next": "16.2.0-canary.51",
"outdent": "0.8.0",
"prettier": "2.5.1",
"typescript": "5.9.2"
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index bbb4d9909a669..d75d62d3b311f 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -1011,7 +1011,7 @@ importers:
packages/eslint-config-next:
dependencies:
'@next/eslint-plugin-next':
- specifier: 16.2.0-canary.50
+ specifier: 16.2.0-canary.51
version: link:../eslint-plugin-next
eslint:
specifier: '>=9.0.0'
@@ -1088,7 +1088,7 @@ importers:
packages/next:
dependencies:
'@next/env':
- specifier: 16.2.0-canary.50
+ specifier: 16.2.0-canary.51
version: link:../next-env
'@swc/helpers':
specifier: 0.5.15
@@ -1216,19 +1216,19 @@ importers:
specifier: 1.2.0
version: 1.2.0
'@next/font':
- specifier: 16.2.0-canary.50
+ specifier: 16.2.0-canary.51
version: link:../font
'@next/polyfill-module':
- specifier: 16.2.0-canary.50
+ specifier: 16.2.0-canary.51
version: link:../next-polyfill-module
'@next/polyfill-nomodule':
- specifier: 16.2.0-canary.50
+ specifier: 16.2.0-canary.51
version: link:../next-polyfill-nomodule
'@next/react-refresh-utils':
- specifier: 16.2.0-canary.50
+ specifier: 16.2.0-canary.51
version: link:../react-refresh-utils
'@next/swc':
- specifier: 16.2.0-canary.50
+ specifier: 16.2.0-canary.51
version: link:../next-swc
'@opentelemetry/api':
specifier: 1.6.0
@@ -1943,7 +1943,7 @@ importers:
version: 1.0.20
devDependencies:
next:
- specifier: 16.2.0-canary.50
+ specifier: 16.2.0-canary.51
version: link:../next
outdent:
specifier: 0.8.0
diff --git a/rust-toolchain.toml b/rust-toolchain.toml
index 766686a77cea0..fba28e9d94ff7 100644
--- a/rust-toolchain.toml
+++ b/rust-toolchain.toml
@@ -1,5 +1,5 @@
# if you update this, also update `.devcontainer/rust/devcontainer-feature.json`
[toolchain]
-channel = "nightly-2026-02-05"
+channel = "nightly-2026-02-18"
components = ["rustfmt", "clippy", "rust-analyzer"]
profile = "minimal"
diff --git a/test/development/app-dir/react-performance-track/react-performance-track.test.ts b/test/development/app-dir/react-performance-track/react-performance-track.test.ts
index 0193cdf8457e2..638d6a52975f0 100644
--- a/test/development/app-dir/react-performance-track/react-performance-track.test.ts
+++ b/test/development/app-dir/react-performance-track/react-performance-track.test.ts
@@ -110,8 +110,26 @@ describe('react-performance-track', () => {
})
const track = await browser.eval('window.reactServerRequests.getSnapshot()')
- // TODO: Should include "draftMode [Prefetchable]".
- expect(track).toEqual([])
+ // TODO the addition of a promise to delay some Segments from rendering until the later Static
+ // stage has caused the draftMode snapshot to include an empty-named entry. This is probably
+ // a bug in React and should be fixed there but
+ // expect(track).toEqual([])
+ expect(track).toEqual(
+ expect.arrayContaining([
+ {
+ name: '\u200b [Prerender]',
+ properties: [],
+ },
+ ])
+ )
+ let didThrow = false
+ try {
+ // including this anti-assertion here so we can restore the test when the bug in React is fixed
+ expect(track).toEqual([])
+ } catch (e) {
+ didThrow = true
+ }
+ expect(didThrow).toBe(true)
})
it('should show headers', async () => {
diff --git a/test/e2e/app-dir/instant-validation/app/suspense-in-root/page.tsx b/test/e2e/app-dir/instant-validation/app/suspense-in-root/page.tsx
index 3e7f0c7c99868..a014750ae22b3 100644
--- a/test/e2e/app-dir/instant-validation/app/suspense-in-root/page.tsx
+++ b/test/e2e/app-dir/instant-validation/app/suspense-in-root/page.tsx
@@ -38,6 +38,15 @@ export default async function Page() {
+
+
+
+
+
+
+
+
+
Static
diff --git a/test/e2e/app-dir/instant-validation/app/suspense-in-root/runtime/invalid-sync-io-after-cache-with-cookie-input/page.tsx b/test/e2e/app-dir/instant-validation/app/suspense-in-root/runtime/invalid-sync-io-after-cache-with-cookie-input/page.tsx
new file mode 100644
index 0000000000000..bba2f4092c784
--- /dev/null
+++ b/test/e2e/app-dir/instant-validation/app/suspense-in-root/runtime/invalid-sync-io-after-cache-with-cookie-input/page.tsx
@@ -0,0 +1,36 @@
+import { cookies } from 'next/headers'
+
+export const unstable_instant = {
+ prefetch: 'runtime',
+ samples: [{}],
+}
+
+// This page HAS runtime prefetch enabled. cookies() is passed as a promise
+// input to a public "use cache" function. The cache doesn't read the cookies
+// in its body — they're only part of the cache key. After the cache resolves,
+// Date.now() is sync IO that should error because we're in a
+// runtime-prefetchable segment where cookies() has resolved at EarlyRuntime.
+//
+// This test validates that the cache input encoding resolves in the correct
+// runtime stage (EarlyRuntime for prefetchable segments). If the cache input
+// abort signal incorrectly waited for the Runtime stage, the cache would
+// resolve later, and Date.now() would happen at the Runtime stage where
+// canSyncInterrupt returns false — missing the error.
+
+async function cachedFn(cookiePromise: Promise) {
+ 'use cache'
+ // Intentionally not reading the cookie promise in the body.
+ // It's only used as part of the cache key via input encoding.
+ return 'cached result'
+}
+
+export default async function Page() {
+ const cookiePromise = cookies().then((c) => c.get('testCookie')?.value ?? '')
+ await cachedFn(cookiePromise)
+ const now = Date.now()
+ return (
+
+
Runtime page with sync IO after cache with cookie input: {now}
+
+ )
+}
diff --git a/test/e2e/app-dir/instant-validation/app/suspense-in-root/runtime/invalid-sync-io-in-runtime-with-valid-static-parent/layout.tsx b/test/e2e/app-dir/instant-validation/app/suspense-in-root/runtime/invalid-sync-io-in-runtime-with-valid-static-parent/layout.tsx
new file mode 100644
index 0000000000000..80cd9589c8083
--- /dev/null
+++ b/test/e2e/app-dir/instant-validation/app/suspense-in-root/runtime/invalid-sync-io-in-runtime-with-valid-static-parent/layout.tsx
@@ -0,0 +1,28 @@
+import { cookies } from 'next/headers'
+import { Suspense } from 'react'
+
+// This layout does NOT have runtime prefetch — it's a static segment.
+// The sync IO after cookies() is valid here because this segment won't
+// be runtime prefetched.
+
+async function RuntimeContent() {
+ await cookies()
+ const now = Date.now()
+ return
+ )
+}
diff --git a/test/e2e/app-dir/instant-validation/app/suspense-in-root/runtime/invalid-sync-io-in-runtime-with-valid-static-parent/page.tsx b/test/e2e/app-dir/instant-validation/app/suspense-in-root/runtime/invalid-sync-io-in-runtime-with-valid-static-parent/page.tsx
new file mode 100644
index 0000000000000..30d4766b7937e
--- /dev/null
+++ b/test/e2e/app-dir/instant-validation/app/suspense-in-root/runtime/invalid-sync-io-in-runtime-with-valid-static-parent/page.tsx
@@ -0,0 +1,20 @@
+import { cookies } from 'next/headers'
+
+export const unstable_instant = {
+ prefetch: 'runtime',
+ samples: [{}],
+}
+
+// This page HAS runtime prefetch enabled. The sync IO (Date.now()) after
+// cookies() is invalid here because during a runtime prefetch, cookies()
+// resolves and then Date.now() would abort the prerender too early.
+
+export default async function Page() {
+ await cookies()
+ const now = Date.now()
+ return (
+
+
Runtime page with sync IO after cookies: {now}
+
+ )
+}
diff --git a/test/e2e/app-dir/instant-validation/app/suspense-in-root/runtime/valid-sync-io-in-static-parent/layout.tsx b/test/e2e/app-dir/instant-validation/app/suspense-in-root/runtime/valid-sync-io-in-static-parent/layout.tsx
new file mode 100644
index 0000000000000..cbdb0d793d151
--- /dev/null
+++ b/test/e2e/app-dir/instant-validation/app/suspense-in-root/runtime/valid-sync-io-in-static-parent/layout.tsx
@@ -0,0 +1,31 @@
+import { cookies } from 'next/headers'
+import { Suspense } from 'react'
+
+// This layout does NOT have runtime prefetch — it's a static segment.
+// The RuntimeContent component accesses cookies() then Date.now().
+// In a static prefetch the render would never get past cookies() so the
+// sync IO is unreachable. In a runtime prefetch, cookies() would resolve
+// but this layout is not runtime-prefetchable — only the child page is.
+// So the sync IO here should not error.
+
+async function RuntimeContent() {
+ await cookies()
+ const now = Date.now()
+ return
while client routing should warn when scripts are in head",
"updating
while client routing should warn when stylesheets or scripts are in head"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -2411,12 +2413,12 @@
"runtimeError": false
},
"test/development/pages-dir/client-navigation/on-click.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"Client navigation with onClick action should always replace the state and perform additional action",
"Client navigation with onClick action should not reload if default was prevented",
"Client navigation with onClick action should reload the page and perform additional action"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -2623,27 +2625,28 @@
"runtimeError": false
},
"test/development/start-no-build/start-no-build.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"next start without next build should show error when there is no production build"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
},
"test/development/tsconfig-path-reloading/index.test.ts": {
- "passed": [],
- "failed": [
+ "passed": [
"tsconfig-path-reloading tsconfig added after starting dev should automatically fast refresh content when path is added without error",
"tsconfig-path-reloading tsconfig added after starting dev should load with initial paths config correctly",
- "tsconfig-path-reloading tsconfig added after starting dev should recover from module not found when paths is updated",
"tsconfig-path-reloading tsconfig should automatically fast refresh content when path is added without error",
- "tsconfig-path-reloading tsconfig should load with initial paths config correctly",
+ "tsconfig-path-reloading tsconfig should load with initial paths config correctly"
+ ],
+ "failed": [
+ "tsconfig-path-reloading tsconfig added after starting dev should recover from module not found when paths is updated",
"tsconfig-path-reloading tsconfig should recover from module not found when paths is updated"
],
"pending": [],
"flakey": [],
- "runtimeError": true
+ "runtimeError": false
},
"test/development/typescript-auto-install/index.test.ts": {
"passed": [
@@ -2756,12 +2759,12 @@
"runtimeError": false
},
"test/e2e/app-dir-export/test/dynamic-missing-gsp.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"app dir - with output export - dynamic missing gsp should error when client component has generateStaticParams should work",
"app dir - with output export - dynamic missing gsp should error when dynamic route is missing generateStaticParams should work",
"app dir - with output export - dynamic missing gsp should error when dynamic route is set to true should work"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -2926,19 +2929,20 @@
"runtimeError": false
},
"test/e2e/app-dir/actions/app-action-form-state.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"app-dir action useActionState should send the action to the provided permalink with form state when JS disabled",
"app-dir action useActionState should support hydrating the app from progressively enhanced form request",
"app-dir action useActionState should support submitting form state with JS",
"app-dir action useActionState should support submitting form state without JS"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
},
"test/e2e/app-dir/actions/app-action-node-middleware.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"app-dir action handling \"use server\" export values should error when exporting non async functions at build time",
"app-dir action handling Edge SSR should allow cookie and header async storages",
"app-dir action handling Edge SSR should handle basic actions correctly",
@@ -3020,7 +3024,6 @@
"app-dir action handling should trigger an error boundary for action responses with an invalid content-type",
"app-dir action handling should work with interception routes"
],
- "failed": [],
"pending": [
"app-dir action handling fetch actions should handle revalidateTag + redirect",
"app-dir action handling server actions render client components client component imported action should support importing client components from actions",
@@ -3042,14 +3045,14 @@
"runtimeError": false
},
"test/e2e/app-dir/actions/app-action-size-limit-invalid-node-middleware.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"app-dir action size limit invalid config should respect the size set in serverActions.bodySizeLimit for multipart fetch actions should error for requests that exceed the size limit",
"app-dir action size limit invalid config should respect the size set in serverActions.bodySizeLimit for multipart fetch actions should not error for requests that are at the size limit",
"app-dir action size limit invalid config should respect the size set in serverActions.bodySizeLimit for multipart fetch actions should not error for requests that stay below the size limit",
"app-dir action size limit invalid config should respect the size set in serverActions.bodySizeLimit for plaintext fetch actions should error for requests that exceed the size limit",
"app-dir action size limit invalid config should respect the size set in serverActions.bodySizeLimit for plaintext fetch actions should not error for requests that stay below the size limit"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -3268,10 +3271,10 @@
"runtimeError": false
},
"test/e2e/app-dir/app-config-crossorigin/index.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"app dir - crossOrigin config should render correctly with assetPrefix: \"/\""
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -3343,12 +3346,12 @@
"runtimeError": false
},
"test/e2e/app-dir/app-custom-cache-handler/index.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"app-dir - custom-cache-handler - cjs cjs module exports should have logs from cache-handler",
"app-dir - custom-cache-handler - cjs-default-export cjs default export should have logs from cache-handler",
"app-dir - custom-cache-handler - esm esm default export should have logs from cache-handler"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -3503,7 +3506,8 @@
"runtimeError": false
},
"test/e2e/app-dir/app-middleware-proxy/app-middleware-proxy.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"app-dir with proxy Mutate request headers for Edge Functions Adds new headers",
"app-dir with proxy Mutate request headers for Edge Functions Deletes headers",
"app-dir with proxy Mutate request headers for Edge Functions Updates headers",
@@ -3516,6 +3520,7 @@
"app-dir with proxy retains a link response header from the proxy",
"app-dir with proxy should be possible to modify cookies & read them in an RSC in a single request",
"app-dir with proxy should be possible to read cookies that are set during the proxy handling of a server action",
+ "app-dir with proxy should filter correctly after proxy rewrite",
"app-dir with proxy should ignore x-middleware-set-cookie as a request header",
"app-dir with proxy should log compilation time",
"app-dir with proxy should not incorrectly treat a Location header as a rewrite",
@@ -3523,9 +3528,6 @@
"app-dir with proxy should respect cookie options of merged proxy cookies",
"app-dir with proxy should support unstable_cache in proxy"
],
- "failed": [
- "app-dir with proxy should filter correctly after proxy rewrite"
- ],
"pending": [
"app-dir with proxy Mutate request headers for Edge Functions Supports draft mode",
"app-dir with proxy Mutate request headers for Serverless Functions Supports draft mode",
@@ -3707,7 +3709,8 @@
"runtimeError": false
},
"test/e2e/app-dir/app-routes/app-custom-route-base-path.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"app-custom-routes automatic implementations implements HEAD on routes with GET already implemented",
"app-custom-routes automatic implementations implements OPTIONS on routes",
"app-custom-routes basic fetch request with a response abort via a DELETE request aborts without error on /basic/endpoint",
@@ -3776,12 +3779,11 @@
"app-custom-routes works with generateStaticParams correctly revalidates correctly on /revalidate-1/second/data.json",
"app-custom-routes works with generateStaticParams correctly revalidates correctly on /revalidate-1/three/data.json"
],
- "failed": [],
"pending": [
"app-custom-routes basic fetch request with a response response supports the NextResponse.rewrite() helper"
],
"flakey": [],
- "runtimeError": false
+ "runtimeError": true
},
"test/e2e/app-dir/app-routes/app-custom-routes.test.ts": {
"passed": [
@@ -3964,8 +3966,7 @@
"runtimeError": false
},
"test/e2e/app-dir/app-static/app-static.test.ts": {
- "passed": [],
- "failed": [
+ "passed": [
"app-dir static/dynamic handling Incremental cache limits should not cache request if response data size is greater than 2MB and FetchCache is possible in development mode",
"app-dir static/dynamic handling it should revalidate tag correctly with edge route handler",
"app-dir static/dynamic handling it should revalidate tag correctly with node route handler",
@@ -4053,6 +4054,7 @@
"app-dir static/dynamic handling useSearchParams client should bailout to client rendering - with suspense boundary",
"app-dir static/dynamic handling useSearchParams client should have values from canonical url on rewrite"
],
+ "failed": [],
"pending": [
"app-dir static/dynamic handling should correctly de-dupe fetch without next cache /react-fetch-deduping-edge",
"app-dir static/dynamic handling should correctly de-dupe fetch without next cache /react-fetch-deduping-node",
@@ -4277,11 +4279,11 @@
"runtimeError": false
},
"test/e2e/app-dir/autoscroll-with-css-modules/index.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"router autoscrolling on navigation with css modules vertical scroll when page imports css modules should scroll to top of document when navigating between to pages without layout when",
"router autoscrolling on navigation with css modules vertical scroll when page imports css modules should scroll when clicking in JS"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -4310,10 +4312,10 @@
"runtimeError": false
},
"test/e2e/app-dir/binary/rsc-binary.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"RSC binary serialization should correctly encode/decode binaries and hydrate"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -4435,7 +4437,8 @@
"runtimeError": false
},
"test/e2e/app-dir/cache-components-errors/cache-components-errors.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"Cache Components Errors Dev Dynamic Boundary should not show a collapsed redbox error",
"Cache Components Errors Dev Dynamic Metadata - Dynamic Route should not show a collapsed redbox error",
"Cache Components Errors Dev Dynamic Metadata - Error Route should show a collapsed redbox error",
@@ -4497,7 +4500,6 @@
"Cache Components Errors Dev With `use cache: private` in `use cache` should show a redbox error",
"Cache Components Errors Dev With `use cache: private` without Suspense should show a redbox error"
],
- "failed": [],
"pending": [
"Cache Components Errors Dev Unhandled Rejection Suppression should suppress unhandled rejections during prerender validation in dev",
"Cache Components Errors Dev With `use cache: private` with `connection()` should show a redbox error"
@@ -4516,11 +4518,11 @@
"runtimeError": false
},
"test/e2e/app-dir/cache-components-request-apis/cache-components-request-apis.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"Request Promises On Prerender Completion does not run in dev",
"Request Promises On Prerender Interruption does not run in dev"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -4724,12 +4726,12 @@
"runtimeError": false
},
"test/e2e/app-dir/cache-components/cache-components.web-crypto.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"cache-components should not have route specific errors",
"cache-components should prerender pages with cached `crypto.getRandomValues(...)` calls",
"cache-components should prerender pages with cached `crypto.randomUUID()` calls"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -4754,13 +4756,13 @@
"runtimeError": false
},
"test/e2e/app-dir/client-module-with-package-type/index.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"esm-client-module-without-exports \"type\": \"commonjs\" in package.json should render without errors: import cjs",
"esm-client-module-without-exports \"type\": \"commonjs\" in package.json should render without errors: require cjs",
"esm-client-module-without-exports \"type\": \"module\" in package.json should render without errors: import esm",
"esm-client-module-without-exports \"type\": \"module\" in package.json should render without errors: require esm"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -4879,17 +4881,19 @@
"runtimeError": false
},
"test/e2e/app-dir/css-modules-scoping/css-modules-scoping.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"css-modules-scoping should not prefix grid areas",
"css-modules-scoping should prefix animation"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
},
"test/e2e/app-dir/css-order/css-order.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
+ "css-order loose should load correct styles navigating first -> first-client",
"css-order loose should load correct styles navigating first -> second",
"css-order loose should load correct styles navigating first -> second-client",
"css-order loose should load correct styles navigating first -> third",
@@ -4936,6 +4940,7 @@
"css-order loose should load correct styles on second-client",
"css-order loose should load correct styles on third",
"css-order loose should load correct styles on vendor",
+ "css-order strict should load correct styles navigating first -> first-client",
"css-order strict should load correct styles navigating first -> second",
"css-order strict should load correct styles navigating first -> second-client",
"css-order strict should load correct styles navigating first -> third",
@@ -4989,10 +4994,6 @@
"css-order strict should load correct styles on third",
"css-order strict should load correct styles on vendor"
],
- "failed": [
- "css-order loose should load correct styles navigating first -> first-client",
- "css-order strict should load correct styles navigating first -> first-client"
- ],
"pending": [
"css-order loose should load correct styles navigating big-interleaved-a -> big-interleaved-b",
"css-order loose should load correct styles navigating big-interleaved-b -> big-interleaved-a",
@@ -5094,8 +5095,8 @@
"runtimeError": false
},
"test/e2e/app-dir/cssnano-colormin/index.test.ts": {
- "passed": ["cssnano-colormin should not minify rgb colors to hsla"],
- "failed": [],
+ "passed": [],
+ "failed": ["cssnano-colormin should not minify rgb colors to hsla"],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -5252,12 +5253,12 @@
"runtimeError": false
},
"test/e2e/app-dir/dynamic-in-generate-params/index.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"app-dir - dynamic in generate params should be able to call fetch while generating multiple dynamic pages",
"app-dir - dynamic in generate params should be able to call while generating multiple dynamic sitemaps",
"app-dir - dynamic in generate params should render sitemap with generateSitemaps in force-dynamic config dynamically"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -5282,7 +5283,8 @@
"runtimeError": false
},
"test/e2e/app-dir/dynamic/dynamic.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"app dir - next/dynamic no SSR should not render client component imported through ssr: false in client components",
"app dir - next/dynamic no SSR should not render client component imported through ssr: false in client components in edge runtime",
"app dir - next/dynamic no SSR should support dynamic import with TLA in client components",
@@ -5297,7 +5299,6 @@
"app dir - next/dynamic should not render loading by default",
"app dir - next/dynamic should render loading by default if loading is specified and loader is slow"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -5443,10 +5444,10 @@
"runtimeError": false
},
"test/e2e/app-dir/external-redirect/external-redirect.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"external-redirect regression: Server Action triggered from onClick redirects to external URL"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -5619,11 +5620,11 @@
"runtimeError": false
},
"test/e2e/app-dir/global-not-found/cache-components/cache-components.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"global-not-found - cache-components should render global-not-found for 404 routes",
"global-not-found - cache-components should render not-found boundary when calling notFound() in a page"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -5647,11 +5648,11 @@
"runtimeError": false
},
"test/e2e/app-dir/global-not-found/no-root-layout/no-root-layout.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"global-not-found - no-root-layout should render global-not-found for 404",
"global-not-found - no-root-layout should ssr global-not-found for 404"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -5806,8 +5807,7 @@
"instant validation - opting out of static shells does not require a static shell if a layout is configured as blocking",
"instant validation - opting out of static shells does not require a static shell if a page is configured as blocking",
"instant validation - opting out of static shells does not require a static shell if a root layouts is configured as blocking",
- "instant validation - with debug channel requires a static shell if a below a static layout page is configured as blocking errors in dev",
- "instant validation - without debug channel requires a static shell if a below a static layout page is configured as blocking errors in dev"
+ "instant validation requires a static shell if a below a static layout page is configured as blocking errors in dev"
],
"failed": [],
"pending": [],
@@ -5815,121 +5815,81 @@
"runtimeError": false
},
"test/e2e/app-dir/instant-validation/instant-validation.test.ts": {
- "passed": [
- "instant validation - with debug channel client navigation blocking invalid - blocking page inside a runtime layout is not allowed if the layout has no suspense",
- "instant validation - with debug channel client navigation blocking invalid - blocking page inside a static layout is not allowed if the layout has no suspense",
- "instant validation - with debug channel client navigation blocking invalid - missing suspense inside blocking layout",
- "instant validation - with debug channel client navigation blocking valid - blocking layout with unstable_instant = false is allowed to block",
- "instant validation - with debug channel client navigation blocking valid - blocking page inside a runtime layout is allowed if the layout has suspense",
- "instant validation - with debug channel client navigation blocking valid - blocking page inside a static layout is allowed if the layout has suspense",
- "instant validation - with debug channel client navigation disabling validation in a layout",
- "instant validation - with debug channel client navigation disabling validation in a page",
- "instant validation - with debug channel client navigation disabling validation in a page with a parent that has a config",
- "instant validation - with debug channel client navigation invalid - missing suspense around dynamic (with loading.js)",
- "instant validation - with debug channel client navigation invalid - missing suspense in parallel slot default slot",
- "instant validation - with debug channel client navigation invalid - missing suspense in parallel slot index",
- "instant validation - with debug channel client navigation invalid - missing suspense in parallel slot subpage",
- "instant validation - with debug channel client navigation invalid - runtime prefetch - missing suspense around dynamic",
- "instant validation - with debug channel client navigation invalid - runtime prefetch - missing suspense around dynamic in a layout",
- "instant validation - with debug channel client navigation invalid - runtime prefetch - suspense too high",
- "instant validation - with debug channel client navigation invalid - runtime prefetch - sync IO after runtime API",
- "instant validation - with debug channel client navigation invalid - static prefetch - missing suspense around dynamic",
- "instant validation - with debug channel client navigation invalid - static prefetch - missing suspense around dynamic in a layout",
- "instant validation - with debug channel client navigation invalid - static prefetch - missing suspense around params",
- "instant validation - with debug channel client navigation invalid - static prefetch - missing suspense around runtime",
- "instant validation - with debug channel client navigation invalid - static prefetch - missing suspense around search params",
- "instant validation - with debug channel client navigation invalid - static prefetch - suspense too high",
- "instant validation - with debug channel client navigation valid - runtime prefetch - does not require Suspense around params",
- "instant validation - with debug channel client navigation valid - runtime prefetch - does not require Suspense around search params",
- "instant validation - with debug channel client navigation valid - runtime prefetch - suspense only around dynamic",
- "instant validation - with debug channel client navigation valid - static prefetch - suspense around runtime and dynamic",
- "instant validation - with debug channel client navigation valid - target segment not visible in all navigations",
- "instant validation - with debug channel initial load blocking invalid - blocking page inside a runtime layout is not allowed if the layout has no suspense",
- "instant validation - with debug channel initial load blocking invalid - blocking page inside a static layout is not allowed if the layout has no suspense",
- "instant validation - with debug channel initial load blocking invalid - missing suspense inside blocking layout",
- "instant validation - with debug channel initial load blocking valid - blocking layout with unstable_instant = false is allowed to block",
- "instant validation - with debug channel initial load blocking valid - blocking page inside a runtime layout is allowed if the layout has suspense",
- "instant validation - with debug channel initial load blocking valid - blocking page inside a static layout is allowed if the layout has suspense",
- "instant validation - with debug channel initial load disabling validation in a layout",
- "instant validation - with debug channel initial load disabling validation in a page",
- "instant validation - with debug channel initial load disabling validation in a page with a parent that has a config",
- "instant validation - with debug channel initial load invalid - missing suspense around dynamic (with loading.js)",
- "instant validation - with debug channel initial load invalid - missing suspense in parallel slot default slot",
- "instant validation - with debug channel initial load invalid - missing suspense in parallel slot index",
- "instant validation - with debug channel initial load invalid - missing suspense in parallel slot subpage",
- "instant validation - with debug channel initial load invalid - runtime prefetch - missing suspense around dynamic",
- "instant validation - with debug channel initial load invalid - runtime prefetch - missing suspense around dynamic in a layout",
- "instant validation - with debug channel initial load invalid - runtime prefetch - suspense too high",
- "instant validation - with debug channel initial load invalid - runtime prefetch - sync IO after runtime API",
- "instant validation - with debug channel initial load invalid - static prefetch - missing suspense around dynamic",
- "instant validation - with debug channel initial load invalid - static prefetch - missing suspense around dynamic in a layout",
- "instant validation - with debug channel initial load invalid - static prefetch - missing suspense around params",
- "instant validation - with debug channel initial load invalid - static prefetch - missing suspense around runtime",
- "instant validation - with debug channel initial load invalid - static prefetch - missing suspense around search params",
- "instant validation - with debug channel initial load invalid - static prefetch - suspense too high",
- "instant validation - with debug channel initial load valid - runtime prefetch - does not require Suspense around params",
- "instant validation - with debug channel initial load valid - runtime prefetch - does not require Suspense around search params",
- "instant validation - with debug channel initial load valid - runtime prefetch - suspense only around dynamic",
- "instant validation - with debug channel initial load valid - static prefetch - suspense around runtime and dynamic",
- "instant validation - with debug channel initial load valid - target segment not visible in all navigations",
- "instant validation - without debug channel client navigation blocking invalid - blocking page inside a runtime layout is not allowed if the layout has no suspense",
- "instant validation - without debug channel client navigation blocking invalid - blocking page inside a static layout is not allowed if the layout has no suspense",
- "instant validation - without debug channel client navigation blocking invalid - missing suspense inside blocking layout",
- "instant validation - without debug channel client navigation blocking valid - blocking layout with unstable_instant = false is allowed to block",
- "instant validation - without debug channel client navigation blocking valid - blocking page inside a runtime layout is allowed if the layout has suspense",
- "instant validation - without debug channel client navigation blocking valid - blocking page inside a static layout is allowed if the layout has suspense",
- "instant validation - without debug channel client navigation disabling validation in a layout",
- "instant validation - without debug channel client navigation disabling validation in a page",
- "instant validation - without debug channel client navigation disabling validation in a page with a parent that has a config",
- "instant validation - without debug channel client navigation invalid - missing suspense around dynamic (with loading.js)",
- "instant validation - without debug channel client navigation invalid - missing suspense in parallel slot default slot",
- "instant validation - without debug channel client navigation invalid - missing suspense in parallel slot index",
- "instant validation - without debug channel client navigation invalid - missing suspense in parallel slot subpage",
- "instant validation - without debug channel client navigation invalid - runtime prefetch - missing suspense around dynamic",
- "instant validation - without debug channel client navigation invalid - runtime prefetch - missing suspense around dynamic in a layout",
- "instant validation - without debug channel client navigation invalid - runtime prefetch - suspense too high",
- "instant validation - without debug channel client navigation invalid - runtime prefetch - sync IO after runtime API",
- "instant validation - without debug channel client navigation invalid - static prefetch - missing suspense around dynamic",
- "instant validation - without debug channel client navigation invalid - static prefetch - missing suspense around dynamic in a layout",
- "instant validation - without debug channel client navigation invalid - static prefetch - missing suspense around params",
- "instant validation - without debug channel client navigation invalid - static prefetch - missing suspense around runtime",
- "instant validation - without debug channel client navigation invalid - static prefetch - missing suspense around search params",
- "instant validation - without debug channel client navigation invalid - static prefetch - suspense too high",
- "instant validation - without debug channel client navigation valid - runtime prefetch - does not require Suspense around params",
- "instant validation - without debug channel client navigation valid - runtime prefetch - does not require Suspense around search params",
- "instant validation - without debug channel client navigation valid - runtime prefetch - suspense only around dynamic",
- "instant validation - without debug channel client navigation valid - static prefetch - suspense around runtime and dynamic",
- "instant validation - without debug channel client navigation valid - target segment not visible in all navigations",
- "instant validation - without debug channel initial load blocking invalid - blocking page inside a runtime layout is not allowed if the layout has no suspense",
- "instant validation - without debug channel initial load blocking invalid - blocking page inside a static layout is not allowed if the layout has no suspense",
- "instant validation - without debug channel initial load blocking invalid - missing suspense inside blocking layout",
- "instant validation - without debug channel initial load blocking valid - blocking layout with unstable_instant = false is allowed to block",
- "instant validation - without debug channel initial load blocking valid - blocking page inside a runtime layout is allowed if the layout has suspense",
- "instant validation - without debug channel initial load blocking valid - blocking page inside a static layout is allowed if the layout has suspense",
- "instant validation - without debug channel initial load disabling validation in a layout",
- "instant validation - without debug channel initial load disabling validation in a page",
- "instant validation - without debug channel initial load disabling validation in a page with a parent that has a config",
- "instant validation - without debug channel initial load invalid - missing suspense around dynamic (with loading.js)",
- "instant validation - without debug channel initial load invalid - missing suspense in parallel slot default slot",
- "instant validation - without debug channel initial load invalid - missing suspense in parallel slot index",
- "instant validation - without debug channel initial load invalid - missing suspense in parallel slot subpage",
- "instant validation - without debug channel initial load invalid - runtime prefetch - missing suspense around dynamic",
- "instant validation - without debug channel initial load invalid - runtime prefetch - missing suspense around dynamic in a layout",
- "instant validation - without debug channel initial load invalid - runtime prefetch - suspense too high",
- "instant validation - without debug channel initial load invalid - runtime prefetch - sync IO after runtime API",
- "instant validation - without debug channel initial load invalid - static prefetch - missing suspense around dynamic",
- "instant validation - without debug channel initial load invalid - static prefetch - missing suspense around dynamic in a layout",
- "instant validation - without debug channel initial load invalid - static prefetch - missing suspense around params",
- "instant validation - without debug channel initial load invalid - static prefetch - missing suspense around runtime",
- "instant validation - without debug channel initial load invalid - static prefetch - missing suspense around search params",
- "instant validation - without debug channel initial load invalid - static prefetch - suspense too high",
- "instant validation - without debug channel initial load valid - runtime prefetch - does not require Suspense around params",
- "instant validation - without debug channel initial load valid - runtime prefetch - does not require Suspense around search params",
- "instant validation - without debug channel initial load valid - runtime prefetch - suspense only around dynamic",
- "instant validation - without debug channel initial load valid - static prefetch - suspense around runtime and dynamic",
- "instant validation - without debug channel initial load valid - target segment not visible in all navigations"
+ "passed": [],
+ "failed": [
+ "instant validation client navigation blocking invalid - blocking page inside a runtime layout is not allowed if the layout has no suspense",
+ "instant validation client navigation blocking invalid - blocking page inside a static layout is not allowed if the layout has no suspense",
+ "instant validation client navigation blocking invalid - missing suspense inside blocking layout",
+ "instant validation client navigation blocking valid - blocking layout with unstable_instant = false is allowed to block",
+ "instant validation client navigation blocking valid - blocking page inside a runtime layout is allowed if the layout has suspense",
+ "instant validation client navigation blocking valid - blocking page inside a static layout is allowed if the layout has suspense",
+ "instant validation client navigation client components unable to validate - parent suspends on client data and blocks children",
+ "instant validation client navigation client components valid - parent suspends on client data but does not block children",
+ "instant validation client navigation client components valid - parent uses dynamic usePathname() in a client component",
+ "instant validation client navigation client components valid - parent uses sync IO in a client component",
+ "instant validation client navigation client components valid - parent uses useSearchPatams() in a client component",
+ "instant validation client navigation client errors unable to validate - client error from sibling of children slot without suspense",
+ "instant validation client navigation client errors unable to validate - client error in parent blocks children",
+ "instant validation client navigation client errors valid - client error from sibling of children slot with suspense",
+ "instant validation client navigation disabling validation in a layout",
+ "instant validation client navigation disabling validation in a page",
+ "instant validation client navigation disabling validation in a page with a parent that has a config",
+ "instant validation client navigation invalid - missing suspense around dynamic (with loading.js)",
+ "instant validation client navigation invalid - missing suspense in parallel slot default slot",
+ "instant validation client navigation invalid - missing suspense in parallel slot index",
+ "instant validation client navigation invalid - missing suspense in parallel slot subpage",
+ "instant validation client navigation invalid - runtime prefetch - missing suspense around dynamic",
+ "instant validation client navigation invalid - runtime prefetch - missing suspense around dynamic in a layout",
+ "instant validation client navigation invalid - runtime prefetch - suspense too high",
+ "instant validation client navigation invalid - runtime prefetch - sync IO after runtime API",
+ "instant validation client navigation invalid - static prefetch - missing suspense around dynamic",
+ "instant validation client navigation invalid - static prefetch - missing suspense around dynamic in a layout",
+ "instant validation client navigation invalid - static prefetch - missing suspense around params",
+ "instant validation client navigation invalid - static prefetch - missing suspense around runtime",
+ "instant validation client navigation invalid - static prefetch - missing suspense around search params",
+ "instant validation client navigation invalid - static prefetch - suspense too high",
+ "instant validation client navigation valid - runtime prefetch - does not require Suspense around params",
+ "instant validation client navigation valid - runtime prefetch - does not require Suspense around search params",
+ "instant validation client navigation valid - runtime prefetch - suspense only around dynamic",
+ "instant validation client navigation valid - static prefetch - suspense around runtime and dynamic",
+ "instant validation client navigation valid - target segment not visible in all navigations",
+ "instant validation initial load blocking invalid - blocking page inside a runtime layout is not allowed if the layout has no suspense",
+ "instant validation initial load blocking invalid - blocking page inside a static layout is not allowed if the layout has no suspense",
+ "instant validation initial load blocking invalid - missing suspense inside blocking layout",
+ "instant validation initial load blocking valid - blocking layout with unstable_instant = false is allowed to block",
+ "instant validation initial load blocking valid - blocking page inside a runtime layout is allowed if the layout has suspense",
+ "instant validation initial load blocking valid - blocking page inside a static layout is allowed if the layout has suspense",
+ "instant validation initial load client components unable to validate - parent suspends on client data and blocks children",
+ "instant validation initial load client components valid - parent suspends on client data but does not block children",
+ "instant validation initial load client components valid - parent uses dynamic usePathname() in a client component",
+ "instant validation initial load client components valid - parent uses sync IO in a client component",
+ "instant validation initial load client components valid - parent uses useSearchPatams() in a client component",
+ "instant validation initial load client errors unable to validate - client error from sibling of children slot without suspense",
+ "instant validation initial load client errors unable to validate - client error in parent blocks children",
+ "instant validation initial load client errors valid - client error from sibling of children slot with suspense",
+ "instant validation initial load disabling validation in a layout",
+ "instant validation initial load disabling validation in a page",
+ "instant validation initial load disabling validation in a page with a parent that has a config",
+ "instant validation initial load invalid - missing suspense around dynamic (with loading.js)",
+ "instant validation initial load invalid - missing suspense in parallel slot default slot",
+ "instant validation initial load invalid - missing suspense in parallel slot index",
+ "instant validation initial load invalid - missing suspense in parallel slot subpage",
+ "instant validation initial load invalid - runtime prefetch - missing suspense around dynamic",
+ "instant validation initial load invalid - runtime prefetch - missing suspense around dynamic in a layout",
+ "instant validation initial load invalid - runtime prefetch - suspense too high",
+ "instant validation initial load invalid - runtime prefetch - sync IO after runtime API",
+ "instant validation initial load invalid - static prefetch - missing suspense around dynamic",
+ "instant validation initial load invalid - static prefetch - missing suspense around dynamic in a layout",
+ "instant validation initial load invalid - static prefetch - missing suspense around params",
+ "instant validation initial load invalid - static prefetch - missing suspense around runtime",
+ "instant validation initial load invalid - static prefetch - missing suspense around search params",
+ "instant validation initial load invalid - static prefetch - suspense too high",
+ "instant validation initial load valid - runtime prefetch - does not require Suspense around params",
+ "instant validation initial load valid - runtime prefetch - does not require Suspense around search params",
+ "instant validation initial load valid - runtime prefetch - suspense only around dynamic",
+ "instant validation initial load valid - static prefetch - suspense around runtime and dynamic",
+ "instant validation initial load valid - target segment not visible in all navigations"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -5953,19 +5913,18 @@
"runtimeError": false
},
"test/e2e/app-dir/interception-dynamic-segment/interception-dynamic-segment.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"interception-dynamic-segment should intercept consistently with back/forward navigation",
"interception-dynamic-segment should intercept multiple times from root",
"interception-dynamic-segment should work when interception route is paired with a dynamic segment"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
},
"test/e2e/app-dir/interception-dynamic-single-segment/interception-dynamic-single-segment.test.ts": {
- "passed": [],
- "failed": [
+ "passed": [
"interception-dynamic-single-segment nested navigation - descendants of intercepting route should intercept multiple times from the same route",
"interception-dynamic-single-segment nested navigation - descendants of intercepting route should intercept when navigating between different dynamic segments",
"interception-dynamic-single-segment nested navigation - descendants of intercepting route should intercept when navigating from a child route using back navigation",
@@ -5976,6 +5935,7 @@
"interception-dynamic-single-segment should intercept with programmatic navigation using router.push",
"interception-dynamic-single-segment should intercept with purely static multi-segment paths"
],
+ "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -6015,10 +5975,10 @@
"runtimeError": false
},
"test/e2e/app-dir/interception-routes-output-export/interception-routes-output-export.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"interception-routes-output-export should error when using interception routes with static export"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -6113,7 +6073,8 @@
"runtimeError": false
},
"test/e2e/app-dir/logging/fetch-logging.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"app-dir - fetch logging placeholder to satisfy at least one test when isNextDev is false",
"app-dir - fetch logging should not log requests for HMR refreshes",
"app-dir - logging with default logging should not contain metadata internal segments for dynamic metadata routes",
@@ -6168,10 +6129,9 @@
"app-dir - logging with verbose logging for edge runtime should show cache reason of noStore when use with fetch",
"app-dir - logging with verbose logging for edge runtime when logging.fetches.hmrRefreshes is true should log requests for HMR refreshes"
],
- "failed": [],
"pending": [],
"flakey": [],
- "runtimeError": false
+ "runtimeError": true
},
"test/e2e/app-dir/logging/fetch-warning.test.ts": {
"passed": [
@@ -6198,20 +6158,19 @@
"runtimeError": false
},
"test/e2e/app-dir/mdx-no-mdx-components/mdx.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"mdx app directory should allow importing client components",
"mdx app directory should work in initial html",
"mdx app directory should work using browser",
"mdx pages directory should work in initial html"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
},
"test/e2e/app-dir/mdx/mdx.test.ts": {
- "passed": [],
- "failed": [
+ "passed": [
"mdx with-mdx-rs app directory should allow importing client components",
"mdx with-mdx-rs app directory should allow overriding components",
"mdx with-mdx-rs app directory should work in initial html",
@@ -6240,6 +6199,7 @@
"mdx without-mdx-rs pages directory should work using browser",
"mdx without-mdx-rs pages directory should work using browser with mdx import"
],
+ "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -6383,11 +6343,11 @@
"runtimeError": false
},
"test/e2e/app-dir/metadata-static-file/metadata-static-file-dynamic-route.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"metadata-files-static-output-dynamic-route should have correct link tags for dynamic page with static placeholder",
"metadata-files-static-output-dynamic-route should serve static files when requested with placeholder for dynamic page"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -6413,11 +6373,11 @@
"runtimeError": false
},
"test/e2e/app-dir/metadata-static-file/metadata-static-file-parallel-route.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"metadata-files-static-output-parallel-route should have correct link tags for parallel slot page",
"metadata-files-static-output-parallel-route should serve static files when requested to its route for parallel slot page"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -6570,7 +6530,8 @@
"runtimeError": false
},
"test/e2e/app-dir/metadata/metadata.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"app dir - metadata basic should apply metadata when navigating client-side",
"app dir - metadata basic should handle metadataBase as url string",
"app dir - metadata basic should handle metadataBase for urls resolved as only URL type",
@@ -6620,7 +6581,6 @@
"app dir - metadata viewport should skip initial-scale from viewport if it is set to undefined",
"app dir - metadata viewport should support dynamic viewport export"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -6758,14 +6718,15 @@
"runtimeError": false
},
"test/e2e/app-dir/navigation-with-queued-actions/index.test.ts": {
- "passed": ["actions works"],
- "failed": [],
+ "passed": [],
+ "failed": ["actions works"],
"pending": [],
"flakey": [],
"runtimeError": false
},
"test/e2e/app-dir/navigation/navigation.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"app dir - navigation SEO should contain default meta tags in error page",
"app dir - navigation SEO should emit noindex meta tag for not found page when streaming",
"app dir - navigation SEO should emit refresh meta tag (permanent) for redirect page when streaming",
@@ -6818,7 +6779,6 @@
"app dir - navigation useRouter identity between navigations should preserve identity when navigating between different pages",
"app dir - navigation useRouter identity between navigations should preserve identity when navigating to the same page"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -7438,10 +7398,10 @@
"runtimeError": false
},
"test/e2e/app-dir/next-config-ts/import-js-extensions-esm/next-config-ts-import-js-extensions-esm.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"next-config-ts-import-js-extensions-esm should import js extensions (ESM)"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -7569,7 +7529,9 @@
"runtimeError": false
},
"test/e2e/app-dir/next-font/next-font.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
+ "app dir - next/font app dir - next-font Dev errors should recover on font loader error",
"app dir - next/font app dir - next-font computed styles should have correct styles at /",
"app dir - next/font app dir - next-font computed styles should have correct styles at /client",
"app dir - next/font app dir - next-font import values should have correct values at /",
@@ -7577,9 +7539,6 @@
"app dir - next/font app dir - next-font import values should transform code in node_modules",
"app dir - next/font app dir - next-font navigation should not have duplicate preload tags on navigation"
],
- "failed": [
- "app dir - next/font app dir - next-font Dev errors should recover on font loader error"
- ],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -7594,10 +7553,10 @@
"runtimeError": false
},
"test/e2e/app-dir/next-image-src-with-query-without-local-patterns/next-image-src-with-query-without-local-patterns.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"next-image-src-with-query-without-local-patterns should throw error for relative image with query without localPatterns"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -7612,14 +7571,14 @@
"runtimeError": false
},
"test/e2e/app-dir/next-image/next-image-proxy.test.ts": {
- "passed": [],
- "failed": [
+ "passed": [
"next-image-proxy loads images without any errors",
"next-image-proxy should work with connection upgrade by removing it via filterReqHeaders()"
],
+ "failed": [],
"pending": [],
"flakey": [],
- "runtimeError": true
+ "runtimeError": false
},
"test/e2e/app-dir/next-image/next-image.test.ts": {
"passed": [],
@@ -7776,7 +7735,8 @@
"runtimeError": false
},
"test/e2e/app-dir/not-found/basic/index.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"app dir - not-found - basic should propagate notFound errors past a segment's error boundary",
"app dir - not-found - basic should return 404 status code for custom not-found page",
"app dir - not-found - basic with default runtime should escalate notFound to parent layout if no not-found boundary present in current layer",
@@ -7791,10 +7751,9 @@
"app dir - not-found - basic with runtime = edge should return 404 status if notFound() is called in shell",
"app dir - not-found - basic with runtime = edge should use the not-found page for non-matching routes"
],
- "failed": [],
"pending": [],
"flakey": [],
- "runtimeError": false
+ "runtimeError": true
},
"test/e2e/app-dir/not-found/conflict-route/index.test.ts": {
"passed": [
@@ -7827,11 +7786,11 @@
"runtimeError": false
},
"test/e2e/app-dir/not-found/group-route-root-not-found/index.test.ts": {
- "passed": [],
- "failed": [
+ "passed": [
"app dir - group routes with root not-found should render default 404 with root layout for non-existent page",
"app dir - group routes with root not-found should render root not found for group routes if hit 404"
],
+ "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -7944,7 +7903,8 @@
"runtimeError": false
},
"test/e2e/app-dir/parallel-routes-and-interception/parallel-routes-and-interception.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"parallel-routes-and-interception (trailingSlash: false) parallel routes should apply the catch-all route to the parallel route if no matching route is found",
"parallel-routes-and-interception (trailingSlash: false) parallel routes should display all parallel route params with useParams",
"parallel-routes-and-interception (trailingSlash: false) parallel routes should handle a loading state",
@@ -8003,19 +7963,18 @@
"parallel-routes-and-interception (trailingSlash: true) route intercepting with prerendered dynamic routes should render intercepted route",
"parallel-routes-and-interception-conflicting-pages should gracefully handle when two page segments match the `children` parallel slot"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
},
"test/e2e/app-dir/parallel-routes-breadcrumbs/parallel-routes-breadcrumbs.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"parallel-routes-breadcrumbs should provide an unmatched catch-all route with params",
"parallel-routes-breadcrumbs should render the breadcrumbs correctly with catchall route segments",
"parallel-routes-breadcrumbs should render the breadcrumbs correctly with optional catchall route segments",
"parallel-routes-breadcrumbs should render the breadcrumbs correctly with the non-dynamic route segments"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -8039,10 +7998,10 @@
"runtimeError": false
},
"test/e2e/app-dir/parallel-routes-catchall-dynamic-segment/parallel-routes-catchall-dynamic-segment.test.ts": {
- "passed": [],
- "failed": [
+ "passed": [
"parallel-routes-catchall-dynamic-segment should match default and dynamic segment paths before catch-all"
],
+ "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -8147,7 +8106,8 @@
"runtimeError": false
},
"test/e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"parallel-routes-revalidation router.refresh (dynamic) - searchParams: false should correctly refresh data for previously intercepted modal and active page slot",
"parallel-routes-revalidation router.refresh (dynamic) - searchParams: false should correctly refresh data for the intercepted route and previously active page slot",
"parallel-routes-revalidation router.refresh (dynamic) - searchParams: true should correctly refresh data for previously intercepted modal and active page slot",
@@ -8167,7 +8127,6 @@
"parallel-routes-revalidation should refresh the correct page when a server action triggers a redirect",
"parallel-routes-revalidation should submit the action and revalidate the page data"
],
- "failed": [],
"pending": [
"parallel-routes-revalidation server action revalidation should not trigger a refresh for the page that is being redirected to"
],
@@ -8175,7 +8134,8 @@
"runtimeError": false
},
"test/e2e/app-dir/parallel-routes-root-param-dynamic-child/parallel-routes-root-param-dynamic-child.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"parallel-routes-root-param-dynamic-child Base Routes should render a 200 for /en (in generateStaticParams)",
"parallel-routes-root-param-dynamic-child Base Routes should render a 200 for /fr (in generateStaticParams)",
"parallel-routes-root-param-dynamic-child Base Routes should render a 404 for /es (not in generateStaticParams)",
@@ -8190,7 +8150,6 @@
"parallel-routes-root-param-dynamic-child Without generateStaticParams (no-gsp) should render a 200 for /es/no-gsp/stories/dynamic-123",
"parallel-routes-root-param-dynamic-child Without generateStaticParams (no-gsp) should render a 200 for /fr/no-gsp/stories/dynamic-123"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -8227,13 +8186,13 @@
"runtimeError": false
},
"test/e2e/app-dir/phase-changes/cookies.test.ts": {
- "passed": [],
- "failed": [
+ "passed": [
"setting cookies stops cookie mutations when changing phases from a route handler to after via closure",
"setting cookies stops cookie mutations when changing phases from an action to a page render",
"setting cookies stops cookie mutations when changing phases from an action to after via closure",
"setting cookies stops cookie mutations when changing phases from middleware to after via closure"
],
+ "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -8600,23 +8559,23 @@
"runtimeError": false
},
"test/e2e/app-dir/react-max-headers-length/react-max-headers-length.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"react-max-headers-length reactMaxHeadersLength = 0 should respect reactMaxHeadersLength",
"react-max-headers-length reactMaxHeadersLength = 10000 should respect reactMaxHeadersLength",
"react-max-headers-length reactMaxHeadersLength = 400 should respect reactMaxHeadersLength",
"react-max-headers-length reactMaxHeadersLength = undefined should respect reactMaxHeadersLength"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
},
"test/e2e/app-dir/reexport-client-component-metadata/reexport-client-component-metadata.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"app-dir - reexport-client-component-metadata should render the layout metadata if not override",
"app-dir - reexport-client-component-metadata should render the page metadata if override"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -8642,10 +8601,10 @@
"runtimeError": false
},
"test/e2e/app-dir/require-context/require-context.test.ts": {
- "passed": [],
- "failed": [
+ "passed": [
"require-context should get correct require context when using regex filtering"
],
+ "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -8771,7 +8730,8 @@
"runtimeError": false
},
"test/e2e/app-dir/rewrites-redirects/rewrites-redirects.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"redirects and rewrites navigation using button should redirect from middleware correctly",
"redirects and rewrites navigation using button should redirect from next.config.js correctly",
"redirects and rewrites navigation using button should redirect from next.config.js correctly with empty query params",
@@ -8787,7 +8747,6 @@
"redirects and rewrites redirects to exotic url schemes preserving slashes",
"redirects and rewrites redirects to exotic url schemes without adding unwanted slashes"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -8800,16 +8759,17 @@
"runtimeError": false
},
"test/e2e/app-dir/root-layout-render-once/index.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"app-dir root layout render once should only render root layout once"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
},
"test/e2e/app-dir/root-layout/root-layout.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"app-dir root layout Should do a mpa navigation when switching root layout should work with basic routes",
"app-dir root layout Should do a mpa navigation when switching root layout should work with dynamic catchall routes",
"app-dir root layout Should do a mpa navigation when switching root layout should work with dynamic routes",
@@ -8819,7 +8779,6 @@
"app-dir root layout should correctly handle navigation between multiple root layouts",
"app-dir root layout should correctly handle navigation between multiple root layouts when redirecting in a server action"
],
- "failed": [],
"pending": [
"app-dir root layout Missing required tags should error on page load",
"app-dir root layout Missing required tags should error on page load on static generation",
@@ -8847,8 +8806,7 @@
"runtimeError": false
},
"test/e2e/app-dir/router-autoscroll/router-autoscroll.test.ts": {
- "passed": [],
- "failed": [
+ "passed": [
"router autoscrolling on navigation bugs Should apply scroll when loading.js is used",
"router autoscrolling on navigation bugs Should scroll to the top of the layout when the first child is display none",
"router autoscrolling on navigation bugs Should scroll to the top of the layout when the first child is position fixed",
@@ -8867,6 +8825,7 @@
"router autoscrolling on navigation vertical scroll should scroll to top of document with new metadata",
"router autoscrolling on navigation vertical scroll should scroll to top of page when scrolling to phe top of the document wouldn't have the page in the viewport"
],
+ "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -9021,21 +8980,21 @@
"runtimeError": false
},
"test/e2e/app-dir/scss/basic-module-prepend-data/basic-module-prepend-data.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"Basic Module Prepend Data Support ({\"sass\": \"1.54.0\"}) should render the module",
"Basic Module Prepend Data Support ({\"sass-embedded\": \"1.75.0\"}) should render the module"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
},
"test/e2e/app-dir/scss/basic-module/basic-module.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"Basic SCSS Module Support ({\"sass\": \"1.54.0\"}) should render the module",
"Basic SCSS Module Support ({\"sass-embedded\": \"1.75.0\"}) should render the module"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -9061,11 +9020,11 @@
"runtimeError": false
},
"test/e2e/app-dir/scss/composes-basic/composes-basic.test.ts": {
- "passed": [],
- "failed": [
+ "passed": [
"CSS Module Composes Usage (Basic) ({\"sass\": \"1.54.0\"}) should render the module",
"CSS Module Composes Usage (Basic) ({\"sass-embedded\": \"1.75.0\"}) should render the module"
],
+ "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -9170,21 +9129,21 @@
"runtimeError": false
},
"test/e2e/app-dir/scss/loader-order/loader-order.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"SCSS Support loader handling Preprocessor loader order ({\"sass\": \"1.54.0\"}) should render the module",
"SCSS Support loader handling Preprocessor loader order ({\"sass-embedded\": \"1.75.0\"}) should render the module"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
},
"test/e2e/app-dir/scss/multi-global-reversed/multi-global-reversed.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"(SCSS) Multi Global Support (reversed) ({\"sass\": \"1.54.0\"}) should render the page",
"(SCSS) Multi Global Support (reversed) ({\"sass-embedded\": \"1.75.0\"}) should render the page"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -9214,11 +9173,11 @@
"runtimeError": false
},
"test/e2e/app-dir/scss/nested-global/nested-global.test.ts": {
- "passed": [],
- "failed": [
+ "passed": [
"Nested @import() Global Support ({\"sass\": \"1.54.0\"}) should render the page",
"Nested @import() Global Support ({\"sass-embedded\": \"1.75.0\"}) should render the page"
],
+ "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -9318,11 +9277,11 @@
"runtimeError": false
},
"test/e2e/app-dir/scss/unused/unused.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"unused scss Body is not hidden when broken in Development development only should have body visible",
"unused scss Body is not hidden when unused in Development ($dependencies) development only should have body visible"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -9368,10 +9327,10 @@
"runtimeError": false
},
"test/e2e/app-dir/scss/valid-and-invalid-global/valid-and-invalid-global.test.ts": {
- "passed": [],
- "failed": [
+ "passed": [
"Valid and Invalid Global CSS with Custom App should show a build error"
],
+ "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -9479,15 +9438,15 @@
"runtimeError": false
},
"test/e2e/app-dir/segment-cache/force-stale/force-stale.test.ts": {
- "passed": ["force stale prefetching is disabled in dev"],
- "failed": [],
+ "passed": [],
+ "failed": ["force stale prefetching is disabled in dev"],
"pending": [],
"flakey": [],
"runtimeError": false
},
"test/e2e/app-dir/segment-cache/memory-pressure/segment-cache-memory-pressure.test.ts": {
- "passed": ["segment cache memory pressure disabled in development"],
- "failed": [],
+ "passed": [],
+ "failed": ["segment cache memory pressure disabled in development"],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -9605,16 +9564,17 @@
"runtimeError": false
},
"test/e2e/app-dir/self-importing-package/self-importing-package.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"self-importing-package should resolve self-imports in an external package"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
},
"test/e2e/app-dir/server-action-logging/server-action-logging.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"server-action-logging should log error action",
"server-action-logging should log inline action",
"server-action-logging should log notFound action",
@@ -9627,7 +9587,6 @@
"server-action-logging should show relative file path in log",
"server-action-logging when logging.serverFunctions is disabled should not log server actions"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -9656,12 +9615,12 @@
"runtimeError": false
},
"test/e2e/app-dir/server-components-externals/index.test.ts": {
- "passed": [],
- "failed": [
+ "passed": [
"app-dir - server components externals should externalize serversExternalPackages for server rendering layer",
"app-dir - server components externals should have externals for those in config.serverExternalPackages",
"app-dir - server components externals uses externals for predefined list in server-external-packages.json"
],
+ "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -9780,13 +9739,13 @@
"runtimeError": false
},
"test/e2e/app-dir/static-siblings/static-siblings.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"static-siblings cross-route-group siblings should navigate to static sibling after visiting dynamic route",
"static-siblings deeply nested siblings should navigate to static sibling after visiting dynamic route",
"static-siblings parallel route siblings should navigate to static sibling after visiting dynamic route",
"static-siblings same-directory siblings should navigate to static sibling after visiting dynamic route"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -9806,8 +9765,8 @@
"runtimeError": false
},
"test/e2e/app-dir/syntax-highlighter-crash/syntax-highlighter-crash.test.ts": {
- "passed": ["syntax-highlighter-crash should render the page"],
- "failed": [],
+ "passed": [],
+ "failed": ["syntax-highlighter-crash should render the page"],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -9829,11 +9788,11 @@
"runtimeError": false
},
"test/e2e/app-dir/temporary-references/temporary-references.test.ts": {
- "passed": [],
- "failed": [
+ "passed": [
"temporary-references should return the same object that was sent to the action (edge)",
"temporary-references should return the same object that was sent to the action (node)"
],
+ "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -9937,13 +9896,13 @@
"runtimeError": false
},
"test/e2e/app-dir/typed-routes/typed-routes.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"typed-routes should correctly convert custom route patterns from path-to-regexp to bracket syntax",
"typed-routes should generate RouteContext type for route handlers",
"typed-routes should generate route types correctly",
"typed-routes should update route types file when routes change"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -9956,22 +9915,22 @@
"runtimeError": false
},
"test/e2e/app-dir/unauthorized/basic/unauthorized-basic.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"app dir - unauthorized - basic should escalate unauthorized to parent layout if no unauthorized boundary present in current layer",
"app dir - unauthorized - basic should match dynamic route unauthorized boundary correctly"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
},
"test/e2e/app-dir/unauthorized/default/unauthorized-default.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"app dir - unauthorized with default unauthorized boundary should be able to navigate to page calling unauthorized",
"app dir - unauthorized with default unauthorized boundary should be able to navigate to page with calling unauthorized in metadata",
"app dir - unauthorized with default unauthorized boundary should render default unauthorized for group routes if unauthorized is not defined"
],
- "failed": [],
"pending": [
"app dir - unauthorized with default unauthorized boundary should error on client unauthorized from root layout in browser",
"app dir - unauthorized with default unauthorized boundary should error on server unauthorized from root layout on server-side"
@@ -10002,11 +9961,11 @@
"runtimeError": false
},
"test/e2e/app-dir/unstable-rethrow/unstable-rethrow.test.ts": {
- "passed": [],
- "failed": [
+ "passed": [
"unstable-rethrow should correctly trigger the not found page as not found",
"unstable-rethrow should handle an internal error that gets propagated to the `cause` field"
],
+ "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -10109,14 +10068,13 @@
"runtimeError": false
},
"test/e2e/app-dir/use-cache-search-params/use-cache-search-params.test.ts": {
- "passed": [
- "use-cache-search-params when searchParams are caught inside of \"use cache\" should also show an error after the second reload",
- "use-cache-search-params when searchParams are caught inside of \"use cache\" should show an error",
- "use-cache-search-params when searchParams are unused inside of \"use cache\" should not show an error"
- ],
+ "passed": [],
"failed": [
"use-cache-search-params should show an error when searchParams are used inside of a cached generateMetadata",
"use-cache-search-params should show an error when searchParams are used inside of a cached generateViewport",
+ "use-cache-search-params when searchParams are caught inside of \"use cache\" should also show an error after the second reload",
+ "use-cache-search-params when searchParams are caught inside of \"use cache\" should show an error",
+ "use-cache-search-params when searchParams are unused inside of \"use cache\" should not show an error",
"use-cache-search-params when searchParams are used inside of \"use cache\" should show an error"
],
"pending": [],
@@ -10133,22 +10091,22 @@
"runtimeError": false
},
"test/e2e/app-dir/use-cache-unknown-cache-kind/use-cache-unknown-cache-kind.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"use-cache-unknown-cache-kind should not show an error for default cache kinds",
"use-cache-unknown-cache-kind should recover from the build error if the cache handler is defined",
"use-cache-unknown-cache-kind should show a build error"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
},
"test/e2e/app-dir/use-cache-with-server-function-props/use-cache-with-server-function-props.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"use-cache-with-server-function-props should be able to use inline server actions as props",
"use-cache-with-server-function-props should be able to use nested cache functions as props"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -10211,8 +10169,7 @@
"runtimeError": false
},
"test/e2e/app-dir/use-params/use-params.test.ts": {
- "passed": [],
- "failed": [
+ "passed": [
"use-params should work for catch all params",
"use-params should work for nested dynamic params",
"use-params should work for nested dynamic params client navigating",
@@ -10221,6 +10178,7 @@
"use-params should work on pages router",
"use-params shouldn't rerender host component when prefetching"
],
+ "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -10317,10 +10275,10 @@
"runtimeError": false
},
"test/e2e/app-dir/webpack-loader-set-environment-variable/webpack-loader-set-environment-variable.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"webpack-loader-set-environment-variable loader that sets an environment variable should work"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -10335,17 +10293,17 @@
"runtimeError": false
},
"test/e2e/app-dir/with-babel/with-babel.test.ts": {
- "passed": ["with babel should support babel in app dir"],
- "failed": [],
+ "passed": [],
+ "failed": ["with babel should support babel in app dir"],
"pending": [],
"flakey": [],
"runtimeError": false
},
"test/e2e/app-dir/with-exported-function-config/with-exported-function-config.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"with-exported-function-config should have correct values in function config manifest"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -10378,13 +10336,13 @@
"runtimeError": false
},
"test/e2e/app-document/client.test.ts": {
- "passed": [],
- "failed": [
+ "passed": [
"Document and App - Client side should detect the changes to pages/_app.js and display it",
"Document and App - Client side should detect the changes to pages/_document.js and display it",
"Document and App - Client side should keep state between page navigations",
"Document and App - Client side should share module state with pages"
],
+ "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -10543,13 +10501,13 @@
"runtimeError": false
},
"test/e2e/basepath/router-events.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"basePath should use urls with basepath in router events",
"basePath should use urls with basepath in router events for cancelled routes",
"basePath should use urls with basepath in router events for failed route change",
"basePath should use urls with basepath in router events for hash changes"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -10566,11 +10524,11 @@
"runtimeError": false
},
"test/e2e/browserslist-extends/index.test.ts": {
- "passed": ["browserslist-extends should work"],
- "failed": [],
+ "passed": [],
+ "failed": ["browserslist-extends should work"],
"pending": [],
"flakey": [],
- "runtimeError": false
+ "runtimeError": true
},
"test/e2e/browserslist/browserslist.test.ts": {
"passed": [],
@@ -10602,8 +10560,7 @@
"runtimeError": false
},
"test/e2e/cancel-request/stream-cancel.test.ts": {
- "passed": [],
- "failed": [
+ "passed": [
"streaming responses cancel inner stream after disconnect edge app route handler cancels stalled stream",
"streaming responses cancel inner stream after disconnect edge app route handler cancels stream making progress",
"streaming responses cancel inner stream after disconnect edge app route handler cancels stream that never sent data",
@@ -10620,6 +10577,7 @@
"streaming responses cancel inner stream after disconnect node pages api cancels stream making progress",
"streaming responses cancel inner stream after disconnect node pages api cancels stream that never sent data"
],
+ "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -10719,14 +10677,14 @@
"runtimeError": false
},
"test/e2e/conflicting-app-page-error/index.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"Conflict between app file and pages file should error again when there is new conflict",
"Conflict between app file and pages file should not show error overlay for non conflict pages under app or pages dir",
"Conflict between app file and pages file should show error overlay for /",
"Conflict between app file and pages file should show error overlay for /another",
"Conflict between app file and pages file should support hmr with conflicts"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -10739,17 +10697,17 @@
"runtimeError": false
},
"test/e2e/cpu-profiling/cpu-profiling-dev.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"CPU Profiling - next dev should create CPU profile files on exit"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
},
"test/e2e/cpu-profiling/cpu-profiling.test.ts": {
- "passed": ["CPU Profiling - next start skip for development/deploy mode"],
- "failed": [],
+ "passed": [],
+ "failed": ["CPU Profiling - next start skip for development/deploy mode"],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -10776,8 +10734,7 @@
"runtimeError": false
},
"test/e2e/deferred-entries/deferred-entries.test.ts": {
- "passed": [],
- "failed": [
+ "passed": [
"deferred-entries should build app router dynamic and catch-all routes when using deferred entries",
"deferred-entries should build app router dynamic route with generateStaticParams when using deferred entries",
"deferred-entries should build app router metadata routes when using deferred entries",
@@ -10802,9 +10759,10 @@
"deferred-entries should run middleware for app router, pages router, and API routes",
"deferred-entries should update deferred rendered timestamp during HMR when non-deferred entry changes"
],
+ "failed": [],
"pending": [],
"flakey": [],
- "runtimeError": true
+ "runtimeError": false
},
"test/e2e/define/define.test.ts": {
"passed": [
@@ -10918,16 +10876,17 @@
"runtimeError": false
},
"test/e2e/edge-compiler-module-exports-preference/index.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"Edge compiler module exports preference favors the browser export"
],
- "failed": [],
"pending": [],
"flakey": [],
- "runtimeError": false
+ "runtimeError": true
},
"test/e2e/edge-configurable-runtime/index.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"Configurable runtime for pages and API routes In development mode errors about page using edge runtime",
"Configurable runtime for pages and API routes In development mode runs with no warning API route on the edge runtime",
"Configurable runtime for pages and API routes In development mode warns about API route using experimental-edge runtime",
@@ -10937,22 +10896,22 @@
"Configurable runtime for src/pages and API routes In development mode warns about API route using experimental-edge runtime",
"Configurable runtime for src/pages and API routes In development mode warns about page using edge runtime"
],
- "failed": [],
"pending": [],
"flakey": [],
- "runtimeError": false
+ "runtimeError": true
},
"test/e2e/edge-pages-support/edge-document.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"edge render - custom _document with edge runtime should render page properly"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
},
"test/e2e/edge-pages-support/index.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"edge-render-getserversideprops should have correct query for pages/api",
"edge-render-getserversideprops should have correct query for pages/api dynamic",
"edge-render-getserversideprops should have correct query/params on /[id]",
@@ -10962,7 +10921,6 @@
"edge-render-getserversideprops should respond to _next/data for [id] correctly",
"edge-render-getserversideprops should respond to _next/data for index correctly"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -10989,10 +10947,10 @@
"runtimeError": false
},
"test/e2e/error-handler-not-found-req-url/error-handler-not-found-req-url.test.ts": {
- "passed": [],
- "failed": [
+ "passed": [
"error-handler-not-found-req-url should log the correct request url and asPath for not found _error page"
],
+ "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -11153,18 +11111,19 @@
"runtimeError": false
},
"test/e2e/i18n-api-support/index.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"i18n API support should fallback rewrite non-matching API request",
"i18n API support should respond to normal API request",
"i18n API support should respond to normal dynamic API request"
],
- "failed": [],
"pending": [],
"flakey": [],
- "runtimeError": false
+ "runtimeError": true
},
"test/e2e/i18n-data-fetching-redirect/redirect-from-context.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"i18n-data-fetching-redirect Redirect to locale from context gsp-blocking-redirect en",
"i18n-data-fetching-redirect Redirect to locale from context gsp-blocking-redirect sv",
"i18n-data-fetching-redirect Redirect to locale from context gsp-fallback-redirect en",
@@ -11178,13 +11137,13 @@
"i18n-data-fetching-redirect Redirect to locale from context next/link gssp-redirect en",
"i18n-data-fetching-redirect Redirect to locale from context next/link gssp-redirect sv"
],
- "failed": [],
"pending": [],
"flakey": [],
- "runtimeError": false
+ "runtimeError": true
},
"test/e2e/i18n-data-fetching-redirect/redirect.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"i18n-data-fetching-redirect Redirect to another locale gsp-blocking-redirect en -> sv",
"i18n-data-fetching-redirect Redirect to another locale gsp-blocking-redirect sv -> en",
"i18n-data-fetching-redirect Redirect to another locale gsp-fallback-redirect en -> sv",
@@ -11198,13 +11157,13 @@
"i18n-data-fetching-redirect Redirect to another locale next/link gssp-redirect en -> sv",
"i18n-data-fetching-redirect Redirect to another locale next/link gssp-redirect sv -> en"
],
- "failed": [],
"pending": [],
"flakey": [],
- "runtimeError": false
+ "runtimeError": true
},
"test/e2e/i18n-data-route/i18n-data-route.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"i18n-data-route with locale prefix /en-CA should render /[slug]/about via /en-CA/blog/about",
"i18n-data-route with locale prefix /en-CA should render /about via /en-CA/about",
"i18n-data-route with locale prefix /en-CA should serve data for /[slug]/about",
@@ -11218,7 +11177,6 @@
"i18n-data-route without locale prefix should serve data for /[slug]/about",
"i18n-data-route without locale prefix should serve data for /about"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -11299,8 +11257,7 @@
"runtimeError": false
},
"test/e2e/i18n-fallback-collision/i18n-fallback-collision.test.ts": {
- "passed": [],
- "failed": [
+ "passed": [
"i18n-disallow-multiple-locales should 404 properly for fallback: false non-prerendered /es/first/non-existent",
"i18n-disallow-multiple-locales should 404 properly for fallback: false non-prerendered /es/first/second/non-existent",
"i18n-disallow-multiple-locales should 404 properly for fallback: false non-prerendered /es/non-existent",
@@ -11313,6 +11270,7 @@
"i18n-disallow-multiple-locales should render properly for fallback: false prerendered /first/second/third",
"i18n-disallow-multiple-locales should render properly for fallback: false prerendered /first/second/third/fourth"
],
+ "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -11468,17 +11426,18 @@
"runtimeError": false
},
"test/e2e/import-meta/import-meta.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"import-meta import.meta.url should work in browser",
"import-meta import.meta.url should work on the server"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
},
"test/e2e/instrumentation-client-hook/instrumentation-client-hook.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"Instrumentation Client Hook App Router should execute instrumentation-client from app router before hydration",
"Instrumentation Client Hook HMR in development mode should reload instrumentation-client when modified",
"Instrumentation Client Hook Pages Router should execute instrumentation-client from pages router before hydration",
@@ -11486,18 +11445,17 @@
"Instrumentation Client Hook onRouterTransitionStart onRouterTransitionStart fires at the start of a back/forward navigation",
"Instrumentation Client Hook onRouterTransitionStart onRouterTransitionStart fires at the start of a navigation"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
},
"test/e2e/instrumentation-hook-src/instrumentation-hook-src.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"instrumentation-hook-rsc instrumentation should not overlap with a instrumentation page",
"instrumentation-hook-rsc instrumentation should run the edge instrumentation compiled version with the edge runtime",
"instrumentation-hook-rsc instrumentation should run the instrumentation hook"
],
- "failed": [],
"pending": [
"instrumentation-hook-rsc instrumentation should reload the server when the instrumentation hook changes"
],
@@ -11505,7 +11463,8 @@
"runtimeError": false
},
"test/e2e/instrumentation-hook/instrumentation-hook.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"Instrumentation Hook general should not overlap with a instrumentation page",
"Instrumentation Hook with-async-edge-page with-async-edge-page should run the instrumentation hook",
"Instrumentation Hook with-async-node-page with-async-node-page should run the instrumentation hook",
@@ -11516,7 +11475,6 @@
"Instrumentation Hook with-node-api with-node-api should run the instrumentation hook",
"Instrumentation Hook with-node-page with-node-page should run the instrumentation hook"
],
- "failed": [],
"pending": [
"Instrumentation Hook general should reload the server when the instrumentation hook changes"
],
@@ -11545,12 +11503,12 @@
"runtimeError": false
},
"test/e2e/invalid-static-asset-404-app/invalid-static-asset-404-app-base-path.test.ts": {
- "passed": [],
- "failed": [
+ "passed": [
"invalid-static-asset-404-app-base-path should return 404 with plain text when fetching invalid asset path",
"invalid-static-asset-404-app-base-path should return correct output with status 200 on valid asset path",
"invalid-static-asset-404-app-base-path should return custom 404 page when fetching invalid non-asset path"
],
+ "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -11685,7 +11643,8 @@
"runtimeError": false
},
"test/e2e/manual-client-base-path/index.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"manual-client-base-path should navigate correctly from another",
"manual-client-base-path should navigate correctly from index",
"manual-client-base-path should not update with basePath on mount /",
@@ -11694,35 +11653,35 @@
"manual-client-base-path should not update with basePath on mount /dynamic/second",
"manual-client-base-path should not warn for flag in output"
],
- "failed": [],
"pending": [],
"flakey": [],
- "runtimeError": false
+ "runtimeError": true
},
"test/e2e/middleware-base-path/test/index.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"Middleware base tests router.query must exist when Link clicked page routing",
"Middleware base tests should allow client-side navigation to the root",
"Middleware base tests should execute from absolute paths"
],
- "failed": [],
"pending": [],
"flakey": [],
- "runtimeError": false
+ "runtimeError": true
},
"test/e2e/middleware-custom-matchers-basepath/test/index.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"Middleware custom matchers basePath should match",
"Middleware custom matchers basePath should match has query on client routing",
"Middleware custom matchers basePath should not match"
],
- "failed": [],
"pending": [],
"flakey": [],
- "runtimeError": false
+ "runtimeError": true
},
"test/e2e/middleware-custom-matchers-i18n/test/index.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"Middleware custom matchers i18n should match /en/hello",
"Middleware custom matchers i18n should match /hello",
"Middleware custom matchers i18n should match /nl-NL/about",
@@ -11737,7 +11696,6 @@
"Middleware custom matchers i18n should not match /invalid/hello",
"Middleware custom matchers with root should not match"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -11779,15 +11737,15 @@
"runtimeError": true
},
"test/e2e/middleware-dynamic-basepath-matcher/test/index.test.ts": {
- "passed": [],
- "failed": [
+ "passed": [
"Middleware custom matchers basePath should match",
"Middleware custom matchers basePath should match query path",
"Middleware custom matchers basePath should not match"
],
+ "failed": [],
"pending": [],
"flakey": [],
- "runtimeError": true
+ "runtimeError": false
},
"test/e2e/middleware-fetches-with-any-http-method/index.test.ts": {
"passed": [
@@ -12126,7 +12084,8 @@
"runtimeError": false
},
"test/e2e/middleware-rewrites/test/index.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"Middleware Rewrite /fr can rewrite from path with colon",
"Middleware Rewrite /fr can rewrite from path with colon and retain query parameter",
"Middleware Rewrite /fr can rewrite to path with colon",
@@ -12184,22 +12143,22 @@
"Middleware Rewrite should rewrite without hard navigation",
"Middleware Rewrite support colons in path"
],
- "failed": [],
"pending": [
"Middleware Rewrite includes the locale in rewrites by default"
],
"flakey": [],
- "runtimeError": false
+ "runtimeError": true
},
"test/e2e/middleware-shallow-link/index.test.ts": {
- "passed": ["browser-shallow-navigation should render the correct page"],
- "failed": [],
+ "passed": [],
+ "failed": ["browser-shallow-navigation should render the correct page"],
"pending": [],
"flakey": [],
- "runtimeError": false
+ "runtimeError": true
},
"test/e2e/middleware-static-files/index.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"Middleware Runtime should match middleware correctly for /another%2ffile.svg",
"Middleware Runtime should match middleware correctly for /another%2fhello",
"Middleware Runtime should match middleware correctly for /another/file.svg",
@@ -12220,13 +12179,13 @@
"Middleware Runtime should match middleware correctly for /vercel copy.svg",
"Middleware Runtime should match middleware correctly for /vercel%20copy.svg"
],
- "failed": [],
"pending": [],
"flakey": [],
- "runtimeError": false
+ "runtimeError": true
},
"test/e2e/middleware-trailing-slash/test/index.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"Middleware Runtime trailing slash allows shallow linking with middleware",
"Middleware Runtime trailing slash refreshes the page when middleware changes ",
"Middleware Runtime trailing slash should add a rewrite header on data requests for rewrites",
@@ -12252,10 +12211,9 @@
"Middleware Runtime trailing slash without .html extension should work when navigating",
"Middleware Runtime trailing slash without .html extension should work when requesting the page directly"
],
- "failed": [],
"pending": [],
"flakey": [],
- "runtimeError": false
+ "runtimeError": true
},
"test/e2e/module-layer/module-layer.test.ts": {
"passed": [],
@@ -12294,13 +12252,13 @@
"runtimeError": false
},
"test/e2e/new-link-behavior/child-a-tag-error.test.ts": {
- "passed": [],
- "failed": [
+ "passed": [
"New Link Behavior with child should throw error with child"
],
+ "failed": [],
"pending": [],
"flakey": [],
- "runtimeError": true
+ "runtimeError": false
},
"test/e2e/new-link-behavior/index.test.ts": {
"passed": [
@@ -12407,38 +12365,39 @@
"runtimeError": false
},
"test/e2e/next-font/with-proxy.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"next/font/google with proxy should use a proxy agent when proxy environment variable is set"
],
- "failed": [],
"pending": [],
"flakey": [],
- "runtimeError": false
+ "runtimeError": true
},
"test/e2e/next-font/without-preloaded-fonts.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"next/font/google no preloads with _app without fonts",
"next/font/google no preloads with _app without preload",
"next/font/google without-preloaded-fonts without _app without fonts",
"next/font/google without-preloaded-fonts without _app without preload"
],
- "failed": [],
"pending": [],
"flakey": [],
- "runtimeError": false
+ "runtimeError": true
},
"test/e2e/next-form/basepath/next-form-basepath.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"app dir - form - with basepath should add basePath to `action`",
"app dir - form - with basepath should not add basePath to a submitter's formAction"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
},
"test/e2e/next-form/default/app-dir.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"next-form - app dir does not navigate if preventDefault is called in onSubmit",
"next-form - app dir does not push a new history entry if `replace` is passed",
"next-form - app dir functions passed to action runs client action",
@@ -12454,7 +12413,6 @@
"next-form - app dir unsupported attributes on submitter should warn if submitter sets \"formTarget\" to an unsupported value and fall back to default submit behavior",
"next-form - app dir url-encodes file inputs, but warns about them"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -12488,17 +12446,17 @@
"runtimeError": false
},
"test/e2e/next-head/index.test.ts": {
- "passed": [],
- "failed": [
+ "passed": [
"next/head should have correct head tags after hydration",
"next/head should have correct head tags from a fragment",
"next/head should have correct head tags in initial document",
"next/head should have current head tags from a _document getInitialProps",
"next/head should place charset element at the top of "
],
+ "failed": [],
"pending": [],
"flakey": [],
- "runtimeError": true
+ "runtimeError": false
},
"test/e2e/next-image-forward-ref/index.test.ts": {
"passed": [
@@ -12597,7 +12555,8 @@
"runtimeError": false
},
"test/e2e/og-api/index.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"og-api should respond from index",
"og-api should throw error when returning a response object in pages/api in node runtime",
"og-api should work in app route",
@@ -12605,22 +12564,22 @@
"og-api should work in middleware",
"og-api should work in pages/api"
],
- "failed": [],
"pending": [],
"flakey": [],
- "runtimeError": false
+ "runtimeError": true
},
"test/e2e/og-routes-custom-font/og-routes-custom-font.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"og-routes-custom-font should render og with custom font for app routes"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
},
"test/e2e/on-request-error/basic/basic.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"on-request-error - basic app router should catch app routes error in edge runtime",
"on-request-error - basic app router should catch app routes error in node runtime",
"on-request-error - basic app router should catch client component page error in edge runtime",
@@ -12633,20 +12592,19 @@
"on-request-error - basic pages router should catch pages router page error in edge runtime",
"on-request-error - basic pages router should catch pages router page error in node runtime"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
},
"test/e2e/on-request-error/dynamic-routes/dynamic-routes.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"on-request-error - dynamic-routes app router should catch app router dynamic page error with search params",
"on-request-error - dynamic-routes app router should catch app router dynamic routes error with search params",
"on-request-error - dynamic-routes app router should catch suspense rendering page error in node runtime",
"on-request-error - dynamic-routes pages router should catch pages router dynamic API route error with search params",
"on-request-error - dynamic-routes pages router should catch pages router dynamic page error with search params"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -12669,13 +12627,13 @@
"runtimeError": false
},
"test/e2e/on-request-error/server-action-error/server-action-error.test.ts": {
- "passed": [],
- "failed": [
+ "passed": [
"on-request-error - server-action-error should catch server action error in listener callback in edge runtime",
"on-request-error - server-action-error should catch server action error in listener callback in nodejs runtime",
"on-request-error - server-action-error should catch the server action form error in edge runtime",
"on-request-error - server-action-error should catch the server action form error in nodejs runtime"
],
+ "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -12825,10 +12783,10 @@
"runtimeError": false
},
"test/e2e/postcss-config-package/index.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"postcss-config-json works with postcss config specified in package.json"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -12846,26 +12804,26 @@
"runtimeError": false
},
"test/e2e/prerender-crawler.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"Prerender crawler handling should block for crawler correctly",
"Prerender crawler handling should return fallback for non-crawler correctly",
"Prerender crawler handling should return prerendered page for correctly"
],
- "failed": [],
"pending": [],
"flakey": [],
- "runtimeError": false
+ "runtimeError": true
},
"test/e2e/prerender-native-module.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"prerender native module should render /blog/first correctly",
"prerender native module should render /blog/second correctly",
"prerender native module should render index correctly"
],
- "failed": [],
"pending": [],
"flakey": [],
- "runtimeError": false
+ "runtimeError": true
},
"test/e2e/prerender.test.ts": {
"passed": [],
@@ -12949,8 +12907,7 @@
"runtimeError": true
},
"test/e2e/react-compiler/react-compiler.test.ts": {
- "passed": [],
- "failed": [
+ "passed": [
"react-compiler babelrc should memoize Components",
"react-compiler babelrc should name functions in dev",
"react-compiler babelrc should work with a library that uses the react-server condition",
@@ -12962,6 +12919,7 @@
"react-compiler default should work with a library using use client",
"react-compiler default throws if the React Compiler is used in a React Server environment"
],
+ "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -13085,20 +13043,21 @@
"runtimeError": false
},
"test/e2e/streaming-ssr-edge/streaming-ssr-edge.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"streaming-ssr-edge should not stream to crawlers or google pagerender bot",
"streaming-ssr-edge should render 500 error from gIP correctly",
"streaming-ssr-edge should render 500 error from render function correctly",
"streaming-ssr-edge should render fallback if error raised from suspense during streaming",
"streaming-ssr-edge should support streaming for fizz response"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
},
"test/e2e/streaming-ssr/index.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"streaming SSR with custom next configs should match more specific route along with dynamic routes",
"streaming SSR with custom next configs should redirect paths without trailing-slash and render when slash is appended",
"streaming SSR with custom next configs should render multi-byte characters correctly in streaming",
@@ -13106,29 +13065,28 @@
"streaming SSR with custom next configs should render styled-jsx styles in streaming",
"streaming SSR with custom next configs should work with custom document"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
},
"test/e2e/styled-jsx/index.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"styled-jsx should contain styled-jsx styles during SSR",
"styled-jsx should render styles during CSR",
"styled-jsx should render styles inside TypeScript"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
},
"test/e2e/swc-plugins/index.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"swcPlugins incompatible plugin version shows a redbox in dev",
"swcPlugins invalid plugin name shows a redbox in dev",
"swcPlugins supports swcPlugins basic case"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -13167,13 +13125,13 @@
"runtimeError": true
},
"test/e2e/test-template/{{ toFileName name }}/{{ toFileName name }}.test.ts": {
- "passed": [],
- "failed": [
+ "passed": [
"{{name}} should work using browser",
"{{name}} should work using cheerio",
"{{name}} should work with fetch",
"{{name}} should work with html"
],
+ "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -13360,21 +13318,21 @@
"runtimeError": false
},
"test/e2e/tsconfig-module-preserve/index.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"tsconfig module: preserve allows you to skip moduleResolution, esModuleInterop and resolveJsonModule when using \"module: preserve\""
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
},
"test/e2e/tsconfig-path/index.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"specified tsconfig app router: allows a user-specific tsconfig via the next config",
"specified tsconfig middleware: allows a user-specific tsconfig via the next config",
"specified tsconfig pages router: allows a user-specific tsconfig via the next config"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -13389,8 +13347,8 @@
"runtimeError": false
},
"test/e2e/turbopack-loader-config/index.test.ts": {
- "passed": ["turbopack-loader-config should only run the test in turbopack"],
- "failed": [],
+ "passed": [],
+ "failed": ["turbopack-loader-config should only run the test in turbopack"],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -13413,16 +13371,16 @@
"runtimeError": false
},
"test/e2e/type-module-interop/index.test.ts": {
- "passed": [],
- "failed": [
+ "passed": [
"Type module interop should render client-side",
"Type module interop should render client-side with modules",
"Type module interop should render server-side",
"Type module interop should render server-side with modules"
],
+ "failed": [],
"pending": [],
"flakey": [],
- "runtimeError": true
+ "runtimeError": false
},
"test/e2e/typescript-custom-tsconfig/test/index.test.ts": {
"passed": [
@@ -13564,40 +13522,40 @@
"runtimeError": false
},
"test/e2e/useselectedlayoutsegment-s-in-pages-router/useselectedlayoutsegment-s-in-pages-router.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"useSelectedLayoutSegment(s) in Pages Router Should render with `useSelectedLayoutSegment(s) hooks"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
},
"test/e2e/vary-header/test/index.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"Vary Header Tests should preserve custom vary header and append RSC headers in app route handlers",
"Vary Header Tests should preserve custom vary header in API routes",
"Vary Header Tests should preserve middleware vary header in combination with route handlers"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
},
"test/e2e/with-router/index.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"withRouter SSR should show an error when trying to use router methods during SSR",
"withRouter production mode allows observation of navigation events using top level Router",
"withRouter production mode allows observation of navigation events using top level Router deprecated behavior",
"withRouter production mode allows observation of navigation events using withRouter"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
},
"test/e2e/worker-react-refresh/worker-react-refresh.test.tsx": {
- "passed": ["worker-react-refresh does not cause any runtime errors"],
- "failed": [],
+ "passed": [],
+ "failed": ["worker-react-refresh does not cause any runtime errors"],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -13621,10 +13579,10 @@
"runtimeError": false
},
"test/e2e/yarn-pnp/test/with-sass.test.ts": {
- "passed": [],
- "failed": [
+ "passed": [
"yarn PnP should compile and serve the index page correctly with-sass"
],
+ "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -14463,13 +14421,14 @@
},
"test/integration/create-next-app/biome-config.test.ts": {
"passed": [
+ "create-next-app Biome configuration should match biome.json snapshot"
+ ],
+ "failed": [
"create-next-app Biome configuration should format code with biome successfully",
- "create-next-app Biome configuration should match biome.json snapshot",
"create-next-app Biome configuration should run biome check successfully on generated JavaScript project",
"create-next-app Biome configuration should run biome check successfully on generated TypeScript project",
"create-next-app Biome configuration should show errors when biome detects issues"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
@@ -14662,7 +14621,8 @@
"runtimeError": false
},
"test/integration/create-next-app/templates/pages.test.ts": {
- "passed": [
+ "passed": [],
+ "failed": [
"create-next-app --no-app (Pages Router) should create JavaScript project with --js flag",
"create-next-app --no-app (Pages Router) should create TailwindCSS project with --tailwind flag",
"create-next-app --no-app (Pages Router) should create TypeScript project with --ts flag",
@@ -14670,7 +14630,6 @@
"create-next-app --no-app (Pages Router) should create an empty project with --empty flag",
"create-next-app --no-app (Pages Router) should create project inside \"src\" directory with --src-dir flag"
],
- "failed": [],
"pending": [],
"flakey": [],
"runtimeError": false
diff --git a/test/unit/web-runtime/next-url.test.ts b/test/unit/web-runtime/next-url.test.ts
index 8ee079672a4f7..5beded4e7ef8c 100644
--- a/test/unit/web-runtime/next-url.test.ts
+++ b/test/unit/web-runtime/next-url.test.ts
@@ -205,6 +205,19 @@ it('consider 127.0.0.1 and variations as localhost', () => {
expect(new NextURL('https://[::1]:3000/hello')).toStrictEqual(httpsUrl)
})
+it('preserves loopback hostnames inside encoded query parameter values', () => {
+ const url = new NextURL(
+ 'https://example.com/api/echo?redirect_uri=http%3A%2F%2F127.0.0.1%3A12345%2Ftest'
+ )
+
+ expect(url.searchParams.get('redirect_uri')).toEqual(
+ 'http://127.0.0.1:12345/test'
+ )
+ expect(url.href).toEqual(
+ 'https://example.com/api/echo?redirect_uri=http%3A%2F%2F127.0.0.1%3A12345%2Ftest'
+ )
+})
+
it('allows to change the port', () => {
const url = new NextURL('https://localhost:3000/foo')
url.port = '3001'
diff --git a/turbopack/crates/turbopack-core/src/lib.rs b/turbopack/crates/turbopack-core/src/lib.rs
index 420adf3dc8446..bfcba4ace04cc 100644
--- a/turbopack/crates/turbopack-core/src/lib.rs
+++ b/turbopack/crates/turbopack-core/src/lib.rs
@@ -1,6 +1,5 @@
#![feature(min_specialization)]
#![feature(type_alias_impl_trait)]
-#![feature(assert_matches)]
#![feature(arbitrary_self_types)]
#![feature(arbitrary_self_types_pointers)]
#![feature(impl_trait_in_assoc_type)]
diff --git a/turbopack/crates/turbopack-ecmascript/src/source_map.rs b/turbopack/crates/turbopack-ecmascript/src/source_map.rs
index c05a47f120057..42a0613cc1d37 100644
--- a/turbopack/crates/turbopack-ecmascript/src/source_map.rs
+++ b/turbopack/crates/turbopack-ecmascript/src/source_map.rs
@@ -56,10 +56,8 @@ fn maybe_decode_data_url(url: &str) -> Option {
let data_b64 = if let Some(data) = url.strip_prefix(DATA_PREAMBLE) {
data
- } else if let Some(data) = url.strip_prefix(DATA_PREAMBLE_CHARSET) {
- data
} else {
- return None;
+ url.strip_prefix(DATA_PREAMBLE_CHARSET)?
};
data_encoding::BASE64