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

Transform class static block #12143

Merged
Show file tree
Hide file tree
Changes from 4 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
3 changes: 3 additions & 0 deletions packages/babel-plugin-proposal-class-static-block/.npmignore
@@ -0,0 +1,3 @@
src
test
*.log
19 changes: 19 additions & 0 deletions packages/babel-plugin-proposal-class-static-block/README.md
@@ -0,0 +1,19 @@
# @babel/plugin-proposal-class-static-block

> Allow transforming of class static blocks

See our website [@babel/plugin-proposal-class-static-block](https://babeljs.io/docs/en/next/babel-plugin-proposal-class-static-block.html) for more information.

## Install

Using npm:

```sh
npm install --save-dev @babel/plugin-proposal-class-static-block
```

or using yarn:

```sh
yarn add @babel/plugin-proposal-class-static-block --dev
```
28 changes: 28 additions & 0 deletions packages/babel-plugin-proposal-class-static-block/package.json
@@ -0,0 +1,28 @@
{
"name": "@babel/plugin-proposal-class-static-block",
"version": "7.11.0",
"description": "Allow parsing of class static blocks",
"repository": {
"type": "git",
"url": "https://github.com/babel/babel.git",
"directory": "packages/babel-plugin-proposal-class-static-block"
},
"license": "MIT",
"publishConfig": {
"access": "public"
},
"main": "./lib/index.js",
"exports": {
".": "./lib/index.js"
},
"keywords": [
"babel-plugin"
],
"dependencies": {
"@babel/helper-plugin-utils": "workspace:^7.10.1",
"@babel/plugin-syntax-class-static-block": "workspace:^7.11.0"
},
"peerDependencies": {
"@babel/core": "^7.12.0"
}
}
66 changes: 66 additions & 0 deletions packages/babel-plugin-proposal-class-static-block/src/index.js
@@ -0,0 +1,66 @@
import { declare } from "@babel/helper-plugin-utils";
import syntaxClassStaticBlock from "@babel/plugin-syntax-class-static-block";

/**
* Generate a uid that is not in `denyList`
*
* @param {*} scope
* @param {Set<string>} a deny list that the generated uid should avoid
* @returns
*/
function generateUid(scope, denyList: Set<string>) {
const name = "";
let uid;
let i = 1;
do {
uid = scope._generateUid(name, i);
i++;
} while (denyList.has(uid));
return uid;
}

/**
* Get private names defined in current class body
*
* @param {NodePath<ClassBody>} classBody
* @returns {Set<string>} A set of defined private names
*/
function getPrivateNames(classBody: NodePath<ClassBody>): Set<string> {
const privateNames = new Set();
for (const path of classBody.get("body")) {
if (path.isPrivate()) {
privateNames.add(path.get("key.id").node.name);
}
}
return privateNames;
}

export default declare(({ types: t, template, assertVersion }) => {
// todo remove this check after Babel 7.12.0 is published
JLHwung marked this conversation as resolved.
Show resolved Hide resolved
if (process.env.NODE_ENV !== "test") {
assertVersion("^7.12.0");
Copy link
Contributor Author

Choose a reason for hiding this comment

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

As a new package it requires @babel/core 7.12.0. It depends on @babel/type 7.12.0 and @babel/parser 7.12.0.

}

return {
name: "proposal-class-static-block",
inherits: syntaxClassStaticBlock,
visitor: {
StaticBlock(path: NodePath<StaticBlock>) {
const { parentPath: classBody, scope } = path;
const staticBlockRef = t.privateName(
t.identifier(generateUid(scope, getPrivateNames(classBody))),
);
classBody.pushContainer(
"body",
t.classPrivateProperty(
staticBlockRef,
template.expression.ast`(() => { ${path.node.body} })()`,
[],
/* static */ true,
),
);
path.remove();
},
},
};
});
@@ -0,0 +1,7 @@
class Foo {
static {
this.foo = Foo.bar;
}
static bar = 42;
}
expect(Foo.foo).toBe(42);
@@ -0,0 +1,7 @@
class Foo {
static {
this.foo = this.bar;
}
static bar = 42;
}
expect(Foo.foo).toBe(42);
@@ -0,0 +1,7 @@
class Foo {
static {
this.foo = this.bar;
}
static bar = 42;
}
expect(Foo.foo).toBe(42);
@@ -0,0 +1,8 @@
class Foo {
static bar = 42;
static #_ = (() => {
this.foo = this.bar;
})();
}

expect(Foo.foo).toBe(42);
@@ -0,0 +1,6 @@
class Foo {
static {
this.foo = 42;
}
}
expect(Foo.foo).toBe(42);
@@ -0,0 +1,14 @@
class Foo extends class extends class Base {
static {
this.qux = 21;
}
} {
static {
this.bar = 21;
}
} {
static {
this.foo = this.bar + this.qux;
}
}
expect(Foo.foo).toBe(42);
@@ -0,0 +1,14 @@
class Foo extends class extends class Base {
static {
this.qux = 21;
}
} {
static {
this.bar = 21;
}
} {
static {
this.foo = this.bar + this.qux;
}
}
expect(Foo.foo).toBe(42);
@@ -0,0 +1,15 @@
class Foo extends class extends class Base {
static #_ = (() => {
this.qux = 21;
})();
} {
static #_ = (() => {
this.bar = 21;
})();
} {
static #_ = (() => {
this.foo = this.bar + this.qux;
})();
}

expect(Foo.foo).toBe(42);
@@ -0,0 +1,8 @@
class Foo {
static #bar = 21;
static {
this.foo = this.#bar + this.qux;
}
static qux = 21;
}
expect(Foo.foo).toBe(42);
@@ -0,0 +1,8 @@
class Foo {
static #_ = 42;
// static block can not be tranformed as `#_` here
static {
this.foo = this.#_;
}
}
expect(Foo.foo).toBe(42);
@@ -0,0 +1,8 @@
class Foo {
static #_ = 42;
// static block can not be tranformed as `#_` here
static {
this.foo = this.#_;
}
}
expect(Foo.foo).toBe(42);
@@ -0,0 +1,9 @@
class Foo {
static #_ = 42; // static block can not be tranformed as `#_` here

static #_2 = (() => {
this.foo = this.#_;
})();
}

expect(Foo.foo).toBe(42);
@@ -0,0 +1,4 @@
{
"plugins": ["proposal-class-static-block", "syntax-class-properties"],
"minNodeVersion": "12.0.0"
}
@@ -0,0 +1,8 @@
let getFoo;
class Foo {
static #foo = 42;
static {
getFoo = () => this.#foo;
}
}
expect(getFoo()).toBe(42);
@@ -0,0 +1,11 @@
class Foo extends class {
static {
this.bar = 42;
}
} {
static bar = 21;
static {
this.foo = super.bar;
}
}
expect(Foo.foo).toBe(42);
@@ -0,0 +1,3 @@
{
"plugins": ["proposal-class-static-block"]
}
@@ -0,0 +1,3 @@
import runner from "@babel/helper-plugin-test-runner";

runner(__dirname);
2 changes: 1 addition & 1 deletion packages/babel-traverse/src/scope/index.js
Expand Up @@ -368,7 +368,7 @@ export default class Scope {
.replace(/[0-9]+$/g, "");

let uid;
let i = 0;
let i = 1;
do {
uid = this._generateUid(name, i);
i++;
Expand Down
2 changes: 1 addition & 1 deletion packages/babel-types/src/definitions/experimental.js
Expand Up @@ -108,7 +108,7 @@ defineType("PipelinePrimaryTopicReference", {

defineType("ClassPrivateProperty", {
visitor: ["key", "value", "decorators"],
builder: ["key", "value", "decorators"],
builder: ["key", "value", "decorators", "static"],
aliases: ["Property", "Private"],
fields: {
key: {
Expand Down
13 changes: 12 additions & 1 deletion yarn.lock
Expand Up @@ -1004,6 +1004,17 @@ __metadata:
languageName: unknown
linkType: soft

"@babel/plugin-proposal-class-static-block@workspace:packages/babel-plugin-proposal-class-static-block":
version: 0.0.0-use.local
resolution: "@babel/plugin-proposal-class-static-block@workspace:packages/babel-plugin-proposal-class-static-block"
dependencies:
"@babel/helper-plugin-utils": "workspace:^7.10.1"
"@babel/plugin-syntax-class-static-block": "workspace:^7.11.0"
peerDependencies:
"@babel/core": ^7.12.0
languageName: unknown
linkType: soft

"@babel/plugin-proposal-decorators@workspace:^7.10.4, @babel/plugin-proposal-decorators@workspace:^7.10.5, @babel/plugin-proposal-decorators@workspace:packages/babel-plugin-proposal-decorators":
version: 0.0.0-use.local
resolution: "@babel/plugin-proposal-decorators@workspace:packages/babel-plugin-proposal-decorators"
Expand Down Expand Up @@ -1449,7 +1460,7 @@ __metadata:
languageName: unknown
linkType: soft

"@babel/plugin-syntax-class-static-block@workspace:packages/babel-plugin-syntax-class-static-block":
"@babel/plugin-syntax-class-static-block@workspace:^7.11.0, @babel/plugin-syntax-class-static-block@workspace:packages/babel-plugin-syntax-class-static-block":
version: 0.0.0-use.local
resolution: "@babel/plugin-syntax-class-static-block@workspace:packages/babel-plugin-syntax-class-static-block"
dependencies:
Expand Down