From 7a697c09a83748e7dcc7392fa2353f6f5cc7d323 Mon Sep 17 00:00:00 2001 From: Evan Wallace Date: Sat, 18 Nov 2023 14:07:09 -0500 Subject: [PATCH] allow `for (await using of of of) ;` --- CHANGELOG.md | 9 +++++---- internal/js_parser/js_parser.go | 6 +++--- internal/js_parser/js_parser_test.go | 9 +++++++-- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c1bc5f435f..6b9f2c9a134 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,17 +35,18 @@ document.onkeydown=o=>o.keyCode===65&&console.log("🧀"); ``` -* Parse an upcoming change to TypeScript type syntax ([#3490](https://github.com/evanw/esbuild/issues/3490), [#3491](https://github.com/evanw/esbuild/pull/3491)) +* Parse upcoming changes to TypeScript syntax ([#3490](https://github.com/evanw/esbuild/issues/3490), [#3491](https://github.com/evanw/esbuild/pull/3491)) - With this release, you can now use `from` as the name of a default type-only import in TypeScript code: + With this release, you can now use `from` as the name of a default type-only import in TypeScript code, as well as `of` as the name of an `await using` loop iteration variable: ```ts import type from from 'from' + for (await using of of of) ; ``` - This matches a similar [change in the TypeScript compiler](https://github.com/microsoft/TypeScript/issues/56376) which will start allowing this syntax in an upcoming version of TypeScript. + This matches similar changes in the TypeScript compiler ([#56376](https://github.com/microsoft/TypeScript/issues/56376) and [#55555](https://github.com/microsoft/TypeScript/issues/55555)) which will start allowing this syntax in an upcoming version of TypeScript. Please never actually write code like this. - This change was contributed by [@magic-akari](https://github.com/magic-akari). + The type-only import syntax change was contributed by [@magic-akari](https://github.com/magic-akari). ## 0.19.5 diff --git a/internal/js_parser/js_parser.go b/internal/js_parser/js_parser.go index c2a949d7891..79f4f45bca4 100644 --- a/internal/js_parser/js_parser.go +++ b/internal/js_parser/js_parser.go @@ -4817,7 +4817,7 @@ func (p *parser) parseExprOrLetOrUsingStmt(opts parseStmtOpts) (js_ast.Expr, js_ usingLoc := p.saveExprCommentsHere() usingRange := p.lexer.Range() p.lexer.Next() - if p.lexer.Token == js_lexer.TIdentifier && !p.lexer.HasNewlineBefore && (!opts.isForLoopInit || p.lexer.Raw() != "of") { + if p.lexer.Token == js_lexer.TIdentifier && !p.lexer.HasNewlineBefore { // It's an "await using" declaration if we get here if opts.lexicalDecl != lexicalDeclAllowAll { p.forbidLexicalDecl(usingRange.Loc) @@ -7447,6 +7447,8 @@ func (p *parser) parseStmt(opts parseStmtOpts) js_ast.Stmt { return js_ast.Stmt{Loc: loc, Data: &js_ast.SForIn{Init: initOrNil, Value: value, Body: body}} } + p.lexer.Expect(js_lexer.TSemicolon) + // "await using" declarations are only allowed in for-of loops if local, ok := initOrNil.Data.(*js_ast.SLocal); ok && local.Kind == js_ast.LocalAwaitUsing { p.log.AddError(&p.tracker, js_lexer.RangeOfIdentifier(p.source, initOrNil.Loc), "\"await using\" declarations are not allowed here") @@ -7457,8 +7459,6 @@ func (p *parser) parseStmt(opts parseStmtOpts) js_ast.Stmt { p.requireInitializers(local.Kind, decls) } - p.lexer.Expect(js_lexer.TSemicolon) - if p.lexer.Token != js_lexer.TSemicolon { testOrNil = p.parseExpr(js_ast.LLowest) } diff --git a/internal/js_parser/js_parser_test.go b/internal/js_parser/js_parser_test.go index 20f63e0398c..2d845c26f62 100644 --- a/internal/js_parser/js_parser_test.go +++ b/internal/js_parser/js_parser_test.go @@ -6399,8 +6399,13 @@ func TestUsing(t *testing.T) { expectPrinted(t, "for (using x = y;;) ;", "for (using x = y; ; )\n ;\n") expectPrinted(t, "for (using x of y) ;", "for (using x of y)\n ;\n") expectPrinted(t, "for (using of x) ;", "for (using of x)\n ;\n") + expectPrinted(t, "for (using of of) ;", "for (using of of)\n ;\n") + expectPrinted(t, "for (await using of of x) ;", "for (await using of of x)\n ;\n") + expectPrinted(t, "for (await using of of of) ;", "for (await using of of of)\n ;\n") expectPrinted(t, "for await (using x of y) ;", "for await (using x of y)\n ;\n") expectPrinted(t, "for await (using of x) ;", "for await (using of x)\n ;\n") + expectParseError(t, "for (using of of x) ;", ": ERROR: Expected \")\" but found \"x\"\n") + expectParseError(t, "for (using of of of) ;", ": ERROR: Expected \")\" but found \"of\"\n") expectParseError(t, "for (using x in y) ;", ": ERROR: \"using\" declarations are not allowed here\n") expectParseError(t, "for (using x;;) ;", ": ERROR: The declaration \"x\" must be initialized\n") expectParseError(t, "for (using x = y of z) ;", ": ERROR: for-of loop variables cannot have an initializer\n") @@ -6416,10 +6421,10 @@ func TestUsing(t *testing.T) { expectParseError(t, "await using [x] = y", ": ERROR: Invalid assignment target\n") expectParseError(t, "for (await using x in y) ;", ": ERROR: \"await using\" declarations are not allowed here\n") expectParseError(t, "for (await using x = y;;) ;", ": ERROR: \"await using\" declarations are not allowed here\n") - expectParseError(t, "for (await using of x) ;", ": ERROR: Invalid assignment target\n") + expectParseError(t, "for (await using of x) ;", ": ERROR: Expected \";\" but found \"x\"\n") expectParseError(t, "for (await using x = y of z) ;", ": ERROR: for-of loop variables cannot have an initializer\n") expectParseError(t, "for (await using \n x of y) ;", ": ERROR: Expected \";\" but found \"x\"\n") - expectParseError(t, "for await (await using of x) ;", ": ERROR: Invalid assignment target\n") + expectParseError(t, "for await (await using of x) ;", ": ERROR: Expected \"of\" but found \"x\"\n") expectParseError(t, "for await (await using x = y of z) ;", ": ERROR: for-of loop variables cannot have an initializer\n") expectParseError(t, "for await (await using \n x of y) ;", ": ERROR: Expected \"of\" but found \"x\"\n")