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,
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).await?
82 {
83 return Ok(OutputAssetsWithReferenced {
84 assets: ResolvedVc::cell(vec![]),
85 referenced_assets: 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 async fn references(self: Vc<Self>) -> Result<Vc<ModuleReferences>> {
128 let assets = self.chunk_group().all_assets().await?;
129
130 Ok(Vc::cell(
131 assets
132 .into_iter()
133 .copied()
134 .map(|chunk| async move {
135 Ok(ResolvedVc::upcast(
136 SingleOutputAssetReference::new(
137 *chunk,
138 manifest_chunk_reference_description(),
139 )
140 .to_resolved()
141 .await?,
142 ))
143 })
144 .try_join()
145 .await?,
146 ))
147 }
148}
149
150#[turbo_tasks::value_impl]
151impl Asset for ManifestAsyncModule {
152 #[turbo_tasks::function]
153 fn content(&self) -> Vc<AssetContent> {
154 panic!("content() should not be called");
155 }
156}
157
158#[turbo_tasks::value_impl]
159impl ChunkableModule for ManifestAsyncModule {
160 #[turbo_tasks::function]
161 fn as_chunk_item(
162 self: ResolvedVc<Self>,
163 _module_graph: Vc<ModuleGraph>,
164 chunking_context: ResolvedVc<Box<dyn ChunkingContext>>,
165 ) -> Vc<Box<dyn turbopack_core::chunk::ChunkItem>> {
166 Vc::upcast(
167 ManifestChunkItem {
168 chunking_context,
169 manifest: self,
170 }
171 .cell(),
172 )
173 }
174}
175
176#[turbo_tasks::value_impl]
177impl EcmascriptChunkPlaceable for ManifestAsyncModule {
178 #[turbo_tasks::function]
179 fn get_exports(&self) -> Vc<EcmascriptExports> {
180 EcmascriptExports::Value.cell()
181 }
182}