Skip to content

Commit

Permalink
fix #3308: TS type arguments for JS decorators
Browse files Browse the repository at this point in the history
  • Loading branch information
evanw committed Aug 11, 2023
1 parent be9e098 commit a973f87
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 0 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@

## Unreleased

* Parse TypeScript type arguments for JavaScript decorators ([#3308](https://github.com/evanw/esbuild/issues/3308))

When parsing JavaScript decorators in TypeScript (i.e. with `experimentalDecorators` disabled), esbuild previously didn't parse type arguments. Type arguments will now be parsed starting with this release. For example:

```ts
@foo<number>
@bar<number, string>()
class Foo {}
```

* Fix glob patterns matching extra stuff at the end ([#3306](https://github.com/evanw/esbuild/issues/3306))

Previously glob patterns such as `./*.js` would incorrectly behave like `./*.js*` during path matching (also matching `.js.map` files, for example). This was never intentional behavior, and has now been fixed.
Expand Down
11 changes: 11 additions & 0 deletions internal/js_parser/js_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -6626,8 +6626,14 @@ func (p *parser) parseDecorator() js_ast.Expr {

memberExpr := js_ast.Expr{Loc: nameRange.Loc, Data: &js_ast.EIdentifier{Ref: p.storeNameInRef(name)}}

// "@x<y>() class{}"
if p.options.ts.Parse {
p.skipTypeScriptTypeArguments(skipTypeScriptTypeArgumentsOpts{})
}

for p.lexer.Token == js_lexer.TDot {
p.lexer.Next()

if p.lexer.Token == js_lexer.TPrivateIdentifier {
memberExpr.Data = &js_ast.EIndex{
Target: memberExpr,
Expand All @@ -6642,6 +6648,11 @@ func (p *parser) parseDecorator() js_ast.Expr {
}
p.lexer.Expect(js_lexer.TIdentifier)
}

// "@x.y<z>() class{}"
if p.options.ts.Parse {
p.skipTypeScriptTypeArguments(skipTypeScriptTypeArgumentsOpts{})
}
}

// The grammar for "DecoratorMemberExpression" currently forbids "?."
Expand Down
10 changes: 10 additions & 0 deletions internal/js_parser/ts_parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2037,6 +2037,16 @@ func TestTSDecorators(t *testing.T) {
expectParseErrorTS(t, "@new Function() class Foo {}", "<stdin>: ERROR: Expected identifier but found \"new\"\n")
expectParseErrorTS(t, "@() => {} class Foo {}", "<stdin>: ERROR: Unexpected \")\"\n")

expectPrintedTS(t, "class Foo { @x<{}> y: any }", "class Foo {\n @x\n y;\n}\n")
expectPrintedTS(t, "class Foo { @x<{}>() y: any }", "class Foo {\n @x()\n y;\n}\n")
expectPrintedTS(t, "class Foo { @x<{}> @y<[], () => {}> z: any }", "class Foo {\n @x\n @y\n z;\n}\n")
expectPrintedTS(t, "class Foo { @x<{}>() @y<[], () => {}>() z: any }", "class Foo {\n @x()\n @y()\n z;\n}\n")
expectPrintedTS(t, "class Foo { @x<{}>.y<[], () => {}> z: any }", "class Foo {\n @x.y\n z;\n}\n")

// TypeScript 5.0+ allows this but Babel doesn't. I believe this is a bug
// with TypeScript: https://github.com/microsoft/TypeScript/issues/55336
expectParseErrorTS(t, "class Foo { @x<{}>().y<[], () => {}>() z: any }", "<stdin>: ERROR: Expected identifier but found \".\"\n")

errorText := "<stdin>: ERROR: Transforming JavaScript decorators to the configured target environment is not supported yet\n"
expectParseErrorWithUnsupportedFeaturesTS(t, compat.Decorators, "@dec class Foo {}", errorText)
expectParseErrorWithUnsupportedFeaturesTS(t, compat.Decorators, "class Foo { @dec x }", errorText)
Expand Down

0 comments on commit a973f87

Please sign in to comment.