Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager — all in one.
Bun v1.0.36 fixes 13 bugs. Adds support for fs.openAsBlob
and fs.opendir
, fixes edgecase in bun install with multiple bin
entries in package.json
, fixes bun build --target bun
encoding, fixes bug with process.stdin & process.stdout, fixes bug in http2, fixes bug with .env in bun run, fixes various Bun shell bugs and improves Node.js compatibility.
Bun v1.1 (Bundows) is coming April 1st.
Previous releases
v1.0.35
fixed a regression from Bun v1.0.34v1.0.34
fixes 7 bugs, bunx uses less memory, bun install gets faster on Docker & WSL, a conflicting devDependency hoisting bug is fixed, a cyclical CommonJS & ESM import crash is fixed, cross-mount fs.cp & fs.copyFile get 50% faster on Linux, and reliability improvements for bun install & bun's runtime.v1.0.33
fixes 2 bugs, including a bug with the mv command in Bun Shell and in node:crypto creating & verifying signaturesv1.0.32
fixes 13 bugs and improves Node.js compatibility. 'ws' package can now send & receive ping/pong events. util.promisify'd setTimeout setInterval, setImmediate work now. FileHandle methods have been implemented.
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
Node.js compatibility improvements
New: fs.openAsBlob
Bun now supports the recently added fs.openAsBlob()
API, which allows you to open a file as a Blob. This returns the same underlying Blob
as Bun.file
.
import { openAsBlob } from "node:fs";
const blob = await openAsBlob("hello.txt");
console.log(await blob.text()); // "Hello, world!"
New: fs.opendir
We also added support for fs.opendir()
, which allows you to open a directory and read its contents.
import { opendir } from "node:fs";
const dir = await opendir(".");
for await (const dirent of dir) {
console.log(dirent.name); // "hello.txt", "world.txt"
}
Fixed: Hang piping process.stdin to process.stdout
When at least 16 KB was piped to process.stdout, the process would sometimes hang. This has been fixed.
Fixed: Crash in http2
A crash that could occur when using the http2
client has been fixed. This crash was related to unimplemented HTTP2 features.
Fixed: Readable.toWeb(process.stdin)
The Readable.toWeb()
function was not working correctly when reading from process.stdin
. This has been fixed.
Now Readable.toWeb(process.stdin)
is effectively the same as Bun.stdin.stream()
.
Fixed: Regression using process.stdout.moveCursor()
A regression in Bun v1.0.34 caused process.stdout.moveCursor()
to throw ReferenceError: Can't find variable: readline
. This has been fixed.
Fixed: TextDecoder error missing code
property
When decoding an invalid UTF-8 string with TextDecoder
, the error object would not have a code
property. The Web API doesn't return a code
property for invalid UTF-8 strings, but Node.js does. For compatiblity, we now return the same code
property as Node.js.
This fixes a bug blocking @angular/cli new
from running using Bun.
Fixed: non-blocking fs.readv & fs.writev
The node:fs APIs fs.readv
and fs.writev
were running in a blocking manner. This has been fixed. We now enqueue the readv & writev functions to the threadpool when their sync
versions are not called.
Fixed: Edgecase with multiple bin
entries in package.json
Previously, there was a bug when:
- exactly one version of a package had a
bin
entry in the NPM Registry API - all other versions did not have a
bin
entry bin
object had multiple entries
This bug caused bun install
to fail to link the binaries properly.
{
"bin": {
"a": "bin",
"b": "bin",
}
}
Thanks to @dylan-conway for fixing this issue.
Fixed: missing terminate
method in ws
server
The ws
polyfill in Bun was missing the terminate
method on the WebSocketServer's WebSocket instance. This has been fixed.
Thanks to @paperclover for fixing this issue.
Runtime improvements
File descriptor leak prevention mechanism
POSIX defaults file descriptors to be inherited by child processes. This frequently causes file descriptor leaks in all sorts of ways. Bun has always used the O_CLOEXEC
flag to prevent file descriptors from being inherited, but there were cases where this was not enough.
On modern Linux kernels, Bun now uses the close_range
system call to prevent file descriptors from being inherited without the O_CLOEXEC flag. This is a much more reliable way to prevent file descriptor leaks.
On macOS, Bun exclusively uses posix_spawn to spawn child processes which has an equivalent mechanism to prevent file descriptor leaks which makes this harder to happen in the first place.
Restore stdin/stdout to their original state on SIGINT/SIGTERM
Previously, Bun would not always restore stdin/stdout to their original state on SIGINT/SIGTERM. This has been fixed.
Non-blocking TTY reads
On POSIX, Bun now reads from stdin in a non-blocking manner. Normally, this would cause the other end of the pipe to also be non-blocking, but we have a workaround (thanks to reading some code from libuv). We use ttyname_r
to open the TTY as a non-blocking file descriptor without affecting the other end of the pipe.
Fixed: Crash using Bun.escapeHTML
We fixed a crash where specific input could crash Bun.escapeHTML
, which was caused by an off-by-one bug.
Thanks to Querijn Voet for reporting this issue.
Fixed: Edgecase with WebSocket handshake
A bug in our WebSocket
client implementation could cause non-101 status codes to be treated as a WebSocket upgrade request. This bug was not known to ever exist in the wild, but we fixed it anyway.
Fixed: potential file descriptor redirection bug in Bun.spawn
A bug that could cause redirecting stdin
, stdout
, or stderr
led to Bun closing the file descriptors before the child process finished starting. This bug was caused by misunderstanding how the dup2
libc function works. When dup2
receives the same file descriptor as the destination, it does nothing. Now when redirecting the same file descriptor, Bun will instead remove the O_CLOEXEC
flag from the file descriptor which allows the child process to inherit the file descriptor. This bug only impacted linux, and was more difficult to reproduce than just inheriting file descriptors.
Fixed: incorrect .env propagation in bun run
A regression caused .env
files to be loaded unexpectedly when using bun run
before the script is run. This regression has been fixed and we've improved our test suite to prevent this from occurring again.
Shell (Bun.$) stability improvements
We fixed various bugs and regressions with the Bun shell, including:
- A race condition where the shell would hang.
- A possible crash when the subprocess exited before the event loop was ready.
- A possible crash when stdin was over 128kb in size.
- When spawning a subprocess that uses interactive mode, user input would not be sent to the subprocess. This affected packages like
@inquirer/prompts
.
import { $ } from "bun";
await $`bun input.js | bun prompt.js`;
const { select } = require("@inquirer/prompts");
async function run() {
const foobar = await select({
message: "Foo or Bar",
choices: [
{ name: "Foo", value: "foo" },
{ name: "Bar", value: "bar" },
],
});
console.error("Choice:", foobar);
}
run();
// Simulate pressing the down arrow key
const writer = Bun.stdout.writer();
await Bun.sleep(100);
writer.write("\\x1b[B");
// Simulate pressing the enter key
await Bun.sleep(100);
writer.write("\\x0D");
writer.flush();
Thanks to @zackradisic for fixing these issue.
Fixed: bun build --target bun
used wrong encoding
Bun transpiles files to latin1 because the file size is reduced when being stored as utf-16. There was a bug where bun build --target bun
would encode as utf-8 instead, which caused issues with non-latin1 characters. This has been fixed.
Given the following file, previously it would have been encoded as-is in utf-8.
console.log({ 我: "a" });
Now, it is encoded properly in latin1.
// @bun
console.log({ "\u{6211}": "a" });
Thanks to @pfgithub for fixing this issue.
Bundows (Bun v1.1) is April 1st
Bun v1.1 will ship on April 1st.