Skip to content

Commit

Permalink
Fix binding rest element semantics in ES6/ES7+
Browse files Browse the repository at this point in the history
  • Loading branch information
RReverser committed May 19, 2017
1 parent 79acac0 commit d8769e8
Show file tree
Hide file tree
Showing 4 changed files with 14 additions and 12 deletions.
2 changes: 1 addition & 1 deletion src/expression.js
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,7 @@ pp.parseParenAndDistinguishExpression = function(canBeArrow) {
break
} else if (this.type === tt.ellipsis) {
spreadStart = this.start
exprList.push(this.parseParenItem(this.parseRest()))
exprList.push(this.parseParenItem(this.parseRest(true)))
if (this.type === tt.comma) this.raise(this.start, "Comma is not permitted after the rest element")
break
} else {
Expand Down
14 changes: 8 additions & 6 deletions src/lval.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ pp.toAssignableList = function(exprList, isBinding) {
--end
}

if (isBinding && last && last.type === "RestElement" && last.argument.type !== "Identifier")
if (this.options.ecmaVersion === 6 && isBinding && last && last.type === "RestElement" && last.argument.type !== "Identifier")
this.unexpected(last.argument.start)
}
for (let i = 0; i < end; i++) {
Expand All @@ -95,13 +95,15 @@ pp.parseSpread = function(refDestructuringErrors) {
return this.finishNode(node, "SpreadElement")
}

pp.parseRest = function(allowNonIdent) {
pp.parseRest = function(isBinding) {
let node = this.startNode()
this.next()

// RestElement inside of a function parameter must be an identifier
if (allowNonIdent) node.argument = this.type === tt.name ? this.parseIdent() : this.unexpected()
else node.argument = this.type === tt.name || this.type === tt.bracketL ? this.parseBindingAtom() : this.unexpected()
if (this.options.ecmaVersion === 6 && isBinding && this.type !== tt.name)
this.unexpected()

node.argument = this.parseBindingAtom()

return this.finishNode(node, "RestElement")
}
Expand All @@ -128,7 +130,7 @@ pp.parseBindingAtom = function() {
}
}

pp.parseBindingList = function(close, allowEmpty, allowTrailingComma, allowNonIdent) {
pp.parseBindingList = function(close, allowEmpty, allowTrailingComma) {
let elts = [], first = true
while (!this.eat(close)) {
if (first) first = false
Expand All @@ -138,7 +140,7 @@ pp.parseBindingList = function(close, allowEmpty, allowTrailingComma, allowNonId
} else if (allowTrailingComma && this.afterTrailingComma(close)) {
break
} else if (this.type === tt.ellipsis) {
let rest = this.parseRest(allowNonIdent)
let rest = this.parseRest(true)
this.parseBindingListItem(rest)
elts.push(rest)
if (this.type === tt.comma) this.raise(this.start, "Comma is not permitted after the rest element")
Expand Down
2 changes: 1 addition & 1 deletion src/statement.js
Original file line number Diff line number Diff line change
Expand Up @@ -500,7 +500,7 @@ pp.parseFunction = function(node, isStatement, allowExpressionBody, isAsync) {

pp.parseFunctionParams = function(node) {
this.expect(tt.parenL)
node.params = this.parseBindingList(tt.parenR, false, this.options.ecmaVersion >= 8, true)
node.params = this.parseBindingList(tt.parenR, false, this.options.ecmaVersion >= 8)
this.checkYieldAwaitInDefaultParams()
}

Expand Down
8 changes: 4 additions & 4 deletions test/tests-harmony.js
Original file line number Diff line number Diff line change
Expand Up @@ -10951,7 +10951,7 @@ test("({ x(...[ a, b ]){} })", {
end: {line: 1, column: 22}
}
}, {
ecmaVersion: 6,
ecmaVersion: 7,
ranges: true,
locations: true
});
Expand Down Expand Up @@ -11187,7 +11187,7 @@ test("({ x({ a: { w, x }, b: [y, z] }, ...[a, b, c]){} })", {
end: {line: 1, column: 51}
}
}, {
ecmaVersion: 6,
ecmaVersion: 7,
ranges: true,
locations: true
});
Expand Down Expand Up @@ -12353,7 +12353,7 @@ test("var [a, ...[b, c]] = d", {
end: {line: 1, column: 22}
}
}, {
ecmaVersion: 6,
ecmaVersion: 7,
ranges: true,
locations: true
});
Expand Down Expand Up @@ -13051,7 +13051,7 @@ testFail("([ 5 ]) => {}", "Assigning to rvalue (1:3)", {ecmaVersion: 6});

testFail("({ 5 }) => {}", "Unexpected token (1:5)", {ecmaVersion: 6});

testFail("(...[ 5 ]) => {}", "Unexpected token (1:6)", {ecmaVersion: 6});
testFail("(...[ 5 ]) => {}", "Unexpected token (1:6)", {ecmaVersion: 7});

test("[...{ a }] = b", {}, {ecmaVersion: 6});

Expand Down

0 comments on commit d8769e8

Please sign in to comment.