Bun v1.1.26 is here! This release fixes 9 bugs (addressing 652 👍). bun oudated
shows outdated dependencies. Bun.serve()
gets a new idleTimeout
option for socket timeouts, and subscriberCount(topic: string)
for a count of websocket clients subscribed to a topic. bun test.only skips all other tests. expect.assertions(n) in async functionn is fixed. "use strict" in CommonJS modules is now preserved. Plus, more node.js compatibility improvements and bug fixes.
We're hiring systems engineers in San Francisco to build the future of JavaScript!
To install Bun
curl -fsSL https://bun.sh/install | bash
npm install -g bun
powershell -c "irm bun.sh/install.ps1|iex"
scoop install 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
bun outdated
shows outdated dependencies
bun outdated
is a new subcommand that shows you which dependencies are outdated.
bun outdated
In the next version of Bun
— Bun (@bunjavascript) August 23, 2024
bun outdated lists oudated dependencies, their semver-matching versions, and the latest version pic.twitter.com/7pKSSdQfGK
The Update
column displays what the next semver-matching version is. The Latest
column displays the latest
tagged version from the npm registry.
This was one of the top most upvoted issues on Bun's GitHub repository. Huge thanks to @dylan-conway for implementing this feature!
test.only
skips all other tests
Previously, the following would run the first two tests, and skip the third test. This was very confusing! Why did we do it this way!?
import { test, describe } from "bun:test";
test("i should not run!", () => {
// previously: runs
// now: does not run
console.log("why am i running?");
});
// ... more tests in a much longer file ...
test.only("i should run!", () => {
// runs
console.log("yes only i should run");
});
test("I definitely should not run!", () => {
// does not run
console.log("i don't run");
});
This was really frustrating because the only way around it was the --only
CLI flag.
bun test --only
Now, you don't have to do that. bun test
will detect there was a .only
test in the file and skip all the tests that don't have .only
in them.
The existence of a .only
test in a file is also reset when the next module starts loading tests. This means that a .only
will only impact the current file instead of all files.
subscriberCount(topic: string) in Bun.serve()
Bun.serve()
's builtin-in WebSocket server now supports subscriberCount(topic: string)
to get the number of websocket clients subscribed to a topic.
import { serve } from "bun";
const server = serve({
port: 3002,
websocket: {
open(ws) {
const count = server.subscriberCount("chat");
ws.subscribe("chat");
ws.publish(`chat`, `🐰 #${count} joined the chat`);
},
},
fetch(req, server) {
return server.upgrade(req);
},
});
idleTimeout
in Bun.serve()
You can now set a custom idle timeout (in seconds) for Bun.serve()'s builtin-in HTTP(s) server.
import { serve } from "bun";
const server = serve({
async fetch(req) {
await Bun.sleep(1000 * 60 * 2); // 2 minutes
return new Response("Hello, it's been 2 minutes!");
},
// minutes:
idleTimeout: 60 * 4, // 4 minutes
});
Previously, this was always set to 10 seconds. The default continues to be 10 seconds, but in cases where you need that to be a longer or shorter amount of time, you can now set it to a different value.
This option was previously only available for connected WebSocket clients, and now it's available for regular HTTP(s) requests as well.
Thanks to @cirospaciari for implementing this feature!
Fixed: expect.assertions(n)
in async functions
expect.assertions(n: number)
now works as expected in async functions.
The following test that should've failed previously would not have failed.
import { test, expect } from "bun:test";
test("this test should NOT pass", async () => {
expect.assertions(1);
await Bun.sleep(2);
// the assertion is commented out.
// so this test should always fail.
// expect(1).toBe(1);
});
Now, the test will fail:
bun test
bun test v1.1.26
passy.test.ts:
AssertionError: expected 1 assertions, but test ended with 0 assertions
✗ this test should NOT pass [3.57ms]
0 pass
1 fail
Ran 1 tests across 1 files. [8.00ms]
expect().toThrow()
supports asymmetric matchers
You can now use expect().toThrow()
with asymmetric matchers like expect.objectContaining()
:
import { test, expect } from "bun:test";
test("this test should NOT pass", () => {
expect(() => {
const error = new Error("oh no!");
error.code = "ERR_OH_NO";
throw error;
}).toThrow(expect.objectContaining({ message: "oh no!", code: "ERR_OH_NO" }));
});
Fixed: done
callback in tests causing a hang
Previously, there were a number of cases where using a done
callback in test
would cause the test to hang indefinitely when not called.
For example, this test would fail and then hang forever:
import { test, expect } from "bun:test";
test("this test should NOT hang", (done) => {
process.nextTick(() => {
throw new Error("oh no!");
done();
});
});
One could argue, "The done
callback was never called! It's only logical that it would hang forever!" but that's not the case. The test already failed. It had an uncaught exception. Therefore, the test does not need to hang forever (or timeout). It can fail immediately once all microtasks have been drained and the task queue is empty.
In other words, tests will continue running once all other known work is complete instead of waiting for the done
callback to be called after an exception is thrown.
Fixed: mock().mockName() not returning this
The mock()
function in Bun's test runner now returns this
. This is to align the behavior with jest so that existing tests written for jest can be ported to Bun.
Node.js compatibility improvements
Fixed: Top-level "use strict"
in CommonJS modules preserved at runtime
Previously, Bun would strip a top-level "use strict"
directive from CommonJS modules at runtime. This was intended for ES modules as it is unnecessary in those cases, but it IS necessary for CommonJS modules and is now fixed.
Preivously, the following code would print "I am globalThis" in Node.js, and "I am undefined" in Bun.
// Before:
"use strict";
function whoami() {
return this;
}
const me = whoami();
if (me === globalThis) {
console.log("I am globalThis!");
} else {
console.log("I am undefined!");
}
exports.whoami = whoami;
Now, it prints "I am globalThis" in both Node.js and Bun.
Fixed: util.inherits bug
A bug where util.inherits
was using Object.create
instead of Object.setPrototypeOf
has been fixed. This caused the snowflake sdk to fail to load.
Thanks to @dylan-conway for fixing this bug!
Fixed: crypto.randomValues() crash in certain cases
A rare JIT-related crash in crypto.randomValues()
has been fixed.
Fixed: crash in Buffer in certain cases
A rare crash in Buffer
found while running the Node.js test suite has been fixed.
Fixed: ERR_INVALID_THIS
code returned in certain web APIs
Node.js' test suite expects certain web APIs to return an error with the ERR_INVALID_THIS
code
property.
For compatibility, Bun now returns these errors with the ERR_INVALID_THIS
code.
Fixed: dns.resolveSrv confusing weight
and priority
A bug where the priority
field was being set to the weight
field in dns.resolveSrv
has been fixed, thanks to @cirospaciari.
Fixed: rare crash in fetch()
A rare crash in fetch()
involving AbortSignal has been fixed, thanks to @cirospaciari.