Skip to content

Commit 27c8fbf

Browse files
authored
feat: support preserve-unknown to keep unknown import.meta properties (#12796)
1 parent 49b036b commit 27c8fbf

File tree

15 files changed

+184
-42
lines changed

15 files changed

+184
-42
lines changed

crates/node_binding/napi-binding.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2388,7 +2388,7 @@ export interface RawJavascriptParserOptions {
23882388
reexportExportsPresence?: string
23892389
worker?: Array<string>
23902390
overrideStrict?: string
2391-
importMeta?: boolean
2391+
importMeta?: string
23922392
/**
23932393
* This option is experimental in Rspack only and subject to change or be removed anytime.
23942394
* @experimental

crates/rspack/src/builder/mod.rs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,15 @@ use rspack_core::{
4343
CssExportsConvention, CssGeneratorOptions, CssModuleGeneratorOptions, CssModuleParserOptions,
4444
CssParserImport, CssParserOptions, DynamicImportMode, EntryDescription, EntryOptions,
4545
EntryRuntime, Environment, Experiments, ExternalItem, ExternalType, Filename, GeneratorOptions,
46-
GeneratorOptionsMap, JavascriptParserCommonjsExportsOption, JavascriptParserCommonjsOptions,
47-
JavascriptParserOptions, JavascriptParserOrder, JavascriptParserUrl, JsonGeneratorOptions,
48-
JsonParserOptions, LibraryName, LibraryNonUmdObject, LibraryOptions, LibraryType,
49-
MangleExportsOption, Mode, ModuleNoParseRules, ModuleOptions, ModuleRule, ModuleRuleEffect,
50-
ModuleType, NodeDirnameOption, NodeFilenameOption, NodeGlobalOption, NodeOption, Optimization,
51-
OutputOptions, ParseOption, ParserOptions, ParserOptionsMap, PathInfo, PublicPath, Resolve,
52-
RuleSetCondition, RuleSetLogicalConditions, SideEffectOption, StatsOptions, TrustedTypes,
53-
UsedExportsOption, WasmLoading, WasmLoadingType, incremental::IncrementalOptions,
46+
GeneratorOptionsMap, ImportMeta, JavascriptParserCommonjsExportsOption,
47+
JavascriptParserCommonjsOptions, JavascriptParserOptions, JavascriptParserOrder,
48+
JavascriptParserUrl, JsonGeneratorOptions, JsonParserOptions, LibraryName, LibraryNonUmdObject,
49+
LibraryOptions, LibraryType, MangleExportsOption, Mode, ModuleNoParseRules, ModuleOptions,
50+
ModuleRule, ModuleRuleEffect, ModuleType, NodeDirnameOption, NodeFilenameOption,
51+
NodeGlobalOption, NodeOption, Optimization, OutputOptions, ParseOption, ParserOptions,
52+
ParserOptionsMap, PathInfo, PublicPath, Resolve, RuleSetCondition, RuleSetLogicalConditions,
53+
SideEffectOption, StatsOptions, TrustedTypes, UsedExportsOption, WasmLoading, WasmLoadingType,
54+
incremental::IncrementalOptions,
5455
};
5556
use rspack_error::{Error, Result};
5657
use rspack_fs::{IntermediateFileSystem, ReadableFileSystem, WritableFileSystem};
@@ -1702,7 +1703,13 @@ impl ModuleOptionsBuilder {
17021703
wrapped_context_critical: Some(false),
17031704
wrapped_context_reg_exp: Some(RspackRegex::new(".*").expect("should initialize `Regex`")),
17041705
worker: Some(vec!["...".to_string()]),
1705-
import_meta: Some(true),
1706+
import_meta: target_properties.module.map(|val| {
1707+
if val {
1708+
ImportMeta::PreserveUnknown
1709+
} else {
1710+
ImportMeta::Enabled
1711+
}
1712+
}),
17061713
require_alias: Some(false),
17071714
require_as_expression: Some(true),
17081715
require_dynamic: Some(true),

crates/rspack/tests/snapshots/defaults__default_options.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1654,7 +1654,7 @@ CompilerOptions {
16541654
),
16551655
override_strict: None,
16561656
import_meta: Some(
1657-
true,
1657+
Enabled,
16581658
),
16591659
require_alias: Some(
16601660
false,

crates/rspack_binding_api/src/raw_options/raw_module/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use rspack_core::{
1919
CssAutoGeneratorOptions, CssAutoParserOptions, CssGeneratorOptions, CssModuleGeneratorOptions,
2020
CssModuleParserOptions, CssParserImport, CssParserImportContext, CssParserOptions,
2121
DescriptionData, DynamicImportFetchPriority, DynamicImportMode, ExportPresenceMode, FuncUseCtx,
22-
GeneratorOptions, GeneratorOptionsMap, JavascriptParserCommonjsExportsOption,
22+
GeneratorOptions, GeneratorOptionsMap, ImportMeta, JavascriptParserCommonjsExportsOption,
2323
JavascriptParserCommonjsOptions, JavascriptParserOptions, JavascriptParserOrder,
2424
JavascriptParserUrl, JsonGeneratorOptions, JsonParserOptions, ModuleNoParseRule,
2525
ModuleNoParseRules, ModuleNoParseTestFn, ModuleOptions, ModuleRule, ModuleRuleEffect,
@@ -287,7 +287,7 @@ pub struct RawJavascriptParserOptions {
287287
pub reexport_exports_presence: Option<String>,
288288
pub worker: Option<Vec<String>>,
289289
pub override_strict: Option<String>,
290-
pub import_meta: Option<bool>,
290+
pub import_meta: Option<String>,
291291
/// This option is experimental in Rspack only and subject to change or be removed anytime.
292292
/// @experimental
293293
pub require_alias: Option<bool>,
@@ -365,7 +365,7 @@ impl From<RawJavascriptParserOptions> for JavascriptParserOptions {
365365
override_strict: value
366366
.override_strict
367367
.map(|e| OverrideStrict::from(e.as_str())),
368-
import_meta: value.import_meta,
368+
import_meta: value.import_meta.map(|e| ImportMeta::from(e.as_str())),
369369
require_alias: value.require_alias,
370370
require_as_expression: value.require_as_expression,
371371
require_dynamic: value.require_dynamic,

crates/rspack_core/src/options/module.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,24 @@ impl From<&str> for OverrideStrict {
281281
}
282282
}
283283

284+
#[cacheable]
285+
#[derive(Debug, Clone, Copy, MergeFrom)]
286+
pub enum ImportMeta {
287+
PreserveUnknown,
288+
Enabled,
289+
Disabled,
290+
}
291+
292+
impl From<&str> for ImportMeta {
293+
fn from(value: &str) -> Self {
294+
match value {
295+
"preserve-unknown" => Self::PreserveUnknown,
296+
"false" => Self::Disabled,
297+
_ => Self::Enabled,
298+
}
299+
}
300+
}
301+
284302
#[cacheable]
285303
#[derive(Debug, Clone, MergeFrom, Default)]
286304
pub struct JavascriptParserOptions {
@@ -299,7 +317,7 @@ pub struct JavascriptParserOptions {
299317
pub type_reexports_presence: Option<TypeReexportPresenceMode>,
300318
pub worker: Option<Vec<String>>,
301319
pub override_strict: Option<OverrideStrict>,
302-
pub import_meta: Option<bool>,
320+
pub import_meta: Option<ImportMeta>,
303321
pub require_alias: Option<bool>,
304322
pub require_as_expression: Option<bool>,
305323
pub require_dynamic: Option<bool>,

crates/rspack_plugin_javascript/src/parser_plugin/import_meta_plugin.rs

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use itertools::Itertools;
2-
use rspack_core::{ConstDependency, DependencyRange, property_access};
2+
use rspack_core::{ConstDependency, DependencyRange, ImportMeta, property_access};
33
use rspack_error::{Error, Severity};
44
use rspack_util::SpanExt;
55
use swc_core::{
@@ -18,7 +18,7 @@ use crate::{
1818
},
1919
};
2020

21-
pub struct ImportMetaPlugin;
21+
pub struct ImportMetaPlugin(pub(crate) ImportMeta);
2222

2323
impl ImportMetaPlugin {
2424
fn import_meta_url(&self, parser: &JavascriptParser) -> String {
@@ -32,11 +32,15 @@ impl ImportMetaPlugin {
3232
}
3333

3434
fn import_meta_unknown_property(&self, members: &Vec<String>) -> String {
35-
format!(
36-
r#"/* unsupported import.meta.{} */ undefined{}"#,
37-
members.join("."),
38-
property_access(members, 1)
39-
)
35+
if matches!(self.0, ImportMeta::PreserveUnknown) {
36+
format!("import.meta{}", property_access(members, 0))
37+
} else {
38+
format!(
39+
r#"/* unsupported import.meta.{} */ undefined{}"#,
40+
members.join("."),
41+
property_access(members, 1)
42+
)
43+
}
4044
}
4145

4246
fn process_import_meta_resolve(
@@ -339,6 +343,9 @@ impl JavascriptParserPlugin for ImportMetaPlugin {
339343
match root_info {
340344
ExportedVariableInfo::Name(root) => {
341345
if root == expr_name::IMPORT_META {
346+
if matches!(self.0, ImportMeta::PreserveUnknown) {
347+
return Some(true);
348+
}
342349
let members = parser
343350
.get_member_expression_info(ExprRef::Member(expr), AllowedMemberTypes::Expression)
344351
.and_then(|info| match info {

crates/rspack_plugin_javascript/src/parser_plugin/node_stuff_plugin.rs

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use rspack_core::{
2-
CachedConstDependency, ConstDependency, NodeDirnameOption, NodeFilenameOption, NodeGlobalOption,
3-
RuntimeGlobals, RuntimeRequirementsDependency, get_context, parse_resource,
2+
CachedConstDependency, ConstDependency, ImportMeta, NodeDirnameOption, NodeFilenameOption,
3+
NodeGlobalOption, RuntimeGlobals, RuntimeRequirementsDependency, get_context, parse_resource,
44
};
55
use rspack_error::{Diagnostic, cyan, yellow};
66
use rspack_util::SpanExt;
@@ -589,7 +589,10 @@ impl JavascriptParserPlugin for NodeStuffPlugin {
589589
return None;
590590
}
591591
// Skip if importMeta is disabled
592-
if parser.javascript_options.import_meta == Some(false) {
592+
if matches!(
593+
parser.javascript_options.import_meta,
594+
Some(ImportMeta::Disabled)
595+
) {
593596
return None;
594597
}
595598
// Skip if node: false or node.filename is disabled
@@ -625,7 +628,10 @@ impl JavascriptParserPlugin for NodeStuffPlugin {
625628
return None;
626629
}
627630
// Skip if importMeta is disabled
628-
if parser.javascript_options.import_meta == Some(false) {
631+
if matches!(
632+
parser.javascript_options.import_meta,
633+
Some(ImportMeta::Disabled)
634+
) {
629635
return None;
630636
}
631637
// Skip if node: false or node.dirname is disabled
@@ -660,7 +666,10 @@ impl JavascriptParserPlugin for NodeStuffPlugin {
660666
match for_name {
661667
expr_name::IMPORT_META_FILENAME => {
662668
// Skip processing if importMeta is disabled
663-
if parser.javascript_options.import_meta == Some(false) {
669+
if matches!(
670+
parser.javascript_options.import_meta,
671+
Some(ImportMeta::Disabled)
672+
) {
664673
return None;
665674
}
666675
// Skip processing if node: false or node.filename is disabled
@@ -681,7 +690,10 @@ impl JavascriptParserPlugin for NodeStuffPlugin {
681690
}
682691
expr_name::IMPORT_META_DIRNAME => {
683692
// Skip processing if importMeta is disabled
684-
if parser.javascript_options.import_meta == Some(false) {
693+
if matches!(
694+
parser.javascript_options.import_meta,
695+
Some(ImportMeta::Disabled)
696+
) {
685697
return None;
686698
}
687699
// Skip processing if node: false or node.dirname is disabled
@@ -762,7 +774,10 @@ impl JavascriptParserPlugin for NodeStuffPlugin {
762774
return None;
763775
}
764776
// Skip processing if importMeta is disabled
765-
if parser.javascript_options.import_meta == Some(false) {
777+
if matches!(
778+
parser.javascript_options.import_meta,
779+
Some(ImportMeta::Disabled)
780+
) {
766781
return None;
767782
}
768783
let property = if for_name == expr_name::IMPORT_META_FILENAME {
@@ -797,7 +812,10 @@ impl JavascriptParserPlugin for NodeStuffPlugin {
797812
};
798813

799814
// Skip processing if importMeta is disabled
800-
if parser.javascript_options.import_meta == Some(false) {
815+
if matches!(
816+
parser.javascript_options.import_meta,
817+
Some(ImportMeta::Disabled)
818+
) {
801819
return None;
802820
}
803821

@@ -820,7 +838,10 @@ impl JavascriptParserPlugin for NodeStuffPlugin {
820838
}
821839

822840
// Skip processing if importMeta is disabled
823-
if parser.javascript_options.import_meta == Some(false) {
841+
if matches!(
842+
parser.javascript_options.import_meta,
843+
Some(ImportMeta::Disabled)
844+
) {
824845
return None;
825846
}
826847

crates/rspack_plugin_javascript/src/visitors/dependency/parser/mod.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use rspack_cacheable::{
2222
};
2323
use rspack_core::{
2424
AsyncDependenciesBlock, BoxDependency, BoxDependencyTemplate, BuildInfo, BuildMeta,
25-
CompilerOptions, DependencyLocation, DependencyRange, FactoryMeta,
25+
CompilerOptions, DependencyLocation, DependencyRange, FactoryMeta, ImportMeta,
2626
JavascriptParserCommonjsExportsOption, JavascriptParserOptions, ModuleIdentifier, ModuleLayer,
2727
ModuleType, ParseMeta, ResourceData, SideEffectsBailoutItemWithSpan,
2828
};
@@ -417,8 +417,13 @@ impl<'parser> JavascriptParser<'parser> {
417417
plugins.push(Box::new(
418418
parser_plugin::ImportMetaContextDependencyParserPlugin,
419419
));
420-
if let Some(true) = javascript_options.import_meta {
421-
plugins.push(Box::new(parser_plugin::ImportMetaPlugin));
420+
if matches!(
421+
javascript_options.import_meta,
422+
Some(ImportMeta::Enabled | ImportMeta::PreserveUnknown)
423+
) {
424+
plugins.push(Box::new(parser_plugin::ImportMetaPlugin(
425+
javascript_options.import_meta.expect("should have value"),
426+
)));
422427
} else {
423428
plugins.push(Box::new(parser_plugin::ImportMetaDisabledPlugin));
424429
}

packages/rspack/src/config/adapter.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -561,7 +561,10 @@ function getRawJavascriptParserOptions(
561561
dynamicImportPreload: parser.dynamicImportPreload?.toString(),
562562
dynamicImportPrefetch: parser.dynamicImportPrefetch?.toString(),
563563
dynamicImportFetchPriority: parser.dynamicImportFetchPriority,
564-
importMeta: parser.importMeta,
564+
importMeta:
565+
typeof parser.importMeta === 'boolean'
566+
? String(parser.importMeta)
567+
: parser.importMeta,
565568
url: parser.url?.toString(),
566569
exprContextCritical: parser.exprContextCritical,
567570
unknownContextCritical: parser.unknownContextCritical,

packages/rspack/src/config/defaults.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ export const applyRspackOptionsDefaults = (
112112
mode: options.mode,
113113
uniqueName: options.output.uniqueName,
114114
deferImport: options.experiments.deferImport,
115+
outputModule: options.output.module,
115116
});
116117

117118
applyOutputDefaults(options, {
@@ -255,7 +256,13 @@ const applySnapshotDefaults = (
255256

256257
const applyJavascriptParserOptionsDefaults = (
257258
parserOptions: JavascriptParserOptions,
258-
{ deferImport }: { deferImport?: boolean },
259+
{
260+
deferImport,
261+
outputModule,
262+
}: {
263+
deferImport?: boolean;
264+
outputModule: RspackOptionsNormalized['output']['module'];
265+
},
259266
) => {
260267
D(parserOptions, 'dynamicImportMode', 'lazy');
261268
D(parserOptions, 'dynamicImportPrefetch', false);
@@ -273,7 +280,7 @@ const applyJavascriptParserOptionsDefaults = (
273280
D(parserOptions, 'commonjs', true);
274281
D(parserOptions, 'importDynamic', true);
275282
D(parserOptions, 'worker', ['...']);
276-
D(parserOptions, 'importMeta', true);
283+
D(parserOptions, 'importMeta', outputModule ? 'preserve-unknown' : true);
277284
D(parserOptions, 'typeReexportsPresence', 'no-tolerant');
278285
D(parserOptions, 'jsx', false);
279286
D(parserOptions, 'deferImport', deferImport);
@@ -305,12 +312,14 @@ const applyModuleDefaults = (
305312
mode,
306313
uniqueName,
307314
deferImport,
315+
outputModule,
308316
}: {
309317
asyncWebAssembly: boolean;
310318
targetProperties: false | TargetProperties;
311319
mode?: Mode;
312320
uniqueName?: string;
313321
deferImport?: boolean;
322+
outputModule: RspackOptionsNormalized['output']['module'];
314323
},
315324
) => {
316325
assertNotNill(module.parser);
@@ -328,6 +337,7 @@ const applyModuleDefaults = (
328337
assertNotNill(module.parser.javascript);
329338
applyJavascriptParserOptionsDefaults(module.parser.javascript, {
330339
deferImport,
340+
outputModule,
331341
});
332342

333343
F(module.parser, JSON_MODULE_TYPE, () => ({}));

0 commit comments

Comments
 (0)