From f337ba22eb1d9b25218b33ec037e0fe97d09767f Mon Sep 17 00:00:00 2001 From: Michael Ireland Date: Fri, 21 Nov 2025 09:56:20 -0600 Subject: [PATCH 1/3] fix(javascript): prevent import.meta.url replacement in web target --- .../src/parser_plugin/import_meta_plugin.rs | 30 ++++++++++++------- .../parsing/import-meta-url-web/index.js | 5 ++++ .../import-meta-url-web/rspack.config.js | 3 ++ 3 files changed, 27 insertions(+), 11 deletions(-) create mode 100644 tests/rspack-test/configCases/parsing/import-meta-url-web/index.js create mode 100644 tests/rspack-test/configCases/parsing/import-meta-url-web/rspack.config.js diff --git a/crates/rspack_plugin_javascript/src/parser_plugin/import_meta_plugin.rs b/crates/rspack_plugin_javascript/src/parser_plugin/import_meta_plugin.rs index e2f70846b0ad..028a24b57ca3 100644 --- a/crates/rspack_plugin_javascript/src/parser_plugin/import_meta_plugin.rs +++ b/crates/rspack_plugin_javascript/src/parser_plugin/import_meta_plugin.rs @@ -79,11 +79,15 @@ impl JavascriptParserPlugin for ImportMetaPlugin { if for_name == expr_name::IMPORT_META_VERSION { Some(eval::evaluate_to_number(5_f64, start, end)) } else if for_name == expr_name::IMPORT_META_URL { - Some(eval::evaluate_to_string( - self.import_meta_url(parser), - start, - end, - )) + if parser.compiler_options.output.environment.supports_document() { + None + } else { + Some(eval::evaluate_to_string( + self.import_meta_url(parser), + start, + end, + )) + } } else { None } @@ -226,12 +230,16 @@ impl JavascriptParserPlugin for ImportMetaPlugin { ) -> Option { if for_name == expr_name::IMPORT_META_URL { // import.meta.url - parser.add_presentational_dependency(Box::new(ConstDependency::new( - member_expr.span().into(), - format!("'{}'", self.import_meta_url(parser)).into(), - None, - ))); - Some(true) + if parser.compiler_options.output.environment.supports_document() { + Some(true) + } else { + parser.add_presentational_dependency(Box::new(ConstDependency::new( + member_expr.span().into(), + format!("'{}'", self.import_meta_url(parser)).into(), + None, + ))); + Some(true) + } } else if for_name == expr_name::IMPORT_META_VERSION { // import.meta.webpack parser.add_presentational_dependency(Box::new(ConstDependency::new( diff --git a/tests/rspack-test/configCases/parsing/import-meta-url-web/index.js b/tests/rspack-test/configCases/parsing/import-meta-url-web/index.js new file mode 100644 index 000000000000..c3394e39d5f6 --- /dev/null +++ b/tests/rspack-test/configCases/parsing/import-meta-url-web/index.js @@ -0,0 +1,5 @@ +it("should not be replaced by file path", function() { + const url = import.meta.url; + expect(url).not.toMatch(/^file:\/\//); + expect(url).toMatch(/^http:\/\//); // Or whatever the test runner uses +}); diff --git a/tests/rspack-test/configCases/parsing/import-meta-url-web/rspack.config.js b/tests/rspack-test/configCases/parsing/import-meta-url-web/rspack.config.js new file mode 100644 index 000000000000..20f2621b17a0 --- /dev/null +++ b/tests/rspack-test/configCases/parsing/import-meta-url-web/rspack.config.js @@ -0,0 +1,3 @@ +module.exports = { + target: "web", +}; From 396aa66fb7755faf935a2fb1ed4a9cc909580279 Mon Sep 17 00:00:00 2001 From: Michael Ireland Date: Sat, 29 Nov 2025 22:15:49 -0600 Subject: [PATCH 2/3] fix: check if module is ES module before using import.meta.url The script must be an ES module to use import.meta.url. We cannot use supports_document() to determine this. This change adds a check for parser.is_esm before handling import.meta.url in both evaluate_identifier and member methods. --- .../src/parser_plugin/import_meta_plugin.rs | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/crates/rspack_plugin_javascript/src/parser_plugin/import_meta_plugin.rs b/crates/rspack_plugin_javascript/src/parser_plugin/import_meta_plugin.rs index 028a24b57ca3..2fdb2a6b698b 100644 --- a/crates/rspack_plugin_javascript/src/parser_plugin/import_meta_plugin.rs +++ b/crates/rspack_plugin_javascript/src/parser_plugin/import_meta_plugin.rs @@ -79,14 +79,18 @@ impl JavascriptParserPlugin for ImportMetaPlugin { if for_name == expr_name::IMPORT_META_VERSION { Some(eval::evaluate_to_number(5_f64, start, end)) } else if for_name == expr_name::IMPORT_META_URL { - if parser.compiler_options.output.environment.supports_document() { - None + if parser.is_esm { + if parser.compiler_options.output.environment.supports_document() { + None + } else { + Some(eval::evaluate_to_string( + self.import_meta_url(parser), + start, + end, + )) + } } else { - Some(eval::evaluate_to_string( - self.import_meta_url(parser), - start, - end, - )) + None } } else { None @@ -230,6 +234,10 @@ impl JavascriptParserPlugin for ImportMetaPlugin { ) -> Option { if for_name == expr_name::IMPORT_META_URL { // import.meta.url + if !parser.is_esm { + // import.meta.url is only available in ES modules + return None; + } if parser.compiler_options.output.environment.supports_document() { Some(true) } else { From 54b40cf0c1dfe1361976353465ac4b42cf6f6090 Mon Sep 17 00:00:00 2001 From: Michael Ireland Date: Sun, 30 Nov 2025 09:36:24 -0600 Subject: [PATCH 3/3] fix(javascript): preserve import.meta.url in destructuring for web targets When destructuring import.meta in ES modules targeting web environments, preserve import.meta.url using a getter function instead of replacing it with a file:// URL. This ensures the browser can resolve it to the actual script URL at runtime. --- .../src/parser_plugin/import_meta_plugin.rs | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/crates/rspack_plugin_javascript/src/parser_plugin/import_meta_plugin.rs b/crates/rspack_plugin_javascript/src/parser_plugin/import_meta_plugin.rs index 2fdb2a6b698b..1ac655fd5966 100644 --- a/crates/rspack_plugin_javascript/src/parser_plugin/import_meta_plugin.rs +++ b/crates/rspack_plugin_javascript/src/parser_plugin/import_meta_plugin.rs @@ -80,7 +80,12 @@ impl JavascriptParserPlugin for ImportMetaPlugin { Some(eval::evaluate_to_number(5_f64, start, end)) } else if for_name == expr_name::IMPORT_META_URL { if parser.is_esm { - if parser.compiler_options.output.environment.supports_document() { + if parser + .compiler_options + .output + .environment + .supports_document() + { None } else { Some(eval::evaluate_to_string( @@ -180,7 +185,18 @@ impl JavascriptParserPlugin for ImportMetaPlugin { let mut content = vec![]; for prop in referenced_properties_in_destructuring.iter() { if prop.id == "url" { - content.push(format!(r#"url: "{}""#, self.import_meta_url(parser))) + if parser.is_esm + && parser + .compiler_options + .output + .environment + .supports_document() + { + // Preserve import.meta.url for web targets in ES modules using a getter + content.push(r#"get url() { return import.meta.url; }"#.to_string()) + } else { + content.push(format!(r#"url: "{}""#, self.import_meta_url(parser))) + } } else if prop.id == "webpack" { content.push(format!(r#"webpack: {}"#, self.import_meta_version())); } else { @@ -238,7 +254,12 @@ impl JavascriptParserPlugin for ImportMetaPlugin { // import.meta.url is only available in ES modules return None; } - if parser.compiler_options.output.environment.supports_document() { + if parser + .compiler_options + .output + .environment + .supports_document() + { Some(true) } else { parser.add_presentational_dependency(Box::new(ConstDependency::new(