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, Chunks, 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::{CjsStaticExports, 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 pub component_chunks: Vec<ResolvedVc<Box<dyn Chunk>>>,
52}
53
54#[turbo_tasks::value_impl]
55impl EcmascriptChunk {
56 #[turbo_tasks::function]
57 pub fn new(
58 chunking_context: ResolvedVc<Box<dyn ChunkingContext>>,
59 content: ResolvedVc<EcmascriptChunkContent>,
60 component_chunks: Vec<ResolvedVc<Box<dyn Chunk>>>,
61 ) -> Vc<Self> {
62 EcmascriptChunk {
63 chunking_context,
64 content,
65 component_chunks,
66 }
67 .cell()
68 }
69
70 #[turbo_tasks::function]
71 pub fn component_chunks(&self) -> Vc<Chunks> {
72 Vc::cell(self.component_chunks.clone())
73 }
74
75 #[turbo_tasks::function]
76 pub fn entry_ids(self: Vc<Self>) -> Vc<ModuleIds> {
77 Vc::cell(Default::default())
79 }
80}
81
82#[turbo_tasks::value_impl]
83impl OutputAssetsReference for EcmascriptChunk {
84 #[turbo_tasks::function]
85 async fn references(&self) -> Result<Vc<OutputAssetsWithReferenced>> {
86 let content = self.content.await?;
87 let references = content
88 .chunk_items
89 .iter()
90 .map(async |with_info| {
91 let r = with_info.references().await?;
92 Ok((
93 r.assets.await?,
94 r.referenced_assets.await?,
95 r.references.await?,
96 ))
97 })
98 .try_join()
99 .await?;
100 Ok(OutputAssetsWithReferenced {
101 assets: ResolvedVc::cell(
102 references
103 .iter()
104 .flat_map(|(assets, _, _)| assets.into_iter().copied())
105 .collect(),
106 ),
107 referenced_assets: ResolvedVc::cell(
108 references
109 .iter()
110 .flat_map(|(_, referenced_assets, _)| referenced_assets.into_iter().copied())
111 .collect(),
112 ),
113 references: ResolvedVc::cell(
114 references
115 .iter()
116 .flat_map(|(_, _, references)| references.into_iter().copied())
117 .collect(),
118 ),
119 }
120 .cell())
121 }
122}
123
124#[turbo_tasks::value_impl]
125impl Chunk for EcmascriptChunk {
126 #[turbo_tasks::function]
127 async fn ident(&self) -> Result<Vc<AssetIdent>> {
128 let chunk_items = &*self.content.included_chunk_items().await?;
129 let mut common_path = if let Some(chunk_item) = chunk_items.first() {
130 let path = chunk_item.asset_ident().await?.path.clone();
131 Some(path)
132 } else {
133 None
134 };
135
136 for &chunk_item in chunk_items.iter() {
138 if let Some(common_path_ref) = common_path.as_mut() {
139 let path = &chunk_item.asset_ident().await?.path;
140 while !path.is_inside_or_equal_ref(common_path_ref) {
141 let parent = common_path_ref.parent();
142 if parent == *common_path_ref {
143 common_path = None;
144 break;
145 }
146 *common_path_ref = parent;
147 }
148 }
149 }
150
151 let assets = chunk_items
152 .iter()
153 .map(async |&chunk_item| {
154 Ok((
155 rcstr!("chunk item"),
156 chunk_item.content_ident().to_resolved().await?,
157 ))
158 })
159 .try_join()
160 .await?;
161
162 let path = if let Some(common_path) = common_path {
163 common_path
164 } else {
165 ServerFileSystem::new().root().owned().await?
166 };
167 let mut ident = AssetIdent::from_path(path);
168 ident.assets.extend(assets);
169
170 Ok(ident.into_vc())
171 }
172
173 #[turbo_tasks::function]
174 fn chunking_context(&self) -> Vc<Box<dyn ChunkingContext>> {
175 *self.chunking_context
176 }
177
178 #[turbo_tasks::function]
179 fn chunk_items(&self) -> Vc<ChunkItems> {
180 self.content.included_chunk_items()
181 }
182}
183
184#[turbo_tasks::value_impl]
185impl EcmascriptChunk {
186 #[turbo_tasks::function]
187 pub fn chunk_content(&self) -> Vc<EcmascriptChunkContent> {
188 *self.content
189 }
190}
191
192#[turbo_tasks::value_impl]
193impl Introspectable for EcmascriptChunk {
194 #[turbo_tasks::function]
195 fn ty(&self) -> Vc<RcStr> {
196 Vc::cell(rcstr!("ecmascript chunk"))
197 }
198
199 #[turbo_tasks::function]
200 fn title(self: Vc<Self>) -> Vc<RcStr> {
201 self.ident().to_string()
202 }
203
204 #[turbo_tasks::function]
205 async fn details(&self) -> Result<Vc<RcStr>> {
206 let mut details = String::new();
207 details += "Chunk items:\n\n";
208 for chunk_item in self.content.included_chunk_items().await? {
209 writeln!(details, "- {}", chunk_item.asset_ident().to_string().await?)?;
210 }
211 Ok(Vc::cell(details.into()))
212 }
213
214 #[turbo_tasks::function]
215 async fn children(self: Vc<Self>) -> Result<Vc<IntrospectableChildren>> {
216 let mut children = children_from_output_assets(self.references())
217 .owned()
218 .await?;
219 for chunk_item in self.await?.content.included_chunk_items().await? {
220 children.insert((
221 rcstr!("module"),
222 IntrospectableModule::new(chunk_item.module())
223 .to_resolved()
224 .await?,
225 ));
226 }
227 Ok(Vc::cell(children))
228 }
229}