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