mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 20:32:10 +00:00
feat(transformer/decorators): support transform member decorators (#2171)
This commit is contained in:
parent
fc1592bc97
commit
e5719e9b4d
3 changed files with 330 additions and 139 deletions
|
|
@ -473,6 +473,14 @@ impl<'a> PropertyKey<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn name(&self) -> Option<Atom> {
|
||||||
|
if self.is_private_identifier() {
|
||||||
|
self.private_name()
|
||||||
|
} else {
|
||||||
|
self.static_name()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_specific_id(&self, name: &str) -> bool {
|
pub fn is_specific_id(&self, name: &str) -> bool {
|
||||||
match self {
|
match self {
|
||||||
PropertyKey::Identifier(ident) => ident.name == name,
|
PropertyKey::Identifier(ident) => ident.name == name,
|
||||||
|
|
@ -1901,6 +1909,22 @@ impl<'a> ClassElement<'a> {
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn has_decorator(&self) -> bool {
|
||||||
|
#[allow(clippy::match_same_arms)]
|
||||||
|
match self {
|
||||||
|
Self::TSIndexSignature(_)
|
||||||
|
| Self::TSAbstractMethodDefinition(_)
|
||||||
|
| Self::TSAbstractPropertyDefinition(_) => false,
|
||||||
|
Self::MethodDefinition(method) => !method.decorators.is_empty(),
|
||||||
|
Self::PropertyDefinition(property) => !property.decorators.is_empty(),
|
||||||
|
Self::AccessorProperty(_) => {
|
||||||
|
// TODO: AccessorProperty doesn't have decorators property
|
||||||
|
false
|
||||||
|
}
|
||||||
|
Self::StaticBlock(_) => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Hash)]
|
#[derive(Debug, Hash)]
|
||||||
|
|
|
||||||
|
|
@ -63,18 +63,28 @@ impl<'a> Decorators<'a> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_variable_declarator(&self, name: &str) -> VariableDeclarator<'a> {
|
pub fn get_variable_declarator(&self, name: Atom) -> VariableDeclarator<'a> {
|
||||||
self.ast.variable_declarator(
|
self.ast.variable_declarator(
|
||||||
SPAN,
|
SPAN,
|
||||||
VariableDeclarationKind::Var,
|
VariableDeclarationKind::Var,
|
||||||
BindingPattern::new_with_kind(
|
BindingPattern::new_with_kind(
|
||||||
self.ast.binding_pattern_identifier(BindingIdentifier::new(SPAN, name.into())),
|
self.ast.binding_pattern_identifier(BindingIdentifier::new(SPAN, name)),
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::unnecessary_wraps)]
|
||||||
|
pub fn get_assignment_target_maybe_default(
|
||||||
|
&self,
|
||||||
|
name: Atom,
|
||||||
|
) -> Option<AssignmentTargetMaybeDefault<'a>> {
|
||||||
|
Some(AssignmentTargetMaybeDefault::AssignmentTarget(
|
||||||
|
self.ast.simple_assignment_target_identifier(IdentifierReference::new(SPAN, name)),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: use generate_uid of scope to generate unique name
|
// TODO: use generate_uid of scope to generate unique name
|
||||||
pub fn get_unique_name(&mut self, name: &Atom) -> Atom {
|
pub fn get_unique_name(&mut self, name: &Atom) -> Atom {
|
||||||
let uid = self.uid_map.entry(name.clone()).or_insert(0);
|
let uid = self.uid_map.entry(name.clone()).or_insert(0);
|
||||||
|
|
@ -96,40 +106,54 @@ impl<'a> Decorators<'a> {
|
||||||
|| None,
|
|| None,
|
||||||
|declaration| {
|
|declaration| {
|
||||||
if let Declaration::ClassDeclaration(class) = declaration {
|
if let Declaration::ClassDeclaration(class) = declaration {
|
||||||
if class.decorators.is_empty() {
|
if !Self::can_transform(class) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let class_name = class
|
let has_decorator = !class.decorators.is_empty();
|
||||||
.id
|
let class_name = if has_decorator {
|
||||||
.clone()
|
class
|
||||||
.map(|id| self.get_unique_name(&id.name))
|
.id
|
||||||
.or_else(|| Some(self.get_unique_name(&"class".into())));
|
.clone()
|
||||||
|
.map(|id| self.get_unique_name(&id.name))
|
||||||
|
.or_else(|| Some(self.get_unique_name(&"class".into())))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
self.bottom_statements.push(self.ast.module_declaration(
|
if has_decorator {
|
||||||
ModuleDeclaration::ExportNamedDeclaration(
|
self.bottom_statements.push(self.ast.module_declaration(
|
||||||
self.ast.export_named_declaration(
|
ModuleDeclaration::ExportNamedDeclaration(
|
||||||
SPAN,
|
self.ast.export_named_declaration(
|
||||||
None,
|
|
||||||
self.ast.new_vec_single(ExportSpecifier::new(
|
|
||||||
SPAN,
|
SPAN,
|
||||||
ModuleExportName::Identifier(IdentifierName::new(
|
None,
|
||||||
|
self.ast.new_vec_single(ExportSpecifier::new(
|
||||||
SPAN,
|
SPAN,
|
||||||
class_name.clone().unwrap(),
|
ModuleExportName::Identifier(
|
||||||
|
IdentifierName::new(
|
||||||
|
SPAN,
|
||||||
|
class_name.clone().unwrap(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ModuleExportName::Identifier(
|
||||||
|
IdentifierName::new(
|
||||||
|
SPAN,
|
||||||
|
class.id.clone().unwrap().name,
|
||||||
|
),
|
||||||
|
),
|
||||||
)),
|
)),
|
||||||
ModuleExportName::Identifier(IdentifierName::new(
|
None,
|
||||||
SPAN,
|
ImportOrExportKind::Value,
|
||||||
class.id.clone().unwrap().name,
|
),
|
||||||
)),
|
|
||||||
)),
|
|
||||||
None,
|
|
||||||
ImportOrExportKind::Value,
|
|
||||||
),
|
),
|
||||||
),
|
));
|
||||||
));
|
}
|
||||||
|
|
||||||
return Some(Statement::Declaration(
|
let new_declaration = self.transform_class(class, class_name);
|
||||||
self.transform_class(class, class_name),
|
if has_decorator {
|
||||||
));
|
return Some(Statement::Declaration(new_declaration));
|
||||||
|
}
|
||||||
|
*declaration = new_declaration;
|
||||||
|
return None;
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
},
|
},
|
||||||
|
|
@ -139,36 +163,43 @@ impl<'a> Decorators<'a> {
|
||||||
if let ExportDefaultDeclarationKind::ClassDeclaration(class) =
|
if let ExportDefaultDeclarationKind::ClassDeclaration(class) =
|
||||||
&mut export.declaration
|
&mut export.declaration
|
||||||
{
|
{
|
||||||
if class.decorators.is_empty() {
|
if !Self::can_transform(class) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let class_name = class
|
let class_has_decorator = !class.decorators.is_empty();
|
||||||
.id
|
let class_name = if class_has_decorator {
|
||||||
.clone()
|
class
|
||||||
.map(|id| self.get_unique_name(&id.name))
|
.id
|
||||||
.or_else(|| Some(self.get_unique_name(&"class".into())));
|
.clone()
|
||||||
|
.map(|id| self.get_unique_name(&id.name))
|
||||||
|
.or_else(|| Some(self.get_unique_name(&"class".into())))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
self.bottom_statements.push(self.ast.module_declaration(
|
if class_has_decorator {
|
||||||
ModuleDeclaration::ExportNamedDeclaration(
|
self.bottom_statements.push(self.ast.module_declaration(
|
||||||
self.ast.export_named_declaration(
|
ModuleDeclaration::ExportNamedDeclaration(
|
||||||
SPAN,
|
self.ast.export_named_declaration(
|
||||||
None,
|
|
||||||
self.ast.new_vec_single(ExportSpecifier::new(
|
|
||||||
SPAN,
|
SPAN,
|
||||||
ModuleExportName::Identifier(IdentifierName::new(
|
None,
|
||||||
|
self.ast.new_vec_single(ExportSpecifier::new(
|
||||||
SPAN,
|
SPAN,
|
||||||
class_name.clone().unwrap(),
|
ModuleExportName::Identifier(IdentifierName::new(
|
||||||
|
SPAN,
|
||||||
|
class_name.clone().unwrap(),
|
||||||
|
)),
|
||||||
|
ModuleExportName::Identifier(IdentifierName::new(
|
||||||
|
SPAN,
|
||||||
|
"default".into(),
|
||||||
|
)),
|
||||||
)),
|
)),
|
||||||
ModuleExportName::Identifier(IdentifierName::new(
|
None,
|
||||||
SPAN,
|
ImportOrExportKind::Value,
|
||||||
Atom::from("default"),
|
),
|
||||||
)),
|
|
||||||
)),
|
|
||||||
None,
|
|
||||||
ImportOrExportKind::Value,
|
|
||||||
),
|
),
|
||||||
),
|
));
|
||||||
));
|
}
|
||||||
|
|
||||||
Some(Statement::Declaration(self.transform_class(class, class_name)))
|
Some(Statement::Declaration(self.transform_class(class, class_name)))
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -185,10 +216,10 @@ impl<'a> Decorators<'a> {
|
||||||
pub fn transform_declaration(&mut self, decl: &mut Declaration<'a>) {
|
pub fn transform_declaration(&mut self, decl: &mut Declaration<'a>) {
|
||||||
let new_decl = match decl {
|
let new_decl = match decl {
|
||||||
Declaration::ClassDeclaration(class) => {
|
Declaration::ClassDeclaration(class) => {
|
||||||
if class.decorators.is_empty() {
|
if Self::can_transform(class) {
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(self.transform_class(class, None))
|
Some(self.transform_class(class, None))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
|
|
@ -198,6 +229,10 @@ impl<'a> Decorators<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn can_transform(class: &Class<'a>) -> bool {
|
||||||
|
!class.decorators.is_empty() || class.body.body.iter().any(ClassElement::has_decorator)
|
||||||
|
}
|
||||||
|
|
||||||
/// transform version: 2023-05
|
/// transform version: 2023-05
|
||||||
pub fn transform_class(
|
pub fn transform_class(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|
@ -207,37 +242,40 @@ impl<'a> Decorators<'a> {
|
||||||
if self.options.version.is_legacy() {
|
if self.options.version.is_legacy() {
|
||||||
return self.transform_class_legacy(class, class_name);
|
return self.transform_class_legacy(class, class_name);
|
||||||
}
|
}
|
||||||
let class_name = class_name.unwrap_or_else(|| self.get_unique_name(&"class".into()));
|
|
||||||
|
|
||||||
let class_decs_name = self.get_unique_name(&"classDecs".into());
|
let has_decorator = !class.decorators.is_empty();
|
||||||
let init_class_name = self.get_unique_name(&"initClass".into());
|
let has_member_decorator = class.body.body.iter().any(ClassElement::has_decorator);
|
||||||
|
|
||||||
{
|
let mut declarations = self.ast.new_vec();
|
||||||
// insert var _initClass, _classDecs;
|
|
||||||
let mut declarations = self.ast.new_vec_with_capacity(2);
|
|
||||||
declarations.push(self.get_variable_declarator(&init_class_name));
|
|
||||||
declarations.push(self.get_variable_declarator(&class_decs_name));
|
|
||||||
let variable_declaration = self.ast.variable_declaration(
|
|
||||||
SPAN,
|
|
||||||
VariableDeclarationKind::Var,
|
|
||||||
declarations,
|
|
||||||
Modifiers::empty(),
|
|
||||||
);
|
|
||||||
|
|
||||||
self.top_statements.push(Statement::Declaration(Declaration::VariableDeclaration(
|
let mut c_elements = self.ast.new_vec();
|
||||||
variable_declaration,
|
let mut e_elements = self.ast.new_vec();
|
||||||
)));
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
// insert member decorators
|
||||||
// insert _classDecs = decorators;
|
let mut member_decorators_vec = self.ast.new_vec();
|
||||||
let left = self.ast.simple_assignment_target_identifier(IdentifierReference::new(
|
let mut class_decorators_argument =
|
||||||
SPAN,
|
Argument::Expression(self.ast.array_expression(SPAN, self.ast.new_vec(), None));
|
||||||
class_decs_name.clone(),
|
|
||||||
));
|
|
||||||
|
|
||||||
let right =
|
if has_decorator {
|
||||||
self.ast.array_expression(
|
let class_name = class_name.unwrap_or_else(|| self.get_unique_name(&"class".into()));
|
||||||
|
|
||||||
|
let class_decs_name = self.get_unique_name(&"classDecs".into());
|
||||||
|
let init_class_name = self.get_unique_name(&"initClass".into());
|
||||||
|
|
||||||
|
{
|
||||||
|
// insert var _initClass, _classDecs;
|
||||||
|
declarations.push(self.get_variable_declarator(init_class_name.clone()));
|
||||||
|
declarations.push(self.get_variable_declarator(class_decs_name.clone()));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// insert _classDecs = decorators;
|
||||||
|
let left = self.ast.simple_assignment_target_identifier(IdentifierReference::new(
|
||||||
|
SPAN,
|
||||||
|
class_decs_name.clone(),
|
||||||
|
));
|
||||||
|
|
||||||
|
let right = self.ast.array_expression(
|
||||||
SPAN,
|
SPAN,
|
||||||
{
|
{
|
||||||
let mut elements = self.ast.new_vec();
|
let mut elements = self.ast.new_vec();
|
||||||
|
|
@ -248,26 +286,174 @@ impl<'a> Decorators<'a> {
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
let assign_class_decs = self.ast.expression_statement(
|
let assign_class_decs = self.ast.expression_statement(
|
||||||
SPAN,
|
SPAN,
|
||||||
self.ast.assignment_expression(SPAN, AssignmentOperator::Assign, left, right),
|
self.ast.assignment_expression(SPAN, AssignmentOperator::Assign, left, right),
|
||||||
);
|
);
|
||||||
self.top_statements.push(assign_class_decs);
|
self.top_statements.push(assign_class_decs);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
{
|
||||||
|
// insert let _className
|
||||||
|
let declarations =
|
||||||
|
self.ast.new_vec_single(self.get_variable_declarator(class_name.clone()));
|
||||||
|
let variable_declaration = self.ast.variable_declaration(
|
||||||
|
SPAN,
|
||||||
|
VariableDeclarationKind::Let,
|
||||||
|
declarations,
|
||||||
|
Modifiers::empty(),
|
||||||
|
);
|
||||||
|
self.top_statements.push(Statement::Declaration(Declaration::VariableDeclaration(
|
||||||
|
variable_declaration,
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
c_elements.push(self.get_assignment_target_maybe_default(class_name));
|
||||||
|
c_elements.push(self.get_assignment_target_maybe_default(init_class_name.clone()));
|
||||||
|
|
||||||
|
class_decorators_argument =
|
||||||
|
Argument::Expression(self.ast.identifier_reference_expression(
|
||||||
|
IdentifierReference::new(SPAN, class_decs_name),
|
||||||
|
));
|
||||||
|
|
||||||
|
{
|
||||||
|
// call _initClass
|
||||||
|
let callee = self.ast.identifier_reference_expression(IdentifierReference::new(
|
||||||
|
SPAN,
|
||||||
|
init_class_name,
|
||||||
|
));
|
||||||
|
let call_expr =
|
||||||
|
self.ast.call_expression(SPAN, callee, self.ast.new_vec(), false, None);
|
||||||
|
let statements =
|
||||||
|
self.ast.new_vec_single(self.ast.expression_statement(SPAN, call_expr));
|
||||||
|
let static_block = self.ast.static_block(SPAN, statements);
|
||||||
|
class.body.body.insert(0, static_block);
|
||||||
|
}
|
||||||
|
} else if has_member_decorator {
|
||||||
|
let elements: std::vec::Vec<_> = {
|
||||||
|
class
|
||||||
|
.body
|
||||||
|
.body
|
||||||
|
.iter_mut()
|
||||||
|
.enumerate()
|
||||||
|
.filter_map(|(index, element)| match element {
|
||||||
|
ClassElement::MethodDefinition(def) => {
|
||||||
|
if def.decorators.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some((index, def.key.name(), def.computed, &def.decorators))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ClassElement::PropertyDefinition(def) => {
|
||||||
|
if def.decorators.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some((index, def.key.name(), def.computed, &def.decorators))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut replace_elements = HashMap::new();
|
||||||
|
|
||||||
|
for (index, name, computed, decorators) in elements {
|
||||||
|
let init_name = self.get_unique_name(&if computed {
|
||||||
|
"init_computedKey".into()
|
||||||
|
} else {
|
||||||
|
format!("init_{}", name.clone().unwrap()).into()
|
||||||
|
});
|
||||||
|
decorators.iter().for_each(|decorator| {
|
||||||
|
let dec_name = self.get_unique_name(&"dec".into());
|
||||||
|
declarations.push(self.get_variable_declarator(dec_name.clone()));
|
||||||
|
|
||||||
|
let left = self.ast.simple_assignment_target_identifier(
|
||||||
|
IdentifierReference::new(SPAN, dec_name.clone()),
|
||||||
|
);
|
||||||
|
let right = self.ast.copy(&decorator.expression);
|
||||||
|
let dec_expr = self.ast.assignment_expression(
|
||||||
|
SPAN,
|
||||||
|
AssignmentOperator::Assign,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
);
|
||||||
|
e_elements.push(self.get_assignment_target_maybe_default(init_name.clone()));
|
||||||
|
let mut decorator_elements = self.ast.new_vec_with_capacity(2);
|
||||||
|
decorator_elements.push(ArrayExpressionElement::Expression(
|
||||||
|
self.ast.identifier_reference_expression(IdentifierReference::new(
|
||||||
|
SPAN, dec_name,
|
||||||
|
)),
|
||||||
|
));
|
||||||
|
decorator_elements.push(ArrayExpressionElement::Expression(
|
||||||
|
self.ast.literal_number_expression(NumberLiteral::new(
|
||||||
|
SPAN,
|
||||||
|
0f64,
|
||||||
|
"0",
|
||||||
|
oxc_syntax::NumberBase::Decimal,
|
||||||
|
)),
|
||||||
|
));
|
||||||
|
if let Some(name) = name.clone() {
|
||||||
|
decorator_elements.push(ArrayExpressionElement::Expression(
|
||||||
|
self.ast.literal_string_expression(StringLiteral::new(SPAN, name)),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
member_decorators_vec.push(ArrayExpressionElement::Expression(
|
||||||
|
self.ast.array_expression(SPAN, decorator_elements, None),
|
||||||
|
));
|
||||||
|
|
||||||
|
self.top_statements.push(self.ast.expression_statement(SPAN, dec_expr));
|
||||||
|
});
|
||||||
|
|
||||||
|
declarations.push(self.get_variable_declarator(init_name.clone()));
|
||||||
|
|
||||||
|
if let Some(name) = name.clone() {
|
||||||
|
replace_elements.insert(
|
||||||
|
index,
|
||||||
|
self.ast.class_property(
|
||||||
|
SPAN,
|
||||||
|
self.ast
|
||||||
|
.property_key_identifier(IdentifierName::new(SPAN, name.clone())),
|
||||||
|
Some(self.ast.call_expression(
|
||||||
|
SPAN,
|
||||||
|
self.ast.identifier_reference_expression(IdentifierReference::new(
|
||||||
|
SPAN, init_name,
|
||||||
|
)),
|
||||||
|
self.ast.new_vec_single(Argument::Expression(
|
||||||
|
self.ast.this_expression(SPAN),
|
||||||
|
)),
|
||||||
|
false,
|
||||||
|
None,
|
||||||
|
)),
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
self.ast.new_vec(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// replace the element with `name = init_name(this)`
|
||||||
|
for (index, element) in class.body.body.iter_mut().enumerate() {
|
||||||
|
if let Some(new_element) = replace_elements.remove(&index) {
|
||||||
|
*element = new_element;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
// insert let _className
|
// insert all variable_declarator in same variable_declaration
|
||||||
|
|
||||||
let declarations = self.ast.new_vec_single(self.get_variable_declarator(&class_name));
|
|
||||||
let variable_declaration = self.ast.variable_declaration(
|
let variable_declaration = self.ast.variable_declaration(
|
||||||
SPAN,
|
SPAN,
|
||||||
VariableDeclarationKind::Let,
|
VariableDeclarationKind::Var,
|
||||||
declarations,
|
declarations,
|
||||||
Modifiers::empty(),
|
Modifiers::empty(),
|
||||||
);
|
);
|
||||||
self.top_statements.push(Statement::Declaration(Declaration::VariableDeclaration(
|
|
||||||
variable_declaration,
|
self.top_statements.insert(
|
||||||
)));
|
0,
|
||||||
|
Statement::Declaration(Declaration::VariableDeclaration(variable_declaration)),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
@ -281,39 +467,33 @@ impl<'a> Decorators<'a> {
|
||||||
IdentifierName::new(SPAN, "applyDecs2305".into()),
|
IdentifierName::new(SPAN, "applyDecs2305".into()),
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
let mut arguments = self.ast.new_vec();
|
|
||||||
arguments.push(Argument::Expression(self.ast.this_expression(SPAN)));
|
|
||||||
let decs = self.ast.new_vec();
|
|
||||||
arguments.push(Argument::Expression(self.ast.array_expression(SPAN, decs, None)));
|
|
||||||
arguments.push(Argument::Expression(
|
|
||||||
self.ast.identifier_reference_expression(IdentifierReference::new(
|
|
||||||
SPAN,
|
|
||||||
class_decs_name,
|
|
||||||
)),
|
|
||||||
));
|
|
||||||
let object = self.ast.call_expression(SPAN, callee, arguments, false, None);
|
|
||||||
let call_expr = self.ast.static_member_expression(
|
|
||||||
SPAN,
|
|
||||||
object,
|
|
||||||
IdentifierName::new(SPAN, "c".into()),
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut elements = self.ast.new_vec();
|
let mut arguments =
|
||||||
elements.push(Some(AssignmentTargetMaybeDefault::AssignmentTarget(
|
self.ast.new_vec_single(Argument::Expression(self.ast.this_expression(SPAN)));
|
||||||
self.ast.simple_assignment_target_identifier(IdentifierReference::new(
|
arguments.push(Argument::Expression(self.ast.array_expression(
|
||||||
SPAN, class_name,
|
SPAN,
|
||||||
)),
|
member_decorators_vec,
|
||||||
|
None,
|
||||||
)));
|
)));
|
||||||
elements.push(Some(AssignmentTargetMaybeDefault::AssignmentTarget(
|
arguments.push(class_decorators_argument);
|
||||||
self.ast.simple_assignment_target_identifier(IdentifierReference::new(
|
|
||||||
|
let mut call_expr = self.ast.call_expression(SPAN, callee, arguments, false, None);
|
||||||
|
|
||||||
|
if has_decorator && has_decorator == has_member_decorator {
|
||||||
|
// TODO: support this case
|
||||||
|
} else if has_decorator || has_member_decorator {
|
||||||
|
call_expr = self.ast.static_member_expression(
|
||||||
SPAN,
|
SPAN,
|
||||||
init_class_name.clone(),
|
call_expr,
|
||||||
)),
|
IdentifierName::new(SPAN, if has_decorator { "c".into() } else { "e".into() }),
|
||||||
)));
|
false,
|
||||||
let left = self
|
);
|
||||||
.ast
|
}
|
||||||
.array_assignment_target(ArrayAssignmentTarget::new_with_elements(SPAN, elements));
|
|
||||||
|
let left = self.ast.array_assignment_target(ArrayAssignmentTarget::new_with_elements(
|
||||||
|
SPAN,
|
||||||
|
if c_elements.is_empty() { e_elements } else { c_elements },
|
||||||
|
));
|
||||||
let new_expr =
|
let new_expr =
|
||||||
self.ast.assignment_expression(SPAN, AssignmentOperator::Assign, left, call_expr);
|
self.ast.assignment_expression(SPAN, AssignmentOperator::Assign, left, call_expr);
|
||||||
|
|
||||||
|
|
@ -323,18 +503,6 @@ impl<'a> Decorators<'a> {
|
||||||
class.body.body.insert(0, static_block);
|
class.body.body.insert(0, static_block);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
// call _initClass
|
|
||||||
let callee = self
|
|
||||||
.ast
|
|
||||||
.identifier_reference_expression(IdentifierReference::new(SPAN, init_class_name));
|
|
||||||
let call_expr = self.ast.call_expression(SPAN, callee, self.ast.new_vec(), false, None);
|
|
||||||
let statements =
|
|
||||||
self.ast.new_vec_single(self.ast.expression_statement(SPAN, call_expr));
|
|
||||||
let static_block = self.ast.static_block(SPAN, statements);
|
|
||||||
class.body.body.insert(1, static_block);
|
|
||||||
}
|
|
||||||
|
|
||||||
Declaration::ClassDeclaration(self.ast.copy(class))
|
Declaration::ClassDeclaration(self.ast.copy(class))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -361,7 +529,7 @@ impl<'a> Decorators<'a> {
|
||||||
let decl = self.ast.variable_declaration(
|
let decl = self.ast.variable_declaration(
|
||||||
SPAN,
|
SPAN,
|
||||||
VariableDeclarationKind::Var,
|
VariableDeclarationKind::Var,
|
||||||
self.ast.new_vec_single(self.get_variable_declarator(&class_identifier_name)),
|
self.ast.new_vec_single(self.get_variable_declarator(class_identifier_name)),
|
||||||
Modifiers::empty(),
|
Modifiers::empty(),
|
||||||
);
|
);
|
||||||
self.top_statements
|
self.top_statements
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
Passed: 329/1369
|
Passed: 330/1369
|
||||||
|
|
||||||
# All Passed:
|
# All Passed:
|
||||||
* babel-plugin-transform-numeric-separator
|
* babel-plugin-transform-numeric-separator
|
||||||
|
|
@ -911,7 +911,7 @@ Passed: 329/1369
|
||||||
* 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 (5/190)
|
# babel-plugin-proposal-decorators (6/190)
|
||||||
* 2018-09-transformation/async-generator-method/input.js
|
* 2018-09-transformation/async-generator-method/input.js
|
||||||
* 2018-09-transformation/class-decorators-yield-await/input.js
|
* 2018-09-transformation/class-decorators-yield-await/input.js
|
||||||
* 2021-12-accessors/context-name/input.js
|
* 2021-12-accessors/context-name/input.js
|
||||||
|
|
@ -1019,7 +1019,6 @@ Passed: 329/1369
|
||||||
* 2023-05-duplicated-keys--to-es2015/method-and-field/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-duplicated-keys--to-es2015/methods-with-same-key/input.js
|
||||||
* 2023-05-exported/default-named/input.mjs
|
* 2023-05-exported/default-named/input.mjs
|
||||||
* 2023-05-exported/member-decorator/input.mjs
|
|
||||||
* 2023-05-fields/context-name/input.js
|
* 2023-05-fields/context-name/input.js
|
||||||
* 2023-05-fields/private/input.js
|
* 2023-05-fields/private/input.js
|
||||||
* 2023-05-fields/public/input.js
|
* 2023-05-fields/public/input.js
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue