mirror of
https://github.com/hanzoai/next.js.git
synced 2026-09-24 17:00:51 +00:00
Turbopack: respect the module-sync export condition (#93970)
I set it to `::Unknown` because we the runtime may or may not support module-sync. So let's just trace both for now There is one problem though: https://nodejs.org/docs/latest-v26.x/api/packages.html#conditional-exports > "module-sync" - matches no matter the package is loaded via import, import() or require(). The format is expected to be ES modules that does not contain top-level await in its module graph - if it does, ERR_REQUIRE_ASYNC_MODULE will be thrown when the module is require()-ed. So we have multiple options: 1. We definitely want to respect module-sync for tracing. We don't really have to throw ERR_REQUIRE_ASYNC_MODULE here, Node.js will do it at runtime anyway. 2. ~~What about bundling? Either~~ - ~~Respect module-sync always, but don't throw ERR_REQUIRE_ASYNC_MODULE.~~ - ~~Respect module-sync always, and do throw a build error the module requires TLA. This would require a separate validation pass though.~~ - I'm not enabling it for bundling for now
This commit is contained in:
@@ -39,9 +39,12 @@ pub enum ResolveModules {
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(TraceRawVcs, Hash, PartialEq, Eq, Clone, Copy, Debug, NonLocalValue, Encode, Decode)]
|
||||
#[derive(
|
||||
TraceRawVcs, Hash, PartialEq, Eq, Clone, Copy, Debug, NonLocalValue, Encode, Decode, Default,
|
||||
)]
|
||||
pub enum ConditionValue {
|
||||
Set,
|
||||
#[default]
|
||||
Unset,
|
||||
Unknown,
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ use turbopack_core::{
|
||||
output::{OutputAsset, OutputAssetsReference},
|
||||
reference::all_assets_from_entries,
|
||||
reference_type::ReferenceType,
|
||||
resolve::options::ConditionValue,
|
||||
traced_asset::TracedAsset,
|
||||
};
|
||||
use turbopack_ecmascript::AnalyzeMode;
|
||||
@@ -109,6 +110,7 @@ async fn node_file_trace_operation(
|
||||
enable_node_native_modules: true,
|
||||
enable_node_modules: Some(input_dir),
|
||||
custom_conditions: vec![rcstr!("node")],
|
||||
module_sync: ConditionValue::Unknown,
|
||||
enable_node_externals: true,
|
||||
loose_errors: true,
|
||||
collect_affecting_sources: true,
|
||||
|
||||
@@ -66,6 +66,9 @@ async fn apply_esm_specific_options_internal(
|
||||
for conditions in get_condition_maps(&mut options) {
|
||||
conditions.insert(rcstr!("import"), ConditionValue::Set);
|
||||
conditions.insert(rcstr!("require"), ConditionValue::Unset);
|
||||
// Don't set "module-sync" to ConditionValue::Set here. When tracing, the Node.js runtime
|
||||
// version might not support it yet, so we still want the "import"/"require"/"default"
|
||||
// result anyway.
|
||||
}
|
||||
|
||||
if clear_extensions {
|
||||
@@ -83,6 +86,9 @@ pub async fn apply_cjs_specific_options(options: Vc<ResolveOptions>) -> Result<V
|
||||
for conditions in get_condition_maps(&mut options) {
|
||||
conditions.insert(rcstr!("import"), ConditionValue::Unset);
|
||||
conditions.insert(rcstr!("require"), ConditionValue::Set);
|
||||
// Don't set "module-sync" to ConditionValue::Set here. When tracing, the Node.js runtime
|
||||
// version might not support it yet, so we still want the "import"/"require"/"default"
|
||||
// result anyway.
|
||||
}
|
||||
Ok(options.cell())
|
||||
}
|
||||
|
||||
@@ -88,6 +88,9 @@ async fn base_resolve_options(
|
||||
if opt.module {
|
||||
conditions.insert(rcstr!("module"), ConditionValue::Set);
|
||||
}
|
||||
if opt.module_sync != ConditionValue::Unset {
|
||||
conditions.insert(rcstr!("module-sync"), opt.module_sync);
|
||||
}
|
||||
if let Some(environment) = emulating {
|
||||
for condition in environment.resolve_conditions().await?.iter() {
|
||||
conditions.insert(condition.clone(), ConditionValue::Set);
|
||||
|
||||
@@ -7,7 +7,7 @@ use turbopack_core::{
|
||||
condition::ContextCondition,
|
||||
environment::Environment,
|
||||
resolve::{
|
||||
options::{ImportMap, ResolvedMap},
|
||||
options::{ConditionValue, ImportMap, ResolvedMap},
|
||||
plugin::{AfterResolvePlugin, BeforeResolvePlugin},
|
||||
},
|
||||
};
|
||||
@@ -53,6 +53,8 @@ pub struct ResolveOptionsContext {
|
||||
pub browser: bool,
|
||||
/// Enables the "module" field and export condition in package.json
|
||||
pub module: bool,
|
||||
/// Enables the "module-sync" export condition in package.json
|
||||
pub module_sync: ConditionValue,
|
||||
pub custom_conditions: Vec<RcStr>,
|
||||
pub custom_extensions: Option<Vec<RcStr>>,
|
||||
/// An additional import map to use when resolving modules.
|
||||
|
||||
@@ -51,6 +51,7 @@ use turbopack_core::{
|
||||
rebase::RebasedAsset,
|
||||
reference::all_assets_from_entry,
|
||||
reference_type::ReferenceType,
|
||||
resolve::options::ConditionValue,
|
||||
};
|
||||
use turbopack_ecmascript::AnalyzeMode;
|
||||
use turbopack_resolve::resolve_options_context::ResolveOptionsContext;
|
||||
@@ -414,6 +415,7 @@ async fn node_file_trace_operation(
|
||||
enable_node_native_modules: true,
|
||||
enable_node_modules: Some(input_dir.clone()),
|
||||
custom_conditions: vec![rcstr!("node")],
|
||||
module_sync: ConditionValue::Unknown,
|
||||
collect_affecting_sources: true,
|
||||
..Default::default()
|
||||
}
|
||||
|
||||
+2
-1
@@ -1,6 +1,7 @@
|
||||
;[
|
||||
'test/unit/imports-module-sync/input.js',
|
||||
'test/unit/imports-module-sync/internal-default.js',
|
||||
// @vercel/nft outputs internal-default.js here instead, but I think that's wrong?
|
||||
'test/unit/imports-module-sync/internal-import.js',
|
||||
'test/unit/imports-module-sync/internal-sync.js',
|
||||
'test/unit/imports-module-sync/package.json',
|
||||
]
|
||||
|
||||
+2
-1
@@ -1,5 +1,6 @@
|
||||
;[
|
||||
'test/unit/module-sync-condition-es-nested/fallback.js',
|
||||
// @vercel/nft outputs fallback.js here instead, but I think that's wrong?
|
||||
'test/unit/module-sync-condition-es-nested/import.js',
|
||||
'test/unit/module-sync-condition-es-nested/input.js',
|
||||
'test/unit/module-sync-condition-es-nested/module-sync.js',
|
||||
'test/unit/module-sync-condition-es-nested/package.json',
|
||||
|
||||
+2
-1
@@ -1,5 +1,6 @@
|
||||
;[
|
||||
'test/unit/module-sync-condition-es/fallback.js',
|
||||
// @vercel/nft outputs fallback.js here instead, but I think that's wrong?
|
||||
'test/unit/module-sync-condition-es/import.js',
|
||||
'test/unit/module-sync-condition-es/input.js',
|
||||
'test/unit/module-sync-condition-es/module-sync.js',
|
||||
'test/unit/module-sync-condition-es/package.json',
|
||||
|
||||
+2
-1
@@ -1,5 +1,6 @@
|
||||
;[
|
||||
'test/unit/self-reference-module-sync/default.js',
|
||||
// @vercel/nft outputs default.js here instead, but I think that's wrong?
|
||||
'test/unit/self-reference-module-sync/import.js',
|
||||
'test/unit/self-reference-module-sync/input.js',
|
||||
'test/unit/self-reference-module-sync/module-sync.js',
|
||||
'test/unit/self-reference-module-sync/package.json',
|
||||
|
||||
@@ -30,6 +30,7 @@ use turbopack_core::{
|
||||
output::OutputAsset,
|
||||
reference::all_assets_from_entries,
|
||||
reference_type::ReferenceType,
|
||||
resolve::options::ConditionValue,
|
||||
traced_asset::TracedAsset,
|
||||
};
|
||||
use turbopack_ecmascript::AnalyzeMode;
|
||||
@@ -108,8 +109,8 @@ static ALLOC: turbo_tasks_malloc::TurboMalloc = turbo_tasks_malloc::TurboMalloc;
|
||||
// #[case::import_meta_tpl_cnd("import-meta-tpl-cnd")]
|
||||
#[case::import_meta_url("import-meta-url")]
|
||||
// #[case::imports("imports")]
|
||||
// #[case::imports_module_sync("imports-module-sync")]
|
||||
// #[case::imports_module_sync_cjs("imports-module-sync-cjs")]
|
||||
#[case::imports_module_sync("imports-module-sync")]
|
||||
#[case::imports_module_sync_cjs("imports-module-sync-cjs")]
|
||||
// #[case::jsonc_parser_wrapper("jsonc-parser-wrapper")]
|
||||
// #[case::jsx_input("jsx-input")]
|
||||
// #[case::microtime_node_gyp("microtime-node-gyp")]
|
||||
@@ -123,10 +124,12 @@ static ALLOC: turbo_tasks_malloc::TurboMalloc = turbo_tasks_malloc::TurboMalloc;
|
||||
#[case::module_create_require_no_mixed("module-create-require-no-mixed")]
|
||||
// #[case::module_register("module-register")]
|
||||
// #[case::module_require("module-require")]
|
||||
// #[case::module_sync_condition_cjs("module-sync-condition-cjs")]
|
||||
#[case::module_sync_condition_cjs("module-sync-condition-cjs")]
|
||||
// Turbopack always includes the module-sync version, regardless of the current Node version
|
||||
// #[case::module_sync_condition_cjs_node20("module-sync-condition-cjs-node20")]
|
||||
// #[case::module_sync_condition_es("module-sync-condition-es")]
|
||||
// #[case::module_sync_condition_es_nested("module-sync-condition-es-nested")]
|
||||
#[case::module_sync_condition_es("module-sync-condition-es")]
|
||||
#[case::module_sync_condition_es_nested("module-sync-condition-es-nested")]
|
||||
// Turbopack always includes the module-sync version, regardless of the current Node version
|
||||
// #[case::module_sync_condition_es_node20("module-sync-condition-es-node20")]
|
||||
// #[case::mongoose("mongoose")]
|
||||
// #[case::multi_input("multi-input")]
|
||||
@@ -165,7 +168,7 @@ static ALLOC: turbo_tasks_malloc::TurboMalloc = turbo_tasks_malloc::TurboMalloc;
|
||||
// #[case::resolve_from("resolve-from")]
|
||||
// #[case::resolve_hook("resolve-hook")]
|
||||
// #[case::return_emission("return-emission")]
|
||||
// #[case::self_reference_module_sync("self-reference-module-sync")]
|
||||
#[case::self_reference_module_sync("self-reference-module-sync")]
|
||||
// #[case::shiki("shiki")]
|
||||
// #[case::string_concat("string-concat")]
|
||||
#[case::syntax_err("syntax-err")]
|
||||
@@ -250,6 +253,7 @@ async fn node_file_trace_operation(package_root: RcStr, input: RcStr) -> Result<
|
||||
enable_node_native_modules: true,
|
||||
enable_node_modules: Some(input_dir.clone()),
|
||||
custom_conditions: vec![rcstr!("node")],
|
||||
module_sync: ConditionValue::Unknown,
|
||||
..Default::default()
|
||||
}
|
||||
.cell(),
|
||||
|
||||
@@ -36,8 +36,11 @@ use turbopack_core::{
|
||||
},
|
||||
resolve::{
|
||||
ExternalTraced, ExternalType, ModulePart, ModuleResolveResult, ModuleResolveResultItem,
|
||||
ResolveResult, ResolveResultItem, options::ResolveOptions, origin::PlainResolveOrigin,
|
||||
parse::Request, resolve,
|
||||
ResolveResult, ResolveResultItem,
|
||||
options::{ConditionValue, ResolveOptions},
|
||||
origin::PlainResolveOrigin,
|
||||
parse::Request,
|
||||
resolve,
|
||||
},
|
||||
source::Source,
|
||||
source_transform::SourceTransforms,
|
||||
@@ -926,6 +929,7 @@ pub async fn externals_tracing_module_context(
|
||||
loose_errors: true,
|
||||
collect_affecting_sources: true,
|
||||
custom_conditions: vec![rcstr!("node")],
|
||||
module_sync: ConditionValue::Unknown,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user