From 7ee343a053d4cc586312262798a11d0bc446bc0f Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Tue, 18 Nov 2025 13:50:54 +0100 Subject: [PATCH] Turbopack: fix passing project options from napi --- crates/napi/src/next_api/project.rs | 94 ++++++++++++------- crates/next-api/src/project.rs | 16 ++++ .../next/src/build/swc/generated-native.d.ts | 10 +- packages/next/src/build/swc/index.ts | 7 +- packages/next/src/build/swc/types.ts | 75 +++------------ 5 files changed, 93 insertions(+), 109 deletions(-) diff --git a/crates/napi/src/next_api/project.rs b/crates/napi/src/next_api/project.rs index 1f785de2107d58..b8b0133c814f49 100644 --- a/crates/napi/src/next_api/project.rs +++ b/crates/napi/src/next_api/project.rs @@ -137,8 +137,8 @@ pub struct NapiProjectOptions { /// Unix path. E.g. `apps/my-app` pub project_path: RcStr, - /// A path where to emit the build outputs, relative to [`Project::project_path`], always Unix - /// path. Corresponds to next.config.js's `distDir`. + /// A path where tracing output will be written to and/or cache is read/written. + /// Usually equal to the `distDir` in next.config.js. /// E.g. `.next` pub dist_dir: RcStr, @@ -192,11 +192,6 @@ pub struct NapiPartialProjectOptions { /// E.g. `apps/my-app` pub project_path: Option, - /// A path where to emit the build outputs, relative to [`Project::project_path`], always a - /// Unix path. Corresponds to next.config.js's `distDir`. - /// E.g. `.next` - pub dist_dir: Option>, - /// Filesystem watcher options. pub watch: Option, @@ -267,43 +262,70 @@ impl From for WatchOptions { impl From for ProjectOptions { fn from(val: NapiProjectOptions) -> Self { + let NapiProjectOptions { + root_path, + project_path, + // Only used for initializing cache and tracing + dist_dir: _, + watch, + next_config, + env, + define_env, + dev, + encryption_key, + build_id, + preview_props, + browserslist_query, + no_mangling, + current_node_js_version, + } = val; ProjectOptions { - root_path: val.root_path, - project_path: val.project_path, - watch: val.watch.into(), - next_config: val.next_config, - env: val - .env - .into_iter() - .map(|var| (var.name, var.value)) - .collect(), - define_env: val.define_env.into(), - dev: val.dev, - encryption_key: val.encryption_key, - build_id: val.build_id, - preview_props: val.preview_props.into(), - browserslist_query: val.browserslist_query, - no_mangling: val.no_mangling, - current_node_js_version: val.current_node_js_version, + root_path, + project_path, + watch: watch.into(), + next_config, + env: env.into_iter().map(|var| (var.name, var.value)).collect(), + define_env: define_env.into(), + dev, + encryption_key, + build_id, + preview_props: preview_props.into(), + browserslist_query, + no_mangling, + current_node_js_version, } } } impl From for PartialProjectOptions { fn from(val: NapiPartialProjectOptions) -> Self { + let NapiPartialProjectOptions { + root_path, + project_path, + watch, + next_config, + env, + define_env, + dev, + encryption_key, + build_id, + preview_props, + browserslist_query, + no_mangling, + } = val; PartialProjectOptions { - root_path: val.root_path, - project_path: val.project_path, - watch: val.watch.map(From::from), - next_config: val.next_config, - env: val - .env - .map(|env| env.into_iter().map(|var| (var.name, var.value)).collect()), - define_env: val.define_env.map(|env| env.into()), - dev: val.dev, - encryption_key: val.encryption_key, - build_id: val.build_id, - preview_props: val.preview_props.map(|props| props.into()), + root_path, + project_path, + watch: watch.map(From::from), + next_config, + env: env.map(|env| env.into_iter().map(|var| (var.name, var.value)).collect()), + define_env: define_env.map(|env| env.into()), + dev, + encryption_key, + build_id, + preview_props: preview_props.map(|props| props.into()), + browserslist_query, + no_mangling, } } } diff --git a/crates/next-api/src/project.rs b/crates/next-api/src/project.rs index 92caa1d190df67..9efcfcc916aee8 100644 --- a/crates/next-api/src/project.rs +++ b/crates/next-api/src/project.rs @@ -229,6 +229,14 @@ pub struct PartialProjectOptions { /// Options for draft mode. pub preview_props: Option, + + /// The browserslist query to use for targeting browsers. + pub browserslist_query: Option, + + /// When the code is minified, this opts out of the default mangling of + /// local names for variables, functions etc., which can be useful for + /// debugging/profiling purposes. + pub no_mangling: Option, } #[derive( @@ -347,6 +355,8 @@ impl ProjectContainer { encryption_key, build_id, preview_props, + browserslist_query, + no_mangling, } = options; let resolved_self = self.to_resolved().await?; @@ -388,6 +398,12 @@ impl ProjectContainer { if let Some(preview_props) = preview_props { new_options.preview_props = preview_props; } + if let Some(browserslist_query) = browserslist_query { + new_options.browserslist_query = browserslist_query; + } + if let Some(no_mangling) = no_mangling { + new_options.no_mangling = no_mangling; + } // TODO: Handle mode switch, should prevent mode being switched. let watch = new_options.watch; diff --git a/packages/next/src/build/swc/generated-native.d.ts b/packages/next/src/build/swc/generated-native.d.ts index 08fed01ec5009a..b2bfc13857b4ed 100644 --- a/packages/next/src/build/swc/generated-native.d.ts +++ b/packages/next/src/build/swc/generated-native.d.ts @@ -123,8 +123,8 @@ export interface NapiProjectOptions { */ projectPath: RcStr /** - * A path where to emit the build outputs, relative to [`Project::project_path`], always Unix - * path. Corresponds to next.config.js's `distDir`. + * A path where tracing output will be written to and/or cache is read/written. + * Usually equal to the `distDir` in next.config.js. * E.g. `.next` */ distDir: RcStr @@ -172,12 +172,6 @@ export interface NapiPartialProjectOptions { * E.g. `apps/my-app` */ projectPath?: RcStr - /** - * A path where to emit the build outputs, relative to [`Project::project_path`], always a - * Unix path. Corresponds to next.config.js's `distDir`. - * E.g. `.next` - */ - distDir?: RcStr | undefined | null /** Filesystem watcher options. */ watch?: NapiWatchOptions /** The contents of next.config.js, serialized to JSON. */ diff --git a/packages/next/src/build/swc/index.ts b/packages/next/src/build/swc/index.ts index 3b4071d4083e39..c0ff835a8f49a8 100644 --- a/packages/next/src/build/swc/index.ts +++ b/packages/next/src/build/swc/index.ts @@ -29,6 +29,7 @@ import type { Endpoint, HmrIdentifiers, Lockfile, + PartialProjectOptions, Project, ProjectOptions, RawEntrypoints, @@ -651,7 +652,7 @@ function bindingToApi( } async function rustifyPartialProjectOptions( - options: Partial + options: PartialProjectOptions ): Promise { return { ...options, @@ -659,7 +660,7 @@ function bindingToApi( options.nextConfig && (await serializeNextConfig( options.nextConfig, - path.join(options.rootPath!, options.projectPath!) + path.join(options.rootPath, options.projectPath) )), env: options.env && rustifyEnv(options.env), } @@ -672,7 +673,7 @@ function bindingToApi( this._nativeProject = nativeProject } - async update(options: Partial) { + async update(options: PartialProjectOptions) { await binding.projectUpdate( this._nativeProject, await rustifyPartialProjectOptions(options) diff --git a/packages/next/src/build/swc/types.ts b/packages/next/src/build/swc/types.ts index 3726cc10aac865..b9e0fee184c24d 100644 --- a/packages/next/src/build/swc/types.ts +++ b/packages/next/src/build/swc/types.ts @@ -5,6 +5,8 @@ import type { RefCell, NapiTurboEngineOptions, NapiSourceDiagnostic, + NapiProjectOptions, + NapiPartialProjectOptions, } from './generated-native' export type { NapiTurboEngineOptions as TurboEngineOptions } @@ -367,27 +369,8 @@ export type WrittenEndpoint = config: EndpointConfig } -export interface ProjectOptions { - /** - * An absolute root path (Unix or Windows path) from which all files must be nested under. Trying - * to access a file outside this root will fail, so think of this as a chroot. - * E.g. `/home/user/projects/my-repo`. - */ - rootPath: string - - /** - * A path which contains the app/pages directories, relative to `root_path`, always a Unix path. - * E.g. `apps/my-app` - */ - projectPath: string - - /** - * A path where to emit the build outputs, relative to [`Project::project_path`], always a Unix - * path. Corresponds to next.config.js's `distDir`. - * E.g. `.next` - */ - distDir: string - +export interface ProjectOptions + extends Omit { /** * The next.config.js contents. */ @@ -397,53 +380,21 @@ export interface ProjectOptions { * A map of environment variables to use when compiling code. */ env: Record +} - defineEnv: DefineEnv - - /** - * Whether to watch the filesystem for file changes. - */ - watch: { - enable: boolean - pollIntervalMs?: number - } - - /** - * The mode in which Next.js is running. - */ - dev: boolean - - /** - * The server actions encryption key. - */ - encryptionKey: string - - /** - * The build id. - */ - buildId: string - - /** - * Options for draft mode. - */ - previewProps: __ApiPreviewProps - - /** - * The browserslist query to use for targeting browsers. - */ - browserslistQuery: string - +export interface PartialProjectOptions + extends Omit { + rootPath: NapiProjectOptions['rootPath'] + projectPath: NapiProjectOptions['projectPath'] /** - * When the code is minified, this opts out of the default mangling of local - * names for variables, functions etc., which can be useful for - * debugging/profiling purposes. + * The next.config.js contents. */ - noMangling: boolean + nextConfig?: NextConfigComplete /** - * The version of Node.js that is available/currently running. + * A map of environment variables to use when compiling code. */ - currentNodeJsVersion: string + env?: Record } export interface DefineEnv {