diff --git a/packages/babel-plugin-transform-es2015-parameters/src/rest.js b/packages/babel-plugin-transform-es2015-parameters/src/rest.js index d0868536b2..b05e7ece4d 100644 --- a/packages/babel-plugin-transform-es2015-parameters/src/rest.js +++ b/packages/babel-plugin-transform-es2015-parameters/src/rest.js @@ -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); diff --git a/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/rest-length/exec.js b/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/rest-length/exec.js new file mode 100644 index 0000000000..7481b53abf --- /dev/null +++ b/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/rest-length/exec.js @@ -0,0 +1,8 @@ +var length = function (a, b, ...items) { + return items.length; +}; + +assert.equal(length(), 0); +assert.equal(length(1), 0); +assert.equal(length(1, 2), 0); +assert.equal(length(1, 2, 3), 1); diff --git a/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/rest-length/expected.js b/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/rest-length/expected.js index 174b8f6d46..2936b88a09 100644 --- a/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/rest-length/expected.js +++ b/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/rest-length/expected.js @@ -1,6 +1,6 @@ var t = function (f) { arguments.length <= 1 ? undefined : arguments[1]; - arguments.length <= arguments.length - 1 - 1 + 1 ? undefined : arguments[arguments.length - 1 - 1 + 1]; + arguments.length <= (arguments.length <= 1 ? 0 : arguments.length - 1) - 1 + 1 ? undefined : arguments[(arguments.length <= 1 ? 0 : arguments.length - 1) - 1 + 1]; }; function t(f) { @@ -11,4 +11,4 @@ function t(f) { items; items[0]; items[items.length - 1]; -} +} \ No newline at end of file diff --git a/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/rest-member-expression-deoptimisation/expected.js b/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/rest-member-expression-deoptimisation/expected.js index 7a07b92415..6036ad8e64 100644 --- a/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/rest-member-expression-deoptimisation/expected.js +++ b/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/rest-member-expression-deoptimisation/expected.js @@ -63,11 +63,11 @@ var b = function () { }; var b = function (foo) { - return (arguments.length - 1) * 2; + return (arguments.length <= 1 ? 0 : arguments.length - 1) * 2; }; var b = function (foo, baz) { - return arguments.length - 2; + return arguments.length <= 2 ? 0 : arguments.length - 2; }; function x() { @@ -193,4 +193,4 @@ function postfixDecrement() { } rest[0]--; -} +} \ No newline at end of file