Skip to content

Commit

Permalink
allow for (await using of of of) ;
Browse files Browse the repository at this point in the history
  • Loading branch information
evanw committed Nov 18, 2023
1 parent 08b4607 commit 7a697c0
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 9 deletions.
9 changes: 5 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
6 changes: 3 additions & 3 deletions internal/js_parser/js_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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")
Expand All @@ -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)
}
Expand Down
9 changes: 7 additions & 2 deletions internal/js_parser/js_parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) ;", "<stdin>: ERROR: Expected \")\" but found \"x\"\n")
expectParseError(t, "for (using of of of) ;", "<stdin>: ERROR: Expected \")\" but found \"of\"\n")
expectParseError(t, "for (using x in y) ;", "<stdin>: ERROR: \"using\" declarations are not allowed here\n")
expectParseError(t, "for (using x;;) ;", "<stdin>: ERROR: The declaration \"x\" must be initialized\n")
expectParseError(t, "for (using x = y of z) ;", "<stdin>: ERROR: for-of loop variables cannot have an initializer\n")
Expand All @@ -6416,10 +6421,10 @@ func TestUsing(t *testing.T) {
expectParseError(t, "await using [x] = y", "<stdin>: ERROR: Invalid assignment target\n")
expectParseError(t, "for (await using x in y) ;", "<stdin>: ERROR: \"await using\" declarations are not allowed here\n")
expectParseError(t, "for (await using x = y;;) ;", "<stdin>: ERROR: \"await using\" declarations are not allowed here\n")
expectParseError(t, "for (await using of x) ;", "<stdin>: ERROR: Invalid assignment target\n")
expectParseError(t, "for (await using of x) ;", "<stdin>: ERROR: Expected \";\" but found \"x\"\n")
expectParseError(t, "for (await using x = y of z) ;", "<stdin>: ERROR: for-of loop variables cannot have an initializer\n")
expectParseError(t, "for (await using \n x of y) ;", "<stdin>: ERROR: Expected \";\" but found \"x\"\n")
expectParseError(t, "for await (await using of x) ;", "<stdin>: ERROR: Invalid assignment target\n")
expectParseError(t, "for await (await using of x) ;", "<stdin>: ERROR: Expected \"of\" but found \"x\"\n")
expectParseError(t, "for await (await using x = y of z) ;", "<stdin>: ERROR: for-of loop variables cannot have an initializer\n")
expectParseError(t, "for await (await using \n x of y) ;", "<stdin>: ERROR: Expected \"of\" but found \"x\"\n")

Expand Down

0 comments on commit 7a697c0

Please sign in to comment.