turbopack_ecmascript/rename/
module.rs1use std::collections::BTreeMap;
2
3use anyhow::{Result, bail};
4use turbo_tasks::{ResolvedVc, Vc};
5use turbo_tasks_fs::{File, FileContent};
6use turbopack_core::{
7 asset::{Asset, AssetContent},
8 chunk::{
9 AsyncModuleInfo, ChunkableModule, ChunkingContext, EvaluatableAsset, MergeableModule,
10 MergeableModules, MergeableModulesExposed,
11 },
12 ident::AssetIdent,
13 module::{Module, ModuleSideEffects},
14 module_graph::ModuleGraph,
15 reference::ModuleReferences,
16 resolve::{ExportUsage, ModulePart},
17 source::OptionSource,
18};
19
20use crate::{
21 AnalyzeEcmascriptModuleResult, EcmascriptAnalyzable, EcmascriptAnalyzableExt,
22 EcmascriptModuleContent, EcmascriptModuleContentOptions, EcmascriptOptions,
23 MergedEcmascriptModule, SpecifiedModuleType,
24 chunk::{
25 EcmascriptChunkItemContent, EcmascriptChunkPlaceable, EcmascriptExports,
26 ecmascript_chunk_item,
27 },
28 code_gen::CodeGens,
29 references::{
30 async_module::{AsyncModule, OptionAsyncModule},
31 esm::{EsmExport, EsmExports, base::EsmAssetReferences},
32 },
33 side_effect_optimization::reference::EcmascriptModulePartReference,
34};
35
36#[turbo_tasks::value]
39pub struct EcmascriptModuleRenameModule {
40 module: ResolvedVc<Box<dyn EcmascriptChunkPlaceable>>,
41 part: ModulePart,
45}
46
47#[turbo_tasks::value_impl]
48impl EcmascriptModuleRenameModule {
49 #[turbo_tasks::function]
50 pub fn new(
51 module: ResolvedVc<Box<dyn EcmascriptChunkPlaceable>>,
52 part: ModulePart,
53 ) -> Vc<Self> {
54 assert!(
55 matches!(
56 part,
57 ModulePart::RenamedExport { .. } | ModulePart::RenamedNamespace { .. }
58 ),
59 "{part:?} is unexpected for EcmascriptModuleRenameModule"
60 );
61 EcmascriptModuleRenameModule { module, part }.cell()
62 }
63
64 #[turbo_tasks::function]
65 pub async fn async_module(&self) -> Result<Vc<AsyncModule>> {
66 let (import_externals, has_top_level_await) =
67 if let Some(async_module) = *self.module.get_async_module().await? {
68 (
69 async_module.await?.import_externals,
70 async_module.await?.has_top_level_await,
71 )
72 } else {
73 (false, false)
74 };
75 Ok(AsyncModule {
76 has_top_level_await,
77 import_externals,
78 }
79 .cell())
80 }
81}
82
83impl EcmascriptModuleRenameModule {
84 pub async fn module_reference(&self) -> Result<ResolvedVc<EcmascriptModulePartReference>> {
85 match &self.part {
86 ModulePart::RenamedNamespace { .. } => {
87 EcmascriptModulePartReference::new_normal(
88 *self.module,
89 self.part.clone(),
90 ExportUsage::all(),
91 )
92 .to_resolved()
93 .await
94 }
95 ModulePart::RenamedExport {
96 original_export, ..
97 } => {
98 EcmascriptModulePartReference::new_normal(
99 *self.module,
100 self.part.clone(),
101 ExportUsage::named(original_export.clone()),
102 )
103 .to_resolved()
104 .await
105 }
106 _ => {
107 bail!("Unexpected ModulePart for EcmascriptModuleRenameModule");
108 }
109 }
110 }
111}
112
113#[turbo_tasks::value_impl]
114impl Module for EcmascriptModuleRenameModule {
115 #[turbo_tasks::function]
116 fn source(&self) -> Vc<OptionSource> {
117 Vc::cell(None)
118 }
119
120 #[turbo_tasks::function]
121 fn ident(&self) -> Vc<AssetIdent> {
122 self.module.ident().with_part(self.part.clone())
123 }
124
125 #[turbo_tasks::function]
126 async fn references(self: Vc<Self>) -> Result<Vc<ModuleReferences>> {
127 let reference = self.await?.module_reference().await?;
128 Ok(Vc::cell(vec![ResolvedVc::upcast(reference)]))
129 }
130
131 #[turbo_tasks::function]
132 async fn is_self_async(self: Vc<Self>) -> Result<Vc<bool>> {
133 let async_module = self.async_module();
134 let references = self.references();
135 let is_self_async = async_module
136 .resolve()
137 .await?
138 .is_self_async(references.resolve().await?)
139 .resolve()
140 .await?;
141 Ok(is_self_async)
142 }
143
144 #[turbo_tasks::function]
145 fn side_effects(&self) -> Vc<ModuleSideEffects> {
146 ModuleSideEffects::ModuleEvaluationIsSideEffectFree.cell()
148 }
149}
150
151#[turbo_tasks::value_impl]
152impl Asset for EcmascriptModuleRenameModule {
153 #[turbo_tasks::function]
154 fn content(&self) -> Vc<AssetContent> {
155 let f = File::from("");
156
157 AssetContent::file(FileContent::Content(f).cell())
158 }
159}
160
161#[turbo_tasks::value_impl]
162impl EcmascriptAnalyzable for EcmascriptModuleRenameModule {
163 #[turbo_tasks::function]
164 fn analyze(&self) -> Result<Vc<AnalyzeEcmascriptModuleResult>> {
165 bail!("EcmascriptModuleRenameModule::analyze shouldn't be called");
166 }
167
168 #[turbo_tasks::function]
169 fn module_content_without_analysis(
170 &self,
171 _generate_source_map: bool,
172 ) -> Result<Vc<EcmascriptModuleContent>> {
173 bail!("EcmascriptModuleRenameModule::module_content_without_analysis shouldn't be called");
174 }
175
176 #[turbo_tasks::function]
177 async fn module_content_options(
178 self: ResolvedVc<Self>,
179 chunking_context: ResolvedVc<Box<dyn ChunkingContext>>,
180 async_module_info: Option<ResolvedVc<AsyncModuleInfo>>,
181 ) -> Result<Vc<EcmascriptModuleContentOptions>> {
182 let reference = self.await?.module_reference().await?;
183
184 Ok(EcmascriptModuleContentOptions {
185 parsed: None,
186 module: ResolvedVc::upcast(self),
187 specified_module_type: SpecifiedModuleType::EcmaScript,
188 chunking_context,
189 references: self.references().to_resolved().await?,
190 part_references: vec![reference],
191 esm_references: EsmAssetReferences::empty().to_resolved().await?,
192 code_generation: CodeGens::empty().to_resolved().await?,
193 async_module: ResolvedVc::cell(Some(self.async_module().to_resolved().await?)),
194 generate_source_map: false,
198 original_source_map: None,
199 exports: self.get_exports().to_resolved().await?,
200 async_module_info,
201 }
202 .cell())
203 }
204}
205
206#[turbo_tasks::value_impl]
207impl EcmascriptChunkPlaceable for EcmascriptModuleRenameModule {
208 #[turbo_tasks::function]
209 async fn get_exports(&self) -> Result<Vc<EcmascriptExports>> {
210 let reference = self.module_reference().await?;
211 let mut exports = BTreeMap::new();
212
213 match &self.part {
214 ModulePart::RenamedExport {
215 original_export,
216 export,
217 } => {
218 exports.insert(
219 export.clone(),
220 EsmExport::ImportedBinding(
221 ResolvedVc::upcast(reference),
222 original_export.clone(),
223 false,
224 ),
225 );
226 }
227 ModulePart::RenamedNamespace { export } => {
228 exports.insert(
229 export.clone(),
230 EsmExport::ImportedNamespace(ResolvedVc::upcast(reference)),
231 );
232 }
233 _ => bail!("Unexpected ModulePart for EcmascriptModuleRenameModule"),
234 }
235
236 let exports = EsmExports {
237 exports,
238 star_exports: Vec::new(),
239 }
240 .resolved_cell();
241 Ok(EcmascriptExports::EsmExports(exports).cell())
242 }
243
244 #[turbo_tasks::function]
245 async fn get_async_module(self: Vc<Self>) -> Result<Vc<OptionAsyncModule>> {
246 Ok(Vc::cell(Some(self.async_module().to_resolved().await?)))
247 }
248
249 #[turbo_tasks::function]
250 async fn chunk_item_content(
251 self: Vc<Self>,
252 chunking_context: Vc<Box<dyn ChunkingContext>>,
253 _module_graph: Vc<ModuleGraph>,
254 async_module_info: Option<Vc<AsyncModuleInfo>>,
255 _estimated: bool,
256 ) -> Result<Vc<EcmascriptChunkItemContent>> {
257 let async_module_options = self.get_async_module().module_options(async_module_info);
258 let content = self.module_content(chunking_context, async_module_info);
259 Ok(EcmascriptChunkItemContent::new(
260 content,
261 chunking_context,
262 async_module_options,
263 ))
264 }
265}
266
267#[turbo_tasks::value_impl]
268impl ChunkableModule for EcmascriptModuleRenameModule {
269 #[turbo_tasks::function]
270 fn as_chunk_item(
271 self: ResolvedVc<Self>,
272 module_graph: ResolvedVc<ModuleGraph>,
273 chunking_context: ResolvedVc<Box<dyn ChunkingContext>>,
274 ) -> Vc<Box<dyn turbopack_core::chunk::ChunkItem>> {
275 ecmascript_chunk_item(ResolvedVc::upcast(self), module_graph, chunking_context)
276 }
277}
278
279#[turbo_tasks::value_impl]
280impl EvaluatableAsset for EcmascriptModuleRenameModule {}
281
282#[turbo_tasks::value_impl]
283impl MergeableModule for EcmascriptModuleRenameModule {
284 #[turbo_tasks::function]
285 async fn merge(
286 self: Vc<Self>,
287 modules: Vc<MergeableModulesExposed>,
288 entry_points: Vc<MergeableModules>,
289 ) -> Result<Vc<Box<dyn ChunkableModule>>> {
290 Ok(Vc::upcast(
291 *MergedEcmascriptModule::new(
292 modules,
293 entry_points,
294 EcmascriptOptions::default().resolved_cell(),
295 )
296 .await?,
297 ))
298 }
299}