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..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 @@ -79,11 +79,24 @@ 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.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 { + None + } } else { None } @@ -172,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 { @@ -226,12 +250,25 @@ 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.is_esm { + // import.meta.url is only available in ES modules + return None; + } + 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", +};