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::OutputAssets,
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 chunks(&self) -> Vc<OutputAssets> {
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_chunks(self: ResolvedVc<Self>) -> Result<Vc<OutputAssets>> {
69 let this = self.await?;
70 if let Some(chunk_items) = this.availability_info.available_modules() {
71 let inner_module = ResolvedVc::upcast(this.inner);
72 let batches = this
73 .module_graph
74 .module_batches(this.chunking_context.batching_config())
75 .await?;
76 let module_or_batch = batches.get_entry(inner_module).await?;
77 if let Some(chunkable_module_or_batch) =
78 ChunkableModuleOrBatch::from_module_or_batch(module_or_batch)
79 && *chunk_items.get(chunkable_module_or_batch).await?
80 {
81 return Ok(Vc::cell(vec![]));
82 }
83 }
84 Ok(this.chunking_context.chunk_group_assets(
85 self.ident(),
86 ChunkGroup::Async(ResolvedVc::upcast(self)),
87 *this.module_graph,
88 this.availability_info,
89 ))
90 }
91
92 #[turbo_tasks::function]
93 pub fn module_ident(&self) -> Vc<AssetIdent> {
94 self.inner.ident()
95 }
96
97 #[turbo_tasks::function]
98 pub async fn content_ident(&self) -> Result<Vc<AssetIdent>> {
99 let mut ident = self.inner.ident();
100 if let Some(available_modules) = self.availability_info.available_modules() {
101 ident = ident.with_modifier(available_modules.hash().await?.to_string().into());
102 }
103 Ok(ident)
104 }
105}
106
107fn manifest_chunk_reference_description() -> RcStr {
108 rcstr!("manifest chunk")
109}
110
111#[turbo_tasks::value_impl]
112impl Module for ManifestAsyncModule {
113 #[turbo_tasks::function]
114 fn ident(&self) -> Vc<AssetIdent> {
115 self.inner
116 .ident()
117 .with_modifier(manifest_chunk_reference_description())
118 }
119
120 #[turbo_tasks::function]
121 async fn references(self: Vc<Self>) -> Result<Vc<ModuleReferences>> {
122 let chunks = self.chunks();
123
124 Ok(Vc::cell(
125 chunks
126 .await?
127 .iter()
128 .copied()
129 .map(|chunk| async move {
130 Ok(ResolvedVc::upcast(
131 SingleOutputAssetReference::new(
132 *chunk,
133 manifest_chunk_reference_description(),
134 )
135 .to_resolved()
136 .await?,
137 ))
138 })
139 .try_join()
140 .await?,
141 ))
142 }
143}
144
145#[turbo_tasks::value_impl]
146impl Asset for ManifestAsyncModule {
147 #[turbo_tasks::function]
148 fn content(&self) -> Vc<AssetContent> {
149 panic!("content() should not be called");
150 }
151}
152
153#[turbo_tasks::value_impl]
154impl ChunkableModule for ManifestAsyncModule {
155 #[turbo_tasks::function]
156 fn as_chunk_item(
157 self: ResolvedVc<Self>,
158 _module_graph: Vc<ModuleGraph>,
159 chunking_context: ResolvedVc<Box<dyn ChunkingContext>>,
160 ) -> Vc<Box<dyn turbopack_core::chunk::ChunkItem>> {
161 Vc::upcast(
162 ManifestChunkItem {
163 chunking_context,
164 manifest: self,
165 }
166 .cell(),
167 )
168 }
169}
170
171#[turbo_tasks::value_impl]
172impl EcmascriptChunkPlaceable for ManifestAsyncModule {
173 #[turbo_tasks::function]
174 fn get_exports(&self) -> Vc<EcmascriptExports> {
175 EcmascriptExports::Value.cell()
176 }
177}