feat(transformer): add decorators plugin (#2139)

This commit is contained in:
Dunqing 2024-01-24 11:09:19 +08:00 committed by GitHub
parent 1ee6d8cea9
commit 9e598ff650
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 524 additions and 8 deletions

View file

@ -1443,6 +1443,12 @@ pub struct BindingPattern<'a> {
pub optional: bool, pub optional: bool,
} }
impl<'a> BindingPattern<'a> {
pub fn new_with_kind(kind: BindingPatternKind<'a>) -> Self {
Self { kind, type_annotation: None, optional: false }
}
}
#[derive(Debug, Hash)] #[derive(Debug, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize), serde(untagged))] #[cfg_attr(feature = "serde", derive(Serialize), serde(untagged))]
pub enum BindingPatternKind<'a> { pub enum BindingPatternKind<'a> {

View file

@ -16,6 +16,7 @@ mod es2021;
mod es2022; mod es2022;
mod es3; mod es3;
mod options; mod options;
mod proposals;
mod react_jsx; mod react_jsx;
mod regexp; mod regexp;
#[cfg(test)] #[cfg(test)]
@ -31,6 +32,7 @@ use oxc_ast::{ast::*, AstBuilder, AstKind, VisitMut};
use oxc_diagnostics::Error; use oxc_diagnostics::Error;
use oxc_semantic::{ScopeFlags, Semantic}; use oxc_semantic::{ScopeFlags, Semantic};
use oxc_span::SourceType; use oxc_span::SourceType;
use proposals::Decorators;
use crate::{ use crate::{
context::TransformerCtx, es2015::*, es2016::ExponentiationOperator, context::TransformerCtx, es2015::*, es2016::ExponentiationOperator,
@ -43,12 +45,14 @@ pub use crate::{
es2015::ArrowFunctionsOptions, es2015::ArrowFunctionsOptions,
es2020::NullishCoalescingOperatorOptions, es2020::NullishCoalescingOperatorOptions,
options::{TransformOptions, TransformTarget}, options::{TransformOptions, TransformTarget},
proposals::DecoratorsOptions,
react_jsx::{ReactJsxOptions, ReactJsxRuntime, ReactJsxRuntimeOption}, react_jsx::{ReactJsxOptions, ReactJsxRuntime, ReactJsxRuntimeOption},
typescript::TypescriptOptions, typescript::TypescriptOptions,
}; };
pub struct Transformer<'a> { pub struct Transformer<'a> {
ctx: TransformerCtx<'a>, ctx: TransformerCtx<'a>,
decorators: Option<Decorators<'a>>,
#[allow(unused)] #[allow(unused)]
typescript: Option<TypeScript<'a>>, typescript: Option<TypeScript<'a>>,
react_jsx: Option<ReactJsx<'a>>, react_jsx: Option<ReactJsx<'a>>,
@ -90,6 +94,7 @@ impl<'a> Transformer<'a> {
Self { Self {
ctx: ctx.clone(), ctx: ctx.clone(),
decorators: Decorators::new(Rc::clone(&ast), ctx.clone(), &options),
// TODO: pass verbatim_module_syntax from user config // TODO: pass verbatim_module_syntax from user config
typescript: source_type.is_typescript().then(|| TypeScript::new(Rc::clone(&ast), ctx.clone(), false, &options)), typescript: source_type.is_typescript().then(|| TypeScript::new(Rc::clone(&ast), ctx.clone(), false, &options)),
regexp_flags: RegexpFlags::new(Rc::clone(&ast), &options), regexp_flags: RegexpFlags::new(Rc::clone(&ast), &options),
@ -164,7 +169,7 @@ impl<'a> VisitMut<'a> for Transformer<'a> {
self.visit_statements(&mut program.body); self.visit_statements(&mut program.body);
self.react_jsx.as_mut().map(|t| t.add_react_jsx_runtime_imports(program)); self.react_jsx.as_mut().map(|t| t.add_react_jsx_runtime_imports(program));
self.decorators.as_mut().map(|t| t.transform_program(program));
self.leave_node(kind); self.leave_node(kind);
self.leave_scope(); self.leave_scope();
} }
@ -202,6 +207,7 @@ impl<'a> VisitMut<'a> for Transformer<'a> {
fn visit_declaration(&mut self, decl: &mut Declaration<'a>) { fn visit_declaration(&mut self, decl: &mut Declaration<'a>) {
self.visit_declaration_match(decl); self.visit_declaration_match(decl);
self.typescript.as_mut().map(|t| t.transform_declaration(decl)); self.typescript.as_mut().map(|t| t.transform_declaration(decl));
self.decorators.as_mut().map(|t| t.transform_declaration(decl));
} }
fn visit_expression(&mut self, expr: &mut Expression<'a>) { fn visit_expression(&mut self, expr: &mut Expression<'a>) {

View file

@ -2,7 +2,7 @@ use oxc_syntax::assumptions::CompilerAssumptions;
use crate::{ use crate::{
es2015::ArrowFunctionsOptions, es2020::NullishCoalescingOperatorOptions, es2015::ArrowFunctionsOptions, es2020::NullishCoalescingOperatorOptions,
react_jsx::ReactJsxOptions, typescript::TypescriptOptions, proposals::DecoratorsOptions, react_jsx::ReactJsxOptions, typescript::TypescriptOptions,
}; };
#[derive(Debug, Default, Clone)] #[derive(Debug, Default, Clone)]
@ -35,6 +35,8 @@ pub struct TransformOptions {
pub babel_8_breaking: Option<bool>, pub babel_8_breaking: Option<bool>,
pub instanceof: bool, pub instanceof: bool,
pub new_target: bool, pub new_target: bool,
// Proposal
pub decorators: Option<DecoratorsOptions>,
} }
/// See <https://www.typescriptlang.org/tsconfig#target> /// See <https://www.typescriptlang.org/tsconfig#target>

View file

@ -0,0 +1,149 @@
use std::rc::Rc;
use oxc_allocator::Box;
use oxc_ast::{ast::*, AstBuilder};
use oxc_span::{Atom, SPAN};
use oxc_syntax::operator::{AssignmentOperator, LogicalOperator};
use serde::Deserialize;
use crate::{context::TransformerCtx, options::TransformOptions};
/// Proposal: Decorators
///
/// References:
/// * <https://babel.dev/docs/babel-plugin-proposal-decorators>
/// * <https://github.com/babel/babel/blob/main/packages/babel-plugin-proposal-decorators>
/// * <https://github.com/tc39/proposal-decorators>
pub struct Decorators<'a> {
ast: Rc<AstBuilder<'a>>,
_ctx: TransformerCtx<'a>,
options: DecoratorsOptions,
// Insert to the top of the program
top_statements: Vec<Statement<'a>>,
}
#[derive(Debug, Clone, Copy, Default, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct DecoratorsOptions {
version: Version,
}
#[derive(Debug, Default, Clone, Copy, Deserialize)]
#[serde(rename_all = "camelCase")]
enum Version {
Legacy,
#[serde(rename = "2023-05")]
#[default]
Year2023May,
}
impl Version {
fn is_legacy(self) -> bool {
matches!(self, Self::Legacy)
}
}
impl<'a> Decorators<'a> {
pub fn new(
ast: Rc<AstBuilder<'a>>,
ctx: TransformerCtx<'a>,
options: &TransformOptions,
) -> Option<Self> {
options.decorators.map(|options| Self {
ast,
_ctx: ctx,
options,
top_statements: Vec::new(),
})
}
pub fn transform_program(&mut self, program: &mut Program<'a>) {
program.body.splice(0..0, self.top_statements.drain(..));
}
pub fn transform_declaration(&mut self, decl: &mut Declaration<'a>) {
let new_decl = match decl {
Declaration::ClassDeclaration(class) => {
if self.options.version.is_legacy() {
Some(self.transform_class_legacy(class))
} else {
None
}
}
_ => None,
};
if let Some(new_decl) = new_decl {
*decl = new_decl;
}
}
pub fn transform_class_legacy(
&mut self,
class: &mut Box<'a, oxc_ast::ast::Class<'a>>,
) -> Declaration<'a> {
let class_identifier_name: Atom = "_class".into();
let class_identifier = IdentifierReference::new(SPAN, class_identifier_name.clone());
let decl = self.ast.variable_declaration(
SPAN,
VariableDeclarationKind::Var,
self.ast.new_vec_single(self.ast.variable_declarator(
SPAN,
VariableDeclarationKind::Var,
BindingPattern::new_with_kind(self.ast.binding_pattern_identifier(
BindingIdentifier::new(SPAN, class_identifier_name),
)),
None,
false,
)),
Modifiers::empty(),
);
self.top_statements.push(Statement::Declaration(Declaration::VariableDeclaration(decl)));
let left = AssignmentTarget::SimpleAssignmentTarget(
self.ast.simple_assignment_target_identifier(class_identifier.clone()),
);
let right = self.ast.class_expression(self.ast.copy(class));
let new_expr =
self.ast.assignment_expression(SPAN, AssignmentOperator::Assign, left, right);
let new_expr = class.decorators.drain(..).fold(new_expr, |new_expr, decorator| {
match &decorator.expression {
Expression::Identifier(identifier) => self.ast.call_expression(
SPAN,
self.ast.identifier_reference_expression(IdentifierReference::new(
SPAN,
identifier.name.clone(),
)),
self.ast.new_vec_single(Argument::Expression(self.ast.copy(&new_expr))),
false,
None,
),
_ => new_expr,
}
});
let init = self.ast.logical_expression(
SPAN,
new_expr,
LogicalOperator::Or,
self.ast.identifier_reference_expression(class_identifier),
);
let declarator = self.ast.variable_declarator(
SPAN,
VariableDeclarationKind::Let,
BindingPattern::new_with_kind(
self.ast.binding_pattern_identifier(self.ast.copy(&class.id.clone().unwrap())),
),
Some(init),
false,
);
Declaration::VariableDeclaration(self.ast.variable_declaration(
SPAN,
VariableDeclarationKind::Let,
self.ast.new_vec_single(declarator),
Modifiers::empty(),
))
}
}

View file

@ -0,0 +1,3 @@
mod decorators;
pub use decorators::{Decorators, DecoratorsOptions};

View file

@ -1,4 +1,4 @@
Passed: 323/1179 Passed: 325/1369
# All Passed: # All Passed:
* babel-plugin-transform-numeric-separator * babel-plugin-transform-numeric-separator
@ -832,8 +832,7 @@ Passed: 323/1179
* general/function-duplicate-name/input.js * general/function-duplicate-name/input.js
* general/object/input.js * general/object/input.js
# babel-plugin-transform-typescript (92/158) # babel-plugin-transform-typescript (93/158)
* class/abstract-class-decorated/input.ts
* class/abstract-class-decorated-method/input.ts * class/abstract-class-decorated-method/input.ts
* class/abstract-class-decorated-parameter/input.ts * class/abstract-class-decorated-parameter/input.ts
* class/accessor-allowDeclareFields-false/input.ts * class/accessor-allowDeclareFields-false/input.ts
@ -912,3 +911,194 @@ Passed: 323/1179
* spread-transform/transform-to-babel-extend/input.js * spread-transform/transform-to-babel-extend/input.js
* spread-transform/transform-to-object-assign/input.js * spread-transform/transform-to-object-assign/input.js
# babel-plugin-proposal-decorators (1/190)
* 2018-09-transformation/async-generator-method/input.js
* 2018-09-transformation/class-decorators-yield-await/input.js
* 2021-12-accessors/context-name/input.js
* 2021-12-accessors--to-es2015/context-name/input.js
* 2021-12-fields/context-name/input.js
* 2021-12-fields--to-es2015/context-name/input.js
* 2021-12-getters/context-name/input.js
* 2021-12-getters--to-es2015/context-name/input.js
* 2021-12-methods/context-name/input.js
* 2021-12-methods--to-es2015/context-name/input.js
* 2021-12-misc/initProto-existing-derived-constructor/input.js
* 2021-12-misc/setting-private-method/input.js
* 2021-12-misc/setting-private-method-via-array-pattern/input.js
* 2021-12-misc/setting-private-method-via-for-of/input.js
* 2021-12-misc/setting-private-method-via-object-pattern/input.js
* 2021-12-misc/setting-private-method-via-rest/input.js
* 2021-12-misc/setting-private-method-via-update/input.js
* 2021-12-setters/context-name/input.js
* 2021-12-setters--to-es2015/context-name/input.js
* 2022-03-accessors/context-name/input.js
* 2022-03-accessors--to-es2015/context-name/input.js
* 2022-03-classes/decorator-access-modified-fields/input.js
* 2022-03-classes/decorator-access-modified-methods/input.js
* 2022-03-fields/context-name/input.js
* 2022-03-fields--to-es2015/context-name/input.js
* 2022-03-getters/context-name/input.js
* 2022-03-getters--to-es2015/context-name/input.js
* 2022-03-methods/context-name/input.js
* 2022-03-methods--to-es2015/context-name/input.js
* 2022-03-misc/initProto-existing-derived-constructor/input.js
* 2022-03-misc/setting-private-method/input.js
* 2022-03-misc/setting-private-method-via-array-pattern/input.js
* 2022-03-misc/setting-private-method-via-for-of/input.js
* 2022-03-misc/setting-private-method-via-object-pattern/input.js
* 2022-03-misc/setting-private-method-via-rest/input.js
* 2022-03-misc/setting-private-method-via-update/input.js
* 2022-03-setters/context-name/input.js
* 2022-03-setters--to-es2015/context-name/input.js
* 2023-01-accessors/context-name/input.js
* 2023-01-accessors--to-es2015/context-name/input.js
* 2023-01-classes/decorator-access-modified-fields/input.js
* 2023-01-classes/decorator-access-modified-methods/input.js
* 2023-01-fields/context-name/input.js
* 2023-01-fields--to-es2015/context-name/input.js
* 2023-01-getters/context-name/input.js
* 2023-01-getters--to-es2015/context-name/input.js
* 2023-01-methods/context-name/input.js
* 2023-01-methods--to-es2015/context-name/input.js
* 2023-01-misc/initProto-existing-derived-constructor/input.js
* 2023-01-misc/setting-private-method/input.js
* 2023-01-misc/setting-private-method-via-array-pattern/input.js
* 2023-01-misc/setting-private-method-via-for-of/input.js
* 2023-01-misc/setting-private-method-via-object-pattern/input.js
* 2023-01-misc/setting-private-method-via-rest/input.js
* 2023-01-misc/setting-private-method-via-update/input.js
* 2023-01-setters/context-name/input.js
* 2023-01-setters--to-es2015/context-name/input.js
* 2023-05-accessors/context-name/input.js
* 2023-05-accessors/private/input.js
* 2023-05-accessors/public/input.js
* 2023-05-accessors/static-private/input.js
* 2023-05-accessors/static-public/input.js
* 2023-05-accessors/undecorated-private/input.js
* 2023-05-accessors/undecorated-public/input.js
* 2023-05-accessors/undecorated-static-private/input.js
* 2023-05-accessors/undecorated-static-public/input.js
* 2023-05-accessors--to-es2015/context-name/input.js
* 2023-05-accessors--to-es2015/private/input.js
* 2023-05-accessors--to-es2015/public/input.js
* 2023-05-accessors--to-es2015/static-private/input.js
* 2023-05-accessors--to-es2015/static-public/input.js
* 2023-05-accessors--to-es2015/undecorated-private/input.js
* 2023-05-accessors--to-es2015/undecorated-public/input.js
* 2023-05-accessors--to-es2015/undecorated-static-private/input.js
* 2023-05-accessors--to-es2015/undecorated-static-public/input.js
* 2023-05-assumption-constantSuper/super-in-nested-constructor-expression/input.js
* 2023-05-assumption-constantSuper/super-in-private-accessor/input.js
* 2023-05-assumption-constantSuper/super-in-private-method/input.js
* 2023-05-classes/decorator-access-modified-fields/input.js
* 2023-05-classes/decorator-access-modified-methods/input.js
* 2023-05-classes/expressions/input.js
* 2023-05-classes/expressions-static-blocks/input.js
* 2023-05-classes/inheritance/input.js
* 2023-05-classes/initializers/input.js
* 2023-05-classes/replacement/input.js
* 2023-05-classes/replacement-static-installed-on-correct-class/input.js
* 2023-05-classes/replacement-static-this/input.js
* 2023-05-classes/replacement-with-expr/input.js
* 2023-05-classes--to-es2015/decorator-access-modified-fields/input.js
* 2023-05-classes--to-es2015/decorator-access-modified-methods/input.js
* 2023-05-classes--to-es2015/expressions/input.js
* 2023-05-classes--to-es2015/expressions-static-blocks/input.js
* 2023-05-classes--to-es2015/inheritance/input.js
* 2023-05-classes--to-es2015/initializers/input.js
* 2023-05-classes--to-es2015/replacement/input.js
* 2023-05-classes--to-es2015/replacement-static-installed-on-correct-class/input.js
* 2023-05-classes--to-es2015/replacement-static-this/input.js
* 2023-05-classes--to-es2015/replacement-with-expr/input.js
* 2023-05-duplicated-keys/computed-keys-same-ast/input.js
* 2023-05-duplicated-keys/computed-keys-same-value/input.js
* 2023-05-duplicated-keys/method-and-field/input.js
* 2023-05-duplicated-keys/methods-with-same-key/input.js
* 2023-05-duplicated-keys--to-es2015/computed-keys-same-ast/input.js
* 2023-05-duplicated-keys--to-es2015/computed-keys-same-value/input.js
* 2023-05-duplicated-keys--to-es2015/method-and-field/input.js
* 2023-05-duplicated-keys--to-es2015/methods-with-same-key/input.js
* 2023-05-exported/default-anonymous/input.mjs
* 2023-05-exported/default-named/input.mjs
* 2023-05-exported/member-decorator/input.mjs
* 2023-05-exported/named/input.mjs
* 2023-05-fields/context-name/input.js
* 2023-05-fields/private/input.js
* 2023-05-fields/public/input.js
* 2023-05-fields/static-private/input.js
* 2023-05-fields/static-public/input.js
* 2023-05-fields--to-es2015/context-name/input.js
* 2023-05-fields--to-es2015/private/input.js
* 2023-05-fields--to-es2015/public/input.js
* 2023-05-fields--to-es2015/static-private/input.js
* 2023-05-fields--to-es2015/static-public/input.js
* 2023-05-getters/context-name/input.js
* 2023-05-getters/private/input.js
* 2023-05-getters/public/input.js
* 2023-05-getters/static-private/input.js
* 2023-05-getters/static-public/input.js
* 2023-05-getters--to-es2015/context-name/input.js
* 2023-05-getters--to-es2015/private/input.js
* 2023-05-getters--to-es2015/public/input.js
* 2023-05-getters--to-es2015/static-private/input.js
* 2023-05-getters--to-es2015/static-public/input.js
* 2023-05-getters-and-setters/private/input.js
* 2023-05-getters-and-setters/public/input.js
* 2023-05-getters-and-setters/static-private/input.js
* 2023-05-getters-and-setters/static-public/input.js
* 2023-05-getters-and-setters--to-es2015/private/input.js
* 2023-05-getters-and-setters--to-es2015/public/input.js
* 2023-05-getters-and-setters--to-es2015/static-private/input.js
* 2023-05-getters-and-setters--to-es2015/static-public/input.js
* 2023-05-methods/context-name/input.js
* 2023-05-methods/private/input.js
* 2023-05-methods/public/input.js
* 2023-05-methods/static-private/input.js
* 2023-05-methods/static-public/input.js
* 2023-05-methods--to-es2015/context-name/input.js
* 2023-05-methods--to-es2015/private/input.js
* 2023-05-methods--to-es2015/public/input.js
* 2023-05-methods--to-es2015/static-private/input.js
* 2023-05-methods--to-es2015/static-public/input.js
* 2023-05-misc/all-decorators/input.js
* 2023-05-misc/initProto-existing-derived-constructor/input.js
* 2023-05-misc/initProto-existing-derived-constructor-multiple-super/input.js
* 2023-05-misc/private-keys-in-enclosing-class/input.js
* 2023-05-misc/setting-private-method/input.js
* 2023-05-misc/setting-private-method-in-body/input.js
* 2023-05-misc/setting-private-method-via-array-pattern/input.js
* 2023-05-misc/setting-private-method-via-for-of/input.js
* 2023-05-misc/setting-private-method-via-object-pattern/input.js
* 2023-05-misc/setting-private-method-via-rest/input.js
* 2023-05-misc/setting-private-method-via-update/input.js
* 2023-05-misc/setting-shadowed-private-method-valid/input.js
* 2023-05-misc/super-in-decorator/input.js
* 2023-05-misc/super-in-nested-constructor-expression/input.js
* 2023-05-misc/super-in-private-accessor/input.js
* 2023-05-misc/super-in-private-method/input.js
* 2023-05-misc/this/input.js
* 2023-05-misc/valid-expression-formats/input.js
* 2023-05-misc--to-es2015/initProto-existing-derived-constructor/input.js
* 2023-05-misc--to-es2015/super-in-decorator/input.js
* 2023-05-misc--to-es2015/this/input.js
* 2023-05-misc--to-es2015/valid-expression-formats/input.js
* 2023-05-ordering/initializers-and-static-blocks/input.js
* 2023-05-ordering--to-es2015/initializers-and-static-blocks/input.js
* 2023-05-setters/context-name/input.js
* 2023-05-setters/private/input.js
* 2023-05-setters/public/input.js
* 2023-05-setters/static-private/input.js
* 2023-05-setters/static-public/input.js
* 2023-05-setters--to-es2015/context-name/input.js
* 2023-05-setters--to-es2015/private/input.js
* 2023-05-setters--to-es2015/public/input.js
* 2023-05-setters--to-es2015/static-private/input.js
* 2023-05-setters--to-es2015/static-public/input.js
* legacy-decl-to-expression/class-decorators/input.mjs
* legacy-decl-to-expression/method-decorators/input.mjs
* legacy-decl-to-expression/no-decorators/input.mjs
* legacy-regression/10264/input.mjs
* legacy-regression/7030/input.js
* legacy-regression/8041/input.mjs
* legacy-regression/8559/input.mjs

View file

@ -1,4 +1,4 @@
Passed: 386/454 Passed: 428/649
# All Passed: # All Passed:
* babel-plugin-transform-class-static-block * babel-plugin-transform-class-static-block
@ -102,3 +102,158 @@ Passed: 386/454
* general/class-properties/exec.js * general/class-properties/exec.js
* general/class-properties-loose/exec.js * general/class-properties-loose/exec.js
# babel-plugin-proposal-decorators (42/195)
* 2021-12-fields/context-name/exec.js
* 2021-12-fields--to-es2015/context-name/exec.js
* 2021-12-getters/context-name/exec.js
* 2021-12-getters--to-es2015/context-name/exec.js
* 2021-12-methods/context-name/exec.js
* 2021-12-methods--to-es2015/context-name/exec.js
* 2021-12-misc/decorator-evaluation-scope/exec.js
* 2021-12-misc/initProto-existing-derived-constructor/exec.js
* 2021-12-misc--to-es2015/accessor-old-initializer-prop-support/exec.js
* 2021-12-setters/context-name/exec.js
* 2021-12-setters--to-es2015/context-name/exec.js
* 2022-03-classes/decorator-access-modified-fields/exec.js
* 2022-03-classes/decorator-access-modified-methods/exec.js
* 2022-03-fields/context-name/exec.js
* 2022-03-fields--to-es2015/context-name/exec.js
* 2022-03-getters/context-name/exec.js
* 2022-03-getters--to-es2015/context-name/exec.js
* 2022-03-methods/context-name/exec.js
* 2022-03-methods--to-es2015/context-name/exec.js
* 2022-03-misc/decorator-evaluation-scope/exec.js
* 2022-03-misc/initProto-existing-derived-constructor/exec.js
* 2022-03-misc/initializer-property-ignored/exec.js
* 2022-03-setters/context-name/exec.js
* 2022-03-setters--to-es2015/context-name/exec.js
* 2023-01-classes/decorator-access-modified-fields/exec.js
* 2023-01-classes/decorator-access-modified-methods/exec.js
* 2023-01-fields/context-name/exec.js
* 2023-01-fields--to-es2015/context-name/exec.js
* 2023-01-getters/context-name/exec.js
* 2023-01-getters--to-es2015/context-name/exec.js
* 2023-01-methods/context-name/exec.js
* 2023-01-methods--to-es2015/context-name/exec.js
* 2023-01-misc/decorator-evaluation-scope/exec.js
* 2023-01-misc/initProto-existing-derived-constructor/exec.js
* 2023-01-misc/initializer-property-ignored/exec.js
* 2023-01-setters/context-name/exec.js
* 2023-01-setters--to-es2015/context-name/exec.js
* 2023-05-accessors--to-es2015/private/exec.js
* 2023-05-accessors--to-es2015/public/exec.js
* 2023-05-accessors--to-es2015/undecorated-private/exec.js
* 2023-05-accessors--to-es2015/undecorated-public/exec.js
* 2023-05-classes/ctx/exec.js
* 2023-05-classes/decorator-access-modified-classes/exec.js
* 2023-05-classes/decorator-access-modified-fields/exec.js
* 2023-05-classes/decorator-access-modified-methods/exec.js
* 2023-05-classes--to-es2015/ctx/exec.js
* 2023-05-classes--to-es2015/decorator-access-modified-classes/exec.js
* 2023-05-classes--to-es2015/decorator-access-modified-fields/exec.js
* 2023-05-classes--to-es2015/decorator-access-modified-methods/exec.js
* 2023-05-classes--to-es2015/inheritance/exec.js
* 2023-05-classes--to-es2015/initializers/exec.js
* 2023-05-classes--to-es2015/replacement/exec.js
* 2023-05-classes--to-es2015/replacement-static-installed-on-correct-class/exec.js
* 2023-05-classes--to-es2015/replacement-static-this/exec.js
* 2023-05-classes--to-es2015/replacement-with-expr/exec.js
* 2023-05-duplicated-keys--to-es2015/computed-keys-same-ast/exec.js
* 2023-05-duplicated-keys--to-es2015/computed-keys-same-value/exec.js
* 2023-05-duplicated-keys--to-es2015/method-and-field/exec.js
* 2023-05-duplicated-keys--to-es2015/methods-with-same-key/exec.js
* 2023-05-fields/context-name/exec.js
* 2023-05-fields--to-es2015/context-name/exec.js
* 2023-05-fields--to-es2015/private/exec.js
* 2023-05-fields--to-es2015/public/exec.js
* 2023-05-fields--to-es2015/static-private/exec.js
* 2023-05-fields--to-es2015/static-public/exec.js
* 2023-05-getters/context-name/exec.js
* 2023-05-getters--to-es2015/context-name/exec.js
* 2023-05-getters--to-es2015/private/exec.js
* 2023-05-getters--to-es2015/public/exec.js
* 2023-05-getters--to-es2015/static-private/exec.js
* 2023-05-getters--to-es2015/static-public/exec.js
* 2023-05-getters-and-setters--to-es2015/private/exec.js
* 2023-05-getters-and-setters--to-es2015/public/exec.js
* 2023-05-getters-and-setters--to-es2015/static-private/exec.js
* 2023-05-getters-and-setters--to-es2015/static-public/exec.js
* 2023-05-methods/context-name/exec.js
* 2023-05-methods--to-es2015/context-name/exec.js
* 2023-05-methods--to-es2015/private/exec.js
* 2023-05-methods--to-es2015/private-with-initializers/exec.js
* 2023-05-methods--to-es2015/public/exec.js
* 2023-05-methods--to-es2015/public-with-initializers/exec.js
* 2023-05-methods--to-es2015/static-private/exec.js
* 2023-05-methods--to-es2015/static-private-with-initializers/exec.js
* 2023-05-methods--to-es2015/static-public/exec.js
* 2023-05-methods--to-es2015/static-public-with-initializers/exec.js
* 2023-05-misc/class-tdz-during-decorators/exec.js
* 2023-05-misc/decorator-evaluation-scope/exec.js
* 2023-05-misc/initProto-existing-derived-constructor/exec.js
* 2023-05-misc/initializer-property-ignored/exec.js
* 2023-05-misc/this/exec.js
* 2023-05-misc--to-es2015/class-and-method-decorators/exec.js
* 2023-05-misc--to-es2015/class-and-property-decorators/exec.js
* 2023-05-misc--to-es2015/decorator-evaluation-scope/exec.js
* 2023-05-misc--to-es2015/initProto-existing-derived-constructor/exec.js
* 2023-05-misc--to-es2015/initializer-property-ignored/exec.js
* 2023-05-misc--to-es2015/initializer-timing/exec.js
* 2023-05-misc--to-es2015/leaked-context-addInitializer/exec.js
* 2023-05-misc--to-es2015/leaked-context-addInitializer-throw/exec.js
* 2023-05-misc--to-es2015/this/exec.js
* 2023-05-ordering/accessor-init-and-set-consistent/exec.js
* 2023-05-ordering/accessor-initializers-fields/exec.js
* 2023-05-ordering/accessor-initializers-setters/exec.js
* 2023-05-ordering/accessor-method-initializers/exec.js
* 2023-05-ordering/accessor-static-method-initializers/exec.js
* 2023-05-ordering/field/exec.js
* 2023-05-ordering/field-initializers-after-methods/exec.js
* 2023-05-ordering/static-field-initializers-after-methods/exec.js
* 2023-05-ordering--to-es2015/accessor-initializers-fields/exec.js
* 2023-05-ordering--to-es2015/accessor-initializers-setters/exec.js
* 2023-05-ordering--to-es2015/accessor-method-initializers/exec.js
* 2023-05-ordering--to-es2015/accessor-static-method-initializers/exec.js
* 2023-05-ordering--to-es2015/field/exec.js
* 2023-05-ordering--to-es2015/field-initializers-after-methods/exec.js
* 2023-05-ordering--to-es2015/static-field-initializers-after-methods/exec.js
* 2023-05-runtime-errors--to-es2015/invalid-accessor-decorator-return/exec.js
* 2023-05-runtime-errors--to-es2015/invalid-add-initializer/exec.js
* 2023-05-runtime-errors--to-es2015/invalid-class-decorator-return/exec.js
* 2023-05-runtime-errors--to-es2015/invalid-field-decorator-return/exec.js
* 2023-05-runtime-errors--to-es2015/invalid-getter-decorator-return/exec.js
* 2023-05-runtime-errors--to-es2015/invalid-method-decorator-return/exec.js
* 2023-05-runtime-errors--to-es2015/invalid-setter-decorator-return/exec.js
* 2023-05-setters/context-name/exec.js
* 2023-05-setters--to-es2015/context-name/exec.js
* 2023-05-setters--to-es2015/private/exec.js
* 2023-05-setters--to-es2015/public/exec.js
* 2023-05-setters--to-es2015/static-private/exec.js
* 2023-05-setters--to-es2015/static-public/exec.js
* legacy-class-export-default/exec.mjs
* legacy-class-ordering/order/exec.js
* legacy-class-ordering/reverse-order/exec.js
* legacy-class-prototype-methods/mutate-descriptor/exec.js
* legacy-class-prototype-methods/numeric-props/exec.js
* legacy-class-prototype-methods/return-descriptor/exec.js
* legacy-class-prototype-methods/string-props/exec.js
* legacy-class-prototype-properties/child-classes-properties/exec.js
* legacy-class-prototype-properties/mutate-descriptor/exec.js
* legacy-class-prototype-properties/mutate-initialzer/exec.js
* legacy-class-prototype-properties/properties-without-initializer/exec.js
* legacy-class-prototype-properties/return-descriptor/exec.js
* legacy-class-prototype-properties/string-literal-properties/exec.js
* legacy-class-static-methods/mutate-descriptor/exec.js
* legacy-class-static-methods/numeric-props/exec.js
* legacy-class-static-methods/return-descriptor/exec.js
* legacy-class-static-methods/string-props/exec.js
* legacy-class-static-properties/mutate-descriptor/exec.js
* legacy-class-static-properties/mutate-initialzer/exec.js
* legacy-class-static-properties/properties-without-initializer/exec.js
* legacy-class-static-properties/return-descriptor/exec.js
* legacy-regression/8512/exec.js
* metadata/class/exec.js
* metadata/element/exec.js
* metadata/subclass-no-super-decorators/exec.js
* metadata/subclass-super-decorators/exec.js

View file

@ -89,6 +89,8 @@ const CASES: &[&str] = &[
"babel-plugin-transform-typescript", "babel-plugin-transform-typescript",
// React // React
"babel-plugin-transform-react-jsx", "babel-plugin-transform-react-jsx",
// Proposal
"babel-plugin-proposal-decorators",
]; ];
const EXCLUDE_TESTS: &[&str] = &["babel-plugin-transform-typescript/test/fixtures/enum"]; const EXCLUDE_TESTS: &[&str] = &["babel-plugin-transform-typescript/test/fixtures/enum"];

View file

@ -11,8 +11,8 @@ use oxc_semantic::SemanticBuilder;
use oxc_span::{SourceType, VALID_EXTENSIONS}; use oxc_span::{SourceType, VALID_EXTENSIONS};
use oxc_tasks_common::{normalize_path, print_diff_in_terminal, BabelOptions}; use oxc_tasks_common::{normalize_path, print_diff_in_terminal, BabelOptions};
use oxc_transformer::{ use oxc_transformer::{
ArrowFunctionsOptions, NullishCoalescingOperatorOptions, ReactJsxOptions, TransformOptions, ArrowFunctionsOptions, DecoratorsOptions, NullishCoalescingOperatorOptions, ReactJsxOptions,
TransformTarget, Transformer, TypescriptOptions, TransformOptions, TransformTarget, Transformer, TypescriptOptions,
}; };
use serde::de::DeserializeOwned; use serde::de::DeserializeOwned;
use serde_json::Value; use serde_json::Value;
@ -89,6 +89,9 @@ pub trait TestCase {
TransformOptions { TransformOptions {
target: TransformTarget::ESNext, target: TransformTarget::ESNext,
babel_8_breaking: options.babel_8_breaking, babel_8_breaking: options.babel_8_breaking,
decorators: options
.get_plugin("proposal-decorators")
.map(get_options::<DecoratorsOptions>),
react_jsx: options react_jsx: options
.get_plugin("transform-react-jsx") .get_plugin("transform-react-jsx")
.map(get_options::<ReactJsxOptions>), .map(get_options::<ReactJsxOptions>),