Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Class binding is in TDZ during decorators initialization #16138

Merged
merged 1 commit into from Nov 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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);