rspack_core/dependency/
context_element_dependency.rs1use itertools::Itertools;
2use rspack_cacheable::{
3 cacheable, cacheable_dyn,
4 with::{AsOption, AsPreset, AsVec},
5};
6use rspack_util::json_stringify;
7use swc_core::ecma::atoms::Atom;
8
9use super::{AffectType, FactorizeInfo};
10use crate::{
11 AsContextDependency, AsDependencyCodeGeneration, Context, ContextMode, ContextNameSpaceObject,
12 ContextOptions, ContextTypePrefix, Dependency, DependencyCategory, DependencyId, DependencyType,
13 ExportsType, ExtendedReferencedExport, ImportAttributes, ModuleDependency, ModuleGraph,
14 ModuleGraphCacheArtifact, ModuleLayer, ReferencedExport, ResourceIdentifier, RuntimeSpec,
15 create_exports_object_referenced,
16};
17
18#[cacheable]
19#[derive(Debug, Clone)]
20pub struct ContextElementDependency {
21 pub id: DependencyId,
22 pub options: ContextOptions,
24 pub request: String,
25 pub user_request: String,
26 pub category: DependencyCategory,
27 pub context: Context,
28 pub layer: Option<ModuleLayer>,
29 pub resource_identifier: ResourceIdentifier,
30 #[cacheable(with=AsOption<AsVec<AsVec<AsPreset>>>)]
31 pub referenced_exports: Option<Vec<Vec<Atom>>>,
32 pub dependency_type: DependencyType,
33 pub attributes: Option<ImportAttributes>,
34 pub factorize_info: FactorizeInfo,
35}
36
37impl ContextElementDependency {
38 pub fn create_resource_identifier(
39 resource: &str,
40 path: &str,
41 attributes: Option<&ImportAttributes>,
42 ) -> ResourceIdentifier {
43 let mut ident = format!("context{resource}|{path}");
44 if let Some(attributes) = attributes {
45 ident += &json_stringify(&attributes);
46 }
47 ident.into()
48 }
49}
50
51#[cacheable_dyn]
52impl Dependency for ContextElementDependency {
53 fn id(&self) -> &DependencyId {
54 &self.id
55 }
56
57 fn category(&self) -> &DependencyCategory {
58 &self.category
59 }
60
61 fn dependency_type(&self) -> &DependencyType {
62 &self.dependency_type
63 }
64
65 fn get_context(&self) -> Option<&Context> {
66 Some(&self.context)
67 }
68
69 fn get_layer(&self) -> Option<&ModuleLayer> {
70 self.layer.as_ref()
71 }
72
73 fn get_attributes(&self) -> Option<&ImportAttributes> {
74 self.attributes.as_ref()
75 }
76
77 fn resource_identifier(&self) -> Option<&str> {
78 Some(&self.resource_identifier)
79 }
80
81 fn get_referenced_exports(
82 &self,
83 module_graph: &ModuleGraph,
84 module_graph_cache: &ModuleGraphCacheArtifact,
85 _runtime: Option<&RuntimeSpec>,
86 ) -> Vec<ExtendedReferencedExport> {
87 if let Some(referenced_exports) = &self.referenced_exports {
88 for referenced_export in referenced_exports {
89 if matches!(
90 self.dependency_type,
91 DependencyType::ContextElement(ContextTypePrefix::Import)
92 ) && referenced_export
93 .first()
94 .is_some_and(|export| export == "default")
95 {
96 let is_strict = module_graph
97 .get_parent_module(&self.id)
98 .and_then(|id| module_graph.module_by_identifier(id))
99 .and_then(|m| m.as_context_module())
100 .map(|m| {
101 matches!(
102 m.get_context_options().namespace_object,
103 ContextNameSpaceObject::Strict
104 )
105 });
106
107 let exports_type = is_strict.and_then(|is_strict| {
108 module_graph
109 .get_module_by_dependency_id(&self.id)
110 .map(|m| m.get_exports_type(module_graph, module_graph_cache, is_strict))
111 });
112
113 if let Some(exports_type) = exports_type
114 && matches!(
115 exports_type,
116 ExportsType::DefaultOnly | ExportsType::DefaultWithNamed
117 )
118 {
119 return create_exports_object_referenced();
120 }
121 }
122 }
123
124 referenced_exports
125 .iter()
126 .map(|export| {
127 ExtendedReferencedExport::Export(ReferencedExport::new(export.clone(), false, false))
128 })
129 .collect_vec()
130 } else {
131 create_exports_object_referenced()
132 }
133 }
134
135 fn could_affect_referencing_module(&self) -> AffectType {
136 AffectType::True
137 }
138}
139
140#[cacheable_dyn]
141impl ModuleDependency for ContextElementDependency {
142 fn request(&self) -> &str {
143 &self.request
144 }
145
146 fn user_request(&self) -> &str {
147 &self.user_request
148 }
149
150 fn weak(&self) -> bool {
151 matches!(
152 self.options.mode,
153 ContextMode::AsyncWeak | ContextMode::Weak
154 )
155 }
156
157 fn factorize_info(&self) -> &FactorizeInfo {
158 &self.factorize_info
159 }
160
161 fn factorize_info_mut(&mut self) -> &mut FactorizeInfo {
162 &mut self.factorize_info
163 }
164}
165
166impl AsDependencyCodeGeneration for ContextElementDependency {}
167impl AsContextDependency for ContextElementDependency {}