better arguments aliasing for arrow functions, add it to block binding - fixes #52
This commit is contained in:
parent
6a392be338
commit
73c491ecb4
@ -19,8 +19,7 @@ exports.ArrowFunctionExpression = function (node) {
|
||||
|
||||
exports.FunctionDeclaration =
|
||||
exports.FunctionExpression = function (node, parent, opts, generateUid) {
|
||||
var hasArguments = false;
|
||||
var id;
|
||||
var argumentsId;
|
||||
|
||||
// traverse the function and find all arrow functions
|
||||
traverse(node, function (node) {
|
||||
@ -28,22 +27,15 @@ exports.FunctionExpression = function (node, parent, opts, generateUid) {
|
||||
|
||||
// traverse all child nodes of this arrow function and find a sole arguments
|
||||
// identifier
|
||||
traverse(node, function (node, parent) {
|
||||
if (node.type === "Identifier" && node.name === "arguments" &&
|
||||
parent.type !== "MemberExpression") {
|
||||
hasArguments = true;
|
||||
id = id || b.identifier(generateUid("arguments"));
|
||||
return id;
|
||||
}
|
||||
}, traverse.FUNCTION_TYPES);
|
||||
argumentsId = util.aliasArguments(generateUid, node, argumentsId);
|
||||
|
||||
return false;
|
||||
}, ["FunctionDeclaration", "FunctionExpression"]);
|
||||
|
||||
if (hasArguments) {
|
||||
if (argumentsId) {
|
||||
util.ensureBlock(node);
|
||||
node.body.body.unshift(b.variableDeclaration("var", [
|
||||
b.variableDeclarator(id, b.identifier("arguments"))
|
||||
b.variableDeclarator(argumentsId, b.identifier("arguments"))
|
||||
]));
|
||||
}
|
||||
};
|
||||
|
||||
@ -23,8 +23,8 @@ var hasLet = function (nodes) {
|
||||
return has;
|
||||
};
|
||||
|
||||
exports.Program = function (node) {
|
||||
if (hasLet(node.body)) node.body = buildNode(node.body).node;
|
||||
exports.Program = function (node, parent, opts, generateUid) {
|
||||
if (hasLet(node.body)) node.body = buildNode(node.body, generateUid).node;
|
||||
};
|
||||
|
||||
exports.BlockStatement = function (node, parent, opts, generateUid) {
|
||||
@ -35,7 +35,7 @@ exports.BlockStatement = function (node, parent, opts, generateUid) {
|
||||
|
||||
var body = node.body;
|
||||
|
||||
var built = buildNode(node.body, true);
|
||||
var built = buildNode(node.body, generateUid);
|
||||
node.body = built.node;
|
||||
|
||||
traverse(built.body, function (node) {
|
||||
@ -62,13 +62,13 @@ exports.BlockStatement = function (node, parent, opts, generateUid) {
|
||||
};
|
||||
|
||||
var buildForStatement = function (key) {
|
||||
return function (node, parent) {
|
||||
return function (node, parent, opts, generateUid) {
|
||||
if (isLet(node[key])) {
|
||||
if (parent.type === "LabeledStatement") {
|
||||
throw util.errorWithNode(parent, "Label statements not supported with block binding yet.");
|
||||
}
|
||||
|
||||
return buildNode(node).node;
|
||||
return buildNode(node, generateUid).node;
|
||||
}
|
||||
};
|
||||
};
|
||||
@ -76,7 +76,7 @@ var buildForStatement = function (key) {
|
||||
exports.ForOfStatement = exports.ForInStatement = buildForStatement("left");
|
||||
exports.ForStatement = buildForStatement("init");
|
||||
|
||||
var buildNode = function (node) {
|
||||
var buildNode = function (node, generateUid) {
|
||||
var nodes = [];
|
||||
|
||||
// hoist normal variable declarations
|
||||
@ -113,17 +113,27 @@ var buildNode = function (node) {
|
||||
|
||||
//
|
||||
|
||||
var argumentsId = util.aliasArguments(generateUid, node);
|
||||
|
||||
if (argumentsId) {
|
||||
nodes.push(b.variableDeclaration("var", [
|
||||
b.variableDeclarator(argumentsId, b.identifier("arguments"))
|
||||
]));
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
var block = b.blockStatement([]);
|
||||
block.body = node;
|
||||
|
||||
var func = b.functionExpression(null, [], block, false);
|
||||
|
||||
//
|
||||
|
||||
var templateName = "function-call";
|
||||
if (traverse.hasType(node, "ThisExpression")) templateName += "-this";
|
||||
if (traverse.hasType(node, "ReturnStatement", traverse.FUNCTION_TYPES)) templateName += "-return";
|
||||
|
||||
//
|
||||
|
||||
nodes.push(util.template(templateName, {
|
||||
FUNCTION: func
|
||||
}, true));
|
||||
|
||||
@ -212,6 +212,28 @@ exports.parse = function (opts, code, callback) {
|
||||
}
|
||||
};
|
||||
|
||||
exports.aliasArguments = function (generateUid, node, id) {
|
||||
var isArgumentIdentifier = function (node) {
|
||||
return node.type === "Identifier" && node.name === "arguments";
|
||||
};
|
||||
|
||||
var getId = function () {
|
||||
return id = id || b.identifier(generateUid("arguments"));
|
||||
};
|
||||
|
||||
traverse(node, function (node, parent) {
|
||||
if (isArgumentIdentifier(node) && parent.type !== "MemberExpression") {
|
||||
return getId();
|
||||
} else if (node.type === "MemberExpression" && isArgumentIdentifier(node.object)) {
|
||||
node.object = getId();
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}, traverse.FUNCTION_TYPES);
|
||||
|
||||
return id;
|
||||
};
|
||||
|
||||
try {
|
||||
exports.templates = require("../../templates.json");
|
||||
} catch (err) {
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
function outer() {
|
||||
function one() {
|
||||
var inner = () => arguments;
|
||||
return [].slice.call(inner());
|
||||
}
|
||||
console.log(outer(1, 2));
|
||||
one(1, 2);
|
||||
|
||||
function outer() {
|
||||
function two() {
|
||||
var inner = () => arguments;
|
||||
|
||||
var another = function () {
|
||||
@ -13,4 +13,22 @@ function outer() {
|
||||
|
||||
return [].slice.call(inner());
|
||||
}
|
||||
console.log(outer(1, 2));
|
||||
two(1, 2);
|
||||
|
||||
function three() {
|
||||
var fn = () => arguments[0] + "bar";
|
||||
return fn();
|
||||
}
|
||||
three("foo");
|
||||
|
||||
function four() {
|
||||
var fn = () => arguments[0].foo + "bar";
|
||||
return fn();
|
||||
}
|
||||
four({ foo: "foo" });
|
||||
|
||||
function five(obj) {
|
||||
var fn = () => obj.arguments[0].foo + "bar";
|
||||
return fn();
|
||||
}
|
||||
five({ arguments: ["foo"] });
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
function outer() {
|
||||
function one() {
|
||||
var _arguments = arguments;
|
||||
var inner = function () { return _arguments; };
|
||||
return [].slice.call(inner());
|
||||
}
|
||||
console.log(outer(1, 2));
|
||||
one(1, 2);
|
||||
|
||||
function outer() {
|
||||
function two() {
|
||||
var _arguments2 = arguments;
|
||||
var inner = function () { return _arguments2; };
|
||||
|
||||
@ -16,4 +16,30 @@ function outer() {
|
||||
|
||||
return [].slice.call(inner());
|
||||
}
|
||||
console.log(outer(1, 2));
|
||||
two(1, 2);
|
||||
|
||||
function three() {
|
||||
var _arguments4 = arguments;
|
||||
var fn = function () {
|
||||
return _arguments4[0] + "bar";
|
||||
};
|
||||
return fn();
|
||||
}
|
||||
three("foo");
|
||||
|
||||
function four() {
|
||||
var _arguments5 = arguments;
|
||||
var fn = function () {
|
||||
return _arguments5[0].foo + "bar";
|
||||
};
|
||||
return fn();
|
||||
}
|
||||
four({ foo: "foo" });
|
||||
|
||||
function five(obj) {
|
||||
var fn = function () {
|
||||
return obj.arguments[0].foo + "bar";
|
||||
};
|
||||
return fn();
|
||||
}
|
||||
five({ arguments: ["foo"] });
|
||||
|
||||
6
test/fixtures/syntax/block-binding/arguments/actual.js
vendored
Normal file
6
test/fixtures/syntax/block-binding/arguments/actual.js
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
(function () {
|
||||
if (true) {
|
||||
let a = arguments[0];
|
||||
console.log(a);
|
||||
}
|
||||
})(1);
|
||||
9
test/fixtures/syntax/block-binding/arguments/expected.js
vendored
Normal file
9
test/fixtures/syntax/block-binding/arguments/expected.js
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
(function () {
|
||||
if (true) {
|
||||
var _arguments = arguments;
|
||||
(function () {
|
||||
var a = _arguments[0];
|
||||
console.log(a);
|
||||
})();
|
||||
}
|
||||
})(1);
|
||||
Loading…
x
Reference in New Issue
Block a user