Skip to content

Commit

Permalink
Fix evaluation order of decorators with cached receiver (#16281)
Browse files Browse the repository at this point in the history
* Add failing test

* Fix evaluation order of decorators with cached receiver

* Use one temp var per decorated element

* Use one temp var per class
  • Loading branch information
nicolo-ribaudo committed Feb 18, 2024
1 parent b36fdfc commit 2061eae
Show file tree
Hide file tree
Showing 18 changed files with 111 additions and 91 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -909,6 +909,7 @@ function transformClass(
const decoratedPrivateMethods = new Set<string>();

let classInitLocal: t.Identifier, classIdLocal: t.Identifier;
let decoratorReceiverId: t.Identifier | null = null;

// Memoise the this value `a.b` of decorator member expressions `@a.b.dec`,
type HandleDecoratorExpressionsResult = {
Expand All @@ -929,16 +930,19 @@ function transformClass(
(!process.env.BABEL_8_BREAKING && version === "2023-05")) &&
t.isMemberExpression(expression)
) {
if (
t.isSuper(expression.object) ||
t.isThisExpression(expression.object)
) {
object = memoiseExpression(t.thisExpression(), "obj");
} else {
if (!scopeParent.isStatic(expression.object)) {
expression.object = memoiseExpression(expression.object, "obj");
}
if (t.isSuper(expression.object)) {
object = t.thisExpression();
} else if (scopeParent.isStatic(expression.object)) {
object = t.cloneNode(expression.object);
} else {
decoratorReceiverId ??=
scopeParent.generateDeclaredUidIdentifier("obj");
object = t.assignmentExpression(
"=",
t.cloneNode(decoratorReceiverId),
expression.object,
);
expression.object = t.cloneNode(decoratorReceiverId);
}
}
decoratorsThis.push(object);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
class A extends B {
m() {
var _initProto, _initClass, _obj, _classDecs, _obj2, _m2Decs, _C2;
_obj = this;
_classDecs = [_obj, super.dec1];
_obj2 = this;
_m2Decs = [_obj2, super.dec2];
var _initProto, _initClass, _classDecs, _m2Decs, _C2;
_classDecs = [this, super.dec1];
_m2Decs = [this, super.dec2];
let _C;
class C {
constructor() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
var _initClass, _obj, _obj2, _classDecs, _obj3, _obj4, _xDecs, _init_x, _obj5, _yDecs, _init_y, _A2;
_obj = o1;
_obj2 = o2;
_classDecs = [_obj, _obj.dec, void 0, dec, _obj2, _obj2.dec];
_obj3 = o2;
_obj4 = o3.o;
_xDecs = [_obj3, _obj3.dec, _obj4, _obj4.dec];
_obj5 = o2;
_yDecs = [_obj5, _obj5.dec, void 0, dec];
var _initClass, _obj, _classDecs, _xDecs, _init_x, _yDecs, _init_y, _A2;
_classDecs = [_obj = o1, _obj.dec, void 0, dec, _obj = o2, _obj.dec];
_xDecs = [_obj = o2, _obj.dec, _obj = o3.o, _obj.dec];
_yDecs = [_obj = o2, _obj.dec, void 0, dec];
let _A;
class A {
constructor() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
var _initProto, _initClass, _obj, _classDecs, _obj2, _methodDecs, _Foo2;
var _initProto, _initClass, _obj, _classDecs, _methodDecs, _Foo2;
const dec = () => {};
_obj = array;
_classDecs = [void 0, dec, void 0, call(), void 0, chain.expr(), void 0, arbitrary + expr, _obj, _obj[expr]];
_obj2 = array;
_methodDecs = [void 0, dec, void 0, call(), void 0, chain.expr(), void 0, arbitrary + expr, _obj2, _obj2[expr]];
_classDecs = [void 0, dec, void 0, call(), void 0, chain.expr(), void 0, arbitrary + expr, _obj = array, _obj[expr]];
_methodDecs = [void 0, dec, void 0, call(), void 0, chain.expr(), void 0, arbitrary + expr, _obj = array, _obj[expr]];
let _Foo;
var _a = /*#__PURE__*/new WeakMap();
class Foo {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
class A extends B {
m() {
var _initProto, _initClass, _obj, _classDecs, _obj2, _m2Decs;
_obj = this;
_classDecs = [_obj, super.dec1];
_obj2 = this;
_m2Decs = [_obj2, super.dec2];
var _initProto, _initClass, _classDecs, _m2Decs;
_classDecs = [this, super.dec1];
_m2Decs = [this, super.dec2];
let _C;
class C {
static {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
var _initClass, _obj, _obj2, _classDecs, _obj3, _obj4, _xDecs, _init_x, _obj5, _yDecs, _init_y;
_obj = o1;
_obj2 = o2;
_classDecs = [_obj, _obj.dec, void 0, dec, _obj2, _obj2.dec];
_obj3 = o2;
_obj4 = o3.o;
_xDecs = [_obj3, _obj3.dec, _obj4, _obj4.dec];
_obj5 = o2;
_yDecs = [_obj5, _obj5.dec, void 0, dec];
var _initClass, _obj, _classDecs, _xDecs, _init_x, _yDecs, _init_y;
_classDecs = [_obj = o1, _obj.dec, void 0, dec, _obj = o2, _obj.dec];
_xDecs = [_obj = o2, _obj.dec, _obj = o3.o, _obj.dec];
_yDecs = [_obj = o2, _obj.dec, void 0, dec];
let _A;
class A {
static {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
var _initProto, _initClass, _obj, _classDecs, _obj2, _methodDecs;
var _initProto, _initClass, _obj, _classDecs, _methodDecs;
const dec = () => {};
_obj = array;
_classDecs = [void 0, dec, void 0, call(), void 0, chain.expr(), void 0, arbitrary + expr, _obj, _obj[expr]];
_obj2 = array;
_methodDecs = [void 0, dec, void 0, call(), void 0, chain.expr(), void 0, arbitrary + expr, _obj2, _obj2[expr]];
_classDecs = [void 0, dec, void 0, call(), void 0, chain.expr(), void 0, arbitrary + expr, _obj = array, _obj[expr]];
_methodDecs = [void 0, dec, void 0, call(), void 0, chain.expr(), void 0, arbitrary + expr, _obj = array, _obj[expr]];
let _Foo;
class Foo {
static {
Expand All @@ -15,8 +13,8 @@ class Foo {
#a = void _initProto(this);
method() {}
makeClass() {
var _obj3, _barDecs, _init_bar;
return _obj3 = this, _barDecs = [_obj3, this.#a], class Nested {
var _barDecs, _init_bar;
return _barDecs = [this, this.#a], class Nested {
static {
[_init_bar] = babelHelpers.applyDecs2305(this, [[_barDecs, 16, "bar"]], []).e;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
class A extends B {
m() {
var _initProto, _initClass, _obj, _classDecs, _obj2, _m2Decs, _C2;
_obj = this;
_classDecs = [_obj, super.dec1];
_obj2 = this;
_m2Decs = [_obj2, super.dec2];
var _initProto, _initClass, _classDecs, _m2Decs, _C2;
_classDecs = [this, super.dec1];
_m2Decs = [this, super.dec2];
let _C;
class C {
constructor() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
var _initClass, _obj, _obj2, _classDecs, _obj3, _obj4, _xDecs, _init_x, _init_extra_x, _obj5, _yDecs, _init_y, _init_extra_y, _A2;
_obj = o1;
_obj2 = o2;
_classDecs = [_obj, _obj.dec, void 0, dec, _obj2, _obj2.dec];
_obj3 = o2;
_obj4 = o3.o;
_xDecs = [_obj3, _obj3.dec, _obj4, _obj4.dec];
_obj5 = o2;
_yDecs = [_obj5, _obj5.dec, void 0, dec];
var _initClass, _obj, _classDecs, _xDecs, _init_x, _init_extra_x, _yDecs, _init_y, _init_extra_y, _A2;
_classDecs = [_obj = o1, _obj.dec, void 0, dec, _obj = o2, _obj.dec];
_xDecs = [_obj = o2, _obj.dec, _obj = o3.o, _obj.dec];
_yDecs = [_obj = o2, _obj.dec, void 0, dec];
let _A;
class A {
constructor() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
var _initProto, _initClass, _obj, _classDecs, _obj2, _methodDecs, _Foo2;
var _initProto, _initClass, _obj, _classDecs, _methodDecs, _Foo2;
const dec = () => {};
_obj = array;
_classDecs = [void 0, dec, void 0, call(), void 0, chain.expr(), void 0, arbitrary + expr, _obj, _obj[expr]];
_obj2 = array;
_methodDecs = [void 0, dec, void 0, call(), void 0, chain.expr(), void 0, arbitrary + expr, _obj2, _obj2[expr]];
_classDecs = [void 0, dec, void 0, call(), void 0, chain.expr(), void 0, arbitrary + expr, _obj = array, _obj[expr]];
_methodDecs = [void 0, dec, void 0, call(), void 0, chain.expr(), void 0, arbitrary + expr, _obj = array, _obj[expr]];
let _Foo;
var _a = /*#__PURE__*/new WeakMap();
class Foo {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
class A extends B {
m() {
var _initProto, _initClass, _obj, _classDecs, _obj2, _m2Decs;
_obj = this;
_classDecs = [_obj, super.dec1];
_obj2 = this;
_m2Decs = [_obj2, super.dec2];
var _initProto, _initClass, _classDecs, _m2Decs;
_classDecs = [this, super.dec1];
_m2Decs = [this, super.dec2];
let _C;
class C {
static {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
var _initClass, _obj, _obj2, _obj3, _classDecs, _obj4, _obj5, _obj6, _xDecs, _init_x, _init_extra_x, _obj7, _yDecs, _init_y, _init_extra_y;
_obj = o1;
_obj2 = o2;
_obj3 = o4.o();
_classDecs = [_obj, _obj.dec, void 0, dec, _obj2, _obj2.dec, _obj3, _obj3.dec];
_obj4 = o2;
_obj5 = o3.o;
_obj6 = o4.o();
_xDecs = [_obj4, _obj4.dec, _obj5, _obj5.dec, _obj6, _obj6.dec];
_obj7 = o2;
_yDecs = [_obj7, _obj7.dec, void 0, dec];
var _initClass, _obj, _classDecs, _xDecs, _init_x, _init_extra_x, _yDecs, _init_y, _init_extra_y;
_classDecs = [_obj = o1, _obj.dec, void 0, dec, _obj = o2, _obj.dec, _obj = o4.o(), _obj.dec];
_xDecs = [_obj = o2, _obj.dec, _obj = o3.o, _obj.dec, _obj = o4.o(), _obj.dec];
_yDecs = [_obj = o2, _obj.dec, void 0, dec];
let _A;
class A {
static {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
var _initProto, _initClass, _obj, _classDecs, _obj2, _methodDecs;
var _initProto, _initClass, _obj, _classDecs, _methodDecs;
const dec = () => {};
_obj = array;
_classDecs = [void 0, dec, void 0, call(), void 0, chain.expr(), void 0, arbitrary + expr, _obj, _obj[expr]];
_obj2 = array;
_methodDecs = [void 0, dec, void 0, call(), void 0, chain.expr(), void 0, arbitrary + expr, _obj2, _obj2[expr]];
_classDecs = [void 0, dec, void 0, call(), void 0, chain.expr(), void 0, arbitrary + expr, _obj = array, _obj[expr]];
_methodDecs = [void 0, dec, void 0, call(), void 0, chain.expr(), void 0, arbitrary + expr, _obj = array, _obj[expr]];
let _Foo;
class Foo {
static {
Expand All @@ -15,8 +13,8 @@ class Foo {
#a = void _initProto(this);
method() {}
makeClass() {
var _obj3, _barDecs, _init_bar, _init_extra_bar;
return _obj3 = this, _barDecs = [_obj3, this.#a], class Nested {
var _barDecs, _init_bar, _init_extra_bar;
return _barDecs = [this, this.#a], class Nested {
static {
[_init_bar, _init_extra_bar] = babelHelpers.applyDecs2311(this, [[_barDecs, 16, "bar"]], []).e;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
let result = [];
const fn = () => { result.push(1); return () => {} }
const obj = {
get prop() {
result.push(2);
return {
get foo() { result.push(3); return () => {} }
}
}
};
class A {
@fn()
@obj.prop.foo
method() {}
}

expect(result).toEqual([1, 2, 3]);
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
let fn, obj;
class A {
@fn()
@obj.prop.foo
method() {}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
var _initProto, _obj, _methodDecs, _A;
let fn, obj;
_methodDecs = [void 0, fn(), _obj = obj.prop, _obj.foo];
class A {
constructor() {
_initProto(this);
}
method() {}
}
_A = A;
[_initProto] = babelHelpers.applyDecs2311(_A, [[_methodDecs, 18, "method"]], []).e;
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
let fn, obj;
class A {
@fn()
@obj.prop.foo
method() {}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
var _initProto, _obj, _methodDecs;
let fn, obj;
_methodDecs = [void 0, fn(), _obj = obj.prop, _obj.foo];
class A {
static {
[_initProto] = babelHelpers.applyDecs2311(this, [[_methodDecs, 18, "method"]], []).e;
}
constructor() {
_initProto(this);
}
method() {}
}

0 comments on commit 2061eae

Please sign in to comment.