diff --git a/src/parser/expression.js b/src/parser/expression.js index 0d4c371938..f8a50c7d84 100644 --- a/src/parser/expression.js +++ b/src/parser/expression.js @@ -691,6 +691,8 @@ pp.parseObj = function (isPattern, refShorthandDefaultPos) { node.properties = []; this.next(); + let firstRestLocation = null; + while (!this.eat(tt.braceR)) { if (first) { first = false; @@ -713,7 +715,21 @@ pp.parseObj = function (isPattern, refShorthandDefaultPos) { prop = this.parseSpread(); prop.type = isPattern ? "RestProperty" : "SpreadProperty"; node.properties.push(prop); - continue; + if (isPattern) { + const position = this.state.start; + if (firstRestLocation !== null) { + this.unexpected(firstRestLocation, "Cannot have multiple rest elements when destructuring"); + } else if (this.eat(tt.braceR)) { + break; + } else if (this.match(tt.comma) && this.lookahead().type === tt.braceR) { + this.unexpected(position, "A trailing comma is not permitted after the rest element"); + } else { + firstRestLocation = position; + continue; + } + } else { + continue; + } } prop.method = false; @@ -753,6 +769,10 @@ pp.parseObj = function (isPattern, refShorthandDefaultPos) { node.properties.push(prop); } + if (firstRestLocation !== null) { + this.unexpected(firstRestLocation, "The rest element has to be the last element when destructuring"); + } + if (decorators.length) { this.raise(this.state.start, "You have trailing decorators with no property"); } diff --git a/test/fixtures/experimental/uncategorised/9/actual.js b/test/fixtures/experimental/object-rest-spread/1/actual.js similarity index 100% rename from test/fixtures/experimental/uncategorised/9/actual.js rename to test/fixtures/experimental/object-rest-spread/1/actual.js diff --git a/test/fixtures/experimental/uncategorised/9/expected.json b/test/fixtures/experimental/object-rest-spread/1/expected.json similarity index 100% rename from test/fixtures/experimental/uncategorised/9/expected.json rename to test/fixtures/experimental/object-rest-spread/1/expected.json diff --git a/test/fixtures/experimental/object-rest-spread/10/actual.js b/test/fixtures/experimental/object-rest-spread/10/actual.js new file mode 100644 index 0000000000..ae868e52ac --- /dev/null +++ b/test/fixtures/experimental/object-rest-spread/10/actual.js @@ -0,0 +1 @@ +let { x, y, } = obj; diff --git a/test/fixtures/experimental/object-rest-spread/10/expected.json b/test/fixtures/experimental/object-rest-spread/10/expected.json new file mode 100644 index 0000000000..bce210e65b --- /dev/null +++ b/test/fixtures/experimental/object-rest-spread/10/expected.json @@ -0,0 +1,211 @@ +{ + "type": "File", + "start": 0, + "end": 20, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 20 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 20, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 20 + } + }, + "sourceType": "script", + "body": [ + { + "type": "VariableDeclaration", + "start": 0, + "end": 20, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 20 + } + }, + "declarations": [ + { + "type": "VariableDeclarator", + "start": 4, + "end": 19, + "loc": { + "start": { + "line": 1, + "column": 4 + }, + "end": { + "line": 1, + "column": 19 + } + }, + "id": { + "type": "ObjectPattern", + "start": 4, + "end": 13, + "loc": { + "start": { + "line": 1, + "column": 4 + }, + "end": { + "line": 1, + "column": 13 + } + }, + "properties": [ + { + "type": "ObjectProperty", + "start": 6, + "end": 7, + "loc": { + "start": { + "line": 1, + "column": 6 + }, + "end": { + "line": 1, + "column": 7 + } + }, + "method": false, + "shorthand": true, + "computed": false, + "key": { + "type": "Identifier", + "start": 6, + "end": 7, + "loc": { + "start": { + "line": 1, + "column": 6 + }, + "end": { + "line": 1, + "column": 7 + }, + "identifierName": "x" + }, + "name": "x" + }, + "value": { + "type": "Identifier", + "start": 6, + "end": 7, + "loc": { + "start": { + "line": 1, + "column": 6 + }, + "end": { + "line": 1, + "column": 7 + }, + "identifierName": "x" + }, + "name": "x" + }, + "extra": { + "shorthand": true + } + }, + { + "type": "ObjectProperty", + "start": 9, + "end": 10, + "loc": { + "start": { + "line": 1, + "column": 9 + }, + "end": { + "line": 1, + "column": 10 + } + }, + "method": false, + "shorthand": true, + "computed": false, + "key": { + "type": "Identifier", + "start": 9, + "end": 10, + "loc": { + "start": { + "line": 1, + "column": 9 + }, + "end": { + "line": 1, + "column": 10 + }, + "identifierName": "y" + }, + "name": "y" + }, + "value": { + "type": "Identifier", + "start": 9, + "end": 10, + "loc": { + "start": { + "line": 1, + "column": 9 + }, + "end": { + "line": 1, + "column": 10 + }, + "identifierName": "y" + }, + "name": "y" + }, + "extra": { + "shorthand": true + } + } + ] + }, + "init": { + "type": "Identifier", + "start": 16, + "end": 19, + "loc": { + "start": { + "line": 1, + "column": 16 + }, + "end": { + "line": 1, + "column": 19 + }, + "identifierName": "obj" + }, + "name": "obj" + } + } + ], + "kind": "let" + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/test/fixtures/experimental/uncategorised/10/actual.js b/test/fixtures/experimental/object-rest-spread/2/actual.js similarity index 100% rename from test/fixtures/experimental/uncategorised/10/actual.js rename to test/fixtures/experimental/object-rest-spread/2/actual.js diff --git a/test/fixtures/experimental/uncategorised/10/expected.json b/test/fixtures/experimental/object-rest-spread/2/expected.json similarity index 100% rename from test/fixtures/experimental/uncategorised/10/expected.json rename to test/fixtures/experimental/object-rest-spread/2/expected.json diff --git a/test/fixtures/experimental/uncategorised/11/actual.js b/test/fixtures/experimental/object-rest-spread/3/actual.js similarity index 100% rename from test/fixtures/experimental/uncategorised/11/actual.js rename to test/fixtures/experimental/object-rest-spread/3/actual.js diff --git a/test/fixtures/experimental/uncategorised/11/expected.json b/test/fixtures/experimental/object-rest-spread/3/expected.json similarity index 100% rename from test/fixtures/experimental/uncategorised/11/expected.json rename to test/fixtures/experimental/object-rest-spread/3/expected.json diff --git a/test/fixtures/experimental/uncategorised/12/actual.js b/test/fixtures/experimental/object-rest-spread/4/actual.js similarity index 100% rename from test/fixtures/experimental/uncategorised/12/actual.js rename to test/fixtures/experimental/object-rest-spread/4/actual.js diff --git a/test/fixtures/experimental/uncategorised/12/expected.json b/test/fixtures/experimental/object-rest-spread/4/expected.json similarity index 100% rename from test/fixtures/experimental/uncategorised/12/expected.json rename to test/fixtures/experimental/object-rest-spread/4/expected.json diff --git a/test/fixtures/experimental/uncategorised/13/actual.js b/test/fixtures/experimental/object-rest-spread/5/actual.js similarity index 100% rename from test/fixtures/experimental/uncategorised/13/actual.js rename to test/fixtures/experimental/object-rest-spread/5/actual.js diff --git a/test/fixtures/experimental/uncategorised/13/expected.json b/test/fixtures/experimental/object-rest-spread/5/expected.json similarity index 100% rename from test/fixtures/experimental/uncategorised/13/expected.json rename to test/fixtures/experimental/object-rest-spread/5/expected.json diff --git a/test/fixtures/experimental/object-rest-spread/6/actual.js b/test/fixtures/experimental/object-rest-spread/6/actual.js new file mode 100644 index 0000000000..0d8a75b880 --- /dev/null +++ b/test/fixtures/experimental/object-rest-spread/6/actual.js @@ -0,0 +1 @@ +({x, ...y, a, ...b, c, }) diff --git a/test/fixtures/experimental/uncategorised/14/expected.json b/test/fixtures/experimental/object-rest-spread/6/expected.json similarity index 87% rename from test/fixtures/experimental/uncategorised/14/expected.json rename to test/fixtures/experimental/object-rest-spread/6/expected.json index 761b028be8..748d406185 100644 --- a/test/fixtures/experimental/uncategorised/14/expected.json +++ b/test/fixtures/experimental/object-rest-spread/6/expected.json @@ -1,7 +1,7 @@ { "type": "File", "start": 0, - "end": 23, + "end": 25, "loc": { "start": { "line": 1, @@ -9,13 +9,13 @@ }, "end": { "line": 1, - "column": 23 + "column": 25 } }, "program": { "type": "Program", "start": 0, - "end": 23, + "end": 25, "loc": { "start": { "line": 1, @@ -23,7 +23,7 @@ }, "end": { "line": 1, - "column": 23 + "column": 25 } }, "sourceType": "script", @@ -31,7 +31,7 @@ { "type": "ExpressionStatement", "start": 0, - "end": 23, + "end": 25, "loc": { "start": { "line": 1, @@ -39,13 +39,13 @@ }, "end": { "line": 1, - "column": 23 + "column": 25 } }, "expression": { "type": "ObjectExpression", "start": 1, - "end": 22, + "end": 24, "loc": { "start": { "line": 1, @@ -53,7 +53,7 @@ }, "end": { "line": 1, - "column": 22 + "column": 24 } }, "properties": [ @@ -86,7 +86,8 @@ "end": { "line": 1, "column": 3 - } + }, + "identifierName": "x" }, "name": "x" }, @@ -102,9 +103,13 @@ "end": { "line": 1, "column": 3 - } + }, + "identifierName": "x" }, "name": "x" + }, + "extra": { + "shorthand": true } }, { @@ -133,7 +138,8 @@ "end": { "line": 1, "column": 9 - } + }, + "identifierName": "y" }, "name": "y" } @@ -167,7 +173,8 @@ "end": { "line": 1, "column": 12 - } + }, + "identifierName": "a" }, "name": "a" }, @@ -183,9 +190,13 @@ "end": { "line": 1, "column": 12 - } + }, + "identifierName": "a" }, "name": "a" + }, + "extra": { + "shorthand": true } }, { @@ -214,7 +225,8 @@ "end": { "line": 1, "column": 18 - } + }, + "identifierName": "b" }, "name": "b" } @@ -248,7 +260,8 @@ "end": { "line": 1, "column": 21 - } + }, + "identifierName": "c" }, "name": "c" }, @@ -264,14 +277,19 @@ "end": { "line": 1, "column": 21 - } + }, + "identifierName": "c" }, "name": "c" + }, + "extra": { + "shorthand": true } } ], "extra": { - "parenthesized": true + "parenthesized": true, + "parenStart": 0 } } } diff --git a/test/fixtures/experimental/object-rest-spread/7/actual.js b/test/fixtures/experimental/object-rest-spread/7/actual.js new file mode 100644 index 0000000000..6a338741f5 --- /dev/null +++ b/test/fixtures/experimental/object-rest-spread/7/actual.js @@ -0,0 +1 @@ +let { ...x, y, z } = obj; diff --git a/test/fixtures/experimental/object-rest-spread/7/options.json b/test/fixtures/experimental/object-rest-spread/7/options.json new file mode 100644 index 0000000000..09b3275eae --- /dev/null +++ b/test/fixtures/experimental/object-rest-spread/7/options.json @@ -0,0 +1,3 @@ +{ + "throws": "The rest element has to be the last element when destructuring (1:10)" +} diff --git a/test/fixtures/experimental/object-rest-spread/8/actual.js b/test/fixtures/experimental/object-rest-spread/8/actual.js new file mode 100644 index 0000000000..62308375b6 --- /dev/null +++ b/test/fixtures/experimental/object-rest-spread/8/actual.js @@ -0,0 +1 @@ +let { x, y, ...z, } = obj; diff --git a/test/fixtures/experimental/object-rest-spread/8/options.json b/test/fixtures/experimental/object-rest-spread/8/options.json new file mode 100644 index 0000000000..4a97ac85ea --- /dev/null +++ b/test/fixtures/experimental/object-rest-spread/8/options.json @@ -0,0 +1,3 @@ +{ + "throws": "A trailing comma is not permitted after the rest element (1:16)" +} diff --git a/test/fixtures/experimental/object-rest-spread/9/actual.js b/test/fixtures/experimental/object-rest-spread/9/actual.js new file mode 100644 index 0000000000..df7243be62 --- /dev/null +++ b/test/fixtures/experimental/object-rest-spread/9/actual.js @@ -0,0 +1 @@ +let { x, ...y, ...z } = obj; diff --git a/test/fixtures/experimental/object-rest-spread/9/options.json b/test/fixtures/experimental/object-rest-spread/9/options.json new file mode 100644 index 0000000000..03ba1e37e8 --- /dev/null +++ b/test/fixtures/experimental/object-rest-spread/9/options.json @@ -0,0 +1,3 @@ +{ + "throws": "Cannot have multiple rest elements when destructuring (1:13)" +} diff --git a/test/fixtures/experimental/uncategorised/10/options.json b/test/fixtures/experimental/object-rest-spread/options.json similarity index 100% rename from test/fixtures/experimental/uncategorised/10/options.json rename to test/fixtures/experimental/object-rest-spread/options.json diff --git a/test/fixtures/experimental/uncategorised/11/options.json b/test/fixtures/experimental/uncategorised/11/options.json deleted file mode 100644 index 4de042a697..0000000000 --- a/test/fixtures/experimental/uncategorised/11/options.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "plugins": ["objectRestSpread"] -} diff --git a/test/fixtures/experimental/uncategorised/12/options.json b/test/fixtures/experimental/uncategorised/12/options.json deleted file mode 100644 index 4de042a697..0000000000 --- a/test/fixtures/experimental/uncategorised/12/options.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "plugins": ["objectRestSpread"] -} diff --git a/test/fixtures/experimental/uncategorised/13/options.json b/test/fixtures/experimental/uncategorised/13/options.json deleted file mode 100644 index 4de042a697..0000000000 --- a/test/fixtures/experimental/uncategorised/13/options.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "plugins": ["objectRestSpread"] -} diff --git a/test/fixtures/experimental/uncategorised/14/actual.js b/test/fixtures/experimental/uncategorised/14/actual.js deleted file mode 100644 index 3a17541c45..0000000000 --- a/test/fixtures/experimental/uncategorised/14/actual.js +++ /dev/null @@ -1 +0,0 @@ -({x, ...y, a, ...b, c}) \ No newline at end of file diff --git a/test/fixtures/experimental/uncategorised/14/options.json b/test/fixtures/experimental/uncategorised/14/options.json deleted file mode 100644 index 4de042a697..0000000000 --- a/test/fixtures/experimental/uncategorised/14/options.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "plugins": ["objectRestSpread"] -} diff --git a/test/fixtures/experimental/uncategorised/9/options.json b/test/fixtures/experimental/uncategorised/9/options.json deleted file mode 100644 index 4de042a697..0000000000 --- a/test/fixtures/experimental/uncategorised/9/options.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "plugins": ["objectRestSpread"] -}