Skip to content

Commit 7df26e2

Browse files
Boshenclaude
andcommitted
feat(transformer): move explicit resource management to ES2026
Move explicit resource management from proposals to ES2026, as it is now a finalized ECMAScript 2026 feature. Changes: - Create ES2026 module with explicit_resource_management - Update EnvOptions to include ES2026Options - Remove explicit_resource_management from proposals - Update TransformerImpl to use x2_es2026 instead of explicit_resource_management 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 81a28d4 commit 7df26e2

File tree

15 files changed

+1065
-861
lines changed

15 files changed

+1065
-861
lines changed

crates/oxc_compat/src/es_features.rs

Lines changed: 929 additions & 821 deletions
Large diffs are not rendered by default.

crates/oxc_compat/src/es_target.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ impl ESVersion for ESTarget {
2020
Self::ES2023 => Version(2023, 0, 0),
2121
Self::ES2024 => Version(2024, 0, 0),
2222
Self::ES2025 => Version(2025, 0, 0),
23+
Self::ES2026 => Version(2026, 0, 0),
2324
Self::ESNext => Version(9999, 0, 0),
2425
}
2526
}

crates/oxc_syntax/src/es_target.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ pub enum ESTarget {
1818
ES2023,
1919
ES2024,
2020
ES2025,
21+
ES2026,
2122
#[default]
2223
ESNext,
2324
}
@@ -39,6 +40,7 @@ impl FromStr for ESTarget {
3940
"es2023" => Ok(Self::ES2023),
4041
"es2024" => Ok(Self::ES2024),
4142
"es2025" => Ok(Self::ES2025),
43+
"es2026" => Ok(Self::ES2026),
4244
"esnext" => Ok(Self::ESNext),
4345
_ => Err(format!("Invalid target \"{s}\".")),
4446
}
@@ -59,6 +61,7 @@ impl fmt::Display for ESTarget {
5961
Self::ES2023 => "es2023",
6062
Self::ES2024 => "es2024",
6163
Self::ES2025 => "es2025",
64+
Self::ES2026 => "es2026",
6265
Self::ESNext => "esnext",
6366
};
6467
f.write_str(s)
File renamed without changes.
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
use oxc_ast::ast::*;
2+
use oxc_traverse::Traverse;
3+
4+
use crate::{
5+
context::{TransformCtx, TraverseCtx},
6+
state::TransformState,
7+
};
8+
9+
mod explicit_resource_management;
10+
mod options;
11+
12+
use explicit_resource_management::ExplicitResourceManagement;
13+
pub use options::ES2026Options;
14+
15+
pub struct ES2026<'a, 'ctx> {
16+
explicit_resource_management: Option<ExplicitResourceManagement<'a, 'ctx>>,
17+
}
18+
19+
impl<'a, 'ctx> ES2026<'a, 'ctx> {
20+
pub fn new(options: ES2026Options, ctx: &'ctx TransformCtx<'a>) -> Self {
21+
let explicit_resource_management = if options.explicit_resource_management {
22+
Some(ExplicitResourceManagement::new(ctx))
23+
} else {
24+
None
25+
};
26+
Self { explicit_resource_management }
27+
}
28+
}
29+
30+
impl<'a> Traverse<'a, TransformState<'a>> for ES2026<'a, '_> {
31+
fn enter_program(&mut self, program: &mut Program<'a>, ctx: &mut TraverseCtx<'a>) {
32+
if let Some(explicit_resource_management) = &mut self.explicit_resource_management {
33+
explicit_resource_management.enter_program(program, ctx);
34+
}
35+
}
36+
37+
fn enter_for_of_statement(
38+
&mut self,
39+
for_of_stmt: &mut ForOfStatement<'a>,
40+
ctx: &mut TraverseCtx<'a>,
41+
) {
42+
if let Some(explicit_resource_management) = &mut self.explicit_resource_management {
43+
explicit_resource_management.enter_for_of_statement(for_of_stmt, ctx);
44+
}
45+
}
46+
47+
fn exit_static_block(&mut self, block: &mut StaticBlock<'a>, ctx: &mut TraverseCtx<'a>) {
48+
if let Some(explicit_resource_management) = &mut self.explicit_resource_management {
49+
explicit_resource_management.exit_static_block(block, ctx);
50+
}
51+
}
52+
53+
fn enter_function_body(&mut self, body: &mut FunctionBody<'a>, ctx: &mut TraverseCtx<'a>) {
54+
if let Some(explicit_resource_management) = &mut self.explicit_resource_management {
55+
explicit_resource_management.enter_function_body(body, ctx);
56+
}
57+
}
58+
59+
fn enter_statement(&mut self, stmt: &mut Statement<'a>, ctx: &mut TraverseCtx<'a>) {
60+
if let Some(explicit_resource_management) = &mut self.explicit_resource_management {
61+
explicit_resource_management.enter_statement(stmt, ctx);
62+
}
63+
}
64+
65+
fn enter_try_statement(&mut self, node: &mut TryStatement<'a>, ctx: &mut TraverseCtx<'a>) {
66+
if let Some(explicit_resource_management) = &mut self.explicit_resource_management {
67+
explicit_resource_management.enter_try_statement(node, ctx);
68+
}
69+
}
70+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
use serde::Deserialize;
2+
3+
#[derive(Debug, Default, Clone, Copy, Deserialize)]
4+
#[serde(default, rename_all = "camelCase", deny_unknown_fields)]
5+
pub struct ES2026Options {
6+
#[serde(skip)]
7+
pub explicit_resource_management: bool,
8+
}

crates/oxc_transformer/src/lib.rs

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ mod es2019;
3131
mod es2020;
3232
mod es2021;
3333
mod es2022;
34+
mod es2026;
3435
mod jsx;
3536
mod proposals;
3637
mod regexp;
@@ -50,8 +51,8 @@ use es2019::ES2019;
5051
use es2020::ES2020;
5152
use es2021::ES2021;
5253
use es2022::ES2022;
54+
use es2026::ES2026;
5355
use jsx::Jsx;
54-
use proposals::ExplicitResourceManagement;
5556
use regexp::RegExp;
5657
use rustc_hash::FxHashMap;
5758
use state::TransformState;
@@ -70,6 +71,7 @@ pub use crate::{
7071
es2020::ES2020Options,
7172
es2021::ES2021Options,
7273
es2022::{ClassPropertiesOptions, ES2022Options},
74+
es2026::ES2026Options,
7375
jsx::{JsxOptions, JsxRuntime, ReactRefreshOptions},
7476
options::{
7577
ESTarget, Engine, EngineTargets, EnvOptions, Module, TransformOptions,
@@ -98,6 +100,7 @@ pub struct Transformer<'a> {
98100
plugins: PluginsOptions,
99101
jsx: JsxOptions,
100102
env: EnvOptions,
103+
#[expect(dead_code)]
101104
proposals: ProposalOptions,
102105
}
103106

@@ -140,15 +143,12 @@ impl<'a> Transformer<'a> {
140143
common: Common::new(&self.env, &self.ctx),
141144
decorator: Decorator::new(self.decorator, &self.ctx),
142145
plugins: Plugins::new(self.plugins, &self.ctx),
143-
explicit_resource_management: self
144-
.proposals
145-
.explicit_resource_management
146-
.then(|| ExplicitResourceManagement::new(&self.ctx)),
147146
x0_typescript: program
148147
.source_type
149148
.is_typescript()
150149
.then(|| TypeScript::new(&self.typescript, &self.ctx)),
151150
x1_jsx: Jsx::new(self.jsx, self.env.es2018.object_rest_spread, ast_builder, &self.ctx),
151+
x2_es2026: ES2026::new(self.env.es2026, &self.ctx),
152152
x2_es2022: ES2022::new(
153153
self.env.es2022,
154154
!self.typescript.allow_declare_fields
@@ -178,8 +178,8 @@ struct TransformerImpl<'a, 'ctx> {
178178
x0_typescript: Option<TypeScript<'a, 'ctx>>,
179179
decorator: Decorator<'a, 'ctx>,
180180
plugins: Plugins<'a, 'ctx>,
181-
explicit_resource_management: Option<ExplicitResourceManagement<'a, 'ctx>>,
182181
x1_jsx: Jsx<'a, 'ctx>,
182+
x2_es2026: ES2026<'a, 'ctx>,
183183
x2_es2022: ES2022<'a, 'ctx>,
184184
x2_es2021: ES2021<'a, 'ctx>,
185185
x2_es2020: ES2020<'a, 'ctx>,
@@ -200,9 +200,7 @@ impl<'a> Traverse<'a, TransformState<'a>> for TransformerImpl<'a, '_> {
200200
}
201201
self.plugins.enter_program(program, ctx);
202202
self.x1_jsx.enter_program(program, ctx);
203-
if let Some(explicit_resource_management) = self.explicit_resource_management.as_mut() {
204-
explicit_resource_management.enter_program(program, ctx);
205-
}
203+
self.x2_es2026.enter_program(program, ctx);
206204
}
207205

208206
fn exit_program(&mut self, program: &mut Program<'a>, ctx: &mut TraverseCtx<'a>) {
@@ -316,9 +314,7 @@ impl<'a> Traverse<'a, TransformState<'a>> for TransformerImpl<'a, '_> {
316314

317315
fn exit_static_block(&mut self, block: &mut StaticBlock<'a>, ctx: &mut TraverseCtx<'a>) {
318316
self.common.exit_static_block(block, ctx);
319-
if let Some(explicit_resource_management) = self.explicit_resource_management.as_mut() {
320-
explicit_resource_management.exit_static_block(block, ctx);
321-
}
317+
self.x2_es2026.exit_static_block(block, ctx);
322318
self.x2_es2022.exit_static_block(block, ctx);
323319
}
324320

@@ -409,9 +405,7 @@ impl<'a> Traverse<'a, TransformState<'a>> for TransformerImpl<'a, '_> {
409405

410406
fn enter_function_body(&mut self, body: &mut FunctionBody<'a>, ctx: &mut TraverseCtx<'a>) {
411407
self.common.enter_function_body(body, ctx);
412-
if let Some(explicit_resource_management) = self.explicit_resource_management.as_mut() {
413-
explicit_resource_management.enter_function_body(body, ctx);
414-
}
408+
self.x2_es2026.enter_function_body(body, ctx);
415409
}
416410

417411
fn exit_function_body(&mut self, body: &mut FunctionBody<'a>, ctx: &mut TraverseCtx<'a>) {
@@ -603,9 +597,7 @@ impl<'a> Traverse<'a, TransformState<'a>> for TransformerImpl<'a, '_> {
603597
typescript.enter_statement(stmt, ctx);
604598
}
605599
self.x2_es2018.enter_statement(stmt, ctx);
606-
if let Some(explicit_resource_management) = self.explicit_resource_management.as_mut() {
607-
explicit_resource_management.enter_statement(stmt, ctx);
608-
}
600+
self.x2_es2026.enter_statement(stmt, ctx);
609601
}
610602

611603
fn enter_declaration(&mut self, decl: &mut Declaration<'a>, ctx: &mut TraverseCtx<'a>) {
@@ -646,9 +638,7 @@ impl<'a> Traverse<'a, TransformState<'a>> for TransformerImpl<'a, '_> {
646638
if let Some(typescript) = self.x0_typescript.as_mut() {
647639
typescript.enter_for_of_statement(stmt, ctx);
648640
}
649-
if let Some(explicit_resource_management) = self.explicit_resource_management.as_mut() {
650-
explicit_resource_management.enter_for_of_statement(stmt, ctx);
651-
}
641+
self.x2_es2026.enter_for_of_statement(stmt, ctx);
652642
self.x2_es2018.enter_for_of_statement(stmt, ctx);
653643
}
654644

@@ -660,9 +650,7 @@ impl<'a> Traverse<'a, TransformState<'a>> for TransformerImpl<'a, '_> {
660650
}
661651

662652
fn enter_try_statement(&mut self, stmt: &mut TryStatement<'a>, ctx: &mut TraverseCtx<'a>) {
663-
if let Some(explicit_resource_management) = self.explicit_resource_management.as_mut() {
664-
explicit_resource_management.enter_try_statement(stmt, ctx);
665-
}
653+
self.x2_es2026.enter_try_statement(stmt, ctx);
666654
}
667655

668656
fn enter_catch_clause(&mut self, clause: &mut CatchClause<'a>, ctx: &mut TraverseCtx<'a>) {

crates/oxc_transformer/src/options/babel/plugins.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,10 @@ pub struct BabelPlugins {
7070
// ES2022
7171
pub class_static_block: bool,
7272
pub class_properties: Option<ClassPropertiesOptions>,
73+
// ES2026
74+
pub explicit_resource_management: bool,
7375
// Decorator
7476
pub legacy_decorator: Option<DecoratorOptions>,
75-
// Proposals
76-
pub explicit_resource_management: bool,
7777
// Built-in plugins
7878
pub styled_components: Option<StyledComponentsOptions>,
7979
}

crates/oxc_transformer/src/options/env.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use crate::{
99
es2020::ES2020Options,
1010
es2021::ES2021Options,
1111
es2022::{ClassPropertiesOptions, ES2022Options},
12+
es2026::ES2026Options,
1213
regexp::RegExpOptions,
1314
};
1415

@@ -38,6 +39,8 @@ pub struct EnvOptions {
3839
pub es2021: ES2021Options,
3940

4041
pub es2022: ES2022Options,
42+
43+
pub es2026: ES2026Options,
4144
}
4245

4346
impl EnvOptions {
@@ -84,6 +87,7 @@ impl EnvOptions {
8487
class_static_block: true,
8588
class_properties: Some(ClassPropertiesOptions::default()),
8689
},
90+
es2026: ES2026Options { explicit_resource_management: true },
8791
}
8892
}
8993

@@ -161,6 +165,9 @@ impl From<EngineTargets> for EnvOptions {
161165
class_static_block: o.has_feature(ES2022ClassStaticBlock),
162166
class_properties: o.has_feature(ES2022ClassProperties).then(Default::default),
163167
},
168+
es2026: ES2026Options {
169+
explicit_resource_management: o.has_feature(ES2026ExplicitResourceManagement),
170+
},
164171
}
165172
}
166173
}

crates/oxc_transformer/src/options/mod.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use crate::{
1313
es2020::ES2020Options,
1414
es2021::ES2021Options,
1515
es2022::ES2022Options,
16+
es2026::ES2026Options,
1617
jsx::JsxOptions,
1718
plugins::{PluginsOptions, StyledComponentsOptions},
1819
proposals::ProposalOptions,
@@ -277,10 +278,11 @@ impl TryFrom<&BabelOptions> for TransformOptions {
277278
es2020,
278279
es2021,
279280
es2022,
281+
es2026: ES2026Options {
282+
explicit_resource_management: options.plugins.explicit_resource_management,
283+
},
280284
},
281-
proposals: ProposalOptions {
282-
explicit_resource_management: options.plugins.explicit_resource_management,
283-
},
285+
proposals: ProposalOptions::default(),
284286
helper_loader,
285287
plugins,
286288
})

0 commit comments

Comments
 (0)