turbopack_core/reference/
mod.rs1use std::collections::HashSet;
2
3use anyhow::Result;
4use turbo_rcstr::RcStr;
5use turbo_tasks::{
6 FxIndexSet, ReadRef, ResolvedVc, TryFlatJoinIterExt, TryJoinIterExt, ValueToString, Vc,
7 graph::{AdjacencyMap, GraphTraversal},
8};
9
10use crate::{
11 chunk::{ChunkableModuleReference, ChunkingType, ChunkingTypeOption},
12 module::{Module, Modules},
13 output::{OutputAsset, OutputAssets},
14 raw_module::RawModule,
15 resolve::{ExportUsage, ModuleResolveResult, RequestKey},
16};
17pub mod source_map;
18
19pub use source_map::SourceMapReference;
20
21#[turbo_tasks::value_trait]
29pub trait ModuleReference: ValueToString {
30 #[turbo_tasks::function]
31 fn resolve_reference(self: Vc<Self>) -> Vc<ModuleResolveResult>;
32 }
35
36#[turbo_tasks::value(transparent)]
38pub struct ModuleReferences(Vec<ResolvedVc<Box<dyn ModuleReference>>>);
39
40#[turbo_tasks::value_impl]
41impl ModuleReferences {
42 #[turbo_tasks::function]
44 pub fn empty() -> Vc<Self> {
45 Vc::cell(Vec::new())
46 }
47}
48
49#[turbo_tasks::value]
51pub struct SingleModuleReference {
52 asset: ResolvedVc<Box<dyn Module>>,
53 description: RcStr,
54}
55
56#[turbo_tasks::value_impl]
57impl ModuleReference for SingleModuleReference {
58 #[turbo_tasks::function]
59 fn resolve_reference(&self) -> Vc<ModuleResolveResult> {
60 *ModuleResolveResult::module(self.asset)
61 }
62}
63
64#[turbo_tasks::value_impl]
65impl ValueToString for SingleModuleReference {
66 #[turbo_tasks::function]
67 fn to_string(&self) -> Vc<RcStr> {
68 Vc::cell(self.description.clone())
69 }
70}
71
72#[turbo_tasks::value_impl]
73impl SingleModuleReference {
74 #[turbo_tasks::function]
77 pub fn new(asset: ResolvedVc<Box<dyn Module>>, description: RcStr) -> Vc<Self> {
78 Self::cell(SingleModuleReference { asset, description })
79 }
80
81 #[turbo_tasks::function]
83 pub fn asset(&self) -> Vc<Box<dyn Module>> {
84 *self.asset
85 }
86}
87
88#[turbo_tasks::value]
89pub struct SingleChunkableModuleReference {
90 asset: ResolvedVc<Box<dyn Module>>,
91 description: RcStr,
92 export: ResolvedVc<ExportUsage>,
93}
94
95#[turbo_tasks::value_impl]
96impl SingleChunkableModuleReference {
97 #[turbo_tasks::function]
98 pub fn new(
99 asset: ResolvedVc<Box<dyn Module>>,
100 description: RcStr,
101 export: ResolvedVc<ExportUsage>,
102 ) -> Vc<Self> {
103 Self::cell(SingleChunkableModuleReference {
104 asset,
105 description,
106 export,
107 })
108 }
109}
110
111#[turbo_tasks::value_impl]
112impl ChunkableModuleReference for SingleChunkableModuleReference {
113 #[turbo_tasks::function]
114 fn chunking_type(self: Vc<Self>) -> Vc<ChunkingTypeOption> {
115 Vc::cell(Some(ChunkingType::Parallel {
116 inherit_async: true,
117 hoisted: false,
118 }))
119 }
120
121 #[turbo_tasks::function]
122 fn export_usage(&self) -> Vc<ExportUsage> {
123 *self.export
124 }
125}
126
127#[turbo_tasks::value_impl]
128impl ModuleReference for SingleChunkableModuleReference {
129 #[turbo_tasks::function]
130 fn resolve_reference(&self) -> Vc<ModuleResolveResult> {
131 *ModuleResolveResult::module(self.asset)
132 }
133}
134
135#[turbo_tasks::value_impl]
136impl ValueToString for SingleChunkableModuleReference {
137 #[turbo_tasks::function]
138 fn to_string(&self) -> Vc<RcStr> {
139 Vc::cell(self.description.clone())
140 }
141}
142
143#[turbo_tasks::value]
145pub struct SingleOutputAssetReference {
146 asset: ResolvedVc<Box<dyn OutputAsset>>,
147 description: RcStr,
148}
149
150#[turbo_tasks::value_impl]
151impl ModuleReference for SingleOutputAssetReference {
152 #[turbo_tasks::function]
153 fn resolve_reference(&self) -> Vc<ModuleResolveResult> {
154 *ModuleResolveResult::output_asset(RequestKey::default(), self.asset)
155 }
156}
157
158#[turbo_tasks::value_impl]
159impl ValueToString for SingleOutputAssetReference {
160 #[turbo_tasks::function]
161 fn to_string(&self) -> Vc<RcStr> {
162 Vc::cell(self.description.clone())
163 }
164}
165
166#[turbo_tasks::value_impl]
167impl SingleOutputAssetReference {
168 #[turbo_tasks::function]
171 pub fn new(asset: ResolvedVc<Box<dyn OutputAsset>>, description: RcStr) -> Vc<Self> {
172 Self::cell(SingleOutputAssetReference { asset, description })
173 }
174
175 #[turbo_tasks::function]
177 pub fn asset(&self) -> Vc<Box<dyn OutputAsset>> {
178 *self.asset
179 }
180}
181
182#[turbo_tasks::function]
188pub async fn referenced_modules_and_affecting_sources(
189 module: Vc<Box<dyn Module>>,
190) -> Result<Vc<Modules>> {
191 let references = module.references().await?;
192
193 let resolved_references = references
194 .iter()
195 .map(|r| r.resolve_reference())
196 .try_join()
197 .await?;
198 let mut modules = Vec::new();
199 for resolve_result in resolved_references {
200 modules.extend(resolve_result.primary_modules_raw_iter());
201 modules.extend(
202 resolve_result
203 .affecting_sources_iter()
204 .map(|source| async move {
205 Ok(ResolvedVc::upcast(
206 RawModule::new(*source).to_resolved().await?,
207 ))
208 })
209 .try_join()
210 .await?,
211 );
212 }
213
214 let resolved_modules: FxIndexSet<_> = modules.into_iter().collect();
215
216 Ok(Vc::cell(resolved_modules.into_iter().collect()))
217}
218
219#[turbo_tasks::value]
220pub struct TracedModuleReference {
221 module: ResolvedVc<Box<dyn Module>>,
222}
223
224#[turbo_tasks::value_impl]
225impl ModuleReference for TracedModuleReference {
226 #[turbo_tasks::function]
227 fn resolve_reference(&self) -> Vc<ModuleResolveResult> {
228 *ModuleResolveResult::module(self.module)
229 }
230}
231
232#[turbo_tasks::value_impl]
233impl ValueToString for TracedModuleReference {
234 #[turbo_tasks::function]
235 async fn to_string(&self) -> Result<Vc<RcStr>> {
236 Ok(Vc::cell(
237 format!("traced {}", self.module.ident().to_string().await?).into(),
238 ))
239 }
240}
241
242#[turbo_tasks::value_impl]
243impl ChunkableModuleReference for TracedModuleReference {
244 #[turbo_tasks::function]
245 fn chunking_type(&self) -> Vc<ChunkingTypeOption> {
246 Vc::cell(Some(ChunkingType::Traced))
247 }
248}
249
250#[turbo_tasks::value_impl]
251impl TracedModuleReference {
252 #[turbo_tasks::function]
253 pub fn new(module: ResolvedVc<Box<dyn Module>>) -> Vc<Self> {
254 Self::cell(TracedModuleReference { module })
255 }
256}
257
258#[turbo_tasks::function]
264pub async fn primary_referenced_modules(module: Vc<Box<dyn Module>>) -> Result<Vc<Modules>> {
265 let mut set = HashSet::new();
266 let modules = module
267 .references()
268 .await?
269 .iter()
270 .map(|reference| async {
271 reference
272 .resolve_reference()
273 .resolve()
274 .await?
275 .primary_modules()
276 .owned()
277 .await
278 })
279 .try_join()
280 .await?
281 .into_iter()
282 .flatten()
283 .filter(|&module| set.insert(module))
284 .collect();
285 Ok(Vc::cell(modules))
286}
287
288#[turbo_tasks::value(transparent)]
289pub struct ModulesWithRefData(Vec<(ChunkingType, ExportUsage, ReadRef<Modules>)>);
290
291#[turbo_tasks::function]
297pub async fn primary_chunkable_referenced_modules(
298 module: ResolvedVc<Box<dyn Module>>,
299 include_traced: bool,
300) -> Result<Vc<ModulesWithRefData>> {
301 let modules = module
302 .references()
303 .await?
304 .iter()
305 .map(|reference| async {
306 if let Some(reference) =
307 ResolvedVc::try_downcast::<Box<dyn ChunkableModuleReference>>(*reference)
308 && let Some(chunking_type) = &*reference.chunking_type().await?
309 {
310 if !include_traced && matches!(chunking_type, ChunkingType::Traced) {
311 return Ok(None);
312 }
313
314 let resolved = reference
315 .resolve_reference()
316 .resolve()
317 .await?
318 .primary_modules()
319 .await?;
320 let export = reference.export_usage().owned().await?;
321
322 return Ok(Some((chunking_type.clone(), export, resolved)));
323 }
324 Ok(None)
325 })
326 .try_flat_join()
327 .await?;
328 Ok(Vc::cell(modules))
329}
330
331#[turbo_tasks::function]
334pub async fn all_assets_from_entries(entries: Vc<OutputAssets>) -> Result<Vc<OutputAssets>> {
335 Ok(Vc::cell(
336 AdjacencyMap::new()
337 .skip_duplicates()
338 .visit(
339 entries.await?.iter().copied().map(ResolvedVc::upcast),
340 get_referenced_assets,
341 )
342 .await
343 .completed()?
344 .into_inner()
345 .into_postorder_topological()
346 .collect(),
347 ))
348}
349
350pub async fn get_referenced_assets(
352 asset: ResolvedVc<Box<dyn OutputAsset>>,
353) -> Result<impl Iterator<Item = ResolvedVc<Box<dyn OutputAsset>>> + Send> {
354 Ok(asset
355 .references()
356 .await?
357 .iter()
358 .copied()
359 .collect::<Vec<_>>()
360 .into_iter())
361}