Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager — 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
fixes 27 bugs (addressing 103 👍 reactions), fixes an 8x perf regression to Bun.serve(), adds a new--conditions
flag tobun build
and Bun's runtime, adds support forexpect.assertions()
andexpect.hasAssertions()
in Bun's test runner, fixes crashes and improves Node.js compatibility.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 Shellv1.0.28
fixes 6 bugs (addressing 26 👍 reactions). Fixes bugs impacting Prisma and Astro,node:events
,node:readline
, andnode:http2
. Fixes a bug in Bun Shell involving stdin redirection and fixes bugs inbun:test
withtest.each
anddescribe.only
.
To install Bun:
curl -fsSL https://bun.sh/install | bash
npm install -g 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
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.
Bun will also await dangling promises so you don't need to append await
to your code.
For reference, here is an equivalent output using node --print
:
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 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.
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 for adding this feature!
New: bun add --trust <package>
We've made improvements to how Bun handles 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.
bun add v1.0.31
Saved lockfile
installed @biomejs/biome@1.6.1 with binaries:
- biome
1 package installed [55.00ms]
Blocked 1 postinstall. Run `bun pm untrusted` for details.
New: bun pm untrusted
If you want to see which scripts were blocked, you can run bun pm untrusted
.
bun pm untrusted v1.0.31
./node_modules/@biomejs/biome @1.6.1
» [postinstall]: node scripts/postinstall.js
These dependencies had their lifecycle scripts blocked during install.
If you trust them and wish to run their scripts, use `bun pm trust`.
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
.
bun pm trust v1.0.31
./node_modules/@biomejs/biome @1.6.1
✓ [postinstall]: node scripts/postinstall.js
1 script ran across 1 package [71.00ms]
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.
{
"dependencies": {
"@biomejs/biome": "1.6.1"
},
"trustedDependencies": [
"@biomejs/biome"
]
}
Thanks to @dylan-conway for improving this feature!
New: Unix sockets in fetch()
Bun now supports sending HTTP requests over a Unix socket.
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.
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:
- 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. - A fallback implementation using
SIGCHLD
which is supported on all Linux kernels
In psuedocode, the fallback implementation used to look something like this:
// 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 underlyingeventfd
, 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.
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()
API that allows you to style text using ANSI escape codes. We added this to Bun.
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:
This is a failure!
This is a warning!
This is a success!
Thanks to @paperdave for working on this!
New: socketPath
option in node:http
We added support for the socketPath
option in node:http
. This allows you to send HTTP requests using a Unix socket or an abstract domain socket.
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
and url.domainToUnicode
APIs. These are legacy Node.js APIs that useful for converting domain names to and from their ASCII and Unicode representations.
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 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.
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 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.
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 @paperdave 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.
import { expect } from "bun:test";
expect(Bun.sleep(1000)).resolves.toBeTruthy();
Thanks to @paperdave 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 for fixing this bug!
Implemented: 2nd argument for URLSearchParams.delete
& URLSearchParams.has
The URLSearchParams.prototype.delete
and URLSearchParams.prototype.has
methods get support for a second "value"
argument. This allows you to delete or check for a specific value in a URLSearchParams.
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.
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 @paperdave 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 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.
Bun for Windows currently passes 92.51% of Bun's test suite
— Bun (@bunjavascript) March 12, 2024
████████████░ 92.51%