We're hiring C/C++ and Zig engineers to build the future of JavaScript! Join our team →
Last week, we launched our new JavaScript bundler in Bun v0.6.0.
Today, we're releasing support for node:vm
, improvements to node:tls
and node:http
— which fixes support for socket.io
and mongodb
, improvements to bun test
— which introduces test.todo()
, test timeouts, and better preloading, and many fixes to Bun's bundler.
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
Introducing node:vm
Bun now has support for the built-in node:vm
module. It can be used to execute code, similar to eval()
, except with more control over which globalThis
JavaScript context the code is executed.
import { runInContext } from "node:vm";
let context = {
foo: "bar",
baz: 123,
};
runInContext(`foo = "fizz"; delete baz;`, context);
console.log(context.foo); // "fizz"
console.log(context.baz); // undefined
You can also use runInNewContext
to run code in a separate JavaScript context.
import { runInNewContext } from "node:vm";
runInNewContext(`globalThis.fetch = undefined;`);
console.log(globalThis.fetch); // [Function fetch]
Thanks to @silversquirl for implementing this feature!
Fixes for node:tls
and node:http
We've fixed a lot of code with TLS and HTTP, such as TLS handshaking, so you can now use socket.io
and mongodb
authentication in Bun.
In the next version of Bunhttps://t.co/Pc0bps2VFV server works, and it runs 2x faster in Bun.
— Jarred Sumner (@jarredsumner) May 21, 2023
left: bun (400k msgs/sec)
right: node (200k msgs/sec) pic.twitter.com/9jW09NiGGc
Thanks to @cirospaciari for working on this!
Improvments to bun test
test.todo()
You can now use test.todo()
to mark tests that you want to implement later.
expect().toBeCloseTo()
You can also use expect().toBeCloseTo()
to compare two floating-point numbers.
import { test, expect } from "bun:test";
test("toBeCloseTo()", () => {
expect(3 + 0.14).toBeCloseTo(3.14);
expect(3.14).toBeCloseTo(Math.PI, 2);
});
Thanks to @blackmann for working on both of these features!
Test timeouts
You can now set a timeout for your tests with a third argument to test()
.
import { test } from "bun:test";
test("i took too long", async () => {
await Bun.sleep(100);
}, 50); // the last argument is a timeout in milliseconds
Hook support with --preload
You can now use beforeAll
, beforeEach
, afterEach
, and afterAll
with the --preload
flag.
This lets you run code before and after all files instead of just the current file. This is useful for libraries that need to be initialized before running tests.
import { test, beforeAll, beforeEach, afterEach, afterAll } from "bun:test";
beforeEach(() => {
console.log("This runs before each test in every file");
});
Fixes to pretty-printing
We also fixed bug that would cause code like this to print values as undefined
in the test runner.
import { test, expect } from "bun:test";
test("wat", () => {
const left = {};
const right = {};
for (let i = 0; i < 2; i++) {
left[i] = i + 1;
right[i] = i + 2;
}
expect(left).toBe(right);
});
Before | After |
---|---|
Fixes to bun build
A crash that was highlighted in Using Bun.js as a bundler when
--minify
with multiple entry points was enabled has been fixed. It was a race condition when merging adjacent top-level variable declarations.A bug that caused assets to copy to an incorrect output path has been fixed.
A minifier bug involving template literals being incorrectly merged has been fixed.
A race condition that could occur when generating sourcemaps has been fixed.
A bug that allowed generated variable names to start with numbers has been fixed.
A crash that could occur when creating the
BuildArtifact
objects after saving to disk has been fixed.A memory leak in the logs has been fixed.
Improved an error message when using a Node.js built-in when building for browsers to suggest g the
--target
option tonode
orbun
.
fetch()
memory leak
Two memory leaks found in fetch()
have been fixed.
- The callback was creating two strongly-held references to the
Promise<Response>
object, which prevented it from being garbage collected. - The input validation logic would potentially create a strongly held
Promise<Response>
and immediately discarded it, without releasing the strong reference. This prevented thePromise<Response>
from being garbage collected.
This was embarrassing and we've improved our test coverage for memory leak tests to make sure this doesn't happen again. Here was graph of the memory leak, courtesy of @dimka3553:
Improvements to console.log()
Mismatched quotes
Previously, console.log()
would print mismatched quotes for non-ascii property names. This is now fixed.
{
'🐛 Bug with mismatched quotes": 'fixed'
}
Set depth limit
Previously, console.log()
would print an infinite amount of nested objects, excluding circular references. This was sometimes undesirable and caused crashes when printing sufficiently large objects. This has been fixed with a depth limit of 8.
Remove unnecessary quote identifiers
Previously, Bun would unnecessarily quote object keys in console.log
and this was a little noisy. After a Twitter poll voted 90% in favor of removing the quotes, we did it.
in the next version of bun
— Jarred Sumner (@jarredsumner) May 19, 2023
console.log(obj) property keys with valid identifiers are no longer quoted pic.twitter.com/w1uSCovyRM
Changes to WebSocket
Breaking change to publishToSelf
behaviour
Bun supports publish/subscribe in its server-side WebSocket
APIs. You can use Server.publish()
or ServerWebSocket.publish()
to send a message to each connected client.
However, we made a design mistake with the ServerWebSocket.publish()
API, as it also sent a message to itself — when the typical behaviour is to exclude it. We patched this mistake by introducing an optional publishToSelf
option, but the default behaviour was still confusing, as highlighted by various issues.
So we're relunctantly fixing this behaviour, with a breaking change, to match developers' intuition. We rarely make these types of decisions, but when we do, we make sure there is overwhelming evidence and feedback that maintaing the status-quo is more harmful than any potential breakage.
const server = Bun.serve({
websocket: {
open(ws) {
ws.subscribe("topic");
// <= Bun v0.6.2
ws.publish("topic", "send to all clients, including `ws`");
// >= Bun v0.6.3
ws.publish("topic", "send to all clients, excluding `ws`");
},
},
fetch(request, server) {
if (server.upgrade(request)) {
return;
}
return new Response();
},
});
Buffer
support in WebSocket
messages
Many npm packages expect Buffer
objects as WebSocket
messages. Instead of asking you to re-create the Buffer
object yourself when passing through to a library, Bun now lets you directly receive a "nodebuffer"
value for binary WebSocket messages.
const server = Bun.serve({
websocket: {
open(ws) {
ws.binaryType = "nodebuffer";
ws.send(Buffer.from("hello world"));
},
message(ws, message) {
console.log(Buffer.isBuffer(message)); // true
},
},
fetch(request, server) {
if (server.upgrade(request)) {
return;
}
return new Response("hello world");
},
});
const client = new WebSocket("ws://localhost:3000");
client.binaryType = "nodebuffer";
client.onmessage = ({ data }) => {
console.log(Buffer.isBuffer(data)); // true
};
More bug fixes
fs.writeFile({ flag: "a" })
now appends to files instead of overwriting it- N-API finalizers are now called with the correct data pointer and finalizer hint
- A crash that could occur when creating many Error objects inside a bound function has been fixed, thanks to @Constellation
- Setting megamorphic property values gets faster in this release, thanks to @Constellation
Changelog
2544742 | Fixed memory leak with BuildError and ResolveError by @Jarred-Sumner |
4f7198f | Fixed incorrect behaviour with fs.writeFile({ flag: "a" }) by @Jarred-Sumner |
aacbef3 | Improved error message when node built-in could not be resolved by @Jarred-Sumner |
#2939 | Fixed incorrect encoding of utf8 property names by @Jarred-Sumner |
#2937 | Fixed bug with incorrect String.raw output by @dylan-conway |
#2870 | Implemented expect().toBeCloseTo() by @blackmann |
#2947 | Fixed crash when bundling with multiple entrypoints by @Jarred-Sumner |
#2949 | Fixed "Numeric separators are not allowed at the end of numeric literals" by @Jarred-Sumner |
5bec025 | Fixed issue where the cwd is not writable during bundling by @Jarred-Sumner |
b76974a | Fixed bug where IncomingMessage.socket was not writable by @Jarred-Sumner |
#2785 | Implemented node:vm by @silversquirl |
#2962 | Improved node-fetch polyfill to include more exports by @Jarred-Sumner |