Skip to content

Commit

Permalink
Support computed class property names (babel#4499)
Browse files Browse the repository at this point in the history
** Depends on babel/babylon#121 **

* `babel-types`: Add `computed` field to `ClassProperty`

* `babel-plugin-transform-class-properties`: handle computed property names correctly

* `babel-generator`: add tests for class properties (computed/literal, static/instance)
  • Loading branch information
motiz88 committed Sep 11, 2016
1 parent d2d34ba commit d1150f6
Show file tree
Hide file tree
Showing 9 changed files with 70 additions and 5 deletions.
8 changes: 7 additions & 1 deletion packages/babel-generator/src/generators/classes.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,13 @@ export function ClassProperty(node: Object) {
this.word("static");
this.space();
}
this.print(node.key, node);
if (node.computed) {
this.token("[");
this.print(node.key, node);
this.token("]");
} else {
this.print(node.key, node);
}
this.print(node.typeAnnotation, node);
if (node.value) {
this.space();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
class Foo {
foo;
foo = 1;
"foo";
"foo" = 1;
["foo"];
["foo"] = 1;
["f" + "oo"];
["f" + "oo"] = 1;

static foo;
static foo = 1;
static "foo";
static "foo" = 1;
static ["foo"];
static ["foo"] = 1;
static ["f" + "oo"];
static ["f" + "oo"] = 1;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
class Foo {
foo;
foo = 1;
"foo";
"foo" = 1;
["foo"];
["foo"] = 1;
["f" + "oo"];
["f" + "oo"] = 1;

static foo;
static foo = 1;
static "foo";
static "foo" = 1;
static ["foo"];
static ["foo"] = 1;
static ["f" + "oo"];
static ["f" + "oo"] = 1;
}
1 change: 1 addition & 0 deletions packages/babel-generator/test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ suites.forEach(function (testSuite) {
"exportExtensions",
"functionBind",
"classConstructorCall",
"classProperties",
],
strictMode: false,
sourceType: "module",
Expand Down
5 changes: 3 additions & 2 deletions packages/babel-plugin-transform-class-properties/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,15 @@ export default function ({ types: t }) {
if (!propNode.value) continue;

let isStatic = propNode.static;
let isComputed = propNode.computed || t.isLiteral(prop.key);

if (isStatic) {
nodes.push(t.expressionStatement(
t.assignmentExpression("=", t.memberExpression(ref, propNode.key), propNode.value)
t.assignmentExpression("=", t.memberExpression(ref, propNode.key, isComputed), propNode.value)
));
} else {
instanceBody.push(t.expressionStatement(
t.assignmentExpression("=", t.memberExpression(t.thisExpression(), propNode.key), propNode.value)
t.assignmentExpression("=", t.memberExpression(t.thisExpression(), propNode.key, isComputed), propNode.value)
));
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
class Foo {
[bar] = "foo";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
var Foo = function Foo() {
babelHelpers.classCallCheck(this, Foo);
this[bar] = "foo";
};
9 changes: 8 additions & 1 deletion packages/babel-types/src/definitions/flow.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import defineType from "./index";
import defineType, {
assertValueType
} from "./index";

defineType("AnyTypeAnnotation", {
aliases: ["Flow", "FlowBaseAnnotation"],
Expand Down Expand Up @@ -42,8 +44,13 @@ defineType("ClassImplements", {

defineType("ClassProperty", {
visitor: ["key", "value", "typeAnnotation", "decorators"],
builder: ["key", "value", "computed", "typeAnnotation", "decorators"],
aliases: ["Flow", "Property"],
fields: {
computed: {
validate: assertValueType("boolean"),
default: false
}
// todo
}
});
Expand Down
7 changes: 6 additions & 1 deletion packages/babel-types/src/validators.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,14 @@ export function isReferenced(node: Object, parent: Object): boolean {
return parent.name !== node;

// no: class { NODE = value; }
// yes: class { [NODE] = value; }
// yes: class { key = NODE; }
case "ClassProperty":
return parent.value === node;
if (parent.key === node) {
return parent.computed;
} else {
return parent.value === node;
}

// no: import NODE from "foo";
// no: import * as NODE from "foo";
Expand Down

0 comments on commit d1150f6

Please sign in to comment.