handle TCO for calls that exceed the functions parameter count - fixes #1589

This commit is contained in:
Sebastian McKenzie 2015-05-21 01:21:49 +01:00
parent f2f6bbb02c
commit 348c0d2542
3 changed files with 51 additions and 2 deletions

View File

@ -51,7 +51,7 @@ var visitor = {
}, },
ReferencedIdentifier(node, parent, scope, state) { ReferencedIdentifier(node, parent, scope, state) {
if (node.name === "arguments" && !state.isShadowed) { if (node.name === "arguments" && (!state.isShadowed || node._shadowedFunctionLiteral)) {
state.needsArguments = true; state.needsArguments = true;
state.argumentsPaths.push(this); state.argumentsPaths.push(this);
} }
@ -211,6 +211,7 @@ class TailCallTransformer {
var decl = t.variableDeclarator(this.argumentsId); var decl = t.variableDeclarator(this.argumentsId);
if (this.argumentsId) { if (this.argumentsId) {
decl.init = t.identifier("arguments"); decl.init = t.identifier("arguments");
decl.init._shadowedFunctionLiteral = true;
} }
topVars.push(decl); topVars.push(decl);
} }
@ -291,7 +292,8 @@ class TailCallTransformer {
} }
subTransformCallExpression(node) { subTransformCallExpression(node) {
var callee = node.callee, thisBinding, args; var callee = node.callee;
var thisBinding, args;
if (t.isMemberExpression(callee, { computed: false }) && t.isIdentifier(callee.property)) { if (t.isMemberExpression(callee, { computed: false }) && t.isIdentifier(callee.property)) {
switch (callee.property.name) { switch (callee.property.name) {
@ -301,6 +303,7 @@ class TailCallTransformer {
case "apply": case "apply":
args = node.arguments[1] || t.identifier("undefined"); args = node.arguments[1] || t.identifier("undefined");
this.needsArguments = true;
break; break;
default: default:
@ -334,6 +337,10 @@ class TailCallTransformer {
args = t.arrayExpression(node.arguments); args = t.arrayExpression(node.arguments);
} }
if (t.isArrayExpression(args) && args.elements.length > this.node.params.length) {
this.needsArguments = true;
}
var argumentsId = this.getArgumentsId(); var argumentsId = this.getArgumentsId();
var params = this.getParams(); var params = this.getParams();

View File

@ -0,0 +1,9 @@
var count = (i = 10) => {
if (!i) return;
return count(i - 1);
};
function count2(i = 10) {
if (!i) return;
return count2(i - 1);
}

View File

@ -0,0 +1,33 @@
"use strict";
var count = function count() {
var _arguments = arguments;
var _again = true;
_function: while (_again) {
i = undefined;
_again = false;
var i = _arguments[0] === undefined ? 10 : _arguments[0];
if (!i) return;
_arguments = [i - 1];
_again = true;
continue _function;
}
};
function count2() {
var _arguments2 = arguments;
var _again2 = true;
_function2: while (_again2) {
i = undefined;
_again2 = false;
var i = _arguments2[0] === undefined ? 10 : _arguments2[0];
if (!i) return;
_arguments2 = [i - 1];
_again2 = true;
continue _function2;
}
}