---
title: Bun v0.6.10
description: Reduced memory usage, fs.watch(), better CommonJS support, improvements to `bun test`, `bun install`, and many bugfixes.
date: "2023-06-26T20:15:43+00:00"
author: ashcon
draft: false
---

{% callout %}
We're hiring C/C++ and Zig engineers to build the future of JavaScript! [Join our team →](/careers)
{% /callout %}

We've been releasing a lot of changes to Bun recently, here's a recap in case you missed it:

- [`v0.6.0`](/blog/bun-bundler) - Introducing `bun build`, Bun's new JavaScript bundler.
- [`v0.6.2`](/blog/bun-v0.6.2) - Performance boosts: 20% faster `JSON.parse`, up to 2x faster `Proxy` and `arguments`.
- [`v0.6.3`](/blog/bun-v0.6.3) - Implemented `node:vm`, lots of fixes to `node:http` and `node:tls`.
- [`v0.6.4`](/blog/bun-v0.6.4) - Implemented `require.cache`, `process.env.TZ`, and 80% faster `bun test`.
- [`v0.6.5`](/blog/bun-v0.6.5) - Native support for CommonJS modules (_previously, Bun did CJS to ESM transpilation_),
- [`v0.6.6`](/blog/bun-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`](/blog/bun-v0.6.7) - Node.js compatibility improvements to unblock Discord.js, Prisma, and Puppeteer
- [`v0.6.8`](/blog/bun-v0.6.8) - Introduced `Bun.password`, mocking in `bun test`, and `toMatchObject()`
- [`v0.6.9`](/blog/bun-v0.6.9) - Less memory usage and support for non-ascii filenames

To install Bun:

{% codetabs %}

```sh#curl
$ curl -fsSL https://bun.sh/install | bash
```

```sh#npm
$ npm install -g bun
```

```sh#brew
$ brew tap oven-sh/bun
$ brew install bun
```

```sh#docker
$ docker pull oven/bun
$ docker run --rm --init --ulimit memlock=-1:-1 oven/bun
```

{% /codetabs %}

{% raw %}
<br>
{% /raw %}

To upgrade Bun:

```sh
$ bun upgrade
```

## Improved CommonJS support

Loading npm packages in Bun is more reliable now. This is because we rewrote CommonJS module loading (again). We've fixed many crashes related to loading CommonJS modules and improved our CommonJS module loader to be more compatible with Node.js.

### [`webpack`](https://github.com/webpack/webpack) now works in Bun

{% raw %}

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">In the next version of Bun<br><br>webpack seems to work, thanks to <a href="https://twitter.com/dylanconway111?ref_src=twsrc%5Etfw">@dylanconway111</a> and <a href="https://twitter.com/cirospaciari?ref_src=twsrc%5Etfw">@cirospaciari</a> <a href="https://t.co/V9HEl3YRXy">pic.twitter.com/V9HEl3YRXy</a></p>&mdash; Jarred Sumner (@jarredsumner) <a href="https://twitter.com/jarredsumner/status/1673181952416047104?ref_src=twsrc%5Etfw">June 26, 2023</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
{% /raw %}

### `require.main` is now supported

`require.main` is a popular way for Node.js CLIs to check if the currently executing script started the process:

```ts
if (require.main === module.id) {
  // do something
}
```

Bun now supports [`require.main`](https://nodejs.org/api/modules.html#requiremain) which unblocks several Node.js CLIs.

We've also added [`process.mainModule`](https://nodejs.org/api/process.html#processmainmodule) which is an alias of `require.main`.

```js
console.log(require.main === process.mainModule); // true
```

### `__esModule` annotation is now supported

Bun now has runtime support for the `__esModule` annotation used by bundlers & TypeScript to indicate what `default` export should point to when importing a CommonJS module as an ES Module.

`__esModule` is an annotation that preserves the `export default <value>` for ESM that was converted into CommonJS and subseqntly re-imported back into ESM.

> Should `import a from 'b'` reference `module.exports` or `module.exports.default`?

This question is one of the things that has made the CommonJS -> ES Module transition difficult for the JavaScript ecosystem.

`__esModule` is a way to preserve the `default` import which is generated by Webpack, Babel, esbuild and used in many packages on npm. Bun now has runtime support for this.

That means the following input ES Module:

```js
export default 42;
```

Would typically be converted by build tools into CommonJS published to npm as something like:

```js
exports.default = 42;
exports.__esModule = true;
```

The `__esModule` annotation preserves the `default` value when imported back into ESM:

```js
import foo from "./foo.js";
console.log(foo); // 42
```

Note that, in Node.js, the `default` export is not preserved:

```js
import foo from "./foo.js";

// This is already the "default" export
// so why should you have to do .default to get the original value?
console.log(foo.default); // 42
```

For continued compatibility with Node.js, this behavior is disabled when there is no `__esModule` annotation OR when the enclosing package.json sets `"type"` to `"module"` (meaning, this is used in situations where Node.js would normally not support ESM anyway).

## WebSocket client encoding fix

We fixed an encoding bug in Bun's client implementation of `WebSocket`, which could cause a text frame with latin1 encoding to be truncated.

Thanks to these changes, support for [`puppeteer`](https://github.com/puppeteer/puppeteer) has been improved in Bun.

```js
import puppeteer from "puppeteer";

const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto("https://example.com/");
await page.click("a");
await browser.close();
```

## Improvements to `bun:test`

Bun now supports more matchers when using `bun test`:

- [`.resolves()`](https://jestjs.io/docs/asynchronous#resolves--rejects)
- [`.rejects()`](https://jestjs.io/docs/asynchronous#resolves--rejects)
- [`.toBeArray()`](https://jest-extended.jestcommunity.dev/docs/matchers/array/#tobearray)
- [`.toBeArrayOfSize()`](https://jest-extended.jestcommunity.dev/docs/matchers/array/#tobearrayofsize)
- [`.toBeTypeOf()`](https://vitest.dev/api/expect.html#tobetypeof)

```js
import { test, expect } from "bun:test";

test("new matchers", () => {
  expect(fetch("http://example.com")).resolves.toBeInstanceOf(Response);
  expect(fetch("invalid")).rejects.toBeInstanceOf(Error);
  expect([]).toBeArray();
  expect([1, 2, 3]).toBeArrayOfSize(3);
  expect("").toBeTypeOf("string");
});
```

There is also improved support for mocking with [`spyOn()`](https://vitest.dev/api/vi.html#vi-spyon).

```js
import { test, expect, spyOn } from "bun:test";

test("spyOn()", () => {
  const service = {
    hasPermission: () => false,
  };

  let hasPermission = false;
  const spy = spyOn(service, "hasPermission").mockImplementation(
    () => hasPermission,
  );
  hasPermission = true;

  expect(service.hasPermission()).toBe(true);
  expect(spy).toHaveBeenCalled();
});
```

With all these changes, it should be faster and easier than ever to migrate your existing project to use `bun test`. Here's what happens a popular npm package, such as `zod`, migrates to `bun test`.

{% raw %}

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">Benchmarking Bun / Vitest / Jest against Zod&#39;s test suite<br><br>Bun — 230ms<br>Vitest — 1.9s (8x slower)<br>Jest + SWC — 3s (13x slower)<br>Jest w/ ts-jest — 6.7s (29x slower)<br>Jest w/ Babel — 7.4s (32x slower) <a href="https://t.co/RFqZ06hH5K">pic.twitter.com/RFqZ06hH5K</a></p>&mdash; Colin McDonnell (@colinhacks) <a href="https://twitter.com/colinhacks/status/1673408135720239104?ref_src=twsrc%5Etfw">June 26, 2023</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
{% /raw %}

## Bugfixes to `.env` support

Bun has builtin support for loading `.env` files into `process.env`, saving you from needing to run `require("dotenv").config()` on startup, allowing you to use `.env` files in your tests, and in package.json `"scripts"`.

There were several bugs with this functionality that @alexlamsl has fixed:

- Windows-style newlines could cause it to crash https://github.com/oven-sh/bun/issues/411
- .env with `$` inside the value of an environment variable were considered a nested variable when they shouldn't have been https://github.com/oven-sh/bun/issues/2823
- A crash on inputs of certain lengths https://github.com/oven-sh/bun/issues/3042

## Node.js compatibility improvements

### Watch files in Bun

[`fs.watch()`](https://nodejs.org/docs/latest/api/fs.html#fswatchfilename-options-listener) is now implemented!

```js
import { watch } from "node:fs";

// file path
watch(".", (eventType, filename) => {
  console.log(`event type = ${eventType}`);
  if (filename) {
    console.log(`filename = ${filename}`);
  }
});
```

- `Bun.argv` now matches `process.argv`.

```js
import { deepEquals } from "bun";

console.log(deepEquals(Bun.argv, process.argv)); // true
```

- More of V8's [stack trace](https://v8.dev/docs/stack-trace-api) API now works.

```js
function getStack() {
  const cause = new Error();
  const prevPrepareStackTrace = Error.prepareStackTrace;
  Error.prepareStackTrace = (_, stack) => {
    console.log(stack[0].getFunctionName()); // "getStack"
    console.log(typeof stack[0].getLineNumber()); // "number"
    console.log(typeof stack[0].getColumnNumber()); // "number"
  };
  Error.captureStackTrace(cause);
  Error.prepareStackTrace = prevPrepareStackTrace;
}
```

- [`fs.writev`](https://nodejs.org/api/fs.html#fswritevsyncfd-buffers-position) and [`fs.readv`](https://nodejs.org/api/fs.html#fsreadvsyncfd-buffers-position) are now implemented.

```js
import { openSync, writevSync } from "node:fs";

const fd = openSync("path/to/file");
const buffers = [new Uint8Array(3), new Uint8Array(3), new Uint8Array(3)];
console.log(writevSync(fd, buffers)); // 9
```

- `Module._nodeModulePaths` is now supported. This function returns an array of paths that Bun will search for modules in.

```js
import { _nodeModulePaths } from "node:module";

console.log(_nodeModulePaths(".")); // ["/path/to/node_modules", "/path/node_modules", "/node_modules"]
```

- `crypto.randomInt()` is now supported, thanks to [@lenovouser](https://github.com/lenovouser)
- `util.deprecate` now supports `"code"` argument
- `fs.createWriteStream` now supports passing flags correctly, thanks to [@Hanaasagi](https://github.com/Hanaasagi)

## Improvements to `bun install`

We've also made a few additions to `bun install`.

### `--exact <package>`

`bun install --exact` gives you the same behavior as `npm install --save-exact` or `yarn add --exact`. It pins the version of the package you're installing to the exact version you specify.

```sh
$ bun install --exact elysia@0.5.20
```

### `--frozen-lockfile`

In this mode, Bun will throw an error if the `bun.lock` file is out of sync with `package.json`. This is useful for CI environments, where you want to ensure that `bun.lock` is up to date.

```sh
$ bun install --frozen-lockfile
```

### `trustedDependencies`

You can now configure an allow-list of dependencies to run lifecycle scripts, such as `postinstall`. By default, these scripts are not run to make Bun more secure by default.

```json#package.json
{
  "trustedDependencies": [
    "puppeteer"
  ]
}
```

We are planning to add a default list in the near future so that installing packages that rely on postinstall works as expected by default.

## More bug fixes

- A crash that could occur when writing files with `Bun.write` has been fixed
- The `node:tls` module was missing some ES exports
- The `bun:sqlite` package was missing a `default` export for the `Database` class
- `mkdirSync(path, {recursive: true})` would sometimes return an empty string when it shouldn't have
- File names in exception logs were sometimes garbled and that has been fixed
- Fixed a bug where module resolution for file: URLs with space characters in them would be % encoded instead of decoded
- Fixed a crash when readdir returns a large directory and some elements are UTF-16
- Fixed a potential crash when booelan arguments in node:fs functions are passed as non-boolean arguments

## More new stuff

- The `lastInTextNode` property in HTMLRewriter's `TextChunk` is now supported which tells you if the current chunk of text is the last one. Thanks to [@bru02](https://github.com/bru02)

## Changelog

{% table %}

---

- [`#3310`](https://github.com/oven-sh/bun/pull/3310)
- Changed `Bun.argv` to be same as `process.argv` by [@Jarred-Sumner](https://github.com/Jarred-Sumner)

---

- [`7f535a2`](https://github.com/oven-sh/bun/commit/7f535a20a24581696337871e6717c0c8e626c0ca)
- Fixed issue when assigning `module.require` by [@Jarred-Sumner](https://github.com/Jarred-Sumner)

---

- [`#3314`](https://github.com/oven-sh/bun/pull/3314)
- Improved validation of `Bun.serve` options by [@cirospaciari](https://github.com/cirospaciari)

---

- [`#3320`](https://github.com/oven-sh/bun/pull/3320)
- Fixed bugs with CommonJS imports by [@Jarred-Sumner](https://github.com/Jarred-Sumner)

---

- [`#3337`](https://github.com/oven-sh/bun/pull/3337)
- Fixed bug where `const` decleration could be tree-shaked before usage by [@dylan-conway](https://github.com/dylan-conway)

---

- [`8ad9e57`](https://github.com/oven-sh/bun/commit/8ad9e5755d67967a4c033241635fc2a214066f41)
- Added missing alias for `ucs2` encoding by [@Jarred-Sumner](https://github.com/Jarred-Sumner)

---

- [`b951c1f`](https://github.com/oven-sh/bun/commit/b951c1f89e90aeb4507d4402b4f1f5e5520b4923)
- Improved memory usage across the board by [@Jarred-Sumner](https://github.com/Jarred-Sumner)

---

- [`#3362`](https://github.com/oven-sh/bun/pull/3362)
- Improved detection of ESM and CommonJS when file has no exports by [@Jarred-Sumner](https://github.com/Jarred-Sumner)

---

- [`#3316`](https://github.com/oven-sh/bun/pull/3316)
- Implemented `toBeArray`, `toBeArrayOfSize`, and `toBeTypeOf` for `bun:test` by [@TiranexDev](https://github.com/TiranexDev)

---

- [`#3359`](https://github.com/oven-sh/bun/pull/3359)
- Implemented more of V8's stack trace APIs by [@kvakil](https://github.com/kvakil)

---

- [`#3363`](https://github.com/oven-sh/bun/pull/3363)
- Fixed overflow of `fs.utimesSync()` by [@Jarred-Sumner](https://github.com/Jarred-Sumner)

---

- [`83d7ec7`](https://github.com/oven-sh/bun/commit/83d7ec728f073261176b0bea8451b936c5a376ad)
- Fixed bug with `.copy()` after `.digest()` with `node:crypto` by [@Jarred-Sumner](https://github.com/Jarred-Sumner)

---

- [`#3367`](https://github.com/oven-sh/bun/pull/3367)
- Implemented asymetric matcher support for `toEqual`, `toStrictEqual`, and `toHaveProperty` by [@dylan-conway](https://github.com/dylan-conway)

---

- [`#3360`](https://github.com/oven-sh/bun/pull/3360)
- Fixed bugs with JSX in classic mode by [@dylan-conway](https://github.com/dylan-conway)

---

- [`#3368`](https://github.com/oven-sh/bun/pull/3368)
- Improved error message with circular dependencies by [@Jarred-Sumner](https://github.com/Jarred-Sumner)

---

- [`#3369`](https://github.com/oven-sh/bun/pull/3369)
- Fixed crash with `.env` files by [@Jarred-Sumner](https://github.com/Jarred-Sumner)

---

- [`#3304`](https://github.com/oven-sh/bun/pull/3304)
- Implemented more support for `mock()` in `bun:test` by [@paperclover](https://github.com/paperclover)

---

- [`#3378`](https://github.com/oven-sh/bun/pull/3378)
- Fixed usage of `bun:test` in CommonJS files by [@Jarred-Sumner](https://github.com/Jarred-Sumner)

---

- [`#3347`](https://github.com/oven-sh/bun/pull/3347)
- Fixed various bugs with `.env` file parsing by [@alexlamsl](https://github.com/alexlamsl)

---

- [`#3318`](https://github.com/oven-sh/bun/pull/3318)
- Implemented `resolves` and `rejects` for `expect()` by [@Electroid](https://github.com/Electroid)

---

- [`#3377`](https://github.com/oven-sh/bun/pull/3377)
- Fixed bug with `node-fetch` import by [@paperclover](https://github.com/paperclover)

---

- [`#3376`](https://github.com/oven-sh/bun/pull/3376)
- Implemented `spyOn()` in `bun:test` by [@paperclover](https://github.com/paperclover)

---

- [`#3249`](https://github.com/oven-sh/bun/pull/3249)
- Implemented `fs.watch()` by [@cirospaciari](https://github.com/cirospaciari)

---

- [`#3379`](https://github.com/oven-sh/bun/pull/3379)
- Rewrote support for CommonJS by [@Jarred-Sumner](https://github.com/Jarred-Sumner)

---

- [`#3394`](https://github.com/oven-sh/bun/pull/3394)
- Fixed bug with latin1 strings in `WebSocket` by [@Jarred-Sumner](https://github.com/Jarred-Sumner)

---

- [`#3400`](https://github.com/oven-sh/bun/pull/3400)
- Fixed potential crash with `bun install --production` by [@Jarred-Sumner](https://github.com/Jarred-Sumner)

---

- [`5bd94b8`](https://github.com/oven-sh/bun/commit/5bd94b8f47efab5ca736e6ec76b72e991df1da11)
- Implemented `process.mainModule` by [@Jarred-Sumner](https://github.com/Jarred-Sumner)

---

- [`#3402`](https://github.com/oven-sh/bun/pull/3402)
- Fixed bug with constructor of `WriteStream` by [@Hanaasagi](https://github.com/Hanaasagi)

---

- [`#3405`](https://github.com/oven-sh/bun/pull/3405)
- Implemented support for embedding files in compiled executables by [@Jarred-Sumner](https://github.com/Jarred-Sumner)

---

- [`#3365`](https://github.com/oven-sh/bun/pull/3365)
- Implemented `bun install --frozen-lockfile` by [@tiagotex](https://github.com/tiagotex)

---

- [`#3356`](https://github.com/oven-sh/bun/pull/3356)
- Update lol-html by [@bru02](https://github.com/bru02)

---

- [`#3401`](https://github.com/oven-sh/bun/pull/3401)
- Fixed crash with lol-html by [@Jarred-Sumner](https://github.com/Jarred-Sumner)

---

- [`#3411`](https://github.com/oven-sh/bun/pull/3411)
- Implemented `_nodeModulePaths` and `require.main.paths` by [@dylan-conway](https://github.com/dylan-conway)

---

- [`#3288`](https://github.com/oven-sh/bun/pull/3288)
- Implemented `trustedDependencies` in `package.json` by [@alexlamsl](https://github.com/alexlamsl)

---

- [`#3419`](https://github.com/oven-sh/bun/pull/3419)
- Implemented `writev` and `readv` by [@Jarred-Sumner](https://github.com/Jarred-Sumner)

---

- [`#3393`](https://github.com/oven-sh/bun/pull/3393)
- Implemented `__esModule` annotations by [@Jarred-Sumner](https://github.com/Jarred-Sumner)

---

{% /table %}

[**Full Changelog**](https://github.com/oven-sh/bun/compare/bun-v0.6.9...bun-v0.6.10)
