This release fixes two regressions impacting Elysia and AsyncLocalStorage, a hang in @discordjs/ws, CMYK JPEG decoding in Bun.Image, a rare JIT crash, and a GC crash on musl.
To install Bun
curl
curl -fsSL https://bun.sh/install | bashnpm
npm install -g bunpowershell
powershell -c "irm bun.sh/install.ps1|iex"scoop
scoop install bunbrew
brew tap oven-sh/bunbrew install bundocker
docker pull oven/bundocker run --rm --init --ulimit memlock=-1:-1 oven/bunTo upgrade Bun
bun upgradeFixed: bun build variable name collision#
A regression introduced in Bun v1.4.1 impacting Elysia caused bun build to rename a nested var to the same name as a let in the same block. Builds importing Elysia would fail to load with SyntaxError: Cannot declare a var variable that shadows a let/const/class variable. This has been fixed and a regression test has been added.
index.js
function foo () {
{
let exports2 = {};
var exports = exports2;
}
return exports;
}
module.exports = foo();bun build index.js --outfile out.js would output code containing:
out.js
// inside CJS module wrapper
function foo() {
{
let exports2 = {};
var exports2 = exports2; // SyntaxError
}
return exports2;
}
module.exports = foo();The same bug could also give a let the name of a function parameter or catch binding, producing code that evaluates but computes incorrect values.
Fixed: AsyncLocalStorage memory leak#
A regression introduced in Bun v1.4.1 caused a timer, immediate, or pending promise created inside store.exit() or a nested store.run() to keep the outer store value alive for as long as that timer or promise existed. getStore() still returned the correct value, so only memory usage was affected. This has been fixed.
const store = new AsyncLocalStorage();
store.run(bigPerRequestContext, () => {
store.exit(() => setTimeout(() => {}, 3_600_000));
// kept bigPerRequestContext alive for an hour
});Fixed: worker_threads 'online' event order#
A Worker from node:worker_threads didn't emit 'online' first, causing @discordjs/ws to hang due to missing a worker's first message. The order now matches Node.js.
import { Worker, isMainThread, parentPort } from "worker_threads";
import { once } from "events";
if (isMainThread) {
const worker = new Worker(new URL(import.meta.url));
await once(worker, "online");
worker.on("message", (msg) => {
console.log(msg); // never received in v1.4.1
});
} else {
parentPort.postMessage("hi");
}Fixed: Bun.Image decodes CMYK and YCCK JPEGs#
Bun.Image now decodes 4-component CMYK and YCCK JPEGs. Previously these failed with Image: decode failed. They are converted to RGB on decode, so every transform and output format works.
await new Bun.Image("photo-cmyk.jpg").resize(400, 400).webp().bytes();Upgraded JavaScriptCore#
Bun v1.4.2 pulls in about 350 more upstream WebKit commits. They include Intl and TypedArray correctness fixes, a fix for a Proxy crash, and cheaper Date objects.
new Intl.PluralRules("en").select(1n); // => "one" (was TypeError)new Int32Array(array)(and the other TypedArray constructors) read a stale or missing element when an element'svalueOfmutatedarrayduring conversion.TypedArray.prototype.sliceinto aSymbol.speciesview that overlaps its source on the same buffer now copies in spec order.Intl.DurationFormatwithstyle: "digital"no longer prints a stray:whenminutesis0and hidden.Object.setPrototypeOf(handler, null)on aProxyhandler that had already served a trap could crash when the handler came from a class defined inside a function called many times.
Bugfixes#
- Fixed: a rare crash in long-running processes after a prototype that JIT-optimized code had cached property lookups through was garbage-collected.
- Fixed: on musl (Alpine),
Array.prototype.splice,shift, or shrinkingarray.lengthon an array of objects could crash on a GC thread or hang if it ran while the GC was marking.
- Fixed:
.json()on aResponse,Blob,Bun.file(), orproc.stdoutrejected invalid JSON with a genericFailed to parse JSONinstead of theSyntaxErrormessageJSON.parsegives, such asJSON Parse error: Expected '}'.
- Fixed:
bun installandbun addcould panic withrange end index out of rangewhenbun.lockbor a cached registry manifest stored a package-name hash that didn't match the name.
- Fixed: on Linux, if registering a
Bun.file().writer()FileSinkwith epoll failed (for examplefs.epoll.max_user_watchesexhausted), its file descriptor was closed twice, which could close an unrelated descriptor that reused the number.