From 852348d700d5f171d8c0526bbc7eae53c70218f5 Mon Sep 17 00:00:00 2001 From: Justin Ridgewell Date: Fri, 16 Dec 2016 10:53:52 -0500 Subject: [PATCH] Fix default parameter - rest parameter edge case (#3572) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the rest parameter shared the same name as a default identifier for a param, the loop would be hoisted outside the function! ```js var a = 1; for (var _len = arguments.length, a = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { a[_key - 1] = arguments[_key]; } function foo2() { var b = arguments.length <= 0 || arguments[0] === undefined ? a : arguments[0]; assert.equal(b, 1); } foo2(undefined, 2); ``` And if you tried to reference any index or `#length`, it’d blow up and refuse to transpile. --- .../src/rest.js | 5 +++++ .../parameters/default-rest/actual.js | 15 +++++++++++++ .../fixtures/parameters/default-rest/exec.js | 15 +++++++++++++ .../parameters/default-rest/expected.js | 21 +++++++++++++++++++ 4 files changed, 56 insertions(+) create mode 100644 packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/default-rest/actual.js create mode 100644 packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/default-rest/exec.js create mode 100644 packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/default-rest/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 70b3666770..bda77d8c11 100644 --- a/packages/babel-plugin-transform-es2015-parameters/src/rest.js +++ b/packages/babel-plugin-transform-es2015-parameters/src/rest.js @@ -69,6 +69,11 @@ let memberExpressionOptimisationVisitor = { } else { let {parentPath} = path; + // Is this identifier the right hand side of a default parameter? + if (parentPath.listKey === "params" && parentPath.key < state.offset) { + return; + } + // ex: `args[0]` // ex: `args.whatever` if (parentPath.isMemberExpression({ object: node })) { diff --git a/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/default-rest/actual.js b/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/default-rest/actual.js new file mode 100644 index 0000000000..1f3eeb12c8 --- /dev/null +++ b/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/default-rest/actual.js @@ -0,0 +1,15 @@ +const a = 1; +function rest(b = a, ...a) { + assert.equal(b, 1); +} +rest(undefined, 2) + +function rest2(b = a, ...a) { + assert.equal(a[0], 2); +} +rest2(undefined, 2) + +function rest3(b = a, ...a) { + assert.equal(a.length, 1); +} +rest3(undefined, 2) diff --git a/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/default-rest/exec.js b/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/default-rest/exec.js new file mode 100644 index 0000000000..1f3eeb12c8 --- /dev/null +++ b/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/default-rest/exec.js @@ -0,0 +1,15 @@ +const a = 1; +function rest(b = a, ...a) { + assert.equal(b, 1); +} +rest(undefined, 2) + +function rest2(b = a, ...a) { + assert.equal(a[0], 2); +} +rest2(undefined, 2) + +function rest3(b = a, ...a) { + assert.equal(a.length, 1); +} +rest3(undefined, 2) diff --git a/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/default-rest/expected.js b/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/default-rest/expected.js new file mode 100644 index 0000000000..f74dcedeed --- /dev/null +++ b/packages/babel-plugin-transform-es2015-parameters/test/fixtures/parameters/default-rest/expected.js @@ -0,0 +1,21 @@ +var a = 1; +function rest() { + var b = arguments.length <= 0 || arguments[0] === undefined ? a : arguments[0]; + + assert.equal(b, 1); +} +rest(undefined, 2); + +function rest2() { + var b = arguments.length <= 0 || arguments[0] === undefined ? a : arguments[0]; + + assert.equal(arguments.length <= 1 ? undefined : arguments[1], 2); +} +rest2(undefined, 2); + +function rest3() { + var b = arguments.length <= 0 || arguments[0] === undefined ? a : arguments[0]; + + assert.equal(arguments.length - 1, 1); +} +rest3(undefined, 2);