turbopack_ecmascript/rename/
module.rs1use anyhow::{Result, bail};
2use turbo_frozenmap::FrozenMap;
3use turbo_tasks::{ResolvedVc, Vc};
4use turbo_tasks_fs::{File, FileContent};
5use turbopack_core::{
6 asset::{Asset, AssetContent},
7 chunk::{
8 AsyncModuleInfo, ChunkableModule, ChunkingContext, EvaluatableAsset, MergeableModule,
9 MergeableModules, MergeableModulesExposed,
10 },
11 ident::AssetIdent,
12 module::{Module, ModuleSideEffects},
13 module_graph::ModuleGraph,
14 reference::ModuleReferences,
15 resolve::{ExportUsage, ModulePart},
16 source::OptionSource,
17};
18
19use crate::{
20 AnalyzeEcmascriptModuleResult, EcmascriptAnalyzable, EcmascriptAnalyzableExt,
21 EcmascriptModuleContent, EcmascriptModuleContentOptions, EcmascriptOptions,
22 MergedEcmascriptModule, SpecifiedModuleType,
23 chunk::{
24 EcmascriptChunkItemContent, EcmascriptChunkPlaceable, EcmascriptExports,
25 ecmascript_chunk_item,
26 },
27 code_gen::CodeGens,
28 references::{
29 async_module::{AsyncModule, OptionAsyncModule},
30 esm::{EsmExport, EsmExports, base::EsmAssetReferences},
31 },
32 side_effect_optimization::reference::EcmascriptModulePartReference,
33};
34
35#[turbo_tasks::value]
38pub struct EcmascriptModuleRenameModule {
39 module: ResolvedVc<Box<dyn EcmascriptChunkPlaceable>>,
40 part: ModulePart,
44}
45
46#[turbo_tasks::value_impl]
47impl EcmascriptModuleRenameModule {
48 #[turbo_tasks::function]
49 pub fn new(
50 module: ResolvedVc<Box<dyn EcmascriptChunkPlaceable>>,
51 part: ModulePart,
52 ) -> Vc<Self> {
53 assert!(
54 matches!(
55 part,
56 ModulePart::RenamedExport { .. } | ModulePart::RenamedNamespace { .. }
57 ),
58 "{part:?} is unexpected for EcmascriptModuleRenameModule"
59 );
60 EcmascriptModuleRenameModule { module, part }.cell()
61 }
62
63 #[turbo_tasks::function]
64 pub async fn async_module(&self) -> Result<Vc<AsyncModule>> {
65 let (import_externals, has_top_level_await) =
66 if let Some(async_module) = *self.module.get_async_module().await? {
67 (
68 async_module.await?.import_externals,
69 async_module.await?.has_top_level_await,
70 )
71 } else {
72 (false, false)
73 };
74 Ok(AsyncModule {
75 has_top_level_await,
76 import_externals,
77 }
78 .cell())
79 }
80}
81
82impl EcmascriptModuleRenameModule {
83 pub async fn module_reference(&self) -> Result<ResolvedVc<EcmascriptModulePartReference>> {
84 match &self.part {
85 ModulePart::RenamedNamespace { .. } => {
86 EcmascriptModulePartReference::new_normal(
87 *self.module,
88 self.part.clone(),
89 ExportUsage::all(),
90 )
91 .to_resolved()
92 .await
93 }
94 ModulePart::RenamedExport {
95 original_export, ..
96 } => {
97 EcmascriptModulePartReference::new_normal(
98 *self.module,
99 self.part.clone(),
100 ExportUsage::named(original_export.clone()),
101 )
102 .to_resolved()
103 .await
104 }
105 _ => {
106 bail!("Unexpected ModulePart for EcmascriptModuleRenameModule");
107 }
108 }
109 }
110}
111
112#[turbo_tasks::value_impl]
113impl Module for EcmascriptModuleRenameModule {
114 #[turbo_tasks::function]
115 fn source(&self) -> Vc<OptionSource> {
116 Vc::cell(None)
117 }
118
119 #[turbo_tasks::function]
120 async fn ident(&self) -> Result<Vc<AssetIdent>> {
121 Ok(self
122 .module
123 .ident()
124 .owned()
125 .await?
126 .with_part(self.part.clone())
127 .into_vc())
128 }
129
130 #[turbo_tasks::function]
131 async fn references(self: Vc<Self>) -> Result<Vc<ModuleReferences>> {
132 let reference = self.await?.module_reference().await?;
133 Ok(Vc::cell(vec![ResolvedVc::upcast(reference)]))
134 }
135
136 #[turbo_tasks::function]
137 async fn is_self_async(self: Vc<Self>) -> Result<Vc<bool>> {
138 let async_module = self.async_module();
139 let references = self.references();
140 let is_self_async = async_module
141 .to_resolved()
142 .await?
143 .is_self_async(*references.to_resolved().await?)
144 .to_resolved()
145 .await?;
146 Ok(*is_self_async)
147 }
148
149 #[turbo_tasks::function]
150 fn side_effects(&self) -> Vc<ModuleSideEffects> {
151 ModuleSideEffects::ModuleEvaluationIsSideEffectFree.cell()
153 }
154}
155
156#[turbo_tasks::value_impl]
157impl Asset for EcmascriptModuleRenameModule {
158 #[turbo_tasks::function]
159 fn content(&self) -> Vc<AssetContent> {
160 let f = File::from("");
161
162 AssetContent::file(FileContent::Content(f).cell())
163 }
164}
165
166#[turbo_tasks::value_impl]
167impl EcmascriptAnalyzable for EcmascriptModuleRenameModule {
168 #[turbo_tasks::function]
169 fn analyze(&self) -> Result<Vc<AnalyzeEcmascriptModuleResult>> {
170 bail!("EcmascriptModuleRenameModule::analyze shouldn't be called");
171 }
172
173 #[turbo_tasks::function]
174 fn module_content_without_analysis(
175 &self,
176 _generate_source_map: bool,
177 ) -> Result<Vc<EcmascriptModuleContent>> {
178 bail!("EcmascriptModuleRenameModule::module_content_without_analysis shouldn't be called");
179 }
180
181 #[turbo_tasks::function]
182 async fn module_content_options(
183 self: ResolvedVc<Self>,
184 chunking_context: ResolvedVc<Box<dyn ChunkingContext>>,
185 async_module_info: Option<ResolvedVc<AsyncModuleInfo>>,
186 ) -> Result<Vc<EcmascriptModuleContentOptions>> {
187 let reference = self.await?.module_reference().await?;
188
189 Ok(EcmascriptModuleContentOptions {
190 parsed: None,
191 module: ResolvedVc::upcast(self),
192 specified_module_type: SpecifiedModuleType::EcmaScript,
193 chunking_context,
194 references: self.references().to_resolved().await?,
195 part_references: vec![reference],
196 esm_references: EsmAssetReferences::empty().to_resolved().await?,
197 code_generation: CodeGens::empty().to_resolved().await?,
198 async_module: ResolvedVc::cell(Some(self.async_module().to_resolved().await?)),
199 generate_source_map: false,
203 original_source_map: None,
204 exports: self.get_exports().to_resolved().await?,
205 async_module_info,
206 }
207 .cell())
208 }
209}
210
211#[turbo_tasks::value_impl]
212impl EcmascriptChunkPlaceable for EcmascriptModuleRenameModule {
213 #[turbo_tasks::function]
214 async fn get_exports(&self) -> Result<Vc<EcmascriptExports>> {
215 let reference = self.module_reference().await?;
216
217 let export = match &self.part {
218 ModulePart::RenamedExport {
219 original_export,
220 export,
221 } => (
222 export.clone(),
223 EsmExport::ImportedBinding(
224 ResolvedVc::upcast(reference),
225 original_export.clone(),
226 false,
227 ),
228 ),
229 ModulePart::RenamedNamespace { export } => (
230 export.clone(),
231 EsmExport::ImportedNamespace(ResolvedVc::upcast(reference)),
232 ),
233 _ => bail!("Unexpected ModulePart for EcmascriptModuleRenameModule"),
234 };
235
236 let exports = EsmExports {
237 exports: FrozenMap::from_unique_sorted_box(Box::new([export])),
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}