Bun

Bun v1.0.22


Ashcon Partovi ยท January 9, 2024

Bun v1.0.22 fixes 29 bugs (addressing 118 ๐Ÿ‘ reactions), fixes bun install issues on Vercel, adds performance.mark() APIs, adds child_process support for extra pipes, makes Buffer.concat faster, adds toBeEmptyObject and toContainKeys matchers, fixes console.table width using emojis, and support for argv and execArgv options in worker_threads, and supports Brotli in fetch.

Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager โ€” all in one. In case you missed it, here are some of the recent changes to Bun:

  • v1.0.21 - Fixes 33 bugs (addressing 80 ๐Ÿ‘ reactions). console.table() support. Bun.write, Bun.file, and bun:sqlite use less memory. Large file uploads with FormData use less memory. bun:sqlite error messages get more detailed. Memory leak in errors from node:fs fixed. Node.js compatibility improvements, and many crashes fixed.
  • v1.0.20 - Reduces memory usage in fs.readlink, fs.readFile, fs.writeFile, fs.stat and HTMLRewriter. Fixes a regression where setTimeout caused high CPU usage on Linux. HTMLRewriter.transform now supports strings and ArrayBuffer. fs.writeFile() and fs.readFile() now support hex & base64 encodings. Bun.spawn shows how much CPU & memory the process used.
  • v1.0.19 - Fixes 26 bugs (addressing 92 ๐Ÿ‘ reactions). Use @types/bun instead of bun-types. Fixes --frozen-lockfile bug. bcrypt & argon2 packages now work. setTimeout & setInterval get 4x higher throughput. module mocks in bun:test resolve specifiers. Optimized spawnSync() for large stdio on Linux. Bun.peek() gets 90x faster, expect(map1).toEqual(map2) gets 100x faster. Bugfixes to NAPI, bun install, and Node.js compatibility improvements.

To install Bun:

curl
npm
brew
docker
curl
curl -fsSL https://bun.sh/install | bash
npm
npm install -g bun
brew
brew tap oven-sh/bun
brew install bun
docker
docker pull oven/bun
docker run --rm --init --ulimit memlock=-1:-1 oven/bun

To upgrade Bun:

bun upgrade

Fixed: Issues with bun install on Vercel

In a recent release of Bun, we introduced changes to bun install to make lifecycle scripts run faster by running them in parallel. When doing this, we also changed the how Bun sets the current working directory for lifecycle scripts, and started to use the posix_spawn_file_actions_addchdir_np C-standard library function.

Bun was not properly checking if that function failed. The function was introduced in glibc 2.29, but Vercel uses glibc 2.26. Therefore, when running bun install on Vercel, the function would fail, and bun install would not handle that failure.

The fix was to implement a posix_spawn-like polyfill for Linux.

New: performance.mark() APIs

You can now use user-timings APIs, which include performance.mark() and performance.measure(). This is useful for measuring the performance of your code.

performance.mark("start");
while (true) {
  // ...
}
performance.mark("end");
performance.measure("task", "start", "end");

You can also use the PerformanceObserver API to listen for performance events.

const observer = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    if (entry.entryType === "mark") {
      console.log(entry); // { name: "start", startTime: 0 }
    } else if (entry.entryType === "measure") {
      console.log(entry); // { name: "task", startTime: 0, duration: 1000 }
    }
  }
});

observer.observe({ entryTypes: ["mark", "measure"] });

Thanks to @gvilums for submitting a PR to add this to Bun, and thanks to the WebKit team for their implementation of these APIs.

New: child_process support for extra pipes

You can now pass extra pipes to child_process functions. This is useful for passing data between processes. For example, you can pass a pipe to a child process, and then write to that pipe from the parent process.

parent.js
child.js
parent.js
import { spawn } from "node:child_process";

const child = spawn(process.argv0, ["child.js"], {
  stdio: ["inherit", "inherit", "inherit", "pipe"],
});

const pipe = child.stdio[3];
pipe.on("data", (data) => {
  console.log(data.toString()); // "hello!"
});
child.js
import { createWriteStream } from "node:fs";

const stream = createWriteStream(null, { fd: 3 });
stream.on("ready", () => {
  stream.write("hello!");
});

Coming soon: Playwright support

These changes were necessary to support Playwright, which uses extra pipes to communicate with the browser process. However, there is still one outstanding PR that needs to be merged to get Playwright working with Bun.

Thanks to @nektro for implementing this missing API.

New: Brotli support for fetch

You can now use fetch to make requests with the br encoding. This is useful for making requests to servers that support Brotli compression.

const response = await fetch("https://example.com", {
  headers: {
    "Accept-Encoding": "br",
  },
});

We also changed brotli support to be statically-linked in Bun, instead of dynamically-linked. This fixed issues with certain Linux distros and older macOS releases that did not have the nessary libraries.

New: toBeEmptyObject and toContainKeys matchers

You can now use expect().toBeEmptyObject() to check if an object is empty.

expect({}).toBeEmptyObject();
expect({ a: 1 }).not.toBeEmptyObject();

You can also use expect().toContainKeys() or expect().toContainAnyKeys() to check if an object contains certain keys.

expect({ a: 1, b: 2 }).toContainKeys(["a", "b"]);
expect({ a: 1, b: 2 }).not.toContainKeys(["c"]);
expect({ foo: "bar" }).toContainAnyKeys(["foo", "baz"]);
expect({ foo: "bar" }).not.toContainAnyKeys(["baz"]);

Thanks to @coratgerl for implementing this feature.

New: 15% to 400% faster Buffer.concat

Using Buffer.concat is now 15% to 400% faster, depending on the size of the buffers being concatenated.

We also fixed a bug where Buffer.concat would crash when concatenating a large number of buffers. This was caused by an out-of-memory error not being handled correctly.

New: 10% to 15% faster new Headers(object)

Using new Headers(object) and new URLSearchParams(object) with an object is now 10% to 15% faster.

Fixed: console.table width using emojis

In Bun v1.0.21, we added support for console.table. However, we did not properly handle emojis, and the table would be misaligned if there were emojis or unicode characters in the table. This has been fixed by using the official Unicode dataset to determine the width of each character.

Before (Bun v1.0.21)After (Bun v1.0.22)

Thanks to @otgerrogla for implementing console.table, and following up to fix this bug.

New: argv and execArgv options for worker_threads

Bun did not support the argv and execArgv options for worker_threads. This has been fixed.

index.js
worker.js
index.js
import { Worker } from "node:worker_threads";

const worker = new Worker("./worker.js", {
  argv: ["--foo", "bar"],
  execArgv: ["--inspect"],
});

worker.on("message", (data) => {
  console.log(data);
  // { argv: [ "--foo", "bar" ], execArgv: [ "--inspect" ] }
});
worker.js
postMessage({
  argv: process.argv,
  execArgv: process.execArgv,
});

Thanks to @otgerrogla for fixing this missing functionality.

Fixed: Binding to 0.0.0.0 would bind to IPv6 as well

There was a bug where createServer would bind to both IPv4 and IPv6 when binding to 0.0.0.0. This has been fixed thanks to @Hanaasagi.

Fixed: HTTP method casing in node:http

In Bun v1.0.10, we introduced a bug where the PURGE and OPTIONS headers were not being properly transformed to uppercase. This caused problems with Fastify and CORS pre-flight requests. This has been fixed thanks to @asomethings.

Fixed: Partial consume on BufferList

There was a bug where multiple, partial consumes on BufferList would not increment the offset properly. This caused cbor to not work properly, and has been fixed thanks to @hborchardt.

Fixed: bun build --compile with compiled:// URL

We fixed a bug where bun build --compile would not work with compiled:// URLs. This has been fixed by changing compiled:// URLs to use a special prefix that Bun recognizes.

New: assert.doesNotMatch

You can now use assert.doesNotMatch to check if a string does not match a regular expression.

assert.doesNotMatch("I will not match", /match/);

Thanks to @markusn for implementing this missing API.

Thanks to 22 contributors!

Thank you to all the contributors to this release of Bun, including the new 13 contributors who submitted their first pull request!

You can also read the full changelog.