rspack_plugin_javascript/dependency/
pure_expression_dependency.rs1use rspack_cacheable::{cacheable, cacheable_dyn};
2use rspack_collections::{IdentifierMap, IdentifierSet};
3use rspack_core::{
4 AsContextDependency, AsModuleDependency, Compilation, ConnectionState, Dependency,
5 DependencyCodeGeneration, DependencyId, DependencyRange, DependencyTemplate,
6 DependencyTemplateType, ModuleGraph, ModuleGraphCacheArtifact, ModuleIdentifier,
7 RuntimeCondition, RuntimeSpec, SideEffectsStateArtifact, TemplateContext, TemplateReplaceSource,
8 UsedByExports,
9};
10use rspack_hash::{RspackHash, RspackHasher};
11
12use crate::runtime_condition_used_by_exports;
13
14#[cacheable]
15#[derive(Debug, Clone)]
16pub struct PureExpressionDependency {
17 pub range: DependencyRange,
18 used_by_exports: Option<UsedByExports>,
19 id: DependencyId,
20 pub module_identifier: ModuleIdentifier,
21}
22
23impl PureExpressionDependency {
24 pub fn new(range: DependencyRange, module_identifier: ModuleIdentifier) -> Self {
25 Self {
26 range,
27 used_by_exports: None,
28 id: DependencyId::default(),
29 module_identifier,
30 }
31 }
32
33 fn get_runtime_condition(
34 &self,
35 compilation: &Compilation,
36 runtime: Option<&RuntimeSpec>,
37 ) -> RuntimeCondition {
38 runtime_condition_used_by_exports(
39 compilation,
40 &self.module_identifier,
41 runtime,
42 self.used_by_exports.as_ref(),
43 )
44 }
45
46 pub fn set_used_by_exports(&mut self, used_by_exports: Option<UsedByExports>) {
47 self.used_by_exports = used_by_exports;
48 }
49}
50
51#[cacheable_dyn]
52impl Dependency for PureExpressionDependency {
53 fn id(&self) -> &rspack_core::DependencyId {
54 &self.id
55 }
56
57 fn range(&self) -> Option<DependencyRange> {
58 Some(self.range)
59 }
60
61 fn get_module_evaluation_side_effects_state(
62 &self,
63 _module_graph: &ModuleGraph,
64 _module_graph_cache: &ModuleGraphCacheArtifact,
65 _side_effects_state_artifact: &SideEffectsStateArtifact,
66 _module_chain: &mut IdentifierSet,
67 _connection_state_cache: &mut IdentifierMap<ConnectionState>,
68 ) -> ConnectionState {
69 ConnectionState::Active(false)
70 }
71
72 fn could_affect_referencing_module(&self) -> rspack_core::AffectType {
73 rspack_core::AffectType::False
74 }
75}
76
77impl AsModuleDependency for PureExpressionDependency {}
78
79#[cacheable_dyn]
80impl DependencyCodeGeneration for PureExpressionDependency {
81 fn dependency_template(&self) -> Option<DependencyTemplateType> {
82 Some(PureExpressionDependencyTemplate::template_type())
83 }
84
85 fn update_hash(
86 &self,
87 hasher: &mut RspackHasher,
88 compilation: &Compilation,
89 runtime: Option<&RuntimeSpec>,
90 ) {
91 let runtime_condition = self.get_runtime_condition(compilation, runtime);
92 runtime_condition.hash(hasher);
93 }
94}
95
96impl AsContextDependency for PureExpressionDependency {}
97
98#[cacheable]
99#[derive(Debug, Clone, Default)]
100pub struct PureExpressionDependencyTemplate;
101
102impl PureExpressionDependencyTemplate {
103 pub fn template_type() -> DependencyTemplateType {
104 DependencyTemplateType::Custom("PureExpressionDependency")
105 }
106}
107
108impl DependencyTemplate for PureExpressionDependencyTemplate {
109 fn render(
110 &self,
111 dep: &dyn DependencyCodeGeneration,
112 source: &mut TemplateReplaceSource,
113 code_generatable_context: &mut TemplateContext,
114 ) {
115 let dep = dep
116 .as_any()
117 .downcast_ref::<PureExpressionDependency>()
118 .expect("PureExpressionDependencyTemplate should be used for PureExpressionDependency");
119
120 let runtime_condition = dep.get_runtime_condition(
121 code_generatable_context.compilation,
122 code_generatable_context.runtime,
123 );
124 let condition = match &runtime_condition {
125 rspack_core::RuntimeCondition::Boolean(true) => return,
126 rspack_core::RuntimeCondition::Boolean(false) => None,
127 rspack_core::RuntimeCondition::Spec(_spec) => Some(
128 code_generatable_context
129 .runtime_template
130 .runtime_condition_expression(
131 &code_generatable_context
132 .compilation
133 .build_chunk_graph_artifact
134 .chunk_graph,
135 Some(&runtime_condition),
136 code_generatable_context.runtime,
137 ),
138 ),
139 };
140
141 if let Some(condition) = condition {
142 source.insert(
143 dep.range.start,
144 format!("(/* runtime-dependent pure expression or super */ {condition} ? ("),
145 None,
146 );
147 source.insert_static(dep.range.end, ") : null)", None);
148 } else {
149 source.insert_static(
150 dep.range.start,
151 "(/* unused pure expression or super */ null && (",
152 None,
153 );
154 source.insert_static(dep.range.end, "))", None);
155 }
156 }
157}