Computed class properties (#4500)
* Support computed class property names (#4499) ** 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) * doc: Update babel-types with ClassProperty.computed * chore(package): update babylon to v6.11.0 * babel-types: move ClassProperty.computed to be last builder arg
This commit is contained in:
parent
a81a0d0f84
commit
03d772c2ec
@ -33,7 +33,7 @@
|
|||||||
"babel-register": "^6.14.0",
|
"babel-register": "^6.14.0",
|
||||||
"babel-traverse": "^6.14.0",
|
"babel-traverse": "^6.14.0",
|
||||||
"babel-types": "^6.14.0",
|
"babel-types": "^6.14.0",
|
||||||
"babylon": "^6.9.0",
|
"babylon": "^6.11.0",
|
||||||
"convert-source-map": "^1.1.0",
|
"convert-source-map": "^1.1.0",
|
||||||
"debug": "^2.1.1",
|
"debug": "^2.1.1",
|
||||||
"json5": "^0.4.0",
|
"json5": "^0.4.0",
|
||||||
|
|||||||
@ -21,6 +21,6 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"babel-helper-fixtures": "^6.9.0",
|
"babel-helper-fixtures": "^6.9.0",
|
||||||
"babylon": "^6.9.0"
|
"babylon": "^6.11.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -55,7 +55,13 @@ export function ClassProperty(node: Object) {
|
|||||||
this.word("static");
|
this.word("static");
|
||||||
this.space();
|
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);
|
this.print(node.typeAnnotation, node);
|
||||||
if (node.value) {
|
if (node.value) {
|
||||||
this.space();
|
this.space();
|
||||||
|
|||||||
19
packages/babel-generator/test/fixtures/types/ClassBody-ClassProperty/actual.js
vendored
Normal file
19
packages/babel-generator/test/fixtures/types/ClassBody-ClassProperty/actual.js
vendored
Normal file
@ -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;
|
||||||
|
}
|
||||||
19
packages/babel-generator/test/fixtures/types/ClassBody-ClassProperty/expected.js
vendored
Normal file
19
packages/babel-generator/test/fixtures/types/ClassBody-ClassProperty/expected.js
vendored
Normal file
@ -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;
|
||||||
|
}
|
||||||
@ -170,6 +170,7 @@ suites.forEach(function (testSuite) {
|
|||||||
"exportExtensions",
|
"exportExtensions",
|
||||||
"functionBind",
|
"functionBind",
|
||||||
"classConstructorCall",
|
"classConstructorCall",
|
||||||
|
"classProperties",
|
||||||
],
|
],
|
||||||
strictMode: false,
|
strictMode: false,
|
||||||
sourceType: "module",
|
sourceType: "module",
|
||||||
|
|||||||
@ -58,14 +58,15 @@ export default function ({ types: t }) {
|
|||||||
if (!propNode.value) continue;
|
if (!propNode.value) continue;
|
||||||
|
|
||||||
let isStatic = propNode.static;
|
let isStatic = propNode.static;
|
||||||
|
let isComputed = propNode.computed || t.isLiteral(prop.key);
|
||||||
|
|
||||||
if (isStatic) {
|
if (isStatic) {
|
||||||
nodes.push(t.expressionStatement(
|
nodes.push(t.expressionStatement(
|
||||||
t.assignmentExpression("=", t.memberExpression(ref, propNode.key), propNode.value)
|
t.assignmentExpression("=", t.memberExpression(ref, propNode.key, isComputed), propNode.value)
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
instanceBody.push(t.expressionStatement(
|
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)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,3 @@
|
|||||||
|
class Foo {
|
||||||
|
[bar] = "foo";
|
||||||
|
}
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
var Foo = function Foo() {
|
||||||
|
babelHelpers.classCallCheck(this, Foo);
|
||||||
|
this[bar] = "foo";
|
||||||
|
};
|
||||||
@ -8,7 +8,7 @@
|
|||||||
"repository": "https://github.com/babel/babel/tree/master/packages/babel-template",
|
"repository": "https://github.com/babel/babel/tree/master/packages/babel-template",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"babylon": "^6.9.0",
|
"babylon": "^6.11.0",
|
||||||
"babel-traverse": "^6.15.0",
|
"babel-traverse": "^6.15.0",
|
||||||
"babel-types": "^6.15.0",
|
"babel-types": "^6.15.0",
|
||||||
"babel-runtime": "^6.9.0",
|
"babel-runtime": "^6.9.0",
|
||||||
|
|||||||
@ -12,7 +12,7 @@
|
|||||||
"babel-messages": "^6.8.0",
|
"babel-messages": "^6.8.0",
|
||||||
"babel-runtime": "^6.9.0",
|
"babel-runtime": "^6.9.0",
|
||||||
"babel-types": "^6.15.0",
|
"babel-types": "^6.15.0",
|
||||||
"babylon": "^6.9.0",
|
"babylon": "^6.11.0",
|
||||||
"debug": "^2.2.0",
|
"debug": "^2.2.0",
|
||||||
"globals": "^8.3.0",
|
"globals": "^8.3.0",
|
||||||
"invariant": "^2.2.0",
|
"invariant": "^2.2.0",
|
||||||
|
|||||||
@ -217,7 +217,7 @@ Aliases: `Function`, `Scopable`, `BlockParent`, `FunctionParent`, `Method`
|
|||||||
- `returnType` (default: `null`)
|
- `returnType` (default: `null`)
|
||||||
- `typeParameters` (default: `null`)
|
- `typeParameters` (default: `null`)
|
||||||
|
|
||||||
### t.classProperty(key, value, typeAnnotation, decorators)
|
### t.classProperty(key, value, typeAnnotation, decorators, computed)
|
||||||
|
|
||||||
See also `t.isClassProperty(node, opts)` and `t.assertClassProperty(node, opts)`.
|
See also `t.isClassProperty(node, opts)` and `t.assertClassProperty(node, opts)`.
|
||||||
|
|
||||||
@ -227,6 +227,7 @@ Aliases: `Flow`, `Property`
|
|||||||
- `value` (required)
|
- `value` (required)
|
||||||
- `typeAnnotation` (required)
|
- `typeAnnotation` (required)
|
||||||
- `decorators` (required)
|
- `decorators` (required)
|
||||||
|
- `computed`: `boolean` (default: `false`)
|
||||||
|
|
||||||
### t.conditionalExpression(test, consequent, alternate)
|
### t.conditionalExpression(test, consequent, alternate)
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
import defineType from "./index";
|
import defineType, {
|
||||||
|
assertValueType
|
||||||
|
} from "./index";
|
||||||
|
|
||||||
defineType("AnyTypeAnnotation", {
|
defineType("AnyTypeAnnotation", {
|
||||||
aliases: ["Flow", "FlowBaseAnnotation"],
|
aliases: ["Flow", "FlowBaseAnnotation"],
|
||||||
@ -42,8 +44,13 @@ defineType("ClassImplements", {
|
|||||||
|
|
||||||
defineType("ClassProperty", {
|
defineType("ClassProperty", {
|
||||||
visitor: ["key", "value", "typeAnnotation", "decorators"],
|
visitor: ["key", "value", "typeAnnotation", "decorators"],
|
||||||
|
builder: ["key", "value", "typeAnnotation", "decorators", "computed"],
|
||||||
aliases: ["Flow", "Property"],
|
aliases: ["Flow", "Property"],
|
||||||
fields: {
|
fields: {
|
||||||
|
computed: {
|
||||||
|
validate: assertValueType("boolean"),
|
||||||
|
default: false
|
||||||
|
}
|
||||||
// todo
|
// todo
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@ -100,9 +100,14 @@ export function isReferenced(node: Object, parent: Object): boolean {
|
|||||||
return parent.name !== node;
|
return parent.name !== node;
|
||||||
|
|
||||||
// no: class { NODE = value; }
|
// no: class { NODE = value; }
|
||||||
|
// yes: class { [NODE] = value; }
|
||||||
// yes: class { key = NODE; }
|
// yes: class { key = NODE; }
|
||||||
case "ClassProperty":
|
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 NODE from "foo";
|
||||||
// no: import * as NODE from "foo";
|
// no: import * as NODE from "foo";
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user