---
title: Bun v1.0.31
description: Fixes 54 bugs (addresses 113 👍 reactions), introduces `bun --print`, `<stdin> | bun run -`, `bun add --trust`, `fetch()` with Unix sockets, fixes macOS binary size regression, fixes high CPU usage bug in spawn() on older linux, adds `util.styleText`, Node.js compatibiltiy improvements, bun install bugfixes, and bunx bugfixes
date: "2024-03-14T22:19:59+00:00"
author: ashcon
draft: false
---

Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager &mdash; all in one.

Bun v1.0.31 fixes 54 bugs (addresses 113 👍 reactions), introduces `bun --print`, `<stdin> | bun run -`, `bun add --trust`, `fetch()` with Unix sockets, fixes macOS binary size regression, fixes high CPU usage bug in spawn() on older linux, adds `util.styleText`, Node.js compatibiltiy improvements, bun install bugfixes, and bunx bugfixes.

#### Previous releases

- [`v1.0.30`](/blog/bun-v1.0.30) fixes 27 bugs (addressing 103 👍 reactions), fixes an 8x perf regression to Bun.serve(), adds a new `--conditions` flag to `bun build` and Bun's runtime, adds support for `expect.assertions()` and `expect.hasAssertions()` in Bun's test runner, fixes crashes and improves Node.js compatibility.
- [`v1.0.29`](/blog/bun-v1.0.29) fixes 8 bugs. Bun.stringWidth(a) is a ~6,756x faster drop-in replacement for the popular 'string-width' package. bunx checks for updates more frequently. Adds expect().toBeOneOf() in bun:test. Memory leak impacting Prisma is fixed. Shell now supports advanced redirects like '2>&1', '&>'. Reliability improvements to bunx, bun install, WebSocket client, and Bun Shell
- [`v1.0.28`](/blog/bun-v1.0.28) fixes 6 bugs (addressing 26 👍 reactions). Fixes bugs impacting Prisma and Astro, `node:events`, `node:readline`, and `node:http2`. Fixes a bug in Bun Shell involving stdin redirection and fixes bugs in `bun:test` with `test.each` and `describe.only`.

#### To install Bun:

{% codetabs %}

```sh#curl
$ curl -fsSL https://bun.sh/install | bash
```

```sh#npm
$ npm install -g bun
```

```sh#brew
$ brew tap oven-sh/bun
$ brew install bun
```

```sh#docker
$ docker pull oven/bun
$ docker run --rm --init --ulimit memlock=-1:-1 oven/bun
```

{% /codetabs %}

#### To upgrade Bun:

```sh
$ bun upgrade
```

## New: `bun --print`

You can now use `bun --print` to evaluate the provided code and print the result using `console.log`. It's the same as `node --print`, except it supports top-level await, ESM, CommonJS, TypeScript, and JSX.

{% image src="https://github.com/oven-sh/bun/assets/3238291/785a956a-a446-47b8-8835-dcd3af1ad6db" alt="bun --print 'fetch(\"https://api.github.com/repos/bigskysoftware/htmx\").then(r => r.json())'" /%}

Bun will also await dangling promises so you don't need to append `await` to your code.

{% image src="https://github.com/oven-sh/bun/assets/3238291/619e3b3a-ec11-47ab-8723-c9a5c1bf4879" alt="bun --print 'fetch(\"https://api.github.com/repos/bigskysoftware/htmx\").then(r => r.json())'" /%}

For reference, here is an equivalent output using `node --print`:

{% image src="https://github.com/oven-sh/bun/assets/3238291/6e782e85-21c0-4539-81ec-76c29a4e4873" alt="node --print 'await fetch(\"https://api.github.com/repos/bigskysoftware/htmx\").then(r => r.json())'" /%}

We implemented this because many npm packages have `postinstall` scripts that call `node --print`, and we don't want `bun install` to have any issues when you don't have Node.js installed.

Thanks to [@dylan-conway](https://github.com/dylan-conway) for implementing this!

## New: Run code from stdin

You can now pipe stdin into Bun using `bun run -`. This is useful for running code from a file or a script.

{% image src="https://github.com/oven-sh/bun/assets/3238291/5c063b3c-a522-4ea8-803c-078cc76659f4 " caption="echo 'console.log(\"Hello\")' | bun run -" /%}

```sh
cat file.js | bun run -
bun run - < file.js
```

As usual in Bun, this works with top-level await, ESM, CommonJS, TypeScript, and JSX.

Thanks to [@nektro](https://github.com/nektro) for adding this feature!

## New: `bun add --trust <package>`

We've made improvements to how Bun handles [`trustedDependencies`](https://bun.sh/docs/install/lifecycle#trusteddependencies) in your package.json. By default, Bun does not run `postinstall` scripts for packages that are not trusted. This is a security feature to prevent malicious code from running on your machine.

When you first add a package, Bun will tell you if the package had a `postinstall` script that did not run.

{% raw %}

<pre><code><span class="t-bold">bun add </span><span class="t-gray">v1.0.31</span><br/> Saved lockfile<br/><br/> <span class="t-green">installed</span> @biomejs/biome<span class="t-gray">@1.6.1</span> with binaries:<br/>  <span class="t-gray">- </span><span class="t-bold">biome</span><br/><br/> <span class="t-green">1</span> package installed <span class="t-gray">[</span><span class="t-bold t-gray">55.00ms</span><span class="t-gray">]</span><br/><br/><span class="t-gray"> Blocked 1 postinstall. Run \`bun pm untrusted\` for details.</span><br/></code></pre>

{% /raw %}

## New: `bun pm untrusted`

If you want to see which scripts were blocked, you can run `bun pm untrusted`.

{% raw %}

<pre><code><span class="t-bold">bun pm untrusted </span><span class="t-gray">v1.0.31</span><br/><br/><span class="t-gray">./node_modules/@biomejs/biome @1.6.1</span><br/> <span class="t-yellow">»</span> [postinstall]<span class="t-gray">:</span> <span class="t-cyan">node scripts/postinstall.js</span><br/><br/>These dependencies had their lifecycle scripts blocked during install.<br/><br/>If you trust them and wish to run their scripts, use <span class="t-gray">\`</span><span class="t-yellow">bun pm trust</span><span class="t-gray">\`</span>.<br/></code></pre>

{% /raw %}

## New: `bun pm trust`

If you trust the package, you can run `bun pm trust [package]`. If you want to trust every package, you can also run `bun pm trust --all`.

{% raw %}

<pre><code><span class="t-bold">bun pm trust </span><span class="t-gray">v1.0.31</span><br/><br/><span class="t-gray">./node_modules/@biomejs/biome @1.6.1</span><br/> <span class="t-green">✓</span> [postinstall]<span class="t-gray">:</span> <span class="t-cyan">node scripts/postinstall.js</span><br/><br/> <span class="t-green">1</span> script ran across 1 package <span class="t-gray">[</span><span class="t-bold t-gray">71.00ms</span><span class="t-gray">]</span><br/></code></pre>

{% /raw %}

The most popular packages are already trusted by default. You can see the list of trusted packages by running `bun pm default-trusted`.

If you already know you want to trust a dependency, you can add it using `bun add --trust [package]`. This will add the package and it's transitive dependencies to your `trustedDependencies` list so you don't need to run `bun pm trust` for that package.

```json-diff
{
  "dependencies": {
    "@biomejs/biome": "1.6.1"
  },
+  "trustedDependencies": [
+    "@biomejs/biome"
+  ]
}
```

Thanks to [@dylan-conway](https://github.com/dylan-conway) for improving this feature!

## New: Unix sockets in `fetch()`

Bun now supports sending HTTP requests over a Unix socket.

```js
const response = await fetch("http://localhost/info", {
  // a file path to a Unix socket
  unix: "/var/run/docker.sock",
});

const { ID } = await response.json();
console.log("Docker ID:", ID);
```

This means you can send `fetch()` request to services that speak HTTP but communicate using Unix sockets, like the Docker daemon.

This feature works with `fetch` and with `node:http`.

Ordinarily, unix sockets have a file path limit of around 108 characters, but on Linux we've added a workaround to support longer paths.

### Abstract domain sockets in `fetch()`

We also added support for a obscure Linux feature called "abstract domain sockets".

Unlike Unix sockets, abstract sockets do not exist on the filesystem and get cleaned up automatically when both ends are closed. They are useful in environments where one process might not share filesystem permissions with the parent.

```js
import { $, serve } from "bun";

const unix = "\0much-abstract-very-domain";
const server = serve({
  unix,

  fetch(req) {
    return new Response("hello from abstract socket!");
  },
});

// abstract domain sockets don't exist in the filesystem
// and they don't run on a port
await $`rm -rf ${unix.slice(1)}`;

// but we can still make requests to them
await $`curl --abstract-unix-socket ${unix.slice(1)} http://anything/hello`;
await fetch(`http://a:1234/b`, { unix });

server.stop();
```

Abstract sockets works using `fetch()`, `Bun.serve()`, and `socketPath` in `node:http`.

## Fixed: Bun.spawn() 100% CPU usage bug on older Linux kernels

Correctly spawning processes and monitoring when they exit is extremely complicated.

For Linux, Bun has two implementations for monitoring when a spawned process exits:

1. Using `pidfd_open(2)` which was fully added to the Linux Kernel in v5.10 (Dec 2020). pidfd is the most efficient way to monitor when a process exits because it can be used with epoll or io_uring, like other file descriptors.
2. A fallback implementation using `SIGCHLD` which is supported on all Linux kernels

In psuedocode, the fallback implementation used to look something like this:

```js
// in a dedicated thread:
while (true) {
  for (const pid of pids) {
    if (wait4(pid, WNOHANG, ...) === pid) {
      pids.delete(pid);
      tellBunThatProcessExited(pid);
    }
  }

  sleepUntilNewPidsOrAnyProcessExits(eventfd, signalfd);
}
```

There was a bug where the equivalent of `sleepUntilNewPidsOrAnyProcessExits` would immediately resolve when it should've slept, causing Bun to consume 100% CPU on this thread.

There were two causes of this bug:

- We were not calling `read()` on the underlying `eventfd`, leading it to always be ready to read (and thus never sleep)
- The signal handler for `SIGCHLD` was not being installed correctly, leading the thread to never receive the signal

The first bug prevented the second bug from being noticed. Since it never slept, it never needed to wake up to handle the signal.

To prevent this from regressing in the future, we added a test that checks CPU usage when spawning `sleep infinity` and killing the subprocess after 1 second. If the CPU time is greater than 1/2 a second, the test fails.

### Fixed: missing resourceUsage stats in Bun.spawn() on older Linux kernels

Bun supports tracking how much memory, CPU time, and more stats a spawned process consumes. In the fallback implementation on older Linux kernels, we were not able to track these stats. Now we can.

```js
const proc = Bun.spawn({
  cmd: ["sleep", "1"],
});

await proc.exited;

console.log(proc.resourceUsage);

// Before: all 0s
```

## Fixed: bun executable size regression on macOS

In Bun v1.0.28 (last month), we added `Bun.stringWidth` which used more functions from the ICU internationalization library. A mistake in Bun's build process led to statically-linking the entire ICU library into the Bun executable on macOS. This increased the size of Bun's executable by 32.7 MB.

| size on macOS | Bun version |
| ------------- | ----------- |
| 47.8 MB       | Bun v1.0.31 |
| 80.4 MB       | Bun v1.0.30 |
| 80.4 MB       | Bun v1.0.29 |
| 47.7 MB       | Bun v1.0.28 |

This regression has been fixed, and we will add monitoring to prevent this from happening again.

## Node.js compatibility improvements

### New: `util.styleText()`

Node.js recently added the [`util.styleText()`](https://nodejs.org/api/util.html#utilstyletextformat-text) API that allows you to style text using ANSI escape codes. We added this to Bun.

```js
import { styleText } from "node:util";

console.log(styleText("red", "This is a failure!"));
console.log(styleText("yellow", "This is a warning!"));
console.log(styleText("green", "This is a success!"));
```

The code above will print the following output:

{% raw %}

<pre><code><span class="t-red">This is a failure!</span><br/><span class="t-yellow">This is a warning!</span><br/><span class="t-green">This is a success!</span><br/></code></pre>

{% /raw %}

Thanks to [@paperclover](https://github.com/paperclover) for working on this!

### New: `socketPath` option in `node:http`

We added support for the [`socketPath`](https://nodejs.org/api/http.html#httprequesturl-options-callback) option in `node:http`. This allows you to send HTTP requests using a Unix socket or an abstract domain socket.

```js
import { request } from "node:http";

request(
  {
    socketPath: "/var/run/docker.sock",
    path: "/info",
  },
  (res) => {
    let data = "";
    res.on("data", (chunk) => (data += chunk));
    res.on("end", () => console.log(JSON.parse(data)));
  },
);
```

### New: `domainToASCII` and `domainToUnicode`

We added support for the [`url.domainToASCII`](https://nodejs.org/api/url.html#urldomaintoasciidomain) and [`url.domainToUnicode`](https://nodejs.org/api/url.html#urldomaintounicodedomain) APIs. These are legacy Node.js APIs that useful for converting domain names to and from their ASCII and Unicode representations.

```js
import { domainToASCII, domainToUnicode } from "node:url";

console.log(domainToASCII("www.🍕.com")); // => www.xn--xj8h.com
console.log(domainToUnicode("www.xn--xj8h.com")); // => www.🍕.com
```

Thanks to [@nektro](https://github.com/nektro) for adding these APIs!

### Fixed: `child_process` could timeout early

We fixed a bug where spawned `child_process` would timeout early when timeout was defined. This did not affect code where the timeout was not defined.

```js
import { spawn } from "node:child_process";

const start = performance.now();
await new Promise((resolve, reject) => {
  const child = spawn("sleep", ["1000"], { timeout: 1000 });
  child.on("error", reject);
  child.on("exit", resolve);
});
const duration = performance.now() - start;

console.log(duration); // ~10ms instead of ~1000ms
```

Thanks to [@Electroid](https://github.com/Electroid) for fixing this bug!

### Fixed: `socket` event not firing in `node:http`

We fixed a bug where the `socket` event would not fire in `node:http` when a client connected to a server.

```js
import { request } from "http";

const request = request("http://localhost:8080");
await new Promise((resolve, reject) => {
  request.on("error", reject);
  request.on("socket", function onSocket(socket) {
    request.destroy();
    console.log(socket);
    resolve();
  });
});
```

## Fixed: Crash with invalid arguments to `Bun.serve()`

We fixed a bug where `Bun.serve()` would crash if the `Bun.serve()` options were invalid in some cases. It should have thrown an error instead.

Thanks to [@paperclover](https://github.com/paperclover) for fixing this bug!

## Fixed: Crash with `expect()` outside a test

We fixed a bug where `expect()` using an async resolver would crash if it was called outside of a test.

```js
import { expect } from "bun:test";

expect(Bun.sleep(1000)).resolves.toBeTruthy();
```

Thanks to [@paperclover](https://github.com/paperclover) for fixing this bug!

## Fixed: Potential crash when fetch() received an invalid `Location` header

If the `Location` header received by `fetch()` pointed to an invalid URL, Bun would potentially crash. This has now been fixed.

Thanks to [@nektro](https://github.com/nektro) for fixing this bug!

## Implemented: 2nd argument for `URLSearchParams.delete` & `URLSearchParams.has`

The [`URLSearchParams.prototype.delete`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/delete) and [`URLSearchParams.prototype.has`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/has) methods get support for a second `"value"` argument. This allows you to delete or check for a specific value in a URLSearchParams.

```js
const params = new URLSearchParams("a=1&a=2&b=3");
params.delete("a", 1);
params.delete("b", undefined);
params + ""; // => actual='' expected='a=2'
```

This feature was a recent addition to the Web Platform, and we've added it to Bun.

## Fixed: `.test.env` not loading when `NODE_ENV=test`

We found a bug where the `.test.env` file would not load when `NODE_ENV=test` and a `.production.env` file also existed. This has been fixed, thanks to [@nektro](https://github.com/nektro).

## Fixed: Errors not buffered to stderr

We found a performance bug where Bun would not buffer writes when printing stack traces to stderr. This has now been fixed.

## bun install bugfixes

### Fixed: Various bugs with `bunx`

We also fixed various bugs with `bunx`:

- `bunx --bun` would sometimes ignore the `--bun` flag, depending on the flag order.
- `bun x --bun` would forward the `--bun` flag to the script, instead of Bun.
- `bun --bun create` would crash and not work properly.
- `bunx <github>` would sometimes hang.

Thanks to [@paperclover](https://github.com/paperclover) for fixing these bugs!

### Fixed: `node-gyp` would sometimes not run

A bug where `bun install` would not run lifecycle scripts when a package.json had both a `postinstall` script and a `bindings.gyp` file has been fixed. This bug impacted `node-pty`, among other packages.

Thanks to [@dylan-conway](https://github.com/dylan-conway) for fixing this bug!

### Fixed: `bun pm cache rm` now removes bunx cache

Previously, `bun pm cache rm` would not remove the `node_modules` cache for `bunx`. This has been fixed.

## Internal: I/O architecture changes

In this release, we've reimplemented how Bun:

- Spawns processes
- Reads files (streaming)
- Writes files (streaming)

These new implementations do a better job of preventing reads/writes from blocking the main thread, without paying the cost of moving all I/O to a threadpool. Peak memory usage should be lower, especially with `node:stream` & `node:fs`.

Please report any bugs you find when using Bun.file(path).stream(), `fs.createReadStream`, `fs.createWriteStream`, or `Bun.spawn()`.

## Windows support is close

We are close to shipping Windows support with Bun v1.1. Once Bun for Windows passes 95% of Bun's test suite, we will announce the release date.

{% raw %}

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">Bun for Windows currently passes 92.51% of Bun&#39;s test suite<br><br>████████████░ 92.51%</p>&mdash; Bun (@bunjavascript) <a href="https://twitter.com/bunjavascript/status/1767644565581017580?ref_src=twsrc%5Etfw">March 12, 2024</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

{% /raw %}

## Thank you to 18 contributors!

- [@BrookJeynes](https://github.com/BrookJeynes)
- [@camero2734](https://github.com/camero2734)
- [@cirospaciari](https://github.com/cirospaciari)
- [@cyfung1031](https://github.com/cyfung1031)
- [@dylan-conway](https://github.com/dylan-conway)
- [@Electroid](https://github.com/Electroid)
- [@ErikOnBike](https://github.com/ErikOnBike)
- [@eventualbuddha](https://github.com/eventualbuddha)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
- [@jdalton](https://github.com/jdalton)
- [@Marukome0743](https://github.com/Marukome0743)
- [@nektro](https://github.com/nektro)
- [@paperclover](https://github.com/paperclover)
- [@ryands17](https://github.com/ryands17)
- [@sequencerr](https://github.com/sequencerr)
- [@sharpobject](https://github.com/sharpobject)
- [@Yash-Singh1](https://github.com/Yash-Singh1)
- [@zieka](https://github.com/zieka)

[**Full Changelog**](https://github.com/oven-sh/bun/compare/bun-v1.0.30...bun-v1.0.31)
