turbopack_core/reference/
mod.rs1use std::collections::HashSet;
2
3use anyhow::Result;
4use bincode::{Decode, Encode};
5use turbo_rcstr::RcStr;
6use turbo_tasks::{
7 FxIndexSet, NonLocalValue, ResolvedVc, TryFlatJoinIterExt, TryJoinIterExt, ValueToString, Vc,
8 debug::ValueDebugFormat, trace::TraceRawVcs,
9};
10
11use crate::{
12 chunk::ChunkingType,
13 module::{Module, Modules},
14 output::{
15 ExpandOutputAssetsInput, ExpandedOutputAssets, OutputAsset, OutputAssets,
16 expand_output_assets,
17 },
18 raw_module::RawModule,
19 resolve::{BindingUsage, ExportUsage, ImportUsage, ModuleResolveResult, RequestKey},
20};
21pub mod source_map;
22
23pub use source_map::SourceMapReference;
24
25#[turbo_tasks::value_trait]
31pub trait ModuleReference: ValueToString {
32 #[turbo_tasks::function]
33 fn resolve_reference(self: Vc<Self>) -> Vc<ModuleResolveResult>;
34 fn chunking_type(&self) -> Option<ChunkingType> {
38 None
39 }
40
41 fn binding_usage(&self) -> BindingUsage {
42 BindingUsage::default()
43 }
44}
45
46#[turbo_tasks::value(transparent)]
48pub struct ModuleReferences(Vec<ResolvedVc<Box<dyn ModuleReference>>>);
49
50#[turbo_tasks::value_impl]
51impl ModuleReferences {
52 #[turbo_tasks::function]
54 pub fn empty() -> Vc<Self> {
55 Vc::cell(Vec::new())
56 }
57}
58
59#[turbo_tasks::value]
61#[derive(ValueToString)]
62#[value_to_string(self.description)]
63pub struct SingleModuleReference {
64 asset: ResolvedVc<Box<dyn Module>>,
65 description: RcStr,
66}
67
68#[turbo_tasks::value_impl]
69impl ModuleReference for SingleModuleReference {
70 #[turbo_tasks::function]
71 fn resolve_reference(&self) -> Vc<ModuleResolveResult> {
72 *ModuleResolveResult::module(self.asset)
73 }
74}
75
76#[turbo_tasks::value_impl]
77impl SingleModuleReference {
78 #[turbo_tasks::function]
81 pub fn new(asset: ResolvedVc<Box<dyn Module>>, description: RcStr) -> Vc<Self> {
82 Self::cell(SingleModuleReference { asset, description })
83 }
84
85 #[turbo_tasks::function]
87 pub fn asset(&self) -> Vc<Box<dyn Module>> {
88 *self.asset
89 }
90}
91
92#[turbo_tasks::value]
93#[derive(ValueToString)]
94#[value_to_string(self.description)]
95pub struct SingleChunkableModuleReference {
96 asset: ResolvedVc<Box<dyn Module>>,
97 description: RcStr,
98 export: ExportUsage,
99}
100
101#[turbo_tasks::value_impl]
102impl SingleChunkableModuleReference {
103 #[turbo_tasks::function]
104 pub async fn new(
105 asset: ResolvedVc<Box<dyn Module>>,
106 description: RcStr,
107 export: Vc<ExportUsage>,
108 ) -> Result<Vc<Self>> {
109 Ok(Self::cell(SingleChunkableModuleReference {
110 asset,
111 description,
112 export: export.owned().await?,
113 }))
114 }
115}
116
117#[turbo_tasks::value_impl]
118impl ModuleReference for SingleChunkableModuleReference {
119 #[turbo_tasks::function]
120 fn resolve_reference(&self) -> Vc<ModuleResolveResult> {
121 *ModuleResolveResult::module(self.asset)
122 }
123
124 fn chunking_type(&self) -> Option<ChunkingType> {
125 Some(ChunkingType::Parallel {
126 inherit_async: true,
127 hoisted: false,
128 })
129 }
130
131 fn binding_usage(&self) -> BindingUsage {
132 BindingUsage {
133 import: ImportUsage::TopLevel,
134 export: self.export.clone(),
135 }
136 }
137}
138
139#[turbo_tasks::value]
141#[derive(ValueToString)]
142#[value_to_string(self.description)]
143pub struct SingleOutputAssetReference {
144 asset: ResolvedVc<Box<dyn OutputAsset>>,
145 description: RcStr,
146}
147
148#[turbo_tasks::value_impl]
149impl ModuleReference for SingleOutputAssetReference {
150 #[turbo_tasks::function]
151 fn resolve_reference(&self) -> Vc<ModuleResolveResult> {
152 *ModuleResolveResult::output_asset(RequestKey::default(), self.asset)
153 }
154}
155
156#[turbo_tasks::value_impl]
157impl SingleOutputAssetReference {
158 #[turbo_tasks::function]
161 pub fn new(asset: ResolvedVc<Box<dyn OutputAsset>>, description: RcStr) -> Vc<Self> {
162 Self::cell(SingleOutputAssetReference { asset, description })
163 }
164
165 #[turbo_tasks::function]
167 pub fn asset(&self) -> Vc<Box<dyn OutputAsset>> {
168 *self.asset
169 }
170}
171
172#[turbo_tasks::function]
178pub async fn referenced_modules_and_affecting_sources(
179 module: Vc<Box<dyn Module>>,
180) -> Result<Vc<Modules>> {
181 let references = module.references().await?;
182
183 let resolved_references = references
184 .iter()
185 .map(|r| r.resolve_reference())
186 .try_join()
187 .await?;
188 let mut modules = Vec::new();
189 for resolve_result in resolved_references {
190 modules.extend(resolve_result.primary_modules_raw_iter());
191 modules.extend(
192 resolve_result
193 .affecting_sources_iter()
194 .map(|source| async move {
195 Ok(ResolvedVc::upcast(
196 RawModule::new(*source).to_resolved().await?,
197 ))
198 })
199 .try_join()
200 .await?,
201 );
202 }
203
204 let resolved_modules: FxIndexSet<_> = modules.into_iter().collect();
205
206 Ok(Vc::cell(resolved_modules.into_iter().collect()))
207}
208
209#[turbo_tasks::value]
210#[derive(ValueToString)]
211#[value_to_string("traced {}", self.module.ident())]
212pub struct TracedModuleReference {
213 module: ResolvedVc<Box<dyn Module>>,
214}
215
216#[turbo_tasks::value_impl]
217impl ModuleReference for TracedModuleReference {
218 #[turbo_tasks::function]
219 fn resolve_reference(&self) -> Vc<ModuleResolveResult> {
220 *ModuleResolveResult::module(self.module)
221 }
222
223 fn chunking_type(&self) -> Option<ChunkingType> {
224 Some(ChunkingType::Traced)
225 }
226}
227
228#[turbo_tasks::value_impl]
229impl TracedModuleReference {
230 #[turbo_tasks::function]
231 pub fn new(module: ResolvedVc<Box<dyn Module>>) -> Vc<Self> {
232 Self::cell(TracedModuleReference { module })
233 }
234}
235
236#[turbo_tasks::function]
242pub async fn primary_referenced_modules(module: Vc<Box<dyn Module>>) -> Result<Vc<Modules>> {
243 let mut set = HashSet::new();
244 let modules = module
245 .references()
246 .await?
247 .iter()
248 .map(|reference| async {
249 reference
250 .resolve_reference()
251 .resolve()
252 .await?
253 .primary_modules()
254 .owned()
255 .await
256 })
257 .try_join()
258 .await?
259 .into_iter()
260 .flatten()
261 .filter(|&module| set.insert(module))
262 .collect();
263 Ok(Vc::cell(modules))
264}
265
266#[derive(Clone, Eq, PartialEq, ValueDebugFormat, TraceRawVcs, NonLocalValue, Encode, Decode)]
267pub struct ResolvedReference {
268 pub chunking_type: ChunkingType,
269 pub binding_usage: BindingUsage,
270 pub modules: Vec<ResolvedVc<Box<dyn Module>>>,
271}
272
273#[turbo_tasks::value(transparent)]
274pub struct ModulesWithRefData(Vec<(ResolvedVc<Box<dyn ModuleReference>>, ResolvedReference)>);
275
276#[turbo_tasks::function]
282pub async fn primary_chunkable_referenced_modules(
283 module: ResolvedVc<Box<dyn Module>>,
284 include_traced: bool,
285 include_binding_usage: bool,
286) -> Result<Vc<ModulesWithRefData>> {
287 let modules = module
288 .references()
289 .await?
290 .iter()
291 .map(|reference| async {
292 let trait_ref = reference.into_trait_ref().await?;
293 if let Some(chunking_type) = &trait_ref.chunking_type() {
294 if !include_traced && matches!(chunking_type, ChunkingType::Traced) {
295 return Ok(None);
296 }
297
298 let resolved = reference
299 .resolve_reference()
300 .await?
301 .primary_modules_ref()
302 .await?;
303 let binding_usage = if include_binding_usage {
304 trait_ref.binding_usage()
305 } else {
306 BindingUsage::default()
307 };
308
309 return Ok(Some((
310 *reference,
311 ResolvedReference {
312 chunking_type: chunking_type.clone(),
313 binding_usage,
314 modules: resolved,
315 },
316 )));
317 }
318 Ok(None)
319 })
320 .try_flat_join()
321 .await?;
322 Ok(Vc::cell(modules))
323}
324
325#[turbo_tasks::function]
328pub async fn all_assets_from_entries(
329 entries: Vc<OutputAssets>,
330) -> Result<Vc<ExpandedOutputAssets>> {
331 Ok(Vc::cell(
332 expand_output_assets(
333 entries
334 .await?
335 .into_iter()
336 .map(|&asset| ExpandOutputAssetsInput::Asset(asset)),
337 true,
338 )
339 .await?,
340 ))
341}
342
343#[turbo_tasks::function]
346pub async fn all_assets_from_entry(
347 entry: ResolvedVc<Box<dyn OutputAsset>>,
348) -> Result<Vc<ExpandedOutputAssets>> {
349 Ok(Vc::cell(
350 expand_output_assets(std::iter::once(ExpandOutputAssetsInput::Asset(entry)), true).await?,
351 ))
352}