github.com/evanw/esbuild@v0.21.4/CHANGELOG-2023.md (about)

     1  # Changelog: 2023
     2  
     3  This changelog documents all esbuild versions published in the year 2023 (versions 0.16.13 through 0.19.11).
     4  
     5  ## 0.19.11
     6  
     7  * Fix TypeScript-specific class transform edge case ([#3559](https://github.com/evanw/esbuild/issues/3559))
     8  
     9      The previous release introduced an optimization that avoided transforming `super()` in the class constructor for TypeScript code compiled with `useDefineForClassFields` set to `false` if all class instance fields have no initializers. The rationale was that in this case, all class instance fields are omitted in the output so no changes to the constructor are needed. However, if all of this is the case _and_ there are `#private` instance fields with initializers, those private instance field initializers were still being moved into the constructor. This was problematic because they were being inserted before the call to `super()` (since `super()` is now no longer transformed in that case). This release introduces an additional optimization that avoids moving the private instance field initializers into the constructor in this edge case, which generates smaller code, matches the TypeScript compiler's output more closely, and avoids this bug:
    10  
    11      ```ts
    12      // Original code
    13      class Foo extends Bar {
    14        #private = 1;
    15        public: any;
    16        constructor() {
    17          super();
    18        }
    19      }
    20  
    21      // Old output (with esbuild v0.19.9)
    22      class Foo extends Bar {
    23        constructor() {
    24          super();
    25          this.#private = 1;
    26        }
    27        #private;
    28      }
    29  
    30      // Old output (with esbuild v0.19.10)
    31      class Foo extends Bar {
    32        constructor() {
    33          this.#private = 1;
    34          super();
    35        }
    36        #private;
    37      }
    38  
    39      // New output
    40      class Foo extends Bar {
    41        #private = 1;
    42        constructor() {
    43          super();
    44        }
    45      }
    46      ```
    47  
    48  * Minifier: allow reording a primitive past a side-effect ([#3568](https://github.com/evanw/esbuild/issues/3568))
    49  
    50      The minifier previously allowed reordering a side-effect past a primitive, but didn't handle the case of reordering a primitive past a side-effect. This additional case is now handled:
    51  
    52      ```js
    53      // Original code
    54      function f() {
    55        let x = false;
    56        let y = x;
    57        const boolean = y;
    58        let frag = $.template(`<p contenteditable="${boolean}">hello world</p>`);
    59        return frag;
    60      }
    61  
    62      // Old output (with --minify)
    63      function f(){const e=!1;return $.template(`<p contenteditable="${e}">hello world</p>`)}
    64  
    65      // New output (with --minify)
    66      function f(){return $.template('<p contenteditable="false">hello world</p>')}
    67      ```
    68  
    69  * Minifier: consider properties named using known `Symbol` instances to be side-effect free ([#3561](https://github.com/evanw/esbuild/issues/3561))
    70  
    71      Many things in JavaScript can have side effects including property accesses and ToString operations, so using a symbol such as `Symbol.iterator` as a computed property name is not obviously side-effect free. This release adds a special case for known `Symbol` instances so that they are considered side-effect free when used as property names. For example, this class declaration will now be considered side-effect free:
    72  
    73      ```js
    74      class Foo {
    75        *[Symbol.iterator]() {
    76        }
    77      }
    78      ```
    79  
    80  * Provide the `stop()` API in node to exit esbuild's child process ([#3558](https://github.com/evanw/esbuild/issues/3558))
    81  
    82      You can now call `stop()` in esbuild's node API to exit esbuild's child process to reclaim the resources used. It only makes sense to do this for a long-lived node process when you know you will no longer be making any more esbuild API calls. It is not necessary to call this to allow node to exit, and it's advantageous to not call this in between calls to esbuild's API as sharing a single long-lived esbuild child process is more efficient than re-creating a new esbuild child process for every API call. This API call used to exist but was removed in [version 0.9.0](https://github.com/evanw/esbuild/releases/v0.9.0). This release adds it back due to a user request.
    83  
    84  ## 0.19.10
    85  
    86  * Fix glob imports in TypeScript files ([#3319](https://github.com/evanw/esbuild/issues/3319))
    87  
    88      This release fixes a problem where bundling a TypeScript file containing a glob import could emit a call to a helper function that doesn't exist. The problem happened because esbuild's TypeScript transformation removes unused imports (which is required for correctness, as they may be type-only imports) and esbuild's glob import transformation wasn't correctly marking the imported helper function as used. This wasn't caught earlier because most of esbuild's glob import tests were written in JavaScript, not in TypeScript.
    89  
    90  * Fix `require()` glob imports with bundling disabled ([#3546](https://github.com/evanw/esbuild/issues/3546))
    91  
    92      Previously `require()` calls containing glob imports were incorrectly transformed when bundling was disabled. All glob imports should only be transformed when bundling is enabled. This bug has been fixed.
    93  
    94  * Fix a panic when transforming optional chaining with `define` ([#3551](https://github.com/evanw/esbuild/issues/3551), [#3554](https://github.com/evanw/esbuild/pull/3554))
    95  
    96      This release fixes a case where esbuild could crash with a panic, which was triggered by using `define` to replace an expression containing an optional chain. Here is an example:
    97  
    98      ```js
    99      // Original code
   100      console.log(process?.env.SHELL)
   101  
   102      // Old output (with --define:process.env={})
   103      /* panic: Internal error (while parsing "<stdin>") */
   104  
   105      // New output (with --define:process.env={})
   106      var define_process_env_default = {};
   107      console.log(define_process_env_default.SHELL);
   108      ```
   109  
   110      This fix was contributed by [@hi-ogawa](https://github.com/hi-ogawa).
   111  
   112  * Work around a bug in node's CommonJS export name detector ([#3544](https://github.com/evanw/esbuild/issues/3544))
   113  
   114      The export names of a CommonJS module are dynamically-determined at run time because CommonJS exports are properties on a mutable object. But the export names of an ES module are statically-determined at module instantiation time by using `import` and `export` syntax and cannot be changed at run time.
   115  
   116      When you import a CommonJS module into an ES module in node, node scans over the source code to attempt to detect the set of export names that the CommonJS module will end up using. That statically-determined set of names is used as the set of names that the ES module is allowed to import at module instantiation time. However, this scan appears to have bugs (or at least, can cause false positives) because it doesn't appear to do any scope analysis. Node will incorrectly consider the module to export something even if the assignment is done to a local variable instead of to the module-level `exports` object. For example:
   117  
   118      ```js
   119      // confuseNode.js
   120      exports.confuseNode = function(exports) {
   121        // If this local is called "exports", node incorrectly
   122        // thinks this file has an export called "notAnExport".
   123        exports.notAnExport = function() {
   124        };
   125      };
   126      ```
   127  
   128      You can see that node incorrectly thinks the file `confuseNode.js` has an export called `notAnExport` when that file is loaded in an ES module context:
   129  
   130      ```console
   131      $ node -e 'import("./confuseNode.js").then(console.log)'
   132      [Module: null prototype] {
   133        confuseNode: [Function (anonymous)],
   134        default: { confuseNode: [Function (anonymous)] },
   135        notAnExport: undefined
   136      }
   137      ```
   138  
   139      To avoid this, esbuild will now rename local variables that use the names `exports` and `module` when generating CommonJS output for the `node` platform.
   140  
   141  * Fix the return value of esbuild's `super()` shim ([#3538](https://github.com/evanw/esbuild/issues/3538))
   142  
   143      Some people write `constructor` methods that use the return value of `super()` instead of using `this`. This isn't too common because [TypeScript doesn't let you do that](https://github.com/microsoft/TypeScript/issues/37847) but it can come up when writing JavaScript. Previously esbuild's class lowering transform incorrectly transformed the return value of `super()` into `undefined`. With this release, the return value of `super()` will now be `this` instead:
   144  
   145      ```js
   146      // Original code
   147      class Foo extends Object {
   148        field
   149        constructor() {
   150          console.log(typeof super())
   151        }
   152      }
   153      new Foo
   154  
   155      // Old output (with --target=es6)
   156      class Foo extends Object {
   157        constructor() {
   158          var __super = (...args) => {
   159            super(...args);
   160            __publicField(this, "field");
   161          };
   162          console.log(typeof __super());
   163        }
   164      }
   165      new Foo();
   166  
   167      // New output (with --target=es6)
   168      class Foo extends Object {
   169        constructor() {
   170          var __super = (...args) => {
   171            super(...args);
   172            __publicField(this, "field");
   173            return this;
   174          };
   175          console.log(typeof __super());
   176        }
   177      }
   178      new Foo();
   179      ```
   180  
   181  * Terminate the Go GC when esbuild's `stop()` API is called ([#3552](https://github.com/evanw/esbuild/issues/3552))
   182  
   183      If you use esbuild with WebAssembly and pass the `worker: false` flag to `esbuild.initialize()`, then esbuild will run the WebAssembly module on the main thread. If you do this within a Deno test and that test calls `esbuild.stop()` to clean up esbuild's resources, Deno may complain that a `setTimeout()` call lasted past the end of the test. This happens when the Go is in the middle of a garbage collection pass and has scheduled additional ongoing garbage collection work. Normally calling `esbuild.stop()` will terminate the web worker that the WebAssembly module runs in, which will terminate the Go GC, but that doesn't happen if you disable the web worker with `worker: false`.
   184  
   185      With this release, esbuild will now attempt to terminate the Go GC in this edge case by calling `clearTimeout()` on these pending timeouts.
   186  
   187  * Apply `/* @__NO_SIDE_EFFECTS__ */` on tagged template literals ([#3511](https://github.com/evanw/esbuild/issues/3511))
   188  
   189      Tagged template literals that reference functions annotated with a `@__NO_SIDE_EFFECTS__` comment are now able to be removed via tree-shaking if the result is unused. This is a convention from [Rollup](https://github.com/rollup/rollup/pull/5024). Here is an example:
   190  
   191      ```js
   192      // Original code
   193      const html = /* @__NO_SIDE_EFFECTS__ */ (a, ...b) => ({ a, b })
   194      html`<a>remove</a>`
   195      x = html`<b>keep</b>`
   196  
   197      // Old output (with --tree-shaking=true)
   198      const html = /* @__NO_SIDE_EFFECTS__ */ (a, ...b) => ({ a, b });
   199      html`<a>remove</a>`;
   200      x = html`<b>keep</b>`;
   201  
   202      // New output (with --tree-shaking=true)
   203      const html = /* @__NO_SIDE_EFFECTS__ */ (a, ...b) => ({ a, b });
   204      x = html`<b>keep</b>`;
   205      ```
   206  
   207      Note that this feature currently only works within a single file, so it's not especially useful. This feature does not yet work across separate files. I still recommend using `@__PURE__` annotations instead of this feature, as they have wider tooling support. The drawback of course is that `@__PURE__` annotations need to be added at each call site, not at the declaration, and for non-call expressions such as template literals you need to wrap the expression in an IIFE (immediately-invoked function expression) to create a call expression to apply the `@__PURE__` annotation to.
   208  
   209  * Publish builds for IBM AIX PowerPC 64-bit ([#3549](https://github.com/evanw/esbuild/issues/3549))
   210  
   211      This release publishes a binary executable to npm for IBM AIX PowerPC 64-bit, which means that in theory esbuild can now be installed in that environment with `npm install esbuild`. This hasn't actually been tested yet. If you have access to such a system, it would be helpful to confirm whether or not doing this actually works.
   212  
   213  ## 0.19.9
   214  
   215  * Add support for transforming new CSS gradient syntax for older browsers
   216  
   217      The specification called [CSS Images Module Level 4](https://www.w3.org/TR/css-images-4/) introduces new CSS gradient syntax for customizing how the browser interpolates colors in between color stops. You can now control the color space that the interpolation happens in as well as (for "polar" color spaces) control whether hue angle interpolation happens clockwise or counterclockwise. You can read more about this in [Mozilla's blog post about new CSS gradient features](https://developer.mozilla.org/en-US/blog/css-color-module-level-4/).
   218  
   219      With this release, esbuild will now automatically transform this syntax for older browsers in the `target` list. For example, here's a gradient that should appear as a rainbow in a browser that supports this new syntax:
   220  
   221      ```css
   222      /* Original code */
   223      .rainbow-gradient {
   224        width: 100px;
   225        height: 100px;
   226        background: linear-gradient(in hsl longer hue, #7ff, #77f);
   227      }
   228  
   229      /* New output (with --target=chrome99) */
   230      .rainbow-gradient {
   231        width: 100px;
   232        height: 100px;
   233        background:
   234          linear-gradient(
   235            #77ffff,
   236            #77ffaa 12.5%,
   237            #77ff80 18.75%,
   238            #84ff77 21.88%,
   239            #99ff77 25%,
   240            #eeff77 37.5%,
   241            #fffb77 40.62%,
   242            #ffe577 43.75%,
   243            #ffbb77 50%,
   244            #ff9077 56.25%,
   245            #ff7b77 59.38%,
   246            #ff7788 62.5%,
   247            #ff77dd 75%,
   248            #ff77f2 78.12%,
   249            #f777ff 81.25%,
   250            #cc77ff 87.5%,
   251            #7777ff);
   252      }
   253      ```
   254  
   255      You can now use this syntax in your CSS source code and esbuild will automatically convert it to an equivalent gradient for older browsers. In addition, esbuild will now also transform "double position" and "transition hint" syntax for older browsers as appropriate:
   256  
   257      ```css
   258      /* Original code */
   259      .stripes {
   260        width: 100px;
   261        height: 100px;
   262        background: linear-gradient(#e65 33%, #ff2 33% 67%, #99e 67%);
   263      }
   264      .glow {
   265        width: 100px;
   266        height: 100px;
   267        background: radial-gradient(white 10%, 20%, black);
   268      }
   269  
   270      /* New output (with --target=chrome33) */
   271      .stripes {
   272        width: 100px;
   273        height: 100px;
   274        background:
   275          linear-gradient(
   276            #e65 33%,
   277            #ff2 33%,
   278            #ff2 67%,
   279            #99e 67%);
   280      }
   281      .glow {
   282        width: 100px;
   283        height: 100px;
   284        background:
   285          radial-gradient(
   286            #ffffff 10%,
   287            #aaaaaa 12.81%,
   288            #959595 15.62%,
   289            #7b7b7b 21.25%,
   290            #5a5a5a 32.5%,
   291            #444444 43.75%,
   292            #323232 55%,
   293            #161616 77.5%,
   294            #000000);
   295      }
   296      ```
   297  
   298      You can see visual examples of these new syntax features by looking at [esbuild's gradient transformation tests](https://esbuild.github.io/gradient-tests/).
   299  
   300      If necessary, esbuild will construct a new gradient that approximates the original gradient by recursively splitting the interval in between color stops until the approximation error is within a small threshold. That is why the above output CSS contains many more color stops than the input CSS.
   301  
   302      Note that esbuild deliberately _replaces_ the original gradient with the approximation instead of inserting the approximation before the original gradient as a fallback. The latest version of Firefox has multiple gradient rendering bugs (including incorrect interpolation of partially-transparent colors and interpolating non-sRGB colors using the incorrect color space). If esbuild didn't replace the original gradient, then Firefox would use the original gradient instead of the fallback the appearance would be incorrect in Firefox. In other words, the latest version of Firefox supports modern gradient syntax but interprets it incorrectly.
   303  
   304  * Add support for `color()`, `lab()`, `lch()`, `oklab()`, `oklch()`, and `hwb()` in CSS
   305  
   306      CSS has recently added lots of new ways of specifying colors. You can read more about this in [Chrome's blog post about CSS color spaces](https://developer.chrome.com/docs/css-ui/high-definition-css-color-guide).
   307  
   308      This release adds support for minifying colors that use the `color()`, `lab()`, `lch()`, `oklab()`, `oklch()`, or `hwb()` syntax and/or transforming these colors for browsers that don't support it yet:
   309  
   310      ```css
   311      /* Original code */
   312      div {
   313        color: hwb(90deg 20% 40%);
   314        background: color(display-p3 1 0 0);
   315      }
   316  
   317      /* New output (with --target=chrome99) */
   318      div {
   319        color: #669933;
   320        background: #ff0f0e;
   321        background: color(display-p3 1 0 0);
   322      }
   323      ```
   324  
   325      As you can see, colors outside of the sRGB color space such as `color(display-p3 1 0 0)` are mapped back into the sRGB gamut and inserted as a fallback for browsers that don't support the new color syntax.
   326  
   327  * Allow empty type parameter lists in certain cases ([#3512](https://github.com/evanw/esbuild/issues/3512))
   328  
   329      TypeScript allows interface declarations and type aliases to have empty type parameter lists. Previously esbuild didn't handle this edge case but with this release, esbuild will now parse this syntax:
   330  
   331      ```ts
   332      interface Foo<> {}
   333      type Bar<> = {}
   334      ```
   335  
   336      This fix was contributed by [@magic-akari](https://github.com/magic-akari).
   337  
   338  ## 0.19.8
   339  
   340  * Add a treemap chart to esbuild's bundle analyzer ([#2848](https://github.com/evanw/esbuild/issues/2848))
   341  
   342      The bundler analyzer on esbuild's website (https://esbuild.github.io/analyze/) now has a treemap chart type in addition to the two existing chart types (sunburst and flame). This should be more familiar for people coming from other similar tools, as well as make better use of large screens.
   343  
   344  * Allow decorators after the `export` keyword ([#104](https://github.com/evanw/esbuild/issues/104))
   345  
   346      Previously esbuild's decorator parser followed the original behavior of TypeScript's experimental decorators feature, which only allowed decorators to come before the `export` keyword. However, the upcoming JavaScript decorators feature also allows decorators to come after the `export` keyword. And with TypeScript 5.0, TypeScript now also allows experimental decorators to come after the `export` keyword too. So esbuild now allows this as well:
   347  
   348      ```js
   349      // This old syntax has always been permitted:
   350      @decorator export class Foo {}
   351      @decorator export default class Foo {}
   352  
   353      // This new syntax is now permitted too:
   354      export @decorator class Foo {}
   355      export default @decorator class Foo {}
   356      ```
   357  
   358      In addition, esbuild's decorator parser has been rewritten to fix several subtle and likely unimportant edge cases with esbuild's parsing of exports and decorators in TypeScript (e.g. TypeScript apparently does automatic semicolon insertion after `interface` and `export interface` but not after `export default interface`).
   359  
   360  * Pretty-print decorators using the same whitespace as the original
   361  
   362      When printing code containing decorators, esbuild will now try to respect whether the original code contained newlines after the decorator or not. This can make generated code containing many decorators much more compact to read:
   363  
   364      ```js
   365      // Original code
   366      class Foo {
   367        @a @b @c abc
   368        @x @y @z xyz
   369      }
   370  
   371      // Old output
   372      class Foo {
   373        @a
   374        @b
   375        @c
   376        abc;
   377        @x
   378        @y
   379        @z
   380        xyz;
   381      }
   382  
   383      // New output
   384      class Foo {
   385        @a @b @c abc;
   386        @x @y @z xyz;
   387      }
   388      ```
   389  
   390  ## 0.19.7
   391  
   392  * Add support for bundling code that uses import attributes ([#3384](https://github.com/evanw/esbuild/issues/3384))
   393  
   394      JavaScript is gaining new syntax for associating a map of string key-value pairs with individual ESM imports. The proposal is still a work in progress and is still undergoing significant changes before being finalized. However, the first iteration has already been shipping in Chromium-based browsers for a while, and the second iteration has landed in V8 and is now shipping in node, so it makes sense for esbuild to support it. Here are the two major iterations of this proposal (so far):
   395  
   396      1. Import assertions (deprecated, will not be standardized)
   397          * Uses the `assert` keyword
   398          * Does _not_ affect module resolution
   399          * Causes an error if the assertion fails
   400          * Shipping in Chrome 91+ (and in esbuild 0.11.22+)
   401  
   402      2. Import attributes (currently set to become standardized)
   403          * Uses the `with` keyword
   404          * Affects module resolution
   405          * Unknown attributes cause an error
   406          * Shipping in node 21+
   407  
   408      You can already use esbuild to bundle code that uses import assertions (the first iteration). However, this feature is mostly useless for bundlers because import assertions are not allowed to affect module resolution. It's basically only useful as an annotation on external imports, which esbuild will then preserve in the output for use in a browser (which would otherwise refuse to load certain imports).
   409  
   410      With this release, esbuild now supports bundling code that uses import attributes (the second iteration). This is much more useful for bundlers because they are allowed to affect module resolution, which means the key-value pairs can be provided to plugins. Here's an example, which uses esbuild's built-in support for the upcoming [JSON module standard](https://github.com/tc39/proposal-json-modules):
   411  
   412      ```js
   413      // On static imports
   414      import foo from './package.json' with { type: 'json' }
   415      console.log(foo)
   416  
   417      // On dynamic imports
   418      const bar = await import('./package.json', { with: { type: 'json' } })
   419      console.log(bar)
   420      ```
   421  
   422      One important consequence of the change in semantics between import assertions and import attributes is that two imports with identical paths but different import attributes are now considered to be different modules. This is because the import attributes are provided to the loader, which might then use those attributes during loading. For example, you could imagine an image loader that produces an image of a different size depending on the import attributes.
   423  
   424      Import attributes are now reported in the [metafile](https://esbuild.github.io/api/#metafile) and are now provided to [on-load plugins](https://esbuild.github.io/plugins/#on-load) as a map in the `with` property. For example, here's an esbuild plugin that turns all imports with a `type` import attribute equal to `'cheese'` into a module that exports the cheese emoji:
   425  
   426      ```js
   427      const cheesePlugin = {
   428        name: 'cheese',
   429        setup(build) {
   430          build.onLoad({ filter: /.*/ }, args => {
   431            if (args.with.type === 'cheese') return {
   432              contents: `export default "šŸ§€"`,
   433            }
   434          })
   435        }
   436      }
   437  
   438      require('esbuild').build({
   439        bundle: true,
   440        write: false,
   441        stdin: {
   442          contents: `
   443            import foo from 'data:text/javascript,' with { type: 'cheese' }
   444            console.log(foo)
   445          `,
   446        },
   447        plugins: [cheesePlugin],
   448      }).then(result => {
   449        const code = new Function(result.outputFiles[0].text)
   450        code()
   451      })
   452      ```
   453  
   454      Warning: It's possible that the second iteration of this feature may change significantly again even though it's already shipping in real JavaScript VMs (since it has already happened once before). In that case, esbuild may end up adjusting its implementation to match the eventual standard behavior. So keep in mind that by using this, you are using an unstable upcoming JavaScript feature that may undergo breaking changes in the future.
   455  
   456  * Adjust TypeScript experimental decorator behavior ([#3230](https://github.com/evanw/esbuild/issues/3230), [#3326](https://github.com/evanw/esbuild/issues/3326), [#3394](https://github.com/evanw/esbuild/issues/3394))
   457  
   458      With this release, esbuild will now allow TypeScript experimental decorators to access both static class properties and `#private` class names. For example:
   459  
   460      ```js
   461      const check =
   462        <T,>(a: T, b: T): PropertyDecorator =>
   463          () => console.log(a === b)
   464  
   465      async function test() {
   466        class Foo {
   467          static #foo = 1
   468          static bar = 1 + Foo.#foo
   469          @check(Foo.#foo, 1) a: any
   470          @check(Foo.bar, await Promise.resolve(2)) b: any
   471        }
   472      }
   473  
   474      test().then(() => console.log('pass'))
   475      ```
   476  
   477      This will now print `true true pass` when compiled by esbuild. Previously esbuild evaluated TypeScript decorators outside of the class body, so it didn't allow decorators to access `Foo` or `#foo`. Now esbuild does something different, although it's hard to concisely explain exactly what esbuild is doing now (see the background section below for more information).
   478  
   479      Note that TypeScript's experimental decorator support is currently buggy: TypeScript's compiler passes this test if only the first `@check` is present or if only the second `@check` is present, but TypeScript's compiler fails this test if both checks are present together. I haven't changed esbuild to match TypeScript's behavior exactly here because I'm waiting for TypeScript to fix these bugs instead.
   480  
   481      Some background: TypeScript experimental decorators don't have consistent semantics regarding the context that the decorators are evaluated in. For example, TypeScript will let you use `await` within a decorator, which implies that the decorator runs outside the class body (since `await` isn't supported inside a class body), but TypeScript will also let you use `#private` names, which implies that the decorator runs inside the class body (since `#private` names are only supported inside a class body). The value of `this` in a decorator is also buggy (the run-time value of `this` changes if any decorator in the class uses a `#private` name but the type of `this` doesn't change, leading to the type checker no longer matching reality). These inconsistent semantics make it hard for esbuild to implement this feature as decorator evaluation happens in some superposition of both inside and outside the class body that is particular to the internal implementation details of the TypeScript compiler.
   482  
   483  * Forbid `--keep-names` when targeting old browsers ([#3477](https://github.com/evanw/esbuild/issues/3477))
   484  
   485      The `--keep-names` setting needs to be able to assign to the `name` property on functions and classes. However, before ES6 this property was non-configurable, and attempting to assign to it would throw an error. So with this release, esbuild will no longer allow you to enable this setting while also targeting a really old browser.
   486  
   487  ## 0.19.6
   488  
   489  * Fix a constant folding bug with bigint equality
   490  
   491      This release fixes a bug where esbuild incorrectly checked for bigint equality by checking the equality of the bigint literal text. This is correct if the bigint doesn't have a radix because bigint literals without a radix are always in canonical form (since leading zeros are not allowed). However, this is incorrect if the bigint has a radix (e.g. `0x123n`) because the canonical form is not enforced when a radix is present.
   492  
   493      ```js
   494      // Original code
   495      console.log(!!0n, !!1n, 123n === 123n)
   496      console.log(!!0x0n, !!0x1n, 123n === 0x7Bn)
   497  
   498      // Old output
   499      console.log(false, true, true);
   500      console.log(true, true, false);
   501  
   502      // New output
   503      console.log(false, true, true);
   504      console.log(!!0x0n, !!0x1n, 123n === 0x7Bn);
   505      ```
   506  
   507  * Add some improvements to the JavaScript minifier
   508  
   509      This release adds more cases to the JavaScript minifier, including support for inlining `String.fromCharCode` and `String.prototype.charCodeAt` when possible:
   510  
   511      ```js
   512      // Original code
   513      document.onkeydown = e => e.keyCode === 'A'.charCodeAt(0) && console.log(String.fromCharCode(55358, 56768))
   514  
   515      // Old output (with --minify)
   516      document.onkeydown=o=>o.keyCode==="A".charCodeAt(0)&&console.log(String.fromCharCode(55358,56768));
   517  
   518      // New output (with --minify)
   519      document.onkeydown=o=>o.keyCode===65&&console.log("šŸ§€");
   520      ```
   521  
   522      In addition, immediately-invoked function expressions (IIFEs) that return a single expression are now inlined when minifying. This makes it possible to use IIFEs in combination with `@__PURE__` annotations to annotate arbitrary expressions as side-effect free without the IIFE wrapper impacting code size. For example:
   523  
   524      ```js
   525      // Original code
   526      const sideEffectFreeOffset = /* @__PURE__ */ (() => computeSomething())()
   527      use(sideEffectFreeOffset)
   528  
   529      // Old output (with --minify)
   530      const e=(()=>computeSomething())();use(e);
   531  
   532      // New output (with --minify)
   533      const e=computeSomething();use(e);
   534      ```
   535  
   536  * Automatically prefix the `mask-composite` CSS property for WebKit ([#3493](https://github.com/evanw/esbuild/issues/3493))
   537  
   538      The `mask-composite` property will now be prefixed as `-webkit-mask-composite` for older WebKit-based browsers. In addition to prefixing the property name, handling older browsers also requires rewriting the values since WebKit uses non-standard names for the mask composite modes:
   539  
   540      ```css
   541      /* Original code */
   542      div {
   543        mask-composite: add, subtract, intersect, exclude;
   544      }
   545  
   546      /* New output (with --target=chrome100) */
   547      div {
   548        -webkit-mask-composite:
   549          source-over,
   550          source-out,
   551          source-in,
   552          xor;
   553        mask-composite:
   554          add,
   555          subtract,
   556          intersect,
   557          exclude;
   558      }
   559      ```
   560  
   561  * Avoid referencing `this` from JSX elements in derived class constructors ([#3454](https://github.com/evanw/esbuild/issues/3454))
   562  
   563      When you enable `--jsx=automatic` and `--jsx-dev`, the JSX transform is supposed to insert `this` as the last argument to the `jsxDEV` function. I'm not sure exactly why this is and I can't find any specification for it, but in any case this causes the generated code to crash when you use a JSX element in a derived class constructor before the call to `super()` as `this` is not allowed to be accessed at that point. For example
   564  
   565      ```js
   566      // Original code
   567      class ChildComponent extends ParentComponent {
   568        constructor() {
   569          super(<div />)
   570        }
   571      }
   572  
   573      // Problematic output (with --loader=jsx --jsx=automatic --jsx-dev)
   574      import { jsxDEV } from "react/jsx-dev-runtime";
   575      class ChildComponent extends ParentComponent {
   576        constructor() {
   577          super(/* @__PURE__ */ jsxDEV("div", {}, void 0, false, {
   578            fileName: "<stdin>",
   579            lineNumber: 3,
   580            columnNumber: 15
   581          }, this)); // The reference to "this" crashes here
   582        }
   583      }
   584      ```
   585  
   586      The TypeScript compiler doesn't handle this at all while the Babel compiler just omits `this` for the entire constructor (even after the call to `super()`). There seems to be no specification so I can't be sure that this change doesn't break anything important. But given that Babel is pretty loose with this and TypeScript doesn't handle this at all, I'm guessing this value isn't too important. React's blog post seems to indicate that this value was intended to be used for a React-specific migration warning at some point, so it could even be that this value is irrelevant now. Anyway the crash in this case should now be fixed.
   587  
   588  * Allow package subpath imports to map to node built-ins ([#3485](https://github.com/evanw/esbuild/issues/3485))
   589  
   590      You are now able to use a [subpath import](https://nodejs.org/api/packages.html#subpath-imports) in your package to resolve to a node built-in module. For example, with a `package.json` file like this:
   591  
   592      ```json
   593      {
   594        "type": "module",
   595        "imports": {
   596          "#stream": {
   597            "node": "stream",
   598            "default": "./stub.js"
   599          }
   600        }
   601      }
   602      ```
   603  
   604      You can now import from node's `stream` module like this:
   605  
   606      ```js
   607      import * as stream from '#stream';
   608      console.log(Object.keys(stream));
   609      ```
   610  
   611      This will import from node's `stream` module when the platform is `node` and from `./stub.js` otherwise.
   612  
   613  * No longer throw an error when a `Symbol` is missing ([#3453](https://github.com/evanw/esbuild/issues/3453))
   614  
   615      Certain JavaScript syntax features use special properties on the global `Symbol` object. For example, the asynchronous iteration syntax uses `Symbol.asyncIterator`. Previously esbuild's generated code for older browsers required this symbol to be polyfilled. However, starting with this release esbuild will use [`Symbol.for()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/for) to construct these symbols if they are missing instead of throwing an error about a missing polyfill. This means your code no longer needs to include a polyfill for missing symbols as long as your code also uses `Symbol.for()` for missing symbols.
   616  
   617  * Parse upcoming changes to TypeScript syntax ([#3490](https://github.com/evanw/esbuild/issues/3490), [#3491](https://github.com/evanw/esbuild/pull/3491))
   618  
   619      With this release, you can now use `from` as the name of a default type-only import in TypeScript code, as well as `of` as the name of an `await using` loop iteration variable:
   620  
   621      ```ts
   622      import type from from 'from'
   623      for (await using of of of) ;
   624      ```
   625  
   626      This matches similar changes in the TypeScript compiler ([#56376](https://github.com/microsoft/TypeScript/issues/56376) and [#55555](https://github.com/microsoft/TypeScript/issues/55555)) which will start allowing this syntax in an upcoming version of TypeScript. Please never actually write code like this.
   627  
   628      The type-only import syntax change was contributed by [@magic-akari](https://github.com/magic-akari).
   629  
   630  ## 0.19.5
   631  
   632  * Fix a regression in 0.19.0 regarding `paths` in `tsconfig.json` ([#3354](https://github.com/evanw/esbuild/issues/3354))
   633  
   634      The fix in esbuild version 0.19.0 to process `tsconfig.json` aliases before the `--packages=external` setting unintentionally broke an edge case in esbuild's handling of certain `tsconfig.json` aliases where there are multiple files with the same name in different directories. This release adjusts esbuild's behavior for this edge case so that it passes while still processing aliases before `--packages=external`. Please read the linked issue for more details.
   635  
   636  * Fix a CSS `font` property minification bug ([#3452](https://github.com/evanw/esbuild/issues/3452))
   637  
   638      This release fixes a bug where esbuild's CSS minifier didn't insert a space between the font size and the font family in the `font` CSS shorthand property in the edge case where the original source code didn't already have a space and the leading string token was shortened to an identifier:
   639  
   640      ```css
   641      /* Original code */
   642      .foo { font: 16px"Menlo"; }
   643  
   644      /* Old output (with --minify) */
   645      .foo{font:16pxMenlo}
   646  
   647      /* New output (with --minify) */
   648      .foo{font:16px Menlo}
   649      ```
   650  
   651  * Fix bundling CSS with asset names containing spaces ([#3410](https://github.com/evanw/esbuild/issues/3410))
   652  
   653      Assets referenced via CSS `url()` tokens may cause esbuild to generate invalid output when bundling if the file name contains spaces (e.g. `url(image 2.png)`). With this release, esbuild will now quote all bundled asset references in `url()` tokens to avoid this problem. This only affects assets loaded using the `file` and `copy` loaders.
   654  
   655  * Fix invalid CSS `url()` tokens in `@import` rules ([#3426](https://github.com/evanw/esbuild/issues/3426))
   656  
   657      In the future, CSS `url()` tokens may contain additional stuff after the URL. This is irrelevant today as no CSS specification does this. But esbuild previously had a bug where using these tokens in an `@import` rule resulted in malformed output. This bug has been fixed.
   658  
   659  * Fix `browser` + `false` + `type: module` in `package.json` ([#3367](https://github.com/evanw/esbuild/issues/3367))
   660  
   661      The `browser` field in `package.json` allows you to map a file to `false` to have it be treated as an empty file when bundling for the browser. However, if `package.json` contains `"type": "module"` then all `.js` files will be considered ESM, not CommonJS. Importing a named import from an empty CommonJS file gives you undefined, but importing a named export from an empty ESM file is a build error. This release changes esbuild's interpretation of these files mapped to `false` in this situation from ESM to CommonJS to avoid generating build errors for named imports.
   662  
   663  * Fix a bug in top-level await error reporting ([#3400](https://github.com/evanw/esbuild/issues/3400))
   664  
   665      Using `require()` on a file that contains [top-level await](https://v8.dev/features/top-level-await) is not allowed because `require()` must return synchronously and top-level await makes that impossible. You will get a build error if you try to bundle code that does this with esbuild. This release fixes a bug in esbuild's error reporting code for complex cases of this situation involving multiple levels of imports to get to the module containing the top-level await.
   666  
   667  * Update to Unicode 15.1.0
   668  
   669      The character tables that determine which characters form valid JavaScript identifiers have been updated from Unicode version 15.0.0 to the newly-released Unicode version 15.1.0. I'm not putting an example in the release notes because all of the new characters will likely just show up as little squares since fonts haven't been updated yet. But you can read https://www.unicode.org/versions/Unicode15.1.0/#Summary for more information about the changes.
   670  
   671      This upgrade was contributed by [@JLHwung](https://github.com/JLHwung).
   672  
   673  ## 0.19.4
   674  
   675  * Fix printing of JavaScript decorators in tricky cases ([#3396](https://github.com/evanw/esbuild/issues/3396))
   676  
   677      This release fixes some bugs where esbuild's pretty-printing of JavaScript decorators could incorrectly produced code with a syntax error. The problem happened because esbuild sometimes substitutes identifiers for other expressions in the pretty-printer itself, but the decision about whether to wrap the expression or not didn't account for this. Here are some examples:
   678  
   679      ```js
   680      // Original code
   681      import { constant } from './constants.js'
   682      import { imported } from 'external'
   683      import { undef } from './empty.js'
   684      class Foo {
   685        @constant()
   686        @imported()
   687        @undef()
   688        foo
   689      }
   690  
   691      // Old output (with --bundle --format=cjs --packages=external --minify-syntax)
   692      var import_external = require("external");
   693      var Foo = class {
   694        @123()
   695        @(0, import_external.imported)()
   696        @(void 0)()
   697        foo;
   698      };
   699  
   700      // New output (with --bundle --format=cjs --packages=external --minify-syntax)
   701      var import_external = require("external");
   702      var Foo = class {
   703        @(123())
   704        @((0, import_external.imported)())
   705        @((void 0)())
   706        foo;
   707      };
   708      ```
   709  
   710  * Allow pre-release versions to be passed to `target` ([#3388](https://github.com/evanw/esbuild/issues/3388))
   711  
   712      People want to be able to pass version numbers for unreleased versions of node (which have extra stuff after the version numbers) to esbuild's `target` setting and have esbuild do something reasonable with them. These version strings are of course not present in esbuild's internal feature compatibility table because an unreleased version has not been released yet (by definition). With this release, esbuild will now attempt to accept these version strings passed to `target` and do something reasonable with them.
   713  
   714  ## 0.19.3
   715  
   716  * Fix `list-style-type` with the `local-css` loader ([#3325](https://github.com/evanw/esbuild/issues/3325))
   717  
   718      The `local-css` loader incorrectly treated all identifiers provided to `list-style-type` as a custom local identifier. That included identifiers such as `none` which have special meaning in CSS, and which should not be treated as custom local identifiers. This release fixes this bug:
   719  
   720      ```css
   721      /* Original code */
   722      ul { list-style-type: none }
   723  
   724      /* Old output (with --loader=local-css) */
   725      ul {
   726        list-style-type: stdin_none;
   727      }
   728  
   729      /* New output (with --loader=local-css) */
   730      ul {
   731        list-style-type: none;
   732      }
   733      ```
   734  
   735      Note that this bug only affected code using the `local-css` loader. It did not affect code using the `css` loader.
   736  
   737  * Avoid inserting temporary variables before `use strict` ([#3322](https://github.com/evanw/esbuild/issues/3322))
   738  
   739      This release fixes a bug where esbuild could incorrectly insert automatically-generated temporary variables before `use strict` directives:
   740  
   741      ```js
   742      // Original code
   743      function foo() {
   744        'use strict'
   745        a.b?.c()
   746      }
   747  
   748      // Old output (with --target=es6)
   749      function foo() {
   750        var _a;
   751        "use strict";
   752        (_a = a.b) == null ? void 0 : _a.c();
   753      }
   754  
   755      // New output (with --target=es6)
   756      function foo() {
   757        "use strict";
   758        var _a;
   759        (_a = a.b) == null ? void 0 : _a.c();
   760      }
   761      ```
   762  
   763  * Adjust TypeScript `enum` output to better approximate `tsc` ([#3329](https://github.com/evanw/esbuild/issues/3329))
   764  
   765      TypeScript enum values can be either number literals or string literals. Numbers create a bidirectional mapping between the name and the value but strings only create a unidirectional mapping from the name to the value. When the enum value is neither a number literal nor a string literal, TypeScript and esbuild both default to treating it as a number:
   766  
   767      ```ts
   768      // Original TypeScript code
   769      declare const foo: any
   770      enum Foo {
   771        NUMBER = 1,
   772        STRING = 'a',
   773        OTHER = foo,
   774      }
   775  
   776      // Compiled JavaScript code (from "tsc")
   777      var Foo;
   778      (function (Foo) {
   779        Foo[Foo["NUMBER"] = 1] = "NUMBER";
   780        Foo["STRING"] = "a";
   781        Foo[Foo["OTHER"] = foo] = "OTHER";
   782      })(Foo || (Foo = {}));
   783      ```
   784  
   785      However, TypeScript does constant folding slightly differently than esbuild. For example, it may consider template literals to be string literals in some cases:
   786  
   787      ```ts
   788      // Original TypeScript code
   789      declare const foo = 'foo'
   790      enum Foo {
   791        PRESENT = `${foo}`,
   792        MISSING = `${bar}`,
   793      }
   794  
   795      // Compiled JavaScript code (from "tsc")
   796      var Foo;
   797      (function (Foo) {
   798        Foo["PRESENT"] = "foo";
   799        Foo[Foo["MISSING"] = `${bar}`] = "MISSING";
   800      })(Foo || (Foo = {}));
   801      ```
   802  
   803      The template literal initializer for `PRESENT` is treated as a string while the template literal initializer for `MISSING` is treated as a number. Previously esbuild treated both of these cases as a number but starting with this release, esbuild will now treat both of these cases as a string. This doesn't exactly match the behavior of `tsc` but in the case where the behavior diverges `tsc` reports a compile error, so this seems like acceptible behavior for esbuild. Note that handling these cases completely correctly would require esbuild to parse type declarations (see the `declare` keyword), which esbuild deliberately doesn't do.
   804  
   805  * Ignore case in CSS in more places ([#3316](https://github.com/evanw/esbuild/issues/3316))
   806  
   807      This release makes esbuild's CSS support more case-agnostic, which better matches how browsers work. For example:
   808  
   809      ```css
   810      /* Original code */
   811      @KeyFrames Foo { From { OpaCity: 0 } To { OpaCity: 1 } }
   812      body { CoLoR: YeLLoW }
   813  
   814      /* Old output (with --minify) */
   815      @KeyFrames Foo{From {OpaCity: 0} To {OpaCity: 1}}body{CoLoR:YeLLoW}
   816  
   817      /* New output (with --minify) */
   818      @KeyFrames Foo{0%{OpaCity:0}To{OpaCity:1}}body{CoLoR:#ff0}
   819      ```
   820  
   821      Please never actually write code like this.
   822  
   823  * Improve the error message for `null` entries in `exports` ([#3377](https://github.com/evanw/esbuild/issues/3377))
   824  
   825      Package authors can disable package export paths with the `exports` map in `package.json`. With this release, esbuild now has a clearer error message that points to the `null` token in `package.json` itself instead of to the surrounding context. Here is an example of the new error message:
   826  
   827      ```
   828      āœ˜ [ERROR] Could not resolve "msw/browser"
   829  
   830          lib/msw-config.ts:2:28:
   831            2 ā”‚ import { setupWorker } from 'msw/browser';
   832              ā•µ                             ~~~~~~~~~~~~~
   833  
   834        The path "./browser" cannot be imported from package "msw" because it was explicitly disabled by
   835        the package author here:
   836  
   837          node_modules/msw/package.json:17:14:
   838            17 ā”‚       "node": null,
   839               ā•µ               ~~~~
   840  
   841        You can mark the path "msw/browser" as external to exclude it from the bundle, which will remove
   842        this error and leave the unresolved path in the bundle.
   843      ```
   844  
   845  * Parse and print the `with` keyword in `import` statements
   846  
   847      JavaScript was going to have a feature called "import assertions" that adds an `assert` keyword to `import` statements. It looked like this:
   848  
   849      ```js
   850      import stuff from './stuff.json' assert { type: 'json' }
   851      ```
   852  
   853      The feature provided a way to assert that the imported file is of a certain type (but was not allowed to affect how the import is interpreted, even though that's how everyone expected it to behave). The feature was fully specified and then actually implemented and shipped in Chrome before the people behind the feature realized that they should allow it to affect how the import is interpreted after all. So import assertions are no longer going to be added to the language.
   854  
   855      Instead, the [current proposal](https://github.com/tc39/proposal-import-attributes) is to add a feature called "import attributes" instead that adds a `with` keyword to import statements. It looks like this:
   856  
   857      ```js
   858      import stuff from './stuff.json' with { type: 'json' }
   859      ```
   860  
   861      This feature provides a way to affect how the import is interpreted. With this release, esbuild now has preliminary support for parsing and printing this new `with` keyword. The `with` keyword is not yet interpreted by esbuild, however, so bundling code with it will generate a build error. All this release does is allow you to use esbuild to process code containing it (such as removing types from TypeScript code). Note that this syntax is not yet a part of JavaScript and may be removed or altered in the future if the specification changes (which it already has once, as described above). If that happens, esbuild reserves the right to remove or alter its support for this syntax too.
   862  
   863  ## 0.19.2
   864  
   865  * Update how CSS nesting is parsed again
   866  
   867      CSS nesting syntax has been changed again, and esbuild has been updated to match. Type selectors may now be used with CSS nesting:
   868  
   869      ```css
   870      .foo {
   871        div {
   872          color: red;
   873        }
   874      }
   875      ```
   876  
   877      Previously this was disallowed in the CSS specification because it's ambiguous whether an identifier is a declaration or a nested rule starting with a type selector without requiring unbounded lookahead in the parser. It has now been allowed because the CSS working group has decided that requiring unbounded lookahead is acceptable after all.
   878  
   879      Note that this change means esbuild no longer considers any existing browser to support CSS nesting since none of the existing browsers support this new syntax. CSS nesting will now always be transformed when targeting a browser. This situation will change in the future as browsers add support for this new syntax.
   880  
   881  * Fix a scope-related bug with `--drop-labels=` ([#3311](https://github.com/evanw/esbuild/issues/3311))
   882  
   883      The recently-released `--drop-labels=` feature previously had a bug where esbuild's internal scope stack wasn't being restored properly when a statement with a label was dropped. This could manifest as a tree-shaking issue, although it's possible that this could have also been causing other subtle problems too. The bug has been fixed in this release.
   884  
   885  * Make renamed CSS names unique across entry points ([#3295](https://github.com/evanw/esbuild/issues/3295))
   886  
   887      Previously esbuild's generated names for local names in CSS were only unique within a given entry point (or across all entry points when code splitting was enabled). That meant that building multiple entry points with esbuild could result in local names being renamed to the same identifier even when those entry points were built simultaneously within a single esbuild API call. This problem was especially likely to happen with minification enabled. With this release, esbuild will now avoid renaming local names from two separate entry points to the same name if those entry points were built with a single esbuild API call, even when code splitting is disabled.
   888  
   889  * Fix CSS ordering bug with `@layer` before `@import`
   890  
   891      CSS lets you put `@layer` rules before `@import` rules to define the order of layers in a stylesheet. Previously esbuild's CSS bundler incorrectly ordered these after the imported files because before the introduction of cascade layers to CSS, imported files could be bundled by removing the `@import` rules and then joining files together in the right order. But with `@layer`, CSS files may now need to be split apart into multiple pieces in the bundle. For example:
   892  
   893      ```
   894      /* Original code */
   895      @layer start;
   896      @import "data:text/css,@layer inner.start;";
   897      @import "data:text/css,@layer inner.end;";
   898      @layer end;
   899  
   900      /* Old output (with --bundle) */
   901      @layer inner.start;
   902      @layer inner.end;
   903      @layer start;
   904      @layer end;
   905  
   906      /* New output (with --bundle) */
   907      @layer start;
   908      @layer inner.start;
   909      @layer inner.end;
   910      @layer end;
   911      ```
   912  
   913  * Unwrap nested duplicate `@media` rules ([#3226](https://github.com/evanw/esbuild/issues/3226))
   914  
   915      With this release, esbuild's CSS minifier will now automatically unwrap duplicate nested `@media` rules:
   916  
   917      ```css
   918      /* Original code */
   919      @media (min-width: 1024px) {
   920        .foo { color: red }
   921        @media (min-width: 1024px) {
   922          .bar { color: blue }
   923        }
   924      }
   925  
   926      /* Old output (with --minify) */
   927      @media (min-width: 1024px){.foo{color:red}@media (min-width: 1024px){.bar{color:#00f}}}
   928  
   929      /* New output (with --minify) */
   930      @media (min-width: 1024px){.foo{color:red}.bar{color:#00f}}
   931      ```
   932  
   933      These rules are unlikely to be authored manually but may result from using frameworks such as Tailwind to generate CSS.
   934  
   935  ## 0.19.1
   936  
   937  * Fix a regression with `baseURL` in `tsconfig.json` ([#3307](https://github.com/evanw/esbuild/issues/3307))
   938  
   939      The previous release moved `tsconfig.json` path resolution before `--packages=external` checks to allow the [`paths` field](https://www.typescriptlang.org/tsconfig#paths) in `tsconfig.json` to avoid a package being marked as external. However, that reordering accidentally broke the behavior of the `baseURL` field from `tsconfig.json`. This release moves these path resolution rules around again in an attempt to allow both of these cases to work.
   940  
   941  * Parse TypeScript type arguments for JavaScript decorators ([#3308](https://github.com/evanw/esbuild/issues/3308))
   942  
   943      When parsing JavaScript decorators in TypeScript (i.e. with `experimentalDecorators` disabled), esbuild previously didn't parse type arguments. Type arguments will now be parsed starting with this release. For example:
   944  
   945      ```ts
   946      @foo<number>
   947      @bar<number, string>()
   948      class Foo {}
   949      ```
   950  
   951  * Fix glob patterns matching extra stuff at the end ([#3306](https://github.com/evanw/esbuild/issues/3306))
   952  
   953      Previously glob patterns such as `./*.js` would incorrectly behave like `./*.js*` during path matching (also matching `.js.map` files, for example). This was never intentional behavior, and has now been fixed.
   954  
   955  * Change the permissions of esbuild's generated output files ([#3285](https://github.com/evanw/esbuild/issues/3285))
   956  
   957      This release changes the permissions of the output files that esbuild generates to align with the default behavior of node's [`fs.writeFileSync`](https://nodejs.org/api/fs.html#fswritefilesyncfile-data-options) function. Since most tools written in JavaScript use `fs.writeFileSync`, this should make esbuild more consistent with how other JavaScript build tools behave.
   958  
   959      The full Unix-y details: Unix permissions use three-digit octal notation where the three digits mean "user, group, other" in that order. Within a digit, 4 means "read" and 2 means "write" and 1 means "execute". So 6 == 4 + 2 == read + write. Previously esbuild uses 0644 permissions (the leading 0 means octal notation) but the permissions for `fs.writeFileSync` defaults to 0666, so esbuild will now use 0666 permissions. This does not necessarily mean that the files esbuild generates will end up having 0666 permissions, however, as there is another Unix feature called "umask" where the operating system masks out some of these bits. If your umask is set to 0022 then the generated files will have 0644 permissions, and if your umask is set to 0002 then the generated files will have 0664 permissions.
   960  
   961  * Fix a subtle CSS ordering issue with `@import` and `@layer`
   962  
   963      With this release, esbuild may now introduce additional `@layer` rules when bundling CSS to better preserve the layer ordering of the input code. Here's an example of an edge case where this matters:
   964  
   965      ```css
   966      /* entry.css */
   967      @import "a.css";
   968      @import "b.css";
   969      @import "a.css";
   970      ```
   971  
   972      ```css
   973      /* a.css */
   974      @layer a {
   975        body {
   976          background: red;
   977        }
   978      }
   979      ```
   980  
   981      ```css
   982      /* b.css */
   983      @layer b {
   984        body {
   985          background: green;
   986        }
   987      }
   988      ```
   989  
   990      This CSS should set the body background to `green`, which is what happens in the browser. Previously esbuild generated the following output which incorrectly sets the body background to `red`:
   991  
   992      ```css
   993      /* b.css */
   994      @layer b {
   995        body {
   996          background: green;
   997        }
   998      }
   999  
  1000      /* a.css */
  1001      @layer a {
  1002        body {
  1003          background: red;
  1004        }
  1005      }
  1006      ```
  1007  
  1008      This difference in behavior is because the browser evaluates `a.css` + `b.css` + `a.css` (in CSS, each `@import` is replaced with a copy of the imported file) while esbuild was only writing out `b.css` + `a.css`. The first copy of `a.css` wasn't being written out by esbuild for two reasons: 1) bundlers care about code size and try to avoid emitting duplicate CSS and 2) when there are multiple copies of a CSS file, normally only the _last_ copy matters since the last declaration with equal specificity wins in CSS.
  1009  
  1010      However, `@layer` was recently added to CSS and for `@layer` the _first_ copy matters because layers are ordered using their first location in source code order. This introduction of `@layer` means esbuild needs to change its bundling algorithm. An easy solution would be for esbuild to write out `a.css` twice, but that would be inefficient. So what I'm going to try to have esbuild do with this release is to write out an abbreviated form of the first copy of a CSS file that only includes the `@layer` information, and then still only write out the full CSS file once for the last copy. So esbuild's output for this edge case now looks like this:
  1011  
  1012      ```css
  1013      /* a.css */
  1014      @layer a;
  1015  
  1016      /* b.css */
  1017      @layer b {
  1018        body {
  1019          background: green;
  1020        }
  1021      }
  1022  
  1023      /* a.css */
  1024      @layer a {
  1025        body {
  1026          background: red;
  1027        }
  1028      }
  1029      ```
  1030  
  1031      The behavior of the bundled CSS now matches the behavior of the unbundled CSS. You may be wondering why esbuild doesn't just write out `a.css` first followed by `b.css`. That would work in this case but it doesn't work in general because for any rules outside of a `@layer` rule, the last copy should still win instead of the first copy.
  1032  
  1033  * Fix a bug with esbuild's TypeScript type definitions ([#3299](https://github.com/evanw/esbuild/pull/3299))
  1034  
  1035      This release fixes a copy/paste error with the TypeScript type definitions for esbuild's JS API:
  1036  
  1037      ```diff
  1038       export interface TsconfigRaw {
  1039         compilerOptions?: {
  1040      -    baseUrl?: boolean
  1041      +    baseUrl?: string
  1042           ...
  1043         }
  1044       }
  1045      ```
  1046  
  1047      This fix was contributed by [@privatenumber](https://github.com/privatenumber).
  1048  
  1049  ## 0.19.0
  1050  
  1051  **This release deliberately contains backwards-incompatible changes.** To avoid automatically picking up releases like this, you should either be pinning the exact version of `esbuild` in your `package.json` file (recommended) or be using a version range syntax that only accepts patch upgrades such as `^0.18.0` or `~0.18.0`. See npm's documentation about [semver](https://docs.npmjs.com/cli/v6/using-npm/semver/) for more information.
  1052  
  1053  * Handle import paths containing wildcards ([#56](https://github.com/evanw/esbuild/issues/56), [#700](https://github.com/evanw/esbuild/issues/700), [#875](https://github.com/evanw/esbuild/issues/875), [#976](https://github.com/evanw/esbuild/issues/976), [#2221](https://github.com/evanw/esbuild/issues/2221), [#2515](https://github.com/evanw/esbuild/issues/2515))
  1054  
  1055      This release introduces wildcards in import paths in two places:
  1056  
  1057      * **Entry points**
  1058  
  1059          You can now pass a string containing glob-style wildcards such as `./src/*.ts` as an entry point and esbuild will search the file system for files that match the pattern. This can be used to easily pass esbuild all files with a certain extension on the command line in a cross-platform way. Previously you had to rely on the shell to perform glob expansion, but that is obviously shell-dependent and didn't work at all on Windows. Note that to use this feature on the command line you will have to quote the pattern so it's passed verbatim to esbuild without any expansion by the shell. Here's an example:
  1060  
  1061          ```sh
  1062          esbuild --minify "./src/*.ts" --outdir=out
  1063          ```
  1064  
  1065          Specifically the `*` character will match any character except for the `/` character, and the `/**/` character sequence will match a path separator followed by zero or more path elements. Other wildcard operators found in glob patterns such as `?` and `[...]` are not supported.
  1066  
  1067      * **Run-time import paths**
  1068  
  1069          Import paths that are evaluated at run-time can now be bundled in certain limited situations. The import path expression must be a form of string concatenation and must start with either `./` or `../`. Each non-string expression in the string concatenation chain becomes a wildcard. The `*` wildcard is chosen unless the previous character is a `/`, in which case the `/**/*` character sequence is used. Some examples:
  1070  
  1071          ```js
  1072          // These two forms are equivalent
  1073          const json1 = await import('./data/' + kind + '.json')
  1074          const json2 = await import(`./data/${kind}.json`)
  1075          ```
  1076  
  1077          This feature works with `require(...)` and `import(...)` because these can all accept run-time expressions. It does not work with `import` and `export` statements because these cannot accept run-time expressions. If you want to prevent esbuild from trying to bundle these imports, you should move the string concatenation expression outside of the `require(...)` or `import(...)`. For example:
  1078  
  1079          ```js
  1080          // This will be bundled
  1081          const json1 = await import('./data/' + kind + '.json')
  1082  
  1083          // This will not be bundled
  1084          const path = './data/' + kind + '.json'
  1085          const json2 = await import(path)
  1086          ```
  1087  
  1088          Note that using this feature means esbuild will potentially do a lot of file system I/O to find all possible files that might match the pattern. This is by design, and is not a bug. If this is a concern, I recommend either avoiding the `/**/` pattern (e.g. by not putting a `/` before a wildcard) or using this feature only in directory subtrees which do not have many files that don't match the pattern (e.g. making a subdirectory for your JSON files and explicitly including that subdirectory in the pattern).
  1089  
  1090  * Path aliases in `tsconfig.json` no longer count as packages ([#2792](https://github.com/evanw/esbuild/issues/2792), [#3003](https://github.com/evanw/esbuild/issues/3003), [#3160](https://github.com/evanw/esbuild/issues/3160), [#3238](https://github.com/evanw/esbuild/issues/3238))
  1091  
  1092      Setting `--packages=external` tells esbuild to make all import paths external when they look like a package path. For example, an import of `./foo/bar` is not a package path and won't be external while an import of `foo/bar` is a package path and will be external. However, the [`paths` field](https://www.typescriptlang.org/tsconfig#paths) in `tsconfig.json` allows you to create import paths that look like package paths but that do not resolve to packages. People do not want these paths to count as package paths. So with this release, the behavior of `--packages=external` has been changed to happen after the `tsconfig.json` path remapping step.
  1093  
  1094  * Use the `local-css` loader for `.module.css` files by default ([#20](https://github.com/evanw/esbuild/issues/20))
  1095  
  1096      With this release the `css` loader is still used for `.css` files except that `.module.css` files now use the `local-css` loader. This is a common convention in the web development community. If you need `.module.css` files to use the `css` loader instead, then you can override this behavior with `--loader:.module.css=css`.
  1097  
  1098  ## 0.18.20
  1099  
  1100  * Support advanced CSS `@import` rules ([#953](https://github.com/evanw/esbuild/issues/953), [#3137](https://github.com/evanw/esbuild/issues/3137))
  1101  
  1102      CSS `@import` statements have been extended to allow additional trailing tokens after the import path. These tokens sort of make the imported file behave as if it were wrapped in a `@layer`, `@supports`, and/or `@media` rule. Here are some examples:
  1103  
  1104      ```css
  1105      @import url(foo.css);
  1106      @import url(foo.css) layer;
  1107      @import url(foo.css) layer(bar);
  1108      @import url(foo.css) layer(bar) supports(display: flex);
  1109      @import url(foo.css) layer(bar) supports(display: flex) print;
  1110      @import url(foo.css) layer(bar) print;
  1111      @import url(foo.css) supports(display: flex);
  1112      @import url(foo.css) supports(display: flex) print;
  1113      @import url(foo.css) print;
  1114      ```
  1115  
  1116      You can read more about this advanced syntax [here](https://developer.mozilla.org/en-US/docs/Web/CSS/@import). With this release, esbuild will now bundle `@import` rules with these trailing tokens and will wrap the imported files in the corresponding rules. Note that this now means a given imported file can potentially appear in multiple places in the bundle. However, esbuild will still only load it once (e.g. on-load plugins will only run once per file, not once per import).
  1117  
  1118  ## 0.18.19
  1119  
  1120  * Implement `composes` from CSS modules ([#20](https://github.com/evanw/esbuild/issues/20))
  1121  
  1122      This release implements the `composes` annotation from the [CSS modules specification](https://github.com/css-modules/css-modules#composition). It provides a way for class selectors to reference other class selectors (assuming you are using the `local-css` loader). And with the `from` syntax, this can even work with local names across CSS files. For example:
  1123  
  1124      ```js
  1125      // app.js
  1126      import { submit } from './style.css'
  1127      const div = document.createElement('div')
  1128      div.className = submit
  1129      document.body.appendChild(div)
  1130      ```
  1131  
  1132      ```css
  1133      /* style.css */
  1134      .button {
  1135        composes: pulse from "anim.css";
  1136        display: inline-block;
  1137      }
  1138      .submit {
  1139        composes: button;
  1140        font-weight: bold;
  1141      }
  1142      ```
  1143  
  1144      ```css
  1145      /* anim.css */
  1146      @keyframes pulse {
  1147        from, to { opacity: 1 }
  1148        50% { opacity: 0.5 }
  1149      }
  1150      .pulse {
  1151        animation: 2s ease-in-out infinite pulse;
  1152      }
  1153      ```
  1154  
  1155      Bundling this with esbuild using `--bundle --outdir=dist --loader:.css=local-css` now gives the following:
  1156  
  1157      ```js
  1158      (() => {
  1159        // style.css
  1160        var submit = "anim_pulse style_button style_submit";
  1161  
  1162        // app.js
  1163        var div = document.createElement("div");
  1164        div.className = submit;
  1165        document.body.appendChild(div);
  1166      })();
  1167      ```
  1168  
  1169      ```css
  1170      /* anim.css */
  1171      @keyframes anim_pulse {
  1172        from, to {
  1173          opacity: 1;
  1174        }
  1175        50% {
  1176          opacity: 0.5;
  1177        }
  1178      }
  1179      .anim_pulse {
  1180        animation: 2s ease-in-out infinite anim_pulse;
  1181      }
  1182  
  1183      /* style.css */
  1184      .style_button {
  1185        display: inline-block;
  1186      }
  1187      .style_submit {
  1188        font-weight: bold;
  1189      }
  1190      ```
  1191  
  1192      Import paths in the `composes: ... from` syntax are resolved using the new `composes-from` import kind, which can be intercepted by plugins during import path resolution when bundling is enabled.
  1193  
  1194      Note that the order in which composed CSS classes from separate files appear in the bundled output file is deliberately _**undefined**_ by design (see [the specification](https://github.com/css-modules/css-modules#composing-from-other-files) for details). You are not supposed to declare the same CSS property in two separate class selectors and then compose them together. You are only supposed to compose CSS class selectors that declare non-overlapping CSS properties.
  1195  
  1196      Issue [#20](https://github.com/evanw/esbuild/issues/20) (the issue tracking CSS modules) is esbuild's most-upvoted issue! With this change, I now consider esbuild's implementation of CSS modules to be complete. There are still improvements to make and there may also be bugs with the current implementation, but these can be tracked in separate issues.
  1197  
  1198  * Fix non-determinism with `tsconfig.json` and symlinks ([#3284](https://github.com/evanw/esbuild/issues/3284))
  1199  
  1200      This release fixes an issue that could cause esbuild to sometimes emit incorrect build output in cases where a file under the effect of `tsconfig.json` is inconsistently referenced through a symlink. It can happen when using `npm link` to create a symlink within `node_modules` to an unpublished package. The build result was non-deterministic because esbuild runs module resolution in parallel and the result of the `tsconfig.json` lookup depended on whether the import through the symlink or not through the symlink was resolved first. This problem was fixed by moving the `realpath` operation before the `tsconfig.json` lookup.
  1201  
  1202  * Add a `hash` property to output files ([#3084](https://github.com/evanw/esbuild/issues/3084), [#3293](https://github.com/evanw/esbuild/issues/3293))
  1203  
  1204      As a convenience, every output file in esbuild's API now includes a `hash` property that is a hash of the `contents` field. This is the hash that's used internally by esbuild to detect changes between builds for esbuild's live-reload feature. You may also use it to detect changes between your own builds if its properties are sufficient for your use case.
  1205  
  1206      This feature has been added directly to output file objects since it's just a hash of the `contents` field, so it makes conceptual sense to store it in the same location. Another benefit of putting it there instead of including it as a part of the watch mode API is that it can be used without watch mode enabled. You can use it to compare the output of two independent builds that were done at different times.
  1207  
  1208      The hash algorithm (currently [XXH64](https://xxhash.com/)) is implementation-dependent and may be changed at any time in between esbuild versions. If you don't like esbuild's choice of hash algorithm then you are welcome to hash the contents yourself instead. As with any hash algorithm, note that while two different hashes mean that the contents are different, two equal hashes do not necessarily mean that the contents are equal. You may still want to compare the contents in addition to the hashes to detect with certainty when output files have been changed.
  1209  
  1210  * Avoid generating duplicate prefixed declarations in CSS ([#3292](https://github.com/evanw/esbuild/issues/3292))
  1211  
  1212      There was a request for esbuild's CSS prefixer to avoid generating a prefixed declaration if a declaration by that name is already present in the same rule block. So with this release, esbuild will now avoid doing this:
  1213  
  1214      ```css
  1215      /* Original code */
  1216      body {
  1217        backdrop-filter: blur(30px);
  1218        -webkit-backdrop-filter: blur(45px);
  1219      }
  1220  
  1221      /* Old output (with --target=safari12) */
  1222      body {
  1223        -webkit-backdrop-filter: blur(30px);
  1224        backdrop-filter: blur(30px);
  1225        -webkit-backdrop-filter: blur(45px);
  1226      }
  1227  
  1228      /* New output (with --target=safari12) */
  1229      body {
  1230        backdrop-filter: blur(30px);
  1231        -webkit-backdrop-filter: blur(45px);
  1232      }
  1233      ```
  1234  
  1235      This can result in a visual difference in certain cases (for example if the browser understands `blur(30px)` but not `blur(45px)`, it will be able to fall back to `blur(30px)`). But this change means esbuild now matches the behavior of [Autoprefixer](https://autoprefixer.github.io/) which is probably a good representation of how people expect this feature to work.
  1236  
  1237  ## 0.18.18
  1238  
  1239  * Fix asset references with the `--line-limit` flag ([#3286](https://github.com/evanw/esbuild/issues/3286))
  1240  
  1241      The recently-released `--line-limit` flag tells esbuild to terminate long lines after they pass this length limit. This includes automatically wrapping long strings across multiple lines using escaped newline syntax. However, using this could cause esbuild to generate incorrect code for references from generated output files to assets in the bundle (i.e. files loaded with the `file` or `copy` loaders). This is because esbuild implements asset references internally using find-and-replace with a randomly-generated string, but the find operation fails if the string is split by an escaped newline due to line wrapping. This release fixes the problem by not wrapping these strings. This issue affected asset references in both JS and CSS files.
  1242  
  1243  * Support local names in CSS for `@keyframe`, `@counter-style`, and `@container` ([#20](https://github.com/evanw/esbuild/issues/20))
  1244  
  1245      This release extends support for local names in CSS files loaded with the `local-css` loader to cover the `@keyframe`, `@counter-style`, and `@container` rules (and also `animation`, `list-style`, and `container` declarations). Here's an example:
  1246  
  1247      ```css
  1248      @keyframes pulse {
  1249        from, to { opacity: 1 }
  1250        50% { opacity: 0.5 }
  1251      }
  1252      @counter-style moon {
  1253        system: cyclic;
  1254        symbols: šŸŒ• šŸŒ– šŸŒ— šŸŒ˜ šŸŒ‘ šŸŒ’ šŸŒ“ šŸŒ”;
  1255      }
  1256      @container squish {
  1257        li { float: left }
  1258      }
  1259      ul {
  1260        animation: 2s ease-in-out infinite pulse;
  1261        list-style: inside moon;
  1262        container: squish / size;
  1263      }
  1264      ```
  1265  
  1266      With the `local-css` loader enabled, that CSS will be turned into something like this (with the local name mapping exposed to JS):
  1267  
  1268      ```css
  1269      @keyframes stdin_pulse {
  1270        from, to {
  1271          opacity: 1;
  1272        }
  1273        50% {
  1274          opacity: 0.5;
  1275        }
  1276      }
  1277      @counter-style stdin_moon {
  1278        system: cyclic;
  1279        symbols: šŸŒ• šŸŒ– šŸŒ— šŸŒ˜ šŸŒ‘ šŸŒ’ šŸŒ“ šŸŒ”;
  1280      }
  1281      @container stdin_squish {
  1282        li {
  1283          float: left;
  1284        }
  1285      }
  1286      ul {
  1287        animation: 2s ease-in-out infinite stdin_pulse;
  1288        list-style: inside stdin_moon;
  1289        container: stdin_squish / size;
  1290      }
  1291      ```
  1292  
  1293      If you want to use a global name within a file loaded with the `local-css` loader, you can use a `:global` selector to do that:
  1294  
  1295      ```css
  1296      div {
  1297        /* All symbols are global inside this scope (i.e.
  1298         * "pulse", "moon", and "squish" are global below) */
  1299        :global {
  1300          animation: 2s ease-in-out infinite pulse;
  1301          list-style: inside moon;
  1302          container: squish / size;
  1303        }
  1304      }
  1305      ```
  1306  
  1307      If you want to use `@keyframes`, `@counter-style`, or `@container` with a global name, make sure it's in a file that uses the `css` or `global-css` loader instead of the `local-css` loader. For example, you can configure `--loader:.module.css=local-css` so that the `local-css` loader only applies to `*.module.css` files.
  1308  
  1309  * Support strings as keyframe animation names in CSS ([#2555](https://github.com/evanw/esbuild/issues/2555))
  1310  
  1311      With this release, esbuild will now parse animation names that are specified as strings and will convert them to identifiers. The CSS specification allows animation names to be specified using either identifiers or strings but Chrome only understands identifiers, so esbuild will now always convert string names to identifier names for Chrome compatibility:
  1312  
  1313      ```css
  1314      /* Original code */
  1315      @keyframes "hide menu" {
  1316        from { opacity: 1 }
  1317        to { opacity: 0 }
  1318      }
  1319      menu.hide {
  1320        animation: 0.5s ease-in-out "hide menu";
  1321      }
  1322  
  1323      /* Old output */
  1324      @keyframes "hide menu" { from { opacity: 1 } to { opacity: 0 } }
  1325      menu.hide {
  1326        animation: 0.5s ease-in-out "hide menu";
  1327      }
  1328  
  1329      /* New output */
  1330      @keyframes hide\ menu {
  1331        from {
  1332          opacity: 1;
  1333        }
  1334        to {
  1335          opacity: 0;
  1336        }
  1337      }
  1338      menu.hide {
  1339        animation: 0.5s ease-in-out hide\ menu;
  1340      }
  1341      ```
  1342  
  1343  ## 0.18.17
  1344  
  1345  * Support `An+B` syntax and `:nth-*()` pseudo-classes in CSS
  1346  
  1347      This adds support for the `:nth-child()`, `:nth-last-child()`, `:nth-of-type()`, and `:nth-last-of-type()` pseudo-classes to esbuild, which has the following consequences:
  1348  
  1349      * The [`An+B` syntax](https://drafts.csswg.org/css-syntax-3/#anb-microsyntax) is now parsed, so parse errors are now reported
  1350      * `An+B` values inside these pseudo-classes are now pretty-printed (e.g. a leading `+` will be stripped because it's not in the AST)
  1351      * When minification is enabled, `An+B` values are reduced to equivalent but shorter forms (e.g. `2n+0` => `2n`, `2n+1` => `odd`)
  1352      * Local CSS names in an `of` clause are now detected (e.g. in `:nth-child(2n of :local(.foo))` the name `foo` is now renamed)
  1353  
  1354      ```css
  1355      /* Original code */
  1356      .foo:nth-child(+2n+1 of :local(.bar)) {
  1357        color: red;
  1358      }
  1359  
  1360      /* Old output (with --loader=local-css) */
  1361      .stdin_foo:nth-child(+2n + 1 of :local(.bar)) {
  1362        color: red;
  1363      }
  1364  
  1365      /* New output (with --loader=local-css) */
  1366      .stdin_foo:nth-child(2n+1 of .stdin_bar) {
  1367        color: red;
  1368      }
  1369      ```
  1370  
  1371  * Adjust CSS nesting parser for IE7 hacks ([#3272](https://github.com/evanw/esbuild/issues/3272))
  1372  
  1373      This fixes a regression with esbuild's treatment of IE7 hacks in CSS. CSS nesting allows selectors to be used where declarations are expected. There's an IE7 hack where prefixing a declaration with a `*` causes that declaration to only be applied in IE7 due to a bug in IE7's CSS parser. However, it's valid for nested CSS selectors to start with `*`. So esbuild was incorrectly parsing these declarations and anything following it up until the next `{` as a selector for a nested CSS rule. This release changes esbuild's parser to terminate the parsing of selectors for nested CSS rules when a `;` is encountered to fix this edge case:
  1374  
  1375      ```css
  1376      /* Original code */
  1377      .item {
  1378        *width: 100%;
  1379        height: 1px;
  1380      }
  1381  
  1382      /* Old output */
  1383      .item {
  1384        *width: 100%; height: 1px; {
  1385        }
  1386      }
  1387  
  1388      /* New output */
  1389      .item {
  1390        *width: 100%;
  1391        height: 1px;
  1392      }
  1393      ```
  1394  
  1395      Note that the syntax for CSS nesting is [about to change again](https://github.com/w3c/csswg-drafts/issues/7961), so esbuild's CSS parser may still not be completely accurate with how browsers do and/or will interpret CSS nesting syntax. Expect additional updates to esbuild's CSS parser in the future to deal with upcoming CSS specification changes.
  1396  
  1397  * Adjust esbuild's warning about undefined imports for TypeScript `import` equals declarations ([#3271](https://github.com/evanw/esbuild/issues/3271))
  1398  
  1399      In JavaScript, accessing a missing property on an import namespace object is supposed to result in a value of `undefined` at run-time instead of an error at compile-time. This is something that esbuild warns you about by default because doing this can indicate a bug with your code. For example:
  1400  
  1401      ```js
  1402      // app.js
  1403      import * as styles from './styles'
  1404      console.log(styles.buton)
  1405      ```
  1406  
  1407      ```js
  1408      // styles.js
  1409      export let button = {}
  1410      ```
  1411  
  1412      If you bundle `app.js` with esbuild you will get this:
  1413  
  1414      ```
  1415      ā–² [WARNING] Import "buton" will always be undefined because there is no matching export in "styles.js" [import-is-undefined]
  1416  
  1417          app.js:2:19:
  1418            2 ā”‚ console.log(styles.buton)
  1419              ā”‚                    ~~~~~
  1420              ā•µ                    button
  1421  
  1422        Did you mean to import "button" instead?
  1423  
  1424          styles.js:1:11:
  1425            1 ā”‚ export let button = {}
  1426              ā•µ            ~~~~~~
  1427      ```
  1428  
  1429      However, there is TypeScript-only syntax for `import` equals declarations that can represent either a type import (which esbuild should ignore) or a value import (which esbuild should respect). Since esbuild doesn't have a type system, it tries to only respect `import` equals declarations that are actually used as values. Previously esbuild always generated this warning for unused imports referenced within `import` equals declarations even when the reference could be a type instead of a value. Starting with this release, esbuild will now only warn in this case if the import is actually used. Here is an example of some code that no longer causes an incorrect warning:
  1430  
  1431      ```ts
  1432      // app.ts
  1433      import * as styles from './styles'
  1434      import ButtonType = styles.Button
  1435      ```
  1436  
  1437      ```ts
  1438      // styles.ts
  1439      export interface Button {}
  1440      ```
  1441  
  1442  ## 0.18.16
  1443  
  1444  * Fix a regression with whitespace inside `:is()` ([#3265](https://github.com/evanw/esbuild/issues/3265))
  1445  
  1446      The change to parse the contents of `:is()` in version 0.18.14 introduced a regression that incorrectly flagged the contents as a syntax error if the contents started with a whitespace token (for example `div:is( .foo ) {}`). This regression has been fixed.
  1447  
  1448  ## 0.18.15
  1449  
  1450  * Add the `--serve-fallback=` option ([#2904](https://github.com/evanw/esbuild/issues/2904))
  1451  
  1452      The web server built into esbuild serves the latest in-memory results of the configured build. If the requested path doesn't match any in-memory build result, esbuild also provides the `--servedir=` option to tell esbuild to serve the requested path from that directory instead. And if the requested path doesn't match either of those things, esbuild will either automatically generate a directory listing (for directories) or return a 404 error.
  1453  
  1454      Starting with this release, that last step can now be replaced with telling esbuild to serve a specific HTML file using the `--serve-fallback=` option. This can be used to provide a "not found" page for missing URLs. It can also be used to implement a [single-page app](https://en.wikipedia.org/wiki/Single-page_application) that mutates the current URL and therefore requires the single app entry point to be served when the page is loaded regardless of whatever the current URL is.
  1455  
  1456  * Use the `tsconfig` field in `package.json` during `extends` resolution ([#3247](https://github.com/evanw/esbuild/issues/3247))
  1457  
  1458       This release adds a feature from [TypeScript 3.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html#tsconfigjson-inheritance-via-nodejs-packages) where if a `tsconfig.json` file specifies a package name in the `extends` field and that package's `package.json` file has a `tsconfig` field, the contents of that field are used in the search for the base `tsconfig.json` file.
  1459  
  1460  * Implement CSS nesting without `:is()` when possible ([#1945](https://github.com/evanw/esbuild/issues/1945))
  1461  
  1462      Previously esbuild would always produce a warning when transforming nested CSS for a browser that doesn't support the `:is()` pseudo-class. This was because the nesting transform needs to generate an `:is()` in some complex cases which means the transformed CSS would then not work in that browser. However, the CSS nesting transform can often be done without generating an `:is()`. So with this release, esbuild will no longer warn when targeting browsers that don't support `:is()` in the cases where an `:is()` isn't needed to represent the nested CSS.
  1463  
  1464      In addition, esbuild's nested CSS transform has been updated to avoid generating an `:is()` in cases where an `:is()` is preferable but there's a longer alternative that is also equivalent. This update means esbuild can now generate a combinatorial explosion of CSS for complex CSS nesting syntax when targeting browsers that don't support `:is()`. This combinatorial explosion is necessary to accurately represent the original semantics. For example:
  1465  
  1466      ```css
  1467      /* Original code */
  1468      .first,
  1469      .second,
  1470      .third {
  1471        & > & {
  1472          color: red;
  1473        }
  1474      }
  1475  
  1476      /* Old output (with --target=chrome80) */
  1477      :is(.first, .second, .third) > :is(.first, .second, .third) {
  1478        color: red;
  1479      }
  1480  
  1481      /* New output (with --target=chrome80) */
  1482      .first > .first,
  1483      .first > .second,
  1484      .first > .third,
  1485      .second > .first,
  1486      .second > .second,
  1487      .second > .third,
  1488      .third > .first,
  1489      .third > .second,
  1490      .third > .third {
  1491        color: red;
  1492      }
  1493      ```
  1494  
  1495      This change means you can now use CSS nesting with esbuild when targeting an older browser that doesn't support `:is()`. You'll now only get a warning from esbuild if you use complex CSS nesting syntax that esbuild can't represent in that older browser without using `:is()`. There are two such cases:
  1496  
  1497      ```css
  1498      /* Case 1 */
  1499      a b {
  1500        .foo & {
  1501          color: red;
  1502        }
  1503      }
  1504  
  1505      /* Case 2 */
  1506      a {
  1507        > b& {
  1508          color: red;
  1509        }
  1510      }
  1511      ```
  1512  
  1513      These two cases still need to use `:is()`, both for different reasons, and cannot be used when targeting an older browser that doesn't support `:is()`:
  1514  
  1515      ```css
  1516      /* Case 1 */
  1517      .foo :is(a b) {
  1518        color: red;
  1519      }
  1520  
  1521      /* Case 2 */
  1522      a > a:is(b) {
  1523        color: red;
  1524      }
  1525      ```
  1526  
  1527  * Automatically lower `inset` in CSS for older browsers
  1528  
  1529      With this release, esbuild will now automatically expand the `inset` property to the `top`, `right`, `bottom`, and `left` properties when esbuild's `target` is set to a browser that doesn't support `inset`:
  1530  
  1531      ```css
  1532      /* Original code */
  1533      .app {
  1534        position: absolute;
  1535        inset: 10px 20px;
  1536      }
  1537  
  1538      /* Old output (with --target=chrome80) */
  1539      .app {
  1540        position: absolute;
  1541        inset: 10px 20px;
  1542      }
  1543  
  1544      /* New output (with --target=chrome80) */
  1545      .app {
  1546        position: absolute;
  1547        top: 10px;
  1548        right: 20px;
  1549        bottom: 10px;
  1550        left: 20px;
  1551      }
  1552      ```
  1553  
  1554  * Add support for the new [`@starting-style`](https://drafts.csswg.org/css-transitions-2/#defining-before-change-style-the-starting-style-rule) CSS rule ([#3249](https://github.com/evanw/esbuild/pull/3249))
  1555  
  1556      This at rule allow authors to start CSS transitions on first style update. That is, you can now make the transition take effect when the `display` property changes from `none` to `block`.
  1557  
  1558      ```css
  1559      /* Original code */
  1560      @starting-style {
  1561        h1 {
  1562          background-color: transparent;
  1563        }
  1564      }
  1565  
  1566      /* Output */
  1567      @starting-style{h1{background-color:transparent}}
  1568      ```
  1569  
  1570      This was contributed by [@yisibl](https://github.com/yisibl).
  1571  
  1572  ## 0.18.14
  1573  
  1574  * Implement local CSS names ([#20](https://github.com/evanw/esbuild/issues/20))
  1575  
  1576      This release introduces two new loaders called `global-css` and `local-css` and two new pseudo-class selectors `:local()` and `:global()`. This is a partial implementation of the popular [CSS modules](https://github.com/css-modules/css-modules) approach for avoiding unintentional name collisions in CSS. I'm not calling this feature "CSS modules" because although some people in the community call it that, other people in the community have started using "CSS modules" to refer to [something completely different](https://github.com/WICG/webcomponents/blob/60c9f682b63c622bfa0d8222ea6b1f3b659e007c/proposals/css-modules-v1-explainer.md) and now CSS modules is an overloaded term.
  1577  
  1578      Here's how this new local CSS name feature works with esbuild:
  1579  
  1580      * Identifiers that look like `.className` and `#idName` are global with the `global-css` loader and local with the `local-css` loader. Global identifiers are the same across all files (the way CSS normally works) but local identifiers are different between different files. If two separate CSS files use the same local identifier `.button`, esbuild will automatically rename one of them so that they don't collide. This is analogous to how esbuild automatically renames JS local variables with the same name in separate JS files to avoid name collisions.
  1581  
  1582      * It only makes sense to use local CSS names with esbuild when you are also using esbuild's bundler to bundle JS files that import CSS files. When you do that, esbuild will generate one export for each local name in the CSS file. The JS code can import these names and use them when constructing HTML DOM. For example:
  1583  
  1584          ```js
  1585          // app.js
  1586          import { outerShell } from './app.css'
  1587          const div = document.createElement('div')
  1588          div.className = outerShell
  1589          document.body.appendChild(div)
  1590          ```
  1591  
  1592          ```css
  1593          /* app.css */
  1594          .outerShell {
  1595            position: absolute;
  1596            inset: 0;
  1597          }
  1598          ```
  1599  
  1600          When you bundle this with `esbuild app.js --bundle --loader:.css=local-css --outdir=out` you'll now get this (notice how the local CSS name `outerShell` has been renamed):
  1601  
  1602          ```js
  1603          // out/app.js
  1604          (() => {
  1605            // app.css
  1606            var outerShell = "app_outerShell";
  1607  
  1608            // app.js
  1609            var div = document.createElement("div");
  1610            div.className = outerShell;
  1611            document.body.appendChild(div);
  1612          })();
  1613          ```
  1614  
  1615          ```css
  1616          /* out/app.css */
  1617          .app_outerShell {
  1618            position: absolute;
  1619            inset: 0;
  1620          }
  1621          ```
  1622  
  1623          This feature only makes sense to use when bundling is enabled both because your code needs to `import` the renamed local names so that it can use them, and because esbuild needs to be able to process all CSS files containing local names in a single bundling operation so that it can successfully rename conflicting local names to avoid collisions.
  1624  
  1625      * If you are in a global CSS file (with the `global-css` loader) you can create a local name using `:local()`, and if you are in a local CSS file (with the `local-css` loader) you can create a global name with `:global()`. So the choice of the `global-css` loader vs. the `local-css` loader just sets the default behavior for identifiers, but you can override it on a case-by-case basis as necessary. For example:
  1626  
  1627          ```css
  1628          :local(.button) {
  1629            color: red;
  1630          }
  1631          :global(.button) {
  1632            color: blue;
  1633          }
  1634          ```
  1635  
  1636          Processing this CSS file with esbuild with either the `global-css` or `local-css` loader will result in something like this:
  1637  
  1638          ```css
  1639          .stdin_button {
  1640            color: red;
  1641          }
  1642          .button {
  1643            color: blue;
  1644          }
  1645          ```
  1646  
  1647      * The names that esbuild generates for local CSS names are an implementation detail and are not intended to be hard-coded anywhere. The only way you should be referencing the local CSS names in your JS or HTML is with an `import` statement in JS that is bundled with esbuild, as demonstrated above. For example, when `--minify` is enabled esbuild will use a different name generation algorithm which generates names that are as short as possible (analogous to how esbuild minifies local identifiers in JS).
  1648  
  1649      * You can easily use both global CSS files and local CSS files simultaneously if you give them different file extensions. For example, you could pass `--loader:.css=global-css` and `--loader:.module.css=local-css` to esbuild so that `.css` files still use global names by default but `.module.css` files use local names by default.
  1650  
  1651      * Keep in mind that the `css` loader is different than the `global-css` loader. The `:local` and `:global` annotations are not enabled with the `css` loader and will be passed through unchanged. This allows you to have the option of using esbuild to process CSS containing while preserving these annotations. It also means that local CSS names are disabled by default for now (since the `css` loader is currently the default for CSS files). The `:local` and `:global` syntax may be enabled by default in a future release.
  1652  
  1653      Note that esbuild's implementation does not currently have feature parity with other implementations of modular CSS in similar tools. This is only a preliminary release with a partial implementation that includes some basic behavior to get the process started. Additional behavior may be added in future releases. In particular, this release does not implement:
  1654  
  1655      * The `composes` pragma
  1656      * Tree shaking for unused local CSS
  1657      * Local names for keyframe animations, grid lines, `@container`, `@counter-style`, etc.
  1658  
  1659      Issue [#20](https://github.com/evanw/esbuild/issues/20) (the issue for this feature) is esbuild's most-upvoted issue! While this release still leaves that issue open, it's an important first step in that direction.
  1660  
  1661  * Parse `:is`, `:has`, `:not`, and `:where` in CSS
  1662  
  1663      With this release, esbuild will now parse the contents of these pseudo-class selectors as a selector list. This means you will now get syntax warnings within these selectors for invalid selector syntax. It also means that esbuild's CSS nesting transform behaves slightly differently than before because esbuild is now operating on an AST instead of a token stream. For example:
  1664  
  1665      ```css
  1666      /* Original code */
  1667      div {
  1668        :where(.foo&) {
  1669          color: red;
  1670        }
  1671      }
  1672  
  1673      /* Old output (with --target=chrome90) */
  1674      :where(.foo:is(div)) {
  1675        color: red;
  1676      }
  1677  
  1678      /* New output (with --target=chrome90) */
  1679      :where(div.foo) {
  1680        color: red;
  1681      }
  1682      ```
  1683  
  1684  ## 0.18.13
  1685  
  1686  * Add the `--drop-labels=` option ([#2398](https://github.com/evanw/esbuild/issues/2398))
  1687  
  1688      If you want to conditionally disable some development-only code and have it not be present in the final production bundle, right now the most straightforward way of doing this is to use the `--define:` flag along with a specially-named global variable. For example, consider the following code:
  1689  
  1690      ```js
  1691      function main() {
  1692        DEV && doAnExpensiveCheck()
  1693      }
  1694      ```
  1695  
  1696      You can build this for development and production like this:
  1697  
  1698      * Development: `esbuild --define:DEV=true`
  1699      * Production: `esbuild --define:DEV=false`
  1700  
  1701      One drawback of this approach is that the resulting code crashes if you don't provide a value for `DEV` with `--define:`. In practice this isn't that big of a problem, and there are also various ways to work around this.
  1702  
  1703      However, another approach that avoids this drawback is to use JavaScript label statements instead. That's what the `--drop-labels=` flag implements. For example, consider the following code:
  1704  
  1705      ```js
  1706      function main() {
  1707        DEV: doAnExpensiveCheck()
  1708      }
  1709      ```
  1710  
  1711      With this release, you can now build this for development and production like this:
  1712  
  1713      * Development: `esbuild`
  1714      * Production: `esbuild --drop-labels=DEV`
  1715  
  1716      This means that code containing optional development-only checks can now be written such that it's safe to run without any additional configuration. The `--drop-labels=` flag takes comma-separated list of multiple label names to drop.
  1717  
  1718  * Avoid causing `unhandledRejection` during shutdown ([#3219](https://github.com/evanw/esbuild/issues/3219))
  1719  
  1720      All pending esbuild JavaScript API calls are supposed to fail if esbuild's underlying child process is unexpectedly terminated. This can happen if `SIGINT` is sent to the parent `node` process with Ctrl+C, for example. Previously doing this could also cause an unhandled promise rejection when esbuild attempted to communicate this failure to its own child process that no longer exists. This release now swallows this communication failure, which should prevent this internal unhandled promise rejection. This change means that you can now use esbuild's JavaScript API with a custom `SIGINT` handler that extends the lifetime of the `node` process without esbuild's internals causing an early exit due to an unhandled promise rejection.
  1721  
  1722  * Update browser compatibility table scripts
  1723  
  1724      The scripts that esbuild uses to compile its internal browser compatibility table have been overhauled. Briefly:
  1725  
  1726      * Converted from JavaScript to TypeScript
  1727      * Fixed some bugs that resulted in small changes to the table
  1728      * Added [`caniuse-lite`](https://www.npmjs.com/package/caniuse-lite) and [`@mdn/browser-compat-data`](https://www.npmjs.com/package/@mdn/browser-compat-data) as new data sources (replacing manually-copied information)
  1729  
  1730      This change means it's now much easier to keep esbuild's internal compatibility tables up to date. You can review the table changes here if you need to debug something about this change:
  1731  
  1732      * [JS table changes](https://github.com/evanw/esbuild/compare/d259b8fac717ee347c19bd8299f2c26d7c87481a...af1d35c372f78c14f364b63e819fd69548508f55#diff-1649eb68992c79753469f02c097de309adaf7231b45cc816c50bf751af400eb4)
  1733      * [CSS table changes](https://github.com/evanw/esbuild/commit/95feb2e09877597cb929469ce43811bdf11f50c1#diff-4e1c4f269e02c5ea31cbd5138d66751e32cf0e240524ee8a966ac756f0e3c3cd)
  1734  
  1735  ## 0.18.12
  1736  
  1737  * Fix a panic with `const enum` inside parentheses ([#3205](https://github.com/evanw/esbuild/issues/3205))
  1738  
  1739      This release fixes an edge case where esbuild could potentially panic if a TypeScript `const enum` statement was used inside of a parenthesized expression and was followed by certain other scope-related statements. Here's a minimal example that triggers this edge case:
  1740  
  1741      ```ts
  1742      (() => {
  1743        const enum E { a };
  1744        () => E.a
  1745      })
  1746      ```
  1747  
  1748  * Allow a newline in the middle of TypeScript `export type` statement ([#3225](https://github.com/evanw/esbuild/issues/3225))
  1749  
  1750      Previously esbuild incorrectly rejected the following valid TypeScript code:
  1751  
  1752      ```ts
  1753      export type
  1754      { T };
  1755  
  1756      export type
  1757      * as foo from 'bar';
  1758      ```
  1759  
  1760      Code that uses a newline after `export type` is now allowed starting with this release.
  1761  
  1762  * Fix cross-module inlining of string enums ([#3210](https://github.com/evanw/esbuild/issues/3210))
  1763  
  1764      A refactoring typo in version 0.18.9 accidentally introduced a regression with cross-module inlining of string enums when combined with computed property accesses. This regression has been fixed.
  1765  
  1766  * Rewrite `.js` to `.ts` inside packages with `exports` ([#3201](https://github.com/evanw/esbuild/issues/3201))
  1767  
  1768      Packages with the `exports` field are supposed to disable node's path resolution behavior that allows you to import a file with a different extension than the one in the source code (for example, importing `foo/bar` to get `foo/bar.js`). And TypeScript has behavior where you can import a non-existent `.js` file and you will get the `.ts` file instead. Previously the presence of the `exports` field caused esbuild to disable all extension manipulation stuff which included both node's implicit file extension searching and TypeScript's file extension swapping. However, TypeScript appears to always apply file extension swapping even in this case. So with this release, esbuild will now rewrite `.js` to `.ts` even inside packages with `exports`.
  1769  
  1770  * Fix a redirect edge case in esbuild's development server ([#3208](https://github.com/evanw/esbuild/issues/3208))
  1771  
  1772      The development server canonicalizes directory URLs by adding a trailing slash. For example, visiting `/about` redirects to `/about/` if `/about/index.html` would be served. However, if the requested path begins with two slashes, then the redirect incorrectly turned into a protocol-relative URL. For example, visiting `//about` redirected to `//about/` which the browser turns into `http://about/`. This release fixes the bug by canonicalizing the URL path when doing this redirect.
  1773  
  1774  ## 0.18.11
  1775  
  1776  * Fix a TypeScript code generation edge case ([#3199](https://github.com/evanw/esbuild/issues/3199))
  1777  
  1778      This release fixes a regression in version 0.18.4 where using a TypeScript `namespace` that exports a `class` declaration combined with `--keep-names` and a `--target` of `es2021` or earlier could cause esbuild to export the class from the namespace using an incorrect name (notice the assignment to `X2._Y` vs. `X2.Y`):
  1779  
  1780      ```ts
  1781      // Original code
  1782  
  1783      // Old output (with --keep-names --target=es2021)
  1784      var X;
  1785      ((X2) => {
  1786        const _Y = class _Y {
  1787        };
  1788        __name(_Y, "Y");
  1789        let Y = _Y;
  1790        X2._Y = _Y;
  1791      })(X || (X = {}));
  1792  
  1793      // New output (with --keep-names --target=es2021)
  1794      var X;
  1795      ((X2) => {
  1796        const _Y = class _Y {
  1797        };
  1798        __name(_Y, "Y");
  1799        let Y = _Y;
  1800        X2.Y = _Y;
  1801      })(X || (X = {}));
  1802      ```
  1803  
  1804  ## 0.18.10
  1805  
  1806  * Fix a tree-shaking bug that removed side effects ([#3195](https://github.com/evanw/esbuild/issues/3195))
  1807  
  1808      This fixes a regression in version 0.18.4 where combining `--minify-syntax` with `--keep-names` could cause expressions with side effects after a function declaration to be considered side-effect free for tree shaking purposes. The reason was because `--keep-names` generates an expression statement containing a call to a helper function after the function declaration with a special flag that makes the function call able to be tree shaken, and then `--minify-syntax` could potentially merge that expression statement with following expressions without clearing the flag. This release fixes the bug by clearing the flag when merging expression statements together.
  1809  
  1810  * Fix an incorrect warning about CSS nesting ([#3197](https://github.com/evanw/esbuild/issues/3197))
  1811  
  1812      A warning is currently generated when transforming nested CSS to a browser that doesn't support `:is()` because transformed nested CSS may need to use that feature to represent nesting. This was previously always triggered when an at-rule was encountered in a declaration context. Typically the only case you would encounter this is when using CSS nesting within a selector rule. However, there is a case where that's not true: when using a margin at-rule such as `@top-left` within `@page`. This release avoids incorrectly generating a warning in this case by checking that the at-rule is within a selector rule before generating a warning.
  1813  
  1814  ## 0.18.9
  1815  
  1816  * Fix `await using` declarations inside `async` generator functions
  1817  
  1818      I forgot about the new `await using` declarations when implementing lowering for `async` generator functions in the previous release. This change fixes the transformation of `await using` declarations when they are inside lowered `async` generator functions:
  1819  
  1820      ```js
  1821      // Original code
  1822      async function* foo() {
  1823        await using x = await y
  1824      }
  1825  
  1826      // Old output (with --supported:async-generator=false)
  1827      function foo() {
  1828        return __asyncGenerator(this, null, function* () {
  1829          await using x = yield new __await(y);
  1830        });
  1831      }
  1832  
  1833      // New output (with --supported:async-generator=false)
  1834      function foo() {
  1835        return __asyncGenerator(this, null, function* () {
  1836          var _stack = [];
  1837          try {
  1838            const x = __using(_stack, yield new __await(y), true);
  1839          } catch (_) {
  1840            var _error = _, _hasError = true;
  1841          } finally {
  1842            var _promise = __callDispose(_stack, _error, _hasError);
  1843            _promise && (yield new __await(_promise));
  1844          }
  1845        });
  1846      }
  1847      ```
  1848  
  1849  * Insert some prefixed CSS properties when appropriate ([#3122](https://github.com/evanw/esbuild/issues/3122))
  1850  
  1851      With this release, esbuild will now insert prefixed CSS properties in certain cases when the `target` setting includes browsers that require a certain prefix. This is currently done for the following properties:
  1852  
  1853      * `appearance: *;` => `-webkit-appearance: *; -moz-appearance: *;`
  1854      * `backdrop-filter: *;` => `-webkit-backdrop-filter: *;`
  1855      * `background-clip: text` => `-webkit-background-clip: text;`
  1856      * `box-decoration-break: *;` => `-webkit-box-decoration-break: *;`
  1857      * `clip-path: *;` => `-webkit-clip-path: *;`
  1858      * `font-kerning: *;` => `-webkit-font-kerning: *;`
  1859      * `hyphens: *;` => `-webkit-hyphens: *;`
  1860      * `initial-letter: *;` => `-webkit-initial-letter: *;`
  1861      * `mask-image: *;` => `-webkit-mask-image: *;`
  1862      * `mask-origin: *;` => `-webkit-mask-origin: *;`
  1863      * `mask-position: *;` => `-webkit-mask-position: *;`
  1864      * `mask-repeat: *;` => `-webkit-mask-repeat: *;`
  1865      * `mask-size: *;` => `-webkit-mask-size: *;`
  1866      * `position: sticky;` => `position: -webkit-sticky;`
  1867      * `print-color-adjust: *;` => `-webkit-print-color-adjust: *;`
  1868      * `tab-size: *;` => `-moz-tab-size: *; -o-tab-size: *;`
  1869      * `text-decoration-color: *;` => `-webkit-text-decoration-color: *; -moz-text-decoration-color: *;`
  1870      * `text-decoration-line: *;` => `-webkit-text-decoration-line: *; -moz-text-decoration-line: *;`
  1871      * `text-decoration-skip: *;` => `-webkit-text-decoration-skip: *;`
  1872      * `text-emphasis-color: *;` => `-webkit-text-emphasis-color: *;`
  1873      * `text-emphasis-position: *;` => `-webkit-text-emphasis-position: *;`
  1874      * `text-emphasis-style: *;` => `-webkit-text-emphasis-style: *;`
  1875      * `text-orientation: *;` => `-webkit-text-orientation: *;`
  1876      * `text-size-adjust: *;` => `-webkit-text-size-adjust: *; -ms-text-size-adjust: *;`
  1877      * `user-select: *;` => `-webkit-user-select: *; -moz-user-select: *; -ms-user-select: *;`
  1878  
  1879      Here is an example:
  1880  
  1881      ```css
  1882      /* Original code */
  1883      div {
  1884        mask-image: url(x.png);
  1885      }
  1886  
  1887      /* Old output (with --target=chrome99) */
  1888      div {
  1889        mask-image: url(x.png);
  1890      }
  1891  
  1892      /* New output (with --target=chrome99) */
  1893      div {
  1894        -webkit-mask-image: url(x.png);
  1895        mask-image: url(x.png);
  1896      }
  1897      ```
  1898  
  1899      Browser compatibility data was sourced from the tables on https://caniuse.com. Support for more CSS properties can be added in the future as appropriate.
  1900  
  1901  * Fix an obscure identifier minification bug ([#2809](https://github.com/evanw/esbuild/issues/2809))
  1902  
  1903      Function declarations in nested scopes behave differently depending on whether or not `"use strict"` is present. To avoid generating code that behaves differently depending on whether strict mode is enabled or not, esbuild transforms nested function declarations into variable declarations. However, there was a bug where the generated variable name was not being recorded as declared internally, which meant that it wasn't being renamed correctly by the minifier and could cause a name collision. This bug has been fixed:
  1904  
  1905      ```js
  1906      // Original code
  1907      const n = ''
  1908      for (let i of [0,1]) {
  1909        function f () {}
  1910      }
  1911  
  1912      // Old output (with --minify-identifiers --format=esm)
  1913      const f = "";
  1914      for (let o of [0, 1]) {
  1915        let n = function() {
  1916        };
  1917        var f = n;
  1918      }
  1919  
  1920      // New output (with --minify-identifiers --format=esm)
  1921      const f = "";
  1922      for (let o of [0, 1]) {
  1923        let n = function() {
  1924        };
  1925        var t = n;
  1926      }
  1927      ```
  1928  
  1929  * Fix a bug in esbuild's compatibility table script ([#3179](https://github.com/evanw/esbuild/pull/3179))
  1930  
  1931      Setting esbuild's `target` to a specific JavaScript engine tells esbuild to use the JavaScript syntax feature compatibility data from https://kangax.github.io/compat-table/es6/ for that engine to determine which syntax features to allow. However, esbuild's script that builds this internal compatibility table had a bug that incorrectly ignores tests for engines that still have outstanding implementation bugs which were never fixed. This change fixes this bug with the script.
  1932  
  1933      The only case where this changed the information in esbuild's internal compatibility table is that the `hermes` target is marked as no longer supporting destructuring. This is because there is a failing destructuring-related test for Hermes on https://kangax.github.io/compat-table/es6/. If you want to use destructuring with Hermes anyway, you can pass `--supported:destructuring=true` to esbuild to override the `hermes` target and force esbuild to accept this syntax.
  1934  
  1935      This fix was contributed by [@ArrayZoneYour](https://github.com/ArrayZoneYour).
  1936  
  1937  ## 0.18.8
  1938  
  1939  * Implement transforming `async` generator functions ([#2780](https://github.com/evanw/esbuild/issues/2780))
  1940  
  1941      With this release, esbuild will now transform `async` generator functions into normal generator functions when the configured target environment doesn't support them. These functions behave similar to normal generator functions except that they use the `Symbol.asyncIterator` interface instead of the `Symbol.iterator` interface and the iteration methods return promises. Here's an example (helper functions are omitted):
  1942  
  1943      ```js
  1944      // Original code
  1945      async function* foo() {
  1946        yield Promise.resolve(1)
  1947        await new Promise(r => setTimeout(r, 100))
  1948        yield *[Promise.resolve(2)]
  1949      }
  1950      async function bar() {
  1951        for await (const x of foo()) {
  1952          console.log(x)
  1953        }
  1954      }
  1955      bar()
  1956  
  1957      // New output (with --target=es6)
  1958      function foo() {
  1959        return __asyncGenerator(this, null, function* () {
  1960          yield Promise.resolve(1);
  1961          yield new __await(new Promise((r) => setTimeout(r, 100)));
  1962          yield* __yieldStar([Promise.resolve(2)]);
  1963        });
  1964      }
  1965      function bar() {
  1966        return __async(this, null, function* () {
  1967          try {
  1968            for (var iter = __forAwait(foo()), more, temp, error; more = !(temp = yield iter.next()).done; more = false) {
  1969              const x = temp.value;
  1970              console.log(x);
  1971            }
  1972          } catch (temp) {
  1973            error = [temp];
  1974          } finally {
  1975            try {
  1976              more && (temp = iter.return) && (yield temp.call(iter));
  1977            } finally {
  1978              if (error)
  1979                throw error[0];
  1980            }
  1981          }
  1982        });
  1983      }
  1984      bar();
  1985      ```
  1986  
  1987      This is an older feature that was added to JavaScript in ES2018 but I didn't implement the transformation then because it's a rarely-used feature. Note that esbuild already added support for transforming `for await` loops (the other part of the [asynchronous iteration proposal](https://github.com/tc39/proposal-async-iteration)) a year ago, so support for asynchronous iteration should now be complete.
  1988  
  1989      I have never used this feature myself and code that uses this feature is hard to come by, so this transformation has not yet been tested on real-world code. If you do write code that uses this feature, please let me know if esbuild's `async` generator transformation doesn't work with your code.
  1990  
  1991  ## 0.18.7
  1992  
  1993  * Add support for `using` declarations in TypeScript 5.2+ ([#3191](https://github.com/evanw/esbuild/issues/3191))
  1994  
  1995      TypeScript 5.2 (due to be released in August of 2023) will introduce `using` declarations, which will allow you to automatically dispose of the declared resources when leaving the current scope. You can read the [TypeScript PR for this feature](https://github.com/microsoft/TypeScript/pull/54505) for more information. This release of esbuild adds support for transforming this syntax to target environments without support for `using` declarations (which is currently all targets other than `esnext`). Here's an example (helper functions are omitted):
  1996  
  1997      ```js
  1998      // Original code
  1999      class Foo {
  2000        [Symbol.dispose]() {
  2001          console.log('cleanup')
  2002        }
  2003      }
  2004      using foo = new Foo;
  2005      foo.bar();
  2006  
  2007      // New output (with --target=es6)
  2008      var _stack = [];
  2009      try {
  2010        var Foo = class {
  2011          [Symbol.dispose]() {
  2012            console.log("cleanup");
  2013          }
  2014        };
  2015        var foo = __using(_stack, new Foo());
  2016        foo.bar();
  2017      } catch (_) {
  2018        var _error = _, _hasError = true;
  2019      } finally {
  2020        __callDispose(_stack, _error, _hasError);
  2021      }
  2022      ```
  2023  
  2024      The injected helper functions ensure that the method named `Symbol.dispose` is called on `new Foo` when control exits the scope. Note that as with all new JavaScript APIs, you'll need to polyfill `Symbol.dispose` if it's not present before you use it. This is not something that esbuild does for you because esbuild only handles syntax, not APIs. Polyfilling it can be done with something like this:
  2025  
  2026      ```js
  2027      Symbol.dispose ||= Symbol('Symbol.dispose')
  2028      ```
  2029  
  2030      This feature also introduces `await using` declarations which are like `using` declarations but they call `await` on the disposal method (not on the initializer). Here's an example (helper functions are omitted):
  2031  
  2032      ```js
  2033      // Original code
  2034      class Foo {
  2035        async [Symbol.asyncDispose]() {
  2036          await new Promise(done => {
  2037            setTimeout(done, 1000)
  2038          })
  2039          console.log('cleanup')
  2040        }
  2041      }
  2042      await using foo = new Foo;
  2043      foo.bar();
  2044  
  2045      // New output (with --target=es2022)
  2046      var _stack = [];
  2047      try {
  2048        var Foo = class {
  2049          async [Symbol.asyncDispose]() {
  2050            await new Promise((done) => {
  2051              setTimeout(done, 1e3);
  2052            });
  2053            console.log("cleanup");
  2054          }
  2055        };
  2056        var foo = __using(_stack, new Foo(), true);
  2057        foo.bar();
  2058      } catch (_) {
  2059        var _error = _, _hasError = true;
  2060      } finally {
  2061        var _promise = __callDispose(_stack, _error, _hasError);
  2062        _promise && await _promise;
  2063      }
  2064      ```
  2065  
  2066      The injected helper functions ensure that the method named `Symbol.asyncDispose` is called on `new Foo` when control exits the scope, and that the returned promise is awaited. Similarly to `Symbol.dispose`, you'll also need to polyfill `Symbol.asyncDispose` before you use it.
  2067  
  2068  * Add a `--line-limit=` flag to limit line length ([#3170](https://github.com/evanw/esbuild/issues/3170))
  2069  
  2070      Long lines are common in minified code. However, many tools and text editors can't handle long lines. This release introduces the `--line-limit=` flag to tell esbuild to wrap lines longer than the provided number of bytes. For example, `--line-limit=80` tells esbuild to insert a newline soon after a given line reaches 80 bytes in length. This setting applies to both JavaScript and CSS, and works even when minification is disabled. Note that turning this setting on will make your files bigger, as the extra newlines take up additional space in the file (even after gzip compression).
  2071  
  2072  ## 0.18.6
  2073  
  2074  * Fix tree-shaking of classes with decorators ([#3164](https://github.com/evanw/esbuild/issues/3164))
  2075  
  2076      This release fixes a bug where esbuild incorrectly allowed tree-shaking on classes with decorators. Each decorator is a function call, so classes with decorators must never be tree-shaken. This bug was a regression that was unintentionally introduced in version 0.18.2 by the change that enabled tree-shaking of lowered private fields. Previously decorators were always lowered, and esbuild always considered the automatically-generated decorator code to be a side effect. But this is no longer the case now that esbuild analyzes side effects using the AST before lowering takes place. This bug was fixed by considering any decorator a side effect.
  2077  
  2078  * Fix a minification bug involving function expressions ([#3125](https://github.com/evanw/esbuild/issues/3125))
  2079  
  2080      When minification is enabled, esbuild does limited inlining of `const` symbols at the top of a scope. This release fixes a bug where inlineable symbols were incorrectly removed assuming that they were inlined. They may not be inlined in cases where they were referenced by earlier constants in the body of a function expression. The declarations involved in these edge cases are now kept instead of being removed:
  2081  
  2082      ```js
  2083      // Original code
  2084      {
  2085        const fn = () => foo
  2086        const foo = 123
  2087        console.log(fn)
  2088      }
  2089  
  2090      // Old output (with --minify-syntax)
  2091      console.log((() => foo)());
  2092  
  2093      // New output (with --minify-syntax)
  2094      {
  2095        const fn = () => foo, foo = 123;
  2096        console.log(fn);
  2097      }
  2098      ```
  2099  
  2100  ## 0.18.5
  2101  
  2102  * Implement auto accessors ([#3009](https://github.com/evanw/esbuild/issues/3009))
  2103  
  2104      This release implements the new auto-accessor syntax from the upcoming [JavaScript decorators proposal](https://github.com/tc39/proposal-decorators). The auto-accessor syntax looks like this:
  2105  
  2106      ```js
  2107      class Foo {
  2108        accessor foo;
  2109        static accessor bar;
  2110      }
  2111      new Foo().foo = Foo.bar;
  2112      ```
  2113  
  2114      This syntax is not yet a part of JavaScript but it was [added to TypeScript in version 4.9](https://devblogs.microsoft.com/typescript/announcing-typescript-4-9/#auto-accessors-in-classes). More information about this feature can be found in [microsoft/TypeScript#49705](https://github.com/microsoft/TypeScript/pull/49705). Auto-accessors will be transformed if the target is set to something other than `esnext`:
  2115  
  2116      ```js
  2117      // Output (with --target=esnext)
  2118      class Foo {
  2119        accessor foo;
  2120        static accessor bar;
  2121      }
  2122      new Foo().foo = Foo.bar;
  2123  
  2124      // Output (with --target=es2022)
  2125      class Foo {
  2126        #foo;
  2127        get foo() {
  2128          return this.#foo;
  2129        }
  2130        set foo(_) {
  2131          this.#foo = _;
  2132        }
  2133        static #bar;
  2134        static get bar() {
  2135          return this.#bar;
  2136        }
  2137        static set bar(_) {
  2138          this.#bar = _;
  2139        }
  2140      }
  2141      new Foo().foo = Foo.bar;
  2142  
  2143      // Output (with --target=es2021)
  2144      var _foo, _bar;
  2145      class Foo {
  2146        constructor() {
  2147          __privateAdd(this, _foo, void 0);
  2148        }
  2149        get foo() {
  2150          return __privateGet(this, _foo);
  2151        }
  2152        set foo(_) {
  2153          __privateSet(this, _foo, _);
  2154        }
  2155        static get bar() {
  2156          return __privateGet(this, _bar);
  2157        }
  2158        static set bar(_) {
  2159          __privateSet(this, _bar, _);
  2160        }
  2161      }
  2162      _foo = new WeakMap();
  2163      _bar = new WeakMap();
  2164      __privateAdd(Foo, _bar, void 0);
  2165      new Foo().foo = Foo.bar;
  2166      ```
  2167  
  2168      You can also now use auto-accessors with esbuild's TypeScript experimental decorator transformation, which should behave the same as decorating the underlying getter/setter pair.
  2169  
  2170      **Please keep in mind that this syntax is not yet part of JavaScript.** This release enables auto-accessors in `.js` files with the expectation that it will be a part of JavaScript soon. However, esbuild may change or remove this feature in the future if JavaScript ends up changing or removing this feature. Use this feature with caution for now.
  2171  
  2172  * Pass through JavaScript decorators ([#104](https://github.com/evanw/esbuild/issues/104))
  2173  
  2174      In this release, esbuild now parses decorators from the upcoming [JavaScript decorators proposal](https://github.com/tc39/proposal-decorators) and passes them through to the output unmodified (as long as the language target is set to `esnext`). Transforming JavaScript decorators to environments that don't support them has not been implemented yet. The only decorator transform that esbuild currently implements is still the TypeScript experimental decorator transform, which only works in `.ts` files and which requires `"experimentalDecorators": true` in your `tsconfig.json` file.
  2175  
  2176  * Static fields with assign semantics now use static blocks if possible
  2177  
  2178      Setting `useDefineForClassFields` to false in TypeScript requires rewriting class fields to assignment statements. Previously this was done by removing the field from the class body and adding an assignment statement after the class declaration. However, this also caused any private fields to also be lowered by necessity (in case a field initializer uses a private symbol, either directly or indirectly). This release changes this transform to use an inline static block if it's supported, which avoids needing to lower private fields in this scenario:
  2179  
  2180      ```js
  2181      // Original code
  2182      class Test {
  2183        static #foo = 123
  2184        static bar = this.#foo
  2185      }
  2186  
  2187      // Old output (with useDefineForClassFields=false)
  2188      var _foo;
  2189      const _Test = class _Test {
  2190      };
  2191      _foo = new WeakMap();
  2192      __privateAdd(_Test, _foo, 123);
  2193      _Test.bar = __privateGet(_Test, _foo);
  2194      let Test = _Test;
  2195  
  2196      // New output (with useDefineForClassFields=false)
  2197      class Test {
  2198        static #foo = 123;
  2199        static {
  2200          this.bar = this.#foo;
  2201        }
  2202      }
  2203      ```
  2204  
  2205  * Fix TypeScript experimental decorators combined with `--mangle-props` ([#3177](https://github.com/evanw/esbuild/issues/3177))
  2206  
  2207      Previously using TypeScript experimental decorators combined with the `--mangle-props` setting could result in a crash, as the experimental decorator transform was not expecting a mangled property as a class member. This release fixes the crash so you can now combine both of these features together safely.
  2208  
  2209  ## 0.18.4
  2210  
  2211  * Bundling no longer unnecessarily transforms class syntax ([#1360](https://github.com/evanw/esbuild/issues/1360), [#1328](https://github.com/evanw/esbuild/issues/1328), [#1524](https://github.com/evanw/esbuild/issues/1524), [#2416](https://github.com/evanw/esbuild/issues/2416))
  2212  
  2213      When bundling, esbuild automatically converts top-level class statements to class expressions. Previously this conversion had the unfortunate side-effect of also transforming certain other class-related syntax features to avoid correctness issues when the references to the class name within the class body. This conversion has been reworked to avoid doing this:
  2214  
  2215      ```js
  2216      // Original code
  2217      export class Foo {
  2218        static foo = () => Foo
  2219      }
  2220  
  2221      // Old output (with --bundle)
  2222      var _Foo = class {
  2223      };
  2224      var Foo = _Foo;
  2225      __publicField(Foo, "foo", () => _Foo);
  2226  
  2227      // New output (with --bundle)
  2228      var Foo = class _Foo {
  2229        static foo = () => _Foo;
  2230      };
  2231      ```
  2232  
  2233      This conversion process is very complicated and has many edge cases (including interactions with static fields, static blocks, private class properties, and TypeScript experimental decorators). It should already be pretty robust but a change like this may introduce new unintentional behavior. Please report any issues with this upgrade on the esbuild bug tracker.
  2234  
  2235      You may be wondering why esbuild needs to do this at all. One reason to do this is that esbuild's bundler sometimes needs to lazily-evaluate a module. For example, a module may end up being both the target of a dynamic `import()` call and a static `import` statement. Lazy module evaluation is done by wrapping the top-level module code in a closure. To avoid a performance hit for static `import` statements, esbuild stores top-level exported symbols outside of the closure and references them directly instead of indirectly.
  2236  
  2237      Another reason to do this is that multiple JavaScript VMs have had and continue to have performance issues with TDZ (i.e. "temporal dead zone") checks. These checks validate that a let, or const, or class symbol isn't used before it's initialized. Here are two issues with well-known VMs:
  2238  
  2239      * V8: https://bugs.chromium.org/p/v8/issues/detail?id=13723 (10% slowdown)
  2240      * JavaScriptCore: https://bugs.webkit.org/show_bug.cgi?id=199866 (1,000% slowdown!)
  2241  
  2242      JavaScriptCore had a severe performance issue as their TDZ implementation had time complexity that was quadratic in the number of variables needing TDZ checks in the same scope (with the top-level scope typically being the worst offender). V8 has ongoing issues with TDZ checks being present throughout the code their JIT generates even when they have already been checked earlier in the same function or when the function in question has already been run (so the checks have already happened).
  2243  
  2244      Due to esbuild's parallel architecture, esbuild both a) needs to convert class statements into class expressions during parsing and b) doesn't yet know whether this module will need to be lazily-evaluated or not in the parser. So esbuild always does this conversion during bundling in case it's needed for correctness (and also to avoid potentially catastrophic performance issues due to bundling creating a large scope with many TDZ variables).
  2245  
  2246  * Enforce TDZ errors in computed class property keys ([#2045](https://github.com/evanw/esbuild/issues/2045))
  2247  
  2248      JavaScript allows class property keys to be generated at run-time using code, like this:
  2249  
  2250      ```js
  2251      class Foo {
  2252        static foo = 'foo'
  2253        static [Foo.foo + '2'] = 2
  2254      }
  2255      ```
  2256  
  2257      Previously esbuild treated references to the containing class name within computed property keys as a reference to the partially-initialized class object. That meant code that attempted to reference properties of the class object (such as the code above) would get back `undefined` instead of throwing an error.
  2258  
  2259      This release rewrites references to the containing class name within computed property keys into code that always throws an error at run-time, which is how this JavaScript code is supposed to work. Code that does this will now also generate a warning. You should never write code like this, but it now should be more obvious when incorrect code like this is written.
  2260  
  2261  * Fix an issue with experimental decorators and static fields ([#2629](https://github.com/evanw/esbuild/issues/2629))
  2262  
  2263      This release also fixes a bug regarding TypeScript experimental decorators and static class fields which reference the enclosing class name in their initializer. This affected top-level classes when bundling was enabled. Previously code that does this could crash because the class name wasn't initialized yet. This case should now be handled correctly:
  2264  
  2265      ```ts
  2266      // Original code
  2267      class Foo {
  2268        @someDecorator
  2269        static foo = 'foo'
  2270        static bar = Foo.foo.length
  2271      }
  2272  
  2273      // Old output
  2274      const _Foo = class {
  2275        static foo = "foo";
  2276        static bar = _Foo.foo.length;
  2277      };
  2278      let Foo = _Foo;
  2279      __decorateClass([
  2280        someDecorator
  2281      ], Foo, "foo", 2);
  2282  
  2283      // New output
  2284      const _Foo = class _Foo {
  2285        static foo = "foo";
  2286        static bar = _Foo.foo.length;
  2287      };
  2288      __decorateClass([
  2289        someDecorator
  2290      ], _Foo, "foo", 2);
  2291      let Foo = _Foo;
  2292      ```
  2293  
  2294  * Fix a minification regression with negative numeric properties ([#3169](https://github.com/evanw/esbuild/issues/3169))
  2295  
  2296      Version 0.18.0 introduced a regression where computed properties with negative numbers were incorrectly shortened into a non-computed property when minification was enabled. This regression has been fixed:
  2297  
  2298      ```js
  2299      // Original code
  2300      x = {
  2301        [1]: 1,
  2302        [-1]: -1,
  2303        [NaN]: NaN,
  2304        [Infinity]: Infinity,
  2305        [-Infinity]: -Infinity,
  2306      }
  2307  
  2308      // Old output (with --minify)
  2309      x={1:1,-1:-1,NaN:NaN,1/0:1/0,-1/0:-1/0};
  2310  
  2311      // New output (with --minify)
  2312      x={1:1,[-1]:-1,NaN:NaN,[1/0]:1/0,[-1/0]:-1/0};
  2313      ```
  2314  
  2315  ## 0.18.3
  2316  
  2317  * Fix a panic due to empty static class blocks ([#3161](https://github.com/evanw/esbuild/issues/3161))
  2318  
  2319      This release fixes a bug where an internal invariant that was introduced in the previous release was sometimes violated, which then caused a panic. It happened when bundling code containing an empty static class block with both minification and bundling enabled.
  2320  
  2321  ## 0.18.2
  2322  
  2323  * Lower static blocks when static fields are lowered ([#2800](https://github.com/evanw/esbuild/issues/2800), [#2950](https://github.com/evanw/esbuild/issues/2950), [#3025](https://github.com/evanw/esbuild/issues/3025))
  2324  
  2325      This release fixes a bug where esbuild incorrectly did not lower static class blocks when static class fields needed to be lowered. For example, the following code should print `1 2 3` but previously printed `2 1 3` instead due to this bug:
  2326  
  2327      ```js
  2328      // Original code
  2329      class Foo {
  2330        static x = console.log(1)
  2331        static { console.log(2) }
  2332        static y = console.log(3)
  2333      }
  2334  
  2335      // Old output (with --supported:class-static-field=false)
  2336      class Foo {
  2337        static {
  2338          console.log(2);
  2339        }
  2340      }
  2341      __publicField(Foo, "x", console.log(1));
  2342      __publicField(Foo, "y", console.log(3));
  2343  
  2344      // New output (with --supported:class-static-field=false)
  2345      class Foo {
  2346      }
  2347      __publicField(Foo, "x", console.log(1));
  2348      console.log(2);
  2349      __publicField(Foo, "y", console.log(3));
  2350      ```
  2351  
  2352  * Use static blocks to implement `--keep-names` on classes ([#2389](https://github.com/evanw/esbuild/issues/2389))
  2353  
  2354      This change fixes a bug where the `name` property could previously be incorrect within a class static context when using `--keep-names`. The problem was that the `name` property was being initialized after static blocks were run instead of before. This has been fixed by moving the `name` property initializer into a static block at the top of the class body:
  2355  
  2356      ```js
  2357      // Original code
  2358      if (typeof Foo === 'undefined') {
  2359        let Foo = class {
  2360          static test = this.name
  2361        }
  2362        console.log(Foo.test)
  2363      }
  2364  
  2365      // Old output (with --keep-names)
  2366      if (typeof Foo === "undefined") {
  2367        let Foo2 = /* @__PURE__ */ __name(class {
  2368          static test = this.name;
  2369        }, "Foo");
  2370        console.log(Foo2.test);
  2371      }
  2372  
  2373      // New output (with --keep-names)
  2374      if (typeof Foo === "undefined") {
  2375        let Foo2 = class {
  2376          static {
  2377            __name(this, "Foo");
  2378          }
  2379          static test = this.name;
  2380        };
  2381        console.log(Foo2.test);
  2382      }
  2383      ```
  2384  
  2385      This change was somewhat involved, especially regarding what esbuild considers to be side-effect free. Some unused classes that weren't removed by tree shaking in previous versions of esbuild may now be tree-shaken. One example is classes with static private fields that are transformed by esbuild into code that doesn't use JavaScript's private field syntax. Previously esbuild's tree shaking analysis ran on the class after syntax lowering, but with this release it will run on the class before syntax lowering, meaning it should no longer be confused by class mutations resulting from automatically-generated syntax lowering code.
  2386  
  2387  ## 0.18.1
  2388  
  2389  * Fill in `null` entries in input source maps ([#3144](https://github.com/evanw/esbuild/issues/3144))
  2390  
  2391      If esbuild bundles input files with source maps and those source maps contain a `sourcesContent` array with `null` entries, esbuild previously copied those `null` entries over to the output source map. With this release, esbuild will now attempt to fill in those `null` entries by looking for a file on the file system with the corresponding name from the `sources` array. This matches esbuild's existing behavior that automatically generates the `sourcesContent` array from the file system if the entire `sourcesContent` array is missing.
  2392  
  2393  * Support `/* @__KEY__ */` comments for mangling property names ([#2574](https://github.com/evanw/esbuild/issues/2574))
  2394  
  2395      Property mangling is an advanced feature that enables esbuild to minify certain property names, even though it's not possible to automatically determine that it's safe to do so. The safe property names are configured via regular expression such as `--mangle-props=_$` (mangle all properties ending in `_`).
  2396  
  2397      Sometimes it's desirable to also minify strings containing property names, even though it's not possible to automatically determine which strings are property names. This release makes it possible to do this by annotating those strings with `/* @__KEY__ */`. This is a convention that Terser added earlier this year, and which esbuild is now following too: https://github.com/terser/terser/pull/1365. Using it looks like this:
  2398  
  2399      ```js
  2400      // Original code
  2401      console.log(
  2402        [obj.mangle_, obj.keep],
  2403        [obj.get('mangle_'), obj.get('keep')],
  2404        [obj.get(/* @__KEY__ */ 'mangle_'), obj.get(/* @__KEY__ */ 'keep')],
  2405      )
  2406  
  2407      // Old output (with --mangle-props=_$)
  2408      console.log(
  2409        [obj.a, obj.keep],
  2410        [obj.get("mangle_"), obj.get("keep")],
  2411        [obj.get(/* @__KEY__ */ "mangle_"), obj.get(/* @__KEY__ */ "keep")]
  2412      );
  2413  
  2414      // New output (with --mangle-props=_$)
  2415      console.log(
  2416        [obj.a, obj.keep],
  2417        [obj.get("mangle_"), obj.get("keep")],
  2418        [obj.get(/* @__KEY__ */ "a"), obj.get(/* @__KEY__ */ "keep")]
  2419      );
  2420      ```
  2421  
  2422  * Support `/* @__NO_SIDE_EFFECTS__ */` comments for functions ([#3149](https://github.com/evanw/esbuild/issues/3149))
  2423  
  2424      Rollup has recently added support for `/* @__NO_SIDE_EFFECTS__ */` annotations before functions to indicate that calls to these functions can be removed if the result is unused (i.e. the calls can be assumed to have no side effects). This release adds basic support for these to esbuild as well, which means esbuild will now parse these comments in input files and preserve them in output files. This should help people that use esbuild in combination with Rollup.
  2425  
  2426      Note that this doesn't necessarily mean esbuild will treat these calls as having no side effects, as esbuild's parallel architecture currently isn't set up to enable this type of cross-file tree-shaking information (tree-shaking decisions regarding a function call are currently local to the file they appear in). If you want esbuild to consider a function call to have no side effects, make sure you continue to annotate the function call with `/* @__PURE__ */` (which is the previously-established convention for communicating this).
  2427  
  2428  ## 0.18.0
  2429  
  2430  **This release deliberately contains backwards-incompatible changes.** To avoid automatically picking up releases like this, you should either be pinning the exact version of `esbuild` in your `package.json` file (recommended) or be using a version range syntax that only accepts patch upgrades such as `^0.17.0` or `~0.17.0`. See npm's documentation about [semver](https://docs.npmjs.com/cli/v6/using-npm/semver/) for more information.
  2431  
  2432  The breaking changes in this release mainly focus on fixing some long-standing issues with esbuild's handling of `tsconfig.json` files. Here are all the changes in this release, in detail:
  2433  
  2434  * Add a way to try esbuild online ([#797](https://github.com/evanw/esbuild/issues/797))
  2435  
  2436      There is now a way to try esbuild live on esbuild's website without installing it: https://esbuild.github.io/try/. In addition to being able to more easily evaluate esbuild, this should also make it more efficient to generate esbuild bug reports. For example, you can use it to compare the behavior of different versions of esbuild on the same input. The state of the page is stored in the URL for easy sharing. Many thanks to [@hyrious](https://github.com/hyrious) for creating https://hyrious.me/esbuild-repl/, which was the main inspiration for this addition to esbuild's website.
  2437  
  2438      Two forms of build options are supported: either CLI-style ([example](https://esbuild.github.io/try/#dAAwLjE3LjE5AC0tbG9hZGVyPXRzeCAtLW1pbmlmeSAtLXNvdXJjZW1hcABsZXQgZWw6IEpTWC5FbGVtZW50ID0gPGRpdiAvPg)) or JS-style ([example](https://esbuild.github.io/try/#dAAwLjE3LjE5AHsKICBsb2FkZXI6ICd0c3gnLAogIG1pbmlmeTogdHJ1ZSwKICBzb3VyY2VtYXA6IHRydWUsCn0AbGV0IGVsOiBKU1guRWxlbWVudCA9IDxkaXYgLz4)). Both are converted into a JS object that's passed to esbuild's WebAssembly API. The CLI-style argument parser is a custom one that simulates shell quoting rules, and the JS-style argument parser is also custom and parses a superset of JSON (basically JSON5 + regular expressions). So argument parsing is an approximate simulation of what happens for real but hopefully it should be close enough.
  2439  
  2440  * Changes to esbuild's `tsconfig.json` support ([#3019](https://github.com/evanw/esbuild/issues/3019)):
  2441  
  2442      This release makes the following changes to esbuild's `tsconfig.json` support:
  2443  
  2444      * Using experimental decorators now requires `"experimentalDecorators": true` ([#104](https://github.com/evanw/esbuild/issues/104))
  2445  
  2446          Previously esbuild would always compile decorators in TypeScript code using TypeScript's experimental decorator transform. Now that standard JavaScript decorators are close to being finalized, esbuild will now require you to use `"experimentalDecorators": true` to do this. This new requirement makes it possible for esbuild to introduce a transform for standard JavaScript decorators in TypeScript code in the future. Such a transform has not been implemented yet, however.
  2447  
  2448      * TypeScript's `target` no longer affects esbuild's `target` ([#2628](https://github.com/evanw/esbuild/issues/2628))
  2449  
  2450          Some people requested that esbuild support TypeScript's `target` setting, so support for it was added (in [version 0.12.4](https://github.com/evanw/esbuild/releases/v0.12.4)). However, esbuild supports reading from multiple `tsconfig.json` files within a single build, which opens up the possibility that different files in the build have different language targets configured. There isn't really any reason to do this and it can lead to unexpected results. So with this release, the `target` setting in `tsconfig.json` will no longer affect esbuild's own `target` setting. You will have to use esbuild's own target setting instead (which is a single, global value).
  2451  
  2452      * TypeScript's `jsx` setting no longer causes esbuild to preserve JSX syntax ([#2634](https://github.com/evanw/esbuild/issues/2634))
  2453  
  2454          TypeScript has a setting called [`jsx`](https://www.typescriptlang.org/tsconfig#jsx) that controls how to transform JSX into JS. The tool-agnostic transform is called `react`, and the React-specific transform is called `react-jsx` (or `react-jsxdev`). There is also a setting called `preserve` which indicates JSX should be passed through untransformed. Previously people would run esbuild with `"jsx": "preserve"` in their `tsconfig.json` files and then be surprised when esbuild preserved their JSX. So with this release, esbuild will now ignore `"jsx": "preserve"` in `tsconfig.json` files. If you want to preserve JSX syntax with esbuild, you now have to use `--jsx=preserve`.
  2455  
  2456          Note: Some people have suggested that esbuild's equivalent `jsx` setting override the one in `tsconfig.json`. However, some projects need to legitimately have different files within the same build use different transforms (i.e. `react` vs. `react-jsx`) and having esbuild's global `jsx` setting override `tsconfig.json` would prevent this from working. This release ignores `"jsx": "preserve"` but still allows other `jsx` values in `tsconfig.json` files to override esbuild's global `jsx` setting to keep the ability for multiple files within the same build to use different transforms.
  2457  
  2458      * `useDefineForClassFields` behavior has changed ([#2584](https://github.com/evanw/esbuild/issues/2584), [#2993](https://github.com/evanw/esbuild/issues/2993))
  2459  
  2460          Class fields in TypeScript look like this (`x` is a class field):
  2461  
  2462          ```js
  2463          class Foo {
  2464            x = 123
  2465          }
  2466          ```
  2467  
  2468          TypeScript has legacy behavior that uses assignment semantics instead of define semantics for class fields when [`useDefineForClassFields`](https://www.typescriptlang.org/tsconfig#useDefineForClassFields) is enabled (in which case class fields in TypeScript behave differently than they do in JavaScript, which is arguably "wrong").
  2469  
  2470          This legacy behavior exists because TypeScript added class fields to TypeScript before they were added to JavaScript. The TypeScript team decided to go with assignment semantics and shipped their implementation. Much later on TC39 decided to go with define semantics for class fields in JavaScript instead. This behaves differently if the base class has a setter with the same name:
  2471  
  2472          ```js
  2473          class Base {
  2474            set x(_) {
  2475              console.log('x:', _)
  2476            }
  2477          }
  2478  
  2479          // useDefineForClassFields: false
  2480          class AssignSemantics extends Base {
  2481            constructor() {
  2482              super()
  2483              this.x = 123
  2484            }
  2485          }
  2486  
  2487          // useDefineForClassFields: true
  2488          class DefineSemantics extends Base {
  2489            constructor() {
  2490              super()
  2491              Object.defineProperty(this, 'x', { value: 123 })
  2492            }
  2493          }
  2494  
  2495          console.log(
  2496            new AssignSemantics().x, // Calls the setter
  2497            new DefineSemantics().x // Doesn't call the setter
  2498          )
  2499          ```
  2500  
  2501          When you run `tsc`, the value of `useDefineForClassFields` defaults to `false` when it's not specified and the `target` in `tsconfig.json` is present but earlier than `ES2022`. This sort of makes sense because the class field language feature was added in ES2022, so before ES2022 class fields didn't exist (and thus TypeScript's legacy behavior is active). However, TypeScript's `target` setting currently defaults to `ES3` which unfortunately means that the `useDefineForClassFields` setting currently defaults to false (i.e. to "wrong"). In other words if you run `tsc` with all default settings, class fields will behave incorrectly.
  2502  
  2503          Previously esbuild tried to do what `tsc` did. That meant esbuild's version of `useDefineForClassFields` was `false` by default, and was also `false` if esbuild's `--target=` was present but earlier than `es2022`. However, TypeScript's legacy class field behavior is becoming increasingly irrelevant and people who expect class fields in TypeScript to work like they do in JavaScript are confused when they use esbuild with default settings. It's also confusing that the behavior of class fields would change if you changed the language target (even though that's exactly how TypeScript works).
  2504  
  2505          So with this release, esbuild will now only use the information in `tsconfig.json` to determine whether `useDefineForClassFields` is true or not. Specifically `useDefineForClassFields` will be respected if present, otherwise it will be `false` if `target` is present in `tsconfig.json` and is `ES2021` or earlier, otherwise it will be `true`. Targets passed to esbuild's `--target=` setting will no longer affect `useDefineForClassFields`.
  2506  
  2507          Note that this means different directories in your build can have different values for this setting since esbuild allows different directories to have different `tsconfig.json` files within the same build. This should let you migrate your code one directory at a time without esbuild's `--target=` setting affecting the semantics of your code.
  2508  
  2509      * Add support for `verbatimModuleSyntax` from TypeScript 5.0
  2510  
  2511          TypeScript 5.0 added a new option called [`verbatimModuleSyntax`](https://www.typescriptlang.org/tsconfig#verbatimModuleSyntax) that deprecates and replaces two older options, `preserveValueImports` and `importsNotUsedAsValues`. Setting `verbatimModuleSyntax` to true in `tsconfig.json` tells esbuild to not drop unused import statements. Specifically esbuild now treats `"verbatimModuleSyntax": true` as if you had specified both `"preserveValueImports": true` and `"importsNotUsedAsValues": "preserve"`.
  2512  
  2513      * Add multiple inheritance for `tsconfig.json` from TypeScript 5.0
  2514  
  2515          TypeScript 5.0 now allows [multiple inheritance for `tsconfig.json` files](https://devblogs.microsoft.com/typescript/announcing-typescript-5-0/#supporting-multiple-configuration-files-in-extends). You can now pass an array of filenames via the `extends` parameter and your `tsconfig.json` will start off containing properties from all of those configuration files, in order. This release of esbuild adds support for this new TypeScript feature.
  2516  
  2517      * Remove support for `moduleSuffixes` ([#2395](https://github.com/evanw/esbuild/issues/2395))
  2518  
  2519          The community has requested that esbuild remove support for TypeScript's `moduleSuffixes` feature, so it has been removed in this release. Instead you can use esbuild's `--resolve-extensions=` feature to select which module suffix you want to build with.
  2520  
  2521      * Apply `--tsconfig=` overrides to `stdin` and virtual files ([#385](https://github.com/evanw/esbuild/issues/385), [#2543](https://github.com/evanw/esbuild/issues/2543))
  2522  
  2523          When you override esbuild's automatic `tsconfig.json` file detection with `--tsconfig=` to pass a specific `tsconfig.json` file, esbuild previously didn't apply these settings to source code passed via the `stdin` API option or to TypeScript files from plugins that weren't in the `file` namespace. This release changes esbuild's behavior so that settings from `tsconfig.json` also apply to these source code files as well.
  2524  
  2525      * Support `--tsconfig-raw=` in build API calls ([#943](https://github.com/evanw/esbuild/issues/943), [#2440](https://github.com/evanw/esbuild/issues/2440))
  2526  
  2527          Previously if you wanted to override esbuild's automatic `tsconfig.json` file detection, you had to create a new `tsconfig.json` file and pass the file name to esbuild via the `--tsconfig=` flag. With this release, you can now optionally use `--tsconfig-raw=` instead to pass the contents of `tsconfig.json` to esbuild directly instead of passing the file name. For example, you can now use `--tsconfig-raw={"compilerOptions":{"experimentalDecorators":true}}` to enable TypeScript experimental decorators directly using a command-line flag (assuming you escape the quotes correctly using your current shell's quoting rules). The `--tsconfig-raw=` flag previously only worked with transform API calls but with this release, it now works with build API calls too.
  2528  
  2529      * Ignore all `tsconfig.json` files in `node_modules` ([#276](https://github.com/evanw/esbuild/issues/276), [#2386](https://github.com/evanw/esbuild/issues/2386))
  2530  
  2531          This changes esbuild's behavior that applies `tsconfig.json` to all files in the subtree of the directory containing `tsconfig.json`. In version 0.12.7, esbuild started ignoring `tsconfig.json` files inside `node_modules` folders. The rationale is that people typically do this by mistake and that doing this intentionally is a rare use case that doesn't need to be supported. However, this change only applied to certain syntax-specific settings (e.g. `jsxFactory`) but did not apply to path resolution settings (e.g. `paths`). With this release, esbuild will now ignore all `tsconfig.json` files in `node_modules` instead of only ignoring certain settings.
  2532  
  2533      * Ignore `tsconfig.json` when resolving paths within `node_modules` ([#2481](https://github.com/evanw/esbuild/issues/2481))
  2534  
  2535          Previously fields in `tsconfig.json` related to path resolution (e.g. `paths`) were respected for all files in the subtree containing that `tsconfig.json` file, even within a nested `node_modules` subdirectory. This meant that a project's `paths` settings could potentially affect any bundled packages. With this release, esbuild will no longer use `tsconfig.json` settings during path resolution inside nested `node_modules` subdirectories.
  2536  
  2537      * Prefer `.js` over `.ts` within `node_modules` ([#3019](https://github.com/evanw/esbuild/issues/3019))
  2538  
  2539          The default list of implicit extensions that esbuild will try appending to import paths contains `.ts` before `.js`. This makes it possible to bundle TypeScript projects that reference other files in the project using extension-less imports (e.g. `./some-file` to load `./some-file.ts` instead of `./some-file.js`). However, this behavior is undesirable within `node_modules` directories. Some package authors publish both their original TypeScript code and their compiled JavaScript code side-by-side. In these cases, esbuild should arguably be using the compiled JavaScript files instead of the original TypeScript files because the TypeScript compilation settings for files within the package should be determined by the package author, not the user of esbuild. So with this release, esbuild will now prefer implicit `.js` extensions over `.ts` when searching for import paths within `node_modules`.
  2540  
  2541      These changes are intended to improve esbuild's compatibility with `tsc` and reduce the number of unfortunate behaviors regarding `tsconfig.json` and esbuild.
  2542  
  2543  * Add a workaround for bugs in Safari 16.2 and earlier ([#3072](https://github.com/evanw/esbuild/issues/3072))
  2544  
  2545      Safari's JavaScript parser had a bug (which has now been fixed) where at least something about unary/binary operators nested inside default arguments nested inside either a function or class expression was incorrectly considered a syntax error if that expression was the target of a property assignment. Here are some examples that trigger this Safari bug:
  2546  
  2547      ```
  2548      ā± x(function (y = -1) {}.z = 2)
  2549      SyntaxError: Left hand side of operator '=' must be a reference.
  2550  
  2551      ā± x(class { f(y = -1) {} }.z = 2)
  2552      SyntaxError: Left hand side of operator '=' must be a reference.
  2553      ```
  2554  
  2555      It's not clear what the exact conditions are that trigger this bug. However, a workaround for this bug appears to be to post-process your JavaScript to wrap any in function and class declarations that are the direct target of a property access expression in parentheses. That's the workaround that UglifyJS applies for this issue: [mishoo/UglifyJS#2056](https://github.com/mishoo/UglifyJS/pull/2056). So that's what esbuild now does starting with this release:
  2556  
  2557      ```js
  2558      // Original code
  2559      x(function (y = -1) {}.z = 2, class { f(y = -1) {} }.z = 2)
  2560  
  2561      // Old output (with --minify --target=safari16.2)
  2562      x(function(c=-1){}.z=2,class{f(c=-1){}}.z=2);
  2563  
  2564      // New output (with --minify --target=safari16.2)
  2565      x((function(c=-1){}).z=2,(class{f(c=-1){}}).z=2);
  2566      ```
  2567  
  2568      This fix is not enabled by default. It's only enabled when `--target=` contains Safari 16.2 or earlier, such as with `--target=safari16.2`. You can also explicitly enable or disable this specific transform (called `function-or-class-property-access`) with `--supported:function-or-class-property-access=false`.
  2569  
  2570  * Fix esbuild's TypeScript type declarations to forbid unknown properties ([#3089](https://github.com/evanw/esbuild/issues/3089))
  2571  
  2572      Version 0.17.0 of esbuild introduced a specific form of function overloads in the TypeScript type definitions for esbuild's API calls that looks like this:
  2573  
  2574      ```ts
  2575      interface TransformOptions {
  2576        legalComments?: 'none' | 'inline' | 'eof' | 'external'
  2577      }
  2578  
  2579      interface TransformResult<ProvidedOptions extends TransformOptions = TransformOptions> {
  2580        legalComments: string | (ProvidedOptions['legalComments'] extends 'external' ? never : undefined)
  2581      }
  2582  
  2583      declare function transformSync<ProvidedOptions extends TransformOptions>(input: string, options?: ProvidedOptions): TransformResult<ProvidedOptions>
  2584      declare function transformSync(input: string, options?: TransformOptions): TransformResult
  2585      ```
  2586  
  2587      This more accurately reflects how esbuild's JavaScript API behaves. The result object returned by `transformSync` only has the `legalComments` property if you pass `legalComments: 'external'`:
  2588  
  2589      ```ts
  2590      // These have type "string | undefined"
  2591      transformSync('').legalComments
  2592      transformSync('', { legalComments: 'eof' }).legalComments
  2593  
  2594      // This has type "string"
  2595      transformSync('', { legalComments: 'external' }).legalComments
  2596      ```
  2597  
  2598      However, this form of function overloads unfortunately allows typos (e.g. `egalComments`) to pass the type checker without generating an error as TypeScript allows all objects with unknown properties to extend `TransformOptions`. These typos result in esbuild's API throwing an error at run-time.
  2599  
  2600      To prevent typos during type checking, esbuild's TypeScript type definitions will now use a different form that looks like this:
  2601  
  2602      ```ts
  2603      type SameShape<Out, In extends Out> = In & { [Key in Exclude<keyof In, keyof Out>]: never }
  2604  
  2605      interface TransformOptions {
  2606        legalComments?: 'none' | 'inline' | 'eof' | 'external'
  2607      }
  2608  
  2609      interface TransformResult<ProvidedOptions extends TransformOptions = TransformOptions> {
  2610        legalComments: string | (ProvidedOptions['legalComments'] extends 'external' ? never : undefined)
  2611      }
  2612  
  2613      declare function transformSync<T extends TransformOptions>(input: string, options?: SameShape<TransformOptions, T>): TransformResult<T>
  2614      ```
  2615  
  2616      This change should hopefully not affect correct code. It should hopefully introduce type errors only for incorrect code.
  2617  
  2618  * Fix CSS nesting transform for pseudo-elements ([#3119](https://github.com/evanw/esbuild/issues/3119))
  2619  
  2620      This release fixes esbuild's CSS nesting transform for pseudo-elements (e.g. `::before` and `::after`). The CSS nesting specification says that [the nesting selector does not work with pseudo-elements](https://www.w3.org/TR/css-nesting-1/#ref-for-matches-pseudo%E2%91%A0). This can be seen in the example below: esbuild does not carry the parent pseudo-element `::before` through the nesting selector `&`. However, that doesn't apply to pseudo-elements that are within the same selector. Previously esbuild had a bug where it considered pseudo-elements in both locations as invalid. This release changes esbuild to only consider those from the parent selector invalid, which should align with the specification:
  2621  
  2622      ```css
  2623      /* Original code */
  2624      a, b::before {
  2625        &.c, &::after {
  2626          content: 'd';
  2627        }
  2628      }
  2629  
  2630      /* Old output (with --target=chrome90) */
  2631      a:is(.c, ::after) {
  2632        content: "d";
  2633      }
  2634  
  2635      /* New output (with --target=chrome90) */
  2636      a.c,
  2637      a::after {
  2638        content: "d";
  2639      }
  2640      ```
  2641  
  2642  * Forbid `&` before a type selector in nested CSS
  2643  
  2644      The people behind the work-in-progress CSS nesting specification have very recently [decided to forbid nested CSS that looks like `&div`](https://github.com/w3c/csswg-drafts/issues/8662#issuecomment-1514977935). You will have to use either `div&` or `&:is(div)` instead. This release of esbuild has been updated to take this new change into consideration. Doing this now generates a warning. The suggested fix is slightly different depending on where in the overall selector it happened:
  2645  
  2646      ```
  2647      ā–² [WARNING] Cannot use type selector "input" directly after nesting selector "&" [css-syntax-error]
  2648  
  2649          example.css:2:3:
  2650            2 ā”‚   &input {
  2651              ā”‚    ~~~~~
  2652              ā•µ    :is(input)
  2653  
  2654        CSS nesting syntax does not allow the "&" selector to come before a type selector. You can wrap
  2655        this selector in ":is()" as a workaround. This restriction exists to avoid problems with SASS
  2656        nesting, where the same syntax means something very different that has no equivalent in real CSS
  2657        (appending a suffix to the parent selector).
  2658  
  2659      ā–² [WARNING] Cannot use type selector "input" directly after nesting selector "&" [css-syntax-error]
  2660  
  2661          example.css:6:8:
  2662            6 ā”‚   .form &input {
  2663              ā”‚         ~~~~~~
  2664              ā•µ         input&
  2665  
  2666        CSS nesting syntax does not allow the "&" selector to come before a type selector. You can move
  2667        the "&" to the end of this selector as a workaround. This restriction exists to avoid problems
  2668        with SASS nesting, where the same syntax means something very different that has no equivalent in
  2669        real CSS (appending a suffix to the parent selector).
  2670      ```
  2671  
  2672  ## 0.17.19
  2673  
  2674  * Fix CSS transform bugs with nested selectors that start with a combinator ([#3096](https://github.com/evanw/esbuild/issues/3096))
  2675  
  2676      This release fixes several bugs regarding transforming nested CSS into non-nested CSS for older browsers. The bugs were due to lack of test coverage for nested selectors with more than one compound selector where they all start with the same combinator. Here's what some problematic cases look like before and after these fixes:
  2677  
  2678      ```css
  2679      /* Original code */
  2680      .foo {
  2681        > &a,
  2682        > &b {
  2683          color: red;
  2684        }
  2685      }
  2686      .bar {
  2687        > &a,
  2688        + &b {
  2689          color: green;
  2690        }
  2691      }
  2692  
  2693      /* Old output (with --target=chrome90) */
  2694      .foo :is(> .fooa, > .foob) {
  2695        color: red;
  2696      }
  2697      .bar :is(> .bara, + .barb) {
  2698        color: green;
  2699      }
  2700  
  2701      /* New output (with --target=chrome90) */
  2702      .foo > :is(a.foo, b.foo) {
  2703        color: red;
  2704      }
  2705      .bar > a.bar,
  2706      .bar + b.bar {
  2707        color: green;
  2708      }
  2709      ```
  2710  
  2711  * Fix bug with TypeScript parsing of instantiation expressions followed by `=` ([#3111](https://github.com/evanw/esbuild/issues/3111))
  2712  
  2713      This release fixes esbuild's TypeScript-to-JavaScript conversion code in the case where a potential instantiation expression is followed immediately by a `=` token (such that the trailing `>` becomes a `>=` token). Previously esbuild considered that to still be an instantiation expression, but the official TypeScript compiler considered it to be a `>=` operator instead. This release changes esbuild's interpretation to match TypeScript. This edge case currently [appears to be problematic](https://sucrase.io/#transforms=typescript&compareWithTypeScript=true&code=x%3Cy%3E%3Da%3Cb%3Cc%3E%3E()) for other TypeScript-to-JavaScript converters as well:
  2714  
  2715      | Original code | TypeScript | esbuild 0.17.18 | esbuild 0.17.19 | Sucrase | Babel |
  2716      |---|---|---|---|---|---|
  2717      | `x<y>=a<b<c>>()` | `x<y>=a();` | `x=a();` | `x<y>=a();` | `x=a()` | Invalid left-hand side in assignment expression |
  2718  
  2719  * Avoid removing unrecognized directives from the directive prologue when minifying ([#3115](https://github.com/evanw/esbuild/issues/3115))
  2720  
  2721      The [directive prologue](https://262.ecma-international.org/6.0/#sec-directive-prologues-and-the-use-strict-directive) in JavaScript is a sequence of top-level string expressions that come before your code. The only directives that JavaScript engines currently recognize are `use strict` and sometimes `use asm`. However, the people behind React have made up their own directive for their own custom dialect of JavaScript. Previously esbuild only preserved the `use strict` directive when minifying, although you could still write React JavaScript with esbuild using something like `--banner:js="'your directive here';"`. With this release, you can now put arbitrary directives in the entry point and esbuild will preserve them in its minified output:
  2722  
  2723      ```js
  2724      // Original code
  2725      'use wtf'; console.log(123)
  2726  
  2727      // Old output (with --minify)
  2728      console.log(123);
  2729  
  2730      // New output (with --minify)
  2731      "use wtf";console.log(123);
  2732      ```
  2733  
  2734      Note that this means esbuild will no longer remove certain stray top-level strings when minifying. This behavior is an intentional change because these stray top-level strings are actually part of the directive prologue, and could potentially have semantics assigned to them (as was the case with React).
  2735  
  2736  * Improved minification of binary shift operators
  2737  
  2738      With this release, esbuild's minifier will now evaluate the `<<` and `>>>` operators if the resulting code would be shorter:
  2739  
  2740      ```js
  2741      // Original code
  2742      console.log(10 << 10, 10 << 20, -123 >>> 5, -123 >>> 10);
  2743  
  2744      // Old output (with --minify)
  2745      console.log(10<<10,10<<20,-123>>>5,-123>>>10);
  2746  
  2747      // New output (with --minify)
  2748      console.log(10240,10<<20,-123>>>5,4194303);
  2749      ```
  2750  
  2751  ## 0.17.18
  2752  
  2753  * Fix non-default JSON import error with `export {} from` ([#3070](https://github.com/evanw/esbuild/issues/3070))
  2754  
  2755      This release fixes a bug where esbuild incorrectly identified statements of the form `export { default as x } from "y" assert { type: "json" }` as a non-default import. The bug did not affect code of the form `import { default as x } from ...` (only code that used the `export` keyword).
  2756  
  2757  * Fix a crash with an invalid subpath import ([#3067](https://github.com/evanw/esbuild/issues/3067))
  2758  
  2759      Previously esbuild could crash when attempting to generate a friendly error message for an invalid [subpath import](https://nodejs.org/api/packages.html#subpath-imports) (i.e. an import starting with `#`). This happened because esbuild originally only supported the `exports` field and the code for that error message was not updated when esbuild later added support for the `imports` field. This crash has been fixed.
  2760  
  2761  ## 0.17.17
  2762  
  2763  * Fix CSS nesting transform for top-level `&` ([#3052](https://github.com/evanw/esbuild/issues/3052))
  2764  
  2765      Previously esbuild could crash with a stack overflow when lowering CSS nesting rules with a top-level `&`, such as in the code below. This happened because esbuild's CSS nesting transform didn't handle top-level `&`, causing esbuild to inline the top-level selector into itself. This release handles top-level `&` by replacing it with [the `:scope` pseudo-class](https://drafts.csswg.org/selectors-4/#the-scope-pseudo):
  2766  
  2767      ```css
  2768      /* Original code */
  2769      &,
  2770      a {
  2771        .b {
  2772          color: red;
  2773        }
  2774      }
  2775  
  2776      /* New output (with --target=chrome90) */
  2777      :is(:scope, a) .b {
  2778        color: red;
  2779      }
  2780      ```
  2781  
  2782  * Support `exports` in `package.json` for `extends` in `tsconfig.json` ([#3058](https://github.com/evanw/esbuild/issues/3058))
  2783  
  2784      TypeScript 5.0 added the ability to use `extends` in `tsconfig.json` to reference a path in a package whose `package.json` file contains an `exports` map that points to the correct location. This doesn't automatically work in esbuild because `tsconfig.json` affects esbuild's path resolution, so esbuild's normal path resolution logic doesn't apply.
  2785  
  2786      This release adds support for doing this by adding some additional code that attempts to resolve the `extends` path using the `exports` field. The behavior should be similar enough to esbuild's main path resolution logic to work as expected.
  2787  
  2788      Note that esbuild always treats this `extends` import as a `require()` import since that's what TypeScript appears to do. Specifically the `require` condition will be active and the `import` condition will be inactive.
  2789  
  2790  * Fix watch mode with `NODE_PATH` ([#3062](https://github.com/evanw/esbuild/issues/3062))
  2791  
  2792      Node has a rarely-used feature where you can extend the set of directories that node searches for packages using the `NODE_PATH` environment variable. While esbuild supports this too, previously a bug prevented esbuild's watch mode from picking up changes to imported files that were contained directly in a `NODE_PATH` directory. You're supposed to use `NODE_PATH` for packages, but some people abuse this feature by putting files in that directory instead (e.g. `node_modules/some-file.js` instead of `node_modules/some-pkg/some-file.js`). The watch mode bug happens when you do this because esbuild first tries to read `some-file.js` as a directory and then as a file. Watch mode was incorrectly waiting for `some-file.js` to become a valid directory. This release fixes this edge case bug by changing watch mode to watch `some-file.js` as a file when this happens.
  2793  
  2794  ## 0.17.16
  2795  
  2796  * Fix CSS nesting transform for triple-nested rules that start with a combinator ([#3046](https://github.com/evanw/esbuild/issues/3046))
  2797  
  2798      This release fixes a bug with esbuild where triple-nested CSS rules that start with a combinator were not transformed correctly for older browsers. Here's an example of such a case before and after this bug fix:
  2799  
  2800      ```css
  2801      /* Original input */
  2802      .a {
  2803        color: red;
  2804        > .b {
  2805          color: green;
  2806          > .c {
  2807            color: blue;
  2808          }
  2809        }
  2810      }
  2811  
  2812      /* Old output (with --target=chrome90) */
  2813      .a {
  2814        color: red;
  2815      }
  2816      .a > .b {
  2817        color: green;
  2818      }
  2819      .a .b > .c {
  2820        color: blue;
  2821      }
  2822  
  2823      /* New output (with --target=chrome90) */
  2824      .a {
  2825        color: red;
  2826      }
  2827      .a > .b {
  2828        color: green;
  2829      }
  2830      .a > .b > .c {
  2831        color: blue;
  2832      }
  2833      ```
  2834  
  2835  * Support `--inject` with a file loaded using the `copy` loader ([#3041](https://github.com/evanw/esbuild/issues/3041))
  2836  
  2837      This release now allows you to use `--inject` with a file that is loaded using the `copy` loader. The `copy` loader copies the imported file to the output directory verbatim and rewrites the path in the `import` statement to point to the copied output file. When used with `--inject`, this means the injected file will be copied to the output directory as-is and a bare `import` statement for that file will be inserted in any non-copy output files that esbuild generates.
  2838  
  2839      Note that since esbuild doesn't parse the contents of copied files, esbuild will not expose any of the export names as usable imports when you do this (in the way that esbuild's `--inject` feature is typically used). However, any side-effects that the injected file has will still occur.
  2840  
  2841  ## 0.17.15
  2842  
  2843  * Allow keywords as type parameter names in mapped types ([#3033](https://github.com/evanw/esbuild/issues/3033))
  2844  
  2845      TypeScript allows type keywords to be used as parameter names in mapped types. Previously esbuild incorrectly treated this as an error. Code that does this is now supported:
  2846  
  2847      ```ts
  2848      type Foo = 'a' | 'b' | 'c'
  2849      type A = { [keyof in Foo]: number }
  2850      type B = { [infer in Foo]: number }
  2851      type C = { [readonly in Foo]: number }
  2852      ```
  2853  
  2854  * Add annotations for re-exported modules in node ([#2486](https://github.com/evanw/esbuild/issues/2486), [#3029](https://github.com/evanw/esbuild/issues/3029))
  2855  
  2856      Node lets you import named imports from a CommonJS module using ESM import syntax. However, the allowed names aren't derived from the properties of the CommonJS module. Instead they are derived from an arbitrary syntax-only analysis of the CommonJS module's JavaScript AST.
  2857  
  2858      To accommodate node doing this, esbuild's ESM-to-CommonJS conversion adds a special non-executable "annotation" for node that describes the exports that node should expose in this scenario. It takes the form `0 && (module.exports = { ... })` and comes at the end of the file (`0 && expr` means `expr` is never evaluated).
  2859  
  2860      Previously esbuild didn't do this for modules re-exported using the `export * from` syntax. Annotations for these re-exports will now be added starting with this release:
  2861  
  2862      ```js
  2863      // Original input
  2864      export { foo } from './foo'
  2865      export * from './bar'
  2866  
  2867      // Old output (with --format=cjs --platform=node)
  2868      ...
  2869      0 && (module.exports = {
  2870        foo
  2871      });
  2872  
  2873      // New output (with --format=cjs --platform=node)
  2874      ...
  2875      0 && (module.exports = {
  2876        foo,
  2877        ...require("./bar")
  2878      });
  2879      ```
  2880  
  2881      Note that you need to specify both `--format=cjs` and `--platform=node` to get these node-specific annotations.
  2882  
  2883  * Avoid printing an unnecessary space in between a number and a `.` ([#3026](https://github.com/evanw/esbuild/pull/3026))
  2884  
  2885      JavaScript typically requires a space in between a number token and a `.` token to avoid the `.` being interpreted as a decimal point instead of a member expression. However, this space is not required if the number token itself contains a decimal point, an exponent, or uses a base other than 10. This release of esbuild now avoids printing the unnecessary space in these cases:
  2886  
  2887      ```js
  2888      // Original input
  2889      foo(1000 .x, 0 .x, 0.1 .x, 0.0001 .x, 0xFFFF_0000_FFFF_0000 .x)
  2890  
  2891      // Old output (with --minify)
  2892      foo(1e3 .x,0 .x,.1 .x,1e-4 .x,0xffff0000ffff0000 .x);
  2893  
  2894      // New output (with --minify)
  2895      foo(1e3.x,0 .x,.1.x,1e-4.x,0xffff0000ffff0000.x);
  2896      ```
  2897  
  2898  * Fix server-sent events with live reload when writing to the file system root ([#3027](https://github.com/evanw/esbuild/issues/3027))
  2899  
  2900      This release fixes a bug where esbuild previously failed to emit server-sent events for live reload when `outdir` was the file system root, such as `/`. This happened because `/` is the only path on Unix that cannot have a trailing slash trimmed from it, which was fixed by improved path handling.
  2901  
  2902  ## 0.17.14
  2903  
  2904  * Allow the TypeScript 5.0 `const` modifier in object type declarations ([#3021](https://github.com/evanw/esbuild/issues/3021))
  2905  
  2906      The new TypeScript 5.0 `const` modifier was added to esbuild in version 0.17.5, and works with classes, functions, and arrow expressions. However, support for it wasn't added to object type declarations (e.g. interfaces) due to an oversight. This release adds support for these cases, so the following TypeScript 5.0 code can now be built with esbuild:
  2907  
  2908      ```ts
  2909      interface Foo { <const T>(): T }
  2910      type Bar = { new <const T>(): T }
  2911      ```
  2912  
  2913  * Implement preliminary lowering for CSS nesting ([#1945](https://github.com/evanw/esbuild/issues/1945))
  2914  
  2915      Chrome has [implemented the new CSS nesting specification](https://developer.chrome.com/articles/css-nesting/) in version 112, which is currently in beta but will become stable very soon. So CSS nesting is now a part of the web platform!
  2916  
  2917      This release of esbuild can now transform nested CSS syntax into non-nested CSS syntax for older browsers. The transformation relies on the `:is()` pseudo-class in many cases, so the transformation is only guaranteed to work when targeting browsers that support `:is()` (e.g. Chrome 88+). You'll need to set esbuild's [`target`](https://esbuild.github.io/api/#target) to the browsers you intend to support to tell esbuild to do this transformation. You will get a warning if you use CSS nesting syntax with a `target` which includes older browsers that don't support `:is()`.
  2918  
  2919      The lowering transformation looks like this:
  2920  
  2921      ```css
  2922      /* Original input */
  2923      a.btn {
  2924        color: #333;
  2925        &:hover { color: #444 }
  2926        &:active { color: #555 }
  2927      }
  2928  
  2929      /* New output (with --target=chrome88) */
  2930      a.btn {
  2931        color: #333;
  2932      }
  2933      a.btn:hover {
  2934        color: #444;
  2935      }
  2936      a.btn:active {
  2937        color: #555;
  2938      }
  2939      ```
  2940  
  2941      More complex cases may generate the `:is()` pseudo-class:
  2942  
  2943      ```css
  2944      /* Original input */
  2945      div, p {
  2946        .warning, .error {
  2947          padding: 20px;
  2948        }
  2949      }
  2950  
  2951      /* New output (with --target=chrome88) */
  2952      :is(div, p) :is(.warning, .error) {
  2953        padding: 20px;
  2954      }
  2955      ```
  2956  
  2957      In addition, esbuild now has a special warning message for nested style rules that start with an identifier. This isn't allowed in CSS because the syntax would be ambiguous with the existing declaration syntax. The new warning message looks like this:
  2958  
  2959      ```
  2960      ā–² [WARNING] A nested style rule cannot start with "p" because it looks like the start of a declaration [css-syntax-error]
  2961  
  2962          <stdin>:1:7:
  2963            1 ā”‚ main { p { margin: auto } }
  2964              ā”‚        ^
  2965              ā•µ        :is(p)
  2966  
  2967        To start a nested style rule with an identifier, you need to wrap the identifier in ":is(...)" to
  2968        prevent the rule from being parsed as a declaration.
  2969      ```
  2970  
  2971      Keep in mind that the transformation in this release is a preliminary implementation. CSS has many features that interact in complex ways, and there may be some edge cases that don't work correctly yet.
  2972  
  2973  * Minification now removes unnecessary `&` CSS nesting selectors
  2974  
  2975      This release introduces the following CSS minification optimizations:
  2976  
  2977      ```css
  2978      /* Original input */
  2979      a {
  2980        font-weight: bold;
  2981        & {
  2982          color: blue;
  2983        }
  2984        & :hover {
  2985          text-decoration: underline;
  2986        }
  2987      }
  2988  
  2989      /* Old output (with --minify) */
  2990      a{font-weight:700;&{color:#00f}& :hover{text-decoration:underline}}
  2991  
  2992      /* New output (with --minify) */
  2993      a{font-weight:700;:hover{text-decoration:underline}color:#00f}
  2994      ```
  2995  
  2996  * Minification now removes duplicates from CSS selector lists
  2997  
  2998      This release introduces the following CSS minification optimization:
  2999  
  3000      ```css
  3001      /* Original input */
  3002      div, div { color: red }
  3003  
  3004      /* Old output (with --minify) */
  3005      div,div{color:red}
  3006  
  3007      /* New output (with --minify) */
  3008      div{color:red}
  3009      ```
  3010  
  3011  ## 0.17.13
  3012  
  3013  * Work around an issue with `NODE_PATH` and Go's WebAssembly internals ([#3001](https://github.com/evanw/esbuild/issues/3001))
  3014  
  3015      Go's WebAssembly implementation returns `EINVAL` instead of `ENOTDIR` when using the `readdir` syscall on a file. This messes up esbuild's implementation of node's module resolution algorithm since encountering `ENOTDIR` causes esbuild to continue its search (since it's a normal condition) while other encountering other errors causes esbuild to fail with an I/O error (since it's an unexpected condition). You can encounter this issue in practice if you use node's legacy `NODE_PATH` feature to tell esbuild to resolve node modules in a custom directory that was not installed by npm. This release works around this problem by converting `EINVAL` into `ENOTDIR` for the `readdir` syscall.
  3016  
  3017  * Fix a minification bug with CSS `@layer` rules that have parsing errors ([#3016](https://github.com/evanw/esbuild/issues/3016))
  3018  
  3019      CSS at-rules [require either a `{}` block or a semicolon at the end](https://www.w3.org/TR/css-syntax-3/#consume-at-rule). Omitting both of these causes esbuild to treat the rule as an unknown at-rule. Previous releases of esbuild had a bug that incorrectly removed unknown at-rules without any children during minification if the at-rule token matched an at-rule that esbuild can handle. Specifically [cssnano](https://cssnano.co/) can generate `@layer` rules with parsing errors, and empty `@layer` rules cannot be removed because they have side effects (`@layer` didn't exist when esbuild's CSS support was added, so esbuild wasn't written to handle this). This release changes esbuild to no longer discard `@layer` rules with parsing errors when minifying (the rule `@layer c` has a parsing error):
  3020  
  3021      ```css
  3022      /* Original input */
  3023      @layer a {
  3024        @layer b {
  3025          @layer c
  3026        }
  3027      }
  3028  
  3029      /* Old output (with --minify) */
  3030      @layer a.b;
  3031  
  3032      /* New output (with --minify) */
  3033      @layer a.b.c;
  3034      ```
  3035  
  3036  * Unterminated strings in CSS are no longer an error
  3037  
  3038      The CSS specification provides [rules for handling parsing errors](https://www.w3.org/TR/CSS22/syndata.html#parsing-errors). One of those rules is that user agents must close strings upon reaching the end of a line (i.e., before an unescaped line feed, carriage return or form feed character), but then drop the construct (declaration or rule) in which the string was found. For example:
  3039  
  3040      ```css
  3041      p {
  3042        color: green;
  3043        font-family: 'Courier New Times
  3044        color: red;
  3045        color: green;
  3046      }
  3047      ```
  3048  
  3049      ...would be treated the same as:
  3050  
  3051      ```css
  3052      p { color: green; color: green; }
  3053      ```
  3054  
  3055      ...because the second declaration (from `font-family` to the semicolon after `color: red`) is invalid and is dropped.
  3056  
  3057      Previously using this CSS with esbuild failed to build due to a syntax error, even though the code can be interpreted by a browser. With this release, the code now produces a warning instead of an error, and esbuild prints the invalid CSS such that it stays invalid in the output:
  3058  
  3059      ```css
  3060      /* esbuild's new non-minified output: */
  3061      p {
  3062        color: green;
  3063        font-family: 'Courier New Times
  3064        color: red;
  3065        color: green;
  3066      }
  3067      ```
  3068  
  3069      ```css
  3070      /* esbuild's new minified output: */
  3071      p{font-family:'Courier New Times
  3072      color: red;color:green}
  3073      ```
  3074  
  3075  ## 0.17.12
  3076  
  3077  * Fix a crash when parsing inline TypeScript decorators ([#2991](https://github.com/evanw/esbuild/issues/2991))
  3078  
  3079      Previously esbuild's TypeScript parser crashed when parsing TypeScript decorators if the definition of the decorator was inlined into the decorator itself:
  3080  
  3081      ```ts
  3082      @(function sealed(constructor: Function) {
  3083        Object.seal(constructor);
  3084        Object.seal(constructor.prototype);
  3085      })
  3086      class Foo {}
  3087      ```
  3088  
  3089      This crash was not noticed earlier because this edge case did not have test coverage. The crash is fixed in this release.
  3090  
  3091  ## 0.17.11
  3092  
  3093  * Fix the `alias` feature to always prefer the longest match ([#2963](https://github.com/evanw/esbuild/issues/2963))
  3094  
  3095      It's possible to configure conflicting aliases such as `--alias:a=b` and `--alias:a/c=d`, which is ambiguous for the import path `a/c/x` (since it could map to either `b/c/x` or `d/x`). Previously esbuild would pick the first matching `alias`, which would non-deterministically pick between one of the possible matches. This release fixes esbuild to always deterministically pick the longest possible match.
  3096  
  3097  * Minify calls to some global primitive constructors ([#2962](https://github.com/evanw/esbuild/issues/2962))
  3098  
  3099      With this release, esbuild's minifier now replaces calls to `Boolean`/`Number`/`String`/`BigInt` with equivalent shorter code when relevant:
  3100  
  3101      ```js
  3102      // Original code
  3103      console.log(
  3104        Boolean(a ? (b | c) !== 0 : (c & d) !== 0),
  3105        Number(e ? '1' : '2'),
  3106        String(e ? '1' : '2'),
  3107        BigInt(e ? 1n : 2n),
  3108      )
  3109  
  3110      // Old output (with --minify)
  3111      console.log(Boolean(a?(b|c)!==0:(c&d)!==0),Number(e?"1":"2"),String(e?"1":"2"),BigInt(e?1n:2n));
  3112  
  3113      // New output (with --minify)
  3114      console.log(!!(a?b|c:c&d),+(e?"1":"2"),e?"1":"2",e?1n:2n);
  3115      ```
  3116  
  3117  * Adjust some feature compatibility tables for node ([#2940](https://github.com/evanw/esbuild/issues/2940))
  3118  
  3119      This release makes the following adjustments to esbuild's internal feature compatibility tables for node, which tell esbuild which versions of node are known to support all aspects of that feature:
  3120  
  3121      * `class-private-brand-checks`: node v16.9+ => node v16.4+ (a decrease)
  3122      * `hashbang`: node v12.0+ => node v12.5+ (an increase)
  3123      * `optional-chain`: node v16.9+ => node v16.1+ (a decrease)
  3124      * `template-literal`: node v4+ => node v10+ (an increase)
  3125  
  3126      Each of these adjustments was identified by comparing against data from the `node-compat-table` package and was manually verified using old node executables downloaded from https://nodejs.org/download/release/.
  3127  
  3128  ## 0.17.10
  3129  
  3130  * Update esbuild's handling of CSS nesting to match the latest specification changes ([#1945](https://github.com/evanw/esbuild/issues/1945))
  3131  
  3132      The syntax for the upcoming CSS nesting feature has [recently changed](https://webkit.org/blog/13813/try-css-nesting-today-in-safari-technology-preview/). The `@nest` prefix that was previously required in some cases is now gone, and nested rules no longer have to start with `&` (as long as they don't start with an identifier or function token).
  3133  
  3134      This release updates esbuild's pass-through handling of CSS nesting syntax to match the latest specification changes. So you can now use esbuild to bundle CSS containing nested rules and try them out in a browser that supports CSS nesting (which includes nightly builds of both Chrome and Safari).
  3135  
  3136      However, I'm not implementing lowering of nested CSS to non-nested CSS for older browsers yet. While the syntax has been decided, the semantics are still in flux. In particular, there is still some debate about changing the fundamental way that CSS nesting works. For example, you might think that the following CSS is equivalent to a `.outer .inner button { ... }` rule:
  3137  
  3138      ```css
  3139      .inner button {
  3140        .outer & {
  3141          color: red;
  3142        }
  3143      }
  3144      ```
  3145  
  3146      But instead it's actually equivalent to a `.outer :is(.inner button) { ... }` rule which unintuitively also matches the following DOM structure:
  3147  
  3148      ```html
  3149      <div class="inner">
  3150        <div class="outer">
  3151          <button></button>
  3152        </div>
  3153      </div>
  3154      ```
  3155  
  3156      The `:is()` behavior is preferred by browser implementers because it's more memory-efficient, but the straightforward translation into a `.outer .inner button { ... }` rule is preferred by developers used to the existing CSS preprocessing ecosystem (e.g. SASS). It seems premature to commit esbuild to specific semantics for this syntax at this time given the ongoing debate.
  3157  
  3158  * Fix cross-file CSS rule deduplication involving `url()` tokens ([#2936](https://github.com/evanw/esbuild/issues/2936))
  3159  
  3160      Previously cross-file CSS rule deduplication didn't handle `url()` tokens correctly. These tokens contain references to import paths which may be internal (i.e. in the bundle) or external (i.e. not in the bundle). When comparing two `url()` tokens for equality, the underlying import paths should be compared instead of their references. This release of esbuild fixes `url()` token comparisons. One side effect is that `@font-face` rules should now be deduplicated correctly across files:
  3161  
  3162      ```css
  3163      /* Original code */
  3164      @import "data:text/css, \
  3165        @import 'http://example.com/style.css'; \
  3166        @font-face { src: url(http://example.com/font.ttf) }";
  3167      @import "data:text/css, \
  3168        @font-face { src: url(http://example.com/font.ttf) }";
  3169  
  3170      /* Old output (with --bundle --minify) */
  3171      @import"http://example.com/style.css";@font-face{src:url(http://example.com/font.ttf)}@font-face{src:url(http://example.com/font.ttf)}
  3172  
  3173      /* New output (with --bundle --minify) */
  3174      @import"http://example.com/style.css";@font-face{src:url(http://example.com/font.ttf)}
  3175      ```
  3176  
  3177  ## 0.17.9
  3178  
  3179  * Parse rest bindings in TypeScript types ([#2937](https://github.com/evanw/esbuild/issues/2937))
  3180  
  3181      Previously esbuild was unable to parse the following valid TypeScript code:
  3182  
  3183      ```ts
  3184      let tuple: (...[e1, e2, ...es]: any) => any
  3185      ```
  3186  
  3187      This release includes support for parsing code like this.
  3188  
  3189  * Fix TypeScript code translation for certain computed `declare` class fields ([#2914](https://github.com/evanw/esbuild/issues/2914))
  3190  
  3191      In TypeScript, the key of a computed `declare` class field should only be preserved if there are no decorators for that field. Previously esbuild always preserved the key, but esbuild will now remove the key to match the output of the TypeScript compiler:
  3192  
  3193      ```ts
  3194      // Original code
  3195      declare function dec(a: any, b: any): any
  3196      declare const removeMe: unique symbol
  3197      declare const keepMe: unique symbol
  3198      class X {
  3199          declare [removeMe]: any
  3200          @dec declare [keepMe]: any
  3201      }
  3202  
  3203      // Old output
  3204      var _a;
  3205      class X {
  3206      }
  3207      removeMe, _a = keepMe;
  3208      __decorateClass([
  3209        dec
  3210      ], X.prototype, _a, 2);
  3211  
  3212      // New output
  3213      var _a;
  3214      class X {
  3215      }
  3216      _a = keepMe;
  3217      __decorateClass([
  3218        dec
  3219      ], X.prototype, _a, 2);
  3220      ```
  3221  
  3222  * Fix a crash with path resolution error generation ([#2913](https://github.com/evanw/esbuild/issues/2913))
  3223  
  3224      In certain situations, a module containing an invalid import path could previously cause esbuild to crash when it attempts to generate a more helpful error message. This crash has been fixed.
  3225  
  3226  ## 0.17.8
  3227  
  3228  * Fix a minification bug with non-ASCII identifiers ([#2910](https://github.com/evanw/esbuild/issues/2910))
  3229  
  3230      This release fixes a bug with esbuild where non-ASCII identifiers followed by a keyword were incorrectly not separated by a space. This bug affected both the `in` and `instanceof` keywords. Here's an example of the fix:
  3231  
  3232      ```js
  3233      // Original code
  3234      Ļ€ in a
  3235  
  3236      // Old output (with --minify --charset=utf8)
  3237      Ļ€in a;
  3238  
  3239      // New output (with --minify --charset=utf8)
  3240      Ļ€ in a;
  3241      ```
  3242  
  3243  * Fix a regression with esbuild's WebAssembly API in version 0.17.6 ([#2911](https://github.com/evanw/esbuild/issues/2911))
  3244  
  3245      Version 0.17.6 of esbuild updated the Go toolchain to version 1.20.0. This had the unfortunate side effect of increasing the amount of stack space that esbuild uses (presumably due to some changes to Go's WebAssembly implementation) which could cause esbuild's WebAssembly-based API to crash with a stack overflow in cases where it previously didn't crash. One such case is the package `grapheme-splitter` which contains code that looks like this:
  3246  
  3247      ```js
  3248      if (
  3249        (0x0300 <= code && code <= 0x036F) ||
  3250        (0x0483 <= code && code <= 0x0487) ||
  3251        (0x0488 <= code && code <= 0x0489) ||
  3252        (0x0591 <= code && code <= 0x05BD) ||
  3253        // ... many hundreds of lines later ...
  3254      ) {
  3255        return;
  3256      }
  3257      ```
  3258  
  3259      This edge case involves a chain of binary operators that results in an AST over 400 nodes deep. Normally this wouldn't be a problem because Go has growable call stacks, so the call stack would just grow to be as large as needed. However, WebAssembly byte code deliberately doesn't expose the ability to manipulate the stack pointer, so Go's WebAssembly translation is forced to use the fixed-size WebAssembly call stack. So esbuild's WebAssembly implementation is vulnerable to stack overflow in cases like these.
  3260  
  3261      It's not unreasonable for this to cause a stack overflow, and for esbuild's answer to this problem to be "don't write code like this." That's how many other AST-manipulation tools handle this problem. However, it's possible to implement AST traversal using iteration instead of recursion to work around limited call stack space. This version of esbuild implements this code transformation for esbuild's JavaScript parser and printer, so esbuild's WebAssembly implementation is now able to process the `grapheme-splitter` package (at least when compiled with Go 1.20.0 and run with node's WebAssembly implementation).
  3262  
  3263  ## 0.17.7
  3264  
  3265  * Change esbuild's parsing of TypeScript instantiation expressions to match TypeScript 4.8+ ([#2907](https://github.com/evanw/esbuild/issues/2907))
  3266  
  3267      This release updates esbuild's implementation of instantiation expression erasure to match [microsoft/TypeScript#49353](https://github.com/microsoft/TypeScript/pull/49353). The new rules are as follows (copied from TypeScript's PR description):
  3268  
  3269      > When a potential type argument list is followed by
  3270      >
  3271      > * a line break,
  3272      > * an `(` token,
  3273      > * a template literal string, or
  3274      > * any token except `<` or `>` that isn't the start of an expression,
  3275      >
  3276      > we consider that construct to be a type argument list. Otherwise we consider the construct to be a `<` relational expression followed by a `>` relational expression.
  3277  
  3278  * Ignore `sideEffects: false` for imported CSS files ([#1370](https://github.com/evanw/esbuild/issues/1370), [#1458](https://github.com/evanw/esbuild/pull/1458), [#2905](https://github.com/evanw/esbuild/issues/2905))
  3279  
  3280      This release ignores the `sideEffects` annotation in `package.json` for CSS files that are imported into JS files using esbuild's `css` loader. This means that these CSS files are no longer be tree-shaken.
  3281  
  3282      Importing CSS into JS causes esbuild to automatically create a CSS entry point next to the JS entry point containing the bundled CSS. Previously packages that specified some form of `"sideEffects": false` could potentially cause esbuild to consider one or more of the JS files on the import path to the CSS file to be side-effect free, which would result in esbuild removing that CSS file from the bundle. This was problematic because the removal of that CSS is outwardly observable, since all CSS is global, so it was incorrect for previous versions of esbuild to tree-shake CSS files imported into JS files.
  3283  
  3284  * Add constant folding for certain additional equality cases ([#2394](https://github.com/evanw/esbuild/issues/2394), [#2895](https://github.com/evanw/esbuild/issues/2895))
  3285  
  3286      This release adds constant folding for expressions similar to the following:
  3287  
  3288      ```js
  3289      // Original input
  3290      console.log(
  3291        null === 'foo',
  3292        null === undefined,
  3293        null == undefined,
  3294        false === 0,
  3295        false == 0,
  3296        1 === true,
  3297        1 == true,
  3298      )
  3299  
  3300      // Old output
  3301      console.log(
  3302        null === "foo",
  3303        null === void 0,
  3304        null == void 0,
  3305        false === 0,
  3306        false == 0,
  3307        1 === true,
  3308        1 == true
  3309      );
  3310  
  3311      // New output
  3312      console.log(
  3313        false,
  3314        false,
  3315        true,
  3316        false,
  3317        true,
  3318        false,
  3319        true
  3320      );
  3321      ```
  3322  
  3323  ## 0.17.6
  3324  
  3325  * Fix a CSS parser crash on invalid CSS ([#2892](https://github.com/evanw/esbuild/issues/2892))
  3326  
  3327      Previously the following invalid CSS caused esbuild's parser to crash:
  3328  
  3329      ```css
  3330      @media screen
  3331      ```
  3332  
  3333      The crash was caused by trying to construct a helpful error message assuming that there was an opening `{` token, which is not the case here. This release fixes the crash.
  3334  
  3335  * Inline TypeScript enums that are referenced before their declaration
  3336  
  3337      Previously esbuild inlined enums within a TypeScript file from top to bottom, which meant that references to TypeScript enum members were only inlined within the same file if they came after the enum declaration. With this release, esbuild will now inline enums even when they are referenced before they are declared:
  3338  
  3339      ```ts
  3340      // Original input
  3341      export const foo = () => Foo.FOO
  3342      const enum Foo { FOO = 0 }
  3343  
  3344      // Old output (with --tree-shaking=true)
  3345      export const foo = () => Foo.FOO;
  3346      var Foo = /* @__PURE__ */ ((Foo2) => {
  3347        Foo2[Foo2["FOO"] = 0] = "FOO";
  3348        return Foo2;
  3349      })(Foo || {});
  3350  
  3351      // New output (with --tree-shaking=true)
  3352      export const foo = () => 0 /* FOO */;
  3353      ```
  3354  
  3355      This makes esbuild's TypeScript output smaller and faster when processing code that does this. I noticed this issue when I ran the TypeScript compiler's source code through esbuild's bundler. Now that the TypeScript compiler is going to be bundled with esbuild in the upcoming TypeScript 5.0 release, improvements like this will also improve the TypeScript compiler itself!
  3356  
  3357  * Fix esbuild installation on Arch Linux ([#2785](https://github.com/evanw/esbuild/issues/2785), [#2812](https://github.com/evanw/esbuild/issues/2812), [#2865](https://github.com/evanw/esbuild/issues/2865))
  3358  
  3359      Someone made an unofficial `esbuild` package for Linux that adds the `ESBUILD_BINARY_PATH=/usr/bin/esbuild` environment variable to the user's default environment. This breaks all npm installations of esbuild for users with this unofficial Linux package installed, which has affected many people. Most (all?) people who encounter this problem haven't even installed this unofficial package themselves; instead it was installed for them as a dependency of another Linux package. The problematic change to add the `ESBUILD_BINARY_PATH` environment variable was reverted in the latest version of this unofficial package. However, old versions of this unofficial package are still there and will be around forever. With this release, `ESBUILD_BINARY_PATH` is now ignored by esbuild's install script when it's set to the value `/usr/bin/esbuild`. This should unbreak using npm to install `esbuild` in these problematic Linux environments.
  3360  
  3361      Note: The `ESBUILD_BINARY_PATH` variable is an undocumented way to override the location of esbuild's binary when esbuild's npm package is installed, which is necessary to substitute your own locally-built esbuild binary when debugging esbuild's npm package. It's only meant for very custom situations and should absolutely not be forced on others by default, especially without their knowledge. I may remove the code in esbuild's installer that reads `ESBUILD_BINARY_PATH` in the future to prevent these kinds of issues. It will unfortunately make debugging esbuild harder. If `ESBUILD_BINARY_PATH` is ever removed, it will be done in a "breaking change" release.
  3362  
  3363  ## 0.17.5
  3364  
  3365  * Parse `const` type parameters from TypeScript 5.0
  3366  
  3367      The TypeScript 5.0 beta announcement adds [`const` type parameters](https://devblogs.microsoft.com/typescript/announcing-typescript-5-0-beta/#const-type-parameters) to the language. You can now add the `const` modifier on a type parameter of a function, method, or class like this:
  3368  
  3369      ```ts
  3370      type HasNames = { names: readonly string[] };
  3371      const getNamesExactly = <const T extends HasNames>(arg: T): T["names"] => arg.names;
  3372      const names = getNamesExactly({ names: ["Alice", "Bob", "Eve"] });
  3373      ```
  3374  
  3375      The type of `names` in the above example is `readonly ["Alice", "Bob", "Eve"]`. Marking the type parameter as `const` behaves as if you had written `as const` at every use instead. The above code is equivalent to the following TypeScript, which was the only option before TypeScript 5.0:
  3376  
  3377      ```ts
  3378      type HasNames = { names: readonly string[] };
  3379      const getNamesExactly = <T extends HasNames>(arg: T): T["names"] => arg.names;
  3380      const names = getNamesExactly({ names: ["Alice", "Bob", "Eve"] } as const);
  3381      ```
  3382  
  3383      You can read [the announcement](https://devblogs.microsoft.com/typescript/announcing-typescript-5-0-beta/#const-type-parameters) for more information.
  3384  
  3385  * Make parsing generic `async` arrow functions more strict in `.tsx` files
  3386  
  3387      Previously esbuild's TypeScript parser incorrectly accepted the following code as valid:
  3388  
  3389      ```tsx
  3390      let fn = async <T> () => {};
  3391      ```
  3392  
  3393      The official TypeScript parser rejects this code because it thinks it's the identifier `async` followed by a JSX element starting with `<T>`. So with this release, esbuild will now reject this syntax in `.tsx` files too. You'll now have to add a comma after the type parameter to get generic arrow functions like this to parse in `.tsx` files:
  3394  
  3395      ```tsx
  3396      let fn = async <T,> () => {};
  3397      ```
  3398  
  3399  * Allow the `in` and `out` type parameter modifiers on class expressions
  3400  
  3401      TypeScript 4.7 added the `in` and `out` modifiers on the type parameters of classes, interfaces, and type aliases. However, while TypeScript supported them on both class expressions and class statements, previously esbuild only supported them on class statements due to an oversight. This release now allows these modifiers on class expressions too:
  3402  
  3403      ```ts
  3404      declare let Foo: any;
  3405      Foo = class <in T> { };
  3406      Foo = class <out T> { };
  3407      ```
  3408  
  3409  * Update `enum` constant folding for TypeScript 5.0
  3410  
  3411      TypeScript 5.0 contains an [updated definition of what it considers a constant expression](https://github.com/microsoft/TypeScript/pull/50528):
  3412  
  3413      > An expression is considered a *constant expression* if it is
  3414      >
  3415      > * a number or string literal,
  3416      > * a unary `+`, `-`, or `~` applied to a numeric constant expression,
  3417      > * a binary `+`, `-`, `*`, `/`, `%`, `**`, `<<`, `>>`, `>>>`, `|`, `&`, `^` applied to two numeric constant expressions,
  3418      > * a binary `+` applied to two constant expressions whereof at least one is a string,
  3419      > * a template expression where each substitution expression is a constant expression,
  3420      > * a parenthesized constant expression,
  3421      > * a dotted name (e.g. `x.y.z`) that references a `const` variable with a constant expression initializer and no type annotation,
  3422      > * a dotted name that references an enum member with an enum literal type, or
  3423      > * a dotted name indexed by a string literal (e.g. `x.y["z"]`) that references an enum member with an enum literal type.
  3424  
  3425      This impacts esbuild's implementation of TypeScript's `const enum` feature. With this release, esbuild will now attempt to follow these new rules. For example, you can now initialize an `enum` member with a template literal expression that contains a numeric constant:
  3426  
  3427      ```ts
  3428      // Original input
  3429      const enum Example {
  3430        COUNT = 100,
  3431        ERROR = `Expected ${COUNT} items`,
  3432      }
  3433      console.log(
  3434        Example.COUNT,
  3435        Example.ERROR,
  3436      )
  3437  
  3438      // Old output (with --tree-shaking=true)
  3439      var Example = /* @__PURE__ */ ((Example2) => {
  3440        Example2[Example2["COUNT"] = 100] = "COUNT";
  3441        Example2[Example2["ERROR"] = `Expected ${100 /* COUNT */} items`] = "ERROR";
  3442        return Example2;
  3443      })(Example || {});
  3444      console.log(
  3445        100 /* COUNT */,
  3446        Example.ERROR
  3447      );
  3448  
  3449      // New output (with --tree-shaking=true)
  3450      console.log(
  3451        100 /* COUNT */,
  3452        "Expected 100 items" /* ERROR */
  3453      );
  3454      ```
  3455  
  3456      These rules are not followed exactly due to esbuild's limitations. The rule about dotted references to `const` variables is not followed both because esbuild's enum processing is done in an isolated module setting and because doing so would potentially require esbuild to use a type system, which it doesn't have. For example:
  3457  
  3458      ```ts
  3459      // The TypeScript compiler inlines this but esbuild doesn't:
  3460      declare const x = 'foo'
  3461      const enum Foo { X = x }
  3462      console.log(Foo.X)
  3463      ```
  3464  
  3465      Also, the rule that requires converting numbers to a string currently only followed for 32-bit signed integers and non-finite numbers. This is done to avoid accidentally introducing a bug if esbuild's number-to-string operation doesn't exactly match the behavior of a real JavaScript VM. Currently esbuild's number-to-string constant folding is conservative for safety.
  3466  
  3467  * Forbid definite assignment assertion operators on class methods
  3468  
  3469      In TypeScript, class methods can use the `?` optional property operator but not the `!` definite assignment assertion operator (while class fields can use both):
  3470  
  3471      ```ts
  3472      class Foo {
  3473        // These are valid TypeScript
  3474        a?
  3475        b!
  3476        x?() {}
  3477  
  3478        // This is invalid TypeScript
  3479        y!() {}
  3480      }
  3481      ```
  3482  
  3483      Previously esbuild incorrectly allowed the definite assignment assertion operator with class methods. This will no longer be allowed starting with this release.
  3484  
  3485  ## 0.17.4
  3486  
  3487  * Implement HTTP `HEAD` requests in serve mode ([#2851](https://github.com/evanw/esbuild/issues/2851))
  3488  
  3489      Previously esbuild's serve mode only responded to HTTP `GET` requests. With this release, esbuild's serve mode will also respond to HTTP `HEAD` requests, which are just like HTTP `GET` requests except that the body of the response is omitted.
  3490  
  3491  * Permit top-level await in dead code branches ([#2853](https://github.com/evanw/esbuild/issues/2853))
  3492  
  3493      Adding top-level await to a file has a few consequences with esbuild:
  3494  
  3495      1. It causes esbuild to assume that the input module format is ESM, since top-level await is only syntactically valid in ESM. That prevents you from using `module` and `exports` for exports and also enables strict mode, which disables certain syntax and changes how function hoisting works (among other things).
  3496      2. This will cause esbuild to fail the build if either top-level await isn't supported by your language target (e.g. it's not supported in ES2021) or if top-level await isn't supported by the chosen output format (e.g. it's not supported with CommonJS).
  3497      3. Doing this will prevent you from using `require()` on this file or on any file that imports this file (even indirectly), since the `require()` function doesn't return a promise and so can't represent top-level await.
  3498  
  3499      This release relaxes these rules slightly: rules 2 and 3 will now no longer apply when esbuild has identified the code branch as dead code, such as when it's behind an `if (false)` check. This should make it possible to use esbuild to convert code into different output formats that only uses top-level await conditionally. This release does not relax rule 1. Top-level await will still cause esbuild to unconditionally consider the input module format to be ESM, even when the top-level `await` is in a dead code branch. This is necessary because whether the input format is ESM or not affects the whole file, not just the dead code branch.
  3500  
  3501  * Fix entry points where the entire file name is the extension ([#2861](https://github.com/evanw/esbuild/issues/2861))
  3502  
  3503      Previously if you passed esbuild an entry point where the file extension is the entire file name, esbuild would use the parent directory name to derive the name of the output file. For example, if you passed esbuild a file `./src/.ts` then the output name would be `src.js`. This bug happened because esbuild first strips the file extension to get `./src/` and then joins the path with the working directory to get the absolute path (e.g. `join("/working/dir", "./src/")` gives `/working/dir/src`). However, the join operation also canonicalizes the path which strips the trailing `/`. Later esbuild uses the "base name" operation to extract the name of the output file. Since there is no trailing `/`, esbuild returns `"src"` as the base name instead of `""`, which causes esbuild to incorrectly include the directory name in the output file name. This release fixes this bug by deferring the stripping of the file extension until after all path manipulations have been completed. So now the file `./src/.ts` will generate an output file named `.js`.
  3504  
  3505  * Support replacing property access expressions with inject
  3506  
  3507      At a high level, this change means the `inject` feature can now replace all of the same kinds of names as the `define` feature. So `inject` is basically now a more powerful version of `define`, instead of previously only being able to do some of the things that `define` could do.
  3508  
  3509      Soem background is necessary to understand this change if you aren't already familiar with the `inject` feature. The `inject` feature lets you replace references to global variable with a shim. It works like this:
  3510  
  3511      1. Put the shim in its own file
  3512      2. Export the shim as the name of the global variable you intend to replace
  3513      3. Pass the file to esbuild using the `inject` feature
  3514  
  3515      For example, if you inject the following file using `--inject:./injected.js`:
  3516  
  3517      ```js
  3518      // injected.js
  3519      let processShim = { cwd: () => '/' }
  3520      export { processShim as process }
  3521      ```
  3522  
  3523      Then esbuild will replace all references to `process` with the `processShim` variable, which will cause `process.cwd()` to return `'/'`. This feature is sort of abusing the ESM export alias syntax to specify the mapping of global variables to shims. But esbuild works this way because using this syntax for that purpose is convenient and terse.
  3524  
  3525      However, if you wanted to replace a property access expression, the process was more complicated and not as nice. You would have to:
  3526  
  3527      1. Put the shim in its own file
  3528      2. Export the shim as some random name
  3529      3. Pass the file to esbuild using the `inject` feature
  3530      4. Use esbuild's `define` feature to map the property access expression to the random name you made in step 2
  3531  
  3532      For example, if you inject the following file using `--inject:./injected2.js --define:process.cwd=someRandomName`:
  3533  
  3534      ```js
  3535      // injected2.js
  3536      let cwdShim = () => '/'
  3537      export { cwdShim as someRandomName }
  3538      ```
  3539  
  3540      Then esbuild will replace all references to `process.cwd` with the `cwdShim` variable, which will also cause `process.cwd()` to return `'/'` (but which this time will not mess with other references to `process`, which might be desirable).
  3541  
  3542      With this release, using the inject feature to replace a property access expression is now as simple as using it to replace an identifier. You can now use JavaScript's ["arbitrary moduleĀ namespace identifierĀ names"](https://github.com/tc39/ecma262/pull/2154) feature to specify the property access expression directly using a string literal. For example, if you inject the following file using `--inject:./injected3.js`:
  3543  
  3544      ```js
  3545      // injected3.js
  3546      let cwdShim = () => '/'
  3547      export { cwdShim as 'process.cwd' }
  3548      ```
  3549  
  3550      Then esbuild will now replace all references to `process.cwd` with the `cwdShim` variable, which will also cause `process.cwd()` to return `'/'` (but which will also not mess with other references to `process`).
  3551  
  3552      In addition to inserting a shim for a global variable that doesn't exist, another use case is replacing references to static methods on global objects with cached versions to both minify them better and to make access to them potentially faster. For example:
  3553  
  3554      ```js
  3555      // Injected file
  3556      let cachedMin = Math.min
  3557      let cachedMax = Math.max
  3558      export {
  3559        cachedMin as 'Math.min',
  3560        cachedMax as 'Math.max',
  3561      }
  3562  
  3563      // Original input
  3564      function clampRGB(r, g, b) {
  3565        return {
  3566          r: Math.max(0, Math.min(1, r)),
  3567          g: Math.max(0, Math.min(1, g)),
  3568          b: Math.max(0, Math.min(1, b)),
  3569        }
  3570      }
  3571  
  3572      // Old output (with --minify)
  3573      function clampRGB(a,t,m){return{r:Math.max(0,Math.min(1,a)),g:Math.max(0,Math.min(1,t)),b:Math.max(0,Math.min(1,m))}}
  3574  
  3575      // New output (with --minify)
  3576      var a=Math.min,t=Math.max;function clampRGB(h,M,m){return{r:t(0,a(1,h)),g:t(0,a(1,M)),b:t(0,a(1,m))}}
  3577      ```
  3578  
  3579  ## 0.17.3
  3580  
  3581  * Fix incorrect CSS minification for certain rules ([#2838](https://github.com/evanw/esbuild/issues/2838))
  3582  
  3583      Certain rules such as `@media` could previously be minified incorrectly. Due to a typo in the duplicate rule checker, two known `@`-rules that share the same hash code were incorrectly considered to be equal. This problem was made worse by the rule hashing code considering two unknown declarations (such as CSS variables) to have the same hash code, which also isn't optimal from a performance perspective. Both of these issues have been fixed:
  3584  
  3585      ```css
  3586      /* Original input */
  3587      @media (prefers-color-scheme: dark) { body { --VAR-1: #000; } }
  3588      @media (prefers-color-scheme: dark) { body { --VAR-2: #000; } }
  3589  
  3590      /* Old output (with --minify) */
  3591      @media (prefers-color-scheme: dark){body{--VAR-2: #000}}
  3592  
  3593      /* New output (with --minify) */
  3594      @media (prefers-color-scheme: dark){body{--VAR-1: #000}}@media (prefers-color-scheme: dark){body{--VAR-2: #000}}
  3595      ```
  3596  
  3597  ## 0.17.2
  3598  
  3599  * Add `onDispose` to the plugin API ([#2140](https://github.com/evanw/esbuild/issues/2140), [#2205](https://github.com/evanw/esbuild/issues/2205))
  3600  
  3601      If your plugin wants to perform some cleanup after it's no longer going to be used, you can now use the `onDispose` API to register a callback for cleanup-related tasks. For example, if a plugin starts a long-running child process then it may want to terminate that process when the plugin is discarded. Previously there was no way to do this. Here's an example:
  3602  
  3603      ```js
  3604      let examplePlugin = {
  3605        name: 'example',
  3606        setup(build) {
  3607          build.onDispose(() => {
  3608            console.log('This plugin is no longer used')
  3609          })
  3610        },
  3611      }
  3612      ```
  3613  
  3614      These `onDispose` callbacks will be called after every `build()` call regardless of whether the build failed or not as well as after the first `dispose()` call on a given build context.
  3615  
  3616  ## 0.17.1
  3617  
  3618  * Make it possible to cancel a build ([#2725](https://github.com/evanw/esbuild/issues/2725))
  3619  
  3620      The context object introduced in version 0.17.0 has a new `cancel()` method. You can use it to cancel a long-running build so that you can start a new one without needing to wait for the previous one to finish. When this happens, the previous build should always have at least one error and have no output files (i.e. it will be a failed build).
  3621  
  3622      Using it might look something like this:
  3623  
  3624      * JS:
  3625  
  3626          ```js
  3627          let ctx = await esbuild.context({
  3628            // ...
  3629          })
  3630  
  3631          let rebuildWithTimeLimit = timeLimit => {
  3632            let timeout = setTimeout(() => ctx.cancel(), timeLimit)
  3633            return ctx.rebuild().finally(() => clearTimeout(timeout))
  3634          }
  3635  
  3636          let build = await rebuildWithTimeLimit(500)
  3637          ```
  3638  
  3639      * Go:
  3640  
  3641          ```go
  3642          ctx, err := api.Context(api.BuildOptions{
  3643            // ...
  3644          })
  3645          if err != nil {
  3646            return
  3647          }
  3648  
  3649          rebuildWithTimeLimit := func(timeLimit time.Duration) api.BuildResult {
  3650            t := time.NewTimer(timeLimit)
  3651            go func() {
  3652              <-t.C
  3653              ctx.Cancel()
  3654            }()
  3655            result := ctx.Rebuild()
  3656            t.Stop()
  3657            return result
  3658          }
  3659  
  3660          build := rebuildWithTimeLimit(500 * time.Millisecond)
  3661          ```
  3662  
  3663      This API is a quick implementation and isn't maximally efficient, so the build may continue to do some work for a little bit before stopping. For example, I have added stop points between each top-level phase of the bundler and in the main module graph traversal loop, but I haven't added fine-grained stop points within the internals of the linker. How quickly esbuild stops can be improved in future releases. This means you'll want to wait for `cancel()` and/or the previous `rebuild()` to finish (i.e. await the returned promise in JavaScript) before starting a new build, otherwise `rebuild()` will give you the just-canceled build that still hasn't ended yet. Note that `onEnd` callbacks will still be run regardless of whether or not the build was canceled.
  3664  
  3665  * Fix server-sent events without `servedir` ([#2827](https://github.com/evanw/esbuild/issues/2827))
  3666  
  3667      The server-sent events for live reload were incorrectly using `servedir` to calculate the path to modified output files. This means events couldn't be sent when `servedir` wasn't specified. This release uses the internal output directory (which is always present) instead of `servedir` (which might be omitted), so live reload should now work when `servedir` is not specified.
  3668  
  3669  * Custom entry point output paths now work with the `copy` loader ([#2828](https://github.com/evanw/esbuild/issues/2828))
  3670  
  3671      Entry points can optionally provide custom output paths to change the path of the generated output file. For example, `esbuild foo=abc.js bar=xyz.js --outdir=out` generates the files `out/foo.js` and `out/bar.js`. However, this previously didn't work when using the `copy` loader due to an oversight. This bug has been fixed. For example, you can now do `esbuild foo=abc.html bar=xyz.html --outdir=out --loader:.html=copy` to generate the files `out/foo.html` and `out/bar.html`.
  3672  
  3673  * The JS API can now take an array of objects ([#2828](https://github.com/evanw/esbuild/issues/2828))
  3674  
  3675      Previously it was not possible to specify two entry points with the same custom output path using the JS API, although it was possible to do this with the Go API and the CLI. This will not cause a collision if both entry points use different extensions (e.g. if one uses `.js` and the other uses `.css`). You can now pass the JS API an array of objects to work around this API limitation:
  3676  
  3677      ```js
  3678      // The previous API didn't let you specify duplicate output paths
  3679      let result = await esbuild.build({
  3680        entryPoints: {
  3681          // This object literal contains a duplicate key, so one is ignored
  3682          'dist': 'foo.js',
  3683          'dist': 'bar.css',
  3684        },
  3685      })
  3686  
  3687      // You can now specify duplicate output paths as an array of objects
  3688      let result = await esbuild.build({
  3689        entryPoints: [
  3690          { in: 'foo.js', out: 'dist' },
  3691          { in: 'bar.css', out: 'dist' },
  3692        ],
  3693      })
  3694      ```
  3695  
  3696  ## 0.17.0
  3697  
  3698  **This release deliberately contains backwards-incompatible changes.** To avoid automatically picking up releases like this, you should either be pinning the exact version of `esbuild` in your `package.json` file (recommended) or be using a version range syntax that only accepts patch upgrades such as `^0.16.0` or `~0.16.0`. See npm's documentation about [semver](https://docs.npmjs.com/cli/v6/using-npm/semver/) for more information.
  3699  
  3700  At a high level, the breaking changes in this release fix some long-standing issues with the design of esbuild's incremental, watch, and serve APIs. This release also introduces some exciting new features such as live reloading. In detail:
  3701  
  3702  * Move everything related to incremental builds to a new `context` API ([#1037](https://github.com/evanw/esbuild/issues/1037), [#1606](https://github.com/evanw/esbuild/issues/1606), [#2280](https://github.com/evanw/esbuild/issues/2280), [#2418](https://github.com/evanw/esbuild/issues/2418))
  3703  
  3704      This change removes the `incremental` and `watch` options as well as the `serve()` method, and introduces a new `context()` method. The context method takes the same arguments as the `build()` method but only validates its arguments and does not do an initial build. Instead, builds can be triggered using the `rebuild()`, `watch()`, and `serve()` methods on the returned context object. The new context API looks like this:
  3705  
  3706      ```js
  3707      // Create a context for incremental builds
  3708      const context = await esbuild.context({
  3709        entryPoints: ['app.ts'],
  3710        bundle: true,
  3711      })
  3712  
  3713      // Manually do an incremental build
  3714      const result = await context.rebuild()
  3715  
  3716      // Enable watch mode
  3717      await context.watch()
  3718  
  3719      // Enable serve mode
  3720      await context.serve()
  3721  
  3722      // Dispose of the context
  3723      context.dispose()
  3724      ```
  3725  
  3726      The switch to the context API solves a major issue with the previous API which is that if the initial build fails, a promise is thrown in JavaScript which prevents you from accessing the returned result object. That prevented you from setting up long-running operations such as watch mode when the initial build contained errors. It also makes tearing down incremental builds simpler as there is now a single way to do it instead of three separate ways.
  3727  
  3728      In addition, this release also makes some subtle changes to how incremental builds work. Previously every call to `rebuild()` started a new build. If you weren't careful, then builds could actually overlap. This doesn't cause any problems with esbuild itself, but could potentially cause problems with plugins (esbuild doesn't even give you a way to identify which overlapping build a given plugin callback is running on). Overlapping builds also arguably aren't useful, or at least aren't useful enough to justify the confusion and complexity that they bring. With this release, there is now only ever a single active build per context. Calling `rebuild()` before the previous rebuild has finished now "merges" with the existing rebuild instead of starting a new build.
  3729  
  3730  * Allow using `watch` and `serve` together ([#805](https://github.com/evanw/esbuild/issues/805), [#1650](https://github.com/evanw/esbuild/issues/1650), [#2576](https://github.com/evanw/esbuild/issues/2576))
  3731  
  3732      Previously it was not possible to use watch mode and serve mode together. The rationale was that watch mode is one way of automatically rebuilding your project and serve mode is another (since serve mode automatically rebuilds on every request). However, people want to combine these two features to make "live reloading" where the browser automatically reloads the page when files are changed on the file system.
  3733  
  3734      This release now allows you to use these two features together. You can only call the `watch()` and `serve()` APIs once each per context, but if you call them together on the same context then esbuild will automatically rebuild both when files on the file system are changed *and* when the server serves a request.
  3735  
  3736  * Support "live reloading" through server-sent events ([#802](https://github.com/evanw/esbuild/issues/802))
  3737  
  3738      [Server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events) are a simple way to pass one-directional messages asynchronously from the server to the client. Serve mode now provides a `/esbuild` endpoint with an `change` event that triggers every time esbuild's output changes. So you can now implement simple "live reloading" (i.e. reloading the page when a file is edited and saved) like this:
  3739  
  3740      ```js
  3741      new EventSource('/esbuild').addEventListener('change', () => location.reload())
  3742      ```
  3743  
  3744      The event payload is a JSON object with the following shape:
  3745  
  3746      ```ts
  3747      interface ChangeEvent {
  3748        added: string[]
  3749        removed: string[]
  3750        updated: string[]
  3751      }
  3752      ```
  3753  
  3754      This JSON should also enable more complex live reloading scenarios. For example, the following code hot-swaps changed CSS `<link>` tags in place without reloading the page (but still reloads when there are other types of changes):
  3755  
  3756      ```js
  3757      new EventSource('/esbuild').addEventListener('change', e => {
  3758        const { added, removed, updated } = JSON.parse(e.data)
  3759        if (!added.length && !removed.length && updated.length === 1) {
  3760          for (const link of document.getElementsByTagName("link")) {
  3761            const url = new URL(link.href)
  3762            if (url.host === location.host && url.pathname === updated[0]) {
  3763              const next = link.cloneNode()
  3764              next.href = updated[0] + '?' + Math.random().toString(36).slice(2)
  3765              next.onload = () => link.remove()
  3766              link.parentNode.insertBefore(next, link.nextSibling)
  3767              return
  3768            }
  3769          }
  3770        }
  3771        location.reload()
  3772      })
  3773      ```
  3774  
  3775      Implementing live reloading like this has a few known caveats:
  3776  
  3777      * These events only trigger when esbuild's output changes. They do not trigger when files unrelated to the build being watched are changed. If your HTML file references other files that esbuild doesn't know about and those files are changed, you can either manually reload the page or you can implement your own live reloading infrastructure instead of using esbuild's built-in behavior.
  3778  
  3779      * The `EventSource` API is supposed to automatically reconnect for you. However, there's a bug in Firefox that breaks this if the server is ever temporarily unreachable: https://bugzilla.mozilla.org/show_bug.cgi?id=1809332. Workarounds are to use any other browser, to manually reload the page if this happens, or to write more complicated code that manually closes and re-creates the `EventSource` object if there is a connection error. I'm hopeful that this bug will be fixed.
  3780  
  3781      * Browser vendors have decided to not implement HTTP/2 without TLS. This means that each `/esbuild` event source will take up one of your precious 6 simultaneous per-domain HTTP/1.1 connections. So if you open more than six HTTP tabs that use this live-reloading technique, you will be unable to use live reloading in some of those tabs (and other things will likely also break). The workaround is to enable HTTPS, which is now possible to do in esbuild itself (see below).
  3782  
  3783  * Add built-in support for HTTPS ([#2169](https://github.com/evanw/esbuild/issues/2169))
  3784  
  3785      You can now tell esbuild's built-in development server to use HTTPS instead of HTTP. This is sometimes necessary because browser vendors have started making modern web features unavailable to HTTP websites. Previously you had to put a proxy in front of esbuild to enable HTTPS since esbuild's development server only supported HTTP. But with this release, you can now enable HTTPS with esbuild without an additional proxy.
  3786  
  3787      To enable HTTPS with esbuild:
  3788  
  3789      1. Generate a self-signed certificate. There are many ways to do this. Here's one way, assuming you have `openssl` installed:
  3790  
  3791          ```
  3792          openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 9999 -nodes -subj /CN=127.0.0.1
  3793          ```
  3794  
  3795      2. Add `--keyfile=key.pem` and `--certfile=cert.pem` to your esbuild development server command
  3796      3. Click past the scary warning in your browser when you load your page
  3797  
  3798      If you have more complex needs than this, you can still put a proxy in front of esbuild and use that for HTTPS instead. Note that if you see the message "Client sent an HTTP request to an HTTPS server" when you load your page, then you are using the incorrect protocol. Replace `http://` with `https://` in your browser's URL bar.
  3799  
  3800      Keep in mind that esbuild's HTTPS support has nothing to do with security. The only reason esbuild now supports HTTPS is because browsers have made it impossible to do local development with certain modern web features without jumping through these extra hoops. *Please do not use esbuild's development server for anything that needs to be secure.* It's only intended for local development and no considerations have been made for production environments whatsoever.
  3801  
  3802  * Better support copying `index.html` into the output directory ([#621](https://github.com/evanw/esbuild/issues/621), [#1771](https://github.com/evanw/esbuild/issues/1771))
  3803  
  3804      Right now esbuild only supports JavaScript and CSS as first-class content types. Previously this meant that if you were building a website with a HTML file, a JavaScript file, and a CSS file, you could use esbuild to build the JavaScript file and the CSS file into the output directory but not to copy the HTML file into the output directory. You needed a separate `cp` command for that.
  3805  
  3806      Or so I thought. It turns out that the `copy` loader added in version 0.14.44 of esbuild is sufficient to have esbuild copy the HTML file into the output directory as well. You can add something like `index.html --loader:.html=copy` and esbuild will copy `index.html` into the output directory for you. The benefits of this are a) you don't need a separate `cp` command and b) the `index.html` file will automatically be re-copied when esbuild is in watch mode and the contents of `index.html` are edited. This also goes for other non-HTML file types that you might want to copy.
  3807  
  3808      This pretty much already worked. The one thing that didn't work was that esbuild's built-in development server previously only supported implicitly loading `index.html` (e.g. loading `/about/index.html` when you visit `/about/`) when `index.html` existed on the file system. Previously esbuild didn't support implicitly loading `index.html` if it was a build result. That bug has been fixed with this release so it should now be practical to use the `copy` loader to do this.
  3809  
  3810  * Fix `onEnd` not being called in serve mode ([#1384](https://github.com/evanw/esbuild/issues/1384))
  3811  
  3812      Previous releases had a bug where plugin `onEnd` callbacks weren't called when using the top-level `serve()` API. This API no longer exists and the internals have been reimplemented such that `onEnd` callbacks should now always be called at the end of every build.
  3813  
  3814  * Incremental builds now write out build results differently ([#2104](https://github.com/evanw/esbuild/issues/2104))
  3815  
  3816      Previously build results were always written out after every build. However, this could cause the output directory to fill up with files from old builds if code splitting was enabled, since the file names for code splitting chunks contain content hashes and old files were not deleted.
  3817  
  3818      With this release, incremental builds in esbuild will now delete old output files from previous builds that are no longer relevant. Subsequent incremental builds will also no longer overwrite output files whose contents haven't changed since the previous incremental build.
  3819  
  3820  * The `onRebuild` watch mode callback was removed ([#980](https://github.com/evanw/esbuild/issues/980), [#2499](https://github.com/evanw/esbuild/issues/2499))
  3821  
  3822      Previously watch mode accepted an `onRebuild` callback which was called whenever watch mode rebuilt something. This was not great in practice because if you are running code after a build, you likely want that code to run after every build, not just after the second and subsequent builds. This release removes option to provide an `onRebuild` callback. You can create a plugin with an `onEnd` callback instead. The `onEnd` plugin API already exists, and is a way to run some code after every build.
  3823  
  3824  * You can now return errors from `onEnd` ([#2625](https://github.com/evanw/esbuild/issues/2625))
  3825  
  3826      It's now possible to add additional build errors and/or warnings to the current build from within your `onEnd` callback by returning them in an array. This is identical to how the `onStart` callback already works. The evaluation of `onEnd` callbacks have been moved around a bit internally to make this possible.
  3827  
  3828      Note that the build will only fail (i.e. reject the promise) if the additional errors are returned from `onEnd`. Adding additional errors to the result object that's passed to `onEnd` won't affect esbuild's behavior at all.
  3829  
  3830  * Print URLs and ports from the Go and JS APIs ([#2393](https://github.com/evanw/esbuild/issues/2393))
  3831  
  3832      Previously esbuild's CLI printed out something like this when serve mode is active:
  3833  
  3834      ```
  3835       > Local:   http://127.0.0.1:8000/
  3836       > Network: http://192.168.0.1:8000/
  3837      ```
  3838  
  3839      The CLI still does this, but now the JS and Go serve mode APIs will do this too. This only happens when the log level is set to `verbose`, `debug`, or `info` but not when it's set to `warning`, `error`, or `silent`.
  3840  
  3841  ### Upgrade guide for existing code:
  3842  
  3843  * Rebuild (a.k.a. incremental build):
  3844  
  3845      Before:
  3846  
  3847      ```js
  3848      const result = await esbuild.build({ ...buildOptions, incremental: true });
  3849      builds.push(result);
  3850      for (let i = 0; i < 4; i++) builds.push(await result.rebuild());
  3851      await result.rebuild.dispose(); // To free resources
  3852      ```
  3853  
  3854      After:
  3855  
  3856      ```js
  3857      const ctx = await esbuild.context(buildOptions);
  3858      for (let i = 0; i < 5; i++) builds.push(await ctx.rebuild());
  3859      await ctx.dispose(); // To free resources
  3860      ```
  3861  
  3862      Previously the first build was done differently than subsequent builds. Now both the first build and subsequent builds are done using the same API.
  3863  
  3864  * Serve:
  3865  
  3866      Before:
  3867  
  3868      ```js
  3869      const serveResult = await esbuild.serve(serveOptions, buildOptions);
  3870      ...
  3871      serveResult.stop(); await serveResult.wait; // To free resources
  3872      ```
  3873  
  3874      After:
  3875  
  3876      ```js
  3877      const ctx = await esbuild.context(buildOptions);
  3878      const serveResult = await ctx.serve(serveOptions);
  3879      ...
  3880      await ctx.dispose(); // To free resources
  3881      ```
  3882  
  3883  * Watch:
  3884  
  3885      Before:
  3886  
  3887      ```js
  3888      const result = await esbuild.build({ ...buildOptions, watch: true });
  3889      ...
  3890      result.stop(); // To free resources
  3891      ```
  3892  
  3893      After:
  3894  
  3895      ```js
  3896      const ctx = await esbuild.context(buildOptions);
  3897      await ctx.watch();
  3898      ...
  3899      await ctx.dispose(); // To free resources
  3900      ```
  3901  
  3902  * Watch with `onRebuild`:
  3903  
  3904      Before:
  3905  
  3906      ```js
  3907      const onRebuild = (error, result) => {
  3908        if (error) console.log('subsequent build:', error);
  3909        else console.log('subsequent build:', result);
  3910      };
  3911      try {
  3912        const result = await esbuild.build({ ...buildOptions, watch: { onRebuild } });
  3913        console.log('first build:', result);
  3914        ...
  3915        result.stop(); // To free resources
  3916      } catch (error) {
  3917        console.log('first build:', error);
  3918      }
  3919      ```
  3920  
  3921      After:
  3922  
  3923      ```js
  3924      const plugins = [{
  3925        name: 'my-plugin',
  3926        setup(build) {
  3927          let count = 0;
  3928          build.onEnd(result => {
  3929            if (count++ === 0) console.log('first build:', result);
  3930            else console.log('subsequent build:', result);
  3931          });
  3932        },
  3933      }];
  3934      const ctx = await esbuild.context({ ...buildOptions, plugins });
  3935      await ctx.watch();
  3936      ...
  3937      await ctx.dispose(); // To free resources
  3938      ```
  3939  
  3940      The `onRebuild` function has now been removed. The replacement is to make a plugin with an `onEnd` callback.
  3941  
  3942      Previously `onRebuild` did not fire for the first build (only for subsequent builds). This was usually problematic, so using `onEnd` instead of `onRebuild` is likely less error-prone. But if you need to emulate the old behavior of `onRebuild` that ignores the first build, then you'll need to manually count and ignore the first build in your plugin (as demonstrated above).
  3943  
  3944  Notice how all of these API calls are now done off the new context object. You should now be able to use all three kinds of incremental builds (`rebuild`, `serve`, and `watch`) together on the same context object. Also notice how calling `dispose` on the context is now the common way to discard the context and free resources in all of these situations.
  3945  
  3946  ## 0.16.17
  3947  
  3948  * Fix additional comment-related regressions ([#2814](https://github.com/evanw/esbuild/issues/2814))
  3949  
  3950      This release fixes more edge cases where the new comment preservation behavior that was added in 0.16.14 could introduce syntax errors. Specifically:
  3951  
  3952      ```js
  3953      x = () => (/* comment */ {})
  3954      for ((/* comment */ let).x of y) ;
  3955      function *f() { yield (/* comment */class {}) }
  3956      ```
  3957  
  3958      These cases caused esbuild to generate code with a syntax error in version 0.16.14 or above. These bugs have now been fixed.
  3959  
  3960  ## 0.16.16
  3961  
  3962  * Fix a regression caused by comment preservation ([#2805](https://github.com/evanw/esbuild/issues/2805))
  3963  
  3964      The new comment preservation behavior that was added in 0.16.14 introduced a regression where comments in certain locations could cause esbuild to omit certain necessary parentheses in the output. The outermost parentheses were incorrectly removed for the following syntax forms, which then introduced syntax errors:
  3965  
  3966      ```js
  3967      (/* comment */ { x: 0 }).x;
  3968      (/* comment */ function () { })();
  3969      (/* comment */ class { }).prototype;
  3970      ```
  3971  
  3972      This regression has been fixed.
  3973  
  3974  ## 0.16.15
  3975  
  3976  * Add `format` to input files in the JSON metafile data
  3977  
  3978      When `--metafile` is enabled, input files may now have an additional `format` field that indicates the export format used by this file. When present, the value will either be `cjs` for CommonJS-style exports or `esm` for ESM-style exports. This can be useful in bundle analysis.
  3979  
  3980      For example, esbuild's new [Bundle Size Analyzer](https://esbuild.github.io/analyze/) now uses this information to visualize whether ESM or CommonJS was used for each directory and file of source code (click on the CJS/ESM bar at the top).
  3981  
  3982      This information is helpful when trying to reduce the size of your bundle. Using the ESM variant of a dependency instead of the CommonJS variant always results in a faster and smaller bundle because it omits CommonJS wrappers, and also may result in better tree-shaking as it allows esbuild to perform tree-shaking at the statement level instead of the module level.
  3983  
  3984  * Fix a bundling edge case with dynamic import ([#2793](https://github.com/evanw/esbuild/issues/2793))
  3985  
  3986      This release fixes a bug where esbuild's bundler could produce incorrect output. The problematic edge case involves the entry point importing itself using a dynamic `import()` expression in an imported file, like this:
  3987  
  3988      ```js
  3989      // src/a.js
  3990      export const A = 42;
  3991  
  3992      // src/b.js
  3993      export const B = async () => (await import(".")).A
  3994  
  3995      // src/index.js
  3996      export * from "./a"
  3997      export * from "./b"
  3998      ```
  3999  
  4000  * Remove new type syntax from type declarations in the `esbuild` package ([#2798](https://github.com/evanw/esbuild/issues/2798))
  4001  
  4002      Previously you needed to use TypeScript 4.3 or newer when using the `esbuild` package from TypeScript code due to the use of a getter in an interface in `node_modules/esbuild/lib/main.d.ts`. This release removes this newer syntax to allow people with versions of TypeScript as far back as TypeScript 3.5 to use this latest version of the `esbuild` package. Here is change that was made to esbuild's type declarations:
  4003  
  4004      ```diff
  4005       export interface OutputFile {
  4006         /** "text" as bytes */
  4007         contents: Uint8Array;
  4008         /** "contents" as text (changes automatically with "contents") */
  4009      -  get text(): string;
  4010      +  readonly text: string;
  4011       }
  4012      ```
  4013  
  4014  ## 0.16.14
  4015  
  4016  * Preserve some comments in expressions ([#2721](https://github.com/evanw/esbuild/issues/2721))
  4017  
  4018      Various tools give semantic meaning to comments embedded inside of expressions. For example, Webpack and Vite have special "magic comments" that can be used to affect code splitting behavior:
  4019  
  4020      ```js
  4021      import(/* webpackChunkName: "foo" */ '../foo');
  4022      import(/* @vite-ignore */ dynamicVar);
  4023      new Worker(/* webpackChunkName: "bar" */ new URL("../bar.ts", import.meta.url));
  4024      new Worker(new URL('./path', import.meta.url), /* @vite-ignore */ dynamicOptions);
  4025      ```
  4026  
  4027      Since esbuild can be used as a preprocessor for these tools (e.g. to strip TypeScript types), it can be problematic if esbuild doesn't do additional work to try to retain these comments. Previously esbuild special-cased Webpack comments in these specific locations in the AST. But Vite would now like to use similar comments, and likely other tools as well.
  4028  
  4029      So with this release, esbuild now will attempt to preserve some comments inside of expressions in more situations than before. This behavior is mainly intended to preserve these special "magic comments" that are meant for other tools to consume, although esbuild will no longer only preserve Webpack-specific comments so it should now be tool-agnostic. There is no guarantee that all such comments will be preserved (especially when `--minify-syntax` is enabled). So this change does *not* mean that esbuild is now usable as a code formatter. In particular comment preservation is more likely to happen with leading comments than with trailing comments. You should put comments that you want to be preserved *before* the relevant expression instead of after it. Also note that this change does not retain any more statement-level comments than before (i.e. comments not embedded inside of expressions). Comment preservation is not enabled when `--minify-whitespace` is enabled (which is automatically enabled when you use `--minify`).
  4030  
  4031  ## 0.16.13
  4032  
  4033  * Publish a new bundle visualization tool
  4034  
  4035      While esbuild provides bundle metadata via the `--metafile` flag, previously esbuild left analysis of it completely up to third-party tools (well, outside of the rudimentary `--analyze` flag). However, the esbuild website now has a built-in bundle visualization tool:
  4036  
  4037      * https://esbuild.github.io/analyze/
  4038  
  4039      You can pass `--metafile` to esbuild to output bundle metadata, then upload that JSON file to this tool to visualize your bundle. This is helpful for answering questions such as:
  4040  
  4041      * Which packages are included in my bundle?
  4042      * How did a specific file get included?
  4043      * How small did a specific file compress to?
  4044      * Was a specific file tree-shaken or not?
  4045  
  4046      I'm publishing this tool because I think esbuild should provide *some* answer to "how do I visualize my bundle" without requiring people to reach for third-party tools. At the moment the tool offers two types of visualizations: a radial "sunburst chart" and a linear "flame chart". They serve slightly different but overlapping use cases (e.g. the sunburst chart is more keyboard-accessible while the flame chart is easier with the mouse). This tool may continue to evolve over time.
  4047  
  4048  * Fix `--metafile` and `--mangle-cache` with `--watch` ([#1357](https://github.com/evanw/esbuild/issues/1357))
  4049  
  4050      The CLI calls the Go API and then also writes out the metafile and/or mangle cache JSON files if those features are enabled. This extra step is necessary because these files are returned by the Go API as in-memory strings. However, this extra step accidentally didn't happen for all builds after the initial build when watch mode was enabled. This behavior used to work but it was broken in version 0.14.18 by the introduction of the mangle cache feature. This release fixes the combination of these features, so the metafile and mangle cache features should now work with watch mode. This behavior was only broken for the CLI, not for the JS or Go APIs.
  4051  
  4052  * Add an `original` field to the metafile
  4053  
  4054      The metadata file JSON now has an additional field: each import in an input file now contains the pre-resolved path in the `original` field in addition to the post-resolved path in the `path` field. This means it's now possible to run certain additional analysis over your bundle. For example, you should be able to use this to detect when the same package subpath is represented multiple times in the bundle, either because multiple versions of a package were bundled or because a package is experiencing the [dual-package hazard](https://nodejs.org/api/packages.html#dual-package-hazard).