add optional protoToAssign transformer

This commit is contained in:
Sebastian McKenzie
2015-01-04 07:38:36 +11:00
parent 8b2788e930
commit 324a0b408a
15 changed files with 189 additions and 6 deletions

View File

@@ -19,6 +19,7 @@ function File(opts) {
File.declarations = [
"inherits",
"defaults",
"prototype-properties",
"apply-constructor",
"tagged-template-literal",
@@ -97,18 +98,23 @@ File.normaliseOptions = function (opts) {
File.prototype.getTransformers = function () {
var file = this;
var transformers = [];
var secondPassTransformers = [];
_.each(transform.transformers, function (transformer) {
if (transformer.canRun(file)) {
transformers.push(transformer);
if (transformer.secondPass) {
secondPassTransformers.push(transformer);
}
if (transformer.manipulateOptions) {
transformer.manipulateOptions(file.opts, file);
}
}
});
return transformers;
return transformers.concat(secondPassTransformers);
};
File.prototype.toArray = function (node, i) {

View File

@@ -0,0 +1,8 @@
(function (obj, defaults) {
for (var key in defaults) {
if (obj[key] === undefined) {
obj[key] = defaults[key];
}
}
return obj;
})

View File

@@ -81,6 +81,8 @@ _.each({
generators: require("./transformers/es6-generators"),
restParameters: require("./transformers/es6-rest-parameters"),
protoToAssign: require("./transformers/optional-proto-to-assign"),
_declarations: require("./transformers/_declarations"),
// wrap up
@@ -88,7 +90,6 @@ _.each({
_moduleFormatter: require("./transformers/_module-formatter"),
useStrict: require("./transformers/use-strict"),
protoToAssign: require("./transformers/optional-proto-to-assign"),
coreAliasing: require("./transformers/optional-core-aliasing"),
undefinedToVoid: require("./transformers/optional-undefined-to-void"),

View File

@@ -7,6 +7,7 @@ var _ = require("lodash");
function Transformer(key, transformer, opts) {
this.manipulateOptions = transformer.manipulateOptions;
this.experimental = !!transformer.experimental;
this.secondPass = !!transformer.secondPass;
this.transformer = Transformer.normalise(transformer);
this.optional = !!transformer.optional;
this.opts = opts || {};
@@ -41,16 +42,14 @@ Transformer.normalise = function (transformer) {
Transformer.prototype.astRun = function (file, key) {
var transformer = this.transformer;
var ast = file.ast;
if (transformer.ast && transformer.ast[key]) {
transformer.ast[key](ast, file);
transformer.ast[key](file.ast, file);
}
};
Transformer.prototype.transform = function (file) {
var transformer = this.transformer;
var ast = file.ast;
var build = function (exit) {
return function (node, parent, scope) {
@@ -67,7 +66,7 @@ Transformer.prototype.transform = function (file) {
this.astRun(file, "before");
traverse(ast, {
traverse(file.ast, {
enter: build(),
exit: build(true)
});

View File

@@ -1,5 +1,7 @@
var t = require("../../types");
exports.secondPass = true;
exports.BlockStatement =
exports.Program = function (node) {
var kinds = {};
@@ -22,4 +24,6 @@ exports.Program = function (node) {
for (kind in kinds) {
node.body.unshift(t.variableDeclaration(kind, kinds[kind]));
}
node._declarations = null;
};

View File

@@ -0,0 +1,63 @@
var t = require("../../types");
var _ = require("lodash");
var OBJECT_ASSIGN_MEMBER = t.memberExpression(t.identifier("Object"), t.identifier("assign"));
var isProtoKey = function (node) {
return t.isLiteral(t.toComputedKey(node, node.key), { value: "__proto__" });
};
var isProtoAssignmentExpression = function (node) {
var left = node.left;
return t.isMemberExpression(left) && t.isLiteral(t.toComputedKey(left, left.property), { value: "__proto__" });
};
var buildDefaultsCallExpression = function (expr, ref, file) {
return t.expressionStatement(t.callExpression(file.addDeclaration("defaults"), [ref, expr.right]));
};
exports.optional = true;
exports.secondPass = true;
exports.AssignmentExpression = function (node, parent, file, scope) {
if (t.isExpressionStatement(parent)) return;
if (!isProtoAssignmentExpression(node)) return;
var nodes = [];
var left = node.left.object;
var temp = scope.generateTempBasedOnNode(node.left.object, file);
nodes.push(t.expressionStatement(t.assignmentExpression("=", temp, left)));
nodes.push(buildDefaultsCallExpression(node, temp, file));
if (temp) nodes.push(temp);
return t.toSequenceExpression(nodes);
};
exports.ExpressionStatement = function (node, parent, file, scope) {
var expr = node.expression;
if (!t.isAssignmentExpression(expr, { operator: "=" })) return;
if (isProtoAssignmentExpression(expr)) {
return buildDefaultsCallExpression(expr, expr.left.object, file);
}
};
exports.ObjectExpression = function (node) {
var proto;
for (var i in node.properties) {
var prop = node.properties[i];
if (isProtoKey(prop)) {
proto = prop.value;
_.pull(node.properties, prop);
}
}
if (proto) {
var args = [t.objectExpression([]), proto];
if (node.properties.length) args.push(node);
return t.callExpression(OBJECT_ASSIGN_MEMBER, args);
}
};