Skip to content

v0.14.49

Compare
Choose a tag to compare
@github-actions github-actions released this 10 Jul 17:19
  • Keep inlined constants when direct eval is present (#2361)

    Version 0.14.19 of esbuild added inlining of certain const variables during minification, which replaces all references to the variable with the initializer and then removes the variable declaration. However, this could generate incorrect code when direct eval is present because the direct eval could reference the constant by name. This release fixes the problem by preserving the const variable declaration in this case:

    // Original code
    console.log((() => { const x = 123; return x + eval('x') }))
    
    // Old output (with --minify)
    console.log(()=>123+eval("x"));
    
    // New output (with --minify)
    console.log(()=>{const x=123;return 123+eval("x")});
  • Fix an incorrect error in TypeScript when targeting ES5 (#2375)

    Previously when compiling TypeScript code to ES5, esbuild could incorrectly consider the following syntax forms as a transformation error:

    0 ? ([]) : 1 ? ({}) : 2;

    The error messages looked like this:

    ✘ [ERROR] Transforming destructuring to the configured target environment ("es5") is not supported yet
    
        example.ts:1:5:
          1 │ 0 ? ([]) : 1 ? ({}) : 2;
            ╵      ^
    
    ✘ [ERROR] Transforming destructuring to the configured target environment ("es5") is not supported yet
    
        example.ts:1:16:
          1 │ 0 ? ([]) : 1 ? ({}) : 2;
            ╵                 ^
    

    These parenthesized literals followed by a colon look like the start of an arrow function expression followed by a TypeScript return type (e.g. ([]) : 1 could be the start of the TypeScript arrow function ([]): 1 => 1). Unlike in JavaScript, parsing arrow functions in TypeScript requires backtracking. In this case esbuild correctly determined that this expression wasn't an arrow function after all but the check for destructuring was incorrectly not covered under the backtracking process. With this release, the error message is now only reported if the parser successfully parses an arrow function without backtracking.

  • Fix generated TypeScript enum comments containing */ (#2369, #2371)

    TypeScript enum values that are equal to a number or string literal are inlined (references to the enum are replaced with the literal value) and have a /* ... */ comment after them with the original enum name to improve readability. However, this comment is omitted if the enum name contains the character sequence */ because that would end the comment early and cause a syntax error:

    // Original TypeScript
    enum Foo { '/*' = 1, '*/' = 2 }
    console.log(Foo['/*'], Foo['*/'])
    
    // Generated JavaScript
    console.log(1 /* /* */, 2);

    This was originally handled correctly when TypeScript enum inlining was initially implemented since it was only supported within a single file. However, when esbuild was later extended to support TypeScript enum inlining across files, this special case where the enum name contains */ was not handled in that new code. Starting with this release, esbuild will now handle enums with names containing */ correctly when they are inlined across files:

    // foo.ts
    export enum Foo { '/*' = 1, '*/' = 2 }
    
    // bar.ts
    import { Foo } from './foo'
    console.log(Foo['/*'], Foo['*/'])
    
    // Old output (with --bundle --format=esm)
    console.log(1 /* /* */, 2 /* */ */);
    
    // New output (with --bundle --format=esm)
    console.log(1 /* /* */, 2);

    This fix was contributed by @magic-akari.

  • Allow declare class fields to be initialized (#2380)

    This release fixes an oversight in the TypeScript parser that disallowed initializers for declare class fields. TypeScript actually allows the following limited initializer expressions for readonly fields:

    declare const enum a { b = 0 }
    
    class Foo {
      // These are allowed by TypeScript
      declare readonly a = 0
      declare readonly b = -0
      declare readonly c = 0n
      declare readonly d = -0n
      declare readonly e = 'x'
      declare readonly f = `x`
      declare readonly g = a.b
      declare readonly h = a['b']
    
      // These are not allowed by TypeScript
      declare readonly x = (0)
      declare readonly y = null
      declare readonly z = -a.b
    }

    So with this release, esbuild now allows initializers for declare class fields too. To future-proof this in case TypeScript allows more expressions as initializers in the future (such as null), esbuild will allow any expression as an initializer and will leave the specifics of TypeScript's special-casing here to the TypeScript type checker.

  • Fix a bug in esbuild's feature compatibility table generator (#2365)

    Passing specific JavaScript engines to esbuild's --target flag restricts esbuild to only using JavaScript features that are supported on those engines in the output files that esbuild generates. The data for this feature is automatically derived from this compatibility table with a script: https://kangax.github.io/compat-table/.

    However, the script had a bug that could incorrectly consider a JavaScript syntax feature to be supported in a given engine even when it doesn't actually work in that engine. Specifically this bug happened when a certain aspect of JavaScript syntax has always worked incorrectly in that engine and the bug in that engine has never been fixed. This situation hasn't really come up before because previously esbuild pretty much only targeted JavaScript engines that always fix their bugs, but the two new JavaScript engines that were added in the previous release (Hermes and Rhino) have many aspects of the JavaScript specification that have never been implemented, and may never be implemented. For example, the let and const keywords are not implemented correctly in those engines.

    With this release, esbuild's compatibility table generator script has been fixed and as a result, esbuild will now correctly consider a JavaScript syntax feature to be unsupported in a given engine if there is some aspect of that syntax that is broken in all known versions of that engine. This means that the following JavaScript syntax features are no longer considered to be supported by these engines (represented using esbuild's internal names for these syntax features):

    Hermes:

    • arrow
    • const-and-let
    • default-argument
    • generator
    • optional-catch-binding
    • optional-chain
    • rest-argument
    • template-literal

    Rhino:

    • arrow
    • const-and-let
    • destructuring
    • for-of
    • generator
    • object-extensions
    • template-literal

    IE:

    • const-and-let