From 6cff8a1133a7ccd369e2f8ca0e2aadce8397714b Mon Sep 17 00:00:00 2001 From: Niklas Mischkulnig <4586894+mischnic@users.noreply.github.com> Date: Thu, 13 Feb 2025 22:13:32 +0100 Subject: [PATCH 1/6] wip --- .../crates/turbopack-ecmascript/src/lib.rs | 19 ++- .../src/references/esm/base.rs | 17 +-- .../src/references/mod.rs | 113 ++++++++++-------- .../side_effect_optimization/facade/module.rs | 38 +++--- .../locals/chunk_item.rs | 5 +- .../side_effect_optimization/locals/module.rs | 10 +- .../src/tree_shake/asset.rs | 6 +- .../src/tree_shake/chunk_item.rs | 15 +-- 8 files changed, 122 insertions(+), 101 deletions(-) diff --git a/turbopack/crates/turbopack-ecmascript/src/lib.rs b/turbopack/crates/turbopack-ecmascript/src/lib.rs index 5199e6257f8c0..65270883f8e83 100644 --- a/turbopack/crates/turbopack-ecmascript/src/lib.rs +++ b/turbopack/crates/turbopack-ecmascript/src/lib.rs @@ -417,7 +417,8 @@ impl EcmascriptAnalyzable for EcmascriptModuleAsset { ) -> Result> { let parsed = self.parse().to_resolved().await?; - let analyze = self.analyze().await?; + let analyze = self.analyze(); + let analyze_ref = analyze.await?; let module_type_result = *self.determine_module_type().await?; let generate_source_map = chunking_context.reference_module_source_maps(Vc::upcast(self)); @@ -428,12 +429,12 @@ impl EcmascriptAnalyzable for EcmascriptModuleAsset { module_type_result.module_type, module_graph, chunking_context, - *analyze.references, - *analyze.code_generation, - *analyze.async_module, + analyze.references(), + *analyze_ref.code_generation, + *analyze_ref.async_module, generate_source_map, - *analyze.source_map, - *analyze.exports, + *analyze_ref.source_map, + *analyze_ref.exports, async_module_info, )) } @@ -590,15 +591,13 @@ impl Module for EcmascriptModuleAsset { #[turbo_tasks::function] async fn references(self: Vc) -> Result> { - let analyze = self.analyze().await?; - let references = analyze.references.await?.iter().copied().collect(); - Ok(Vc::cell(references)) + Ok(self.analyze().references()) } #[turbo_tasks::function] async fn is_self_async(self: Vc) -> Result> { if let Some(async_module) = *self.get_async_module().await? { - Ok(async_module.is_self_async(*self.analyze().await?.references)) + Ok(async_module.is_self_async(self.references())) } else { Ok(Vc::cell(false)) } diff --git a/turbopack/crates/turbopack-ecmascript/src/references/esm/base.rs b/turbopack/crates/turbopack-ecmascript/src/references/esm/base.rs index 29d03a5748dd0..55aa42d482763 100644 --- a/turbopack/crates/turbopack-ecmascript/src/references/esm/base.rs +++ b/turbopack/crates/turbopack-ecmascript/src/references/esm/base.rs @@ -33,7 +33,7 @@ use super::export::{all_known_export_names, is_export_missing}; use crate::{ analyzer::imports::ImportAnnotations, chunk::EcmascriptChunkPlaceable, - code_gen::{CodeGenerateable, CodeGeneration}, + code_gen::CodeGeneration, magic_identifier, references::util::{request_to_string, throw_module_not_found_expr}, runtime_functions::{TURBOPACK_EXTERNAL_IMPORT, TURBOPACK_EXTERNAL_REQUIRE, TURBOPACK_IMPORT}, @@ -110,6 +110,9 @@ impl ReferencedAsset { } } +#[turbo_tasks::value(transparent)] +pub struct EsmAssetReferences(Vec>); + #[turbo_tasks::value(shared)] #[derive(Hash, Debug)] pub struct EsmAssetReference { @@ -252,14 +255,12 @@ impl ChunkableModuleReference for EsmAssetReference { } } -#[turbo_tasks::value_impl] -impl CodeGenerateable for EsmAssetReference { - #[turbo_tasks::function] - async fn code_generation( +impl EsmAssetReference { + pub async fn code_generation( self: Vc, module_graph: Vc, chunking_context: Vc>, - ) -> Result> { + ) -> Result { let this = &*self.await?; // only chunked references can be imported @@ -392,9 +393,9 @@ impl CodeGenerateable for EsmAssetReference { }; if let Some((key, stmt)) = result { - Ok(CodeGeneration::hoisted_stmt(key, stmt).cell()) + Ok(CodeGeneration::hoisted_stmt(key, stmt)) } else { - Ok(CodeGeneration::empty().cell()) + Ok(CodeGeneration::empty()) } } } diff --git a/turbopack/crates/turbopack-ecmascript/src/references/mod.rs b/turbopack/crates/turbopack-ecmascript/src/references/mod.rs index c31395be46876..e39b226301ca7 100644 --- a/turbopack/crates/turbopack-ecmascript/src/references/mod.rs +++ b/turbopack/crates/turbopack-ecmascript/src/references/mod.rs @@ -28,7 +28,7 @@ use num_traits::Zero; use once_cell::sync::Lazy; use parking_lot::Mutex; use regex::Regex; -use rustc_hash::FxHashMap; +use rustc_hash::{FxHashMap, FxHashSet}; use serde::{Deserialize, Serialize}; use swc_core::{ atoms::JsWord, @@ -154,12 +154,14 @@ use crate::{ }; #[turbo_tasks::value(shared)] -#[derive(Clone)] pub struct AnalyzeEcmascriptModuleResult { - pub references: ResolvedVc, - pub local_references: ResolvedVc, - pub reexport_references: ResolvedVc, - pub evaluation_references: ResolvedVc, + references: Vec>>, + + esm_references: Vec>, + esm_local_references: Vec>, + pub esm_reexport_references: Vec>, + pub esm_evaluation_references: Vec>, + pub code_generation: ResolvedVc, pub exports: ResolvedVc, pub async_module: ResolvedVc, @@ -168,16 +170,29 @@ pub struct AnalyzeEcmascriptModuleResult { pub source_map: ResolvedVc, } +#[turbo_tasks::value_impl] +impl AnalyzeEcmascriptModuleResult { + #[turbo_tasks::function] + pub fn references(&self) -> Vc { + Vc::cell( + self.esm_local_references + .iter() + .map(|r| ResolvedVc::upcast(*r)) + .chain(self.references.iter().copied()) + .collect(), + ) + } +} + /// A temporary analysis result builder to pass around, to be turned into an /// `Vc` eventually. pub struct AnalyzeEcmascriptModuleResultBuilder { references: FxIndexSet>>, - local_references: FxIndexSet>>, - esm_references: Vec, - esm_local_references: Vec, - esm_reexport_references: Vec, - esm_evaluation_references: Vec, + esm_references: FxHashSet, + esm_local_references: FxHashSet, + esm_reexport_references: FxHashSet, + esm_evaluation_references: FxHashSet, code_gens: Vec, exports: EcmascriptExports, @@ -190,7 +205,6 @@ impl AnalyzeEcmascriptModuleResultBuilder { pub fn new() -> Self { Self { references: Default::default(), - local_references: Default::default(), esm_references: Default::default(), esm_local_references: Default::default(), esm_reexport_references: Default::default(), @@ -207,7 +221,6 @@ impl AnalyzeEcmascriptModuleResultBuilder { pub fn add_reference(&mut self, reference: ResolvedVc>>) { let r = ResolvedVc::upcast(reference); self.references.insert(r); - self.local_references.insert(r); } /// Adds an asset reference with codegen to the analysis result. @@ -219,22 +232,22 @@ impl AnalyzeEcmascriptModuleResultBuilder { /// Adds an ESM asset reference to the analysis result. pub fn add_esm_reference(&mut self, idx: usize) { - self.esm_references.push(idx); - self.esm_local_references.push(idx); + self.esm_references.insert(idx); + self.esm_local_references.insert(idx); } /// Adds an reexport ESM reference to the analysis result. /// If you're unsure about which function to use, use `add_reference()` pub fn add_esm_reexport_reference(&mut self, idx: usize) { - self.esm_references.push(idx); - self.esm_reexport_references.push(idx); + self.esm_references.insert(idx); + self.esm_reexport_references.insert(idx); } /// Adds an evaluation ESM reference to the analysis result. /// If you're unsure about which function to use, use `add_reference()` pub fn add_esm_evaluation_reference(&mut self, idx: usize) { - self.esm_references.push(idx); - self.esm_evaluation_references.push(idx); + self.esm_references.insert(idx); + self.esm_evaluation_references.insert(idx); } /// Adds a codegen to the analysis result. @@ -271,41 +284,42 @@ impl AnalyzeEcmascriptModuleResultBuilder { import_references: Vec>, track_reexport_references: bool, ) -> Result> { - self.esm_references.sort(); - let esm_references = self - .esm_references + let mut esm_references: Vec<_> = self.esm_references.into_iter().collect(); + esm_references.sort(); + let esm_references = esm_references .into_iter() - .map(|i| ResolvedVc::upcast(import_references[i])); + .map(|i| import_references[i]) + .collect(); let (esm_local_references, esm_reexport_references, esm_evaluation_references) = if track_reexport_references { - self.esm_local_references.sort(); - self.esm_reexport_references.sort(); - self.esm_evaluation_references.sort(); + let mut esm_local_references: Vec<_> = + self.esm_local_references.into_iter().collect(); + let mut esm_reexport_references: Vec<_> = + self.esm_reexport_references.into_iter().collect(); + let mut esm_evaluation_references: Vec<_> = + self.esm_evaluation_references.into_iter().collect(); + esm_local_references.sort(); + esm_reexport_references.sort(); + esm_evaluation_references.sort(); ( - Some( - self.esm_local_references - .into_iter() - .map(|i| ResolvedVc::upcast(import_references[i])), - ), - self.esm_reexport_references + esm_local_references + .into_iter() + .map(|i| import_references[i]) + .collect(), + esm_reexport_references .into_iter() - .map(|i| ResolvedVc::upcast(import_references[i])) + .map(|i| import_references[i]) .collect(), - self.esm_evaluation_references + esm_evaluation_references .into_iter() - .map(|i| ResolvedVc::upcast(import_references[i])) + .map(|i| import_references[i]) .collect(), ) } else { - (None, vec![], vec![]) + (vec![], vec![], vec![]) }; - let references: Vec<_> = esm_references.chain(self.references.into_iter()).collect(); - let local_references: Vec<_> = esm_local_references - .into_iter() - .flatten() - .chain(self.local_references.into_iter()) - .collect(); + let references: Vec<_> = self.references.into_iter().collect(); let source_map = if let Some(source_map) = self.source_map { source_map @@ -316,10 +330,11 @@ impl AnalyzeEcmascriptModuleResultBuilder { self.code_gens.shrink_to_fit(); Ok(AnalyzeEcmascriptModuleResult::cell( AnalyzeEcmascriptModuleResult { - references: ResolvedVc::cell(references), - local_references: ResolvedVc::cell(local_references), - reexport_references: ResolvedVc::cell(esm_reexport_references), - evaluation_references: ResolvedVc::cell(esm_evaluation_references), + references: (references), + esm_references: (esm_references), + esm_local_references: (esm_local_references), + esm_reexport_references: (esm_reexport_references), + esm_evaluation_references: (esm_evaluation_references), code_generation: ResolvedVc::cell(self.code_gens), exports: self.exports.resolved_cell(), async_module: self.async_module, @@ -1235,13 +1250,13 @@ pub(crate) async fn analyse_ecmascript_module_internal( span: _, in_try: _, } => { - let Some(r) = import_references.get(esm_reference_index).copied() else { + let Some(r) = import_references.get(esm_reference_index) else { continue; }; if let Some("__turbopack_module_id__") = export.as_deref() { analysis.add_reference_code_gen( - EsmModuleIdAssetReference::new(r), + EsmModuleIdAssetReference::new(*r), ast_path.into(), ) } else { @@ -1277,7 +1292,7 @@ pub(crate) async fn analyse_ecmascript_module_internal( } analysis.add_esm_reference(esm_reference_index); - analysis.add_code_gen(EsmBinding::new(r, export, ast_path.into())); + analysis.add_code_gen(EsmBinding::new(*r, export, ast_path.into())); } } Effect::TypeOf { diff --git a/turbopack/crates/turbopack-ecmascript/src/side_effect_optimization/facade/module.rs b/turbopack/crates/turbopack-ecmascript/src/side_effect_optimization/facade/module.rs index 970aa88062852..8bec6c6f944b0 100644 --- a/turbopack/crates/turbopack-ecmascript/src/side_effect_optimization/facade/module.rs +++ b/turbopack/crates/turbopack-ecmascript/src/side_effect_optimization/facade/module.rs @@ -81,14 +81,16 @@ impl Module for EcmascriptModuleFacadeModule { ); }; let result = module.analyze().await?; - let references = result.evaluation_references; - let mut references = references.owned().await?; - references.push(ResolvedVc::upcast( - EcmascriptModulePartReference::new_part(*self.module, ModulePart::locals()) - .to_resolved() - .await?, - )); - references + result + .esm_evaluation_references + .iter() + .map(|r| ResolvedVc::upcast(*r)) + .chain(std::iter::once(ResolvedVc::upcast( + EcmascriptModulePartReference::new_part(*self.module, ModulePart::locals()) + .to_resolved() + .await?, + ))) + .collect() } ModulePart::Exports => { let Some(module) = @@ -96,18 +98,20 @@ impl Module for EcmascriptModuleFacadeModule { else { bail!( "Expected EcmascriptModuleAsset for a EcmascriptModuleFacadeModule with \ - ModulePart::Evaluation" + ModulePart::Exports" ); }; let result = module.analyze().await?; - let references = result.reexport_references; - let mut references = references.owned().await?; - references.push(ResolvedVc::upcast( - EcmascriptModulePartReference::new_part(*self.module, ModulePart::locals()) - .to_resolved() - .await?, - )); - references + result + .esm_reexport_references + .iter() + .map(|r| ResolvedVc::upcast(*r)) + .chain(std::iter::once(ResolvedVc::upcast( + EcmascriptModulePartReference::new_part(*self.module, ModulePart::locals()) + .to_resolved() + .await?, + ))) + .collect() } ModulePart::Facade => { vec![ diff --git a/turbopack/crates/turbopack-ecmascript/src/side_effect_optimization/locals/chunk_item.rs b/turbopack/crates/turbopack-ecmascript/src/side_effect_optimization/locals/chunk_item.rs index f8fc438599ac0..6389fa0e45c58 100644 --- a/turbopack/crates/turbopack-ecmascript/src/side_effect_optimization/locals/chunk_item.rs +++ b/turbopack/crates/turbopack-ecmascript/src/side_effect_optimization/locals/chunk_item.rs @@ -43,7 +43,8 @@ impl EcmascriptChunkItem for EcmascriptModuleLocalsChunkItem { let original_module = module.module; let parsed = original_module.parse().resolve().await?; - let analyze_result = original_module.analyze().await?; + let analyze = original_module.analyze(); + let analyze_result = analyze.await?; let async_module_options = analyze_result .async_module .module_options(async_module_info); @@ -58,7 +59,7 @@ impl EcmascriptChunkItem for EcmascriptModuleLocalsChunkItem { module_type_result.module_type, *module_graph, *chunking_context, - *analyze_result.local_references, + analyze.references(), *analyze_result.code_generation, *analyze_result.async_module, generate_source_map, diff --git a/turbopack/crates/turbopack-ecmascript/src/side_effect_optimization/locals/module.rs b/turbopack/crates/turbopack-ecmascript/src/side_effect_optimization/locals/module.rs index 61e95947ed867..0498444e6d638 100644 --- a/turbopack/crates/turbopack-ecmascript/src/side_effect_optimization/locals/module.rs +++ b/turbopack/crates/turbopack-ecmascript/src/side_effect_optimization/locals/module.rs @@ -50,15 +50,15 @@ impl Module for EcmascriptModuleLocalsModule { #[turbo_tasks::function] async fn references(&self) -> Result> { - let result = self.module.analyze().await?; - Ok(*result.local_references) + let result = self.module.analyze(); + Ok(result.references()) } #[turbo_tasks::function] - async fn is_self_async(&self) -> Result> { - let analyze = self.module.analyze().await?; + async fn is_self_async(self: Vc) -> Result> { + let analyze = self.await?.module.analyze().await?; if let Some(async_module) = *analyze.async_module.await? { - let is_self_async = async_module.is_self_async(*analyze.local_references); + let is_self_async = async_module.is_self_async(self.references()); Ok(is_self_async) } else { Ok(Vc::cell(false)) diff --git a/turbopack/crates/turbopack-ecmascript/src/tree_shake/asset.rs b/turbopack/crates/turbopack-ecmascript/src/tree_shake/asset.rs index 3dddcf62e66e0..126068e5d5a4d 100644 --- a/turbopack/crates/turbopack-ecmascript/src/tree_shake/asset.rs +++ b/turbopack/crates/turbopack-ecmascript/src/tree_shake/asset.rs @@ -292,11 +292,11 @@ impl Module for EcmascriptModulePartAsset { async fn references(&self) -> Result> { let split_data = split_module(*self.full_module).await?; - let analyze = analyze(*self.full_module, self.part.clone()).await?; + let analyze = analyze(*self.full_module, self.part.clone()); let deps = match &*split_data { SplitResult::Ok { deps, .. } => deps, - SplitResult::Failed { .. } => return Ok(*analyze.references), + SplitResult::Failed { .. } => return Ok(analyze.references()), }; let part_dep = |part: ModulePart| -> Vc> { @@ -306,7 +306,7 @@ impl Module for EcmascriptModulePartAsset { )) }; - let mut references = analyze.references.await?.to_vec(); + let mut references = analyze.references().owned().await?; // Facade depends on evaluation and re-exports if self.part == ModulePart::Facade { diff --git a/turbopack/crates/turbopack-ecmascript/src/tree_shake/chunk_item.rs b/turbopack/crates/turbopack-ecmascript/src/tree_shake/chunk_item.rs index 653c9f55344c8..bbb707941f9af 100644 --- a/turbopack/crates/turbopack-ecmascript/src/tree_shake/chunk_item.rs +++ b/turbopack/crates/turbopack-ecmascript/src/tree_shake/chunk_item.rs @@ -51,8 +51,9 @@ impl EcmascriptChunkItem for EcmascriptModulePartChunkItem { let split_data = split_module(*module.full_module); let parsed = part_of_module(split_data, module.part.clone()); - let analyze = self.module.analyze().await?; - let async_module_options = analyze.async_module.module_options(async_module_info); + let analyze = self.module.analyze(); + let analyze_ref = analyze.await?; + let async_module_options = analyze_ref.async_module.module_options(async_module_info); let module_type_result = *module.full_module.determine_module_type().await?; let generate_source_map = self @@ -65,12 +66,12 @@ impl EcmascriptChunkItem for EcmascriptModulePartChunkItem { module_type_result.module_type, *self.module_graph, *self.chunking_context, - *analyze.references, - *analyze.code_generation, - *analyze.async_module, + analyze.references(), + *analyze_ref.code_generation, + *analyze_ref.async_module, generate_source_map, - *analyze.source_map, - *analyze.exports, + *analyze_ref.source_map, + *analyze_ref.exports, async_module_info, ); From 97d7326a4033818c21fd42ed0cbe24a884919501 Mon Sep 17 00:00:00 2001 From: Niklas Mischkulnig <4586894+mischnic@users.noreply.github.com> Date: Thu, 13 Feb 2025 22:56:48 +0100 Subject: [PATCH 2/6] wip --- .../crates/turbopack-ecmascript/src/lib.rs | 27 +++--- .../src/references/mod.rs | 40 ++++++--- .../facade/chunk_item.rs | 24 ++--- .../side_effect_optimization/facade/module.rs | 88 ++++++++++++++++++- .../locals/chunk_item.rs | 5 +- .../side_effect_optimization/locals/module.rs | 2 +- .../src/side_effect_optimization/reference.rs | 17 ++-- .../src/tree_shake/chunk_item.rs | 2 +- 8 files changed, 147 insertions(+), 58 deletions(-) diff --git a/turbopack/crates/turbopack-ecmascript/src/lib.rs b/turbopack/crates/turbopack-ecmascript/src/lib.rs index 65270883f8e83..cd0f0ba084d13 100644 --- a/turbopack/crates/turbopack-ecmascript/src/lib.rs +++ b/turbopack/crates/turbopack-ecmascript/src/lib.rs @@ -42,7 +42,7 @@ use std::{ use anyhow::Result; use chunk::EcmascriptChunkItem; -use code_gen::{CodeGenerateable, CodeGeneration, CodeGenerationHoistedStmt}; +use code_gen::{CodeGeneration, CodeGenerationHoistedStmt}; use either::Either; use parse::{parse, ParseResult}; use path_visitor::ApplyVisitors; @@ -95,7 +95,9 @@ use crate::{ chunk::EcmascriptChunkPlaceable, code_gen::CodeGens, parse::generate_js_source_map, - references::{analyse_ecmascript_module, async_module::OptionAsyncModule}, + references::{ + analyse_ecmascript_module, async_module::OptionAsyncModule, esm::base::EsmAssetReferences, + }, transform::remove_shebang, }; @@ -429,7 +431,7 @@ impl EcmascriptAnalyzable for EcmascriptModuleAsset { module_type_result.module_type, module_graph, chunking_context, - analyze.references(), + (analyze.references(), *analyze_ref.esm_references), *analyze_ref.code_generation, *analyze_ref.async_module, generate_source_map, @@ -765,7 +767,7 @@ impl EcmascriptModuleContent { specified_module_type: SpecifiedModuleType, module_graph: Vc, chunking_context: Vc>, - references: Vc, + (references, esm_references): (Vc, Vc), code_generation: Vc, async_module: Vc, generate_source_map: Vc, @@ -773,13 +775,6 @@ impl EcmascriptModuleContent { exports: Vc, async_module_info: Option>, ) -> Result> { - let mut code_gen_cells = Vec::new(); - for r in references.await?.iter() { - if let Some(code_gen) = ResolvedVc::try_sidecast::>(*r) { - code_gen_cells.push(code_gen.code_generation(module_graph, chunking_context)); - } - } - let additional_code_gens = [ if let Some(async_module) = &*async_module.await? { Some( @@ -806,17 +801,21 @@ impl EcmascriptModuleContent { }, ]; + let esm_code_gens = esm_references + .await? + .iter() + .map(|r| r.code_generation(module_graph, chunking_context)) + .try_join() + .await?; let code_gens = code_generation .await? .iter() .map(|c| c.code_generation(module_graph, chunking_context)) .try_join() .await?; - let code_gen_cells = code_gen_cells.into_iter().try_join().await?; - let code_gens = code_gen_cells + let code_gens = esm_code_gens .iter() - .map(|c| &**c) .chain(additional_code_gens.iter().flatten()) .chain(code_gens.iter()); gen_content_with_code_gens( diff --git a/turbopack/crates/turbopack-ecmascript/src/references/mod.rs b/turbopack/crates/turbopack-ecmascript/src/references/mod.rs index e39b226301ca7..dfdaa2e79286f 100644 --- a/turbopack/crates/turbopack-ecmascript/src/references/mod.rs +++ b/turbopack/crates/turbopack-ecmascript/src/references/mod.rs @@ -136,7 +136,10 @@ use crate::{ async_module::{AsyncModule, OptionAsyncModule}, cjs::{CjsRequireAssetReference, CjsRequireCacheAccess, CjsRequireResolveAssetReference}, dynamic_expression::DynamicExpression, - esm::{module_id::EsmModuleIdAssetReference, EsmBinding, UrlRewriteBehavior}, + esm::{ + base::EsmAssetReferences, module_id::EsmModuleIdAssetReference, EsmBinding, + UrlRewriteBehavior, + }, ident::IdentReplacement, member::MemberReplacement, node::PackageJsonReference, @@ -157,10 +160,10 @@ use crate::{ pub struct AnalyzeEcmascriptModuleResult { references: Vec>>, - esm_references: Vec>, - esm_local_references: Vec>, - pub esm_reexport_references: Vec>, - pub esm_evaluation_references: Vec>, + pub esm_references: ResolvedVc, + pub esm_local_references: ResolvedVc, + pub esm_reexport_references: ResolvedVc, + pub esm_evaluation_references: ResolvedVc, pub code_generation: ResolvedVc, pub exports: ResolvedVc, @@ -173,14 +176,27 @@ pub struct AnalyzeEcmascriptModuleResult { #[turbo_tasks::value_impl] impl AnalyzeEcmascriptModuleResult { #[turbo_tasks::function] - pub fn references(&self) -> Vc { - Vc::cell( + pub async fn references(&self) -> Result> { + Ok(Vc::cell( + self.esm_references + .await? + .iter() + .map(|r| ResolvedVc::upcast(*r)) + .chain(self.references.iter().copied()) + .collect(), + )) + } + + #[turbo_tasks::function] + pub async fn local_references(&self) -> Result> { + Ok(Vc::cell( self.esm_local_references + .await? .iter() .map(|r| ResolvedVc::upcast(*r)) .chain(self.references.iter().copied()) .collect(), - ) + )) } } @@ -331,10 +347,10 @@ impl AnalyzeEcmascriptModuleResultBuilder { Ok(AnalyzeEcmascriptModuleResult::cell( AnalyzeEcmascriptModuleResult { references: (references), - esm_references: (esm_references), - esm_local_references: (esm_local_references), - esm_reexport_references: (esm_reexport_references), - esm_evaluation_references: (esm_evaluation_references), + esm_references: ResolvedVc::cell(esm_references), + esm_local_references: ResolvedVc::cell(esm_local_references), + esm_reexport_references: ResolvedVc::cell(esm_reexport_references), + esm_evaluation_references: ResolvedVc::cell(esm_evaluation_references), code_generation: ResolvedVc::cell(self.code_gens), exports: self.exports.resolved_cell(), async_module: self.async_module, diff --git a/turbopack/crates/turbopack-ecmascript/src/side_effect_optimization/facade/chunk_item.rs b/turbopack/crates/turbopack-ecmascript/src/side_effect_optimization/facade/chunk_item.rs index 668e184df6685..6ef30935fdddd 100644 --- a/turbopack/crates/turbopack-ecmascript/src/side_effect_optimization/facade/chunk_item.rs +++ b/turbopack/crates/turbopack-ecmascript/src/side_effect_optimization/facade/chunk_item.rs @@ -8,7 +8,7 @@ use swc_core::{ codegen::{text_writer::JsWriter, Emitter}, }, }; -use turbo_tasks::{ResolvedVc, TryJoinIterExt, Vc}; +use turbo_tasks::{ResolvedVc, Vc}; use turbo_tasks_fs::rope::RopeBuilder; use turbopack_core::{ chunk::{AsyncModuleInfo, ChunkItem, ChunkType, ChunkingContext}, @@ -23,7 +23,6 @@ use crate::{ EcmascriptChunkItem, EcmascriptChunkItemContent, EcmascriptChunkItemOptions, EcmascriptChunkPlaceable, EcmascriptChunkType, EcmascriptExports, }, - code_gen::CodeGenerateable, process_content_with_code_gens, }; @@ -67,21 +66,16 @@ impl EcmascriptChunkItem for EcmascriptModuleFacadeChunkItem { let mut code = RopeBuilder::default(); - let references = self.module.references(); - let references_ref = references.await?; - let mut code_gens_cells = Vec::with_capacity(references_ref.len() + 2); - for r in &references_ref { - if let Some(code_gen) = ResolvedVc::try_sidecast::>(*r) { - code_gens_cells - .push(code_gen.code_generation(*self.module_graph, *chunking_context)); - } - } + let esm_code_gens = self + .module + .code_generation(*self.module_graph, *chunking_context) + .await?; let additional_code_gens = [ self.module .async_module() .code_generation( async_module_info, - references, + self.module.references(), *self.module_graph, *chunking_context, ) @@ -90,11 +84,7 @@ impl EcmascriptChunkItem for EcmascriptModuleFacadeChunkItem { .code_generation(*self.module_graph, *chunking_context) .await?, ]; - let code_gen_cells = code_gens_cells.into_iter().try_join().await?; - let code_gens = code_gen_cells - .iter() - .map(|cg| &**cg) - .chain(additional_code_gens.iter()); + let code_gens = esm_code_gens.iter().chain(additional_code_gens.iter()); let mut program = Program::Module(swc_core::ecma::ast::Module::dummy()); process_content_with_code_gens(&mut program, &Globals::new(), None, code_gens); diff --git a/turbopack/crates/turbopack-ecmascript/src/side_effect_optimization/facade/module.rs b/turbopack/crates/turbopack-ecmascript/src/side_effect_optimization/facade/module.rs index 8bec6c6f944b0..f47700f118c4a 100644 --- a/turbopack/crates/turbopack-ecmascript/src/side_effect_optimization/facade/module.rs +++ b/turbopack/crates/turbopack-ecmascript/src/side_effect_optimization/facade/module.rs @@ -1,7 +1,7 @@ use std::collections::BTreeMap; use anyhow::{bail, Result}; -use turbo_tasks::{ResolvedVc, Vc}; +use turbo_tasks::{ResolvedVc, TryJoinIterExt, Vc}; use turbo_tasks_fs::{glob::Glob, File, FileContent}; use turbopack_core::{ asset::{Asset, AssetContent}, @@ -16,6 +16,7 @@ use turbopack_core::{ use super::chunk_item::EcmascriptModuleFacadeChunkItem; use crate::{ chunk::{EcmascriptChunkPlaceable, EcmascriptExports}, + code_gen::CodeGeneration, references::{ async_module::{AsyncModule, OptionAsyncModule}, esm::{EsmExport, EsmExports}, @@ -59,6 +60,89 @@ impl EcmascriptModuleFacadeModule { } } +impl EcmascriptModuleFacadeModule { + pub async fn code_generation( + self: Vc, + module_graph: Vc, + chunking_context: Vc>, + ) -> Result> { + let this = self.await?; + Ok(match &this.ty { + ModulePart::Evaluation => { + let Some(module) = + ResolvedVc::try_sidecast::>(this.module) + else { + bail!( + "Expected EcmascriptModuleAsset for a EcmascriptModuleFacadeModule with \ + ModulePart::Evaluation" + ); + }; + let result = module.analyze().await?; + let mut code_gens = result + .esm_evaluation_references + .await? + .iter() + .map(|r| r.code_generation(module_graph, chunking_context)) + .try_join() + .await?; + code_gens.push( + EcmascriptModulePartReference::new_part(*this.module, ModulePart::locals()) + .code_generation(module_graph, chunking_context) + .await?, + ); + code_gens + } + ModulePart::Exports => { + let Some(module) = + ResolvedVc::try_sidecast::>(this.module) + else { + bail!( + "Expected EcmascriptModuleAsset for a EcmascriptModuleFacadeModule with \ + ModulePart::Exports" + ); + }; + let result = module.analyze().await?; + let mut code_gens = result + .esm_reexport_references + .await? + .iter() + .map(|r| r.code_generation(module_graph, chunking_context)) + .try_join() + .await?; + code_gens.push( + EcmascriptModulePartReference::new_part(*this.module, ModulePart::locals()) + .code_generation(module_graph, chunking_context) + .await?, + ); + code_gens + } + ModulePart::Facade => { + vec![ + EcmascriptModulePartReference::new_part(*this.module, ModulePart::evaluation()) + .code_generation(module_graph, chunking_context) + .await?, + EcmascriptModulePartReference::new_part(*this.module, ModulePart::exports()) + .code_generation(module_graph, chunking_context) + .await?, + ] + } + ModulePart::RenamedNamespace { .. } => vec![ + EcmascriptModulePartReference::new(*this.module) + .code_generation(module_graph, chunking_context) + .await?, + ], + ModulePart::RenamedExport { .. } => vec![ + EcmascriptModulePartReference::new(*this.module) + .code_generation(module_graph, chunking_context) + .await?, + ], + _ => { + bail!("Unexpected ModulePart for EcmascriptModuleFacadeModule"); + } + }) + } +} + #[turbo_tasks::value_impl] impl Module for EcmascriptModuleFacadeModule { #[turbo_tasks::function] @@ -83,6 +167,7 @@ impl Module for EcmascriptModuleFacadeModule { let result = module.analyze().await?; result .esm_evaluation_references + .await? .iter() .map(|r| ResolvedVc::upcast(*r)) .chain(std::iter::once(ResolvedVc::upcast( @@ -104,6 +189,7 @@ impl Module for EcmascriptModuleFacadeModule { let result = module.analyze().await?; result .esm_reexport_references + .await? .iter() .map(|r| ResolvedVc::upcast(*r)) .chain(std::iter::once(ResolvedVc::upcast( diff --git a/turbopack/crates/turbopack-ecmascript/src/side_effect_optimization/locals/chunk_item.rs b/turbopack/crates/turbopack-ecmascript/src/side_effect_optimization/locals/chunk_item.rs index 6389fa0e45c58..8750f2f0c570e 100644 --- a/turbopack/crates/turbopack-ecmascript/src/side_effect_optimization/locals/chunk_item.rs +++ b/turbopack/crates/turbopack-ecmascript/src/side_effect_optimization/locals/chunk_item.rs @@ -59,7 +59,10 @@ impl EcmascriptChunkItem for EcmascriptModuleLocalsChunkItem { module_type_result.module_type, *module_graph, *chunking_context, - analyze.references(), + ( + analyze.local_references(), + *analyze_result.esm_local_references, + ), *analyze_result.code_generation, *analyze_result.async_module, generate_source_map, diff --git a/turbopack/crates/turbopack-ecmascript/src/side_effect_optimization/locals/module.rs b/turbopack/crates/turbopack-ecmascript/src/side_effect_optimization/locals/module.rs index 0498444e6d638..1d49adaaac974 100644 --- a/turbopack/crates/turbopack-ecmascript/src/side_effect_optimization/locals/module.rs +++ b/turbopack/crates/turbopack-ecmascript/src/side_effect_optimization/locals/module.rs @@ -51,7 +51,7 @@ impl Module for EcmascriptModuleLocalsModule { #[turbo_tasks::function] async fn references(&self) -> Result> { let result = self.module.analyze(); - Ok(result.references()) + Ok(result.local_references()) } #[turbo_tasks::function] diff --git a/turbopack/crates/turbopack-ecmascript/src/side_effect_optimization/reference.rs b/turbopack/crates/turbopack-ecmascript/src/side_effect_optimization/reference.rs index 1407883c4b4e0..9134ca08e8afb 100644 --- a/turbopack/crates/turbopack-ecmascript/src/side_effect_optimization/reference.rs +++ b/turbopack/crates/turbopack-ecmascript/src/side_effect_optimization/reference.rs @@ -17,10 +17,8 @@ use super::{ facade::module::EcmascriptModuleFacadeModule, locals::module::EcmascriptModuleLocalsModule, }; use crate::{ - chunk::EcmascriptChunkPlaceable, - code_gen::{CodeGenerateable, CodeGeneration}, - references::esm::base::ReferencedAsset, - runtime_functions::TURBOPACK_IMPORT, + chunk::EcmascriptChunkPlaceable, code_gen::CodeGeneration, + references::esm::base::ReferencedAsset, runtime_functions::TURBOPACK_IMPORT, utils::module_id_to_lit, }; @@ -111,14 +109,12 @@ impl ChunkableModuleReference for EcmascriptModulePartReference { } } -#[turbo_tasks::value_impl] -impl CodeGenerateable for EcmascriptModulePartReference { - #[turbo_tasks::function] - async fn code_generation( +impl EcmascriptModulePartReference { + pub async fn code_generation( self: Vc, module_graph: Vc, chunking_context: Vc>, - ) -> Result> { + ) -> Result { let referenced_asset = ReferencedAsset::from_resolve_result(self.resolve_reference()); let referenced_asset = referenced_asset.await?; let ident = referenced_asset @@ -142,7 +138,6 @@ impl CodeGenerateable for EcmascriptModulePartReference { turbopack_import: Expr = TURBOPACK_IMPORT.into(), id: Expr = module_id_to_lit(&id), ), - ) - .cell()) + )) } } diff --git a/turbopack/crates/turbopack-ecmascript/src/tree_shake/chunk_item.rs b/turbopack/crates/turbopack-ecmascript/src/tree_shake/chunk_item.rs index bbb707941f9af..da9bbeaf89eea 100644 --- a/turbopack/crates/turbopack-ecmascript/src/tree_shake/chunk_item.rs +++ b/turbopack/crates/turbopack-ecmascript/src/tree_shake/chunk_item.rs @@ -66,7 +66,7 @@ impl EcmascriptChunkItem for EcmascriptModulePartChunkItem { module_type_result.module_type, *self.module_graph, *self.chunking_context, - analyze.references(), + (analyze.references(), *analyze_ref.esm_references), *analyze_ref.code_generation, *analyze_ref.async_module, generate_source_map, From 18212c3d72e5d6a73229d7a6c383d480a57a9d7d Mon Sep 17 00:00:00 2001 From: Niklas Mischkulnig <4586894+mischnic@users.noreply.github.com> Date: Fri, 14 Feb 2025 10:37:57 +0100 Subject: [PATCH 3/6] wip --- .../src/references/mod.rs | 111 +++++++++++------- 1 file changed, 69 insertions(+), 42 deletions(-) diff --git a/turbopack/crates/turbopack-ecmascript/src/references/mod.rs b/turbopack/crates/turbopack-ecmascript/src/references/mod.rs index dfdaa2e79286f..1c648b42694c7 100644 --- a/turbopack/crates/turbopack-ecmascript/src/references/mod.rs +++ b/turbopack/crates/turbopack-ecmascript/src/references/mod.rs @@ -298,42 +298,58 @@ impl AnalyzeEcmascriptModuleResultBuilder { pub async fn build( mut self, import_references: Vec>, + import_references_namespace_rewritten: FxHashMap< + usize, + FxIndexMap>, + >, track_reexport_references: bool, ) -> Result> { - let mut esm_references: Vec<_> = self.esm_references.into_iter().collect(); - esm_references.sort(); - let esm_references = esm_references - .into_iter() - .map(|i| import_references[i]) - .collect(); - let (esm_local_references, esm_reexport_references, esm_evaluation_references) = - if track_reexport_references { - let mut esm_local_references: Vec<_> = - self.esm_local_references.into_iter().collect(); - let mut esm_reexport_references: Vec<_> = - self.esm_reexport_references.into_iter().collect(); - let mut esm_evaluation_references: Vec<_> = - self.esm_evaluation_references.into_iter().collect(); - esm_local_references.sort(); - esm_reexport_references.sort(); - esm_evaluation_references.sort(); - ( - esm_local_references - .into_iter() - .map(|i| import_references[i]) - .collect(), - esm_reexport_references - .into_iter() - .map(|i| import_references[i]) - .collect(), - esm_evaluation_references - .into_iter() - .map(|i| import_references[i]) - .collect(), - ) - } else { - (vec![], vec![], vec![]) - }; + // import_references_namespace_rewritten needs to be spliced in at the correct index into + // esm_references and esm_local_references + let mut esm_references = Vec::with_capacity( + self.esm_references.len() + import_references_namespace_rewritten.len(), + ); + let mut esm_local_references = track_reexport_references.then(|| { + Vec::with_capacity( + self.esm_local_references.len() + import_references_namespace_rewritten.len(), + ) + }); + let mut esm_reexport_references = track_reexport_references + .then(|| Vec::with_capacity(self.esm_reexport_references.len())); + let mut esm_evaluation_references = track_reexport_references + .then(|| Vec::with_capacity(self.esm_evaluation_references.len())); + for (i, reference) in import_references.iter().enumerate() { + if self.esm_references.contains(&i) { + esm_references.push(*reference); + } + esm_references.extend( + import_references_namespace_rewritten + .get(&i) + .iter() + .flat_map(|m| m.values().copied()), + ); + if let Some(esm_local_references) = &mut esm_local_references { + if self.esm_local_references.contains(&i) { + esm_local_references.push(*reference); + } + esm_local_references.extend( + import_references_namespace_rewritten + .get(&i) + .iter() + .flat_map(|m| m.values().copied()), + ); + } + if let Some(esm_evaluation_references) = &mut esm_evaluation_references { + if self.esm_evaluation_references.contains(&i) { + esm_evaluation_references.push(*reference); + } + } + if let Some(esm_reexport_references) = &mut esm_reexport_references { + if self.esm_reexport_references.contains(&i) { + esm_reexport_references.push(*reference); + } + } + } let references: Vec<_> = self.references.into_iter().collect(); @@ -346,11 +362,15 @@ impl AnalyzeEcmascriptModuleResultBuilder { self.code_gens.shrink_to_fit(); Ok(AnalyzeEcmascriptModuleResult::cell( AnalyzeEcmascriptModuleResult { - references: (references), + references, esm_references: ResolvedVc::cell(esm_references), - esm_local_references: ResolvedVc::cell(esm_local_references), - esm_reexport_references: ResolvedVc::cell(esm_reexport_references), - esm_evaluation_references: ResolvedVc::cell(esm_evaluation_references), + esm_local_references: ResolvedVc::cell(esm_local_references.unwrap_or_default()), + esm_reexport_references: ResolvedVc::cell( + esm_reexport_references.unwrap_or_default(), + ), + esm_evaluation_references: ResolvedVc::cell( + esm_evaluation_references.unwrap_or_default(), + ), code_generation: ResolvedVc::cell(self.code_gens), exports: self.exports.resolved_cell(), async_module: self.async_module, @@ -526,7 +546,9 @@ pub(crate) async fn analyse_ecmascript_module_internal( .. } = &*parsed else { - return analysis.build(vec![], false).await; + return analysis + .build(Default::default(), Default::default(), false) + .await; }; let compile_time_info = compile_time_info_for_module_type( @@ -644,7 +666,8 @@ pub(crate) async fn analyse_ecmascript_module_internal( // Ad-hoc created import references that are resolved `import * as x from ...; x.foo` accesses // This caches repeated access because EsmAssetReference::new is not a turbo task function. - let mut import_references_namespace_rewritten = FxIndexMap::default(); + let mut import_references_namespace_rewritten: FxHashMap> = + FxHashMap::default(); let span = tracing::info_span!("esm import references"); let import_references = async { @@ -1284,7 +1307,9 @@ pub(crate) async fn analyse_ecmascript_module_internal( if r_ref.export_name.is_none() && export.is_some() { if let Some(export) = export { let r = *import_references_namespace_rewritten - .entry((esm_reference_index, export.clone())) + .entry(esm_reference_index) + .or_default() + .entry(export.clone()) .or_insert_with(|| { EsmAssetReference::new( r_ref.origin, @@ -1296,7 +1321,8 @@ pub(crate) async fn analyse_ecmascript_module_internal( ) .resolved_cell() }); - analysis.add_reference(r); + // No need to add a reference, + // import_references_namespace_rewritten are all added later on analysis.add_code_gen(EsmBinding::new( r, Some(export), @@ -1349,6 +1375,7 @@ pub(crate) async fn analyse_ecmascript_module_internal( analysis .build( import_references, + import_references_namespace_rewritten, matches!( options.tree_shaking_mode, Some(TreeShakingMode::ReexportsOnly) From 6e8910f2c3c7c70830bec1a2d42eacb9680ef1ad Mon Sep 17 00:00:00 2001 From: Niklas Mischkulnig <4586894+mischnic@users.noreply.github.com> Date: Fri, 14 Feb 2025 11:22:03 +0100 Subject: [PATCH 4/6] Fix FreeVarReference::EcmaScriptModule --- .../src/references/mod.rs | 141 +++++++++++------- 1 file changed, 89 insertions(+), 52 deletions(-) diff --git a/turbopack/crates/turbopack-ecmascript/src/references/mod.rs b/turbopack/crates/turbopack-ecmascript/src/references/mod.rs index 1c648b42694c7..7b472ffac90a7 100644 --- a/turbopack/crates/turbopack-ecmascript/src/references/mod.rs +++ b/turbopack/crates/turbopack-ecmascript/src/references/mod.rs @@ -23,6 +23,7 @@ use std::{borrow::Cow, collections::BTreeMap, future::Future, mem::take, ops::De use anyhow::{bail, Result}; use constant_condition::{ConstantConditionCodeGen, ConstantConditionValue}; use constant_value::ConstantValueCodeGen; +use indexmap::map::Entry; use lazy_static::lazy_static; use num_traits::Zero; use once_cell::sync::Lazy; @@ -210,6 +211,11 @@ pub struct AnalyzeEcmascriptModuleResultBuilder { esm_reexport_references: FxHashSet, esm_evaluation_references: FxHashSet, + esm_references_free_var: FxIndexMap>, + // Ad-hoc created import references that are resolved `import * as x from ...; x.foo` accesses + // This caches repeated access because EsmAssetReference::new is not a turbo task function. + esm_references_rewritten: FxHashMap>>, + code_gens: Vec, exports: EcmascriptExports, async_module: ResolvedVc, @@ -225,6 +231,8 @@ impl AnalyzeEcmascriptModuleResultBuilder { esm_local_references: Default::default(), esm_reexport_references: Default::default(), esm_evaluation_references: Default::default(), + esm_references_rewritten: Default::default(), + esm_references_free_var: Default::default(), code_gens: Default::default(), exports: EcmascriptExports::None, async_module: ResolvedVc::cell(None), @@ -294,25 +302,54 @@ impl AnalyzeEcmascriptModuleResultBuilder { self.successful = successful; } + pub fn add_esm_reference_namespace_resolved( + &mut self, + esm_reference_idx: usize, + export: RcStr, + on_insert: impl FnOnce() -> ResolvedVc, + ) -> ResolvedVc { + *self + .esm_references_rewritten + .entry(esm_reference_idx) + .or_default() + .entry(export) + .or_insert_with(on_insert) + } + + pub async fn add_esm_reference_free_var( + &mut self, + request: RcStr, + on_insert: impl AsyncFnOnce() -> Result>, + ) -> Result> { + Ok(match self.esm_references_free_var.entry(request) { + Entry::Occupied(e) => *e.get(), + Entry::Vacant(e) => *e.insert(on_insert().await?), + }) + } + /// Builds the final analysis result. Resolves internal Vcs. pub async fn build( mut self, import_references: Vec>, - import_references_namespace_rewritten: FxHashMap< - usize, - FxIndexMap>, - >, track_reexport_references: bool, ) -> Result> { - // import_references_namespace_rewritten needs to be spliced in at the correct index into - // esm_references and esm_local_references + // esm_references_rewritten (and esm_references_free_var) needs to be spliced in at the + // correct index into esm_references and esm_local_references let mut esm_references = Vec::with_capacity( - self.esm_references.len() + import_references_namespace_rewritten.len(), + self.esm_references.len() + + self.esm_references_free_var.len() + + self.esm_references_rewritten.len(), ); + esm_references.extend(self.esm_references_free_var.values()); + let mut esm_local_references = track_reexport_references.then(|| { - Vec::with_capacity( - self.esm_local_references.len() + import_references_namespace_rewritten.len(), - ) + let mut esm_local_references = Vec::with_capacity( + self.esm_local_references.len() + + self.esm_references_free_var.len() + + self.esm_references_rewritten.len(), + ); + esm_local_references.extend(self.esm_references_free_var.values()); + esm_local_references }); let mut esm_reexport_references = track_reexport_references .then(|| Vec::with_capacity(self.esm_reexport_references.len())); @@ -323,7 +360,7 @@ impl AnalyzeEcmascriptModuleResultBuilder { esm_references.push(*reference); } esm_references.extend( - import_references_namespace_rewritten + self.esm_references_rewritten .get(&i) .iter() .flat_map(|m| m.values().copied()), @@ -333,7 +370,7 @@ impl AnalyzeEcmascriptModuleResultBuilder { esm_local_references.push(*reference); } esm_local_references.extend( - import_references_namespace_rewritten + self.esm_references_rewritten .get(&i) .iter() .flat_map(|m| m.values().copied()), @@ -546,9 +583,7 @@ pub(crate) async fn analyse_ecmascript_module_internal( .. } = &*parsed else { - return analysis - .build(Default::default(), Default::default(), false) - .await; + return analysis.build(Default::default(), false).await; }; let compile_time_info = compile_time_info_for_module_type( @@ -664,11 +699,6 @@ pub(crate) async fn analyse_ecmascript_module_internal( set_handler_and_globals(&handler, globals, || create_graph(program, eval_context)) }; - // Ad-hoc created import references that are resolved `import * as x from ...; x.foo` accesses - // This caches repeated access because EsmAssetReference::new is not a turbo task function. - let mut import_references_namespace_rewritten: FxHashMap> = - FxHashMap::default(); - let span = tracing::info_span!("esm import references"); let import_references = async { let mut import_references = Vec::with_capacity(eval_context.imports.references().len()); @@ -1306,11 +1336,10 @@ pub(crate) async fn analyse_ecmascript_module_internal( let r_ref = r.await?; if r_ref.export_name.is_none() && export.is_some() { if let Some(export) = export { - let r = *import_references_namespace_rewritten - .entry(esm_reference_index) - .or_default() - .entry(export.clone()) - .or_insert_with(|| { + let r = analysis.add_esm_reference_namespace_resolved( + esm_reference_index, + export.clone(), + || { EsmAssetReference::new( r_ref.origin, r_ref.request, @@ -1320,9 +1349,8 @@ pub(crate) async fn analyse_ecmascript_module_internal( r_ref.import_externals, ) .resolved_cell() - }); - // No need to add a reference, - // import_references_namespace_rewritten are all added later on + }, + ); analysis.add_code_gen(EsmBinding::new( r, Some(export), @@ -1375,7 +1403,6 @@ pub(crate) async fn analyse_ecmascript_module_internal( analysis .build( import_references, - import_references_namespace_rewritten, matches!( options.tree_shaking_mode, Some(TreeShakingMode::ReexportsOnly) @@ -2477,33 +2504,43 @@ async fn handle_free_var_reference( lookup_path, export, } => { - let esm_reference = EsmAssetReference::new( - if let Some(lookup_path) = lookup_path { - ResolvedVc::upcast( - PlainResolveOrigin::new(state.origin.asset_context(), **lookup_path) + let esm_reference = analysis + .add_esm_reference_free_var(request.clone(), async || { + Ok(EsmAssetReference::new( + if let Some(lookup_path) = lookup_path { + ResolvedVc::upcast( + PlainResolveOrigin::new( + state.origin.asset_context(), + **lookup_path, + ) + .to_resolved() + .await?, + ) + } else { + state.origin + }, + Request::parse(Value::new(request.clone().into())) .to_resolved() .await?, + IssueSource::from_swc_offsets( + state.source, + span.lo.to_u32(), + span.hi.to_u32(), + ), + Default::default(), + match state.tree_shaking_mode { + Some(TreeShakingMode::ModuleFragments) + | Some(TreeShakingMode::ReexportsOnly) => { + export.clone().map(ModulePart::export) + } + None => None, + }, + state.import_externals, ) - } else { - state.origin - }, - Request::parse(Value::new(request.clone().into())) - .to_resolved() - .await?, - IssueSource::from_swc_offsets(state.source, span.lo.to_u32(), span.hi.to_u32()), - Default::default(), - match state.tree_shaking_mode { - Some(TreeShakingMode::ModuleFragments) - | Some(TreeShakingMode::ReexportsOnly) => { - export.clone().map(ModulePart::export) - } - None => None, - }, - state.import_externals, - ) - .resolved_cell(); + .resolved_cell()) + }) + .await?; - analysis.add_reference(esm_reference); analysis.add_code_gen(EsmBinding::new( esm_reference, export.clone(), From ded4128615b7da6362672ce248dda9518bb2215e Mon Sep 17 00:00:00 2001 From: Niklas Mischkulnig <4586894+mischnic@users.noreply.github.com> Date: Fri, 14 Feb 2025 13:55:46 +0100 Subject: [PATCH 5/6] cleanup --- .../turbopack-ecmascript/src/code_gen.rs | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/turbopack/crates/turbopack-ecmascript/src/code_gen.rs b/turbopack/crates/turbopack-ecmascript/src/code_gen.rs index 60ff5eb0aaced..02792c2f620a1 100644 --- a/turbopack/crates/turbopack-ecmascript/src/code_gen.rs +++ b/turbopack/crates/turbopack-ecmascript/src/code_gen.rs @@ -31,19 +31,9 @@ use crate::references::{ AstPath, }; -/// impl of code generation inferred from a ModuleReference. -/// This is rust only and can't be implemented by non-rust plugins. -#[turbo_tasks::value( - shared, - serialization = "none", - eq = "manual", - into = "new", - cell = "new" -)] #[derive(Default)] pub struct CodeGeneration { /// ast nodes matching the span will be visitor by the visitor - #[turbo_tasks(debug_ignore, trace_ignore)] pub visitors: Vec<(Vec, Box)>, pub hoisted_stmts: Vec, pub early_hoisted_stmts: Vec, @@ -90,11 +80,9 @@ impl CodeGeneration { } } -#[turbo_tasks::value(shared)] #[derive(Clone)] pub struct CodeGenerationHoistedStmt { pub key: RcStr, - #[turbo_tasks(trace_ignore)] pub stmt: Stmt, } @@ -108,15 +96,6 @@ pub trait VisitorFactory: Send + Sync { fn create<'a>(&'a self) -> Box; } -#[turbo_tasks::value_trait] -pub trait CodeGenerateable { - fn code_generation( - self: Vc, - module_graph: Vc, - chunking_context: Vc>, - ) -> Vc; -} - #[derive(PartialEq, Eq, Serialize, Deserialize, TraceRawVcs, ValueDebugFormat, NonLocalValue)] pub enum CodeGen { // AMD occurs very rarely and makes the enum much bigger From 5b6a0f4ba2b7a916618df75aeeb57628a5d14aa8 Mon Sep 17 00:00:00 2001 From: Niklas Mischkulnig <4586894+mischnic@users.noreply.github.com> Date: Mon, 17 Feb 2025 09:15:21 +0100 Subject: [PATCH 6/6] refactor into EcmascriptModuleContentOptions --- .../crates/turbopack-ecmascript/src/lib.rs | 79 ++++++++++++------- .../locals/chunk_item.rs | 28 +++---- .../src/tree_shake/chunk_item.rs | 29 ++++--- 3 files changed, 80 insertions(+), 56 deletions(-) diff --git a/turbopack/crates/turbopack-ecmascript/src/lib.rs b/turbopack/crates/turbopack-ecmascript/src/lib.rs index cd0f0ba084d13..2a03e9f22785c 100644 --- a/turbopack/crates/turbopack-ecmascript/src/lib.rs +++ b/turbopack/crates/turbopack-ecmascript/src/lib.rs @@ -426,18 +426,21 @@ impl EcmascriptAnalyzable for EcmascriptModuleAsset { let generate_source_map = chunking_context.reference_module_source_maps(Vc::upcast(self)); Ok(EcmascriptModuleContent::new( - *parsed, - self.ident(), - module_type_result.module_type, - module_graph, - chunking_context, - (analyze.references(), *analyze_ref.esm_references), - *analyze_ref.code_generation, - *analyze_ref.async_module, - generate_source_map, - *analyze_ref.source_map, - *analyze_ref.exports, - async_module_info, + EcmascriptModuleContentOptions { + parsed, + ident: self.ident(), + specified_module_type: module_type_result.module_type, + module_graph, + chunking_context, + references: analyze.references(), + esm_references: *analyze_ref.esm_references, + code_generation: *analyze_ref.code_generation, + async_module: *analyze_ref.async_module, + generate_source_map, + original_source_map: analyze_ref.source_map, + exports: *analyze_ref.exports, + async_module_info, + }, )) } } @@ -757,24 +760,44 @@ pub struct EcmascriptModuleContent { // pub refresh: bool, } +#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, TaskInput)] +pub struct EcmascriptModuleContentOptions { + parsed: ResolvedVc, + ident: Vc, + specified_module_type: SpecifiedModuleType, + module_graph: Vc, + chunking_context: Vc>, + references: Vc, + esm_references: Vc, + code_generation: Vc, + async_module: Vc, + generate_source_map: Vc, + original_source_map: ResolvedVc, + exports: Vc, + async_module_info: Option>, +} + #[turbo_tasks::value_impl] impl EcmascriptModuleContent { /// Creates a new [`Vc`]. #[turbo_tasks::function] - pub async fn new( - parsed: ResolvedVc, - ident: ResolvedVc, - specified_module_type: SpecifiedModuleType, - module_graph: Vc, - chunking_context: Vc>, - (references, esm_references): (Vc, Vc), - code_generation: Vc, - async_module: Vc, - generate_source_map: Vc, - original_source_map: ResolvedVc, - exports: Vc, - async_module_info: Option>, - ) -> Result> { + pub async fn new(input: EcmascriptModuleContentOptions) -> Result> { + let EcmascriptModuleContentOptions { + parsed, + ident, + specified_module_type, + module_graph, + chunking_context, + references, + esm_references, + code_generation, + async_module, + generate_source_map, + original_source_map, + exports, + async_module_info, + } = input; + let additional_code_gens = [ if let Some(async_module) = &*async_module.await? { Some( @@ -839,7 +862,7 @@ impl EcmascriptModuleContent { ) -> Result> { gen_content_with_code_gens( parsed.to_resolved().await?, - ident.to_resolved().await?, + ident, specified_module_type, &[], generate_source_map, @@ -851,7 +874,7 @@ impl EcmascriptModuleContent { async fn gen_content_with_code_gens( parsed: ResolvedVc, - ident: ResolvedVc, + ident: Vc, specified_module_type: SpecifiedModuleType, code_gens: impl IntoIterator, generate_source_map: Vc, diff --git a/turbopack/crates/turbopack-ecmascript/src/side_effect_optimization/locals/chunk_item.rs b/turbopack/crates/turbopack-ecmascript/src/side_effect_optimization/locals/chunk_item.rs index 8750f2f0c570e..9c4e87091b707 100644 --- a/turbopack/crates/turbopack-ecmascript/src/side_effect_optimization/locals/chunk_item.rs +++ b/turbopack/crates/turbopack-ecmascript/src/side_effect_optimization/locals/chunk_item.rs @@ -13,7 +13,7 @@ use crate::{ EcmascriptChunkItem, EcmascriptChunkItemContent, EcmascriptChunkPlaceable, EcmascriptChunkType, }, - EcmascriptModuleContent, + EcmascriptModuleContent, EcmascriptModuleContentOptions, }; /// The chunk item for [EcmascriptModuleLocalsModule]. @@ -41,7 +41,7 @@ impl EcmascriptChunkItem for EcmascriptModuleLocalsChunkItem { let module_graph = self.module_graph; let exports = self.module.get_exports(); let original_module = module.module; - let parsed = original_module.parse().resolve().await?; + let parsed = original_module.parse().to_resolved().await?; let analyze = original_module.analyze(); let analyze_result = analyze.await?; @@ -53,23 +53,21 @@ impl EcmascriptChunkItem for EcmascriptModuleLocalsChunkItem { let generate_source_map = chunking_context.reference_module_source_maps(*ResolvedVc::upcast(self.module)); - let content = EcmascriptModuleContent::new( + let content = EcmascriptModuleContent::new(EcmascriptModuleContentOptions { parsed, - self.module.ident(), - module_type_result.module_type, - *module_graph, - *chunking_context, - ( - analyze.local_references(), - *analyze_result.esm_local_references, - ), - *analyze_result.code_generation, - *analyze_result.async_module, + ident: self.module.ident(), + specified_module_type: module_type_result.module_type, + module_graph: *module_graph, + chunking_context: *chunking_context, + references: analyze.local_references(), + esm_references: *analyze_result.esm_local_references, + code_generation: *analyze_result.code_generation, + async_module: *analyze_result.async_module, generate_source_map, - *analyze_result.source_map, + original_source_map: analyze_result.source_map, exports, async_module_info, - ); + }); Ok(EcmascriptChunkItemContent::new( content, diff --git a/turbopack/crates/turbopack-ecmascript/src/tree_shake/chunk_item.rs b/turbopack/crates/turbopack-ecmascript/src/tree_shake/chunk_item.rs index da9bbeaf89eea..bd6314fffdcb0 100644 --- a/turbopack/crates/turbopack-ecmascript/src/tree_shake/chunk_item.rs +++ b/turbopack/crates/turbopack-ecmascript/src/tree_shake/chunk_item.rs @@ -20,7 +20,7 @@ use crate::{ runtime_functions::{TURBOPACK_EXPORT_NAMESPACE, TURBOPACK_IMPORT}, tree_shake::side_effect_module::SideEffectsModule, utils::StringifyModuleId, - EcmascriptModuleContent, + EcmascriptModuleContent, EcmascriptModuleContentOptions, }; /// This is an implementation of [ChunkItem] for @@ -49,7 +49,9 @@ impl EcmascriptChunkItem for EcmascriptModulePartChunkItem { let module = self.module.await?; let split_data = split_module(*module.full_module); - let parsed = part_of_module(split_data, module.part.clone()); + let parsed = part_of_module(split_data, module.part.clone()) + .to_resolved() + .await?; let analyze = self.module.analyze(); let analyze_ref = analyze.await?; @@ -60,20 +62,21 @@ impl EcmascriptChunkItem for EcmascriptModulePartChunkItem { .chunking_context .reference_module_source_maps(*ResolvedVc::upcast(self.module)); - let content = EcmascriptModuleContent::new( + let content = EcmascriptModuleContent::new(EcmascriptModuleContentOptions { parsed, - self.module.ident(), - module_type_result.module_type, - *self.module_graph, - *self.chunking_context, - (analyze.references(), *analyze_ref.esm_references), - *analyze_ref.code_generation, - *analyze_ref.async_module, + ident: self.module.ident(), + specified_module_type: module_type_result.module_type, + module_graph: *self.module_graph, + chunking_context: *self.chunking_context, + references: analyze.references(), + esm_references: *analyze_ref.esm_references, + code_generation: *analyze_ref.code_generation, + async_module: *analyze_ref.async_module, generate_source_map, - *analyze_ref.source_map, - *analyze_ref.exports, + original_source_map: analyze_ref.source_map, + exports: *analyze_ref.exports, async_module_info, - ); + }); Ok(EcmascriptChunkItemContent::new( content,