Bun v1.0.19 fixes 26 bugs (addressing 92 👍 reactions). Use @types/bun
instead of bun-types
. Fixes "lockfile had changes, but is frozen" 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
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.14
-Bun.Glob
, a fast API for matching files and strings using glob patterns. It also fixes a race condition when extracting dependencies duringbun install
, improves TypeScript module resolution innode_modules
, and makes error messages easier to read.v1.0.15
- Fixes 23 bugs (addressing 117 👍 reactions),tsc
starts 2x faster. StableWebSocket
client, syntax-highlighted errors, cleaner stack traces, add custom test matchers withexpect.extend()
+ additional expect matchers.v1.0.16
- Fixes 49 bugs (addressing 38 👍 reactions). Concurrent IO for Bun.file & Bun.write gets 3x faster and now supports Google Cloud Run & Vercel, Bun.write auto-creates the parent directory if it doesn't exist,expect.extend
inside of preload works,napi_create_object
gets 2.5x faster, bugfix for module resolution impacting Astro v4 and p-limit, console.log bugfixesv1.0.17
- Fixes 15 bugs (addressing 152 👍 reactions). bun install postinstall scripts run for top 500 packages,bunx supabase
starts 30x faster thannpx supabase
,bunx esbuild
starts 50x faster thannpx esbuild
and bugfixes to bun installv1.0.18
- Fixes 27 bugs (addressing 28 👍 reactions). A hang impacting create-vite & create-next & stdin has been fixed. Lifecycle scripts reporting "node" or "node-gyp" not found has been fixed. expect().rejects works like Jest now, and more bug fixes
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
Re-introducing @types/bun
(formerly bun-types
)
@types/bun
gives you type definitions for Bun. It's a separate package from Bun itself, to make it easier to use Bun with your text editor or IDE.
Previously, this package was called bun-types
and there were a lot of issues with it:
- You had to set
types
in yourtsconfig.json
, which broke loading packages using the@types
folder convention - We embedded a slightly modified version of
@types/node
, which frequently conflicted with the real@types/node
package - It didn't "just work" with TypeScript unless you configured it correctly
- DOM/Web types would occasionally conflict with Bun's types
Now, @types/bun
should just work. It re-exports the real @types/node
package so there's no conflicts. Since it's now in the @types
namespace, it should work without breaking @types/*
packages.
To install @types/bun
:
bun add -d @types/bun
Or you can ue bun init
:
bun init
bcrypt & argon2 packages now work
N-API compatibility improvements unlocked bcrypt
and argon2
package support in Bun. These packages are widely used to securely hash & verify passwords.
Bun.password also lets you hash and verify passwords using either bcrypt or argon2 without any dependencies to install.
|
|
Fixed: "lockfile had changes, but is frozen" bug
The code path used by --frozen-lockfile
to detect whether a lockfile changed sometimes incorrectly reported that the lockfile changed when it didn't. This would cause errors like:
error: lockfile had changes, but is frozen
To fix this, we've changed how we define "frozen". Instead of relying on input from the filesystem which can potentially change for unrelated reasons, we've switched it to using a hash of the package names and their versions sorted alphabetically with their version numbers. We think this is a more reliable approach.
To see what the hash of your lockfile is, run:
bun pm hash-string
View example output
setTimeout
& setInterval
get 4x higher throughput
Bun's setTimeout
and setInterval
implementations are now 4x faster on Linux x64. We've added a timer heap to more efficiently manage timers.
❯ bun setTimeout-leak-test.js
Executed 1003520 timers in 421.560553 ms
❯ bun-1.0.18 setTimeout-leak-test.js
Executed 1003520 timers in 2287.405973 ms
Thanks to @mitchellh's libxev for the timer heap implementation.
Why is timer performance important?
You might be thinking something like:
"Timers delay code execution. Why does it matter if it's fast?"
Timer scheduling has a significant performance impact on your code, and many libraries use timers to schedule work with a slight delay. Timers don't have to trigger much faster, but timer scheduling needs to be fast.
Bun's previous timer implementation was somewhat irresponsible. On Linux, it created a timerfd
for every timer. This means every timer involves multiple system-calls and occupies a file descriptor. That's a lot of overhead for code which potentially runs very frequently.
Bun's new timer implementation uses a timer heap. This is a data structure that allows us to efficiently schedule potentially millions of timers.
Fixed: setInterval
sometimes still ran after clearInterval
There was a bug where an already-cancelled call to setInterval
would occasionally still run one time. This was fixed along the way to rewriting the timer implementation.
Better error for using await
outside an async
function
We've added a better error message when you use await
outside of an async
function.
❯ bun file.js # after
3 | await fetch("https://example.com")
^
error: "await" can only be used inside an "async" function
at file.js:3:9
2 | function ohNo() {
^
note: Consider adding the "async" keyword here
at file.js:2:1
Before, it would just say:
❯ bun-1.0.18 file.js # before
3 | await fetch("https://example.com")
^
error: Expected ";" but found "fetch"
at file.js:3:9
Optimized Bun.spawnSync
for large input on Linux
On Linux, Bun.spawnSync
now gets smarter about how it reads and writes data from child processes. We've switched from a pipe which must be read & written in a loop by the parent process to an in-memory file descriptor which does not cause processes to block when reading or writing large amounts of data. This also lets us avoid cloning the data from the child process to the parent process which can be expensive for large amounts of data.
This change makes Bun.spawnSync
50% faster when the child process has a large amount of output.
Bun.peek()
gets 90x faster
Bun.peek(promise)
lets you read a promise's value without waiting for it to resolve, if it's no longer pending. This is useful to avoid microtasks and improve performance.
We've switched the implementation from relying on C++ SPI to using a JavaScriptCore bytecode intrinsic which makes it 90x faster.
Thanks to @paperdave
expect(map1).toEqual(map2) gets 100x faster
We've optimized the implementation of expect(...).toEqual
when comparing Map
instances. This makes it 100x faster for maps. This also makes it faster for Set
instances.
We've also fixed a bug where toEqual
on large maps would sometimes incorrectly report the maps are not equal.
module mocks in bun:test
resolve specifiers
Bun supports mocking modules in bun:test
using the mock.module
function. Previously, the specifier
argument had to exactly match the resolved module specifier used when loading the overridden module.
This was very confusing! People usually don't think about the difference between a resolved module specifier and a module specifier, and that means it seemed to not work when it actually did. Since ES Modules resolve and link modules before evaluating them, the resolved module specifier is usually different from the module specifier you use in import
statements.
Now, mock.module
resolves the specifier before mocking the module. This means you can use the module specifier (the path you put in import
statements) instead of the resolved module specifier (the path you see in error messages).
import { mock, test, expect } from "bun:test";
import _ from "lodash";
// Before: you had to resolve it yourself:
mock.module(require.resolve("lodash"), () => ({ default: "mocked" }));
// Now: you can use the module specifier:
mock.module("lodash", () => ({ default: "mocked" }));
test("lodash is mocked", () => {
expect(_).toEqual("mocked");
});
Log slow postinstall scripts
If a post-install script takes longer than 500ms to run, bun install
will now log it as a warning. This is useful to identify slow post-install scripts.
bun add v1.0.19 (7e59f287)
installed re2@1.20.9
+warn: re2's install script took 57.7s
92 packages installed [58.20s]
To avoid cluttering your terminal scrollback, we only log the slowest post-install script (not all of them).
Thanks to @paperdave.
Fixed: potential hang when running post-install scripts
There was an event loop bug that could cause bun install
to potentially hang (by not realizing they've exited) when running post-install scripts. This was fixed, thanks to @dylan-conway.
bun install --verbose
now streams post-install script output
When running bun install --verbose
, post-install script output is now streamed to the terminal instead of buffered and printed at the end. This makes it easier to see what's happening. Thanks to @dylan-conway for implementing this.
Fixed: missing progress bar in post-install script output
In certain cases, bun install
would not show a progress bar while the post-install scripts are running. This has been fixed, thanks to @dylan-conway.
Fixed: stringifying SHA1, SHA256, MD5 hashes sometimes output too long of a string
A bug when encoding the output of a SHA1, SHA256, or MD5 hash as a hex
or base64
string would sometimes output a string that was longer than the contents of the hash. This is now fixed.
This impacted:
Bun.CryptoHasher
createHash
innode:crypto
Upgraded SQLite from v3.38.5 to v3.44.2
bun:sqlite
is a fast SQLite client built into Bun. On Linux, bun:sqlite
is statically linked which means we embed the SQLite library into Bun itself. This means you don't need to install SQLite on your system to use it.
We've upgraded the embedded SQLite library from v3.38.5 to v3.44.2. You can see the full changelog here.
Fixed: TypeScript parser edgecase
Previously, the following input would incorrectly fail to parse:
const a = <T = any>(): T => null as T;
const b = a<string>
This is now fixed. Thanks to @paperdave for fixing this.
Fixed: crash in bun init
A crash that sometimes occurred in bun init
has been fixed, thanks to @paperdave.
Fixed: regression with $NODE_ENV
In Bun v1.0.18 (the previous version), we accidentally removed setting a default value for NODE_ENV
. This breaking change was not meant to be included in Bun v1.01.8. We may do a breaking change in the future to unset a default value (outside bun test
), but we will not do this in a patch release.
Thanks to @paperdave for fixing this.
Fixed: printing bug with holey arrays
There was a bug where printing holey arrays would miss the delimiter & comma. This is now fixed, thanks to @amartin96.
After:
❯ bun -e 'console.log([1,,,2,1,3])' # After
[ 1, 2 x empty items, 2, 1, 3 ]
Before:
❯ bun-1.0.18 -e 'console.log([1,,,2,1,3])' # Before
[ 12 x empty items, 2, 1, 3 ]
New matcher in bun:test expect().toContainEqual()
We've added a new matcher to bun:test
called toContainEqual
. This is similar to toContain
, but it uses toEqual
to compare the values instead of ===
.
import { test, expect } from "bun:test";
test("toContainEqual", () => {
expect("hello world").toContainEqual("hello");
expect("hello world").not.toContainEqual("jello");
});
Thanks to @Electroid for implementing this.
Credits
We love seeing new contributors! Here are the 9 people who made their first contribution to Bun in this release:
- @Osmose made their first contribution in #7275
- @scotttrinh made their first contribution in #7686
- @vlechemin made their first contribution in #7688
- @dotspencer made their first contribution in #7727
- @spicyzboss made their first contribution in #7737
- @bjon made their first contribution in #7738
- @amartin96 made their first contribution in #7751
- @sirhypernova made their first contribution in #7760