use a different helper if a class contains class methods to avoid non-enumerability and delegation to es6.properties.computed transformer - fixes #984, closes #986

This commit is contained in:
Sebastian McKenzie
2015-03-10 13:04:02 +11:00
parent 3bd14f9e07
commit f3bd9cbcb8
9 changed files with 122 additions and 54 deletions

View File

@@ -50,6 +50,7 @@ export default class File {
"inherits",
"defaults",
"create-class",
"create-computed-class",
"apply-constructor",
"tagged-template-literal",
"tagged-template-literal-loose",

View File

@@ -5,33 +5,40 @@ import has from "lodash/object/has";
import t from "../../types";
export function push(mutatorMap, key, kind, computed, value) {
var alias;
var alias = t.toKeyAlias({ computed }, key);
if (t.isIdentifier(key)) {
alias = key.name;
if (computed) alias = `computed:${alias}`;
} else if (t.isLiteral(key)) {
alias = String(key.value);
} else {
alias = JSON.stringify(traverse.removeProperties(t.cloneDeep(key)));
}
var map;
if (has(mutatorMap, alias)) {
map = mutatorMap[alias];
} else {
map = {};
}
var map = {};
if (has(mutatorMap, alias)) map = mutatorMap[alias];
mutatorMap[alias] = map;
map._key = key;
if (computed) {
map._computed = true;
}
if (computed) map._computed = true;
map[kind] = value;
}
export function hasComputed(mutatorMap) {
for (var key in mutatorMap) {
if (mutatorMap[key]._computed) {
return true;
}
}
return false;
}
export function toComputedObjectFromClass(obj) {
var objExpr = t.arrayExpression([]);
for (var i = 0; i < obj.properties.length; i++) {
var prop = obj.properties[i];
var val = prop.value;
val.properties.unshift(t.property("init", t.identifier("key"), t.toComputedKey(prop)));
objExpr.elements.push(val);
}
return objExpr;
}
export function toClassObject(mutatorMap) {
var objExpr = t.objectExpression([]);
@@ -49,6 +56,7 @@ export function toClassObject(mutatorMap) {
var prop = t.property("init", t.identifier(key), node);
t.inheritsComments(prop, inheritNode);
t.removeComments(inheritNode);
mapNode.properties.push(prop);
});
@@ -59,35 +67,11 @@ export function toClassObject(mutatorMap) {
}
export function toDefineObject(mutatorMap) {
var objExpr = t.objectExpression([]);
each(mutatorMap, function (map) {
var mapNode = t.objectExpression([]);
var propNode = t.property("init", map._key, mapNode, map._computed);
if (map.value) {
map.writable = t.literal(true);
}
if (map.value) map.writable = t.literal(true);
map.configurable = t.literal(true);
map.enumerable = t.literal(true);
each(map, function (node, key) {
if (key[0] === "_") return;
node = t.clone(node);
var inheritNode = node;
if (t.isMethodDefinition(node)) node = node.value;
var prop = t.property("init", t.identifier(key), node);
t.inheritsComments(prop, inheritNode);
t.removeComments(inheritNode);
mapNode.properties.push(prop);
});
objExpr.properties.push(propNode);
});
return objExpr;
return toClassObject(mutatorMap);
}

View File

@@ -0,0 +1,18 @@
(function() {
function defineProperties(target, rawProps) {
var props = {};
for (var i = 0; i < rawProps.length; i ++) {
var prop = rawProps[i];
prop.configurable = true;
if (prop.value) prop.writable = true;
props[prop.key] = prop;
}
Object.defineProperties(target, props);
}
return function (Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);
if (staticProps) defineProperties(Constructor, staticProps);
return Constructor;
};
})()

View File

@@ -217,6 +217,7 @@ class ClassTransformer {
var instanceProps;
var staticProps;
var classHelper = "create-class";
if (this.hasInstanceMutators) {
instanceProps = defineMap.toClassObject(this.instanceMutatorMap);
@@ -227,13 +228,19 @@ class ClassTransformer {
}
if (instanceProps || staticProps) {
if (defineMap.hasComputed(this.instanceMutatorMap) || defineMap.hasComputed(this.staticMutatorMap)) {
if (instanceProps) instanceProps = defineMap.toComputedObjectFromClass(instanceProps);
if (staticProps) staticProps = defineMap.toComputedObjectFromClass(staticProps);
classHelper = "create-computed-class";
}
instanceProps ||= t.literal(null);
var args = [this.classRef, instanceProps];
if (staticProps) args.push(staticProps);
body.push(t.expressionStatement(
t.callExpression(this.file.addHelper("create-class"), args)
t.callExpression(this.file.addHelper(classHelper), args)
));
}
}

View File

@@ -126,7 +126,7 @@ each(t.BUILDER_KEYS, function (keys, type) {
* Description
*/
t.toComputedKey = function (node: Object, key: Object): Object {
t.toComputedKey = function (node: Object, key: Object = node.key): Object {
if (!node.computed) {
if (t.isIdentifier(key)) key = t.literal(key.name);
}
@@ -701,6 +701,23 @@ t.getLastStatements = function (node: Object): Array<Object> {
return nodes;
};
/**
* Description
*/
t.toKeyAlias = function (node: Object, key: Object = node.key) {
var alias;
if (t.isIdentifier(key)) {
alias = key.name;
} else if (t.isLiteral(key)) {
alias = JSON.stringify(key.value);
} else {
alias = JSON.stringify(traverse.removeProperties(t.cloneDeep(key)));
}
if (node.computed) alias = `[${alias}]`;
return alias;
};
/**
* Description
*/