diff --git a/packages/babel-plugin-transform-es2015-parameters/src/rest.js b/packages/babel-plugin-transform-es2015-parameters/src/rest.js index 50072a0d04..0cc5a8c83a 100644 --- a/packages/babel-plugin-transform-es2015-parameters/src/rest.js +++ b/packages/babel-plugin-transform-es2015-parameters/src/rest.js @@ -11,6 +11,10 @@ let buildRest = template(` } `); +let loadRest = template(` + ARGUMENTS.length <= KEY || ARGUMENTS[KEY] === undefined ? undefined : ARGUMENTS[KEY] +`); + let memberExpressionOptimisationVisitor = { Scope(path, state) { // check if this scope has a local binding that will shadow the rest parameter @@ -84,21 +88,6 @@ let memberExpressionOptimisationVisitor = { } }; -function optimiseMemberExpression(parent, offset) { - if (offset === 0) return; - - let newExpr; - let prop = parent.property; - - if (t.isLiteral(prop)) { - prop.value += offset; - prop.raw = String(prop.value); - } else { // // UnaryExpression, BinaryExpression - newExpr = t.binaryExpression("+", prop, t.numericLiteral(offset)); - parent.property = newExpr; - } -} - function hasRest(node) { return t.isRestElement(node.params[node.params.length - 1]); } @@ -116,16 +105,25 @@ export let visitor = { // otherwise `arguments` will be remapped in arrow functions argsId._shadowedFunctionLiteral = path; - // support patterns - if (t.isPattern(rest)) { - let pattern = rest; - rest = scope.generateUidIdentifier("ref"); + function optimiseCandidate(parent, parentPath, offset) { + if (t.isReturnStatement(parentPath.parent) || t.isIdentifier(parentPath.parent.id)) { + parentPath.replaceWith(loadRest({ + ARGUMENTS: argsId, + KEY: t.numericLiteral(parent.property.value + offset) + })); + } else { + if (offset === 0) return; + let newExpr; + let prop = parent.property; - let declar = t.variableDeclaration("let", pattern.elements.map(function (elem, index) { - let accessExpr = t.memberExpression(rest, t.numericLiteral(index), true); - return t.variableDeclarator(elem, accessExpr); - })); - node.body.body.unshift(declar); + if (t.isLiteral(prop)) { + prop.value += offset; + prop.raw = String(prop.value); + } else { // UnaryExpression, BinaryExpression + newExpr = t.binaryExpression("+", prop, t.numericLiteral(offset)); + parent.property = newExpr; + } + } } // check and optimise for extremely common cases @@ -153,9 +151,7 @@ export let visitor = { if (state.candidates.length) { for (let candidate of (state.candidates: Array)) { candidate.replaceWith(argsId); - if (candidate.parentPath.isMemberExpression()) { - optimiseMemberExpression(candidate.parent, state.offset); - } + optimiseCandidate(candidate.parent, candidate.parentPath, state.offset); } } return; @@ -166,8 +162,6 @@ export let visitor = { // deopt shadowed functions as transforms like regenerator may try touch the allocation loop state.deopted = state.deopted || !!node.shadow; - // - let start = t.numericLiteral(node.params.length); let key = scope.generateUidIdentifier("key"); let len = scope.generateUidIdentifier("len"); diff --git a/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/rest-arrow-functions/actual.js b/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/rest-arrow-functions/actual.js index 43378f3344..e9d376e92b 100644 --- a/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/rest-arrow-functions/actual.js +++ b/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/rest-arrow-functions/actual.js @@ -14,7 +14,7 @@ var somefun = function () { }; var _d = args1[1]; }; - let get1stArg = (...args) => args[0]; + let get3rdArg = (...args) => args[2]; } function demo1(...args) { diff --git a/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/rest-arrow-functions/expected.js b/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/rest-arrow-functions/expected.js index 62c2f6d931..171f1d01a0 100644 --- a/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/rest-arrow-functions/expected.js +++ b/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/rest-arrow-functions/expected.js @@ -1,21 +1,21 @@ var concat = function () { - var x = arguments[0]; - var y = arguments[1]; + var x = arguments.length <= 0 || arguments[0] === undefined ? undefined : arguments[0]; + var y = arguments.length <= 1 || arguments[1] === undefined ? undefined : arguments[1]; }; var somefun = function () { var get2ndArg = function (a, b) { - var _b = arguments[2]; + var _b = arguments.length <= 2 || arguments[2] === undefined ? undefined : arguments[2]; var somef = function (x, y, z) { - var _a = arguments[3]; + var _a = arguments.length <= 3 || arguments[3] === undefined ? undefined : arguments[3]; }; var somefg = function (c, d, e, f) { - var _a = arguments[4]; + var _a = arguments.length <= 4 || arguments[4] === undefined ? undefined : arguments[4]; }; - var _d = arguments[3]; + var _d = arguments.length <= 3 || arguments[3] === undefined ? undefined : arguments[3]; }; - var get1stArg = function () { - return arguments[0]; + var get3rdArg = function () { + return arguments.length <= 2 || arguments[2] === undefined ? undefined : arguments[2]; }; }; diff --git a/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/rest-member-expression-optimisation/expected.js b/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/rest-member-expression-optimisation/expected.js index dbae1250ad..9a680b3ad4 100644 --- a/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/rest-member-expression-optimisation/expected.js +++ b/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/rest-member-expression-optimisation/expected.js @@ -1,9 +1,9 @@ var t = function () { - var x = arguments[0]; - var y = arguments[1]; + var x = arguments.length <= 0 || arguments[0] === undefined ? undefined : arguments[0]; + var y = arguments.length <= 1 || arguments[1] === undefined ? undefined : arguments[1]; }; function t() { - var x = arguments[0]; - var y = arguments[1]; + var x = arguments.length <= 0 || arguments[0] === undefined ? undefined : arguments[0]; + var y = arguments.length <= 1 || arguments[1] === undefined ? undefined : arguments[1]; }