From 8decefe8bc414bc5d09a1b05e6752b837b3cfbf2 Mon Sep 17 00:00:00 2001 From: Buu Nguyen Date: Tue, 11 Jul 2017 20:26:57 -0700 Subject: [PATCH] Fix bug incorrect dereferencing rest argument (#5810) * Fix bug incorrect dereferencing rest argument * Fix pure path * Minor refactor --- .../src/rest.js | 28 +++++++++++++------ .../parameters/regression-4348/expected.js | 2 +- .../parameters/regression-5787/actual.js | 10 +++++++ .../parameters/regression-5787/exec.js | 12 ++++++++ .../parameters/regression-5787/expected.js | 12 ++++++++ .../parameters/rest-length/expected.js | 2 +- 6 files changed, 56 insertions(+), 10 deletions(-) create mode 100644 packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/regression-5787/actual.js create mode 100644 packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/regression-5787/exec.js create mode 100644 packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/regression-5787/expected.js diff --git a/packages/babel-plugin-transform-es2015-parameters/src/rest.js b/packages/babel-plugin-transform-es2015-parameters/src/rest.js index 141fa582c7..e74df03e97 100644 --- a/packages/babel-plugin-transform-es2015-parameters/src/rest.js +++ b/packages/babel-plugin-transform-es2015-parameters/src/rest.js @@ -12,11 +12,11 @@ const buildRest = template(` `); const restIndex = template(` - ARGUMENTS.length <= INDEX ? undefined : ARGUMENTS[INDEX] + (INDEX < OFFSET || ARGUMENTS.length <= INDEX) ? undefined : ARGUMENTS[INDEX] `); const restIndexImpure = template(` - REF = INDEX, ARGUMENTS.length <= REF ? undefined : ARGUMENTS[REF] + REF = INDEX, (REF < OFFSET || ARGUMENTS.length <= REF) ? undefined : ARGUMENTS[REF] `); const restLength = template(` @@ -159,6 +159,7 @@ function hasRest(node) { } function optimiseIndexGetter(path, argsId, offset) { + const offsetLiteral = t.numericLiteral(offset); let index; if (t.isNumericLiteral(path.parent.property)) { @@ -167,11 +168,7 @@ function optimiseIndexGetter(path, argsId, offset) { // Avoid unnecessary '+ 0' index = path.parent.property; } else { - index = t.binaryExpression( - "+", - path.parent.property, - t.numericLiteral(offset), - ); + index = t.binaryExpression("+", path.parent.property, offsetLiteral); } const { scope } = path; @@ -181,17 +178,32 @@ function optimiseIndexGetter(path, argsId, offset) { path.parentPath.replaceWith( restIndexImpure({ ARGUMENTS: argsId, + OFFSET: offsetLiteral, INDEX: index, REF: temp, }), ); } else { - path.parentPath.replaceWith( + const parentPath = path.parentPath; + parentPath.replaceWith( restIndex({ ARGUMENTS: argsId, + OFFSET: offsetLiteral, INDEX: index, }), ); + + // See if we can statically evaluate the first test (i.e. index < offset) + // and optimize the AST accordingly. + const offsetTestPath = parentPath.get("test").get("left"); + const valRes = offsetTestPath.evaluate(); + if (valRes.confident) { + if (valRes.value === true) { + parentPath.replaceWith(parentPath.scope.buildUndefinedNode()); + } else { + parentPath.get("test").replaceWith(parentPath.get("test").get("right")); + } + } } } diff --git a/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/regression-4348/expected.js b/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/regression-4348/expected.js index 72353b43e3..e6e8f4c01a 100644 --- a/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/regression-4348/expected.js +++ b/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/regression-4348/expected.js @@ -2,5 +2,5 @@ function first() { var _ref; var index = 0; - return _ref = index++, arguments.length <= _ref ? undefined : arguments[_ref]; + return _ref = index++, _ref < 0 || arguments.length <= _ref ? undefined : arguments[_ref]; } diff --git a/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/regression-5787/actual.js b/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/regression-5787/actual.js new file mode 100644 index 0000000000..2708aceb5e --- /dev/null +++ b/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/regression-5787/actual.js @@ -0,0 +1,10 @@ +function f(a, ...rest) { + let b = rest[rest.length - 3]; + let c = rest[rest.length - 2]; + let d = rest[rest.length - 1]; + return [a, b, c, d]; +} + +function f(a, ...rest) { + return rest[-1]; +} diff --git a/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/regression-5787/exec.js b/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/regression-5787/exec.js new file mode 100644 index 0000000000..796aa79b8e --- /dev/null +++ b/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/regression-5787/exec.js @@ -0,0 +1,12 @@ +function f1(a, ...rest) { + let b = rest[rest.length - 3]; + let c = rest[rest.length - 2]; + let d = rest[rest.length - 1]; + return [a, b, c, d]; +} +assert.deepEqual(f1(1, 2), [1, undefined, undefined, 2]) + +function f2(a, ...rest) { + return rest[-1]; +} +assert.equal(f2(1, 2), undefined) diff --git a/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/regression-5787/expected.js b/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/regression-5787/expected.js new file mode 100644 index 0000000000..a63c255355 --- /dev/null +++ b/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/regression-5787/expected.js @@ -0,0 +1,12 @@ +function f(a) { + var _ref, _ref2, _ref3; + + var b = (_ref = (arguments.length <= 1 ? 0 : arguments.length - 1) - 3 + 1, _ref < 1 || arguments.length <= _ref ? undefined : arguments[_ref]); + var c = (_ref2 = (arguments.length <= 1 ? 0 : arguments.length - 1) - 2 + 1, _ref2 < 1 || arguments.length <= _ref2 ? undefined : arguments[_ref2]); + var d = (_ref3 = (arguments.length <= 1 ? 0 : arguments.length - 1) - 1 + 1, _ref3 < 1 || arguments.length <= _ref3 ? undefined : arguments[_ref3]); + return [a, b, c, d]; +} + +function f(a) { + return void 0; +} 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 0ce220bc76..966fb11f0c 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 @@ -2,7 +2,7 @@ var t = function (f) { var _ref; arguments.length <= 1 ? undefined : arguments[1]; - _ref = (arguments.length <= 1 ? 0 : arguments.length - 1) - 1 + 1, arguments.length <= _ref ? undefined : arguments[_ref]; + _ref = (arguments.length <= 1 ? 0 : arguments.length - 1) - 1 + 1, _ref < 1 || arguments.length <= _ref ? undefined : arguments[_ref]; }; function t(f) {