diff --git a/crates/next-api/src/dynamic_imports.rs b/crates/next-api/src/dynamic_imports.rs index 72c1d3d8bdaae..44292abc24f91 100644 --- a/crates/next-api/src/dynamic_imports.rs +++ b/crates/next-api/src/dynamic_imports.rs @@ -266,7 +266,7 @@ async fn build_dynamic_imports_map_for_module( // https://github.com/vercel/next.js/pull/56389#discussion_r1349336374 // don't emit specific error as we expect there's a parse error already reported - let ParseResult::Ok { program, .. } = &*ecmascript_asset.failsafe_parse().await? else { + let ParseResult::Ok { program, .. } = &*ecmascript_asset.failsafe_parse(None).await? else { return Ok(Vc::cell(None)); }; diff --git a/crates/next-core/src/util.rs b/crates/next-core/src/util.rs index cf621ac85f8ac..fc37df6303200 100644 --- a/crates/next-core/src/util.rs +++ b/crates/next-core/src/util.rs @@ -378,7 +378,7 @@ pub async fn parse_config_from_source(module: Vc>) -> Result) -> Result>; + /// This function accpets `part` because we need to apply some transforms after splitting the + /// module. + /// + /// If we don't accept `part`, we would need a way to ensure that all callers of + /// `failsafe_parse` applies the same transforms. + fn failsafe_parse(self: Vc, part: Option>) -> Result>; fn parse_original(self: Vc) -> Result>; @@ -342,8 +362,11 @@ impl ModuleTypeResult { #[turbo_tasks::value_impl] impl EcmascriptParsable for EcmascriptModuleAsset { #[turbo_tasks::function] - async fn failsafe_parse(self: Vc) -> Result> { - let real_result = self.parse(); + async fn failsafe_parse( + self: Vc, + part: Option>, + ) -> Result> { + let real_result = self.parse(part); let real_result_value = real_result.await?; let this = self.await?; let result_value = if matches!(*real_result_value, ParseResult::Ok { .. }) { @@ -359,7 +382,7 @@ impl EcmascriptParsable for EcmascriptModuleAsset { #[turbo_tasks::function] async fn parse_original(self: Vc) -> Result> { - Ok(self.failsafe_parse()) + Ok(self.failsafe_parse(None)) } #[turbo_tasks::function] @@ -383,7 +406,7 @@ impl EcmascriptAnalyzable for EcmascriptModuleAsset { ) -> Result> { let this = self.await?; - let parsed = self.parse(); + let parsed = self.parse(None); Ok(EcmascriptModuleContent::new_without_analysis( parsed, @@ -398,7 +421,7 @@ impl EcmascriptAnalyzable for EcmascriptModuleAsset { chunking_context: Vc>, async_module_info: Option>, ) -> Result> { - let parsed = self.parse().resolve().await?; + let parsed = self.parse(None).resolve().await?; let analyze = self.analyze().await?; @@ -479,8 +502,17 @@ impl EcmascriptModuleAsset { } #[turbo_tasks::function] - pub fn parse(&self) -> Vc { - parse(self.source, Value::new(self.ty), self.transforms) + pub fn parse(&self, part: Option>) -> Vc { + let parsed = parse(self.source, Value::new(self.ty), self.transforms); + + let parsed = if let Some(part) = part { + let split_data = split(self.source.ident(), self.source, parsed); + part_of_module(split_data, part) + } else { + parsed + }; + + apply_transforms(self.source, parsed, self.transforms_after_split) } #[turbo_tasks::function] @@ -922,6 +954,99 @@ async fn gen_content_with_visitors( } } +#[turbo_tasks::function] +async fn apply_transforms( + source: Vc>, + parsed: Vc, + transforms: Vc, +) -> Result> { + let transforms = &*transforms.await?; + + let ParseResult::Ok { + program, + comments, + eval_context, + globals, + source_map, + top_level_mark, + } = &*parsed.await? + else { + return Ok(parsed); + }; + + let merged_comments = SwcComments::default(); + for c in comments.leading.iter() { + merged_comments.leading.insert(*c.0, c.1.clone()); + } + for c in comments.trailing.iter() { + merged_comments.trailing.insert(*c.0, c.1.clone()); + } + + let handler = Handler::with_emitter( + true, + false, + Box::new(IssueEmitter::new( + source, + source_map.clone(), + Some("Ecmascript file had an error".into()), + )), + ); + + // TODO: Optimize this + let fs_path_vc = source.ident().path(); + let fs_path = &*fs_path_vc.await?; + let file_path_hash = hash_xxh3_hash64(&*source.ident().to_string().await?) as u128; + + WrapFuture::new( + async { + let mut program = program.clone(); + + let transform_context = TransformContext { + comments: &merged_comments, + source_map, + top_level_mark: *top_level_mark, + unresolved_mark: eval_context.unresolved_mark, + file_path_str: &fs_path.path, + file_name_str: fs_path.file_name(), + file_name_hash: file_path_hash, + file_path: fs_path_vc, + }; + + let span = tracing::trace_span!("transforms"); + for transform in transforms.iter() { + transform.apply(&mut program, &transform_context).await?; + } + drop(span); + + let comments = Arc::new(ImmutableComments::new(merged_comments)); + + let eval_context = EvalContext::new( + &program, + eval_context.unresolved_mark, + *top_level_mark, + Some(&comments), + None, + ); + + Ok(ParseResult::Ok { + program, + comments: comments.clone(), + eval_context, + globals: globals.clone(), + source_map: source_map.clone(), + top_level_mark: *top_level_mark, + } + .cell()) + }, + |f, cx| { + GLOBALS.set(globals, || { + HANDLER.set(&handler, || HELPERS.set(&Helpers::new(true), || f.poll(cx))) + }) + }, + ) + .await +} + pub fn register() { turbo_tasks::register(); turbo_tasks_fs::register(); diff --git a/turbopack/crates/turbopack-ecmascript/src/references/mod.rs b/turbopack/crates/turbopack-ecmascript/src/references/mod.rs index dcea989c23a27..73d16e051fbd0 100644 --- a/turbopack/crates/turbopack-ecmascript/src/references/mod.rs +++ b/turbopack/crates/turbopack-ecmascript/src/references/mod.rs @@ -36,7 +36,6 @@ use regex::Regex; use sourcemap::decode_data_url; use swc_core::{ atoms::JsWord, - base::SwcComments, common::{ comments::{CommentKind, Comments}, errors::{DiagnosticId, Handler, HANDLER}, @@ -46,7 +45,6 @@ use swc_core::{ }, ecma::{ ast::*, - transforms::base::helpers::{Helpers, HELPERS}, visit::{ fields::{AssignExprField, AssignTargetField, SimpleAssignTargetField}, AstParentKind, AstParentNodeRef, VisitAstPath, VisitWithAstPath, @@ -54,9 +52,8 @@ use swc_core::{ }, }; use tracing::Instrument; -use turbo_tasks::{util::WrapFuture, RcStr, TryJoinIterExt, Upcast, Value, ValueToString, Vc}; +use turbo_tasks::{RcStr, TryJoinIterExt, Upcast, Value, ValueToString, Vc}; use turbo_tasks_fs::FileSystemPath; -use turbo_tasks_hash::hash_xxh3_hash64; use turbopack_core::{ compile_time_info::{ CompileTimeInfo, DefineableNameSegment, FreeVarReference, FreeVarReferences, @@ -128,7 +125,7 @@ use crate::{ }, chunk::EcmascriptExports, code_gen::{CodeGen, CodeGenerateable, CodeGenerateableWithAsyncModuleInfo, CodeGenerateables}, - magic_identifier, parse, + magic_identifier, references::{ async_module::{AsyncModule, OptionAsyncModule}, cjs::{CjsRequireAssetReference, CjsRequireCacheAccess, CjsRequireResolveAssetReference}, @@ -138,11 +135,10 @@ use crate::{ require_context::{RequireContextAssetReference, RequireContextMap}, type_issue::SpecifiedModuleTypeIssue, }, - swc_comments::ImmutableComments, - tree_shake::{find_turbopack_part_id_in_asserts, part_of_module, split}, + tree_shake::find_turbopack_part_id_in_asserts, utils::{module_value_to_well_known_object, AstPathRange}, EcmascriptInputTransforms, EcmascriptModuleAsset, EcmascriptParsable, SpecifiedModuleType, - TransformContext, TreeShakingMode, + TreeShakingMode, }; #[derive(Clone)] @@ -436,7 +432,6 @@ pub(crate) async fn analyse_ecmascript_module_internal( let source = raw_module.source; let ty = Value::new(raw_module.ty); let transforms = raw_module.transforms; - let transforms_after_split = raw_module.transforms_after_split; let options = raw_module.options; let options = options.await?; let import_externals = options.import_externals; @@ -453,15 +448,7 @@ pub(crate) async fn analyse_ecmascript_module_internal( EcmascriptModuleAssetType::Ecmascript => false, }; - let parsed = if let Some(part) = part { - let parsed = parse(source, ty, transforms); - let split_data = split(source.ident(), source, parsed); - part_of_module(split_data, part) - } else { - module.failsafe_parse() - }; - - let parsed = apply_transforms(source, parsed, transforms_after_split); + let parsed = module.failsafe_parse(part); let ModuleTypeResult { module_type: specified_type, @@ -1261,98 +1248,6 @@ pub(crate) async fn analyse_ecmascript_module_internal( .await } -#[turbo_tasks::function] -async fn apply_transforms( - source: Vc>, - parsed: Vc, - transforms: Vc, -) -> Result> { - let transforms = &*transforms.await?; - - let ParseResult::Ok { - program, - comments, - eval_context, - globals, - source_map, - top_level_mark, - } = &*parsed.await? - else { - return Ok(parsed); - }; - - let merged_comments = SwcComments::default(); - for c in comments.leading.iter() { - merged_comments.leading.insert(*c.0, c.1.clone()); - } - for c in comments.trailing.iter() { - merged_comments.trailing.insert(*c.0, c.1.clone()); - } - - let handler = Handler::with_emitter( - true, - false, - Box::new(IssueEmitter::new( - source, - source_map.clone(), - Some("Ecmascript file had an error".into()), - )), - ); - - // TODO: Optimize this - let fs_path_vc = source.ident().path(); - let fs_path = &*fs_path_vc.await?; - let file_path_hash = hash_xxh3_hash64(&*source.ident().to_string().await?) as u128; - - WrapFuture::new( - async { - let mut program = program.clone(); - - let transform_context = TransformContext { - comments: &merged_comments, - source_map, - top_level_mark: *top_level_mark, - unresolved_mark: eval_context.unresolved_mark, - file_path_str: &fs_path.path, - file_name_str: fs_path.file_name(), - file_name_hash: file_path_hash, - file_path: fs_path_vc, - }; - - let span = tracing::trace_span!("transforms"); - for transform in transforms.iter() { - transform.apply(&mut program, &transform_context).await?; - } - drop(span); - - let comments = Arc::new(ImmutableComments::new(merged_comments)); - - let eval_context = EvalContext::new( - &program, - eval_context.unresolved_mark, - *top_level_mark, - None, - ); - - Ok(ParseResult::Ok { - program, - comments: comments.clone(), - eval_context, - globals: globals.clone(), - source_map: source_map.clone(), - top_level_mark: *top_level_mark, - } - .cell()) - }, - |f, cx| { - GLOBALS.set(globals, || { - HANDLER.set(&handler, || HELPERS.set(&Helpers::new(true), || f.poll(cx))) - }) - }, - ) - .await -} - fn handle_call_boxed<'a, G: Fn(Vec) + Send + Sync + 'a>( ast_path: &'a [AstParentKind], span: Span, 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 13eb72cdef06f..ab01d5889e94f 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 @@ -39,7 +39,7 @@ impl EcmascriptChunkItem for EcmascriptModuleLocalsChunkItem { let chunking_context = self.chunking_context; let exports = self.module.get_exports(); let original_module = module.module; - let parsed = original_module.parse().resolve().await?; + let parsed = original_module.parse(None).resolve().await?; let analyze_result = original_module.analyze().await?; let async_module_options = analyze_result diff --git a/turbopack/crates/turbopack-ecmascript/src/tree_shake/asset.rs b/turbopack/crates/turbopack-ecmascript/src/tree_shake/asset.rs index 0afbf04d58ff1..041e671907fbd 100644 --- a/turbopack/crates/turbopack-ecmascript/src/tree_shake/asset.rs +++ b/turbopack/crates/turbopack-ecmascript/src/tree_shake/asset.rs @@ -37,17 +37,21 @@ pub struct EcmascriptModulePartAsset { #[turbo_tasks::value_impl] impl EcmascriptParsable for EcmascriptModulePartAsset { #[turbo_tasks::function] - async fn failsafe_parse(self: Vc) -> Result> { + async fn failsafe_parse( + self: Vc, + part: Option>, + ) -> Result> { let this = self.await?; - let parsed = this.full_module.failsafe_parse(); + let parsed = this.full_module.failsafe_parse(Some(this.part)); let split_data = split(this.full_module.ident(), this.full_module.source(), parsed); Ok(part_of_module(split_data, this.part)) } #[turbo_tasks::function] async fn parse_original(self: Vc) -> Result> { - Ok(self.await?.full_module.parse_original()) + let this = self.await?; + Ok(this.full_module.parse_original()) } #[turbo_tasks::function] diff --git a/turbopack/crates/turbopack-ecmascript/src/tree_shake/mod.rs b/turbopack/crates/turbopack-ecmascript/src/tree_shake/mod.rs index e76f6f815338d..bccd7bb8dce7b 100644 --- a/turbopack/crates/turbopack-ecmascript/src/tree_shake/mod.rs +++ b/turbopack/crates/turbopack-ecmascript/src/tree_shake/mod.rs @@ -437,7 +437,11 @@ impl PartialEq for SplitResult { #[turbo_tasks::function] pub(super) async fn split_module(asset: Vc) -> Result> { - Ok(split(asset.source().ident(), asset.source(), asset.parse())) + Ok(split( + asset.source().ident(), + asset.source(), + asset.parse(None), + )) } #[turbo_tasks::function] @@ -549,7 +553,7 @@ pub(super) async fn split( } #[turbo_tasks::function] -pub(super) async fn part_of_module( +pub(crate) async fn part_of_module( split_data: Vc, part: Vc, ) -> Result> {