Fix error in rest parameter length optimization (#3573)

If there aren’t enough arguments to get to the offset index, we would
return an negative length.
This commit is contained in:
Justin Ridgewell
2016-07-12 21:12:45 -04:00
committed by Henry Zhu
parent 57ef3ea8eb
commit 823ffbd87c
4 changed files with 25 additions and 20 deletions

View File

@@ -13,10 +13,14 @@ let buildRest = template(`
}
`);
let loadRest = template(`
let restIndex = template(`
ARGUMENTS.length <= INDEX ? undefined : ARGUMENTS[INDEX]
`);
let restLength = template(`
ARGUMENTS.length <= OFFSET ? 0 : ARGUMENTS.length - OFFSET
`);
let memberExpressionOptimisationVisitor = {
Scope(path, state) {
// check if this scope has a local binding that will shadow the rest parameter
@@ -155,21 +159,18 @@ function optimiseIndexGetter(path, argsId, offset) {
index = t.binaryExpression("+", path.parent.property, t.numericLiteral(offset));
}
path.parentPath.replaceWith(loadRest({
path.parentPath.replaceWith(restIndex({
ARGUMENTS: argsId,
INDEX: index,
}));
}
function optimiseLengthGetter(path, argsLengthExpression, argsId, offset) {
function optimiseLengthGetter(path, argsId, offset) {
if (offset) {
path.parentPath.replaceWith(
t.binaryExpression(
"-",
argsLengthExpression,
t.numericLiteral(offset),
)
);
path.parentPath.replaceWith(restLength({
ARGUMENTS: argsId,
OFFSET: t.numericLiteral(offset),
}));
} else {
path.replaceWith(argsId);
}
@@ -183,10 +184,6 @@ export let visitor = {
let rest = node.params.pop().argument;
let argsId = t.identifier("arguments");
let argsLengthExpression = t.memberExpression(
argsId,
t.identifier("length"),
);
// otherwise `arguments` will be remapped in arrow functions
argsId._shadowedFunctionLiteral = path;
@@ -230,7 +227,7 @@ export let visitor = {
optimiseIndexGetter(path, argsId, state.offset);
break;
case "lengthGetter":
optimiseLengthGetter(path, argsLengthExpression, argsId, state.offset);
optimiseLengthGetter(path, argsId, state.offset);
break;
default:
path.replaceWith(argsId);