Fix default parameter - rest parameter edge case (#3572)

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.
This commit is contained in:
Justin Ridgewell
2016-12-16 10:53:52 -05:00
committed by Henry Zhu
parent 196cdd4dce
commit 852348d700
4 changed files with 56 additions and 0 deletions

View File

@@ -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 })) {

View File

@@ -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)

View File

@@ -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)

View File

@@ -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);