1use anyhow::Result;
2use rustc_hash::FxHashMap;
3use serde::{Deserialize, Serialize};
4use turbo_rcstr::RcStr;
5use turbo_tasks::{NonLocalValue, ResolvedVc, TaskInput, Upcast, Vc, trace::TraceRawVcs};
6use turbo_tasks_fs::FileSystemPath;
7use turbo_tasks_hash::DeterministicHash;
8
9use super::{ChunkableModule, EvaluatableAssets, availability_info::AvailabilityInfo};
10use crate::{
11 asset::Asset,
12 chunk::{ChunkItem, ChunkType, ModuleId},
13 environment::Environment,
14 ident::AssetIdent,
15 module::Module,
16 module_graph::{
17 ModuleGraph, chunk_group_info::ChunkGroup, export_usage::ModuleExportUsage,
18 module_batches::BatchingConfig,
19 },
20 output::{OutputAsset, OutputAssets},
21};
22
23#[derive(
24 Debug,
25 TaskInput,
26 Clone,
27 Copy,
28 PartialEq,
29 Eq,
30 Hash,
31 Serialize,
32 Deserialize,
33 TraceRawVcs,
34 DeterministicHash,
35 NonLocalValue,
36)]
37#[serde(rename_all = "kebab-case")]
38pub enum MangleType {
39 OptimalSize,
40 Deterministic,
41}
42
43#[turbo_tasks::value(shared)]
44#[derive(Debug, TaskInput, Clone, Copy, Hash, DeterministicHash)]
45pub enum MinifyType {
46 Minify { mangle: Option<MangleType> },
49 NoMinify,
50}
51
52impl Default for MinifyType {
53 fn default() -> Self {
54 Self::Minify {
55 mangle: Some(MangleType::OptimalSize),
56 }
57 }
58}
59
60#[turbo_tasks::value(shared)]
61#[derive(Debug, Default, TaskInput, Clone, Copy, Hash, DeterministicHash)]
62pub enum SourceMapsType {
63 #[default]
65 Full,
66 None,
68}
69
70#[derive(
71 Debug,
72 TaskInput,
73 Clone,
74 Copy,
75 PartialEq,
76 Eq,
77 Hash,
78 Serialize,
79 Deserialize,
80 TraceRawVcs,
81 DeterministicHash,
82 NonLocalValue,
83)]
84pub enum ChunkGroupType {
85 Entry,
86 Evaluated,
87}
88
89#[turbo_tasks::value(shared)]
90pub struct ChunkGroupResult {
91 pub assets: ResolvedVc<OutputAssets>,
92 pub availability_info: AvailabilityInfo,
93}
94
95#[turbo_tasks::value(shared)]
96pub struct EntryChunkGroupResult {
97 pub asset: ResolvedVc<Box<dyn OutputAsset>>,
98 pub availability_info: AvailabilityInfo,
99}
100
101#[derive(
102 Default,
103 Debug,
104 Clone,
105 PartialEq,
106 Eq,
107 Hash,
108 Serialize,
109 Deserialize,
110 TraceRawVcs,
111 NonLocalValue,
112 TaskInput,
113)]
114pub struct ChunkingConfig {
115 pub min_chunk_size: usize,
118
119 pub max_chunk_count_per_group: usize,
122
123 pub max_merge_chunk_size: usize,
126
127 #[allow(dead_code)]
128 pub placeholder_for_future_extensions: (),
129}
130
131#[turbo_tasks::value(transparent)]
132pub struct ChunkingConfigs(FxHashMap<ResolvedVc<Box<dyn ChunkType>>, ChunkingConfig>);
133
134#[turbo_tasks::value_trait]
136pub trait ChunkingContext {
137 #[turbo_tasks::function]
138 fn name(self: Vc<Self>) -> Vc<RcStr>;
139 #[turbo_tasks::function]
140 fn should_use_file_source_map_uris(self: Vc<Self>) -> Vc<bool>;
141 #[turbo_tasks::function]
143 fn root_path(self: Vc<Self>) -> Vc<FileSystemPath>;
144 #[turbo_tasks::function]
146 fn output_root(self: Vc<Self>) -> Vc<FileSystemPath>;
147 #[turbo_tasks::function]
150 fn output_root_to_root_path(self: Vc<Self>) -> Vc<RcStr>;
151
152 #[turbo_tasks::function]
155 fn environment(self: Vc<Self>) -> Vc<Environment>;
156
157 #[turbo_tasks::function]
160 fn chunk_root_path(self: Vc<Self>) -> Vc<FileSystemPath>;
161
162 #[turbo_tasks::function]
167 fn chunk_path(
168 self: Vc<Self>,
169 asset: Option<Vc<Box<dyn Asset>>>,
170 ident: Vc<AssetIdent>,
171 content_hashing_prefix: Option<RcStr>,
172 extension: RcStr,
173 ) -> Vc<FileSystemPath>;
174
175 #[turbo_tasks::function]
177 fn reference_chunk_source_maps(self: Vc<Self>, chunk: Vc<Box<dyn OutputAsset>>) -> Vc<bool>;
178
179 #[turbo_tasks::function]
181 fn reference_module_source_maps(self: Vc<Self>, module: Vc<Box<dyn Module>>) -> Vc<bool>;
182
183 #[turbo_tasks::function]
186 fn asset_url(self: Vc<Self>, ident: FileSystemPath) -> Result<Vc<RcStr>>;
187
188 #[turbo_tasks::function]
189 fn asset_path(
190 self: Vc<Self>,
191 content_hash: RcStr,
192 original_asset_ident: Vc<AssetIdent>,
193 ) -> Vc<FileSystemPath>;
194
195 #[turbo_tasks::function]
196 fn is_hot_module_replacement_enabled(self: Vc<Self>) -> Vc<bool> {
197 Vc::cell(false)
198 }
199
200 #[turbo_tasks::function]
201 fn chunking_configs(self: Vc<Self>) -> Vc<ChunkingConfigs> {
202 Vc::cell(Default::default())
203 }
204
205 #[turbo_tasks::function]
206 fn batching_config(self: Vc<Self>) -> Vc<BatchingConfig> {
207 BatchingConfig::new(BatchingConfig {
208 ..Default::default()
209 })
210 }
211
212 #[turbo_tasks::function]
215 fn is_tracing_enabled(self: Vc<Self>) -> Vc<bool> {
216 Vc::cell(false)
217 }
218
219 #[turbo_tasks::function]
221 fn is_module_merging_enabled(self: Vc<Self>) -> Vc<bool> {
222 Vc::cell(false)
223 }
224
225 #[turbo_tasks::function]
228 fn is_dynamic_chunk_content_loading_enabled(self: Vc<Self>) -> Vc<bool> {
229 Vc::cell(false)
230 }
231
232 #[turbo_tasks::function]
233 fn minify_type(self: Vc<Self>) -> Vc<MinifyType> {
234 MinifyType::NoMinify.cell()
235 }
236
237 #[turbo_tasks::function]
238 fn async_loader_chunk_item(
239 &self,
240 module: Vc<Box<dyn ChunkableModule>>,
241 module_graph: Vc<ModuleGraph>,
242 availability_info: AvailabilityInfo,
243 ) -> Vc<Box<dyn ChunkItem>>;
244 #[turbo_tasks::function]
245 fn async_loader_chunk_item_id(&self, module: Vc<Box<dyn ChunkableModule>>) -> Vc<ModuleId>;
246
247 #[turbo_tasks::function]
248 fn chunk_group(
249 self: Vc<Self>,
250 ident: Vc<AssetIdent>,
251 chunk_group: ChunkGroup,
252 module_graph: Vc<ModuleGraph>,
253 availability_info: AvailabilityInfo,
254 ) -> Vc<ChunkGroupResult>;
255
256 #[turbo_tasks::function]
257 fn evaluated_chunk_group(
258 self: Vc<Self>,
259 ident: Vc<AssetIdent>,
260 chunk_group: ChunkGroup,
261 module_graph: Vc<ModuleGraph>,
262 availability_info: AvailabilityInfo,
263 ) -> Vc<ChunkGroupResult>;
264
265 #[turbo_tasks::function]
270 fn entry_chunk_group(
271 self: Vc<Self>,
272 path: FileSystemPath,
273 evaluatable_assets: Vc<EvaluatableAssets>,
274 module_graph: Vc<ModuleGraph>,
275 extra_chunks: Vc<OutputAssets>,
276 availability_info: AvailabilityInfo,
277 ) -> Result<Vc<EntryChunkGroupResult>>;
278
279 #[turbo_tasks::function]
280 async fn chunk_item_id_from_ident(
281 self: Vc<Self>,
282 ident: Vc<AssetIdent>,
283 ) -> Result<Vc<ModuleId>>;
284
285 #[turbo_tasks::function]
286 fn chunk_item_id(self: Vc<Self>, module: Vc<Box<dyn ChunkItem>>) -> Vc<ModuleId> {
287 self.chunk_item_id_from_ident(module.asset_ident())
288 }
289 #[turbo_tasks::function]
290 fn chunk_item_id_from_module(self: Vc<Self>, module: Vc<Box<dyn Module>>) -> Vc<ModuleId> {
291 self.chunk_item_id_from_ident(module.ident())
292 }
293
294 #[turbo_tasks::function]
295 async fn module_export_usage(
296 self: Vc<Self>,
297 module: Vc<Box<dyn Module>>,
298 ) -> Result<Vc<ModuleExportUsage>>;
299}
300
301pub trait ChunkingContextExt {
302 fn root_chunk_group(
303 self: Vc<Self>,
304 ident: Vc<AssetIdent>,
305 chunk_group: ChunkGroup,
306 module_graph: Vc<ModuleGraph>,
307 ) -> Vc<ChunkGroupResult>
308 where
309 Self: Send;
310
311 fn root_chunk_group_assets(
312 self: Vc<Self>,
313 ident: Vc<AssetIdent>,
314 chunk_group: ChunkGroup,
315 module_graph: Vc<ModuleGraph>,
316 ) -> Vc<OutputAssets>
317 where
318 Self: Send;
319
320 fn evaluated_chunk_group_assets(
321 self: Vc<Self>,
322 ident: Vc<AssetIdent>,
323 chunk_group: ChunkGroup,
324 module_graph: Vc<ModuleGraph>,
325 availability_info: AvailabilityInfo,
326 ) -> Vc<OutputAssets>
327 where
328 Self: Send;
329
330 fn entry_chunk_group_asset(
331 self: Vc<Self>,
332 path: FileSystemPath,
333 evaluatable_assets: Vc<EvaluatableAssets>,
334 module_graph: Vc<ModuleGraph>,
335 extra_chunks: Vc<OutputAssets>,
336 availability_info: AvailabilityInfo,
337 ) -> Vc<Box<dyn OutputAsset>>
338 where
339 Self: Send;
340
341 fn root_entry_chunk_group(
342 self: Vc<Self>,
343 path: FileSystemPath,
344 evaluatable_assets: Vc<EvaluatableAssets>,
345 module_graph: Vc<ModuleGraph>,
346 extra_chunks: Vc<OutputAssets>,
347 ) -> Vc<EntryChunkGroupResult>
348 where
349 Self: Send;
350
351 fn root_entry_chunk_group_asset(
352 self: Vc<Self>,
353 path: FileSystemPath,
354 evaluatable_assets: Vc<EvaluatableAssets>,
355 module_graph: Vc<ModuleGraph>,
356 extra_chunks: Vc<OutputAssets>,
357 ) -> Vc<Box<dyn OutputAsset>>
358 where
359 Self: Send;
360
361 fn chunk_group_assets(
362 self: Vc<Self>,
363 ident: Vc<AssetIdent>,
364 chunk_group: ChunkGroup,
365 module_graph: Vc<ModuleGraph>,
366 availability_info: AvailabilityInfo,
367 ) -> Vc<OutputAssets>
368 where
369 Self: Send;
370}
371
372impl<T: ChunkingContext + Send + Upcast<Box<dyn ChunkingContext>>> ChunkingContextExt for T {
373 fn root_chunk_group(
374 self: Vc<Self>,
375 ident: Vc<AssetIdent>,
376 chunk_group: ChunkGroup,
377 module_graph: Vc<ModuleGraph>,
378 ) -> Vc<ChunkGroupResult> {
379 self.chunk_group(ident, chunk_group, module_graph, AvailabilityInfo::Root)
380 }
381
382 fn root_chunk_group_assets(
383 self: Vc<Self>,
384 ident: Vc<AssetIdent>,
385 chunk_group: ChunkGroup,
386 module_graph: Vc<ModuleGraph>,
387 ) -> Vc<OutputAssets> {
388 root_chunk_group_assets(Vc::upcast(self), ident, chunk_group, module_graph)
389 }
390
391 fn evaluated_chunk_group_assets(
392 self: Vc<Self>,
393 ident: Vc<AssetIdent>,
394 chunk_group: ChunkGroup,
395 module_graph: Vc<ModuleGraph>,
396 availability_info: AvailabilityInfo,
397 ) -> Vc<OutputAssets> {
398 evaluated_chunk_group_assets(
399 Vc::upcast(self),
400 ident,
401 chunk_group,
402 module_graph,
403 availability_info,
404 )
405 }
406
407 fn entry_chunk_group_asset(
408 self: Vc<Self>,
409 path: FileSystemPath,
410 evaluatable_assets: Vc<EvaluatableAssets>,
411 module_graph: Vc<ModuleGraph>,
412 extra_chunks: Vc<OutputAssets>,
413 availability_info: AvailabilityInfo,
414 ) -> Vc<Box<dyn OutputAsset>> {
415 entry_chunk_group_asset(
416 Vc::upcast(self),
417 path,
418 evaluatable_assets,
419 module_graph,
420 extra_chunks,
421 availability_info,
422 )
423 }
424
425 fn root_entry_chunk_group(
426 self: Vc<Self>,
427 path: FileSystemPath,
428 evaluatable_assets: Vc<EvaluatableAssets>,
429 module_graph: Vc<ModuleGraph>,
430 extra_chunks: Vc<OutputAssets>,
431 ) -> Vc<EntryChunkGroupResult> {
432 self.entry_chunk_group(
433 path,
434 evaluatable_assets,
435 module_graph,
436 extra_chunks,
437 AvailabilityInfo::Root,
438 )
439 }
440
441 fn root_entry_chunk_group_asset(
442 self: Vc<Self>,
443 path: FileSystemPath,
444 evaluatable_assets: Vc<EvaluatableAssets>,
445 module_graph: Vc<ModuleGraph>,
446 extra_chunks: Vc<OutputAssets>,
447 ) -> Vc<Box<dyn OutputAsset>> {
448 entry_chunk_group_asset(
449 Vc::upcast(self),
450 path,
451 evaluatable_assets,
452 module_graph,
453 extra_chunks,
454 AvailabilityInfo::Root,
455 )
456 }
457
458 fn chunk_group_assets(
459 self: Vc<Self>,
460 ident: Vc<AssetIdent>,
461 chunk_group: ChunkGroup,
462 module_graph: Vc<ModuleGraph>,
463 availability_info: AvailabilityInfo,
464 ) -> Vc<OutputAssets> {
465 chunk_group_assets(
466 Vc::upcast(self),
467 ident,
468 chunk_group,
469 module_graph,
470 availability_info,
471 )
472 }
473}
474
475#[turbo_tasks::function]
476async fn root_chunk_group_assets(
477 chunking_context: Vc<Box<dyn ChunkingContext>>,
478 ident: Vc<AssetIdent>,
479 chunk_group: ChunkGroup,
480 module_graph: Vc<ModuleGraph>,
481) -> Result<Vc<OutputAssets>> {
482 Ok(*chunking_context
483 .root_chunk_group(ident, chunk_group, module_graph)
484 .await?
485 .assets)
486}
487
488#[turbo_tasks::function]
489async fn evaluated_chunk_group_assets(
490 chunking_context: Vc<Box<dyn ChunkingContext>>,
491 ident: Vc<AssetIdent>,
492 chunk_group: ChunkGroup,
493 module_graph: Vc<ModuleGraph>,
494 availability_info: AvailabilityInfo,
495) -> Result<Vc<OutputAssets>> {
496 Ok(*chunking_context
497 .evaluated_chunk_group(ident, chunk_group, module_graph, availability_info)
498 .await?
499 .assets)
500}
501
502#[turbo_tasks::function]
503async fn entry_chunk_group_asset(
504 chunking_context: Vc<Box<dyn ChunkingContext>>,
505 path: FileSystemPath,
506 evaluatable_assets: Vc<EvaluatableAssets>,
507 module_graph: Vc<ModuleGraph>,
508 extra_chunks: Vc<OutputAssets>,
509 availability_info: AvailabilityInfo,
510) -> Result<Vc<Box<dyn OutputAsset>>> {
511 Ok(*chunking_context
512 .entry_chunk_group(
513 path,
514 evaluatable_assets,
515 module_graph,
516 extra_chunks,
517 availability_info,
518 )
519 .await?
520 .asset)
521}
522
523#[turbo_tasks::function]
524async fn chunk_group_assets(
525 chunking_context: Vc<Box<dyn ChunkingContext>>,
526 ident: Vc<AssetIdent>,
527 chunk_group: ChunkGroup,
528 module_graph: Vc<ModuleGraph>,
529 availability_info: AvailabilityInfo,
530) -> Result<Vc<OutputAssets>> {
531 Ok(*chunking_context
532 .chunk_group(ident, chunk_group, module_graph, availability_info)
533 .await?
534 .assets)
535}