From f81c281fc47525f30f0dfd0dab355f34f2fac262 Mon Sep 17 00:00:00 2001 From: Kevin Smith Date: Tue, 5 Apr 2016 13:28:31 -0400 Subject: [PATCH] Parse for-await statements when asyncGenerators plugin is active --- src/parser/statement.js | 32 ++- .../for-await-async-context/actual.js | 3 + .../for-await-async-context/options.json | 3 + .../for-await-no-in/actual.js | 3 + .../for-await-no-in/expected.json | 184 ++++++++++++++++++ .../for-await-no-in/options.json | 3 + .../for-await-no-semi-1/actual.js | 3 + .../for-await-no-semi-1/options.json | 3 + .../for-await-no-semi-2/actual.js | 3 + .../for-await-no-semi-2/options.json | 3 + .../for-await-no-semi-3/actual.js | 3 + .../for-await-no-semi-3/options.json | 3 + .../async-generators/for-await/actual.js | 3 + .../async-generators/for-await/expected.json | 183 +++++++++++++++++ 14 files changed, 426 insertions(+), 6 deletions(-) create mode 100644 test/fixtures/experimental/async-generators/for-await-async-context/actual.js create mode 100644 test/fixtures/experimental/async-generators/for-await-async-context/options.json create mode 100644 test/fixtures/experimental/async-generators/for-await-no-in/actual.js create mode 100644 test/fixtures/experimental/async-generators/for-await-no-in/expected.json create mode 100644 test/fixtures/experimental/async-generators/for-await-no-in/options.json create mode 100644 test/fixtures/experimental/async-generators/for-await-no-semi-1/actual.js create mode 100644 test/fixtures/experimental/async-generators/for-await-no-semi-1/options.json create mode 100644 test/fixtures/experimental/async-generators/for-await-no-semi-2/actual.js create mode 100644 test/fixtures/experimental/async-generators/for-await-no-semi-2/options.json create mode 100644 test/fixtures/experimental/async-generators/for-await-no-semi-3/actual.js create mode 100644 test/fixtures/experimental/async-generators/for-await-no-semi-3/options.json create mode 100644 test/fixtures/experimental/async-generators/for-await/actual.js create mode 100644 test/fixtures/experimental/async-generators/for-await/expected.json diff --git a/src/parser/statement.js b/src/parser/statement.js index 5a9c2ae9df..291e5a66d5 100644 --- a/src/parser/statement.js +++ b/src/parser/statement.js @@ -224,9 +224,18 @@ pp.parseDoStatement = function (node) { pp.parseForStatement = function (node) { this.next(); this.state.labels.push(loopLabel); + + let forAwait = false; + if (this.hasPlugin("asyncGenerators") && this.state.inAsync && this.isContextual("await")) { + forAwait = true; + this.next(); + } this.expect(tt.parenL); if (this.match(tt.semi)) { + if (forAwait) { + this.unexpected(); + } return this.parseFor(node, null); } @@ -238,10 +247,12 @@ pp.parseForStatement = function (node) { if (this.match(tt._in) || this.isContextual("of")) { if (init.declarations.length === 1 && !init.declarations[0].init) { - return this.parseForIn(node, init); + return this.parseForIn(node, init, forAwait); } } - + if (forAwait) { + this.unexpected(); + } return this.parseFor(node, init); } @@ -250,10 +261,13 @@ pp.parseForStatement = function (node) { if (this.match(tt._in) || this.isContextual("of")) { this.toAssignable(init); this.checkLVal(init); - return this.parseForIn(node, init); + return this.parseForIn(node, init, forAwait); } else if (refShorthandDefaultPos.start) { this.unexpected(refShorthandDefaultPos.start); } + if (forAwait) { + this.unexpected(); + } return this.parseFor(node, init); }; @@ -508,9 +522,15 @@ pp.parseFor = function (node, init) { // Parse a `for`/`in` and `for`/`of` loop, which are almost // same from parser's perspective. -pp.parseForIn = function (node, init) { - let type = this.match(tt._in) ? "ForInStatement" : "ForOfStatement"; - this.next(); +pp.parseForIn = function (node, init, forAwait) { + let type; + if (forAwait) { + this.eatContextual("of"); + type = "ForAwaitStatement"; + } else { + type = this.match(tt._in) ? "ForInStatement" : "ForOfStatement"; + this.next(); + } node.left = init; node.right = this.parseExpression(); this.expect(tt.parenR); diff --git a/test/fixtures/experimental/async-generators/for-await-async-context/actual.js b/test/fixtures/experimental/async-generators/for-await-async-context/actual.js new file mode 100644 index 0000000000..c0c11b897f --- /dev/null +++ b/test/fixtures/experimental/async-generators/for-await-async-context/actual.js @@ -0,0 +1,3 @@ +function f() { + for await (let x of y); +} diff --git a/test/fixtures/experimental/async-generators/for-await-async-context/options.json b/test/fixtures/experimental/async-generators/for-await-async-context/options.json new file mode 100644 index 0000000000..9660494a29 --- /dev/null +++ b/test/fixtures/experimental/async-generators/for-await-async-context/options.json @@ -0,0 +1,3 @@ +{ + "throws": "Unexpected token (2:6)" +} diff --git a/test/fixtures/experimental/async-generators/for-await-no-in/actual.js b/test/fixtures/experimental/async-generators/for-await-no-in/actual.js new file mode 100644 index 0000000000..546c318b86 --- /dev/null +++ b/test/fixtures/experimental/async-generators/for-await-no-in/actual.js @@ -0,0 +1,3 @@ +async function f() { + for await (let x in y); +} diff --git a/test/fixtures/experimental/async-generators/for-await-no-in/expected.json b/test/fixtures/experimental/async-generators/for-await-no-in/expected.json new file mode 100644 index 0000000000..968a854fcc --- /dev/null +++ b/test/fixtures/experimental/async-generators/for-await-no-in/expected.json @@ -0,0 +1,184 @@ +{ + "type": "File", + "start": 0, + "end": 48, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 1 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 48, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 1 + } + }, + "sourceType": "script", + "body": [ + { + "type": "FunctionDeclaration", + "start": 0, + "end": 48, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 1 + } + }, + "id": { + "type": "Identifier", + "start": 15, + "end": 16, + "loc": { + "start": { + "line": 1, + "column": 15 + }, + "end": { + "line": 1, + "column": 16 + } + }, + "name": "f" + }, + "generator": false, + "expression": false, + "async": true, + "params": [], + "body": { + "type": "BlockStatement", + "start": 19, + "end": 48, + "loc": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 3, + "column": 1 + } + }, + "body": [ + { + "type": "ForAwaitStatement", + "start": 23, + "end": 46, + "loc": { + "start": { + "line": 2, + "column": 2 + }, + "end": { + "line": 2, + "column": 25 + } + }, + "await": true, + "left": { + "type": "VariableDeclaration", + "start": 34, + "end": 39, + "loc": { + "start": { + "line": 2, + "column": 13 + }, + "end": { + "line": 2, + "column": 18 + } + }, + "declarations": [ + { + "type": "VariableDeclarator", + "start": 38, + "end": 39, + "loc": { + "start": { + "line": 2, + "column": 17 + }, + "end": { + "line": 2, + "column": 18 + } + }, + "id": { + "type": "Identifier", + "start": 38, + "end": 39, + "loc": { + "start": { + "line": 2, + "column": 17 + }, + "end": { + "line": 2, + "column": 18 + } + }, + "name": "x" + }, + "init": null + } + ], + "kind": "let" + }, + "right": { + "type": "Identifier", + "start": 43, + "end": 44, + "loc": { + "start": { + "line": 2, + "column": 22 + }, + "end": { + "line": 2, + "column": 23 + } + }, + "name": "y" + }, + "body": { + "type": "EmptyStatement", + "start": 45, + "end": 46, + "loc": { + "start": { + "line": 2, + "column": 24 + }, + "end": { + "line": 2, + "column": 25 + } + } + } + } + ], + "directives": [] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/test/fixtures/experimental/async-generators/for-await-no-in/options.json b/test/fixtures/experimental/async-generators/for-await-no-in/options.json new file mode 100644 index 0000000000..f8dd5c55d9 --- /dev/null +++ b/test/fixtures/experimental/async-generators/for-await-no-in/options.json @@ -0,0 +1,3 @@ +{ + "throws": "Unexpected token (2:19)" +} diff --git a/test/fixtures/experimental/async-generators/for-await-no-semi-1/actual.js b/test/fixtures/experimental/async-generators/for-await-no-semi-1/actual.js new file mode 100644 index 0000000000..c8a195bb3c --- /dev/null +++ b/test/fixtures/experimental/async-generators/for-await-no-semi-1/actual.js @@ -0,0 +1,3 @@ +async function f() { + for await (;false;); +} diff --git a/test/fixtures/experimental/async-generators/for-await-no-semi-1/options.json b/test/fixtures/experimental/async-generators/for-await-no-semi-1/options.json new file mode 100644 index 0000000000..f45f06d72e --- /dev/null +++ b/test/fixtures/experimental/async-generators/for-await-no-semi-1/options.json @@ -0,0 +1,3 @@ +{ + "throws": "Unexpected token (2:13)" +} diff --git a/test/fixtures/experimental/async-generators/for-await-no-semi-2/actual.js b/test/fixtures/experimental/async-generators/for-await-no-semi-2/actual.js new file mode 100644 index 0000000000..817ff94c10 --- /dev/null +++ b/test/fixtures/experimental/async-generators/for-await-no-semi-2/actual.js @@ -0,0 +1,3 @@ +async function f() { + for await (let i = 0;false;); +} diff --git a/test/fixtures/experimental/async-generators/for-await-no-semi-2/options.json b/test/fixtures/experimental/async-generators/for-await-no-semi-2/options.json new file mode 100644 index 0000000000..c2c8f56374 --- /dev/null +++ b/test/fixtures/experimental/async-generators/for-await-no-semi-2/options.json @@ -0,0 +1,3 @@ +{ + "throws": "Unexpected token (2:22)" +} diff --git a/test/fixtures/experimental/async-generators/for-await-no-semi-3/actual.js b/test/fixtures/experimental/async-generators/for-await-no-semi-3/actual.js new file mode 100644 index 0000000000..6982933ab4 --- /dev/null +++ b/test/fixtures/experimental/async-generators/for-await-no-semi-3/actual.js @@ -0,0 +1,3 @@ +async function f() { + for await (x = 0;false;); +} diff --git a/test/fixtures/experimental/async-generators/for-await-no-semi-3/options.json b/test/fixtures/experimental/async-generators/for-await-no-semi-3/options.json new file mode 100644 index 0000000000..ae405ee221 --- /dev/null +++ b/test/fixtures/experimental/async-generators/for-await-no-semi-3/options.json @@ -0,0 +1,3 @@ +{ + "throws": "Unexpected token (2:18)" +} diff --git a/test/fixtures/experimental/async-generators/for-await/actual.js b/test/fixtures/experimental/async-generators/for-await/actual.js new file mode 100644 index 0000000000..ab5cce67f6 --- /dev/null +++ b/test/fixtures/experimental/async-generators/for-await/actual.js @@ -0,0 +1,3 @@ +async function f() { + for await (let x of y); +} diff --git a/test/fixtures/experimental/async-generators/for-await/expected.json b/test/fixtures/experimental/async-generators/for-await/expected.json new file mode 100644 index 0000000000..1551481f51 --- /dev/null +++ b/test/fixtures/experimental/async-generators/for-await/expected.json @@ -0,0 +1,183 @@ +{ + "type": "File", + "start": 0, + "end": 48, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 1 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 48, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 1 + } + }, + "sourceType": "script", + "body": [ + { + "type": "FunctionDeclaration", + "start": 0, + "end": 48, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 1 + } + }, + "id": { + "type": "Identifier", + "start": 15, + "end": 16, + "loc": { + "start": { + "line": 1, + "column": 15 + }, + "end": { + "line": 1, + "column": 16 + } + }, + "name": "f" + }, + "generator": false, + "expression": false, + "async": true, + "params": [], + "body": { + "type": "BlockStatement", + "start": 19, + "end": 48, + "loc": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 3, + "column": 1 + } + }, + "body": [ + { + "type": "ForAwaitStatement", + "start": 23, + "end": 46, + "loc": { + "start": { + "line": 2, + "column": 2 + }, + "end": { + "line": 2, + "column": 25 + } + }, + "left": { + "type": "VariableDeclaration", + "start": 34, + "end": 39, + "loc": { + "start": { + "line": 2, + "column": 13 + }, + "end": { + "line": 2, + "column": 18 + } + }, + "declarations": [ + { + "type": "VariableDeclarator", + "start": 38, + "end": 39, + "loc": { + "start": { + "line": 2, + "column": 17 + }, + "end": { + "line": 2, + "column": 18 + } + }, + "id": { + "type": "Identifier", + "start": 38, + "end": 39, + "loc": { + "start": { + "line": 2, + "column": 17 + }, + "end": { + "line": 2, + "column": 18 + } + }, + "name": "x" + }, + "init": null + } + ], + "kind": "let" + }, + "right": { + "type": "Identifier", + "start": 43, + "end": 44, + "loc": { + "start": { + "line": 2, + "column": 22 + }, + "end": { + "line": 2, + "column": 23 + } + }, + "name": "y" + }, + "body": { + "type": "EmptyStatement", + "start": 45, + "end": 46, + "loc": { + "start": { + "line": 2, + "column": 24 + }, + "end": { + "line": 2, + "column": 25 + } + } + } + } + ], + "directives": [] + } + } + ], + "directives": [] + } +}