turbopack_ecmascript/manifest/
chunk_asset.rs1use anyhow::Result;
2use turbo_rcstr::RcStr;
3use turbo_tasks::{ResolvedVc, TryJoinIterExt, Value, 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::function]
22fn modifier() -> Vc<RcStr> {
23 Vc::cell("manifest chunk".into())
24}
25
26#[turbo_tasks::value(shared)]
38pub struct ManifestAsyncModule {
39 pub inner: ResolvedVc<Box<dyn ChunkableModule>>,
40 pub module_graph: ResolvedVc<ModuleGraph>,
41 pub chunking_context: ResolvedVc<Box<dyn ChunkingContext>>,
42 pub availability_info: AvailabilityInfo,
43}
44
45#[turbo_tasks::value_impl]
46impl ManifestAsyncModule {
47 #[turbo_tasks::function]
48 pub async fn new(
49 module: ResolvedVc<Box<dyn ChunkableModule>>,
50 module_graph: ResolvedVc<ModuleGraph>,
51 chunking_context: ResolvedVc<Box<dyn ChunkingContext>>,
52 availability_info: Value<AvailabilityInfo>,
53 ) -> Vc<Self> {
54 Self::cell(ManifestAsyncModule {
55 inner: module,
56 module_graph,
57 chunking_context,
58 availability_info: availability_info.into_value(),
59 })
60 }
61
62 #[turbo_tasks::function]
63 pub(super) fn chunks(&self) -> Vc<OutputAssets> {
64 self.chunking_context.chunk_group_assets(
65 self.inner.ident(),
66 ChunkGroup::Async(ResolvedVc::upcast(self.inner)),
67 *self.module_graph,
68 Value::new(self.availability_info),
69 )
70 }
71
72 #[turbo_tasks::function]
73 pub async fn manifest_chunks(self: ResolvedVc<Self>) -> Result<Vc<OutputAssets>> {
74 let this = self.await?;
75 if let Some(chunk_items) = this.availability_info.available_modules() {
76 let inner_module = ResolvedVc::upcast(this.inner);
77 let batches = this
78 .module_graph
79 .module_batches(this.chunking_context.batching_config())
80 .await?;
81 let module_or_batch = batches.get_entry(inner_module).await?;
82 if let Some(chunkable_module_or_batch) =
83 ChunkableModuleOrBatch::from_module_or_batch(module_or_batch)
84 {
85 if *chunk_items.get(chunkable_module_or_batch).await? {
86 return Ok(Vc::cell(vec![]));
87 }
88 }
89 }
90 Ok(this.chunking_context.chunk_group_assets(
91 self.ident(),
92 ChunkGroup::Async(ResolvedVc::upcast(self)),
93 *this.module_graph,
94 Value::new(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 =
108 ident.with_modifier(Vc::cell(available_modules.hash().await?.to_string().into()));
109 }
110 Ok(ident)
111 }
112}
113
114#[turbo_tasks::function]
115fn manifest_chunk_reference_description() -> Vc<RcStr> {
116 Vc::cell("manifest chunk".into())
117}
118
119#[turbo_tasks::value_impl]
120impl Module for ManifestAsyncModule {
121 #[turbo_tasks::function]
122 fn ident(&self) -> Vc<AssetIdent> {
123 self.inner.ident().with_modifier(modifier())
124 }
125
126 #[turbo_tasks::function]
127 async fn references(self: Vc<Self>) -> Result<Vc<ModuleReferences>> {
128 let chunks = self.chunks();
129
130 Ok(Vc::cell(
131 chunks
132 .await?
133 .iter()
134 .copied()
135 .map(|chunk| async move {
136 Ok(ResolvedVc::upcast(
137 SingleOutputAssetReference::new(
138 *chunk,
139 manifest_chunk_reference_description(),
140 )
141 .to_resolved()
142 .await?,
143 ))
144 })
145 .try_join()
146 .await?,
147 ))
148 }
149}
150
151#[turbo_tasks::value_impl]
152impl Asset for ManifestAsyncModule {
153 #[turbo_tasks::function]
154 fn content(&self) -> Vc<AssetContent> {
155 panic!("content() should not be called");
156 }
157}
158
159#[turbo_tasks::value_impl]
160impl ChunkableModule for ManifestAsyncModule {
161 #[turbo_tasks::function]
162 async fn as_chunk_item(
163 self: ResolvedVc<Self>,
164 _module_graph: Vc<ModuleGraph>,
165 chunking_context: ResolvedVc<Box<dyn ChunkingContext>>,
166 ) -> Vc<Box<dyn turbopack_core::chunk::ChunkItem>> {
167 Vc::upcast(
168 ManifestChunkItem {
169 chunking_context,
170 manifest: self,
171 }
172 .cell(),
173 )
174 }
175}
176
177#[turbo_tasks::value_impl]
178impl EcmascriptChunkPlaceable for ManifestAsyncModule {
179 #[turbo_tasks::function]
180 fn get_exports(&self) -> Vc<EcmascriptExports> {
181 EcmascriptExports::Value.cell()
182 }
183}