Changelog

oven-sh/bun · · 35 commits

Bun tightens HTTP, install, and stream fixes

Major fixes landed across cluster, HTTP/2/3, install, streams, abort timers, and bundler bytecode behavior.

Cluster now supports real handle passing and round-robin sharing (cirospaciari626034f)

Bun’s node:cluster implementation was brought in line with Node’s behavior, including IPC handle passing, round-robin fd handoff, shared handles, and UDP clustering. This unblocks workers from silently binding their own sockets and makes clustered servers actually share listeners as expected.

Install now handles shared git repos and workspace-targeted updates correctly (robobuna63b064, robobun315136d, robobuna8c807f)

Git dependencies that point at different branches of the same repository now share clone work safely without dropping package resolution callbacks. Bun also fixed bun update filtering/recursive updates for non-interactive runs, and tightened lockfile resolution so bundled optional peers don’t drift past the hoist root.

HTTP and TLS fix a batch of connection-lifecycle bugs (robobun2055fe9, robobunfd1ea1b, robobun0825a8b, robobunaa9a59f)

Several low-level HTTP bugs were corrected around refcounting, proxy tunnel reuse, adopted sockets, and TLS write reentrancy. Together these changes reduce use-after-free risk, keep HTTPS proxy tunnels pooled in the right TLS context, and make socket adoption/writes safer under load.

AbortSignal.timeout no longer leaks or stalls in edge cases (robobun6e047ff, robobun7f1ae4e)

AbortSignal.timeout() now keeps its timer armed even if observers disappear before the deadline, and it also cancels/discards unfired timers when the heap drops them. That fixes both missed timeouts and long-lived heap leaks under fake timers, isolate swaps, and test teardown.

Streams now deliver direct-stream bytes and promises more consistently (robobun8c7ed92)

Direct ReadableStream sources now deliver bytes written after a flush to pipeTo, tee, and for-await readers instead of dropping them. The controller logic was adjusted so queued consumers and promise-backed reads follow the right delivery path.

Bytecode ESM output now matches the printer’s exports (robobuna0782cd)

The bundler stopped building ESM bytecode module records from stale linker state and instead uses what the printer emits. This fixes broken --compile --bytecode --format=esm output where re-exports could become TDZ failures at runtime.

ESM imports for builtin/native modules stay lazy (robobund8e3e19, robobun6596bf1, robobun2ffb8d4)

Bun’s ESM views of builtins like bun, node:process, and node:module no longer eagerly reify every export at import time. That preserves lazy accessor behavior and avoids unnecessary work and side effects during module loading.

Other misc changes