Skip to content

Commit

Permalink
fix: change javascript parser options in child compiler (#7812)
Browse files Browse the repository at this point in the history
  • Loading branch information
ahabhgk authored Sep 9, 2024
1 parent 0075187 commit 500c045
Show file tree
Hide file tree
Showing 12 changed files with 215 additions and 209 deletions.
52 changes: 35 additions & 17 deletions crates/rspack_binding_options/src/options/raw_module/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ use rspack_core::{
AssetParserDataUrlOptions, AssetParserOptions, AssetResourceGeneratorOptions,
CssAutoGeneratorOptions, CssAutoParserOptions, CssGeneratorOptions, CssModuleGeneratorOptions,
CssModuleParserOptions, CssParserOptions, DescriptionData, DynamicImportFetchPriority,
DynamicImportMode, ExportPresenceMode, FuncUseCtx, GeneratorOptions,
GeneratorOptionsByModuleType, JavascriptParserOptions, JavascriptParserOrder,
JavascriptParserUrl, ModuleNoParseRule, ModuleNoParseRules, ModuleNoParseTestFn, ModuleOptions,
ModuleRule, ModuleRuleEffect, ModuleRuleEnforce, ModuleRuleUse, ModuleRuleUseLoader, ModuleType,
OverrideStrict, ParserOptions, ParserOptionsByModuleType,
DynamicImportMode, ExportPresenceMode, FuncUseCtx, GeneratorOptions, GeneratorOptionsMap,
JavascriptParserOptions, JavascriptParserOrder, JavascriptParserUrl, ModuleNoParseRule,
ModuleNoParseRules, ModuleNoParseTestFn, ModuleOptions, ModuleRule, ModuleRuleEffect,
ModuleRuleEnforce, ModuleRuleUse, ModuleRuleUseLoader, OverrideStrict, ParserOptions,
ParserOptionsMap,
};
use rspack_error::error;
use rspack_napi::regexp::{JsRegExp, JsRegExpExt};
Expand Down Expand Up @@ -203,14 +203,32 @@ impl From<RawParserOptions> for ParserOptions {
.expect("should have an \"asset\" when RawParserOptions.type is \"asset\"")
.into(),
),
"javascript" | "javascript/auto" | "javascript/dynamic" | "javascript/esm" => {
Self::Javascript(
value
.javascript
.expect("should have an \"javascript\" when RawParserOptions.type is \"javascript\"")
.into(),
)
}
"javascript" => Self::Javascript(
value
.javascript
.expect("should have an \"javascript\" when RawParserOptions.type is \"javascript\"")
.into(),
),
"javascript/auto" => Self::JavascriptAuto(
value
.javascript
.expect("should have an \"javascript\" when RawParserOptions.type is \"javascript/auto\"")
.into(),
),
"javascript/dynamic" => Self::JavascriptDynamic(
value
.javascript
.expect(
"should have an \"javascript\" when RawParserOptions.type is \"javascript/dynamic\"",
)
.into(),
),
"javascript/esm" => Self::JavascriptEsm(
value
.javascript
.expect("should have an \"javascript\" when RawParserOptions.type is \"javascript/esm\"")
.into(),
),
"css" => Self::Css(
value
.css
Expand Down Expand Up @@ -805,16 +823,16 @@ impl TryFrom<RawModuleOptions> for ModuleOptions {
.parser
.map(|x| {
x.into_iter()
.map(|(k, v)| Ok((ModuleType::from(k.as_str()), v.into())))
.collect::<std::result::Result<ParserOptionsByModuleType, rspack_error::Error>>()
.map(|(k, v)| Ok((k, v.into())))
.collect::<std::result::Result<ParserOptionsMap, rspack_error::Error>>()
})
.transpose()?,
generator: value
.generator
.map(|x| {
x.into_iter()
.map(|(k, v)| Ok((ModuleType::from(k.as_str()), v.into())))
.collect::<std::result::Result<GeneratorOptionsByModuleType, rspack_error::Error>>()
.map(|(k, v)| Ok((k, v.into())))
.collect::<std::result::Result<GeneratorOptionsMap, rspack_error::Error>>()
})
.transpose()?,
no_parse: value
Expand Down
49 changes: 38 additions & 11 deletions crates/rspack_core/src/normal_module_factory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -691,25 +691,52 @@ impl NormalModuleFactory {
.module
.parser
.as_ref()
.and_then(|p| p.get(module_type))
.cloned();
.and_then(|p| match module_type {
ModuleType::JsAuto | ModuleType::JsDynamic | ModuleType::JsEsm => {
let options = p.get(module_type.as_str());
let javascript_options = p.get("javascript").cloned();
// Merge `module.parser.["javascript/xxx"]` with `module.parser.["javascript"]` first
rspack_util::merge_from_optional_with(
javascript_options,
options,
|javascript_options, options| match (javascript_options, options) {
(
ParserOptions::Javascript(a),
ParserOptions::JavascriptAuto(b)
| ParserOptions::JavascriptDynamic(b)
| ParserOptions::JavascriptEsm(b),
) => ParserOptions::Javascript(a.merge_from(b)),
_ => unreachable!(),
},
)
}
_ => p.get(module_type.as_str()).cloned(),
});
let global_generator = self
.options
.module
.generator
.as_ref()
.and_then(|g| g.get(module_type))
.cloned();
.and_then(|g| g.get(module_type.as_str()).cloned());
let parser = rspack_util::merge_from_optional_with(
global_parser,
parser.as_ref(),
|global, local| match (&global, local) {
(ParserOptions::Asset(_), ParserOptions::Asset(_))
| (ParserOptions::Css(_), ParserOptions::Css(_))
| (ParserOptions::CssAuto(_), ParserOptions::CssAuto(_))
| (ParserOptions::CssModule(_), ParserOptions::CssModule(_))
| (ParserOptions::Javascript(_), ParserOptions::Javascript(_)) => global.merge_from(local),
_ => global,
|global, local| match (global, local) {
(ParserOptions::Asset(a), ParserOptions::Asset(b)) => ParserOptions::Asset(a.merge_from(b)),
(ParserOptions::Css(a), ParserOptions::Css(b)) => ParserOptions::Css(a.merge_from(b)),
(ParserOptions::CssAuto(a), ParserOptions::CssAuto(b)) => {
ParserOptions::CssAuto(a.merge_from(b))
}
(ParserOptions::CssModule(a), ParserOptions::CssModule(b)) => {
ParserOptions::CssModule(a.merge_from(b))
}
(
ParserOptions::Javascript(a),
ParserOptions::JavascriptAuto(b)
| ParserOptions::JavascriptDynamic(b)
| ParserOptions::JavascriptEsm(b),
) => ParserOptions::Javascript(a.merge_from(b)),
(global, _) => global,
},
);
let generator = rspack_util::merge_from_optional_with(
Expand Down
38 changes: 24 additions & 14 deletions crates/rspack_core/src/options/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,17 @@ use rustc_hash::FxHashMap as HashMap;
use crate::{Filename, Module, ModuleType, PublicPath, Resolve};

#[derive(Debug)]
pub struct ParserOptionsByModuleType(HashMap<ModuleType, ParserOptions>);
pub struct ParserOptionsMap(HashMap<String, ParserOptions>);

impl FromIterator<(ModuleType, ParserOptions)> for ParserOptionsByModuleType {
fn from_iter<I: IntoIterator<Item = (ModuleType, ParserOptions)>>(i: I) -> Self {
impl FromIterator<(String, ParserOptions)> for ParserOptionsMap {
fn from_iter<I: IntoIterator<Item = (String, ParserOptions)>>(i: I) -> Self {
Self(HashMap::from_iter(i))
}
}

impl ParserOptionsByModuleType {
pub fn get<'a>(&'a self, module_type: &'a ModuleType) -> Option<&'a ParserOptions> {
self.0.get(module_type)
impl ParserOptionsMap {
pub fn get<'a>(&'a self, key: &'a str) -> Option<&'a ParserOptions> {
self.0.get(key)
}
}

Expand All @@ -37,6 +37,9 @@ pub enum ParserOptions {
CssAuto(CssAutoParserOptions),
CssModule(CssModuleParserOptions),
Javascript(JavascriptParserOptions),
JavascriptAuto(JavascriptParserOptions),
JavascriptEsm(JavascriptParserOptions),
JavascriptDynamic(JavascriptParserOptions),
Unknown,
}

Expand All @@ -57,6 +60,13 @@ impl ParserOptions {
get_variant!(get_css_auto, CssAuto, CssAutoParserOptions);
get_variant!(get_css_module, CssModule, CssModuleParserOptions);
get_variant!(get_javascript, Javascript, JavascriptParserOptions);
get_variant!(get_javascript_auto, JavascriptAuto, JavascriptParserOptions);
get_variant!(get_javascript_esm, JavascriptEsm, JavascriptParserOptions);
get_variant!(
get_javascript_dynamic,
JavascriptDynamic,
JavascriptParserOptions
);
}

#[derive(Debug, Clone, Copy, MergeFrom)]
Expand Down Expand Up @@ -259,17 +269,17 @@ pub struct CssModuleParserOptions {
}

#[derive(Debug)]
pub struct GeneratorOptionsByModuleType(HashMap<ModuleType, GeneratorOptions>);
pub struct GeneratorOptionsMap(HashMap<String, GeneratorOptions>);

impl FromIterator<(ModuleType, GeneratorOptions)> for GeneratorOptionsByModuleType {
fn from_iter<I: IntoIterator<Item = (ModuleType, GeneratorOptions)>>(i: I) -> Self {
impl FromIterator<(String, GeneratorOptions)> for GeneratorOptionsMap {
fn from_iter<I: IntoIterator<Item = (String, GeneratorOptions)>>(i: I) -> Self {
Self(HashMap::from_iter(i))
}
}

impl GeneratorOptionsByModuleType {
pub fn get(&self, module_type: &ModuleType) -> Option<&GeneratorOptions> {
self.0.get(module_type)
impl GeneratorOptionsMap {
pub fn get(&self, key: &str) -> Option<&GeneratorOptions> {
self.0.get(key)
}
}

Expand Down Expand Up @@ -758,7 +768,7 @@ pub enum ModuleRuleEnforce {
#[derive(Debug, Default)]
pub struct ModuleOptions {
pub rules: Vec<ModuleRule>,
pub parser: Option<ParserOptionsByModuleType>,
pub generator: Option<GeneratorOptionsByModuleType>,
pub parser: Option<ParserOptionsMap>,
pub generator: Option<GeneratorOptionsMap>,
pub no_parse: Option<ModuleNoParseRules>,
}
74 changes: 45 additions & 29 deletions crates/rspack_plugin_javascript/src/parser_plugin/worker_plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,12 @@ static WORKER_FROM_REGEX: LazyLock<Regex> =
LazyLock::new(|| Regex::new(r"^(.+?)(\(\))?\s+from\s+(.+)$").expect("invalid regex"));

const WORKER_SPECIFIER_TAG: &str = "_identifier__worker_specifier_tag__";
const DEFAULT_SYNTAX: [&str; 4] = [
"Worker",
"SharedWorker",
"navigator.serviceWorker.register()",
"Worker from worker_threads",
];

#[derive(Debug, Clone)]
struct WorkerSpecifierData {
Expand All @@ -214,41 +220,51 @@ impl WorkerPlugin {
pattern_syntax: FxHashMap::default(),
};
for syntax in syntax_list {
if let Some(syntax) = syntax.strip_prefix('*')
&& let Some(first_dot) = syntax.find('.')
&& let Some(syntax) = syntax.strip_suffix("()")
{
let pattern = &syntax[0..first_dot];
let members = &syntax[first_dot + 1..];
if let Some(value) = this.pattern_syntax.get_mut(pattern) {
value.insert(members.to_string());
} else {
this.pattern_syntax.insert(
pattern.to_string(),
FxHashSet::from_iter([members.to_string()]),
);
}
} else if let Some(syntax) = syntax.strip_suffix("()") {
this.call_syntax.insert(syntax.to_string());
} else if let Some(captures) = WORKER_FROM_REGEX.captures(syntax) {
let ids = &captures[1];
let is_call = &captures.get(2).is_some();
let source = &captures[3];
if *is_call {
this
.from_call_syntax
.insert((ids.to_string(), source.to_string()));
} else {
this
.from_new_syntax
.insert((ids.to_string(), source.to_string()));
if syntax == "..." {
for syntax in DEFAULT_SYNTAX {
this.handle_syntax(syntax);
}
} else {
this.new_syntax.insert(syntax.to_string());
this.handle_syntax(syntax);
}
}
this
}

fn handle_syntax(&mut self, syntax: &str) {
if let Some(syntax) = syntax.strip_prefix('*')
&& let Some(first_dot) = syntax.find('.')
&& let Some(syntax) = syntax.strip_suffix("()")
{
let pattern = &syntax[0..first_dot];
let members = &syntax[first_dot + 1..];
if let Some(value) = self.pattern_syntax.get_mut(pattern) {
value.insert(members.to_string());
} else {
self.pattern_syntax.insert(
pattern.to_string(),
FxHashSet::from_iter([members.to_string()]),
);
}
} else if let Some(syntax) = syntax.strip_suffix("()") {
self.call_syntax.insert(syntax.to_string());
} else if let Some(captures) = WORKER_FROM_REGEX.captures(syntax) {
let ids = &captures[1];
let is_call = &captures.get(2).is_some();
let source = &captures[3];
if *is_call {
self
.from_call_syntax
.insert((ids.to_string(), source.to_string()));
} else {
self
.from_new_syntax
.insert((ids.to_string(), source.to_string()));
}
} else {
self.new_syntax.insert(syntax.to_string());
}
}
}

impl JavascriptParserPlugin for WorkerPlugin {
Expand Down
15 changes: 11 additions & 4 deletions crates/rspack_util/src/merge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,17 @@ impl<T: MergeFrom> MergeFrom for Option<T> {
}
}

impl<T: MergeFrom> MergeFrom for Vec<T> {
fn merge_from(mut self, other: &Self) -> Self {
self.extend(other.iter().cloned());
self
impl MergeFrom for Vec<String> {
fn merge_from(self, other: &Self) -> Self {
let mut res = Vec::new();
for item in other {
if item == "..." {
res.extend(self.clone());
} else {
res.push(item.clone());
}
}
res
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,57 +174,6 @@ Object {
],
"wrappedContextCritical": false,
},
"javascript/auto": Object {
"dynamicImportMode": "lazy",
"dynamicImportPrefetch": false,
"dynamicImportPreload": false,
"exportsPresence": undefined,
"exprContextCritical": true,
"importExportsPresence": undefined,
"importMeta": true,
"overrideStrict": undefined,
"reexportExportsPresence": undefined,
"strictExportPresence": false,
"url": true,
"worker": Array [
"...",
],
"wrappedContextCritical": false,
},
"javascript/dynamic": Object {
"dynamicImportMode": "lazy",
"dynamicImportPrefetch": false,
"dynamicImportPreload": false,
"exportsPresence": undefined,
"exprContextCritical": true,
"importExportsPresence": undefined,
"importMeta": true,
"overrideStrict": undefined,
"reexportExportsPresence": undefined,
"strictExportPresence": false,
"url": true,
"worker": Array [
"...",
],
"wrappedContextCritical": false,
},
"javascript/esm": Object {
"dynamicImportMode": "lazy",
"dynamicImportPrefetch": false,
"dynamicImportPreload": false,
"exportsPresence": undefined,
"exprContextCritical": true,
"importExportsPresence": undefined,
"importMeta": true,
"overrideStrict": undefined,
"reexportExportsPresence": undefined,
"strictExportPresence": false,
"url": true,
"worker": Array [
"...",
],
"wrappedContextCritical": false,
},
},
"rules": Array [],
},
Expand Down
Loading

2 comments on commit 500c045

@rspack-bot
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Benchmark detail: Open

Name Base (2024-09-09 cec9cff) Current Change
10000_development-mode + exec 2.22 s ± 26 ms 2.23 s ± 25 ms +0.46 %
10000_development-mode_hmr + exec 684 ms ± 7.5 ms 694 ms ± 11 ms +1.37 %
10000_production-mode + exec 2.84 s ± 32 ms 2.86 s ± 54 ms +0.88 %
arco-pro_development-mode + exec 1.88 s ± 53 ms 1.84 s ± 79 ms -2.08 %
arco-pro_development-mode_hmr + exec 435 ms ± 2.4 ms 436 ms ± 4.3 ms +0.07 %
arco-pro_production-mode + exec 3.25 s ± 57 ms 3.28 s ± 70 ms +0.88 %
arco-pro_production-mode_generate-package-json-webpack-plugin + exec 3.32 s ± 71 ms 3.29 s ± 65 ms -0.94 %
threejs_development-mode_10x + exec 1.66 s ± 23 ms 1.69 s ± 16 ms +1.29 %
threejs_development-mode_10x_hmr + exec 811 ms ± 4.2 ms 814 ms ± 11 ms +0.37 %
threejs_production-mode_10x + exec 5.17 s ± 26 ms 5.19 s ± 42 ms +0.34 %

@rspack-bot
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Ran ecosystem CI: Open

suite result
modernjs ✅ success
_selftest ✅ success
nx ❌ failure
rspress ✅ success
rslib ✅ success
rsbuild ✅ success
examples ❌ failure

Please sign in to comment.