support destructuring in AssignmentStatement and ForOf loops

This commit is contained in:
Sebastian McKenzie 2014-10-09 22:26:23 +11:00
parent b6e533ec5d
commit 4df2333938
10 changed files with 86 additions and 21 deletions

View File

@ -114,10 +114,10 @@ transform.transformers = {
templateLiterals: require("./transformers/template-literals"), templateLiterals: require("./transformers/template-literals"),
propertyMethodAssignment: require("./transformers/property-method-assignment"), propertyMethodAssignment: require("./transformers/property-method-assignment"),
defaultParameters: require("./transformers/default-parameters"), defaultParameters: require("./transformers/default-parameters"),
destructuring: require("./transformers/destructuring"),
generators: require("./transformers/generators"), generators: require("./transformers/generators"),
blockBinding: require("./transformers/block-binding"), blockBinding: require("./transformers/block-binding"),
restParameters: require("./transformers/rest-parameters"), restParameters: require("./transformers/rest-parameters"),
forOf: require("./transformers/for-of"), forOf: require("./transformers/for-of"),
destructuring: require("./transformers/destructuring"),
unicodeRegex: require("./transformers/unicode-regex") unicodeRegex: require("./transformers/unicode-regex")
}; };

View File

@ -2,15 +2,14 @@ var util = require("../util");
var b = require("ast-types").builders; var b = require("ast-types").builders;
var _ = require("lodash"); var _ = require("lodash");
var isPattern = function (id) {
return id.type === "ArrayPattern" || id.type === "ObjectPattern";
};
var buildVariableAssign = function (kind, id, init) { var buildVariableAssign = function (kind, id, init) {
return b.variableDeclaration(kind, [ if (kind === false) {
b.variableDeclarator(id, init) return b.expressionStatement(b.assignmentExpression("=", id, init));
]); } else {
return b.variableDeclaration(kind, [
b.variableDeclarator(id, init)
]);
}
}; };
var push = function (kind, nodes, pattern, parentId) { var push = function (kind, nodes, pattern, parentId) {
@ -26,7 +25,7 @@ var pushObjectPattern = function (kind, nodes, pattern, parentId) {
var pattern2 = prop.value; var pattern2 = prop.value;
var patternId2 = b.memberExpression(parentId, prop.key, false); var patternId2 = b.memberExpression(parentId, prop.key, false);
if (isPattern(pattern2)) { if (util.isPattern(pattern2)) {
push(kind, nodes, pattern2, patternId2); push(kind, nodes, pattern2, patternId2);
} else { } else {
nodes.push(buildVariableAssign(kind, pattern2, patternId2)); nodes.push(buildVariableAssign(kind, pattern2, patternId2));
@ -69,7 +68,7 @@ exports.FunctionExpression = function (node, parent, opts, generateUid) {
var nodes = []; var nodes = [];
node.params = node.params.map(function (pattern) { node.params = node.params.map(function (pattern) {
if (!isPattern(pattern)) return pattern; if (!util.isPattern(pattern)) return pattern;
var parentId = b.identifier(generateUid("ref")); var parentId = b.identifier(generateUid("ref"));
@ -78,15 +77,35 @@ exports.FunctionExpression = function (node, parent, opts, generateUid) {
return parentId; return parentId;
}); });
block.body = nodes.concat(block.body); block.body = nodes.concat(block.body || []);
};
exports.ExpressionStatement = function (node, parent, opts, generateUid) {
var expr = node.expression;
if (expr.type !== "AssignmentExpression") return;
if (!util.isPattern(expr.left)) return;
var nodes = [];
var ref = b.identifier(generateUid("ref"));
nodes.push(b.variableDeclaration("var", [
b.variableDeclarator(ref, expr.right)
]));
push(false, nodes, expr.left, ref);
return nodes;
}; };
exports.VariableDeclaration = function (node, parent, opts, generateUid) { exports.VariableDeclaration = function (node, parent, opts, generateUid) {
if (parent.type === "ForInStatement") return;
var nodes = []; var nodes = [];
var hasPattern = false; var hasPattern = false;
_.each(node.declarations, function (declar) { _.each(node.declarations, function (declar) {
if (isPattern(declar.id)) { if (util.isPattern(declar.id)) {
hasPattern = true; hasPattern = true;
return false; return false;
} }
@ -96,7 +115,7 @@ exports.VariableDeclaration = function (node, parent, opts, generateUid) {
_.each(node.declarations, function (declar) { _.each(node.declarations, function (declar) {
var patternId = declar.init; var patternId = declar.init;
var pattern = declar.id; var pattern = declar.id;
if (isPattern(pattern)) { if (util.isPattern(pattern) && patternId) {
pushPattern(node.kind, nodes, pattern, patternId, generateUid); pushPattern(node.kind, nodes, pattern, patternId, generateUid);
} else { } else {
nodes.push(buildVariableAssign(node.kind, declar.id, declar.init)); nodes.push(buildVariableAssign(node.kind, declar.id, declar.init));

View File

@ -1,18 +1,39 @@
var util = require("../util"); var util = require("../util");
var b = require("ast-types").builders;
exports.ForOfStatement = function (node, parent, opts, generateUid) { exports.ForOfStatement = function (node, parent, opts, generateUid) {
var declar;
var isPattern = false;
var key;
if (node.left.type === "VariableDeclaration") {
declar = node.left;
key = declar.declarations[0].id;
} else {
isPattern = true;
declar = node.left[0];
key = b.identifier(generateUid("ref"));
}
var node2 = util.template("for-of", { var node2 = util.template("for-of", {
ITERATOR_KEY: generateUid("iterator"), ITERATOR_KEY: generateUid("iterator"),
STEP_KEY: generateUid("step"), STEP_KEY: generateUid("step"),
OBJECT: node.right, OBJECT: node.right,
KEY: node.left.declarations[0].id KEY: key
}); });
var block = node2.body; var block = node2.body;
block.body = block.body.concat(node.body.body);
if (isPattern) {
block.body.push(b.variableDeclaration(declar.kind, [
b.variableDeclarator(declar.declarations[0].id, key)
]));
}
block.body = block.body.concat(node.body.body || []);
var declar = block.body[0]; var declar = block.body[0];
declar.kind = node.left.kind; declar.kind = declar.kind;
return node2; return node2;
}; };

View File

@ -11,15 +11,15 @@ _.each(esprima.Syntax, function (name) {
estraverse.VisitorKeys[name] = estraverse.VisitorKeys[name] || []; estraverse.VisitorKeys[name] = estraverse.VisitorKeys[name] || [];
}); });
exports.parse = function (filename, code, callback) { exports.parse = function (filename, code, callback, opts) {
try { try {
var ast = esprima.parse(code, { var ast = esprima.parse(code, _.extend(opts || {}, {
comment: true, comment: true,
source: filename, source: filename,
tokens: true, tokens: true,
range: true, range: true,
loc: true loc: true
}); }));
estraverse.attachComments(ast, ast.comments, ast.tokens); estraverse.attachComments(ast, ast.comments, ast.tokens);
@ -41,6 +41,10 @@ exports.parse = function (filename, code, callback) {
} }
}; };
exports.isPattern = function (node) {
return node.type === "ArrayPattern" || node.type === "ObjectPattern";
};
exports.generate = function (ast, opts) { exports.generate = function (ast, opts) {
opts = opts || {}; opts = opts || {};
@ -218,6 +222,8 @@ try {
var loc = templatesLoc + "/" + name; var loc = templatesLoc + "/" + name;
var code = fs.readFileSync(loc, "utf8"); var code = fs.readFileSync(loc, "utf8");
exports.templates[key] = exports.removeProperties(exports.parse(loc, code)); exports.templates[key] = exports.removeProperties(exports.parse(loc, code, null, {
tolerant: true
}));
}); });
} }

View File

@ -0,0 +1 @@
[a, b] = f();

View File

@ -0,0 +1,3 @@
var _ref = f();
a = _ref[0];
b = _ref[1];

View File

@ -0,0 +1,3 @@
for (var [name, value] in obj) {
print("Name: " + name + ", Value: " + value);
}

View File

@ -0,0 +1,4 @@
for (var name in obj) {
var value = obj[name];
print("Name: " + name + ", Value: " + value);
}

View File

@ -0,0 +1,3 @@
for (var [ name, before, after ] of this.test.expectation.registers) {
}

View File

@ -0,0 +1,5 @@
for (var _iterator = this.test.expectation.registers[Symbol.iterator](), _step; !(_step = _iterator.next()).done;) {
var name = _step.value[0];
var before = _step.value[1];
var after = _step.value[2];
}