turbopack_ecmascript/manifest/
chunk_asset.rs1use anyhow::Result;
2use turbo_rcstr::{RcStr, rcstr};
3use turbo_tasks::{ResolvedVc, TryJoinIterExt, Vc};
4use turbopack_core::{
5 chunk::{
6 ChunkableModule, ChunkingContext, ChunkingContextExt, availability_info::AvailabilityInfo,
7 },
8 ident::AssetIdent,
9 module::{Module, ModuleSideEffects},
10 module_graph::{
11 ModuleGraph, chunk_group_info::ChunkGroup, module_batch::ChunkableModuleOrBatch,
12 },
13 output::OutputAssetsWithReferenced,
14 reference::{ModuleReferences, SingleOutputAssetReference},
15};
16
17use super::chunk_item::ManifestChunkItem;
18use crate::chunk::{EcmascriptChunkPlaceable, EcmascriptExports};
19
20#[turbo_tasks::value(shared)]
32pub struct ManifestAsyncModule {
33 pub inner: ResolvedVc<Box<dyn ChunkableModule>>,
34 pub module_graph: ResolvedVc<ModuleGraph>,
35 pub chunking_context: ResolvedVc<Box<dyn ChunkingContext>>,
36 pub availability_info: AvailabilityInfo,
37}
38
39#[turbo_tasks::value_impl]
40impl ManifestAsyncModule {
41 #[turbo_tasks::function]
42 pub fn new(
43 module: ResolvedVc<Box<dyn ChunkableModule>>,
44 module_graph: ResolvedVc<ModuleGraph>,
45 chunking_context: ResolvedVc<Box<dyn ChunkingContext>>,
46 availability_info: AvailabilityInfo,
47 ) -> Vc<Self> {
48 Self::cell(ManifestAsyncModule {
49 inner: module,
50 module_graph,
51 chunking_context,
52 availability_info,
53 })
54 }
55
56 #[turbo_tasks::function]
57 pub(super) fn chunk_group(&self) -> Vc<OutputAssetsWithReferenced> {
58 self.chunking_context.chunk_group_assets(
59 self.inner.ident(),
60 ChunkGroup::Async(ResolvedVc::upcast(self.inner)),
61 *self.module_graph,
62 self.availability_info,
63 )
64 }
65
66 #[turbo_tasks::function]
67 pub async fn manifest_chunk_group(
68 self: ResolvedVc<Self>,
69 ) -> Result<Vc<OutputAssetsWithReferenced>> {
70 let this = self.await?;
71 if let Some(chunk_items) = this.availability_info.available_modules() {
72 let inner_module = ResolvedVc::upcast(this.inner);
73 let batches = this
74 .module_graph
75 .module_batches(this.chunking_context.batching_config())
76 .await?;
77 let module_or_batch = batches.get_entry(inner_module).await?;
78 if let Some(chunkable_module_or_batch) =
79 ChunkableModuleOrBatch::from_module_or_batch(module_or_batch)
80 && *chunk_items.get(chunkable_module_or_batch.into()).await?
81 {
82 return Ok(OutputAssetsWithReferenced {
83 assets: ResolvedVc::cell(vec![]),
84 referenced_assets: ResolvedVc::cell(vec![]),
85 references: ResolvedVc::cell(vec![]),
86 }
87 .cell());
88 }
89 }
90 Ok(this.chunking_context.chunk_group_assets(
91 self.ident(),
92 ChunkGroup::Async(ResolvedVc::upcast(self)),
93 *this.module_graph,
94 this.availability_info,
95 ))
96 }
97
98 #[turbo_tasks::function]
99 pub fn module_ident(&self) -> Vc<AssetIdent> {
100 self.inner.ident()
101 }
102
103 #[turbo_tasks::function]
104 pub async fn content_ident(&self) -> Result<Vc<AssetIdent>> {
105 let mut ident = self.inner.ident();
106 if let Some(available_modules) = self.availability_info.available_modules() {
107 ident = ident.with_modifier(available_modules.hash().await?.to_string().into());
108 }
109 Ok(ident)
110 }
111}
112
113fn manifest_chunk_reference_description() -> RcStr {
114 rcstr!("manifest chunk")
115}
116
117#[turbo_tasks::value_impl]
118impl Module for ManifestAsyncModule {
119 #[turbo_tasks::function]
120 fn ident(&self) -> Vc<AssetIdent> {
121 self.inner
122 .ident()
123 .with_modifier(manifest_chunk_reference_description())
124 }
125
126 #[turbo_tasks::function]
127 fn source(&self) -> Vc<turbopack_core::source::OptionSource> {
128 Vc::cell(None)
129 }
130
131 #[turbo_tasks::function]
132 async fn references(self: Vc<Self>) -> Result<Vc<ModuleReferences>> {
133 let assets = self.chunk_group().expand_all_assets().await?;
134
135 Ok(Vc::cell(
136 assets
137 .into_iter()
138 .copied()
139 .map(|chunk| async move {
140 Ok(ResolvedVc::upcast(
141 SingleOutputAssetReference::new(
142 *chunk,
143 manifest_chunk_reference_description(),
144 )
145 .to_resolved()
146 .await?,
147 ))
148 })
149 .try_join()
150 .await?,
151 ))
152 }
153
154 #[turbo_tasks::function]
155 fn side_effects(self: Vc<Self>) -> Vc<ModuleSideEffects> {
156 ModuleSideEffects::SideEffectFree.cell()
157 }
158}
159
160#[turbo_tasks::value_impl]
161impl ChunkableModule for ManifestAsyncModule {
162 #[turbo_tasks::function]
163 fn as_chunk_item(
164 self: ResolvedVc<Self>,
165 _module_graph: Vc<ModuleGraph>,
166 chunking_context: ResolvedVc<Box<dyn ChunkingContext>>,
167 ) -> Vc<Box<dyn turbopack_core::chunk::ChunkItem>> {
168 Vc::upcast(
169 ManifestChunkItem {
170 chunking_context,
171 manifest: self,
172 }
173 .cell(),
174 )
175 }
176}
177
178#[turbo_tasks::value_impl]
179impl EcmascriptChunkPlaceable for ManifestAsyncModule {
180 #[turbo_tasks::function]
181 fn get_exports(&self) -> Vc<EcmascriptExports> {
182 EcmascriptExports::Value.cell()
183 }
184}