Bun

Bun v0.6.9


Jarred Sumner · June 13, 2023

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 - Introducing bun build, Bun's new JavaScript bundler.
  • v0.6.2 - Performance boosts: 20% faster JSON.parse, up to 2x faster Proxy and arguments.
  • v0.6.3 - Implemented node:vm, lots of fixes to node:http and node:tls.
  • v0.6.4 - Implemented require.cache, process.env.TZ, and 80% faster bun test.
  • v0.6.5 - Native support for CommonJS modules (previously, Bun did CJS to ESM transpilation),
  • v0.6.6 - bun test improvements, including Github Actions support, test.only(), test.if(), describe.skip(), and 15+ more expect() matchers; also streaming file uploads using fetch().
  • v0.6.7 - Node.js compatibility improvements to unblock Discord.js, Prisma, and Puppeteer
  • v0.6.8 - Bun.password, function mocking in bun test, and a toMatchObject expect matcher. Plus an experimental inspector mode in Bun.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
npm
brew
docker
curl
curl -fsSL https://bun.sh/install | bash
npm
npm install -g bun
brew
brew tap oven-sh/bun
brew install bun
docker
docker pull oven/bun
docker run --rm --init --ulimit memlock=-1:-1 oven/bun

To upgrade Bun:

bun upgrade

Bun.serve() uses less memory to send strings

Bun now supports zero-copy string Response bodies in Bun.serve().

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.

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.

image

Non-ascii filenames

Previously, Bun would throw an error when importing a file with a non-ascii filename.

shell
👋.js
shell
bun run 👋.js

error: FileNotFound reading "/Users/jarred/Desktop/ð.js"
👋.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

#3277add --save argument to install by @kvakil
#3292handle unwrapping require in any expression by @dylan-conway
#3286Typo in readline by @paperdave
#3290workaround quote escape issues for bun run

View Full Changelog