turbopack_ecmascript/side_effect_optimization/locals/
module.rs1use std::collections::BTreeMap;
2
3use anyhow::{Result, bail};
4use turbo_tasks::{ResolvedVc, Vc};
5use turbo_tasks_fs::glob::Glob;
6use turbopack_core::{
7 asset::{Asset, AssetContent},
8 chunk::{
9 AsyncModuleInfo, ChunkableModule, ChunkingContext, MergeableModule, MergeableModules,
10 MergeableModulesExposed,
11 },
12 ident::AssetIdent,
13 module::Module,
14 module_graph::ModuleGraph,
15 reference::ModuleReferences,
16 resolve::ModulePart,
17};
18
19use super::chunk_item::EcmascriptModuleLocalsChunkItem;
20use crate::{
21 AnalyzeEcmascriptModuleResult, EcmascriptAnalyzable, EcmascriptModuleAsset,
22 EcmascriptModuleContent, EcmascriptModuleContentOptions, MergedEcmascriptModule,
23 chunk::{EcmascriptChunkPlaceable, EcmascriptExports},
24 references::{
25 async_module::OptionAsyncModule,
26 esm::{EsmExport, EsmExports},
27 },
28};
29
30#[turbo_tasks::value]
34pub struct EcmascriptModuleLocalsModule {
35 pub module: ResolvedVc<EcmascriptModuleAsset>,
36}
37
38#[turbo_tasks::value_impl]
39impl EcmascriptModuleLocalsModule {
40 #[turbo_tasks::function]
41 pub fn new(module: ResolvedVc<EcmascriptModuleAsset>) -> Vc<Self> {
42 EcmascriptModuleLocalsModule { module }.cell()
43 }
44}
45
46#[turbo_tasks::value_impl]
47impl Module for EcmascriptModuleLocalsModule {
48 #[turbo_tasks::function]
49 fn ident(&self) -> Vc<AssetIdent> {
50 self.module.ident().with_part(ModulePart::locals())
51 }
52
53 #[turbo_tasks::function]
54 fn references(&self) -> Result<Vc<ModuleReferences>> {
55 let result = self.module.analyze();
56 Ok(result.local_references())
57 }
58
59 #[turbo_tasks::function]
60 async fn is_self_async(self: Vc<Self>) -> Result<Vc<bool>> {
61 let analyze = self.await?.module.analyze().await?;
62 if let Some(async_module) = *analyze.async_module.await? {
63 let is_self_async = async_module.is_self_async(self.references());
64 Ok(is_self_async)
65 } else {
66 Ok(Vc::cell(false))
67 }
68 }
69}
70
71#[turbo_tasks::value_impl]
72impl Asset for EcmascriptModuleLocalsModule {
73 #[turbo_tasks::function]
74 fn content(&self) -> Vc<AssetContent> {
75 self.module.content()
76 }
77}
78
79#[turbo_tasks::value_impl]
80impl EcmascriptAnalyzable for EcmascriptModuleLocalsModule {
81 #[turbo_tasks::function]
82 fn analyze(&self) -> Vc<AnalyzeEcmascriptModuleResult> {
83 self.module.analyze()
84 }
85
86 #[turbo_tasks::function]
87 fn module_content_without_analysis(
88 &self,
89 generate_source_map: bool,
90 ) -> Vc<EcmascriptModuleContent> {
91 self.module
92 .module_content_without_analysis(generate_source_map)
93 }
94
95 #[turbo_tasks::function]
96 async fn module_content_options(
97 self: ResolvedVc<Self>,
98 chunking_context: ResolvedVc<Box<dyn ChunkingContext>>,
99 async_module_info: Option<ResolvedVc<AsyncModuleInfo>>,
100 ) -> Result<Vc<EcmascriptModuleContentOptions>> {
101 let exports = self.get_exports().to_resolved().await?;
102 let original_module = self.await?.module;
103 let parsed = original_module.parse().to_resolved().await?;
104
105 let analyze = original_module.analyze();
106 let analyze_result = analyze.await?;
107
108 let module_type_result = original_module.determine_module_type().await?;
109 let generate_source_map = *chunking_context
110 .reference_module_source_maps(Vc::upcast(*self))
111 .await?;
112
113 Ok(EcmascriptModuleContentOptions {
114 parsed,
115 module: ResolvedVc::upcast(self),
116 specified_module_type: module_type_result.module_type,
117 chunking_context,
118 references: analyze.local_references().to_resolved().await?,
119 esm_references: analyze_result.esm_local_references,
120 part_references: vec![],
121 code_generation: analyze_result.code_generation,
122 async_module: analyze_result.async_module,
123 generate_source_map,
124 original_source_map: analyze_result.source_map,
125 exports,
126 async_module_info,
127 }
128 .cell())
129 }
130}
131
132#[turbo_tasks::value_impl]
133impl EcmascriptChunkPlaceable for EcmascriptModuleLocalsModule {
134 #[turbo_tasks::function]
135 async fn get_exports(&self) -> Result<Vc<EcmascriptExports>> {
136 let EcmascriptExports::EsmExports(exports) = *self.module.get_exports().await? else {
137 bail!("EcmascriptModuleLocalsModule must only be used on modules with EsmExports");
138 };
139 let esm_exports = exports.await?;
140 let mut exports = BTreeMap::new();
141
142 for (name, export) in &esm_exports.exports {
143 match export {
144 EsmExport::ImportedBinding(..) | EsmExport::ImportedNamespace(..) => {
145 }
147 EsmExport::LocalBinding(local_name, mutable) => {
148 exports.insert(
149 name.clone(),
150 EsmExport::LocalBinding(local_name.clone(), *mutable),
151 );
152 }
153 EsmExport::Error => {
154 exports.insert(name.clone(), EsmExport::Error);
155 }
156 }
157 }
158
159 let exports = EsmExports {
160 exports,
161 star_exports: vec![],
162 }
163 .resolved_cell();
164 Ok(EcmascriptExports::EsmExports(exports).cell())
165 }
166
167 #[turbo_tasks::function]
168 fn is_marked_as_side_effect_free(&self, side_effect_free_packages: Vc<Glob>) -> Vc<bool> {
169 self.module
170 .is_marked_as_side_effect_free(side_effect_free_packages)
171 }
172
173 #[turbo_tasks::function]
174 fn get_async_module(&self) -> Vc<OptionAsyncModule> {
175 self.module.get_async_module()
176 }
177}
178
179#[turbo_tasks::value_impl]
180impl ChunkableModule for EcmascriptModuleLocalsModule {
181 #[turbo_tasks::function]
182 fn as_chunk_item(
183 self: ResolvedVc<Self>,
184 _module_graph: ResolvedVc<ModuleGraph>,
185 chunking_context: ResolvedVc<Box<dyn ChunkingContext>>,
186 ) -> Vc<Box<dyn turbopack_core::chunk::ChunkItem>> {
187 Vc::upcast(
188 EcmascriptModuleLocalsChunkItem {
189 module: self,
190 chunking_context,
191 }
192 .cell(),
193 )
194 }
195}
196
197#[turbo_tasks::value_impl]
198impl MergeableModule for EcmascriptModuleLocalsModule {
199 #[turbo_tasks::function]
200 async fn merge(
201 &self,
202 modules: Vc<MergeableModulesExposed>,
203 entry_points: Vc<MergeableModules>,
204 ) -> Result<Vc<Box<dyn ChunkableModule>>> {
205 Ok(Vc::upcast(
206 *MergedEcmascriptModule::new(modules, entry_points, self.module.await?.options).await?,
207 ))
208 }
209}