diff --git a/crates/oxc_ast/src/ast/js.rs b/crates/oxc_ast/src/ast/js.rs index 0ee6299d3..9df68cd9f 100644 --- a/crates/oxc_ast/src/ast/js.rs +++ b/crates/oxc_ast/src/ast/js.rs @@ -1443,6 +1443,12 @@ pub struct BindingPattern<'a> { 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)] #[cfg_attr(feature = "serde", derive(Serialize), serde(untagged))] pub enum BindingPatternKind<'a> { diff --git a/crates/oxc_transformer/src/lib.rs b/crates/oxc_transformer/src/lib.rs index b9ed83046..106053b42 100644 --- a/crates/oxc_transformer/src/lib.rs +++ b/crates/oxc_transformer/src/lib.rs @@ -16,6 +16,7 @@ mod es2021; mod es2022; mod es3; mod options; +mod proposals; mod react_jsx; mod regexp; #[cfg(test)] @@ -31,6 +32,7 @@ use oxc_ast::{ast::*, AstBuilder, AstKind, VisitMut}; use oxc_diagnostics::Error; use oxc_semantic::{ScopeFlags, Semantic}; use oxc_span::SourceType; +use proposals::Decorators; use crate::{ context::TransformerCtx, es2015::*, es2016::ExponentiationOperator, @@ -43,12 +45,14 @@ pub use crate::{ es2015::ArrowFunctionsOptions, es2020::NullishCoalescingOperatorOptions, options::{TransformOptions, TransformTarget}, + proposals::DecoratorsOptions, react_jsx::{ReactJsxOptions, ReactJsxRuntime, ReactJsxRuntimeOption}, typescript::TypescriptOptions, }; pub struct Transformer<'a> { ctx: TransformerCtx<'a>, + decorators: Option>, #[allow(unused)] typescript: Option>, react_jsx: Option>, @@ -90,6 +94,7 @@ impl<'a> Transformer<'a> { Self { ctx: ctx.clone(), + decorators: Decorators::new(Rc::clone(&ast), ctx.clone(), &options), // TODO: pass verbatim_module_syntax from user config typescript: source_type.is_typescript().then(|| TypeScript::new(Rc::clone(&ast), ctx.clone(), false, &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.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_scope(); } @@ -202,6 +207,7 @@ impl<'a> VisitMut<'a> for Transformer<'a> { fn visit_declaration(&mut self, decl: &mut Declaration<'a>) { self.visit_declaration_match(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>) { diff --git a/crates/oxc_transformer/src/options.rs b/crates/oxc_transformer/src/options.rs index f572c5fbd..1ade2f5bb 100644 --- a/crates/oxc_transformer/src/options.rs +++ b/crates/oxc_transformer/src/options.rs @@ -2,7 +2,7 @@ use oxc_syntax::assumptions::CompilerAssumptions; use crate::{ es2015::ArrowFunctionsOptions, es2020::NullishCoalescingOperatorOptions, - react_jsx::ReactJsxOptions, typescript::TypescriptOptions, + proposals::DecoratorsOptions, react_jsx::ReactJsxOptions, typescript::TypescriptOptions, }; #[derive(Debug, Default, Clone)] @@ -35,6 +35,8 @@ pub struct TransformOptions { pub babel_8_breaking: Option, pub instanceof: bool, pub new_target: bool, + // Proposal + pub decorators: Option, } /// See diff --git a/crates/oxc_transformer/src/proposals/decorators.rs b/crates/oxc_transformer/src/proposals/decorators.rs new file mode 100644 index 000000000..56d2ae31f --- /dev/null +++ b/crates/oxc_transformer/src/proposals/decorators.rs @@ -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: +/// * +/// * +/// * +pub struct Decorators<'a> { + ast: Rc>, + _ctx: TransformerCtx<'a>, + options: DecoratorsOptions, + // Insert to the top of the program + top_statements: Vec>, +} + +#[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>, + ctx: TransformerCtx<'a>, + options: &TransformOptions, + ) -> Option { + 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(), + )) + } +} diff --git a/crates/oxc_transformer/src/proposals/mod.rs b/crates/oxc_transformer/src/proposals/mod.rs new file mode 100644 index 000000000..0a69a3d45 --- /dev/null +++ b/crates/oxc_transformer/src/proposals/mod.rs @@ -0,0 +1,3 @@ +mod decorators; + +pub use decorators::{Decorators, DecoratorsOptions}; diff --git a/tasks/transform_conformance/babel.snap.md b/tasks/transform_conformance/babel.snap.md index 756442a23..740d17457 100644 --- a/tasks/transform_conformance/babel.snap.md +++ b/tasks/transform_conformance/babel.snap.md @@ -1,4 +1,4 @@ -Passed: 323/1179 +Passed: 325/1369 # All Passed: * babel-plugin-transform-numeric-separator @@ -832,8 +832,7 @@ Passed: 323/1179 * general/function-duplicate-name/input.js * general/object/input.js -# babel-plugin-transform-typescript (92/158) -* class/abstract-class-decorated/input.ts +# babel-plugin-transform-typescript (93/158) * class/abstract-class-decorated-method/input.ts * class/abstract-class-decorated-parameter/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-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 + diff --git a/tasks/transform_conformance/babel_exec.snap.md b/tasks/transform_conformance/babel_exec.snap.md index a2bbd458b..a6f0407fb 100644 --- a/tasks/transform_conformance/babel_exec.snap.md +++ b/tasks/transform_conformance/babel_exec.snap.md @@ -1,4 +1,4 @@ -Passed: 386/454 +Passed: 428/649 # All Passed: * babel-plugin-transform-class-static-block @@ -102,3 +102,158 @@ Passed: 386/454 * general/class-properties/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 + diff --git a/tasks/transform_conformance/src/lib.rs b/tasks/transform_conformance/src/lib.rs index e80f6598e..d318acbfd 100644 --- a/tasks/transform_conformance/src/lib.rs +++ b/tasks/transform_conformance/src/lib.rs @@ -89,6 +89,8 @@ const CASES: &[&str] = &[ "babel-plugin-transform-typescript", // React "babel-plugin-transform-react-jsx", + // Proposal + "babel-plugin-proposal-decorators", ]; const EXCLUDE_TESTS: &[&str] = &["babel-plugin-transform-typescript/test/fixtures/enum"]; diff --git a/tasks/transform_conformance/src/test_case.rs b/tasks/transform_conformance/src/test_case.rs index 691280918..9edccc965 100644 --- a/tasks/transform_conformance/src/test_case.rs +++ b/tasks/transform_conformance/src/test_case.rs @@ -11,8 +11,8 @@ use oxc_semantic::SemanticBuilder; use oxc_span::{SourceType, VALID_EXTENSIONS}; use oxc_tasks_common::{normalize_path, print_diff_in_terminal, BabelOptions}; use oxc_transformer::{ - ArrowFunctionsOptions, NullishCoalescingOperatorOptions, ReactJsxOptions, TransformOptions, - TransformTarget, Transformer, TypescriptOptions, + ArrowFunctionsOptions, DecoratorsOptions, NullishCoalescingOperatorOptions, ReactJsxOptions, + TransformOptions, TransformTarget, Transformer, TypescriptOptions, }; use serde::de::DeserializeOwned; use serde_json::Value; @@ -89,6 +89,9 @@ pub trait TestCase { TransformOptions { target: TransformTarget::ESNext, babel_8_breaking: options.babel_8_breaking, + decorators: options + .get_plugin("proposal-decorators") + .map(get_options::), react_jsx: options .get_plugin("transform-react-jsx") .map(get_options::),