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