Skip to content

Commit af354f6

Browse files
authored
Merge branch 'canary' into revert-84526-revert-84376-sokra/avoid-double-invalidation
2 parents 54e8671 + 24a046f commit af354f6

File tree

100 files changed

+1263
-900
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

100 files changed

+1263
-900
lines changed

crates/next-api/src/project.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,6 +1073,7 @@ impl Project {
10731073
turbo_source_maps: self.next_config().server_source_maps(),
10741074
no_mangling: self.no_mangling(),
10751075
scope_hoisting: self.next_config().turbo_scope_hoisting(self.next_mode()),
1076+
debug_ids: self.next_config().turbopack_debug_ids(),
10761077
};
10771078
Ok(if client_assets {
10781079
get_server_chunking_context_with_client_assets(

crates/next-core/src/next_server/context.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -993,6 +993,7 @@ pub struct ServerChunkingContextOptions {
993993
pub turbo_source_maps: Vc<bool>,
994994
pub no_mangling: Vc<bool>,
995995
pub scope_hoisting: Vc<bool>,
996+
pub debug_ids: Vc<bool>,
996997
}
997998

998999
#[turbo_tasks::function]
@@ -1013,6 +1014,7 @@ pub async fn get_server_chunking_context_with_client_assets(
10131014
turbo_source_maps,
10141015
no_mangling,
10151016
scope_hoisting,
1017+
debug_ids,
10161018
} = options;
10171019

10181020
let next_mode = mode.await?;
@@ -1045,7 +1047,8 @@ pub async fn get_server_chunking_context_with_client_assets(
10451047
})
10461048
.module_id_strategy(module_id_strategy.to_resolved().await?)
10471049
.export_usage(*export_usage.await?)
1048-
.file_tracing(next_mode.is_production());
1050+
.file_tracing(next_mode.is_production())
1051+
.debug_ids(*debug_ids.await?);
10491052

10501053
if next_mode.is_development() {
10511054
builder = builder.use_file_source_map_uris();
@@ -1089,6 +1092,7 @@ pub async fn get_server_chunking_context(
10891092
turbo_source_maps,
10901093
no_mangling,
10911094
scope_hoisting,
1095+
debug_ids,
10921096
} = options;
10931097
let next_mode = mode.await?;
10941098
// TODO(alexkirsz) This should return a trait that can be implemented by the
@@ -1118,7 +1122,8 @@ pub async fn get_server_chunking_context(
11181122
})
11191123
.module_id_strategy(module_id_strategy.to_resolved().await?)
11201124
.export_usage(*export_usage.await?)
1121-
.file_tracing(next_mode.is_production());
1125+
.file_tracing(next_mode.is_production())
1126+
.debug_ids(*debug_ids.await?);
11221127

11231128
if next_mode.is_development() {
11241129
builder = builder.use_file_source_map_uris()
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
---
2+
title: Invalid Prefetch Configuration
3+
---
4+
5+
## Why This Message Occurred
6+
7+
You provided an invalid configuration for `export const unstable_prefetch` in a Layout or Page file.
8+
9+
### Example of Correct Usage
10+
11+
#### Static Prefetching
12+
13+
```tsx filename="app/.../layout.tsx"
14+
export const unstable_prefetch = {
15+
mode: 'static',
16+
}
17+
```
18+
19+
#### Runtime Prefetching
20+
21+
```tsx filename="app/[slug]/page.tsx"
22+
export const unstable_prefetch = {
23+
mode: 'runtime',
24+
samples: [
25+
{
26+
cookies: [{ name: 'experiment', value: 'A' }],
27+
params: { slug: 'example' },
28+
},
29+
],
30+
}
31+
```

package.json

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@
199199
"eslint-plugin-jsdoc": "48.0.4",
200200
"eslint-plugin-mdx": "3.1.5",
201201
"eslint-plugin-react": "7.35.0",
202-
"eslint-plugin-react-hooks": "0.0.0-experimental-85c427d8-20251003",
202+
"eslint-plugin-react-hooks": "0.0.0-experimental-4fdf7cf2-20251003",
203203
"eslint-v8": "npm:eslint@^8.57.0",
204204
"event-stream": "4.0.1",
205205
"execa": "2.0.3",
@@ -259,16 +259,16 @@
259259
"pretty-ms": "7.0.0",
260260
"random-seed": "0.3.0",
261261
"react": "19.0.0",
262-
"react-builtin": "npm:[email protected]85c427d8-20251003",
262+
"react-builtin": "npm:[email protected]4fdf7cf2-20251003",
263263
"react-dom": "19.0.0",
264-
"react-dom-builtin": "npm:[email protected]85c427d8-20251003",
265-
"react-dom-experimental-builtin": "npm:[email protected]85c427d8-20251003",
266-
"react-experimental-builtin": "npm:[email protected]85c427d8-20251003",
267-
"react-is-builtin": "npm:[email protected]85c427d8-20251003",
268-
"react-server-dom-turbopack": "19.3.0-canary-85c427d8-20251003",
269-
"react-server-dom-turbopack-experimental": "npm:[email protected]85c427d8-20251003",
270-
"react-server-dom-webpack": "19.3.0-canary-85c427d8-20251003",
271-
"react-server-dom-webpack-experimental": "npm:[email protected]85c427d8-20251003",
264+
"react-dom-builtin": "npm:[email protected]4fdf7cf2-20251003",
265+
"react-dom-experimental-builtin": "npm:[email protected]4fdf7cf2-20251003",
266+
"react-experimental-builtin": "npm:[email protected]4fdf7cf2-20251003",
267+
"react-is-builtin": "npm:[email protected]4fdf7cf2-20251003",
268+
"react-server-dom-turbopack": "19.3.0-canary-4fdf7cf2-20251003",
269+
"react-server-dom-turbopack-experimental": "npm:[email protected]4fdf7cf2-20251003",
270+
"react-server-dom-webpack": "19.3.0-canary-4fdf7cf2-20251003",
271+
"react-server-dom-webpack-experimental": "npm:[email protected]4fdf7cf2-20251003",
272272
"react-ssr-prepass": "1.0.8",
273273
"react-virtualized": "9.22.3",
274274
"relay-compiler": "13.0.2",
@@ -278,8 +278,8 @@
278278
"resolve-from": "5.0.0",
279279
"sass": "1.54.0",
280280
"satori": "0.15.2",
281-
"scheduler-builtin": "npm:[email protected]85c427d8-20251003",
282-
"scheduler-experimental-builtin": "npm:[email protected]85c427d8-20251003",
281+
"scheduler-builtin": "npm:[email protected]4fdf7cf2-20251003",
282+
"scheduler-experimental-builtin": "npm:[email protected]4fdf7cf2-20251003",
283283
"seedrandom": "3.0.5",
284284
"semver": "7.3.7",
285285
"serve-handler": "6.1.6",
@@ -323,10 +323,10 @@
323323
"@types/react-dom": "19.1.10",
324324
"@types/retry": "0.12.0",
325325
"jest-snapshot": "30.0.0-alpha.6",
326-
"react": "19.3.0-canary-85c427d8-20251003",
327-
"react-dom": "19.3.0-canary-85c427d8-20251003",
328-
"react-is": "19.3.0-canary-85c427d8-20251003",
329-
"scheduler": "0.28.0-canary-85c427d8-20251003"
326+
"react": "19.3.0-canary-4fdf7cf2-20251003",
327+
"react-dom": "19.3.0-canary-4fdf7cf2-20251003",
328+
"react-is": "19.3.0-canary-4fdf7cf2-20251003",
329+
"scheduler": "0.28.0-canary-4fdf7cf2-20251003"
330330
},
331331
"packageExtensions": {
332332

packages/next/src/build/segment-config/app/app-segment-config.ts

Lines changed: 103 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,91 @@
11
import { z } from 'next/dist/compiled/zod'
22
import { formatZodError } from '../../../shared/lib/zod'
33

4+
const CookieSchema = z
5+
.object({
6+
name: z.string(),
7+
value: z.string(),
8+
httpOnly: z.boolean().optional(),
9+
path: z.string().optional(),
10+
})
11+
.strict()
12+
13+
const RuntimeSampleSchema = z
14+
.object({
15+
cookies: z.array(CookieSchema).optional(),
16+
headers: z.array(z.tuple([z.string(), z.string()])).optional(),
17+
params: z.record(z.union([z.string(), z.array(z.string())])).optional(),
18+
searchParams: z
19+
.record(z.union([z.string(), z.array(z.string()), z.undefined()]))
20+
.optional(),
21+
})
22+
.strict()
23+
24+
const StaticPrefetchSchema = z
25+
.object({
26+
mode: z.literal('static'),
27+
from: z.array(z.string()).optional(),
28+
expectUnableToVerify: z.boolean().optional(),
29+
})
30+
.strict()
31+
32+
const RuntimePrefetchSchema = z
33+
.object({
34+
mode: z.literal('runtime'),
35+
samples: z.array(RuntimeSampleSchema).min(1),
36+
from: z.array(z.string()).optional(),
37+
expectUnableToVerify: z.boolean().optional(),
38+
})
39+
.strict()
40+
41+
const PrefetchSchema = z.discriminatedUnion('mode', [
42+
StaticPrefetchSchema,
43+
RuntimePrefetchSchema,
44+
])
45+
46+
export type Prefetch = StaticPrefetch | RuntimePrefetch
47+
export type PrefetchForTypeCheckInternal = __GenericPrefetch | Prefetch
48+
// the __GenericPrefetch type is used to avoid type widening issues with
49+
// our choice to make exports the medium for programming a Next.js application
50+
// With exports the type is controlled by the module and all we can do is assert on it
51+
// from a consumer. However with string literals in objects these are by default typed widely
52+
// and thus cannot match the discriminated union type. If we figure out a better way we should
53+
// delete the __GenericPrefetch member.
54+
interface __GenericPrefetch {
55+
mode: string
56+
samples?: Array<WideRuntimeSample>
57+
from?: string[]
58+
expectUnableToVerify?: boolean
59+
}
60+
interface StaticPrefetch {
61+
mode: 'static'
62+
from?: string[]
63+
expectUnableToVerify?: boolean
64+
}
65+
interface RuntimePrefetch {
66+
mode: 'runtime'
67+
samples: Array<RuntimeSample>
68+
from?: string[]
69+
expectUnableToVerify?: boolean
70+
}
71+
type WideRuntimeSample = {
72+
cookies?: RuntimeSample['cookies']
73+
headers?: Array<string[]>
74+
params?: RuntimeSample['params']
75+
searchParams?: RuntimeSample['searchParams']
76+
}
77+
type RuntimeSample = {
78+
cookies?: Array<{
79+
name: string
80+
value: string
81+
httpOnly?: boolean
82+
path?: string
83+
}>
84+
headers?: Array<[string, string]>
85+
params?: { [key: string]: string | string[] }
86+
searchParams?: { [key: string]: string | string[] | undefined }
87+
}
88+
489
/**
590
* The schema for configuration for a page.
691
*/
@@ -43,7 +128,7 @@ const AppSegmentConfigSchema = z.object({
43128
* How this segment should be prefetched.
44129
* (only applicable when `clientSegmentCache` is enabled)
45130
*/
46-
unstable_prefetch: z.enum(['unstable_static', 'unstable_runtime']).optional(),
131+
unstable_prefetch: PrefetchSchema.optional(),
47132

48133
/**
49134
* The preferred region for the page.
@@ -80,11 +165,22 @@ export function parseAppSegmentConfig(
80165
): AppSegmentConfig {
81166
const parsed = AppSegmentConfigSchema.safeParse(data, {
82167
errorMap: (issue, ctx) => {
83-
if (issue.path.length === 1 && issue.path[0] === 'revalidate') {
84-
return {
85-
message: `Invalid revalidate value ${JSON.stringify(
86-
ctx.data
87-
)} on "${route}", must be a non-negative number or false`,
168+
if (issue.path.length === 1) {
169+
switch (issue.path[0]) {
170+
case 'revalidate': {
171+
return {
172+
message: `Invalid revalidate value ${JSON.stringify(
173+
ctx.data
174+
)} on "${route}", must be a non-negative number or false`,
175+
}
176+
}
177+
case 'unstable_prefetch': {
178+
return {
179+
// @TODO replace this link with a link to the docs when they are written
180+
message: `Invalid unstable_prefetch value ${JSON.stringify(ctx.data)} on "${route}", must be an object with a mode of "static" or "runtime". Read more at https://nextjs.org/docs/messages/invalid-prefetch-configuration`,
181+
}
182+
}
183+
default:
88184
}
89185
}
90186

@@ -137,7 +233,7 @@ export type AppSegmentConfig = {
137233
* How this segment should be prefetched.
138234
* (only applicable when `clientSegmentCache` is enabled)
139235
*/
140-
unstable_prefetch?: 'unstable_static' | 'unstable_runtime'
236+
unstable_prefetch?: Prefetch
141237

142238
/**
143239
* The preferred region for the page.

packages/next/src/build/webpack/plugins/next-types-plugin/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ ${
5252
: `import type { ResolvingMetadata, ResolvingViewport } from 'next/dist/lib/metadata/types/metadata-interface.js'`
5353
}
5454
55+
import type { PrefetchForTypeCheckInternal } from 'next/dist/build/segment-config/app/app-segment-config.js'
56+
5557
type TEntry = typeof import('${relativePath}.js')
5658
5759
type SegmentParams<T extends Object = any> = T extends Record<string, any>
@@ -67,7 +69,7 @@ checkFields<Diff<{
6769
}
6870
config?: {}
6971
generateStaticParams?: Function
70-
unstable_prefetch?: 'unstable_static' | 'unstable_runtime'
72+
unstable_prefetch?: PrefetchForTypeCheckInternal
7173
revalidate?: RevalidateRange<TEntry> | false
7274
dynamic?: 'auto' | 'force-dynamic' | 'error' | 'force-static'
7375
dynamicParams?: boolean

packages/next/src/compiled/react-dom-experimental/cjs/react-dom-client.development.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32277,11 +32277,11 @@
3227732277
};
3227832278
(function () {
3227932279
var isomorphicReactPackageVersion = React.version;
32280-
if ("19.3.0-experimental-85c427d8-20251003" !== isomorphicReactPackageVersion)
32280+
if ("19.3.0-experimental-4fdf7cf2-20251003" !== isomorphicReactPackageVersion)
3228132281
throw Error(
3228232282
'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' +
3228332283
(isomorphicReactPackageVersion +
32284-
"\n - react-dom: 19.3.0-experimental-85c427d8-20251003\nLearn more: https://react.dev/warnings/version-mismatch")
32284+
"\n - react-dom: 19.3.0-experimental-4fdf7cf2-20251003\nLearn more: https://react.dev/warnings/version-mismatch")
3228532285
);
3228632286
})();
3228732287
("function" === typeof Map &&
@@ -32318,10 +32318,10 @@
3231832318
!(function () {
3231932319
var internals = {
3232032320
bundleType: 1,
32321-
version: "19.3.0-experimental-85c427d8-20251003",
32321+
version: "19.3.0-experimental-4fdf7cf2-20251003",
3232232322
rendererPackageName: "react-dom",
3232332323
currentDispatcherRef: ReactSharedInternals,
32324-
reconcilerVersion: "19.3.0-experimental-85c427d8-20251003"
32324+
reconcilerVersion: "19.3.0-experimental-4fdf7cf2-20251003"
3232532325
};
3232632326
internals.overrideHookState = overrideHookState;
3232732327
internals.overrideHookStateDeletePath = overrideHookStateDeletePath;
@@ -32469,7 +32469,7 @@
3246932469
listenToAllSupportedEvents(container);
3247032470
return new ReactDOMHydrationRoot(initialChildren);
3247132471
};
32472-
exports.version = "19.3.0-experimental-85c427d8-20251003";
32472+
exports.version = "19.3.0-experimental-4fdf7cf2-20251003";
3247332473
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
3247432474
"function" ===
3247532475
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&

packages/next/src/compiled/react-dom-experimental/cjs/react-dom-client.production.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19570,14 +19570,14 @@ ReactDOMHydrationRoot.prototype.unstable_scheduleHydration = function (target) {
1957019570
};
1957119571
var isomorphicReactPackageVersion$jscomp$inline_2217 = React.version;
1957219572
if (
19573-
"19.3.0-experimental-85c427d8-20251003" !==
19573+
"19.3.0-experimental-4fdf7cf2-20251003" !==
1957419574
isomorphicReactPackageVersion$jscomp$inline_2217
1957519575
)
1957619576
throw Error(
1957719577
formatProdErrorMessage(
1957819578
527,
1957919579
isomorphicReactPackageVersion$jscomp$inline_2217,
19580-
"19.3.0-experimental-85c427d8-20251003"
19580+
"19.3.0-experimental-4fdf7cf2-20251003"
1958119581
)
1958219582
);
1958319583
ReactDOMSharedInternals.findDOMNode = function (componentOrElement) {
@@ -19599,10 +19599,10 @@ ReactDOMSharedInternals.findDOMNode = function (componentOrElement) {
1959919599
};
1960019600
var internals$jscomp$inline_2914 = {
1960119601
bundleType: 0,
19602-
version: "19.3.0-experimental-85c427d8-20251003",
19602+
version: "19.3.0-experimental-4fdf7cf2-20251003",
1960319603
rendererPackageName: "react-dom",
1960419604
currentDispatcherRef: ReactSharedInternals,
19605-
reconcilerVersion: "19.3.0-experimental-85c427d8-20251003"
19605+
reconcilerVersion: "19.3.0-experimental-4fdf7cf2-20251003"
1960619606
};
1960719607
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
1960819608
var hook$jscomp$inline_2915 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
@@ -19709,4 +19709,4 @@ exports.hydrateRoot = function (container, initialChildren, options) {
1970919709
listenToAllSupportedEvents(container);
1971019710
return new ReactDOMHydrationRoot(initialChildren);
1971119711
};
19712-
exports.version = "19.3.0-experimental-85c427d8-20251003";
19712+
exports.version = "19.3.0-experimental-4fdf7cf2-20251003";

0 commit comments

Comments
 (0)