Skip to content

Commit

Permalink
fix(es/decorators): Fix init order of 2022-03 impl (#9760)
Browse files Browse the repository at this point in the history
**Description:**
Fix the order of initialization for 2022-03 decorators. TBH the [proposal](https://github.com/tc39/proposal-decorators) isn't very clear on how `init` is executed for [auto-accessor](https://github.com/tc39/proposal-decorators) decorator


**Related issue:**

 - Closes #9669
  • Loading branch information
jzhan-canva authored Jan 15, 2025
1 parent 2d6f9a5 commit 751a310
Show file tree
Hide file tree
Showing 21 changed files with 74 additions and 102 deletions.
6 changes: 6 additions & 0 deletions .changeset/tame-hairs-applaud.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
swc_ecma_transforms_proposal: patch
swc_core: patch
---

Fix 2022-03 decorators initialization order
3 changes: 1 addition & 2 deletions crates/swc/tests/fixture/issues-7xxx/7220/1/output/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ var TestClass = /*#__PURE__*/ function() {
"use strict";
function TestClass() {
_class_call_check(this, TestClass);
_define_property(this, "calls", []);
_initProto(this);
_define_property(this, "calls", (_initProto(this), []));
}
_create_class(TestClass, [
{
Expand Down
82 changes: 42 additions & 40 deletions crates/swc_ecma_transforms_proposal/src/decorator_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ struct ClassState {
/// If not empty, `initProto` should be injected to the constructor.
init_proto: Option<Ident>,
init_proto_args: Vec<Option<ExprOrSpread>>,
is_init_proto_called: bool,

init_static: Option<Ident>,
init_static_args: Vec<Option<ExprOrSpread>>,
Expand Down Expand Up @@ -718,10 +717,10 @@ impl DecoratorPass {
}
}
body.visit_mut_with(self);
c.visit_mut_with(self);
c.ident = preserved_class_name.clone();
replace_ident(&mut c.class, c.ident.to_id(), &preserved_class_name);
c.class.body.extend(body);
c.visit_mut_with(self);
c.class.body.push(ClassMember::StaticBlock(StaticBlock {
span: DUMMY_SP,
body: BlockStmt {
Expand Down Expand Up @@ -814,19 +813,48 @@ impl VisitMut for DecoratorPass {

n.visit_mut_children_with(self);

if !self.state.is_init_proto_called {
if let Some(init_proto) = self.state.init_proto.clone() {
if let Some(init_proto) = self.state.init_proto.clone() {
let init_proto_expr = CallExpr {
span: DUMMY_SP,
callee: init_proto.clone().as_callee(),
args: vec![ThisExpr { span: DUMMY_SP }.as_arg()],
..Default::default()
};
let mut proto_inited = false;
for member in n.body.iter_mut() {
if let ClassMember::ClassProp(prop) = member {
if prop.is_static {
continue;
}
if let Some(value) = prop.value.clone() {
prop.value = Some(Expr::from_exprs(vec![
init_proto_expr.clone().into(),
value,
]));

proto_inited = true;
break;
}
} else if let ClassMember::PrivateProp(prop) = member {
if prop.is_static {
continue;
}
if let Some(value) = prop.value.clone() {
prop.value = Some(Expr::from_exprs(vec![
init_proto_expr.clone().into(),
value,
]));

proto_inited = true;
break;
}
}
}

if !proto_inited {
let c = self.ensure_constructor(n);

inject_after_super(
c,
vec![Box::new(Expr::Call(CallExpr {
span: DUMMY_SP,
callee: init_proto.as_callee(),
args: vec![ThisExpr { span: DUMMY_SP }.as_arg()],
..Default::default()
}))],
)
inject_after_super(c, vec![Box::new(init_proto_expr.into())])
}
}

Expand All @@ -847,7 +875,6 @@ impl VisitMut for DecoratorPass {
}

self.state.init_proto = None;
self.state.is_init_proto_called = false;

self.state.extra_stmts = old_stmts;
}
Expand Down Expand Up @@ -1045,29 +1072,6 @@ impl VisitMut for DecoratorPass {
value: if accessor.decorators.is_empty() {
accessor.value
} else {
let init_proto =
if self.state.is_init_proto_called || accessor.is_static {
None
} else {
self.state.is_init_proto_called = true;

let init_proto = self
.state
.init_proto
.get_or_insert_with(|| private_ident!("_initProto"))
.clone();

Some(
CallExpr {
span: DUMMY_SP,
callee: init_proto.clone().as_callee(),
args: vec![ThisExpr { span: DUMMY_SP }.as_arg()],
..Default::default()
}
.into(),
)
};

let init_call = CallExpr {
span: DUMMY_SP,
callee: init.clone().as_callee(),
Expand All @@ -1078,9 +1082,7 @@ impl VisitMut for DecoratorPass {
}
.into();

Some(Expr::from_exprs(
init_proto.into_iter().chain(once(init_call)).collect(),
))
Some(init_call)
},
type_ann: None,
is_static: accessor.is_static,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ var _init_a, _initProto;
const dec = ()=>{};
class Foo {
static{
({ e: [_init_a, _initProto] } = _apply_decs_2203_r(this, [
({ e: [_init_a, _initProto] } = _apply_decs_2203_r(this, [
[
dec,
2,
Expand All @@ -15,10 +15,7 @@ class Foo {
]
], []));
}
constructor(){
_initProto(this);
}
a = _init_a(this, 123);
a = (_initProto(this), _init_a(this, 123));
a() {
return 1;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ class Foo {
get: get_a,
set: void 0
});
_define_property(this, "value", 1);
_initProto(this);
_define_property(this, "value", (_initProto(this), 1));
}
}
({ e: [_call_a, _initProto] } = _apply_decs_2203_r(Foo, [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ class Foo {
return this.value;
}
constructor(){
_define_property(this, "value", 1);
_initProto(this);
_define_property(this, "value", (_initProto(this), 1));
}
}
({ e: [_initProto] } = _apply_decs_2203_r(Foo, [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ class Foo {
get: get_a,
set: set_a
});
_define_property(this, "value", 1);
_initProto(this);
_define_property(this, "value", (_initProto(this), 1));
}
}
({ e: [_call_a, _call_a1, _initProto] } = _apply_decs_2203_r(Foo, [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ class Foo {
this.value = v;
}
constructor(){
_define_property(this, "value", 1);
_initProto(this);
_define_property(this, "value", (_initProto(this), 1));
}
}
({ e: [_initProto] } = _apply_decs_2203_r(Foo, [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,7 @@ class Foo {
]
], []));
}
constructor(){
_initProto(this);
}
value = 1;
value = (_initProto(this), 1);
get #a() {
return _call_a(this);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const dec = ()=>{};
_computedKey = 'b', _computedKey1 = 'b';
class Foo {
static{
({ e: [_initProto] } = _apply_decs_2203_r(this, [
({ e: [_initProto] } = _apply_decs_2203_r(this, [
[
dec,
3,
Expand All @@ -26,10 +26,7 @@ class Foo {
]
], []));
}
constructor(){
_initProto(this);
}
value = 1;
value = (_initProto(this), 1);
get a() {
return this.value;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ var _call_a, _initProto;
const dec = ()=>{};
class Foo {
static{
({ e: [_call_a, _initProto] } = _apply_decs_2203_r(this, [
({ e: [_call_a, _initProto] } = _apply_decs_2203_r(this, [
[
dec,
3,
Expand All @@ -13,10 +13,7 @@ class Foo {
]
], []));
}
constructor(){
_initProto(this);
}
value = 1;
value = (_initProto(this), 1);
get #a() {
return _call_a(this);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const dec = ()=>{};
_computedKey = 'b';
class Foo {
static{
({ e: [_initProto] } = _apply_decs_2203_r(this, [
({ e: [_initProto] } = _apply_decs_2203_r(this, [
[
dec,
3,
Expand All @@ -16,10 +16,7 @@ class Foo {
]
], []));
}
constructor(){
_initProto(this);
}
value = 1;
value = (_initProto(this), 1);
get a() {
return this.value;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ class Foo {
get: get_a,
set: void 0
});
_define_property(this, "value", 1);
_initProto(this);
_define_property(this, "value", (_initProto(this), 1));
}
}
({ e: [_call_a, _initProto] } = _apply_decs_2203_r(Foo, [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ class Foo {
return this.value;
}
constructor(){
_define_property(this, "value", 1);
_initProto(this);
_define_property(this, "value", (_initProto(this), 1));
}
}
({ e: [_initProto] } = _apply_decs_2203_r(Foo, [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,7 @@ class Foo {
]
], []));
}
constructor(){
_initProto(this);
}
value = 1;
value = (_initProto(this), 1);
get #a() {
return _call_a;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const dec = ()=>{};
_computedKey = 'b';
class Foo {
static{
({ e: [_initProto] } = _apply_decs_2203_r(this, [
({ e: [_initProto] } = _apply_decs_2203_r(this, [
[
dec,
2,
Expand All @@ -16,10 +16,7 @@ class Foo {
]
], []));
}
constructor(){
_initProto(this);
}
value = 1;
value = (_initProto(this), 1);
a() {
return this.value;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,11 +144,11 @@ new class extends _identity {
]));
_initStatic(this);
}
a = _init_a(this);
a = (_initProto(this), _init_a(this));
b() {}
get c() {}
set c(v) {}
#___private_d_1 = (_initProto(this), _init_d(this));
#___private_d_1 = _init_d(this);
get d() {
return this.#___private_d_1;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ class Foo {
get: void 0,
set: set_a
});
_define_property(this, "value", 1);
_initProto(this);
_define_property(this, "value", (_initProto(this), 1));
}
}
({ e: [_call_a, _initProto] } = _apply_decs_2203_r(Foo, [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ class Foo {
return this.value = v;
}
constructor(){
_define_property(this, "value", 1);
_initProto(this);
_define_property(this, "value", (_initProto(this), 1));
}
}
({ e: [_initProto] } = _apply_decs_2203_r(Foo, [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,7 @@ class Foo {
]
], []));
}
constructor(){
_initProto(this);
}
value = 1;
value = (_initProto(this), 1);
set #a(v) {
return _call_a(this, v);
}
Expand Down
Loading

0 comments on commit 751a310

Please sign in to comment.