add support for break and continue in block binding
This commit is contained in:
@@ -3,6 +3,8 @@ var util = require("../util");
|
||||
var b = require("ast-types").builders;
|
||||
var _ = require("lodash");
|
||||
|
||||
var funcTypes = ["FunctionDeclaration", "FunctionExpression"];
|
||||
|
||||
var isLet = function (node) {
|
||||
if (node && node.type === "VariableDeclaration" && node.kind === "let") {
|
||||
node.kind = "var";
|
||||
@@ -22,9 +24,7 @@ var hasLet = function (nodes) {
|
||||
};
|
||||
|
||||
exports.Program = function (node) {
|
||||
if (hasLet(node.body)) {
|
||||
node.body = buildNode(node.body);
|
||||
}
|
||||
if (hasLet(node.body)) node.body = buildNode(node.body);
|
||||
};
|
||||
|
||||
exports.BlockStatement = function (node, parent) {
|
||||
@@ -33,7 +33,31 @@ exports.BlockStatement = function (node, parent) {
|
||||
// ignore if we're the body of a closure already
|
||||
if (parent.type === "FunctionExpression") return;
|
||||
|
||||
node.body = buildNode(node.body);
|
||||
var body = node.body;
|
||||
node.body = buildNode(node.body, true);
|
||||
|
||||
var container = _.last(node.body);
|
||||
traverse.replace(container, function (node) {
|
||||
if (node.type === "ContinueStatement") {
|
||||
return b.returnStatement(null);
|
||||
}
|
||||
}, funcTypes);
|
||||
|
||||
if (traverse.hasType(body, "BreakStatement", funcTypes)) {
|
||||
var id = b.identifier("_break");
|
||||
|
||||
node.body.unshift(b.variableDeclaration("var", [
|
||||
b.variableDeclarator(id, b.literal(false))
|
||||
]));
|
||||
|
||||
traverse.replace(container, function (node) {
|
||||
if (node.type === "BreakStatement") {
|
||||
return b.returnStatement(b.assignmentExpression("=", id, b.literal(true)));
|
||||
}
|
||||
}, funcTypes);
|
||||
|
||||
node.body.push(b.ifStatement(id, b.breakStatement()));
|
||||
}
|
||||
};
|
||||
|
||||
exports.ForOfStatement =
|
||||
@@ -45,7 +69,7 @@ exports.ForStatement = function (node) {
|
||||
if (isLet(node.init)) return buildNode(node);
|
||||
};
|
||||
|
||||
var buildNode = function (node) {
|
||||
var buildNode = function (node, isBlock) {
|
||||
var nodes = [];
|
||||
|
||||
// hoist normal variable declarations
|
||||
@@ -55,9 +79,11 @@ var buildNode = function (node) {
|
||||
if (node._ignoreBlockBindingHoist) return node;
|
||||
|
||||
if (node.type === "VariableDeclaration" && node.kind === "var") {
|
||||
nodes.push(b.variableDeclaration("var", node.declarations.map(function (declar) {
|
||||
var declars = node.declarations.map(function (declar) {
|
||||
return b.variableDeclarator(declar.id, null);
|
||||
})));
|
||||
});
|
||||
|
||||
nodes.push(b.variableDeclaration("var", declars));
|
||||
|
||||
return node.declarations.map(function (declar) {
|
||||
return util.template("assign", {
|
||||
@@ -80,7 +106,8 @@ var buildNode = function (node) {
|
||||
|
||||
var block = b.blockStatement([]);
|
||||
block.body = node;
|
||||
var func = b.functionExpression(null, [], block, false)
|
||||
|
||||
var func = b.functionExpression(null, [], block, false);
|
||||
|
||||
var templateName = "function-call";
|
||||
if (traverse.hasType(node, "ThisExpression")) {
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
var VISITOR_KEYS = require("./visitor-keys");
|
||||
var _ = require("lodash");
|
||||
|
||||
var traverse = module.exports = function (parent, callback) {
|
||||
var traverse = module.exports = function (parent, callback, blacklistTypes) {
|
||||
|
||||
if (_.isArray(parent)) {
|
||||
_.each(parent, function (node) {
|
||||
traverse(node, callback);
|
||||
traverse(node, callback, blacklistTypes);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
var keys = VISITOR_KEYS[parent.type] || [];
|
||||
blacklistTypes = blacklistTypes || [];
|
||||
|
||||
_.each(keys, function (key) {
|
||||
var nodes = parent[key];
|
||||
@@ -20,6 +22,7 @@ var traverse = module.exports = function (parent, callback) {
|
||||
|
||||
// strict references in case the callback modified/replaced the node
|
||||
|
||||
if (blacklistTypes.indexOf(obj[key].type) >= 0) return;
|
||||
var result = callback(obj[key], parent, obj, key);
|
||||
if (result === false) return;
|
||||
|
||||
@@ -47,12 +50,15 @@ var traverse = module.exports = function (parent, callback) {
|
||||
|
||||
traverse.Delete = {};
|
||||
|
||||
traverse.hasType = function (tree, type) {
|
||||
traverse.hasType = function (tree, type, blacklistTypes) {
|
||||
if (tree.type === type) return true;
|
||||
|
||||
var has = false;
|
||||
blacklistTypes = blacklistTypes || []
|
||||
|
||||
if (_.isArray(tree)) {
|
||||
return !!_.find(tree, function (node) {
|
||||
return traverse.hasType(node, type);
|
||||
return traverse.hasType(node, type, blacklistTypes);
|
||||
});
|
||||
} else {
|
||||
traverse(tree, function (node) {
|
||||
@@ -60,7 +66,7 @@ traverse.hasType = function (tree, type) {
|
||||
has = true;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}, blacklistTypes);
|
||||
}
|
||||
|
||||
return has;
|
||||
@@ -69,6 +75,7 @@ traverse.hasType = function (tree, type) {
|
||||
traverse.replace = function (node, callback) {
|
||||
traverse(node, function (node, parent, obj, key) {
|
||||
var result = callback(node, parent);
|
||||
if (result === false) return false;
|
||||
if (result != null) obj[key] = result;
|
||||
});
|
||||
};
|
||||
|
||||
6
test/fixtures/block-binding/for-in-block-wrap-break/actual.js
vendored
Normal file
6
test/fixtures/block-binding/for-in-block-wrap-break/actual.js
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
var arr = [1, 2, 3];
|
||||
for (let i in arr) {
|
||||
let val = arr[i];
|
||||
console.log(val * 2);
|
||||
break;
|
||||
}
|
||||
16
test/fixtures/block-binding/for-in-block-wrap-break/expected.js
vendored
Normal file
16
test/fixtures/block-binding/for-in-block-wrap-break/expected.js
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
var arr = [
|
||||
1,
|
||||
2,
|
||||
3
|
||||
];
|
||||
(function () {
|
||||
for (var i in arr) {
|
||||
var _break = false;
|
||||
(function () {
|
||||
var val = arr[i];
|
||||
console.log(val * 2);
|
||||
return _break = true;
|
||||
}());
|
||||
if (_break) break;
|
||||
}
|
||||
}());
|
||||
6
test/fixtures/block-binding/for-in-block-wrap-continue/actual.js
vendored
Normal file
6
test/fixtures/block-binding/for-in-block-wrap-continue/actual.js
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
var arr = [1, 2, 3];
|
||||
for (let i in arr) {
|
||||
let val = arr[i];
|
||||
console.log(val * 2);
|
||||
continue;
|
||||
}
|
||||
14
test/fixtures/block-binding/for-in-block-wrap-continue/expected.js
vendored
Normal file
14
test/fixtures/block-binding/for-in-block-wrap-continue/expected.js
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
var arr = [
|
||||
1,
|
||||
2,
|
||||
3
|
||||
];
|
||||
(function () {
|
||||
for (var i in arr) {
|
||||
(function () {
|
||||
var val = arr[i];
|
||||
console.log(val * 2);
|
||||
return;
|
||||
}());
|
||||
}
|
||||
}());
|
||||
Reference in New Issue
Block a user