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