Skip to content

Commit

Permalink
fix #2991: crash with inline typescript decorator
Browse files Browse the repository at this point in the history
  • Loading branch information
evanw committed Mar 15, 2023
1 parent 0c8a0a9 commit 3b38ce3
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 2 deletions.
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
# Changelog

## Unreleased

* Fix a crash when parsing inline TypeScript decorators ([#2991](https://github.com/evanw/esbuild/issues/2991))

Previously esbuild's TypeScript parser crashed when parsing TypeScript decorators if the definition of the decorator was inlined into the decorator itself:

```ts
@(function sealed(constructor: Function) {
Object.seal(constructor);
Object.seal(constructor.prototype);
})
class Foo {}
```

This crash was not noticed earlier because this edge case did not have test coverage. The crash is fixed in this release.

## 0.17.11

* Fix the `alias` feature to always prefer the longest match ([#2963](https://github.com/evanw/esbuild/issues/2963))
Expand Down
2 changes: 0 additions & 2 deletions internal/js_parser/ts_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -1245,7 +1245,6 @@ func (p *parser) parseTypeScriptDecorators(tsDecoratorScope *js_ast.Scope) []js_
p.currentScope = tsDecoratorScope

for p.lexer.Token == js_lexer.TAt {
loc := p.lexer.Loc()
p.lexer.Next()

// Parse a new/call expression with "exprFlagTSDecorator" so we ignore
Expand All @@ -1257,7 +1256,6 @@ func (p *parser) parseTypeScriptDecorators(tsDecoratorScope *js_ast.Scope) []js_
//
// This matches the behavior of the TypeScript compiler.
value := p.parseExprWithFlags(js_ast.LNew, exprFlagTSDecorator)
value.Loc = loc
tsDecorators = append(tsDecorators, value)
}

Expand Down
6 changes: 6 additions & 0 deletions internal/js_parser/ts_parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1773,6 +1773,12 @@ func TestTSDecorator(t *testing.T) {
"<stdin>: ERROR: Cannot use \"yield\" outside a generator function\n")
expectParseErrorTS(t, "function foo() { @dec(yield x) class Foo {} }", "<stdin>: ERROR: Cannot use \"yield\" outside a generator function\n")
expectParseErrorTS(t, "function foo() { class Foo { @dec(yield x) foo() {} } }", "<stdin>: ERROR: Cannot use \"yield\" outside a generator function\n")

// Check inline function expressions
expectPrintedTS(t, "@((x, y) => x + y) class Foo {}", "let Foo = class {\n};\nFoo = __decorateClass([\n (x, y) => x + y\n], Foo);\n")
expectPrintedTS(t, "@((x, y) => x + y) export class Foo {}", "export let Foo = class {\n};\nFoo = __decorateClass([\n (x, y) => x + y\n], Foo);\n")
expectPrintedTS(t, "@(function(x, y) { return x + y }) class Foo {}", "let Foo = class {\n};\nFoo = __decorateClass([\n function(x, y) {\n return x + y;\n }\n], Foo);\n")
expectPrintedTS(t, "@(function(x, y) { return x + y }) export class Foo {}", "export let Foo = class {\n};\nFoo = __decorateClass([\n function(x, y) {\n return x + y;\n }\n], Foo);\n")
}

func TestTSTry(t *testing.T) {
Expand Down

0 comments on commit 3b38ce3

Please sign in to comment.