Skip to content

Commit

Permalink
Remove ordering constraints for static-blocks plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolo-ribaudo committed May 11, 2021
1 parent 9e241fc commit a6cda9a
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 60 deletions.
13 changes: 4 additions & 9 deletions packages/babel-helper-create-class-features-plugin/src/index.js
Expand Up @@ -154,15 +154,10 @@ export function createClassFeaturePlugin({
if (!isDecorated) isDecorated = hasOwnDecorators(path.node);

if (path.isStaticBlock?.()) {
throw path.buildCodeFrameError(`Incorrect plugin order, \`@babel/plugin-proposal-class-static-block\` should be placed before class features plugins
{
"plugins": [
"@babel/plugin-proposal-class-static-block",
"@babel/plugin-proposal-private-property-in-object",
"@babel/plugin-proposal-private-methods",
"@babel/plugin-proposal-class-properties",
]
}`);
throw path.buildCodeFrameError(
"Compiling class fields and private methods requires compiling class static blocks." +
" Please add `@babel/plugin-proposal-class-static-block` to your Babel configuration.",
);
}
}

Expand Down
@@ -0,0 +1,4 @@
class A {
#x;
static {}
}
@@ -0,0 +1,4 @@
{
"plugins": ["proposal-class-properties", "syntax-class-static-block"],
"throws": "Compiling class fields and private methods requires compiling class static blocks. Please add `@babel/plugin-proposal-class-static-block` to your Babel configuration."
}
59 changes: 33 additions & 26 deletions packages/babel-plugin-proposal-class-static-block/src/index.js
Expand Up @@ -26,32 +26,39 @@ export default declare(({ types: t, template, assertVersion }) => {
name: "proposal-class-static-block",
inherits: syntaxClassStaticBlock,
visitor: {
Class(path: NodePath<Class>) {
const { scope } = path;
const classBody = path.get("body");
const privateNames = new Set();
const body = classBody.get("body");
for (const path of body) {
if (path.isPrivate()) {
privateNames.add(path.get("key.id").node.name);
}
}
for (const path of body) {
if (!path.isStaticBlock()) continue;
const staticBlockPrivateId = generateUid(scope, privateNames);
privateNames.add(staticBlockPrivateId);
const staticBlockRef = t.privateName(
t.identifier(staticBlockPrivateId),
);
path.replaceWith(
t.classPrivateProperty(
staticBlockRef,
template.expression.ast`(() => { ${path.node.body} })()`,
[],
/* static */ true,
),
);
}
Program(path) {
// We run this from the program visitor, so that when transforming private elements
// we are sure that static blocks have already been transformed regarless of the
// plugins order in the user config.
path.traverse({
Class(path: NodePath<Class>) {
const { scope } = path;
const classBody = path.get("body");
const privateNames = new Set();
const body = classBody.get("body");
for (const path of body) {
if (path.isPrivate()) {
privateNames.add(path.get("key.id").node.name);
}
}
for (const path of body) {
if (!path.isStaticBlock()) continue;
const staticBlockPrivateId = generateUid(scope, privateNames);
privateNames.add(staticBlockPrivateId);
const staticBlockRef = t.privateName(
t.identifier(staticBlockPrivateId),
);
path.replaceWith(
t.classPrivateProperty(
staticBlockRef,
template.expression.ast`(() => { ${path.node.body} })()`,
[],
/* static */ true,
),
);
}
},
});
},
},
};
Expand Down
Expand Up @@ -2,15 +2,15 @@ import * as babel from "@babel/core";
import proposalClassStaticBlock from "..";

describe("plugin ordering", () => {
it("should throw when @babel/plugin-proposal-class-static-block is after class features plugin", () => {
it("should work when @babel/plugin-proposal-class-static-block is after class features plugin", () => {
const source = `class Foo {
static {
this.foo = Foo.bar;
}
static bar = 42;
}
`;
expect(() => {
static {
this.foo = Foo.bar;
}
static bar = 42;
}
`;
expect(
babel.transform(source, {
filename: "example.js",
highlightCode: false,
Expand All @@ -20,22 +20,20 @@ describe("plugin ordering", () => {
"@babel/plugin-proposal-class-properties",
proposalClassStaticBlock,
],
});
})
.toThrow(`Incorrect plugin order, \`@babel/plugin-proposal-class-static-block\` should be placed before class features plugins
{
"plugins": [
"@babel/plugin-proposal-class-static-block",
"@babel/plugin-proposal-private-property-in-object",
"@babel/plugin-proposal-private-methods",
"@babel/plugin-proposal-class-properties",
]
}
1 | class Foo {
> 2 | static {
| ^
3 | this.foo = Foo.bar;
4 | }
5 | static bar = 42;`);
}).code,
).toMatchInlineSnapshot(`
"function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
class Foo {}
var _ = {
writable: true,
value: (() => {
Foo.foo = Foo.bar;
})()
};
_defineProperty(Foo, \\"bar\\", 42);"
`);
});
});

0 comments on commit a6cda9a

Please sign in to comment.