We're hiring C/C++ and Zig engineers to build the future of JavaScript! Join our team →
We've been releasing a lot of changes to Bun recently, here's a recap in case you missed it:
v0.6.0- Introducingbun build, Bun's new JavaScript bundler.v0.6.2- Performance boosts: 20% fasterJSON.parse, up to 2x fasterProxyandarguments.v0.6.3- Implementednode:vm, lots of fixes tonode:httpandnode:tls.v0.6.4- Implementedrequire.cache,process.env.TZ, and 80% fasterbun test.v0.6.5- Native support for CommonJS modules (previously, Bun did CJS to ESM transpilation),v0.6.6-bun testimprovements, including Github Actions support,test.only(),test.if(),describe.skip(), and 15+ moreexpect()matchers; also streaming file uploads usingfetch().v0.6.7- Node.js compatibility improvements to unblock Discord.js, Prisma, and Puppeteerv0.6.8-Bun.password, function mocking inbun test, and atoMatchObjectexpect matcher. Plus an experimentalinspectormode inBun.serve().
This release reduces Bun's memory usage across the board and fixes bugs in the bundler/transpiler, CommonJS module loading, bun run, and bun install.
To install Bun:
curl -fsSL https://bun.sh/install | bashnpm install -g bunbrew tap oven-sh/bunbrew install bundocker pull oven/bundocker run --rm --init --ulimit memlock=-1:-1 oven/bunTo upgrade Bun:
bun upgradeBun.serve() uses less memory to send strings
Bun now supports zero-copy string Response bodies in Bun.serve().
In the next version of Bun
— Jarred Sumner (@jarredsumner) June 11, 2023
Sending strings with Bun's HTTP server uses less memory.
After responding to 1000 requests with a 12 MB string
Bun: 60 MB ram
Deno: 425 MB ram
Node: 1414 MB ram pic.twitter.com/LJ6FdAcWkZ
We've also applied this optimization to Response outside of Bun.serve()
Previously, the following code would clone text twice:
const text = await Bun.file("file.txt").text();
// Copy #1
const response = new Response(text);
// Copy #2
await response.text();
Now, it doesn't copy, saving you memory.
Cold bun install uses 50% less memory
We free more memory in bun install now, reducing memory usage by 50% for cold installs.
In the next version of Bun
— Jarred Sumner (@jarredsumner) June 10, 2023
bun install (cold) uses 2x less memory pic.twitter.com/HePmK3uHUx
Importing modules in Bun's runtime uses less memory
We've fixed a couple memory leaks in Bun that happened when importing modules in Bun's runtime, and improved our bindings with JavaScriptCore for source code management.
Non-ascii filenames
Previously, Bun would throw an error when importing a file with a non-ascii filename.
bun run 👋.js
error: FileNotFound reading "/Users/jarred/Desktop/ð.js"console.log("hello!");
This error was caused by both a printing bug and a bug in Bun's JavaScriptCore bindings when reading import identifier names.
Bugfixes to mocks in bun test
mockResolvedValue is fixed in bun test now. Previously, mockResolvedValue would appear to do nothing in bun test.
To use mockResolvedValue:
import { mock, test, expect } from "bun:test";
test("hey", async () => {
const fn = mock.mockResolvedValue(1);
expect(fn()).toBeInstanceOf(Promise);
const value = await fn();
expect(value).toBe(1); // 1
});
The mock object returned was missing a .bind, .apply, .call, .name, and .length functions. This has been fixed. We've also made it so that the .name of the mocked function is copied over from the original function automatically.
import { mock, test, expect } from "bun:test";
test("hey", async () => {
const hey = mock(function yo() {
return 42;
});
expect(hey.name).toBe("yo");
});
Crash in CommonJS require() fixed
This release fixes a crash that can occur when many CommonJS files are imported and then the garbage collector is run after the files are no longer in use:
import "lodash/omit.js";
import "lodash/findIndex.js";
import "discord.js";
Bun.gc(true);
This was a bug in the CommonJS module loader not correctly preventing the function from being garbage collected.
A memory leak in node:crypto has been fixed
This release fixes a memory leak in node:crypto. The following code would leak about 192 bytes per call.
const crypto = require("crypto");
function sha256(buf) {
return crypto.createHash("sha256").update(buf).digest();
}
async function main() {
for (var i = 1000000; i >= 0; i--) {
const buf = Buffer.alloc(2046);
const hash = sha256(buf);
if (i % 1000 === 0) {
await new Promise((r) => setTimeout(r, 20));
global.gc ? global.gc() : Bun?.gc(true);
}
}
}
main();
After:
Before:
Node.js, for comparison:
Changelog
#3277 | add --save argument to install by @kvakil |
#3292 | handle unwrapping require in any expression by @dylan-conway |
#3286 | Typo in readline by @paperclover |
#3290 | workaround quote escape issues for bun run |