---
title: Bun v1.0.19
description: "Fixes 26 bugs (addressing 92 👍 reactions). Use @types/bun instead of bun-types. Fixes --frozen-lockfile bug. bcrypt & argon2 packages now work. setTimeout & setInterval get 4x higher throughput. module mocks in bun:test resolve specifiers. Optimized spawnSync() for large stdio on Linux. Bun.peek() gets 90x faster, expect(map1).toEqual(map2) gets 100x faster. Bugfixes to NAPI, bun install, and Node.js compatibility improvements"
date: "2023-12-22T08:26:18.952Z"
author: jarred
draft: false
---

Bun v1.0.19 fixes 26 bugs (addressing 92 👍 reactions). Use `@types/bun` instead of `bun-types`. Fixes "lockfile had changes, but is frozen" bug. `bcrypt` & `argon2` packages now work. `setTimeout` & `setInterval` get 4x higher throughput. module mocks in `bun:test` resolve specifiers. Optimized spawnSync() for large stdio on Linux. `Bun.peek()` gets 90x faster, `expect(map1).toEqual(map2)` gets 100x faster. Bugfixes to NAPI, bun install, and Node.js compatibility improvements

Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager &mdash; all in one. In case you missed it, here are some of the recent changes to Bun:

- [`v1.0.14`](/blog/bun-v1.0.14) - `Bun.Glob`, a fast API for matching files and strings using glob patterns. It also fixes a race condition when extracting dependencies during `bun install`, improves TypeScript module resolution in `node_modules`, and makes error messages easier to read.
- [`v1.0.15`](/blog/bun-v1.0.15) - Fixes 23 bugs (addressing 117 👍 reactions), `tsc` starts 2x faster. Stable `WebSocket` client, syntax-highlighted errors, cleaner stack traces, add custom test matchers with `expect.extend()` + additional expect matchers.
- [`v1.0.16`](/blog/bun-v1.0.16) - Fixes 49 bugs (addressing 38 👍 reactions). Concurrent IO for Bun.file & Bun.write gets 3x faster and now supports Google Cloud Run & Vercel, Bun.write auto-creates the parent directory if it doesn't exist, `expect.extend` inside of preload works, `napi_create_object` gets 2.5x faster, bugfix for module resolution impacting Astro v4 and p-limit, console.log bugfixes
- [`v1.0.17`](/blog/bun-v1.0.17) - Fixes 15 bugs (addressing 152 👍 reactions). bun install postinstall scripts run for top 500 packages, `bunx supabase` starts 30x faster than `npx supabase`, `bunx esbuild` starts 50x faster than `npx esbuild` and bugfixes to bun install
- [`v1.0.18`](/blog/bun-v1.0.18) - Fixes 27 bugs (addressing 28 👍 reactions). A hang impacting create-vite & create-next & stdin has been fixed. Lifecycle scripts reporting "node" or "node-gyp" not found has been fixed. expect().rejects works like Jest now, and more bug fixes

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 %}

To upgrade Bun:

```sh
$ bun upgrade
```

## Re-introducing `@types/bun` (formerly `bun-types`)

`@types/bun` gives you type definitions for Bun. It's a separate package from Bun itself, to make it easier to use Bun with your text editor or IDE.

Previously, this package was called `bun-types` and there were a lot of issues with it:

- You had to set `types` in your `tsconfig.json`, which broke loading packages using the `@types` folder convention
- We embedded a slightly modified version of `@types/node`, which frequently conflicted with the real `@types/node` package
- It didn't "just work" with TypeScript unless you configured it correctly
- DOM/Web types would occasionally conflict with Bun's types

Now, `@types/bun` should just work. It re-exports the real `@types/node` package so there's no conflicts. Since it's now in the `@types` namespace, it should work without breaking `@types/*` packages.

To install `@types/bun`:

```sh
$ bun add -d @types/bun
```

Or you can ue `bun init`:

```sh
$ bun init
```

## bcrypt & argon2 packages now work

[N-API](https://nodejs.org/api/n-api.html) compatibility improvements unlocked [`bcrypt`](https://github.com/kelektiv/node.bcrypt.js) and [`argon2`](https://github.com/ranisalt/node-argon2#readme) package support in Bun. These packages are widely used to securely hash & verify passwords.

{% callout %}

[Bun.password](https://bun.sh/docs/api/hashing#bun-password) also lets you hash and verify passwords using either bcrypt or argon2 without any dependencies to install.

{% /callout %}

{% raw %}

<table class="table-auto margin-0">

<tbody>

<tr class="flex mobile-flex-wrap">

<td>
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">in the next version of bun<br><br>the &quot;bcrypt&quot; npm package works <a href="https://t.co/IwDSTvKHA0">pic.twitter.com/IwDSTvKHA0</a></p>&mdash; Jarred Sumner (@jarredsumner) <a href="https://twitter.com/jarredsumner/status/1737799500029431863?ref_src=twsrc%5Etfw">December 21, 2023</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</td>

<!-- flex-wrap table tailwind -->
<td>

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">In the next version of Bun<br><br>the &quot;node-argon2&quot; package works <a href="https://t.co/gYxkXUgWBP">pic.twitter.com/gYxkXUgWBP</a></p>&mdash; Jarred Sumner (@jarredsumner) <a href="https://twitter.com/jarredsumner/status/1737782581259833532?ref_src=twsrc%5Etfw">December 21, 2023</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

</td>

</tbody>

</table>

{% /raw %}

## Fixed: "lockfile had changes, but is frozen" bug

The code path used by `--frozen-lockfile` to detect whether a lockfile changed sometimes incorrectly reported that the lockfile changed when it didn't. This would cause errors like:

```
error: lockfile had changes, but is frozen
```

To fix this, we've changed how we define "frozen". Instead of relying on input from the filesystem which can potentially change for unrelated reasons, we've switched it to using a hash of the package names and their versions sorted alphabetically with their version numbers. We think this is a more reliable approach.

To see what the hash of your lockfile is, run:

```sh
$ bun pm hash-string
```

{% details summary="View example output" %}

```sh
-- BEGIN SHA512/256(`${alphabetize(name)}@${order(version)}`) --
@ampproject/remapping@2.2.1
@babel/code-frame@7.22.5
@babel/compat-data@7.22.9
@babel/core@7.22.9
@babel/generator@7.22.9
@babel/helper-annotate-as-pure@7.22.5
@babel/helper-compilation-targets@7.22.9
@babel/helper-create-class-features-plugin@7.22.9
@babel/helper-environment-visitor@7.22.5
@babel/helper-function-name@7.22.5
@babel/helper-hoist-variables@7.22.5
@babel/helper-member-expression-to-functions@7.22.5
@babel/helper-module-imports@7.22.5
@babel/helper-module-transforms@7.22.9
@babel/helper-optimise-call-expression@7.22.5
@babel/helper-plugin-utils@7.22.5
@babel/helper-replace-supers@7.22.9
@babel/helper-simple-access@7.22.5
@babel/helper-skip-transparent-expression-wrappers@7.22.5
@babel/helper-split-export-declaration@7.22.6
@babel/helper-string-parser@7.22.5
@babel/helper-validator-identifier@7.22.5
@babel/helper-validator-option@7.22.5
@babel/helpers@7.22.6
@babel/highlight@7.22.5
@babel/parser@7.22.7
@babel/plugin-syntax-jsx@7.22.5
@babel/plugin-syntax-typescript@7.22.5
@babel/plugin-transform-modules-commonjs@7.22.5
@babel/plugin-transform-typescript@7.22.9
@babel/preset-typescript@7.22.5
@babel/standalone@7.22.9
@babel/template@7.22.5
@babel/traverse@7.22.8
@babel/types@7.22.5
@jridgewell/gen-mapping@0.3.3
@jridgewell/resolve-uri@3.1.0
@jridgewell/set-array@1.1.2
@jridgewell/sourcemap-codec@1.4.14
@jridgewell/sourcemap-codec@1.4.15
@jridgewell/trace-mapping@0.3.18
ansi-styles@3.2.1
browserslist@4.21.10
caniuse-lite@1.0.30001519
chalk@2.4.2
color-convert@1.9.3
color-name@1.1.3
convert-source-map@1.9.0
debug@4.3.4
electron-to-chromium@1.4.485
escalade@3.1.1
escape-string-regexp@1.0.5
gensync@1.0.0-beta.2
globals@11.12.0
has-flag@3.0.0
js-tokens@4.0.0
jsesc@2.5.2
json5@2.2.3
lodash@4.17.21
lru-cache@5.1.1
ms@2.1.2
node-releases@2.0.13
picocolors@1.0.0
semver@6.3.1
supports-color@5.5.0
to-fast-properties@2.0.0
update-browserslist-db@1.0.11
yallist@3.1.1
-- END HASH--
```

{% /details %}

## `setTimeout` & `setInterval` get 4x higher throughput

Bun's `setTimeout` and `setInterval` implementations are now 4x faster on Linux x64. We've added a timer heap to more efficiently manage timers.

```js
❯ bun setTimeout-leak-test.js
Executed 1003520 timers in 421.560553 ms

❯ bun-1.0.18 setTimeout-leak-test.js
Executed 1003520 timers in 2287.405973 ms
```

Thanks to [@mitchellh](https://github.com/mitchellh)'s [libxev](https://github.com/mitchellh/libxev) for the timer heap implementation.

### Why is timer performance important?

You might be thinking something like:

> "Timers delay code execution. Why does it matter if it's fast?"

Timer scheduling has a significant performance impact on your code, and many libraries use timers to schedule work with a slight delay. Timers don't have to trigger much faster, but timer scheduling needs to be fast.

Bun's previous timer implementation was somewhat irresponsible. On Linux, it created a [`timerfd`](https://man7.org/linux/man-pages/man2/timerfd_create.2.html) for every timer. This means every timer involves multiple system-calls and occupies a file descriptor. That's a lot of overhead for code which potentially runs very frequently.

Bun's new timer implementation uses a timer heap. This is a data structure that allows us to efficiently schedule potentially millions of timers.

### Fixed: `setInterval` sometimes still ran after `clearInterval`

There was a bug where an already-cancelled call to `setInterval` would occasionally still run one time. This was fixed along the way to rewriting the timer implementation.

## Better error for using `await` outside an `async` function

We've added a better error message when you use `await` outside of an `async` function.

```js
❯ bun file.js # after
3 |   await fetch("https://example.com")
            ^
error: "await" can only be used inside an "async" function
    at file.js:3:9

2 | function ohNo() {
    ^
note: Consider adding the "async" keyword here
   at file.js:2:1
```

Before, it would just say:

```js
❯ bun-1.0.18 file.js # before
3 |   await fetch("https://example.com")
            ^
error: Expected ";" but found "fetch"
    at file.js:3:9
```

## Optimized `Bun.spawnSync` for large input on Linux

On Linux, `Bun.spawnSync` now gets smarter about how it reads and writes data from child processes. We've switched from a pipe which must be read & written in a loop by the parent process to an in-memory file descriptor which does not cause processes to block when reading or writing large amounts of data. This also lets us avoid cloning the data from the child process to the parent process which can be expensive for large amounts of data.

This change makes `Bun.spawnSync` 50% faster when the child process has a large amount of output.

{% image src="https://github.com/oven-sh/bun/assets/709451/49a7167a-a31d-444b-ab00-1c209ddf4ed0" alt="Bun.spawnSync performance improvements" /%}

## `Bun.peek()` gets 90x faster

`Bun.peek(promise)` lets you read a promise's value without waiting for it to resolve, if it's no longer pending. This is useful to avoid microtasks and improve performance.

We've switched the implementation from relying on C++ SPI to using a JavaScriptCore bytecode intrinsic which makes it 90x faster.

Thanks to [@paperclover](https://github.com/paperclover)

## expect(map1).toEqual(map2) gets 100x faster

We've optimized the implementation of `expect(...).toEqual` when comparing `Map` instances. This makes it 100x faster for maps. This also makes it faster for `Set` instances.

We've also fixed a bug where `toEqual` on large maps would sometimes incorrectly report the maps are not equal.

[View on X](https://twitter.com/jarredsumner/status/1737392048410697829)

## module mocks in `bun:test` resolve specifiers

Bun supports mocking modules in `bun:test` using the `mock.module` function. Previously, the `specifier` argument had to exactly match the resolved module specifier used when loading the overridden module.

This was very confusing! People usually don't think about the difference between a resolved module specifier and a module specifier, and that means it seemed to not work when it actually did. Since ES Modules resolve and link modules before evaluating them, the resolved module specifier is usually different from the module specifier you use in `import` statements.

Now, `mock.module` resolves the specifier before mocking the module. This means you can use the module specifier (the path you put in `import` statements) instead of the resolved module specifier (the path you see in error messages).

```js-diff
import { mock, test, expect } from "bun:test";
import _ from "lodash";

- // Before: you had to resolve it yourself:
- mock.module(require.resolve("lodash"), () => ({ default: "mocked" }));
+ // Now: you can use the module specifier:
+ mock.module("lodash", () => ({ default: "mocked" }));

test("lodash is mocked", () => {
  expect(_).toEqual("mocked");
});
```

## Log slow postinstall scripts

If a post-install script takes longer than 500ms to run, `bun install` will now log it as a warning. This is useful to identify slow post-install scripts.

```sh
bun add v1.0.19 (7e59f287)

 installed re2@1.20.9

+warn: re2's install script took 57.7s

 92 packages installed [58.20s]
```

To avoid cluttering your terminal scrollback, we only log the slowest post-install script (not all of them).

Thanks to [@paperclover](https://github.com/paperclover).

## Fixed: potential hang when running post-install scripts

There was an event loop bug that could cause `bun install` to potentially hang (by not realizing they've exited) when running post-install scripts. This was fixed, thanks to [@dylan-conway](https://github.com/dylan-conway).

## `bun install --verbose` now streams post-install script output

When running `bun install --verbose`, post-install script output is now streamed to the terminal instead of buffered and printed at the end. This makes it easier to see what's happening. Thanks to [@dylan-conway](https://github.com/dylan-conway) for implementing this.

## Fixed: missing progress bar in post-install script output

In certain cases, `bun install` would not show a progress bar while the post-install scripts are running. This has been fixed, thanks to [@dylan-conway](https://github.com/dylan-conway).

## Fixed: stringifying SHA1, SHA256, MD5 hashes sometimes output too long of a string

A bug when encoding the output of a SHA1, SHA256, or MD5 hash as a `hex` or `base64` string would sometimes output a string that was longer than the contents of the hash. This is now fixed.

This impacted:

- `Bun.CryptoHasher`
- `createHash` in `node:crypto`

## Upgraded SQLite from v3.38.5 to v3.44.2

`bun:sqlite` is a fast SQLite client built into Bun. On Linux, `bun:sqlite` is statically linked which means we embed the SQLite library into Bun itself. This means you don't need to install SQLite on your system to use it.

We've upgraded the embedded SQLite library from v3.38.5 to v3.44.2. You can see the full changelog [here](https://www.sqlite.org/changes.html).

## Fixed: TypeScript parser edgecase

Previously, the following input would incorrectly fail to parse:

```
const a = <T = any>(): T => null as T;
const b = a<string>
```

This is now fixed. Thanks to [@paperclover](https://github.com/paperclover) for fixing this.

## Fixed: crash in `bun init`

A crash that sometimes occurred in `bun init` has been fixed, thanks to [@paperclover](https://github.com/paperclover).

## Fixed: regression with `$NODE_ENV`

In Bun v1.0.18 (the previous version), we accidentally removed setting a default value for `NODE_ENV`. This breaking change was not meant to be included in Bun v1.01.8. We may do a breaking change in the future to unset a default value (outside `bun test`), but we will not do this in a patch release.

Thanks to [@paperclover](https://github.com/paperclover) for fixing this.

## Fixed: printing bug with holey arrays

There was a bug where printing holey arrays would miss the delimiter & comma. This is now fixed, thanks to [@amartin96](https://github.com/amartin96).

After:

```js
❯ bun -e 'console.log([1,,,2,1,3])' # After
[ 1, 2 x empty items, 2, 1, 3 ]
```

Before:

```js
❯ bun-1.0.18 -e 'console.log([1,,,2,1,3])' # Before
[ 12 x empty items, 2, 1, 3 ]
```

## New matcher in bun:test `expect().toContainEqual()`

We've added a new matcher to `bun:test` called `toContainEqual`. This is similar to `toContain`, but it uses `toEqual` to compare the values instead of `===`.

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

test("toContainEqual", () => {
  expect("hello world").toContainEqual("hello");
  expect("hello world").not.toContainEqual("jello");
});
```

Thanks to [@Electroid](https://github.com/Electroid) for implementing this.

## Credits

We love seeing new contributors! Here are the 9 people who made their first contribution to Bun in this release:

- [@Osmose](https://github.com/Osmose) made their first contribution in [#7275](https://github.com/oven-sh/bun/pull/7275)
- [@scotttrinh](https://github.com/scotttrinh) made their first contribution in [#7686](https://github.com/oven-sh/bun/pull/7686)
- [@vlechemin](https://github.com/vlechemin) made their first contribution in [#7688](https://github.com/oven-sh/bun/pull/7688)
- [@dotspencer](https://github.com/dotspencer) made their first contribution in [#7727](https://github.com/oven-sh/bun/pull/7727)
- [@spicyzboss](https://github.com/spicyzboss) made their first contribution in [#7737](https://github.com/oven-sh/bun/pull/7737)
- [@bjon](https://github.com/bjon) made their first contribution in [#7738](https://github.com/oven-sh/bun/pull/7738)
- [@amartin96](https://github.com/amartin96) made their first contribution in [#7751](https://github.com/oven-sh/bun/pull/7751)
- [@sirhypernova](https://github.com/sirhypernova) made their first contribution in [#7760](https://github.com/oven-sh/bun/pull/7760)

### Thanks to 18 contributors for making Bun v1.0.19 possible

- [@amartin96](https://github.com/amartin96)
- [@bjon](https://github.com/bjon)
- [@cirospaciari](https://github.com/cirospaciari)
- [@colinhacks](https://github.com/colinhacks)
- [@dotspencer](https://github.com/dotspencer)
- [@dylan-conway](https://github.com/dylan-conway)
- [@Electroid](https://github.com/Electroid)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
- [@mathiasrw](https://github.com/mathiasrw)
- [@mitchellh](https://github.com/mitchellh) (for libxev timer heap code)
- [@o-az](https://github.com/o-az)
- [@Osmose](https://github.com/Osmose)
- [@paperclover](https://github.com/paperclover)
- [@scotttrinh](https://github.com/scotttrinh)
- [@sirenkovladd](https://github.com/sirenkovladd)
- [@sirhypernova](https://github.com/sirhypernova)
- [@spicyzboss](https://github.com/spicyzboss)
- [@vlechemin](https://github.com/vlechemin)
