From cec9cff3161f00bdb20b9a6cd08c8c0cad3ec049 Mon Sep 17 00:00:00 2001 From: Cong-Cong Pan Date: Fri, 6 Sep 2024 17:43:45 +0800 Subject: [PATCH 1/4] docs: fix typo in zh docs (#7820) fix: typo in docs --- website/docs/zh/api/javascript-api/index.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/website/docs/zh/api/javascript-api/index.mdx b/website/docs/zh/api/javascript-api/index.mdx index 7ae40be01da..9d2a1c951bb 100644 --- a/website/docs/zh/api/javascript-api/index.mdx +++ b/website/docs/zh/api/javascript-api/index.mdx @@ -121,13 +121,13 @@ const compiler = rspack({ const watching = compiler.watch( { // 示例 - aggregateTimeout: 300, - poll: undefined, + aggregateTimeout: 300, + poll: undefined, }, (err, stats) => { // 这里打印 watch/build 结果... console.log(stats); - } + }, ); ``` From aca19d4fe9541e95d6242b835ca4973b645cebcd Mon Sep 17 00:00:00 2001 From: hardfist Date: Mon, 9 Sep 2024 17:02:54 +0800 Subject: [PATCH 2/4] refactor(core): use `output_filesystem` with dynamic dispatch (#7817) * feat(chore): use dyn output_filesystem * fix: remove debug constraint * fix: remove debug --- crates/node_binding/src/compiler.rs | 4 +--- crates/node_binding/src/lib.rs | 6 ++++-- crates/rspack_core/src/compiler/hmr.rs | 6 +----- crates/rspack_core/src/compiler/mod.rs | 20 ++++++++------------ packages/rspack-cli/jest.config.js | 21 +++++++++------------ 5 files changed, 23 insertions(+), 34 deletions(-) diff --git a/crates/node_binding/src/compiler.rs b/crates/node_binding/src/compiler.rs index 2f7a8f71f14..d49f54c95b0 100644 --- a/crates/node_binding/src/compiler.rs +++ b/crates/node_binding/src/compiler.rs @@ -7,9 +7,7 @@ use std::{ }, }; -use rspack_fs_node::AsyncNodeWritableFileSystem; - -type CompilerInner = rspack_core::Compiler; +type CompilerInner = rspack_core::Compiler; /// `Compiler` struct that is `!Unpin`. pub(crate) struct Compiler(CompilerInner, PhantomPinned); diff --git a/crates/node_binding/src/lib.rs b/crates/node_binding/src/lib.rs index 7f17cbcd1f2..4afbc5021a0 100644 --- a/crates/node_binding/src/lib.rs +++ b/crates/node_binding/src/lib.rs @@ -67,8 +67,10 @@ impl Rspack { let rspack = rspack_core::Compiler::new( compiler_options, plugins, - AsyncNodeWritableFileSystem::new(output_filesystem) - .map_err(|e| Error::from_reason(format!("Failed to create writable filesystem: {e}",)))?, + Box::new( + AsyncNodeWritableFileSystem::new(output_filesystem) + .map_err(|e| Error::from_reason(format!("Failed to create writable filesystem: {e}",)))?, + ), Some(resolver_factory), Some(loader_resolver_factory), ); diff --git a/crates/rspack_core/src/compiler/hmr.rs b/crates/rspack_core/src/compiler/hmr.rs index 2a662dc6d26..e6c709d1ffc 100644 --- a/crates/rspack_core/src/compiler/hmr.rs +++ b/crates/rspack_core/src/compiler/hmr.rs @@ -3,7 +3,6 @@ use std::path::PathBuf; use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; use rspack_collections::{Identifier, IdentifierMap}; use rspack_error::Result; -use rspack_fs::AsyncWritableFileSystem; use rspack_hash::RspackHashDigest; use rspack_sources::Source; use rustc_hash::FxHashSet as HashSet; @@ -12,10 +11,7 @@ use crate::{ fast_set, get_chunk_from_ukey, ChunkKind, Compilation, Compiler, ModuleExecutor, RuntimeSpec, }; -impl Compiler -where - T: AsyncWritableFileSystem + Send + Sync, -{ +impl Compiler { pub async fn rebuild( &mut self, changed_files: std::collections::HashSet, diff --git a/crates/rspack_core/src/compiler/mod.rs b/crates/rspack_core/src/compiler/mod.rs index 2c4e0d94854..6f38dc889b5 100644 --- a/crates/rspack_core/src/compiler/mod.rs +++ b/crates/rspack_core/src/compiler/mod.rs @@ -2,9 +2,9 @@ mod compilation; mod hmr; mod make; mod module_executor; - use std::sync::Arc; +use derivative::Derivative; use rspack_error::Result; use rspack_fs::AsyncWritableFileSystem; use rspack_futures::FuturesResults; @@ -49,13 +49,12 @@ pub struct CompilerHooks { pub asset_emitted: CompilerAssetEmittedHook, } -#[derive(Debug)] -pub struct Compiler -where - T: AsyncWritableFileSystem + Send + Sync, -{ +#[derive(Derivative)] +#[derivative(Debug)] +pub struct Compiler { pub options: Arc, - pub output_filesystem: T, + #[derivative(Debug = "ignore")] + pub output_filesystem: Box, pub compilation: Compilation, pub plugin_driver: SharedPluginDriver, pub resolver_factory: Arc, @@ -67,15 +66,12 @@ where unaffected_modules_cache: Arc, } -impl Compiler -where - T: AsyncWritableFileSystem + Send + Sync, -{ +impl Compiler { #[instrument(skip_all)] pub fn new( options: CompilerOptions, plugins: Vec, - output_filesystem: T, + output_filesystem: Box, // no need to pass resolve_factory in rust api resolver_factory: Option>, loader_resolver_factory: Option>, diff --git a/packages/rspack-cli/jest.config.js b/packages/rspack-cli/jest.config.js index 0b2118a394f..40ee463f5f0 100644 --- a/packages/rspack-cli/jest.config.js +++ b/packages/rspack-cli/jest.config.js @@ -1,17 +1,14 @@ /** @type {import('ts-jest/dist/types').JestConfigWithTsJest} */ const config = { - preset: "ts-jest", - testEnvironment: "../../scripts/test/patch-node-env.cjs", - testTimeout: process.env.CI ? 200000 : 30000, - testMatch: ["/tests/**/*.test.ts", "/tests/**/*.test.js"], - watchPathIgnorePatterns: ["/tests/.*/dist"], - extensionsToTreatAsEsm: [".mts"], - globals: { - "ts-jest": { - tsconfig: "/tests/tsconfig.json" - } - }, - prettierPath: require.resolve("prettier-2") + preset: 'ts-jest', + testEnvironment: '../../scripts/test/patch-node-env.cjs', + testTimeout: process.env.CI ? 200000 : 30000, + testMatch: ['/tests/**/*.test.ts', '/tests/**/*.test.js'], + watchPathIgnorePatterns: ['/tests/.*/dist'], + extensionsToTreatAsEsm: ['.mts'], + globals: {'ts-jest': {tsconfig: '/tests/tsconfig.json'}}, + cache: false, + prettierPath: require.resolve('prettier-2') }; module.exports = config; From 0075187ac60784da5a75a2bdac0d1ca2aeca5ddc Mon Sep 17 00:00:00 2001 From: Cong-Cong Pan Date: Mon, 9 Sep 2024 17:07:28 +0800 Subject: [PATCH 3/4] fix: should not transform source to buffer (#7821) * fix: transform source to buffer * chore: add test case --- .../src/source_map_dev_tool_plugin.rs | 30 ++++++------------- .../index.js | 0 .../rspack.config.js | 11 ++++++- .../test.config.js | 0 4 files changed, 19 insertions(+), 22 deletions(-) rename packages/rspack-test-tools/tests/configCases/plugins/{source-map-dev-tool-plugin-source-root => source-map-dev-tool-plugin}/index.js (100%) rename packages/rspack-test-tools/tests/configCases/plugins/{source-map-dev-tool-plugin-source-root => source-map-dev-tool-plugin}/rspack.config.js (61%) rename packages/rspack-test-tools/tests/configCases/plugins/{source-map-dev-tool-plugin-source-root => source-map-dev-tool-plugin}/test.config.js (100%) diff --git a/crates/rspack_plugin_devtool/src/source_map_dev_tool_plugin.rs b/crates/rspack_plugin_devtool/src/source_map_dev_tool_plugin.rs index 7c672d635bf..f58d8340b9e 100644 --- a/crates/rspack_plugin_devtool/src/source_map_dev_tool_plugin.rs +++ b/crates/rspack_plugin_devtool/src/source_map_dev_tool_plugin.rs @@ -342,18 +342,9 @@ impl SourceMapDevToolPlugin { mapped_sources .into_par_iter() - .map(|(filename, asset, source_map)| { - let code_buffer = { - let mut buffer = Vec::with_capacity(asset.size()); - asset.to_writer(&mut buffer).into_diagnostic()?; - buffer - }; - let source_map_buffer = match source_map { - Some(map) => { - let mut buffer = Vec::new(); - map.to_writer(&mut buffer).into_diagnostic()?; - Some(buffer) - } + .map(|(filename, source, source_map)| { + let source_map_json = match source_map { + Some(map) => Some(map.to_json().into_diagnostic()?), None => None, }; @@ -367,10 +358,7 @@ impl SourceMapDevToolPlugin { ) }) .clone(); - // convert to RawSource to reduce one time source map calculation when convert to JsCompatSource - let raw_source = RawSource::from(code_buffer).boxed(); - let Some(source_map_buffer) = source_map_buffer else { - asset.source = Some(raw_source); + let Some(source_map_json) = source_map_json else { return Ok(MappedAsset { asset: (filename, asset), source_map: None, @@ -440,7 +428,7 @@ impl SourceMapDevToolPlugin { }; asset.source = Some( ConcatSource::new([ - raw_source, + source.clone(), RawSource::from( current_source_mapping_url_comment.replace("[url]", &source_map_url), ) @@ -450,7 +438,7 @@ impl SourceMapDevToolPlugin { ); asset.info.related.source_map = Some(source_map_filename.clone()); } else { - asset.source = Some(raw_source); + asset.source = Some(source.clone()); } let mut source_map_asset_info = AssetInfo::default().with_development(true); if let Some(asset) = compilation.assets().get(filename.as_ref()) { @@ -458,7 +446,7 @@ impl SourceMapDevToolPlugin { source_map_asset_info.version = asset.info.version.clone(); } let source_map_asset = CompilationAsset::new( - Some(RawSource::from(source_map_buffer).boxed()), + Some(RawSource::from(source_map_json).boxed()), source_map_asset_info, ); Ok(MappedAsset { @@ -476,10 +464,10 @@ impl SourceMapDevToolPlugin { )) } }; - let base64 = rspack_base64::encode_to_string(&source_map_buffer); + let base64 = rspack_base64::encode_to_string(source_map_json.as_bytes()); asset.source = Some( ConcatSource::new([ - raw_source, + source.clone(), RawSource::from(current_source_mapping_url_comment.replace( "[url]", &format!("data:application/json;charset=utf-8;base64,{base64}"), diff --git a/packages/rspack-test-tools/tests/configCases/plugins/source-map-dev-tool-plugin-source-root/index.js b/packages/rspack-test-tools/tests/configCases/plugins/source-map-dev-tool-plugin/index.js similarity index 100% rename from packages/rspack-test-tools/tests/configCases/plugins/source-map-dev-tool-plugin-source-root/index.js rename to packages/rspack-test-tools/tests/configCases/plugins/source-map-dev-tool-plugin/index.js diff --git a/packages/rspack-test-tools/tests/configCases/plugins/source-map-dev-tool-plugin-source-root/rspack.config.js b/packages/rspack-test-tools/tests/configCases/plugins/source-map-dev-tool-plugin/rspack.config.js similarity index 61% rename from packages/rspack-test-tools/tests/configCases/plugins/source-map-dev-tool-plugin-source-root/rspack.config.js rename to packages/rspack-test-tools/tests/configCases/plugins/source-map-dev-tool-plugin/rspack.config.js index fd79c85c76d..ecc18ea6d1e 100644 --- a/packages/rspack-test-tools/tests/configCases/plugins/source-map-dev-tool-plugin-source-root/rspack.config.js +++ b/packages/rspack-test-tools/tests/configCases/plugins/source-map-dev-tool-plugin/rspack.config.js @@ -19,6 +19,15 @@ module.exports = { }), new rspack.DefinePlugin({ CONTEXT: JSON.stringify(__dirname) - }) + }), + compiler => { + compiler.hooks.compilation.tap("PLUGIN", compilation => { + compilation.hooks.afterProcessAssets.tap("PLUGIN", assets => { + for (const asset of Object.values(assets)) { + expect(typeof asset.source()).toBe("string"); + } + }); + }); + } ] }; diff --git a/packages/rspack-test-tools/tests/configCases/plugins/source-map-dev-tool-plugin-source-root/test.config.js b/packages/rspack-test-tools/tests/configCases/plugins/source-map-dev-tool-plugin/test.config.js similarity index 100% rename from packages/rspack-test-tools/tests/configCases/plugins/source-map-dev-tool-plugin-source-root/test.config.js rename to packages/rspack-test-tools/tests/configCases/plugins/source-map-dev-tool-plugin/test.config.js From 500c045e6d8df7c2fb50885f4e5011b58b55f077 Mon Sep 17 00:00:00 2001 From: Gengkun Date: Mon, 9 Sep 2024 17:31:35 +0800 Subject: [PATCH 4/4] fix: change javascript parser options in child compiler (#7812) --- .../src/options/raw_module/mod.rs | 52 ++++++++----- .../rspack_core/src/normal_module_factory.rs | 49 +++++++++--- crates/rspack_core/src/options/module.rs | 38 ++++++---- .../src/parser_plugin/worker_plugin.rs | 74 +++++++++++-------- crates/rspack_util/src/merge.rs | 15 +++- .../tests/__snapshots__/Defaults.test.js.snap | 51 ------------- .../child-entry.js | 6 ++ .../change-parser-in-child-compiler/img.png | 0 .../change-parser-in-child-compiler/index.js | 1 + .../rspack.config.js | 25 +++++++ packages/rspack/src/config/adapter.ts | 39 ++++------ packages/rspack/src/config/defaults.ts | 74 ++++--------------- 12 files changed, 215 insertions(+), 209 deletions(-) create mode 100644 packages/rspack-test-tools/tests/configCases/module/change-parser-in-child-compiler/child-entry.js create mode 100644 packages/rspack-test-tools/tests/configCases/module/change-parser-in-child-compiler/img.png create mode 100644 packages/rspack-test-tools/tests/configCases/module/change-parser-in-child-compiler/index.js create mode 100644 packages/rspack-test-tools/tests/configCases/module/change-parser-in-child-compiler/rspack.config.js diff --git a/crates/rspack_binding_options/src/options/raw_module/mod.rs b/crates/rspack_binding_options/src/options/raw_module/mod.rs index d2d88aecb15..f0dfbf0504d 100644 --- a/crates/rspack_binding_options/src/options/raw_module/mod.rs +++ b/crates/rspack_binding_options/src/options/raw_module/mod.rs @@ -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}; @@ -203,14 +203,32 @@ impl From 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 @@ -805,16 +823,16 @@ impl TryFrom for ModuleOptions { .parser .map(|x| { x.into_iter() - .map(|(k, v)| Ok((ModuleType::from(k.as_str()), v.into()))) - .collect::>() + .map(|(k, v)| Ok((k, v.into()))) + .collect::>() }) .transpose()?, generator: value .generator .map(|x| { x.into_iter() - .map(|(k, v)| Ok((ModuleType::from(k.as_str()), v.into()))) - .collect::>() + .map(|(k, v)| Ok((k, v.into()))) + .collect::>() }) .transpose()?, no_parse: value diff --git a/crates/rspack_core/src/normal_module_factory.rs b/crates/rspack_core/src/normal_module_factory.rs index 26c42c33805..4caff05fadc 100644 --- a/crates/rspack_core/src/normal_module_factory.rs +++ b/crates/rspack_core/src/normal_module_factory.rs @@ -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( diff --git a/crates/rspack_core/src/options/module.rs b/crates/rspack_core/src/options/module.rs index ff54c5e0d4d..a6f01bf5778 100644 --- a/crates/rspack_core/src/options/module.rs +++ b/crates/rspack_core/src/options/module.rs @@ -16,17 +16,17 @@ use rustc_hash::FxHashMap as HashMap; use crate::{Filename, Module, ModuleType, PublicPath, Resolve}; #[derive(Debug)] -pub struct ParserOptionsByModuleType(HashMap); +pub struct ParserOptionsMap(HashMap); -impl FromIterator<(ModuleType, ParserOptions)> for ParserOptionsByModuleType { - fn from_iter>(i: I) -> Self { +impl FromIterator<(String, ParserOptions)> for ParserOptionsMap { + fn from_iter>(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) } } @@ -37,6 +37,9 @@ pub enum ParserOptions { CssAuto(CssAutoParserOptions), CssModule(CssModuleParserOptions), Javascript(JavascriptParserOptions), + JavascriptAuto(JavascriptParserOptions), + JavascriptEsm(JavascriptParserOptions), + JavascriptDynamic(JavascriptParserOptions), Unknown, } @@ -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)] @@ -259,17 +269,17 @@ pub struct CssModuleParserOptions { } #[derive(Debug)] -pub struct GeneratorOptionsByModuleType(HashMap); +pub struct GeneratorOptionsMap(HashMap); -impl FromIterator<(ModuleType, GeneratorOptions)> for GeneratorOptionsByModuleType { - fn from_iter>(i: I) -> Self { +impl FromIterator<(String, GeneratorOptions)> for GeneratorOptionsMap { + fn from_iter>(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) } } @@ -758,7 +768,7 @@ pub enum ModuleRuleEnforce { #[derive(Debug, Default)] pub struct ModuleOptions { pub rules: Vec, - pub parser: Option, - pub generator: Option, + pub parser: Option, + pub generator: Option, pub no_parse: Option, } diff --git a/crates/rspack_plugin_javascript/src/parser_plugin/worker_plugin.rs b/crates/rspack_plugin_javascript/src/parser_plugin/worker_plugin.rs index dcda6c5ce19..9e4aa9dd958 100644 --- a/crates/rspack_plugin_javascript/src/parser_plugin/worker_plugin.rs +++ b/crates/rspack_plugin_javascript/src/parser_plugin/worker_plugin.rs @@ -198,6 +198,12 @@ static WORKER_FROM_REGEX: LazyLock = 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 { @@ -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 { diff --git a/crates/rspack_util/src/merge.rs b/crates/rspack_util/src/merge.rs index 7ca532b1a09..d0eb4545917 100644 --- a/crates/rspack_util/src/merge.rs +++ b/crates/rspack_util/src/merge.rs @@ -23,10 +23,17 @@ impl MergeFrom for Option { } } -impl MergeFrom for Vec { - fn merge_from(mut self, other: &Self) -> Self { - self.extend(other.iter().cloned()); - self +impl MergeFrom for Vec { + 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 } } diff --git a/packages/rspack-test-tools/tests/__snapshots__/Defaults.test.js.snap b/packages/rspack-test-tools/tests/__snapshots__/Defaults.test.js.snap index 08dab610b0f..ea11c5b027b 100644 --- a/packages/rspack-test-tools/tests/__snapshots__/Defaults.test.js.snap +++ b/packages/rspack-test-tools/tests/__snapshots__/Defaults.test.js.snap @@ -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 [], }, diff --git a/packages/rspack-test-tools/tests/configCases/module/change-parser-in-child-compiler/child-entry.js b/packages/rspack-test-tools/tests/configCases/module/change-parser-in-child-compiler/child-entry.js new file mode 100644 index 00000000000..ddcaf2b30f5 --- /dev/null +++ b/packages/rspack-test-tools/tests/configCases/module/change-parser-in-child-compiler/child-entry.js @@ -0,0 +1,6 @@ +export const test = (it) => { + it("should not have 'Invalid URL' error with relative URL in child compilation", () => { + const url = new URL("./img.png", import.meta.url); + expect(url.href.endsWith(".png")) + }) +} diff --git a/packages/rspack-test-tools/tests/configCases/module/change-parser-in-child-compiler/img.png b/packages/rspack-test-tools/tests/configCases/module/change-parser-in-child-compiler/img.png new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/rspack-test-tools/tests/configCases/module/change-parser-in-child-compiler/index.js b/packages/rspack-test-tools/tests/configCases/module/change-parser-in-child-compiler/index.js new file mode 100644 index 00000000000..87a5cc2fee8 --- /dev/null +++ b/packages/rspack-test-tools/tests/configCases/module/change-parser-in-child-compiler/index.js @@ -0,0 +1 @@ +__non_webpack_require__("./__child-main.js").test(it) diff --git a/packages/rspack-test-tools/tests/configCases/module/change-parser-in-child-compiler/rspack.config.js b/packages/rspack-test-tools/tests/configCases/module/change-parser-in-child-compiler/rspack.config.js new file mode 100644 index 00000000000..50eee9a4efb --- /dev/null +++ b/packages/rspack-test-tools/tests/configCases/module/change-parser-in-child-compiler/rspack.config.js @@ -0,0 +1,25 @@ +/** + * @type {import('@rspack/core').RspackOptions} + */ +module.exports = { + plugins: [ + function (compiler) { + compiler.hooks.make.tapAsync('test', (compilation, callback) => { + const child = compilation.createChildCompiler("test", { + filename: '__child-[name].js', + publicPath: '', + }, [ + new compiler.webpack.library.EnableLibraryPlugin('commonjs'), + new compiler.webpack.EntryPlugin(compilation.options.context, "./child-entry.js", { + name: "main", + library: { + type: "commonjs", + } + }) + ]); + child.options.module.parser.javascript.url = "relative"; + child.runAsChild(callback); + }) + } + ], +}; diff --git a/packages/rspack/src/config/adapter.ts b/packages/rspack/src/config/adapter.ts index 7b5ead98906..73143fe602a 100644 --- a/packages/rspack/src/config/adapter.ts +++ b/packages/rspack/src/config/adapter.ts @@ -336,8 +336,8 @@ function getRawModule( ); return { rules, - parser: getRawParserOptionsByModuleType(module.parser), - generator: getRawGeneratorOptionsByModuleType(module.generator), + parser: getRawParserOptionsMap(module.parser), + generator: getRawGeneratorOptionsMap(module.generator), noParse: module.noParse }; } @@ -575,7 +575,7 @@ function getRawRuleSetLogicalConditions( }; } -function getRawParserOptionsByModuleType( +function getRawParserOptionsMap( parser: ParserOptionsByModuleType ): Record { return Object.fromEntries( @@ -585,11 +585,11 @@ function getRawParserOptionsByModuleType( ); } -function getRawGeneratorOptionsByModuleType( - parser: GeneratorOptionsByModuleType +function getRawGeneratorOptionsMap( + generator: GeneratorOptionsByModuleType ): Record { return Object.fromEntries( - Object.entries(parser) + Object.entries(generator) .map(([k, v]) => [k, getRawGeneratorOptions(v, k)]) .filter(([k, v]) => v !== undefined) ); @@ -606,8 +606,10 @@ function getRawParserOptions( }; } if (type === "javascript") { - // Filter this out, since `parser["javascript"]` already merge into `parser["javascript/*"]` in default.ts - return; + return { + type: "javascript", + javascript: getRawJavascriptParserOptions(parser) + }; } if (type === "javascript/auto") { return { @@ -677,25 +679,16 @@ function getRawJavascriptParserOptions( ? "false" : parser.reexportExportsPresence, strictExportPresence: parser.strictExportPresence ?? false, - worker: getRawJavascriptParserOptionsWorker(parser.worker!), + worker: + typeof parser.worker === "boolean" + ? parser.worker + ? ["..."] + : [] + : parser.worker ?? ["..."], overrideStrict: parser.overrideStrict }; } -function getRawJavascriptParserOptionsWorker( - worker: boolean | string[] -): RawJavascriptParserOptions["worker"] { - const DEFAULT_SYNTAX = [ - "Worker", - "SharedWorker", - "navigator.serviceWorker.register()", - "Worker from worker_threads" - ]; - return ( - worker === false ? [] : Array.isArray(worker) ? worker : ["..."] - ).flatMap(item => (item === "..." ? DEFAULT_SYNTAX : item)); -} - function getRawAssetParserOptions( parser: AssetParserOptions ): RawAssetParserOptions { diff --git a/packages/rspack/src/config/defaults.ts b/packages/rspack/src/config/defaults.ts index 7281280cbf7..9af1d263de8 100644 --- a/packages/rspack/src/config/defaults.ts +++ b/packages/rspack/src/config/defaults.ts @@ -234,46 +234,21 @@ const applySnapshotDefaults = ( ) => {}; const applyJavascriptParserOptionsDefaults = ( - parserOptions: JavascriptParserOptions, - fallback?: JavascriptParserOptions + parserOptions: JavascriptParserOptions ) => { - D(parserOptions, "dynamicImportMode", fallback?.dynamicImportMode ?? "lazy"); - D( - parserOptions, - "dynamicImportPrefetch", - fallback?.dynamicImportPrefetch ?? false - ); - D( - parserOptions, - "dynamicImportPreload", - fallback?.dynamicImportPreload ?? false - ); - D(parserOptions, "url", fallback?.url ?? true); - D( - parserOptions, - "exprContextCritical", - fallback?.exprContextCritical ?? true - ); - D( - parserOptions, - "wrappedContextCritical", - fallback?.wrappedContextCritical ?? false - ); - D(parserOptions, "exportsPresence", fallback?.exportsPresence); - D(parserOptions, "importExportsPresence", fallback?.importExportsPresence); - D( - parserOptions, - "reexportExportsPresence", - fallback?.reexportExportsPresence - ); - D( - parserOptions, - "strictExportPresence", - fallback?.strictExportPresence ?? false - ); - D(parserOptions, "worker", fallback?.worker ?? ["..."]); - D(parserOptions, "overrideStrict", fallback?.overrideStrict ?? undefined); - D(parserOptions, "importMeta", fallback?.importMeta ?? true); + D(parserOptions, "dynamicImportMode", "lazy"); + D(parserOptions, "dynamicImportPrefetch", false); + D(parserOptions, "dynamicImportPreload", false); + D(parserOptions, "url", true); + D(parserOptions, "exprContextCritical", true); + D(parserOptions, "wrappedContextCritical", false); + D(parserOptions, "exportsPresence", undefined); + D(parserOptions, "importExportsPresence", undefined); + D(parserOptions, "reexportExportsPresence", undefined); + D(parserOptions, "strictExportPresence", false); + D(parserOptions, "worker", ["..."]); + D(parserOptions, "overrideStrict", undefined); + D(parserOptions, "importMeta", true); }; const applyModuleDefaults = ( @@ -303,27 +278,6 @@ const applyModuleDefaults = ( assertNotNill(module.parser.javascript); applyJavascriptParserOptionsDefaults(module.parser.javascript); - F(module.parser, "javascript/auto", () => ({})); - assertNotNill(module.parser["javascript/auto"]); - applyJavascriptParserOptionsDefaults( - module.parser["javascript/auto"], - module.parser.javascript - ); - - F(module.parser, "javascript/dynamic", () => ({})); - assertNotNill(module.parser["javascript/dynamic"]); - applyJavascriptParserOptionsDefaults( - module.parser["javascript/dynamic"], - module.parser.javascript - ); - - F(module.parser, "javascript/esm", () => ({})); - assertNotNill(module.parser["javascript/esm"]); - applyJavascriptParserOptionsDefaults( - module.parser["javascript/esm"], - module.parser.javascript - ); - if (css) { F(module.parser, "css", () => ({})); assertNotNill(module.parser.css);