mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +00:00
feat(transformer): support optional-catch-binding plugin (#4885)
part of #4754 The implementation copy from the original implementation which removed in https://github.com/oxc-project/oxc/pull/2865.
This commit is contained in:
parent
69da9fda3a
commit
ab1d08ccfb
9 changed files with 128 additions and 5 deletions
35
crates/oxc_transformer/src/es2019/mod.rs
Normal file
35
crates/oxc_transformer/src/es2019/mod.rs
Normal file
|
|
@ -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
crates/oxc_transformer/src/es2019/optional_catch_binding.rs
Normal file
52
crates/oxc_transformer/src/es2019/optional_catch_binding.rs
Normal file
|
|
@ -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
crates/oxc_transformer/src/es2019/options.rs
Normal file
16
crates/oxc_transformer/src/es2019/options.rs
Normal file
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -16,6 +16,7 @@ mod options;
|
||||||
mod env;
|
mod env;
|
||||||
mod es2015;
|
mod es2015;
|
||||||
mod es2016;
|
mod es2016;
|
||||||
|
mod es2019;
|
||||||
mod es2020;
|
mod es2020;
|
||||||
mod react;
|
mod react;
|
||||||
mod typescript;
|
mod typescript;
|
||||||
|
|
@ -28,6 +29,7 @@ mod helpers {
|
||||||
use std::{path::Path, rc::Rc};
|
use std::{path::Path, rc::Rc};
|
||||||
|
|
||||||
use es2016::ES2016;
|
use es2016::ES2016;
|
||||||
|
use es2019::ES2019;
|
||||||
use es2020::ES2020;
|
use es2020::ES2020;
|
||||||
use oxc_allocator::{Allocator, Vec};
|
use oxc_allocator::{Allocator, Vec};
|
||||||
use oxc_ast::{ast::*, AstBuilder, Trivias};
|
use oxc_ast::{ast::*, AstBuilder, Trivias};
|
||||||
|
|
@ -63,6 +65,7 @@ pub struct Transformer<'a> {
|
||||||
x0_typescript: TypeScript<'a>,
|
x0_typescript: TypeScript<'a>,
|
||||||
x1_react: React<'a>,
|
x1_react: React<'a>,
|
||||||
x2_es2020: ES2020<'a>,
|
x2_es2020: ES2020<'a>,
|
||||||
|
x2_es2019: ES2019<'a>,
|
||||||
x2_es2016: ES2016<'a>,
|
x2_es2016: ES2016<'a>,
|
||||||
x3_es2015: ES2015<'a>,
|
x3_es2015: ES2015<'a>,
|
||||||
}
|
}
|
||||||
|
|
@ -88,8 +91,9 @@ impl<'a> Transformer<'a> {
|
||||||
ctx: Rc::clone(&ctx),
|
ctx: Rc::clone(&ctx),
|
||||||
x0_typescript: TypeScript::new(options.typescript, Rc::clone(&ctx)),
|
x0_typescript: TypeScript::new(options.typescript, Rc::clone(&ctx)),
|
||||||
x1_react: React::new(options.react, 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_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),
|
x3_es2015: ES2015::new(options.es2015, ctx),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -317,6 +321,10 @@ impl<'a> Traverse<'a> for Transformer<'a> {
|
||||||
self.x0_typescript.transform_for_in_statement(stmt, ctx);
|
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(
|
fn enter_ts_export_assignment(
|
||||||
&mut self,
|
&mut self,
|
||||||
export_assignment: &mut TSExportAssignment<'a>,
|
export_assignment: &mut TSExportAssignment<'a>,
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ use crate::{
|
||||||
env::{can_enable_plugin, EnvOptions, Versions},
|
env::{can_enable_plugin, EnvOptions, Versions},
|
||||||
es2015::{ArrowFunctionsOptions, ES2015Options},
|
es2015::{ArrowFunctionsOptions, ES2015Options},
|
||||||
es2016::ES2016Options,
|
es2016::ES2016Options,
|
||||||
|
es2019::ES2019Options,
|
||||||
es2020::ES2020Options,
|
es2020::ES2020Options,
|
||||||
options::babel::BabelOptions,
|
options::babel::BabelOptions,
|
||||||
react::ReactOptions,
|
react::ReactOptions,
|
||||||
|
|
@ -39,6 +40,8 @@ pub struct TransformOptions {
|
||||||
|
|
||||||
pub es2016: ES2016Options,
|
pub es2016: ES2016Options,
|
||||||
|
|
||||||
|
pub es2019: ES2019Options,
|
||||||
|
|
||||||
pub es2020: ES2020Options,
|
pub es2020: ES2020Options,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -115,6 +118,11 @@ impl TransformOptions {
|
||||||
enable_plugin(plugin_name, options, &env_options, &targets).is_some()
|
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 es2020 = ES2020Options::default().with_nullish_coalescing_operator({
|
||||||
let plugin_name = "transform-nullish-coalescing-operator";
|
let plugin_name = "transform-nullish-coalescing-operator";
|
||||||
enable_plugin(plugin_name, options, &env_options, &targets).is_some()
|
enable_plugin(plugin_name, options, &env_options, &targets).is_some()
|
||||||
|
|
@ -152,6 +160,7 @@ impl TransformOptions {
|
||||||
react,
|
react,
|
||||||
es2015,
|
es2015,
|
||||||
es2016,
|
es2016,
|
||||||
|
es2019,
|
||||||
es2020,
|
es2020,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
commit: 12619ffe
|
commit: 12619ffe
|
||||||
|
|
||||||
Passed: 458/943
|
Passed: 462/947
|
||||||
|
|
||||||
# All Passed:
|
# All Passed:
|
||||||
|
* babel-plugin-transform-optional-catch-binding
|
||||||
* babel-preset-react
|
* babel-preset-react
|
||||||
* babel-plugin-transform-react-display-name
|
* babel-plugin-transform-react-display-name
|
||||||
* babel-plugin-transform-react-jsx-self
|
* babel-plugin-transform-react-jsx-self
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
commit: 12619ffe
|
commit: 12619ffe
|
||||||
|
|
||||||
Passed: 12/18
|
Passed: 13/19
|
||||||
|
|
||||||
# All Passed:
|
# All Passed:
|
||||||
* babel-plugin-transform-nullish-coalescing-operator
|
* babel-plugin-transform-nullish-coalescing-operator
|
||||||
|
* babel-plugin-transform-optional-catch-binding
|
||||||
* babel-plugin-transform-exponentiation-operator
|
* babel-plugin-transform-exponentiation-operator
|
||||||
* babel-plugin-transform-arrow-functions
|
* babel-plugin-transform-arrow-functions
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
commit: 12619ffe
|
commit: 12619ffe
|
||||||
|
|
||||||
Passed: 5/8
|
Passed: 6/9
|
||||||
|
|
||||||
# All Passed:
|
# All Passed:
|
||||||
|
* babel-plugin-transform-optional-catch-binding
|
||||||
* babel-plugin-transform-react-jsx
|
* babel-plugin-transform-react-jsx
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ pub(crate) const PLUGINS: &[&str] = &[
|
||||||
// // [Syntax] "babel-plugin-transform-syntax-dynamic-import",
|
// // [Syntax] "babel-plugin-transform-syntax-dynamic-import",
|
||||||
// // [Syntax] "babel-plugin-transform-syntax-import-meta",
|
// // [Syntax] "babel-plugin-transform-syntax-import-meta",
|
||||||
// // ES2019
|
// // ES2019
|
||||||
// "babel-plugin-transform-optional-catch-binding",
|
"babel-plugin-transform-optional-catch-binding",
|
||||||
// "babel-plugin-transform-json-strings",
|
// "babel-plugin-transform-json-strings",
|
||||||
// // ES2018
|
// // ES2018
|
||||||
// "babel-plugin-transform-async-generator-functions",
|
// "babel-plugin-transform-async-generator-functions",
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue