Skip to content

Commit 976b57a

Browse files
committed
validate await in shorthand destructuring
1 parent 8ac7529 commit 976b57a

File tree

2 files changed

+32
-5
lines changed

2 files changed

+32
-5
lines changed

internal/js_parser/js_parser.go

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2014,9 +2014,13 @@ func (p *parser) parseProperty(startLoc logger.Loc, kind js_ast.PropertyKind, op
20142014
if !opts.isClass && kind == js_ast.PropertyNormal && p.lexer.Token != js_lexer.TColon &&
20152015
p.lexer.Token != js_lexer.TOpenParen && p.lexer.Token != js_lexer.TLessThan &&
20162016
!opts.isGenerator && !opts.isAsync && js_lexer.Keywords[name.String] == js_lexer.T(0) {
2017-
if (p.fnOrArrowDataParse.await != allowIdent && name.String == "await") || (p.fnOrArrowDataParse.yield != allowIdent && name.String == "yield") {
2017+
2018+
// Forbid invalid identifiers
2019+
if (p.fnOrArrowDataParse.await != allowIdent && name.String == "await") ||
2020+
(p.fnOrArrowDataParse.yield != allowIdent && name.String == "yield") {
20182021
p.log.AddError(&p.tracker, nameRange, fmt.Sprintf("Cannot use %q as an identifier here:", name.String))
20192022
}
2023+
20202024
ref := p.storeNameInRef(name)
20212025
value := js_ast.Expr{Loc: key.Loc, Data: &js_ast.EIdentifier{Ref: ref}}
20222026

@@ -2323,20 +2327,26 @@ func (p *parser) parsePropertyBinding() js_ast.PropertyBinding {
23232327

23242328
default:
23252329
name := p.lexer.Identifier
2326-
loc := p.lexer.Loc()
2330+
nameRange := p.lexer.Range()
23272331
if !p.lexer.IsIdentifierOrKeyword() {
23282332
p.lexer.Expect(js_lexer.TIdentifier)
23292333
}
23302334
p.lexer.Next()
23312335
if p.isMangledProp(name.String) {
2332-
key = js_ast.Expr{Loc: loc, Data: &js_ast.EMangledProp{Ref: p.storeNameInRef(name)}}
2336+
key = js_ast.Expr{Loc: nameRange.Loc, Data: &js_ast.EMangledProp{Ref: p.storeNameInRef(name)}}
23332337
} else {
2334-
key = js_ast.Expr{Loc: loc, Data: &js_ast.EString{Value: helpers.StringToUTF16(name.String)}}
2338+
key = js_ast.Expr{Loc: nameRange.Loc, Data: &js_ast.EString{Value: helpers.StringToUTF16(name.String)}}
23352339
}
23362340

23372341
if p.lexer.Token != js_lexer.TColon && p.lexer.Token != js_lexer.TOpenParen {
2342+
// Forbid invalid identifiers
2343+
if (p.fnOrArrowDataParse.await != allowIdent && name.String == "await") ||
2344+
(p.fnOrArrowDataParse.yield != allowIdent && name.String == "yield") {
2345+
p.log.AddError(&p.tracker, nameRange, fmt.Sprintf("Cannot use %q as an identifier here:", name.String))
2346+
}
2347+
23382348
ref := p.storeNameInRef(name)
2339-
value := js_ast.Binding{Loc: loc, Data: &js_ast.BIdentifier{Ref: ref}}
2349+
value := js_ast.Binding{Loc: nameRange.Loc, Data: &js_ast.BIdentifier{Ref: ref}}
23402350

23412351
var defaultValueOrNil js_ast.Expr
23422352
if p.lexer.Token == js_lexer.TEquals {
@@ -5230,10 +5240,13 @@ func (p *parser) parseBinding() js_ast.Binding {
52305240
switch p.lexer.Token {
52315241
case js_lexer.TIdentifier:
52325242
name := p.lexer.Identifier
5243+
5244+
// Forbid invalid identifiers
52335245
if (p.fnOrArrowDataParse.await != allowIdent && name.String == "await") ||
52345246
(p.fnOrArrowDataParse.yield != allowIdent && name.String == "yield") {
52355247
p.log.AddError(&p.tracker, p.lexer.Range(), fmt.Sprintf("Cannot use %q as an identifier here:", name.String))
52365248
}
5249+
52375250
ref := p.storeNameInRef(name)
52385251
p.lexer.Next()
52395252
return js_ast.Binding{Loc: loc, Data: &js_ast.BIdentifier{Ref: ref}}

internal/js_parser/js_parser_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,20 @@ func TestAwait(t *testing.T) {
584584
expectPrinted(t, "await (x * y)", "await (x * y);\n")
585585
expectPrinted(t, "await (x ** y)", "await (x ** y);\n")
586586

587+
expectParseError(t, "var { await } = {}", "<stdin>: ERROR: Cannot use \"await\" as an identifier here:\n")
588+
expectParseError(t, "async function f() { var { await } = {} }", "<stdin>: ERROR: Cannot use \"await\" as an identifier here:\n")
589+
expectParseError(t, "async function* f() { var { await } = {} }", "<stdin>: ERROR: Cannot use \"await\" as an identifier here:\n")
590+
expectParseError(t, "class C { async f() { var { await } = {} } }", "<stdin>: ERROR: Cannot use \"await\" as an identifier here:\n")
591+
expectParseError(t, "class C { async* f() { var { await } = {} } }", "<stdin>: ERROR: Cannot use \"await\" as an identifier here:\n")
592+
expectParseError(t, "class C { static { var { await } = {} } }", "<stdin>: ERROR: Cannot use \"await\" as an identifier here:\n")
593+
594+
expectParseError(t, "var {} = { await }", "<stdin>: ERROR: Cannot use \"await\" as an identifier here:\n")
595+
expectParseError(t, "async function f() { var {} = { await } }", "<stdin>: ERROR: Cannot use \"await\" as an identifier here:\n")
596+
expectParseError(t, "async function* f() { var {} = { await } }", "<stdin>: ERROR: Cannot use \"await\" as an identifier here:\n")
597+
expectParseError(t, "class C { async f() { var {} = { await } } }", "<stdin>: ERROR: Cannot use \"await\" as an identifier here:\n")
598+
expectParseError(t, "class C { async* f() { var {} = { await } } }", "<stdin>: ERROR: Cannot use \"await\" as an identifier here:\n")
599+
expectParseError(t, "class C { static { var {} = { await } } }", "<stdin>: ERROR: Cannot use \"await\" as an identifier here:\n")
600+
587601
expectParseError(t, "await delete x",
588602
`<stdin>: ERROR: Delete of a bare identifier cannot be used in an ECMAScript module
589603
<stdin>: NOTE: This file is considered to be an ECMAScript module because of the top-level "await" keyword here:

0 commit comments

Comments
 (0)