diff --git a/internal/js_parser/js_parser.go b/internal/js_parser/js_parser.go index 1c2df9aa393..78b752d729c 100644 --- a/internal/js_parser/js_parser.go +++ b/internal/js_parser/js_parser.go @@ -2014,9 +2014,13 @@ func (p *parser) parseProperty(startLoc logger.Loc, kind js_ast.PropertyKind, op if !opts.isClass && kind == js_ast.PropertyNormal && p.lexer.Token != js_lexer.TColon && p.lexer.Token != js_lexer.TOpenParen && p.lexer.Token != js_lexer.TLessThan && !opts.isGenerator && !opts.isAsync && js_lexer.Keywords[name.String] == js_lexer.T(0) { - if (p.fnOrArrowDataParse.await != allowIdent && name.String == "await") || (p.fnOrArrowDataParse.yield != allowIdent && name.String == "yield") { + + // Forbid invalid identifiers + if (p.fnOrArrowDataParse.await != allowIdent && name.String == "await") || + (p.fnOrArrowDataParse.yield != allowIdent && name.String == "yield") { p.log.AddError(&p.tracker, nameRange, fmt.Sprintf("Cannot use %q as an identifier here:", name.String)) } + ref := p.storeNameInRef(name) value := js_ast.Expr{Loc: key.Loc, Data: &js_ast.EIdentifier{Ref: ref}} @@ -2323,20 +2327,26 @@ func (p *parser) parsePropertyBinding() js_ast.PropertyBinding { default: name := p.lexer.Identifier - loc := p.lexer.Loc() + nameRange := p.lexer.Range() if !p.lexer.IsIdentifierOrKeyword() { p.lexer.Expect(js_lexer.TIdentifier) } p.lexer.Next() if p.isMangledProp(name.String) { - key = js_ast.Expr{Loc: loc, Data: &js_ast.EMangledProp{Ref: p.storeNameInRef(name)}} + key = js_ast.Expr{Loc: nameRange.Loc, Data: &js_ast.EMangledProp{Ref: p.storeNameInRef(name)}} } else { - key = js_ast.Expr{Loc: loc, Data: &js_ast.EString{Value: helpers.StringToUTF16(name.String)}} + key = js_ast.Expr{Loc: nameRange.Loc, Data: &js_ast.EString{Value: helpers.StringToUTF16(name.String)}} } if p.lexer.Token != js_lexer.TColon && p.lexer.Token != js_lexer.TOpenParen { + // Forbid invalid identifiers + if (p.fnOrArrowDataParse.await != allowIdent && name.String == "await") || + (p.fnOrArrowDataParse.yield != allowIdent && name.String == "yield") { + p.log.AddError(&p.tracker, nameRange, fmt.Sprintf("Cannot use %q as an identifier here:", name.String)) + } + ref := p.storeNameInRef(name) - value := js_ast.Binding{Loc: loc, Data: &js_ast.BIdentifier{Ref: ref}} + value := js_ast.Binding{Loc: nameRange.Loc, Data: &js_ast.BIdentifier{Ref: ref}} var defaultValueOrNil js_ast.Expr if p.lexer.Token == js_lexer.TEquals { @@ -5230,10 +5240,13 @@ func (p *parser) parseBinding() js_ast.Binding { switch p.lexer.Token { case js_lexer.TIdentifier: name := p.lexer.Identifier + + // Forbid invalid identifiers if (p.fnOrArrowDataParse.await != allowIdent && name.String == "await") || (p.fnOrArrowDataParse.yield != allowIdent && name.String == "yield") { p.log.AddError(&p.tracker, p.lexer.Range(), fmt.Sprintf("Cannot use %q as an identifier here:", name.String)) } + ref := p.storeNameInRef(name) p.lexer.Next() return js_ast.Binding{Loc: loc, Data: &js_ast.BIdentifier{Ref: ref}} diff --git a/internal/js_parser/js_parser_test.go b/internal/js_parser/js_parser_test.go index 23f4c13d4b1..e55e4bc7984 100644 --- a/internal/js_parser/js_parser_test.go +++ b/internal/js_parser/js_parser_test.go @@ -584,6 +584,20 @@ func TestAwait(t *testing.T) { expectPrinted(t, "await (x * y)", "await (x * y);\n") expectPrinted(t, "await (x ** y)", "await (x ** y);\n") + expectParseError(t, "var { await } = {}", ": ERROR: Cannot use \"await\" as an identifier here:\n") + expectParseError(t, "async function f() { var { await } = {} }", ": ERROR: Cannot use \"await\" as an identifier here:\n") + expectParseError(t, "async function* f() { var { await } = {} }", ": ERROR: Cannot use \"await\" as an identifier here:\n") + expectParseError(t, "class C { async f() { var { await } = {} } }", ": ERROR: Cannot use \"await\" as an identifier here:\n") + expectParseError(t, "class C { async* f() { var { await } = {} } }", ": ERROR: Cannot use \"await\" as an identifier here:\n") + expectParseError(t, "class C { static { var { await } = {} } }", ": ERROR: Cannot use \"await\" as an identifier here:\n") + + expectParseError(t, "var {} = { await }", ": ERROR: Cannot use \"await\" as an identifier here:\n") + expectParseError(t, "async function f() { var {} = { await } }", ": ERROR: Cannot use \"await\" as an identifier here:\n") + expectParseError(t, "async function* f() { var {} = { await } }", ": ERROR: Cannot use \"await\" as an identifier here:\n") + expectParseError(t, "class C { async f() { var {} = { await } } }", ": ERROR: Cannot use \"await\" as an identifier here:\n") + expectParseError(t, "class C { async* f() { var {} = { await } } }", ": ERROR: Cannot use \"await\" as an identifier here:\n") + expectParseError(t, "class C { static { var {} = { await } } }", ": ERROR: Cannot use \"await\" as an identifier here:\n") + expectParseError(t, "await delete x", `: ERROR: Delete of a bare identifier cannot be used in an ECMAScript module : NOTE: This file is considered to be an ECMAScript module because of the top-level "await" keyword here: