turbopack_ecmascript/chunk/
mod.rs1pub(crate) mod batch;
2pub(crate) mod chunk_type;
3pub(crate) mod code_and_ids;
4pub(crate) mod content;
5pub(crate) mod data;
6pub(crate) mod item;
7pub(crate) mod placeable;
8
9use std::fmt::Write;
10
11use anyhow::Result;
12use turbo_rcstr::RcStr;
13use turbo_tasks::{ResolvedVc, TryFlatJoinIterExt, TryJoinIterExt, Value, ValueToString, Vc};
14use turbo_tasks_fs::FileSystem;
15use turbopack_core::{
16 chunk::{Chunk, ChunkItem, ChunkItems, ChunkingContext, ModuleIds},
17 ident::AssetIdent,
18 introspect::{
19 Introspectable, IntrospectableChildren, module::IntrospectableModule,
20 utils::children_from_output_assets,
21 },
22 output::{OutputAsset, OutputAssets},
23 server_fs::ServerFileSystem,
24};
25
26pub use self::{
27 batch::{
28 EcmascriptChunkBatchWithAsyncInfo, EcmascriptChunkItemBatchGroup,
29 EcmascriptChunkItemOrBatchWithAsyncInfo,
30 },
31 chunk_type::EcmascriptChunkType,
32 code_and_ids::{BatchGroupCodeAndIds, CodeAndIds, batch_group_code_and_ids, item_code_and_ids},
33 content::EcmascriptChunkContent,
34 data::EcmascriptChunkData,
35 item::{
36 EcmascriptChunkItem, EcmascriptChunkItemContent, EcmascriptChunkItemExt,
37 EcmascriptChunkItemOptions, EcmascriptChunkItemWithAsyncInfo,
38 },
39 placeable::{EcmascriptChunkPlaceable, EcmascriptExports},
40};
41
42#[turbo_tasks::value]
43pub struct EcmascriptChunk {
44 pub chunking_context: ResolvedVc<Box<dyn ChunkingContext>>,
45 pub content: ResolvedVc<EcmascriptChunkContent>,
46}
47
48#[turbo_tasks::value_impl]
49impl EcmascriptChunk {
50 #[turbo_tasks::function]
51 pub fn new(
52 chunking_context: ResolvedVc<Box<dyn ChunkingContext>>,
53 content: ResolvedVc<EcmascriptChunkContent>,
54 ) -> Vc<Self> {
55 EcmascriptChunk {
56 chunking_context,
57 content,
58 }
59 .cell()
60 }
61
62 #[turbo_tasks::function]
63 pub fn entry_ids(self: Vc<Self>) -> Vc<ModuleIds> {
64 Vc::cell(Default::default())
66 }
67}
68
69#[turbo_tasks::function]
70fn chunk_item_key() -> Vc<RcStr> {
71 Vc::cell("chunk item".into())
72}
73
74#[turbo_tasks::function]
75fn availability_root_key() -> Vc<RcStr> {
76 Vc::cell("current_availability_root".into())
77}
78
79#[turbo_tasks::value_impl]
80impl Chunk for EcmascriptChunk {
81 #[turbo_tasks::function]
82 async fn ident(&self) -> Result<Vc<AssetIdent>> {
83 let chunk_items = &*self.content.included_chunk_items().await?;
84 let mut common_path = if let Some(chunk_item) = chunk_items.first() {
85 let path = chunk_item.asset_ident().path().to_resolved().await?;
86 Some((path, path.await?))
87 } else {
88 None
89 };
90
91 for &chunk_item in chunk_items.iter() {
93 if let Some((common_path_vc, common_path_ref)) = common_path.as_mut() {
94 let path = chunk_item.asset_ident().path().await?;
95 while !path.is_inside_or_equal_ref(common_path_ref) {
96 let parent = common_path_vc.parent().to_resolved().await?;
97 if parent == *common_path_vc {
98 common_path = None;
99 break;
100 }
101 *common_path_vc = parent;
102 *common_path_ref = (*common_path_vc).await?;
103 }
104 }
105 }
106
107 let chunk_item_key = chunk_item_key().to_resolved().await?;
108 let assets = chunk_items
109 .iter()
110 .map(|&chunk_item| async move {
111 Ok((
112 chunk_item_key,
113 chunk_item.content_ident().to_resolved().await?,
114 ))
115 })
116 .try_join()
117 .await?;
118
119 let ident = AssetIdent {
120 path: if let Some((common_path, _)) = common_path {
121 common_path
122 } else {
123 ServerFileSystem::new().root().to_resolved().await?
124 },
125 query: ResolvedVc::cell(RcStr::default()),
126 fragment: None,
127 assets,
128 modifiers: Vec::new(),
129 parts: Vec::new(),
130 layer: None,
131 content_type: None,
132 };
133
134 Ok(AssetIdent::new(Value::new(ident)))
135 }
136
137 #[turbo_tasks::function]
138 fn chunking_context(&self) -> Vc<Box<dyn ChunkingContext>> {
139 *ResolvedVc::upcast(self.chunking_context)
140 }
141
142 #[turbo_tasks::function]
143 async fn references(&self) -> Result<Vc<OutputAssets>> {
144 let content = self.content.await?;
145 let mut referenced_output_assets: Vec<ResolvedVc<Box<dyn OutputAsset>>> = content
146 .chunk_items
147 .iter()
148 .map(async |with_info| Ok(with_info.references().await?.into_iter().copied()))
149 .try_flat_join()
150 .await?;
151 referenced_output_assets.extend(content.referenced_output_assets.iter().copied());
152 Ok(Vc::cell(referenced_output_assets))
153 }
154
155 #[turbo_tasks::function]
156 async fn chunk_items(&self) -> Vc<ChunkItems> {
157 self.content.included_chunk_items()
158 }
159}
160
161#[turbo_tasks::value_impl]
162impl ValueToString for EcmascriptChunk {
163 #[turbo_tasks::function]
164 async fn to_string(self: Vc<Self>) -> Result<Vc<RcStr>> {
165 Ok(Vc::cell(
166 format!("chunk {}", self.ident().to_string().await?).into(),
167 ))
168 }
169}
170
171#[turbo_tasks::value_impl]
172impl EcmascriptChunk {
173 #[turbo_tasks::function]
174 pub fn chunk_content(&self) -> Vc<EcmascriptChunkContent> {
175 *self.content
176 }
177}
178
179#[turbo_tasks::function]
180fn introspectable_type() -> Vc<RcStr> {
181 Vc::cell("ecmascript chunk".into())
182}
183
184#[turbo_tasks::function]
185fn chunk_item_module_key() -> Vc<RcStr> {
186 Vc::cell("module".into())
187}
188
189#[turbo_tasks::value_impl]
190impl Introspectable for EcmascriptChunk {
191 #[turbo_tasks::function]
192 fn ty(&self) -> Vc<RcStr> {
193 introspectable_type()
194 }
195
196 #[turbo_tasks::function]
197 fn title(self: Vc<Self>) -> Vc<RcStr> {
198 self.ident().to_string()
199 }
200
201 #[turbo_tasks::function]
202 async fn details(self: Vc<Self>) -> Result<Vc<RcStr>> {
203 let mut details = String::new();
204 let this = self.await?;
205 details += "Chunk items:\n\n";
206 for chunk_item in this.content.included_chunk_items().await? {
207 writeln!(details, "- {}", chunk_item.asset_ident().to_string().await?)?;
208 }
209 Ok(Vc::cell(details.into()))
210 }
211
212 #[turbo_tasks::function]
213 async fn children(self: Vc<Self>) -> Result<Vc<IntrospectableChildren>> {
214 let mut children = children_from_output_assets(self.references())
215 .owned()
216 .await?;
217 let chunk_item_module_key = chunk_item_module_key().to_resolved().await?;
218 for chunk_item in self.await?.content.included_chunk_items().await? {
219 children.insert((
220 chunk_item_module_key,
221 IntrospectableModule::new(chunk_item.module())
222 .to_resolved()
223 .await?,
224 ));
225 }
226 Ok(Vc::cell(children))
227 }
228}