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

fix: wrap anonymous class expression within statement #15113

Merged
merged 2 commits into from Nov 3, 2022
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 @@ -937,7 +937,12 @@ function transformClass(
class extends ${state.addHelper("identity")} {}
` as t.ClassExpression;
staticsClass.body.body = [
t.staticBlock([t.toStatement(path.node, false)]),
t.staticBlock([
t.toStatement(originalClass, true) ||
// If toStatement returns false, originalClass must be an anonymous ClassExpression,
// because `export default @dec ...` has been handled in the export visitor before.
t.expressionStatement(originalClass as t.ClassExpression),
]),
Comment on lines -940 to +945
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be better to fix in t.toStatement?

Also unrelated to this PR, the type definition and implementation of t.toStatement seem inconsistent.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be better to fix in t.toStatement?

I don't know much context here but it seems that we intentionally fail toStatement for anonymous class expression

it("fail if class expression has no id", function () {
const node = t.classExpression(null, null, t.classBody([]), []);
expect(function () {
t.toStatement(node);
}).toThrow(Error);
expect(t.toStatement(node, /* ignore = */ true)).toBe(false);
t.assertClassExpression(node);
});

/cc @nicolo-ribaudo if you can shred some light here.

If we decided to overturn this behaviour, we still need the patch here until Babel 8 because the plugin does not depend on @babel/types.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

liuxingbaoyu@98ca541

Good find, now I think it's fine.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe the reason is that t.toStatement of a ClassExpression should return a ClassDeclaration, but converting a class expression without an ID is generally not safe.

...statics,
];

Expand Down
@@ -0,0 +1,12 @@
const dec = () => {};
const A = @dec class A { static {} }
const B = @dec class C { static {} }
const D = @dec class { static {} }
const E = (@dec class { static {} }, 123);
const F = [@dec class G { static {} }, @dec class { static {} }];
const H = @dec class extends I { static {} };
const J = @dec class K extends L { static {} };

function classFactory() {
return @dec class { static {} }
}
@@ -0,0 +1,67 @@
var _initClass, _A, _temp, _initClass2, _C, _temp2, _initClass3, _D, _temp3, _initClass4, _decorated_class, _temp4, _class2, _initClass5, _G, _temp5, _initClass6, _decorated_class2, _temp6, _class3, _initClass7, _H, _temp7, _initClass8, _K, _temp8;
const dec = () => {};
const A = (new (_temp = class extends babelHelpers.identity {
constructor() {
super(_A), (() => {})(), _initClass();
}
}, (() => {
class A {}
[_A, _initClass] = babelHelpers.applyDecs(A, [], [dec]);
})(), _temp)(), _A);
const B = (new (_temp2 = class extends babelHelpers.identity {
constructor() {
super(_C), (() => {})(), _initClass2();
}
}, (() => {
class C {}
[_C, _initClass2] = babelHelpers.applyDecs(C, [], [dec]);
})(), _temp2)(), _C);
const D = (new (_temp3 = class extends babelHelpers.identity {
constructor() {
super(_D), (() => {})(), _initClass3();
}
}, (() => {
class D {}
[_D, _initClass3] = babelHelpers.applyDecs(D, [], [dec]);
})(), _temp3)(), _D);
const E = ((new (_temp4 = class extends babelHelpers.identity {
constructor() {
super(_decorated_class), (() => {})(), _initClass4();
}
}, (_class2 = class {}, [_decorated_class, _initClass4] = babelHelpers.applyDecs(_class2, [], [dec])), _temp4)(), _decorated_class), 123);
const F = [(new (_temp5 = class extends babelHelpers.identity {
constructor() {
super(_G), (() => {})(), _initClass5();
}
}, (() => {
class G {}
[_G, _initClass5] = babelHelpers.applyDecs(G, [], [dec]);
})(), _temp5)(), _G), (new (_temp6 = class extends babelHelpers.identity {
constructor() {
super(_decorated_class2), (() => {})(), _initClass6();
}
}, (_class3 = class {}, [_decorated_class2, _initClass6] = babelHelpers.applyDecs(_class3, [], [dec])), _temp6)(), _decorated_class2)];
const H = (new (_temp7 = class extends babelHelpers.identity {
constructor() {
super(_H), (() => {})(), _initClass7();
}
}, (() => {
class H extends I {}
[_H, _initClass7] = babelHelpers.applyDecs(H, [], [dec]);
})(), _temp7)(), _H);
const J = (new (_temp8 = class extends babelHelpers.identity {
constructor() {
super(_K), (() => {})(), _initClass8();
}
}, (() => {
class K extends L {}
[_K, _initClass8] = babelHelpers.applyDecs(K, [], [dec]);
})(), _temp8)(), _K);
function classFactory() {
var _initClass9, _decorated_class3, _temp9, _class5;
return new (_temp9 = class extends babelHelpers.identity {
constructor() {
super(_decorated_class3), (() => {})(), _initClass9();
}
}, (_class5 = class {}, [_decorated_class3, _initClass9] = babelHelpers.applyDecs(_class5, [], [dec])), _temp9)(), _decorated_class3;
}
@@ -0,0 +1,12 @@
const dec = () => {};
const A = @dec class A { static {} }
const B = @dec class C { static {} }
const D = @dec class { static {} }
const E = (@dec class { static {} }, 123);
const F = [@dec class G { static {} }, @dec class { static {} }];
const H = @dec class extends I { static {} };
const J = @dec class K extends L { static {} };

function classFactory() {
return @dec class { static {} }
}
@@ -0,0 +1,112 @@
var _initClass, _A, _initClass2, _C, _initClass3, _D, _initClass4, _decorated_class, _initClass5, _G, _initClass6, _decorated_class2, _initClass7, _H, _initClass8, _K;
const dec = () => {};
const A = (new class extends babelHelpers.identity {
static {
class A {
static {
[_A, _initClass] = babelHelpers.applyDecs(this, [], [dec]);
}
}
}
constructor() {
super(_A), (() => {})(), _initClass();
}
}(), _A);
const B = (new class extends babelHelpers.identity {
static {
class C {
static {
[_C, _initClass2] = babelHelpers.applyDecs(this, [], [dec]);
}
}
}
constructor() {
super(_C), (() => {})(), _initClass2();
}
}(), _C);
const D = (new class extends babelHelpers.identity {
static {
class D {
static {
[_D, _initClass3] = babelHelpers.applyDecs(this, [], [dec]);
}
}
}
constructor() {
super(_D), (() => {})(), _initClass3();
}
}(), _D);
const E = ((new class extends babelHelpers.identity {
static {
(class {
static {
[_decorated_class, _initClass4] = babelHelpers.applyDecs(this, [], [dec]);
}
});
}
constructor() {
super(_decorated_class), (() => {})(), _initClass4();
}
}(), _decorated_class), 123);
const F = [(new class extends babelHelpers.identity {
static {
class G {
static {
[_G, _initClass5] = babelHelpers.applyDecs(this, [], [dec]);
}
}
}
constructor() {
super(_G), (() => {})(), _initClass5();
}
}(), _G), (new class extends babelHelpers.identity {
static {
(class {
static {
[_decorated_class2, _initClass6] = babelHelpers.applyDecs(this, [], [dec]);
}
});
}
constructor() {
super(_decorated_class2), (() => {})(), _initClass6();
}
}(), _decorated_class2)];
const H = (new class extends babelHelpers.identity {
static {
class H extends I {
static {
[_H, _initClass7] = babelHelpers.applyDecs(this, [], [dec]);
}
}
}
constructor() {
super(_H), (() => {})(), _initClass7();
}
}(), _H);
const J = (new class extends babelHelpers.identity {
static {
class K extends L {
static {
[_K, _initClass8] = babelHelpers.applyDecs(this, [], [dec]);
}
}
}
constructor() {
super(_K), (() => {})(), _initClass8();
}
}(), _K);
function classFactory() {
var _initClass9, _decorated_class3;
return new class extends babelHelpers.identity {
static {
(class {
static {
[_decorated_class3, _initClass9] = babelHelpers.applyDecs(this, [], [dec]);
}
});
}
constructor() {
super(_decorated_class3), (() => {})(), _initClass9();
}
}(), _decorated_class3;
}
@@ -0,0 +1,12 @@
const dec = () => {};
const A = @dec class A { static {} }
const B = @dec class C { static {} }
const D = @dec class { static {} }
const E = (@dec class { static {} }, 123);
const F = [@dec class G { static {} }, @dec class { static {} }];
const H = @dec class extends I { static {} };
const J = @dec class K extends L { static {} };

function classFactory() {
return @dec class { static {} }
}
@@ -0,0 +1,67 @@
var _initClass, _A, _temp, _initClass2, _C, _temp2, _initClass3, _D, _temp3, _initClass4, _decorated_class, _temp4, _class2, _initClass5, _G, _temp5, _initClass6, _decorated_class2, _temp6, _class3, _initClass7, _H, _temp7, _initClass8, _K, _temp8;
const dec = () => {};
const A = (new (_temp = class extends babelHelpers.identity {
constructor() {
super(_A), (() => {})(), _initClass();
}
}, (() => {
class A {}
[_A, _initClass] = babelHelpers.applyDecs2203(A, [], [dec]);
})(), _temp)(), _A);
const B = (new (_temp2 = class extends babelHelpers.identity {
constructor() {
super(_C), (() => {})(), _initClass2();
}
}, (() => {
class C {}
[_C, _initClass2] = babelHelpers.applyDecs2203(C, [], [dec]);
})(), _temp2)(), _C);
const D = (new (_temp3 = class extends babelHelpers.identity {
constructor() {
super(_D), (() => {})(), _initClass3();
}
}, (() => {
class D {}
[_D, _initClass3] = babelHelpers.applyDecs2203(D, [], [dec]);
})(), _temp3)(), _D);
const E = ((new (_temp4 = class extends babelHelpers.identity {
constructor() {
super(_decorated_class), (() => {})(), _initClass4();
}
}, (_class2 = class {}, [_decorated_class, _initClass4] = babelHelpers.applyDecs2203(_class2, [], [dec])), _temp4)(), _decorated_class), 123);
const F = [(new (_temp5 = class extends babelHelpers.identity {
constructor() {
super(_G), (() => {})(), _initClass5();
}
}, (() => {
class G {}
[_G, _initClass5] = babelHelpers.applyDecs2203(G, [], [dec]);
})(), _temp5)(), _G), (new (_temp6 = class extends babelHelpers.identity {
constructor() {
super(_decorated_class2), (() => {})(), _initClass6();
}
}, (_class3 = class {}, [_decorated_class2, _initClass6] = babelHelpers.applyDecs2203(_class3, [], [dec])), _temp6)(), _decorated_class2)];
const H = (new (_temp7 = class extends babelHelpers.identity {
constructor() {
super(_H), (() => {})(), _initClass7();
}
}, (() => {
class H extends I {}
[_H, _initClass7] = babelHelpers.applyDecs2203(H, [], [dec]);
})(), _temp7)(), _H);
const J = (new (_temp8 = class extends babelHelpers.identity {
constructor() {
super(_K), (() => {})(), _initClass8();
}
}, (() => {
class K extends L {}
[_K, _initClass8] = babelHelpers.applyDecs2203(K, [], [dec]);
})(), _temp8)(), _K);
function classFactory() {
var _initClass9, _decorated_class3, _temp9, _class5;
return new (_temp9 = class extends babelHelpers.identity {
constructor() {
super(_decorated_class3), (() => {})(), _initClass9();
}
}, (_class5 = class {}, [_decorated_class3, _initClass9] = babelHelpers.applyDecs2203(_class5, [], [dec])), _temp9)(), _decorated_class3;
}
@@ -0,0 +1,12 @@
const dec = () => {};
const A = @dec class A { static {} }
const B = @dec class C { static {} }
const D = @dec class { static {} }
const E = (@dec class { static {} }, 123);
const F = [@dec class G { static {} }, @dec class { static {} }];
const H = @dec class extends I { static {} };
const J = @dec class K extends L { static {} };

function classFactory() {
return @dec class { static {} }
}