rspack_plugin_javascript/dependency/
module_argument_dependency.rs1use rspack_cacheable::{cacheable, cacheable_dyn};
2use rspack_core::{
3 Compilation, DependencyCodeGeneration, DependencyLocation, DependencyRange, DependencyTemplate,
4 DependencyTemplateType, RuntimeGlobals, RuntimeSpec, TemplateContext, TemplateReplaceSource,
5};
6use rspack_hash::{RspackHash, RspackHasher};
7
8#[cacheable]
9#[derive(Debug, Clone)]
10pub struct ModuleArgumentDependency {
11 id: Option<String>,
12 range: DependencyRange,
13 loc: Option<DependencyLocation>,
14}
15
16impl ModuleArgumentDependency {
17 pub fn new(id: Option<String>, range: DependencyRange, loc: Option<DependencyLocation>) -> Self {
18 Self { id, range, loc }
19 }
20
21 pub fn loc(&self) -> Option<DependencyLocation> {
22 self.loc.clone()
23 }
24}
25
26impl RspackHash for ModuleArgumentDependency {
27 fn hash(&self, state: &mut RspackHasher) {
28 "range".hash(state);
29 self.range.hash(state);
30 if let Some(id) = &self.id {
31 "id".hash(state);
32 id.hash(state);
33 }
34
35 match self.id.as_deref() {
36 Some("id") => {
37 "runtime_requirements".hash(state);
38 RuntimeGlobals::MODULE_ID.hash(state);
39 }
40 Some("loaded") => {
41 "runtime_requirements".hash(state);
42 RuntimeGlobals::MODULE_LOADED.hash(state);
43 }
44 Some("hot" | "hot.accept" | "hot.decline") => {
45 "runtime_requirements".hash(state);
46 RuntimeGlobals::MODULE.hash(state);
47 }
48 _ => {}
49 }
50 }
51}
52
53#[cacheable_dyn]
54impl DependencyCodeGeneration for ModuleArgumentDependency {
55 fn dependency_template(&self) -> Option<DependencyTemplateType> {
56 Some(ModuleArgumentDependencyTemplate::template_type())
57 }
58
59 fn update_hash(
60 &self,
61 hasher: &mut RspackHasher,
62 _compilation: &Compilation,
63 _runtime: Option<&RuntimeSpec>,
64 ) {
65 RspackHash::hash(self, hasher);
66 }
67}
68
69#[cacheable]
70#[derive(Debug, Clone, Default)]
71pub struct ModuleArgumentDependencyTemplate;
72
73impl ModuleArgumentDependencyTemplate {
74 pub fn template_type() -> DependencyTemplateType {
75 DependencyTemplateType::Custom("ModuleArgumentDependency")
76 }
77}
78
79impl DependencyTemplate for ModuleArgumentDependencyTemplate {
80 fn render(
81 &self,
82 dep: &dyn DependencyCodeGeneration,
83 source: &mut TemplateReplaceSource,
84 code_generatable_context: &mut TemplateContext,
85 ) {
86 let dep = dep
87 .as_any()
88 .downcast_ref::<ModuleArgumentDependency>()
89 .expect("ModuleArgumentDependencyTemplate should be used for ModuleArgumentDependency");
90
91 let TemplateContext {
92 compilation,
93 module,
94 runtime_template,
95 ..
96 } = code_generatable_context;
97
98 let module_argument = runtime_template.render_module_argument(
99 compilation
100 .get_module_graph()
101 .module_by_identifier(&module.identifier())
102 .expect("should have mgm")
103 .get_module_argument(),
104 );
105
106 let content = if let Some(id) = &dep.id {
107 match id.as_str() {
108 "id" => runtime_template
109 .runtime_requirements_mut()
110 .insert(RuntimeGlobals::MODULE_ID),
111 "loaded" => runtime_template
112 .runtime_requirements_mut()
113 .insert(RuntimeGlobals::MODULE_LOADED),
114 _ => {}
115 };
116
117 format!("{module_argument}.{id}")
118 } else {
119 module_argument
120 };
121
122 source.replace(dep.range.start, dep.range.end, content, None);
123 }
124}