From 0801a52621510c491791188291b83ced3b4c6bd3 Mon Sep 17 00:00:00 2001 From: CPunisher <1343316114@qq.com> Date: Mon, 23 Dec 2024 10:44:21 +0800 Subject: [PATCH 1/6] fix --- .../src/raw_options/raw_module/mod.rs | 11 +++ crates/rspack_core/src/options/module.rs | 68 +++++++++++++++---- crates/rspack_core/src/utils/module_rules.rs | 52 +++++++++++--- 3 files changed, 109 insertions(+), 22 deletions(-) diff --git a/crates/rspack_binding_values/src/raw_options/raw_module/mod.rs b/crates/rspack_binding_values/src/raw_options/raw_module/mod.rs index da924f94b08..ed6e2105b7b 100644 --- a/crates/rspack_binding_values/src/raw_options/raw_module/mod.rs +++ b/crates/rspack_binding_values/src/raw_options/raw_module/mod.rs @@ -138,6 +138,17 @@ impl TryFrom for rspack_core::RuleSetCondition { } } +impl TryFrom for rspack_core::RuleSetConditionMatch { + type Error = rspack_error::Error; + + fn try_from(x: RawRuleSetCondition) -> rspack_error::Result { + Ok(Self { + condition: x.try_into()?, + match_when_empty: None, + }) + } +} + type ThreadsafeUse = ThreadsafeFunction>; #[derive(Debug, Default)] diff --git a/crates/rspack_core/src/options/module.rs b/crates/rspack_core/src/options/module.rs index 9579dc6c5b1..5bf261cbd10 100644 --- a/crates/rspack_core/src/options/module.rs +++ b/crates/rspack_core/src/options/module.rs @@ -636,6 +636,32 @@ impl RuleSetCondition { Self::Func(f) => f(data).await, } } + + #[async_recursion] + pub async fn match_when_empty(&self) -> Result { + let res = match self { + RuleSetCondition::String(s) => s.len() == 0, + RuleSetCondition::Regexp(rspack_regex) => rspack_regex.test(""), + RuleSetCondition::Logical(logical) => logical.match_when_empty().await?, + RuleSetCondition::Array(arr) => { + arr.len() != 0 && try_any(arr, |c| async move { c.match_when_empty().await }).await? + } + RuleSetCondition::Func(func) => func("".into()).await?, + }; + Ok(res) + } +} + +#[derive(Debug)] +pub struct RuleSetConditionMatch { + pub condition: RuleSetCondition, + pub match_when_empty: Option, +} + +impl RuleSetConditionMatch { + pub async fn try_match(&self, data: DataRef<'_>) -> Result { + self.condition.try_match(data).await + } } #[derive(Debug, Default)] @@ -665,6 +691,24 @@ impl RuleSetLogicalConditions { } Ok(true) } + + pub async fn match_when_empty(&self) -> Result { + let mut has_condition = false; + let mut match_when_empty = true; + if let Some(and) = &self.and { + has_condition = true; + match_when_empty &= try_all(and, |i| async { i.match_when_empty().await }).await?; + } + if let Some(or) = &self.or { + has_condition = true; + match_when_empty &= try_any(or, |i| async { i.match_when_empty().await }).await?; + } + if let Some(not) = &self.not { + has_condition = true; + match_when_empty &= !not.match_when_empty().await?; + } + Ok(has_condition && match_when_empty) + } } pub struct FuncUseCtx { @@ -693,21 +737,21 @@ pub struct ModuleRule { /// Note: /// This is a custom matching rule not initially designed by webpack. /// Only for single-threaded environment interoperation purpose. - pub rspack_resource: Option, + pub rspack_resource: Option, /// A condition matcher matching an absolute path. - pub test: Option, - pub include: Option, - pub exclude: Option, + pub test: Option, + pub include: Option, + pub exclude: Option, /// A condition matcher matching an absolute path. - pub resource: Option, + pub resource: Option, /// A condition matcher against the resource query. - pub resource_query: Option, - pub resource_fragment: Option, - pub dependency: Option, - pub issuer: Option, - pub issuer_layer: Option, - pub scheme: Option, - pub mimetype: Option, + pub resource_query: Option, + pub resource_fragment: Option, + pub dependency: Option, + pub issuer: Option, + pub issuer_layer: Option, + pub scheme: Option, + pub mimetype: Option, pub description_data: Option, pub with: Option, pub one_of: Option>, diff --git a/crates/rspack_core/src/utils/module_rules.rs b/crates/rspack_core/src/utils/module_rules.rs index 5f3e15938fa..15c6afbbedf 100644 --- a/crates/rspack_core/src/utils/module_rules.rs +++ b/crates/rspack_core/src/utils/module_rules.rs @@ -87,7 +87,9 @@ pub async fn module_rule_matcher<'a>( return Ok(false); } } else { - return Ok(false); + if !resource_query_rule.condition.match_when_empty().await? { + return Ok(false); + } } } @@ -100,7 +102,13 @@ pub async fn module_rule_matcher<'a>( return Ok(false); } } else { - return Ok(false); + if !resource_fragment_condition + .condition + .match_when_empty() + .await? + { + return Ok(false); + } } } @@ -113,14 +121,18 @@ pub async fn module_rule_matcher<'a>( return Ok(false); } } else { - return Ok(false); + if !mimetype_condition.condition.match_when_empty().await? { + return Ok(false); + } } } if let Some(scheme_condition) = &module_rule.scheme { let scheme = resource_data.get_scheme(); if scheme.is_none() { - return Ok(false); + if !scheme_condition.condition.match_when_empty().await? { + return Ok(false); + } } if !scheme_condition.try_match(scheme.as_str().into()).await? { return Ok(false); @@ -134,7 +146,11 @@ pub async fn module_rule_matcher<'a>( return Ok(false); } } - None => return Ok(false), + None => { + if !issuer_rule.condition.match_when_empty().await? { + return Ok(false); + } + } } } @@ -145,7 +161,11 @@ pub async fn module_rule_matcher<'a>( return Ok(false); } } - None => return Ok(false), + None => { + if !issuer_layer_rule.condition.match_when_empty().await? { + return Ok(false); + } + } }; } @@ -168,11 +188,17 @@ pub async fn module_rule_matcher<'a>( return Ok(false); } } else { - return Ok(false); + if !matcher.match_when_empty().await? { + return Ok(false); + } } } } else { - return Ok(false); + for matcher in description_data.values() { + if !matcher.match_when_empty().await? { + return Ok(false); + } + } } } @@ -184,11 +210,17 @@ pub async fn module_rule_matcher<'a>( return Ok(false); } } else { - return Ok(false); + if !matcher.match_when_empty().await? { + return Ok(false); + } } } } else { - return Ok(false); + for matcher in with.values() { + if !matcher.match_when_empty().await? { + return Ok(false); + } + } } } From 968328368900e1e30b95479c81042e8ab8101ba1 Mon Sep 17 00:00:00 2001 From: CPunisher <1343316114@qq.com> Date: Mon, 23 Dec 2024 10:56:59 +0800 Subject: [PATCH 2/6] rwlock cache --- .../src/raw_options/raw_module/mod.rs | 5 +--- crates/rspack_core/src/options/module.rs | 28 +++++++++++++++++-- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/crates/rspack_binding_values/src/raw_options/raw_module/mod.rs b/crates/rspack_binding_values/src/raw_options/raw_module/mod.rs index ed6e2105b7b..92f2baea68f 100644 --- a/crates/rspack_binding_values/src/raw_options/raw_module/mod.rs +++ b/crates/rspack_binding_values/src/raw_options/raw_module/mod.rs @@ -142,10 +142,7 @@ impl TryFrom for rspack_core::RuleSetConditionMatch { type Error = rspack_error::Error; fn try_from(x: RawRuleSetCondition) -> rspack_error::Result { - Ok(Self { - condition: x.try_into()?, - match_when_empty: None, - }) + Ok(Self::new(x.try_into()?)) } } diff --git a/crates/rspack_core/src/options/module.rs b/crates/rspack_core/src/options/module.rs index 5bf261cbd10..584cd2034ad 100644 --- a/crates/rspack_core/src/options/module.rs +++ b/crates/rspack_core/src/options/module.rs @@ -12,6 +12,7 @@ use rspack_macros::MergeFrom; use rspack_regex::RspackRegex; use rspack_util::{try_all, try_any, MergeFrom}; use rustc_hash::FxHashMap as HashMap; +use tokio::sync::RwLock; use crate::{Compilation, Filename, Module, ModuleType, PublicPath, Resolve}; @@ -560,8 +561,8 @@ impl Default for CssExportsConvention { } } -pub type DescriptionData = HashMap; -pub type With = HashMap; +pub type DescriptionData = HashMap; +pub type With = HashMap; pub type RuleSetConditionFnMatcher = Box BoxFuture<'static, Result> + Sync + Send>; @@ -655,13 +656,34 @@ impl RuleSetCondition { #[derive(Debug)] pub struct RuleSetConditionMatch { pub condition: RuleSetCondition, - pub match_when_empty: Option, + match_when_empty: RwLock>, } impl RuleSetConditionMatch { + pub fn new(condition: RuleSetCondition) -> Self { + Self { + condition, + match_when_empty: RwLock::new(None), + } + } + pub async fn try_match(&self, data: DataRef<'_>) -> Result { self.condition.try_match(data).await } + + pub async fn match_when_empty(&self) -> Result { + if let Some(match_when_empty) = self.match_when_empty.read().await.as_ref() { + return Ok(*match_when_empty); + } + + Ok( + *self + .match_when_empty + .write() + .await + .insert(self.condition.match_when_empty().await?), + ) + } } #[derive(Debug, Default)] From 2edb453a55ef6e9e7eedfa1da374d02194cc4c09 Mon Sep 17 00:00:00 2001 From: CPunisher <1343316114@qq.com> Date: Mon, 23 Dec 2024 11:10:50 +0800 Subject: [PATCH 3/6] add test --- .../configCases/loader/match-when-empty/a.js | 1 + .../loader/match-when-empty/index.js | 7 +++++ .../loader/match-when-empty/loader.js | 3 +++ .../loader/match-when-empty/rspack.config.js | 26 +++++++++++++++++++ 4 files changed, 37 insertions(+) create mode 100644 packages/rspack-test-tools/tests/configCases/loader/match-when-empty/a.js create mode 100644 packages/rspack-test-tools/tests/configCases/loader/match-when-empty/index.js create mode 100644 packages/rspack-test-tools/tests/configCases/loader/match-when-empty/loader.js create mode 100644 packages/rspack-test-tools/tests/configCases/loader/match-when-empty/rspack.config.js diff --git a/packages/rspack-test-tools/tests/configCases/loader/match-when-empty/a.js b/packages/rspack-test-tools/tests/configCases/loader/match-when-empty/a.js new file mode 100644 index 00000000000..f31c910d79c --- /dev/null +++ b/packages/rspack-test-tools/tests/configCases/loader/match-when-empty/a.js @@ -0,0 +1 @@ +export default "a.js" \ No newline at end of file diff --git a/packages/rspack-test-tools/tests/configCases/loader/match-when-empty/index.js b/packages/rspack-test-tools/tests/configCases/loader/match-when-empty/index.js new file mode 100644 index 00000000000..a7ced44acc5 --- /dev/null +++ b/packages/rspack-test-tools/tests/configCases/loader/match-when-empty/index.js @@ -0,0 +1,7 @@ +import a1 from "./a.js" with { type: "raw" }; +import a2 from "./a.js"; + +it("should hit loader", () => { + expect(a1).toEqual("export default \"a.js\""); + expect(a2).toEqual("loader.js"); +}); \ No newline at end of file diff --git a/packages/rspack-test-tools/tests/configCases/loader/match-when-empty/loader.js b/packages/rspack-test-tools/tests/configCases/loader/match-when-empty/loader.js new file mode 100644 index 00000000000..290ed756509 --- /dev/null +++ b/packages/rspack-test-tools/tests/configCases/loader/match-when-empty/loader.js @@ -0,0 +1,3 @@ +module.exports = function (content) { + return "export default 'loader.js'"; +}; diff --git a/packages/rspack-test-tools/tests/configCases/loader/match-when-empty/rspack.config.js b/packages/rspack-test-tools/tests/configCases/loader/match-when-empty/rspack.config.js new file mode 100644 index 00000000000..c76cdcb7d9e --- /dev/null +++ b/packages/rspack-test-tools/tests/configCases/loader/match-when-empty/rspack.config.js @@ -0,0 +1,26 @@ +module.exports = { + mode: "development", + entry: "./index.js", + devtool: false, + module: { + rules: [ + { + test: /a\.js/, + with: { + type: { + not: "raw" + } + }, + use: [ + { + loader: "./loader.js", + } + ] + }, + { + with: { type: "raw" }, + type: "asset/source" + } + ] + } +}; From 954be0cc0eb045c795b0c0e0e48af579848169ab Mon Sep 17 00:00:00 2001 From: CPunisher <1343316114@qq.com> Date: Mon, 23 Dec 2024 11:19:09 +0800 Subject: [PATCH 4/6] remove unnecessary --- crates/rspack_core/src/options/module.rs | 16 ++++++++-------- crates/rspack_core/src/utils/module_rules.rs | 16 ++++++---------- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/crates/rspack_core/src/options/module.rs b/crates/rspack_core/src/options/module.rs index 584cd2034ad..f49e9e064ef 100644 --- a/crates/rspack_core/src/options/module.rs +++ b/crates/rspack_core/src/options/module.rs @@ -639,7 +639,7 @@ impl RuleSetCondition { } #[async_recursion] - pub async fn match_when_empty(&self) -> Result { + async fn match_when_empty(&self) -> Result { let res = match self { RuleSetCondition::String(s) => s.len() == 0, RuleSetCondition::Regexp(rspack_regex) => rspack_regex.test(""), @@ -655,7 +655,7 @@ impl RuleSetCondition { #[derive(Debug)] pub struct RuleSetConditionMatch { - pub condition: RuleSetCondition, + condition: RuleSetCondition, match_when_empty: RwLock>, } @@ -759,17 +759,17 @@ pub struct ModuleRule { /// Note: /// This is a custom matching rule not initially designed by webpack. /// Only for single-threaded environment interoperation purpose. - pub rspack_resource: Option, + pub rspack_resource: Option, /// A condition matcher matching an absolute path. - pub test: Option, - pub include: Option, - pub exclude: Option, + pub test: Option, + pub include: Option, + pub exclude: Option, /// A condition matcher matching an absolute path. - pub resource: Option, + pub resource: Option, /// A condition matcher against the resource query. pub resource_query: Option, pub resource_fragment: Option, - pub dependency: Option, + pub dependency: Option, pub issuer: Option, pub issuer_layer: Option, pub scheme: Option, diff --git a/crates/rspack_core/src/utils/module_rules.rs b/crates/rspack_core/src/utils/module_rules.rs index 15c6afbbedf..a35e6dc5e41 100644 --- a/crates/rspack_core/src/utils/module_rules.rs +++ b/crates/rspack_core/src/utils/module_rules.rs @@ -87,7 +87,7 @@ pub async fn module_rule_matcher<'a>( return Ok(false); } } else { - if !resource_query_rule.condition.match_when_empty().await? { + if !resource_query_rule.match_when_empty().await? { return Ok(false); } } @@ -102,11 +102,7 @@ pub async fn module_rule_matcher<'a>( return Ok(false); } } else { - if !resource_fragment_condition - .condition - .match_when_empty() - .await? - { + if !resource_fragment_condition.match_when_empty().await? { return Ok(false); } } @@ -121,7 +117,7 @@ pub async fn module_rule_matcher<'a>( return Ok(false); } } else { - if !mimetype_condition.condition.match_when_empty().await? { + if !mimetype_condition.match_when_empty().await? { return Ok(false); } } @@ -130,7 +126,7 @@ pub async fn module_rule_matcher<'a>( if let Some(scheme_condition) = &module_rule.scheme { let scheme = resource_data.get_scheme(); if scheme.is_none() { - if !scheme_condition.condition.match_when_empty().await? { + if !scheme_condition.match_when_empty().await? { return Ok(false); } } @@ -147,7 +143,7 @@ pub async fn module_rule_matcher<'a>( } } None => { - if !issuer_rule.condition.match_when_empty().await? { + if !issuer_rule.match_when_empty().await? { return Ok(false); } } @@ -162,7 +158,7 @@ pub async fn module_rule_matcher<'a>( } } None => { - if !issuer_layer_rule.condition.match_when_empty().await? { + if !issuer_layer_rule.match_when_empty().await? { return Ok(false); } } From 555133763f75e032a85f68287339fe57522cd55e Mon Sep 17 00:00:00 2001 From: CPunisher <1343316114@qq.com> Date: Mon, 23 Dec 2024 11:42:21 +0800 Subject: [PATCH 5/6] clippy --- crates/rspack_core/src/options/module.rs | 4 +-- crates/rspack_core/src/utils/module_rules.rs | 36 +++++++------------- 2 files changed, 14 insertions(+), 26 deletions(-) diff --git a/crates/rspack_core/src/options/module.rs b/crates/rspack_core/src/options/module.rs index f49e9e064ef..f5919f23457 100644 --- a/crates/rspack_core/src/options/module.rs +++ b/crates/rspack_core/src/options/module.rs @@ -641,11 +641,11 @@ impl RuleSetCondition { #[async_recursion] async fn match_when_empty(&self) -> Result { let res = match self { - RuleSetCondition::String(s) => s.len() == 0, + RuleSetCondition::String(s) => s.is_empty(), RuleSetCondition::Regexp(rspack_regex) => rspack_regex.test(""), RuleSetCondition::Logical(logical) => logical.match_when_empty().await?, RuleSetCondition::Array(arr) => { - arr.len() != 0 && try_any(arr, |c| async move { c.match_when_empty().await }).await? + arr.is_empty() && try_any(arr, |c| async move { c.match_when_empty().await }).await? } RuleSetCondition::Func(func) => func("".into()).await?, }; diff --git a/crates/rspack_core/src/utils/module_rules.rs b/crates/rspack_core/src/utils/module_rules.rs index a35e6dc5e41..02b3beac3d1 100644 --- a/crates/rspack_core/src/utils/module_rules.rs +++ b/crates/rspack_core/src/utils/module_rules.rs @@ -86,10 +86,8 @@ pub async fn module_rule_matcher<'a>( { return Ok(false); } - } else { - if !resource_query_rule.match_when_empty().await? { - return Ok(false); - } + } else if !resource_query_rule.match_when_empty().await? { + return Ok(false); } } @@ -101,10 +99,8 @@ pub async fn module_rule_matcher<'a>( { return Ok(false); } - } else { - if !resource_fragment_condition.match_when_empty().await? { - return Ok(false); - } + } else if !resource_fragment_condition.match_when_empty().await? { + return Ok(false); } } @@ -116,19 +112,15 @@ pub async fn module_rule_matcher<'a>( { return Ok(false); } - } else { - if !mimetype_condition.match_when_empty().await? { - return Ok(false); - } + } else if !mimetype_condition.match_when_empty().await? { + return Ok(false); } } if let Some(scheme_condition) = &module_rule.scheme { let scheme = resource_data.get_scheme(); - if scheme.is_none() { - if !scheme_condition.match_when_empty().await? { - return Ok(false); - } + if scheme.is_none() && !scheme_condition.match_when_empty().await? { + return Ok(false); } if !scheme_condition.try_match(scheme.as_str().into()).await? { return Ok(false); @@ -183,10 +175,8 @@ pub async fn module_rule_matcher<'a>( if !matcher.try_match(v.into()).await? { return Ok(false); } - } else { - if !matcher.match_when_empty().await? { - return Ok(false); - } + } else if !matcher.match_when_empty().await? { + return Ok(false); } } } else { @@ -205,10 +195,8 @@ pub async fn module_rule_matcher<'a>( if !matcher.try_match(v.into()).await? { return Ok(false); } - } else { - if !matcher.match_when_empty().await? { - return Ok(false); - } + } else if !matcher.match_when_empty().await? { + return Ok(false); } } } else { From 8c26740bdc3aef068e8c3005bbd0fda64f2a66b0 Mon Sep 17 00:00:00 2001 From: CPunisher <1343316114@qq.com> Date: Mon, 23 Dec 2024 14:14:47 +0800 Subject: [PATCH 6/6] fix --- .../src/raw_options/raw_module/mod.rs | 2 +- crates/rspack_core/src/options/module.rs | 42 ++++++++----------- 2 files changed, 19 insertions(+), 25 deletions(-) diff --git a/crates/rspack_binding_values/src/raw_options/raw_module/mod.rs b/crates/rspack_binding_values/src/raw_options/raw_module/mod.rs index 92f2baea68f..bd9d0e46a95 100644 --- a/crates/rspack_binding_values/src/raw_options/raw_module/mod.rs +++ b/crates/rspack_binding_values/src/raw_options/raw_module/mod.rs @@ -138,7 +138,7 @@ impl TryFrom for rspack_core::RuleSetCondition { } } -impl TryFrom for rspack_core::RuleSetConditionMatch { +impl TryFrom for rspack_core::RuleSetConditionWithEmpty { type Error = rspack_error::Error; fn try_from(x: RawRuleSetCondition) -> rspack_error::Result { diff --git a/crates/rspack_core/src/options/module.rs b/crates/rspack_core/src/options/module.rs index f5919f23457..9ff79097201 100644 --- a/crates/rspack_core/src/options/module.rs +++ b/crates/rspack_core/src/options/module.rs @@ -12,7 +12,7 @@ use rspack_macros::MergeFrom; use rspack_regex::RspackRegex; use rspack_util::{try_all, try_any, MergeFrom}; use rustc_hash::FxHashMap as HashMap; -use tokio::sync::RwLock; +use tokio::sync::OnceCell; use crate::{Compilation, Filename, Module, ModuleType, PublicPath, Resolve}; @@ -561,8 +561,8 @@ impl Default for CssExportsConvention { } } -pub type DescriptionData = HashMap; -pub type With = HashMap; +pub type DescriptionData = HashMap; +pub type With = HashMap; pub type RuleSetConditionFnMatcher = Box BoxFuture<'static, Result> + Sync + Send>; @@ -654,16 +654,16 @@ impl RuleSetCondition { } #[derive(Debug)] -pub struct RuleSetConditionMatch { +pub struct RuleSetConditionWithEmpty { condition: RuleSetCondition, - match_when_empty: RwLock>, + match_when_empty: OnceCell, } -impl RuleSetConditionMatch { +impl RuleSetConditionWithEmpty { pub fn new(condition: RuleSetCondition) -> Self { Self { condition, - match_when_empty: RwLock::new(None), + match_when_empty: OnceCell::new(), } } @@ -672,17 +672,11 @@ impl RuleSetConditionMatch { } pub async fn match_when_empty(&self) -> Result { - if let Some(match_when_empty) = self.match_when_empty.read().await.as_ref() { - return Ok(*match_when_empty); - } - - Ok( - *self - .match_when_empty - .write() - .await - .insert(self.condition.match_when_empty().await?), - ) + self + .match_when_empty + .get_or_try_init(|| async { self.condition.match_when_empty().await }) + .await + .copied() } } @@ -767,13 +761,13 @@ pub struct ModuleRule { /// A condition matcher matching an absolute path. pub resource: Option, /// A condition matcher against the resource query. - pub resource_query: Option, - pub resource_fragment: Option, + pub resource_query: Option, + pub resource_fragment: Option, pub dependency: Option, - pub issuer: Option, - pub issuer_layer: Option, - pub scheme: Option, - pub mimetype: Option, + pub issuer: Option, + pub issuer_layer: Option, + pub scheme: Option, + pub mimetype: Option, pub description_data: Option, pub with: Option, pub one_of: Option>,