turbopack_core/chunk/
chunking_context.rs

1use anyhow::{Result, bail};
2use bincode::{Decode, Encode};
3use rustc_hash::FxHashMap;
4use serde::{Deserialize, Serialize};
5use turbo_rcstr::RcStr;
6use turbo_tasks::{NonLocalValue, ResolvedVc, TaskInput, Upcast, Vc, trace::TraceRawVcs};
7use turbo_tasks_fs::FileSystemPath;
8use turbo_tasks_hash::DeterministicHash;
9
10use crate::{
11    asset::Asset,
12    chunk::{
13        ChunkItem, ChunkType, ChunkableModule, EvaluatableAssets, ModuleId,
14        availability_info::AvailabilityInfo,
15    },
16    environment::Environment,
17    ident::AssetIdent,
18    module::Module,
19    module_graph::{
20        ModuleGraph, binding_usage_info::ModuleExportUsage, chunk_group_info::ChunkGroup,
21        module_batches::BatchingConfig,
22    },
23    output::{
24        ExpandOutputAssetsInput, OutputAsset, OutputAssets, OutputAssetsReferences,
25        OutputAssetsWithReferenced, expand_output_assets,
26    },
27    reference::ModuleReference,
28};
29
30#[derive(
31    Debug,
32    TaskInput,
33    Clone,
34    Copy,
35    PartialEq,
36    Eq,
37    Hash,
38    Deserialize,
39    TraceRawVcs,
40    DeterministicHash,
41    NonLocalValue,
42    Encode,
43    Decode,
44)]
45#[serde(rename_all = "kebab-case")]
46pub enum MangleType {
47    OptimalSize,
48    Deterministic,
49}
50
51#[turbo_tasks::value(shared)]
52#[derive(Debug, TaskInput, Clone, Copy, Hash, DeterministicHash, Deserialize)]
53pub enum MinifyType {
54    // TODO instead of adding a new property here,
55    // refactor that to Minify(MinifyOptions) to allow defaults on MinifyOptions
56    Minify { mangle: Option<MangleType> },
57    NoMinify,
58}
59
60impl Default for MinifyType {
61    fn default() -> Self {
62        Self::Minify {
63            mangle: Some(MangleType::OptimalSize),
64        }
65    }
66}
67
68#[turbo_tasks::value(shared)]
69#[derive(Debug, Default, TaskInput, Clone, Copy, Hash, DeterministicHash)]
70pub enum SourceMapsType {
71    /// Extracts source maps from input files and writes source maps for output files.
72    #[default]
73    Full,
74    /// Ignores existing input source maps, but writes source maps for output files.
75    Partial,
76    /// Ignores the existence of source maps and does not write source maps for output files.
77    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    Encode,
94    Decode,
95)]
96pub enum ChunkGroupType {
97    Entry,
98    Evaluated,
99}
100
101#[turbo_tasks::value(shared)]
102#[derive(Clone)]
103pub struct ChunkGroupResult {
104    pub assets: ResolvedVc<OutputAssets>,
105    pub referenced_assets: ResolvedVc<OutputAssets>,
106    pub references: ResolvedVc<OutputAssetsReferences>,
107    pub availability_info: AvailabilityInfo,
108}
109
110impl ChunkGroupResult {
111    pub fn empty() -> Vc<Self> {
112        ChunkGroupResult {
113            assets: ResolvedVc::cell(vec![]),
114            referenced_assets: ResolvedVc::cell(vec![]),
115            references: ResolvedVc::cell(vec![]),
116            availability_info: AvailabilityInfo::root(),
117        }
118        .cell()
119    }
120
121    pub fn empty_resolved() -> ResolvedVc<Self> {
122        ChunkGroupResult {
123            assets: ResolvedVc::cell(vec![]),
124            referenced_assets: ResolvedVc::cell(vec![]),
125            references: ResolvedVc::cell(vec![]),
126            availability_info: AvailabilityInfo::root(),
127        }
128        .resolved_cell()
129    }
130}
131
132#[turbo_tasks::value_impl]
133impl ChunkGroupResult {
134    #[turbo_tasks::function]
135    pub async fn output_assets_with_referenced(&self) -> Result<Vc<OutputAssetsWithReferenced>> {
136        Ok(OutputAssetsWithReferenced {
137            assets: self.assets,
138            referenced_assets: self.referenced_assets,
139            references: self.references,
140        }
141        .cell())
142    }
143
144    #[turbo_tasks::function]
145    pub async fn concatenate(&self, next: Vc<Self>) -> Result<Vc<Self>> {
146        let next = next.await?;
147        Ok(ChunkGroupResult {
148            assets: self.assets.concatenate(*next.assets).to_resolved().await?,
149            referenced_assets: self
150                .referenced_assets
151                .concatenate(*next.referenced_assets)
152                .to_resolved()
153                .await?,
154            references: self
155                .references
156                .concatenate(*next.references)
157                .to_resolved()
158                .await?,
159            availability_info: next.availability_info,
160        }
161        .cell())
162    }
163
164    #[turbo_tasks::function]
165    pub async fn all_assets(&self) -> Result<Vc<OutputAssets>> {
166        Ok(Vc::cell(
167            expand_output_assets(
168                self.assets
169                    .await?
170                    .into_iter()
171                    .chain(self.referenced_assets.await?.into_iter())
172                    .copied()
173                    .map(ExpandOutputAssetsInput::Asset)
174                    .chain(
175                        self.references
176                            .await?
177                            .into_iter()
178                            .copied()
179                            .map(ExpandOutputAssetsInput::Reference),
180                    ),
181                false,
182            )
183            .await?,
184        ))
185    }
186
187    /// Returns only primary asset entries. Doesn't expand OutputAssets. Doesn't return referenced
188    /// assets.
189    #[turbo_tasks::function]
190    pub fn primary_assets(&self) -> Vc<OutputAssets> {
191        *self.assets
192    }
193
194    #[turbo_tasks::function]
195    pub async fn referenced_assets(&self) -> Result<Vc<OutputAssets>> {
196        Ok(Vc::cell(
197            expand_output_assets(
198                self.referenced_assets
199                    .await?
200                    .into_iter()
201                    .copied()
202                    .map(ExpandOutputAssetsInput::Asset)
203                    .chain(
204                        self.references
205                            .await?
206                            .into_iter()
207                            .copied()
208                            .map(ExpandOutputAssetsInput::Reference),
209                    ),
210                false,
211            )
212            .await?,
213        ))
214    }
215}
216
217#[turbo_tasks::value(shared)]
218pub struct EntryChunkGroupResult {
219    pub asset: ResolvedVc<Box<dyn OutputAsset>>,
220    pub availability_info: AvailabilityInfo,
221}
222
223#[derive(
224    Default,
225    Debug,
226    Clone,
227    PartialEq,
228    Eq,
229    Hash,
230    TraceRawVcs,
231    NonLocalValue,
232    TaskInput,
233    Encode,
234    Decode,
235)]
236pub struct ChunkingConfig {
237    /// Try to avoid creating more than 1 chunk smaller than this size.
238    /// It merges multiple small chunks into bigger ones to avoid that.
239    pub min_chunk_size: usize,
240
241    /// Try to avoid creating more than this number of chunks per group.
242    /// It merges multiple chunks into bigger ones to avoid that.
243    pub max_chunk_count_per_group: usize,
244
245    /// Never merges chunks bigger than this size with other chunks.
246    /// This makes sure that code in big chunks is not duplicated in multiple chunks.
247    pub max_merge_chunk_size: usize,
248
249    #[allow(dead_code)]
250    pub placeholder_for_future_extensions: (),
251}
252
253#[turbo_tasks::value(transparent)]
254pub struct ChunkingConfigs(FxHashMap<ResolvedVc<Box<dyn ChunkType>>, ChunkingConfig>);
255
256#[turbo_tasks::value(shared)]
257#[derive(Debug, Clone, Copy, Hash, TaskInput, Default, Deserialize)]
258pub enum SourceMapSourceType {
259    AbsoluteFileUri,
260    RelativeUri,
261    #[default]
262    TurbopackUri,
263}
264
265/// A context for the chunking that influences the way chunks are created
266#[turbo_tasks::value_trait]
267pub trait ChunkingContext {
268    #[turbo_tasks::function]
269    fn name(self: Vc<Self>) -> Vc<RcStr>;
270    #[turbo_tasks::function]
271    fn source_map_source_type(self: Vc<Self>) -> Vc<SourceMapSourceType>;
272    /// The root path of the project
273    #[turbo_tasks::function]
274    fn root_path(self: Vc<Self>) -> Vc<FileSystemPath>;
275    /// The output root path in the output filesystem
276    #[turbo_tasks::function]
277    fn output_root(self: Vc<Self>) -> Vc<FileSystemPath>;
278    /// A relative path how to reach the root path from the output root. This is used to compute
279    /// original paths at runtime relative to the output files. e. g. import.meta.url needs that.
280    #[turbo_tasks::function]
281    fn output_root_to_root_path(self: Vc<Self>) -> Vc<RcStr>;
282
283    // TODO remove this, a chunking context should not be bound to a specific
284    // environment since this can change due to transitions in the module graph
285    #[turbo_tasks::function]
286    fn environment(self: Vc<Self>) -> Vc<Environment>;
287
288    /// The path to the folder where all chunks are placed. This can be used to compute relative
289    /// paths.
290    #[turbo_tasks::function]
291    fn chunk_root_path(self: Vc<Self>) -> Vc<FileSystemPath>;
292
293    // TODO(alexkirsz) Remove this from the chunking context. This should be at the
294    // discretion of chunking context implementors. However, we currently use this
295    // in a couple of places in `turbopack-css`, so we need to remove that
296    // dependency first.
297    #[turbo_tasks::function]
298    fn chunk_path(
299        self: Vc<Self>,
300        asset: Option<Vc<Box<dyn Asset>>>,
301        ident: Vc<AssetIdent>,
302        content_hashing_prefix: Option<RcStr>,
303        extension: RcStr,
304    ) -> Vc<FileSystemPath>;
305
306    /// Reference Source Map Assets for chunks
307    #[turbo_tasks::function]
308    fn reference_chunk_source_maps(self: Vc<Self>, chunk: Vc<Box<dyn OutputAsset>>) -> Vc<bool>;
309
310    /// Include Source Maps for modules
311    #[turbo_tasks::function]
312    fn reference_module_source_maps(self: Vc<Self>, module: Vc<Box<dyn Module>>) -> Vc<bool>;
313
314    /// Returns a URL (relative or absolute, depending on the asset prefix) to
315    /// the static asset based on its `ident`.
316    /// The `tag` is an arbitrary string that can be used to distinguish
317    /// different usages of the same asset (e.g. different base paths).
318    #[turbo_tasks::function]
319    fn asset_url(self: Vc<Self>, ident: FileSystemPath, tag: Option<RcStr>) -> Result<Vc<RcStr>>;
320
321    #[turbo_tasks::function]
322    fn asset_path(
323        self: Vc<Self>,
324        content_hash: RcStr,
325        original_asset_ident: Vc<AssetIdent>,
326        tag: Option<RcStr>,
327    ) -> Vc<FileSystemPath>;
328
329    #[turbo_tasks::function]
330    fn is_hot_module_replacement_enabled(self: Vc<Self>) -> Vc<bool> {
331        Vc::cell(false)
332    }
333
334    #[turbo_tasks::function]
335    fn chunking_configs(self: Vc<Self>) -> Vc<ChunkingConfigs> {
336        Vc::cell(Default::default())
337    }
338
339    #[turbo_tasks::function]
340    fn batching_config(self: Vc<Self>) -> Vc<BatchingConfig> {
341        BatchingConfig::new(BatchingConfig {
342            ..Default::default()
343        })
344    }
345
346    /// Whether `ChunkingType::Traced` are used to create corresponding output assets for each
347    /// traced module.
348    #[turbo_tasks::function]
349    fn is_tracing_enabled(self: Vc<Self>) -> Vc<bool> {
350        Vc::cell(false)
351    }
352
353    /// Whether async modules should create an new availability boundary and therefore nested async
354    /// modules include less modules. Enabling this will lead to better optimized async chunks,
355    /// but it will require to compute all possible paths in the application, which might lead to
356    /// many combinations.
357    #[turbo_tasks::function]
358    fn is_nested_async_availability_enabled(self: Vc<Self>) -> Vc<bool> {
359        Vc::cell(false)
360    }
361
362    /// Whether to use `MergeableModule` to merge modules if possible.
363    #[turbo_tasks::function]
364    fn is_module_merging_enabled(self: Vc<Self>) -> Vc<bool> {
365        Vc::cell(false)
366    }
367
368    /// Whether to include information about the content of the chunk into the runtime, to allow
369    /// more incremental loading of individual chunk items.
370    #[turbo_tasks::function]
371    fn is_dynamic_chunk_content_loading_enabled(self: Vc<Self>) -> Vc<bool> {
372        Vc::cell(false)
373    }
374
375    #[turbo_tasks::function]
376    fn minify_type(self: Vc<Self>) -> Vc<MinifyType> {
377        MinifyType::NoMinify.cell()
378    }
379
380    #[turbo_tasks::function]
381    fn should_use_absolute_url_references(self: Vc<Self>) -> Vc<bool> {
382        Vc::cell(false)
383    }
384
385    #[turbo_tasks::function]
386    fn async_loader_chunk_item(
387        &self,
388        module: Vc<Box<dyn ChunkableModule>>,
389        module_graph: Vc<ModuleGraph>,
390        availability_info: AvailabilityInfo,
391    ) -> Vc<Box<dyn ChunkItem>>;
392    #[turbo_tasks::function]
393    fn async_loader_chunk_item_id(&self, module: Vc<Box<dyn ChunkableModule>>) -> Vc<ModuleId>;
394
395    #[turbo_tasks::function]
396    fn chunk_group(
397        self: Vc<Self>,
398        ident: Vc<AssetIdent>,
399        chunk_group: ChunkGroup,
400        module_graph: Vc<ModuleGraph>,
401        availability_info: AvailabilityInfo,
402    ) -> Vc<ChunkGroupResult>;
403
404    #[turbo_tasks::function]
405    fn evaluated_chunk_group(
406        self: Vc<Self>,
407        ident: Vc<AssetIdent>,
408        chunk_group: ChunkGroup,
409        module_graph: Vc<ModuleGraph>,
410        availability_info: AvailabilityInfo,
411    ) -> Vc<ChunkGroupResult>;
412
413    /// Generates an output chunk that:
414    /// * loads the given extra_chunks in addition to the generated chunks; and
415    /// * evaluates the given assets; and
416    /// * exports the result of evaluating the last module as a CommonJS default export.
417    #[turbo_tasks::function]
418    fn entry_chunk_group(
419        self: Vc<Self>,
420        path: FileSystemPath,
421        evaluatable_assets: Vc<EvaluatableAssets>,
422        module_graph: Vc<ModuleGraph>,
423        extra_chunks: Vc<OutputAssets>,
424        extra_referenced_assets: Vc<OutputAssets>,
425        availability_info: AvailabilityInfo,
426    ) -> Result<Vc<EntryChunkGroupResult>>;
427
428    #[turbo_tasks::function]
429    async fn chunk_item_id_from_ident(
430        self: Vc<Self>,
431        ident: Vc<AssetIdent>,
432    ) -> Result<Vc<ModuleId>>;
433
434    #[turbo_tasks::function]
435    fn chunk_item_id(self: Vc<Self>, module: Vc<Box<dyn ChunkItem>>) -> Vc<ModuleId> {
436        self.chunk_item_id_from_ident(module.asset_ident())
437    }
438    #[turbo_tasks::function]
439    fn chunk_item_id_from_module(self: Vc<Self>, module: Vc<Box<dyn Module>>) -> Vc<ModuleId> {
440        self.chunk_item_id_from_ident(module.ident())
441    }
442
443    #[turbo_tasks::function]
444    async fn module_export_usage(
445        self: Vc<Self>,
446        module: Vc<Box<dyn Module>>,
447    ) -> Result<Vc<ModuleExportUsage>>;
448
449    #[turbo_tasks::function]
450    async fn is_reference_unused(
451        self: Vc<Self>,
452        reference: Vc<Box<dyn ModuleReference>>,
453    ) -> Result<Vc<bool>>;
454
455    /// Returns whether debug IDs are enabled for this chunking context.
456    #[turbo_tasks::function]
457    fn debug_ids_enabled(self: Vc<Self>) -> Vc<bool>;
458}
459
460pub trait ChunkingContextExt {
461    fn root_chunk_group(
462        self: Vc<Self>,
463        ident: Vc<AssetIdent>,
464        chunk_group: ChunkGroup,
465        module_graph: Vc<ModuleGraph>,
466    ) -> Vc<ChunkGroupResult>
467    where
468        Self: Send;
469
470    fn root_chunk_group_assets(
471        self: Vc<Self>,
472        ident: Vc<AssetIdent>,
473        chunk_group: ChunkGroup,
474        module_graph: Vc<ModuleGraph>,
475    ) -> Vc<OutputAssetsWithReferenced>
476    where
477        Self: Send;
478
479    fn evaluated_chunk_group_assets(
480        self: Vc<Self>,
481        ident: Vc<AssetIdent>,
482        chunk_group: ChunkGroup,
483        module_graph: Vc<ModuleGraph>,
484        availability_info: AvailabilityInfo,
485    ) -> Vc<OutputAssetsWithReferenced>
486    where
487        Self: Send;
488
489    fn entry_chunk_group_asset(
490        self: Vc<Self>,
491        path: FileSystemPath,
492        evaluatable_assets: Vc<EvaluatableAssets>,
493        module_graph: Vc<ModuleGraph>,
494        extra_chunks: Vc<OutputAssets>,
495        extra_referenced_assets: Vc<OutputAssets>,
496        availability_info: AvailabilityInfo,
497    ) -> Vc<Box<dyn OutputAsset>>
498    where
499        Self: Send;
500
501    fn root_entry_chunk_group(
502        self: Vc<Self>,
503        path: FileSystemPath,
504        evaluatable_assets: Vc<EvaluatableAssets>,
505        module_graph: Vc<ModuleGraph>,
506        extra_chunks: Vc<OutputAssets>,
507        extra_referenced_assets: Vc<OutputAssets>,
508    ) -> Vc<EntryChunkGroupResult>
509    where
510        Self: Send;
511
512    fn root_entry_chunk_group_asset(
513        self: Vc<Self>,
514        path: FileSystemPath,
515        evaluatable_assets: Vc<EvaluatableAssets>,
516        module_graph: Vc<ModuleGraph>,
517        extra_chunks: Vc<OutputAssets>,
518        extra_referenced_assets: Vc<OutputAssets>,
519    ) -> Vc<Box<dyn OutputAsset>>
520    where
521        Self: Send;
522
523    fn chunk_group_assets(
524        self: Vc<Self>,
525        ident: Vc<AssetIdent>,
526        chunk_group: ChunkGroup,
527        module_graph: Vc<ModuleGraph>,
528        availability_info: AvailabilityInfo,
529    ) -> Vc<OutputAssetsWithReferenced>
530    where
531        Self: Send;
532
533    /// Computes the relative path from the chunk output root to the project root.
534    ///
535    /// This is used to compute relative paths for source maps in certain configurations.
536    fn relative_path_from_chunk_root_to_project_root(self: Vc<Self>) -> Vc<RcStr>
537    where
538        Self: Send;
539}
540
541impl<T: ChunkingContext + Send + Upcast<Box<dyn ChunkingContext>>> ChunkingContextExt for T {
542    fn root_chunk_group(
543        self: Vc<Self>,
544        ident: Vc<AssetIdent>,
545        chunk_group: ChunkGroup,
546        module_graph: Vc<ModuleGraph>,
547    ) -> Vc<ChunkGroupResult> {
548        self.chunk_group(ident, chunk_group, module_graph, AvailabilityInfo::root())
549    }
550
551    fn root_chunk_group_assets(
552        self: Vc<Self>,
553        ident: Vc<AssetIdent>,
554        chunk_group: ChunkGroup,
555        module_graph: Vc<ModuleGraph>,
556    ) -> Vc<OutputAssetsWithReferenced> {
557        root_chunk_group_assets(
558            Vc::upcast_non_strict(self),
559            ident,
560            chunk_group,
561            module_graph,
562        )
563    }
564
565    fn evaluated_chunk_group_assets(
566        self: Vc<Self>,
567        ident: Vc<AssetIdent>,
568        chunk_group: ChunkGroup,
569        module_graph: Vc<ModuleGraph>,
570        availability_info: AvailabilityInfo,
571    ) -> Vc<OutputAssetsWithReferenced> {
572        evaluated_chunk_group_assets(
573            Vc::upcast_non_strict(self),
574            ident,
575            chunk_group,
576            module_graph,
577            availability_info,
578        )
579    }
580
581    fn entry_chunk_group_asset(
582        self: Vc<Self>,
583        path: FileSystemPath,
584        evaluatable_assets: Vc<EvaluatableAssets>,
585        module_graph: Vc<ModuleGraph>,
586        extra_chunks: Vc<OutputAssets>,
587        extra_referenced_assets: Vc<OutputAssets>,
588        availability_info: AvailabilityInfo,
589    ) -> Vc<Box<dyn OutputAsset>> {
590        entry_chunk_group_asset(
591            Vc::upcast_non_strict(self),
592            path,
593            evaluatable_assets,
594            module_graph,
595            extra_chunks,
596            extra_referenced_assets,
597            availability_info,
598        )
599    }
600
601    fn root_entry_chunk_group(
602        self: Vc<Self>,
603        path: FileSystemPath,
604        evaluatable_assets: Vc<EvaluatableAssets>,
605        module_graph: Vc<ModuleGraph>,
606        extra_chunks: Vc<OutputAssets>,
607        extra_referenced_assets: Vc<OutputAssets>,
608    ) -> Vc<EntryChunkGroupResult> {
609        self.entry_chunk_group(
610            path,
611            evaluatable_assets,
612            module_graph,
613            extra_chunks,
614            extra_referenced_assets,
615            AvailabilityInfo::root(),
616        )
617    }
618
619    fn root_entry_chunk_group_asset(
620        self: Vc<Self>,
621        path: FileSystemPath,
622        evaluatable_assets: Vc<EvaluatableAssets>,
623        module_graph: Vc<ModuleGraph>,
624        extra_chunks: Vc<OutputAssets>,
625        extra_referenced_assets: Vc<OutputAssets>,
626    ) -> Vc<Box<dyn OutputAsset>> {
627        entry_chunk_group_asset(
628            Vc::upcast_non_strict(self),
629            path,
630            evaluatable_assets,
631            module_graph,
632            extra_chunks,
633            extra_referenced_assets,
634            AvailabilityInfo::root(),
635        )
636    }
637
638    fn chunk_group_assets(
639        self: Vc<Self>,
640        ident: Vc<AssetIdent>,
641        chunk_group: ChunkGroup,
642        module_graph: Vc<ModuleGraph>,
643        availability_info: AvailabilityInfo,
644    ) -> Vc<OutputAssetsWithReferenced> {
645        chunk_group_assets(
646            Vc::upcast_non_strict(self),
647            ident,
648            chunk_group,
649            module_graph,
650            availability_info,
651        )
652    }
653
654    fn relative_path_from_chunk_root_to_project_root(self: Vc<Self>) -> Vc<RcStr> {
655        relative_path_from_chunk_root_to_project_root(Vc::upcast_non_strict(self))
656    }
657}
658
659#[turbo_tasks::function]
660async fn relative_path_from_chunk_root_to_project_root(
661    chunking_context: Vc<Box<dyn ChunkingContext>>,
662) -> Result<Vc<RcStr>> {
663    // Example,
664    //   project root: /project/root
665    //   output root: /project/root/dist
666    //   chunk root path: /project/root/dist/ssr/chunks
667    //   output_root_to_chunk_root: ../
668    //
669    // Example2,
670    //   project root: /project/root
671    //   output root: /project/out
672    //   chunk root path: /project/out/ssr/chunks
673    //   output_root_to_chunk_root: ../root
674    //
675    // From that we want to return  ../../../root to get from a path in `chunks` to a path in the
676    // project root.
677
678    let chunk_root_path = chunking_context.chunk_root_path().await?;
679    let output_root = chunking_context.output_root().await?;
680    let chunk_to_output_root = chunk_root_path.get_relative_path_to(&output_root);
681    let Some(chunk_to_output_root) = chunk_to_output_root else {
682        bail!(
683            "expected chunk_root_path: {chunk_root_path} to be inside of output_root: \
684             {output_root}",
685            chunk_root_path = chunk_root_path.value_to_string().await?,
686            output_root = output_root.value_to_string().await?
687        );
688    };
689    let output_root_to_chunk_root_path = chunking_context.output_root_to_root_path().await?;
690
691    // Note we cannot use `normalize_path` here since it rejects paths that start with `../`
692    Ok(Vc::cell(
693        format!(
694            "{}/{}",
695            chunk_to_output_root, output_root_to_chunk_root_path
696        )
697        .into(),
698    ))
699}
700
701#[turbo_tasks::function]
702fn root_chunk_group_assets(
703    chunking_context: Vc<Box<dyn ChunkingContext>>,
704    ident: Vc<AssetIdent>,
705    chunk_group: ChunkGroup,
706    module_graph: Vc<ModuleGraph>,
707) -> Vc<OutputAssetsWithReferenced> {
708    chunking_context
709        .root_chunk_group(ident, chunk_group, module_graph)
710        .output_assets_with_referenced()
711}
712
713#[turbo_tasks::function]
714fn evaluated_chunk_group_assets(
715    chunking_context: Vc<Box<dyn ChunkingContext>>,
716    ident: Vc<AssetIdent>,
717    chunk_group: ChunkGroup,
718    module_graph: Vc<ModuleGraph>,
719    availability_info: AvailabilityInfo,
720) -> Vc<OutputAssetsWithReferenced> {
721    chunking_context
722        .evaluated_chunk_group(ident, chunk_group, module_graph, availability_info)
723        .output_assets_with_referenced()
724}
725
726#[turbo_tasks::function]
727async fn entry_chunk_group_asset(
728    chunking_context: Vc<Box<dyn ChunkingContext>>,
729    path: FileSystemPath,
730    evaluatable_assets: Vc<EvaluatableAssets>,
731    module_graph: Vc<ModuleGraph>,
732    extra_chunks: Vc<OutputAssets>,
733    extra_referenced_assets: Vc<OutputAssets>,
734    availability_info: AvailabilityInfo,
735) -> Result<Vc<Box<dyn OutputAsset>>> {
736    Ok(*chunking_context
737        .entry_chunk_group(
738            path,
739            evaluatable_assets,
740            module_graph,
741            extra_chunks,
742            extra_referenced_assets,
743            availability_info,
744        )
745        .await?
746        .asset)
747}
748
749#[turbo_tasks::function]
750fn chunk_group_assets(
751    chunking_context: Vc<Box<dyn ChunkingContext>>,
752    ident: Vc<AssetIdent>,
753    chunk_group: ChunkGroup,
754    module_graph: Vc<ModuleGraph>,
755    availability_info: AvailabilityInfo,
756) -> Vc<OutputAssetsWithReferenced> {
757    chunking_context
758        .chunk_group(ident, chunk_group, module_graph, availability_info)
759        .output_assets_with_referenced()
760}