From 9fe4a61fc8d1fe6f992ea19b4eb345e9398c14b3 Mon Sep 17 00:00:00 2001 From: Evan Wallace Date: Thu, 10 Mar 2022 18:56:25 +0000 Subject: [PATCH] fixes after landing #2038 --- CHANGELOG.md | 11 +++++++++++ internal/js_lexer/js_lexer.go | 10 ++++------ internal/js_parser/ts_parser.go | 9 ++++----- internal/js_parser/ts_parser_test.go | 10 +++++++++- 4 files changed, 28 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 52472588ac8..333c7339b0b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,17 @@ ## Unreleased +* Add support for parsing "instantiation expressions" from TypeScript 4.7 ([#2038](https://github.com/evanw/esbuild/pull/2038)) + + The upcoming version of TypeScript now lets you specify `<...>` type parameters on a JavaScript identifier without using a call expression: + + ```ts + const ErrorMap = Map; // new () => Map + const errorMap = new ErrorMap(); // Map + ``` + + With this release, esbuild can now parse these new type annotations. This feature was contributed by [@g-plane](https://github.com/g-plane). + * Avoid `new Function` in esbuild's library code ([#2081](https://github.com/evanw/esbuild/issues/2081)) 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. diff --git a/internal/js_lexer/js_lexer.go b/internal/js_lexer/js_lexer.go index 5037ff1bcd8..7e94faf5410 100644 --- a/internal/js_lexer/js_lexer.go +++ b/internal/js_lexer/js_lexer.go @@ -2191,12 +2191,10 @@ func (lexer *Lexer) ScanRegExp() { } switch lexer.codePoint { - case '\r', '\n', 0x2028, 0x2029: - // Newlines aren't allowed in regular expressions - lexer.SyntaxError() - - case -1: // This indicates the end of the file - lexer.SyntaxError() + case -1, // This indicates the end of the file + '\r', '\n', 0x2028, 0x2029: // Newlines aren't allowed in regular expressions + lexer.addRangeError(logger.Range{Loc: logger.Loc{Start: int32(lexer.end)}}, "Unterminated regular expression") + panic(LexerPanic{}) default: lexer.step() diff --git a/internal/js_parser/ts_parser.go b/internal/js_parser/ts_parser.go index 969338e983e..ca0bcdb6305 100644 --- a/internal/js_parser/ts_parser.go +++ b/internal/js_parser/ts_parser.go @@ -790,17 +790,16 @@ func (p *parser) isTSArrowFnJSX() (isTSArrowFn bool) { func (p *parser) canFollowTypeArgumentsInExpression() bool { switch p.lexer.Token { case - // These are the only tokens can legally follow a type argument list. So we - // definitely want to treat them as type arg lists. + // These tokens can follow a type argument list in a call expression. js_lexer.TOpenParen, // foo( js_lexer.TNoSubstitutionTemplateLiteral, // foo `...` js_lexer.TTemplateHead: // foo `...${100}...` return true case - // These tokens can't follow in a call expression, - // nor can they start an expression. - // So, consider the type argument list part of an instantiation expression. + // These tokens can't follow in a call expression, nor can they start an + // expression. So, consider the type argument list part of an instantiation + // expression. js_lexer.TComma, // foo, js_lexer.TDot, // foo. js_lexer.TQuestionDot, // foo?. diff --git a/internal/js_parser/ts_parser_test.go b/internal/js_parser/ts_parser_test.go index 6cdd2bb1b4b..c19dce1b0f2 100644 --- a/internal/js_parser/ts_parser_test.go +++ b/internal/js_parser/ts_parser_test.go @@ -1620,6 +1620,14 @@ func TestTSInstantiationExpression(t *testing.T) { expectParseErrorTS(t, "const a8 = f;", ": ERROR: Unexpected \";\"\n") expectParseErrorTS(t, "const b1 = f?.;", ": ERROR: Expected \"(\" but found \";\"\n") + + // The TypeScript compiler doesn't do semicolon insertion before "<" when + // inside "typeof" but does in other situations. Was this an oversight? Not sure, + // but we replicate this behavior because it matters when JSX syntax is enabled. + expectPrintedTSX(t, "type x = typeof y\n\n1", "1;\n") + expectParseErrorTS(t, "type x = typeof y\n\n1\n", ": ERROR: Unterminated regular expression\n") + expectParseErrorTSX(t, "type x = y\n\n1", ": ERROR: Unexpected end of file\n") + expectPrintedTSX(t, "type x = y\n\n1\n", "/* @__PURE__ */ React.createElement(\"number\", null, \"1\");\n") } func TestTSExponentiation(t *testing.T) { @@ -1952,7 +1960,7 @@ func TestTSNoAmbiguousLessThan(t *testing.T) { ": ERROR: This syntax is not allowed in files with the \".mts\" or \".cts\" extension\n") expectParseErrorTSNoAmbiguousLessThan(t, "y", ": ERROR: This syntax is not allowed in files with the \".mts\" or \".cts\" extension\n"+ - ": ERROR: Unexpected end of file\n") + ": ERROR: Unterminated regular expression\n") expectParseErrorTSNoAmbiguousLessThan(t, "", ": ERROR: This syntax is not allowed in files with the \".mts\" or \".cts\" extension\n"+ ": ERROR: Unexpected \">\"\n")