From 6fcadbc230a8187f3e8b05eb421ef8b0142c8ade Mon Sep 17 00:00:00 2001 From: magic-akari Date: Sat, 18 Mar 2023 19:08:32 +0800 Subject: [PATCH] feat: Support `new URL("./foo", import.meta.url)` --- .changeset/loud-toys-watch.md | 5 + crates/rspack_core/src/dependency/mod.rs | 2 + .../src/dependency/mod.rs | 2 + .../src/dependency/url/mod.rs | 136 ++++++++++++++++++ .../visitors/dependency/code_generation.rs | 1 + .../src/visitors/dependency/scanner.rs | 60 +++++++- .../fixtures/new_url/inline/expected/main.js | 20 +++ .../new_url/inline/expected/runtime.js | 117 +++++++++++++++ .../tests/fixtures/new_url/inline/index.js | 5 + .../tests/fixtures/new_url/inline/react.svg | 1 + .../fixtures/new_url/inline/test.config.json | 13 ++ .../tests/fixtures/new_url/inline/vue.svg | 1 + .../resource/expected/5d7c2bf56394b7b7.svg | 1 + .../resource/expected/5f5ecd0973bd7725.svg | 1 + .../new_url/resource/expected/main.js | 20 +++ .../new_url/resource/expected/runtime.js | 122 ++++++++++++++++ .../tests/fixtures/new_url/resource/index.js | 5 + .../tests/fixtures/new_url/resource/react.svg | 1 + .../new_url/resource/test.config.json | 13 ++ .../tests/fixtures/new_url/resource/vue.svg | 1 + 20 files changed, 526 insertions(+), 1 deletion(-) create mode 100644 .changeset/loud-toys-watch.md create mode 100644 crates/rspack_plugin_javascript/src/dependency/url/mod.rs create mode 100644 crates/rspack_plugin_javascript/tests/fixtures/new_url/inline/expected/main.js create mode 100644 crates/rspack_plugin_javascript/tests/fixtures/new_url/inline/expected/runtime.js create mode 100644 crates/rspack_plugin_javascript/tests/fixtures/new_url/inline/index.js create mode 100644 crates/rspack_plugin_javascript/tests/fixtures/new_url/inline/react.svg create mode 100644 crates/rspack_plugin_javascript/tests/fixtures/new_url/inline/test.config.json create mode 100644 crates/rspack_plugin_javascript/tests/fixtures/new_url/inline/vue.svg create mode 100644 crates/rspack_plugin_javascript/tests/fixtures/new_url/resource/expected/5d7c2bf56394b7b7.svg create mode 100644 crates/rspack_plugin_javascript/tests/fixtures/new_url/resource/expected/5f5ecd0973bd7725.svg create mode 100644 crates/rspack_plugin_javascript/tests/fixtures/new_url/resource/expected/main.js create mode 100644 crates/rspack_plugin_javascript/tests/fixtures/new_url/resource/expected/runtime.js create mode 100644 crates/rspack_plugin_javascript/tests/fixtures/new_url/resource/index.js create mode 100644 crates/rspack_plugin_javascript/tests/fixtures/new_url/resource/react.svg create mode 100644 crates/rspack_plugin_javascript/tests/fixtures/new_url/resource/test.config.json create mode 100644 crates/rspack_plugin_javascript/tests/fixtures/new_url/resource/vue.svg diff --git a/.changeset/loud-toys-watch.md b/.changeset/loud-toys-watch.md new file mode 100644 index 000000000000..aba27c1ca0fe --- /dev/null +++ b/.changeset/loud-toys-watch.md @@ -0,0 +1,5 @@ +--- +"@rspack/core": patch +--- + +feat: Support `new URL("./foo", import.meta.url)` diff --git a/crates/rspack_core/src/dependency/mod.rs b/crates/rspack_core/src/dependency/mod.rs index 7a82a6542cc4..0136433ef970 100644 --- a/crates/rspack_core/src/dependency/mod.rs +++ b/crates/rspack_core/src/dependency/mod.rs @@ -35,6 +35,8 @@ pub enum DependencyType { DynamicImport, // cjs require CjsRequire, + // new URL("./foo", import.meta.url) + NewUrl, // import.meta.webpackHot.accept ImportMetaHotAccept, // import.meta.webpackHot.decline diff --git a/crates/rspack_plugin_javascript/src/dependency/mod.rs b/crates/rspack_plugin_javascript/src/dependency/mod.rs index 91e9151ad530..bd4ddc693ffa 100644 --- a/crates/rspack_plugin_javascript/src/dependency/mod.rs +++ b/crates/rspack_plugin_javascript/src/dependency/mod.rs @@ -1,5 +1,7 @@ mod commonjs; pub use commonjs::*; +mod url; +pub use url::*; mod esm; pub use esm::*; mod hmr; diff --git a/crates/rspack_plugin_javascript/src/dependency/url/mod.rs b/crates/rspack_plugin_javascript/src/dependency/url/mod.rs new file mode 100644 index 000000000000..e8f1d4affe40 --- /dev/null +++ b/crates/rspack_plugin_javascript/src/dependency/url/mod.rs @@ -0,0 +1,136 @@ +use rspack_core::{ + create_javascript_visitor, runtime_globals, CodeGeneratable, CodeGeneratableContext, + CodeGeneratableResult, Dependency, DependencyCategory, DependencyId, DependencyType, ErrorSpan, + JsAstPath, ModuleDependency, ModuleIdentifier, +}; +use swc_core::common::Spanned; +use swc_core::ecma::utils::{member_expr, quote_ident, quote_str}; +use swc_core::ecma::{ast::*, atoms::JsWord}; + +#[derive(Debug, Eq, Clone)] +pub struct URLDependency { + id: Option, + parent_module_identifier: Option, + request: JsWord, + span: Option, + #[allow(unused)] + ast_path: JsAstPath, +} + +// Do not edit this, as it is used to uniquely identify the dependency. +impl PartialEq for URLDependency { + fn eq(&self, other: &Self) -> bool { + self.parent_module_identifier == other.parent_module_identifier && self.request == other.request + } +} + +// Do not edit this, as it is used to uniquely identify the dependency. +impl std::hash::Hash for URLDependency { + fn hash(&self, state: &mut H) { + self.parent_module_identifier.hash(state); + self.request.hash(state); + self.category().hash(state); + self.dependency_type().hash(state); + } +} + +impl URLDependency { + pub fn new(request: JsWord, span: Option, ast_path: JsAstPath) -> Self { + Self { + id: None, + parent_module_identifier: None, + request, + span, + ast_path, + } + } +} + +impl Dependency for URLDependency { + fn id(&self) -> Option { + self.id + } + fn set_id(&mut self, id: Option) { + self.id = id; + } + fn parent_module_identifier(&self) -> Option<&ModuleIdentifier> { + self.parent_module_identifier.as_ref() + } + + fn set_parent_module_identifier(&mut self, module_identifier: Option) { + self.parent_module_identifier = module_identifier; + } + + fn category(&self) -> &DependencyCategory { + &DependencyCategory::Url + } + + fn dependency_type(&self) -> &DependencyType { + &DependencyType::NewUrl + } +} + +impl ModuleDependency for URLDependency { + fn request(&self) -> &str { + &self.request + } + + fn user_request(&self) -> &str { + &self.request + } + + fn span(&self) -> Option<&ErrorSpan> { + self.span.as_ref() + } +} + +impl CodeGeneratable for URLDependency { + fn generate( + &self, + code_generatable_context: &mut CodeGeneratableContext, + ) -> rspack_error::Result { + let CodeGeneratableContext { compilation, .. } = code_generatable_context; + let mut code_gen = CodeGeneratableResult::default(); + + if let Some(id) = self.id() { + if let Some(module_id) = compilation + .module_graph + .module_graph_module_by_dependency_id(&id) + .map(|m| m.id(&compilation.chunk_graph).to_string()) + { + code_gen.visitors.push( + create_javascript_visitor!(exact &self.ast_path, visit_mut_new_expr(n: &mut NewExpr) { + let Some(args) = &mut n.args else { return }; + + if let (Some(first), Some(second)) = (args.first(), args.get(1)) { + let path_span = first.span(); + let meta_span = second.span(); + + let require_call = CallExpr { + span: path_span, + callee: Callee::Expr(quote_ident!(runtime_globals::REQUIRE).into()), + args: vec![ExprOrSpread { + spread: None, + expr: quote_str!(&*module_id).into(), + }], + type_args: None, + }; + + args[0] = ExprOrSpread { + spread: None, + expr: require_call.into(), + }; + + args[1] = ExprOrSpread { + spread: None, + expr: member_expr!(meta_span, self.location), + }; + } + }), + ); + } + } + + Ok(code_gen) + } +} diff --git a/crates/rspack_plugin_javascript/src/visitors/dependency/code_generation.rs b/crates/rspack_plugin_javascript/src/visitors/dependency/code_generation.rs index a5db788c14d2..8f0530f520ea 100644 --- a/crates/rspack_plugin_javascript/src/visitors/dependency/code_generation.rs +++ b/crates/rspack_plugin_javascript/src/visitors/dependency/code_generation.rs @@ -266,6 +266,7 @@ impl<'a, 'b> VisitMutAstPath for DependencyVisitor<'a, 'b> { impl_ast_node_interceptor!(module_decl, ModuleDecl); impl_ast_node_interceptor!(module_item, ModuleItem); impl_ast_node_interceptor!(call_expr, CallExpr); + impl_ast_node_interceptor!(new_expr, NewExpr); impl_ast_node_interceptor!(lit, Lit); impl_ast_node_interceptor!(str, Str); } diff --git a/crates/rspack_plugin_javascript/src/visitors/dependency/scanner.rs b/crates/rspack_plugin_javascript/src/visitors/dependency/scanner.rs index 6189ebcb6779..f002b0e01d59 100644 --- a/crates/rspack_plugin_javascript/src/visitors/dependency/scanner.rs +++ b/crates/rspack_plugin_javascript/src/visitors/dependency/scanner.rs @@ -7,8 +7,10 @@ use rspack_regex::RspackRegex; use sugar_path::SugarPath; use swc_core::common::{pass::AstNodePath, Mark, SyntaxContext}; use swc_core::ecma::ast::{ - BinExpr, BinaryOp, CallExpr, Callee, Expr, Lit, MemberProp, ModuleDecl, Tpl, + BinExpr, BinaryOp, CallExpr, Callee, Expr, ExprOrSpread, Ident, Lit, MemberExpr, MemberProp, + MetaPropExpr, MetaPropKind, ModuleDecl, NewExpr, Tpl, }; +use swc_core::ecma::atoms::js_word; use swc_core::ecma::utils::{quote_ident, quote_str}; use swc_core::ecma::visit::{AstParentNodeRef, VisitAstPath, VisitWithPath}; use swc_core::quote; @@ -16,6 +18,7 @@ use swc_core::quote; use super::{as_parent_path, is_require_context_call}; use crate::dependency::{ CommonJSRequireDependency, EsmDynamicImportDependency, EsmExportDependency, EsmImportDependency, + URLDependency, }; pub const WEBPACK_HASH: &str = "__webpack_hash__"; pub const WEBPACK_PUBLIC_PATH: &str = "__webpack_public_path__"; @@ -124,6 +127,52 @@ impl DependencyScanner<'_> { } } } + + // new URL("./foo.png", import.meta.url); + fn add_new_url(&mut self, new_expr: &NewExpr, ast_path: &AstNodePath>) { + if let Expr::Ident(Ident { + sym: js_word!("URL"), + .. + }) = &*new_expr.callee + { + if let Some(args) = &new_expr.args { + if let (Some(first), Some(second)) = (args.first(), args.get(1)) { + if let ( + ExprOrSpread { + spread: None, + expr: box Expr::Lit(Lit::Str(path)), + }, + // import.meta.url + ExprOrSpread { + spread: None, + expr: + box Expr::Member(MemberExpr { + obj: + box Expr::MetaProp(MetaPropExpr { + kind: MetaPropKind::ImportMeta, + .. + }), + prop: + MemberProp::Ident(Ident { + sym: js_word!("url"), + .. + }), + .. + }), + }, + ) = (first, second) + { + self.add_dependency(box URLDependency::new( + path.value.clone(), + Some(new_expr.span.into()), + as_parent_path(ast_path), + )) + } + } + } + } + } + fn add_export( &mut self, module_decl: &ModuleDecl, @@ -237,6 +286,15 @@ impl VisitAstPath for DependencyScanner<'_> { node.visit_children_with_path(self, ast_path); } + fn visit_new_expr<'ast: 'r, 'r>( + &mut self, + node: &'ast NewExpr, + ast_path: &mut AstNodePath>, + ) { + self.add_new_url(node, &*ast_path); + node.visit_children_with_path(self, ast_path); + } + fn visit_expr<'ast: 'r, 'r>( &mut self, expr: &'ast Expr, diff --git a/crates/rspack_plugin_javascript/tests/fixtures/new_url/inline/expected/main.js b/crates/rspack_plugin_javascript/tests/fixtures/new_url/inline/expected/main.js new file mode 100644 index 000000000000..a70ecafca69f --- /dev/null +++ b/crates/rspack_plugin_javascript/tests/fixtures/new_url/inline/expected/main.js @@ -0,0 +1,20 @@ +(self['webpackChunkwebpack'] = self['webpackChunkwebpack'] || []).push([["main"], { +"./react.svg": function (module, exports, __webpack_require__) { +"use strict"; +module.exports = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA4NDEuOSA1OTUuMyI+PGcgZmlsbD0iIzYxREFGQiI+PHBhdGggZD0iTTY2Ni4zIDI5Ni41YzAtMzIuNS00MC43LTYzLjMtMTAzLjEtODIuNCAxNC40LTYzLjYgOC0xMTQuMi0yMC4yLTEzMC40LTYuNS0zLjgtMTQuMS01LjYtMjIuNC01LjZ2MjIuM2M0LjYgMCA4LjMuOSAxMS40IDIuNiAxMy42IDcuOCAxOS41IDM3LjUgMTQuOSA3NS43LTEuMSA5LjQtMi45IDE5LjMtNS4xIDI5LjQtMTkuNi00LjgtNDEtOC41LTYzLjUtMTAuOS0xMy41LTE4LjUtMjcuNS0zNS4zLTQxLjYtNTAgMzIuNi0zMC4zIDYzLjItNDYuOSA4NC00Ni45Vjc4Yy0yNy41IDAtNjMuNSAxOS42LTk5LjkgNTMuNi0zNi40LTMzLjgtNzIuNC01My4yLTk5LjktNTMuMnYyMi4zYzIwLjcgMCA1MS40IDE2LjUgODQgNDYuNi0xNCAxNC43LTI4IDMxLjQtNDEuMyA0OS45LTIyLjYgMi40LTQ0IDYuMS02My42IDExLTIuMy0xMC00LTE5LjctNS4yLTI5LTQuNy0zOC4yIDEuMS02Ny45IDE0LjYtNzUuOCAzLTEuOCA2LjktMi42IDExLjUtMi42Vjc4LjVjLTguNCAwLTE2IDEuOC0yMi42IDUuNi0yOC4xIDE2LjItMzQuNCA2Ni43LTE5LjkgMTMwLjEtNjIuMiAxOS4yLTEwMi43IDQ5LjktMTAyLjcgODIuMyAwIDMyLjUgNDAuNyA2My4zIDEwMy4xIDgyLjQtMTQuNCA2My42LTggMTE0LjIgMjAuMiAxMzAuNCA2LjUgMy44IDE0LjEgNS42IDIyLjUgNS42IDI3LjUgMCA2My41LTE5LjYgOTkuOS01My42IDM2LjQgMzMuOCA3Mi40IDUzLjIgOTkuOSA1My4yIDguNCAwIDE2LTEuOCAyMi42LTUuNiAyOC4xLTE2LjIgMzQuNC02Ni43IDE5LjktMTMwLjEgNjItMTkuMSAxMDIuNS00OS45IDEwMi41LTgyLjN6bS0xMzAuMi02Ni43Yy0zLjcgMTIuOS04LjMgMjYuMi0xMy41IDM5LjUtNC4xLTgtOC40LTE2LTEzLjEtMjQtNC42LTgtOS41LTE1LjgtMTQuNC0yMy40IDE0LjIgMi4xIDI3LjkgNC43IDQxIDcuOXptLTQ1LjggMTA2LjVjLTcuOCAxMy41LTE1LjggMjYuMy0yNC4xIDM4LjItMTQuOSAxLjMtMzAgMi00NS4yIDItMTUuMSAwLTMwLjItLjctNDUtMS45LTguMy0xMS45LTE2LjQtMjQuNi0yNC4yLTM4LTcuNi0xMy4xLTE0LjUtMjYuNC0yMC44LTM5LjggNi4yLTEzLjQgMTMuMi0yNi44IDIwLjctMzkuOSA3LjgtMTMuNSAxNS44LTI2LjMgMjQuMS0zOC4yIDE0LjktMS4zIDMwLTIgNDUuMi0yIDE1LjEgMCAzMC4yLjcgNDUgMS45IDguMyAxMS45IDE2LjQgMjQuNiAyNC4yIDM4IDcuNiAxMy4xIDE0LjUgMjYuNCAyMC44IDM5LjgtNi4zIDEzLjQtMTMuMiAyNi44LTIwLjcgMzkuOXptMzIuMy0xM2M1LjQgMTMuNCAxMCAyNi44IDEzLjggMzkuOC0xMy4xIDMuMi0yNi45IDUuOS00MS4yIDggNC45LTcuNyA5LjgtMTUuNiAxNC40LTIzLjcgNC42LTggOC45LTE2LjEgMTMtMjQuMXpNNDIxLjIgNDMwYy05LjMtOS42LTE4LjYtMjAuMy0yNy44LTMyIDkgLjQgMTguMi43IDI3LjUuNyA5LjQgMCAxOC43LS4yIDI3LjgtLjctOSAxMS43LTE4LjMgMjIuNC0yNy41IDMyem0tNzQuNC01OC45Yy0xNC4yLTIuMS0yNy45LTQuNy00MS03LjkgMy43LTEyLjkgOC4zLTI2LjIgMTMuNS0zOS41IDQuMSA4IDguNCAxNiAxMy4xIDI0IDQuNyA4IDkuNSAxNS44IDE0LjQgMjMuNHpNNDIwLjcgMTYzYzkuMyA5LjYgMTguNiAyMC4zIDI3LjggMzItOS0uNC0xOC4yLS43LTI3LjUtLjctOS40IDAtMTguNy4yLTI3LjguNyA5LTExLjcgMTguMy0yMi40IDI3LjUtMzJ6bS03NCA1OC45Yy00LjkgNy43LTkuOCAxNS42LTE0LjQgMjMuNy00LjYgOC04LjkgMTYtMTMgMjQtNS40LTEzLjQtMTAtMjYuOC0xMy44LTM5LjggMTMuMS0zLjEgMjYuOS01LjggNDEuMi03Ljl6bS05MC41IDEyNS4yYy0zNS40LTE1LjEtNTguMy0zNC45LTU4LjMtNTAuNiAwLTE1LjcgMjIuOS0zNS42IDU4LjMtNTAuNiA4LjYtMy43IDE4LTcgMjcuNy0xMC4xIDUuNyAxOS42IDEzLjIgNDAgMjIuNSA2MC45LTkuMiAyMC44LTE2LjYgNDEuMS0yMi4yIDYwLjYtOS45LTMuMS0xOS4zLTYuNS0yOC0xMC4yek0zMTAgNDkwYy0xMy42LTcuOC0xOS41LTM3LjUtMTQuOS03NS43IDEuMS05LjQgMi45LTE5LjMgNS4xLTI5LjQgMTkuNiA0LjggNDEgOC41IDYzLjUgMTAuOSAxMy41IDE4LjUgMjcuNSAzNS4zIDQxLjYgNTAtMzIuNiAzMC4zLTYzLjIgNDYuOS04NCA0Ni45LTQuNS0uMS04LjMtMS0xMS4zLTIuN3ptMjM3LjItNzYuMmM0LjcgMzguMi0xLjEgNjcuOS0xNC42IDc1LjgtMyAxLjgtNi45IDIuNi0xMS41IDIuNi0yMC43IDAtNTEuNC0xNi41LTg0LTQ2LjYgMTQtMTQuNyAyOC0zMS40IDQxLjMtNDkuOSAyMi42LTIuNCA0NC02LjEgNjMuNi0xMSAyLjMgMTAuMSA0LjEgMTkuOCA1LjIgMjkuMXptMzguNS02Ni43Yy04LjYgMy43LTE4IDctMjcuNyAxMC4xLTUuNy0xOS42LTEzLjItNDAtMjIuNS02MC45IDkuMi0yMC44IDE2LjYtNDEuMSAyMi4yLTYwLjYgOS45IDMuMSAxOS4zIDYuNSAyOC4xIDEwLjIgMzUuNCAxNS4xIDU4LjMgMzQuOSA1OC4zIDUwLjYtLjEgMTUuNy0yMyAzNS42LTU4LjQgNTAuNnpNMzIwLjggNzguNHoiLz48Y2lyY2xlIGN4PSI0MjAuOSIgY3k9IjI5Ni41IiByPSI0NS43Ii8+PHBhdGggZD0iTTUyMC41IDc4LjF6Ii8+PC9nPjwvc3ZnPg==";}, +"./vue.svg": function (module, exports, __webpack_require__) { +"use strict"; +module.exports = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBhcmlhLWhpZGRlbj0idHJ1ZSIgcm9sZT0iaW1nIiBjbGFzcz0iaWNvbmlmeSBpY29uaWZ5LS1sb2dvcyIgd2lkdGg9IjM3LjA3IiBoZWlnaHQ9IjM2IiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ4TWlkWU1pZCBtZWV0IiB2aWV3Qm94PSIwIDAgMjU2IDE5OCI+PHBhdGggZmlsbD0iIzQxQjg4MyIgZD0iTTIwNC44IDBIMjU2TDEyOCAyMjAuOEwwIDBoOTcuOTJMMTI4IDUxLjJMMTU3LjQ0IDBoNDcuMzZaIj48L3BhdGg+PHBhdGggZmlsbD0iIzQxQjg4MyIgZD0ibTAgMGwxMjggMjIwLjhMMjU2IDBoLTUxLjJMMTI4IDEzMi40OEw1MC41NiAwSDBaIj48L3BhdGg+PHBhdGggZmlsbD0iIzM1NDk1RSIgZD0iTTUwLjU2IDBMMTI4IDEzMy4xMkwyMDQuOCAwaC00Ny4zNkwxMjggNTEuMkw5Ny45MiAwSDUwLjU2WiI+PC9wYXRoPjwvc3ZnPg==";}, +"./index.js": function (module, exports, __webpack_require__) { +const imgSrc = new URL(__webpack_require__("./react.svg"), self.location); +const imgSrc2 = __webpack_require__("./vue.svg"); +const img = new Image(); +img.src = imgSrc.href; +img.src = imgSrc2; +}, + +},function(__webpack_require__) { +var __webpack_exports__ = __webpack_require__('./index.js'); + +} +]); \ No newline at end of file diff --git a/crates/rspack_plugin_javascript/tests/fixtures/new_url/inline/expected/runtime.js b/crates/rspack_plugin_javascript/tests/fixtures/new_url/inline/expected/runtime.js new file mode 100644 index 000000000000..0503c9950716 --- /dev/null +++ b/crates/rspack_plugin_javascript/tests/fixtures/new_url/inline/expected/runtime.js @@ -0,0 +1,117 @@ +(function() { +var __webpack_modules__ = { + +} +// The module cache + var __webpack_module_cache__ = {}; +function __webpack_require__(moduleId) { +// Check if module is in cache + var cachedModule = __webpack_module_cache__[moduleId]; + if (cachedModule !== undefined) { + return cachedModule.exports; + } + // Create a new module (and put it into the cache) + var module = (__webpack_module_cache__[moduleId] = { + // no module.loaded needed + exports: {} + }); + // Execute the module function + __webpack_modules__[moduleId](module, module.exports, __webpack_require__); +// Return the exports of the module + return module.exports; + +} +// expose the modules object (__webpack_modules__) + __webpack_require__.m = __webpack_modules__; +// webpack/runtime/on_chunk_loaded +(function() { +var deferred = []; +__webpack_require__.O = function (result, chunkIds, fn, priority) { + if (chunkIds) { + priority = priority || 0; + for (var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) + deferred[i] = deferred[i - 1]; + deferred[i] = [chunkIds, fn, priority]; + return; + } + var notFulfilled = Infinity; + for (var i = 0; i < deferred.length; i++) { + var [chunkIds, fn, priority] = deferred[i]; + var fulfilled = true; + for (var j = 0; j < chunkIds.length; j++) { + if ( + (priority & (1 === 0) || notFulfilled >= priority) && + Object.keys(__webpack_require__.O).every(function (key) { + __webpack_require__.O[key](chunkIds[j]); + }) + ) { + chunkIds.splice(j--, 1); + } else { + fulfilled = false; + if (priority < notFulfilled) notFulfilled = priority; + } + } + if (fulfilled) { + deferred.splice(i--, 1); + var r = fn(); + if (r !== undefined) result = r; + } + } + return result; +}; + +})(); +// webpack/runtime/has_own_property +(function() { +__webpack_require__.o = function (obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); +}; + +})(); +// webpack/runtime/jsonp_chunk_loading +(function() { +var installedChunks = {"runtime": 0,}; +__webpack_require__.O.j = function (chunkId) { + installedChunks[chunkId] === 0; +}; +// install a JSONP callback for chunk loading +var webpackJsonpCallback = function (parentChunkLoadingFunction, data) { + var [chunkIds, moreModules, runtime] = data; + // add "moreModules" to the modules object, + // then flag all "chunkIds" as loaded and fire callback + var moduleId, + chunkId, + i = 0; + if (chunkIds.some(id => installedChunks[id] !== 0)) { + for (moduleId in moreModules) { + if (__webpack_require__.o(moreModules, moduleId)) { + __webpack_require__.m[moduleId] = moreModules[moduleId]; + } + } + if (runtime) var result = runtime(__webpack_require__); + } + if (parentChunkLoadingFunction) parentChunkLoadingFunction(data); + for (; i < chunkIds.length; i++) { + chunkId = chunkIds[i]; + if ( + __webpack_require__.o(installedChunks, chunkId) && + installedChunks[chunkId] + ) { + installedChunks[chunkId][0](); + } + installedChunks[chunkId] = 0; + } + return __webpack_require__.O(result); +}; + +var chunkLoadingGlobal = (self["webpackChunkwebpack"] = + self["webpackChunkwebpack"] || []); +chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0)); +chunkLoadingGlobal.push = webpackJsonpCallback.bind( + null, + chunkLoadingGlobal.push.bind(chunkLoadingGlobal) +); + +})(); + +})(); diff --git a/crates/rspack_plugin_javascript/tests/fixtures/new_url/inline/index.js b/crates/rspack_plugin_javascript/tests/fixtures/new_url/inline/index.js new file mode 100644 index 000000000000..a42b85eb6028 --- /dev/null +++ b/crates/rspack_plugin_javascript/tests/fixtures/new_url/inline/index.js @@ -0,0 +1,5 @@ +const imgSrc = new URL("./react.svg", import.meta.url); +const imgSrc2 = require("./vue.svg"); +const img = new Image(); +img.src = imgSrc.href; +img.src = imgSrc2; diff --git a/crates/rspack_plugin_javascript/tests/fixtures/new_url/inline/react.svg b/crates/rspack_plugin_javascript/tests/fixtures/new_url/inline/react.svg new file mode 100644 index 000000000000..9dfc1c058ceb --- /dev/null +++ b/crates/rspack_plugin_javascript/tests/fixtures/new_url/inline/react.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/crates/rspack_plugin_javascript/tests/fixtures/new_url/inline/test.config.json b/crates/rspack_plugin_javascript/tests/fixtures/new_url/inline/test.config.json new file mode 100644 index 000000000000..8f8c00452e38 --- /dev/null +++ b/crates/rspack_plugin_javascript/tests/fixtures/new_url/inline/test.config.json @@ -0,0 +1,13 @@ +{ + "module": { + "rules": [ + { + "test": { + "matcher": "\\.svg", + "type": "regexp" + }, + "type": "asset/inline" + } + ] + } +} \ No newline at end of file diff --git a/crates/rspack_plugin_javascript/tests/fixtures/new_url/inline/vue.svg b/crates/rspack_plugin_javascript/tests/fixtures/new_url/inline/vue.svg new file mode 100644 index 000000000000..770e9d333ee7 --- /dev/null +++ b/crates/rspack_plugin_javascript/tests/fixtures/new_url/inline/vue.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/crates/rspack_plugin_javascript/tests/fixtures/new_url/resource/expected/5d7c2bf56394b7b7.svg b/crates/rspack_plugin_javascript/tests/fixtures/new_url/resource/expected/5d7c2bf56394b7b7.svg new file mode 100644 index 000000000000..9dfc1c058ceb --- /dev/null +++ b/crates/rspack_plugin_javascript/tests/fixtures/new_url/resource/expected/5d7c2bf56394b7b7.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/crates/rspack_plugin_javascript/tests/fixtures/new_url/resource/expected/5f5ecd0973bd7725.svg b/crates/rspack_plugin_javascript/tests/fixtures/new_url/resource/expected/5f5ecd0973bd7725.svg new file mode 100644 index 000000000000..770e9d333ee7 --- /dev/null +++ b/crates/rspack_plugin_javascript/tests/fixtures/new_url/resource/expected/5f5ecd0973bd7725.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/crates/rspack_plugin_javascript/tests/fixtures/new_url/resource/expected/main.js b/crates/rspack_plugin_javascript/tests/fixtures/new_url/resource/expected/main.js new file mode 100644 index 000000000000..52da813df548 --- /dev/null +++ b/crates/rspack_plugin_javascript/tests/fixtures/new_url/resource/expected/main.js @@ -0,0 +1,20 @@ +(self['webpackChunkwebpack'] = self['webpackChunkwebpack'] || []).push([["main"], { +"./react.svg": function (module, exports, __webpack_require__) { +"use strict"; +module.exports = __webpack_require__.p + "5d7c2bf56394b7b7.svg";}, +"./vue.svg": function (module, exports, __webpack_require__) { +"use strict"; +module.exports = __webpack_require__.p + "5f5ecd0973bd7725.svg";}, +"./index.js": function (module, exports, __webpack_require__) { +const imgSrc = new URL(__webpack_require__("./react.svg"), self.location); +const imgSrc2 = __webpack_require__("./vue.svg"); +const img = new Image(); +img.src = imgSrc.href; +img.src = imgSrc2; +}, + +},function(__webpack_require__) { +var __webpack_exports__ = __webpack_require__('./index.js'); + +} +]); \ No newline at end of file diff --git a/crates/rspack_plugin_javascript/tests/fixtures/new_url/resource/expected/runtime.js b/crates/rspack_plugin_javascript/tests/fixtures/new_url/resource/expected/runtime.js new file mode 100644 index 000000000000..c6730cca4677 --- /dev/null +++ b/crates/rspack_plugin_javascript/tests/fixtures/new_url/resource/expected/runtime.js @@ -0,0 +1,122 @@ +(function() { +var __webpack_modules__ = { + +} +// The module cache + var __webpack_module_cache__ = {}; +function __webpack_require__(moduleId) { +// Check if module is in cache + var cachedModule = __webpack_module_cache__[moduleId]; + if (cachedModule !== undefined) { + return cachedModule.exports; + } + // Create a new module (and put it into the cache) + var module = (__webpack_module_cache__[moduleId] = { + // no module.loaded needed + exports: {} + }); + // Execute the module function + __webpack_modules__[moduleId](module, module.exports, __webpack_require__); +// Return the exports of the module + return module.exports; + +} +// expose the modules object (__webpack_modules__) + __webpack_require__.m = __webpack_modules__; +// webpack/runtime/on_chunk_loaded +(function() { +var deferred = []; +__webpack_require__.O = function (result, chunkIds, fn, priority) { + if (chunkIds) { + priority = priority || 0; + for (var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) + deferred[i] = deferred[i - 1]; + deferred[i] = [chunkIds, fn, priority]; + return; + } + var notFulfilled = Infinity; + for (var i = 0; i < deferred.length; i++) { + var [chunkIds, fn, priority] = deferred[i]; + var fulfilled = true; + for (var j = 0; j < chunkIds.length; j++) { + if ( + (priority & (1 === 0) || notFulfilled >= priority) && + Object.keys(__webpack_require__.O).every(function (key) { + __webpack_require__.O[key](chunkIds[j]); + }) + ) { + chunkIds.splice(j--, 1); + } else { + fulfilled = false; + if (priority < notFulfilled) notFulfilled = priority; + } + } + if (fulfilled) { + deferred.splice(i--, 1); + var r = fn(); + if (r !== undefined) result = r; + } + } + return result; +}; + +})(); +// webpack/runtime/has_own_property +(function() { +__webpack_require__.o = function (obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); +}; + +})(); +// webpack/runtime/public_path +(function() { +__webpack_require__.p = "/"; + +})(); +// webpack/runtime/jsonp_chunk_loading +(function() { +var installedChunks = {"runtime": 0,}; +__webpack_require__.O.j = function (chunkId) { + installedChunks[chunkId] === 0; +}; +// install a JSONP callback for chunk loading +var webpackJsonpCallback = function (parentChunkLoadingFunction, data) { + var [chunkIds, moreModules, runtime] = data; + // add "moreModules" to the modules object, + // then flag all "chunkIds" as loaded and fire callback + var moduleId, + chunkId, + i = 0; + if (chunkIds.some(id => installedChunks[id] !== 0)) { + for (moduleId in moreModules) { + if (__webpack_require__.o(moreModules, moduleId)) { + __webpack_require__.m[moduleId] = moreModules[moduleId]; + } + } + if (runtime) var result = runtime(__webpack_require__); + } + if (parentChunkLoadingFunction) parentChunkLoadingFunction(data); + for (; i < chunkIds.length; i++) { + chunkId = chunkIds[i]; + if ( + __webpack_require__.o(installedChunks, chunkId) && + installedChunks[chunkId] + ) { + installedChunks[chunkId][0](); + } + installedChunks[chunkId] = 0; + } + return __webpack_require__.O(result); +}; + +var chunkLoadingGlobal = (self["webpackChunkwebpack"] = + self["webpackChunkwebpack"] || []); +chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0)); +chunkLoadingGlobal.push = webpackJsonpCallback.bind( + null, + chunkLoadingGlobal.push.bind(chunkLoadingGlobal) +); + +})(); + +})(); diff --git a/crates/rspack_plugin_javascript/tests/fixtures/new_url/resource/index.js b/crates/rspack_plugin_javascript/tests/fixtures/new_url/resource/index.js new file mode 100644 index 000000000000..a42b85eb6028 --- /dev/null +++ b/crates/rspack_plugin_javascript/tests/fixtures/new_url/resource/index.js @@ -0,0 +1,5 @@ +const imgSrc = new URL("./react.svg", import.meta.url); +const imgSrc2 = require("./vue.svg"); +const img = new Image(); +img.src = imgSrc.href; +img.src = imgSrc2; diff --git a/crates/rspack_plugin_javascript/tests/fixtures/new_url/resource/react.svg b/crates/rspack_plugin_javascript/tests/fixtures/new_url/resource/react.svg new file mode 100644 index 000000000000..9dfc1c058ceb --- /dev/null +++ b/crates/rspack_plugin_javascript/tests/fixtures/new_url/resource/react.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/crates/rspack_plugin_javascript/tests/fixtures/new_url/resource/test.config.json b/crates/rspack_plugin_javascript/tests/fixtures/new_url/resource/test.config.json new file mode 100644 index 000000000000..51a270c6ad32 --- /dev/null +++ b/crates/rspack_plugin_javascript/tests/fixtures/new_url/resource/test.config.json @@ -0,0 +1,13 @@ +{ + "module": { + "rules": [ + { + "test": { + "matcher": "\\.svg", + "type": "regexp" + }, + "type": "asset/resource" + } + ] + } +} \ No newline at end of file diff --git a/crates/rspack_plugin_javascript/tests/fixtures/new_url/resource/vue.svg b/crates/rspack_plugin_javascript/tests/fixtures/new_url/resource/vue.svg new file mode 100644 index 000000000000..770e9d333ee7 --- /dev/null +++ b/crates/rspack_plugin_javascript/tests/fixtures/new_url/resource/vue.svg @@ -0,0 +1 @@ + \ No newline at end of file