turbopack_ecmascript/worker_chunk/
chunk_item.rs

1use anyhow::Result;
2use indoc::formatdoc;
3use turbo_rcstr::RcStr;
4use turbo_tasks::{ResolvedVc, TryJoinIterExt, Value, 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::function]
34pub fn worker_modifier() -> Vc<RcStr> {
35    Vc::cell("worker".into())
36}
37
38#[turbo_tasks::value_impl]
39impl WorkerLoaderChunkItem {
40    #[turbo_tasks::function]
41    async fn chunks(&self) -> Result<Vc<OutputAssets>> {
42        let module = self.module.await?;
43
44        Ok(self.chunking_context.evaluated_chunk_group_assets(
45            module.inner.ident().with_modifier(worker_modifier()),
46            ChunkGroup::Isolated(ResolvedVc::upcast(module.inner)),
47            *self.module_graph,
48            Value::new(AvailabilityInfo::Root),
49        ))
50    }
51
52    #[turbo_tasks::function]
53    async fn chunks_data(self: Vc<Self>) -> Result<Vc<ChunksData>> {
54        let this = self.await?;
55        Ok(ChunkData::from_assets(
56            this.chunking_context.output_root(),
57            self.chunks(),
58        ))
59    }
60}
61
62#[turbo_tasks::value_impl]
63impl EcmascriptChunkItem for WorkerLoaderChunkItem {
64    #[turbo_tasks::function]
65    async fn content(self: Vc<Self>) -> Result<Vc<EcmascriptChunkItemContent>> {
66        let chunks_data = self.chunks_data().await?;
67        let chunks_data = chunks_data.iter().try_join().await?;
68        let chunks_data: Vec<_> = chunks_data
69            .iter()
70            .map(|chunk_data| EcmascriptChunkData::new(chunk_data))
71            .collect();
72
73        let code = formatdoc! {
74            r#"
75                {TURBOPACK_EXPORT_VALUE}({TURBOPACK_WORKER_BLOB_URL}({chunks:#}));
76            "#,
77            chunks = StringifyJs(&chunks_data),
78        };
79
80        Ok(EcmascriptChunkItemContent {
81            inner_code: code.into(),
82            ..Default::default()
83        }
84        .into())
85    }
86}
87
88#[turbo_tasks::function]
89fn chunk_reference_description() -> Vc<RcStr> {
90    Vc::cell("worker chunk".into())
91}
92
93#[turbo_tasks::value_impl]
94impl ChunkItem for WorkerLoaderChunkItem {
95    #[turbo_tasks::function]
96    fn asset_ident(&self) -> Vc<AssetIdent> {
97        self.module.ident()
98    }
99
100    #[turbo_tasks::function]
101    fn content_ident(&self) -> Vc<AssetIdent> {
102        self.module.ident()
103    }
104
105    #[turbo_tasks::function]
106    fn references(self: Vc<Self>) -> Vc<OutputAssets> {
107        self.chunks()
108    }
109
110    #[turbo_tasks::function]
111    fn chunking_context(&self) -> Vc<Box<dyn ChunkingContext>> {
112        *ResolvedVc::upcast(self.chunking_context)
113    }
114
115    #[turbo_tasks::function]
116    async fn ty(&self) -> Result<Vc<Box<dyn ChunkType>>> {
117        Ok(Vc::upcast(
118            Vc::<EcmascriptChunkType>::default().resolve().await?,
119        ))
120    }
121
122    #[turbo_tasks::function]
123    fn module(&self) -> Vc<Box<dyn Module>> {
124        *ResolvedVc::upcast(self.module)
125    }
126}