diff --git a/crates/oxc_transformer/src/lib.rs b/crates/oxc_transformer/src/lib.rs index 2d5b4918ded3c..40a2ad1881ecf 100644 --- a/crates/oxc_transformer/src/lib.rs +++ b/crates/oxc_transformer/src/lib.rs @@ -202,6 +202,7 @@ impl<'a> Traverse<'a> for TransformerImpl<'a, '_> { ctx: &mut TraverseCtx<'a>, ) { self.x2_es2018.enter_variable_declaration(decl, ctx); + self.explicit_resource_management.enter_variable_declaration(decl, ctx); } fn enter_variable_declarator( @@ -273,6 +274,7 @@ impl<'a> Traverse<'a> for TransformerImpl<'a, '_> { fn enter_static_block(&mut self, block: &mut StaticBlock<'a>, ctx: &mut TraverseCtx<'a>) { self.common.enter_static_block(block, ctx); + self.explicit_resource_management.enter_static_block(block, ctx); self.x2_es2022.enter_static_block(block, ctx); } diff --git a/crates/oxc_transformer/src/proposals/explicit_resource_management.rs b/crates/oxc_transformer/src/proposals/explicit_resource_management.rs index 677c72d9c22ac..9061618ea5c9c 100644 --- a/crates/oxc_transformer/src/proposals/explicit_resource_management.rs +++ b/crates/oxc_transformer/src/proposals/explicit_resource_management.rs @@ -39,6 +39,7 @@ use rustc_hash::FxHashMap; use oxc_allocator::{Address, Box as ArenaBox, GetAddress, Vec as ArenaVec}; use oxc_ast::{NONE, ast::*}; +use oxc_data_structures::stack::NonEmptyStack; use oxc_ecmascript::BoundNames; use oxc_semantic::{ScopeFlags, ScopeId, SymbolFlags}; use oxc_span::{Atom, SPAN}; @@ -50,11 +51,19 @@ pub struct ExplicitResourceManagement<'a, 'ctx> { ctx: &'ctx TransformCtx<'a>, top_level_using: FxHashMap, + + /// keeps track of whether the current static block contains a `using` declaration + /// so that we can transform it in `exit_static_block` + static_blocks_stack: NonEmptyStack, } impl<'a, 'ctx> ExplicitResourceManagement<'a, 'ctx> { pub fn new(ctx: &'ctx TransformCtx<'a>) -> Self { - Self { ctx, top_level_using: FxHashMap::default() } + Self { + ctx, + top_level_using: FxHashMap::default(), + static_blocks_stack: NonEmptyStack::new(false), + } } } @@ -123,6 +132,10 @@ impl<'a> Traverse<'a> for ExplicitResourceManagement<'a, '_> { }; } + fn enter_static_block(&mut self, _node: &mut StaticBlock<'a>, _ctx: &mut TraverseCtx<'a>) { + self.static_blocks_stack.push(false); + } + /// Transform class static block. /// /// ```js @@ -144,11 +157,25 @@ impl<'a> Traverse<'a> for ExplicitResourceManagement<'a, '_> { /// } /// ``` fn exit_static_block(&mut self, block: &mut StaticBlock<'a>, ctx: &mut TraverseCtx<'a>) { - let scope_id = block.scope_id(); - if let Some(replacement) = - self.transform_statements(&mut block.body, None, scope_id, scope_id, ctx) + if self.static_blocks_stack.pop() { + let scope_id = block.scope_id(); + if let Some(replacement) = + self.transform_statements(&mut block.body, None, scope_id, scope_id, ctx) + { + block.body = ctx.ast.vec1(replacement); + } + } + } + + fn enter_variable_declaration( + &mut self, + node: &mut VariableDeclaration<'a>, + ctx: &mut TraverseCtx<'a>, + ) { + if matches!(node.kind, VariableDeclarationKind::Using | VariableDeclarationKind::AwaitUsing) + && ctx.parent().is_static_block() { - block.body = ctx.ast.vec1(replacement); + *self.static_blocks_stack.last_mut() = true; } }