isConstantExpression should return true for immuable bindings (#8122)

* isConstantExpression should return true for immuable bindings

* New test

* Don't return undefined
This commit is contained in:
Nicolò Ribaudo
2018-06-12 19:40:52 +02:00
committed by Henry Zhu
parent 86c10ff4f3
commit 387cda8fbb
24 changed files with 88 additions and 33 deletions

View File

@@ -319,14 +319,15 @@ export default declare((api, options) => {
const instanceBody = [];
for (const computedPath of computedPaths) {
computedPath.traverse(classFieldDefinitionEvaluationTDZVisitor, {
classRef: path.scope.getBinding(ref.name),
file: this.file,
});
const computedNode = computedPath.node;
// Make sure computed property names are only evaluated once (upon class definition)
// and in the right order in combination with static properties
if (!computedPath.get("key").isConstantExpression()) {
computedPath.traverse(classFieldDefinitionEvaluationTDZVisitor, {
classRef: path.scope.getBinding(ref.name),
file: this.file,
});
const ident = path.scope.generateUidIdentifierBasedOnNode(
computedNode.key,
);

View File

@@ -17,7 +17,6 @@ var _computed2 = computed();
var _ref2 = "test" + one;
var _ref3 = /regex/;
var _bar = bar;
var _baz = baz;
var _ref4 = `template${expression}`;
@@ -33,7 +32,7 @@ function () {
this[void 0] = "void 0";
this[_ref3] = "regex";
this[foo] = "foo";
this[_bar] = "bar";
this[bar] = "bar";
this[_baz] = "baz";
this[`template`] = "template";
this[_ref4] = "template-with-expression";

View File

@@ -17,7 +17,6 @@ var _computed2 = computed();
var _ref2 = "test" + one;
var _ref3 = /regex/;
var _bar = bar;
var _baz = baz;
var _ref4 = `template${expression}`;
@@ -33,7 +32,7 @@ function () {
babelHelpers.defineProperty(this, void 0, "void 0");
babelHelpers.defineProperty(this, _ref3, "regex");
babelHelpers.defineProperty(this, foo, "foo");
babelHelpers.defineProperty(this, _bar, "bar");
babelHelpers.defineProperty(this, bar, "bar");
babelHelpers.defineProperty(this, _baz, "baz");
babelHelpers.defineProperty(this, `template`, "template");
babelHelpers.defineProperty(this, _ref4, "template-with-expression");

View File

@@ -0,0 +1,5 @@
const field = Symbol('field');
class A {
[field] = 10;
}

View File

@@ -0,0 +1,3 @@
{
"plugins": ["external-helpers", "proposal-class-properties"]
}

View File

@@ -0,0 +1,8 @@
const field = Symbol('field');
class A {
constructor() {
babelHelpers.defineProperty(this, field, 10);
}
}

View File

@@ -1,5 +0,0 @@
{
"plugins": ["proposal-class-properties", "transform-classes"],
"minNodeVersion": "6.0.0",
"throws": "Class \"A\" cannot be referenced in computed property keys."
}

View File

@@ -1,3 +0,0 @@
class C {
static [C + 3] = 3;
}

View File

@@ -1,5 +0,0 @@
{
"plugins": ["proposal-class-properties", "transform-classes"],
"minNodeVersion": "6.0.0",
"throws": "Class \"C\" cannot be referenced in computed property keys."
}

View File

@@ -1,3 +0,0 @@
class C {
static [C + 3] = 3;
}

View File

@@ -1,5 +0,0 @@
{
"plugins": [["proposal-class-properties", {"loose": true}]],
"minNodeVersion": "6.0.0",
"throws": "Class \"C\" cannot be referenced in computed property keys."
}

View File

@@ -0,0 +1,5 @@
expect(() => {
class A {
static [{ x: A || 0 }.x];
}
}).toThrow();

View File

@@ -0,0 +1,3 @@
{
"plugins": ["proposal-class-properties", "transform-classes"]
}

View File

@@ -0,0 +1,17 @@
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
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; }
function _classNameTDZError(name) { throw new Error("Class \"" + name + "\" cannot be referenced in computed property keys."); }
var _x$x = {
x: (_classNameTDZError("A"), A) || 0
}.x;
let A = function A() {
"use strict";
_classCallCheck(this, A);
};
_defineProperty(A, _x$x, void 0);

View File

@@ -0,0 +1,5 @@
expect(() => {
class C {
static [C + 3] = 3;
}
}).toThrow();

View File

@@ -0,0 +1,3 @@
{
"plugins": ["proposal-class-properties", "transform-classes"]
}

View File

@@ -0,0 +1,15 @@
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
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; }
function _classNameTDZError(name) { throw new Error("Class \"" + name + "\" cannot be referenced in computed property keys."); }
var _ref = (_classNameTDZError("C"), C) + 3;
let C = function C() {
"use strict";
_classCallCheck(this, C);
};
_defineProperty(C, _ref, 3);

View File

@@ -0,0 +1,5 @@
expect(() => {
class C {
static [C + 3] = 3;
}
}).toThrow();

View File

@@ -0,0 +1,3 @@
{
"plugins": [["proposal-class-properties", { "loose": true }]]
}

View File

@@ -0,0 +1,7 @@
function _classNameTDZError(name) { throw new Error("Class \"" + name + "\" cannot be referenced in computed property keys."); }
var _ref = (_classNameTDZError("C"), C) + 3;
class C {}
C[_ref] = 3;

View File

@@ -402,10 +402,8 @@ export function _resolve(dangerous?, resolved?): ?NodePath {
export function isConstantExpression() {
if (this.isIdentifier()) {
const binding = this.scope.getBinding(this.node.name);
if (!binding) {
return false;
}
return binding.constant && binding.path.get("init").isConstantExpression();
if (!binding) return false;
return binding.constant;
}
if (this.isLiteral()) {