diff --git a/crates/oxc_transformer/src/lib.rs b/crates/oxc_transformer/src/lib.rs index 052867e12a93f..9704c4078ed64 100644 --- a/crates/oxc_transformer/src/lib.rs +++ b/crates/oxc_transformer/src/lib.rs @@ -630,6 +630,12 @@ impl<'a> Traverse<'a> for TransformerImpl<'a, '_> { self.x2_es2018.enter_for_in_statement(stmt, ctx); } + fn enter_try_statement(&mut self, stmt: &mut TryStatement<'a>, ctx: &mut TraverseCtx<'a>) { + if let Some(explicit_resource_management) = self.explicit_resource_management.as_mut() { + explicit_resource_management.enter_try_statement(stmt, ctx); + } + } + fn enter_catch_clause(&mut self, clause: &mut CatchClause<'a>, ctx: &mut TraverseCtx<'a>) { self.x2_es2019.enter_catch_clause(clause, ctx); self.x2_es2018.enter_catch_clause(clause, ctx); diff --git a/crates/oxc_transformer/src/proposals/explicit_resource_management.rs b/crates/oxc_transformer/src/proposals/explicit_resource_management.rs index 24182911ae6d6..a0f38ed4421dc 100644 --- a/crates/oxc_transformer/src/proposals/explicit_resource_management.rs +++ b/crates/oxc_transformer/src/proposals/explicit_resource_management.rs @@ -240,6 +240,55 @@ impl<'a> Traverse<'a> for ExplicitResourceManagement<'a, '_> { } } + /// Transform try statement. + /// + /// ```js + /// try { + /// using x = y(); + /// } catch (err) { } + /// ``` + /// -> + /// ```js + /// try { + /// try { + /// var _usingCtx = babelHelpers.usingCtx(); + /// const x = _usingCtx.u(y()); + /// } catch (_) { + /// _usingCtx.e = _; + /// } finally { + /// _usingCtx.d(); + /// } + /// } catch (err) { } + /// ``` + fn enter_try_statement(&mut self, node: &mut TryStatement<'a>, ctx: &mut TraverseCtx<'a>) { + let scope_id = node.block.scope_id(); + + if let Some((new_stmts, needs_await, using_ctx)) = + self.transform_statements(&mut node.block.body, scope_id, ctx) + { + let block_stmt_scope_id = ctx.insert_scope_between( + ctx.scoping().scope_parent_id(scope_id).unwrap(), + scope_id, + ScopeFlags::empty(), + ); + + node.block.body = ctx.ast.vec1(Self::create_try_stmt( + ctx.ast.block_statement_with_scope_id(SPAN, new_stmts, scope_id), + &using_ctx, + block_stmt_scope_id, + needs_await, + ctx, + )); + + let current_hoist_scope_id = ctx.current_hoist_scope_id(); + node.block.set_scope_id(block_stmt_scope_id); + ctx.scoping_mut().set_symbol_scope_id(using_ctx.symbol_id, current_hoist_scope_id); + ctx.scoping_mut().move_binding(scope_id, current_hoist_scope_id, &using_ctx.name); + + ctx.scoping_mut().change_scope_parent_id(scope_id, Some(block_stmt_scope_id)); + } + } + /// Move any top level `using` declarations within a block statement, /// allowing `enter_statement` to transform them. fn enter_program(&mut self, program: &mut Program<'a>, ctx: &mut TraverseCtx<'a>) { diff --git a/tasks/transform_conformance/snapshots/oxc.snap.md b/tasks/transform_conformance/snapshots/oxc.snap.md index ddca2c85f4d9d..a74634c2fa1c6 100644 --- a/tasks/transform_conformance/snapshots/oxc.snap.md +++ b/tasks/transform_conformance/snapshots/oxc.snap.md @@ -1,6 +1,6 @@ commit: 578ac4df -Passed: 140/232 +Passed: 141/233 # All Passed: * babel-plugin-transform-class-static-block @@ -347,7 +347,7 @@ x Output mismatch x Output mismatch -# babel-plugin-proposal-explicit-resource-management (1/3) +# babel-plugin-proposal-explicit-resource-management (2/4) * export-class-name/input.js x Output mismatch diff --git a/tasks/transform_conformance/tests/babel-plugin-proposal-explicit-resource-management/test/fixtures/try-catch/input.js b/tasks/transform_conformance/tests/babel-plugin-proposal-explicit-resource-management/test/fixtures/try-catch/input.js new file mode 100644 index 0000000000000..a6d245d197876 --- /dev/null +++ b/tasks/transform_conformance/tests/babel-plugin-proposal-explicit-resource-management/test/fixtures/try-catch/input.js @@ -0,0 +1,8 @@ +export class WorkspaceResolver { + async invite() { + try { + await using lock = await acquire(lockFlag); + } catch { + } + } + } \ No newline at end of file diff --git a/tasks/transform_conformance/tests/babel-plugin-proposal-explicit-resource-management/test/fixtures/try-catch/options.json b/tasks/transform_conformance/tests/babel-plugin-proposal-explicit-resource-management/test/fixtures/try-catch/options.json new file mode 100644 index 0000000000000..2bc3ea3845be0 --- /dev/null +++ b/tasks/transform_conformance/tests/babel-plugin-proposal-explicit-resource-management/test/fixtures/try-catch/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["proposal-explicit-resource-management"] +} diff --git a/tasks/transform_conformance/tests/babel-plugin-proposal-explicit-resource-management/test/fixtures/try-catch/output.js b/tasks/transform_conformance/tests/babel-plugin-proposal-explicit-resource-management/test/fixtures/try-catch/output.js new file mode 100644 index 0000000000000..c0a34afd40481 --- /dev/null +++ b/tasks/transform_conformance/tests/babel-plugin-proposal-explicit-resource-management/test/fixtures/try-catch/output.js @@ -0,0 +1,14 @@ +export class WorkspaceResolver { + async invite() { + try { + try { + var _usingCtx = babelHelpers.usingCtx(); + const lock = _usingCtx.a(await acquire(lockFlag)); + } catch (_) { + _usingCtx.e = _; + } finally { + await _usingCtx.d(); + } + } catch {} + } +}