mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 20:32:10 +00:00
feat(transformer/decorators): support method decorator and is not static (#2238)
This commit is contained in:
parent
d0d708295b
commit
ba85b097e0
3 changed files with 89 additions and 9 deletions
|
|
@ -9,7 +9,7 @@ use num_bigint::BigInt;
|
|||
use std::mem;
|
||||
|
||||
use oxc_allocator::{Allocator, Box, String, Vec};
|
||||
use oxc_span::{Atom, GetSpan, SourceType, Span};
|
||||
use oxc_span::{Atom, GetSpan, SourceType, Span, SPAN};
|
||||
use oxc_syntax::{
|
||||
operator::{
|
||||
AssignmentOperator, BinaryOperator, LogicalOperator, UnaryOperator, UpdateOperator,
|
||||
|
|
@ -879,6 +879,23 @@ impl<'a> AstBuilder<'a> {
|
|||
}))
|
||||
}
|
||||
|
||||
pub fn class_constructor(&self, span: Span, value: Box<'a, Function<'a>>) -> ClassElement<'a> {
|
||||
ClassElement::MethodDefinition(self.alloc(MethodDefinition {
|
||||
span,
|
||||
key: self.property_key_expression(self.identifier_reference_expression(
|
||||
IdentifierReference::new(SPAN, "constructor".into()),
|
||||
)),
|
||||
kind: MethodDefinitionKind::Constructor,
|
||||
value,
|
||||
computed: false,
|
||||
r#static: false,
|
||||
r#override: false,
|
||||
optional: false,
|
||||
accessibility: None,
|
||||
decorators: self.new_vec(),
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn accessor_property(
|
||||
&self,
|
||||
span: Span,
|
||||
|
|
|
|||
|
|
@ -117,6 +117,19 @@ impl<'a> Decorators<'a> {
|
|||
Atom::from(format!("_{name}{}", if *uid == 1 { String::new() } else { uid.to_string() }))
|
||||
}
|
||||
|
||||
pub fn get_call_with_this(&self, name: Atom) -> Statement<'a> {
|
||||
self.ast.expression_statement(
|
||||
SPAN,
|
||||
self.ast.call_expression(
|
||||
SPAN,
|
||||
self.ast.identifier_reference_expression(IdentifierReference::new(SPAN, name)),
|
||||
self.ast.new_vec_single(Argument::Expression(self.ast.this_expression(SPAN))),
|
||||
false,
|
||||
None,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn transform_program(&mut self, program: &mut Program<'a>) {
|
||||
program.body.splice(0..0, self.top_statements.drain(..));
|
||||
program.body.append(&mut self.bottom_statements);
|
||||
|
|
@ -378,7 +391,9 @@ impl<'a> Decorators<'a> {
|
|||
ast.array_expression(SPAN, decorator_elements, None)
|
||||
};
|
||||
|
||||
let mut is_proto = false;
|
||||
let mut is_static = false;
|
||||
|
||||
class.body.body.iter_mut().for_each(|element| {
|
||||
if !element.has_decorator() {
|
||||
return;
|
||||
|
|
@ -387,6 +402,8 @@ impl<'a> Decorators<'a> {
|
|||
ClassElement::MethodDefinition(def) => {
|
||||
if def.r#static {
|
||||
is_static = def.r#static;
|
||||
} else {
|
||||
is_proto = true;
|
||||
}
|
||||
let name = def.key.name();
|
||||
let mut flag = DecoratorFlags::get_flag_by_kind(def.kind).bits();
|
||||
|
|
@ -454,6 +471,57 @@ impl<'a> Decorators<'a> {
|
|||
}
|
||||
});
|
||||
|
||||
if is_proto {
|
||||
// The class has method decorator and is not static
|
||||
let name = self.get_unique_name(&"initProto".into());
|
||||
e_elements.push(self.get_assignment_target_maybe_default(name.clone()));
|
||||
declarations.push(self.get_variable_declarator(name.clone()));
|
||||
|
||||
// constructor() { _initProto(this) }
|
||||
if let Some(constructor_element) = class.body.body.iter_mut().find(
|
||||
|element| matches!(element, ClassElement::MethodDefinition(def) if def.kind.is_constructor()),
|
||||
) {
|
||||
if let ClassElement::MethodDefinition(def) = constructor_element {
|
||||
if let Some(body) = &mut def.value.body {
|
||||
body.statements.insert(0, self.get_call_with_this(name));
|
||||
}
|
||||
} else {
|
||||
unreachable!();
|
||||
};
|
||||
} else {
|
||||
// if the class has no constructor, insert a empty constructor and call initProto
|
||||
class.body.body.insert(
|
||||
0,
|
||||
self.ast.class_constructor(
|
||||
SPAN,
|
||||
self.ast.function(
|
||||
FunctionType::FunctionExpression,
|
||||
SPAN,
|
||||
None,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
None,
|
||||
self.ast.formal_parameters(
|
||||
SPAN,
|
||||
FormalParameterKind::FormalParameter,
|
||||
self.ast.new_vec(),
|
||||
None,
|
||||
),
|
||||
Some(self.ast.function_body(
|
||||
SPAN,
|
||||
self.ast.new_vec(),
|
||||
self.ast.new_vec_single(self.get_call_with_this(name)),
|
||||
)),
|
||||
None,
|
||||
None,
|
||||
Modifiers::empty(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if is_static {
|
||||
let name = self.get_unique_name(&"initStatic".into());
|
||||
e_elements.push(self.get_assignment_target_maybe_default(name.clone()));
|
||||
|
|
@ -478,7 +546,7 @@ impl<'a> Decorators<'a> {
|
|||
}
|
||||
|
||||
{
|
||||
// call babelHelpers.applyDecs2305
|
||||
// call babelHelpers.applyDecs2305
|
||||
let callee = self.ast.static_member_expression(
|
||||
SPAN,
|
||||
self.ast.identifier_reference_expression(IdentifierReference::new(
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
Passed: 335/1369
|
||||
Passed: 340/1369
|
||||
|
||||
# All Passed:
|
||||
* babel-plugin-transform-numeric-separator
|
||||
|
|
@ -911,7 +911,7 @@ Passed: 335/1369
|
|||
* spread-transform/transform-to-babel-extend/input.js
|
||||
* spread-transform/transform-to-object-assign/input.js
|
||||
|
||||
# babel-plugin-proposal-decorators (11/190)
|
||||
# babel-plugin-proposal-decorators (16/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
|
||||
|
|
@ -1013,7 +1013,6 @@ Passed: 335/1369
|
|||
* 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
|
||||
|
|
@ -1030,7 +1029,6 @@ Passed: 335/1369
|
|||
* 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--to-es2015/context-name/input.js
|
||||
* 2023-05-getters--to-es2015/private/input.js
|
||||
|
|
@ -1038,7 +1036,6 @@ Passed: 335/1369
|
|||
* 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--to-es2015/private/input.js
|
||||
* 2023-05-getters-and-setters--to-es2015/public/input.js
|
||||
|
|
@ -1046,7 +1043,6 @@ Passed: 335/1369
|
|||
* 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--to-es2015/context-name/input.js
|
||||
* 2023-05-methods--to-es2015/private/input.js
|
||||
|
|
@ -1079,7 +1075,6 @@ Passed: 335/1369
|
|||
* 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--to-es2015/context-name/input.js
|
||||
* 2023-05-setters--to-es2015/private/input.js
|
||||
|
|
|
|||
Loading…
Reference in a new issue