Skip to content

Improve parsing in await and yield context #44680

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions src/compiler/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1501,6 +1501,8 @@ namespace ts {
if (token() === SyntaxKind.Identifier) {
return true;
}

// `let await`/`let yield` in [Yield] or [Await] are allowed here and disallowed in the binder.
return token() > SyntaxKind.LastReservedWord;
}

Expand Down Expand Up @@ -6122,15 +6124,15 @@ namespace ts {
}
}

function nextTokenIsIdentifierOrStartOfDestructuring() {
function nextTokenIsBindingIdentifierOrStartOfDestructuring() {
nextToken();
return isIdentifier() || token() === SyntaxKind.OpenBraceToken || token() === SyntaxKind.OpenBracketToken;
return isBindingIdentifier() || token() === SyntaxKind.OpenBraceToken || token() === SyntaxKind.OpenBracketToken;
}

function isLetDeclaration() {
// In ES6 'let' always starts a lexical declaration if followed by an identifier or {
// or [.
return lookAhead(nextTokenIsIdentifierOrStartOfDestructuring);
return lookAhead(nextTokenIsBindingIdentifierOrStartOfDestructuring);
}

function parseStatement(): Statement {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
tests/cases/conformance/async/es6/functionDeclarations/asyncOrYieldAsBindingIdentifier1.ts(14,9): error TS1359: Identifier expected. 'await' is a reserved word that cannot be used here.
tests/cases/conformance/async/es6/functionDeclarations/asyncOrYieldAsBindingIdentifier1.ts(18,9): error TS1359: Identifier expected. 'await' is a reserved word that cannot be used here.
tests/cases/conformance/async/es6/functionDeclarations/asyncOrYieldAsBindingIdentifier1.ts(22,11): error TS1359: Identifier expected. 'await' is a reserved word that cannot be used here.
tests/cases/conformance/async/es6/functionDeclarations/asyncOrYieldAsBindingIdentifier1.ts(38,9): error TS1359: Identifier expected. 'yield' is a reserved word that cannot be used here.
tests/cases/conformance/async/es6/functionDeclarations/asyncOrYieldAsBindingIdentifier1.ts(42,9): error TS1359: Identifier expected. 'yield' is a reserved word that cannot be used here.
tests/cases/conformance/async/es6/functionDeclarations/asyncOrYieldAsBindingIdentifier1.ts(46,11): error TS1359: Identifier expected. 'yield' is a reserved word that cannot be used here.


==== tests/cases/conformance/async/es6/functionDeclarations/asyncOrYieldAsBindingIdentifier1.ts (6 errors) ====
function f_let () {
let await = 1
}

function f1_var () {
var await = 1
}

function f1_const () {
const await = 1
}

async function f2_let () {
let await = 1
~~~~~
!!! error TS1359: Identifier expected. 'await' is a reserved word that cannot be used here.
}

async function f2_var () {
var await = 1
~~~~~
!!! error TS1359: Identifier expected. 'await' is a reserved word that cannot be used here.
}

async function f2_const () {
const await = 1
~~~~~
!!! error TS1359: Identifier expected. 'await' is a reserved word that cannot be used here.
}

function f3_let () {
let yield = 2
}

function f3_var () {
var yield = 2
}

function f3_const () {
const yield = 2
}

function * f4_let () {
let yield = 2;
~~~~~
!!! error TS1359: Identifier expected. 'yield' is a reserved word that cannot be used here.
}

function * f4_var () {
var yield = 2;
~~~~~
!!! error TS1359: Identifier expected. 'yield' is a reserved word that cannot be used here.
}

function * f4_const () {
const yield = 2;
~~~~~
!!! error TS1359: Identifier expected. 'yield' is a reserved word that cannot be used here.
}
86 changes: 86 additions & 0 deletions tests/baselines/reference/asyncOrYieldAsBindingIdentifier1.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
//// [asyncOrYieldAsBindingIdentifier1.ts]
function f_let () {
let await = 1
}

function f1_var () {
var await = 1
}

function f1_const () {
const await = 1
}

async function f2_let () {
let await = 1
}

async function f2_var () {
var await = 1
}

async function f2_const () {
const await = 1
}

function f3_let () {
let yield = 2
}

function f3_var () {
var yield = 2
}

function f3_const () {
const yield = 2
}

function * f4_let () {
let yield = 2;
}

function * f4_var () {
var yield = 2;
}

function * f4_const () {
const yield = 2;
}

//// [asyncOrYieldAsBindingIdentifier1.js]
function f_let() {
let await = 1;
}
function f1_var() {
var await = 1;
}
function f1_const() {
const await = 1;
}
async function f2_let() {
let await = 1;
}
async function f2_var() {
var await = 1;
}
async function f2_const() {
const await = 1;
}
function f3_let() {
let yield = 2;
}
function f3_var() {
var yield = 2;
}
function f3_const() {
const yield = 2;
}
function* f4_let() {
let yield = 2;
}
function* f4_var() {
var yield = 2;
}
function* f4_const() {
const yield = 2;
}
84 changes: 84 additions & 0 deletions tests/baselines/reference/asyncOrYieldAsBindingIdentifier1.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
=== tests/cases/conformance/async/es6/functionDeclarations/asyncOrYieldAsBindingIdentifier1.ts ===
function f_let () {
>f_let : Symbol(f_let, Decl(asyncOrYieldAsBindingIdentifier1.ts, 0, 0))

let await = 1
>await : Symbol(await, Decl(asyncOrYieldAsBindingIdentifier1.ts, 1, 7))
}

function f1_var () {
>f1_var : Symbol(f1_var, Decl(asyncOrYieldAsBindingIdentifier1.ts, 2, 1))

var await = 1
>await : Symbol(await, Decl(asyncOrYieldAsBindingIdentifier1.ts, 5, 7))
}

function f1_const () {
>f1_const : Symbol(f1_const, Decl(asyncOrYieldAsBindingIdentifier1.ts, 6, 1))

const await = 1
>await : Symbol(await, Decl(asyncOrYieldAsBindingIdentifier1.ts, 9, 9))
}

async function f2_let () {
>f2_let : Symbol(f2_let, Decl(asyncOrYieldAsBindingIdentifier1.ts, 10, 1))

let await = 1
>await : Symbol(await, Decl(asyncOrYieldAsBindingIdentifier1.ts, 13, 7))
}

async function f2_var () {
>f2_var : Symbol(f2_var, Decl(asyncOrYieldAsBindingIdentifier1.ts, 14, 1))

var await = 1
>await : Symbol(await, Decl(asyncOrYieldAsBindingIdentifier1.ts, 17, 7))
}

async function f2_const () {
>f2_const : Symbol(f2_const, Decl(asyncOrYieldAsBindingIdentifier1.ts, 18, 1))

const await = 1
>await : Symbol(await, Decl(asyncOrYieldAsBindingIdentifier1.ts, 21, 9))
}

function f3_let () {
>f3_let : Symbol(f3_let, Decl(asyncOrYieldAsBindingIdentifier1.ts, 22, 1))

let yield = 2
>yield : Symbol(yield, Decl(asyncOrYieldAsBindingIdentifier1.ts, 25, 7))
}

function f3_var () {
>f3_var : Symbol(f3_var, Decl(asyncOrYieldAsBindingIdentifier1.ts, 26, 1))

var yield = 2
>yield : Symbol(yield, Decl(asyncOrYieldAsBindingIdentifier1.ts, 29, 7))
}

function f3_const () {
>f3_const : Symbol(f3_const, Decl(asyncOrYieldAsBindingIdentifier1.ts, 30, 1))

const yield = 2
>yield : Symbol(yield, Decl(asyncOrYieldAsBindingIdentifier1.ts, 33, 9))
}

function * f4_let () {
>f4_let : Symbol(f4_let, Decl(asyncOrYieldAsBindingIdentifier1.ts, 34, 1))

let yield = 2;
>yield : Symbol(yield, Decl(asyncOrYieldAsBindingIdentifier1.ts, 37, 7))
}

function * f4_var () {
>f4_var : Symbol(f4_var, Decl(asyncOrYieldAsBindingIdentifier1.ts, 38, 1))

var yield = 2;
>yield : Symbol(yield, Decl(asyncOrYieldAsBindingIdentifier1.ts, 41, 7))
}

function * f4_const () {
>f4_const : Symbol(f4_const, Decl(asyncOrYieldAsBindingIdentifier1.ts, 42, 1))

const yield = 2;
>yield : Symbol(yield, Decl(asyncOrYieldAsBindingIdentifier1.ts, 45, 9))
}
96 changes: 96 additions & 0 deletions tests/baselines/reference/asyncOrYieldAsBindingIdentifier1.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
=== tests/cases/conformance/async/es6/functionDeclarations/asyncOrYieldAsBindingIdentifier1.ts ===
function f_let () {
>f_let : () => void

let await = 1
>await : number
>1 : 1
}

function f1_var () {
>f1_var : () => void

var await = 1
>await : number
>1 : 1
}

function f1_const () {
>f1_const : () => void

const await = 1
>await : 1
>1 : 1
}

async function f2_let () {
>f2_let : () => Promise<void>

let await = 1
>await : number
>1 : 1
}

async function f2_var () {
>f2_var : () => Promise<void>

var await = 1
>await : number
>1 : 1
}

async function f2_const () {
>f2_const : () => Promise<void>

const await = 1
>await : 1
>1 : 1
}

function f3_let () {
>f3_let : () => void

let yield = 2
>yield : number
>2 : 2
}

function f3_var () {
>f3_var : () => void

var yield = 2
>yield : number
>2 : 2
}

function f3_const () {
>f3_const : () => void

const yield = 2
>yield : 2
>2 : 2
}

function * f4_let () {
>f4_let : () => Generator<never, void, unknown>

let yield = 2;
>yield : number
>2 : 2
}

function * f4_var () {
>f4_var : () => Generator<never, void, unknown>

var yield = 2;
>yield : number
>2 : 2
}

function * f4_const () {
>f4_const : () => Generator<never, void, unknown>

const yield = 2;
>yield : 2
>2 : 2
}
Loading