Skip to main content

rspack_core/dependency/
mod.rs

1mod cached_const_dependency;
2mod const_dependency;
3mod context_dependency;
4mod context_element_dependency;
5mod dependency_category;
6mod dependency_id;
7mod dependency_location;
8mod dependency_template;
9mod dependency_trait;
10mod dependency_type;
11mod entry;
12mod factorize_info;
13mod loader_import;
14mod module_dependency;
15mod runtime_requirements_dependency;
16mod static_exports_dependency;
17
18use std::sync::Arc;
19
20pub use cached_const_dependency::{CachedConstDependency, CachedConstDependencyTemplate};
21pub use const_dependency::{ConstDependency, ConstDependencyTemplate};
22pub use context_dependency::{AsContextDependency, ContextDependency};
23pub use context_element_dependency::ContextElementDependency;
24pub use dependency_category::DependencyCategory;
25pub use dependency_id::*;
26pub use dependency_location::*;
27pub use dependency_template::*;
28pub use dependency_trait::*;
29pub use dependency_type::DependencyType;
30pub use entry::*;
31pub use factorize_info::FactorizeInfo;
32pub use loader_import::*;
33pub use module_dependency::*;
34pub use runtime_requirements_dependency::{
35  RuntimeRequirementsDependency, RuntimeRequirementsDependencyTemplate,
36};
37use rustc_hash::{FxHashMap, FxHashSet};
38use serde::Serialize;
39pub use static_exports_dependency::{StaticExportsDependency, StaticExportsSpec};
40use swc_core::ecma::atoms::Atom;
41
42use crate::{
43  ConnectionState, EvaluatedInlinableValue, ModuleGraph, ModuleGraphCacheArtifact,
44  ModuleGraphConnection, ModuleIdentifier, RuntimeSpec,
45};
46
47#[derive(Debug, Default)]
48pub struct ExportSpec {
49  pub name: Atom,
50  pub export: Option<Nullable<Vec<Atom>>>,
51  pub exports: Option<ExportSpecExports>,
52  pub can_mangle: Option<bool>,
53  pub terminal_binding: Option<bool>,
54  pub priority: Option<u8>,
55  pub hidden: Option<bool>,
56  pub from: Option<ModuleGraphConnection>,
57  pub from_export: Option<ModuleGraphConnection>,
58  pub inlinable: Option<EvaluatedInlinableValue>,
59}
60
61#[derive(Debug, Default)]
62pub struct ExportSpecExports {
63  pub exports: Vec<ExportNameOrSpec>,
64  /// This is used to tell FlagDependencyExportsPlugin that the nested exports that is not
65  /// fully statical, there are maybe some export that dynamically defined by prototype or
66  /// other way, e.g. json exports or enum exports, it's possible to write:
67  ///
68  /// ```js
69  /// import { obj } from "./data.json";
70  /// obj.toString(); // existed but will have an ESModulesLinkingError for toString not exist
71  /// ```
72  ///
73  /// or
74  ///
75  /// ```ts
76  /// export enum Kind { A, B };
77  /// export namespace Kind {
78  ///   export const isA = (value: Kind) => value === Kind.A
79  /// }
80  /// Kind.isB = (value: Kind) => value === Kind.B
81  /// ```
82  ///
83  /// But for now we only use it for enum exports, if there are issues about json exports then
84  /// we can also apply this to json exports
85  pub unknown_provided: bool,
86}
87
88impl ExportSpecExports {
89  pub fn new(exports: Vec<ExportNameOrSpec>) -> Self {
90    Self {
91      exports,
92      unknown_provided: false,
93    }
94  }
95
96  pub fn with_unknown_provided(mut self, unknown_provided: bool) -> Self {
97    self.unknown_provided = unknown_provided;
98    self
99  }
100}
101
102#[derive(Debug)]
103pub enum Nullable<T> {
104  Null,
105  Value(T),
106}
107
108impl ExportSpec {
109  pub fn new(name: String) -> Self {
110    Self {
111      name: Atom::from(name),
112      ..Default::default()
113    }
114  }
115}
116
117#[derive(Debug)]
118pub enum ExportNameOrSpec {
119  String(Atom),
120  ExportSpec(ExportSpec),
121}
122
123impl Default for ExportNameOrSpec {
124  fn default() -> Self {
125    Self::String(Atom::default())
126  }
127}
128
129#[derive(Debug, Default)]
130pub enum ExportsOfExportsSpec {
131  UnknownExports,
132  #[default]
133  NoExports,
134  Names(Vec<ExportNameOrSpec>),
135}
136
137#[derive(Debug, Default)]
138#[allow(unused)]
139pub struct ExportsSpec {
140  pub exports: ExportsOfExportsSpec,
141  pub priority: Option<u8>,
142  pub can_mangle: Option<bool>,
143  pub terminal_binding: Option<bool>,
144  pub from: Option<ModuleGraphConnection>,
145  pub dependencies: Option<Vec<ModuleIdentifier>>,
146  pub hide_export: Option<FxHashSet<Atom>>,
147  pub exclude_exports: Option<FxHashSet<Atom>>,
148}
149
150impl ExportsSpec {
151  pub fn has_nested_exports(&self) -> bool {
152    match &self.exports {
153      ExportsOfExportsSpec::UnknownExports => false,
154      ExportsOfExportsSpec::NoExports => false,
155      ExportsOfExportsSpec::Names(exports) => exports.iter().any(|name| match name {
156        ExportNameOrSpec::String(_) => false,
157        ExportNameOrSpec::ExportSpec(spec) => spec.exports.is_some(),
158      }),
159    }
160  }
161}
162
163pub trait DependencyConditionFn: Sync + Send {
164  fn get_connection_state(
165    &self,
166    conn: &ModuleGraphConnection,
167    runtime: Option<&RuntimeSpec>,
168    module_graph: &ModuleGraph,
169    module_graph_cache: &ModuleGraphCacheArtifact,
170  ) -> ConnectionState;
171}
172
173#[derive(Clone)]
174pub struct DependencyCondition(Arc<dyn DependencyConditionFn>);
175
176impl DependencyCondition {
177  pub fn new(f: impl DependencyConditionFn + 'static) -> Self {
178    Self(Arc::new(f))
179  }
180
181  pub fn get_connection_state(
182    &self,
183    connection: &ModuleGraphConnection,
184    runtime: Option<&RuntimeSpec>,
185    mg: &ModuleGraph,
186    module_graph_cache: &ModuleGraphCacheArtifact,
187  ) -> ConnectionState {
188    self
189      .0
190      .get_connection_state(connection, runtime, mg, module_graph_cache)
191  }
192}
193
194impl std::fmt::Debug for DependencyCondition {
195  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
196    write!(f, "DependencyCondition(...)")
197  }
198}
199
200#[rspack_cacheable::cacheable]
201#[derive(Debug, Clone, Serialize, Default)]
202pub struct ImportAttributes(FxHashMap<String, String>);
203
204impl FromIterator<(String, String)> for ImportAttributes {
205  fn from_iter<T: IntoIterator<Item = (String, String)>>(iter: T) -> Self {
206    Self(FxHashMap::from_iter(iter))
207  }
208}
209
210impl ImportAttributes {
211  pub fn get(&self, k: &str) -> Option<&str> {
212    self.0.get(k).map(|v| v.as_str())
213  }
214
215  pub fn insert(&mut self, k: String, v: String) -> Option<String> {
216    self.0.insert(k, v)
217  }
218}
219
220#[rspack_cacheable::cacheable]
221#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
222pub enum ImportPhase {
223  #[default]
224  Evaluation,
225  Source,
226  Defer,
227}
228
229impl ImportPhase {
230  pub fn is_defer(&self) -> bool {
231    matches!(self, ImportPhase::Defer)
232  }
233}
234
235impl From<swc_core::ecma::ast::ImportPhase> for ImportPhase {
236  fn from(phase: swc_core::ecma::ast::ImportPhase) -> Self {
237    match phase {
238      swc_core::ecma::ast::ImportPhase::Evaluation => Self::Evaluation,
239      swc_core::ecma::ast::ImportPhase::Source => Self::Source,
240      swc_core::ecma::ast::ImportPhase::Defer => Self::Defer,
241    }
242  }
243}