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