Skip to content

Commit

Permalink
feat(transformer): support optional-catch-binding plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
Dunqing committed Aug 14, 2024
1 parent c0d4397 commit a0d1769
Show file tree
Hide file tree
Showing 9 changed files with 128 additions and 5 deletions.
35 changes: 35 additions & 0 deletions crates/oxc_transformer/src/es2019/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
mod optional_catch_binding;
mod options;

pub use optional_catch_binding::OptionalCatchBinding;
pub use options::ES2019Options;
use oxc_ast::ast::*;
use oxc_traverse::TraverseCtx;
use std::rc::Rc;

use crate::context::Ctx;

#[allow(dead_code)]
pub struct ES2019<'a> {
ctx: Ctx<'a>,
options: ES2019Options,

// Plugins
optional_catch_binding: OptionalCatchBinding<'a>,
}

impl<'a> ES2019<'a> {
pub fn new(options: ES2019Options, ctx: Ctx<'a>) -> Self {
Self { optional_catch_binding: OptionalCatchBinding::new(Rc::clone(&ctx)), ctx, options }
}

pub fn transform_catch_clause(
&mut self,
clause: &mut CatchClause<'a>,
ctx: &mut TraverseCtx<'a>,
) {
if self.options.optional_catch_binding {
self.optional_catch_binding.transform_catch_clause(clause, ctx);
}
}
}
52 changes: 52 additions & 0 deletions crates/oxc_transformer/src/es2019/optional_catch_binding.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
use std::cell::Cell;

use oxc_ast::ast::*;
use oxc_semantic::SymbolFlags;
use oxc_span::SPAN;
use oxc_traverse::TraverseCtx;

use crate::context::Ctx;

/// ES2019: Optional Catch Binding
///
/// References:
/// * <https://babel.dev/docs/babel-plugin-transform-optional-catch-binding>
/// * <https://github.com/babel/babel/tree/main/packages/babel-plugin-transform-optional-catch-binding>
pub struct OptionalCatchBinding<'a> {
_ctx: Ctx<'a>,
}

impl<'a> OptionalCatchBinding<'a> {
pub fn new(ctx: Ctx<'a>) -> Self {
Self { _ctx: ctx }
}

/// If CatchClause has no param, add a parameter called `unused`.
///
/// ```ts
/// try {}
/// catch {}
/// ```
/// too
/// ```ts
/// try {}
/// catch (_unused) {}
/// ```
#[allow(clippy::unused_self)]
pub fn transform_catch_clause(&self, clause: &mut CatchClause<'a>, ctx: &mut TraverseCtx<'a>) {
if clause.param.is_some() {
return;
}
let symbol_id =
ctx.generate_uid("unused", ctx.scoping.current_scope_id(), SymbolFlags::CatchVariable);
let name = ctx.ast.atom(ctx.symbols().get_name(symbol_id));
let binding_identifier =
BindingIdentifier { span: SPAN, symbol_id: Cell::new(Some(symbol_id)), name };
let binding_pattern_kind =
ctx.ast.binding_pattern_kind_from_binding_identifier(binding_identifier);
let binding_pattern =
ctx.ast.binding_pattern(binding_pattern_kind, None::<TSTypeAnnotation<'a>>, false);
let param = ctx.ast.catch_parameter(SPAN, binding_pattern);
clause.param = Some(param);
}
}
16 changes: 16 additions & 0 deletions crates/oxc_transformer/src/es2019/options.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use serde::Deserialize;

#[derive(Debug, Default, Clone, Deserialize)]
#[serde(default, rename_all = "camelCase", deny_unknown_fields)]
pub struct ES2019Options {
#[serde(skip)]
pub optional_catch_binding: bool,
}

impl ES2019Options {
#[must_use]
pub fn with_optional_catch_binding(mut self, enable: bool) -> Self {
self.optional_catch_binding = enable;
self
}
}
10 changes: 9 additions & 1 deletion crates/oxc_transformer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ mod options;
mod env;
mod es2015;
mod es2016;
mod es2019;
mod es2020;
mod react;
mod typescript;
Expand All @@ -28,6 +29,7 @@ mod helpers {
use std::{path::Path, rc::Rc};

use es2016::ES2016;
use es2019::ES2019;
use es2020::ES2020;
use oxc_allocator::{Allocator, Vec};
use oxc_ast::{ast::*, AstBuilder, Trivias};
Expand Down Expand Up @@ -63,6 +65,7 @@ pub struct Transformer<'a> {
x0_typescript: TypeScript<'a>,
x1_react: React<'a>,
x2_es2020: ES2020<'a>,
x2_es2019: ES2019<'a>,
x2_es2016: ES2016<'a>,
x3_es2015: ES2015<'a>,
}
Expand All @@ -88,8 +91,9 @@ impl<'a> Transformer<'a> {
ctx: Rc::clone(&ctx),
x0_typescript: TypeScript::new(options.typescript, Rc::clone(&ctx)),
x1_react: React::new(options.react, Rc::clone(&ctx)),
x2_es2016: ES2016::new(options.es2016, Rc::clone(&ctx)),
x2_es2020: ES2020::new(options.es2020, Rc::clone(&ctx)),
x2_es2019: ES2019::new(options.es2019, Rc::clone(&ctx)),
x2_es2016: ES2016::new(options.es2016, Rc::clone(&ctx)),
x3_es2015: ES2015::new(options.es2015, ctx),
}
}
Expand Down Expand Up @@ -317,6 +321,10 @@ impl<'a> Traverse<'a> for Transformer<'a> {
self.x0_typescript.transform_for_in_statement(stmt, ctx);
}

fn enter_catch_clause(&mut self, clause: &mut CatchClause<'a>, ctx: &mut TraverseCtx<'a>) {
self.x2_es2019.transform_catch_clause(clause, ctx);
}

fn enter_ts_export_assignment(
&mut self,
export_assignment: &mut TSExportAssignment<'a>,
Expand Down
9 changes: 9 additions & 0 deletions crates/oxc_transformer/src/options/transformer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use crate::{
env::{can_enable_plugin, EnvOptions, Versions},
es2015::{ArrowFunctionsOptions, ES2015Options},
es2016::ES2016Options,
es2019::ES2019Options,
es2020::ES2020Options,
options::babel::BabelOptions,
react::ReactOptions,
Expand Down Expand Up @@ -39,6 +40,8 @@ pub struct TransformOptions {

pub es2016: ES2016Options,

pub es2019: ES2019Options,

pub es2020: ES2020Options,
}

Expand Down Expand Up @@ -115,6 +118,11 @@ impl TransformOptions {
enable_plugin(plugin_name, options, &env_options, &targets).is_some()
});

let es2019 = ES2019Options::default().with_optional_catch_binding({
let plugin_name = "transform-optional-catch-binding";
enable_plugin(plugin_name, options, &env_options, &targets).is_some()
});

let es2020 = ES2020Options::default().with_nullish_coalescing_operator({
let plugin_name = "transform-nullish-coalescing-operator";
enable_plugin(plugin_name, options, &env_options, &targets).is_some()
Expand Down Expand Up @@ -152,6 +160,7 @@ impl TransformOptions {
react,
es2015,
es2016,
es2019,
es2020,
})
}
Expand Down
3 changes: 2 additions & 1 deletion tasks/transform_conformance/babel.snap.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
commit: 12619ffe

Passed: 458/943
Passed: 462/947

# All Passed:
* babel-plugin-transform-optional-catch-binding
* babel-preset-react
* babel-plugin-transform-react-display-name
* babel-plugin-transform-react-jsx-self
Expand Down
3 changes: 2 additions & 1 deletion tasks/transform_conformance/babel_exec.snap.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
commit: 12619ffe

Passed: 12/18
Passed: 13/19

# All Passed:
* babel-plugin-transform-nullish-coalescing-operator
* babel-plugin-transform-optional-catch-binding
* babel-plugin-transform-exponentiation-operator
* babel-plugin-transform-arrow-functions

Expand Down
3 changes: 2 additions & 1 deletion tasks/transform_conformance/oxc.snap.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
commit: 12619ffe

Passed: 5/8
Passed: 6/9

# All Passed:
* babel-plugin-transform-optional-catch-binding
* babel-plugin-transform-react-jsx


Expand Down
2 changes: 1 addition & 1 deletion tasks/transform_conformance/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub(crate) const PLUGINS: &[&str] = &[
// // [Syntax] "babel-plugin-transform-syntax-dynamic-import",
// // [Syntax] "babel-plugin-transform-syntax-import-meta",
// // ES2019
// "babel-plugin-transform-optional-catch-binding",
"babel-plugin-transform-optional-catch-binding",
// "babel-plugin-transform-json-strings",
// // ES2018
// "babel-plugin-transform-async-generator-functions",
Expand Down

0 comments on commit a0d1769

Please sign in to comment.