turbopack/module_options/
module_rule.rs1use std::fmt::Display;
2
3use anyhow::{Result, bail};
4use bincode::{Decode, Encode};
5use turbo_rcstr::RcStr;
6use turbo_tasks::{NonLocalValue, ResolvedVc, trace::TraceRawVcs};
7use turbo_tasks_fs::FileSystemPath;
8use turbopack_core::{
9 environment::Environment, reference_type::ReferenceType, source::Source,
10 source_transform::SourceTransforms,
11};
12use turbopack_css::CssModuleAssetType;
13use turbopack_ecmascript::{EcmascriptInputTransforms, EcmascriptOptions};
14use turbopack_wasm::source::WebAssemblySourceType;
15
16use crate::module_options::{CustomModuleType, RuleCondition, match_mode::MatchMode};
17
18#[derive(Debug, Clone, TraceRawVcs, PartialEq, Eq, NonLocalValue, Encode, Decode)]
19pub struct ModuleRule {
20 condition: RuleCondition,
21 effects: Vec<ModuleRuleEffect>,
22 match_mode: MatchMode,
23}
24
25impl ModuleRule {
26 pub fn new(mut condition: RuleCondition, effects: Vec<ModuleRuleEffect>) -> Self {
28 condition.flatten();
29 ModuleRule {
30 condition,
31 effects,
32 match_mode: MatchMode::NonInternal,
33 }
34 }
35
36 pub fn new_internal(mut condition: RuleCondition, effects: Vec<ModuleRuleEffect>) -> Self {
38 condition.flatten();
39 ModuleRule {
40 condition,
41 effects,
42 match_mode: MatchMode::Internal,
43 }
44 }
45
46 pub fn new_all(mut condition: RuleCondition, effects: Vec<ModuleRuleEffect>) -> Self {
48 condition.flatten();
49 ModuleRule {
50 condition,
51 effects,
52 match_mode: MatchMode::All,
53 }
54 }
55
56 pub fn effects(&self) -> impl Iterator<Item = &ModuleRuleEffect> {
57 self.effects.iter()
58 }
59
60 pub async fn matches(
61 &self,
62 source: ResolvedVc<Box<dyn Source>>,
63 path: &FileSystemPath,
64 reference_type: &ReferenceType,
65 ) -> Result<bool> {
66 Ok(self.match_mode.matches(reference_type)
67 && self.condition.matches(source, path, reference_type).await?)
68 }
69}
70
71#[turbo_tasks::value(shared)]
72#[derive(Debug, Clone)]
73pub enum ModuleRuleEffect {
74 ModuleType(ModuleType),
75 ExtendEcmascriptTransforms {
78 preprocess: ResolvedVc<EcmascriptInputTransforms>,
80 main: ResolvedVc<EcmascriptInputTransforms>,
82 postprocess: ResolvedVc<EcmascriptInputTransforms>,
84 },
85 SourceTransforms(ResolvedVc<SourceTransforms>),
86 Ignore,
87}
88
89#[turbo_tasks::value(shared)]
90#[derive(Hash, Debug, Clone)]
91pub enum ModuleType {
92 Ecmascript {
93 preprocess: ResolvedVc<EcmascriptInputTransforms>,
95 main: ResolvedVc<EcmascriptInputTransforms>,
97 postprocess: ResolvedVc<EcmascriptInputTransforms>,
99 #[turbo_tasks(trace_ignore)]
100 options: ResolvedVc<EcmascriptOptions>,
101 },
102 Typescript {
103 preprocess: ResolvedVc<EcmascriptInputTransforms>,
105 main: ResolvedVc<EcmascriptInputTransforms>,
107 postprocess: ResolvedVc<EcmascriptInputTransforms>,
109 tsx: bool,
111 analyze_types: bool,
113 #[turbo_tasks(trace_ignore)]
114 options: ResolvedVc<EcmascriptOptions>,
115 },
116 TypescriptDeclaration {
117 preprocess: ResolvedVc<EcmascriptInputTransforms>,
119 main: ResolvedVc<EcmascriptInputTransforms>,
121 postprocess: ResolvedVc<EcmascriptInputTransforms>,
123 #[turbo_tasks(trace_ignore)]
124 options: ResolvedVc<EcmascriptOptions>,
125 },
126 EcmascriptExtensionless {
127 preprocess: ResolvedVc<EcmascriptInputTransforms>,
129 main: ResolvedVc<EcmascriptInputTransforms>,
131 postprocess: ResolvedVc<EcmascriptInputTransforms>,
133 #[turbo_tasks(trace_ignore)]
134 options: ResolvedVc<EcmascriptOptions>,
135 },
136 Json,
137 Raw,
138 NodeAddon,
139 CssModule,
140 Css {
141 ty: CssModuleAssetType,
142 environment: Option<ResolvedVc<Environment>>,
143 },
144 StaticUrlJs {
145 tag: Option<RcStr>,
147 },
148 StaticUrlCss {
149 tag: Option<RcStr>,
151 },
152 InlinedBytesJs,
153 WebAssembly {
154 source_ty: WebAssemblySourceType,
155 },
156 Custom(ResolvedVc<Box<dyn CustomModuleType>>),
157}
158
159impl Display for ModuleType {
160 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
161 match self {
162 ModuleType::Ecmascript { .. } => write!(f, "Ecmascript"),
163 ModuleType::Typescript { .. } => write!(f, "Typescript"),
164 ModuleType::TypescriptDeclaration { .. } => write!(f, "TypescriptDeclaration"),
165 ModuleType::EcmascriptExtensionless { .. } => write!(f, "EcmascriptExtensionless"),
166 ModuleType::Json => write!(f, "Json"),
167 ModuleType::Raw => write!(f, "Raw"),
168 ModuleType::NodeAddon => write!(f, "NodeAddon"),
169 ModuleType::CssModule => write!(f, "CssModule"),
170 ModuleType::Css { .. } => write!(f, "Css"),
171 ModuleType::StaticUrlJs { .. } => write!(f, "StaticUrlJs"),
172 ModuleType::StaticUrlCss { .. } => write!(f, "StaticUrlCss"),
173 ModuleType::InlinedBytesJs => write!(f, "InlinedBytesJs"),
174 ModuleType::WebAssembly { .. } => write!(f, "WebAssembly"),
175 ModuleType::Custom(_) => write!(f, "Custom"),
176 }
177 }
178}
179
180impl ModuleType {
181 pub fn from_str_with_defaults(
184 type_str: &str,
185 preprocess: ResolvedVc<EcmascriptInputTransforms>,
186 main: ResolvedVc<EcmascriptInputTransforms>,
187 postprocess: ResolvedVc<EcmascriptInputTransforms>,
188 options: ResolvedVc<EcmascriptOptions>,
189 environment: Option<ResolvedVc<Environment>>,
190 ) -> Result<Self> {
191 Ok(match type_str {
192 "asset" => ModuleType::StaticUrlJs { tag: None },
193 "ecmascript" => ModuleType::Ecmascript {
194 preprocess,
195 main,
196 postprocess,
197 options,
198 },
199 "typescript" => ModuleType::Typescript {
200 preprocess,
201 main,
202 postprocess,
203 tsx: false,
204 analyze_types: false,
205 options,
206 },
207 "css" => ModuleType::Css {
208 ty: CssModuleAssetType::Default,
209 environment,
210 },
211 "css-module" => ModuleType::CssModule,
212 "wasm" => ModuleType::WebAssembly {
213 source_ty: WebAssemblySourceType::Binary,
214 },
215 "raw" => ModuleType::Raw,
216 "node" => ModuleType::NodeAddon,
217 "bytes" => ModuleType::InlinedBytesJs,
218 _ => bail!(
219 "Unknown module type: {type_str:?}. Valid types are: asset, ecmascript, \
220 typescript, css, css-module, wasm, raw, node, bytes"
221 ),
222 })
223 }
224}