1use std::{
2 alloc::{Layout, LayoutError, alloc, handle_alloc_error},
3 any::Any,
4 fmt::{self, Debug},
5 ops::{Deref, DerefMut},
6 ptr,
7 sync::{Arc, OnceLock, atomic::AtomicUsize},
8};
9
10use rspack_cacheable::{
11 cacheable_dyn,
12 rkyv::{
13 Archive, ArchiveUnsized, Deserialize, DeserializeUnsized, Place, Serialize, SerializeUnsized,
14 de::{FromMetadata, Metadata, Pooling, PoolingExt, SharedPointer},
15 ptr_meta::{Pointee, from_raw_parts_mut},
16 rancor::{Fallible, ResultExt, Source},
17 rc::{ArchivedRc, Flavor, RcResolver},
18 ser::{Sharing, Writer},
19 traits::LayoutRaw,
20 },
21};
22use rspack_collections::{IdentifierMap, IdentifierSet};
23use rspack_error::Diagnostic;
24use rspack_location::DependencyLocation;
25use rspack_util::ext::AsAny;
26use triomphe::{Arc as TriompheArc, UniqueArc};
27use unsize::{CoerceUnsize, Coercion};
28
29use super::{
30 DependencyCategory, DependencyId, DependencyRange, DependencyType, ExportsSpec,
31 dependency_template::AsDependencyCodeGeneration, module_dependency::*,
32};
33use crate::{
34 AsContextDependency, ConnectionState, Context, ExportsInfoArtifact, ForwardId, ImportAttributes,
35 ImportPhase, JavascriptParserUrl, LazyUntil, Module, ModuleGraph, ModuleGraphCacheArtifact,
36 ModuleLayer, ReferencedExport, RuntimeSpec, SideEffectsStateArtifact,
37 create_exports_object_referenced,
38};
39
40#[derive(Debug, Clone, Copy)]
41pub enum AffectType {
42 True,
43 False,
44 Transitive,
45}
46
47#[derive(Debug, Default)]
49pub struct DependencyDiagnosticsContext {
50 module_source: OnceLock<Option<Arc<str>>>,
51}
52
53impl DependencyDiagnosticsContext {
54 fn get_or_init_module_source(&self, init: impl FnOnce() -> Option<Arc<str>>) -> Option<Arc<str>> {
55 self.module_source.get_or_init(init).clone()
56 }
57
58 pub fn module_source(&self, module: &dyn Module) -> Option<Arc<str>> {
60 self.get_or_init_module_source(|| {
61 module
62 .source()
63 .map(|source| source.source().into_string_lossy().into())
64 })
65 }
66}
67
68#[cacheable_dyn]
69pub trait Dependency:
70 AsDependencyCodeGeneration + AsContextDependency + AsModuleDependency + AsAny + Send + Sync + Debug
71{
72 fn id(&self) -> &DependencyId;
73
74 fn category(&self) -> &DependencyCategory {
75 &DependencyCategory::Unknown
76 }
77
78 fn dependency_type(&self) -> &DependencyType {
79 &DependencyType::Unknown
80 }
81
82 fn skip_async_entrypoints(&self) -> bool {
85 false
86 }
87
88 fn url_mode(&self) -> Option<JavascriptParserUrl> {
89 None
90 }
91
92 fn get_context(&self) -> Option<&Context> {
94 None
95 }
96
97 fn get_layer(&self) -> Option<&ModuleLayer> {
99 None
100 }
101
102 fn get_phase(&self) -> ImportPhase {
103 ImportPhase::Evaluation
104 }
105
106 fn get_attributes(&self) -> Option<&ImportAttributes> {
107 None
108 }
109
110 fn get_exports(
111 &self,
112 _mg: &ModuleGraph,
113 _module_graph_cache: &ModuleGraphCacheArtifact,
114 _exports_info_artifact: &ExportsInfoArtifact,
115 ) -> Option<ExportsSpec> {
116 None
117 }
118
119 fn get_module_evaluation_side_effects_state(
120 &self,
121 _module_graph: &ModuleGraph,
122 _module_graph_cache: &ModuleGraphCacheArtifact,
123 _side_effects_state_artifact: &SideEffectsStateArtifact,
124 _module_chain: &mut IdentifierSet,
125 _connection_state_cache: &mut IdentifierMap<ConnectionState>,
126 ) -> ConnectionState {
127 ConnectionState::Active(true)
128 }
129
130 fn loc(&self) -> Option<DependencyLocation> {
131 None
132 }
133
134 fn range(&self) -> Option<DependencyRange> {
135 None
136 }
137
138 fn source_order(&self) -> Option<i32> {
139 None
140 }
141
142 fn resource_identifier(&self) -> Option<&str> {
143 None
144 }
145
146 fn get_diagnostics(
147 &self,
148 _module_graph: &ModuleGraph,
149 _module_graph_cache: &ModuleGraphCacheArtifact,
150 _exports_info_artifact: &ExportsInfoArtifact,
151 ) -> Option<Vec<Diagnostic>> {
152 None
153 }
154
155 fn get_diagnostics_with_context(
156 &self,
157 module_graph: &ModuleGraph,
158 module_graph_cache: &ModuleGraphCacheArtifact,
159 exports_info_artifact: &ExportsInfoArtifact,
160 _context: &DependencyDiagnosticsContext,
161 ) -> Option<Vec<Diagnostic>> {
162 self.get_diagnostics(module_graph, module_graph_cache, exports_info_artifact)
163 }
164
165 fn get_referenced_exports(
166 &self,
167 _module_graph: &ModuleGraph,
168 _module_graph_cache: &ModuleGraphCacheArtifact,
169 _exports_info_artifact: &ExportsInfoArtifact,
170 _runtime: Option<&RuntimeSpec>,
171 ) -> Vec<ReferencedExport> {
172 create_exports_object_referenced()
173 }
174
175 fn could_affect_referencing_module(&self) -> AffectType;
176
177 fn forward_id(&self) -> ForwardId {
178 ForwardId::All
179 }
180
181 fn lazy(&self) -> Option<LazyUntil> {
182 None
183 }
184
185 fn set_lazy(&self) {}
186
187 fn unset_lazy(&self) -> bool {
188 false
189 }
190}
191
192impl dyn Dependency + '_ {
193 pub fn downcast_ref<D: Any>(&self) -> Option<&D> {
194 self.as_any().downcast_ref::<D>()
195 }
196
197 pub fn downcast_mut<D: Any>(&mut self) -> Option<&mut D> {
198 self.as_any_mut().downcast_mut::<D>()
199 }
200
201 pub fn is<D: Any>(&self) -> bool {
202 self.downcast_ref::<D>().is_some()
203 }
204}
205
206pub struct UniqueDependency(UniqueArc<dyn Dependency>);
211
212impl UniqueDependency {
213 pub fn new<D: Dependency + 'static>(dependency: D) -> Self {
214 let coercion =
215 unsafe { Coercion::<D, dyn Dependency>::new(|ptr: *const D| ptr as *const dyn Dependency) };
216 Self(UniqueArc::new(dependency).unsize(coercion))
217 }
218
219 pub fn shareable(self) -> DependencyRef {
220 DependencyRef(self.0.shareable())
221 }
222}
223
224impl Debug for UniqueDependency {
225 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
226 Debug::fmt(self.as_ref(), f)
227 }
228}
229
230impl Deref for UniqueDependency {
231 type Target = dyn Dependency;
232
233 fn deref(&self) -> &Self::Target {
234 &*self.0
235 }
236}
237
238impl DerefMut for UniqueDependency {
239 fn deref_mut(&mut self) -> &mut Self::Target {
240 &mut *self.0
241 }
242}
243
244impl AsRef<dyn Dependency> for UniqueDependency {
245 fn as_ref(&self) -> &(dyn Dependency + 'static) {
246 &*self.0
247 }
248}
249
250impl AsMut<dyn Dependency> for UniqueDependency {
251 fn as_mut(&mut self) -> &mut (dyn Dependency + 'static) {
252 &mut *self.0
253 }
254}
255
256impl Archive for UniqueDependency {
257 type Archived = ArchivedRc<<dyn Dependency as ArchiveUnsized>::Archived, DependencyRefFlavor>;
258 type Resolver = RcResolver;
259
260 fn resolve(&self, resolver: Self::Resolver, out: Place<Self::Archived>) {
261 ArchivedRc::resolve_from_ref(self.as_ref(), resolver, out);
262 }
263}
264
265impl<S> Serialize<S> for UniqueDependency
266where
267 dyn Dependency: SerializeUnsized<S>,
268 S: Writer + Sharing + Fallible + ?Sized,
269 S::Error: Source,
270{
271 fn serialize(&self, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
272 ArchivedRc::<
273 <dyn Dependency as ArchiveUnsized>::Archived,
274 DependencyRefFlavor,
275 >::serialize_from_ref(self.as_ref(), serializer)
276 }
277}
278
279impl<D> Deserialize<UniqueDependency, D>
280 for ArchivedRc<<dyn Dependency as ArchiveUnsized>::Archived, DependencyRefFlavor>
281where
282 <dyn Dependency as Pointee>::Metadata: Into<Metadata> + FromMetadata,
283 <dyn Dependency as ArchiveUnsized>::Archived: DeserializeUnsized<dyn Dependency, D>,
284 D: Fallible + ?Sized,
285 D::Error: Source,
286{
287 fn deserialize(&self, deserializer: &mut D) -> Result<UniqueDependency, D::Error> {
288 let metadata = self.get().deserialize_metadata();
289 let out = <DependencyRef as SharedPointer<dyn Dependency>>::alloc(metadata).into_error()?;
290 unsafe {
291 self.get().deserialize_unsized(deserializer, out)?;
292 }
293 let raw = unsafe { <DependencyRef as SharedPointer<dyn Dependency>>::from_value(out) };
294 let arc = unsafe { TriompheArc::from_raw(raw) };
295 let unique = UniqueArc::try_from(arc)
296 .unwrap_or_else(|_| unreachable!("a freshly deserialized dependency has one owner"));
297 Ok(UniqueDependency(unique))
298 }
299}
300
301pub type BoxDependency = UniqueDependency;
304
305pub struct DependencyRef(TriompheArc<dyn Dependency>);
310
311impl DependencyRef {
312 pub fn new<D: Dependency + 'static>(dependency: D) -> Self {
313 UniqueDependency::new(dependency).shareable()
314 }
315}
316
317impl From<UniqueDependency> for DependencyRef {
318 fn from(dependency: UniqueDependency) -> Self {
319 dependency.shareable()
320 }
321}
322
323impl Clone for DependencyRef {
324 fn clone(&self) -> Self {
325 Self(self.0.clone())
326 }
327}
328
329impl Debug for DependencyRef {
330 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
331 Debug::fmt(self.as_ref(), f)
332 }
333}
334
335impl Deref for DependencyRef {
336 type Target = dyn Dependency;
337
338 fn deref(&self) -> &Self::Target {
339 &*self.0
340 }
341}
342
343impl AsRef<dyn Dependency> for DependencyRef {
344 fn as_ref(&self) -> &(dyn Dependency + 'static) {
345 &*self.0
346 }
347}
348
349pub struct DependencyRefFlavor;
350
351impl Flavor for DependencyRefFlavor {
352 const ALLOW_CYCLES: bool = false;
353}
354
355unsafe impl SharedPointer<dyn Dependency> for DependencyRef {
356 fn alloc(
357 metadata: <dyn Dependency as Pointee>::Metadata,
358 ) -> Result<*mut dyn Dependency, LayoutError> {
359 let value_layout = <dyn Dependency as LayoutRaw>::layout_raw(metadata)?;
360 let (layout, data_offset) = Layout::new::<AtomicUsize>().extend(value_layout)?;
361 let layout = layout.pad_to_align();
362 let allocation = unsafe { alloc(layout) };
363 if allocation.is_null() {
364 handle_alloc_error(layout);
365 }
366
367 unsafe {
368 ptr::write(allocation.cast::<AtomicUsize>(), AtomicUsize::new(1));
369 Ok(from_raw_parts_mut(
370 allocation.add(data_offset).cast(),
371 metadata,
372 ))
373 }
374 }
375
376 unsafe fn from_value(ptr: *mut dyn Dependency) -> *mut dyn Dependency {
377 ptr
378 }
379
380 unsafe fn drop(ptr: *mut dyn Dependency) {
381 drop(unsafe { TriompheArc::from_raw(ptr) });
382 }
383}
384
385impl Archive for DependencyRef {
386 type Archived = ArchivedRc<<dyn Dependency as ArchiveUnsized>::Archived, DependencyRefFlavor>;
387 type Resolver = RcResolver;
388
389 fn resolve(&self, resolver: Self::Resolver, out: Place<Self::Archived>) {
390 ArchivedRc::resolve_from_ref(self.as_ref(), resolver, out);
391 }
392}
393
394impl<S> Serialize<S> for DependencyRef
395where
396 dyn Dependency: SerializeUnsized<S>,
397 S: Writer + Sharing + Fallible + ?Sized,
398 S::Error: Source,
399{
400 fn serialize(&self, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
401 ArchivedRc::<
402 <dyn Dependency as ArchiveUnsized>::Archived,
403 DependencyRefFlavor,
404 >::serialize_from_ref(self.as_ref(), serializer)
405 }
406}
407
408impl<D> Deserialize<DependencyRef, D>
409 for ArchivedRc<<dyn Dependency as ArchiveUnsized>::Archived, DependencyRefFlavor>
410where
411 <dyn Dependency as Pointee>::Metadata: Into<Metadata> + FromMetadata,
412 <dyn Dependency as ArchiveUnsized>::Archived: DeserializeUnsized<dyn Dependency, D>,
413 D: Pooling + Fallible + ?Sized,
414 D::Error: Source,
415{
416 fn deserialize(&self, deserializer: &mut D) -> Result<DependencyRef, D::Error> {
417 let raw = deserializer.deserialize_shared::<_, DependencyRef>(self.get())?;
418 let arc = unsafe { TriompheArc::from_raw(raw) };
419 let _ = TriompheArc::into_raw(arc.clone());
420 Ok(DependencyRef(arc))
421 }
422}