Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update dependency esbuild to v0.14.47 #104

Merged
merged 1 commit into from Jun 28, 2022
Merged

Update dependency esbuild to v0.14.47 #104

merged 1 commit into from Jun 28, 2022

Conversation

renovate[bot]
Copy link
Contributor

@renovate renovate bot commented May 8, 2022

Mend Renovate

This PR contains the following updates:

Package Change Age Adoption Passing Confidence
esbuild 0.14.27 -> 0.14.47 age adoption passing confidence

Release Notes

evanw/esbuild

v0.14.47

Compare Source

  • Make global names more compact when ||= is available (#​2331)

    With this release, the code esbuild generates for the --global-name= setting is now slightly shorter when you don't configure esbuild such that the ||= operator is unsupported (e.g. with --target=chrome80 or --supported:logical-assignment=false):

    // Original code
    exports.foo = 123
    
    // Old output (with --format=iife --global-name=foo.bar.baz --minify)
    var foo=foo||{};foo.bar=foo.bar||{};foo.bar.baz=(()=>{var b=(a,o)=>()=>(o||a((o={exports:{}}).exports,o),o.exports);var c=b(f=>{f.foo=123});return c();})();
    
    // New output (with --format=iife --global-name=foo.bar.baz --minify)
    var foo;((foo||={}).bar||={}).baz=(()=>{var b=(a,o)=>()=>(o||a((o={exports:{}}).exports,o),o.exports);var c=b(f=>{f.foo=123});return c();})();
  • Fix --mangle-quoted=false with --minify-syntax=true

    If property mangling is active and --mangle-quoted is disabled, quoted properties are supposed to be preserved. However, there was a case when this didn't happen if --minify-syntax was enabled, since that internally transforms x['y'] into x.y to reduce code size. This issue has been fixed:

    // Original code
    x.foo = x['bar'] = { foo: y, 'bar': z }
    
    // Old output (with --mangle-props=. --mangle-quoted=false --minify-syntax=true)
    x.a = x.b = { a: y, bar: z };
    
    // New output (with --mangle-props=. --mangle-quoted=false --minify-syntax=true)
    x.a = x.bar = { a: y, bar: z };

    Notice how the property foo is always used unquoted but the property bar is always used quoted, so foo should be consistently mangled while bar should be consistently not mangled.

  • Fix a minification bug regarding this and property initializers

    When minification is enabled, esbuild attempts to inline the initializers of variables that have only been used once into the start of the following expression to reduce code size. However, there was a bug where this transformation could change the value of this when the initializer is a property access and the start of the following expression is a call expression. This release fixes the bug:

    // Original code
    function foo(obj) {
      let fn = obj.prop;
      fn();
    }
    
    // Old output (with --minify)
    function foo(f){f.prop()}
    
    // New output (with --minify)
    function foo(o){let f=o.prop;f()}

v0.14.46

Compare Source

  • Add the ability to override support for individual syntax features (#​2060, #​2290, #​2308)

    The target setting already lets you configure esbuild to restrict its output by only making use of syntax features that are known to be supported in the configured target environment. For example, setting target to chrome50 causes esbuild to automatically transform optional chain expressions into the equivalent older JavaScript and prevents you from using BigInts, among many other things. However, sometimes you may want to customize this set of unsupported syntax features at the individual feature level.

    Some examples of why you might want to do this:

    • JavaScript runtimes often do a quick implementation of newer syntax features that is slower than the equivalent older JavaScript, and you can get a speedup by telling esbuild to pretend this syntax feature isn't supported. For example, V8 has a long-standing performance bug regarding object spread that can be avoided by manually copying properties instead of using object spread syntax. Right now esbuild hard-codes this optimization if you set target to a V8-based runtime.

    • There are many less-used JavaScript runtimes in addition to the ones present in browsers, and these runtimes sometimes just decide not to implement parts of the specification, which might make sense for runtimes intended for embedded environments. For example, the developers behind Facebook's JavaScript runtime Hermes have decided to not implement classes despite it being a major JavaScript feature that was added seven years ago and that is used in virtually every large JavaScript project.

    • You may be processing esbuild's output with another tool, and you may want esbuild to transform certain features and the other tool to transform certain other features. For example, if you are using esbuild to transform files individually to ES5 but you are then feeding the output into Webpack for bundling, you may want to preserve import() expressions even though they are a syntax error in ES5.

    With this release, you can now use --supported:feature=false to force feature to be unsupported. This will cause esbuild to either rewrite code that uses the feature into older code that doesn't use the feature (if esbuild is able to), or to emit a build error (if esbuild is unable to). For example, you can use --supported:arrow=false to turn arrow functions into function expressions and --supported:bigint=false to make it an error to use a BigInt literal. You can also use --supported:feature=true to force it to be supported, which means esbuild will pass it through without transforming it. Keep in mind that this is an advanced feature. For most use cases you will probably want to just use target instead of using this.

    The full set of currently-allowed features are as follows:

    JavaScript:

    • arbitrary-module-namespace-names
    • array-spread
    • arrow
    • async-await
    • async-generator
    • bigint
    • class
    • class-field
    • class-private-accessor
    • class-private-brand-check
    • class-private-field
    • class-private-method
    • class-private-static-accessor
    • class-private-static-field
    • class-private-static-method
    • class-static-blocks
    • class-static-field
    • const-and-let
    • default-argument
    • destructuring
    • dynamic-import
    • exponent-operator
    • export-star-as
    • for-await
    • for-of
    • generator
    • hashbang
    • import-assertions
    • import-meta
    • logical-assignment
    • nested-rest-binding
    • new-target
    • node-colon-prefix-import
    • node-colon-prefix-require
    • nullish-coalescing
    • object-accessors
    • object-extensions
    • object-rest-spread
    • optional-catch-binding
    • optional-chain
    • regexp-dot-all-flag
    • regexp-lookbehind-assertions
    • regexp-match-indices
    • regexp-named-capture-groups
    • regexp-sticky-and-unicode-flags
    • regexp-unicode-property-escapes
    • rest-argument
    • template-literal
    • top-level-await
    • typeof-exotic-object-is-object
    • unicode-escapes

    CSS:

    • hex-rgba
    • rebecca-purple
    • modern-rgb-hsl
    • inset-property
    • nesting

    Since you can now specify --supported:object-rest-spread=false yourself to work around the V8 performance issue mentioned above, esbuild will no longer automatically transform all instances of object spread when targeting a V8-based JavaScript runtime going forward.

    Note that JavaScript feature transformation is very complex and allowing full customization of the set of supported syntax features could cause bugs in esbuild due to new interactions between multiple features that were never possible before. Consider this to be an experimental feature.

  • Implement extends constraints on infer type variables (#​2330)

    TypeScript 4.7 introduced the ability to write an extends constraint after an infer type variable, which looks like this:

    type FirstIfString<T> =
      T extends [infer S extends string, ...unknown[]]
        ? S
        : never;

    You can read the blog post for more details: https://devblogs.microsoft.com/typescript/announcing-typescript-4-7/#extends-constraints-on-infer-type-variables. Previously this was a syntax error in esbuild but with this release, esbuild can now parse this syntax correctly.

  • Allow define to match optional chain expressions (#​2324)

    Previously esbuild's define feature only matched member expressions that did not use optional chaining. With this release, esbuild will now also match those that use optional chaining:

    // Original code
    console.log(a.b, a?.b)
    
    // Old output (with --define:a.b=c)
    console.log(c, a?.b);
    
    // New output (with --define:a.b=c)
    console.log(c, c);

    This is for compatibility with Webpack's DefinePlugin, which behaves the same way.

v0.14.45

Compare Source

  • Add a log message for ambiguous re-exports (#​2322)

    In JavaScript, you can re-export symbols from another file using export * from './another-file'. When you do this from multiple files that export different symbols with the same name, this creates an ambiguous export which is causes that name to not be exported. This is harmless if you don't plan on using the ambiguous export name, so esbuild doesn't have a warning for this. But if you do want a warning for this (or if you want to make it an error), you can now opt-in to seeing this log message with --log-override:ambiguous-reexport=warning or --log-override:ambiguous-reexport=error. The log message looks like this:

    ▲ [WARNING] Re-export of "common" in "example.js" is ambiguous and has been removed [ambiguous-reexport]
    
      One definition of "common" comes from "a.js" here:
    
        a.js:2:11:
          2 │ export let common = 2
            ╵            ~~~~~~
    
      Another definition of "common" comes from "b.js" here:
    
        b.js:3:14:
          3 │ export { b as common }
            ╵               ~~~~~~
    
  • Optimize the output of the JSON loader (#​2161)

    The json loader (which is enabled by default for .json files) parses the file as JSON and generates a JavaScript file with the parsed expression as the default export. This behavior is standard and works in both node and the browser (well, as long as you use an import assertion). As an extension, esbuild also allows you to import additional top-level properties of the JSON object directly as a named export. This is beneficial for tree shaking. For example:

    import { version } from 'esbuild/package.json'
    console.log(version)

    If you bundle the above code with esbuild, you'll get something like the following:

    // node_modules/esbuild/package.json
    var version = "0.14.44";
    
    // example.js
    console.log(version);

    Most of the package.json file is irrelevant and has been omitted from the output due to tree shaking. The way esbuild implements this is to have the JavaScript file that's generated from the JSON look something like this with a separate exported variable for each property on the top-level object:

    // node_modules/esbuild/package.json
    export var name = "esbuild";
    export var version = "0.14.44";
    export var repository = "https://github.com/evanw/esbuild";
    export var bin = {
      esbuild: "bin/esbuild"
    };
    ...
    export default {
      name,
      version,
      repository,
      bin,
      ...
    };

    However, this means that if you import the default export instead of a named export, you will get non-optimal output. The default export references all top-level properties, leading to many unnecessary variables in the output. With this release esbuild will now optimize this case to only generate additional variables for top-level object properties that are actually imported:

    // Original code
    import all, { bar } from 'data:application/json,{"foo":[1,2,3],"bar":[4,5,6]}'
    console.log(all, bar)
    
    // Old output (with --bundle --minify --format=esm)
    var a=[1,2,3],l=[4,5,6],r={foo:a,bar:l};console.log(r,l);
    
    // New output (with --bundle --minify --format=esm)
    var l=[4,5,6],r={foo:[1,2,3],bar:l};console.log(r,l);

    Notice how there is no longer an unnecessary generated variable for foo since it's never imported. And if you only import the default export, esbuild will now reproduce the original JSON object in the output with all top-level properties compactly inline.

  • Add id to warnings returned from the API

    With this release, warnings returned from esbuild's API now have an id property. This identifies which kind of log message it is, which can be used to more easily filter out certain warnings. For example, reassigning a const variable will generate a message with an id of "assign-to-constant". This also gives you the identifier you need to apply a log override for that kind of message: https://esbuild.github.io/api/#log-override.

v0.14.44

Compare Source

  • Add a copy loader (#​2255)

    You can configure the "loader" for a specific file extension in esbuild, which is a way of telling esbuild how it should treat that file. For example, the text loader means the file is imported as a string while the binary loader means the file is imported as a Uint8Array. If you want the imported file to stay a separate file, the only option was previously the file loader (which is intended to be similar to Webpack's file-loader package). This loader copies the file to the output directory and imports the path to that output file as a string. This is useful for a web application because you can refer to resources such as .png images by importing them for their URL. However, it's not helpful if you need the imported file to stay a separate file but to still behave the way it normally would when the code is run without bundling.

    With this release, there is now a new loader called copy that copies the loaded file to the output directory and then rewrites the path of the import statement or require() call to point to the copied file instead of the original file. This will automatically add a content hash to the output name by default (which can be configured with the --asset-names= setting). You can use this by specifying copy for a specific file extension, such as with --loader:.png=copy.

  • Fix a regression in arrow function lowering (#​2302)

    This release fixes a regression with lowering arrow functions to function expressions in ES5. This feature was introduced in version 0.7.2 and regressed in version 0.14.30.

    In JavaScript, regular function expressions treat this as an implicit argument that is determined by how the function is called, but arrow functions treat this as a variable that is captured in the closure from the surrounding lexical scope. This is emulated in esbuild by storing the value of this in a variable before changing the arrow function into a function expression.

    However, the code that did this didn't treat this expressions as a usage of that generated variable. Version 0.14.30 began omitting unused generated variables, which caused the transformation of this to break. This regression happened due to missing test coverage. With this release, the problem has been fixed:

    // Original code
    function foo() {
      return () => this
    }
    
    // Old output (with --target=es5)
    function foo() {
      return function() {
        return _this;
      };
    }
    
    // New output (with --target=es5)
    function foo() {
      var _this = this;
      return function() {
        return _this;
      };
    }

    This fix was contributed by @​nkeynes.

  • Allow entity names as define values (#​2292)

    The "define" feature allows you to replace certain expressions with certain other expressions at compile time. For example, you might want to replace the global identifier IS_PRODUCTION with the boolean value true when building for production. Previously the only expressions you could substitute in were either identifier expressions or anything that is valid JSON syntax. This limitation exists because supporting more complex expressions is more complex (for example, substituting in a require() call could potentially pull in additional files, which would need to be handled). With this release, you can now also now define something as a member expression chain of the form foo.abc.xyz.

  • Implement package self-references (#​2312)

    This release implements a rarely-used feature in node where a package can import itself by name instead of using relative imports. You can read more about this feature here: https://nodejs.org/api/packages.html#self-referencing-a-package-using-its-name. For example, assuming the package.json in a given package looks like this:

    // package.json
    {
      "name": "a-package",
      "exports": {
        ".": "./main.mjs",
        "./foo": "./foo.js"
      }
    }

    Then any module in that package can reference an export in the package itself:

    // ./a-module.mjs
    import { something } from 'a-package'; // Imports "something" from ./main.mjs.

    Self-referencing is also available when using require, both in an ES module, and in a CommonJS one. For example, this code will also work:

    // ./a-module.js
    const { something } = require('a-package/foo'); // Loads from ./foo.js.
  • Add a warning for assigning to an import (#​2319)

    Import bindings are immutable in JavaScript, and assigning to them will throw an error. So instead of doing this:

    import { foo } from 'foo'
    foo++

    You need to do something like this instead:

    import { foo, setFoo } from 'foo'
    setFoo(foo + 1)

    This is already an error if you try to bundle this code with esbuild. However, this was previously allowed silently when bundling is disabled, which can lead to confusion for people who don't know about this aspect of how JavaScript works. So with this release, there is now a warning when you do this:

    ▲ [WARNING] This assignment will throw because "foo" is an import [assign-to-import]
    
        example.js:2:0:
          2 │ foo++
            ╵ ~~~
    
      Imports are immutable in JavaScript. To modify the value of this import, you must export a setter
      function in the imported file (e.g. "setFoo") and then import and call that function here instead.
    

    This new warning can be turned off with --log-override:assign-to-import=silent if you don't want to see it.

  • Implement alwaysStrict in tsconfig.json (#​2264)

    This release adds alwaysStrict to the set of TypeScript tsconfig.json configuration values that esbuild supports. When this is enabled, esbuild will forbid syntax that isn't allowed in strict mode and will automatically insert "use strict"; at the top of generated output files. This matches the behavior of the TypeScript compiler: https://www.typescriptlang.org/tsconfig#alwaysStrict.

v0.14.43

Compare Source

  • Fix TypeScript parse error whe a generic function is the first type argument (#​2306)

    In TypeScript, the << token may need to be split apart into two < tokens if it's present in a type argument context. This was already correctly handled for all type expressions and for identifier expressions such as in the following code:

    // These cases already worked in the previous release
    let foo: Array<<T>() => T>;
    bar<<T>() => T>;

    However, normal expressions of the following form were previously incorrectly treated as syntax errors:

    // These cases were broken but have now been fixed
    foo.bar<<T>() => T>;
    foo?.<<T>() => T>();

    With this release, these cases now parsed correctly.

  • Fix minification regression with pure IIFEs (#​2279)

    An Immediately Invoked Function Expression (IIFE) is a function call to an anonymous function, and is a way of introducing a new function-level scope in JavaScript since JavaScript lacks a way to do this otherwise. And a pure function call is a function call with the special /* @&#8203;__PURE__ */ comment before it, which tells JavaScript build tools that the function call can be considered to have no side effects (and can be removed if it's unused).

    Version 0.14.9 of esbuild introduced a regression that changed esbuild's behavior when these two features were combined. If the IIFE body contains a single expression, the resulting output still contained that expression instead of being empty. This is a minor regression because you normally wouldn't write code like this, so this shouldn't come up in practice, and it doesn't cause any correctness issues (just larger-than-necessary output). It's unusual that you would tell esbuild "remove this if the result is unused" and then not store the result anywhere, since the result is unused by construction. But regardless, the issue has now been fixed.

    For example, the following code is a pure IIFE, which means it should be completely removed when minification is enabled. Previously it was replaced by the contents of the IIFE but it's now completely removed:

    // Original code
    /* @&#8203;__PURE__ */ (() => console.log(1))()
    
    // Old output (with --minify)
    console.log(1);
    
    // New output (with --minify)
  • Add log messages for indirect require references (#​2231)

    A long time ago esbuild used to warn about indirect uses of require because they break esbuild's ability to analyze the dependencies of the code and cause dependencies to not be bundled, resulting in a potentially broken bundle. However, this warning was removed because many people wanted the warning to be removed. Some packages have code that uses require like this but on a code path that isn't used at run-time, so their code still happens to work even though the bundle is incomplete. For example, the following code will not bundle bindings:

    // Prevent React Native packager from seeing modules required with this
    const nodeRequire = require;
    
    function getRealmConstructor(environment) {
      switch (environment) {
        case "node.js":
        case "electron":
          return nodeRequire("bindings")("realm.node").Realm;
      }
    }

    Version 0.11.11 of esbuild removed this warning, which means people no longer have a way to know at compile time whether their bundle is broken in this way. Now that esbuild has custom log message levels, this warning can be added back in a way that should make both people happy. With this release, there is now a log message for this that defaults to the debug log level, which normally isn't visible. You can either do --log-override:indirect-require=warning to make this log message a warning (and therefore visible) or use --log-level=debug to see this and all other debug log messages.

v0.14.42

Compare Source

  • Fix a parser hang on invalid CSS (#​2276)

    Previously invalid CSS with unbalanced parentheses could cause esbuild's CSS parser to hang. An example of such an input is the CSS file :x(. This hang has been fixed.

  • Add support for custom log message levels

    This release allows you to override the default log level of esbuild's individual log messages. For example, CSS syntax errors are treated as warnings instead of errors by default because CSS grammar allows for rules containing syntax errors to be ignored. However, if you would like for esbuild to consider CSS syntax errors to be build errors, you can now configure that like this:

    • CLI

      $ esbuild example.css --log-override:css-syntax-error=error
    • JS API

      let result = await esbuild.build({
        entryPoints: ['example.css'],
        logOverride: {
          'css-syntax-error': 'error',
        },
      })
    • Go API

      result := api.Build(api.BuildOptions{
        EntryPoints: []string{"example.ts"},
        LogOverride: map[string]api.LogLevel{
          "css-syntax-error": api.LogLevelError,
        },
      })

    You can also now use this feature to silence warnings that you are not interested in. Log messages are referred to by their identifier. Each identifier is stable (i.e. shouldn't change over time) except there is no guarantee that the log message will continue to exist. A given log message may potentially be removed in the future, in which case esbuild will ignore log levels set for that identifier. The current list of supported log level identifiers for use with this feature can be found below:

    JavaScript:

    • assign-to-constant
    • call-import-namespace
    • commonjs-variable-in-esm
    • delete-super-property
    • direct-eval
    • duplicate-case
    • duplicate-object-key
    • empty-import-meta
    • equals-nan
    • equals-negative-zero
    • equals-new-object
    • html-comment-in-js
    • impossible-typeof
    • private-name-will-throw
    • semicolon-after-return
    • suspicious-boolean-not
    • this-is-undefined-in-esm
    • unsupported-dynamic-import
    • unsupported-jsx-comment
    • unsupported-regexp
    • unsupported-require-call

    CSS:

    • css-syntax-error
    • invalid-@&#8203;charset
    • invalid-@&#8203;import
    • invalid-@&#8203;nest
    • invalid-@&#8203;layer
    • invalid-calc
    • js-comment-in-css
    • unsupported-@&#8203;charset
    • unsupported-@&#8203;namespace
    • unsupported-css-property

    Bundler:

    • different-path-case
    • ignored-bare-import
    • ignored-dynamic-import
    • import-is-undefined
    • package.json
    • require-resolve-not-external
    • tsconfig.json

    Source maps:

    • invalid-source-mappings
    • sections-in-source-map
    • missing-source-map
    • unsupported-source-map-comment

    Documentation about which identifiers correspond to which log messages will be added in the future, but hasn't been written yet. Note that it's not possible to configure the log level for a build error. This is by design because changing that would cause esbuild to incorrectly proceed in the building process generate invalid build output. You can only configure the log level for non-error log messages (although you can turn non-errors into errors).

v0.14.41

Compare Source

  • Fix a minification regression in 0.14.40 (#​2270, #​2271, #​2273)

    Version 0.14.40 substituted string property keys with numeric property keys if the number has the same string representation as the original string. This was done in three places: computed member expressions, object literal properties, and class fields. However, negative numbers are only valid in computed member expressions while esbuild incorrectly applied this substitution for negative numbers in all places. This release fixes the regression by only doing this substitution for negative numbers in computed member expressions.

    This fix was contributed by @​susiwen8.

v0.14.40

Compare Source

  • Correct esbuild's implementation of "preserveValueImports": true (#​2268)

    TypeScript's preserveValueImports setting tells the compiler to preserve unused imports, which can sometimes be necessary because otherwise TypeScript will remove unused imports as it assumes they are type annotations. This setting is useful for programming environments that strip TypeScript types as part of a larger code transformation where additional code is appended later that will then make use of those unused imports, such as with Svelte or Vue.

    This release fixes an issue where esbuild's implementation of preserveValueImports diverged from the official TypeScript compiler. If the import clause is present but empty of values (even if it contains types), then the import clause should be considered a type-only import clause. This was an oversight, and has now been fixed:

    // Original code
    import "keep"
    import { k1 } from "keep"
    import k2, { type t1 } from "keep"
    import {} from "remove"
    import { type t2 } from "remove"
    
    // Old output under "preserveValueImports": true
    import "keep";
    import { k1 } from "keep";
    import k2, {} from "keep";
    import {} from "remove";
    import {} from "remove";
    
    // New output under "preserveValueImports": true (matches the TypeScript compiler)
    import "keep";
    import { k1 } from "keep";
    import k2 from "keep";
  • Avoid regular expression syntax errors in older browsers (#​2215)

    Previously esbuild always passed JavaScript regular expression literals through unmodified from the input to the output. This is undesirable when the regular expression uses newer features that the configured target environment doesn't support. For example, the d flag (i.e. the match indices feature) is new in ES2022 and doesn't work in older browsers. If esbuild generated a regular expression literal containing the d flag, then older browsers would consider esbuild's output to be a syntax error and none of the code would run.

    With this release, esbuild now detects when an unsupported feature is being used and converts the regular expression literal into a new RegExp() constructor instead. One consequence of this is that the syntax error is transformed into a run-time error, which allows the output code to run (and to potentially handle the run-time error). Another consequence of this is that it allows you to include a polyfill that overwrites the RegExp constructor in older browsers with one that supports modern features. Note that esbuild does not handle polyfills for you, so you will need to include a RegExp polyfill yourself if you want one.

    // Original code
    console.log(/b/d.exec('abc').indices)
    
    // New output (with --target=chrome90)
    console.log(/b/d.exec("abc").indices);
    
    // New output (with --target=chrome89)
    console.log(new RegExp("b", "d").exec("abc").indices);

    This is currently done transparently without a warning. If you would like to debug this transformation to see where in your code esbuild is transforming regular expression literals and why, you can pass --log-level=debug to esbuild and review the information present in esbuild's debug logs.

  • Add Opera to more internal feature compatibility tables (#​2247, #​2252)

    The internal compatibility tables that esbuild uses to determine which environments support which features are derived from multiple sources. Most of it is automatically derived from these ECMAScript compatibility tables, but missing information is manually copied from MDN, GitHub PR comments, and various other websites. Version 0.14.35 of esbuild introduced Opera as a possible target environment which was automatically picked up by the compatibility table script, but the manually-copied information wasn't updated to include Opera. This release fixes this omission so Opera feature compatibility should now be accurate.

    This was contributed by @​lbwa.

  • Ignore EPERM errors on directories (#​2261)

    Previously bundling with esbuild when inside a sandbox environment which does not have permission to access the parent directory did not work because esbuild would try to read the directory to search for a node_modules folder and would then fail the build when that failed. In practice this caused issues with running esbuild with sandbox-exec on macOS. With this release, esbuild will treat directories with permission failures as empty to allow for the node_modules search to continue past the denied directory and into its parent directory. This means it should now be possible to bundle with esbuild in these situations. This fix is similar to the fix in version 0.9.1 but is for EPERM while that fix was for EACCES.

  • Remove an irrelevant extra "use strict" directive (#​2264)

    The presence of a "use strict" directive in the output file is controlled by the presence of one in the entry point. However, there was a bug that would include one twice if the output format is ESM. This bug has been fixed.

  • Minify strings into integers inside computed properties (#​2214)

    This release now minifies a["0"] into a[0] when the result is equivalent:

    // Original code
    console.log(x['0'], { '0': x }, class { '0' = x })
    
    // Old output (with --minify)
    console.log(x["0"],{"0":x},class{"0"=x});
    
    // New output (with --minify)
    console.log(x[0],{0:x},class{0=x});

    This transformation currently only happens when the numeric property represents an integer within the signed 32-bit integer range.

v0.14.39

Compare Source

  • Fix code generation for export default and /* @&#8203;__PURE__ */ call (#​2203)

    The /* @&#8203;__PURE__ */ comment annotation can be added to function calls to indicate that they are side-effect free. These annotations are passed through into the output by esbuild since many JavaScript tools understand them. However, there was an edge case where printing this comment before a function call caused esbuild to fail to parenthesize a function literal because it thought it was no longer at the start of the expression. This problem has been fixed:

    // Original code
    export default /* @&#8203;__PURE__ */ (function() {
    })()
    
    // Old output
    export default /* @&#8203;__PURE__ */ function() {
    }();
    
    // New output
    export default /* @&#8203;__PURE__ */ (function() {
    })();
  • Preserve ... before JSX child expressions (#​2245)

    TypeScript 4.5 changed how JSX child expressions that start with ... are emitted. Previously the ... was omitted but starting with TypeScript 4.5, the ... is now preserved instead. This release updates esbuild to match TypeScript's new output in this case:

    // Original code
    console.log(<a>{...b}</a>)
    
    // Old output
    console.log(/* @&#8203;__PURE__ */ React.createElement("a", null, b));
    
    // New output
    console.log(/* @&#8203;__PURE__ */ React.createElement("a", null, ...b));

    Note that this behavior is TypeScript-specific. Babel doesn't support the ... token at all (it gives the error "Spread children are not supported in React").

  • Slightly adjust esbuild's handling of the browser field in package.json (#​2239)

    This release changes esbuild's interpretation of browser path remapping to fix a regression that was introduced in esbuild version 0.14.21. Browserify has a bug where it incorrectly matches package paths to relative paths in the browser field, and esbuild replicates this bug for compatibility with Browserify. I have a set of tests that I use to verify that esbuild's replication of this Browserify is accurate here: https://github.com/evanw/package-json-browser-tests. However, I was missing a test case and esbuild's behavior diverges from Browserify in this case. This release now handles this edge case as well:

    • entry.js:

      require('pkg/sub')
    • node_modules/pkg/package.json:

      {
        "browser": {
          "./sub": "./sub/foo.js",
          "./sub/sub.js": "./sub/foo.js"
        }
      }
    • node_modules/pkg/sub/foo.js:

      require('sub')
    • node_modules/sub/index.js:

      console.log('works')

    The import path sub in require('sub') was previously matching the remapping "./sub/sub.js": "./sub/foo.js" but with this release it should now no longer match that remapping. Now require('sub') will only match the remapping "./sub/sub": "./sub/foo.js" (without the trailing .js). Browserify apparently only matches without the .js suffix here.

v0.14.38

Compare Source

  • Further fixes to TypeScript 4.7 instantiation expression parsing (#​2201)

    This release fixes some additional edge cases with parsing instantiation expressions from the upcoming version 4.7 of TypeScript. Previously it was allowed for an instantiation expression to precede a binary operator but with this release, that's no longer allowed. This was sometimes valid in the TypeScript 4.7 beta but is no longer allowed in the latest version of TypeScript 4.7. Fixing this also fixed a regression that was introduced by the previous release of esbuild:

    Code TS 4.6.3 TS 4.7.0 beta TS 4.7.0 nightly esbuild 0.14.36 esbuild 0.14.37 esbuild 0.14.38
    a<b> == c<d> Invalid a == c Invalid a == c a == c Invalid
    a<b> in c<d> Invalid Invalid Invalid Invalid a in c Invalid
    a<b>>=c<d> Invalid Invalid Invalid Invalid a >= c Invalid
    a<b>=c<d> Invalid a < b >= c a = c a < b >= c a = c a = c
    a<b>>c<d> a < b >> c a < b >> c a < b >> c a < b >> c a > c a < b >> c

    This table illustrates some of the more significant changes between all of these parsers. The most important part is that esbuild 0.14.38 now matches the behavior of the latest TypeScript compiler for all of these cases.

v0.14.37

Compare Source

  • Add support for TypeScript's moduleSuffixes field from TypeScript 4.7

    The upcoming version of TypeScript adds the moduleSuffixes field to tsconfig.json that introduces more rules to import path resolution. Setting moduleSuffixes to [".ios", ".native", ""] will try to look at the the relative files ./foo.ios.ts, ./foo.native.ts, and finally ./foo.ts for an import path of ./foo. Note that the empty string "" in moduleSuffixes is necessary for TypeScript to also look-up ./foo.ts. This was announced in the TypeScript 4.7 beta blog post.

  • Match the new ASI behavior from TypeScript nightly builds (#​2188)

    This release updates esbuild to match some very recent behavior changes in the TypeScript parser regarding automatic semicolon insertion. For more information, see TypeScript issues #​48711 and #​48654 (I'm not linking to them directly to avoid Dependabot linkback spam on these issues due to esbuild's popularity). The result is that the following TypeScript code is now considered valid TypeScript syntax:

    class A<T> {}
    new A<number> /* ASI now happens here */
    if (0) {}
    
    interface B {
      (a: number): typeof a /* ASI now happens here */
      <T>(): void
    }

    This fix was contributed by @​g-plane.

v0.14.36

Compare Source

  • Revert path metadata validation for now (#​2177)

    This release reverts the path metadata validation that was introduced in the previous release. This validation has uncovered a potential issue with how esbuild handles onResolve callbacks in plugins that will need to be fixed before path metadata validation is re-enabled.

v0.14.35

Compare Source

  • Add support for parsing typeof on #private fields from TypeScript 4.7 (#​2174)

    The upcoming version of TypeScript now lets you use #private fields in typeof type expressions:

    https://devblogs.microsoft.com/typescript/announcing-typescript-4-7-beta/#typeof-on-private-fields

    class Container {
      #data = "hello!";
    
      get data(): typeof this.#data {
        return this.#data;
      }
    
      set data(value: typeof this.#data) {
        this.#data = value;
      }
    }

    With this release, esbuild can now parse these new type expressions as well. This feature was contributed by @​magic-akari.

  • Add Opera and IE to internal CSS feature support matrix (#​2170)

    Version 0.14.18 of esbuild added Opera and IE as available target environments, and added them to the internal JS feature support matrix. CSS feature support was overlooked, however. This release adds knowledge of Opera and IE to esbuild's internal CSS feature support matrix:

    /* Original input */
    a {
      color: rgba(0, 0, 0, 0.5);
    }
    
    /* Old output (with --target=opera49 --minify) */
    a{color:rgba(0,0,0,.5)}
    
    /* New output (with --target=opera49 --minify) */
    a{color:#&#8203;00000080}

    The fix for this issue was contributed by @​sapphi-red.

  • Change TypeScript class field behavior when targeting ES2022

    TypeScript 4.3 introduced a breaking change where class field behavior changes from assign semantics to define semantics when the target setting in tsconfig.json is set to ESNext. Specifically, the default value for TypeScript's useDefineForClassFields setting when unspecified is true if and only if target is ESNext. TypeScript 4.6 introduced another change where this behavior now happens for both ESNext and ES2022. Presumably this will be the case for ES2023 and up as well. With this release, esbuild's behavior has also been changed to match. Now configuring esbuild with --target=es2022 will also cause TypeScript files to use the new class field behavior.

  • Validate that path metadata returned by plugins is consistent

    The plugin API assumes that all metadata for the same path returned by a plugin's onResolve callback is consistent. Previously this assumption was just assumed without any enforcement. Starting with this release, esbuild will now enforce this by generating a build error if this assumption is violated. The lack of validation has not been an issue (I have never heard of this being a problem), but it still seems like a good idea to enforce it. Here's a simple example of a plugin that generates inconsistent sideEffects metadata:

    let buggyPlugin = {
      name: 'buggy',
      setup(build) {
        let count = 0
        build.onResolve({ filter: /^react$/ }, args => {
          return {
            path: require.resolve(args.path),
            sideEffects: count++ > 0,
          }
        })
      },
    }

    Since esbuild processes everything in parallel, the set of metadata that ends up being used for a given path is essentially random since it's whatever the task scheduler decides to schedule first. Thus if a plugin does not consistently provide the same metadata for a given path, subsequent builds may return different results. This new validation check prevents this problem.

    Here's the new error message that's shown when this happens:

    ✘ [ERROR] [plugin buggy] Detected inconsistent metadata for the path "node_modules/react/index.js" when it was imported here:
    
        button.tsx:1:30:
          1 │ import { createElement } from 'react'
            ╵                               ~~~~~~~
    
      The original metadata for that path comes from when it was imported here:
    
        app.tsx:1:23:
          1 │ import * as React from 'react'
            ╵                        ~~~~~~~
    
      The difference in metadata is displayed below:
    
       {
      -  "sideEffects": true,
      +  "sideEffects": false,
       }
    
      This is a bug in the "buggy" plugin. Plugins provide metadata for a given path in an "onResolve"
      callback. All metadata provided for the same path must be consistent to ensure deterministic
      builds. Due to parallelism, one set of provided metadata will be randomly chosen for a given path,
      so providing inconsistent metadata for the same path can cause non-determinism.
    
  • Suggest enabling a missing condition when exports map fails (#​2163)

    This release adds another suggestion to the error message that happens when an exports map lookup fails if the failure could potentially be fixed by adding a missing condition. Here's what the new error message looks like (which now suggests --conditions=module as a possible workaround):

    ✘ [ERROR] Could not resolve "@&#8203;sentry/electron/main"
    
        index.js:1:24:
          1 │ import * as Sentry from '@&#8203;sentry/electron/main'
            ╵                         ~~~~~~~~~~~~~~~~~~~~~~~
    
      The path "./main" is not currently exported by package "@&#8203;sentry/electron":
    
        node_modules/@&#8203;sentry/electron/package.json:8:13:
          8 │   "exports": {
            ╵              ^
    
      None of the conditions provided ("require", "module") match any of the currently active conditions
      ("browser", "default", "import"):
    
        node_modules/@&#8203;sentry/electron/package.json:16:14:
          16 │     "./main": {
             ╵               ^
    
      Consider enabling the "module" condition if this package expects it to be enabled. You can use
      "--conditions=module" to do that:
    
        node_modules/@&#8203;sentry/electron/package.json:18:6:
          18 │       "module": "./esm/main/index.js"
             ╵       ~~~~~~~~
    
      Consider using a "require()" call to import this file, which will work because the "require"
      condition is supported by this package:
    
        index.js:1:24:
          1 │ import * as Sentry from '@&#8203;sentry/electron/main'
            ╵                         ~~~~~~~~~~~~~~~~~~~~~~~
    
      You can mark the path "@&#8203;sentry/electron/main" as external to exclude it from the bundle, which
      will remove this error.
    

    This particular package had an issue where it was using the Webpack-specific module condition without providing a default condition. It looks like the intent in this case was to use the standard import condition instead. This specific change wasn't suggested here because this error message is for package consumers, not package authors.

v0.14.34

Compare Source

Something went wrong with the publishing script for the previous release. Publishing again.

v0.14.33

Compare Source

  • Fix a regression regarding super (#​2158)

    This fixes a regression from the previous release regarding classes with a super class, a private member, and a static field in the scenario where the static field needs to be lowered but where private members are supported by the configured target environment. In this scenario, esbuild could incorrectly inject the instance field initializers that use this into the constructor before the call to super(), which is invalid. This problem has now been fixed (notice that this is now used after super() instead of before):

    // Original code
    class Foo extends Object {
      static FOO;
      constructor() {
        super();
      }
      #foo;
    }
    
    // Old output (with --bundle)
    var _foo;
    var Foo = class extends Object {
      constructor() {
        __privateAdd(this, _foo, void 0);
        super();
      }
    };
    _foo = new WeakMap();
    __publicField(Foo, "FOO");
    
    // New output (with --bundle)
    var _foo;
    var Foo = class extends Object {
      constructor() {
        super();
        __privateAdd(this, _foo, void 0);
      }
    };
    _foo = new WeakMap();
    __publicField(Foo, "FOO");

    During parsing, esbuild scans the class and makes certain decisions about the class such as whether to lower all static fields, whether to lower each private member, or whether calls to super() need to be tracked and adjusted. Previously esbuild made two passes through the class members to compute this information. However, with the new super() call lowering logic added in the previous release, we now need three passes to capture the whole dependency chain for this case: 1) lowering static fields requires 2) lowering private members which requires 3) adjusting super() calls.

    The reason lowering static fields requires lowering private members is because lowering static fields moves their initializers outside of the class body, where they can't access private members anymore. Consider this code:

    class Foo {
      get #foo() {}
      static bar = new Foo().#foo
    }

    We can't just lower static fields without also lowering private members, since that causes a syntax error:

    class Foo {
      get #foo() {}
    }
    Foo.bar = new Foo().#foo;

    And the reason lowering private members requires adjusting super() calls is because the injected private member initializers use this, which is only accessible after super() calls in the constructor.

  • Fix an issue with --keep-names not keeping some names (#​2149)

    This release fixes a regression with --keep-names from version 0.14.26. PR #​2062 attempted to remove superfluous calls to the __name helper function by omitting calls of the form __name(foo, "foo") where the name of the symbol in the first argument is equal to the string in the second argument. This was assuming that the initializer for the symbol would automatically be assigned the expected .name property by the JavaScript VM, which turned out to be an incorrect assumption. To fix the regression, this PR has been reverted.

    The assumption is true in many cases but isn't true when the initializer is moved into another automatically-generated variable, which can sometimes be necessary during the various syntax transformations that esbuild does. For example, consider the following code:

    class Foo {
      static get #foo() { return Foo.name }
      static get foo() { return this.#foo }
    }
    let Bar = Foo
    Foo = { name: 'Bar' }
    console.log(Foo.name, Bar.name)

    This code should print Bar Foo. With --keep-names --target=es6 that code is lowered by esbuild into the following code (omitting the helper function definitions for brevity):

    var _foo, foo_get;
    const _Foo = class {
      static get foo() {
        return __privateGet(this, _foo, foo_get);
      }
    };
    let Foo = _Foo;
    __name(Foo, "Foo");
    _foo = new WeakSet();
    foo_get = /* @&#8203;__PURE__ */ __name(function() {
      return _Foo.name;
    }, "#foo");
    __privateAdd(Foo, _foo);
    let Bar = Foo;
    Foo = { name: "Bar" };
    console.log(Foo.name, Bar.name);

    The injection of the automatically-generated _Foo variable is necessary to preserve the semantics of the captured Foo binding for methods defined within the class body, even when the definition needs to be moved outside of the class body during code transformation. Due to a JavaScript quirk, this binding is immutable and does not change even if Foo is later reassigned. The PR that was reverted was incorrectly removing the call to __name(Foo, "Foo"), which turned out to be necessary after all in this case.

  • Print some large integers using hexadecimal when minifying (#​2162)

    When --minify is active, esbuild will now use one fewer byte to represent certain large integers:

    // Original code
    x = 123456787654321;
    
    // Old output (with --minify)
    x=123456787654321;
    
    // New output (with --minify)
    x=0x704885f926b1;

    This works because a hexadecimal representation can be shorter than a decimal representation starting at around 1012 and above.

    This optimization made me realize that there's probably an opportunity to optimize printed numbers for smaller gzipped size instead of or in addition to just optimizing for minimal uncompressed byte count. The gzip algorithm does better with repetitive sequences, so for example 0xFFFFFFFF is probably a better representation than 4294967295 even though the byte counts are the same. As far as I know, no JavaScript minifier does this optimization yet. I don't know enough about how gzip works to know if this is a good idea or what the right metric for this might be.

  • Add Linux ARM64 support for Deno (#​2156)

    This release adds Linux ARM64 support to esbuild's Deno API implementation, which allows esbuild to be used with Deno on a Raspberry Pi.

v0.14.32

Compare Source

  • Fix super usage in lowered private methods (#​2039)

    Previously esbuild failed to


Configuration

📅 Schedule: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, click this checkbox.

This PR has been generated by Mend Renovate. View repository job log here.

@codecov-commenter
Copy link

codecov-commenter commented May 8, 2022

Codecov Report

Merging #104 (f7c06aa) into main (7f894dc) will not change coverage.
The diff coverage is n/a.

@@           Coverage Diff           @@
##             main     #104   +/-   ##
=======================================
  Coverage   37.20%   37.20%           
=======================================
  Files           7        7           
  Lines          43       43           
  Branches        3        3           
=======================================
  Hits           16       16           
  Misses         27       27           
Flag Coverage Δ
unittests 37.20% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.


Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 7f894dc...f7c06aa. Read the comment docs.

@renovate renovate bot changed the title Update dependency esbuild to v0.14.38 Update dependency esbuild to v0.14.39 May 11, 2022
@renovate renovate bot changed the title Update dependency esbuild to v0.14.39 Update dependency esbuild to v0.14.45 Jun 18, 2022
@renovate renovate bot changed the title Update dependency esbuild to v0.14.45 Update dependency esbuild to v0.14.47 Jun 24, 2022
@gagoar gagoar merged commit 3b11ed8 into main Jun 28, 2022
@gagoar gagoar deleted the renovate/esbuild-0.x branch June 28, 2022 01:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants