Bun

Bun v1.1.35


Dylan Conway · November 19, 2024

We're hiring systems engineers in San Francisco to build the future of JavaScript!

This release fixes 46 bugs (addressing 570 👍). It introduces Musl LibC support, JUnit XML test output, 6 MB binary size reduction, Worker preload option, faster fs.readFile for small files, deep equality support for Headers and URLSearchParams, node:net compatibility improvements, unicode import bugfixes, and several bun install fixes.

To install Bun

curl
npm
powershell
scoop
brew
docker
curl
curl -fsSL https://bun.sh/install | bash
npm
npm install -g bun
powershell
powershell -c "irm bun.sh/install.ps1|iex"
scoop
scoop install 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

Native support for Musl & Alpine Linux

Bun v1.1.35 ships binaries with native support for Musl LibC and is now tested on every commit. This was our #1 rated outstanding feature request with over 281 :+1:. If you are running on Alpine Linux the Bun install script will now download these binaries.

This change additionally affects any use of the Docker image oven/bun:alpine. Previously, we relied on a glibc compatibility hack to run Bun on Alpine Linux - and now it's native.

Bun gets 6 MB smaller

We've reduced the size of the Bun binary by 3.5 MB on Windows, and by 6 MB on Linux and macOS. This was achieved by allocating large structs on the heap instead of the stack, and by removing unwind tables created by our dependencies.

JUnit XML output support for bun test

Bun v1.1.35 adds support for JUnit output in bun test. It can be enabled through the command line with --reporter or through bunfig.toml.

To enable the JUnit reporter and write the output to junit.xml:

bun test --reporter junit --reporter-outfile junit.xml

Or in bunfig.toml:

bunfig.toml
[test.reporter]
junit = "junit.xml"

JUnit is a commonly used XML format for CI/CD test integration with Jenkins, CircleCI, GitLab CI, and more.

preload option for Worker

Bun v1.1.35 introduces a preload option for Worker, which allows you to evaluate a script before the worker script is executed.

preload.js
globalThis.preloaded = true;
index.js
const worker = new Worker(new URL("worker.js", import.meta.url).href, {
    preload: new URL("preload.js", import.meta.url).href
});
worker.js
console.log(globalThis.preloaded); // true

data URI import support

Bun v1.1.35 adds support for importing data URIs as modules.

index.ts
import data from "data:text/javascript,export default 'bun!';"
console.log(data) // bun!

Thanks to @yamalight!

console.group and console.groupEnd

Bun v1.1.35 also adds support for console.group and console.groupEnd.

index.js
console.group("begin");
console.log("indent!");
console.groupEnd();
// begin
//   indent!

${configDir} support in tsconfig.json

Bun v1.1.35 adds support for ${configDir} in tsconfig.json files. This makes relative paths from extended tsconfig.json files more useful, as they can be relative to the directory containing the derived tsconfig.json.

tsconfig.json
{
    "extends": "../tsconfig.base.json"
}
tsconfig.base.json
{
    "compilerOptions": {
        "outDir": "${configDir}/dist"
    }
}

fs.readFile gets up to 10% faster for small files

We've micro-optimized fs.readFile for small files, making it up to 10% faster.

[eval with bun] VSCode codelens action

Headers and URLSearchParams support in expect().toEqual()

Deep equals support for Headers and URLSearchParams has been added in Bun v1.1.35. This allows you to compare entries in Headers and URLSearchParams objects in expect().toEqual(), Bun.deepEquals(), and other deep equality checks.

Each of the following tests would previously fail.

index.test.js
test("Headers", () => {
    const headers1 = new Headers([["a", "b"]]);
    const headers2 = new Headers([["a", "c"]]);
    expect(headers1).not.toEqual(headers2);
});
test("URLSearchParams", () => {
    const params1 = new URLSearchParams("a=b");
    const params2 = new URLSearchParams("a=c");
    expect(params1).not.toEqual(params2);
});

Node compatibility improvements

node:net compatibility improvements for net.Server, net.Socket, and event emitting bugs

We've fixed many compatibility issues with node:net in this release. Most notably, the net.Server class is now fully implemented, and Socket.setKeepAlive and Socket.setNoDelay are implemented.

Thanks to @cirospaciari!

Fixed: node:zlib class prototypes and function names

The classes in node:zlib were missing Object.setPrototypeOf, which would cause subtle issues when the classes are subclassed. This was been fixed, along with more tests for name properties from node:zlib.

Fixed: Resulting signal codes from child_process.spawnSync

The signal property of the result from child_process.spawnSync was not being set correctly. The following code would print null instead of SIGTRAP.

index.js
import { spawnSync } from 'child_process';
console.log(spawnSync(process.argv0, ['-e', 'process.kill(process.pid, "SIGTRAP")']).signal);
// Before:      null
// Bun v1.1.35: SIGTRAP

Fixed thanks to @ippsav!

Fixed: node:https Agent prototype chain regression

A regression causing the prototype chain for node:https Agent instances to be incorrectly set was fixed, thanks to @nektro!

index.js
import { request } from 'node:https';
console.log(request('https://bun.sh/', { agent: false }).end().host);
// Before:        ConnectionRefused: Unable to connect. Is this computer able to access the url?
//                 path: "https://bun.sh:80/"
// Bun v1.1.35:   bun.sh

Fixed: node:net listenwith a unix socket path

Mishandling of the path option in listen from a server from node:net was fixed. The following code would throw an error before Bun v1.1.35 saying TypeError: undefined is not an object.

index.js
import { createServer } from 'node:net';
const server = createServer();
server.listen({ path: 'socket-path' });

Fixed thanks to @ippsav!

Bugfixes

Fixed: Unicode imports and unicode-escaped variable names

Several bugs have been fixed with importing and exporting variables with unicode characters, thanks to @pfgithub!

index.js
import { mile𐃘nautical } from "./lib"
console.log(mile𐃘nautical(10)); // 12
lib.js
export const mile𐃘nautical = int => Math.round(int * 1.150779448)

Fixed: Windows named pipes with forward slashes

Bun was mishandling named pipes with forward slashes on Windows. This has been fixed thanks to @cirospaciari!

Examples from our updated tests:

test(`\\\\.\\pipe\\test\\${randomUUID()}`);
test(`\\\\?\\pipe\\test\\${randomUUID()}`);
test(`//?/pipe/test/${randomUUID()}`);
test(`//./pipe/test/${randomUUID()}`);
test(`/\\./pipe/test/${randomUUID()}`);
test(`/\\./pipe\\test/${randomUUID()}`);
test(`\\/.\\pipe/test\\${randomUUID()}`);

Fixed: vscode debugger bugfix

The vscode debugger wasn't being enabled correctly unless the --inspect flag was used. This caused scoped variables to not be displayed in the debugger.

Fixed thanks to @RiskyMH!

Fixed: node-fetch Request.url bugfix

A bug was causing the url property of a Request object from node-fetch to be undefined. This was fixed by @pfgithub!

index.js
import { Request } from 'node-fetch';
console.log(new Request('https://bun.sh/').url);
// Before: undefined
// After: 'https://bun.sh/'

Fixed: Panic when parsing self closing JSX tags

A crash was fixed where a combination of JSX and function definitions would panic. The fix involved deleting the code used to check for self closing JSX tags, as it was unnecessary.

index.jsx
function Input() {
    return <input>{(() => { if (true) { } })}</input>
}
function fn1() { return 1; }
function fn2() { return 2; }

Fixed thanks to @ceymard!

Fixed: Regression in Bun.CryptoHasher

In Bun v1.1.34 a regression was introduced where Bun.CryptoHasher.update() would throw an error when given a Blob.

index.js
const hasher = new Bun.CryptoHasher("sha512")
hasher.update(new Blob(["hello blob!"]));
hasher.digest();

Fixed thanks to @dylan-conway!

Fixed: Migrating package-lock.json with a root dependency with scripts

An assertion failure was triggered by migrating a package-lock.json with a root dependency that had lifecycle scripts. Fixed by @dylan-conway!

Fixed: Assertion failure with non-existent cafile in bun install

An assertion failure was fixed when an absolute path to a non-existent cafile was provided to bun install on Windows.

bunfig.toml
[install]
cafile = "/does/not/exist/cafile.pem"

Fixed thanks to @dylan-conway!

Bun auto-install uses symlinks to resolve dependencies from the global cache. On Windows, if symlinks weren't available, Bun would fail to import the dependency because the symlink wouldn't exist. This has been fixed by using junctions for auto-install links.

Thanks to @dylan-conway!

Fixed: Crash with non-existent preload script

A crash was fixed when a non-existent preload script was provided to Bun in combination with --hot or --watch.

Fixed: fetch with method OPTIONS always returning ""

A bug causing fetch to always return an empty string with method OPTIONS was fixed, thanks to @Kapsonfire-DE!

index.js
const res = await fetch('https://google.com', { method: 'OPTIONS' });
console.log(await res.text());

Fixed: Bundler crash with onLoad plugins on copy-file loaders used on entrypoints

A crash was fixed in Bun.build when an onLoad plugin matched the entrypoint, and the entrypoint had a copy-file loader type (css with experimentalCss: false, wasm, ...). This was fixed by @zackradisic!

Fixed: setTimeout with node:util.promisify

A regression from Bun v1.1.27 was fixed where setTimeout wouldn't have a promisify implementation if node:timers wasn't imported in the same file. The bug could be reproduced with the following code:

bun --print "require('util').promisify(setTimeout)(1000).then(() => 'done')"

This will now correctly wait one second and print done.

Fixed thanks to @pfgithub!

Thanks to 16 contributors!