turbopack_ecmascript/async_chunk/
module.rs

1use anyhow::Result;
2use turbo_rcstr::RcStr;
3use turbo_tasks::{ResolvedVc, Value, Vc};
4use turbopack_core::{
5    asset::{Asset, AssetContent},
6    chunk::{ChunkableModule, ChunkingContext, availability_info::AvailabilityInfo},
7    ident::AssetIdent,
8    module::Module,
9    module_graph::ModuleGraph,
10    reference::{ModuleReferences, SingleModuleReference},
11};
12
13use crate::async_chunk::chunk_item::AsyncLoaderChunkItem;
14
15#[turbo_tasks::function]
16fn async_loader_modifier() -> Vc<RcStr> {
17    Vc::cell("async loader".into())
18}
19
20/// The AsyncLoaderModule is a module that loads another module async, by
21/// putting it into a separate chunk group.
22#[turbo_tasks::value]
23pub struct AsyncLoaderModule {
24    pub inner: ResolvedVc<Box<dyn ChunkableModule>>,
25    pub chunking_context: ResolvedVc<Box<dyn ChunkingContext>>,
26    pub availability_info: AvailabilityInfo,
27}
28
29#[turbo_tasks::value_impl]
30impl AsyncLoaderModule {
31    #[turbo_tasks::function]
32    pub fn new(
33        module: ResolvedVc<Box<dyn ChunkableModule>>,
34        chunking_context: ResolvedVc<Box<dyn ChunkingContext>>,
35        availability_info: Value<AvailabilityInfo>,
36    ) -> Vc<Self> {
37        Self::cell(AsyncLoaderModule {
38            inner: module,
39            chunking_context,
40            availability_info: availability_info.into_value(),
41        })
42    }
43
44    #[turbo_tasks::function]
45    pub fn asset_ident_for(module: Vc<Box<dyn ChunkableModule>>) -> Vc<AssetIdent> {
46        module.ident().with_modifier(async_loader_modifier())
47    }
48}
49
50#[turbo_tasks::function]
51fn inner_module_reference_description() -> Vc<RcStr> {
52    Vc::cell("async module".into())
53}
54
55#[turbo_tasks::value_impl]
56impl Module for AsyncLoaderModule {
57    #[turbo_tasks::function]
58    fn ident(&self) -> Vc<AssetIdent> {
59        Self::asset_ident_for(*self.inner)
60    }
61
62    #[turbo_tasks::function]
63    async fn references(self: Vc<Self>) -> Result<Vc<ModuleReferences>> {
64        Ok(Vc::cell(vec![ResolvedVc::upcast(
65            SingleModuleReference::new(
66                *ResolvedVc::upcast(self.await?.inner),
67                inner_module_reference_description(),
68            )
69            .to_resolved()
70            .await?,
71        )]))
72    }
73}
74
75#[turbo_tasks::value_impl]
76impl Asset for AsyncLoaderModule {
77    #[turbo_tasks::function]
78    fn content(&self) -> Vc<AssetContent> {
79        panic!("content() should not be called");
80    }
81}
82
83#[turbo_tasks::value_impl]
84impl ChunkableModule for AsyncLoaderModule {
85    #[turbo_tasks::function]
86    async fn as_chunk_item(
87        self: ResolvedVc<Self>,
88        module_graph: ResolvedVc<ModuleGraph>,
89        chunking_context: ResolvedVc<Box<dyn ChunkingContext>>,
90    ) -> Vc<Box<dyn turbopack_core::chunk::ChunkItem>> {
91        Vc::upcast(
92            AsyncLoaderChunkItem {
93                chunking_context,
94                module_graph,
95                module: self,
96            }
97            .cell(),
98        )
99    }
100}