v0.11.16
-
Fix TypeScript
enum
edge case (#1198)In TypeScript, you can reference the inner closure variable in an
enum
within the inner closure by name:enum A { B = A }
The TypeScript compiler generates the following code for this case:
var A; (function (A) { A[A["B"] = A] = "B"; })(A || (A = {}));
However, TypeScript also lets you declare an
enum
value with the same name as the inner closure variable. In that case, the value "shadows" the declaration of the inner closure variable:enum A { A = 1, B = A }
The TypeScript compiler generates the following code for this case:
var A; (function (A) { A[A["A"] = 1] = "A"; A[A["B"] = 1] = "B"; })(A || (A = {}));
Previously esbuild reported a duplicate variable declaration error in the second case due to the collision between the
enum
value and the inner closure variable with the same name. With this release, the shadowing is now handled correctly. -
Parse the
@-moz-document
CSS rule (#1203)This feature has been removed from the web because it's actively harmful, at least according to this discussion. However, there is one exception where
@-moz-document url-prefix() {
is accepted by Firefox to basically be an "if Firefox" conditional rule. Because of this, esbuild now parses the@-moz-document
CSS rule. This should result in better pretty-printing and minification and no more warning when this rule is used. -
Fix syntax error in TypeScript-specific speculative arrow function parsing (#1211)
Because of grammar ambiguities, expressions that start with a parenthesis are parsed using what's called a "cover grammar" that is a super-position of both a parenthesized expression and an arrow function parameter list. In JavaScript, the cover grammar is unambiguously an arrow function if and only if the following token is a
=>
token.But in TypeScript, the expression is still ambiguously a parenthesized expression or an arrow function if the following token is a
:
since it may be the second half of the?:
operator or a return type annotation. This requires speculatively attempting to reduce the cover grammar to an arrow function parameter list.However, when doing this esbuild eagerly reported an error if a default argument was encountered and the target is
es5
(esbuild doesn't support lowering default arguments to ES5). This is problematic in the following TypeScript code since the parenthesized code turns out to not be an arrow function parameter list:function foo(check, hover) { return check ? (hover = 2, bar) : baz(); }
Previously this code incorrectly generated an error since
hover = 2
was incorrectly eagerly validated as a default argument. With this release, the reporting of the default argument error when targetinges5
is now done lazily and only when it's determined that the parenthesized code should actually be interpreted as an arrow function parameter list. -
Further changes to the behavior of the
browser
field (#1209)This release includes some changes to how the
browser
field inpackage.json
is interpreted to better match how Browserify, Webpack, Parcel, and Rollup behave. The interpretation of this map in esbuild is intended to be applied if and only if it's applied by any one of these bundlers. However, there were some cases where esbuild applied the mapping and none of the other bundlers did, which could lead to build failures. These cases have been added to my growing list ofbrowser
field test cases and esbuild's behavior should now be consistent with other bundlers again. -
Avoid placing a
super()
call inside areturn
statement (#1208)When minification is enabled, an expression followed by a return statement (e.g.
a(); return b
) is merged into a single statement (e.g.return a(), b
). This is done because it sometimes results in smaller code. If the return statement is the only statement in a block and the block is in a single-statement context, the block can be removed which saves a few characters.Previously esbuild applied this rule to calls to
super()
inside of constructors. Doing that broke esbuild's class lowering transform that tries to insert class field initializers after thesuper()
call. This transform isn't robust and only scans the top-level statement list inside the constructor, so inserting thesuper()
call inside of thereturn
statement means class field initializers were inserted before thesuper()
call instead of after. This could lead to run-time crashes due to initialization failure.With this release, top-level calls to
super()
will no longer be placed insidereturn
statements (in addition to various other kinds of statements such asthrow
, which are now also handled). This should avoid class field initializers being inserted before thesuper()
call. -
Fix a bug with
onEnd
and watch mode (#1186)This release fixes a bug where
onEnd
plugin callbacks only worked with watch mode when anonRebuild
watch mode callback was present. NowonEnd
callbacks should fire even if there is noonRebuild
callback. -
Fix an edge case with minified export names and code splitting (#1201)
The names of symbols imported from other chunks were previously not considered for renaming during minified name assignment. This could cause a syntax error due to a name collision when two symbols have the same original name. This was just an oversight and has been fixed, so symbols imported from other chunks should now be renamed when minification is enabled.
-
Provide a friendly error message when you forget
async
(#1216)If the parser hits a parse error inside a non-asynchronous function or arrow expression and the previous token is
await
, esbuild will now report a friendly error about a missingasync
keyword instead of reporting the parse error. This behavior matches other JavaScript parsers including TypeScript, Babel, and V8.The previous error looked like this:
> test.ts:2:8: error: Expected ";" but found "f" 2 │ await f(); ╵ ^
The error now looks like this:
> example.js:2:2: error: "await" can only be used inside an "async" function 2 │ await f(); ╵ ~~~~~ example.js:1:0: note: Consider adding the "async" keyword here 1 │ function f() { │ ^ ╵ async