Skip to main content

turbopack_ecmascript/worker_chunk/
module.rs

1use anyhow::Result;
2use turbo_rcstr::{RcStr, rcstr};
3use turbo_tasks::{ResolvedVc, ValueToString, Vc};
4use turbopack_core::{
5    chunk::{
6        ChunkGroupType, ChunkableModule, ChunkableModuleReference, ChunkingContext, ChunkingType,
7        ChunkingTypeOption,
8    },
9    context::AssetContext,
10    ident::AssetIdent,
11    module::{Module, ModuleSideEffects},
12    module_graph::ModuleGraph,
13    reference::{ModuleReference, ModuleReferences},
14    resolve::ModuleResolveResult,
15};
16
17use super::{chunk_item::WorkerLoaderChunkItem, worker_type::WorkerType};
18
19/// The WorkerLoaderModule is a module that creates a separate root chunk group for the given module
20/// and exports a URL (for web workers) or file path (for Node.js workers) to pass to the worker
21/// constructor.
22#[turbo_tasks::value]
23pub struct WorkerLoaderModule {
24    pub inner: ResolvedVc<Box<dyn ChunkableModule>>,
25    pub worker_type: WorkerType,
26    pub asset_context: ResolvedVc<Box<dyn AssetContext>>,
27}
28
29#[turbo_tasks::value_impl]
30impl WorkerLoaderModule {
31    #[turbo_tasks::function]
32    pub fn new(
33        module: ResolvedVc<Box<dyn ChunkableModule>>,
34        worker_type: WorkerType,
35        asset_context: ResolvedVc<Box<dyn AssetContext>>,
36    ) -> Vc<Self> {
37        Self::cell(WorkerLoaderModule {
38            inner: module,
39            worker_type,
40            asset_context,
41        })
42    }
43}
44
45#[turbo_tasks::value_impl]
46impl Module for WorkerLoaderModule {
47    #[turbo_tasks::function]
48    fn ident(&self) -> Vc<AssetIdent> {
49        self.inner
50            .ident()
51            .with_modifier(self.worker_type.modifier_str())
52    }
53
54    #[turbo_tasks::function]
55    fn source(&self) -> Vc<turbopack_core::source::OptionSource> {
56        Vc::cell(None)
57    }
58
59    #[turbo_tasks::function]
60    async fn references(self: Vc<Self>) -> Result<Vc<ModuleReferences>> {
61        let this = self.await?;
62        Ok(Vc::cell(vec![ResolvedVc::upcast(
63            WorkerModuleReference::new(*ResolvedVc::upcast(this.inner), this.worker_type)
64                .to_resolved()
65                .await?,
66        )]))
67    }
68
69    #[turbo_tasks::function]
70    fn side_effects(self: Vc<Self>) -> Vc<ModuleSideEffects> {
71        ModuleSideEffects::SideEffectFree.cell()
72    }
73}
74
75#[turbo_tasks::value_impl]
76impl ChunkableModule for WorkerLoaderModule {
77    #[turbo_tasks::function]
78    async fn as_chunk_item(
79        self: ResolvedVc<Self>,
80        module_graph: ResolvedVc<ModuleGraph>,
81        chunking_context: ResolvedVc<Box<dyn ChunkingContext>>,
82    ) -> Result<Vc<Box<dyn turbopack_core::chunk::ChunkItem>>> {
83        let this = self.await?;
84        Ok(Vc::upcast(
85            WorkerLoaderChunkItem {
86                module: self,
87                module_graph,
88                chunking_context,
89                worker_type: this.worker_type,
90                asset_context: this.asset_context,
91            }
92            .cell(),
93        ))
94    }
95}
96
97#[turbo_tasks::value]
98struct WorkerModuleReference {
99    module: ResolvedVc<Box<dyn Module>>,
100    worker_type: WorkerType,
101}
102
103#[turbo_tasks::value_impl]
104impl WorkerModuleReference {
105    #[turbo_tasks::function]
106    pub fn new(module: ResolvedVc<Box<dyn Module>>, worker_type: WorkerType) -> Vc<Self> {
107        Self::cell(WorkerModuleReference {
108            module,
109            worker_type,
110        })
111    }
112}
113
114#[turbo_tasks::value_impl]
115impl ChunkableModuleReference for WorkerModuleReference {
116    #[turbo_tasks::function]
117    fn chunking_type(&self) -> Vc<ChunkingTypeOption> {
118        Vc::cell(Some(ChunkingType::Isolated {
119            _ty: match self.worker_type {
120                WorkerType::SharedWebWorker | WorkerType::WebWorker => ChunkGroupType::Evaluated,
121                WorkerType::NodeWorkerThread => ChunkGroupType::Entry,
122            },
123            merge_tag: None,
124        }))
125    }
126}
127
128#[turbo_tasks::value_impl]
129impl ModuleReference for WorkerModuleReference {
130    #[turbo_tasks::function]
131    fn resolve_reference(&self) -> Vc<ModuleResolveResult> {
132        *ModuleResolveResult::module(self.module)
133    }
134}
135
136#[turbo_tasks::value_impl]
137impl ValueToString for WorkerModuleReference {
138    #[turbo_tasks::function]
139    fn to_string(&self) -> Vc<RcStr> {
140        Vc::cell(match self.worker_type {
141            WorkerType::WebWorker => rcstr!("web worker module"),
142            WorkerType::NodeWorkerThread => rcstr!("node worker thread module"),
143            WorkerType::SharedWebWorker => rcstr!("shared web worker module"),
144        })
145    }
146}