diff --git a/crates/rspack_core/src/runtime_globals.rs b/crates/rspack_core/src/runtime_globals.rs index 71094f978c71..116beecedc66 100644 --- a/crates/rspack_core/src/runtime_globals.rs +++ b/crates/rspack_core/src/runtime_globals.rs @@ -248,6 +248,15 @@ bitflags! { const RSPACK_UNIQUE_ID = 1 << 64; const HAS_FETCH_PRIORITY = 1 << 65; + + // amd module support + const AMD_DEFINE = 1 << 66; + const AMD_OPTIONS = 1 << 67; + + /** + * the uncaught error handler for the webpack runtime + */ + const UNCAUGHT_ERROR_HANDLER = 1 << 68; } } @@ -293,11 +302,14 @@ impl RuntimeGlobals { R::GET_CHUNK_UPDATE_CSS_FILENAME => "__webpack_require__.hk", R::HMR_MODULE_DATA => "__webpack_require__.hmrD", R::HMR_RUNTIME_STATE_PREFIX => "__webpack_require__.hmrS", + R::AMD_DEFINE => "__webpack_require__.amdD", + R::AMD_OPTIONS => "__webpack_require__.amdO", R::EXTERNAL_INSTALL_CHUNK => "__webpack_require__.C", R::GET_FULL_HASH => "__webpack_require__.h", R::GLOBAL => "__webpack_require__.g", R::RETURN_EXPORTS_FROM_RUNTIME => "return-exports-from-runtime", R::INSTANTIATE_WASM => "__webpack_require__.v", + R::UNCAUGHT_ERROR_HANDLER => "__webpack_require__.oe", R::ASYNC_MODULE => "__webpack_require__.a", R::BASE_URI => "__webpack_require__.b", R::STARTUP_ENTRYPOINT => "__webpack_require__.X", diff --git a/crates/rspack_plugin_javascript/src/dependency/amd/amd_define_dependency.rs b/crates/rspack_plugin_javascript/src/dependency/amd/amd_define_dependency.rs new file mode 100644 index 000000000000..a24845e4961c --- /dev/null +++ b/crates/rspack_plugin_javascript/src/dependency/amd/amd_define_dependency.rs @@ -0,0 +1,325 @@ +use bitflags::bitflags; +use rspack_core::{ + AsContextDependency, AsModuleDependency, Dependency, DependencyCategory, DependencyId, + DependencyTemplate, DependencyType, RuntimeGlobals, TemplateContext, TemplateReplaceSource, +}; +use rspack_util::atom::Atom; + +use super::local_module::LocalModule; + +bitflags! { + #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] + struct Branch: u8 { + const L = 1 << 0; + const A = 1 << 1; + const O = 1 << 2; + const F = 1 << 3; + } +} + +impl Branch { + pub fn get_requests(&self) -> RuntimeGlobals { + match *self { + f if f == Branch::F => { + RuntimeGlobals::REQUIRE | RuntimeGlobals::EXPORTS | RuntimeGlobals::MODULE + } + o if o == Branch::O => RuntimeGlobals::MODULE, + of if of == (Branch::O | Branch::F) => { + RuntimeGlobals::REQUIRE | RuntimeGlobals::EXPORTS | RuntimeGlobals::MODULE + } + af if af == (Branch::A | Branch::F) => RuntimeGlobals::EXPORTS | RuntimeGlobals::MODULE, + ao if ao == (Branch::A | Branch::O) => RuntimeGlobals::MODULE, + aof if aof == (Branch::A | Branch::O | Branch::F) => { + RuntimeGlobals::EXPORTS | RuntimeGlobals::MODULE + } + lf if lf == (Branch::L | Branch::F) => RuntimeGlobals::REQUIRE | RuntimeGlobals::MODULE, + lo if lo == (Branch::L | Branch::O) => RuntimeGlobals::empty(), + lof if lof == (Branch::L | Branch::O | Branch::F) => { + RuntimeGlobals::REQUIRE | RuntimeGlobals::MODULE + } + laf if laf == (Branch::L | Branch::A | Branch::F) => RuntimeGlobals::empty(), + lao if lao == (Branch::L | Branch::A | Branch::O) => RuntimeGlobals::empty(), + laof if laof == (Branch::L | Branch::A | Branch::O | Branch::F) => RuntimeGlobals::empty(), + _ => RuntimeGlobals::empty(), + } + } + + pub fn get_definition(&self, local_module_var: &Option) -> String { + let name = match local_module_var { + Some(name) => &name, + None => "XXX", + }; + match *self { + f if f == Branch::F => "var __WEBPACK_AMD_DEFINE_RESULT__;".to_string(), + o if o == Branch::O => "".to_string(), + of if of == (Branch::O | Branch::F) => { + "var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;".to_string() + } + af if af == (Branch::A | Branch::F) => { + "var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;".to_string() + } + ao if ao == (Branch::A | Branch::O) => "".to_string(), + aof if aof == (Branch::A | Branch::O | Branch::F) => "var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;".to_string(), + lf if lf == (Branch::L | Branch::F) => { + format!("var {}, {}module;", name, name) + }, + lo if lo == (Branch::L | Branch::O) => { + format!("var {};", name) + }, + lof if lof == (Branch::L | Branch::O | Branch::F) => { + format!("var {}, {}factory, {}module;", name, name, name) + }, + laf if laf == (Branch::L | Branch::A | Branch::F) => { + format!("var __WEBPACK_AMD_DEFINE_ARRAY__, {}, {}exports;", name, name) + }, + lao if lao == (Branch::L | Branch::A | Branch::O)=> { + format!("var {};", name) + }, + laof if laof == (Branch::L | Branch::A | Branch::O | Branch::F) => { + format!("var {}array, {}factory, {}exports, {};", name, name, name, name) + }, + _ => "".to_string(), + } + } + + pub fn get_content( + &self, + local_module_var: &Option, + named_module: &Option, + ) -> String { + let local_module_var = match local_module_var { + Some(name) => &name, + None => "XXX", + }; + let named_module = match named_module { + Some(name) => &name, + None => "YYY", + }; + match *self { + f if f == Branch::F => { + format!( + "!(__WEBPACK_AMD_DEFINE_RESULT__ = (#).call(exports, {}, exports, module), + __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__))", + RuntimeGlobals::REQUIRE.name() + ) + } + o if o == Branch::O => "!(module.exports = #)".to_string(), + of if of == (Branch::O | Branch::F) => { + format!( + "!(__WEBPACK_AMD_DEFINE_FACTORY__ = (#), + __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? + (__WEBPACK_AMD_DEFINE_FACTORY__.call(exports, {}, exports, module)) : + __WEBPACK_AMD_DEFINE_FACTORY__), + __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__))", + RuntimeGlobals::REQUIRE.name() + ) + } + af if af == (Branch::A | Branch::F) => "!(__WEBPACK_AMD_DEFINE_ARRAY__ = #, __WEBPACK_AMD_DEFINE_RESULT__ = (#).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), + __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__))".to_string(), + ao if ao == (Branch::A | Branch::O) => "!(#, module.exports = #)".to_string(), + aof if aof == (Branch::A | Branch::O | Branch::F) => { + "!(__WEBPACK_AMD_DEFINE_ARRAY__ = #, __WEBPACK_AMD_DEFINE_FACTORY__ = (#), + __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? + (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), + __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__))".to_string() + } + lf if lf == (Branch::L | Branch::F) => { + format!( + "!({}module = {{ id: {}, exports: {{}}, loaded: false }}, {} = (#).call({}module.exports, {}, {}module.exports, {}module), {}module.loaded = true, {} === undefined && ({} = {}module.exports))", + local_module_var, + named_module, + local_module_var, + local_module_var, + RuntimeGlobals::REQUIRE.name(), + local_module_var, + local_module_var, + local_module_var, + local_module_var, + local_module_var, + local_module_var + ) + } + lo if lo == (Branch::L | Branch::O) => format!("!({} = #)", local_module_var), + lof if lof == (Branch::L | Branch::O | Branch::F) => { + format!( + "!({}factory = (#), (typeof {}factory === 'function' ? (({}module = {{ id: {}, exports: {{}}, loaded: false }}), ({} = {}factory.call({}module.exports, {}, {}module.exports, {}module)), ({}module.loaded = true), {} === undefined && ({} = {}module.exports)) : {} = {}factory))", + local_module_var, + local_module_var, + local_module_var, + named_module, + local_module_var, + local_module_var, + local_module_var, + RuntimeGlobals::REQUIRE.name(), + local_module_var, + local_module_var, + local_module_var, + local_module_var, + local_module_var, + local_module_var, + local_module_var, + local_module_var, + ) + } + laf if laf == (Branch::L | Branch::A | Branch::F) => format!("!(__WEBPACK_AMD_DEFINE_ARRAY__ = #, {} = (#).apply({}exports = {{}}, __WEBPACK_AMD_DEFINE_ARRAY__), {} === undefined && ({} = {}exports))", local_module_var, local_module_var, local_module_var, local_module_var, local_module_var), + lao if lao == (Branch::L | Branch::A | Branch::O) => format!("!(#, {} = #)", local_module_var), + laof if laof == (Branch::L | Branch::A | Branch::O | Branch::F) => format!( + "!({}array = #, {}factory = (#), + (typeof {}factory === 'function' ? + (({} = {}factory.apply({}exports = {{}}, {}array)), {} === undefined && ({} = {}exports)) : + ({} = {}factory) + ))", + local_module_var, + local_module_var, + local_module_var, + local_module_var, + local_module_var, + local_module_var, + local_module_var, + local_module_var, + local_module_var, + local_module_var, + local_module_var, + local_module_var, + ), + _ => "".to_string(), + } + } +} + +#[derive(Debug, Clone)] +pub struct AmdDefineDependency { + id: DependencyId, + range: (u32, u32), + array_range: Option<(u32, u32)>, + function_range: Option<(u32, u32)>, + object_range: Option<(u32, u32)>, + named_module: Option, + local_module: Option, +} + +impl AmdDefineDependency { + pub fn new( + range: (u32, u32), + array_range: Option<(u32, u32)>, + function_range: Option<(u32, u32)>, + object_range: Option<(u32, u32)>, + named_module: Option, + ) -> Self { + Self { + id: DependencyId::new(), + range, + array_range, + function_range, + object_range, + named_module, + local_module: None, + } + } +} + +impl Dependency for AmdDefineDependency { + fn id(&self) -> &DependencyId { + &self.id + } + + fn category(&self) -> &DependencyCategory { + &DependencyCategory::Amd + } + + fn dependency_type(&self) -> &DependencyType { + &DependencyType::AmdDefine + } +} + +impl AmdDefineDependency { + fn local_module_var(&self) -> Option { + self.local_module.as_ref().and_then(|m| { + if m.is_used() { + Some(m.variable_name()) + } else { + None + } + }) + } + + fn branch(&self) -> Branch { + let mut ret = Branch::empty(); + if self.local_module.as_ref().is_some_and(|m| m.is_used()) { + ret |= Branch::L; + } + if self.array_range.is_some() { + ret |= Branch::A; + } + if self.object_range.is_some() { + ret |= Branch::O; + } + if self.function_range.is_some() { + ret |= Branch::F; + } + ret + } +} + +impl DependencyTemplate for AmdDefineDependency { + fn apply( + &self, + source: &mut TemplateReplaceSource, + code_generatable_context: &mut TemplateContext, + ) { + let branch = self.branch(); + code_generatable_context + .runtime_requirements + .insert(branch.get_requests()); + + // TODO: localModuleVar.replace(/\$/g, "$$$$") + let local_module_var = self.local_module_var(); + + let text = branch.get_content(&local_module_var, &self.named_module); + let definition = branch.get_definition(&local_module_var); + + let mut texts = text.split('#'); + + if definition.len() > 0 { + source.insert(0, &definition, None); + } + + let mut current = self.range.0; + if let Some(array_range) = self.array_range { + source.replace(current, array_range.0 - 1, texts.next().unwrap_or(""), None); + current = array_range.1; + } + + if let Some(object_range) = self.object_range { + source.replace( + current, + object_range.0 - 1, + texts.next().unwrap_or(""), + None, + ); + current = object_range.1; + } else if let Some(function_range) = self.function_range { + source.replace( + current, + function_range.0 - 1, + texts.next().unwrap_or(""), + None, + ); + current = function_range.1; + } + + source.replace(current, self.range.1 - 1, texts.next().unwrap_or(""), None); + + if texts.next().is_some() { + panic!("Implementation error"); + } + } + + fn dependency_id(&self) -> Option { + Some(self.id) + } +} + +impl AsModuleDependency for AmdDefineDependency {} + +impl AsContextDependency for AmdDefineDependency {} diff --git a/crates/rspack_plugin_javascript/src/dependency/amd/amd_require_array_dependency.rs b/crates/rspack_plugin_javascript/src/dependency/amd/amd_require_array_dependency.rs new file mode 100644 index 000000000000..b8b0a07ebe5e --- /dev/null +++ b/crates/rspack_plugin_javascript/src/dependency/amd/amd_require_array_dependency.rs @@ -0,0 +1,99 @@ +use itertools::Itertools; +use rspack_core::{ + module_raw, AsContextDependency, AsModuleDependency, Dependency, DependencyCategory, + DependencyId, DependencyTemplate, DependencyType, ModuleDependency, TemplateContext, + TemplateReplaceSource, +}; +use rspack_util::atom::Atom; + +use super::{ + amd_require_item_dependency::AMDRequireItemDependency, + local_module_dependency::LocalModuleDependency, +}; + +#[derive(Debug, Clone)] +pub enum AmdDep { + String(Atom), + LocalModuleDependency(LocalModuleDependency), + AMDRequireItemDependency(AMDRequireItemDependency), +} + +#[derive(Debug, Clone)] +pub struct AmdRequireArrayDependency { + id: DependencyId, + deps_array: Vec, + range: (u32, u32), +} + +impl AmdRequireArrayDependency { + pub fn new(deps_array: Vec, range: (u32, u32)) -> Self { + Self { + id: DependencyId::new(), + deps_array, + range, + } + } +} + +impl Dependency for AmdRequireArrayDependency { + fn id(&self) -> &DependencyId { + &self.id + } + + fn category(&self) -> &DependencyCategory { + &DependencyCategory::Amd + } + + fn dependency_type(&self) -> &DependencyType { + &DependencyType::AmdRequireArray + } +} + +impl AmdRequireArrayDependency { + fn get_content(&self, code_generatable_context: &mut TemplateContext) -> String { + format!( + "[{}]", + self + .deps_array + .iter() + .map(|dep| Self::content_for_dependency(dep, code_generatable_context)) + .join(", ") + ) + } + + fn content_for_dependency( + dep: &AmdDep, + code_generatable_context: &mut TemplateContext, + ) -> String { + match dep { + AmdDep::String(name) => name.to_string(), + AmdDep::LocalModuleDependency(dep) => dep.get_variable_name(), + AmdDep::AMDRequireItemDependency(dep) => module_raw( + code_generatable_context.compilation, + code_generatable_context.runtime_requirements, + dep.id(), + dep.request(), + dep.weak(), + ), + } + } +} + +impl DependencyTemplate for AmdRequireArrayDependency { + fn apply( + &self, + source: &mut TemplateReplaceSource, + code_generatable_context: &mut TemplateContext, + ) { + let content = self.get_content(code_generatable_context); + source.replace(self.range.0, self.range.1 - 1, &content, None); + } + + fn dependency_id(&self) -> Option { + Some(self.id) + } +} + +impl AsModuleDependency for AmdRequireArrayDependency {} + +impl AsContextDependency for AmdRequireArrayDependency {} diff --git a/crates/rspack_plugin_javascript/src/dependency/amd/amd_require_dependency.rs b/crates/rspack_plugin_javascript/src/dependency/amd/amd_require_dependency.rs new file mode 100644 index 000000000000..bd0b1fca34b3 --- /dev/null +++ b/crates/rspack_plugin_javascript/src/dependency/amd/amd_require_dependency.rs @@ -0,0 +1,193 @@ +use rspack_core::{ + block_promise, AsContextDependency, AsModuleDependency, Dependency, DependencyCategory, + DependencyId, DependencyTemplate, DependencyType, RuntimeGlobals, +}; + +#[derive(Debug, Clone)] +pub struct AMDRequireDependency { + id: DependencyId, + outer_range: (u32, u32), + // In the webpack source code, type annotation of `arrayRange` is non-null. + // However, `DependencyTemplate` implementation assumes `arrayRange` can be null in some cases. + // So I use Option here. + array_range: Option<(u32, u32)>, + function_range: Option<(u32, u32)>, + error_callback_range: Option<(u32, u32)>, + function_bind_this: bool, + error_callback_bind_this: bool, +} + +impl AMDRequireDependency { + pub fn new( + outer_range: (u32, u32), + array_range: Option<(u32, u32)>, + function_range: Option<(u32, u32)>, + error_callback_range: Option<(u32, u32)>, + ) -> Self { + Self { + id: DependencyId::new(), + outer_range, + array_range, + function_range, + error_callback_range, + function_bind_this: false, + error_callback_bind_this: false, + } + } +} + +impl Dependency for AMDRequireDependency { + fn id(&self) -> &DependencyId { + &self.id + } + + fn category(&self) -> &DependencyCategory { + &DependencyCategory::Amd + } + + fn dependency_type(&self) -> &DependencyType { + &DependencyType::AmdRequire + } +} + +impl DependencyTemplate for AMDRequireDependency { + fn apply( + &self, + source: &mut rspack_core::TemplateReplaceSource, + code_generatable_context: &mut rspack_core::TemplateContext, + ) { + let module_graph = code_generatable_context.compilation.get_module_graph(); + let block = module_graph.get_parent_block(&self.id); + + let promise = block_promise( + block, + code_generatable_context.runtime_requirements, + code_generatable_context.compilation, + "AMD require", + ); + + // has array range but no function range + if self.array_range.is_some() && self.function_range.is_none() { + let start_block = promise + ".then(function() {"; + let end_block = format!( + ";}})['catch']{}", + RuntimeGlobals::UNCAUGHT_ERROR_HANDLER.name() + ); + code_generatable_context + .runtime_requirements + .insert(RuntimeGlobals::UNCAUGHT_ERROR_HANDLER); + let array_range = self.array_range.unwrap(); + source.replace(self.outer_range.0, array_range.0 - 1, &start_block, None); + source.replace(array_range.1, self.outer_range.1 - 1, &end_block, None); + return; + } + + // has function range but no array range + if self.function_range.is_some() && self.array_range.is_none() { + let start_block = promise + ".then(("; + let end_block = format!( + ").bind(exports, {}, exports, module))['catch']({})", + RuntimeGlobals::REQUIRE.name(), + RuntimeGlobals::UNCAUGHT_ERROR_HANDLER.name() + ); + code_generatable_context + .runtime_requirements + .insert(RuntimeGlobals::UNCAUGHT_ERROR_HANDLER); + let function_range = self.function_range.unwrap(); + source.replace(self.outer_range.0, function_range.0 - 1, &start_block, None); + source.replace(function_range.1, self.outer_range.1 - 1, &end_block, None); + return; + } + + // has array range, function range, and errorCallbackRange + if self.array_range.is_some() + && self.function_range.is_some() + && self.error_callback_range.is_some() + { + let start_block = promise + ".then(function() { "; + let error_range_block = if self.function_bind_this { + "}.bind(this))['catch'](" + } else { + "})['catch'](" + }; + let end_block = if self.error_callback_bind_this { + ".bind(this))" + } else { + ")" + }; + let array_range = self.array_range.unwrap(); + let function_range = self.function_range.unwrap(); + let error_callback_range = self.error_callback_range.unwrap(); + + source.replace(self.outer_range.0, array_range.0 - 1, &start_block, None); + + source.insert(array_range.0, "var __WEBPACK_AMD_REQUIRE_ARRAY__ = ", None); + + source.replace(array_range.1, function_range.0 - 1, "; (", None); + + source.insert( + function_range.1, + ").apply(null, __WEBPACK_AMD_REQUIRE_ARRAY__);", + None, + ); + + source.replace( + function_range.1, + error_callback_range.0 - 1, + error_range_block, + None, + ); + + source.replace( + error_callback_range.1, + self.outer_range.1 - 1, + end_block, + None, + ); + + return; + } + + // has array range, function range, but no errorCallbackRange + if self.array_range.is_some() && self.function_range.is_some() { + let start_block = promise + ".then(function() { "; + let end_block = format!( + "}}{})['catch']({})", + if self.function_bind_this { + ".bind(this)" + } else { + "" + }, + RuntimeGlobals::UNCAUGHT_ERROR_HANDLER.name() + ); + code_generatable_context + .runtime_requirements + .insert(RuntimeGlobals::UNCAUGHT_ERROR_HANDLER); + + let array_range = self.array_range.unwrap(); + let function_range = self.function_range.unwrap(); + + source.replace(self.outer_range.0, array_range.0 - 1, &start_block, None); + + source.insert(array_range.0, "var __WEBPACK_AMD_REQUIRE_ARRAY__ = ", None); + + source.replace(array_range.1, function_range.0 - 1, "; (", None); + + source.insert( + function_range.1, + ").apply(null, __WEBPACK_AMD_REQUIRE_ARRAY__);", + None, + ); + + source.replace(function_range.1, self.outer_range.1 - 1, &end_block, None); + }; + } + + fn dependency_id(&self) -> Option { + Some(self.id) + } +} + +impl AsModuleDependency for AMDRequireDependency {} + +impl AsContextDependency for AMDRequireDependency {} diff --git a/crates/rspack_plugin_javascript/src/dependency/amd/amd_require_item_dependency.rs b/crates/rspack_plugin_javascript/src/dependency/amd/amd_require_item_dependency.rs new file mode 100644 index 000000000000..3daa3ec1e7cb --- /dev/null +++ b/crates/rspack_plugin_javascript/src/dependency/amd/amd_require_item_dependency.rs @@ -0,0 +1,67 @@ +use rspack_core::{ + module_raw, AsContextDependency, Dependency, DependencyCategory, DependencyId, + DependencyTemplate, DependencyType, ModuleDependency, TemplateContext, TemplateReplaceSource, +}; +use rspack_util::atom::Atom; + +#[derive(Debug, Clone)] +pub struct AMDRequireItemDependency { + id: DependencyId, + request: Atom, + range: (u32, u32), +} + +impl AMDRequireItemDependency { + pub fn new(request: Atom, range: (u32, u32)) -> Self { + Self { + id: DependencyId::new(), + request, + range, + } + } +} + +impl Dependency for AMDRequireItemDependency { + fn id(&self) -> &DependencyId { + &self.id + } + + fn category(&self) -> &DependencyCategory { + &DependencyCategory::Amd + } + + fn dependency_type(&self) -> &DependencyType { + &DependencyType::AmdRequireItem + } +} + +impl DependencyTemplate for AMDRequireItemDependency { + fn apply( + &self, + source: &mut TemplateReplaceSource, + code_generatable_context: &mut TemplateContext, + ) { + // ModuleDependencyTemplateAsRequireId + let content = module_raw( + code_generatable_context.compilation, + code_generatable_context.runtime_requirements, + &self.id, + &self.request, + self.weak(), + ); + // TODO: should it be `self.range.1` or `self.range.1 - 1`? + source.replace(self.range.0, self.range.1 - 1, &content, None); + } + + fn dependency_id(&self) -> Option { + Some(self.id) + } +} + +impl ModuleDependency for AMDRequireItemDependency { + fn request(&self) -> &str { + &self.request + } +} + +impl AsContextDependency for AMDRequireItemDependency {} diff --git a/crates/rspack_plugin_javascript/src/dependency/amd/local_module.rs b/crates/rspack_plugin_javascript/src/dependency/amd/local_module.rs new file mode 100644 index 000000000000..b613742f4b56 --- /dev/null +++ b/crates/rspack_plugin_javascript/src/dependency/amd/local_module.rs @@ -0,0 +1,30 @@ +use rspack_util::atom::Atom; + +#[derive(Debug, Clone)] +pub struct LocalModule { + name: Atom, + idx: usize, + used: bool, +} + +impl LocalModule { + pub fn new(name: Atom, idx: usize) -> Self { + Self { + name, + idx, + used: false, + } + } + + pub fn flag_used(&mut self) { + self.used = true; + } + + pub fn variable_name(&self) -> String { + format!("__WEBPACK_LOCAL_MODULE_{}__", self.idx) + } + + pub fn is_used(&self) -> bool { + self.used + } +} diff --git a/crates/rspack_plugin_javascript/src/dependency/amd/local_module_dependency.rs b/crates/rspack_plugin_javascript/src/dependency/amd/local_module_dependency.rs new file mode 100644 index 000000000000..7a1d0b56365b --- /dev/null +++ b/crates/rspack_plugin_javascript/src/dependency/amd/local_module_dependency.rs @@ -0,0 +1,63 @@ +use rspack_core::{ + AsContextDependency, AsModuleDependency, Dependency, DependencyId, DependencyTemplate, + TemplateContext, TemplateReplaceSource, +}; + +use super::local_module::LocalModule; + +#[derive(Debug, Clone)] +pub struct LocalModuleDependency { + id: DependencyId, + local_module: LocalModule, + range: Option<(u32, u32)>, + call_new: bool, +} + +impl LocalModuleDependency { + pub fn new(local_module: LocalModule, range: Option<(u32, u32)>, call_new: bool) -> Self { + Self { + id: DependencyId::new(), + local_module, + range, + call_new, + } + } + + pub fn get_variable_name(&self) -> String { + self.local_module.variable_name() + } +} + +impl Dependency for LocalModuleDependency { + fn id(&self) -> &DependencyId { + &self.id + } +} + +impl DependencyTemplate for LocalModuleDependency { + fn apply( + &self, + source: &mut TemplateReplaceSource, + _code_generatable_context: &mut TemplateContext, + ) { + if let Some(range) = self.range { + let module_instance = if self.call_new { + format!( + "new (function () {{ return {}; }})()", + self.local_module.variable_name() + ) + } else { + self.local_module.variable_name() + }; + source.replace(range.0, range.1 - 1, &module_instance, None); + } + } + + fn dependency_id(&self) -> Option { + Some(self.id) + } +} + +impl AsModuleDependency for LocalModuleDependency {} + +impl AsContextDependency for LocalModuleDependency {} diff --git a/crates/rspack_plugin_javascript/src/dependency/amd/mod.rs b/crates/rspack_plugin_javascript/src/dependency/amd/mod.rs new file mode 100644 index 000000000000..3eaaa0e1b001 --- /dev/null +++ b/crates/rspack_plugin_javascript/src/dependency/amd/mod.rs @@ -0,0 +1,6 @@ +pub mod amd_define_dependency; +pub mod amd_require_array_dependency; +pub mod amd_require_dependency; +pub mod amd_require_item_dependency; +pub mod local_module; +pub mod local_module_dependency; diff --git a/crates/rspack_plugin_javascript/src/dependency/context/amd_require_context_dependency.rs b/crates/rspack_plugin_javascript/src/dependency/context/amd_require_context_dependency.rs new file mode 100644 index 000000000000..2a6334acea8a --- /dev/null +++ b/crates/rspack_plugin_javascript/src/dependency/context/amd_require_context_dependency.rs @@ -0,0 +1,114 @@ +use rspack_core::{ + AsModuleDependency, ContextDependency, ContextOptions, Dependency, DependencyCategory, + DependencyId, DependencyTemplate, DependencyType, ErrorSpan, +}; + +use super::{ + context_dependency_template_as_require_call, create_resource_identifier_for_context_dependency, +}; + +#[derive(Debug, Clone)] +pub struct AMDRequireContextDependency { + callee_start: u32, + callee_end: u32, + args_end: u32, + id: DependencyId, + options: ContextOptions, + span: Option, + resource_identifier: String, + optional: bool, +} + +impl AMDRequireContextDependency { + pub fn new( + callee_start: u32, + callee_end: u32, + args_end: u32, + options: ContextOptions, + span: Option, + optional: bool, + ) -> Self { + let resource_identifier = create_resource_identifier_for_context_dependency(None, &options); + Self { + callee_start, + callee_end, + args_end, + options, + span, + id: DependencyId::new(), + resource_identifier, + optional, + } + } +} + +impl Dependency for AMDRequireContextDependency { + fn id(&self) -> &DependencyId { + &self.id + } + + fn category(&self) -> &DependencyCategory { + &DependencyCategory::Amd + } + + fn dependency_type(&self) -> &DependencyType { + &DependencyType::AmdRequireContext + } + + fn span(&self) -> Option { + self.span + } +} + +impl ContextDependency for AMDRequireContextDependency { + fn request(&self) -> &str { + &self.options.request + } + + fn options(&self) -> &ContextOptions { + &self.options + } + + fn get_context(&self) -> Option<&str> { + None + } + + fn resource_identifier(&self) -> &str { + &self.resource_identifier + } + + fn set_request(&mut self, request: String) { + self.options.request = request; + } + + fn get_optional(&self) -> bool { + self.optional + } + + fn type_prefix(&self) -> rspack_core::ContextTypePrefix { + rspack_core::ContextTypePrefix::Normal + } +} + +impl DependencyTemplate for AMDRequireContextDependency { + fn apply( + &self, + source: &mut rspack_core::TemplateReplaceSource, + code_generatable_context: &mut rspack_core::TemplateContext, + ) { + context_dependency_template_as_require_call( + self, + source, + code_generatable_context, + self.callee_start, + self.callee_end, + self.args_end, + ); + } + + fn dependency_id(&self) -> Option { + Some(self.id) + } +} + +impl AsModuleDependency for AMDRequireContextDependency {} diff --git a/crates/rspack_plugin_javascript/src/dependency/context/mod.rs b/crates/rspack_plugin_javascript/src/dependency/context/mod.rs index c9828b39376e..83bd46e66c4f 100644 --- a/crates/rspack_plugin_javascript/src/dependency/context/mod.rs +++ b/crates/rspack_plugin_javascript/src/dependency/context/mod.rs @@ -1,8 +1,10 @@ +mod amd_require_context_dependency; mod common_js_require_context_dependency; mod import_context_dependency; mod import_meta_context_dependency; mod require_context_dependency; +pub use amd_require_context_dependency::AMDRequireContextDependency; pub use common_js_require_context_dependency::CommonJsRequireContextDependency; pub use import_context_dependency::ImportContextDependency; pub use import_meta_context_dependency::ImportMetaContextDependency; diff --git a/crates/rspack_plugin_javascript/src/dependency/mod.rs b/crates/rspack_plugin_javascript/src/dependency/mod.rs index d4b68d94d080..3c567d48dd6b 100644 --- a/crates/rspack_plugin_javascript/src/dependency/mod.rs +++ b/crates/rspack_plugin_javascript/src/dependency/mod.rs @@ -1,3 +1,4 @@ +mod amd; mod commonjs; mod context; mod esm;