Skip to content

Releases: evanw/esbuild

v0.8.42

05 Feb 07:46
Compare
Choose a tag to compare
  • Fix crash with block-level function declaration and --keep-names (#755)

    This release fixes a crash with block-level function declarations and the --keep-names option. The crash affected code that looks like this:

    if (true) function f() {}
    assert.strictEqual(f.name, 'f')
  • Disallow additional features in strict mode

    This change improves esbuild's compliance with the JavaScript specification. It is now an error to use legacy octal numeric literals and the identifiers implements, interface, let, package, private, protected, public, static, and yield in strict mode code.

  • Basic support for watch mode with plugins (#752)

    With this release, watch mode should now work with simple on-load plugins. Watch mode is implemented by tracking all file system accesses made by esbuild as it does a build. However, this doesn't catch external file system accesses such as those made by plugins. Now if an on-load plugin is used on a path in the file namespace, esbuild will also read the file during watch mode so that watch mode is aware of the file system access. Note that there is not yet API support for a plugin to return additional paths for watch mode to monitor.

  • Make JavaScript API error format more consistent (#745)

    If a JavaScript error is thrown while validating the build options, the thrown error should now have errors and warnings properties just like normal build errors. Previously these properties were only present if the build itself failed but not if build options were invalid. This consistency should make it easier to process errors from the build API call.

v0.8.41

04 Feb 14:22
Compare
Choose a tag to compare
  • Fix memory leak with watch mode when using the CLI (#750)

    This release fixes a memory leak when using --watch from the CLI (command-line interface). When esbuild was in this state, every incremental build resulted in more memory being consumed. This problem did not affect users of the JS API or Go API, only users of the CLI API.

    The problem was that the GC (garbage collector) was disabled. Oops. This is done by default for speed when you use esbuild via the CLI, which makes sense for most CLI use cases because the process is usually short-lived and doesn't need to waste time cleaning up memory. But it does not make sense for flags that cause esbuild to be a long-running process.

    Previously the only exception to this rule was the --serve flag. When I added watch mode, I forgot to enable GC for the --watch flag too. With this release, the GC is enabled for both the --serve and the --watch flags so esbuild should no longer leak memory in watch mode.

  • Special-case certain syntax with --format=esm (#749)

    You can now no longer use the following syntax features with the esm output format:

    • The with statement: with (x) {}
    • Delete of a bare identifier: delete x

    In addition, the following syntax feature is transformed when using the esm output format:

    • For-in variable initializers: for (var x = y in {}) {}x = y; for (var x in {}) {}

    The reason is because all JavaScript engines interpret code in the esm output format as strict mode and these syntax features are disallowed in strict mode. Note that this new strict mode handling behavior in esbuild is only dependent on the output format. It does not depend on the presence or absence of "use strict" directives.

  • Basic "use strict" tracking

    The JavaScript parser now tracks "use strict" directives and propagates strict mode status through the code. In addition, files containing the import and/or export keywords are also considered to be in strict mode. Strict mode handling is complex and esbuild currently doesn't implement all strict mode checks. But the changes in this release are a starting point. It is now an error to use certain syntax features such as a with statement within a strict mode scope.

  • Fix a minifier bug with with statements

    The minifier removes references to local variables if they are unused. However, that's not correct to do inside a with statement scope because what appears to be an identifier may actually be a property access, and property accesses could have arbitrary side effects if they resolve to a getter or setter method. Now all identifier expressions inside with statements are preserved when minifying.

  • Transform block-level function declarations

    Block-level function declarations are now transformed into equivalent syntax that avoids block-level declarations. Strict mode and non-strict mode have subtly incompatible behavior for how block-level function declarations are interpreted. Doing this transformation prevents problems with code that was originally strict mode that is run as non-strict mode and vice versa.

    Now esbuild uses the presence or absence of a strict mode scope to determine how to interpret the block-level function declaration and then converts it to the equivalent unambiguous syntax such that it works the same regardless of whether or not the current scope is in strict mode:

    // This original code:
    while (!y) {
      function y() {}
    }
    
    // is transformed into this code in strict mode:
    while (!y) {
      let y2 = function() {};
    }
    
    // and into this code when not in strict mode:
    while (!y) {
      let y2 = function() {};
      var y = y2;
    }

v0.8.40

04 Feb 04:19
Compare
Choose a tag to compare
  • Fix TypeScript parameter decorators on class constructors (#734)

    This release fixes a TypeScript translation bug where parameter decorators on class constructors were translated incorrectly. Affected code looks like this:

    class Example {
      constructor(@decorator param: any) {}
    }

    This bug has been fixed. In addition, decorators are no longer allowed on class constructors themselves because they are not allowed in TypeScript.

  • Resolve browser entries in package.json with no file extension (#740)

    This fix changes how esbuild interprets the browser field in package.json. It will now remap imports without a file extension to browser map entries without a file extension, which improves compatibility with Webpack. Specifically, a package.json file with "browser": {"./file": "./something.js"} will now match an import of ./file. Previously the package.json file had to contain something like "browser": {"./file.js": "./something.js"} instead. Note that for compatibility with the rest of the ecosystem, a remapping of ./file will counter-intuitively not match an import of ./file.js even though it works fine in the other direction.

  • Warning: npm v7 bug may prevent esbuild installation

    This is a warning for people reading these release notes, not a code change. I have discovered a bug in npm v7 where your package-lock.json file can become corrupted such that no postinstall scripts are run. This bug affects all packages with postinstall scripts, not just esbuild, and happens when running npm v7 on a package-lock.json file from npm v6 or earlier. It seems like deleting and regenerating your package-lock.json file is a valid workaround that should get esbuild working again.

v0.8.39

01 Feb 09:46
Compare
Choose a tag to compare
  • Fix the JavaScript watch mode API exiting early (#730)

    The previous release contained a bug that caused the JavaScript watch mode API to exit early in some cases. This bug should now be fixed. The problem was caused by some code that shouldn't even need to exist now that you are no longer required to call stop() on an esbuild service created by startService() (it was made optional in version 0.8.32). I took the opportunity to clean up the internals of esbuild's JavaScript API implementation which ended up removing the entire section of code that contained this bug.

  • Add an API option for a per-build working directory (#689)

    You can now use the absWorkingDir API option to customize the current working directory. It will default to the value of process.cwd() at the time of the call to startService() when not specified, which matches the existing behavior. The working directory is used for a few different things including resolving relative paths given as API options to absolute paths and pretty-printing absolute paths as relative paths in log messages.

    In addition to being a useful feature, this change also simplifies esbuild's internals. Previously esbuild had to maintain separate child processes if the current working directory was changed in between build API calls. Now esbuild will always reuse the same child process across all build API calls. The stop() call on the startService() API is also now a no-op (it doesn't do anything anymore) and the startService() API may be removed in future releases.

  • Fix stray esbuild process after node exits (#643)

    I discovered that using esbuild's JavaScript incremental build API could result in the child esbuild process not exiting when the parent node process exits. This was due to a reference counting issue. The bug has been fixed so this shouldn't happen anymore.

v0.8.38

31 Jan 10:11
Compare
Choose a tag to compare
  • Implement a simple cross-platform watch mode (#21)

    With this release, you can use the --watch flag to run esbuild in watch mode which watches the file system for changes and does an incremental build when something has changed. The watch mode implementation uses polling instead of OS-specific file system events for portability.

    Note that it is still possible to implement watch mode yourself using esbuild's incremental build API and a file watcher library of your choice if you don't want to use a polling-based approach. Also note that this watch mode feature is about improving developer convenience and does not have any effect on incremental build time (i.e. watch mode is not faster than other forms of incremental builds).

    The new polling system is intended to use relatively little CPU vs. a traditional polling system that scans the whole directory tree at once. The file system is still scanned regularly but each scan only checks a random subset of your files to reduce CPU usage. This means a change to a file will be picked up soon after the change is made but not necessarily instantly. With the current heuristics, large projects should be completely scanned around every 2 seconds so in the worst case it could take up to 2 seconds for a change to be noticed. However, after a change has been noticed the change's path goes on a short list of recently changed paths which are checked on every scan, so further changes to recently changed files should be noticed almost instantly.

  • Add pluginData to pass data between plugins (#696)

    You can now return additional data from a plugin in the optional pluginData field and it will be passed to the next plugin that runs in the plugin chain. So if you return it from an onLoad plugin, it will be passed to the onResolve plugins for any imports in that file, and if you return it from an onResolve plugin, an arbitrary one will be passed to the onLoad plugin when it loads the file (it's arbitrary since the relationship is many-to-one). This is useful to pass data between different plugins without them having to coordinate directly.

v0.8.37

30 Jan 12:36
Compare
Choose a tag to compare
  • Improve ambiguous import handling (#723)

    It is an error to try to import a name from a file where there are multiple matching exports due to multiple export * from statements from files which export that name. This release contains a few improvements to ambiguous import handling:

    1. This release fixes a bug where named export shadowing didn't work correctly with multiple levels of re-exports. A named export closer in the re-export chain is supposed to hide a named export deeper in the re-export chain without causing an ambiguous import. The bug caused this case to be incorrectly flagged as an error even though it should have been allowed. This case is now allowed without an error.

    2. Previously the error message just said that there was an ambiguous import but didn't have any additional information. With this release, the error message also points out where the two different exports that have collided are in their original source files. Hopefully this should make it quicker to diagnose these types of issues.

    3. Real JavaScript environments only treat ambiguous imports as an error if they are explicitly a named import. Using the import * as syntax and then accessing the ambiguous import with a property access results in undefined instead of an error. Previously esbuild also treated this case as an error because it automatically rewrites star-import syntax to named-import syntax to improve tree shaking. With this release, this case is now treated as a warning instead of an error and the import will be automatically replaced with an undefined literal in the bundled code.

  • Reuse automatically-generated temporary *.node files (#719)

    The previous change to hide the automatically-generated N-API native node extensions from Yarn 2 writes these *.node files to the system's temporary directory. A new one was being created on each run which is wasteful even though they are only a few kilobytes in size. With this release *.node files will now be reused if they are already present in the system's temporary directory, so a new one is no longer created on each run. This fix was contributed by @kzc.

  • Fix the serve API with outfile (#707)

    This release fixes a bug where the serve API did not work with the outfile setting. Using this setting with the serve API should now work fine.

  • Warn about duplicate keys in object literals

    Using a duplicate key in an object literal such as {x: 1, x: 2} is now a warning. This is allowed in JavaScript but results in subsequent keys overwriting the previous key. It's usually a copy/paste error and isn't ever useful so it's worth warning about.

  • Avoid generating duplicate keys in JSON metadata

    The output map that is generated when the metafile feature is active could potentially have duplicate keys if the file loader is used, there are multiple entry points, and two or more entry points reference the same file. This is harmless because both keys mapped to the same value, but it's confusing and unnecessary. Duplicate keys are no longer present in the output map in this latest release.

  • Make the JSON metafile structure match the type definitions (#726)

    Previously imports and/or exports could be missing from entries in the output map in certain cases (specifically for source maps and files loaded with the file loader). This was problematic because the TypeScript type definitions for the metafile say that the imports and exports properties are non-optional. With this release, the imports and exports properties are now always present so the existing TypeScript type definitions are now accurate.

  • Update from Go 1.15.5 to Go 1.15.7

    The version of Go used to build the released binary executables on npm is now Go 1.15.7. This change shouldn't result in any visible changes to esbuild. It was only upgraded because the Go extension for the VSCode IDE now uses the official gopls Go language service and this extension wanted the latest version of Go.

v0.8.36

26 Jan 11:17
Compare
Choose a tag to compare
  • Fix an issue with writing large files to stdout using the WebAssembly executable

    The previous release introduced a regression where large output files written to stdout were incorrectly truncated when using the WebAssembly esbuild command. This regression was due to a missing callback to the JavaScript write() function when called on the stdout stream. The regression has been fixed.

  • Hide the N-API native node extensions from Yarn 2

    The previous release introduced some very small (1-2kb) *.node native extensions to fix a bug with node failing to exit properly. However, this causes Yarn 2 to unzip the esbuild package, which is undesirable. This release puts these native node extensions inside JavaScript code instead to hide them from Yarn 2. The native extensions are written to a temporary file at run-time if necessary.

v0.8.35

26 Jan 09:00
Compare
Choose a tag to compare
  • Fix a commonly-missed corner case with await inside **

    I recently discovered an interesting discussion about JavaScript syntax entitled "Most implementations seem to have missed that await x ** 2 is not legal". Indeed esbuild has missed this, but this is not surprising because V8 has missed this as well and I usually test esbuild against V8 to test if esbuild is conformant with the JavaScript standard. Regardless, it sounds like the result of the discussion is that the specification should stay the same and implementations should be fixed. This release fixes this bug in esbuild's parser. The syntax await x ** 2 is no longer allowed and parentheses are now preserved for the syntax (await x) ** 2.

  • Allow namespaced names in JSX syntax (#702)

    XML-style namespaced names with a : in the middle are a part of the JSX specification but they are explicitly unimplemented by React and TypeScript so esbuild doesn't currently support them. However, there was a user request to support this feature since it's part of the JSX specification and esbuild's JSX support can be used for non-React purposes. So this release now supports namespaced names in JSX expressions:

    let xml =
      <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
               xmlns:dc="http://purl.org/dc/elements/1.1/">
        <rdf:Description rdf:ID="local-record">
          <dc:title>Local Record</dc:title>
        </rdf:Description>
      </rdf:RDF>

    This JSX expression is now transformed by esbuild to the following JavaScript:

    let xml = React.createElement("rdf:RDF", {
      "xmlns:rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
      "xmlns:dc": "http://purl.org/dc/elements/1.1/"
    }, React.createElement("rdf:Description", {
      "rdf:ID": "local-record"
    }, React.createElement("dc:title", null, "Local Record")));

    Note that if you are trying to namespace your React components, this is not the feature to use. You should be using a . instead of a : for namespacing your React components since . resolves to a JavaScript property access.

  • Fix worker: false in esbuild's browser-based JavaScript API

    The browser-based JavaScript API creates a web worker by default but this can be disabled by passing worker: false. When you do this the WebAssembly code is run in the current thread which will lock up the thread. This is mainly useful if you're calling the JavaScript API from within a web worker and you want to avoid creating another nested web worker.

    This option was unintentionally broken when the internal JavaScript web worker source code was moved from an inline function to a string in version 0.5.20. The regression has been fixed and the worker: false scenario now has test coverage.

  • Fix absolute paths with the esbuild-wasm package on Windows (#687)

    The package esbuild-wasm has an esbuild command implemented using WebAssembly instead of using native code. It uses node's WebAssembly implementation and calls methods on node's fs module to access the file system.

    Go's path/filepath module has a bug where Windows paths are interpreted as Unix paths when targeting WebAssembly: golang/go#43768. This causes multiple issues including absolute paths such as C:\path\to\file.js being interpreted as relative paths (since they don't start with a /) and being joined onto the end of other paths.

    To fix this, esbuild now does all of its own path handling instead of using Go's path handling code. The esbuild code base now contains a forked copy of path/filepath that can handle both Windows and Unix paths. The decision about which one to use is made at run-time. When targeting WebAssembly, the presence of the C:\ directory is used to determine if Windows-style paths should be used.

    With this release, it should now be possible to use Windows-style paths with esbuild's WebAssembly implementation on Windows.

  • Fix using stdin with the esbuild-wasm package on Windows (#687)

    Node has an old bug (nodejs/node#19831, nodejs/node#35997) where fs.read returns an EOF error at the end of stdin on Windows. This causes Go's WebAssembly implementation to panic when esbuild tries to read from stdin.

    The workaround was to manually check for this case and then ignore the error in this specific case. With this release, it should now be possible to pipe something to the esbuild command on Windows.

  • Fix stdout and stderr not supporting Unicode in the esbuild-wasm package on Windows (#687)

    Node's fs.write API is broken when writing Unicode to stdout and stderr on Windows, and this will never be fixed: nodejs/node#24550. This is problematic for Go's WebAssembly implementation because it uses this API for writing to all file descriptors.

    The workaround is to manually intercept the file descriptors for stdout and stderr and redirect them to process.stdout and process.stderr respectively. Passing Unicode text to write() on these objects instead of on the fs API strangely works fine. So with this release, Unicode text should now display correctly when using esbuild's WebAssembly implementation on Windows (or at least, as correctly as the poor Unicode support in Windows Command Prompt allows).

  • Add a hack for faster command-line execution for the WebAssembly module in certain cases

    Node has an unfortunate bug where the node process is unnecessarily kept open while a WebAssembly module is being optimized: nodejs/node#36616. This means cases where running esbuild should take a few milliseconds can end up taking many seconds instead.

    The workaround is to force node to exit by ending the process early. This is done in one of two ways depending on the exit code. For non-zero exit codes (i.e. when there is a build error), the esbuild command now calls process.kill(process.pid) to avoid the hang.

    For zero exit codes, the esbuild command now loads a N-API native node extension that calls the operating system's exit(0) function. This is done without requiring node-gyp by precompiling each supported platform and just including all of them in the esbuild-wasm package since they are so small. If this hack doesn't work in certain cases, the process should exit anyway just potentially many seconds later. Currently the only supported platforms for this hack are 64-bit macOS, Windows, and Linux.

  • Fix non-absolute paths with the esbuild-wasm package in the browser (#693)

    When using esbuild in the browser via WebAssembly, it was not possible to specify an non-absolute output path. Normally you can do this and esbuild will just convert it to an absolute path by resolving it as a relative path from the current working directory. However, Go's WebAssembly implementation has no current working directory so the conversion operation to an absolute path failed, causing esbuild's API to fail.

    With this release, esbuild should now behave as if the current working directory is / in the browser. For example, this means calling the build() API with outfile: 'file.js' should now generate an output file called /file.js instead of causing an error.

v0.8.34

21 Jan 23:41
Compare
Choose a tag to compare
  • Fix a parser bug about suffix expressions after an arrow function body (#701)

    The JavaScript parser incorrectly handled suffix expressions after a non-expression arrow function body. In practice, this came up when a semicolon was omitted from the end of an expression statement and the following expression could be considered a suffix expression:

    x = () => {}
    (y)

    This was incorrectly parsed as (x = () => {})(y); instead of x = () => {}; y;. With this release, this edge case should now be parsed correctly.

  • Add new neutral platform to help text (#695)

    The new --platform=neutral API option that was added in the previous release was incorrectly not listed in the CLI help text for the platform feature. This omission has been fixed. The fix was contributed by @hardfist.

v0.8.33

18 Jan 02:11
Compare
Choose a tag to compare
  • Fix esbuild potentially exiting early during incremental rebuilds

    The change in the previous release to make calling stop() optional caused a regression for incremental rebuilds where calling rebuild() could potentially cause the process to exit early before the incremental rebuild is completed. This is because the implementation of rebuild() was missing a reference count to track that the service is now temporarily needed again. This omission was an oversight, and has now been fixed.

  • Fix using the new sourcesContent option with the transform API (#682)

    Due to an oversight, the sourcesContent: false option that was added in version 0.8.27 didn't work with the JavaScript transform API. This was unintentional and has been fixed. This fix was contributed by @jschaf.

  • Insert the object spread shim in constructor methods after the super() call (#678)

    This fixes an issue with the transform for object spread to older compile targets. Previously the following code would be transformed to code that crashes when run if the compile target is es2017 or lower:

    class Derived extends Base {
      prop = null;
      constructor({ ...args }) {
        super(args);
      }
    }

    This code was incorrectly compiled to something like this, which will throw ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor:

    class Derived extends Base {
      constructor(_a) {
        __publicField(this, "prop", null);
        var args = __rest(_a, []);
        super(args);
      }
    }

    With this release, it will now be compiled to something like this instead:

    class Derived extends Base {
      constructor(_a) {
        var args = __rest(_a, []);
        super(args);
        __publicField(this, "prop", null);
      }
    }
  • Add the --platform=neutral API option (#674)

    There are currently two platform values: browser (the default) and node. These settings are a convenient way to configure multiple defaults for other API options for maximum compatibility. However, some users want to configure everything themselves so esbuild does not assume any platform-specific behavior. In this case you can now use --platform=neutral to disable platform-specific default values. Note that this means if you want to use npm-style packages you will have to configure a main field yourself with something like --main-fields=main.

  • Provide minified and non-minified versions of in-browser API library (#616)

    The in-browser JavaScript API libraries for esbuild are in the esbuild-wasm package. There are two: esbuild-wasm/lib/browser.js in UMD format and esbuild-wasm/esm/browser.js in ESM format. Previously these were minified since they contain a large string of JavaScript that cannot be minified by other tools. Now they are no longer minified, and there are new minified versions available at esbuild-wasm/lib/browser.min.js and esbuild-wasm/esm/browser.min.js.