turbopack_ecmascript/worker_chunk/
chunk_item.rs

1use anyhow::Result;
2use indoc::formatdoc;
3use turbo_rcstr::rcstr;
4use turbo_tasks::{ResolvedVc, TryJoinIterExt, Vc};
5use turbopack_core::{
6    chunk::{
7        ChunkData, ChunkItem, ChunkType, ChunkingContext, ChunkingContextExt, ChunksData,
8        availability_info::AvailabilityInfo,
9    },
10    ident::AssetIdent,
11    module::Module,
12    module_graph::{ModuleGraph, chunk_group_info::ChunkGroup},
13    output::OutputAssets,
14};
15
16use super::module::WorkerLoaderModule;
17use crate::{
18    chunk::{
19        EcmascriptChunkItem, EcmascriptChunkItemContent, EcmascriptChunkType,
20        data::EcmascriptChunkData,
21    },
22    runtime_functions::{TURBOPACK_EXPORT_VALUE, TURBOPACK_WORKER_BLOB_URL},
23    utils::StringifyJs,
24};
25
26#[turbo_tasks::value(shared)]
27pub struct WorkerLoaderChunkItem {
28    pub module: ResolvedVc<WorkerLoaderModule>,
29    pub module_graph: ResolvedVc<ModuleGraph>,
30    pub chunking_context: ResolvedVc<Box<dyn ChunkingContext>>,
31}
32
33#[turbo_tasks::value_impl]
34impl WorkerLoaderChunkItem {
35    #[turbo_tasks::function]
36    async fn chunks(&self) -> Result<Vc<OutputAssets>> {
37        let module = self.module.await?;
38
39        Ok(self.chunking_context.evaluated_chunk_group_assets(
40            module.inner.ident().with_modifier(rcstr!("worker")),
41            ChunkGroup::Isolated(ResolvedVc::upcast(module.inner)),
42            *self.module_graph,
43            AvailabilityInfo::Root,
44        ))
45    }
46
47    #[turbo_tasks::function]
48    async fn chunks_data(self: Vc<Self>) -> Result<Vc<ChunksData>> {
49        let this = self.await?;
50        Ok(ChunkData::from_assets(
51            this.chunking_context.output_root().owned().await?,
52            self.chunks(),
53        ))
54    }
55}
56
57#[turbo_tasks::value_impl]
58impl EcmascriptChunkItem for WorkerLoaderChunkItem {
59    #[turbo_tasks::function]
60    async fn content(self: Vc<Self>) -> Result<Vc<EcmascriptChunkItemContent>> {
61        let chunks_data = self.chunks_data().await?;
62        let chunks_data = chunks_data.iter().try_join().await?;
63        let chunks_data: Vec<_> = chunks_data
64            .iter()
65            .map(|chunk_data| EcmascriptChunkData::new(chunk_data))
66            .collect();
67
68        let code = formatdoc! {
69            r#"
70                {TURBOPACK_EXPORT_VALUE}({TURBOPACK_WORKER_BLOB_URL}({chunks:#}));
71            "#,
72            chunks = StringifyJs(&chunks_data),
73        };
74
75        Ok(EcmascriptChunkItemContent {
76            inner_code: code.into(),
77            ..Default::default()
78        }
79        .into())
80    }
81}
82
83#[turbo_tasks::value_impl]
84impl ChunkItem for WorkerLoaderChunkItem {
85    #[turbo_tasks::function]
86    fn asset_ident(&self) -> Vc<AssetIdent> {
87        self.module.ident()
88    }
89
90    #[turbo_tasks::function]
91    fn content_ident(&self) -> Vc<AssetIdent> {
92        self.module.ident()
93    }
94
95    #[turbo_tasks::function]
96    fn references(self: Vc<Self>) -> Vc<OutputAssets> {
97        self.chunks()
98    }
99
100    #[turbo_tasks::function]
101    fn chunking_context(&self) -> Vc<Box<dyn ChunkingContext>> {
102        *ResolvedVc::upcast(self.chunking_context)
103    }
104
105    #[turbo_tasks::function]
106    async fn ty(&self) -> Result<Vc<Box<dyn ChunkType>>> {
107        Ok(Vc::upcast(
108            Vc::<EcmascriptChunkType>::default().resolve().await?,
109        ))
110    }
111
112    #[turbo_tasks::function]
113    fn module(&self) -> Vc<Box<dyn Module>> {
114        *ResolvedVc::upcast(self.module)
115    }
116}