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

cmd/compile: "runtime: bad pointer in frame" in riscv64 with complier optimizations #51101

Closed
piggynl opened this issue Feb 9, 2022 · 12 comments
Closed
Labels
arch-riscv NeedsFix
Milestone

Comments

@piggynl
Copy link

@piggynl piggynl commented Feb 9, 2022

What version of Go are you using (go version)?

$ go version
go version go1.17.6 linux/riscv64

Does this issue reproduce with the latest release?

Yes.

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE=""
GOARCH="riscv64"
GOBIN=""
GOCACHE="/home/piggy/.cache/go-build"
GOENV="/home/piggy/.config/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="riscv64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/piggy/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/piggy/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/lib/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/lib/go/pkg/tool/linux_riscv64"
GOVCS=""
GOVERSION="go1.17.6"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/dev/null"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build2469834381=/tmp/go-build -gno-record-gcc-switches"

What did you do?

Reproduce: (you should have Node.js and Yarn pre-installed)

$ uname -m
riscv64

$ # build esbuild
$ git clone https://github.com/evanw/esbuild.git
$ cd esbuild
$ CGO_ENABLED=0 go build ./cmd/esbuild -o esbuild
$ cd ..

$ # get input files for esbuild
$ git clone https://github.com/tridactyl/tridactyl.git
$ cd tridactyl
$ yarn upgrade esbuild@^0.14.21 # make yarn happy (esbuild added support for riscv64 in 0.14.21)
$ yarn install
$ ../esbuild/esbuild --bundle src/background.ts --outfile=/dev/null 2>&1 | tee buildlog.txt

What did you expect to see?

esbuild works as intended, like in amd64.

What did you see instead?

runtime: bad pointer in frame github.com/evanw/esbuild/internal/js_parser.(*parser).visitBinding at 0x3f9cc244b8: 0xc0
fatal error: invalid pointer found on stack

runtime stack:
runtime.throw({0x4c9114, 0x1e})
        runtime/panic.go:1198 +0x60 fp=0x3f9c185830 sp=0x3f9c185808 pc=0x4c6a8
runtime.adjustpointers(0x3f9cc24470, 0x3f9c185910, 0x3f9c185d10, {0x752c80, 0x77ae00})
        runtime/stack.go:617 +0x224 fp=0x3f9c185878 sp=0x3f9c185830 pc=0x69204
runtime.adjustframe(0x3f9c185c28, 0x3f9c185d10)
        runtime/stack.go:659 +0xf8 fp=0x3f9c185948 sp=0x3f9c185878 pc=0x69300
runtime.gentraceback(0xffffffffffffffff, 0xffffffffffffffff, 0x0, 0x3f9c99cea0, 0x0, 0x0, 0x7fffffff, 0x4e2f50, 0x3f9c185d10, 0x0)
        runtime/traceback.go:350 +0x7e4 fp=0x3f9c185c80 sp=0x3f9c185948 pc=0x76604
runtime.copystack(0x3f9c99cea0, 0x10000)
        runtime/stack.go:918 +0x230 fp=0x3f9c185e30 sp=0x3f9c185c80 pc=0x69a28
runtime.newstack()
        runtime/stack.go:1097 +0x4b8 fp=0x3f9c185fd0 sp=0x3f9c185e30 pc=0x69fc0
runtime.morestack()
        runtime/asm_riscv64.s:202 +0x70 fp=0x3f9c185fd8 sp=0x3f9c185fd0 pc=0x80a68

goroutine 128 [copystack]:
runtime.growslice(0x478360, {0x3f9c9d8210, 0x2, 0x2}, 0x3)
        runtime/slice.go:162 +0x10 fp=0x3f9cc243a0 sp=0x3f9cc243a0 pc=0x676a8
github.com/evanw/esbuild/internal/js_parser.(*parser).recordDeclaredSymbol(...)
        github.com/evanw/esbuild/internal/js_parser/js_parser.go:8448
github.com/evanw/esbuild/internal/js_parser.(*parser).visitBinding(0x3f9c9f8800, {{0x564e00, 0x3f9c90d160}, {0x559}}, {0x3f9cc0e6a0})
        github.com/evanw/esbuild/internal/js_parser/js_parser.go:8463 +0x148 fp=0x3f9cc245f8 sp=0x3f9cc243a0 pc=0x2c57a8
github.com/evanw/esbuild/internal/js_parser.(*parser).visitArgs(0x3f9c9f8800, {0x3f9c912ff0, 0x1, 0x1}, {{0x3f9c90fb48, 0x1, 0x1}, 0x0, 0x0})
        github.com/evanw/esbuild/internal/js_parser/js_parser.go:10527 +0x238 fp=0x3f9cc247a0 sp=0x3f9cc245f8 pc=0x2d9970
... some frames omitted ...
github.com/evanw/esbuild/internal/bundler.parseFile({{0x5725c8, 0x3f9c00e380}, {0x3f9c0b6930, 0x3f9c00a180, 0x3f9c00a198, 0x3f9c01e1e0, 0x3}, {0x56ca80, 0x3f9c06b500}, 0x3f9c050360, ...})
        github.com/evanw/esbuild/internal/bundler/bundler.go:185 +0xce0 fp=0x3f9cc2bbe8 sp=0x3f9cc29910 pc=0x38d188
runtime.goexit()
        runtime/asm_riscv64.s:507 +0x4 fp=0x3f9cc2bbe8 sp=0x3f9cc2bbe8 pc=0x82904
created by github.com/evanw/esbuild/internal/bundler.(*scanner).maybeParseFile
        github.com/evanw/esbuild/internal/bundler/bundler.go:1189 +0x838

... and stack traces of other goroutines

The full output: http://fars.ee/4nkQ


I've tested the build options below. It seems the bug is caused by the optimizer?

Build Options Result
(default) esbuild crashes
-gcflags=all="-N" esbuild works fine
-gcflags=all="-l" esbuild works fine
-gcflags=all="-N -l" esbuild works fine

Also, I'm working on a minimal reproduce.

@mengzhuo
Copy link
Contributor

@mengzhuo mengzhuo commented Feb 10, 2022

The js_parser is using unsafe to do pointer operation.
It looks like an esbuild bug to me.

@evanw
Copy link

@evanw evanw commented Feb 10, 2022

Is this mostly deterministic? Does this always or almost always happen? If so, you could try just removing the unsafe code to see if it still happens. There is only a small amount of unsafe code in js_parser.go:

 // The name is temporarily stored in the ref until the scope traversal pass
 // happens, at which point a symbol will be generated and the ref will point
 // to the symbol instead.
 //
 // The scope traversal pass will reconstruct the name using one of two methods.
 // In the common case, the name is a slice of the file itself. In that case we
 // can just store the slice and not need to allocate any extra memory. In the
 // rare case, the name is an externally-allocated string. In that case we store
 // an index to the string and use that index during the scope traversal pass.
 func (p *parser) storeNameInRef(name string) js_ast.Ref {
-  c := (*reflect.StringHeader)(unsafe.Pointer(&p.source.Contents))
-  n := (*reflect.StringHeader)(unsafe.Pointer(&name))
-
-  // Is the data in "name" a subset of the data in "p.source.Contents"?
-  if n.Data >= c.Data && n.Data+uintptr(n.Len) < c.Data+uintptr(c.Len) {
-    // The name is a slice of the file contents, so we can just reference it by
-    // length and don't have to allocate anything. This is the common case.
-    //
-    // It's stored as a negative value so we'll crash if we try to use it. That
-    // way we'll catch cases where we've forgotten to call loadNameFromRef().
-    // The length is the negative part because we know it's non-zero.
-    return js_ast.Ref{SourceIndex: -uint32(n.Len), InnerIndex: uint32(n.Data - c.Data)}
-  } else {
     // The name is some memory allocated elsewhere. This is either an inline
     // string constant in the parser or an identifier with escape sequences
     // in the source code, which is very unusual. Stash it away for later.
     // This uses allocations but it should hopefully be very uncommon.
     ref := js_ast.Ref{SourceIndex: 0x80000000, InnerIndex: uint32(len(p.allocatedNames))}
     p.allocatedNames = append(p.allocatedNames, name)
     return ref
-  }
 }

The unsafe code is used to recover the index and length of a substring within the string. Reusing the memory with the unsafe code saves about 20mb of memory in esbuild's primary benchmark but it's not necessary for esbuild to function, and can be commented out. If the problem still happens with that commented out then it's not due to unsafe.

@evanw
Copy link

@evanw evanw commented Feb 10, 2022

Update: I just removed use of the unsafe package on esbuild's master branch. So you should be able to try it again without needing to apply the code modification I described above.

@piggynl
Copy link
Author

@piggynl piggynl commented Feb 10, 2022

Hi @mengzhuo,

After removing the usage of unsafe package, esbuild still crashes with runtime: bad pointer in frame. This happens with the patch in this issue and with evanw/esbuild@4db57c1, on a SiFive Unmatched RISC-V development board and in qemu-riscv64.


Is this mostly deterministic? Does this always or almost always happen?

Yes. This always happens.


To whom wants to test but without a development board (cc @evanw),

This wiki page Setup Arch Linux RISC-V Development Environment can helps you setup an environment with QEMU. After the setup, run pacman -S git go nodejs yarn (and gdb?), then it will be ready to reproduce.

@mengzhuo
Copy link
Contributor

@mengzhuo mengzhuo commented Feb 10, 2022

Updated: I got the same failure that just run js_parser test.


Could you provide a mininal test (without yarn/nodejs parts) ? I can't install yarn on my unmatched box.

@mengzhuo
Copy link
Contributor

@mengzhuo mengzhuo commented Feb 10, 2022

Kindly cc @mknyszek @thanm @cherrymui

@cherrymui cherrymui added NeedsInvestigation arch-riscv labels Feb 10, 2022
@cherrymui cherrymui added this to the Backlog milestone Feb 10, 2022
@cherrymui
Copy link
Member

@cherrymui cherrymui commented Feb 14, 2022

The bad pointer is from a subtraction of two (valid) pointer values, from

(EqPtr x y) => (SEQZ (SUB <x.Type> x y))

The temporary value (SUB <x.Type> x y) should not be a pointer type, as it is the difference of two pointers and may not point to valid memory. Will send a CL.

@gopherbot
Copy link

@gopherbot gopherbot commented Feb 14, 2022

Change https://go.dev/cl/385655 mentions this issue: cmd/compile: correct type of pointer difference on RISCV64

@cherrymui
Copy link
Member

@cherrymui cherrymui commented Feb 14, 2022

@gopherbot please backport this to previous releases. This can cause runtime crashes.

@gopherbot
Copy link

@gopherbot gopherbot commented Feb 14, 2022

Backport issue(s) opened: #51198 (for 1.16), #51199 (for 1.17).

Remember to create the cherry-pick CL(s) as soon as the patch is submitted to master, according to https://go.dev/wiki/MinorReleases.

@dmitshur dmitshur added NeedsFix and removed NeedsInvestigation labels Feb 14, 2022
@dmitshur dmitshur removed this from the Backlog milestone Feb 14, 2022
@dmitshur dmitshur added this to the Go1.18 milestone Feb 14, 2022
@gopherbot
Copy link

@gopherbot gopherbot commented Feb 17, 2022

Change https://go.dev/cl/386474 mentions this issue: [release-branch.go1.17] cmd/compile: correct type of pointer difference on RISCV64

@gopherbot
Copy link

@gopherbot gopherbot commented Feb 17, 2022

Change https://go.dev/cl/386475 mentions this issue: [release-branch.go1.16] cmd/compile: correct type of pointer difference on RISCV64

gopherbot pushed a commit that referenced this issue Feb 18, 2022
…ce on RISCV64

Pointer comparison is lowered to the following on RISCV64

(EqPtr x y) => (SEQZ (SUB <x.Type> x y))

The difference of two pointers (the SUB) should not be pointer
type. Otherwise it can cause the GC to find a bad pointer.

Updates #51101.
Fixes #51198.

Change-Id: I7e73c2155c36ff403c032981a9aa9cccbfdf0f64
Reviewed-on: https://go-review.googlesource.com/c/go/+/385655
Trust: Cherry Mui <cherryyz@google.com>
Run-TryBot: Cherry Mui <cherryyz@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit 1ed30ca)
Reviewed-on: https://go-review.googlesource.com/c/go/+/386475
gopherbot pushed a commit that referenced this issue Feb 18, 2022
…ce on RISCV64

Pointer comparison is lowered to the following on RISCV64

(EqPtr x y) => (SEQZ (SUB <x.Type> x y))

The difference of two pointers (the SUB) should not be pointer
type. Otherwise it can cause the GC to find a bad pointer.

Updates #51101.
Fixes #51199.

Change-Id: I7e73c2155c36ff403c032981a9aa9cccbfdf0f64
Reviewed-on: https://go-review.googlesource.com/c/go/+/385655
Trust: Cherry Mui <cherryyz@google.com>
Run-TryBot: Cherry Mui <cherryyz@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit 1ed30ca)
Reviewed-on: https://go-review.googlesource.com/c/go/+/386474
aviator-app bot pushed a commit to airplanedev/lib that referenced this issue Mar 4, 2022
[![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [github.com/evanw/esbuild](https://togithub.com/evanw/esbuild) | require | patch | `v0.14.2` -> `v0.14.25` |
| [github.com/goccy/go-yaml](https://togithub.com/goccy/go-yaml) | require | patch | `v1.9.4` -> `v1.9.5` |
| [github.com/mitchellh/mapstructure](https://togithub.com/mitchellh/mapstructure) | require | minor | `v1.1.2` -> `v1.4.3` |

---

### Release Notes

<details>
<summary>evanw/esbuild</summary>

### [`v0.14.25`](https://togithub.com/evanw/esbuild/releases/v0.14.25)

[Compare Source](https://togithub.com/evanw/esbuild/compare/v0.14.24...v0.14.25)

-   Reduce minification of CSS transforms to avoid Safari bugs ([#&#8203;2057](https://togithub.com/evanw/esbuild/issues/2057))

    In Safari, applying a 3D CSS transform to an element can cause it to render in a different order than applying a 2D CSS transform even if the transformation matrix is identical. I believe this is a bug in Safari because the [CSS `transform` specification](https://drafts.csswg.org/css-transforms-1/#transform-rendering) doesn't seem to distinguish between 2D and 3D transforms as far as rendering order:

    > For elements whose layout is governed by the CSS box model, any value other than `none` for the `transform` property results in the creation of a stacking context.

    This bug means that minifying a 3D transform into a 2D transform must be avoided even though it's a valid transformation because it can cause rendering differences in Safari. Previously esbuild sometimes minified 3D CSS transforms into 2D CSS transforms but with this release, esbuild will no longer do that:

    ```css
    /* Original code */
    div { transform: matrix3d(2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1) }

    /* Old output (with --minify) */
    div{transform:scale(2)}

    /* New output (with --minify) */
    div{transform:scale3d(2,2,1)}
    ```

-   Minification now takes advantage of the `?.` operator

    This adds new code minification rules that shorten code with the `?.` optional chaining operator when the result is equivalent:

    ```ts
    // Original code
    let foo = (x) => {
      if (x !== null && x !== undefined) x.y()
      return x === null || x === undefined ? undefined : x.z
    }

    // Old output (with --minify)
    let foo=n=>(n!=null&&n.y(),n==null?void 0:n.z);

    // New output (with --minify)
    let foo=n=>(n?.y(),n?.z);
    ```

    This only takes effect when minification is enabled and when the configured target environment is known to support the optional chaining operator. As always, make sure to set `--target=` to the appropriate language target if you are running the minified code in an environment that doesn't support the latest JavaScript features.

-   Add source mapping information for some non-executable tokens ([#&#8203;1448](https://togithub.com/evanw/esbuild/issues/1448))

    Code coverage tools can generate reports that tell you if any code exists that has not been run (or "covered") during your tests. You can use this information to add additional tests for code that isn't currently covered.

    Some popular JavaScript code coverage tools have bugs where they incorrectly consider lines without any executable code as uncovered, even though there's no test you could possibly write that would cause those lines to be executed. For example, they apparently complain about the lines that only contain the trailing `}` token of an object literal.

    With this release, esbuild now generates source mappings for some of these trailing non-executable tokens. This may not successfully work around bugs in code coverage tools because there are many non-executable tokens in JavaScript and esbuild doesn't map them all (the drawback of mapping these extra tokens is that esbuild will use more memory, build more slowly, and output a bigger source map). The true solution is to fix the bugs in the code coverage tools in the first place.

-   Fall back to WebAssembly on Android x64 ([#&#8203;2068](https://togithub.com/evanw/esbuild/issues/2068))

    Go's compiler supports trivial cross-compiling to almost all platforms without installing any additional software other than the Go compiler itself. This has made it very easy for esbuild to publish native binary executables for many platforms. However, it strangely doesn't support cross-compiling to Android x64 without installing the Android build tools. So instead of publishing a native esbuild binary executable to npm, this release publishes a WebAssembly fallback build. This is essentially the same as the `esbuild-wasm` package but it's installed automatically when you install the `esbuild` package on Android x64. So packages that depend on the `esbuild` package should now work on Android x64. If you want to use a native binary executable of esbuild on Android x64, you may be able to build it yourself from source after installing the Android build tools.

-   Update to Go 1.17.8

    The version of the Go compiler used to compile esbuild has been upgraded from Go 1.17.7 to Go 1.17.8, which fixes the RISC-V 64-bit build. Compiler optimizations for the RISC-V 64-bit build have now been re-enabled.

### [`v0.14.24`](https://togithub.com/evanw/esbuild/releases/v0.14.24)

[Compare Source](https://togithub.com/evanw/esbuild/compare/v0.14.23...v0.14.24)

-   Allow `es2022` as a target environment ([#&#8203;2012](https://togithub.com/evanw/esbuild/issues/2012))

    TypeScript recently [added support for `es2022`](https://devblogs.microsoft.com/typescript/announcing-typescript-4-6/#target-es2022) as a compilation target so esbuild now supports this too. Support for this is preliminary as there is no published ES2022 specification yet (i.e. https://tc39.es/ecma262/2021/ exists but https://tc39.es/ecma262/2022/ is a 404 error). The meaning of esbuild's `es2022` target may change in the future when the specification is finalized. Right now I have made the `es2022` target enable support for the syntax-related [finished proposals](https://togithub.com/tc39/proposals/blob/main/finished-proposals.md) that are marked as `2022`:

    -   Class fields
    -   Class private members
    -   Class static blocks
    -   Ergonomic class private member checks
    -   Top-level await

    I have also included the "arbitrary module namespace names" feature since I'm guessing it will end up in the ES2022 specification (this syntax feature was added to the specification without a proposal). TypeScript has [not added support for this yet](https://togithub.com/microsoft/TypeScript/issues/40594).

-   Match `define` to strings in index expressions ([#&#8203;2050](https://togithub.com/evanw/esbuild/issues/2050))

    With this release, configuring `--define:foo.bar=baz` now matches and replaces both `foo.bar` and `foo['bar']` expressions in the original source code. This is necessary for people who have enabled TypeScript's [`noPropertyAccessFromIndexSignature` feature](https://www.typescriptlang.org/tsconfig#noPropertyAccessFromIndexSignature), which prevents you from using normal property access syntax on a type with an index signature such as in the following code:

    ```ts
    declare let foo: { [key: string]: any }
    foo.bar // This is a type error if noPropertyAccessFromIndexSignature is enabled
    foo['bar']
    ```

    Previously esbuild would generate the following output with `--define:foo.bar=baz`:

    ```js
    baz;
    foo["bar"];
    ```

    Now esbuild will generate the following output instead:

    ```js
    baz;
    baz;
    ```

-   Add `--mangle-quoted` to mangle quoted properties ([#&#8203;218](https://togithub.com/evanw/esbuild/issues/218))

    The `--mangle-props=` flag tells esbuild to automatically rename all properties matching the provided regular expression to shorter names to save space. Previously esbuild never modified the contents of string literals. In particular, `--mangle-props=_` would mangle `foo._bar` but not `foo['_bar']`. There are some coding patterns where renaming quoted property names is desirable, such as when using TypeScript's [`noPropertyAccessFromIndexSignature` feature](https://www.typescriptlang.org/tsconfig#noPropertyAccessFromIndexSignature) or when using TypeScript's [discriminated union narrowing behavior](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#discriminated-unions):

    ```ts
    interface Foo { _foo: string }
    interface Bar { _bar: number }
    declare const value: Foo | Bar
    console.log('_foo' in value ? value._foo : value._bar)
    ```

    The `'_foo' in value` check tells TypeScript to narrow the type of `value` to `Foo` in the true branch and to `Bar` in the false branch. Previously esbuild didn't mangle the property name `'_foo'` because it was inside a string literal. With this release, you can now use `--mangle-quoted` to also rename property names inside string literals:

    ```js
    // Old output (with --mangle-props=_)
    console.log("_foo" in value ? value.a : value.b);

    // New output (with --mangle-props=_ --mangle-quoted)
    console.log("a" in value ? value.a : value.b);
    ```

-   Parse and discard TypeScript `export as namespace` statements ([#&#8203;2070](https://togithub.com/evanw/esbuild/issues/2070))

    TypeScript `.d.ts` type declaration files can sometimes contain statements of the form `export as namespace foo;`. I believe these serve to declare that the module adds a property of that name to the global object. You aren't supposed to feed `.d.ts` files to esbuild so this normally doesn't matter, but sometimes esbuild can end up having to parse them. One such case is if you import a type-only package who's `main` field in `package.json` is a `.d.ts` file.

    Previously esbuild only allowed `export as namespace` statements inside a `declare` context:

    ```ts
    declare module Foo {
      export as namespace foo;
    }
    ```

    Now esbuild will also allow these statements outside of a `declare` context:

    ```ts
    export as namespace foo;
    ```

    These statements are still just ignored and discarded.

-   Strip import assertions from unrecognized `import()` expressions ([#&#8203;2036](https://togithub.com/evanw/esbuild/issues/2036))

    The new "import assertions" JavaScript language feature adds an optional second argument to dynamic `import()` expressions, which esbuild does support. However, this optional argument must be stripped when targeting older JavaScript environments for which this second argument would be a syntax error. Previously esbuild failed to strip this second argument in cases when the first argument to `import()` wasn't a string literal. This problem is now fixed:

    ```js
    // Original code
    console.log(import(foo, { assert: { type: 'json' } }))

    // Old output (with --target=es6)
    console.log(import(foo, { assert: { type: "json" } }));

    // New output (with --target=es6)
    console.log(import(foo));
    ```

-   Remove simplified statement-level literal expressions ([#&#8203;2063](https://togithub.com/evanw/esbuild/issues/2063))

    With this release, esbuild now removes simplified statement-level expressions if the simplified result is a literal expression even when minification is disabled. Previously this was only done when minification is enabled. This change was only made because some people are bothered by seeing top-level literal expressions. This change has no effect on code behavior.

-   Ignore `.d.ts` rules in `paths` in `tsconfig.json` files ([#&#8203;2074](https://togithub.com/evanw/esbuild/issues/2074), [#&#8203;2075](https://togithub.com/evanw/esbuild/pull/2075))

    TypeScript's `tsconfig.json` configuration file has a `paths` field that lets you remap import paths to alternative files on the file system. This field is interpreted by esbuild during bundling so that esbuild's behavior matches that of the TypeScript type checker. However, people sometimes override import paths to JavaScript files to instead point to a `.d.ts` TypeScript type declaration file for that JavaScript file. The intent of this is to just use the remapping for type information and not to actually import the `.d.ts` file during the build.

    With this release, esbuild will now ignore rules in `paths` that result in a `.d.ts` file during path resolution. This means code that does this should now be able to be bundled without modifying its `tsconfig.json` file to remove the `.d.ts` rule. This change was contributed by [@&#8203;magic-akari](https://togithub.com/magic-akari).

-   Disable Go compiler optimizations for the Linux RISC-V 64bit build ([#&#8203;2035](https://togithub.com/evanw/esbuild/pull/2035))

    Go's RISC-V 64bit compiler target has a fatal compiler optimization bug that causes esbuild to crash when it's run: [https://github.com/golang/go/issues/51101](https://togithub.com/golang/go/issues/51101). As a temporary workaround until a version of the Go compiler with the fix is published, Go compiler optimizations have been disabled for RISC-V. The 7.7mb esbuild binary executable for RISC-V is now 8.7mb instead. This workaround was contributed by [@&#8203;piggynl](https://togithub.com/piggynl).

### [`v0.14.23`](https://togithub.com/evanw/esbuild/releases/v0.14.23)

[Compare Source](https://togithub.com/evanw/esbuild/compare/v0.14.22...v0.14.23)

-   Update feature database to indicate that node 16.14+ supports import assertions ([#&#8203;2030](https://togithub.com/evanw/esbuild/issues/2030))

    Node versions 16.14 and above now support import assertions according to [these release notes](https://togithub.com/nodejs/node/blob/6db686710ee1579452b2908a7a41b91cb729b944/doc/changelogs/CHANGELOG_V16.md#&#8203;16.14.0). This release updates esbuild's internal feature compatibility database with this information, so esbuild no longer strips import assertions with `--target=node16.14`:

    ```js
    // Original code
    import data from './package.json' assert { type: 'json' }
    console.log(data)

    // Old output (with --target=node16.14)
    import data from "./package.json";
    console.log(data);

    // New output (with --target=node16.14)
    import data from "./package.json" assert { type: "json" };
    console.log(data);
    ```

-   Basic support for CSS `@layer` rules ([#&#8203;2027](https://togithub.com/evanw/esbuild/issues/2027))

    This adds basic parsing support for a new CSS feature called `@layer` that changes how the CSS cascade works. Adding parsing support for this rule to esbuild means esbuild can now minify the contents of `@layer` rules:

    ```css
    /* Original code */
    @&#8203;layer a {
      @&#8203;layer b {
        div {
          color: yellow;
          margin: 0.0px;
        }
      }
    }

    /* Old output (with --minify) */
    @&#8203;layer a{@&#8203;layer b {div {color: yellow; margin: 0px;}}}

    /* New output (with --minify) */
    @&#8203;layer a.b{div{color:#ff0;margin:0}}
    ```

    You can read more about `@layer` here:

    -   Documentation: https://developer.mozilla.org/en-US/docs/Web/CSS/[@&#8203;layer](https://togithub.com/layer)
    -   Motivation: https://developer.chrome.com/blog/cascade-layers/

    Note that the support added in this release is only for parsing and printing `@layer` rules. The bundler does not yet know about these rules and bundling with `@layer` may result in behavior changes since these new rules have unusual ordering constraints that behave differently than all other CSS rules. Specifically the order is derived from the *first* instance while with every other CSS rule, the order is derived from the *last* instance.

### [`v0.14.22`](https://togithub.com/evanw/esbuild/releases/v0.14.22)

[Compare Source](https://togithub.com/evanw/esbuild/compare/v0.14.21...v0.14.22)

-   Preserve whitespace for token lists that look like CSS variable declarations ([#&#8203;2020](https://togithub.com/evanw/esbuild/issues/2020))

    Previously esbuild removed the whitespace after the CSS variable declaration in the following CSS:

    ```css
    /* Original input */
    @&#8203;supports (--foo: ){html{background:green}}

    /* Previous output */
    @&#8203;supports (--foo:){html{background:green}}
    ```

    However, that broke rendering in Chrome as it caused Chrome to ignore the entire rule. This did not break rendering in Firefox and Safari, so there's a browser bug either with Chrome or with both Firefox and Safari. In any case, esbuild now preserves whitespace after the CSS variable declaration in this case.

-   Ignore legal comments when merging adjacent duplicate CSS rules ([#&#8203;2016](https://togithub.com/evanw/esbuild/issues/2016))

    This release now generates more compact minified CSS when there are legal comments in between two adjacent rules with identical content:

    ```css
    /* Original code */
    a { color: red }
    /* @&#8203;preserve */
    b { color: red }

    /* Old output (with --minify) */
    a{color:red}/* @&#8203;preserve */b{color:red}

    /* New output (with --minify) */
    a,b{color:red}/* @&#8203;preserve */
    ```

-   Block `onResolve` and `onLoad` until `onStart` ends ([#&#8203;1967](https://togithub.com/evanw/esbuild/issues/1967))

    This release changes the semantics of the `onStart` callback. All `onStart` callbacks from all plugins are run concurrently so that a slow plugin doesn't hold up the entire build. That's still the case. However, previously the only thing waiting for the `onStart` callbacks to finish was the end of the build. This meant that `onResolve` and/or `onLoad` callbacks could sometimes run before `onStart` had finished. This was by design but violated user expectations. With this release, all `onStart` callbacks must finish before any `onResolve` and/or `onLoad` callbacks are run.

-   Add a self-referential `default` export to the JS API ([#&#8203;1897](https://togithub.com/evanw/esbuild/issues/1897))

    Some people try to use esbuild's API using `import esbuild from 'esbuild'` instead of `import * as esbuild from 'esbuild'` (i.e. using a default import instead of a namespace import). There is no `default` export so that wasn't ever intended to work. But it would work sometimes depending on which tools you used and how they were configured so some people still wrote code this way. This release tries to make that work by adding a self-referential `default` export that is equal to esbuild's module namespace object.

    More detail: The published package for esbuild's JS API is in CommonJS format, although the source code for esbuild's JS API is in ESM format. The original ESM code for esbuild's JS API has no export named `default` so using a default import like this doesn't work with Babel-compatible toolchains (since they respect the semantics of the original ESM code). However, it happens to work with node-compatible toolchains because node's implementation of importing CommonJS from ESM broke compatibility with existing conventions and automatically creates a `default` export which is set to `module.exports`. This is an unfortunate compatibility headache because it means the `default` import only works sometimes. This release tries to fix this by explicitly creating a self-referential `default` export. It now doesn't matter if you do `esbuild.build()`, `esbuild.default.build()`, or `esbuild.default.default.build()` because they should all do the same thing. Hopefully this means people don't have to deal with this problem anymore.

-   Handle `write` errors when esbuild's child process is killed ([#&#8203;2007](https://togithub.com/evanw/esbuild/issues/2007))

    If you type Ctrl+C in a terminal when a script that uses esbuild's JS library is running, esbuild's child process may be killed before the parent process. In that case calls to the `write()` syscall may fail with an `EPIPE` error. Previously this resulted in an uncaught exception because esbuild didn't handle this case. Starting with this release, esbuild should now catch these errors and redirect them into a general `The service was stopped` error which should be returned from whatever top-level API calls were in progress.

-   Better error message when browser WASM bugs are present ([#&#8203;1863](https://togithub.com/evanw/esbuild/issues/1863))

    Safari's WebAssembly implementation appears to be broken somehow, at least when running esbuild. Sometimes this manifests as a stack overflow and sometimes as a Go panic. Previously a Go panic resulted in the error message `Can't find variable: fs` but this should now result in the Go panic being printed to the console. Using esbuild's WebAssembly library in Safari is still broken but now there's a more helpful error message.

    More detail: When Go panics, it prints a stack trace to stderr (i.e. file descriptor 2). Go's WebAssembly shim calls out to node's `fs.writeSync()` function to do this, and it converts calls to `fs.writeSync()` into calls to `console.log()` in the browser by providing a shim for `fs`. However, Go's shim code stores the shim on `window.fs` in the browser. This is undesirable because it pollutes the global scope and leads to brittle code that can break if other code also uses `window.fs`. To avoid this, esbuild shadows the global object by wrapping Go's shim. But that broke bare references to `fs` since the shim is no longer stored on `window.fs`. This release now stores the shim in a local variable named `fs` so that bare references to `fs` work correctly.

-   Undo incorrect dead-code elimination with destructuring ([#&#8203;1183](https://togithub.com/evanw/esbuild/issues/1183))

    Previously esbuild eliminated these statements as dead code if tree-shaking was enabled:

    ```js
    let [a] = {}
    let { b } = null
    ```

    This is incorrect because both of these lines will throw an error when evaluated. With this release, esbuild now preserves these statements even when tree shaking is enabled.

-   Update to Go 1.17.7

    The version of the Go compiler used to compile esbuild has been upgraded from Go 1.17.6 to Go 1.17.7, which contains a few [compiler and security bug fixes](https://togithub.com/golang/go/issues?q=milestone%3AGo1.17.7+label%3ACherryPickApproved).

### [`v0.14.21`](https://togithub.com/evanw/esbuild/releases/v0.14.21)

[Compare Source](https://togithub.com/evanw/esbuild/compare/v0.14.20...v0.14.21)

-   Handle an additional `browser` map edge case ([#&#8203;2001](https://togithub.com/evanw/esbuild/pull/2001), [#&#8203;2002](https://togithub.com/evanw/esbuild/issues/2002))

    There is a community convention around the `browser` field in `package.json` that allows remapping import paths within a package when the package is bundled for use within a browser. There isn't a rigorous definition of how it's supposed to work and every bundler implements it differently. The approach esbuild uses is to try to be "maximally compatible" in that if at least one bundler exhibits a particular behavior regarding the `browser` map that allows a mapping to work, then esbuild also attempts to make that work.

    I have a collection of test cases for this going here: https://github.com/evanw/package-json-browser-tests. However, I was missing test coverage for the edge case where a package path import in a subdirectory of the package could potentially match a remapping. The "maximally compatible" approach means replicating bugs in Browserify's implementation of the feature where package paths are mistaken for relative paths and are still remapped. Here's a specific example of an edge case that's now handled:

    -   `entry.js`:

        ```js
        require('pkg/sub')
        ```

    -   `node_modules/pkg/package.json`:

        ```json
        {
          "browser": {
            "./sub": "./sub/foo.js",
            "./sub/sub": "./sub/bar.js"
          }
        }
        ```

    -   `node_modules/pkg/sub/foo.js`:

        ```js
        require('sub')
        ```

    -   `node_modules/pkg/sub/bar.js`:

        ```js
        console.log('works')
        ```

    The import path `sub` in `require('sub')` is mistaken for a relative path by Browserify due to a bug in Browserify, so Browserify treats it as if it were `./sub` instead. This is a Browserify-specific behavior and currently doesn't happen in any other bundler (except for esbuild, which attempts to replicate Browserify's bug).

    Previously esbuild was incorrectly resolving `./sub` relative to the top-level package directory instead of to the subdirectory in this case, which meant `./sub` was incorrectly matching `"./sub": "./sub/foo.js"` instead of `"./sub/sub": "./sub/bar.js"`. This has been fixed so esbuild can now emulate Browserify's bug correctly in this edge case.

-   Support for esbuild with Linux on RISC-V 64bit ([#&#8203;2000](https://togithub.com/evanw/esbuild/pull/2000))

    With this release, esbuild now has a published binary executable for the RISC-V 64bit architecture in the [`esbuild-linux-riscv64`](https://www.npmjs.com/package/esbuild-linux-riscv64) npm package. This change was contributed by [@&#8203;piggynl](https://togithub.com/piggynl).

### [`v0.14.20`](https://togithub.com/evanw/esbuild/releases/v0.14.20)

[Compare Source](https://togithub.com/evanw/esbuild/compare/v0.14.19...v0.14.20)

-   Fix property mangling and keyword properties ([#&#8203;1998](https://togithub.com/evanw/esbuild/issues/1998))

    Previously enabling property mangling with `--mangle-props=` failed to add a space before property names after a keyword. This bug has been fixed:

    ```js
    // Original code
    class Foo {
      static foo = {
        get bar() {}
      }
    }

    // Old output (with --minify --mangle-props=.)
    class Foo{statics={gett(){}}}

    // New output (with --minify --mangle-props=.)
    class Foo{static s={get t(){}}}
    ```

### [`v0.14.19`](https://togithub.com/evanw/esbuild/releases/v0.14.19)

[Compare Source](https://togithub.com/evanw/esbuild/compare/v0.14.18...v0.14.19)

-   Special-case `const` inlining at the top of a scope ([#&#8203;1317](https://togithub.com/evanw/esbuild/issues/1317), [#&#8203;1981](https://togithub.com/evanw/esbuild/issues/1981))

    The minifier now inlines `const` variables (even across modules during bundling) if a certain set of specific requirements are met:

    -   All `const` variables to be inlined are at the top of their scope
    -   That scope doesn't contain any `import` or `export` statements with paths
    -   All constants to be inlined are `null`, `undefined`, `true`, `false`, an integer, or a short real number
    -   Any expression outside of a small list of allowed ones stops constant identification

    Practically speaking this basically means that you can trigger this optimization by just putting the constants you want inlined into a separate file (e.g. `constants.js`) and bundling everything together.

    These specific conditions are present to avoid esbuild unintentionally causing any behavior changes by inlining constants when the variable reference could potentially be evaluated before being declared. It's possible to identify more cases where constants can be inlined but doing so may require complex call graph analysis so it has not been implemented. Although these specific heuristics may change over time, this general approach to constant inlining should continue to work going forward.

    Here's an example:

    ```js
    // Original code
    const bold = 1 << 0;
    const italic = 1 << 1;
    const underline = 1 << 2;
    const font = bold | italic | underline;
    console.log(font);

    // Old output (with --minify --bundle)
    (()=>{var o=1<<0,n=1<<1,c=1<<2,t=o|n|c;console.log(t);})();

    // New output (with --minify --bundle)
    (()=>{console.log(7);})();
    ```

### [`v0.14.18`](https://togithub.com/evanw/esbuild/releases/v0.14.18)

[Compare Source](https://togithub.com/evanw/esbuild/compare/v0.14.17...v0.14.18)

-   Add the `--mangle-cache=` feature ([#&#8203;1977](https://togithub.com/evanw/esbuild/issues/1977))

    This release adds a cache API for the newly-released `--mangle-props=` feature. When enabled, all mangled property renamings are recorded in the cache during the initial build. Subsequent builds reuse the renamings stored in the cache and add additional renamings for any newly-added properties. This has a few consequences:

    -   You can customize what mangled properties are renamed to by editing the cache before passing it to esbuild (the cache is a map of the original name to the mangled name).

    -   The cache serves as a list of all properties that were mangled. You can easily scan it to see if there are any unexpected property renamings.

    -   You can disable mangling for individual properties by setting the renamed value to `false` instead of to a string. This is similar to the `--reserve-props=` setting but on a per-property basis.

    -   You can ensure consistent renaming between builds (e.g. a main-thread file and a web worker, or a library and a plugin). Without this feature, each build would do an independent renaming operation and the mangled property names likely wouldn't be consistent.

    Here's how to use it:

    -   CLI

        ```sh
        $ esbuild example.ts --mangle-props=_$ --mangle-cache=cache.json
        ```

    -   JS API

        ```js
        let result = await esbuild.build({
          entryPoints: ['example.ts'],
          mangleProps: /_$/,
          mangleCache: {
            customRenaming_: '__c',
            disabledRenaming_: false,
          },
        })
        let updatedMangleCache = result.mangleCache
        ```

    -   Go API

        ```go
        result := api.Build(api.BuildOptions{
          EntryPoints: []string{"example.ts"},
          MangleProps: "_$",
          MangleCache: map[string]interface{}{
            "customRenaming_":   "__c",
            "disabledRenaming_": false,
          },
        })
        updatedMangleCache := result.MangleCache
        ```

    The above code would do something like the following:

    ```js
    // Original code
    x = {
      customRenaming_: 1,
      disabledRenaming_: 2,
      otherProp_: 3,
    }

    // Generated code
    x = {
      __c: 1,
      disabledRenaming_: 2,
      a: 3
    };

    // Updated mangle cache
    {
      "customRenaming_": "__c",
      "disabledRenaming_": false,
      "otherProp_": "a"
    }
    ```

-   Add `opera` and `ie` as possible target environments

    You can now target [Opera](https://www.opera.com/) and/or [Internet Explorer](https://www.microsoft.com/en-us/download/internet-explorer.aspx) using the `--target=` setting. For example, `--target=opera45,ie9` targets Opera 45 and Internet Explorer 9. This change does not add any additional features to esbuild's code transformation pipeline to transform newer syntax so that it works in Internet Explorer. It just adds information about what features are supported in these browsers to esbuild's internal feature compatibility table.

-   Minify `typeof x !== 'undefined'` to `typeof x < 'u'`

    This release introduces a small improvement for code that does a lot of `typeof` checks against `undefined`:

    ```js
    // Original code
    y = typeof x !== 'undefined';

    // Old output (with --minify)
    y=typeof x!="undefined";

    // New output (with --minify)
    y=typeof x<"u";
    ```

    This transformation is only active when minification is enabled, and is disabled if the language target is set lower than ES2020 or if Internet Explorer is set as a target environment. Before ES2020, implementations were allowed to return non-standard values from the `typeof` operator for a few objects. Internet Explorer took advantage of this to sometimes return the string `'unknown'` instead of `'undefined'`. But this has been removed from the specification and Internet Explorer was the only engine to do this, so this minification is valid for code that does not need to target Internet Explorer.

### [`v0.14.17`](https://togithub.com/evanw/esbuild/releases/v0.14.17)

[Compare Source](https://togithub.com/evanw/esbuild/compare/v0.14.16...v0.14.17)

-   Attempt to fix an install script issue on Ubuntu Linux ([#&#8203;1711](https://togithub.com/evanw/esbuild/issues/1711))

    There have been some reports of esbuild failing to install on Ubuntu Linux for a while now. I haven't been able to reproduce this myself due to lack of reproduction instructions until today, when I learned that the issue only happens when you install node from the [Snap Store](https://snapcraft.io/) instead of downloading the [official version of node](https://nodejs.org/dist/).

    The problem appears to be that when node is installed from the Snap Store, install scripts are run with stderr not being writable? This then appears to cause a problem for esbuild's install script when it uses `execFileSync` to validate that the esbuild binary is working correctly. This throws the error `EACCES: permission denied, write` even though this particular command never writes to stderr.

    Node's documentation says that stderr for `execFileSync` defaults to that of the parent process. Forcing it to `'pipe'` instead appears to fix the issue, although I still don't fully understand what's happening or why. I'm publishing this small change regardless to see if it fixes this install script edge case.

-   Avoid a syntax error due to `--mangle-props=.` and `super()` ([#&#8203;1976](https://togithub.com/evanw/esbuild/issues/1976))

    This release fixes an issue where passing `--mangle-props=.` (i.e. telling esbuild to mangle every single property) caused a syntax error with code like this:

    ```js
    class Foo {}
    class Bar extends Foo {
      constructor() {
        super();
      }
    }
    ```

    The problem was that `constructor` was being renamed to another method, which then made it no longer a constructor, which meant that `super()` was now a syntax error. I have added a workaround that avoids renaming any property named `constructor` so that esbuild doesn't generate a syntax error here.

    Despite this fix, I highly recommend not using `--mangle-props=.` because your code will almost certainly be broken. You will have to manually add every single property that you don't want mangled to `--reserve-props=` which is an excessive maintenance burden (e.g. reserve `parse` to use `JSON.parse`). Instead I recommend using a common pattern for all properties you intend to be mangled that is unlikely to appear in the APIs you use such as "ends in an underscore." This is an opt-in approach instead of an opt-out approach. It also makes it obvious when reading the code which properties will be mangled and which ones won't be.

### [`v0.14.16`](https://togithub.com/evanw/esbuild/releases/v0.14.16)

[Compare Source](https://togithub.com/evanw/esbuild/compare/v0.14.15...v0.14.16)

-   Support property name mangling with some TypeScript syntax features

    The newly-released `--mangle-props=` feature previously only affected JavaScript syntax features. This release adds support for using mangle props with certain TypeScript syntax features:

    -   **TypeScript parameter properties**

        Parameter properties are a TypeScript-only shorthand way of initializing a class field directly from the constructor argument list. Previously parameter properties were not treated as properties to be mangled. They should now be handled correctly:

        ```ts
        // Original code
        class Foo {
          constructor(public foo_) {}
        }
        new Foo().foo_;

        // Old output (with --minify --mangle-props=_)
        class Foo{constructor(c){this.foo_=c}}new Foo().o;

        // New output (with --minify --mangle-props=_)
        class Foo{constructor(o){this.c=o}}new Foo().c;
        ```

    -   **TypeScript namespaces**

        Namespaces are a TypeScript-only way to add properties to an object. Previously exported namespace members were not treated as properties to be mangled. They should now be handled correctly:

        ```ts
        // Original code
        namespace ns {
          export let foo_ = 1;
          export function bar_(x) {}
        }
        ns.bar_(ns.foo_);

        // Old output (with --minify --mangle-props=_)
        var ns;(e=>{e.foo_=1;function t(a){}e.bar_=t})(ns||={}),ns.e(ns.o);

        // New output (with --minify --mangle-props=_)
        var ns;(e=>{e.e=1;function o(p){}e.t=o})(ns||={}),ns.t(ns.e);
        ```

-   Fix property name mangling for lowered class fields

    This release fixes a compiler crash with `--mangle-props=` and class fields that need to be transformed to older versions of JavaScript. The problem was that doing this is an unusual case where the mangled property name must be represented as a string instead of as a property name, which previously wasn't implemented. This case should now work correctly:

    ```js
    // Original code
    class Foo {
      static foo_;
    }
    Foo.foo_ = 0;

    // New output (with --mangle-props=_ --target=es6)
    class Foo {
    }
    __publicField(Foo, "a");
    Foo.a = 0;
    ```

### [`v0.14.15`](https://togithub.com/evanw/esbuild/releases/v0.14.15)

[Compare Source](https://togithub.com/evanw/esbuild/compare/v0.14.14...v0.14.15)

-   Add property name mangling with `--mangle-props=` ([#&#8203;218](https://togithub.com/evanw/esbuild/issues/218))

    ⚠️ **Using this feature can break your code in subtle ways.** Do not use this feature unless you know what you are doing, and you know exactly how it will affect both your code and all of your dependencies. ⚠️

    This release introduces property name mangling, which is similar to an existing feature from the popular [UglifyJS](github.com/mishoo/uglifyjs) and [Terser](github.com/terser/terser) JavaScript minifiers. This setting lets you pass a regular expression to esbuild to tell esbuild to automatically rename all properties that match this regular expression. It's useful when you want to minify certain property names in your code either to make the generated code smaller or to somewhat obfuscate your code's intent.

    Here's an example that uses the regular expression `_[![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [github.com/evanw/esbuild](https://togithub.com/evanw/esbuild) | require | patch | `v0.14.2` -> `v0.14.25` |
| [github.com/goccy/go-yaml](https://togithub.com/goccy/go-yaml) | require | patch | `v1.9.4` -> `v1.9.5` |
| [github.com/mitchellh/mapstructure](https://togithub.com/mitchellh/mapstructure) | require | minor | `v1.1.2` -> `v1.4.3` |

---

 to mangle all properties ending in an underscore, such as `foo_`:

        $ echo 'console.log({ foo_: 0 }.foo_)' | esbuild --mangle-props=_$
        console.log({ a: 0 }.a);

    Only mangling properties that end in an underscore is a reasonable heuristic because normal JS code doesn't typically contain identifiers like that. Browser APIs also don't use this naming convention so this also avoids conflicts with browser APIs. If you want to avoid mangling names such as [`__defineGetter__`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/\__defineGetter\_\_) you could consider using a more complex regular expression such as `[^_]_[![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [github.com/evanw/esbuild](https://togithub.com/evanw/esbuild) | require | patch | `v0.14.2` -> `v0.14.25` |
| [github.com/goccy/go-yaml](https://togithub.com/goccy/go-yaml) | require | patch | `v1.9.4` -> `v1.9.5` |
| [github.com/mitchellh/mapstructure](https://togithub.com/mitchellh/mapstructure) | require | minor | `v1.1.2` -> `v1.4.3` |

---

 (i.e. must end in a non-underscore followed by an underscore).

    This is a separate setting instead of being part of the minify setting because it's an unsafe transformation that does not work on arbitrary JavaScript code. It only works if the provided regular expression matches all of the properties that you want mangled and does not match any of the properties that you don't want mangled. It also only works if you do not under any circumstances reference a property name to be mangled as a string. For example, it means you can't use `Object.defineProperty(obj, 'prop', ...)` or `obj['prop']` with a mangled property. Specifically the following syntax constructs are the only ones eligible for property mangling:

    | Syntax                          | Example                 |
    |---------------------------------|-------------------------|
    | Dot property access             | `x.foo_`                |
    | Dot optional chain              | `x?.foo_`               |
    | Object properties               | `x = { foo_: y }`       |
    | Object methods                  | `x = { foo_() {} }`     |
    | Class fields                    | `class x { foo_ = y }`  |
    | Class methods                   | `class x { foo_() {} }` |
    | Object destructuring binding    | `let { foo_: x } = y`   |
    | Object destructuring assignment | `({ foo_: x } = y)`     |
    | JSX element names               | `<X.foo_></X.foo_>`     |
    | JSX attribute names             | `<X foo_={y} />`        |

    You can avoid property mangling for an individual property by quoting it as a string. However, you must consistently use quotes or no quotes for a given property everywhere for this to work. For example, `print({ foo_: 0 }.foo_)` will be mangled into `print({ a: 0 }.a)` while `print({ 'foo_': 0 }['foo_'])` will not be mangled.

    When using this feature, keep in mind that property names are only consistently mangled within a single esbuild API call but not across esbuild API calls. Each esbuild API call does an independent property mangling operation so output files generated by two different API calls may mangle the same property to two different names, which could cause the resulting code to behave incorrectly.

    If you would like to exclude certain properties from mangling, you can reserve them with the `--reserve-props=` setting. For example, this uses the regular expression `^__.*__[![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [github.com/evanw/esbuild](https://togithub.com/evanw/esbuild) | require | patch | `v0.14.2` -> `v0.14.25` |
| [github.com/goccy/go-yaml](https://togithub.com/goccy/go-yaml) | require | patch | `v1.9.4` -> `v1.9.5` |
| [github.com/mitchellh/mapstructure](https://togithub.com/mitchellh/mapstructure) | require | minor | `v1.1.2` -> `v1.4.3` |

---

 to reserve all properties that start and end with two underscores, such as `__foo__`:

        $ echo 'console.log({ __foo__: 0 }.__foo__)' | esbuild --mangle-props=_$
        console.log({ a: 0 }.a);

        $ echo 'console.log({ __foo__: 0 }.__foo__)' | esbuild --mangle-props=_$ "--reserve-props=^__.*__$"
        console.log({ __foo__: 0 }.__foo__);

-   Mark esbuild as supporting node v12+ ([#&#8203;1970](https://togithub.com/evanw/esbuild/issues/1970))

    Someone requested that esbuild populate the `engines.node` field in `package.json`. This release adds the following to each `package.json` file that esbuild publishes:

    ```json
    "engines": {
      "node": ">=12"
    },
    ```

    This was chosen because it's the oldest version of node that's currently still receiving support from the node team, and so is the oldest version of node that esbuild supports: https://nodejs.org/en/about/releases/.

-   Remove error recovery for invalid `//` comments in CSS ([#&#8203;1965](https://togithub.com/evanw/esbuild/issues/1965))

    Previously esbuild treated `//` as a comment in CSS and generated a warning, even though comments in CSS use `/* ... */` instead. This allowed you to run esbuild on CSS intended for certain CSS preprocessors that support single-line comments.

    However, some people are changing from another build tool to esbuild and have a code base that relies on `//` being preserved even though it's nonsense CSS and causes the entire surrounding rule to be discarded by the browser. Presumably this nonsense CSS ended up there at some point due to an incorrectly-configured build pipeline and the site now relies on that entire rule being discarded. If esbuild interprets `//` as a comment, it could cause the rule to no longer be discarded or even cause something else to happen.

    With this release, esbuild no longer treats `//` as a comment in CSS. It still warns about it but now passes it through unmodified. This means it's no longer possible to run esbuild on CSS code containing single-line comments but it means that esbuild's behavior regarding these nonsensical CSS rules more accurately represents what happens in a browser.

### [`v0.14.14`](https://togithub.com/evanw/esbuild/releases/v0.14.14)

[Compare Source](https://togithub.com/evanw/esbuild/compare/v0.14.13...v0.14.14)

-   Fix bug with filename hashes and the `file` loader ([#&#8203;1957](https://togithub.com/evanw/esbuild/issues/1957))

    This release fixes a bug where if a file name template has the `[hash]` placeholder (either `--entry-names=` or `--chunk-names=`), the hash that esbuild generates didn't include the content of the string generated by the `file` loader. Importing a file with the `file` loader causes the imported file to be copied to the output directory and causes the imported value to be the relative path from the output JS file to that copied file. This bug meant that if the `--asset-names=` setting also contained `[hash]` and the file loaded with the `file` loader was changed, the hash in the copied file name would change but the hash of the JS file would not change, which could potentially result in a stale JS file being loaded. Now the hash of the JS file will be changed too which fixes the reload issue.

-   Prefer the `import` condition for entry points ([#&#8203;1956](https://togithub.com/evanw/esbuild/issues/1956))

    The `exports` field in `package.json` maps package subpaths to file paths. The mapping can be conditional, which lets it vary in different situations. For example, you can have an `import` condition that applies when the subpath originated from a JS import statement, and a `require` condition that applies when the subpath originated from a JS require call. These are supposed to be mutually exclusive according to the specification: https://nodejs.org/api/packages.html#conditional-exports.

    However, there's a situation with esbuild where it's not immediately obvious which one should be applied: when a package name is specified as an entry point. For example, this can happen if you do `esbuild --bundle some-pkg` on the command line. In this situation `some-pkg` does not originate from either a JS import statement or a JS require call. Previously esbuild just didn't apply the `import` or `require` conditions. But that could result in path resolution failure if the package doesn't provide a back-up `default` condition, as is the case with the `is-plain-object` package.

    Starting with this release, esbuild will now use the `import` condition in this case. This appears to be how Webpack and Rollup handle this situation so this change makes esbuild consistent with other tools in the ecosystem. Parcel (the other major bundler) just doesn't handle this case at all so esbuild's behavior is not at odds with Parcel's behavior here.

-   Make parsing of invalid `@keyframes` rules more robust ([#&#8203;1959](https://togithub.com/evanw/esbuild/issues/1959))

    This improves esbuild's parsing of certain malformed `@keyframes` rules to avoid them affecting the following rule. This fix only affects invalid CSS files, and does not change any behavior for files containing valid CSS. Here's an example of the fix:

    ```css
    /* Original code */
    @&#8203;keyframes x { . }
    @&#8203;keyframes y { 1% { a: b; } }

    /* Old output (with --minify) */
    @&#8203;keyframes x{y{1% {a: b;}}}

    /* New output (with --minify) */
    @&#8203;keyframes x{.}@&#8203;keyframes y{1%{a:b}}
    ```

### [`v0.14.13`](https://togithub.com/evanw/esbuild/releases/v0.14.13)

[Compare Source](https://togithub.com/evanw/esbuild/compare/v0.14.12...v0.14.13)

-   Be more consistent about external paths ([#&#8203;619](https://togithub.com/evanw/esbuild/issues/619))

    The rules for marking paths as external using `--external:` grew over time as more special-cases were added. This release reworks the internal representation to be more straightforward and robust. A side effect is that wildcard patterns can now match post-resolve paths in addition to pre-resolve paths. Specifically you can now do `--external:./node_modules/*` to mark all files in the `./node_modules/` directory as external.

    This is the updated logic:

    -   Before path resolution begins, import paths are checked against everything passed via an `--external:` flag. In addition, if something looks like a package path (i.e. doesn't start with `/` or `./` or `../`), import paths are checked to see if they have that package path as a path prefix (so `--external:@&#8203;foo/bar` matches the import path `@foo/bar/baz`).

    -   After path resolution ends, the absolute paths are checked against everything passed via `--external:` that doesn't look like a package path (i.e. that starts with `/` or `./` or `../`). But before checking, the pattern is transformed to be relative to the current working directory.

-   Attempt to explain why esbuild can't run ([#&#8203;1819](https://togithub.com/evanw/esbuild/issues/1819))

    People sometimes try to install esbuild on one OS and then copy the `node_modules` directory over to another OS without reinstalling. This works with JavaScript code but doesn't work with esbuild because esbuild is a native binary executable. This release attempts to offer a helpful error message when this happens. It looks like this:

        $ ./node_modules/.bin/esbuild
        ./node_modules/esbuild/bin/esbuild:106
                  throw new Error(`
                  ^

        Error:
        You installed esbuild on another platform than the one you're currently using.
        This won't work because esbuild is written with native code and needs to
        install a platform-specific binary executable.

        Specifically the "esbuild-linux-arm64" package is present but this platform
        needs the "esbuild-darwin-arm64" package instead. People often get into this
        situation by installing esbuild on Windows or macOS and copying "node_modules"
        into a Docker image that runs Linux, or by copying "node_modules" between
        Windows and WSL environments.

        If you are installing with npm, you can try not copying the "node_modules"
        directory when you copy the files over, and running "npm ci" or "npm install"
        on the destination platform after the copy. Or you could consider using yarn
        instead which has built-in support for installing a package on multiple
        platforms simultaneously.

        If you are installing with yarn, you can try listing both this platform and the
        other platform in your ".yarnrc.yml" file using the "supportedArchitectures"
        feature: https://yarnpkg.com/configuration/yarnrc/#supportedArchitectures
        Keep in mind that this means multiple copies of esbuild will be present.

        Another alternative is to use the "esbuild-wasm" package instead, which works
        the same way on all platforms. But it comes with a heavy performance cost and
        can sometimes be 10x slower than the "esbuild" package, so you may also not
        want to do that.

            at generateBinPath (./node_modules/esbuild/bin/esbuild:106:17)
            at Object.<anonymous> (./node_modules/esbuild/bin/esbuild:161:39)
            at Module._compile (node:internal/modules/cjs/loader:1101:14)
            at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
            at Module.load (node:internal/modules/cjs/loader:981:32)
            at Function.Module._load (node:internal/modules/cjs/loader:822:12)
            at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
            at node:internal/main/run_main_module:17:47

### [`v0.14.12`](https://togithub.com/evanw/esbuild/releases/v0.14.12)

[Compare Source](https://togithub.com/evanw/esbuild/compare/v0.14.11...v0.14.12)

-   Ignore invalid `@import` rules in CSS ([#&#8203;1946](https://togithub.com/evanw/esbuild/issues/1946))

    In CSS, `@import` rules must come first before any other kind of rule (except for `@charset` rules). Previously esbuild would warn about incorrectly ordered `@import` rules and then hoist them to the top of the file. This broke people who wrote invalid `@import` rules in the middle of their files and then relied on them being ignored. With this release, esbuild will now ignore invalid `@import` rules and pass them through unmodified. This more accurately follows the CSS specification. Note that this behavior differs from other tools like Parcel, which does hoist CSS `@import` rules.

-   Print invalid CSS differently ([#&#8203;1947](https://togithub.com/evanw/esbuild/issues/1947))

    This changes how esbuild prints nested `@import` statements that are missing a trailing `;`, which is invalid CSS. The result is still partially invalid CSS, but now printed in a better-looking way:

    ```css
    /* Original code */
    .bad { @&#8203;import url("other") }
    .red { background: red; }

    /* Old output (with --minify) */
    .bad{@&#8203;import url(other) } .red{background: red;}}

    /* New output (with --minify) */
    .bad{@&#8203;import url(other);}.red{background:red}
    ```

-   Warn about CSS nesting syntax ([#&#8203;1945](https://togithub.com/evanw/esbuild/issues/1945))

    There's a proposed [CSS syntax for nesting rules](https://drafts.csswg.org/css-nesting/) using the `&` selector, but it's not currently implemented in any browser. Previously esbuild silently passed the syntax through untransformed. With this release, esbuild will now warn when you use nesting syntax with a `--target=` setting that includes a browser.

-   Warn about `}` and `>` inside JSX elements

    The `}` and `>` characters are invalid inside JSX elements according to [the JSX specification](https://facebook.github.io/jsx/) because they commonly result from typos like these that are hard to catch in code reviews:

    ```jsx
    function F() {
      return <div>></div>;
    }
    function G() {
      return <div>{1}}</div>;
    }
    ```

    The TypeScript compiler already [treats this as an error](https://togithub.com/microsoft/TypeScript/issues/36341), so esbuild now treats this as an error in TypeScript files too. That looks like this:

        ✘ [ERROR] The character ">" is not valid inside a JSX element

            example.tsx:2:14:
              2 │   return <div>></div>;
                │               ^
                ╵               {'>'}

          Did you mean to escape it as "{'>'}" instead?

        ✘ [ERROR] The character "}" is not valid inside a JSX element

            example.tsx:5:17:
              5 │   return <div>{1}}</div>;
                │                  ^
                ╵                  {'}'}

          Did you mean to escape it as "{'}'}" instead?

    Babel doesn't yet treat this as an error, so esbuild only warns about these characters in JavaScript files for now. Babel 8 [treats this as an error](https://togithub.com/babel/babel/issues/11042) but Babel 8 [hasn't been released yet](https://togithub.com/babel/babel/issues/10746). If you see this warning, I recommend fixing the invalid JSX syntax because it will become an error in the future.

-   Warn about basic CSS property typos

    This release now generates a warning if you use a CSS property that is one character off from a known CSS property:

        ▲ [WARNING] "marign-left" is not a known CSS property

            example.css:2:2:
              2 │   marign-left: 12px;
                │   ~~~~~~~~~~~
                ╵   margin-left

          Did you mean "margin-left" instead?

### [`v0.14.11`](https://togithub.com/evanw/esbuild/releases/v0.14.11)

[Compare Source](https://togithub.com/evanw/esbuild/compare/v0.14.10...v0.14.11)

-   Fix a bug with enum inlining ([#&#8203;1903](https://togithub.com/evanw/esbuild/issues/1903))

    The new TypeScript enum inlining behavior had a bug where it worked correctly if you used `export enum Foo` but not if you used `enum Foo` and then later `export { Foo }`. This release fixes the bug so enum inlining now works correctly in this case.

-   Warn about `module.exports.foo = ...` in ESM ([#&#8203;1907](https://togithub.com/evanw/esbuild/issues/1907))

    The `module` variable is treated as a global variable reference instead of as a CommonJS module reference in ESM code, which can cause problems for people that try to use both CommonJS and ESM exports in the same file. There has been a warning about this since version 0.14.9. However, the warning only covered cases like `exports.foo = bar` and `module.exports = bar` but not `module.exports.foo = bar`. This last case is now handled;

        ▲ [WARNING] The CommonJS "module" variable is treated as a global variable in an ECMAScript module and may not work as expected

            example.ts:2:0:
              2 │ module.exports.b = 1
                ╵ ~~~~~~

          This file is considered to be an ECMAScript module because of the "export" keyword here:

            example.ts:1:0:
              1 │ export let a = 1
                ╵ ~~~~~~

-   Enable esbuild's CLI with Deno ([#&#8203;1913](https://togithub.com/evanw/esbuild/issues/1913))

    This release allows you to use Deno as an esbuild installer, without also needing to use esbuild's JavaScript API. You can now use esbuild's CLI with Deno:

        deno run --allow-all "https://deno.land/x/esbuild@v0.14.11/mod.js" --version

### [`v0.14.10`](https://togithub.com/evanw/esbuild/releases/v0.14.10)

[Compare Source](https://togithub.com/evanw/esbuild/compare/v0.14.9...v0.14.10)

-   Enable tree shaking of classes with lowered static fields ([#&#8203;175](https://togithub.com/evanw/esbuild/issues/175))

    If the configured target environment doesn't support static class fields, they are converted into a call to esbuild's `__publicField` function instead. However, esbuild's tree-shaking pass treated this call as a side effect, which meant that all classes with static fields were ineligible for tree shaking. This release fixes the problem by explicitly ignoring calls to the `__publicField` function during tree shaking side-effect determination. Tree shaking is now enabled for these classes:

    ```js
    // Original code
    class Foo { static foo = 'foo' }
    class Bar { static bar = 'bar' }
    new Bar()

    // Old output (with --tree-shaking=true --target=es6)
    class Foo {
    }
    __publicField(Foo, "foo", "foo");
    class Bar {
    }
    __publicField(Bar, "bar", "bar");
    new Bar();

    // New output (with --tree-shaking=true --target=es6)
    class Bar {
    }
    __publicField(Bar, "bar", "bar");
    new Bar();
    ```

-   Treat `--define:foo=undefined` as an undefined literal instead of an identifier ([#&#8203;1407](https://togithub.com/evanw/esbuild/issues/1407))

    References to the global variable `undefined` are automatically replaced with the literal value for undefined, which appears as `void 0` when printed. This allows for additional optimizations such as collapsing `undefined ?? bar` into just `bar`. However, this substitution was not done for values specified via `--define:`. As a result, esbuild could potentially miss out on certain optimizations in these cases. With this release, it's now possible to use `--define:` to substitute something with an undefined literal:

    ```js
    // Original code
    let win = typeof window !== 'undefined' ? window : {}

    // Old output (with --define:window=undefined --minify)
    let win=typeof undefined!="undefined"?undefined:{};

    // New output (with --define:window=undefined --minify)
    let win={};
    ```

-   Add the `--drop:debugger` flag ([#&#8203;1809](https://togithub.com/evanw/esbuild/issues/1809))

    Passing this flag causes all [`debugger;` statements](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/St

</details>

---

### Configuration

📅 **Schedule**: 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.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://togithub.com/renovatebot/renovate/discussions) if that's undesired.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, click this checkbox.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
arch-riscv NeedsFix
Projects
None yet
Development

No branches or pull requests

6 participants