diff --git a/crates/oxc_transformer/src/es2022/class_properties/static_block_and_prop_init.rs b/crates/oxc_transformer/src/es2022/class_properties/static_block_and_prop_init.rs index 57fbd83845262..21c0facc340b6 100644 --- a/crates/oxc_transformer/src/es2022/class_properties/static_block_and_prop_init.rs +++ b/crates/oxc_transformer/src/es2022/class_properties/static_block_and_prop_init.rs @@ -7,10 +7,12 @@ use oxc_ast::{ ast::*, visit::{walk_mut, VisitMut}, }; +use oxc_span::SPAN; use oxc_syntax::scope::{ScopeFlags, ScopeId}; use oxc_traverse::TraverseCtx; -use super::super::ClassStaticBlock; +use crate::utils::ast_builder::wrap_statements_in_arrow_function_iife; + use super::{ super_converter::{ClassPropertiesSuperConverter, ClassPropertiesSuperConverterMode}, ClassProperties, @@ -88,7 +90,7 @@ impl<'a> ClassProperties<'a, '_> { let outer_scope_id = ctx.current_scope_id(); ctx.scopes_mut().change_parent_id(scope_id, Some(outer_scope_id)); - ClassStaticBlock::wrap_statements_in_iife(stmts, scope_id, ctx) + wrap_statements_in_arrow_function_iife(ctx.ast.move_vec(stmts), scope_id, SPAN, ctx) } fn convert_static_block_with_single_expression_to_expression( diff --git a/crates/oxc_transformer/src/es2022/class_static_block.rs b/crates/oxc_transformer/src/es2022/class_static_block.rs index ecd8861d8136d..2caa456144f5b 100644 --- a/crates/oxc_transformer/src/es2022/class_static_block.rs +++ b/crates/oxc_transformer/src/es2022/class_static_block.rs @@ -41,12 +41,14 @@ use itoa::Buffer as ItoaBuffer; -use oxc_allocator::{String as ArenaString, Vec as ArenaVec}; +use oxc_allocator::String as ArenaString; use oxc_ast::{ast::*, NONE}; use oxc_span::SPAN; use oxc_syntax::scope::{ScopeFlags, ScopeId}; use oxc_traverse::{Traverse, TraverseCtx}; +use crate::utils::ast_builder::wrap_statements_in_arrow_function_iife; + pub struct ClassStaticBlock; impl ClassStaticBlock { @@ -157,32 +159,7 @@ impl ClassStaticBlock { // Always strict mode since we're in a class. *ctx.scopes_mut().get_flags_mut(scope_id) = ScopeFlags::Function | ScopeFlags::Arrow | ScopeFlags::StrictMode; - - Self::wrap_statements_in_iife(stmts, scope_id, ctx) - } - - /// Wrap statements in an IIFE. - /// - /// This function also used by `ClassProperties` transform. - pub(super) fn wrap_statements_in_iife<'a>( - stmts: &mut ArenaVec<'a, Statement<'a>>, - scope_id: ScopeId, - ctx: &mut TraverseCtx<'a>, - ) -> Expression<'a> { - let stmts = ctx.ast.move_vec(stmts); - let params = ctx.ast.alloc_formal_parameters( - SPAN, - FormalParameterKind::ArrowFormalParameters, - ctx.ast.vec(), - NONE, - ); - let body = ctx.ast.alloc_function_body(SPAN, ctx.ast.vec(), stmts); - let arrow = Expression::ArrowFunctionExpression( - ctx.ast.alloc_arrow_function_expression_with_scope_id( - SPAN, false, false, NONE, params, NONE, body, scope_id, - ), - ); - ctx.ast.expression_call(SPAN, arrow, NONE, ctx.ast.vec(), false) + wrap_statements_in_arrow_function_iife(ctx.ast.move_vec(stmts), scope_id, SPAN, ctx) } /// Convert static block to expression which will be value of private field, diff --git a/crates/oxc_transformer/src/utils/ast_builder.rs b/crates/oxc_transformer/src/utils/ast_builder.rs index 5fbfb8b740d74..f4ac299df9ddc 100644 --- a/crates/oxc_transformer/src/utils/ast_builder.rs +++ b/crates/oxc_transformer/src/utils/ast_builder.rs @@ -1,5 +1,6 @@ +use oxc_allocator::Vec as ArenaVec; use oxc_ast::{ast::*, NONE}; -use oxc_semantic::ScopeFlags; +use oxc_semantic::{ScopeFlags, ScopeId}; use oxc_span::{GetSpan, SPAN}; use oxc_traverse::TraverseCtx; @@ -40,28 +41,33 @@ pub(crate) fn create_call_call<'a>( /// Wrap an `Expression` in an arrow function IIFE (immediately invoked function expression) /// with a body block. /// -/// `expr` -> `(() => { return expr; })()` +/// `expr` -> `(() => { return expr; })()` pub(crate) fn wrap_expression_in_arrow_function_iife<'a>( expr: Expression<'a>, ctx: &mut TraverseCtx<'a>, ) -> Expression<'a> { let scope_id = ctx.insert_scope_below_expression(&expr, ScopeFlags::Arrow | ScopeFlags::Function); - let span = expr.span(); + let stmts = ctx.ast.vec1(ctx.ast.statement_return(SPAN, Some(expr))); + wrap_statements_in_arrow_function_iife(stmts, scope_id, span, ctx) +} + +/// Wrap statements in an IIFE (immediately invoked function expression). +/// +/// `x; y; z;` -> `(() => { x; y; z; })()` +pub(crate) fn wrap_statements_in_arrow_function_iife<'a>( + stmts: ArenaVec<'a, Statement<'a>>, + scope_id: ScopeId, + span: Span, + ctx: &mut TraverseCtx<'a>, +) -> Expression<'a> { let kind = FormalParameterKind::ArrowFormalParameters; - let params = ctx.ast.formal_parameters(SPAN, kind, ctx.ast.vec(), NONE); - let statements = ctx.ast.vec1(ctx.ast.statement_return(SPAN, Some(expr))); - let body = ctx.ast.function_body(SPAN, ctx.ast.vec(), statements); - let arrow = ctx.ast.alloc_arrow_function_expression_with_scope_id( - SPAN, false, false, NONE, params, NONE, body, scope_id, - ); - // IIFE - ctx.ast.expression_call( - span, - Expression::ArrowFunctionExpression(arrow), - NONE, - ctx.ast.vec(), - false, - ) + let params = ctx.ast.alloc_formal_parameters(SPAN, kind, ctx.ast.vec(), NONE); + let body = ctx.ast.alloc_function_body(SPAN, ctx.ast.vec(), stmts); + let arrow = + Expression::ArrowFunctionExpression(ctx.ast.alloc_arrow_function_expression_with_scope_id( + SPAN, false, false, NONE, params, NONE, body, scope_id, + )); + ctx.ast.expression_call(span, arrow, NONE, ctx.ast.vec(), false) }