Skip to content

[pull] canary from vercel:canary #202

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions packages/next/src/server/app-render/entry-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,20 @@ if (process.env.NODE_ENV === 'development') {
SegmentViewStateNode = mod.SegmentViewStateNode
}

// For hot-reloader
declare global {
var __next__clear_chunk_cache__: (() => void) | null | undefined
var __turbopack_clear_chunk_cache__: () => void | null | undefined
}
// hot-reloader modules are not bundled so we need to inject `__next__clear_chunk_cache__`
// into globalThis from this file which is bundled.
if (process.env.TURBOPACK) {
globalThis.__next__clear_chunk_cache__ = __turbopack_clear_chunk_cache__
} else {
// Webpack does not have chunks on the server
globalThis.__next__clear_chunk_cache__ = null
}

// patchFetch makes use of APIs such as `React.unstable_postpone` which are only available
// in the experimental channel of React, so export it from here so that it comes from the bundled runtime
export function patchFetch() {
Expand Down
2 changes: 1 addition & 1 deletion packages/next/src/server/config-shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1463,7 +1463,7 @@ export const defaultConfig = Object.freeze({
useCache: undefined,
slowModuleDetection: undefined,
globalNotFound: false,
devtoolSegmentExplorer: false,
devtoolSegmentExplorer: true,
browserDebugInfoInTerminal: false,
optimizeRouterScrolling: false,
strictNextHead: true,
Expand Down
11 changes: 7 additions & 4 deletions packages/next/src/server/dev/hot-reloader-turbopack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ const isTestMode = !!(

const sessionId = Math.floor(Number.MAX_SAFE_INTEGER * Math.random())

declare const __next__clear_chunk_cache__: (() => void) | null | undefined

/**
* Replaces turbopack:///[project] with the specified project in the `source` field.
*/
Expand Down Expand Up @@ -342,10 +344,11 @@ export async function createHotReloaderTurbopack(

resetFetch()

// Edge uses the browser runtime which already disposes chunks individually.
// TODO: process.env.NEXT_RUNTIME is 'nodejs' even though Node.js runtime is not used.
if ('__turbopack_clear_chunk_cache__' in globalThis) {
;(globalThis as any).__turbopack_clear_chunk_cache__()
// Not available in:
// - Pages Router (no server-side HMR)
// - Edge Runtime (uses browser runtime which already disposes chunks individually)
if (typeof __next__clear_chunk_cache__ === 'function') {
__next__clear_chunk_cache__()
}

const serverPaths = writtenEndpoint.serverPaths.map(({ path: p }) =>
Expand Down
464 changes: 288 additions & 176 deletions test/development/acceptance-app/hydration-error.test.ts

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,15 @@ describe('hydration-error-count', () => {
<RedirectBoundary>
<RedirectErrorBoundary router={{...}}>
<InnerLayoutRouter url="/bad-nesting" tree={[...]} cacheNode={{lazyData:null, ...}} ...>
<ClientPageRoot Component={function Page} searchParams={{}} params={{}}>
<Page params={Promise} searchParams={Promise}>
> <p>
<SegmentViewNode type="page" pagePath="bad-nestin...">
<SegmentTrieNode>
<ClientPageRoot Component={function Page} searchParams={{}} params={{}}>
<Page params={Promise} searchParams={Promise}>
> <p>
...",
> <p>
...
...
...",
"description": "In HTML, <p> cannot be a descendant of <p>.
This will cause a hydration error.",
"environmentLabel": null,
Expand Down Expand Up @@ -69,12 +73,16 @@ describe('hydration-error-count', () => {
<RedirectBoundary>
<RedirectErrorBoundary router={{...}}>
<InnerLayoutRouter url="/html-diff" tree={[...]} cacheNode={{lazyData:null, ...}} segmentPath={[...]}>
<ClientPageRoot Component={function Page} searchParams={{}} params={{}}>
<Page params={Promise} searchParams={Promise}>
<p>
+ client
- server
...",
<SegmentViewNode type="page" pagePath="html-diff/...">
<SegmentTrieNode>
<ClientPageRoot Component={function Page} searchParams={{}} params={{}}>
<Page params={Promise} searchParams={Promise}>
<p>
+ client
- server
...
...
...",
"description": "Hydration failed because the server rendered text didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used:",
"environmentLabel": null,
"label": "Recoverable Error",
Expand Down Expand Up @@ -105,11 +113,15 @@ describe('hydration-error-count', () => {
<RedirectBoundary>
<RedirectErrorBoundary router={{...}}>
<InnerLayoutRouter url="/two-issues" tree={[...]} cacheNode={{lazyData:null, ...}} ...>
<ClientPageRoot Component={function Page} searchParams={{}} params={{}}>
<Page params={Promise} searchParams={Promise}>
> <p className="client">
> <p>
...",
<SegmentViewNode type="page" pagePath="two-issues...">
<SegmentTrieNode>
<ClientPageRoot Component={function Page} searchParams={{}} params={{}}>
<Page params={Promise} searchParams={Promise}>
> <p className="client">
> <p>
...
...
...",
"description": "In HTML, <p> cannot be a descendant of <p>.
This will cause a hydration error.",
"environmentLabel": null,
Expand All @@ -133,13 +145,17 @@ describe('hydration-error-count', () => {
<RedirectBoundary>
<RedirectErrorBoundary router={{...}}>
<InnerLayoutRouter url="/two-issues" tree={[...]} cacheNode={{lazyData:null, ...}} ...>
<ClientPageRoot Component={function Page} searchParams={{}} params={{}}>
<Page params={Promise} searchParams={Promise}>
<p
+ className="client"
- className="server"
>
...",
<SegmentViewNode type="page" pagePath="two-issues...">
<SegmentTrieNode>
<ClientPageRoot Component={function Page} searchParams={{}} params={{}}>
<Page params={Promise} searchParams={Promise}>
<p
+ className="client"
- className="server"
>
...
...
...",
"description": "Hydration failed because the server rendered HTML didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used:",
"environmentLabel": null,
"label": "Recoverable Error",
Expand Down Expand Up @@ -171,11 +187,15 @@ describe('hydration-error-count', () => {
<RedirectBoundary>
<RedirectErrorBoundary router={{...}}>
<InnerLayoutRouter url="/hydration..." tree={[...]} cacheNode={{lazyData:null, ...}} ...>
<ClientPageRoot Component={function Page} searchParams={{}} params={{}}>
<Page params={Promise} searchParams={Promise}>
> <p>
<SegmentViewNode type="page" pagePath="hydration-...">
<SegmentTrieNode>
<ClientPageRoot Component={function Page} searchParams={{}} params={{}}>
<Page params={Promise} searchParams={Promise}>
> <p>
...",
> <p>
...
...
...",
"description": "In HTML, <p> cannot be a descendant of <p>.
This will cause a hydration error.",
"environmentLabel": null,
Expand Down
2 changes: 2 additions & 0 deletions test/development/client-dev-overlay/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ describe('client-dev-overlay', () => {
Static
Turbopack
Enabled
Route Info
Preferences"
`)
} else {
Expand All @@ -151,6 +152,7 @@ describe('client-dev-overlay', () => {
Route
Static
Try Turbopack
Route Info
Preferences"
`)
}
Expand Down
4 changes: 2 additions & 2 deletions test/e2e/opentelemetry/instrumentation/opentelemetry.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const EXTERNAL = {
const COLLECTOR_PORT = 9001

describe('opentelemetry', () => {
const { next, skipped } = nextTestSetup({
const { next, skipped, isNextDev } = nextTestSetup({
files: __dirname,
skipDeployment: true,
dependencies: require('./package.json').dependencies,
Expand Down Expand Up @@ -170,7 +170,7 @@ describe('opentelemetry', () => {
},
{
attributes: {
'next.clientComponentLoadCount': 7,
'next.clientComponentLoadCount': isNextDev ? 8 : 7,
'next.span_type':
'NextNodeServer.clientComponentLoading',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ function instantiateModule(moduleId: ModuleId, source: SourceInfo): Module {
n: exportNamespace.bind(null, module, devModuleCache),
m: module,
c: devModuleCache,
C: null,
M: moduleFactories,
l: loadChunk.bind(null, sourceInfo),
L: loadChunkByUrl.bind(null, sourceInfo),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ function instantiateModule(id: ModuleId, source: SourceInfo): Module {
type: SourceType.Parent,
parentId: id,
}),
C: clearChunkCache,
w: loadWebAssembly,
u: loadWebAssemblyModule,
P: resolveAbsolutePath,
Expand Down Expand Up @@ -381,9 +382,6 @@ function isJs(chunkUrlOrPath: ChunkUrl | ChunkPath): boolean {
return regexJsUrl.test(chunkUrlOrPath)
}

// For hot-reloader
;(globalThis as any).__turbopack_clear_chunk_cache__ = clearChunkCache

module.exports = {
getOrInstantiateRuntimeModule,
loadChunk,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ pub const TURBOPACK_LOAD: &TurbopackRuntimeFunctionShortcut =
&TurbopackRuntimeFunctionShortcut::new("__turbopack_context__.l", "l");
pub const TURBOPACK_LOAD_BY_URL: &TurbopackRuntimeFunctionShortcut =
&TurbopackRuntimeFunctionShortcut::new("__turbopack_context__.L", "L");
pub const TURBOPACK_CLEAR_CHUNK_CACHE: &TurbopackRuntimeFunctionShortcut =
&TurbopackRuntimeFunctionShortcut::new("__turbopack_context__.C", "C");
pub const TURBOPACK_DYNAMIC: &TurbopackRuntimeFunctionShortcut =
&TurbopackRuntimeFunctionShortcut::new("__turbopack_context__.j", "j");
pub const TURBOPACK_RESOLVE_ABSOLUTE_PATH: &TurbopackRuntimeFunctionShortcut =
Expand All @@ -81,7 +83,7 @@ pub const TURBOPACK_REQUIRE_REAL: &TurbopackRuntimeFunctionShortcut =

/// Adding an entry to this list will automatically ensure that `__turbopack_XXX__` can be called
/// from user code (by inserting a replacement into free_var_references)
pub const TURBOPACK_RUNTIME_FUNCTION_SHORTCUTS: [(&str, &TurbopackRuntimeFunctionShortcut); 21] = [
pub const TURBOPACK_RUNTIME_FUNCTION_SHORTCUTS: [(&str, &TurbopackRuntimeFunctionShortcut); 22] = [
("__turbopack_require__", TURBOPACK_REQUIRE),
("__turbopack_module_context__", TURBOPACK_MODULE_CONTEXT),
("__turbopack_import__", TURBOPACK_IMPORT),
Expand Down Expand Up @@ -109,4 +111,8 @@ pub const TURBOPACK_RUNTIME_FUNCTION_SHORTCUTS: [(&str, &TurbopackRuntimeFunctio
("__turbopack_refresh__", TURBOPACK_REFRESH),
("__turbopack_require_stub__", TURBOPACK_REQUIRE_STUB),
("__turbopack_require_real__", TURBOPACK_REQUIRE_REAL),
(
"__turbopack_clear_chunk_cache__",
TURBOPACK_CLEAR_CHUNK_CACHE,
),
];

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Large diffs are not rendered by default.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Large diffs are not rendered by default.

Loading