Bun v1.1.13 is here! This release fixes 97 bugs (addressing 211 👍). Reliability improvements to bun install, WebSocket server, fetch, worker_threads. worker_threads now supports eval. URL.createObjectURL
, stack trace error location improvements, several bun install
fixes, and many crashes and bugs fixed.
We're hiring systems engineers in San Francisco to build the future of JavaScript!
Previous releases
v1.1.11
fixes 36 bugs (addressing 362 👍). bun update saves dependency updates to package.json. A peer dependencies resolution bug in bun install is fixed.setTimeout
gets 5x faster throughput on Linux. Node.js compatibility improvements tofs
,zlib
,timers
,http
,dgram
andmodule
. Event loop improvements on macOS. Windows reliability improvements.v1.1.10
fixes 20 bugs. 2x faster uncached bun install on Windows.fetch()
uses up to 2.8x less memory. Several bugfixes to bun install, sourcemaps, Windows reliability improvements and Node.js compatibility improvementsv1.1.9
fixes 67 bugs (addressing 150 👍). Fixes to: workspaces inbun install
, sourcemaps in bun build, IPv6 & VPN connectivity, Loading UNC paths, junctions, symlinks, and pnpm on Windows,fetch()
gets faster, addeddns.prefetch()
API,atob()
gets 8x faster,toString('base64url')
gets 5x faster, expect().toBeReturned() matcher, Node.js compatibility improvements, Bun Shell fixes, and lots more bugfixes.v1.1.0
Bundows. Windows support is here!
To install Bun
curl -fsSL https://bun.sh/install | bash
npm install -g bun
powershell -c "irm bun.sh/install.ps1|iex"
scoop install bun
brew tap oven-sh/bun
brew install bun
docker pull oven/bun
docker run --rm --init --ulimit memlock=-1:-1 oven/bun
To upgrade Bun
bun upgrade
node:worker_threads
now supports eval: true
Similar to the web standards, node:worker_threads
has a feature to allow taking a string of source code.
import * as wt from 'node:worker_threads';
const code = `
import { parentPort } from 'node:worker_threads';
const foo: number = 123;
parentPort.postMessage({ foo } satisfies Data);
`;
const worker = new wt.Worker(code, { eval: true });
worker.on('message', data => {
console.log(data);
});
bun node-worker-eval.ts
{
foo: 123,
}
Implemented URL.createObjectURL
Bun now supports URL.createObjectURL
, which creates a URL from a Blob object. These urls can then be used in APIs like fetch
, Worker
, and import
.
When combined with Worker
, it allows for an easy way to spawn additional threads without creating a new separate URL for the worker's script. Since worker scripts also run through Bun's transpiler, TypeScript syntax is supported.
const code = `
const foo: number = 123;
postMessage({ foo } satisfies Data);
`;
const blob = new File([code], "hey.ts");
const url = URL.createObjectURL(blob);
const worker = new Worker(url);
worker.onmessage = ({data}) => {
console.log("data:", data);
};
bun worker-object-url.ts
{
foo: 123,
}
expect
supports custom failure messages
Bun now supports custom failure messages by passing a string as the second argument to expect
. This works the same as it does in Vitest, allowing you to document what the assertion is checking.
import { test, expect } from 'bun:test';
test("sample", () => {
expect(0.1 + 0.2, "Floating point has precision error").toBe(0.3);
});
$ bun test custom-message
bun test v1.1.12 (43f0913c)
test.test.ts:
1 | import { test, expect } from 'bun:test';
2 |
3 | test("sample", () => {
4 | expect(0.1 + 0.2, "Floating point has precision error").toBe(0.3);
^
-error: expect(received).toBe(expected)
+error: Floating point has precision error
Expected: 0.3
Received: 0.30000000000000004
at /private/tmp/scratchpad_20240606T054447/test.test.ts:4:3
✗ sample [1.94ms]
This is most useful when the value evaluates to a boolean. Instead of just seeing "Expected true, recieved false", tests can make it immediatly obvious what the error is.
Bun install reliability
This release includes several reliability improvements to bun install
.
Fixed: Crash when certain peer dependencies install
When certain peer dependencies are installed and not present in the cache, Bun would potentially crash. This crash has been reported 167 times.
Thanks to @dylan-conway for fixing this!
Fixed: Manifest cache string deduplicating bugfix
When a dependency name and a dependency version existed in the same npm registry manifest file, Bun would potentially deduplicate the strings incorrectly, leading Bun to attempt to download the wrong package. This bug is pretty rare - you would have to have a dependency name that is also a version number, or the version number would have be the same as a dependency name (like an npm tag named "react" and a dependency named "react" in the same registry manifest api response).
Thanks to @dylan-conway for fixing this!
Fixed: Semver parsing edge case with prerelease tags
A bug in Bun's semver parser has been fixed, thanks to @dylan-conway. This bug would cause invalid semver to sometimes successfully install versions with prerelease tags if .
immediately followed the patch number. For example, 1.0.0.alpha
would parse as 1.0.0-alpha
and install if that version existed.
Fixed: Crash and assertion failure when printing bun.lockb in yarn.lock format
A crash when running bun bun.lockb
has been resolved thanks to @dylan-conway. This the assertion failure would sometimes occur when packages had the same dependency in "dependencies"
and "optionalDependencies"
in their package.json
.
Fixed: Npm package manifest validation bugfix
Bun install uses npm manifest files to retrieve package information and determine what dependencies need to be installed. When receiving these manifests, Bun will make sure the "name"
property matches the package name from the request, and error if it does not. This fix allows scoped packages to be url encoded, where possibly @
or /
could be replaced with %40
or %2F
.
{
"name": "%40foo%2fbar"
// ...
}
Thanks to @dylan-conway for fixing this!
Fixed: Package manifest cache bugfix
A bug where a re-install of node_modules
could fail when switching between projects using different default or scoped registries has been fixed.
Thanks to @dylan-conway for fixing this!
Fixed: Installing git dependencies with missing package.json files or "name"
fields
Bun will now successfully install git dependencies that do not have a package.json file committed, or have a package.json file without a "name"
field. The dependency name will be the repository name in these situations.
Thanks to @dylan-conway for fixing this!
Fixed: Aliased workspace dependencies fix
A bug preventing aliased workspace dependencies without a version in their package.json has been fixed. For example, this workspace dependency will now work as expected:
// ./packages/foo/package.json
{
"name": "foo",
"version": "1.0.0",
"dependencies": {
"is-odd": "workspace:is-even@latest"
}
}
// ./packages/is-even/package.json
{
"name": "is-even",
}
Thanks to @dylan-conway
Incorrect manifest cache invalidation optimization
We've disabled an optimization in bun install
that would cause bun install
to potentially hang or receive "Connection closed" errors.
npm's registry api returns a Last-Modified
header, but ignores If-Not-Modified-Since
header. When the Last-Modified
header matched the stored value, Bun would ignore the remaining response body and pretend a 304 was returned. This skips donwloading, decompressing, and parsing the manifest JSON unnecessarily. However, the implementation of this optimization needs to be more robust to handle HTTP keep-alive correctly. For now, we've disabled this optimization.
5 new bun:test matchers
This release adds 5 new matchers to bun:test
:
toContainAllKeys
toContainValue
toContainValues
toContainAllValues
toContainAnyValues
These matchers are useful for testing if objects contain or have specific keys or values.
import { test, expect } from "bun:test";
test("hello", () => {
expect({ a: "hello", b: "world" }).toContainAllKeys(["a", "b"]);
expect({ a: "hello", b: "world" }).toContainValue("hello");
expect({ a: "hello", b: "world" }).toContainValues(["hello", "world"]);
expect({ a: "hello", b: "world" }).toContainAllValues(["hello", "world"]);
expect({ a: "hello", b: "world" }).toContainAnyValues(["world"]);
});
Thanks to @nithinkjoy_tech for adding these matchers!
fetch
stability improvement
We fixed a bug where if you sent thousands of concurrent HTTP requests in a short time frame, some would fail with The socket connection was closed unexpectedly
.
The cause of this was due to Bun's handling of TCP FIN packets. After receiving a TCP FIN packet, Bun now sets SO_LINGER
on the socket to 0
, causing it to immediately close instead of risking getting stuck in the TIME_WAIT
state and then running out of socket descriptors.
Fix stack trace line/column numbers being offset
The code bun uses to remap errors to their original line and column number had some very subtle edge cases. The shortest reproduction was from strictEqual
.
import { strictEqual } from "node:assert";
(function () {});
strictEqual(1, 2);
Which would point to the wrong position.
1 | import { strictEqual } from 'node:assert';
2 |
3 | (function () { })
^
AssertionError: Expected values to be strictly equal:
at module code (/tmp/scratchpad/index.ts:3:2)
Thanks to @paperdave, this entire class of bug has been fixed by fixing a mistake in how line and column numbers are read from JavaScriptCore. The error divot, the printed stack trace, and error.stack
all point to the correct source location.
3 | (function () { })
4 |
5 | strictEqual(1, 2);
^
AssertionError: Expected values to be strictly equal:
at module code (/tmp/scratchpad/index.ts:5:1)
This is important because when using bun build --target=bun --sourcemap --minify
, all source code gets placed on one line, which can cause errors to point to positions in the file which don't even exist.
Minify Infinity
When bundling with --minify-syntax
, the Infinity
constant will be shortened into 1/0
console.log(Infinity);
bun build infinity.ts --minify
console.log(1/0);
WebSocket server reliability improvements
This release fixes three rare bugs in Bun's WebSocket server:
- A crash could occur when the socket connection hung up unexpectedly in a specific code path. We did not see reports of this, but did notice it in debug builds of Bun.
- A case of undefined behavior in the WebSocket server when sending a large message without compression, without TLS, and with no backpressure has been fixed. We have not seen any reports of this causing a crash or data corruption.
- A crash when passing invalid argument types to
isSubscribed
,subscribe
, orunsubscribe
has been fixed. This could also happen if the machine ran out of memory. This issue was reported 1 time.
Fixed: Async WebSocket Server upgrade with custom subprotocols
A bug where the following code would close the connection immediately has been fixed:
import type { ServerWebSocket } from "bun";
const delay = (ms: number) => new Promise((ok) => setTimeout(ok, ms));
Bun.serve<{}>({
fetch: async (req, server) => {
await delay(1);
if (server.upgrade(req)) return;
},
websocket: {
open(ws: ServerWebSocket<{}>): void | Promise<void> {
console.log("open");
},
close(
ws: ServerWebSocket<{}>,
code: number,
reason: string,
): void | Promise<void> {
console.log("closed", code);
},
},
});
new WebSocket("http://localhost:3000", "ocpp1.6");
Thanks to @cirospaciari for fixing this!
Fixed: UTF16 Content-Type header in WebSocket server
If the JavaScript string for "Content-Type"
was encoded as UTF-16, Bun would not read it correctly. This has been fixed, thanks to @cirospaciari.
Fixed: WebSocket memory leak on close
A memory leak when closing WebSockets has been fixed, thanks to @cirospaciari!
Fixed: AbortSignal.any()
bugfix
A bug causing signals from AbortSignal.any()
to not receive an abort event for each dependent signal has been fixed, thanks to @cirospaciari!
The following code will now work as expected:
const controller = new AbortController();
const signal = AbortSignal.any([controller.signal]);
signal.addEventListener("abort", () => {
console.log("aborted!");
});
controller.abort();
Faster crypto.pbkdf2
We've reimplemented crypto.pkdf2
to use optimized BoringSSL functions instead of a JavaScript polyfill implementation.
New:
cpu: Apple M3 Max
runtime: bun 1.1.13 (arm64-darwin)
benchmark time (avg) (min … max) p75 p99 p995
------------------------------------------------------------------------------------ -----------------------------
pbkdf2(iterations = 1000, 'sha256') -> 32 81.5 µs/iter (69.67 µs … 823.54 µs) 81.5 µs 100.5 µs 110.08 µs
pbkdf2(iterations = 500_000, 'sha256') -> 32 31.74 ms/iter (31.16 ms … 33.28 ms) 31.83 ms 33.28 ms 33.28 ms
Previously:
cpu: Apple M3 Max
runtime: bun 1.1.10 (arm64-darwin)
benchmark time (avg) (min … max) p75 p99 p995
------------------------------------------------------------------------------------ -----------------------------
pbkdf2(iterations = 1000, 'sha256') -> 32 2.37 ms/iter (2.05 ms … 5.15 ms) 2.26 ms 5.06 ms 5.06 ms
pbkdf2(iterations = 500_000, 'sha256') -> 32 1.24 s/iter (1.22 s … 1.26 s) 1.25 s 1.26 s 1.26 s
Node.js, for comparison:
cpu: Apple M3 Max
runtime: node v22.2.0 (arm64-darwin)
benchmark time (avg) (min … max) p75 p99 p995
------------------------------------------------------------------------------------ -----------------------------
pbkdf2(iterations = 1000, 'sha256') -> 32 213.68 µs/iter (195.08 µs … 2.35 ms) 217.33 µs 274.71 µs 289.21 µs
pbkdf2(iterations = 500_000, 'sha256') -> 32 104.6 ms/iter (97.97 ms … 114.64 ms) 110.37 ms 114.64 ms 114.64 ms
Fixed: structuredClone(File)
structuredClone
now supports File
objects, which are used in postMessage
.
const blob = new File(["hello"], "hello.txt");
const cloned = structuredClone(blob);
console.log(cloned.name === "hello.txt"); // true
// Previously: false
Thanks to @dylan-conway for fixing this!
Fixed: Worker .terminate()
stability improvements
A crash has been fixed with terminating Worker
s. This was caused by a race condition with pending work (such as fetch
, async node:fs
, and Bun.serve
) while the termination was in progress.
Fixed: node:https
client bug with custom checkServerIdentity
When using node:https
or tls:connect
with a custom checkServerIdentity
function, a race condition could potentially cause the function to never be called. This bug has been fixed.
This does not impact the default checkServerIdentity
function, as that takes a completely separate code path.
Fixed: Crashes during bun update
with unresolved packages
A crash when updating peer dependencies has been resolved where during an update a invalid_package_id
was seen, indicating the package was not yet resolved. Previously, we assumed at this stage that packages were always resolved, but an edge case with peer dependencies can leave this unresolved.
Thanks to @dylan-conway
Fixed: Windows command line parsing crash
A crash relating to invalid utf16 in windows command line strings has been resolved.
Fixed: bun update
preserves ~
version specifiers
If a package.json specified a dependency version such as ~1.1.0
, the ~
will be preserved after the update. Previously, this was only done for ^
ranges.
{
"dependencies": {
// Before running `bun update`
"elysia": "~1.0.21",
// After `bun update`
"elysia": "~1.0.21",
"elysia": "~1.0.22",
}
}
Thanks to @dylan-conway
Fixed: Bun Shell fixes
A couple bugs involving invalid UTF-16 and Bun.$.escape
have been fixed, along with a panic when a command name expands to an empty string.
These are fixed to @zackradisic
Fixed: Bun.deepEquals
with undefined values edge case
Comparing two objects with Bun.deepEquals
would sometimes incorrectly return true
if one of the objects had undefined properties and the other had the same number of properties.
console.log(Bun.deepEquals({ a: undefined }, { b: 1 })); // true
This is fixed thanks to @dylan-conway
Fixed: bun create
typo fix
bun create
using a local template will suggest to run cd
with a relative path to the created project. When the destination was the current directory, it would suggest running cd
with no arguments.
$ bun create elysia
Created elysia project successfully
# To get started, run:
- cd
bun run src/index.ts
Thanks to @Sushants-Git
Fixed: bun create
with a local folder template on Windows
Previously, creating a project using a local template on Windows did not work. This has been resolved.
Thanks to @dylan-conway for fixing this.
Fixed: Help menu fixes
Bun's help menu includes example packages to use with bun create
, bun add
. At some point, the random lists used for these got swapped.
Bun is a fast JavaScript runtime, package manager, bundler, and test runner. (1.1.13)
Usage: bun <command> [...flags] [...args]
Commands:
run ./my-script.ts Execute a file with Bun
lint Run a package.json script
test Run unit tests with Bun
x nuxi Execute a package binary (CLI), installing if needed (bunx)
repl Start a REPL session with Bun
exec Run a shell script directly with Bun
install Install dependencies for a package.json (bun i)
- add next-app Add a dependency to package.json (bun a)
+ add zod Add a dependency to package.json (bun a)
remove backbone Remove a dependency from package.json (bun rm)
update elysia Update outdated dependencies
link [<package>] Register or link a local npm package
unlink Unregister a local npm package
pm <subcommand> Additional package management utilities
build ./a.ts ./b.jsx Bundle TypeScript & JavaScript into a single file
init Start an empty Bun project from a blank template
- create next-app Create a new project from a template (bun c)
+ create zod Create a new project from a template (bun c)
upgrade Upgrade to latest version of Bun.
<command> --help Print help text for command.
Learn more about Bun: https://bun.sh/docs
Join our Discord community: https://bun.sh/discord
Thanks to @MARCROCK22 for fixing this
Improved error message for Bun.serve
when passed a non-Response
object
When passing a non-Response
object to Bun.serve
, Bun will now throw an error with a more helpful message.
// Before:
error: Expected a Response object
// After:
error: Expected a Response object, but received '{}'
Fixed: node:crypto
randomInt
callback
node:crypto
's randomInt
function now correctly accepts a callback with the random number.
import crypto from "crypto";
crypto.randomInt(0, 5000, (err, val) => {
console.log(val);
});
This is fixed thanks to @nektro
Fixed: Classes won't emit unnecessary constructor functions
When bundling TypeScript, Bun will no longer emit an empty constructor for extended classes. This reduces bundle sizes, and speeds up class construction, as this constructor would hit a slow path in JavaScriptCore.
class A {
constructor(argument) {
console.log(`Hello ${argument}`);
}
}
class B extends A {}
new B("World");
// index.ts
class A {
constructor(argument) {
console.log(`Hello ${argument}`);
}
}
class B extends A {
- constructor() {
- super(...arguments);
- }
}
new B("World");
Thanks to @paperdave
Fixed: Crash involving setTimeout
and process.on('uncaughtException')
A crash when throwing an exception in a setTimeout
and using it in process.on('uncaughtException')
has been fixed thanks to @paperdave.
Libarchive, mimalloc, and zstd were updated
libarchive was updated to version 3.7.4
, mimalloc was updated to version 2.1.8
, and zstd was updated to version 1.5.6
.