Skip to content

Commit

Permalink
Class binding is in TDZ during decorators initialization (#16138)
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolo-ribaudo committed Nov 29, 2023
1 parent a31c4b9 commit d4f3a22
Show file tree
Hide file tree
Showing 31 changed files with 78 additions and 44 deletions.
Expand Up @@ -103,19 +103,20 @@ function createLazyPrivateUidGeneratorForClass(
*/
function replaceClassWithVar(
path: NodePath<t.ClassDeclaration | t.ClassExpression>,
): [t.Identifier, NodePath<t.ClassDeclaration | t.ClassExpression>] {
): {
id: t.Identifier;
path: NodePath<t.ClassDeclaration | t.ClassExpression>;
needsDeclaration: boolean;
} {
if (path.type === "ClassDeclaration") {
const varId = path.scope.generateUidIdentifierBasedOnNode(path.node.id);
const classId = t.identifier(path.node.id.name);

path.scope.rename(classId.name, varId.name);

path.insertBefore(
t.variableDeclaration("let", [t.variableDeclarator(varId)]),
);
path.get("id").replaceWith(classId);

return [t.cloneNode(varId), path];
return { id: t.cloneNode(varId), path, needsDeclaration: true };
} else {
let className: string;
let varId: t.Identifier;
Expand Down Expand Up @@ -145,10 +146,11 @@ function replaceClassWithVar(
t.sequenceExpression([newClassExpr, varId]),
);

return [
t.cloneNode(varId),
newPath.get("expressions.0") as NodePath<t.ClassExpression>,
];
return {
id: t.cloneNode(varId),
path: newPath.get("expressions.0") as NodePath<t.ClassExpression>,
needsDeclaration: false,
};
}
}

Expand Down Expand Up @@ -609,12 +611,15 @@ function transformClass(
}
};

let needsDeclaraionForClassBinding = false;
if (classDecorators) {
classInitLocal = scopeParent.generateDeclaredUidIdentifier("initClass");

const [classId, classPath] = replaceClassWithVar(path);
path = classPath;
classIdLocal = classId;
({
id: classIdLocal,
path,
needsDeclaration: needsDeclaraionForClassBinding,
} = replaceClassWithVar(path));

path.node.decorators = null;

Expand Down Expand Up @@ -1108,6 +1113,14 @@ function transformClass(
// into a SequenceExpression
path.insertBefore(assignments.map(expr => t.expressionStatement(expr)));

if (needsDeclaraionForClassBinding) {
path.insertBefore(
t.variableDeclaration("let", [
t.variableDeclarator(t.cloneNode(classIdLocal)),
]),
);
}

// Recrawl the scope to make sure new identifiers are properly synced
path.scope.crawl();

Expand Down
@@ -1,7 +1,7 @@
var _initClass, _dec, _initClass2, _dec2;
const dec = () => {};
let _Bar;
_dec = dec1;
let _Bar;
class Bar {
static {
[_Bar, _initClass] = babelHelpers.applyDecs(this, [], [_dec]);
Expand All @@ -10,8 +10,8 @@ class Bar {
_initClass();
}
}
let _Foo;
_dec2 = dec2;
let _Foo;
class Foo extends _Bar {
static {
[_Foo, _initClass2] = babelHelpers.applyDecs(this, [], [_dec2]);
Expand Down
@@ -1,6 +1,6 @@
var _initClass, _dec;
let _A;
_dec = dec;
let _A;
class A {
static {
[_A, _initClass] = babelHelpers.applyDecs(this, [], [_dec]);
Expand Down
@@ -1,6 +1,6 @@
var _initClass, _dec;
let _default2;
_dec = dec;
let _default2;
class _default {
static {
[_default2, _initClass] = babelHelpers.applyDecs(this, [], [_dec]);
Expand Down
@@ -1,6 +1,6 @@
var _initClass, _dec;
let _A;
_dec = dec;
let _A;
class A {
static {
[_A, _initClass] = babelHelpers.applyDecs(this, [], [_dec]);
Expand Down
@@ -1,6 +1,5 @@
var _initClass, _dec, _dec2, _dec3, _dec4, _dec5, _dec6, _dec7, _dec8, _initProto, _class;
const dec = () => {};
let _Foo;
_dec = call();
_dec2 = chain.expr();
_dec3 = arbitrary + expr;
Expand All @@ -9,6 +8,7 @@ _dec5 = call();
_dec6 = chain.expr();
_dec7 = arbitrary + expr;
_dec8 = array[expr];
let _Foo;
var _a = /*#__PURE__*/new WeakMap();
class Foo {
constructor(...args) {
Expand Down
@@ -1,6 +1,5 @@
var _initClass, _dec, _dec2, _dec3, _dec4, _dec5, _dec6, _dec7, _dec8, _initProto;
const dec = () => {};
let _Foo;
_dec = call();
_dec2 = chain.expr();
_dec3 = arbitrary + expr;
Expand All @@ -9,6 +8,7 @@ _dec5 = call();
_dec6 = chain.expr();
_dec7 = arbitrary + expr;
_dec8 = array[expr];
let _Foo;
class Foo {
static {
[_initProto, _Foo, _initClass] = babelHelpers.applyDecs(this, [[[dec, _dec5, _dec6, _dec7, _dec8], 2, "method"]], [dec, _dec, _dec2, _dec3, _dec4]);
Expand Down
@@ -1,7 +1,7 @@
var _initClass, _dec, _initClass2, _dec2;
const dec = () => {};
let _Bar;
_dec = dec1;
let _Bar;
class Bar {
static {
[_Bar, _initClass] = babelHelpers.applyDecs2203R(this, [], [_dec]).c;
Expand All @@ -10,8 +10,8 @@ class Bar {
_initClass();
}
}
let _Foo;
_dec2 = dec2;
let _Foo;
class Foo extends _Bar {
static {
[_Foo, _initClass2] = babelHelpers.applyDecs2203R(this, [], [_dec2]).c;
Expand Down
@@ -1,6 +1,6 @@
var _initClass, _dec;
let _A;
_dec = dec;
let _A;
class A {
static {
[_A, _initClass] = babelHelpers.applyDecs2203R(this, [], [_dec]).c;
Expand Down
@@ -1,6 +1,6 @@
var _initClass, _dec;
let _default2;
_dec = dec;
let _default2;
class _default {
static {
[_default2, _initClass] = babelHelpers.applyDecs2203R(this, [], [_dec]).c;
Expand Down
@@ -1,6 +1,6 @@
var _initClass, _dec;
let _A;
_dec = dec;
let _A;
class A {
static {
[_A, _initClass] = babelHelpers.applyDecs2203R(this, [], [_dec]).c;
Expand Down
@@ -1,6 +1,5 @@
var _initClass, _dec, _dec2, _dec3, _dec4, _dec5, _dec6, _dec7, _dec8, _initProto, _class;
const dec = () => {};
let _Foo;
_dec = call();
_dec2 = chain.expr();
_dec3 = arbitrary + expr;
Expand All @@ -9,6 +8,7 @@ _dec5 = call();
_dec6 = chain.expr();
_dec7 = arbitrary + expr;
_dec8 = array[expr];
let _Foo;
var _a = /*#__PURE__*/new WeakMap();
class Foo {
constructor(...args) {
Expand Down
@@ -1,6 +1,5 @@
var _initClass, _dec, _dec2, _dec3, _dec4, _dec5, _dec6, _dec7, _dec8, _initProto;
const dec = () => {};
let _Foo;
_dec = call();
_dec2 = chain.expr();
_dec3 = arbitrary + expr;
Expand All @@ -9,6 +8,7 @@ _dec5 = call();
_dec6 = chain.expr();
_dec7 = arbitrary + expr;
_dec8 = array[expr];
let _Foo;
class Foo {
static {
({
Expand Down
@@ -1,7 +1,7 @@
var _initClass, _dec, _initClass2, _dec2;
const dec = () => {};
let _Bar;
_dec = dec1;
let _Bar;
class Bar {
static {
[_Bar, _initClass] = babelHelpers.applyDecs2301(this, [], [_dec]).c;
Expand All @@ -10,8 +10,8 @@ class Bar {
_initClass();
}
}
let _Foo;
_dec2 = dec2;
let _Foo;
class Foo extends _Bar {
static {
[_Foo, _initClass2] = babelHelpers.applyDecs2301(this, [], [_dec2]).c;
Expand Down
@@ -1,6 +1,6 @@
var _initClass, _dec;
let _A;
_dec = dec;
let _A;
class A {
static {
[_A, _initClass] = babelHelpers.applyDecs2301(this, [], [_dec]).c;
Expand Down
@@ -1,6 +1,6 @@
var _initClass, _dec;
let _default2;
_dec = dec;
let _default2;
class _default {
static {
[_default2, _initClass] = babelHelpers.applyDecs2301(this, [], [_dec]).c;
Expand Down
@@ -1,6 +1,6 @@
var _initClass, _dec;
let _A;
_dec = dec;
let _A;
class A {
static {
[_A, _initClass] = babelHelpers.applyDecs2301(this, [], [_dec]).c;
Expand Down
@@ -1,6 +1,5 @@
var _initClass, _dec, _dec2, _dec3, _dec4, _dec5, _dec6, _dec7, _dec8, _initProto, _class;
const dec = () => {};
let _Foo;
_dec = call();
_dec2 = chain.expr();
_dec3 = arbitrary + expr;
Expand All @@ -9,6 +8,7 @@ _dec5 = call();
_dec6 = chain.expr();
_dec7 = arbitrary + expr;
_dec8 = array[expr];
let _Foo;
var _a = /*#__PURE__*/new WeakMap();
class Foo {
constructor(...args) {
Expand Down
@@ -1,6 +1,5 @@
var _initClass, _dec, _dec2, _dec3, _dec4, _dec5, _dec6, _dec7, _dec8, _initProto;
const dec = () => {};
let _Foo;
_dec = call();
_dec2 = chain.expr();
_dec3 = arbitrary + expr;
Expand All @@ -9,6 +8,7 @@ _dec5 = call();
_dec6 = chain.expr();
_dec7 = arbitrary + expr;
_dec8 = array[expr];
let _Foo;
class Foo {
static {
({
Expand Down
@@ -1,7 +1,7 @@
var _initClass, _dec, _initClass2, _dec2, _Bar2;
const dec = () => {};
let _Bar;
_dec = dec1;
let _Bar;
class Bar {
static {
[_Bar, _initClass] = babelHelpers.applyDecs2305(this, [], [_dec]).c;
Expand All @@ -10,8 +10,8 @@ class Bar {
_initClass();
}
}
let _Foo;
_dec2 = dec2;
let _Foo;
class Foo extends (_Bar2 = _Bar) {
static {
[_Foo, _initClass2] = babelHelpers.applyDecs2305(this, [], [_dec2], 0, void 0, _Bar2).c;
Expand Down
@@ -1,6 +1,6 @@
var _initClass, _dec;
let _A;
_dec = dec;
let _A;
class A {
static {
[_A, _initClass] = babelHelpers.applyDecs2305(this, [], [_dec]).c;
Expand Down
@@ -1,6 +1,6 @@
var _initClass, _dec;
let _default2;
_dec = dec;
let _default2;
class _default {
static {
[_default2, _initClass] = babelHelpers.applyDecs2305(this, [], [_dec]).c;
Expand Down
@@ -1,6 +1,6 @@
var _initClass, _dec;
let _A;
_dec = dec;
let _A;
class A {
static {
[_A, _initClass] = babelHelpers.applyDecs2305(this, [], [_dec]).c;
Expand Down
@@ -1,11 +1,11 @@
class A extends B {
m() {
var _initClass, _obj, _dec, _obj2, _dec2, _initProto, _class;
let _C;
_obj = this;
_dec = super.dec1;
_obj2 = this;
_dec2 = super.dec2;
let _C;
class C {
constructor(...args) {
_initProto(this);
Expand Down
@@ -1,5 +1,4 @@
var _initClass, _obj, _dec, _dec2, _obj2, _dec3, _obj3, _dec4, _obj4, _dec5, _init_x, _obj5, _dec6, _dec7, _init_y, _class;
let _A;
_obj = o1;
_dec = _obj.dec;
_dec2 = dec;
Expand All @@ -12,6 +11,7 @@ _dec5 = _obj4.dec;
_obj5 = o2;
_dec6 = _obj5.dec;
_dec7 = dec;
let _A;
class A {
constructor() {
babelHelpers.defineProperty(this, "x", _init_x(this));
Expand Down
@@ -1,6 +1,5 @@
var _initClass, _dec, _dec2, _dec3, _obj, _dec4, _dec5, _dec6, _dec7, _obj2, _dec8, _initProto, _class;
const dec = () => {};
let _Foo;
_dec = call();
_dec2 = chain.expr();
_dec3 = arbitrary + expr;
Expand All @@ -11,6 +10,7 @@ _dec6 = chain.expr();
_dec7 = arbitrary + expr;
_obj2 = array;
_dec8 = _obj2[expr];
let _Foo;
var _a = /*#__PURE__*/new WeakMap();
class Foo {
constructor(...args) {
Expand Down
@@ -0,0 +1,14 @@
let didRun = false;

function dec(fn) {
fn();
return () => {};
}

@dec(() => {
expect(() => Foo).toThrow(ReferenceError);
didRun = true;
}) class Foo {}

expect(didRun).toBe(true);

0 comments on commit d4f3a22

Please sign in to comment.