Support multiple static blocks (#12738)
This commit is contained in:
parent
05fa18e652
commit
1a05b81387
@ -49,7 +49,6 @@ export const ErrorMessages = Object.freeze({
|
|||||||
"`%0` has already been exported. Exported identifiers must be unique.",
|
"`%0` has already been exported. Exported identifiers must be unique.",
|
||||||
DuplicateProto: "Redefinition of __proto__ property",
|
DuplicateProto: "Redefinition of __proto__ property",
|
||||||
DuplicateRegExpFlags: "Duplicate regular expression flag",
|
DuplicateRegExpFlags: "Duplicate regular expression flag",
|
||||||
DuplicateStaticBlock: "Duplicate static block in the same class",
|
|
||||||
ElementAfterRest: "Rest element must be last element",
|
ElementAfterRest: "Rest element must be last element",
|
||||||
EscapedCharNotAnIdentifier: "Invalid Unicode escape",
|
EscapedCharNotAnIdentifier: "Invalid Unicode escape",
|
||||||
ExportBindingIsString:
|
ExportBindingIsString:
|
||||||
|
|||||||
@ -1204,7 +1204,6 @@ export default class StatementParser extends ExpressionParser {
|
|||||||
const state: N.ParseClassMemberState = {
|
const state: N.ParseClassMemberState = {
|
||||||
constructorAllowsSuper,
|
constructorAllowsSuper,
|
||||||
hadConstructor: false,
|
hadConstructor: false,
|
||||||
hadStaticBlock: false,
|
|
||||||
};
|
};
|
||||||
let decorators: N.Decorator[] = [];
|
let decorators: N.Decorator[] = [];
|
||||||
const classBody: N.ClassBody = this.startNode();
|
const classBody: N.ClassBody = this.startNode();
|
||||||
@ -1313,11 +1312,7 @@ export default class StatementParser extends ExpressionParser {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.eat(tt.braceL)) {
|
if (this.eat(tt.braceL)) {
|
||||||
this.parseClassStaticBlock(
|
this.parseClassStaticBlock(classBody, ((member: any): N.StaticBlock));
|
||||||
classBody,
|
|
||||||
((member: any): N.StaticBlock),
|
|
||||||
state,
|
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1521,7 +1516,6 @@ export default class StatementParser extends ExpressionParser {
|
|||||||
parseClassStaticBlock(
|
parseClassStaticBlock(
|
||||||
classBody: N.ClassBody,
|
classBody: N.ClassBody,
|
||||||
member: N.StaticBlock & { decorators?: Array<N.Decorator> },
|
member: N.StaticBlock & { decorators?: Array<N.Decorator> },
|
||||||
state: N.ParseClassMemberState,
|
|
||||||
) {
|
) {
|
||||||
this.expectPlugin("classStaticBlock", member.start);
|
this.expectPlugin("classStaticBlock", member.start);
|
||||||
// Start a new lexical scope
|
// Start a new lexical scope
|
||||||
@ -1538,13 +1532,9 @@ export default class StatementParser extends ExpressionParser {
|
|||||||
this.scope.exit();
|
this.scope.exit();
|
||||||
this.state.labels = oldLabels;
|
this.state.labels = oldLabels;
|
||||||
classBody.body.push(this.finishNode<N.StaticBlock>(member, "StaticBlock"));
|
classBody.body.push(this.finishNode<N.StaticBlock>(member, "StaticBlock"));
|
||||||
if (state.hadStaticBlock) {
|
|
||||||
this.raise(member.start, Errors.DuplicateStaticBlock);
|
|
||||||
}
|
|
||||||
if (member.decorators?.length) {
|
if (member.decorators?.length) {
|
||||||
this.raise(member.start, Errors.DecoratorStaticBlock);
|
this.raise(member.start, Errors.DecoratorStaticBlock);
|
||||||
}
|
}
|
||||||
state.hadStaticBlock = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pushClassProperty(classBody: N.ClassBody, prop: N.ClassProperty) {
|
pushClassProperty(classBody: N.ClassBody, prop: N.ClassProperty) {
|
||||||
|
|||||||
@ -1528,6 +1528,5 @@ export type ParseSubscriptState = {
|
|||||||
|
|
||||||
export type ParseClassMemberState = {|
|
export type ParseClassMemberState = {|
|
||||||
hadConstructor: boolean,
|
hadConstructor: boolean,
|
||||||
hadStaticBlock: boolean,
|
|
||||||
constructorAllowsSuper: boolean,
|
constructorAllowsSuper: boolean,
|
||||||
|};
|
|};
|
||||||
|
|||||||
@ -1,9 +1,6 @@
|
|||||||
{
|
{
|
||||||
"type": "File",
|
"type": "File",
|
||||||
"start":0,"end":53,"loc":{"start":{"line":1,"column":0},"end":{"line":5,"column":1}},
|
"start":0,"end":53,"loc":{"start":{"line":1,"column":0},"end":{"line":5,"column":1}},
|
||||||
"errors": [
|
|
||||||
"SyntaxError: Duplicate static block in the same class (4:2)"
|
|
||||||
],
|
|
||||||
"program": {
|
"program": {
|
||||||
"type": "Program",
|
"type": "Program",
|
||||||
"start":0,"end":53,"loc":{"start":{"line":1,"column":0},"end":{"line":5,"column":1}},
|
"start":0,"end":53,"loc":{"start":{"line":1,"column":0},"end":{"line":5,"column":1}},
|
||||||
@ -30,30 +30,28 @@ export default declare(({ types: t, template, assertVersion }) => {
|
|||||||
const { scope } = path;
|
const { scope } = path;
|
||||||
const classBody = path.get("body");
|
const classBody = path.get("body");
|
||||||
const privateNames = new Set();
|
const privateNames = new Set();
|
||||||
let staticBlockPath;
|
const body = classBody.get("body");
|
||||||
for (const path of classBody.get("body")) {
|
for (const path of body) {
|
||||||
if (path.isPrivate()) {
|
if (path.isPrivate()) {
|
||||||
privateNames.add(path.get("key.id").node.name);
|
privateNames.add(path.get("key.id").node.name);
|
||||||
} else if (path.isStaticBlock()) {
|
|
||||||
staticBlockPath = path;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!staticBlockPath) {
|
for (const path of body) {
|
||||||
return;
|
if (!path.isStaticBlock()) continue;
|
||||||
}
|
const staticBlockPrivateId = generateUid(scope, privateNames);
|
||||||
|
privateNames.add(staticBlockPrivateId);
|
||||||
const staticBlockRef = t.privateName(
|
const staticBlockRef = t.privateName(
|
||||||
t.identifier(generateUid(scope, privateNames)),
|
t.identifier(staticBlockPrivateId),
|
||||||
);
|
);
|
||||||
classBody.pushContainer(
|
path.replaceWith(
|
||||||
"body",
|
|
||||||
t.classPrivateProperty(
|
t.classPrivateProperty(
|
||||||
staticBlockRef,
|
staticBlockRef,
|
||||||
template.expression.ast`(() => { ${staticBlockPath.node.body} })()`,
|
template.expression.ast`(() => { ${path.node.body} })()`,
|
||||||
[],
|
[],
|
||||||
/* static */ true,
|
/* static */ true,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
staticBlockPath.remove();
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
class Foo {
|
class Foo {
|
||||||
|
static bar = 42;
|
||||||
static {
|
static {
|
||||||
this.foo = Foo.bar;
|
this.foo = Foo.bar;
|
||||||
}
|
}
|
||||||
static bar = 42;
|
|
||||||
}
|
}
|
||||||
expect(Foo.foo).toBe(42);
|
expect(Foo.foo).toBe(42);
|
||||||
|
|||||||
@ -0,0 +1,7 @@
|
|||||||
|
class Foo {
|
||||||
|
static bar = 42;
|
||||||
|
static {
|
||||||
|
this.foo = Foo.bar;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect(Foo.foo).toBe(42);
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
class Foo {
|
||||||
|
static bar = 42;
|
||||||
|
static #_ = (() => {
|
||||||
|
this.foo = Foo.bar;
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(Foo.foo).toBe(42);
|
||||||
@ -1,7 +1,7 @@
|
|||||||
class Foo {
|
class Foo {
|
||||||
|
static bar = 42;
|
||||||
static {
|
static {
|
||||||
this.foo = this.bar;
|
this.foo = this.bar;
|
||||||
}
|
}
|
||||||
static bar = 42;
|
|
||||||
}
|
}
|
||||||
expect(Foo.foo).toBe(42);
|
expect(Foo.foo).toBe(42);
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
class Foo {
|
class Foo {
|
||||||
|
static bar = 42;
|
||||||
static {
|
static {
|
||||||
this.foo = this.bar;
|
this.foo = this.bar;
|
||||||
}
|
}
|
||||||
static bar = 42;
|
|
||||||
}
|
}
|
||||||
expect(Foo.foo).toBe(42);
|
expect(Foo.foo).toBe(42);
|
||||||
|
|||||||
@ -1,8 +1,14 @@
|
|||||||
class Foo {
|
class Foo {
|
||||||
static #bar = 21;
|
static #bar = 21;
|
||||||
static {
|
static {
|
||||||
this.foo = this.#bar + this.qux;
|
this.foo = this.#bar;
|
||||||
|
this.qux1 = this.qux;
|
||||||
}
|
}
|
||||||
static qux = 21;
|
static qux = 21;
|
||||||
|
static {
|
||||||
|
this.qux2 = this.qux;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
expect(Foo.foo).toBe(42);
|
expect(Foo.foo).toBe(21);
|
||||||
|
expect(Foo.qux1).toBe(undefined);
|
||||||
|
expect(Foo.qux2).toBe(21);
|
||||||
|
|||||||
@ -0,0 +1,11 @@
|
|||||||
|
class Foo {
|
||||||
|
static #bar = 21;
|
||||||
|
static {
|
||||||
|
this.foo = this.#bar;
|
||||||
|
this.qux1 = this.qux;
|
||||||
|
}
|
||||||
|
static qux = 21;
|
||||||
|
static {
|
||||||
|
this.qux2 = this.qux;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
class Foo {
|
||||||
|
static #bar = 21;
|
||||||
|
static #_ = (() => {
|
||||||
|
this.foo = this.#bar;
|
||||||
|
this.qux1 = this.qux;
|
||||||
|
})();
|
||||||
|
static qux = 21;
|
||||||
|
static #_2 = (() => {
|
||||||
|
this.qux2 = this.qux;
|
||||||
|
})();
|
||||||
|
}
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
class Base {
|
||||||
|
constructor() {
|
||||||
|
this.Foo = class {
|
||||||
|
static {
|
||||||
|
this.foo = new.target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect((new Base).Foo.foo).toBe(undefined);
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
class Base {
|
||||||
|
constructor() {
|
||||||
|
this.Foo = class {
|
||||||
|
static {
|
||||||
|
this.foo = new.target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect((new Base).Foo.foo).toBe(undefined);
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
class Base {
|
||||||
|
constructor() {
|
||||||
|
this.Foo = class {
|
||||||
|
static #_ = (() => {
|
||||||
|
this.foo = new.target;
|
||||||
|
})();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(new Base().Foo.foo).toBe(undefined);
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
class Base {
|
||||||
|
constructor() {
|
||||||
|
this.Foo = class {
|
||||||
|
static {
|
||||||
|
this.foo = new.target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect((new Base).Foo.foo).toBe(undefined);
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
class Base {
|
||||||
|
constructor() {
|
||||||
|
this.Foo = class {
|
||||||
|
static {
|
||||||
|
this.foo = new.target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect((new Base).Foo.foo).toBe(undefined);
|
||||||
@ -1,7 +1,7 @@
|
|||||||
class Foo {
|
class Foo {
|
||||||
|
static bar = 42;
|
||||||
static {
|
static {
|
||||||
this.foo = Foo.bar;
|
this.foo = Foo.bar;
|
||||||
}
|
}
|
||||||
static bar = 42;
|
|
||||||
}
|
}
|
||||||
expect(Foo.foo).toBe(42);
|
expect(Foo.foo).toBe(42);
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
class Foo {
|
class Foo {
|
||||||
|
static bar = 42;
|
||||||
static {
|
static {
|
||||||
this.foo = Foo.bar;
|
this.foo = Foo.bar;
|
||||||
}
|
}
|
||||||
static bar = 42;
|
|
||||||
}
|
}
|
||||||
expect(Foo.foo).toBe(42);
|
expect(Foo.foo).toBe(42);
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
class Foo {
|
class Foo {
|
||||||
|
static bar = 42;
|
||||||
static {
|
static {
|
||||||
this.foo = this.bar;
|
this.foo = this.bar;
|
||||||
}
|
}
|
||||||
static bar = 42;
|
|
||||||
}
|
}
|
||||||
expect(Foo.foo).toBe(42);
|
expect(Foo.foo).toBe(42);
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
class Foo {
|
class Foo {
|
||||||
|
static bar = 42;
|
||||||
static {
|
static {
|
||||||
this.foo = this.bar;
|
this.foo = this.bar;
|
||||||
}
|
}
|
||||||
static bar = 42;
|
|
||||||
}
|
}
|
||||||
expect(Foo.foo).toBe(42);
|
expect(Foo.foo).toBe(42);
|
||||||
|
|||||||
@ -1,8 +1,14 @@
|
|||||||
class Foo {
|
class Foo {
|
||||||
static #bar = 21;
|
static #bar = 21;
|
||||||
static {
|
static {
|
||||||
this.foo = this.#bar + this.qux;
|
this.foo = this.#bar;
|
||||||
|
this.qux1 = this.qux;
|
||||||
}
|
}
|
||||||
static qux = 21;
|
static qux = 21;
|
||||||
|
static {
|
||||||
|
this.qux2 = this.qux;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
expect(Foo.foo).toBe(42);
|
expect(Foo.foo).toBe(21);
|
||||||
|
expect(Foo.qux1).toBe(undefined);
|
||||||
|
expect(Foo.qux2).toBe(21);
|
||||||
|
|||||||
@ -0,0 +1,11 @@
|
|||||||
|
class Foo {
|
||||||
|
static #bar = 21;
|
||||||
|
static {
|
||||||
|
this.foo = this.#bar;
|
||||||
|
this.qux1 = this.qux;
|
||||||
|
}
|
||||||
|
static qux = 21;
|
||||||
|
static {
|
||||||
|
this.qux2 = this.qux;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
var _bar = babelHelpers.classPrivateFieldLooseKey("bar");
|
||||||
|
|
||||||
|
var _ = babelHelpers.classPrivateFieldLooseKey("_");
|
||||||
|
|
||||||
|
var _2 = babelHelpers.classPrivateFieldLooseKey("_2");
|
||||||
|
|
||||||
|
class Foo {}
|
||||||
|
|
||||||
|
Object.defineProperty(Foo, _bar, {
|
||||||
|
writable: true,
|
||||||
|
value: 21
|
||||||
|
});
|
||||||
|
Object.defineProperty(Foo, _, {
|
||||||
|
writable: true,
|
||||||
|
value: (() => {
|
||||||
|
Foo.foo = babelHelpers.classPrivateFieldLooseBase(Foo, _bar)[_bar];
|
||||||
|
Foo.qux1 = Foo.qux;
|
||||||
|
})()
|
||||||
|
});
|
||||||
|
Foo.qux = 21;
|
||||||
|
Object.defineProperty(Foo, _2, {
|
||||||
|
writable: true,
|
||||||
|
value: (() => {
|
||||||
|
Foo.qux2 = Foo.qux;
|
||||||
|
})()
|
||||||
|
});
|
||||||
10
packages/babel-plugin-proposal-class-static-block/test/fixtures/integration/.new-target/exec.js
vendored
Normal file
10
packages/babel-plugin-proposal-class-static-block/test/fixtures/integration/.new-target/exec.js
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
class Base {
|
||||||
|
constructor() {
|
||||||
|
this.Foo = class {
|
||||||
|
static {
|
||||||
|
this.foo = new.target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect((new Base).Foo.foo).toBe(undefined);
|
||||||
11
packages/babel-plugin-proposal-class-static-block/test/fixtures/integration/.new-target/input.js
vendored
Normal file
11
packages/babel-plugin-proposal-class-static-block/test/fixtures/integration/.new-target/input.js
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
class Base {
|
||||||
|
constructor() {
|
||||||
|
this.Foo = class {
|
||||||
|
static {
|
||||||
|
// fixme: new.target should be undefined after transformed
|
||||||
|
this.foo = new.target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect((new Base).Foo.foo).toBe(undefined);
|
||||||
@ -1,7 +1,7 @@
|
|||||||
class Foo {
|
class Foo {
|
||||||
|
static bar = 42;
|
||||||
static {
|
static {
|
||||||
this.foo = Foo.bar;
|
this.foo = Foo.bar;
|
||||||
}
|
}
|
||||||
static bar = 42;
|
|
||||||
}
|
}
|
||||||
expect(Foo.foo).toBe(42);
|
expect(Foo.foo).toBe(42);
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
class Foo {
|
class Foo {
|
||||||
|
static bar = 42;
|
||||||
static {
|
static {
|
||||||
this.foo = Foo.bar;
|
this.foo = Foo.bar;
|
||||||
}
|
}
|
||||||
static bar = 42;
|
|
||||||
}
|
}
|
||||||
expect(Foo.foo).toBe(42);
|
expect(Foo.foo).toBe(42);
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
class Foo {
|
class Foo {
|
||||||
|
static bar = 42;
|
||||||
static {
|
static {
|
||||||
this.foo = this.bar;
|
this.foo = this.bar;
|
||||||
}
|
}
|
||||||
static bar = 42;
|
|
||||||
}
|
}
|
||||||
expect(Foo.foo).toBe(42);
|
expect(Foo.foo).toBe(42);
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
class Foo {
|
class Foo {
|
||||||
|
static bar = 42;
|
||||||
static {
|
static {
|
||||||
this.foo = this.bar;
|
this.foo = this.bar;
|
||||||
}
|
}
|
||||||
static bar = 42;
|
|
||||||
}
|
}
|
||||||
expect(Foo.foo).toBe(42);
|
expect(Foo.foo).toBe(42);
|
||||||
|
|||||||
@ -1,8 +1,14 @@
|
|||||||
class Foo {
|
class Foo {
|
||||||
static #bar = 21;
|
static #bar = 21;
|
||||||
static {
|
static {
|
||||||
this.foo = this.#bar + this.qux;
|
this.foo = this.#bar;
|
||||||
|
this.qux1 = this.qux;
|
||||||
}
|
}
|
||||||
static qux = 21;
|
static qux = 21;
|
||||||
|
static {
|
||||||
|
this.qux2 = this.qux;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
expect(Foo.foo).toBe(42);
|
expect(Foo.foo).toBe(21);
|
||||||
|
expect(Foo.qux1).toBe(undefined);
|
||||||
|
expect(Foo.qux2).toBe(21);
|
||||||
|
|||||||
@ -0,0 +1,11 @@
|
|||||||
|
class Foo {
|
||||||
|
static #bar = 21;
|
||||||
|
static {
|
||||||
|
this.foo = this.#bar;
|
||||||
|
this.qux1 = this.qux;
|
||||||
|
}
|
||||||
|
static qux = 21;
|
||||||
|
static {
|
||||||
|
this.qux2 = this.qux;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
class Foo {}
|
||||||
|
|
||||||
|
var _bar = {
|
||||||
|
writable: true,
|
||||||
|
value: 21
|
||||||
|
};
|
||||||
|
var _ = {
|
||||||
|
writable: true,
|
||||||
|
value: (() => {
|
||||||
|
Foo.foo = babelHelpers.classStaticPrivateFieldSpecGet(Foo, Foo, _bar);
|
||||||
|
Foo.qux1 = Foo.qux;
|
||||||
|
})()
|
||||||
|
};
|
||||||
|
babelHelpers.defineProperty(Foo, "qux", 21);
|
||||||
|
var _2 = {
|
||||||
|
writable: true,
|
||||||
|
value: (() => {
|
||||||
|
Foo.qux2 = Foo.qux;
|
||||||
|
})()
|
||||||
|
};
|
||||||
Loading…
x
Reference in New Issue
Block a user