Skip to content

Commit 9fe4a61

Browse files
committed
fixes after landing #2038
1 parent 5b782b6 commit 9fe4a61

File tree

4 files changed

+28
-12
lines changed

4 files changed

+28
-12
lines changed

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,17 @@
22

33
## Unreleased
44

5+
* Add support for parsing "instantiation expressions" from TypeScript 4.7 ([#2038](https://github.com/evanw/esbuild/pull/2038))
6+
7+
The upcoming version of TypeScript now lets you specify `<...>` type parameters on a JavaScript identifier without using a call expression:
8+
9+
```ts
10+
const ErrorMap = Map<string, Error>; // new () => Map<string, Error>
11+
const errorMap = new ErrorMap(); // Map<string, Error>
12+
```
13+
14+
With this release, esbuild can now parse these new type annotations. This feature was contributed by [@g-plane](https://github.com/g-plane).
15+
516
* Avoid `new Function` in esbuild's library code ([#2081](https://github.com/evanw/esbuild/issues/2081))
617

718
Some JavaScript environments such as Cloudflare Workers or Deno Deploy don't allow `new Function` because they disallow dynamic JavaScript evaluation. Previously esbuild's WebAssembly-based library used this to construct the WebAssembly worker function. With this release, the code is now inlined without using `new Function` so it will be able to run even when this restriction is in place.

internal/js_lexer/js_lexer.go

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2191,12 +2191,10 @@ func (lexer *Lexer) ScanRegExp() {
21912191
}
21922192

21932193
switch lexer.codePoint {
2194-
case '\r', '\n', 0x2028, 0x2029:
2195-
// Newlines aren't allowed in regular expressions
2196-
lexer.SyntaxError()
2197-
2198-
case -1: // This indicates the end of the file
2199-
lexer.SyntaxError()
2194+
case -1, // This indicates the end of the file
2195+
'\r', '\n', 0x2028, 0x2029: // Newlines aren't allowed in regular expressions
2196+
lexer.addRangeError(logger.Range{Loc: logger.Loc{Start: int32(lexer.end)}}, "Unterminated regular expression")
2197+
panic(LexerPanic{})
22002198

22012199
default:
22022200
lexer.step()

internal/js_parser/ts_parser.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -790,17 +790,16 @@ func (p *parser) isTSArrowFnJSX() (isTSArrowFn bool) {
790790
func (p *parser) canFollowTypeArgumentsInExpression() bool {
791791
switch p.lexer.Token {
792792
case
793-
// These are the only tokens can legally follow a type argument list. So we
794-
// definitely want to treat them as type arg lists.
793+
// These tokens can follow a type argument list in a call expression.
795794
js_lexer.TOpenParen, // foo<x>(
796795
js_lexer.TNoSubstitutionTemplateLiteral, // foo<T> `...`
797796
js_lexer.TTemplateHead: // foo<T> `...${100}...`
798797
return true
799798

800799
case
801-
// These tokens can't follow in a call expression,
802-
// nor can they start an expression.
803-
// So, consider the type argument list part of an instantiation expression.
800+
// These tokens can't follow in a call expression, nor can they start an
801+
// expression. So, consider the type argument list part of an instantiation
802+
// expression.
804803
js_lexer.TComma, // foo<x>,
805804
js_lexer.TDot, // foo<x>.
806805
js_lexer.TQuestionDot, // foo<x>?.

internal/js_parser/ts_parser_test.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1620,6 +1620,14 @@ func TestTSInstantiationExpression(t *testing.T) {
16201620

16211621
expectParseErrorTS(t, "const a8 = f<number><number>;", "<stdin>: ERROR: Unexpected \";\"\n")
16221622
expectParseErrorTS(t, "const b1 = f?.<number>;", "<stdin>: ERROR: Expected \"(\" but found \";\"\n")
1623+
1624+
// The TypeScript compiler doesn't do semicolon insertion before "<" when
1625+
// inside "typeof" but does in other situations. Was this an oversight? Not sure,
1626+
// but we replicate this behavior because it matters when JSX syntax is enabled.
1627+
expectPrintedTSX(t, "type x = typeof y\n<number>\n1", "1;\n")
1628+
expectParseErrorTS(t, "type x = typeof y\n<number>\n1\n</number>", "<stdin>: ERROR: Unterminated regular expression\n")
1629+
expectParseErrorTSX(t, "type x = y\n<number>\n1", "<stdin>: ERROR: Unexpected end of file\n")
1630+
expectPrintedTSX(t, "type x = y\n<number>\n1\n</number>", "/* @__PURE__ */ React.createElement(\"number\", null, \"1\");\n")
16231631
}
16241632

16251633
func TestTSExponentiation(t *testing.T) {
@@ -1952,7 +1960,7 @@ func TestTSNoAmbiguousLessThan(t *testing.T) {
19521960
"<stdin>: ERROR: This syntax is not allowed in files with the \".mts\" or \".cts\" extension\n")
19531961
expectParseErrorTSNoAmbiguousLessThan(t, "<x>y</x>",
19541962
"<stdin>: ERROR: This syntax is not allowed in files with the \".mts\" or \".cts\" extension\n"+
1955-
"<stdin>: ERROR: Unexpected end of file\n")
1963+
"<stdin>: ERROR: Unterminated regular expression\n")
19561964
expectParseErrorTSNoAmbiguousLessThan(t, "<x extends></x>",
19571965
"<stdin>: ERROR: This syntax is not allowed in files with the \".mts\" or \".cts\" extension\n"+
19581966
"<stdin>: ERROR: Unexpected \">\"\n")

0 commit comments

Comments
 (0)